summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
committerAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
commit1a78a62555be32868418fe52f8e330c9d0f95d5a (patch)
treed3765a80e7d3b9640ec2e930743630cd6b9fce2b /tools
downloadboost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'tools')
-rw-r--r--tools/Jamfile.v257
-rw-r--r--tools/auto_index/build/Jamfile.v233
-rw-r--r--tools/auto_index/doc/Jamfile.v286
-rw-r--r--tools/auto_index/doc/auto_index.qbk1149
-rw-r--r--tools/auto_index/doc/autoindex.idx93
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/comm_ref.html95
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/overview.html168
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/qbk.html229
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/script_ref.html525
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/tut.html66
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/tut/add_indexes.html173
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/tut/build.html90
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/tut/build_docs.html77
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/tut/configure.html139
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/tut/configure/optional.html106
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/tut/configure/options.html419
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/tut/entries.html62
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/tut/pis.html131
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/tut/refine.html99
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/tut/script.html160
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/workflow.html90
-rw-r--r--tools/auto_index/doc/html/boost_autoindex/xml.html65
-rw-r--r--tools/auto_index/doc/html/boostbook.css588
-rw-r--r--tools/auto_index/doc/html/images/blank.pngbin0 -> 374 bytes
-rw-r--r--tools/auto_index/doc/html/images/caution.pngbin0 -> 1250 bytes
-rw-r--r--tools/auto_index/doc/html/images/caution.svg68
-rw-r--r--tools/auto_index/doc/html/images/draft.pngbin0 -> 17454 bytes
-rw-r--r--tools/auto_index/doc/html/images/home.pngbin0 -> 358 bytes
-rw-r--r--tools/auto_index/doc/html/images/home.svg26
-rw-r--r--tools/auto_index/doc/html/images/important.pngbin0 -> 722 bytes
-rw-r--r--tools/auto_index/doc/html/images/important.svg25
-rw-r--r--tools/auto_index/doc/html/images/next.pngbin0 -> 336 bytes
-rw-r--r--tools/auto_index/doc/html/images/next.svg19
-rw-r--r--tools/auto_index/doc/html/images/next_disabled.pngbin0 -> 1110 bytes
-rw-r--r--tools/auto_index/doc/html/images/note.pngbin0 -> 490 bytes
-rw-r--r--tools/auto_index/doc/html/images/note.svg33
-rw-r--r--tools/auto_index/doc/html/images/prev.pngbin0 -> 334 bytes
-rw-r--r--tools/auto_index/doc/html/images/prev.svg19
-rw-r--r--tools/auto_index/doc/html/images/prev_disabled.pngbin0 -> 1109 bytes
-rw-r--r--tools/auto_index/doc/html/images/tip.pngbin0 -> 449 bytes
-rw-r--r--tools/auto_index/doc/html/images/tip.svg84
-rw-r--r--tools/auto_index/doc/html/images/toc-blank.pngbin0 -> 318 bytes
-rw-r--r--tools/auto_index/doc/html/images/toc-minus.pngbin0 -> 259 bytes
-rw-r--r--tools/auto_index/doc/html/images/toc-plus.pngbin0 -> 264 bytes
-rw-r--r--tools/auto_index/doc/html/images/up.pngbin0 -> 370 bytes
-rw-r--r--tools/auto_index/doc/html/images/up.svg19
-rw-r--r--tools/auto_index/doc/html/images/up_disabled.pngbin0 -> 1115 bytes
-rw-r--r--tools/auto_index/doc/html/images/warning.pngbin0 -> 1241 bytes
-rw-r--r--tools/auto_index/doc/html/images/warning.svg23
-rw-r--r--tools/auto_index/doc/html/index.html83
-rw-r--r--tools/auto_index/doc/html/index/s07.html585
-rw-r--r--tools/auto_index/doc/html/index/s08.html718
-rw-r--r--tools/auto_index/doc/html/reference.css11
-rw-r--r--tools/auto_index/doc/students_t_eg_1.pngbin0 -> 12481 bytes
-rw-r--r--tools/auto_index/doc/students_t_eg_2.pngbin0 -> 8264 bytes
-rw-r--r--tools/auto_index/doc/students_t_eg_3.pngbin0 -> 2334 bytes
-rw-r--r--tools/auto_index/doc/students_t_eg_4.pngbin0 -> 1351 bytes
-rw-r--r--tools/auto_index/include/auto_index_helpers.qbk19
-rw-r--r--tools/auto_index/index.html15
-rw-r--r--tools/auto_index/src/auto_index.cpp778
-rw-r--r--tools/auto_index/src/auto_index.hpp137
-rw-r--r--tools/auto_index/src/file_scanning.cpp495
-rw-r--r--tools/auto_index/src/index_generator.cpp327
-rw-r--r--tools/auto_index/src/tiny_xml.cpp257
-rw-r--r--tools/auto_index/src/tiny_xml.hpp83
-rw-r--r--tools/auto_index/test/Jamfile.v262
-rw-r--r--tools/auto_index/test/index.idx26
-rw-r--r--tools/auto_index/test/test1.gold6671
-rw-r--r--tools/auto_index/test/test2.gold6671
-rw-r--r--tools/auto_index/test/test3.gold6671
-rw-r--r--tools/auto_index/test/type_traits.docbook6673
-rw-r--r--tools/bcp/Jamfile.v237
-rw-r--r--tools/bcp/add_dependent_lib.cpp216
-rw-r--r--tools/bcp/add_path.cpp535
-rw-r--r--tools/bcp/bcp.hpp47
-rw-r--r--tools/bcp/bcp_imp.cpp295
-rw-r--r--tools/bcp/bcp_imp.hpp118
-rw-r--r--tools/bcp/copy_path.cpp240
-rw-r--r--tools/bcp/doc/Jamfile.v218
-rw-r--r--tools/bcp/doc/bcp.qbk211
-rw-r--r--tools/bcp/doc/html/index.html347
-rw-r--r--tools/bcp/file_types.cpp72
-rw-r--r--tools/bcp/fileview.cpp142
-rw-r--r--tools/bcp/fileview.hpp72
-rw-r--r--tools/bcp/index.html17
-rw-r--r--tools/bcp/licence_info.cpp721
-rw-r--r--tools/bcp/licence_info.hpp39
-rw-r--r--tools/bcp/main.cpp182
-rw-r--r--tools/bcp/output_licence_info.cpp408
-rw-r--r--tools/bcp/path_operations.cpp41
-rw-r--r--tools/bcp/scan_cvs_path.cpp147
-rw-r--r--tools/bcp/scan_licence.cpp275
-rw-r--r--tools/bcp/test/Jamfile.v225
-rw-r--r--tools/boostbook/doc/Jamfile.v213
-rw-r--r--tools/boostbook/doc/boostbook.xml385
-rw-r--r--tools/boostbook/doc/documenting.xml254
-rw-r--r--tools/boostbook/doc/reference.dtdxml3480
-rw-r--r--tools/boostbook/doc/reference.xml2951
-rw-r--r--tools/boostbook/doc/together.xml82
-rw-r--r--tools/boostbook/dtd/1.1/boost-no-inspect4
-rw-r--r--tools/boostbook/dtd/1.1/boostbook.dtd435
-rw-r--r--tools/boostbook/dtd/boostbook.dtd439
-rw-r--r--tools/boostbook/index.html21
-rw-r--r--tools/boostbook/setup_boostbook.py300
-rw-r--r--tools/boostbook/setup_boostbook.sh181
-rw-r--r--tools/boostbook/test/Jamfile.v213
-rw-r--r--tools/boostbook/test/alt.xml47
-rw-r--r--tools/boostbook/test/doxygen/Jamfile.v241
-rw-r--r--tools/boostbook/test/doxygen/autodoc.gold29
-rw-r--r--tools/boostbook/test/doxygen/boost/example.hpp139
-rw-r--r--tools/boostbook/test/doxygen/example.xml13
-rwxr-xr-xtools/boostbook/test/more/run-tests.py122
-rw-r--r--tools/boostbook/test/more/tests/book/boostbook.gold4
-rw-r--r--tools/boostbook/test/more/tests/book/boostbook.xml17
-rw-r--r--tools/boostbook/test/more/tests/book/chapter.gold4
-rw-r--r--tools/boostbook/test/more/tests/book/chapter.xml17
-rw-r--r--tools/boostbook/test/more/tests/book/library-autoid.gold4
-rw-r--r--tools/boostbook/test/more/tests/book/library-autoid.xml15
-rw-r--r--tools/boostbook/test/more/tests/book/library.gold4
-rw-r--r--tools/boostbook/test/more/tests/book/library.xml16
-rw-r--r--tools/boostbook/test/more/tests/libs/array.gold311
-rw-r--r--tools/boostbook/test/more/tests/libs/array.xml553
-rw-r--r--tools/boostbook/test/more/tests/libs/hash-ref.gold397
-rw-r--r--tools/boostbook/test/more/tests/libs/hash-ref.xml810
-rw-r--r--tools/boostbook/test/more/tests/libs/unordered-ref.gold1508
-rw-r--r--tools/boostbook/test/more/tests/libs/unordered-ref.xml3629
-rw-r--r--tools/boostbook/test/more/tests/misc/processing.gold5
-rw-r--r--tools/boostbook/test/more/tests/misc/processing.xml18
-rw-r--r--tools/boostbook/test/more/tests/syntax-highlight/comments.gold26
-rw-r--r--tools/boostbook/test/more/tests/syntax-highlight/comments.xml31
-rw-r--r--tools/boostbook/xsl/admon.xsl36
-rw-r--r--tools/boostbook/xsl/annotation.xsl437
-rw-r--r--tools/boostbook/xsl/callout.xsl71
-rw-r--r--tools/boostbook/xsl/caramel/LICENSE58
-rw-r--r--tools/boostbook/xsl/caramel/concept2docbook.xsl812
-rw-r--r--tools/boostbook/xsl/caramel/cpp-operators.xml288
-rw-r--r--tools/boostbook/xsl/caramel/unparser.xsl497
-rw-r--r--tools/boostbook/xsl/chunk-common.xsl126
-rw-r--r--tools/boostbook/xsl/docbook-layout.xsl211
-rw-r--r--tools/boostbook/xsl/docbook.xsl527
-rw-r--r--tools/boostbook/xsl/doxygen/collect.xsl58
-rw-r--r--tools/boostbook/xsl/doxygen/doxygen2boostbook.xsl1620
-rw-r--r--tools/boostbook/xsl/dtd/dtd2boostbook.xsl217
-rw-r--r--tools/boostbook/xsl/error.xsl19
-rw-r--r--tools/boostbook/xsl/fo.xsl395
-rw-r--r--tools/boostbook/xsl/function.xsl1217
-rw-r--r--tools/boostbook/xsl/global.xsl80
-rw-r--r--tools/boostbook/xsl/html-base.xsl383
-rw-r--r--tools/boostbook/xsl/html-help.xsl147
-rw-r--r--tools/boostbook/xsl/html-single.xsl26
-rw-r--r--tools/boostbook/xsl/html.xsl37
-rw-r--r--tools/boostbook/xsl/index.xsl18
-rw-r--r--tools/boostbook/xsl/library.xsl129
-rw-r--r--tools/boostbook/xsl/lookup.xsl424
-rw-r--r--tools/boostbook/xsl/macro.xsl83
-rw-r--r--tools/boostbook/xsl/manpages.xsl195
-rw-r--r--tools/boostbook/xsl/navbar.xsl409
-rw-r--r--tools/boostbook/xsl/reference.xsl198
-rw-r--r--tools/boostbook/xsl/relative-href.xsl98
-rw-r--r--tools/boostbook/xsl/source-highlight.xsl484
-rw-r--r--tools/boostbook/xsl/template.xsl601
-rw-r--r--tools/boostbook/xsl/testing/Jamfile.xsl243
-rw-r--r--tools/boostbook/xsl/testing/testsuite.xsl118
-rw-r--r--tools/boostbook/xsl/type.xsl1693
-rw-r--r--tools/boostbook/xsl/utility.xsl52
-rw-r--r--tools/boostbook/xsl/xhtml.xsl37
-rw-r--r--tools/boostbook/xsl/xref.xsl77
-rw-r--r--tools/build/boost.css65
-rw-r--r--tools/build/index.html21
-rw-r--r--tools/build/v2/Jamroot.jam47
-rw-r--r--tools/build/v2/boost-build.jam8
-rw-r--r--tools/build/v2/boost.css63
-rw-r--r--tools/build/v2/boost_build.pngbin0 -> 7437 bytes
-rw-r--r--tools/build/v2/boost_build.svg174
-rw-r--r--tools/build/v2/bootstrap.bat49
-rw-r--r--tools/build/v2/bootstrap.jam18
-rwxr-xr-xtools/build/v2/bootstrap.sh120
-rw-r--r--tools/build/v2/build-system.jam1008
-rw-r--r--tools/build/v2/build/__init__.py0
-rw-r--r--tools/build/v2/build/ac.jam198
-rw-r--r--tools/build/v2/build/alias.jam73
-rwxr-xr-xtools/build/v2/build/alias.py63
-rw-r--r--tools/build/v2/build/build-request.jam322
-rw-r--r--tools/build/v2/build/build_request.py216
-rw-r--r--tools/build/v2/build/configure.jam237
-rw-r--r--tools/build/v2/build/configure.py164
-rw-r--r--tools/build/v2/build/engine.py172
-rw-r--r--tools/build/v2/build/errors.py127
-rw-r--r--tools/build/v2/build/feature.jam1335
-rw-r--r--tools/build/v2/build/feature.py905
-rw-r--r--tools/build/v2/build/generators.jam1408
-rw-r--r--tools/build/v2/build/generators.py1089
-rw-r--r--tools/build/v2/build/modifiers.jam232
-rw-r--r--tools/build/v2/build/project.ann.py996
-rw-r--r--tools/build/v2/build/project.jam1110
-rw-r--r--tools/build/v2/build/project.py1120
-rw-r--r--tools/build/v2/build/property-set.jam481
-rw-r--r--tools/build/v2/build/property.jam788
-rw-r--r--tools/build/v2/build/property.py593
-rw-r--r--tools/build/v2/build/property_set.py449
-rw-r--r--tools/build/v2/build/readme.txt13
-rw-r--r--tools/build/v2/build/scanner.jam153
-rw-r--r--tools/build/v2/build/scanner.py158
-rw-r--r--tools/build/v2/build/targets.jam1659
-rw-r--r--tools/build/v2/build/targets.py1401
-rw-r--r--tools/build/v2/build/toolset.jam502
-rw-r--r--tools/build/v2/build/toolset.py398
-rw-r--r--tools/build/v2/build/type.jam425
-rw-r--r--tools/build/v2/build/type.py313
-rw-r--r--tools/build/v2/build/version.jam161
-rw-r--r--tools/build/v2/build/virtual-target.jam1317
-rw-r--r--tools/build/v2/build/virtual_target.py1118
-rw-r--r--tools/build/v2/build_system.py872
-rw-r--r--tools/build/v2/changes.txt317
-rw-r--r--tools/build/v2/contrib/boost.jam321
-rw-r--r--tools/build/v2/contrib/tntnet.jam208
-rw-r--r--tools/build/v2/contrib/wxFormBuilder.jam195
-rw-r--r--tools/build/v2/debian/boost-build.docs4
-rw-r--r--tools/build/v2/debian/boost-build.examples1
-rw-r--r--tools/build/v2/debian/changelog6
-rw-r--r--tools/build/v2/debian/conffiles1
-rw-r--r--tools/build/v2/debian/control13
-rw-r--r--tools/build/v2/debian/copyright0
-rw-r--r--tools/build/v2/debian/excludes14
-rwxr-xr-xtools/build/v2/debian/rules56
-rw-r--r--tools/build/v2/doc/bjam.qbk1696
-rw-r--r--tools/build/v2/doc/development_plan.html130
-rw-r--r--tools/build/v2/doc/history.qbk377
-rw-r--r--tools/build/v2/doc/jamfile.jam26
-rw-r--r--tools/build/v2/doc/src/architecture.xml636
-rw-r--r--tools/build/v2/doc/src/catalog.xml9
-rw-r--r--tools/build/v2/doc/src/extending.xml1207
-rw-r--r--tools/build/v2/doc/src/faq.xml458
-rw-r--r--tools/build/v2/doc/src/fragments.xml59
-rw-r--r--tools/build/v2/doc/src/howto.xml34
-rw-r--r--tools/build/v2/doc/src/install.xml150
-rw-r--r--tools/build/v2/doc/src/overview.xml1682
-rw-r--r--tools/build/v2/doc/src/recipes.xml11
-rw-r--r--tools/build/v2/doc/src/reference.xml2325
-rw-r--r--tools/build/v2/doc/src/standalone.xml47
-rw-r--r--tools/build/v2/doc/src/tasks.xml774
-rw-r--r--tools/build/v2/doc/src/tutorial.xml681
-rw-r--r--tools/build/v2/doc/src/userman.xml40
-rw-r--r--tools/build/v2/doc/tools.html92
-rw-r--r--tools/build/v2/engine/Jambase2473
-rw-r--r--tools/build/v2/engine/boehm_gc/AmigaOS.c623
-rw-r--r--tools/build/v2/engine/boehm_gc/BCC_MAKEFILE87
-rw-r--r--tools/build/v2/engine/boehm_gc/ChangeLog363
-rw-r--r--tools/build/v2/engine/boehm_gc/EMX_MAKEFILE140
-rw-r--r--tools/build/v2/engine/boehm_gc/MacOS.c156
-rw-r--r--tools/build/v2/engine/boehm_gc/MacProjects.sit.hqx886
-rw-r--r--tools/build/v2/engine/boehm_gc/Mac_files/MacOS_Test_config.h91
-rw-r--r--tools/build/v2/engine/boehm_gc/Mac_files/MacOS_config.h89
-rw-r--r--tools/build/v2/engine/boehm_gc/Mac_files/dataend.c9
-rw-r--r--tools/build/v2/engine/boehm_gc/Mac_files/datastart.c9
-rw-r--r--tools/build/v2/engine/boehm_gc/Makefile.DLLs107
-rw-r--r--tools/build/v2/engine/boehm_gc/Makefile.am206
-rw-r--r--tools/build/v2/engine/boehm_gc/Makefile.direct737
-rw-r--r--tools/build/v2/engine/boehm_gc/Makefile.dj428
-rw-r--r--tools/build/v2/engine/boehm_gc/Makefile.in1405
-rwxr-xr-xtools/build/v2/engine/boehm_gc/NT_MAKEFILE60
-rw-r--r--tools/build/v2/engine/boehm_gc/NT_STATIC_THREADS_MAKEFILE74
-rw-r--r--tools/build/v2/engine/boehm_gc/NT_THREADS_MAKEFILE2220
-rw-r--r--tools/build/v2/engine/boehm_gc/NT_X64_STATIC_THREADS_MAKEFILE74
-rw-r--r--tools/build/v2/engine/boehm_gc/OS2_MAKEFILE45
-rw-r--r--tools/build/v2/engine/boehm_gc/PCR-Makefile68
-rw-r--r--tools/build/v2/engine/boehm_gc/README.QUICK88
-rw-r--r--tools/build/v2/engine/boehm_gc/SMakefile.amiga177
-rw-r--r--tools/build/v2/engine/boehm_gc/WCC_MAKEFILE196
-rw-r--r--tools/build/v2/engine/boehm_gc/acinclude.m449
-rw-r--r--tools/build/v2/engine/boehm_gc/aclocal.m4929
-rw-r--r--tools/build/v2/engine/boehm_gc/add_gc_prefix.c20
-rw-r--r--tools/build/v2/engine/boehm_gc/allchblk.c850
-rw-r--r--tools/build/v2/engine/boehm_gc/alloc.c1023
-rw-r--r--tools/build/v2/engine/boehm_gc/alpha_mach_dep.S86
-rw-r--r--tools/build/v2/engine/boehm_gc/backgraph.c469
-rw-r--r--tools/build/v2/engine/boehm_gc/bdw-gc.pc10
-rw-r--r--tools/build/v2/engine/boehm_gc/bdw-gc.pc.in10
-rw-r--r--tools/build/v2/engine/boehm_gc/blacklst.c285
-rwxr-xr-xtools/build/v2/engine/boehm_gc/callprocs4
-rw-r--r--tools/build/v2/engine/boehm_gc/checksums.c196
-rwxr-xr-xtools/build/v2/engine/boehm_gc/compile142
-rwxr-xr-xtools/build/v2/engine/boehm_gc/config.guess1500
-rw-r--r--tools/build/v2/engine/boehm_gc/config.sub1608
-rwxr-xr-xtools/build/v2/engine/boehm_gc/configure23503
-rw-r--r--tools/build/v2/engine/boehm_gc/configure.ac658
-rw-r--r--tools/build/v2/engine/boehm_gc/configure.host61
-rwxr-xr-xtools/build/v2/engine/boehm_gc/configure_atomic_ops.sh4
-rw-r--r--tools/build/v2/engine/boehm_gc/cord/cord.am17
-rw-r--r--tools/build/v2/engine/boehm_gc/cord/cordbscs.c919
-rw-r--r--tools/build/v2/engine/boehm_gc/cord/cordprnt.c396
-rw-r--r--tools/build/v2/engine/boehm_gc/cord/cordtest.c235
-rw-r--r--tools/build/v2/engine/boehm_gc/cord/cordxtra.c621
-rw-r--r--tools/build/v2/engine/boehm_gc/cord/de.c603
-rw-r--r--tools/build/v2/engine/boehm_gc/cord/de_cmds.h33
-rw-r--r--tools/build/v2/engine/boehm_gc/cord/de_win.ICObin0 -> 766 bytes
-rw-r--r--tools/build/v2/engine/boehm_gc/cord/de_win.RC78
-rw-r--r--tools/build/v2/engine/boehm_gc/cord/de_win.c370
-rw-r--r--tools/build/v2/engine/boehm_gc/cord/de_win.h103
-rw-r--r--tools/build/v2/engine/boehm_gc/darwin_stop_world.c599
-rw-r--r--tools/build/v2/engine/boehm_gc/dbg_mlc.c1053
-rwxr-xr-xtools/build/v2/engine/boehm_gc/depcomp436
-rw-r--r--tools/build/v2/engine/boehm_gc/digimars.mak90
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README548
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.DGUX386215
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.Mac390
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.MacOSX1
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.OS26
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.amiga322
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.arm.cross68
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.autoconf59
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.changes2594
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.contributors57
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.cords53
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.darwin142
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.dj12
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.environment135
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.ews480081
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.hp18
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.linux131
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.macros82
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.rs60009
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.sgi41
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.solaris264
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.uts2
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.win32221
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/README.win6417
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/barrett_diagram106
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/debugging.html306
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/doc.am55
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/gc.man97
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/gcdescr.html621
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/gcinterface.html278
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/leak.html200
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/overview.html446
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/porting.html333
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/scale.html210
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/simple_example.html202
-rw-r--r--tools/build/v2/engine/boehm_gc/doc/tree.html199
-rw-r--r--tools/build/v2/engine/boehm_gc/dyn_load.c1190
-rw-r--r--tools/build/v2/engine/boehm_gc/finalize.c869
-rw-r--r--tools/build/v2/engine/boehm_gc/gc.mak2220
-rw-r--r--tools/build/v2/engine/boehm_gc/gc_cpp.cc67
-rw-r--r--tools/build/v2/engine/boehm_gc/gc_cpp.cpp2
-rw-r--r--tools/build/v2/engine/boehm_gc/gc_dlopen.c89
-rw-r--r--tools/build/v2/engine/boehm_gc/gcj_mlc.c245
-rw-r--r--tools/build/v2/engine/boehm_gc/gcname.c13
-rw-r--r--tools/build/v2/engine/boehm_gc/headers.c394
-rw-r--r--tools/build/v2/engine/boehm_gc/hpux_test_and_clear.s21
-rw-r--r--tools/build/v2/engine/boehm_gc/ia64_save_regs_in_stack.s12
-rw-r--r--tools/build/v2/engine/boehm_gc/if_mach.c25
-rw-r--r--tools/build/v2/engine/boehm_gc/if_not_there.c38
-rw-r--r--tools/build/v2/engine/boehm_gc/include/cord.h327
-rw-r--r--tools/build/v2/engine/boehm_gc/include/ec.h70
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc.h1139
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc_allocator.h245
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc_amiga_redirects.h30
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc_backptr.h65
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc_config_macros.h179
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc_cpp.h374
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc_gcj.h94
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc_inline.h128
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc_mark.h201
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc_pthread_redirects.h54
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc_tiny_fl.h89
-rw-r--r--tools/build/v2/engine/boehm_gc/include/gc_typed.h111
-rw-r--r--tools/build/v2/engine/boehm_gc/include/include.am54
-rw-r--r--tools/build/v2/engine/boehm_gc/include/javaxfc.h21
-rw-r--r--tools/build/v2/engine/boehm_gc/include/leak_detector.h9
-rw-r--r--tools/build/v2/engine/boehm_gc/include/new_gc_alloc.h484
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/cord_pos.h118
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/darwin_semaphore.h68
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/darwin_stop_world.h22
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/dbg_mlc.h178
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/gc_hdrs.h206
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/gc_locks.h210
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/gc_pmark.h494
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/gc_priv.h2040
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/gcconfig.h2339
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/msvc_dbg.h69
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/pthread_stop_world.h11
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/pthread_support.h84
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/specific.h96
-rw-r--r--tools/build/v2/engine/boehm_gc/include/private/thread_local_alloc.h152
-rw-r--r--tools/build/v2/engine/boehm_gc/include/weakpointer.h221
-rwxr-xr-xtools/build/v2/engine/boehm_gc/install-sh251
-rw-r--r--tools/build/v2/engine/boehm_gc/libtool.m46397
-rwxr-xr-xtools/build/v2/engine/boehm_gc/ltmain.sh6863
-rw-r--r--tools/build/v2/engine/boehm_gc/mach_dep.c242
-rw-r--r--tools/build/v2/engine/boehm_gc/malloc.c510
-rw-r--r--tools/build/v2/engine/boehm_gc/mallocx.c574
-rw-r--r--tools/build/v2/engine/boehm_gc/mark.c1866
-rw-r--r--tools/build/v2/engine/boehm_gc/mark_rts.c617
-rw-r--r--tools/build/v2/engine/boehm_gc/mips_sgi_mach_dep.s46
-rw-r--r--tools/build/v2/engine/boehm_gc/mips_ultrix_mach_dep.s26
-rw-r--r--tools/build/v2/engine/boehm_gc/misc.c1177
-rwxr-xr-xtools/build/v2/engine/boehm_gc/missing336
-rwxr-xr-xtools/build/v2/engine/boehm_gc/mkinstalldirs101
-rw-r--r--tools/build/v2/engine/boehm_gc/msvc_dbg.c348
-rw-r--r--tools/build/v2/engine/boehm_gc/new_hblk.c201
-rw-r--r--tools/build/v2/engine/boehm_gc/obj_map.c90
-rw-r--r--tools/build/v2/engine/boehm_gc/os_dep.c4333
-rw-r--r--tools/build/v2/engine/boehm_gc/pcr_interface.c179
-rw-r--r--tools/build/v2/engine/boehm_gc/pthread_stop_world.c537
-rw-r--r--tools/build/v2/engine/boehm_gc/pthread_support.c1495
-rw-r--r--tools/build/v2/engine/boehm_gc/ptr_chck.c283
-rw-r--r--tools/build/v2/engine/boehm_gc/real_malloc.c31
-rw-r--r--tools/build/v2/engine/boehm_gc/reclaim.c608
-rw-r--r--tools/build/v2/engine/boehm_gc/rs6000_mach_dep.s114
-rw-r--r--tools/build/v2/engine/boehm_gc/setjmp_t.c135
-rw-r--r--tools/build/v2/engine/boehm_gc/sparc_mach_dep.S70
-rw-r--r--tools/build/v2/engine/boehm_gc/sparc_netbsd_mach_dep.s34
-rw-r--r--tools/build/v2/engine/boehm_gc/sparc_sunos4_mach_dep.s38
-rw-r--r--tools/build/v2/engine/boehm_gc/specific.c165
-rw-r--r--tools/build/v2/engine/boehm_gc/stubborn.c58
-rw-r--r--tools/build/v2/engine/boehm_gc/tests/leak_test.c25
-rw-r--r--tools/build/v2/engine/boehm_gc/tests/middle.c26
-rw-r--r--tools/build/v2/engine/boehm_gc/tests/test.c1634
-rw-r--r--tools/build/v2/engine/boehm_gc/tests/test_cpp.cc292
-rw-r--r--tools/build/v2/engine/boehm_gc/tests/tests.am57
-rw-r--r--tools/build/v2/engine/boehm_gc/tests/thread_leak_test.c45
-rw-r--r--tools/build/v2/engine/boehm_gc/thread_local_alloc.c310
-rw-r--r--tools/build/v2/engine/boehm_gc/threadlibs.c63
-rw-r--r--tools/build/v2/engine/boehm_gc/typd_mlc.c722
-rw-r--r--tools/build/v2/engine/boehm_gc/version.h30
-rw-r--r--tools/build/v2/engine/boehm_gc/win32_threads.c1570
-rw-r--r--tools/build/v2/engine/boost-jam.spec64
-rw-r--r--tools/build/v2/engine/boost-no-inspect1
-rw-r--r--tools/build/v2/engine/build.bat532
-rw-r--r--tools/build/v2/engine/build.jam1070
-rwxr-xr-xtools/build/v2/engine/build.sh303
-rw-r--r--tools/build/v2/engine/build_vms.com105
-rw-r--r--tools/build/v2/engine/builtins.c2310
-rw-r--r--tools/build/v2/engine/builtins.h69
-rw-r--r--tools/build/v2/engine/bump_version.py80
-rw-r--r--tools/build/v2/engine/class.c141
-rw-r--r--tools/build/v2/engine/class.h13
-rw-r--r--tools/build/v2/engine/command.c100
-rw-r--r--tools/build/v2/engine/command.h61
-rw-r--r--tools/build/v2/engine/compile.c1424
-rw-r--r--tools/build/v2/engine/compile.h82
-rw-r--r--tools/build/v2/engine/debian/changelog72
-rw-r--r--tools/build/v2/engine/debian/control16
-rw-r--r--tools/build/v2/engine/debian/copyright25
-rw-r--r--tools/build/v2/engine/debian/jam.man.sgml236
-rwxr-xr-xtools/build/v2/engine/debian/rules73
-rw-r--r--tools/build/v2/engine/debug.c132
-rw-r--r--tools/build/v2/engine/debug.h54
-rw-r--r--tools/build/v2/engine/execcmd.h45
-rw-r--r--tools/build/v2/engine/execmac.c69
-rw-r--r--tools/build/v2/engine/execnt.c1296
-rw-r--r--tools/build/v2/engine/execunix.c569
-rw-r--r--tools/build/v2/engine/execvms.c161
-rw-r--r--tools/build/v2/engine/expand.c733
-rw-r--r--tools/build/v2/engine/expand.h14
-rw-r--r--tools/build/v2/engine/filemac.c175
-rw-r--r--tools/build/v2/engine/filent.c387
-rw-r--r--tools/build/v2/engine/fileos2.c138
-rw-r--r--tools/build/v2/engine/filesys.c83
-rw-r--r--tools/build/v2/engine/filesys.h60
-rw-r--r--tools/build/v2/engine/fileunix.c501
-rw-r--r--tools/build/v2/engine/filevms.c327
-rw-r--r--tools/build/v2/engine/frames.c22
-rw-r--r--tools/build/v2/engine/frames.h37
-rw-r--r--tools/build/v2/engine/glob.c152
-rw-r--r--tools/build/v2/engine/hash.c459
-rw-r--r--tools/build/v2/engine/hash.h25
-rw-r--r--tools/build/v2/engine/hcache.c434
-rw-r--r--tools/build/v2/engine/hcache.h18
-rw-r--r--tools/build/v2/engine/hdrmacro.c137
-rw-r--r--tools/build/v2/engine/hdrmacro.h14
-rw-r--r--tools/build/v2/engine/headers.c203
-rw-r--r--tools/build/v2/engine/headers.h16
-rw-r--r--tools/build/v2/engine/jam.c632
-rw-r--r--tools/build/v2/engine/jam.h579
-rw-r--r--tools/build/v2/engine/jambase.c1691
-rw-r--r--tools/build/v2/engine/jambase.h15
-rw-r--r--tools/build/v2/engine/jamgram.c1830
-rw-r--r--tools/build/v2/engine/jamgram.h140
-rw-r--r--tools/build/v2/engine/jamgram.y371
-rw-r--r--tools/build/v2/engine/jamgram.yy329
-rw-r--r--tools/build/v2/engine/jamgramtab.h44
-rw-r--r--tools/build/v2/engine/lists.c339
-rw-r--r--tools/build/v2/engine/lists.h108
-rw-r--r--tools/build/v2/engine/make.c814
-rw-r--r--tools/build/v2/engine/make.h41
-rw-r--r--tools/build/v2/engine/make1.c1145
-rw-r--r--tools/build/v2/engine/md5.c381
-rw-r--r--tools/build/v2/engine/md5.h91
-rw-r--r--tools/build/v2/engine/mem.c75
-rw-r--r--tools/build/v2/engine/mem.h134
-rw-r--r--tools/build/v2/engine/mkjambase.c123
-rw-r--r--tools/build/v2/engine/modules.c168
-rw-r--r--tools/build/v2/engine/modules.h37
-rw-r--r--tools/build/v2/engine/modules/order.c144
-rw-r--r--tools/build/v2/engine/modules/path.c32
-rw-r--r--tools/build/v2/engine/modules/property-set.c110
-rw-r--r--tools/build/v2/engine/modules/readme.txt3
-rw-r--r--tools/build/v2/engine/modules/regex.c96
-rw-r--r--tools/build/v2/engine/modules/sequence.c42
-rw-r--r--tools/build/v2/engine/modules/set.c41
-rw-r--r--tools/build/v2/engine/native.c36
-rw-r--r--tools/build/v2/engine/native.h34
-rw-r--r--tools/build/v2/engine/newstr.c174
-rw-r--r--tools/build/v2/engine/newstr.h14
-rw-r--r--tools/build/v2/engine/option.c94
-rw-r--r--tools/build/v2/engine/option.h23
-rw-r--r--tools/build/v2/engine/output.c125
-rw-r--r--tools/build/v2/engine/output.h29
-rw-r--r--tools/build/v2/engine/parse.c132
-rw-r--r--tools/build/v2/engine/parse.h59
-rw-r--r--tools/build/v2/engine/patchlevel.h17
-rw-r--r--tools/build/v2/engine/pathmac.c252
-rw-r--r--tools/build/v2/engine/pathsys.h91
-rw-r--r--tools/build/v2/engine/pathunix.c457
-rw-r--r--tools/build/v2/engine/pathvms.c406
-rw-r--r--tools/build/v2/engine/pwd.c66
-rw-r--r--tools/build/v2/engine/pwd.h10
-rw-r--r--tools/build/v2/engine/regexp.c1328
-rw-r--r--tools/build/v2/engine/regexp.h32
-rw-r--r--tools/build/v2/engine/rules.c810
-rw-r--r--tools/build/v2/engine/rules.h280
-rw-r--r--tools/build/v2/engine/scan.c418
-rw-r--r--tools/build/v2/engine/scan.h56
-rw-r--r--tools/build/v2/engine/search.c223
-rw-r--r--tools/build/v2/engine/search.h11
-rw-r--r--tools/build/v2/engine/strings.c201
-rw-r--r--tools/build/v2/engine/strings.h34
-rw-r--r--tools/build/v2/engine/subst.c94
-rw-r--r--tools/build/v2/engine/timestamp.c226
-rw-r--r--tools/build/v2/engine/timestamp.h12
-rw-r--r--tools/build/v2/engine/variable.c631
-rw-r--r--tools/build/v2/engine/variable.h35
-rw-r--r--tools/build/v2/engine/w32_getreg.c207
-rw-r--r--tools/build/v2/engine/yyacc.c268
-rw-r--r--tools/build/v2/example/boost-build.jam6
-rw-r--r--tools/build/v2/example/built_tool/Jamroot.jam8
-rw-r--r--tools/build/v2/example/built_tool/core/Jamfile.jam30
-rw-r--r--tools/build/v2/example/built_tool/core/a.td0
-rw-r--r--tools/build/v2/example/built_tool/core/core.cpp5
-rw-r--r--tools/build/v2/example/built_tool/readme.txt5
-rw-r--r--tools/build/v2/example/built_tool/tblgen/Jamfile.jam4
-rw-r--r--tools/build/v2/example/built_tool/tblgen/tblgen.cpp9
-rw-r--r--tools/build/v2/example/customization/class.verbatim7
-rw-r--r--tools/build/v2/example/customization/codegen.cpp36
-rwxr-xr-xtools/build/v2/example/customization/inline_file.py44
-rw-r--r--tools/build/v2/example/customization/jamroot.jam9
-rw-r--r--tools/build/v2/example/customization/readme.txt11
-rw-r--r--tools/build/v2/example/customization/t1.verbatim2
-rw-r--r--tools/build/v2/example/customization/t2.verbatim0
-rw-r--r--tools/build/v2/example/customization/usage.verbatim5
-rw-r--r--tools/build/v2/example/customization/verbatim.jam51
-rw-r--r--tools/build/v2/example/customization/verbatim.py47
-rw-r--r--tools/build/v2/example/generate/REAME.txt11
-rw-r--r--tools/build/v2/example/generate/a.cpp10
-rw-r--r--tools/build/v2/example/generate/gen.jam26
-rw-r--r--tools/build/v2/example/generate/gen.py16
-rw-r--r--tools/build/v2/example/generate/jamroot.jam9
-rw-r--r--tools/build/v2/example/generator/README.txt6
-rw-r--r--tools/build/v2/example/generator/foo.gci10
-rw-r--r--tools/build/v2/example/generator/jamroot.jam6
-rw-r--r--tools/build/v2/example/generator/soap.jam77
-rw-r--r--tools/build/v2/example/gettext/jamfile.jam26
-rw-r--r--tools/build/v2/example/gettext/jamroot.jam6
-rw-r--r--tools/build/v2/example/gettext/main.cpp28
-rw-r--r--tools/build/v2/example/gettext/readme.txt24
-rw-r--r--tools/build/v2/example/gettext/russian.po21
-rw-r--r--tools/build/v2/example/hello/hello.cpp16
-rw-r--r--tools/build/v2/example/hello/jamroot.jam1
-rw-r--r--tools/build/v2/example/hello/readme.txt7
-rw-r--r--tools/build/v2/example/libraries/app/app.cpp15
-rw-r--r--tools/build/v2/example/libraries/app/jamfile.jam9
-rw-r--r--tools/build/v2/example/libraries/jamroot.jam4
-rw-r--r--tools/build/v2/example/libraries/util/foo/bar.cpp13
-rw-r--r--tools/build/v2/example/libraries/util/foo/include/lib1.h10
-rw-r--r--tools/build/v2/example/libraries/util/foo/jamfile.jam9
-rw-r--r--tools/build/v2/example/make/foo.py2
-rw-r--r--tools/build/v2/example/make/jamroot.jam13
-rw-r--r--tools/build/v2/example/make/main_cpp.pro1
-rw-r--r--tools/build/v2/example/make/readme.txt7
-rw-r--r--tools/build/v2/example/pch/include/pch.hpp19
-rw-r--r--tools/build/v2/example/pch/jamroot.jam29
-rw-r--r--tools/build/v2/example/pch/source/hello_world.cpp15
-rw-r--r--tools/build/v2/example/python_modules/jamroot.jam8
-rw-r--r--tools/build/v2/example/python_modules/python_helpers.jam15
-rw-r--r--tools/build/v2/example/python_modules/python_helpers.py18
-rw-r--r--tools/build/v2/example/python_modules/readme.txt16
-rw-r--r--tools/build/v2/example/qt/README.txt20
-rw-r--r--tools/build/v2/example/qt/qt3/hello/canvas.cpp73
-rw-r--r--tools/build/v2/example/qt/qt3/hello/canvas.h35
-rw-r--r--tools/build/v2/example/qt/qt3/hello/jamroot.jam13
-rw-r--r--tools/build/v2/example/qt/qt3/hello/main.cpp36
-rw-r--r--tools/build/v2/example/qt/qt3/moccable-cpp/jamroot.jam11
-rw-r--r--tools/build/v2/example/qt/qt3/moccable-cpp/main.cpp41
-rw-r--r--tools/build/v2/example/qt/qt3/uic/hello_world_widget.ui58
-rw-r--r--tools/build/v2/example/qt/qt3/uic/jamroot.jam15
-rw-r--r--tools/build/v2/example/qt/qt3/uic/main.cpp18
-rw-r--r--tools/build/v2/example/qt/qt4/hello/arrow.cpp158
-rw-r--r--tools/build/v2/example/qt/qt4/hello/arrow.h30
-rw-r--r--tools/build/v2/example/qt/qt4/hello/jamroot.jam14
-rw-r--r--tools/build/v2/example/qt/qt4/hello/main.cpp27
-rw-r--r--tools/build/v2/example/qt/qt4/moccable-cpp/jamroot.jam18
-rw-r--r--tools/build/v2/example/qt/qt4/moccable-cpp/main.cpp39
-rw-r--r--tools/build/v2/example/qt/qt4/uic/hello_world_widget.ui55
-rw-r--r--tools/build/v2/example/qt/qt4/uic/jamroot.jam18
-rw-r--r--tools/build/v2/example/qt/qt4/uic/main.cpp23
-rw-r--r--tools/build/v2/example/variant/a.cpp7
-rw-r--r--tools/build/v2/example/variant/jamfile.jam11
-rw-r--r--tools/build/v2/example/variant/jamroot.jam14
-rw-r--r--tools/build/v2/example/variant/libs/jamfile.jam6
-rw-r--r--tools/build/v2/example/variant/libs/l.cpp9
-rw-r--r--tools/build/v2/example/variant/readme.txt11
-rw-r--r--tools/build/v2/example/versioned/hello.cpp12
-rw-r--r--tools/build/v2/example/versioned/jamfile.jam9
-rw-r--r--tools/build/v2/example/versioned/jamroot.jam8
-rw-r--r--tools/build/v2/exceptions.py44
-rw-r--r--tools/build/v2/hacking.txt154
-rw-r--r--tools/build/v2/index.html165
-rw-r--r--tools/build/v2/kernel/boost-build.jam5
-rw-r--r--tools/build/v2/kernel/bootstrap.jam263
-rw-r--r--tools/build/v2/kernel/bootstrap.py25
-rw-r--r--tools/build/v2/kernel/class.jam420
-rw-r--r--tools/build/v2/kernel/errors.jam274
-rw-r--r--tools/build/v2/kernel/modules.jam354
-rw-r--r--tools/build/v2/manager.py110
-rwxr-xr-xtools/build/v2/nightly.sh30
-rw-r--r--tools/build/v2/notes/README.txt8
-rw-r--r--tools/build/v2/notes/build_dir_option.txt77
-rw-r--r--tools/build/v2/notes/relative_source_paths.txt76
-rw-r--r--tools/build/v2/options/help.jam212
-rw-r--r--tools/build/v2/release_procedure.txt83
-rwxr-xr-xtools/build/v2/roll.sh66
-rw-r--r--tools/build/v2/site-config.jam4
-rw-r--r--tools/build/v2/test/BoostBuild.py921
-rw-r--r--tools/build/v2/test/Jamrules4
-rw-r--r--tools/build/v2/test/TestCmd.py651
-rw-r--r--tools/build/v2/test/abs_workdir.py34
-rw-r--r--tools/build/v2/test/absolute_sources.py96
-rw-r--r--tools/build/v2/test/alias.py107
-rw-r--r--tools/build/v2/test/alternatives.py113
-rw-r--r--tools/build/v2/test/assert-equal.jam33
-rw-r--r--tools/build/v2/test/bad_dirname.py22
-rw-r--r--tools/build/v2/test/boost-build.jam14
-rw-r--r--tools/build/v2/test/boostbook.py23
-rw-r--r--tools/build/v2/test/boostbook/a.hpp16
-rw-r--r--tools/build/v2/test/boostbook/docs.xml36
-rw-r--r--tools/build/v2/test/boostbook/jamroot.jam3
-rw-r--r--tools/build/v2/test/build_dir.py106
-rw-r--r--tools/build/v2/test/build_file.py170
-rw-r--r--tools/build/v2/test/build_no.py28
-rw-r--r--tools/build/v2/test/c_file.py36
-rw-r--r--tools/build/v2/test/chain.py56
-rw-r--r--tools/build/v2/test/check-arguments.jam71
-rw-r--r--tools/build/v2/test/check-bindrule.jam29
-rw-r--r--tools/build/v2/test/check-jam-patches.jam293
-rw-r--r--tools/build/v2/test/check-test-tools.jam26
-rw-r--r--tools/build/v2/test/clean.py116
-rw-r--r--tools/build/v2/test/composite.py25
-rw-r--r--tools/build/v2/test/conditionals.py47
-rw-r--r--tools/build/v2/test/conditionals2.py43
-rw-r--r--tools/build/v2/test/conditionals3.py30
-rwxr-xr-xtools/build/v2/test/conditionals_multiple.py297
-rwxr-xr-xtools/build/v2/test/configuration.py110
-rwxr-xr-xtools/build/v2/test/copy_time.py76
-rw-r--r--tools/build/v2/test/core_d12.py35
-rw-r--r--tools/build/v2/test/core_delete_module.py51
-rw-r--r--tools/build/v2/test/core_dependencies.py157
-rw-r--r--tools/build/v2/test/core_import_module.py63
-rw-r--r--tools/build/v2/test/core_modifiers.py51
-rw-r--r--tools/build/v2/test/core_typecheck.py47
-rw-r--r--tools/build/v2/test/core_varnames.py38
-rw-r--r--tools/build/v2/test/custom_generator.py66
-rw-r--r--tools/build/v2/test/default_build.py93
-rw-r--r--tools/build/v2/test/default_features.py50
-rwxr-xr-xtools/build/v2/test/default_toolset.py211
-rw-r--r--tools/build/v2/test/dependency-test/a.cpp17
-rw-r--r--tools/build/v2/test/dependency-test/a.h8
-rw-r--r--tools/build/v2/test/dependency-test/a_c.c12
-rw-r--r--tools/build/v2/test/dependency-test/b.cpp14
-rw-r--r--tools/build/v2/test/dependency-test/b.h8
-rw-r--r--tools/build/v2/test/dependency-test/c.cpp14
-rw-r--r--tools/build/v2/test/dependency-test/e.cpp15
-rw-r--r--tools/build/v2/test/dependency-test/foo.jam34
-rw-r--r--tools/build/v2/test/dependency-test/foo.py26
-rw-r--r--tools/build/v2/test/dependency-test/jamfile.jam25
-rw-r--r--tools/build/v2/test/dependency-test/jamroot.jam7
-rw-r--r--tools/build/v2/test/dependency-test/src1/a.h10
-rw-r--r--tools/build/v2/test/dependency-test/src1/b.h10
-rw-r--r--tools/build/v2/test/dependency-test/src1/c.h8
-rw-r--r--tools/build/v2/test/dependency-test/src1/z.h5
-rw-r--r--tools/build/v2/test/dependency-test/src2/b.h8
-rw-r--r--tools/build/v2/test/dependency-test/x.foo0
-rw-r--r--tools/build/v2/test/dependency-test/y.foo0
-rw-r--r--tools/build/v2/test/dependency_property.py36
-rw-r--r--tools/build/v2/test/dependency_test.py104
-rw-r--r--tools/build/v2/test/direct-request-test/a.cpp19
-rw-r--r--tools/build/v2/test/direct-request-test/b.cpp22
-rw-r--r--tools/build/v2/test/direct-request-test/b_inverse.cpp22
-rw-r--r--tools/build/v2/test/direct-request-test/jamfile.jam13
-rw-r--r--tools/build/v2/test/direct-request-test/jamfile2.jam9
-rw-r--r--tools/build/v2/test/direct-request-test/jamroot.jam6
-rw-r--r--tools/build/v2/test/direct_request_test.py40
-rw-r--r--tools/build/v2/test/disambiguation.py32
-rw-r--r--tools/build/v2/test/dll_path.py158
-rw-r--r--tools/build/v2/test/double_loading.py30
-rw-r--r--tools/build/v2/test/duplicate.py38
-rw-r--r--tools/build/v2/test/echo_args.jam20
-rw-r--r--tools/build/v2/test/empty.jam5
-rw-r--r--tools/build/v2/test/engine/README.txt5
-rw-r--r--tools/build/v2/test/engine/action_status.jam28
-rw-r--r--tools/build/v2/test/engine/actions_quietly.jam55
-rw-r--r--tools/build/v2/test/engine/builtin_normalize_path.jam60
-rw-r--r--tools/build/v2/test/engine/builtin_shell.jam31
-rw-r--r--tools/build/v2/test/engine/builtin_w32_getregnames.jam17
-rw-r--r--tools/build/v2/test/engine/option_d2.jam50
-rw-r--r--tools/build/v2/test/engine/option_l.jam34
-rw-r--r--tools/build/v2/test/engine/option_n.jam44
-rw-r--r--tools/build/v2/test/engine/parallel_actions.jam91
-rw-r--r--tools/build/v2/test/engine/parallel_multifile_actions_1.jam45
-rw-r--r--tools/build/v2/test/engine/parallel_multifile_actions_2.jam49
-rw-r--r--tools/build/v2/test/engine/rule_param.jam60
-rw-r--r--tools/build/v2/test/engine/stress_var_expand.jam14
-rw-r--r--tools/build/v2/test/engine/target_var.jam16
-rw-r--r--tools/build/v2/test/engine/test.bat53
-rw-r--r--tools/build/v2/test/engine/test.jam91
-rwxr-xr-xtools/build/v2/test/engine/test.sh53
-rw-r--r--tools/build/v2/test/engine/var_expand.jam19
-rw-r--r--tools/build/v2/test/example_customization.py21
-rw-r--r--tools/build/v2/test/example_gettext.py30
-rw-r--r--tools/build/v2/test/example_libraries.py21
-rw-r--r--tools/build/v2/test/example_make.py20
-rw-r--r--tools/build/v2/test/example_qt4.py26
-rwxr-xr-xtools/build/v2/test/exit_status.py26
-rw-r--r--tools/build/v2/test/expansion.py80
-rw-r--r--tools/build/v2/test/explicit.py64
-rwxr-xr-xtools/build/v2/test/file_name_handling.py255
-rw-r--r--tools/build/v2/test/free_features_request.py42
-rw-r--r--tools/build/v2/test/gcc_runtime.py33
-rwxr-xr-xtools/build/v2/test/generator_selection.py140
-rw-r--r--tools/build/v2/test/generators-test/a.cpp22
-rw-r--r--tools/build/v2/test/generators-test/b.cxx10
-rw-r--r--tools/build/v2/test/generators-test/c.tui0
-rw-r--r--tools/build/v2/test/generators-test/d.wd0
-rw-r--r--tools/build/v2/test/generators-test/e.cpp8
-rw-r--r--tools/build/v2/test/generators-test/extra.jam120
-rw-r--r--tools/build/v2/test/generators-test/jamfile.jam19
-rw-r--r--tools/build/v2/test/generators-test/jamroot.jam95
-rw-r--r--tools/build/v2/test/generators-test/lex.jam26
-rw-r--r--tools/build/v2/test/generators-test/lib/c.cpp10
-rw-r--r--tools/build/v2/test/generators-test/lib/jamfile.jam9
-rw-r--r--tools/build/v2/test/generators-test/nm.jam43
-rw-r--r--tools/build/v2/test/generators-test/qt.jam34
-rw-r--r--tools/build/v2/test/generators-test/x.l5
-rw-r--r--tools/build/v2/test/generators-test/y.x_pro0
-rw-r--r--tools/build/v2/test/generators-test/z.cpp16
-rw-r--r--tools/build/v2/test/generators_test.py30
-rw-r--r--tools/build/v2/test/implicit_dependency.py81
-rw-r--r--tools/build/v2/test/indirect_conditional.py78
-rw-r--r--tools/build/v2/test/inherit_toolset.py59
-rwxr-xr-xtools/build/v2/test/inherited_dependency.py237
-rw-r--r--tools/build/v2/test/inline.py64
-rw-r--r--tools/build/v2/test/jamfile.jam11
-rw-r--r--tools/build/v2/test/lib_source_property.py45
-rw-r--r--tools/build/v2/test/library_chain.py166
-rw-r--r--tools/build/v2/test/library_order.py100
-rw-r--r--tools/build/v2/test/library_property.py56
-rw-r--r--tools/build/v2/test/load_dir.py81
-rw-r--r--tools/build/v2/test/load_order.py64
-rw-r--r--tools/build/v2/test/loop.py25
-rw-r--r--tools/build/v2/test/m1-01.py61
-rw-r--r--tools/build/v2/test/m1-02.py90
-rw-r--r--tools/build/v2/test/m1-03.py57
-rw-r--r--tools/build/v2/test/make_rule.py58
-rw-r--r--tools/build/v2/test/module-actions/boost-build.jam5
-rw-r--r--tools/build/v2/test/module-actions/bootstrap.jam61
-rw-r--r--tools/build/v2/test/module_actions.py53
-rw-r--r--tools/build/v2/test/ndebug.py39
-rw-r--r--tools/build/v2/test/no_type.py23
-rw-r--r--tools/build/v2/test/notfile.py44
-rw-r--r--tools/build/v2/test/ordered_include.py41
-rw-r--r--tools/build/v2/test/ordered_properties.py33
-rw-r--r--tools/build/v2/test/out_of_tree.py39
-rw-r--r--tools/build/v2/test/path_features.py85
-rw-r--r--tools/build/v2/test/pch.py55
-rw-r--r--tools/build/v2/test/prebuilt.py43
-rw-r--r--tools/build/v2/test/prebuilt/ext/a.cpp17
-rw-r--r--tools/build/v2/test/prebuilt/ext/debug/a.h13
-rw-r--r--tools/build/v2/test/prebuilt/ext/jamfile.jam13
-rw-r--r--tools/build/v2/test/prebuilt/ext/jamfile2.jam39
-rw-r--r--tools/build/v2/test/prebuilt/ext/jamfile3.jam46
-rw-r--r--tools/build/v2/test/prebuilt/ext/jamroot.jam5
-rw-r--r--tools/build/v2/test/prebuilt/ext/release/a.h13
-rw-r--r--tools/build/v2/test/prebuilt/hello.cpp20
-rw-r--r--tools/build/v2/test/prebuilt/jamfile.jam13
-rw-r--r--tools/build/v2/test/prebuilt/jamroot.jam4
-rwxr-xr-xtools/build/v2/test/preprocessor.py53
-rw-r--r--tools/build/v2/test/print.py48
-rw-r--r--tools/build/v2/test/project-test1.jam18
-rw-r--r--tools/build/v2/test/project-test1/dir/jamfile.jam10
-rw-r--r--tools/build/v2/test/project-test1/dir2/jamfile.jam9
-rw-r--r--tools/build/v2/test/project-test1/dir2/jamroot.jam4
-rw-r--r--tools/build/v2/test/project-test1/jamfile.jam10
-rw-r--r--tools/build/v2/test/project-test1/jamroot.jam6
-rw-r--r--tools/build/v2/test/project-test1/project-test1.jam21
-rw-r--r--tools/build/v2/test/project-test1/readme.txt8
-rw-r--r--tools/build/v2/test/project-test1/standalone-project.jam12
-rw-r--r--tools/build/v2/test/project-test3/a.cpp8
-rw-r--r--tools/build/v2/test/project-test3/jamfile.jam13
-rw-r--r--tools/build/v2/test/project-test3/jamroot.jam46
-rw-r--r--tools/build/v2/test/project-test3/lib/b.cpp8
-rw-r--r--tools/build/v2/test/project-test3/lib/jamfile.jam9
-rw-r--r--tools/build/v2/test/project-test3/lib2/c.cpp8
-rw-r--r--tools/build/v2/test/project-test3/lib2/d.cpp8
-rw-r--r--tools/build/v2/test/project-test3/lib2/helper/e.cpp8
-rw-r--r--tools/build/v2/test/project-test3/lib2/helper/jamfile.jam9
-rw-r--r--tools/build/v2/test/project-test3/lib2/jamfile.jam11
-rw-r--r--tools/build/v2/test/project-test3/lib3/f.cpp8
-rw-r--r--tools/build/v2/test/project-test3/lib3/jamfile.jam37
-rw-r--r--tools/build/v2/test/project-test3/lib3/jamroot.jam5
-rw-r--r--tools/build/v2/test/project-test3/readme.txt7
-rw-r--r--tools/build/v2/test/project-test4/a.cpp8
-rw-r--r--tools/build/v2/test/project-test4/a_gcc.cpp8
-rw-r--r--tools/build/v2/test/project-test4/jamfile.jam11
-rw-r--r--tools/build/v2/test/project-test4/jamfile3.jam5
-rw-r--r--tools/build/v2/test/project-test4/jamfile4.jam4
-rw-r--r--tools/build/v2/test/project-test4/jamfile5.jam6
-rw-r--r--tools/build/v2/test/project-test4/jamroot.jam47
-rw-r--r--tools/build/v2/test/project-test4/lib/b.cpp8
-rw-r--r--tools/build/v2/test/project-test4/lib/jamfile.jam6
-rw-r--r--tools/build/v2/test/project-test4/lib/jamfile1.jam2
-rw-r--r--tools/build/v2/test/project-test4/lib/jamfile2.jam4
-rw-r--r--tools/build/v2/test/project-test4/lib/jamfile3.jam2
-rw-r--r--tools/build/v2/test/project-test4/lib2/jamfile.jam8
-rw-r--r--tools/build/v2/test/project-test4/lib2/jamfile2.jam4
-rw-r--r--tools/build/v2/test/project-test4/readme.txt6
-rw-r--r--tools/build/v2/test/project_dependencies.py51
-rw-r--r--tools/build/v2/test/project_glob.py161
-rw-r--r--tools/build/v2/test/project_root_constants.py66
-rw-r--r--tools/build/v2/test/project_root_rule.py34
-rw-r--r--tools/build/v2/test/project_test1.py78
-rw-r--r--tools/build/v2/test/project_test3.py133
-rw-r--r--tools/build/v2/test/project_test4.py65
-rw-r--r--tools/build/v2/test/property_expansion.py29
-rwxr-xr-xtools/build/v2/test/qt4.py19
-rw-r--r--tools/build/v2/test/qt4/jamroot.jam79
-rw-r--r--tools/build/v2/test/qt4/mock.cpp26
-rw-r--r--tools/build/v2/test/qt4/mock.h21
-rw-r--r--tools/build/v2/test/qt4/phonon.cpp23
-rw-r--r--tools/build/v2/test/qt4/qt3support.cpp29
-rw-r--r--tools/build/v2/test/qt4/qtassistant.cpp21
-rw-r--r--tools/build/v2/test/qt4/qtcore.cpp22
-rw-r--r--tools/build/v2/test/qt4/qtcorefail.cpp23
-rw-r--r--tools/build/v2/test/qt4/qtdeclarative.cpp27
-rw-r--r--tools/build/v2/test/qt4/qtgui.cpp42
-rw-r--r--tools/build/v2/test/qt4/qthelp.cpp22
-rw-r--r--tools/build/v2/test/qt4/qtmultimedia.cpp25
-rw-r--r--tools/build/v2/test/qt4/qtnetwork.cpp33
-rw-r--r--tools/build/v2/test/qt4/qtscript.cpp37
-rw-r--r--tools/build/v2/test/qt4/qtscripttools.cpp47
-rw-r--r--tools/build/v2/test/qt4/qtsql.cpp37
-rw-r--r--tools/build/v2/test/qt4/qtsvg.cpp21
-rw-r--r--tools/build/v2/test/qt4/qttest.cpp30
-rw-r--r--tools/build/v2/test/qt4/qtwebkit.cpp24
-rw-r--r--tools/build/v2/test/qt4/qtxml.cpp29
-rw-r--r--tools/build/v2/test/qt4/qtxmlpatterns.cpp76
-rw-r--r--tools/build/v2/test/railsys.py14
-rw-r--r--tools/build/v2/test/railsys/libx/include/test_libx.h25
-rw-r--r--tools/build/v2/test/railsys/libx/jamroot.jam13
-rw-r--r--tools/build/v2/test/railsys/libx/src/jamfile.jam19
-rw-r--r--tools/build/v2/test/railsys/libx/src/test_libx.cpp15
-rw-r--r--tools/build/v2/test/railsys/program/include/test_a.h22
-rw-r--r--tools/build/v2/test/railsys/program/jamfile.jam45
-rw-r--r--tools/build/v2/test/railsys/program/jamroot.jam14
-rw-r--r--tools/build/v2/test/railsys/program/liba/jamfile.jam14
-rw-r--r--tools/build/v2/test/railsys/program/liba/test_a.cpp17
-rw-r--r--tools/build/v2/test/railsys/program/main/jamfile.jam12
-rw-r--r--tools/build/v2/test/railsys/program/main/main.cpp19
-rw-r--r--tools/build/v2/test/readme.txt6
-rw-r--r--tools/build/v2/test/rebuilds.py51
-rw-r--r--tools/build/v2/test/recursive.jam117
-rw-r--r--tools/build/v2/test/regression.py124
-rw-r--r--tools/build/v2/test/relative_sources.py38
-rw-r--r--tools/build/v2/test/remove_requirement.py89
-rw-r--r--tools/build/v2/test/resolution.py37
-rw-r--r--tools/build/v2/test/searched_lib.py187
-rw-r--r--tools/build/v2/test/skipping.py36
-rwxr-xr-xtools/build/v2/test/sort_rule.py95
-rw-r--r--tools/build/v2/test/source_locations.py42
-rw-r--r--tools/build/v2/test/stage.py258
-rw-r--r--tools/build/v2/test/standalone.py59
-rw-r--r--tools/build/v2/test/startup/boost-root/boost-build.jam7
-rw-r--r--tools/build/v2/test/startup/boost-root/build/boost-build.jam6
-rw-r--r--tools/build/v2/test/startup/boost-root/build/bootstrap.jam7
-rw-r--r--tools/build/v2/test/startup/bootstrap-env/boost-build.jam5
-rw-r--r--tools/build/v2/test/startup/bootstrap-explicit/boost-build.jam6
-rw-r--r--tools/build/v2/test/startup/bootstrap-implicit/readme.txt5
-rw-r--r--tools/build/v2/test/startup/no-bootstrap1/boost-build.jam6
-rw-r--r--tools/build/v2/test/startup/no-bootstrap1/subdir/readme.txt5
-rw-r--r--tools/build/v2/test/startup/no-bootstrap2/boost-build.jam6
-rw-r--r--tools/build/v2/test/startup/no-bootstrap3/boost-build.jam5
-rw-r--r--tools/build/v2/test/startup_v1.py81
-rw-r--r--tools/build/v2/test/startup_v2.py79
-rw-r--r--tools/build/v2/test/subdir1/file-to-bind1
-rw-r--r--tools/build/v2/test/suffix.py78
-rw-r--r--tools/build/v2/test/svn_tree.py668
-rw-r--r--tools/build/v2/test/symlink.py41
-rw-r--r--tools/build/v2/test/tag.py122
-rw-r--r--tools/build/v2/test/template.py42
-rw-r--r--tools/build/v2/test/test-config-example.jam19
-rw-r--r--tools/build/v2/test/test.jam23
-rw-r--r--tools/build/v2/test/test1.py18
-rw-r--r--tools/build/v2/test/test2.py25
-rw-r--r--tools/build/v2/test/test2/Jamrules0
-rw-r--r--tools/build/v2/test/test2/foo.cpp10
-rw-r--r--tools/build/v2/test/test2/jamfile.jam8
-rw-r--r--tools/build/v2/test/test_all.py240
-rw-r--r--tools/build/v2/test/test_nt_line_length.jam39
-rwxr-xr-xtools/build/v2/test/test_result_dumping.py33
-rw-r--r--tools/build/v2/test/test_system.html618
-rw-r--r--tools/build/v2/test/testing-primitives/boost-build.jam5
-rw-r--r--tools/build/v2/test/testing-primitives/bootstrap.jam137
-rw-r--r--tools/build/v2/test/testing_primitives.py30
-rwxr-xr-xtools/build/v2/test/testing_support.py61
-rw-r--r--tools/build/v2/test/timedata.py155
-rw-r--r--tools/build/v2/test/tree.py120
-rw-r--r--tools/build/v2/test/unit-tests.jam262
-rw-r--r--tools/build/v2/test/unit_test.py36
-rw-r--r--tools/build/v2/test/unit_tests.py13
-rw-r--r--tools/build/v2/test/unused.py35
-rw-r--r--tools/build/v2/test/unused/a.cpp9
-rw-r--r--tools/build/v2/test/unused/b.cpp4
-rw-r--r--tools/build/v2/test/unused/b.x0
-rw-r--r--tools/build/v2/test/unused/jamfile.jam11
-rw-r--r--tools/build/v2/test/unused/jamroot.jam57
-rw-r--r--tools/build/v2/test/use_requirements.py295
-rw-r--r--tools/build/v2/test/using.py42
-rw-r--r--tools/build/v2/test/v1-testing/a.cpp5
-rw-r--r--tools/build/v2/test/v1-testing/b.cpp5
-rw-r--r--tools/build/v2/test/v1-testing/boost-build.jam6
-rw-r--r--tools/build/v2/test/v1-testing/c.cpp16
-rw-r--r--tools/build/v2/test/v1-testing/jamfile.jam26
-rw-r--r--tools/build/v2/test/v1_testing.py88
-rw-r--r--tools/build/v2/test/v1_testing/Jamrules0
-rw-r--r--tools/build/v2/test/v1_testing/boost-build.jam6
-rw-r--r--tools/build/v2/test/v1_testing/foo.cpp22
-rw-r--r--tools/build/v2/test/v1_testing/jamfile.jam23
-rw-r--r--tools/build/v2/test/v1_testing/jamroot.jam5
-rw-r--r--tools/build/v2/test/v1_testing/lib-err.cpp7
-rw-r--r--tools/build/v2/test/v1_testing/lib.cpp6
-rw-r--r--tools/build/v2/test/wrapper.py38
-rw-r--r--tools/build/v2/test/wrong_project.py41
-rwxr-xr-xtools/build/v2/to_merge.sh16
-rw-r--r--tools/build/v2/tools/__init__.py0
-rw-r--r--tools/build/v2/tools/acc.jam118
-rw-r--r--tools/build/v2/tools/auto-index.jam212
-rw-r--r--tools/build/v2/tools/bison.jam32
-rw-r--r--tools/build/v2/tools/boostbook-config.jam13
-rw-r--r--tools/build/v2/tools/boostbook.jam727
-rw-r--r--tools/build/v2/tools/borland.jam220
-rw-r--r--tools/build/v2/tools/builtin.jam960
-rw-r--r--tools/build/v2/tools/builtin.py718
-rw-r--r--tools/build/v2/tools/cast.jam91
-rw-r--r--tools/build/v2/tools/cast.py69
-rw-r--r--tools/build/v2/tools/clang-darwin.jam170
-rw-r--r--tools/build/v2/tools/clang-linux.jam196
-rw-r--r--tools/build/v2/tools/clang.jam27
-rw-r--r--tools/build/v2/tools/common.jam986
-rw-r--r--tools/build/v2/tools/common.py840
-rw-r--r--tools/build/v2/tools/como-linux.jam103
-rw-r--r--tools/build/v2/tools/como-win.jam117
-rw-r--r--tools/build/v2/tools/como.jam29
-rw-r--r--tools/build/v2/tools/convert.jam62
-rw-r--r--tools/build/v2/tools/cw-config.jam34
-rw-r--r--tools/build/v2/tools/cw.jam246
-rw-r--r--tools/build/v2/tools/darwin.jam568
-rw-r--r--tools/build/v2/tools/darwin.py57
-rw-r--r--tools/build/v2/tools/dmc.jam134
-rw-r--r--tools/build/v2/tools/docutils.jam84
-rw-r--r--tools/build/v2/tools/doxproc.py859
-rw-r--r--tools/build/v2/tools/doxygen-config.jam11
-rw-r--r--tools/build/v2/tools/doxygen.jam776
-rw-r--r--tools/build/v2/tools/doxygen/windows-paths-check.doxyfile3
-rw-r--r--tools/build/v2/tools/doxygen/windows-paths-check.hpp0
-rw-r--r--tools/build/v2/tools/fop.jam69
-rw-r--r--tools/build/v2/tools/fortran.jam55
-rw-r--r--tools/build/v2/tools/gcc.jam1185
-rw-r--r--tools/build/v2/tools/gcc.py796
-rw-r--r--tools/build/v2/tools/generate.jam108
-rw-r--r--tools/build/v2/tools/gettext.jam230
-rw-r--r--tools/build/v2/tools/gfortran.jam39
-rw-r--r--tools/build/v2/tools/hp_cxx.jam181
-rw-r--r--tools/build/v2/tools/hpfortran.jam35
-rw-r--r--tools/build/v2/tools/ifort.jam44
-rw-r--r--tools/build/v2/tools/intel-darwin.jam220
-rw-r--r--tools/build/v2/tools/intel-linux.jam250
-rw-r--r--tools/build/v2/tools/intel-win.jam184
-rw-r--r--tools/build/v2/tools/intel.jam34
-rw-r--r--tools/build/v2/tools/lex.jam33
-rw-r--r--tools/build/v2/tools/make.jam72
-rw-r--r--tools/build/v2/tools/make.py59
-rw-r--r--tools/build/v2/tools/mc.jam44
-rw-r--r--tools/build/v2/tools/message.jam55
-rw-r--r--tools/build/v2/tools/message.py46
-rw-r--r--tools/build/v2/tools/midl.jam142
-rw-r--r--tools/build/v2/tools/mipspro.jam145
-rw-r--r--tools/build/v2/tools/mpi.jam583
-rw-r--r--tools/build/v2/tools/msvc-config.jam12
-rw-r--r--tools/build/v2/tools/msvc.jam1392
-rw-r--r--tools/build/v2/tools/notfile.jam74
-rw-r--r--tools/build/v2/tools/notfile.py51
-rw-r--r--tools/build/v2/tools/package.jam165
-rw-r--r--tools/build/v2/tools/package.py168
-rw-r--r--tools/build/v2/tools/pathscale.jam168
-rw-r--r--tools/build/v2/tools/pch.jam95
-rw-r--r--tools/build/v2/tools/pch.py83
-rw-r--r--tools/build/v2/tools/pgi.jam147
-rw-r--r--tools/build/v2/tools/python-config.jam27
-rw-r--r--tools/build/v2/tools/python.jam1267
-rw-r--r--tools/build/v2/tools/qcc.jam236
-rw-r--r--tools/build/v2/tools/qt.jam17
-rw-r--r--tools/build/v2/tools/qt3.jam209
-rw-r--r--tools/build/v2/tools/qt4.jam724
-rw-r--r--tools/build/v2/tools/quickbook-config.jam44
-rw-r--r--tools/build/v2/tools/quickbook.jam361
-rw-r--r--tools/build/v2/tools/rc.jam156
-rw-r--r--tools/build/v2/tools/rc.py189
-rw-r--r--tools/build/v2/tools/stage.jam524
-rw-r--r--tools/build/v2/tools/stage.py350
-rw-r--r--tools/build/v2/tools/stlport.jam303
-rw-r--r--tools/build/v2/tools/sun.jam142
-rw-r--r--tools/build/v2/tools/symlink.jam140
-rw-r--r--tools/build/v2/tools/symlink.py112
-rw-r--r--tools/build/v2/tools/testing-aux.jam210
-rw-r--r--tools/build/v2/tools/testing.jam581
-rw-r--r--tools/build/v2/tools/testing.py342
-rw-r--r--tools/build/v2/tools/types/__init__.py18
-rw-r--r--tools/build/v2/tools/types/asm.jam4
-rw-r--r--tools/build/v2/tools/types/asm.py13
-rw-r--r--tools/build/v2/tools/types/cpp.jam86
-rw-r--r--tools/build/v2/tools/types/cpp.py10
-rw-r--r--tools/build/v2/tools/types/exe.jam9
-rw-r--r--tools/build/v2/tools/types/exe.py11
-rw-r--r--tools/build/v2/tools/types/html.jam4
-rw-r--r--tools/build/v2/tools/types/html.py10
-rw-r--r--tools/build/v2/tools/types/lib.jam74
-rw-r--r--tools/build/v2/tools/types/lib.py77
-rw-r--r--tools/build/v2/tools/types/obj.jam9
-rw-r--r--tools/build/v2/tools/types/obj.py11
-rw-r--r--tools/build/v2/tools/types/objc.jam26
-rw-r--r--tools/build/v2/tools/types/preprocessed.jam9
-rw-r--r--tools/build/v2/tools/types/qt.jam10
-rw-r--r--tools/build/v2/tools/types/register.jam39
-rw-r--r--tools/build/v2/tools/types/rsp.jam4
-rw-r--r--tools/build/v2/tools/types/rsp.py10
-rw-r--r--tools/build/v2/tools/unix.jam224
-rw-r--r--tools/build/v2/tools/unix.py150
-rw-r--r--tools/build/v2/tools/vacpp.jam150
-rw-r--r--tools/build/v2/tools/whale.jam116
-rw-r--r--tools/build/v2/tools/xlf.jam39
-rw-r--r--tools/build/v2/tools/xsltproc-config.jam37
-rw-r--r--tools/build/v2/tools/xsltproc.jam194
-rw-r--r--tools/build/v2/tools/xsltproc/included.xsl11
-rw-r--r--tools/build/v2/tools/xsltproc/test.xml2
-rw-r--r--tools/build/v2/tools/xsltproc/test.xsl12
-rw-r--r--tools/build/v2/tools/zlib.jam92
-rw-r--r--tools/build/v2/user-config.jam92
-rw-r--r--tools/build/v2/util/__init__.py136
-rw-r--r--tools/build/v2/util/assert.jam336
-rw-r--r--tools/build/v2/util/container.jam339
-rw-r--r--tools/build/v2/util/doc.jam997
-rw-r--r--tools/build/v2/util/indirect.jam115
-rw-r--r--tools/build/v2/util/indirect.py15
-rw-r--r--tools/build/v2/util/logger.py46
-rw-r--r--tools/build/v2/util/numbers.jam218
-rw-r--r--tools/build/v2/util/option.jam109
-rw-r--r--tools/build/v2/util/option.py35
-rw-r--r--tools/build/v2/util/order.jam169
-rw-r--r--tools/build/v2/util/order.py121
-rw-r--r--tools/build/v2/util/os.jam171
-rw-r--r--tools/build/v2/util/os_j.py19
-rw-r--r--tools/build/v2/util/path.jam934
-rw-r--r--tools/build/v2/util/path.py904
-rw-r--r--tools/build/v2/util/print.jam488
-rw-r--r--tools/build/v2/util/regex.jam193
-rw-r--r--tools/build/v2/util/regex.py25
-rw-r--r--tools/build/v2/util/sequence.jam335
-rw-r--r--tools/build/v2/util/sequence.py50
-rw-r--r--tools/build/v2/util/set.jam93
-rw-r--r--tools/build/v2/util/set.py42
-rw-r--r--tools/build/v2/util/string.jam189
-rw-r--r--tools/build/v2/util/utility.jam235
-rw-r--r--tools/build/v2/util/utility.py155
-rw-r--r--tools/index.html112
-rw-r--r--tools/inspect/apple_macro_check.cpp105
-rw-r--r--tools/inspect/apple_macro_check.hpp39
-rw-r--r--tools/inspect/ascii_check.cpp102
-rw-r--r--tools/inspect/ascii_check.hpp38
-rw-r--r--tools/inspect/assert_macro_check.cpp110
-rw-r--r--tools/inspect/assert_macro_check.hpp40
-rw-r--r--tools/inspect/build/Jamfile.v255
-rw-r--r--tools/inspect/build/msvc/boost_inspect.sln20
-rw-r--r--tools/inspect/build/msvc/boost_inspect.vcproj247
-rw-r--r--tools/inspect/build/msvc/readme.txt4
-rw-r--r--tools/inspect/copyright_check.cpp35
-rw-r--r--tools/inspect/copyright_check.hpp39
-rw-r--r--tools/inspect/crlf_check.cpp97
-rw-r--r--tools/inspect/crlf_check.hpp40
-rw-r--r--tools/inspect/cvs_iterator.hpp81
-rw-r--r--tools/inspect/doc/build.jam21
-rw-r--r--tools/inspect/doc/inspect.qbk128
-rw-r--r--tools/inspect/end_check.cpp58
-rw-r--r--tools/inspect/end_check.hpp40
-rw-r--r--tools/inspect/index.html58
-rw-r--r--tools/inspect/inspect.cpp1000
-rw-r--r--tools/inspect/inspector.hpp106
-rw-r--r--tools/inspect/license_check.cpp48
-rw-r--r--tools/inspect/license_check.hpp40
-rw-r--r--tools/inspect/link_check.cpp487
-rw-r--r--tools/inspect/link_check.hpp72
-rw-r--r--tools/inspect/link_check_test.html24
-rw-r--r--tools/inspect/minmax_check.cpp102
-rw-r--r--tools/inspect/minmax_check.hpp45
-rw-r--r--tools/inspect/path_name_check.cpp110
-rw-r--r--tools/inspect/path_name_check.hpp48
-rw-r--r--tools/inspect/tab_check.cpp44
-rw-r--r--tools/inspect/tab_check.hpp37
-rw-r--r--tools/inspect/time_string.hpp55
-rw-r--r--tools/inspect/unnamed_namespace_check.cpp62
-rw-r--r--tools/inspect/unnamed_namespace_check.hpp39
-rw-r--r--tools/inspect/wrong_line_ends_test.cpp1
-rw-r--r--tools/litre/cplusplus.py810
-rw-r--r--tools/litre/litre.py61
-rw-r--r--tools/litre/tool.py67
-rw-r--r--tools/make-cputime-page.pl54
-rw-r--r--tools/quickbook/Jamfile.v231
-rw-r--r--tools/quickbook/doc/1_6.qbk281
-rw-r--r--tools/quickbook/doc/Jamfile.v228
-rw-r--r--tools/quickbook/doc/block.qbk1113
-rw-r--r--tools/quickbook/doc/change_log.qbk250
-rw-r--r--tools/quickbook/doc/editors.qbk56
-rw-r--r--tools/quickbook/doc/faq.qbk55
-rw-r--r--tools/quickbook/doc/html/images/callouts/1.pngbin0 -> 391 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/10.pngbin0 -> 485 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/11.pngbin0 -> 410 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/12.pngbin0 -> 488 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/13.pngbin0 -> 509 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/14.pngbin0 -> 499 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/15.pngbin0 -> 507 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/2.pngbin0 -> 446 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/3.pngbin0 -> 431 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/4.pngbin0 -> 441 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/5.pngbin0 -> 423 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/6.pngbin0 -> 431 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/7.pngbin0 -> 397 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/8.pngbin0 -> 434 bytes
-rw-r--r--tools/quickbook/doc/html/images/callouts/9.pngbin0 -> 420 bytes
-rw-r--r--tools/quickbook/doc/html/images/extra/katepart/boost.hs.logo.pngbin0 -> 6756 bytes
-rw-r--r--tools/quickbook/doc/html/images/extra/katepart/table.boost.hs.pngbin0 -> 16362 bytes
-rw-r--r--tools/quickbook/doc/html/images/extra/katepart/table.text.editor.pngbin0 -> 14297 bytes
-rw-r--r--tools/quickbook/doc/install.qbk317
-rw-r--r--tools/quickbook/doc/introduction.qbk57
-rw-r--r--tools/quickbook/doc/phrase.qbk546
-rw-r--r--tools/quickbook/doc/quickbook.qbk94
-rw-r--r--tools/quickbook/doc/ref.qbk106
-rw-r--r--tools/quickbook/doc/structure.qbk192
-rw-r--r--tools/quickbook/doc/syntax.qbk54
-rw-r--r--tools/quickbook/extra/katepart/install.sh24
-rw-r--r--tools/quickbook/extra/katepart/katepart.qbk125
-rw-r--r--tools/quickbook/extra/katepart/syntax/boost_hs_boost.xml3020
-rw-r--r--tools/quickbook/extra/katepart/syntax/boost_hs_cpp.xml471
-rw-r--r--tools/quickbook/extra/katepart/syntax/boost_hs_quickbook.xml736
-rw-r--r--tools/quickbook/extra/katepart/syntax/boost_hs_std.xml620
-rw-r--r--tools/quickbook/index.html15
-rw-r--r--tools/quickbook/src/Jamfile.v260
-rw-r--r--tools/quickbook/src/actions.cpp1978
-rw-r--r--tools/quickbook/src/actions.hpp305
-rw-r--r--tools/quickbook/src/actions_class.cpp136
-rw-r--r--tools/quickbook/src/actions_class.hpp107
-rw-r--r--tools/quickbook/src/actions_state.hpp60
-rw-r--r--tools/quickbook/src/block_element_grammar.cpp320
-rw-r--r--tools/quickbook/src/block_tags.hpp40
-rw-r--r--tools/quickbook/src/cleanup.hpp74
-rw-r--r--tools/quickbook/src/code_snippet.cpp600
-rw-r--r--tools/quickbook/src/collector.cpp67
-rw-r--r--tools/quickbook/src/collector.hpp123
-rw-r--r--tools/quickbook/src/doc_info_actions.cpp559
-rw-r--r--tools/quickbook/src/doc_info_grammar.cpp289
-rw-r--r--tools/quickbook/src/doc_info_tags.hpp48
-rw-r--r--tools/quickbook/src/files.cpp507
-rw-r--r--tools/quickbook/src/files.hpp112
-rw-r--r--tools/quickbook/src/fwd.hpp33
-rw-r--r--tools/quickbook/src/grammar.cpp39
-rw-r--r--tools/quickbook/src/grammar.hpp70
-rw-r--r--tools/quickbook/src/grammar_impl.hpp106
-rw-r--r--tools/quickbook/src/id_manager.cpp1141
-rw-r--r--tools/quickbook/src/id_manager.hpp86
-rw-r--r--tools/quickbook/src/input_path.cpp257
-rw-r--r--tools/quickbook/src/input_path.hpp123
-rw-r--r--tools/quickbook/src/intrusive_base.hpp36
-rw-r--r--tools/quickbook/src/iterator.hpp69
-rw-r--r--tools/quickbook/src/main_grammar.cpp933
-rw-r--r--tools/quickbook/src/markups.cpp78
-rw-r--r--tools/quickbook/src/markups.hpp32
-rw-r--r--tools/quickbook/src/parsers.hpp257
-rw-r--r--tools/quickbook/src/phrase_element_grammar.cpp184
-rw-r--r--tools/quickbook/src/phrase_tags.hpp35
-rw-r--r--tools/quickbook/src/post_process.cpp457
-rw-r--r--tools/quickbook/src/post_process.hpp31
-rw-r--r--tools/quickbook/src/quickbook.cpp476
-rw-r--r--tools/quickbook/src/quickbook.hpp46
-rw-r--r--tools/quickbook/src/scoped.hpp32
-rw-r--r--tools/quickbook/src/string_ref.cpp30
-rw-r--r--tools/quickbook/src/string_ref.hpp78
-rw-r--r--tools/quickbook/src/symbols.hpp213
-rw-r--r--tools/quickbook/src/syntax_highlight.cpp569
-rw-r--r--tools/quickbook/src/template_stack.cpp119
-rw-r--r--tools/quickbook/src/template_stack.hpp126
-rw-r--r--tools/quickbook/src/template_tags.hpp26
-rw-r--r--tools/quickbook/src/utils.cpp84
-rw-r--r--tools/quickbook/src/utils.hpp50
-rw-r--r--tools/quickbook/src/value_tags.hpp73
-rw-r--r--tools/quickbook/src/values.cpp853
-rw-r--r--tools/quickbook/src/values.hpp409
-rw-r--r--tools/quickbook/src/values_parse.hpp113
-rw-r--r--tools/quickbook/test/Jamfile.v2115
-rw-r--r--tools/quickbook/test/anchor-1_1.gold145
-rw-r--r--tools/quickbook/test/anchor-1_1.quickbook80
-rw-r--r--tools/quickbook/test/anchor-1_6.gold151
-rw-r--r--tools/quickbook/test/anchor-1_6.quickbook88
-rw-r--r--tools/quickbook/test/blocks-1_5.gold111
-rw-r--r--tools/quickbook/test/blocks-1_5.quickbook46
-rw-r--r--tools/quickbook/test/callouts-1_5.gold241
-rw-r--r--tools/quickbook/test/callouts-1_5.quickbook51
-rw-r--r--tools/quickbook/test/callouts.cpp50
-rw-r--r--tools/quickbook/test/code-1_1.gold52
-rw-r--r--tools/quickbook/test/code-1_1.quickbook51
-rw-r--r--tools/quickbook/test/code-1_5.gold37
-rw-r--r--tools/quickbook/test/code-1_5.quickbook29
-rw-r--r--tools/quickbook/test/code_cpp-1_5.gold27
-rw-r--r--tools/quickbook/test/code_cpp-1_5.quickbook22
-rw-r--r--tools/quickbook/test/code_cpp_mismatched_escape-1_4-fail.quickbook5
-rw-r--r--tools/quickbook/test/code_python-1_5.gold10
-rw-r--r--tools/quickbook/test/code_python-1_5.quickbook8
-rw-r--r--tools/quickbook/test/code_python_mismatched_escape-1_4-fail.quickbook5
-rw-r--r--tools/quickbook/test/code_snippet-1_1.gold22
-rw-r--r--tools/quickbook/test/code_snippet-1_1.quickbook12
-rw-r--r--tools/quickbook/test/code_teletype-1_5.gold12
-rw-r--r--tools/quickbook/test/code_teletype-1_5.quickbook13
-rw-r--r--tools/quickbook/test/command-line/Jamfile.v228
-rw-r--r--tools/quickbook/test/command-line/basic-1_6.quickbook5
-rw-r--r--tools/quickbook/test/command-line/error-fail.quickbook5
-rw-r--r--tools/quickbook/test/command-line/error1.quickbook3
-rw-r--r--tools/quickbook/test/command-line/error2.quickbook7
-rw-r--r--tools/quickbook/test/command_line_macro-1_1.gold12
-rw-r--r--tools/quickbook/test/command_line_macro-1_1.quickbook10
-rw-r--r--tools/quickbook/test/cond_phrase-1_5.gold15
-rw-r--r--tools/quickbook/test/cond_phrase-1_5.quickbook12
-rw-r--r--tools/quickbook/test/doc-info/Jamfile.v234
-rw-r--r--tools/quickbook/test/doc-info/author1.gold13
-rw-r--r--tools/quickbook/test/doc-info/author1.quickbook5
-rw-r--r--tools/quickbook/test/doc-info/author2.gold19
-rw-r--r--tools/quickbook/test/doc-info/author2.quickbook4
-rw-r--r--tools/quickbook/test/doc-info/copyright-fail1.quickbook4
-rw-r--r--tools/quickbook/test/doc-info/copyright-fail2.quickbook6
-rw-r--r--tools/quickbook/test/doc-info/copyright1.gold17
-rw-r--r--tools/quickbook/test/doc-info/copyright1.quickbook5
-rw-r--r--tools/quickbook/test/doc-info/duplicates-1.1.gold35
-rw-r--r--tools/quickbook/test/doc-info/duplicates-1.1.quickbook23
-rw-r--r--tools/quickbook/test/doc-info/duplicates-1.5.gold32
-rw-r--r--tools/quickbook/test/doc-info/duplicates-1.5.quickbook26
-rw-r--r--tools/quickbook/test/doc-info/empty-attributes.gold19
-rw-r--r--tools/quickbook/test/doc-info/empty-attributes.quickbook16
-rw-r--r--tools/quickbook/test/doc-info/empty_title-1_1.gold10
-rw-r--r--tools/quickbook/test/doc-info/empty_title-1_1.quickbook8
-rw-r--r--tools/quickbook/test/doc-info/empty_title-1_5.gold10
-rw-r--r--tools/quickbook/test/doc-info/empty_title-1_5.quickbook7
-rw-r--r--tools/quickbook/test/doc-info/empty_title-1_6.gold4
-rw-r--r--tools/quickbook/test/doc-info/empty_title-1_6.quickbook1
-rw-r--r--tools/quickbook/test/doc-info/encode-1.5.gold26
-rw-r--r--tools/quickbook/test/doc-info/encode-1.5.quickbook14
-rw-r--r--tools/quickbook/test/doc-info/escape-1.6.gold24
-rw-r--r--tools/quickbook/test/doc-info/escape-1.6.quickbook12
-rw-r--r--tools/quickbook/test/doc-info/id1-1.5.gold27
-rw-r--r--tools/quickbook/test/doc-info/id1-1.5.quickbook21
-rw-r--r--tools/quickbook/test/doc-info/id1-docinfo-no-id.quickbook5
-rw-r--r--tools/quickbook/test/doc-info/id1-no-docinfo.quickbook2
-rw-r--r--tools/quickbook/test/doc-info/missing_doc_info-1_6-fail.quickbook3
-rw-r--r--tools/quickbook/test/doc-info/source-mode-1.4.gold33
-rw-r--r--tools/quickbook/test/doc-info/source-mode-1.4.quickbook17
-rw-r--r--tools/quickbook/test/doc-info/source-mode-1.5.gold38
-rw-r--r--tools/quickbook/test/doc-info/source-mode-1.5.quickbook21
-rw-r--r--tools/quickbook/test/doc-info/source-mode-1.6.gold42
-rw-r--r--tools/quickbook/test/doc-info/source-mode-1.6.quickbook21
-rw-r--r--tools/quickbook/test/doc-info/source-mode-cpp-include.quickbook4
-rw-r--r--tools/quickbook/test/doc-info/source-mode-python-include.quickbook5
-rw-r--r--tools/quickbook/test/doc-info/source-mode-teletype-include.quickbook5
-rw-r--r--tools/quickbook/test/doc-info/title_trailing_space-1_1.gold9
-rw-r--r--tools/quickbook/test/doc-info/title_trailing_space-1_1.quickbook5
-rw-r--r--tools/quickbook/test/doc-info/title_trailing_space-1_6.gold9
-rw-r--r--tools/quickbook/test/doc-info/title_trailing_space-1_6.quickbook5
-rw-r--r--tools/quickbook/test/elements-1_5.gold18
-rw-r--r--tools/quickbook/test/elements-1_5.quickbook13
-rw-r--r--tools/quickbook/test/elements-1_6.gold32
-rw-r--r--tools/quickbook/test/elements-1_6.quickbook13
-rw-r--r--tools/quickbook/test/empty.qbk0
-rw-r--r--tools/quickbook/test/escape-1_1.gold32
-rw-r--r--tools/quickbook/test/escape-1_1.quickbook34
-rw-r--r--tools/quickbook/test/escape-1_6.gold32
-rw-r--r--tools/quickbook/test/escape-1_6.quickbook35
-rw-r--r--tools/quickbook/test/escape-mismatched-1_5-fail.quickbook5
-rw-r--r--tools/quickbook/test/heading-1_1.gold76
-rw-r--r--tools/quickbook/test/heading-1_1.quickbook55
-rw-r--r--tools/quickbook/test/heading-1_3.gold24
-rw-r--r--tools/quickbook/test/heading-1_3.quickbook16
-rw-r--r--tools/quickbook/test/heading-1_5.gold87
-rw-r--r--tools/quickbook/test/heading-1_5.quickbook57
-rw-r--r--tools/quickbook/test/heading-1_6.gold109
-rw-r--r--tools/quickbook/test/heading-1_6.quickbook80
-rw-r--r--tools/quickbook/test/heading_unclosed-1_4-fail.quickbook3
-rw-r--r--tools/quickbook/test/hr-1_5.gold34
-rw-r--r--tools/quickbook/test/hr-1_5.quickbook27
-rw-r--r--tools/quickbook/test/hr-1_6.gold39
-rw-r--r--tools/quickbook/test/hr-1_6.quickbook26
-rw-r--r--tools/quickbook/test/html/images/open_clipart_library_logo.svg143
-rw-r--r--tools/quickbook/test/identifier-1_5.gold610
-rw-r--r--tools/quickbook/test/identifier-1_5.quickbook148
-rw-r--r--tools/quickbook/test/identifier-1_6.gold609
-rw-r--r--tools/quickbook/test/identifier-1_6.quickbook148
-rw-r--r--tools/quickbook/test/image-1_5.gold64
-rw-r--r--tools/quickbook/test/image-1_5.quickbook19
-rw-r--r--tools/quickbook/test/image-1_6.gold46
-rw-r--r--tools/quickbook/test/image-1_6.quickbook20
-rw-r--r--tools/quickbook/test/import-1_1-fail.quickbook8
-rw-r--r--tools/quickbook/test/include-1_1-fail.quickbook8
-rw-r--r--tools/quickbook/test/include-1_5.gold30
-rw-r--r--tools/quickbook/test/include-1_5.quickbook17
-rw-r--r--tools/quickbook/test/include-1_6.gold30
-rw-r--r--tools/quickbook/test/include-1_6.quickbook15
-rw-r--r--tools/quickbook/test/include/Jamfile.v244
-rw-r--r--tools/quickbook/test/include/code-import.gold138
-rw-r--r--tools/quickbook/test/include/code-import.quickbook13
-rw-r--r--tools/quickbook/test/include/code-include.gold50
-rw-r--r--tools/quickbook/test/include/code-include.quickbook16
-rw-r--r--tools/quickbook/test/include/compatibility-1_1.gold362
-rw-r--r--tools/quickbook/test/include/compatibility-1_1.quickbook18
-rw-r--r--tools/quickbook/test/include/compatibility-1_5.gold362
-rw-r--r--tools/quickbook/test/include/compatibility-1_5.quickbook18
-rw-r--r--tools/quickbook/test/include/compatibility-1_6.gold362
-rw-r--r--tools/quickbook/test/include/compatibility-1_6.quickbook17
-rw-r--r--tools/quickbook/test/include/compatibility-inc.qbk31
-rw-r--r--tools/quickbook/test/include/compatibility-inc_1_1.qbk33
-rw-r--r--tools/quickbook/test/include/compatibility-inc_1_5.qbk33
-rw-r--r--tools/quickbook/test/include/compatibility-inc_1_6.qbk33
-rw-r--r--tools/quickbook/test/include/doc-title1-1.5.gold27
-rw-r--r--tools/quickbook/test/include/doc-title1-1.5.quickbook27
-rw-r--r--tools/quickbook/test/include/doc-title1-inc1.quickbook1
-rw-r--r--tools/quickbook/test/include/doc-title1-inc2.quickbook4
-rw-r--r--tools/quickbook/test/include/doc-title1-inc3.quickbook1
-rw-r--r--tools/quickbook/test/include/doc-title1a-1.5.gold26
-rw-r--r--tools/quickbook/test/include/doc-title1a-1.5.quickbook20
-rw-r--r--tools/quickbook/test/include/filename-path.gold18
-rw-r--r--tools/quickbook/test/include/filename-path.quickbook9
-rw-r--r--tools/quickbook/test/include/filename.gold18
-rw-r--r--tools/quickbook/test/include/filename.quickbook9
-rw-r--r--tools/quickbook/test/include/filename_include2.quickbook1
-rw-r--r--tools/quickbook/test/include/import-basic-1.6.gold11
-rw-r--r--tools/quickbook/test/include/import-basic-1.6.quickbook12
-rw-r--r--tools/quickbook/test/include/import-basic-inc1.quickbook4
-rw-r--r--tools/quickbook/test/include/import-basic-inc2.quickbook10
-rw-r--r--tools/quickbook/test/include/in_section-1_5.gold66
-rw-r--r--tools/quickbook/test/include/in_section-1_5.quickbook16
-rw-r--r--tools/quickbook/test/include/in_section-1_6.gold90
-rw-r--r--tools/quickbook/test/include/in_section-1_6.quickbook16
-rw-r--r--tools/quickbook/test/include/in_section-include1.qbk11
-rw-r--r--tools/quickbook/test/include/in_section-include2.qbk12
-rw-r--r--tools/quickbook/test/include/include-id-1.5.gold26
-rw-r--r--tools/quickbook/test/include/include-id-1.5.quickbook10
-rw-r--r--tools/quickbook/test/include/include-id-1.6.gold36
-rw-r--r--tools/quickbook/test/include/include-id-1.6.quickbook10
-rw-r--r--tools/quickbook/test/include/include-id-inc1.quickbook1
-rw-r--r--tools/quickbook/test/include/include-id-inc2.quickbook5
-rw-r--r--tools/quickbook/test/include/include-id-inc3.quickbook6
-rw-r--r--tools/quickbook/test/include/include_id_unbalanced-1_6.gold59
-rw-r--r--tools/quickbook/test/include/include_id_unbalanced-1_6.quickbook19
-rw-r--r--tools/quickbook/test/include/include_id_unbalanced-inc1.qbk4
-rw-r--r--tools/quickbook/test/include/include_id_unbalanced-inc1a.qbk3
-rw-r--r--tools/quickbook/test/include/include_id_unbalanced-inc2.qbk5
-rw-r--r--tools/quickbook/test/include/include_id_unbalanced-inc2a.qbk3
-rw-r--r--tools/quickbook/test/include/macros-1.5.gold39
-rw-r--r--tools/quickbook/test/include/macros-1.5.quickbook13
-rw-r--r--tools/quickbook/test/include/macros-1.6.gold66
-rw-r--r--tools/quickbook/test/include/macros-1.6.quickbook21
-rw-r--r--tools/quickbook/test/include/macros-inc1.quickbook15
-rw-r--r--tools/quickbook/test/include/nested_compatibility-1_5.gold48
-rw-r--r--tools/quickbook/test/include/nested_compatibility-1_5.quickbook12
-rw-r--r--tools/quickbook/test/include/nested_compatibility-1_6.gold48
-rw-r--r--tools/quickbook/test/include/nested_compatibility-1_6.quickbook12
-rw-r--r--tools/quickbook/test/include/nested_compatibility_inc-1_5.qbk5
-rw-r--r--tools/quickbook/test/include/nested_compatibility_inc-1_6.qbk5
-rw-r--r--tools/quickbook/test/include/section-fail1.quickbook6
-rw-r--r--tools/quickbook/test/include/section-fail2.quickbook5
-rw-r--r--tools/quickbook/test/include/section-inc1.quickbook1
-rw-r--r--tools/quickbook/test/include/section-inc2.quickbook1
-rw-r--r--tools/quickbook/test/include/section-unclosed.gold10
-rw-r--r--tools/quickbook/test/include/section-unclosed.quickbook5
-rw-r--r--tools/quickbook/test/include/section.gold10
-rw-r--r--tools/quickbook/test/include/section.quickbook6
-rw-r--r--tools/quickbook/test/include/source_mode-1_5.gold7
-rw-r--r--tools/quickbook/test/include/source_mode-1_5.quickbook3
-rw-r--r--tools/quickbook/test/include/source_mode-1_6.gold11
-rw-r--r--tools/quickbook/test/include/source_mode-1_6.quickbook4
-rw-r--r--tools/quickbook/test/include/source_mode-inc1.qbk3
-rw-r--r--tools/quickbook/test/include/sub/filename_include1.quickbook3
-rw-r--r--tools/quickbook/test/include/templates-1.5.gold12
-rw-r--r--tools/quickbook/test/include/templates-1.5.quickbook7
-rw-r--r--tools/quickbook/test/include/templates-1.6.gold15
-rw-r--r--tools/quickbook/test/include/templates-1.6.quickbook11
-rw-r--r--tools/quickbook/test/include/templates-inc1.quickbook4
-rw-r--r--tools/quickbook/test/include2-1_6.gold22
-rw-r--r--tools/quickbook/test/include2-1_6.quickbook8
-rw-r--r--tools/quickbook/test/include_sub-1_5.qbk6
-rw-r--r--tools/quickbook/test/include_sub.qbk9
-rw-r--r--tools/quickbook/test/include_win_path-1_6-fail.quickbook5
-rw-r--r--tools/quickbook/test/link-1_1.gold34
-rw-r--r--tools/quickbook/test/link-1_1.quickbook41
-rw-r--r--tools/quickbook/test/link-1_6.gold38
-rw-r--r--tools/quickbook/test/link-1_6.quickbook45
-rw-r--r--tools/quickbook/test/list_test-1_5.gold386
-rw-r--r--tools/quickbook/test/list_test-1_5.quickbook100
-rw-r--r--tools/quickbook/test/list_test-1_6.gold476
-rw-r--r--tools/quickbook/test/list_test-1_6.quickbook128
-rw-r--r--tools/quickbook/test/macro-1_5.gold26
-rw-r--r--tools/quickbook/test/macro-1_5.quickbook34
-rw-r--r--tools/quickbook/test/macro-1_6.gold26
-rw-r--r--tools/quickbook/test/macro-1_6.quickbook34
-rw-r--r--tools/quickbook/test/mismatched_brackets-1_1-fail.quickbook5
-rw-r--r--tools/quickbook/test/mismatched_brackets1-1_1.gold12
-rw-r--r--tools/quickbook/test/mismatched_brackets1-1_1.quickbook7
-rw-r--r--tools/quickbook/test/mismatched_brackets2-1_1.gold9
-rw-r--r--tools/quickbook/test/mismatched_brackets2-1_1.quickbook7
-rw-r--r--tools/quickbook/test/newline-1_1.gold24
-rw-r--r--tools/quickbook/test/newline-1_1.quickbook10
-rw-r--r--tools/quickbook/test/para_test-1_5.gold75
-rw-r--r--tools/quickbook/test/para_test-1_5.quickbook81
-rw-r--r--tools/quickbook/test/post_process-fail.quickbook3
-rw-r--r--tools/quickbook/test/preformatted-1_1.gold40
-rw-r--r--tools/quickbook/test/preformatted-1_1.quickbook32
-rw-r--r--tools/quickbook/test/preformatted-1_6.gold40
-rw-r--r--tools/quickbook/test/preformatted-1_6.quickbook33
-rw-r--r--tools/quickbook/test/quickbook-testing.jam141
-rw-r--r--tools/quickbook/test/quickbook_manual-1_4.gold3945
-rw-r--r--tools/quickbook/test/quickbook_manual-1_4.quickbook1981
-rw-r--r--tools/quickbook/test/role-1_6.gold9
-rw-r--r--tools/quickbook/test/role-1_6.quickbook5
-rw-r--r--tools/quickbook/test/section-1_4.gold20
-rw-r--r--tools/quickbook/test/section-1_4.quickbook12
-rw-r--r--tools/quickbook/test/section-1_5-unclosed.gold10
-rw-r--r--tools/quickbook/test/section-1_5-unclosed.quickbook5
-rw-r--r--tools/quickbook/test/section-1_5.gold19
-rw-r--r--tools/quickbook/test/section-1_5.quickbook12
-rw-r--r--tools/quickbook/test/simple_markup-1_5.gold58
-rw-r--r--tools/quickbook/test/simple_markup-1_5.quickbook42
-rw-r--r--tools/quickbook/test/snippets/Jamfile.v218
-rw-r--r--tools/quickbook/test/snippets/pass_thru.cpp31
-rw-r--r--tools/quickbook/test/snippets/pass_thru.gold35
-rw-r--r--tools/quickbook/test/snippets/pass_thru.py13
-rw-r--r--tools/quickbook/test/snippets/pass_thru.quickbook12
-rw-r--r--tools/quickbook/test/snippets/unbalanced_snippet1-1_5.gold10
-rw-r--r--tools/quickbook/test/snippets/unbalanced_snippet1-1_5.quickbook8
-rw-r--r--tools/quickbook/test/snippets/unbalanced_snippet1-1_6-fail.quickbook7
-rw-r--r--tools/quickbook/test/snippets/unbalanced_snippet1.cpp3
-rw-r--r--tools/quickbook/test/snippets/unbalanced_snippet2-1_6-fail.quickbook5
-rw-r--r--tools/quickbook/test/snippets/unbalanced_snippet2.cpp1
-rw-r--r--tools/quickbook/test/src/Jamfile.v29
-rw-r--r--tools/quickbook/test/src/text_diff.cpp84
-rw-r--r--tools/quickbook/test/stub.c32
-rw-r--r--tools/quickbook/test/stub.cpp84
-rw-r--r--tools/quickbook/test/stub.py27
-rw-r--r--tools/quickbook/test/svg-1_1.gold18
-rw-r--r--tools/quickbook/test/svg-1_1.quickbook4
-rw-r--r--tools/quickbook/test/table-1_3.gold351
-rw-r--r--tools/quickbook/test/table-1_3.quickbook113
-rw-r--r--tools/quickbook/test/table-1_5.gold442
-rw-r--r--tools/quickbook/test/table-1_5.quickbook133
-rw-r--r--tools/quickbook/test/table-1_6.gold478
-rw-r--r--tools/quickbook/test/table-1_6.quickbook134
-rw-r--r--tools/quickbook/test/template_arguments1-1_1-fail.quickbook10
-rw-r--r--tools/quickbook/test/template_arguments2-1_1-fail.quickbook10
-rw-r--r--tools/quickbook/test/template_arguments3-1_1-fail.quickbook6
-rw-r--r--tools/quickbook/test/template_section-1_5.gold22
-rw-r--r--tools/quickbook/test/template_section-1_5.quickbook20
-rw-r--r--tools/quickbook/test/template_section1-1_5-fail.quickbook9
-rw-r--r--tools/quickbook/test/template_section2-1_5-fail.quickbook10
-rw-r--r--tools/quickbook/test/template_section3-1_5-fail.quickbook9
-rw-r--r--tools/quickbook/test/templates-1_3.gold191
-rw-r--r--tools/quickbook/test/templates-1_3.quickbook200
-rw-r--r--tools/quickbook/test/templates-1_4.gold21
-rw-r--r--tools/quickbook/test/templates-1_4.quickbook37
-rw-r--r--tools/quickbook/test/templates-1_5.gold42
-rw-r--r--tools/quickbook/test/templates-1_5.quickbook72
-rw-r--r--tools/quickbook/test/unicode_escape-1_5.gold156
-rw-r--r--tools/quickbook/test/unicode_escape-1_5.quickbook37
-rw-r--r--tools/quickbook/test/unit/Jamfile.v223
-rw-r--r--tools/quickbook/test/unit/post_process_test.cpp30
-rw-r--r--tools/quickbook/test/unit/symbols_find_null.cpp35
-rw-r--r--tools/quickbook/test/unit/symbols_tests.cpp406
-rw-r--r--tools/quickbook/test/unit/values_test.cpp125
-rw-r--r--tools/quickbook/test/unmatched_element-1_5.gold12
-rw-r--r--tools/quickbook/test/unmatched_element-1_5.quickbook12
-rw-r--r--tools/quickbook/test/unmatched_element-1_6.gold12
-rw-r--r--tools/quickbook/test/unmatched_element-1_6.quickbook12
-rw-r--r--tools/quickbook/test/utf16be_bom-1_5-fail.quickbookbin0 -> 664 bytes
-rw-r--r--tools/quickbook/test/utf16le_bom-1_5-fail.quickbookbin0 -> 664 bytes
-rw-r--r--tools/quickbook/test/utf8-1_5.gold130
-rw-r--r--tools/quickbook/test/utf8-1_5.quickbook30
-rw-r--r--tools/quickbook/test/utf8_bom-1_5.gold130
-rw-r--r--tools/quickbook/test/utf8_bom-1_5.quickbook30
-rw-r--r--tools/quickbook/test/variablelist-1_5-fail.quickbook5
-rw-r--r--tools/quickbook/test/variablelist-1_5.gold107
-rw-r--r--tools/quickbook/test/variablelist-1_5.quickbook30
-rw-r--r--tools/quickbook/test/version-0_1-fail.quickbook5
-rw-r--r--tools/quickbook/test/version-1_7-fail.quickbook5
-rw-r--r--tools/quickbook/test/version-2_0-fail.quickbook5
-rw-r--r--tools/quickbook/test/versions/Jamfile.v219
-rw-r--r--tools/quickbook/test/versions/invalid_macro-1_6.gold36
-rw-r--r--tools/quickbook/test/versions/invalid_macro-1_6.quickbook14
-rw-r--r--tools/quickbook/test/versions/invalid_macro-inc-1_1.qbk7
-rw-r--r--tools/quickbook/test/versions/templates-1_1.qbk15
-rw-r--r--tools/quickbook/test/versions/templates-1_4.qbk20
-rw-r--r--tools/quickbook/test/versions/templates-1_5.qbk19
-rw-r--r--tools/quickbook/test/versions/versions-1_6.gold114
-rw-r--r--tools/quickbook/test/versions/versions-1_6.quickbook26
-rw-r--r--tools/quickbook/test/xinclude/Jamfile.v227
-rw-r--r--tools/quickbook/test/xinclude/sub/stub.xml0
-rw-r--r--tools/quickbook/test/xinclude/xinclude-1_1-alt.gold8
-rw-r--r--tools/quickbook/test/xinclude/xinclude-1_1.gold8
-rw-r--r--tools/quickbook/test/xinclude/xinclude-1_1.quickbook5
-rw-r--r--tools/quickbook/test/xinclude/xmlbase-1_6-fail.quickbook4
-rw-r--r--tools/quickbook/test/xinclude/xmlbase1-1_6-alt.gold9
-rw-r--r--tools/quickbook/test/xinclude/xmlbase1-1_6.gold9
-rw-r--r--tools/quickbook/test/xinclude/xmlbase1-1_6.quickbook8
-rw-r--r--tools/quickbook/test/xinclude/xmlbase2-1_6-alt.gold9
-rw-r--r--tools/quickbook/test/xinclude/xmlbase2-1_6.gold9
-rw-r--r--tools/quickbook/test/xinclude/xmlbase2-1_6.quickbook8
-rw-r--r--tools/quickbook/test/xml_escape-1_2.gold42
-rw-r--r--tools/quickbook/test/xml_escape-1_2.quickbook14
-rw-r--r--tools/quickbook/test/xml_escape-1_5.gold43
-rw-r--r--tools/quickbook/test/xml_escape-1_5.quickbook14
-rw-r--r--tools/regression/build/Jamroot.jam84
-rw-r--r--tools/regression/build/vcide/compiler_status.vcproj59
-rw-r--r--tools/regression/build/vcide/library_status.vcproj64
-rw-r--r--tools/regression/build/vcide/process_jam_log.sln21
-rw-r--r--tools/regression/build/vcide/process_jam_log.vcproj72
-rw-r--r--tools/regression/build/vcide/regression.sln37
-rw-r--r--tools/regression/doc/index.html57
-rw-r--r--tools/regression/doc/library_status.html464
-rw-r--r--tools/regression/index.html23
-rwxr-xr-xtools/regression/src/boost_svn_export_archive.sh70
-rw-r--r--tools/regression/src/collect_and_upload_logs.py546
-rw-r--r--tools/regression/src/compiler_status.cpp1113
-rw-r--r--tools/regression/src/detail/tiny_xml.cpp167
-rw-r--r--tools/regression/src/detail/tiny_xml.hpp70
-rw-r--r--tools/regression/src/detail/tiny_xml_test.cpp17
-rw-r--r--tools/regression/src/detail/tiny_xml_test.txt17
-rw-r--r--tools/regression/src/library_status.cpp991
-rw-r--r--tools/regression/src/library_test.bat21
-rwxr-xr-xtools/regression/src/library_test.sh19
-rwxr-xr-xtools/regression/src/library_test_all.sh85
-rw-r--r--tools/regression/src/process_jam_log.cpp893
-rwxr-xr-xtools/regression/src/process_jam_log.py468
-rw-r--r--tools/regression/src/regression-logs.pl197
-rw-r--r--tools/regression/src/regression.py908
-rw-r--r--tools/regression/src/run.py60
-rw-r--r--tools/regression/src/run_tests.sh197
-rwxr-xr-xtools/regression/src/smoke.py197
-rw-r--r--tools/regression/test/Jamfile.v227
-rw-r--r--tools/regression/test/compile-fail_fail.cpp10
-rw-r--r--tools/regression/test/compile-fail_pass.cpp9
-rw-r--r--tools/regression/test/compile_fail.cpp9
-rw-r--r--tools/regression/test/compile_pass.cpp9
-rw-r--r--tools/regression/test/compile_warn.cpp18
-rw-r--r--tools/regression/test/run-fail_compile-fail.cpp9
-rw-r--r--tools/regression/test/run-fail_fail-warn.cpp16
-rw-r--r--tools/regression/test/run-fail_fail.cpp12
-rw-r--r--tools/regression/test/run-fail_pass.cpp15
-rw-r--r--tools/regression/test/run-fail_warn.cpp20
-rw-r--r--tools/regression/test/run_compile-fail.cpp9
-rw-r--r--tools/regression/test/run_fail-note.cpp17
-rw-r--r--tools/regression/test/run_fail-warn.cpp20
-rw-r--r--tools/regression/test/run_fail.cpp14
-rw-r--r--tools/regression/test/run_note.cpp17
-rw-r--r--tools/regression/test/run_pass.cpp12
-rw-r--r--tools/regression/test/run_warn-note.cpp24
-rw-r--r--tools/regression/test/run_warn.cpp18
-rw-r--r--tools/regression/test/test-boost-build/ignored_rc/ignored_rc.jam11
-rw-r--r--tools/regression/test/test-boost-build/ignored_rc/recognized_rc.jam12
-rw-r--r--tools/regression/test/test-boost-build/missing_dependencies/Jamfile.v29
-rw-r--r--tools/regression/test/test-boost-build/missing_dependencies/lib/Jamfile.v27
-rw-r--r--tools/regression/test/test-boost-build/missing_dependencies/lib/lib.cpp1
-rw-r--r--tools/regression/test/test-boost-build/missing_dependencies/test.cpp1
-rw-r--r--tools/regression/test/test-cases/Huber2629/bjam.log36
-rw-r--r--tools/regression/test/test-cases/Huber2629/expected/results.xml27
-rw-r--r--tools/regression/test/test-cases/general/bjam.log325
-rw-r--r--tools/regression/test/test-cases/general/expected/results.xml167
-rw-r--r--tools/regression/test/test-cases/incremental/bjam.log33
-rw-r--r--tools/regression/test/test-cases/incremental/bjam.log.138
-rw-r--r--tools/regression/test/test-cases/incremental/expected/results.xml9
-rw-r--r--tools/regression/test/test.bat15
-rw-r--r--tools/regression/test/test.py181
-rw-r--r--tools/regression/xsl_reports/README.txt27
-rw-r--r--tools/regression/xsl_reports/boost_wide_report.py835
-rw-r--r--tools/regression/xsl_reports/boostbook_report.py179
-rwxr-xr-xtools/regression/xsl_reports/build_results.sh146
-rw-r--r--tools/regression/xsl_reports/email_maintainers.py840
-rw-r--r--tools/regression/xsl_reports/empty_expected_results.xml5
-rw-r--r--tools/regression/xsl_reports/make_snapshot.py174
-rw-r--r--tools/regression/xsl_reports/report.py371
-rw-r--r--tools/regression/xsl_reports/test/common.py165
-rw-r--r--tools/regression/xsl_reports/test/expected_results.xml3
-rw-r--r--tools/regression/xsl_reports/test/generate_test_results.py160
-rw-r--r--tools/regression/xsl_reports/test/generate_test_results_v1.py85
-rw-r--r--tools/regression/xsl_reports/test/restrict_to_library.xsl36
-rw-r--r--tools/regression/xsl_reports/test/run_notes_regression.py32
-rw-r--r--tools/regression/xsl_reports/test/run_v1.py35
-rw-r--r--tools/regression/xsl_reports/test/test.py34
-rw-r--r--tools/regression/xsl_reports/test/test_boost_wide_report.py36
-rw-r--r--tools/regression/xsl_reports/test_results.xsd107
-rw-r--r--tools/regression/xsl_reports/utils/__init__.py13
-rw-r--r--tools/regression/xsl_reports/utils/accept_args.py30
-rw-r--r--tools/regression/xsl_reports/utils/char_translation_table.py13
-rw-r--r--tools/regression/xsl_reports/utils/check_existance.py9
-rw-r--r--tools/regression/xsl_reports/utils/checked_system.py22
-rw-r--r--tools/regression/xsl_reports/utils/libxslt.py49
-rw-r--r--tools/regression/xsl_reports/utils/log.py18
-rw-r--r--tools/regression/xsl_reports/utils/makedirs.py7
-rw-r--r--tools/regression/xsl_reports/utils/rename.py17
-rw-r--r--tools/regression/xsl_reports/utils/send_mail.py13
-rw-r--r--tools/regression/xsl_reports/utils/sourceforge.py48
-rw-r--r--tools/regression/xsl_reports/utils/tar.py16
-rw-r--r--tools/regression/xsl_reports/utils/zip.py12
-rw-r--r--tools/regression/xsl_reports/xsl/add_expected_results.xsl144
-rw-r--r--tools/regression/xsl_reports/xsl/common.xsl182
-rw-r--r--tools/regression/xsl_reports/xsl/html/issues_legend.html36
-rw-r--r--tools/regression/xsl_reports/xsl/html/library_developer_legend.html72
-rw-r--r--tools/regression/xsl_reports/xsl/html/library_user_legend.html65
-rw-r--r--tools/regression/xsl_reports/xsl/html/make_tinyurl.html24
-rw-r--r--tools/regression/xsl_reports/xsl/html/master.css525
-rw-r--r--tools/regression/xsl_reports/xsl/html/summary_developer_legend.html75
-rw-r--r--tools/regression/xsl_reports/xsl/html/summary_user_legend.html65
-rw-r--r--tools/regression/xsl_reports/xsl/issues_page.xsl223
-rw-r--r--tools/regression/xsl_reports/xsl/links_page.xsl134
-rw-r--r--tools/regression/xsl_reports/xsl/produce_expected_results.xsl31
-rw-r--r--tools/regression/xsl_reports/xsl/result_page.xsl702
-rw-r--r--tools/regression/xsl_reports/xsl/summary_page.xsl361
-rw-r--r--tools/regression/xsl_reports/xsl/test/test_re_match.xml57
-rw-r--r--tools/regression/xsl_reports/xsl/test/test_re_match.xsl60
-rw-r--r--tools/regression/xsl_reports/xsl/v2/add_expected_results.xsl270
-rw-r--r--tools/regression/xsl_reports/xsl/v2/boostbook_log.xsl42
-rw-r--r--tools/regression/xsl_reports/xsl/v2/common.xsl668
-rw-r--r--tools/regression/xsl_reports/xsl/v2/dump_toolsets.xsl39
-rw-r--r--tools/regression/xsl_reports/xsl/v2/expected_to_1_33_format.xsl32
-rw-r--r--tools/regression/xsl_reports/xsl/v2/html/issues_legend.html36
-rw-r--r--tools/regression/xsl_reports/xsl/v2/html/library_developer_legend.html82
-rw-r--r--tools/regression/xsl_reports/xsl/v2/html/library_user_legend.html89
-rw-r--r--tools/regression/xsl_reports/xsl/v2/html/make_tinyurl.html22
-rw-r--r--tools/regression/xsl_reports/xsl/v2/html/master.css654
-rw-r--r--tools/regression/xsl_reports/xsl/v2/html/summary_developer_legend.html72
-rw-r--r--tools/regression/xsl_reports/xsl/v2/html/summary_user_legend.html76
-rw-r--r--tools/regression/xsl_reports/xsl/v2/issues_page.xsl327
-rw-r--r--tools/regression/xsl_reports/xsl/v2/links_page.xsl399
-rw-r--r--tools/regression/xsl_reports/xsl/v2/produce_expected_results.xsl36
-rw-r--r--tools/regression/xsl_reports/xsl/v2/result_page.xsl691
-rw-r--r--tools/regression/xsl_reports/xsl/v2/runners.xsl56
-rw-r--r--tools/regression/xsl_reports/xsl/v2/summary_page.xsl367
-rw-r--r--tools/release/2release.bat16
-rw-r--r--tools/release/README11
-rw-r--r--tools/release/bjam_warnings.bat17
-rwxr-xr-xtools/release/build_docs.sh20
-rwxr-xr-xtools/release/build_release.sh20
-rw-r--r--tools/release/build_release_packages.bat47
-rwxr-xr-xtools/release/build_release_packages.sh43
-rw-r--r--tools/release/index.html64
-rwxr-xr-xtools/release/inspect.sh31
-rw-r--r--tools/release/inspect_trunk.bat42
-rw-r--r--tools/release/linux_user-config.jam21
-rwxr-xr-xtools/release/load_posix.sh10
-rwxr-xr-xtools/release/load_windows.sh10
-rwxr-xr-xtools/release/make_packages.sh45
-rw-r--r--tools/release/merge2release.bat22
-rw-r--r--tools/release/merge_release_cycle_init.bat16
-rw-r--r--tools/release/release-mgt-msvc/compare_trees/compare_trees.vcproj197
-rw-r--r--tools/release/release-mgt-msvc/msvc.sln26
-rw-r--r--tools/release/release-mgt-msvc/strftime/strftime.vcproj193
-rwxr-xr-xtools/release/release_reports.sh31
-rw-r--r--tools/release/revision_number.bat13
-rw-r--r--tools/release/snapshot.bat39
-rwxr-xr-xtools/release/snapshot.sh16
-rw-r--r--tools/release/snapshot_download_docs.bat31
-rwxr-xr-xtools/release/snapshot_inspect.sh31
-rw-r--r--tools/release/snapshot_inspection.bat28
-rw-r--r--tools/release/snapshot_posix.bat69
-rwxr-xr-xtools/release/snapshot_posix.sh65
-rw-r--r--tools/release/snapshot_windows.bat75
-rwxr-xr-xtools/release/snapshot_windows.sh58
-rw-r--r--tools/release/strftime.cpp68
-rw-r--r--tools/release/unmerged.bat17
-rw-r--r--tools/release/unmerged_all.bat86
-rw-r--r--tools/release/unmerged_whatever.bat13
-rw-r--r--tools/release/upload2sourceforge.bat13
-rw-r--r--tools/wave/build/Jamfile.v269
-rw-r--r--tools/wave/cpp.cpp1436
-rw-r--r--tools/wave/cpp.hpp43
-rw-r--r--tools/wave/cpp_config.hpp63
-rw-r--r--tools/wave/cpp_version.hpp25
-rw-r--r--tools/wave/stop_watch.hpp84
-rw-r--r--tools/wave/trace_macro_expansion.hpp1481
1716 files changed, 353197 insertions, 0 deletions
diff --git a/tools/Jamfile.v2 b/tools/Jamfile.v2
new file mode 100644
index 0000000000..d7fab287a8
--- /dev/null
+++ b/tools/Jamfile.v2
@@ -0,0 +1,57 @@
+# Copyright 2005 Rene Rivera
+# Copyright 2005 Hartmut Kaiser
+# Copyright 2005 John Maddock
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+# Jamfile which builds all the tools.
+
+project
+ :
+ requirements
+ <link>static
+ ;
+
+use-project /boost/regression : regression/build ;
+
+TOOLS =
+ bcp//bcp
+ inspect/build//inspect
+ quickbook//quickbook
+ /boost/regression//compiler_status
+ /boost/regression//library_status
+ /boost/regression//process_jam_log
+ wave/build//wave
+ ;
+
+install dist-bin
+ :
+ $(TOOLS)
+ :
+ <install-type>EXE
+ <location>../dist/bin
+ :
+ release
+ ;
+
+install dist-lib
+ :
+ $(TOOLS)
+ :
+ <install-type>LIB
+ <location>../dist/lib
+ :
+ release
+ ;
+
+local patterns = *.dtd *.xml *.xsl LICENSE ;
+local dirs = boostbook/dtd boostbook/xsl ;
+install dist-share-boostbook
+ :
+ [ glob $(dirs)/$(patterns) $(dirs)/*/$(patterns) $(dirs)/*/*/$(patterns) ]
+ :
+ <location>../dist/share
+ <install-source-root>.
+ ;
diff --git a/tools/auto_index/build/Jamfile.v2 b/tools/auto_index/build/Jamfile.v2
new file mode 100644
index 0000000000..2c229f2ef8
--- /dev/null
+++ b/tools/auto_index/build/Jamfile.v2
@@ -0,0 +1,33 @@
+import quickbook ;
+import modules ;
+
+exe auto_index :
+ ../src/auto_index.cpp
+ ../src/file_scanning.cpp
+ ../src/index_generator.cpp
+ ../src/tiny_xml.cpp
+ /boost//regex
+ /boost//filesystem
+ /boost//system
+ /boost//program_options
+: <define>BOOST_ALL_NO_LIB=1 <link>static release ;
+
+install aii : auto_index : <location>. ;
+install i : auto_index : <location>../../../dist/bin ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/auto_index/doc/Jamfile.v2 b/tools/auto_index/doc/Jamfile.v2
new file mode 100644
index 0000000000..e510b7dffb
--- /dev/null
+++ b/tools/auto_index/doc/Jamfile.v2
@@ -0,0 +1,86 @@
+# Copyright John Maddock 2005. Use, modification, and distribution are
+# subject to the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+using quickbook ;
+using auto-index ;
+import modules ;
+
+path-constant images_location : html ;
+
+xml auto_index : auto_index.qbk ;
+
+boostbook standalone
+ :
+ auto_index
+ :
+ # Path for links to Boost:
+ <xsl:param>boost.root=../../../..
+ # Path for libraries index:
+ <xsl:param>boost.libraries=$(boost-root)/libs/libraries.htm
+
+ # Some general style settings:
+ <xsl:param>table.footnote.number.format=1
+ <xsl:param>footnote.number.format=1
+
+ # HTML options first:
+ # Use graphics not text for navigation:
+ <xsl:param>navig.graphics=1
+ # How far down we chunk nested sections, basically all of them:
+ <xsl:param>chunk.section.depth=10
+ # Don't put the first section on the same page as the TOC:
+ <xsl:param>chunk.first.sections=1
+ # How far down sections get TOC's
+ <xsl:param>toc.section.depth=10
+ # Max depth in each TOC:
+ <xsl:param>toc.max.depth=4
+ # How far down we go with TOC's
+ <xsl:param>generate.section.toc.level=10
+ # Index on type:
+ <xsl:param>index.on.type=1
+
+ # PDF Options:
+ # TOC Generation: this is needed for FOP-0.9 and later:
+ <xsl:param>fop1.extensions=0
+ <format>pdf:<xsl:param>xep.extensions=1
+ # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
+ <format>pdf:<xsl:param>fop.extensions=0
+ # No indent on body text:
+ <format>pdf:<xsl:param>body.start.indent=0pt
+ # Margin size:
+ <format>pdf:<xsl:param>page.margin.inner=0.5in
+ # Margin size:
+ <format>pdf:<xsl:param>page.margin.outer=0.5in
+ # Paper type = A4
+ <format>pdf:<xsl:param>paper.type=A4
+ # Yes, we want graphics for admonishments:
+ <xsl:param>admon.graphics=1
+ # Set this one for PDF generation *only*:
+ # default pnd graphics are awful in PDF form,
+ # better use SVG's instead:
+ <format>pdf:<xsl:param>admon.graphics.extension=".svg"
+ <format>pdf:<xsl:param>use.role.for.mediaobject=1
+ <format>pdf:<xsl:param>preferred.mediaobject.role=print
+ <format>pdf:<xsl:param>img.src.path=$(images_location)/
+ <format>pdf:<xsl:param>admon.graphics.path=$(images_location)/images/
+ <format>pdf:<xsl:param>draft.mode="no"
+ # Choose indexing method (separately for html and pdf):
+ <format>html:<auto-index-internal>on # on (or off) to use internally generated indexes.
+
+ <format>pdf:<auto-index-internal>off # on (or off) to use internally generated indexes.
+ :
+ # Default build options, can be overridden on the command line.
+ <auto-index>on # Turns on index (or off).
+ # Turns on (or off) index-verbose for diagnostic info (using /bin auto-index-verbose folders).
+ <auto-index-verbose>on
+
+ <xsl:param>index.on.type=1 # = 1 For the native stylesheets to generate multiple different indexes.
+ # PDF native index support is probably better for PDFs as then you actually get page numbers.
+
+ <auto-index-script>autoindex.idx # Specifies the name of the script to load for mylibrary.
+ ;
+
+install pdf-install : standalone : <install-type>PDF <location>. <name>auto_index.pdf ;
+
+
+
diff --git a/tools/auto_index/doc/auto_index.qbk b/tools/auto_index/doc/auto_index.qbk
new file mode 100644
index 0000000000..17e5fb89e7
--- /dev/null
+++ b/tools/auto_index/doc/auto_index.qbk
@@ -0,0 +1,1149 @@
+[article Boost.AutoIndex
+ [quickbook 1.5]
+ [copyright 2008, 2011 John Maddock]
+ [license
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ [@http://www.boost.org/LICENSE_1_0.txt])
+ ]
+ [authors [Maddock, John]]
+ [/last-revision $Date: 2008-11-04 17:11:53 +0000 (Tue, 04 Nov 2008) $]
+]
+
+[def __quickbook [@http://www.boost.org/doc/tools/quickbook/index.html Quickbook]]
+[def __boostbook [@http://www.boost.org/doc/html/boostbook.html BoostBook]]
+[def __boostbook_docs [@http://www.boost.org/doc/libs/1_41_0/doc/html/boostbook.html BoostBook documentation]]
+[def __quickbook_syntax [@http://www.boost.org/doc/libs/1_41_0/doc/html/quickbook/ref.html Quickbook Syntax Compendium]]
+[def __docbook [@http://www.docbook.org/ DocBook]]
+[def __docbook_params [@http://docbook.sourceforge.net/release/xsl/current/doc/ Docbook xsl:param format options]]
+[def __DocObjMod [@http://en.wikipedia.org/wiki/Document_Object_Model Document Object Model (DOM)]]
+
+[def __doxygen [@http://www.doxygen.org/ Doxygen]]
+[def __pdf [@http://www.adobe.com/products/acrobat/adobepdf.html PDF]]
+
+[template deg[]'''&#xB0;'''] [/ degree sign ]
+
+
+[section:overview Overview]
+
+AutoIndex is a tool for taking the grunt work out of indexing a
+Boostbook\/Docbook document
+(perhaps generated by your Quickbook file mylibrary.qbk,
+and perhaps using also Doxygen autodoc)
+that describes C\/C++ code.
+
+Traditionally, in order to index a Docbook document you would
+have to manually add a large amount of `<indexterm>` markup:
+in fact one `<indexterm>` for each occurrence of each term to be
+indexed.
+
+Instead AutoIndex will automatically scan one or more C\/C++ header files
+and extract all the ['function], ['class], ['macro] and ['typedef]
+names that are defined by those headers, and then insert the
+`<indexterm>`s into the Docbook XML document for you.
+
+AutoIndex can also scan using a list of index terms
+specified in a script file, for example index.idx.
+These manually provided terms can optionally be regular expressions,
+and may allow the user to find references to terms
+that may not occur in the C++ header files. Of course providing a manual
+list of search terms in to index is a tedious task
+(especially handling plurals and variants),
+and requires enough knowledge of the library
+ to guess what users may be seeking to know,
+but at least the real 'grunt work' of
+finding the term and listing the page number is automated.
+
+AutoIndex creates index entries as follows:
+
+for each occurrence of each search term, it creates two index entries:
+
+# The search term as the ['primary index key] and
+ the ['title of the section it appears in] as a subterm.
+
+# The section title as the main index entry and the search term as the subentry.
+
+Thus the user has two chances to find what they're
+looking for, based upon either the section name
+or the ['function], ['class], ['macro] or ['typedef] name.
+
+[note This behaviour can be changed so that only one index entry is created
+ (using the search term as the key and
+ not using the section name except as a sub-entry of the search term).]
+
+So for example in Boost.Math the class name `students_t_distribution` has a primary
+entry that lists all sections the class name appears in:
+
+[$../students_t_eg_1.png]
+
+Then those sections also have primary entries, which list all the search terms those
+sections contain:
+
+[$../students_t_eg_2.png]
+
+Of course these automated index entries may not be quite
+what you're looking for: often you'll get a few spurious entries, a few missing entries,
+and a few entries where the section name used as an index entry is less than ideal.
+So AutoIndex provides some powerful regular expression based rules that allow you
+to add, remove, constrain, or rewrite entries. Normally just a few lines in
+AutoIndex's script file are enough to tailor the output to match the author's
+expectations (and thus hopefully the index user's expectations too!).
+
+AutoIndex also supports multiple indexes (as does Docbook), and since it knows
+which search terms are ['function], ['class], ['macro] or ['typedef] names, it
+can add the necessary attributes to the XML so that you can have separate
+indexes for each of these different types. These specialised indexes only contain
+entries for the ['function], ['class], ['macro] or ['typedef] names, ['section
+names] are never used as primary index terms here, unlike the main "include everything"
+index.
+
+Finally, while the Docbook XSL stylesheets create nice indexes complete with page
+numbers for PDF output, the HTML indexes look poorer by comparison, as these use
+section titles in place of page numbers... but as AutoIndex uses section titles
+as index entries this leads to a lot of repetition, so as an alternative AutoIndex
+can be instructed to construct the index itself. This is faster than using
+the XSL stylesheets, and now each index entry is a hyperlink to the
+appropriate section:
+
+[$../students_t_eg_3.png]
+
+With internal index generation there is also a helpful navigation bar
+at the start of each Index:
+
+[$../students_t_eg_4.png]
+
+Finally, you can choose what kind of XML container wraps an internally generated index -
+this defaults to `<section>...</section>` but you can use either command line options
+or Boost.Build Jamfile features, to select an alternative wrapper - for example ['appendix]
+or ['chapter] would be good choices, whatever fits best into the flow of the
+document. You can even set the container wrapper to type ['index] provided you turn
+off index generation by the XSL stylesheets, for example by setting the following
+build requirements in the Jamfile:
+
+[pre
+<format>html:<auto-index-internal>on # Use internally generated indexes.
+<auto-index-type>index # Use <index>...</index> as the XML wrapper.
+<format>html:<xsl:param>generate.index=0 # Don't let the XSL stylesheets generate indexes.
+]
+
+[endsect] [/section:overview Overview]
+
+[section:tut Getting Started and Tutorial]
+
+[section:build Step 1: Build the AutoIndex tool]
+
+[note This step is strictly optional, but very desirable to speed up build times.]
+
+cd into `tools/auto_index/build` and invoke bjam as:
+
+ bjam release
+
+Optionally pass the name of the compiler toolset you want to use to bjam as well:
+
+ bjam release gcc
+
+This will build the tool and place a copy in the current directory (which is to say `tools/auto_index/build`)
+
+Now open up your `user-config.jam` file and at the end of the file add the line:
+
+[pre
+using auto-index : ['full-path-to-boost-tree]/tools/auto_index/build/auto-index.exe ;
+]
+
+[note
+This declaration must go towards the end of `user-config.jam`, or in any case after the Boostbook initialisation.
+
+Also note that Windows users must use forward slashes in the paths in `user-config.jam`]
+
+[endsect] [/section:build Step 1: Build the AutoIndex tool]
+
+[section:configure Step 2: Configure Boost.Build jamfile to use AutoIndex]
+
+Assuming you have a Jamfile for building your documentation that looks
+something like:
+
+[pre
+boostbook standalone
+ :
+ mylibrary
+ :
+ # build requirements go here:
+ ;
+]
+
+Then add the line:
+
+[pre using auto-index ; ]
+
+to the start of the Jamfile, and then add whatever auto-index options
+you want to the ['build requirements section], for example:
+
+[pre
+ boostbook standalone
+ :
+ mylibrary
+ :
+ # Build requirements go here:
+
+ # <auto-index>on (or off) one turns on (or off) indexing:
+ <auto-index>on
+
+ # Turns on (or off) auto-index-verbose for diagnostic info.
+ # This is highly recommended until you have got all the many details correct!
+ <auto-index-verbose>on
+
+ # Choose the indexing method (separately for html and PDF) - see manual.
+ # Choose indexing method for PDFs:
+ <format>pdf:<auto-index-internal>off
+
+ # Choose indexing method for html:
+ <format>html:<auto-index-internal>on
+
+ # Set the name of the script file to use (index.idx is popular):
+ <auto-index-script>index.idx
+ # Commands in the script file should all use RELATIVE PATHS
+ # otherwise the script will not be portable to other machines.
+ # Relative paths are normally taken as relative to the location
+ # of the script file, but we can add a prefix to all
+ # those relative paths using the <auto-index-prefix> feature.
+ # The path specified by <auto-index-prefix> may be either relative or
+ # absolute, for example the following will get us up to the boost root
+ # directory for most Boost libraries:
+ <auto-index-prefix>..\/..\/..
+
+ # Tell Quickbook that it should enable indexing.
+ <quickbook-define>enable_index ;
+
+ ;
+] [/pre]
+
+[section:options Available Indexing Options]
+
+The available options are:
+
+[variablelist
+[[<auto-index>off/on][Turns indexing of the document on, defaults to
+"off", so be sure to set this if you want AutoIndex invoked!]]
+[[<auto-index-internal>off/on][Chooses whether AutoIndex creates the index
+itself (feature on), or whether it simply inserts the necessary DocBook
+markup so that the DocBook XSL stylesheets can create the index. Defaults to "off".]]
+[[<auto-index-script>filename][Specifies the name of the script to load.]]
+[[<auto-index-no-duplicates>off/on][When ['on] AutoIndex will only index a term
+once in any given section, otherwise (the default) multiple index entries per
+term may be created if the term occurs more than once in the section.]]
+[[<auto-index-section-names>off/on][When ['on] AutoIndex will use create two
+index entries for each term found - one uses the term itself as the primary
+index key, the other uses the enclosing section name. When off the index
+entry that uses the section title is not created. Defaults to "on"]]
+[[<auto-index-verbose>off/on][Defaults to "off". When turned on AutoIndex
+prints progress information - useful for debugging purposes during setup.]]
+[[<auto-index-prefix>filename][Optionally specifies a directory to apply
+as a prefix to all relative file paths in the script file.
+
+You may wish to do this to reduce typing of pathnames, and\/or where the
+paths can't be located relative to the script file location,
+typically if the headers are in the Boost trunk,
+but the script file is in Boost sandbox.
+
+For Boost standard library layout,
+[^<auto-index-prefix>..\/..\/..] will get you back up to the 'root' of the Boost tree,
+so [^!scan-path boost\/mylibrary\/] is where your headers will be, and [^libs\/mylibrary] for other files.
+Without a prefix all relative paths are relative to the location of the script file.
+]]
+
+[[<auto-index-type>element-name][Specifies the name of the XML element in which to enclose an internally generated indexes:
+ defaults to ['section], but could equally be ['appendix] or ['chapter] or some other block level element that has a formal title.
+ The actual list of available options depends upon the Quickbook document type, the following table gives the available options,
+ assuming that the index is placed at the top level, and not in some sub-section or other container:]]
+]
+
+[table
+[[Document Type][Permitted Index Types]]
+[[book][appendix index article chapter reference part]]
+[[article][section appendix index sect1]]
+[[chapter][section index sect1]]
+[[library][The same as Chapter (section index sect1)]]
+[[part][appendix index article chapter reference]]
+[[appendix][section index sect1]]
+[[preface][section index sect1]]
+[[qandadiv][N/A: an index would have to be placed within a subsection of the document.]]
+[[qandaset][N/A: an index would have to be placed within a subsection of the document.]]
+[[reference][N/A: an index would have to be placed within a subsection of the document.]]
+[[set][N/A: an index would have to be placed within a subsection of the document.]]
+]
+
+In large part then the choice of `<auto-index-type>element-name` depends on the
+formatting you want to be applied to the index:
+
+[table
+[[XML Container Used for the Index][Formatting Applied by the XSL Stylesheets]]
+[[appendix][Starts a new page.]]
+[[article][Starts a new page.]]
+[[chapter][Starts a new page.]]
+[[index][Starts a new page only if it's contained within an article or book.]]
+[[part][Starts a new page.]]
+[[reference][Starts a new page.]]
+[[sect1][Starts a new page as long as it's not the first section (but is controlled by the XSL parameters chunk.section.depth and/or chunk.first.sections).]]
+[[section][Starts a new page as long as it's not the first section or nested within another section (but is controlled by the XSL parameters chunk.section.depth and/or chunk.first.sections).]]
+]
+
+In almost all cases the default (section) is the correct choice - the exception is when the index is to be placed
+directly inside a /book/ or /part/, in which case you should probably use the same XML container for the index as
+you use for whatever subdivisions are in the /book/ or /part/. In any event placing a /section/ within a /book/ or
+/part/ will result in invalid XML.
+
+Finally, if you are using Quickbook to generate the documentation, then you may wish to add:
+
+[pre <include>$boost-root/tools/auto_index/include]
+
+to your projects requirements (replacing $boost-root with the path to the root of the Boost tree), so that
+the file auto_index_helpers.qbk can be included in your quickbook source with simply a:
+
+[pre \[include auto_index_helpers.qbk\]]
+
+[endsect] [/section:options Available Indexing Options]
+
+[section:optional Making AutoIndex optional]
+
+It is considerate to make the [*use of auto-index optional] in Boost.Build,
+to allow users who do not have AutoIndex installed to still be able to build your documentation.
+
+This also very convenient while you are refining your documentation,
+to allow you to decide to build indexes, or not:
+building indexes can take long time, if you are just correcting typos,
+you won't want to wait while you keep rebuilding the index!
+
+One method of setting up optional AutoIndex support is to place all
+AutoIndex configuration in a the body of a bjam if statement:
+
+[pre
+ if --enable-index in \[ modules.peek : ARGV \]
+ {
+ ECHO "Building the docs with automatic index generation enabled." ;
+
+ using auto-index ;
+ project : requirements
+ <auto-index>on
+ <auto-index-script>index.idx
+
+ ... other AutoIndex options here...
+
+ # And tell Quickbook that it should enable indexing.
+ <quickbook-define>enable_index
+ ;
+ }
+ else
+ {
+ ECHO "Building the my_library docs with automatic index generation disabled. To get an Index, try building with --enable-index." ;
+ }
+] [/pre]
+
+You will also need to add a conditional statement at the end of your Quickbook file,
+so that the index(es) is/are only added after the last section if indexing is enabled.
+
+[pre
+\[\? '''enable_index'''
+\'\'\'
+ <index/>
+\'\'\'
+\]
+] [/pre]
+
+
+To use this jamfile, you need to cd to your docs folder, for example:
+
+ cd \boost-sandbox\guild\mylibrary\libs\mylibrary\doc
+
+and then run `bjam` to build the docs without index, for example:
+
+ bjam -a html > mylibrary_html.log
+
+or with index(es)
+
+ bjam -a html --enable-index > mylibrary_html_index.log
+
+[endsect] [/section:optional Making AutoIndex optional]
+
+[tip Always send the output to a log file.
+It will contain of lot of stuff, but is invaluable to check if all has gone right,
+or else diagnose what has gone wrong.
+] [/tip]
+
+[tip A return code of 0 is not a reliable indication
+that you have got what you really want -
+inspecting the log file is the only certain way.
+] [/tip]
+
+[tip If you upgrade compiler version, for example MSVC from 9 to 10,
+then you may need to rebuild Autoindex
+to avoid what Microsoft call a 'side-by-side' error.
+And make sure that the autoindex.exe version you are using is the new one.
+] [/tip]
+
+[endsect] [/section:configure Step 2: Configure Boost.Build to use AutoIndex]
+
+[section:add_indexes Step 3: Add indexes to your documentation]
+
+To add a single "include everything" index to a BoostBook\/Docbook document,
+(perhaps generated using Quickbook, and perhaps also using Doxygen reference section),
+add `<index/>` at the location where you want the index to appear.
+The index will be rendered as a separate section called "Index"
+when the documentation is built.
+
+To add multiple indexes, then give each one a title and set its
+`type` attribute to specify which terms will be included, for example
+to place the ['function], ['class], ['macro] or ['typedef] names
+indexed by ['AutoIndex] in separate indexes along with a main
+"include everything" index as well, one could add:
+
+[pre
+<index type\="class_name">
+<title>Class Index<\/title>
+<\/index>
+
+<index type\="typedef_name">
+<title>Typedef Index<\/title>
+<\/index>
+
+<index type\="function_name">
+<title>Function Index<\/title>
+<\/index>
+
+<index type\="macro_name">
+<title>Macro Index<\/title>
+<\/index>
+
+<index\/>
+]
+
+[note Multiple indexes like this only work correctly if you tell the XSL stylesheets
+to honor the "type" attribute on each index as by default [/[*they do not do this]].
+You can turn the feature on by adding `<xsl:param>index.on.type=1` to your projects
+requirements in the Jamfile.]
+
+In Quickbook, you add the same markup but enclose it between two triple-tick \'\'\' escapes,
+thus
+
+[pre \'\'\'<index\/>\'\'\' ]
+
+Or more easily via the helper file auto_index_helpers.qbk, so that given:
+
+[pre \[include auto_index_helpers.qbk\]]
+
+one can simply write:
+
+[pre
+\[named_index class_name Class Index\]
+\[named_index function_name Function Index\]
+\[named_index typedef_name Typedef Index\]
+\[named_index macro_name Macro Index\]
+\[index\]
+]
+
+[note AutoIndex knows nothing of the XML `xinclude` element, so if
+you're writing raw Docbook XML then you may want to run this through an
+XSL processor to flatten everything to one XML file before passing to
+AutoIndex. If you're using Boostbook or quickbook though, this all
+happens for you anyway, and AutoIndex will index the whole document
+including any sections included with `xinclude`.]
+
+If you are using AutoIndex's internal index generation on
+
+[pre
+<auto-index-internal>on
+]
+(usually recommended for HTML output, but ['not] the default)
+then you can also decide what kind of XML wrapper the generated index is placed in.
+By default this is a `<section>...</section>` XML block (this replaces the original
+`<index>...</index>` block). However, depending upon the structure of the document
+and whether or not you want the index on a separate page - or else on the front page after
+the TOC - you may want to place the index inside a different type of XML block. For example
+if your document uses `<chapter>` top level content rather than `<section>`s then
+it may be preferable to place the index in a `<chapter>` or `<appendix>` block.
+You can also place the index inside an `<index>` block if you prefer, in which case the index
+does not appear in on a page of its own, but after the TOC in the HTML output.
+
+You control the type of XML block used by setting the =<auto-index-type>element-name=
+attribute in the Jamfile, or via the `index-type=element-name` command line option to
+AutoIndex itself. For example, to place the index in an appendix, your Jamfile might
+look like:
+
+[pre
+using quickbook ;
+using auto-index ;
+
+xml mylibrary : mylibary.qbk ;
+boostbook standalone
+ :
+ mylibrary
+ :
+ # auto-indexing is on:
+ <auto-index>on
+
+ # PDFs rely on the XSL stylesheets to generate the index:
+ <format>pdf:<auto-index-internal>off
+
+ # HTML output uses auto-index to generate the index:
+ <format>html:<auto-index-internal>on
+
+ # Name of script file to use:
+ <auto-index-script>index.idx
+
+ # Set the XML wrapper for HML Indexes to "appendix":
+ <format>html:<auto-index-type>appendix
+
+ # Turn on multiple index support:
+ <xsl:param>index.on.type=1
+]
+
+
+[endsect] [/section:add_indexes Step 3: Add indexes to your documentation]
+
+[section:script Step 4: Create the .idx script file - to control what to terms to index]
+
+AutoIndex works by reading a script file that tells it what terms to index.
+
+If your document contains largely text, and only a small amount of simple C++,
+and/or if you are using Doxygen to provide a C++ Reference section
+(that lists the C++ elements),
+and/or if you are relying on the indexing provided from a Standalone Doxygen Index,
+you may decide that a index is not needed
+and that you may only want the text part indexed.
+
+But if you want C++ classes functions, typedefs and/or macros AutoIndexed,
+optionally, the script file also tells which other C++ files to scan.
+
+At its simplest, it will scan one or more headers for terms that
+should be indexed in the documentation. So for example to scan
+"myheader.hpp" the script file would just contain:
+
+ !scan myheader.hpp
+ !scan mydetailsheader.hpp
+
+Or, more likely in practice, so
+we can recursively scan through directories looking for all
+the files to scan whose [*name matches a particular regular expression]:
+
+[pre !scan-path "boost\/mylibrary" ".*\.hpp" true ]
+
+Each argument is whitespace separated and can be optionally
+enclosed in "double quotes" (recommended).
+
+The final ['true] argument indicates
+that subdirectories in `/boost/math/mylibrary` should be searched
+recursively in addition to that directory.
+
+[caution The second ['file-name-regex] argument is a regular expression and not a filename GLOB!]
+
+[caution The scan-path is modified by any setting of <auto-index-prefix>.
+The examples here assume that this is [^<auto-index-prefix>..\/..\/..]
+so that `boost/mylibrary` will be your header files,
+`libs/mylibrary/doc` will contain your documentation files and
+`libs/mylibrary/example` will contain your examples.
+]
+
+You could also scan any examples (.cpp) files,
+typically in folder `/mylibrary/lib/example`.
+
+[pre
+# All example source files, assuming no sub-folders.
+!scan-path "libs\/mylibrary\/example" ".*\\.cpp"
+] [/pre]
+
+Often the ['scan] or ['scan-path] rules will bring in too many terms
+to search for, so we need to be able to exclude terms as well:
+
+ !exclude type
+
+Which excludes the term "type" from being indexed.
+
+We can also add terms manually:
+
+ foobar
+
+will index occurrences of "foobar" and:
+
+ foobar \<\w*(foo|bar)\w*\>
+
+will index any whole word containing either "foo" or "bar" within it,
+this is useful when you want to index a lot of similar or related
+words under one entry, for example:
+
+ reflex
+
+Will only index occurrences of "reflex" as a whole word, but:
+
+ reflex \<reflex\w*\>
+
+will index occurrences of "reflex", "reflexing" and
+"reflexed" all under the same entry ['reflex].
+You will very often need to use this to deal with plurals and other variants.
+
+This inclusion rule can also restrict the term to
+certain sections, and add an index category that
+the term should belong to (so it only appears in certain
+indexes).
+
+Finally the script can add rewrite rules, that rename section names
+that are automatically used as index entries. For example we might
+want to remove leading "A" or "The" prefixes from section titles
+when AutoIndex uses them as an index entry:
+
+ !rewrite-name "(?i)(?:A|The)\s+(.*)" "\1"
+
+[endsect] [/section:script Step 4: Create the script file - to control what to terms to index]
+
+[section:entries Step 5: Add Manual Index Entries to Docbook XML - Optional]
+
+If you add manual `<indexentry>` markup to your Docbook XML then these will be
+passed through unchanged. Please note however, that if you are using
+AutoIndex's internal index generation then it only recognises
+`<primary>`, `<secondary>` and `<tertiary>` elements within the `<indexterm>`.
+`<see>` and `<seealso>` elements are not currently recognised
+and AutoIndex will emit a warning if these are used.
+
+Likewise none of the attributes which can be applied to these elements are used when
+AutoIndex generates the index itself, with the exception of the `<type>` attribute.
+
+For Quickbook users, there are some templates in auto_index_helpers.qbk that assist
+in adding manual entries without having to escape to Docbook.
+
+[endsect] [/section:entries Step 5: Add Manual Index Entries to Docbook XML - Optional]
+
+[section:pis Step 6: Using XML processing instructions to control what gets indexed.]
+
+Sometimes when you need to exclude certain sections of text from indexing,
+then you can achieve this with the following XML processing instructions:
+
+[table
+[[Instruction][Effect]]
+[[`<?BoostAutoIndex IgnoreSection?>`]
+ [Causes the whole of the current section to be excluded from indexing.
+ By "section" we mean either a true "section" or any sibling XML element:
+ "dedication", "toc", "lot", "glossary", "bibliography", "preface", "chapter",
+ "reference", "part", "article", "appendix", "index", "setindex", "colophon",
+ "sect1", "refentry", "simplesect", "section" or "partintro".]]
+[[`<?BoostAutoIndex IgnoreBlock?>`]
+ [Causes the whole of the current text block to be excluded from indexing.
+ A text block may be any of the section/chapter elements listed above, or a
+ paragraph, code listing, table etc. The complete list is:
+ "calloutlist", "glosslist", "bibliolist", "itemizedlist", "orderedlist",
+ "segmentedlist", "simplelist", "variablelist", "caution", "important", "note",
+ "tip", "warning", "literallayout", "programlisting", "programlistingco",
+ "screen", "screenco", "screenshot", "synopsis", "cmdsynopsis", "funcsynopsis",
+ "classsynopsis", "fieldsynopsis", "constructorsynopsis",
+ "destructorsynopsis", "methodsynopsis", "formalpara", "para", "simpara",
+ "address", "blockquote", "graphic", "graphicco", "mediaobject",
+ "mediaobjectco", "informalequation", "informalexample", "informalfigure",
+ "informaltable", "equation", "example", "figure", "table", "msgset", "procedure",
+ "sidebar", "qandaset", "task", "productionset", "constraintdef", "anchor",
+ "bridgehead", "remark", "highlights", "abstract", "authorblurb" or "epigraph".]]
+]
+
+For Quickbook users the file auto_index_helpers.qbk contains a helper template
+that assists in inserting these processing instructions, for example:
+
+[pre \[AutoIndex IgnoreSection\]]
+
+Will cause that section to not be indexed.
+
+[endsect] [/section:pis Step 6: Using XML processing instructions to control what gets indexed.]
+
+[section:build_docs Step 7: Build the Docs]
+
+Using Boost.Build you build the docs with either:
+
+ bjam release > mylibrary_html.log
+
+To build the html docs or:
+
+ bjam pdf release > mylibrary_pdf.log
+
+To build the pdf.
+
+During the build process you should see AutoIndex emit a message in the log file
+such as:
+
+[pre Indexing 990 terms... ]
+
+If you don't see that, or if it's indexing 0 terms then something is wrong!
+
+Likewise when index generation is complete, AutoIndex will emit another message:
+
+[pre 38 Index entries were created.]
+
+Again, if you see that 0 entries were created then something is wrong!
+
+Examine the log file, and if the cause is not obvious,
+make sure that you have [^<auto-index-verbose>on] and that
+any needed
+[^!debug regular-expression] directives are in your script file.
+
+[endsect] [/section:build_docs Step 7: Build the Docs]
+
+[section:refine Step 8: Iterate - to refine your index]
+
+Creating a good index is an iterative process, often the first step is
+just to add a header scanning rule to the script file and then generate
+the documentation and see:
+
+* What's missing.
+* What's been included that shouldn't be.
+* What's been included under a poor name.
+
+Further rules can then be added to the script to handle these cases
+and the next iteration examined, and so on.
+
+[tip If you don't understand why a particular term is (or is not) present in the index,
+try adding a ['!debug regular-expression]
+directive to the [link boost_autoindex.script_ref script file].
+] [/tip]
+
+[heading Restricting which Sections are indexed for a particular term]
+
+You can restrict which sections are indexed for a particular term.
+So assuming that the docbook document has the usual hierarchical names for section ID's
+(as Quickbook generates, for example),
+you can easily place a constraint on which sections are examined for a particular term.
+
+For example, if you want to index occurrences of Lord Kelvin's name,
+but only in the introduction section, you might then add:
+
+ Kelvin "" ".*introduction.*"
+
+to the script file,
+assuming that the section ID of the intro is "some_library_or_chapter_name.introduction".
+
+This would avoid an index entry every time 'Kelvin' is found,
+something the user is unlikely to find helpful.
+
+[endsect] [/section:refine Step 8: Iterate - to refine your index]
+
+[endsect] [/section:tut Getting Started and Tutorial]
+
+
+[section:script_ref Script File (.idx) Reference]
+
+The following elements can occur in a script:
+
+[h4 Comments and blank lines]
+
+Blank lines consisting of only whitespace are ignored, so are lines that [*start with a #].
+
+[note You can't append \# comments onto the end of a line\!]
+
+[h4 Inclusion of Index terms]
+
+ term [regular-expression1 [regular-expression2 [category]]]
+
+[variablelist
+[[term][
+['Term to index.]
+
+The index term will form a primary entry in the Index
+with the section title(s) containing the term as secondary entries, and
+also will be used as a secondary entry beneath each of the section
+titles that the index term occurs in.]
+] [/term]
+
+[[regular-expression1][
+['Index term Searcher.]
+
+An optional regular expression: each occurrence
+of the regular expression in the text of the document will result
+in one index term being emitted.
+
+If the regular expression is omitted (default) or is "", then the ['index term] itself
+will be used as the search text - and only occurrence of whole words matching
+['index term] will be indexed.
+
+For example:
+
+``foobar``
+
+will index occurrences of "foobar" in any section, but
+
+``foobar \<\w*(foo|bar)\w*\>``
+
+will index any whole word containing either "foo" or "bar" within it.
+This is useful when you want to index a lot of similar or related words under one entry.
+
+``reflex``
+
+will only index occurrences of "reflex" as a whole word, but:
+
+``reflex \<reflex\w*\>``
+
+will index occurrences of "reflex", "reflexes", "reflexing" and "reflexed" ...
+all under the same entry reflex.
+
+You will very often need to use this to deal with plurals and other variants.]
+] [/regular-expression1]
+
+[[regular-expression2]
+[['Section(s) Selector.]
+
+A constraint that specifies which sections are
+indexed for ['term]: only if the ID of the section matches
+['regular-expression2] exactly will that section be indexed
+for occurrences of ['term].
+
+For example, to limit indexing to just [*one specific section] (but not sub-sections below):
+
+``myclass "" "mylib\.examples"``
+
+
+For example, to limit indexing to specific sections, [*and sub-sections below]:
+
+``myclass "" "mylib\.examples.*"``
+
+will index occurrences of "myclass" as a whole word,
+but only in sections whose section ID [*begins] "mylib.examples", while
+
+``myclass "\<myclass\w*\>" "mylib\.examples.*"``
+
+will also index plurals myclass, myclasses, myclasss ...
+
+and:
+
+``myclass "" "(?!mylib\.introduction).*"``
+
+will index occurrences of "myclass" in any section,
+except those whose section IDs begin "mylib.introduction".
+
+Finally, two (or more) sections can be excluded by OR'ing them together:
+
+``myclass "" "(?!mylib\.introduction|mylib\.reference).*"``
+
+which excludes searching for this term in sections whose ID's start with either "mylib.introduction" or "mylib.reference".
+
+If this third section selection field is omitted (the default)
+or is "", then [*all sections] are indexed for this term.
+]
+] [/regular-expression2]
+
+[[category][
+['Index Category Constraint.]
+
+Optionally a category to place occurrences of ['index term] in.
+If you have multiple indexes then this is the name
+assigned to the indexes "type" attribute.
+
+For example:
+
+ myclass "" "" class_name
+
+Will index occurances of ['myclass] and place them in the class-index if there is one.
+
+]] [/category]
+
+] [/variablelist]
+
+You can have an index term appear more than once in the script file:
+
+* If they have different /category/ names then they are treated quite separately.
+* Otherwise they are combined, so that the logical or of the regular expressions provided are taken.
+
+Thus:
+
+ myterm search_expression1 constrait_expression2 foo
+ myterm search_expression1 constrait_expression2 bar
+
+Will be treated as different terms each with their own entries, while:
+
+ myterm search_expression1 constrait_expression2 mycategory
+ myterm search_expression1 constrait_expression2 mycategory
+
+Will be combined into a single term equivalent to:
+
+ myterm (?:search_expression1|search_expression1) (?:constrait_expression2|constrait_expression2) mycategory
+
+[h4 Source File Scanning]
+
+ !scan source-file-name
+
+Scans the C\/C++ source file ['source-file-name] for definitions of
+['function]s, ['class]s, ['macro]s or ['typedef]s and makes each of
+these a term to be indexed. Terms found are assigned to the index category
+"function_name", "class_name", "macro_name" or "typedef_name" depending
+on how they were seen in the source file. These may then be included
+in a specialised index whose "type" attribute has the same category name.
+
+[important
+When actually indexing a document, the scanner will not index just any old occurrence of the
+terms found in the source files. Instead it searches for class definitions or function or
+typedef declarations. This reduces the number of spurious matches placed in the index, but
+may also miss some legitimate terms:
+refer to the /define-scanner/ command for information on how to change this.
+]
+
+[h4 Directory and Source File Scanning]
+
+ !scan-path directory-name file-name-regex [recurse]
+
+[variablelist
+[[directory-name][The directory to scan: this should be a path relative
+to the script file (or to the path specified with the prefix=path option on the command line)
+and should use all forward slashes in its file name.]]
+
+[[file-name-regex][A regular expression: any file in the directory whose name
+matches the regular expression will be scanned for terms to index.]]
+
+[[recurse][An optional boolean value - either "true" or "false" - that
+indicates whether to recurse into subdirectories. This defaults to "false".]]
+]
+
+[h4 Excluding Terms]
+
+ !exclude term-list
+
+Excludes all the terms in whitespace separated ['term-list] from being indexed.
+This should be placed /after/ any ['!scan] or ['!scan-path] rules which may
+result in the terms becoming included. In other words this removes terms from
+the scanners internal list of things to index.
+
+[h4 Rewriting Section Names]
+
+[pre !rewrite-id regular-expression new-name]
+
+[variablelist
+[[regular-expression][A regular expression: all section ID's that match
+the expression exactly will have index entries ['new-name] instead of
+their title(s).]]
+
+[[new-name][The name that the section will appear under in the index.]]
+]
+
+ !rewrite-name regular-expression format-text
+
+[variablelist
+[[regular-expression][A regular expression: all sections whose titles
+match the regular expression exactly, will have index entries composed
+of the regular expression match combined with the regex format string
+['format-text].]]
+[[format-text][The Perl-style format string used to reformat the title.]]
+]
+
+For example:
+
+[pre
+!rewrite-name "(?:A|An|The)\s+(.*)" "\1"
+]
+
+Will remove any leading "A", "An" or "The" from all index entries - thus preventing lots of
+entries under "The" etc!
+
+[h4 Defining or Changing the File Scanners]
+
+ !define-scanner type file-search-expression xml-regex-formatter term-formatter id-filter filename-filter
+
+When a source file is scanned using the =!scan= or =!scan-path= rules, then the file is searched using
+a series of regular expressions to look for classes, functions, macros or typedefs that should be indexed.
+A set of default regular expressions are provided for this (see below), but sometimes you may want to replace
+the defaults, or add new scanners. The arguments to this rule are:
+
+[variablelist
+[[type][The ['type] to which items found using this rule will assigned, index terms created from the
+source file and then found in the XML, will have the type attribute set to this value, and may then appear in a
+specialized index with the same type attribute]]
+[[file-search-expression][A regular expression that is used to scan the source file for index terms, the result of
+a match against this expression will be transformed by the next two arguments.]]
+[[xml-regex-formatter][A regular expression format string that extracts the salient information from whatever
+matched the ['file-search-expression] in the source file, and creates ['a new regular expression] that will
+be used to search the document being indexed for occurrences of this index term.]]
+[[term-formatter][A regular expression format string that extracts the salient information from whatever
+matched the ['file-search-expression] in the source file, and creates the index term that will appear in
+the index.]]
+[[id-filter][Optional. A regular expression that restricts the section-id's that are searched in the document being indexed:
+only sections whose ID attribute matches this expression exactly will be considered for indexing terms found by this scanner.]]
+[[filename-filter][Optional. A regular expression that restricts which files are scanned by this scanner: only files whose file name
+matches this expression exactly will be scanned for index terms to use. Note that the filename matched against this may
+well be an absolute path, and contain either forward or backward slash path separators.]]
+]
+
+If, when the first file is scanned, there are no scanners whose ['type] is "class_name", "typedef_name", "macro_name" or
+"function_name", then the defaults are installed. These are equivalent to:
+
+ !define-scanner class_name "^[[:space:]]*(template[[:space:]]*<[^;:{]+>[[:space:]]*)?(class|struct)[[:space:]]*(\<\w+\>([[:blank:]]*\([^)]*\))?[[:space:]]*)*(\<\w*\>)[[:space:]]*(<[^;:{]+>)?[[:space:]]*(\{|:[^;\{()]*\{)" "(?:class|struct)[^;{]+\\<\5\\>[^;{]+\\{" \5
+ !define-scanner typedef_name "typedef[^;{}#]+?(\w+)\s*;" "typedef[^;]+\\<\1\\>\\s*;" "\1"
+ !define-scanner "macro_name" "^\s*#\s*define\s+(\w+)" "\\<\1\\>" "\1"
+ !define-scanner "function_name" "\w+(?:\s*<[^>]>)?[\s&*]+?(\w+)\s*(?:BOOST_[[:upper:]_]+\s*)?\([^\)]*\)\s*[;{]" "\\<\\w+\\>(?:\\s+<[^>]*>)?[\\s&*]+\\<\1\\>\\s*\\([^;{]*\\)" "\1"
+
+Note that these defaults are not installed if you have provided your own versions with these ['type] names. In this case if
+you want the default scanners to be in effect as well as your own, you should include the above in your script file.
+It is also perfectly allowable to have multiple scanners with the same ['type], but with the other fields differing.
+
+Finally you should note that the default scanners are quite strict
+in what they will find, for example the class
+scanner will only create index entries for classes that have class definitions of the form:
+
+ class my_class : public base_classes
+ {
+ // etc
+
+In the documentation, so that simple mentions of the class name will ['not] get indexed,
+only the class synopsis if there is one.
+If this isn't how you want things, then include the ['class_name] scanner definition
+above in your script file, and change
+the ['xml-regex-formatter] field to something more permissive, for example:
+
+ !define-scanner class_name "^[[:space:]]*(template[[:space:]]*<[^;:{]+>[[:space:]]*)?(class|struct)[[:space:]]*(\<\w+\>([[:blank:]]*\([^)]*\))?[[:space:]]*)*(\<\w*\>)[[:space:]]*(<[^;:{]+>)?[[:space:]]*(\{|:[^;\{()]*\{)" "\\<\5\\>" \5
+
+Will look for ['any] occurrence of whatever class names the scanner may find in the documentation.
+
+[h4 Debugging scanning]
+
+If you see a term in the index, and you don't understand why it's there, add a ['debug] directive:
+
+[pre
+!debug regular-expression
+]
+
+Now, whenever ['regular-expression] matches either the found index term,
+or the section title it appears in, or the ['type] field of a scanner, then
+some diagnostic information will be printed that will look something like:
+
+[pre
+Debug term found, in block with ID: spirit.qi.reference.parser_concepts.parser
+Current section title is: Notation
+The main index entry will be : Notation
+The indexed term is: parser
+The search regex is: \[P\|p\]arser
+The section constraint is: .*qi.reference.parser_concepts.*
+The index type for this entry is: qi_index
+]
+
+This can produce a lot of output in your log file,
+but until you are satisfied with your file selection and scanning process,
+it is worth switching it on.
+
+[endsect] [/section:script_ref Script File Reference]
+
+[section:workflow Understanding The AutoIndex Workflow]
+
+# Load the script file (usually index.idx)
+ and process it one line at a time,
+ producing one or more index term per (non-comment) line.
+
+# Reading all lines builds a list of ['terms to index].
+ Some of those may be terms defined (by you) directly in the script file,
+ others may be terms found by scanning C++ header and source files
+ that were specified by the ['!scan-path] directive.
+
+# Once the complete list of ['terms to index] is complete,
+ it loads the Docbook XML file.
+ (If this comes from Quickbook\/Doxygen\/Boostbook\/Docbook then this is
+ the complete documentation after conversion to Docbook format).
+
+# AutoIndex builds an internal __DocObjMod of the Docbook XML.
+ This internal representation then gets scanned for occurrences of the ['terms to index].
+ This scanning works at the XML paragraph level
+ (or equivalent sibling such as a table or code block)
+ - so all the XML encoding within a paragraph gets flattened to plain text.[br]
+ This flattening means the regular expressions used to search for ['terms to index]
+ can find anything that is completely contained within a paragraph
+ (or code block etc).
+
+# For each term found then an ['indexterm] Docbook element is inserted
+ into the __DocObjMod (provided internal index generation is off),
+
+# Also the AutoIndex's internal index representation gets updated.
+
+# Once the whole XML document has been indexed,
+ then, if AutoIndex has been instructed to generate the index itself,
+ it creates the necessary XML and inserts this into the __DocObjMod.
+
+# Finally the whole __DocObjMod is written out as a new Docbook XML file,
+ and normal processing of this continues via the XSL stylesheets (with xsltproc)
+ to actually build the final human-readable docs.
+
+[endsect] [/section:workflow AutoIndex Workflow]
+
+
+[section:xml XML Handling]
+
+AutoIndex is rather simplistic in its handling of XML:
+
+* When indexing a document, all block content at the paragraph level gets collapsed into a single
+string for matching against the regular expressions representing each index term. In other words,
+for the most part, you can assume that you're indexing plain text when writing regular expressions.
+* Named XML entities for &, ", ', < or > are converted to their corresponding characters before indexing
+a section of text. However, decimal or hex escape sequences are not currently converted.
+* Index terms are assumed to be plain text (whether they originate from the script file
+or from scanning source files) and the characters &, ", < and > will be escaped to
+&amp; &quot; &lt; and &gt; respectively.
+
+[endsect] [/section:xml XML Handling]
+
+[section:qbk Quickbook Support]
+
+The file auto_index_helpers.qbk in ['boost-path]/tools/auto_index/include contains various Quickbook
+templates to assist with AutoIndex support. One would normally add the above path to your include
+search path via an `<include>path` statement in your Jamfile, and then make the templates available
+to your Quickbook source via a:
+
+[pre \[include auto_index_helpers.qbk\]]
+
+statement at the start of your Quickbook file.
+
+The available templates are then:
+
+[table
+[[Template][Description]]
+[[`[index]`][Creates a main index, with no "type" category set, which will be titled simply "Index".]]
+[[`[named_index type title]`][Creates an index with the type attribute set to "type" and the title will be "title".[br]
+ For example to create an index containing only class names one would typically add `[named_index class_name Class Index]`
+ to your Quickbook source.]]
+[[`[AutoIndex Arg]`][Creates a Docbook processing instruction that will be handled by AutoIndex, valid values for "Arg"
+ are either "IgnoreSection" or "IgnoreBlock".]]
+[[`[indexterm1 primary-key]`][Creates a manual index entry that will link to the current section, and have a single primary key "primary-key".
+ Note that this index key will not have a "type" attribute set, and so will only appear in the main index.]]
+[[`[indexterm2 primary-key secondary-key]`][Creates a manual index entry that will link to the current section, and has
+ "primary-key" and "secondary key" as the primary and secondary keys respectively.
+ Note that this index key will not have a "type" attribute set, and so will only appear in the main index.]]
+[[`[indexterm3 primary-key secondary-key tertiary-key]`][Creates a manual index entry that will link to the current section,
+ and have primary, secondary and tertiary keys: "primary-key", "secondary key" and "tertiary key".
+ Note that this index key will not have a "type" attribute set, and so will only appear in the main index.]]
+
+[[`[typed_indexterm1 type primary-key]`][Creates a manual index entry that will link to the current section, and have a single primary key "primary-key".
+ Note that this index key will have the "type" attribute set to the "type" argument, and so may appear in named sub-indexes
+ that also have their type attribute set.]]
+[[`[typed_indexterm2 type primary-key secondary-key]`][Creates a manual index entry that will link to the current section, and has
+ "primary-key" and "secondary key" as the primary and secondary keys respectively.
+ Note that this index key will have the "type" attribute set to the "type" argument, and so may appear in named sub-indexes
+ that also have their type attribute set.]]
+[[`[typed_indexterm3 type primary-key secondary-key tertiary-key]`][Creates a manual index entry that will link to the current section,
+ and have primary, secondary and tertiary keys: "primary-key", "secondary key" and "tertiary key".
+ Note that this index key will have the "type" attribute set to the "type" argument, and so may appear in named sub-indexes
+ that also have their type attribute set.]]
+]
+
+[endsect]
+
+[section:comm_ref Command Line Reference]
+
+The following command line options are supported by AutoIndex:
+
+[variablelist
+[[--in=infilename][Specifies the name of the XML input file to be indexed.]]
+[[--out=outfilename][Specifies the name of the new XML file to create.]]
+[[--scan=source-filename][Specifies that ['source-filename] should be scanned
+for terms to index.]]
+[[--script=script-filename][Specifies the name of the script file to process.]]
+[[--no-duplicates][If a term occurs more than once in the same section, then
+include only one index entry.]]
+[[--internal-index][Specifies that AutoIndex should generate the actual
+indexes rather than inserting `<indexterm>`s and leaving index generation
+to the XSL stylesheets.]]
+[[--no-section-names][Prevents AutoIndex from using section names as index entries.]]
+[[--prefix=pathname][Specifies a directory to apply as a prefix to all relative file paths in the script file.]]
+[[--index-type=element-name][Specifies the name of the XML element to enclose internally generated indexes in:
+ defaults to ['section], but could equally be ['appendix] or ['chapter]
+ or some other block level element that has a formal title.]]
+]
+
+[endsect] [/section:comm_ref Command Line Reference]
+
+[include ../include/auto_index_helpers.qbk]
+
+[index]
diff --git a/tools/auto_index/doc/autoindex.idx b/tools/auto_index/doc/autoindex.idx
new file mode 100644
index 0000000000..8747267215
--- /dev/null
+++ b/tools/auto_index/doc/autoindex.idx
@@ -0,0 +1,93 @@
+# autoindex.idx index script file
+# for Boost.autoindex Quickbook Doxygen documentation Auto-indexing.
+
+# Copyright (c) 2011 Paul A. Bristow
+
+# Use, modification and distribution is subject to the Boost Software
+# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Diagnostic output - useful during refinement of the index.
+# !debug your-choice-of-regular-expression-to-debug
+
+# Terms that you want to appear in the Index.
+# Term to display in index, and word(s) that are to be matched (as a regular expression).
+
+# Diagnostic while testing.
+#!debug regular-expression
+# For example
+#!debug \w*\<index\w*\>
+
+appendix
+chapter
+section
+
+AutoIndex
+Quickbook
+Boostbook
+Docbook
+Doxygen
+Document Object Model "DOM"
+XML
+html
+PDF
+XSL
+
+MSVC
+side-by-side
+stylesheet \<stylesheet\w*\>
+
+"XSL stylesheet" \<(XSL|stylesheet)\w*\>
+
+bjam
+jamfile
+Boost.Build
+
+"log file" \<log\w*\>
+
+C++
+
+macro
+function
+class
+typedef
+
+# Plural, and plurals.
+plural \<plural\w*\>
+
+# To allow plurals:
+index \<index\w*\>
+
+# Allow hyperlink and hyperlinking:
+hyperlink \<hyperlink\w*\>
+
+# Two word index term, allowing plurals.
+"side effect" \<side effect\w*\>
+
+text \<text\w*\>
+
+page \<page\w*\>
+appendix \<appendi\w*\>
+section \<section\w*\>
+chapter \<chapter\w*\>
+
+script
+
+verbose \<\w*verbose\w*\>
+debug \<debug\w*\>
+
+index term "index term"
+
+!exclude junk
+# Exclude the index term junk from the index,
+# so that "junk" anywhere does not have an index entry.
+
+# Remove leading "A" or "The" prefixes from section titles.
+!rewrite-name "(?i)(?:A|The)\s+(.*)" "\1"
+
+!rewrite-name "Additional Implementation Notes" "Implementation Notes"
+
+
+
+
+
diff --git a/tools/auto_index/doc/html/boost_autoindex/comm_ref.html b/tools/auto_index/doc/html/boost_autoindex/comm_ref.html
new file mode 100644
index 0000000000..a032095b58
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/comm_ref.html
@@ -0,0 +1,95 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Command Line Reference</title>
+<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../index.html" title="Boost.AutoIndex">
+<link rel="prev" href="qbk.html" title="Quickbook Support">
+<link rel="next" href="../index/s08.html" title="Index">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="qbk.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../index/s08.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="boost_autoindex.comm_ref"></a><a class="link" href="comm_ref.html" title="Command Line Reference">Command Line Reference</a>
+</h2></div></div></div>
+<p>
+ The following command line options are supported by AutoIndex:
+ </p>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">--in=infilename</span></dt>
+<dd><p>
+ Specifies the name of the XML input file to be indexed.
+ </p></dd>
+<dt><span class="term">--out=outfilename</span></dt>
+<dd><p>
+ Specifies the name of the new XML file to create.
+ </p></dd>
+<dt><span class="term">--scan=source-filename</span></dt>
+<dd><p>
+ Specifies that <span class="emphasis"><em>source-filename</em></span> should be scanned
+ for terms to index.
+ </p></dd>
+<dt><span class="term">--script=script-filename</span></dt>
+<dd><p>
+ Specifies the name of the script file to process.
+ </p></dd>
+<dt><span class="term">--no-duplicates</span></dt>
+<dd><p>
+ If a term occurs more than once in the same section, then include only
+ one index entry.
+ </p></dd>
+<dt><span class="term">--internal-index</span></dt>
+<dd><p>
+ Specifies that AutoIndex should generate the actual indexes rather than
+ inserting <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">indexterm</span><span class="special">&gt;</span></code>s and leaving index generation to
+ the XSL stylesheets.
+ </p></dd>
+<dt><span class="term">--no-section-names</span></dt>
+<dd><p>
+ Prevents AutoIndex from using section names as index entries.
+ </p></dd>
+<dt><span class="term">--prefix=pathname</span></dt>
+<dd><p>
+ Specifies a directory to apply as a prefix to all relative file paths
+ in the script file.
+ </p></dd>
+<dt><span class="term">--index-type=element-name</span></dt>
+<dd><p>
+ Specifies the name of the XML element to enclose internally generated
+ indexes in: defaults to <span class="emphasis"><em>section</em></span>, but could equally
+ be <span class="emphasis"><em>appendix</em></span> or <span class="emphasis"><em>chapter</em></span> or some
+ other block level element that has a formal title.
+ </p></dd>
+</dl>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="qbk.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../index/s08.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/overview.html b/tools/auto_index/doc/html/boost_autoindex/overview.html
new file mode 100644
index 0000000000..658ac7e236
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/overview.html
@@ -0,0 +1,168 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Overview</title>
+<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../index.html" title="Boost.AutoIndex">
+<link rel="prev" href="../index.html" title="Boost.AutoIndex">
+<link rel="next" href="tut.html" title="Getting Started and Tutorial">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tut.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="boost_autoindex.overview"></a><a class="link" href="overview.html" title="Overview">Overview</a>
+</h2></div></div></div>
+<p>
+ AutoIndex is a tool for taking the grunt work out of indexing a Boostbook/Docbook
+ document (perhaps generated by your Quickbook file mylibrary.qbk, and perhaps
+ using also Doxygen autodoc) that describes C/C++ code.
+ </p>
+<p>
+ Traditionally, in order to index a Docbook document you would have to manually
+ add a large amount of <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">indexterm</span><span class="special">&gt;</span></code> markup: in fact one <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">indexterm</span><span class="special">&gt;</span></code>
+ for each occurrence of each term to be indexed.
+ </p>
+<p>
+ Instead AutoIndex will automatically scan one or more C/C++ header files and
+ extract all the <span class="emphasis"><em>function</em></span>, <span class="emphasis"><em>class</em></span>,
+ <span class="emphasis"><em>macro</em></span> and <span class="emphasis"><em>typedef</em></span> names that are
+ defined by those headers, and then insert the <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">indexterm</span><span class="special">&gt;</span></code>s
+ into the Docbook XML document for you.
+ </p>
+<p>
+ AutoIndex can also scan using a list of index terms specified in a script file,
+ for example index.idx. These manually provided terms can optionally be regular
+ expressions, and may allow the user to find references to terms that may not
+ occur in the C++ header files. Of course providing a manual list of search
+ terms in to index is a tedious task (especially handling plurals and variants),
+ and requires enough knowledge of the library to guess what users may be seeking
+ to know, but at least the real 'grunt work' of finding the term and listing
+ the page number is automated.
+ </p>
+<p>
+ AutoIndex creates index entries as follows:
+ </p>
+<p>
+ for each occurrence of each search term, it creates two index entries:
+ </p>
+<div class="orderedlist"><ol class="orderedlist" type="1">
+<li class="listitem">
+ The search term as the <span class="emphasis"><em>primary index key</em></span> and the
+ <span class="emphasis"><em>title of the section it appears in</em></span> as a subterm.
+ </li>
+<li class="listitem">
+ The section title as the main index entry and the search term as the subentry.
+ </li>
+</ol></div>
+<p>
+ Thus the user has two chances to find what they're looking for, based upon
+ either the section name or the <span class="emphasis"><em>function</em></span>, <span class="emphasis"><em>class</em></span>,
+ <span class="emphasis"><em>macro</em></span> or <span class="emphasis"><em>typedef</em></span> name.
+ </p>
+<div class="note"><table border="0" summary="Note">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td>
+<th align="left">Note</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ This behaviour can be changed so that only one index entry is created (using
+ the search term as the key and not using the section name except as a sub-entry
+ of the search term).
+ </p></td></tr>
+</table></div>
+<p>
+ So for example in Boost.Math the class name <code class="computeroutput"><span class="identifier">students_t_distribution</span></code>
+ has a primary entry that lists all sections the class name appears in:
+ </p>
+<p>
+ <span class="inlinemediaobject"><img src="../../students_t_eg_1.png" alt="students_t_eg_1"></span>
+ </p>
+<p>
+ Then those sections also have primary entries, which list all the search terms
+ those sections contain:
+ </p>
+<p>
+ <span class="inlinemediaobject"><img src="../../students_t_eg_2.png" alt="students_t_eg_2"></span>
+ </p>
+<p>
+ Of course these automated index entries may not be quite what you're looking
+ for: often you'll get a few spurious entries, a few missing entries, and a
+ few entries where the section name used as an index entry is less than ideal.
+ So AutoIndex provides some powerful regular expression based rules that allow
+ you to add, remove, constrain, or rewrite entries. Normally just a few lines
+ in AutoIndex's script file are enough to tailor the output to match the author's
+ expectations (and thus hopefully the index user's expectations too!).
+ </p>
+<p>
+ AutoIndex also supports multiple indexes (as does Docbook), and since it knows
+ which search terms are <span class="emphasis"><em>function</em></span>, <span class="emphasis"><em>class</em></span>,
+ <span class="emphasis"><em>macro</em></span> or <span class="emphasis"><em>typedef</em></span> names, it can add
+ the necessary attributes to the XML so that you can have separate indexes for
+ each of these different types. These specialised indexes only contain entries
+ for the <span class="emphasis"><em>function</em></span>, <span class="emphasis"><em>class</em></span>, <span class="emphasis"><em>macro</em></span>
+ or <span class="emphasis"><em>typedef</em></span> names, <span class="emphasis"><em>section names</em></span> are
+ never used as primary index terms here, unlike the main "include everything"
+ index.
+ </p>
+<p>
+ Finally, while the Docbook XSL stylesheets create nice indexes complete with
+ page numbers for PDF output, the HTML indexes look poorer by comparison, as
+ these use section titles in place of page numbers... but as AutoIndex uses
+ section titles as index entries this leads to a lot of repetition, so as an
+ alternative AutoIndex can be instructed to construct the index itself. This
+ is faster than using the XSL stylesheets, and now each index entry is a hyperlink
+ to the appropriate section:
+ </p>
+<p>
+ <span class="inlinemediaobject"><img src="../../students_t_eg_3.png" alt="students_t_eg_3"></span>
+ </p>
+<p>
+ With internal index generation there is also a helpful navigation bar at the
+ start of each Index:
+ </p>
+<p>
+ <span class="inlinemediaobject"><img src="../../students_t_eg_4.png" alt="students_t_eg_4"></span>
+ </p>
+<p>
+ Finally, you can choose what kind of XML container wraps an internally generated
+ index - this defaults to <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">section</span><span class="special">&gt;...&lt;/</span><span class="identifier">section</span><span class="special">&gt;</span></code>
+ but you can use either command line options or Boost.Build Jamfile features,
+ to select an alternative wrapper - for example <span class="emphasis"><em>appendix</em></span>
+ or <span class="emphasis"><em>chapter</em></span> would be good choices, whatever fits best into
+ the flow of the document. You can even set the container wrapper to type <span class="emphasis"><em>index</em></span>
+ provided you turn off index generation by the XSL stylesheets, for example
+ by setting the following build requirements in the Jamfile:
+ </p>
+<pre class="programlisting">&lt;format&gt;html:&lt;auto-index-internal&gt;on # Use internally generated indexes.
+&lt;auto-index-type&gt;index # Use &lt;index&gt;...&lt;/index&gt; as the XML wrapper.
+&lt;format&gt;html:&lt;xsl:param&gt;generate.index=0 # Don't let the XSL stylesheets generate indexes.
+</pre>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tut.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/qbk.html b/tools/auto_index/doc/html/boost_autoindex/qbk.html
new file mode 100644
index 0000000000..1365b8d2de
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/qbk.html
@@ -0,0 +1,229 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Quickbook Support</title>
+<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../index.html" title="Boost.AutoIndex">
+<link rel="prev" href="xml.html" title="XML Handling">
+<link rel="next" href="comm_ref.html" title="Command Line Reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="xml.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="comm_ref.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="boost_autoindex.qbk"></a><a class="link" href="qbk.html" title="Quickbook Support">Quickbook Support</a>
+</h2></div></div></div>
+<p>
+ The file auto_index_helpers.qbk in <span class="emphasis"><em>boost-path</em></span>/tools/auto_index/include
+ contains various Quickbook templates to assist with AutoIndex support. One
+ would normally add the above path to your include search path via an <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">include</span><span class="special">&gt;</span><span class="identifier">path</span></code>
+ statement in your Jamfile, and then make the templates available to your Quickbook
+ source via a:
+ </p>
+<pre class="programlisting">[include auto_index_helpers.qbk]</pre>
+<p>
+ statement at the start of your Quickbook file.
+ </p>
+<p>
+ The available templates are then:
+ </p>
+<div class="informaltable"><table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>
+ <p>
+ Template
+ </p>
+ </th>
+<th>
+ <p>
+ Description
+ </p>
+ </th>
+</tr></thead>
+<tbody>
+<tr>
+<td>
+ <p>
+ <code class="computeroutput"><span class="special">[</span><span class="identifier">index</span><span class="special">]</span></code>
+ </p>
+ </td>
+<td>
+ <p>
+ Creates a main index, with no "type" category set, which
+ will be titled simply "Index".
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="computeroutput"><span class="special">[</span><span class="identifier">named_index</span>
+ <span class="identifier">type</span> <span class="identifier">title</span><span class="special">]</span></code>
+ </p>
+ </td>
+<td>
+ <p>
+ Creates an index with the type attribute set to "type"
+ and the title will be "title".<br> For example to create
+ an index containing only class names one would typically add <code class="computeroutput"><span class="special">[</span><span class="identifier">named_index</span>
+ <span class="identifier">class_name</span> <span class="identifier">Class</span>
+ <span class="identifier">Index</span><span class="special">]</span></code>
+ to your Quickbook source.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="computeroutput"><span class="special">[</span><span class="identifier">AutoIndex</span>
+ <span class="identifier">Arg</span><span class="special">]</span></code>
+ </p>
+ </td>
+<td>
+ <p>
+ Creates a Docbook processing instruction that will be handled by
+ AutoIndex, valid values for "Arg" are either "IgnoreSection"
+ or "IgnoreBlock".
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="computeroutput"><span class="special">[</span><span class="identifier">indexterm1</span>
+ <span class="identifier">primary</span><span class="special">-</span><span class="identifier">key</span><span class="special">]</span></code>
+ </p>
+ </td>
+<td>
+ <p>
+ Creates a manual index entry that will link to the current section,
+ and have a single primary key "primary-key". Note that
+ this index key will not have a "type" attribute set, and
+ so will only appear in the main index.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="computeroutput"><span class="special">[</span><span class="identifier">indexterm2</span>
+ <span class="identifier">primary</span><span class="special">-</span><span class="identifier">key</span> <span class="identifier">secondary</span><span class="special">-</span><span class="identifier">key</span><span class="special">]</span></code>
+ </p>
+ </td>
+<td>
+ <p>
+ Creates a manual index entry that will link to the current section,
+ and has "primary-key" and "secondary key" as
+ the primary and secondary keys respectively. Note that this index
+ key will not have a "type" attribute set, and so will only
+ appear in the main index.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="computeroutput"><span class="special">[</span><span class="identifier">indexterm3</span>
+ <span class="identifier">primary</span><span class="special">-</span><span class="identifier">key</span> <span class="identifier">secondary</span><span class="special">-</span><span class="identifier">key</span>
+ <span class="identifier">tertiary</span><span class="special">-</span><span class="identifier">key</span><span class="special">]</span></code>
+ </p>
+ </td>
+<td>
+ <p>
+ Creates a manual index entry that will link to the current section,
+ and have primary, secondary and tertiary keys: "primary-key",
+ "secondary key" and "tertiary key". Note that
+ this index key will not have a "type" attribute set, and
+ so will only appear in the main index.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="computeroutput"><span class="special">[</span><span class="identifier">typed_indexterm1</span>
+ <span class="identifier">type</span> <span class="identifier">primary</span><span class="special">-</span><span class="identifier">key</span><span class="special">]</span></code>
+ </p>
+ </td>
+<td>
+ <p>
+ Creates a manual index entry that will link to the current section,
+ and have a single primary key "primary-key". Note that
+ this index key will have the "type" attribute set to the
+ "type" argument, and so may appear in named sub-indexes
+ that also have their type attribute set.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="computeroutput"><span class="special">[</span><span class="identifier">typed_indexterm2</span>
+ <span class="identifier">type</span> <span class="identifier">primary</span><span class="special">-</span><span class="identifier">key</span>
+ <span class="identifier">secondary</span><span class="special">-</span><span class="identifier">key</span><span class="special">]</span></code>
+ </p>
+ </td>
+<td>
+ <p>
+ Creates a manual index entry that will link to the current section,
+ and has "primary-key" and "secondary key" as
+ the primary and secondary keys respectively. Note that this index
+ key will have the "type" attribute set to the "type"
+ argument, and so may appear in named sub-indexes that also have their
+ type attribute set.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="computeroutput"><span class="special">[</span><span class="identifier">typed_indexterm3</span>
+ <span class="identifier">type</span> <span class="identifier">primary</span><span class="special">-</span><span class="identifier">key</span>
+ <span class="identifier">secondary</span><span class="special">-</span><span class="identifier">key</span> <span class="identifier">tertiary</span><span class="special">-</span><span class="identifier">key</span><span class="special">]</span></code>
+ </p>
+ </td>
+<td>
+ <p>
+ Creates a manual index entry that will link to the current section,
+ and have primary, secondary and tertiary keys: "primary-key",
+ "secondary key" and "tertiary key". Note that
+ this index key will have the "type" attribute set to the
+ "type" argument, and so may appear in named sub-indexes
+ that also have their type attribute set.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="xml.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="comm_ref.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/script_ref.html b/tools/auto_index/doc/html/boost_autoindex/script_ref.html
new file mode 100644
index 0000000000..bd994d3d26
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/script_ref.html
@@ -0,0 +1,525 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Script File (.idx) Reference</title>
+<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../index.html" title="Boost.AutoIndex">
+<link rel="prev" href="tut/refine.html" title="Step 8: Iterate - to refine your index">
+<link rel="next" href="workflow.html" title="Understanding The AutoIndex Workflow">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="tut/refine.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="workflow.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="boost_autoindex.script_ref"></a><a class="link" href="script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a>
+</h2></div></div></div>
+<p>
+ The following elements can occur in a script:
+ </p>
+<a name="boost_autoindex.script_ref.comments_and_blank_lines"></a><h5>
+<a name="boost_autoindex.script_ref.comments_and_blank_lines-heading"></a>
+ <a class="link" href="script_ref.html#boost_autoindex.script_ref.comments_and_blank_lines">Comments
+ and blank lines</a>
+ </h5>
+<p>
+ Blank lines consisting of only whitespace are ignored, so are lines that <span class="bold"><strong>start with a #</strong></span>.
+ </p>
+<div class="note"><table border="0" summary="Note">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td>
+<th align="left">Note</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ You can't append # comments onto the end of a line!
+ </p></td></tr>
+</table></div>
+<a name="boost_autoindex.script_ref.inclusion_of_index_terms"></a><h5>
+<a name="boost_autoindex.script_ref.inclusion_of_index_terms-heading"></a>
+ <a class="link" href="script_ref.html#boost_autoindex.script_ref.inclusion_of_index_terms">Inclusion
+ of Index terms</a>
+ </h5>
+<pre class="programlisting"><span class="identifier">term</span> <span class="special">[</span><span class="identifier">regular</span><span class="special">-</span><span class="identifier">expression1</span> <span class="special">[</span><span class="identifier">regular</span><span class="special">-</span><span class="identifier">expression2</span> <span class="special">[</span><span class="identifier">category</span><span class="special">]]]</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">term</span></dt>
+<dd>
+<p>
+ <span class="emphasis"><em>Term to index.</em></span>
+ </p>
+<p>
+ The index term will form a primary entry in the Index with the section
+ title(s) containing the term as secondary entries, and also will be used
+ as a secondary entry beneath each of the section titles that the index
+ term occurs in.
+ </p>
+</dd>
+<dt><span class="term">regular-expression1</span></dt>
+<dd>
+<p>
+ <span class="emphasis"><em>Index term Searcher.</em></span>
+ </p>
+<p>
+ An optional regular expression: each occurrence of the regular expression
+ in the text of the document will result in one index term being emitted.
+ </p>
+<p>
+ If the regular expression is omitted (default) or is "", then
+ the <span class="emphasis"><em>index term</em></span> itself will be used as the search
+ text - and only occurrence of whole words matching <span class="emphasis"><em>index term</em></span>
+ will be indexed.
+ </p>
+<p>
+ For example:
+ </p>
+<p>
+
+</p>
+<pre class="programlisting"><span class="identifier">foobar</span></pre>
+<p>
+ </p>
+<p>
+ will index occurrences of "foobar" in any section, but
+ </p>
+<p>
+
+</p>
+<pre class="programlisting"><span class="identifier">foobar</span> <span class="special">\&lt;\</span><span class="identifier">w</span><span class="special">*(</span><span class="identifier">foo</span><span class="special">|</span><span class="identifier">bar</span><span class="special">)\</span><span class="identifier">w</span><span class="special">*\&gt;</span></pre>
+<p>
+ </p>
+<p>
+ will index any whole word containing either "foo" or "bar"
+ within it. This is useful when you want to index a lot of similar or
+ related words under one entry.
+ </p>
+<p>
+
+</p>
+<pre class="programlisting"><span class="identifier">reflex</span></pre>
+<p>
+ </p>
+<p>
+ will only index occurrences of "reflex" as a whole word, but:
+ </p>
+<p>
+
+</p>
+<pre class="programlisting"><span class="identifier">reflex</span> <span class="special">\&lt;</span><span class="identifier">reflex</span><span class="special">\</span><span class="identifier">w</span><span class="special">*\&gt;</span></pre>
+<p>
+ </p>
+<p>
+ will index occurrences of "reflex", "reflexes", "reflexing"
+ and "reflexed" ... all under the same entry reflex.
+ </p>
+<p>
+ You will very often need to use this to deal with plurals and other variants.
+ </p>
+</dd>
+<dt><span class="term">regular-expression2</span></dt>
+<dd>
+<p>
+ <span class="emphasis"><em>Section(s) Selector.</em></span>
+ </p>
+<p>
+ A constraint that specifies which sections are indexed for <span class="emphasis"><em>term</em></span>:
+ only if the ID of the section matches <span class="emphasis"><em>regular-expression2</em></span>
+ exactly will that section be indexed for occurrences of <span class="emphasis"><em>term</em></span>.
+ </p>
+<p>
+ For example, to limit indexing to just <span class="bold"><strong>one specific
+ section</strong></span> (but not sub-sections below):
+ </p>
+<p>
+
+</p>
+<pre class="programlisting"><span class="identifier">myclass</span> <span class="string">""</span> <span class="string">"mylib\.examples"</span></pre>
+<p>
+ </p>
+<p>
+ For example, to limit indexing to specific sections, <span class="bold"><strong>and
+ sub-sections below</strong></span>:
+ </p>
+<p>
+
+</p>
+<pre class="programlisting"><span class="identifier">myclass</span> <span class="string">""</span> <span class="string">"mylib\.examples.*"</span></pre>
+<p>
+ </p>
+<p>
+ will index occurrences of "myclass" as a whole word, but only
+ in sections whose section ID <span class="bold"><strong>begins</strong></span>
+ "mylib.examples", while
+ </p>
+<p>
+
+</p>
+<pre class="programlisting"><span class="identifier">myclass</span> <span class="string">"\&lt;myclass\w*\&gt;"</span> <span class="string">"mylib\.examples.*"</span></pre>
+<p>
+ </p>
+<p>
+ will also index plurals myclass, myclasses, myclasss ...
+ </p>
+<p>
+ and:
+ </p>
+<p>
+
+</p>
+<pre class="programlisting"><span class="identifier">myclass</span> <span class="string">""</span> <span class="string">"(?!mylib\.introduction).*"</span></pre>
+<p>
+ </p>
+<p>
+ will index occurrences of "myclass" in any section, except
+ those whose section IDs begin "mylib.introduction".
+ </p>
+<p>
+ Finally, two (or more) sections can be excluded by OR'ing them together:
+ </p>
+<p>
+
+</p>
+<pre class="programlisting"><span class="identifier">myclass</span> <span class="string">""</span> <span class="string">"(?!mylib\.introduction|mylib\.reference).*"</span></pre>
+<p>
+ </p>
+<p>
+ which excludes searching for this term in sections whose ID's start with
+ either "mylib.introduction" or "mylib.reference".
+ </p>
+<p>
+ If this third section selection field is omitted (the default) or is
+ "", then <span class="bold"><strong>all sections</strong></span> are
+ indexed for this term.
+ </p>
+</dd>
+<dt><span class="term">category</span></dt>
+<dd>
+<p>
+ <span class="emphasis"><em>Index Category Constraint.</em></span>
+ </p>
+<p>
+ Optionally a category to place occurrences of <span class="emphasis"><em>index term</em></span>
+ in. If you have multiple indexes then this is the name assigned to the
+ indexes "type" attribute.
+ </p>
+<p>
+ For example:
+ </p>
+<p>
+ myclass "" "" class_name
+ </p>
+<p>
+ Will index occurances of <span class="emphasis"><em>myclass</em></span> and place them
+ in the class-index if there is one.
+ </p>
+</dd>
+</dl>
+</div>
+<p>
+ You can have an index term appear more than once in the script file:
+ </p>
+<div class="itemizedlist"><ul class="itemizedlist" type="disc">
+<li class="listitem">
+ If they have different <span class="emphasis"><em>category</em></span> names then they are
+ treated quite separately.
+ </li>
+<li class="listitem">
+ Otherwise they are combined, so that the logical or of the regular expressions
+ provided are taken.
+ </li>
+</ul></div>
+<p>
+ Thus:
+ </p>
+<pre class="programlisting"><span class="identifier">myterm</span> <span class="identifier">search_expression1</span> <span class="identifier">constrait_expression2</span> <span class="identifier">foo</span>
+<span class="identifier">myterm</span> <span class="identifier">search_expression1</span> <span class="identifier">constrait_expression2</span> <span class="identifier">bar</span>
+</pre>
+<p>
+ Will be treated as different terms each with their own entries, while:
+ </p>
+<pre class="programlisting"><span class="identifier">myterm</span> <span class="identifier">search_expression1</span> <span class="identifier">constrait_expression2</span> <span class="identifier">mycategory</span>
+<span class="identifier">myterm</span> <span class="identifier">search_expression1</span> <span class="identifier">constrait_expression2</span> <span class="identifier">mycategory</span>
+</pre>
+<p>
+ Will be combined into a single term equivalent to:
+ </p>
+<pre class="programlisting"><span class="identifier">myterm</span> <span class="special">(?:</span><span class="identifier">search_expression1</span><span class="special">|</span><span class="identifier">search_expression1</span><span class="special">)</span> <span class="special">(?:</span><span class="identifier">constrait_expression2</span><span class="special">|</span><span class="identifier">constrait_expression2</span><span class="special">)</span> <span class="identifier">mycategory</span>
+</pre>
+<a name="boost_autoindex.script_ref.source_file_scanning"></a><h5>
+<a name="boost_autoindex.script_ref.source_file_scanning-heading"></a>
+ <a class="link" href="script_ref.html#boost_autoindex.script_ref.source_file_scanning">Source File
+ Scanning</a>
+ </h5>
+<pre class="programlisting"><span class="special">!</span><span class="identifier">scan</span> <span class="identifier">source</span><span class="special">-</span><span class="identifier">file</span><span class="special">-</span><span class="identifier">name</span>
+</pre>
+<p>
+ Scans the C/C++ source file <span class="emphasis"><em>source-file-name</em></span> for definitions
+ of <span class="emphasis"><em>function</em></span>s, <span class="emphasis"><em>class</em></span>s, <span class="emphasis"><em>macro</em></span>s
+ or <span class="emphasis"><em>typedef</em></span>s and makes each of these a term to be indexed.
+ Terms found are assigned to the index category "function_name", "class_name",
+ "macro_name" or "typedef_name" depending on how they were
+ seen in the source file. These may then be included in a specialised index
+ whose "type" attribute has the same category name.
+ </p>
+<div class="important"><table border="0" summary="Important">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../../../doc/src/images/important.png"></td>
+<th align="left">Important</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ When actually indexing a document, the scanner will not index just any old
+ occurrence of the terms found in the source files. Instead it searches for
+ class definitions or function or typedef declarations. This reduces the number
+ of spurious matches placed in the index, but may also miss some legitimate
+ terms: refer to the <span class="emphasis"><em>define-scanner</em></span> command for information
+ on how to change this.
+ </p></td></tr>
+</table></div>
+<a name="boost_autoindex.script_ref.directory_and_source_file_scanning"></a><h5>
+<a name="boost_autoindex.script_ref.directory_and_source_file_scanning-heading"></a>
+ <a class="link" href="script_ref.html#boost_autoindex.script_ref.directory_and_source_file_scanning">Directory
+ and Source File Scanning</a>
+ </h5>
+<pre class="programlisting"><span class="special">!</span><span class="identifier">scan</span><span class="special">-</span><span class="identifier">path</span> <span class="identifier">directory</span><span class="special">-</span><span class="identifier">name</span> <span class="identifier">file</span><span class="special">-</span><span class="identifier">name</span><span class="special">-</span><span class="identifier">regex</span> <span class="special">[</span><span class="identifier">recurse</span><span class="special">]</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">directory-name</span></dt>
+<dd><p>
+ The directory to scan: this should be a path relative to the script file
+ (or to the path specified with the prefix=path option on the command
+ line) and should use all forward slashes in its file name.
+ </p></dd>
+<dt><span class="term">file-name-regex</span></dt>
+<dd><p>
+ A regular expression: any file in the directory whose name matches the
+ regular expression will be scanned for terms to index.
+ </p></dd>
+<dt><span class="term">recurse</span></dt>
+<dd><p>
+ An optional boolean value - either "true" or "false"
+ - that indicates whether to recurse into subdirectories. This defaults
+ to "false".
+ </p></dd>
+</dl>
+</div>
+<a name="boost_autoindex.script_ref.excluding_terms"></a><h5>
+<a name="boost_autoindex.script_ref.excluding_terms-heading"></a>
+ <a class="link" href="script_ref.html#boost_autoindex.script_ref.excluding_terms">Excluding Terms</a>
+ </h5>
+<pre class="programlisting"><span class="special">!</span><span class="identifier">exclude</span> <span class="identifier">term</span><span class="special">-</span><span class="identifier">list</span>
+</pre>
+<p>
+ Excludes all the terms in whitespace separated <span class="emphasis"><em>term-list</em></span>
+ from being indexed. This should be placed <span class="emphasis"><em>after</em></span> any <span class="emphasis"><em>!scan</em></span>
+ or <span class="emphasis"><em>!scan-path</em></span> rules which may result in the terms becoming
+ included. In other words this removes terms from the scanners internal list
+ of things to index.
+ </p>
+<a name="boost_autoindex.script_ref.rewriting_section_names"></a><h5>
+<a name="boost_autoindex.script_ref.rewriting_section_names-heading"></a>
+ <a class="link" href="script_ref.html#boost_autoindex.script_ref.rewriting_section_names">Rewriting
+ Section Names</a>
+ </h5>
+<pre class="programlisting">!rewrite-id regular-expression new-name</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">regular-expression</span></dt>
+<dd><p>
+ A regular expression: all section ID's that match the expression exactly
+ will have index entries <span class="emphasis"><em>new-name</em></span> instead of their
+ title(s).
+ </p></dd>
+<dt><span class="term">new-name</span></dt>
+<dd><p>
+ The name that the section will appear under in the index.
+ </p></dd>
+</dl>
+</div>
+<pre class="programlisting"><span class="special">!</span><span class="identifier">rewrite</span><span class="special">-</span><span class="identifier">name</span> <span class="identifier">regular</span><span class="special">-</span><span class="identifier">expression</span> <span class="identifier">format</span><span class="special">-</span><span class="identifier">text</span>
+</pre>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">regular-expression</span></dt>
+<dd><p>
+ A regular expression: all sections whose titles match the regular expression
+ exactly, will have index entries composed of the regular expression match
+ combined with the regex format string <span class="emphasis"><em>format-text</em></span>.
+ </p></dd>
+<dt><span class="term">format-text</span></dt>
+<dd><p>
+ The Perl-style format string used to reformat the title.
+ </p></dd>
+</dl>
+</div>
+<p>
+ For example:
+ </p>
+<pre class="programlisting">!rewrite-name "(?:A|An|The)\s+(.*)" "\1"
+</pre>
+<p>
+ Will remove any leading "A", "An" or "The" from
+ all index entries - thus preventing lots of entries under "The" etc!
+ </p>
+<a name="boost_autoindex.script_ref.defining_or_changing_the_file_scanners"></a><h5>
+<a name="boost_autoindex.script_ref.defining_or_changing_the_file_scanners-heading"></a>
+ <a class="link" href="script_ref.html#boost_autoindex.script_ref.defining_or_changing_the_file_scanners">Defining
+ or Changing the File Scanners</a>
+ </h5>
+<pre class="programlisting"><span class="special">!</span><span class="identifier">define</span><span class="special">-</span><span class="identifier">scanner</span> <span class="identifier">type</span> <span class="identifier">file</span><span class="special">-</span><span class="identifier">search</span><span class="special">-</span><span class="identifier">expression</span> <span class="identifier">xml</span><span class="special">-</span><span class="identifier">regex</span><span class="special">-</span><span class="identifier">formatter</span> <span class="identifier">term</span><span class="special">-</span><span class="identifier">formatter</span> <span class="identifier">id</span><span class="special">-</span><span class="identifier">filter</span> <span class="identifier">filename</span><span class="special">-</span><span class="identifier">filter</span>
+</pre>
+<p>
+ When a source file is scanned using the <code class="literal">!scan</code> or <code class="literal">!scan-path</code>
+ rules, then the file is searched using a series of regular expressions to look
+ for classes, functions, macros or typedefs that should be indexed. A set of
+ default regular expressions are provided for this (see below), but sometimes
+ you may want to replace the defaults, or add new scanners. The arguments to
+ this rule are:
+ </p>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">type</span></dt>
+<dd><p>
+ The <span class="emphasis"><em>type</em></span> to which items found using this rule will
+ assigned, index terms created from the source file and then found in
+ the XML, will have the type attribute set to this value, and may then
+ appear in a specialized index with the same type attribute
+ </p></dd>
+<dt><span class="term">file-search-expression</span></dt>
+<dd><p>
+ A regular expression that is used to scan the source file for index terms,
+ the result of a match against this expression will be transformed by
+ the next two arguments.
+ </p></dd>
+<dt><span class="term">xml-regex-formatter</span></dt>
+<dd><p>
+ A regular expression format string that extracts the salient information
+ from whatever matched the <span class="emphasis"><em>file-search-expression</em></span>
+ in the source file, and creates <span class="emphasis"><em>a new regular expression</em></span>
+ that will be used to search the document being indexed for occurrences
+ of this index term.
+ </p></dd>
+<dt><span class="term">term-formatter</span></dt>
+<dd><p>
+ A regular expression format string that extracts the salient information
+ from whatever matched the <span class="emphasis"><em>file-search-expression</em></span>
+ in the source file, and creates the index term that will appear in the
+ index.
+ </p></dd>
+<dt><span class="term">id-filter</span></dt>
+<dd><p>
+ Optional. A regular expression that restricts the section-id's that are
+ searched in the document being indexed: only sections whose ID attribute
+ matches this expression exactly will be considered for indexing terms
+ found by this scanner.
+ </p></dd>
+<dt><span class="term">filename-filter</span></dt>
+<dd><p>
+ Optional. A regular expression that restricts which files are scanned
+ by this scanner: only files whose file name matches this expression exactly
+ will be scanned for index terms to use. Note that the filename matched
+ against this may well be an absolute path, and contain either forward
+ or backward slash path separators.
+ </p></dd>
+</dl>
+</div>
+<p>
+ If, when the first file is scanned, there are no scanners whose <span class="emphasis"><em>type</em></span>
+ is "class_name", "typedef_name", "macro_name"
+ or "function_name", then the defaults are installed. These are equivalent
+ to:
+ </p>
+<pre class="programlisting"><span class="special">!</span><span class="identifier">define</span><span class="special">-</span><span class="identifier">scanner</span> <span class="identifier">class_name</span> <span class="string">"^[[:space:]]*(template[[:space:]]*&lt;[^;:{]+&gt;[[:space:]]*)?(class|struct)[[:space:]]*(\&lt;\w+\&gt;([[:blank:]]*\([^)]*\))?[[:space:]]*)*(\&lt;\w*\&gt;)[[:space:]]*(&lt;[^;:{]+&gt;)?[[:space:]]*(\{|:[^;\{()]*\{)"</span> <span class="string">"(?:class|struct)[^;{]+\\&lt;\5\\&gt;[^;{]+\\{"</span> <span class="special">\</span><span class="number">5</span>
+<span class="special">!</span><span class="identifier">define</span><span class="special">-</span><span class="identifier">scanner</span> <span class="identifier">typedef_name</span> <span class="string">"typedef[^;{}#]+?(\w+)\s*;"</span> <span class="string">"typedef[^;]+\\&lt;\1\\&gt;\\s*;"</span> <span class="string">"\1"</span>
+<span class="special">!</span><span class="identifier">define</span><span class="special">-</span><span class="identifier">scanner</span> <span class="string">"macro_name"</span> <span class="string">"^\s*#\s*define\s+(\w+)"</span> <span class="string">"\\&lt;\1\\&gt;"</span> <span class="string">"\1"</span>
+<span class="special">!</span><span class="identifier">define</span><span class="special">-</span><span class="identifier">scanner</span> <span class="string">"function_name"</span> <span class="string">"\w+(?:\s*&lt;[^&gt;]&gt;)?[\s&amp;*]+?(\w+)\s*(?:BOOST_[[:upper:]_]+\s*)?\([^\)]*\)\s*[;{]"</span> <span class="string">"\\&lt;\\w+\\&gt;(?:\\s+&lt;[^&gt;]*&gt;)?[\\s&amp;*]+\\&lt;\1\\&gt;\\s*\\([^;{]*\\)"</span> <span class="string">"\1"</span>
+</pre>
+<p>
+ Note that these defaults are not installed if you have provided your own versions
+ with these <span class="emphasis"><em>type</em></span> names. In this case if you want the default
+ scanners to be in effect as well as your own, you should include the above
+ in your script file. It is also perfectly allowable to have multiple scanners
+ with the same <span class="emphasis"><em>type</em></span>, but with the other fields differing.
+ </p>
+<p>
+ Finally you should note that the default scanners are quite strict in what
+ they will find, for example the class scanner will only create index entries
+ for classes that have class definitions of the form:
+ </p>
+<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">my_class</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">base_classes</span>
+<span class="special">{</span>
+ <span class="comment">// etc</span>
+</pre>
+<p>
+ In the documentation, so that simple mentions of the class name will <span class="emphasis"><em>not</em></span>
+ get indexed, only the class synopsis if there is one. If this isn't how you
+ want things, then include the <span class="emphasis"><em>class_name</em></span> scanner definition
+ above in your script file, and change the <span class="emphasis"><em>xml-regex-formatter</em></span>
+ field to something more permissive, for example:
+ </p>
+<pre class="programlisting"><span class="special">!</span><span class="identifier">define</span><span class="special">-</span><span class="identifier">scanner</span> <span class="identifier">class_name</span> <span class="string">"^[[:space:]]*(template[[:space:]]*&lt;[^;:{]+&gt;[[:space:]]*)?(class|struct)[[:space:]]*(\&lt;\w+\&gt;([[:blank:]]*\([^)]*\))?[[:space:]]*)*(\&lt;\w*\&gt;)[[:space:]]*(&lt;[^;:{]+&gt;)?[[:space:]]*(\{|:[^;\{()]*\{)"</span> <span class="string">"\\&lt;\5\\&gt;"</span> <span class="special">\</span><span class="number">5</span>
+</pre>
+<p>
+ Will look for <span class="emphasis"><em>any</em></span> occurrence of whatever class names the
+ scanner may find in the documentation.
+ </p>
+<a name="boost_autoindex.script_ref.debugging_scanning"></a><h5>
+<a name="boost_autoindex.script_ref.debugging_scanning-heading"></a>
+ <a class="link" href="script_ref.html#boost_autoindex.script_ref.debugging_scanning">Debugging scanning</a>
+ </h5>
+<p>
+ If you see a term in the index, and you don't understand why it's there, add
+ a <span class="emphasis"><em>debug</em></span> directive:
+ </p>
+<pre class="programlisting">!debug regular-expression
+</pre>
+<p>
+ Now, whenever <span class="emphasis"><em>regular-expression</em></span> matches either the found
+ index term, or the section title it appears in, or the <span class="emphasis"><em>type</em></span>
+ field of a scanner, then some diagnostic information will be printed that will
+ look something like:
+ </p>
+<pre class="programlisting">Debug term found, in block with ID: spirit.qi.reference.parser_concepts.parser
+Current section title is: Notation
+The main index entry will be : Notation
+The indexed term is: parser
+The search regex is: [P|p]arser
+The section constraint is: .<span class="bold"><strong>qi.reference.parser_concepts.</strong></span>
+The index type for this entry is: qi_index
+</pre>
+<p>
+ This can produce a lot of output in your log file, but until you are satisfied
+ with your file selection and scanning process, it is worth switching it on.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="tut/refine.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="workflow.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/tut.html b/tools/auto_index/doc/html/boost_autoindex/tut.html
new file mode 100644
index 0000000000..646e441041
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/tut.html
@@ -0,0 +1,66 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Getting Started and Tutorial</title>
+<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../index.html" title="Boost.AutoIndex">
+<link rel="prev" href="overview.html" title="Overview">
+<link rel="next" href="tut/build.html" title="Step 1: Build the AutoIndex tool">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="overview.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tut/build.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="boost_autoindex.tut"></a><a class="link" href="tut.html" title="Getting Started and Tutorial">Getting Started and Tutorial</a>
+</h2></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section"><a href="tut/build.html">Step 1: Build the AutoIndex
+ tool</a></span></dt>
+<dt><span class="section"><a href="tut/configure.html">Step 2: Configure Boost.Build
+ jamfile to use AutoIndex</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="tut/configure/options.html">Available Indexing
+ Options</a></span></dt>
+<dt><span class="section"><a href="tut/configure/optional.html">Making AutoIndex
+ optional</a></span></dt>
+</dl></dd>
+<dt><span class="section"><a href="tut/add_indexes.html">Step 3: Add indexes
+ to your documentation</a></span></dt>
+<dt><span class="section"><a href="tut/script.html">Step 4: Create the .idx script
+ file - to control what to terms to index</a></span></dt>
+<dt><span class="section"><a href="tut/entries.html">Step 5: Add Manual Index
+ Entries to Docbook XML - Optional</a></span></dt>
+<dt><span class="section"><a href="tut/pis.html">Step 6: Using XML processing
+ instructions to control what gets indexed.</a></span></dt>
+<dt><span class="section"><a href="tut/build_docs.html">Step 7: Build the Docs</a></span></dt>
+<dt><span class="section"><a href="tut/refine.html">Step 8: Iterate - to refine
+ your index</a></span></dt>
+</dl></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="overview.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tut/build.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/tut/add_indexes.html b/tools/auto_index/doc/html/boost_autoindex/tut/add_indexes.html
new file mode 100644
index 0000000000..d2fff87172
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/tut/add_indexes.html
@@ -0,0 +1,173 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Step 3: Add indexes to your documentation</title>
+<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../tut.html" title="Getting Started and Tutorial">
+<link rel="prev" href="configure/optional.html" title="Making AutoIndex optional">
+<link rel="next" href="script.html" title="Step 4: Create the .idx script file - to control what to terms to index">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="configure/optional.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="script.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="boost_autoindex.tut.add_indexes"></a><a class="link" href="add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes
+ to your documentation</a>
+</h3></div></div></div>
+<p>
+ To add a single "include everything" index to a BoostBook/Docbook
+ document, (perhaps generated using Quickbook, and perhaps also using Doxygen
+ reference section), add <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">index</span><span class="special">/&gt;</span></code>
+ at the location where you want the index to appear. The index will be rendered
+ as a separate section called "Index" when the documentation is
+ built.
+ </p>
+<p>
+ To add multiple indexes, then give each one a title and set its <code class="computeroutput"><span class="identifier">type</span></code> attribute to specify which terms will
+ be included, for example to place the <span class="emphasis"><em>function</em></span>, <span class="emphasis"><em>class</em></span>,
+ <span class="emphasis"><em>macro</em></span> or <span class="emphasis"><em>typedef</em></span> names indexed
+ by <span class="emphasis"><em>AutoIndex</em></span> in separate indexes along with a main "include
+ everything" index as well, one could add:
+ </p>
+<pre class="programlisting">&lt;index type="class_name"&gt;
+&lt;title&gt;Class Index&lt;/title&gt;
+&lt;/index&gt;
+
+&lt;index type="typedef_name"&gt;
+&lt;title&gt;Typedef Index&lt;/title&gt;
+&lt;/index&gt;
+
+&lt;index type="function_name"&gt;
+&lt;title&gt;Function Index&lt;/title&gt;
+&lt;/index&gt;
+
+&lt;index type="macro_name"&gt;
+&lt;title&gt;Macro Index&lt;/title&gt;
+&lt;/index&gt;
+
+&lt;index/&gt;
+</pre>
+<div class="note"><table border="0" summary="Note">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
+<th align="left">Note</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ Multiple indexes like this only work correctly if you tell the XSL stylesheets
+ to honor the "type" attribute on each index as by default . You
+ can turn the feature on by adding <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">xsl</span><span class="special">:</span><span class="identifier">param</span><span class="special">&gt;</span><span class="identifier">index</span><span class="special">.</span><span class="identifier">on</span><span class="special">.</span><span class="identifier">type</span><span class="special">=</span><span class="number">1</span></code> to your
+ projects requirements in the Jamfile.
+ </p></td></tr>
+</table></div>
+<p>
+ In Quickbook, you add the same markup but enclose it between two triple-tick
+ ''' escapes, thus
+ </p>
+<pre class="programlisting">'''&lt;index/&gt;''' </pre>
+<p>
+ Or more easily via the helper file auto_index_helpers.qbk, so that given:
+ </p>
+<pre class="programlisting">[include auto_index_helpers.qbk]</pre>
+<p>
+ one can simply write:
+ </p>
+<pre class="programlisting">[named_index class_name Class Index]
+[named_index function_name Function Index]
+[named_index typedef_name Typedef Index]
+[named_index macro_name Macro Index]
+[index]
+</pre>
+<div class="note"><table border="0" summary="Note">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
+<th align="left">Note</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ AutoIndex knows nothing of the XML <code class="computeroutput"><span class="identifier">xinclude</span></code>
+ element, so if you're writing raw Docbook XML then you may want to run
+ this through an XSL processor to flatten everything to one XML file before
+ passing to AutoIndex. If you're using Boostbook or quickbook though, this
+ all happens for you anyway, and AutoIndex will index the whole document
+ including any sections included with <code class="computeroutput"><span class="identifier">xinclude</span></code>.
+ </p></td></tr>
+</table></div>
+<p>
+ If you are using AutoIndex's internal index generation on
+ </p>
+<pre class="programlisting">&lt;auto-index-internal&gt;on
+</pre>
+<p>
+ (usually recommended for HTML output, but <span class="emphasis"><em>not</em></span> the default)
+ then you can also decide what kind of XML wrapper the generated index is
+ placed in. By default this is a <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">section</span><span class="special">&gt;...&lt;/</span><span class="identifier">section</span><span class="special">&gt;</span></code>
+ XML block (this replaces the original <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">index</span><span class="special">&gt;...&lt;/</span><span class="identifier">index</span><span class="special">&gt;</span></code>
+ block). However, depending upon the structure of the document and whether
+ or not you want the index on a separate page - or else on the front page
+ after the TOC - you may want to place the index inside a different type of
+ XML block. For example if your document uses <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">chapter</span><span class="special">&gt;</span></code>
+ top level content rather than <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">section</span><span class="special">&gt;</span></code>s
+ then it may be preferable to place the index in a <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">chapter</span><span class="special">&gt;</span></code>
+ or <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">appendix</span><span class="special">&gt;</span></code> block. You can also place the index inside
+ an <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">index</span><span class="special">&gt;</span></code> block if you prefer, in which case the
+ index does not appear in on a page of its own, but after the TOC in the HTML
+ output.
+ </p>
+<p>
+ You control the type of XML block used by setting the <code class="literal">&lt;auto-index-type&gt;element-name</code>
+ attribute in the Jamfile, or via the <code class="computeroutput"><span class="identifier">index</span><span class="special">-</span><span class="identifier">type</span><span class="special">=</span><span class="identifier">element</span><span class="special">-</span><span class="identifier">name</span></code> command line option to AutoIndex itself.
+ For example, to place the index in an appendix, your Jamfile might look like:
+ </p>
+<pre class="programlisting">using quickbook ;
+using auto-index ;
+
+xml mylibrary : mylibary.qbk ;
+boostbook standalone
+ :
+ mylibrary
+ :
+ # auto-indexing is on:
+ &lt;auto-index&gt;on
+
+ # PDFs rely on the XSL stylesheets to generate the index:
+ &lt;format&gt;pdf:&lt;auto-index-internal&gt;off
+
+ # HTML output uses auto-index to generate the index:
+ &lt;format&gt;html:&lt;auto-index-internal&gt;on
+
+ # Name of script file to use:
+ &lt;auto-index-script&gt;index.idx
+
+ # Set the XML wrapper for HML Indexes to "appendix":
+ &lt;format&gt;html:&lt;auto-index-type&gt;appendix
+
+ # Turn on multiple index support:
+ &lt;xsl:param&gt;index.on.type=1
+</pre>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="configure/optional.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="script.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/tut/build.html b/tools/auto_index/doc/html/boost_autoindex/tut/build.html
new file mode 100644
index 0000000000..a5815d9012
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/tut/build.html
@@ -0,0 +1,90 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Step 1: Build the AutoIndex tool</title>
+<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../tut.html" title="Getting Started and Tutorial">
+<link rel="prev" href="../tut.html" title="Getting Started and Tutorial">
+<link rel="next" href="configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../tut.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="configure.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="boost_autoindex.tut.build"></a><a class="link" href="build.html" title="Step 1: Build the AutoIndex tool">Step 1: Build the AutoIndex
+ tool</a>
+</h3></div></div></div>
+<div class="note"><table border="0" summary="Note">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
+<th align="left">Note</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ This step is strictly optional, but very desirable to speed up build times.
+ </p></td></tr>
+</table></div>
+<p>
+ cd into <code class="computeroutput"><span class="identifier">tools</span><span class="special">/</span><span class="identifier">auto_index</span><span class="special">/</span><span class="identifier">build</span></code> and invoke bjam as:
+ </p>
+<pre class="programlisting"><span class="identifier">bjam</span> <span class="identifier">release</span>
+</pre>
+<p>
+ Optionally pass the name of the compiler toolset you want to use to bjam
+ as well:
+ </p>
+<pre class="programlisting"><span class="identifier">bjam</span> <span class="identifier">release</span> <span class="identifier">gcc</span>
+</pre>
+<p>
+ This will build the tool and place a copy in the current directory (which
+ is to say <code class="computeroutput"><span class="identifier">tools</span><span class="special">/</span><span class="identifier">auto_index</span><span class="special">/</span><span class="identifier">build</span></code>)
+ </p>
+<p>
+ Now open up your <code class="computeroutput"><span class="identifier">user</span><span class="special">-</span><span class="identifier">config</span><span class="special">.</span><span class="identifier">jam</span></code> file and at the end of the file add
+ the line:
+ </p>
+<pre class="programlisting">using auto-index : <span class="emphasis"><em>full-path-to-boost-tree</em></span>/tools/auto_index/build/auto-index.exe ;
+</pre>
+<div class="note"><table border="0" summary="Note">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
+<th align="left">Note</th>
+</tr>
+<tr><td align="left" valign="top">
+<p>
+ This declaration must go towards the end of <code class="computeroutput"><span class="identifier">user</span><span class="special">-</span><span class="identifier">config</span><span class="special">.</span><span class="identifier">jam</span></code>,
+ or in any case after the Boostbook initialisation.
+ </p>
+<p>
+ Also note that Windows users must use forward slashes in the paths in
+ <code class="computeroutput"><span class="identifier">user</span><span class="special">-</span><span class="identifier">config</span><span class="special">.</span><span class="identifier">jam</span></code>
+ </p>
+</td></tr>
+</table></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../tut.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="configure.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/tut/build_docs.html b/tools/auto_index/doc/html/boost_autoindex/tut/build_docs.html
new file mode 100644
index 0000000000..d87ec8b2bd
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/tut/build_docs.html
@@ -0,0 +1,77 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Step 7: Build the Docs</title>
+<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../tut.html" title="Getting Started and Tutorial">
+<link rel="prev" href="pis.html" title="Step 6: Using XML processing instructions to control what gets indexed.">
+<link rel="next" href="refine.html" title="Step 8: Iterate - to refine your index">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="pis.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="refine.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="boost_autoindex.tut.build_docs"></a><a class="link" href="build_docs.html" title="Step 7: Build the Docs">Step 7: Build the Docs</a>
+</h3></div></div></div>
+<p>
+ Using Boost.Build you build the docs with either:
+ </p>
+<pre class="programlisting"><span class="identifier">bjam</span> <span class="identifier">release</span> <span class="special">&gt;</span> <span class="identifier">mylibrary_html</span><span class="special">.</span><span class="identifier">log</span>
+</pre>
+<p>
+ To build the html docs or:
+ </p>
+<pre class="programlisting"><span class="identifier">bjam</span> <span class="identifier">pdf</span> <span class="identifier">release</span> <span class="special">&gt;</span> <span class="identifier">mylibrary_pdf</span><span class="special">.</span><span class="identifier">log</span>
+</pre>
+<p>
+ To build the pdf.
+ </p>
+<p>
+ During the build process you should see AutoIndex emit a message in the log
+ file such as:
+ </p>
+<pre class="programlisting">Indexing 990 terms... </pre>
+<p>
+ If you don't see that, or if it's indexing 0 terms then something is wrong!
+ </p>
+<p>
+ Likewise when index generation is complete, AutoIndex will emit another message:
+ </p>
+<pre class="programlisting">38 Index entries were created.</pre>
+<p>
+ Again, if you see that 0 entries were created then something is wrong!
+ </p>
+<p>
+ Examine the log file, and if the cause is not obvious, make sure that you
+ have <code class="literal">&lt;auto-index-verbose&gt;on</code> and that any needed
+ <code class="literal">!debug regular-expression</code> directives are in your script
+ file.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="pis.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="refine.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/tut/configure.html b/tools/auto_index/doc/html/boost_autoindex/tut/configure.html
new file mode 100644
index 0000000000..451d32a78a
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/tut/configure.html
@@ -0,0 +1,139 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Step 2: Configure Boost.Build jamfile to use AutoIndex</title>
+<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../tut.html" title="Getting Started and Tutorial">
+<link rel="prev" href="build.html" title="Step 1: Build the AutoIndex tool">
+<link rel="next" href="configure/options.html" title="Available Indexing Options">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="build.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="configure/options.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="boost_autoindex.tut.configure"></a><a class="link" href="configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build
+ jamfile to use AutoIndex</a>
+</h3></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section"><a href="configure/options.html">Available Indexing
+ Options</a></span></dt>
+<dt><span class="section"><a href="configure/optional.html">Making AutoIndex
+ optional</a></span></dt>
+</dl></div>
+<p>
+ Assuming you have a Jamfile for building your documentation that looks something
+ like:
+ </p>
+<pre class="programlisting">boostbook standalone
+ :
+ mylibrary
+ :
+ # build requirements go here:
+ ;
+</pre>
+<p>
+ Then add the line:
+ </p>
+<pre class="programlisting">using auto-index ; </pre>
+<p>
+ to the start of the Jamfile, and then add whatever auto-index options you
+ want to the <span class="emphasis"><em>build requirements section</em></span>, for example:
+ </p>
+<pre class="programlisting">boostbook standalone
+ :
+ mylibrary
+ :
+ # Build requirements go here:
+
+ # &lt;auto-index&gt;on (or off) one turns on (or off) indexing:
+ &lt;auto-index&gt;on
+
+ # Turns on (or off) auto-index-verbose for diagnostic info.
+ # This is highly recommended until you have got all the many details correct!
+ &lt;auto-index-verbose&gt;on
+
+ # Choose the indexing method (separately for html and PDF) - see manual.
+ # Choose indexing method for PDFs:
+ &lt;format&gt;pdf:&lt;auto-index-internal&gt;off
+
+ # Choose indexing method for html:
+ &lt;format&gt;html:&lt;auto-index-internal&gt;on
+
+ # Set the name of the script file to use (index.idx is popular):
+ &lt;auto-index-script&gt;index.idx
+ # Commands in the script file should all use RELATIVE PATHS
+ # otherwise the script will not be portable to other machines.
+ # Relative paths are normally taken as relative to the location
+ # of the script file, but we can add a prefix to all
+ # those relative paths using the &lt;auto-index-prefix&gt; feature.
+ # The path specified by &lt;auto-index-prefix&gt; may be either relative or
+ # absolute, for example the following will get us up to the boost root
+ # directory for most Boost libraries:
+ &lt;auto-index-prefix&gt;../../..
+
+ # Tell Quickbook that it should enable indexing.
+ &lt;quickbook-define&gt;enable_index ;
+
+ ;
+</pre>
+<div class="tip"><table border="0" summary="Tip">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
+<th align="left">Tip</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ Always send the output to a log file. It will contain of lot of stuff,
+ but is invaluable to check if all has gone right, or else diagnose what
+ has gone wrong.
+ </p></td></tr>
+</table></div>
+<div class="tip"><table border="0" summary="Tip">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
+<th align="left">Tip</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ A return code of 0 is not a reliable indication that you have got what
+ you really want - inspecting the log file is the only certain way.
+ </p></td></tr>
+</table></div>
+<div class="tip"><table border="0" summary="Tip">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
+<th align="left">Tip</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ If you upgrade compiler version, for example MSVC from 9 to 10, then you
+ may need to rebuild Autoindex to avoid what Microsoft call a 'side-by-side'
+ error. And make sure that the autoindex.exe version you are using is the
+ new one.
+ </p></td></tr>
+</table></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="build.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="configure/options.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/tut/configure/optional.html b/tools/auto_index/doc/html/boost_autoindex/tut/configure/optional.html
new file mode 100644
index 0000000000..510144a0d3
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/tut/configure/optional.html
@@ -0,0 +1,106 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Making AutoIndex optional</title>
+<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../../../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">
+<link rel="prev" href="options.html" title="Available Indexing Options">
+<link rel="next" href="../add_indexes.html" title="Step 3: Add indexes to your documentation">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="options.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../configure.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../add_indexes.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="boost_autoindex.tut.configure.optional"></a><a class="link" href="optional.html" title="Making AutoIndex optional">Making AutoIndex
+ optional</a>
+</h4></div></div></div>
+<p>
+ It is considerate to make the <span class="bold"><strong>use of auto-index optional</strong></span>
+ in Boost.Build, to allow users who do not have AutoIndex installed to still
+ be able to build your documentation.
+ </p>
+<p>
+ This also very convenient while you are refining your documentation, to
+ allow you to decide to build indexes, or not: building indexes can take
+ long time, if you are just correcting typos, you won't want to wait while
+ you keep rebuilding the index!
+ </p>
+<p>
+ One method of setting up optional AutoIndex support is to place all AutoIndex
+ configuration in a the body of a bjam if statement:
+ </p>
+<pre class="programlisting">if --enable-index in [ modules.peek : ARGV ]
+ {
+ ECHO "Building the docs with automatic index generation enabled." ;
+
+ using auto-index ;
+ project : requirements
+ &lt;auto-index&gt;on
+ &lt;auto-index-script&gt;index.idx
+
+ ... other AutoIndex options here...
+
+ # And tell Quickbook that it should enable indexing.
+ &lt;quickbook-define&gt;enable_index
+ ;
+ }
+ else
+ {
+ ECHO "Building the my_library docs with automatic index generation disabled. To get an Index, try building with --enable-index." ;
+ }
+</pre>
+<p>
+ You will also need to add a conditional statement at the end of your Quickbook
+ file, so that the index(es) is/are only added after the last section if
+ indexing is enabled.
+ </p>
+<pre class="programlisting">[? enable_index
+'''
+ &lt;index/&gt;
+'''
+]
+</pre>
+<p>
+ To use this jamfile, you need to cd to your docs folder, for example:
+ </p>
+<pre class="programlisting"><span class="identifier">cd</span> <span class="special">\</span><span class="identifier">boost</span><span class="special">-</span><span class="identifier">sandbox</span><span class="special">\</span><span class="identifier">guild</span><span class="special">\</span><span class="identifier">mylibrary</span><span class="special">\</span><span class="identifier">libs</span><span class="special">\</span><span class="identifier">mylibrary</span><span class="special">\</span><span class="identifier">doc</span>
+</pre>
+<p>
+ and then run <code class="computeroutput"><span class="identifier">bjam</span></code> to build
+ the docs without index, for example:
+ </p>
+<pre class="programlisting"><span class="identifier">bjam</span> <span class="special">-</span><span class="identifier">a</span> <span class="identifier">html</span> <span class="special">&gt;</span> <span class="identifier">mylibrary_html</span><span class="special">.</span><span class="identifier">log</span>
+</pre>
+<p>
+ or with index(es)
+ </p>
+<pre class="programlisting"><span class="identifier">bjam</span> <span class="special">-</span><span class="identifier">a</span> <span class="identifier">html</span> <span class="special">--</span><span class="identifier">enable</span><span class="special">-</span><span class="identifier">index</span> <span class="special">&gt;</span> <span class="identifier">mylibrary_html_index</span><span class="special">.</span><span class="identifier">log</span>
+</pre>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="options.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../configure.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../add_indexes.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/tut/configure/options.html b/tools/auto_index/doc/html/boost_autoindex/tut/configure/options.html
new file mode 100644
index 0000000000..b28501b99b
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/tut/configure/options.html
@@ -0,0 +1,419 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Available Indexing Options</title>
+<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../../../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">
+<link rel="prev" href="../configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">
+<link rel="next" href="optional.html" title="Making AutoIndex optional">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../configure.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../configure.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="optional.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="boost_autoindex.tut.configure.options"></a><a class="link" href="options.html" title="Available Indexing Options">Available Indexing
+ Options</a>
+</h4></div></div></div>
+<p>
+ The available options are:
+ </p>
+<div class="variablelist">
+<p class="title"><b></b></p>
+<dl>
+<dt><span class="term">&lt;auto-index&gt;off/on</span></dt>
+<dd><p>
+ Turns indexing of the document on, defaults to "off", so
+ be sure to set this if you want AutoIndex invoked!
+ </p></dd>
+<dt><span class="term">&lt;auto-index-internal&gt;off/on</span></dt>
+<dd><p>
+ Chooses whether AutoIndex creates the index itself (feature on),
+ or whether it simply inserts the necessary DocBook markup so that
+ the DocBook XSL stylesheets can create the index. Defaults to "off".
+ </p></dd>
+<dt><span class="term">&lt;auto-index-script&gt;filename</span></dt>
+<dd><p>
+ Specifies the name of the script to load.
+ </p></dd>
+<dt><span class="term">&lt;auto-index-no-duplicates&gt;off/on</span></dt>
+<dd><p>
+ When <span class="emphasis"><em>on</em></span> AutoIndex will only index a term once
+ in any given section, otherwise (the default) multiple index entries
+ per term may be created if the term occurs more than once in the
+ section.
+ </p></dd>
+<dt><span class="term">&lt;auto-index-section-names&gt;off/on</span></dt>
+<dd><p>
+ When <span class="emphasis"><em>on</em></span> AutoIndex will use create two index
+ entries for each term found - one uses the term itself as the primary
+ index key, the other uses the enclosing section name. When off the
+ index entry that uses the section title is not created. Defaults
+ to "on"
+ </p></dd>
+<dt><span class="term">&lt;auto-index-verbose&gt;off/on</span></dt>
+<dd><p>
+ Defaults to "off". When turned on AutoIndex prints progress
+ information - useful for debugging purposes during setup.
+ </p></dd>
+<dt><span class="term">&lt;auto-index-prefix&gt;filename</span></dt>
+<dd>
+<p>
+ Optionally specifies a directory to apply as a prefix to all relative
+ file paths in the script file.
+ </p>
+<p>
+ You may wish to do this to reduce typing of pathnames, and/or where
+ the paths can't be located relative to the script file location,
+ typically if the headers are in the Boost trunk, but the script file
+ is in Boost sandbox.
+ </p>
+<p>
+ For Boost standard library layout, <code class="literal">&lt;auto-index-prefix&gt;../../..</code>
+ will get you back up to the 'root' of the Boost tree, so <code class="literal">!scan-path
+ boost/mylibrary/</code> is where your headers will be, and <code class="literal">libs/mylibrary</code>
+ for other files. Without a prefix all relative paths are relative
+ to the location of the script file.
+ </p>
+</dd>
+<dt><span class="term">&lt;auto-index-type&gt;element-name</span></dt>
+<dd><p>
+ Specifies the name of the XML element in which to enclose an internally
+ generated indexes: defaults to <span class="emphasis"><em>section</em></span>, but
+ could equally be <span class="emphasis"><em>appendix</em></span> or <span class="emphasis"><em>chapter</em></span>
+ or some other block level element that has a formal title. The actual
+ list of available options depends upon the Quickbook document type,
+ the following table gives the available options, assuming that the
+ index is placed at the top level, and not in some sub-section or
+ other container:
+ </p></dd>
+</dl>
+</div>
+<div class="informaltable"><table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>
+ <p>
+ Document Type
+ </p>
+ </th>
+<th>
+ <p>
+ Permitted Index Types
+ </p>
+ </th>
+</tr></thead>
+<tbody>
+<tr>
+<td>
+ <p>
+ book
+ </p>
+ </td>
+<td>
+ <p>
+ appendix index article chapter reference part
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ article
+ </p>
+ </td>
+<td>
+ <p>
+ section appendix index sect1
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ chapter
+ </p>
+ </td>
+<td>
+ <p>
+ section index sect1
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ library
+ </p>
+ </td>
+<td>
+ <p>
+ The same as Chapter (section index sect1)
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ part
+ </p>
+ </td>
+<td>
+ <p>
+ appendix index article chapter reference
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ appendix
+ </p>
+ </td>
+<td>
+ <p>
+ section index sect1
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ preface
+ </p>
+ </td>
+<td>
+ <p>
+ section index sect1
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ qandadiv
+ </p>
+ </td>
+<td>
+ <p>
+ N/A: an index would have to be placed within a subsection of
+ the document.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ qandaset
+ </p>
+ </td>
+<td>
+ <p>
+ N/A: an index would have to be placed within a subsection of
+ the document.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ reference
+ </p>
+ </td>
+<td>
+ <p>
+ N/A: an index would have to be placed within a subsection of
+ the document.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ set
+ </p>
+ </td>
+<td>
+ <p>
+ N/A: an index would have to be placed within a subsection of
+ the document.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ In large part then the choice of <code class="computeroutput"><span class="special">&lt;</span><span class="keyword">auto</span><span class="special">-</span><span class="identifier">index</span><span class="special">-</span><span class="identifier">type</span><span class="special">&gt;</span><span class="identifier">element</span><span class="special">-</span><span class="identifier">name</span></code>
+ depends on the formatting you want to be applied to the index:
+ </p>
+<div class="informaltable"><table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>
+ <p>
+ XML Container Used for the Index
+ </p>
+ </th>
+<th>
+ <p>
+ Formatting Applied by the XSL Stylesheets
+ </p>
+ </th>
+</tr></thead>
+<tbody>
+<tr>
+<td>
+ <p>
+ appendix
+ </p>
+ </td>
+<td>
+ <p>
+ Starts a new page.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ article
+ </p>
+ </td>
+<td>
+ <p>
+ Starts a new page.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ chapter
+ </p>
+ </td>
+<td>
+ <p>
+ Starts a new page.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ index
+ </p>
+ </td>
+<td>
+ <p>
+ Starts a new page only if it's contained within an article or
+ book.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ part
+ </p>
+ </td>
+<td>
+ <p>
+ Starts a new page.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ reference
+ </p>
+ </td>
+<td>
+ <p>
+ Starts a new page.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ sect1
+ </p>
+ </td>
+<td>
+ <p>
+ Starts a new page as long as it's not the first section (but
+ is controlled by the XSL parameters chunk.section.depth and/or
+ chunk.first.sections).
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ section
+ </p>
+ </td>
+<td>
+ <p>
+ Starts a new page as long as it's not the first section or nested
+ within another section (but is controlled by the XSL parameters
+ chunk.section.depth and/or chunk.first.sections).
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ In almost all cases the default (section) is the correct choice - the exception
+ is when the index is to be placed directly inside a <span class="emphasis"><em>book</em></span>
+ or <span class="emphasis"><em>part</em></span>, in which case you should probably use the
+ same XML container for the index as you use for whatever subdivisions are
+ in the <span class="emphasis"><em>book</em></span> or <span class="emphasis"><em>part</em></span>. In any event
+ placing a <span class="emphasis"><em>section</em></span> within a <span class="emphasis"><em>book</em></span>
+ or <span class="emphasis"><em>part</em></span> will result in invalid XML.
+ </p>
+<p>
+ Finally, if you are using Quickbook to generate the documentation, then
+ you may wish to add:
+ </p>
+<pre class="programlisting">&lt;include&gt;$boost-root/tools/auto_index/include</pre>
+<p>
+ to your projects requirements (replacing $boost-root with the path to the
+ root of the Boost tree), so that the file auto_index_helpers.qbk can be
+ included in your quickbook source with simply a:
+ </p>
+<pre class="programlisting">[include auto_index_helpers.qbk]</pre>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../configure.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../configure.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="optional.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/tut/entries.html b/tools/auto_index/doc/html/boost_autoindex/tut/entries.html
new file mode 100644
index 0000000000..82dcc8f02f
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/tut/entries.html
@@ -0,0 +1,62 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Step 5: Add Manual Index Entries to Docbook XML - Optional</title>
+<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../tut.html" title="Getting Started and Tutorial">
+<link rel="prev" href="script.html" title="Step 4: Create the .idx script file - to control what to terms to index">
+<link rel="next" href="pis.html" title="Step 6: Using XML processing instructions to control what gets indexed.">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="script.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="pis.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="boost_autoindex.tut.entries"></a><a class="link" href="entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional">Step 5: Add Manual Index
+ Entries to Docbook XML - Optional</a>
+</h3></div></div></div>
+<p>
+ If you add manual <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">indexentry</span><span class="special">&gt;</span></code> markup to your Docbook XML then these
+ will be passed through unchanged. Please note however, that if you are using
+ AutoIndex's internal index generation then it only recognises <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">primary</span><span class="special">&gt;</span></code>, <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">secondary</span><span class="special">&gt;</span></code>
+ and <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">tertiary</span><span class="special">&gt;</span></code> elements within the <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">indexterm</span><span class="special">&gt;</span></code>.
+ <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">see</span><span class="special">&gt;</span></code> and <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">seealso</span><span class="special">&gt;</span></code>
+ elements are not currently recognised and AutoIndex will emit a warning if
+ these are used.
+ </p>
+<p>
+ Likewise none of the attributes which can be applied to these elements are
+ used when AutoIndex generates the index itself, with the exception of the
+ <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">type</span><span class="special">&gt;</span></code> attribute.
+ </p>
+<p>
+ For Quickbook users, there are some templates in auto_index_helpers.qbk that
+ assist in adding manual entries without having to escape to Docbook.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="script.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="pis.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/tut/pis.html b/tools/auto_index/doc/html/boost_autoindex/tut/pis.html
new file mode 100644
index 0000000000..e937fee48a
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/tut/pis.html
@@ -0,0 +1,131 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Step 6: Using XML processing instructions to control what gets indexed.</title>
+<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../tut.html" title="Getting Started and Tutorial">
+<link rel="prev" href="entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional">
+<link rel="next" href="build_docs.html" title="Step 7: Build the Docs">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="entries.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="build_docs.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="boost_autoindex.tut.pis"></a><a class="link" href="pis.html" title="Step 6: Using XML processing instructions to control what gets indexed.">Step 6: Using XML processing
+ instructions to control what gets indexed.</a>
+</h3></div></div></div>
+<p>
+ Sometimes when you need to exclude certain sections of text from indexing,
+ then you can achieve this with the following XML processing instructions:
+ </p>
+<div class="informaltable"><table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>
+ <p>
+ Instruction
+ </p>
+ </th>
+<th>
+ <p>
+ Effect
+ </p>
+ </th>
+</tr></thead>
+<tbody>
+<tr>
+<td>
+ <p>
+ <code class="computeroutput"><span class="special">&lt;?</span><span class="identifier">BoostAutoIndex</span>
+ <span class="identifier">IgnoreSection</span><span class="special">?&gt;</span></code>
+ </p>
+ </td>
+<td>
+ <p>
+ Causes the whole of the current section to be excluded from indexing.
+ By "section" we mean either a true "section"
+ or any sibling XML element: "dedication", "toc",
+ "lot", "glossary", "bibliography",
+ "preface", "chapter", "reference",
+ "part", "article", "appendix", "index",
+ "setindex", "colophon", "sect1",
+ "refentry", "simplesect", "section"
+ or "partintro".
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="computeroutput"><span class="special">&lt;?</span><span class="identifier">BoostAutoIndex</span>
+ <span class="identifier">IgnoreBlock</span><span class="special">?&gt;</span></code>
+ </p>
+ </td>
+<td>
+ <p>
+ Causes the whole of the current text block to be excluded from
+ indexing. A text block may be any of the section/chapter elements
+ listed above, or a paragraph, code listing, table etc. The complete
+ list is: "calloutlist", "glosslist", "bibliolist",
+ "itemizedlist", "orderedlist", "segmentedlist",
+ "simplelist", "variablelist", "caution",
+ "important", "note", "tip", "warning",
+ "literallayout", "programlisting", "programlistingco",
+ "screen", "screenco", "screenshot",
+ "synopsis", "cmdsynopsis", "funcsynopsis",
+ "classsynopsis", "fieldsynopsis", "constructorsynopsis",
+ "destructorsynopsis", "methodsynopsis", "formalpara",
+ "para", "simpara", "address", "blockquote",
+ "graphic", "graphicco", "mediaobject",
+ "mediaobjectco", "informalequation", "informalexample",
+ "informalfigure", "informaltable", "equation",
+ "example", "figure", "table", "msgset",
+ "procedure", "sidebar", "qandaset",
+ "task", "productionset", "constraintdef",
+ "anchor", "bridgehead", "remark",
+ "highlights", "abstract", "authorblurb"
+ or "epigraph".
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ For Quickbook users the file auto_index_helpers.qbk contains a helper template
+ that assists in inserting these processing instructions, for example:
+ </p>
+<pre class="programlisting">[AutoIndex IgnoreSection]</pre>
+<p>
+ Will cause that section to not be indexed.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="entries.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="build_docs.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/tut/refine.html b/tools/auto_index/doc/html/boost_autoindex/tut/refine.html
new file mode 100644
index 0000000000..3299dcb923
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/tut/refine.html
@@ -0,0 +1,99 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Step 8: Iterate - to refine your index</title>
+<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../tut.html" title="Getting Started and Tutorial">
+<link rel="prev" href="build_docs.html" title="Step 7: Build the Docs">
+<link rel="next" href="../script_ref.html" title="Script File (.idx) Reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="build_docs.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../script_ref.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="boost_autoindex.tut.refine"></a><a class="link" href="refine.html" title="Step 8: Iterate - to refine your index">Step 8: Iterate - to refine
+ your index</a>
+</h3></div></div></div>
+<p>
+ Creating a good index is an iterative process, often the first step is just
+ to add a header scanning rule to the script file and then generate the documentation
+ and see:
+ </p>
+<div class="itemizedlist"><ul class="itemizedlist" type="disc">
+<li class="listitem">
+ What's missing.
+ </li>
+<li class="listitem">
+ What's been included that shouldn't be.
+ </li>
+<li class="listitem">
+ What's been included under a poor name.
+ </li>
+</ul></div>
+<p>
+ Further rules can then be added to the script to handle these cases and the
+ next iteration examined, and so on.
+ </p>
+<div class="tip"><table border="0" summary="Tip">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
+<th align="left">Tip</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ If you don't understand why a particular term is (or is not) present in
+ the index, try adding a <span class="emphasis"><em>!debug regular-expression</em></span>
+ directive to the <a class="link" href="../script_ref.html" title="Script File (.idx) Reference">script file</a>.
+ </p></td></tr>
+</table></div>
+<a name="boost_autoindex.tut.refine.restricting_which_sections_are_indexed_for_a_particular_term"></a><h5>
+<a name="boost_autoindex.tut.refine.restricting_which_sections_are_indexed_for_a_particular_term-heading"></a>
+ <a class="link" href="refine.html#boost_autoindex.tut.refine.restricting_which_sections_are_indexed_for_a_particular_term">Restricting
+ which Sections are indexed for a particular term</a>
+ </h5>
+<p>
+ You can restrict which sections are indexed for a particular term. So assuming
+ that the docbook document has the usual hierarchical names for section ID's
+ (as Quickbook generates, for example), you can easily place a constraint
+ on which sections are examined for a particular term.
+ </p>
+<p>
+ For example, if you want to index occurrences of Lord Kelvin's name, but
+ only in the introduction section, you might then add:
+ </p>
+<pre class="programlisting"><span class="identifier">Kelvin</span> <span class="string">""</span> <span class="string">".*introduction.*"</span>
+</pre>
+<p>
+ to the script file, assuming that the section ID of the intro is "some_library_or_chapter_name.introduction".
+ </p>
+<p>
+ This would avoid an index entry every time 'Kelvin' is found, something the
+ user is unlikely to find helpful.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="build_docs.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../script_ref.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/tut/script.html b/tools/auto_index/doc/html/boost_autoindex/tut/script.html
new file mode 100644
index 0000000000..cd272f24f7
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/tut/script.html
@@ -0,0 +1,160 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Step 4: Create the .idx script file - to control what to terms to index</title>
+<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../tut.html" title="Getting Started and Tutorial">
+<link rel="prev" href="add_indexes.html" title="Step 3: Add indexes to your documentation">
+<link rel="next" href="entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="add_indexes.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="entries.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="boost_autoindex.tut.script"></a><a class="link" href="script.html" title="Step 4: Create the .idx script file - to control what to terms to index">Step 4: Create the .idx script
+ file - to control what to terms to index</a>
+</h3></div></div></div>
+<p>
+ AutoIndex works by reading a script file that tells it what terms to index.
+ </p>
+<p>
+ If your document contains largely text, and only a small amount of simple
+ C++, and/or if you are using Doxygen to provide a C++ Reference section (that
+ lists the C++ elements), and/or if you are relying on the indexing provided
+ from a Standalone Doxygen Index, you may decide that a index is not needed
+ and that you may only want the text part indexed.
+ </p>
+<p>
+ But if you want C++ classes functions, typedefs and/or macros AutoIndexed,
+ optionally, the script file also tells which other C++ files to scan.
+ </p>
+<p>
+ At its simplest, it will scan one or more headers for terms that should be
+ indexed in the documentation. So for example to scan "myheader.hpp"
+ the script file would just contain:
+ </p>
+<pre class="programlisting"><span class="special">!</span><span class="identifier">scan</span> <span class="identifier">myheader</span><span class="special">.</span><span class="identifier">hpp</span>
+<span class="special">!</span><span class="identifier">scan</span> <span class="identifier">mydetailsheader</span><span class="special">.</span><span class="identifier">hpp</span>
+</pre>
+<p>
+ Or, more likely in practice, so we can recursively scan through directories
+ looking for all the files to scan whose <span class="bold"><strong>name matches
+ a particular regular expression</strong></span>:
+ </p>
+<pre class="programlisting">!scan-path "boost/mylibrary" ".*.hpp" true </pre>
+<p>
+ Each argument is whitespace separated and can be optionally enclosed in "double
+ quotes" (recommended).
+ </p>
+<p>
+ The final <span class="emphasis"><em>true</em></span> argument indicates that subdirectories
+ in <code class="computeroutput"><span class="special">/</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">mylibrary</span></code> should be searched recursively
+ in addition to that directory.
+ </p>
+<div class="caution"><table border="0" summary="Caution">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Caution]" src="../../../../../../doc/src/images/caution.png"></td>
+<th align="left">Caution</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ The second <span class="emphasis"><em>file-name-regex</em></span> argument is a regular expression
+ and not a filename GLOB!
+ </p></td></tr>
+</table></div>
+<div class="caution"><table border="0" summary="Caution">
+<tr>
+<td rowspan="2" align="center" valign="top" width="25"><img alt="[Caution]" src="../../../../../../doc/src/images/caution.png"></td>
+<th align="left">Caution</th>
+</tr>
+<tr><td align="left" valign="top"><p>
+ The scan-path is modified by any setting of &lt;auto-index-prefix&gt;.
+ The examples here assume that this is <code class="literal">&lt;auto-index-prefix&gt;../../..</code>
+ so that <code class="computeroutput"><span class="identifier">boost</span><span class="special">/</span><span class="identifier">mylibrary</span></code> will be your header files,
+ <code class="computeroutput"><span class="identifier">libs</span><span class="special">/</span><span class="identifier">mylibrary</span><span class="special">/</span><span class="identifier">doc</span></code> will contain your documentation files
+ and <code class="computeroutput"><span class="identifier">libs</span><span class="special">/</span><span class="identifier">mylibrary</span><span class="special">/</span><span class="identifier">example</span></code> will contain your examples.
+ </p></td></tr>
+</table></div>
+<p>
+ You could also scan any examples (.cpp) files, typically in folder <code class="computeroutput"><span class="special">/</span><span class="identifier">mylibrary</span><span class="special">/</span><span class="identifier">lib</span><span class="special">/</span><span class="identifier">example</span></code>.
+ </p>
+<pre class="programlisting"># All example source files, assuming no sub-folders.
+!scan-path "libs/mylibrary/example" ".*\.cpp"
+</pre>
+<p>
+ Often the <span class="emphasis"><em>scan</em></span> or <span class="emphasis"><em>scan-path</em></span> rules
+ will bring in too many terms to search for, so we need to be able to exclude
+ terms as well:
+ </p>
+<pre class="programlisting"><span class="special">!</span><span class="identifier">exclude</span> <span class="identifier">type</span>
+</pre>
+<p>
+ Which excludes the term "type" from being indexed.
+ </p>
+<p>
+ We can also add terms manually:
+ </p>
+<pre class="programlisting"><span class="identifier">foobar</span>
+</pre>
+<p>
+ will index occurrences of "foobar" and:
+ </p>
+<pre class="programlisting"><span class="identifier">foobar</span> <span class="special">\&lt;\</span><span class="identifier">w</span><span class="special">*(</span><span class="identifier">foo</span><span class="special">|</span><span class="identifier">bar</span><span class="special">)\</span><span class="identifier">w</span><span class="special">*\&gt;</span>
+</pre>
+<p>
+ will index any whole word containing either "foo" or "bar"
+ within it, this is useful when you want to index a lot of similar or related
+ words under one entry, for example:
+ </p>
+<pre class="programlisting"><span class="identifier">reflex</span>
+</pre>
+<p>
+ Will only index occurrences of "reflex" as a whole word, but:
+ </p>
+<pre class="programlisting"><span class="identifier">reflex</span> <span class="special">\&lt;</span><span class="identifier">reflex</span><span class="special">\</span><span class="identifier">w</span><span class="special">*\&gt;</span>
+</pre>
+<p>
+ will index occurrences of "reflex", "reflexing" and "reflexed"
+ all under the same entry <span class="emphasis"><em>reflex</em></span>. You will very often
+ need to use this to deal with plurals and other variants.
+ </p>
+<p>
+ This inclusion rule can also restrict the term to certain sections, and add
+ an index category that the term should belong to (so it only appears in certain
+ indexes).
+ </p>
+<p>
+ Finally the script can add rewrite rules, that rename section names that
+ are automatically used as index entries. For example we might want to remove
+ leading "A" or "The" prefixes from section titles when
+ AutoIndex uses them as an index entry:
+ </p>
+<pre class="programlisting"><span class="special">!</span><span class="identifier">rewrite</span><span class="special">-</span><span class="identifier">name</span> <span class="string">"(?i)(?:A|The)\s+(.*)"</span> <span class="string">"\1"</span>
+</pre>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="add_indexes.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="entries.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/workflow.html b/tools/auto_index/doc/html/boost_autoindex/workflow.html
new file mode 100644
index 0000000000..6d08b2829b
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/workflow.html
@@ -0,0 +1,90 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Understanding The AutoIndex Workflow</title>
+<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../index.html" title="Boost.AutoIndex">
+<link rel="prev" href="script_ref.html" title="Script File (.idx) Reference">
+<link rel="next" href="xml.html" title="XML Handling">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="script_ref.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="xml.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="boost_autoindex.workflow"></a><a class="link" href="workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a>
+</h2></div></div></div>
+<div class="orderedlist"><ol class="orderedlist" type="1">
+<li class="listitem">
+ Load the script file (usually index.idx) and process it one line at a time,
+ producing one or more index term per (non-comment) line.
+ </li>
+<li class="listitem">
+ Reading all lines builds a list of <span class="emphasis"><em>terms to index</em></span>.
+ Some of those may be terms defined (by you) directly in the script file,
+ others may be terms found by scanning C++ header and source files that
+ were specified by the <span class="emphasis"><em>!scan-path</em></span> directive.
+ </li>
+<li class="listitem">
+ Once the complete list of <span class="emphasis"><em>terms to index</em></span> is complete,
+ it loads the Docbook XML file. (If this comes from Quickbook/Doxygen/Boostbook/Docbook
+ then this is the complete documentation after conversion to Docbook format).
+ </li>
+<li class="listitem">
+ AutoIndex builds an internal <a href="http://en.wikipedia.org/wiki/Document_Object_Model" target="_top">Document
+ Object Model (DOM)</a> of the Docbook XML. This internal representation
+ then gets scanned for occurrences of the <span class="emphasis"><em>terms to index</em></span>.
+ This scanning works at the XML paragraph level (or equivalent sibling such
+ as a table or code block) - so all the XML encoding within a paragraph
+ gets flattened to plain text.<br> This flattening means the regular expressions
+ used to search for <span class="emphasis"><em>terms to index</em></span> can find anything
+ that is completely contained within a paragraph (or code block etc).
+ </li>
+<li class="listitem">
+ For each term found then an <span class="emphasis"><em>indexterm</em></span> Docbook element
+ is inserted into the <a href="http://en.wikipedia.org/wiki/Document_Object_Model" target="_top">Document
+ Object Model (DOM)</a> (provided internal index generation is off),
+ </li>
+<li class="listitem">
+ Also the AutoIndex's internal index representation gets updated.
+ </li>
+<li class="listitem">
+ Once the whole XML document has been indexed, then, if AutoIndex has been
+ instructed to generate the index itself, it creates the necessary XML and
+ inserts this into the <a href="http://en.wikipedia.org/wiki/Document_Object_Model" target="_top">Document
+ Object Model (DOM)</a>.
+ </li>
+<li class="listitem">
+ Finally the whole <a href="http://en.wikipedia.org/wiki/Document_Object_Model" target="_top">Document
+ Object Model (DOM)</a> is written out as a new Docbook XML file, and
+ normal processing of this continues via the XSL stylesheets (with xsltproc)
+ to actually build the final human-readable docs.
+ </li>
+</ol></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="script_ref.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="xml.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boost_autoindex/xml.html b/tools/auto_index/doc/html/boost_autoindex/xml.html
new file mode 100644
index 0000000000..aee7e6cfa3
--- /dev/null
+++ b/tools/auto_index/doc/html/boost_autoindex/xml.html
@@ -0,0 +1,65 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>XML Handling</title>
+<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../index.html" title="Boost.AutoIndex">
+<link rel="prev" href="workflow.html" title="Understanding The AutoIndex Workflow">
+<link rel="next" href="qbk.html" title="Quickbook Support">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="workflow.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="qbk.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="boost_autoindex.xml"></a><a class="link" href="xml.html" title="XML Handling">XML Handling</a>
+</h2></div></div></div>
+<p>
+ AutoIndex is rather simplistic in its handling of XML:
+ </p>
+<div class="itemizedlist"><ul class="itemizedlist" type="disc">
+<li class="listitem">
+ When indexing a document, all block content at the paragraph level gets
+ collapsed into a single string for matching against the regular expressions
+ representing each index term. In other words, for the most part, you can
+ assume that you're indexing plain text when writing regular expressions.
+ </li>
+<li class="listitem">
+ Named XML entities for &amp;, ", ', &lt; or &gt; are converted to
+ their corresponding characters before indexing a section of text. However,
+ decimal or hex escape sequences are not currently converted.
+ </li>
+<li class="listitem">
+ Index terms are assumed to be plain text (whether they originate from the
+ script file or from scanning source files) and the characters &amp;, ",
+ &lt; and &gt; will be escaped to &amp;amp; &amp;quot; &amp;lt; and &amp;gt;
+ respectively.
+ </li>
+</ul></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="workflow.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="qbk.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/boostbook.css b/tools/auto_index/doc/html/boostbook.css
new file mode 100644
index 0000000000..252fa9ecfd
--- /dev/null
+++ b/tools/auto_index/doc/html/boostbook.css
@@ -0,0 +1,588 @@
+/*=============================================================================
+ Copyright (c) 2004 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Distributed under the Boost Software License, Version 1.0. (See accompany-
+ ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+/*=============================================================================
+ Body defaults
+=============================================================================*/
+
+ body
+ {
+ margin: 1em;
+ font-family: sans-serif;
+ }
+
+/*=============================================================================
+ Paragraphs
+=============================================================================*/
+
+ p
+ {
+ text-align: left;
+ font-size: 10pt;
+ line-height: 1.15;
+ }
+
+/*=============================================================================
+ Program listings
+=============================================================================*/
+
+ /* Code on paragraphs */
+ p tt.computeroutput
+ {
+ font-size: 9pt;
+ }
+
+ pre.synopsis
+ {
+ font-size: 90%;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+ .programlisting,
+ .screen
+ {
+ font-size: 9pt;
+ display: block;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+ /* Program listings in tables don't get borders */
+ td .programlisting,
+ td .screen
+ {
+ margin: 0pc 0pc 0pc 0pc;
+ padding: 0pc 0pc 0pc 0pc;
+ }
+
+/*=============================================================================
+ Headings
+=============================================================================*/
+
+ h1, h2, h3, h4, h5, h6
+ {
+ text-align: left;
+ margin: 1em 0em 0.5em 0em;
+ font-weight: bold;
+ }
+
+ h1 { font: 140% }
+ h2 { font: bold 140% }
+ h3 { font: bold 130% }
+ h4 { font: bold 120% }
+ h5 { font: italic 110% }
+ h6 { font: italic 100% }
+
+ /* Top page titles */
+ title,
+ h1.title,
+ h2.title
+ h3.title,
+ h4.title,
+ h5.title,
+ h6.title,
+ .refentrytitle
+ {
+ font-weight: bold;
+ margin-bottom: 1pc;
+ }
+
+ h1.title { font-size: 140% }
+ h2.title { font-size: 140% }
+ h3.title { font-size: 130% }
+ h4.title { font-size: 120% }
+ h5.title { font-size: 110% }
+ h6.title { font-size: 100% }
+
+ .section h1
+ {
+ margin: 0em 0em 0.5em 0em;
+ font-size: 140%;
+ }
+
+ .section h2 { font-size: 140% }
+ .section h3 { font-size: 130% }
+ .section h4 { font-size: 120% }
+ .section h5 { font-size: 110% }
+ .section h6 { font-size: 100% }
+
+ /* Code on titles */
+ h1 tt.computeroutput { font-size: 140% }
+ h2 tt.computeroutput { font-size: 140% }
+ h3 tt.computeroutput { font-size: 130% }
+ h4 tt.computeroutput { font-size: 120% }
+ h5 tt.computeroutput { font-size: 110% }
+ h6 tt.computeroutput { font-size: 100% }
+
+/*=============================================================================
+ Author
+=============================================================================*/
+
+ h3.author
+ {
+ font-size: 100%
+ }
+
+/*=============================================================================
+ Lists
+=============================================================================*/
+
+ li
+ {
+ font-size: 10pt;
+ line-height: 1.3;
+ }
+
+ /* Unordered lists */
+ ul
+ {
+ text-align: left;
+ }
+
+ /* Ordered lists */
+ ol
+ {
+ text-align: left;
+ }
+
+/*=============================================================================
+ Links
+=============================================================================*/
+
+ a
+ {
+ text-decoration: none; /* no underline */
+ }
+
+ a:hover
+ {
+ text-decoration: underline;
+ }
+
+/*=============================================================================
+ Spirit style navigation
+=============================================================================*/
+
+ .spirit-nav
+ {
+ text-align: right;
+ }
+
+ .spirit-nav a
+ {
+ color: white;
+ padding-left: 0.5em;
+ }
+
+ .spirit-nav img
+ {
+ border-width: 0px;
+ }
+
+/*=============================================================================
+ Copyright footer
+=============================================================================*/
+ .copyright-footer
+ {
+ text-align: right;
+ font-size: 70%;
+ }
+
+ .copyright-footer p
+ {
+ text-align: right;
+ font-size: 80%;
+ }
+
+/*=============================================================================
+ Table of contents
+=============================================================================*/
+
+ .toc
+ {
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.1pc 1pc 0.1pc 1pc;
+ font-size: 80%;
+ line-height: 1.15;
+ }
+
+ .boost-toc
+ {
+ float: right;
+ padding: 0.5pc;
+ }
+
+/*=============================================================================
+ Tables
+=============================================================================*/
+
+ .table-title,
+ div.table p.title
+ {
+ margin-left: 4%;
+ padding-right: 0.5em;
+ padding-left: 0.5em;
+ }
+
+ .informaltable table,
+ .table table
+ {
+ width: 92%;
+ margin-left: 4%;
+ margin-right: 4%;
+ }
+
+ div.informaltable table,
+ div.table table
+ {
+ padding: 4px;
+ }
+
+ /* Table Cells */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ padding: 0.5em;
+ text-align: left;
+ font-size: 9pt;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ padding: 0.5em 0.5em 0.5em 0.5em;
+ border: 1pt solid white;
+ font-size: 80%;
+ }
+
+ table.simplelist
+ {
+ width: auto !important;
+ margin: 0em !important;
+ padding: 0em !important;
+ border: none !important;
+ }
+ table.simplelist td
+ {
+ margin: 0em !important;
+ padding: 0em !important;
+ text-align: left !important;
+ font-size: 9pt !important;
+ border: none !important;
+ }
+
+/*=============================================================================
+ Blurbs
+=============================================================================*/
+
+ div.note,
+ div.tip,
+ div.important,
+ div.caution,
+ div.warning,
+ p.blurb
+ {
+ font-size: 9pt; /* A little bit smaller than the main text */
+ line-height: 1.2;
+ display: block;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+ p.blurb img
+ {
+ padding: 1pt;
+ }
+
+/*=============================================================================
+ Variable Lists
+=============================================================================*/
+
+ /* Make the terms in definition lists bold */
+ div.variablelist dl dt,
+ span.term
+ {
+ font-weight: bold;
+ font-size: 10pt;
+ }
+
+ div.variablelist table tbody tr td
+ {
+ text-align: left;
+ vertical-align: top;
+ padding: 0em 2em 0em 0em;
+ font-size: 10pt;
+ margin: 0em 0em 0.5em 0em;
+ line-height: 1;
+ }
+
+ div.variablelist dl dt
+ {
+ margin-bottom: 0.2em;
+ }
+
+ div.variablelist dl dd
+ {
+ margin: 0em 0em 0.5em 2em;
+ font-size: 10pt;
+ }
+
+ div.variablelist table tbody tr td p,
+ div.variablelist dl dd p
+ {
+ margin: 0em 0em 0.5em 0em;
+ line-height: 1;
+ }
+
+/*=============================================================================
+ Misc
+=============================================================================*/
+
+ /* Title of books and articles in bibliographies */
+ span.title
+ {
+ font-style: italic;
+ }
+
+ span.underline
+ {
+ text-decoration: underline;
+ }
+
+ span.strikethrough
+ {
+ text-decoration: line-through;
+ }
+
+ /* Copyright, Legal Notice */
+ div div.legalnotice p
+ {
+ text-align: left
+ }
+
+/*=============================================================================
+ Colors
+=============================================================================*/
+
+ @media screen
+ {
+ body {
+ background-color: #FFFFFF;
+ }
+
+ /* Links */
+ a
+ {
+ color: #005a9c;
+ }
+
+ a:visited
+ {
+ color: #9c5a9c;
+ }
+
+ h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
+ h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
+ h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
+ {
+ text-decoration: none; /* no underline */
+ color: #000000;
+ }
+
+ /* Syntax Highlighting */
+ .keyword { color: #0000AA; }
+ .identifier { color: #000000; }
+ .special { color: #707070; }
+ .preprocessor { color: #402080; }
+ .char { color: teal; }
+ .comment { color: #800000; }
+ .string { color: teal; }
+ .number { color: teal; }
+ .white_bkd { background-color: #FFFFFF; }
+ .dk_grey_bkd { background-color: #999999; }
+
+ /* Copyright, Legal Notice */
+ .copyright
+ {
+ color: #666666;
+ font-size: small;
+ }
+
+ div div.legalnotice p
+ {
+ color: #666666;
+ }
+
+ /* Program listing */
+ pre.synopsis
+ {
+ border: 1px solid #DCDCDC;
+ }
+
+ .programlisting,
+ .screen
+ {
+ border: 1px solid #DCDCDC;
+ }
+
+ td .programlisting,
+ td .screen
+ {
+ border: 0px solid #DCDCDC;
+ }
+
+ /* Blurbs */
+ div.note,
+ div.tip,
+ div.important,
+ div.caution,
+ div.warning,
+ p.blurb
+ {
+ border: 1px solid #DCDCDC;
+ }
+
+ /* Table of contents */
+ .toc
+ {
+ border: 1px solid #DCDCDC;
+ }
+
+ /* Tables */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ border: 1px solid #DCDCDC;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ background-color: #F0F0F0;
+ border: 1px solid #DCDCDC;
+ }
+
+ .copyright-footer
+ {
+ color: #8F8F8F;
+ }
+
+ /* Misc */
+ span.highlight
+ {
+ color: #00A000;
+ }
+ }
+
+ @media print
+ {
+ /* Links */
+ a
+ {
+ color: black;
+ }
+
+ a:visited
+ {
+ color: black;
+ }
+
+ .spirit-nav
+ {
+ display: none;
+ }
+
+ /* Program listing */
+ pre.synopsis
+ {
+ border: 1px solid gray;
+ }
+
+ .programlisting,
+ .screen
+ {
+ border: 1px solid gray;
+ }
+
+ td .programlisting,
+ td .screen
+ {
+ border: 0px solid #DCDCDC;
+ }
+
+ /* Table of contents */
+ .toc
+ {
+ border: 1px solid gray;
+ }
+
+ .informaltable table,
+ .table table
+ {
+ border: 1px solid gray;
+ border-collapse: collapse;
+ }
+
+ /* Tables */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ border: 1px solid gray;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ border: 1px solid gray;
+ }
+
+ table.simplelist tr td
+ {
+ border: none !important;
+ }
+
+ /* Misc */
+ span.highlight
+ {
+ font-weight: bold;
+ }
+ }
+
+/*=============================================================================
+ Images
+=============================================================================*/
+
+ span.inlinemediaobject img
+ {
+ vertical-align: middle;
+ }
+
+/*==============================================================================
+ Super and Subscript: style so that line spacing isn't effected, see
+ http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=1&postId=5341
+==============================================================================*/
+
+sup,
+sub {
+ height: 0;
+ line-height: 1;
+ vertical-align: baseline;
+ _vertical-align: bottom;
+ position: relative;
+
+}
+
+sup {
+ bottom: 1ex;
+}
+
+sub {
+ top: .5ex;
+}
+
diff --git a/tools/auto_index/doc/html/images/blank.png b/tools/auto_index/doc/html/images/blank.png
new file mode 100644
index 0000000000..764bf4f0c3
--- /dev/null
+++ b/tools/auto_index/doc/html/images/blank.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/caution.png b/tools/auto_index/doc/html/images/caution.png
new file mode 100644
index 0000000000..5b7809ca4a
--- /dev/null
+++ b/tools/auto_index/doc/html/images/caution.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/caution.svg b/tools/auto_index/doc/html/images/caution.svg
new file mode 100644
index 0000000000..4bd586a08e
--- /dev/null
+++ b/tools/auto_index/doc/html/images/caution.svg
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) --><svg height="120.648" id="Layer_1" inkscape:version="0.42" sodipodi:docbase="F:\openclip\svg da inviare" sodipodi:docname="Attenzione.svg" sodipodi:version="0.32" space="preserve" style="overflow:visible;enable-background:new 0 0 133.878 120.648;" version="1.1" viewBox="0 0 133.878 120.648" width="133.878" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg">
+ <metadata>
+ <rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <cc:Work rdf:about="">
+ <dc:title>Attenzione</dc:title>
+ <dc:description></dc:description>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>pulsante</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <dc:publisher>
+ <cc:Agent rdf:about="http://www.openclipart.org/">
+ <dc:title>Open Clip Art Library</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Architetto Francesco Rollandin</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights>
+ <cc:Agent>
+ <dc:title>Architetto Francesco Rollandin</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ <dc:date></dc:date>
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
+ <dc:language>en</dc:language>
+ </cc:Work>
+ <cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
+ <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+ <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+ <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <defs id="defs43"/>
+ <sodipodi:namedview bordercolor="#666666" borderopacity="1.0" id="base" inkscape:current-layer="Layer_1" inkscape:cx="66.939003" inkscape:cy="60.324001" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="510" inkscape:window-width="787" inkscape:window-x="44" inkscape:window-y="58" inkscape:zoom="2.9838869" pagecolor="#ffffff"/>
+ <g id="g3">
+ <linearGradient gradientTransform="matrix(56.9977 90.4964 90.4964 -56.9977 -27343.9609 47971.0547)" gradientUnits="userSpaceOnUse" id="XMLID_4_" x1="-244.5732" x2="-242.8169" y1="455.4199" y2="455.4199">
+ <stop id="stop6" offset="0" style="stop-color:#FFFA5F"/>
+ <stop id="stop8" offset="1" style="stop-color:#9F3300"/>
+ </linearGradient>
+ <path d="M51.333,8.834C34.985,37.343,18.638,65.854,2.289,94.363 c-7.081,12.352,3.352,26.285,16.453,26.285c6.708,0,13.418,0,20.128,0c22.109,0,44.217,0,66.327,0c3.644,0,7.286,0,10.931,0 c13.293,0,20.963-14.273,16.452-26.031c-4.114-10.729-11.861-20.99-17.542-30.922c-8.81-15.403-17.618-30.809-26.429-46.212 c-1.813-3.167-3.622-6.333-5.434-9.5C76.601-3.516,57.616-2.03,51.333,8.834 M53.973,9.064" id="path10" style="fill:url(#XMLID_4_);"/>
+ <path d="M55.474,12.388c-8.247,14.279-16.492,28.559-24.739,42.839 c-5.526,9.567-11.05,19.137-16.577,28.707c-2.732,4.73-7.323,10.456-8.284,16c-3.799,21.9,34.927,15.743,46.734,15.743 c20.073,0,40.144,0,60.215,0c13.716,0,18.636-11.963,12.229-23.063c-6.462-11.195-12.927-22.388-19.389-33.582 c-7.249-12.557-14.499-25.113-21.75-37.671c-1.682-2.916-3.364-5.829-5.049-8.745C73.767,3.785,60.676,3.364,55.474,12.388" id="path12" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFF200;"/>
+ <path d="M55.474,12.388c-8.247,14.279-16.492,28.559-24.739,42.839c-5.526,9.567-11.05,19.137-16.577,28.707 c-2.732,4.73-7.323,10.456-8.284,16c-3.799,21.9,34.927,15.743,46.734,15.743c20.073,0,40.144,0,60.215,0 c13.716,0,18.636-11.963,12.229-23.063c-6.462-11.195-12.927-22.388-19.389-33.582c-7.249-12.557-14.499-25.113-21.75-37.671 c-1.682-2.916-3.364-5.829-5.049-8.745C73.767,3.785,60.676,3.364,55.474,12.388" id="path14" style="fill:#FFCE00;"/>
+ <path d="M126.731,95.522c-8.733-15.127-17.468-30.253-26.201-45.379 c-5.537-9.595-11.078-19.188-16.616-28.781c-3.938-6.821-7.459-15.689-16.813-15.689c1.013,0,5.901,10.225,6.469,11.196 c5.451,9.314,10.902,18.63,16.352,27.947c9.217,15.749,18.433,31.498,27.646,47.249c2.302,3.933,5.356,10.555,1.308,14.397 c-3.148,2.987-7.99,3.196-12.099,3.196c-7.225,0-14.448,0-21.674,0c-22.125,0-44.251,0-66.377,0c-3.598,0-7.197,0-10.794,0 c5.285,7.909,16.341,6.02,24.546,6.02c13.009,0,26.017,0,39.023,0c11.979,0,23.958,0,35.937,0c2.516,0,5.032,0,7.547,0 C125.136,115.678,131.878,104.435,126.731,95.522" id="path16" style="fill:#FFB600;"/>
+ <path d="M14.615,112.457c-4.483-7.751,1.908-16.103,5.793-22.834 c4.698-8.138,9.398-16.276,14.097-24.414C44.54,47.83,54.574,30.448,64.61,13.069c0.789-1.367,3.725-4.568,2.594-5.539 c-3.913-3.353-10.287,1.936-12.107,5.087c-3.129,5.417-6.258,10.835-9.386,16.252c-11.105,19.226-22.209,38.453-33.313,57.68 c-1.649,2.854-3.299,5.713-4.95,8.569c-4.771,8.265-0.075,19.162,9.658,20.446C16.124,114.65,15.294,113.615,14.615,112.457" id="path18" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFE600;"/>
+ <path d="M77.076,34.654c0,10.183-1.788,20.758-3.439,30.772 c-0.369,2.239-4.03,23.609-7.796,14.179c-4.247-10.632-4.832-23.419-5.958-34.696c-0.363-3.638-1.538-8.425-0.563-12.06 C61.667,24.099,77.076,25.199,77.076,34.654" id="path20" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFE1;"/>
+ <path d="M77.076,34.654c-2.018,0.995-1.521,8.717-1.797,11.395c-0.685,6.643-1.505,13.282-2.614,19.869 c-0.79,4.701-1.301,10.862-3.954,14.981c-1.642,2.567-3.405-5.958-3.634-6.932c-2.948-12.443-4.464-25.664-5.09-38.43 c-0.272-5.52,5.164-8.854,10.277-7.622c3.87,0.933,5.217,7.36,7.688,6.738c0.009-11.451-19.755-11.453-19.746,0 c0.017,11.956,2.087,24.599,4.423,36.294c0.501,2.507,1.642,12.376,5.449,12.376c4.059-0.021,5.285-11.432,5.79-14.137 c1.261-6.765,2.139-13.605,2.887-20.444C77.084,45.722,79.281,35.942,77.076,34.654" id="path22" style="fill:#FFFFFF;"/>
+ <linearGradient gradientTransform="matrix(68.2284 33.0019 33.0019 -68.2284 1613.9791 39385.6641)" gradientUnits="userSpaceOnUse" id="XMLID_5_" x1="-246.981" x2="-245.2275" y1="458.29" y2="458.29">
+ <stop id="stop25" offset="0" style="stop-color:#FFFA5F"/>
+ <stop id="stop27" offset="1" style="stop-color:#9F3300"/>
+ </linearGradient>
+ <path d="M57.957,34.654c0,10.053,1.632,20.54,3.242,30.431 c0.479,2.936,4.912,26.502,9.99,15.164c4.987-11.134,5.351-25.201,6.386-37.184c0.273-3.169,1.153-7.045,0.421-10.221 C75.628,22.587,57.957,23.788,57.957,34.654 M60.207,34.654c0-8.061,13.138-9.015,15.459-1.792c1.156,3.597-0.13,8.748-0.508,12.38 c-1.135,10.904-2.052,22.602-5.501,33.069c-2.816,8.545-5.546-10.187-5.934-12.522C62.039,55.63,60.207,44.985,60.207,34.654" id="path29" style="fill-rule:evenodd;clip-rule:evenodd;fill:url(#XMLID_5_);"/>
+ <path d="M77.076,96.788c0,11.964-18.555,11.964-18.555,0 C58.521,84.822,77.076,84.822,77.076,96.788" id="path31" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFE1;"/>
+ <path d="M77.076,96.788c-2.605,1.661-2.157,6.757-7.044,8.101c-6.178,1.7-12.033-4.159-10.336-10.335 c1.439-5.23,7.657-7.767,12.341-5.021c2.91,1.704,3.164,7.913,5.915,7.256c0-14.267-22.698-12.238-20.143,1.826 c0.987,5.444,6.375,9.15,11.814,8.162C72.417,106.271,81.44,98.19,77.076,96.788" id="path33" style="fill:#FFFFFF;"/>
+ <linearGradient gradientTransform="matrix(68.2241 32.9998 32.9998 -68.2241 1604.682 39402.625)" gradientUnits="userSpaceOnUse" id="XMLID_6_" x1="-246.998" x2="-245.2348" y1="458.0625" y2="458.0625">
+ <stop id="stop36" offset="0" style="stop-color:#FFFA5F"/>
+ <stop id="stop38" offset="1" style="stop-color:#9F3300"/>
+ </linearGradient>
+ <path d="M57.395,96.788c0,13.41,20.805,13.41,20.805,0 C78.2,83.376,57.395,83.375,57.395,96.788 M59.647,96.788c0-10.514,16.301-10.514,16.301,0 C75.948,107.3,59.647,107.3,59.647,96.788" id="path40" style="fill-rule:evenodd;clip-rule:evenodd;fill:url(#XMLID_6_);"/>
+ </g>
+</svg>
diff --git a/tools/auto_index/doc/html/images/draft.png b/tools/auto_index/doc/html/images/draft.png
new file mode 100644
index 0000000000..0084708c9b
--- /dev/null
+++ b/tools/auto_index/doc/html/images/draft.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/home.png b/tools/auto_index/doc/html/images/home.png
new file mode 100644
index 0000000000..5584aacb09
--- /dev/null
+++ b/tools/auto_index/doc/html/images/home.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/home.svg b/tools/auto_index/doc/html/images/home.svg
new file mode 100644
index 0000000000..e803a3178f
--- /dev/null
+++ b/tools/auto_index/doc/html/images/home.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 9.0, SVG Export Plug-In -->
+<!DOCTYPE svg [
+ <!ENTITY st0 "fill-rule:nonzero;clip-rule:nonzero;fill:#FFFFFF;stroke:#000000;stroke-miterlimit:4;">
+ <!ENTITY st1 "fill:none;stroke:none;">
+ <!ENTITY st2 "fill:#000000;">
+ <!ENTITY st3 "fill:none;stroke:#FFFFFF;stroke-width:6.3469;stroke-linejoin:round;">
+ <!ENTITY st4 "fill-rule:evenodd;clip-rule:evenodd;stroke:none;">
+ <!ENTITY st5 "fill-rule:nonzero;clip-rule:nonzero;stroke:#000000;stroke-miterlimit:4;">
+]>
+<svg width="48pt" height="48pt" viewBox="0 0 48 48" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+ <g id="Layer_x0020_3" style="&st0;">
+ <g style="&st4;">
+ <path style="&st3;" d="M22.9,7.1L5.1,21.8l0,0c-0.3,0.3-0.5,0.8-0.5,1.2c0,0.2,0,0.4,0.1,0.6c0.3,0.6,0.9,1,1.6,1c0,0,1.1,0,2.2,0c0,2.4,0,14.2,0,14.2c0,1.1,0.8,1.9,1.8,1.9h27.4c1.1,0,1.9-0.9,1.9-2c0,0,0-11.8,0-14.2c1,0,2,0,2,0c0.8,0,1.4-0.5,1.7-1.2
+ c0.1-0.2,0.1-0.4,0.1-0.6c0-0.5-0.2-1-0.7-1.4c0,0-3.6-3-4.5-3.7c0-1.2,0-6.9,0-6.9c0-1.2-0.8-2-2-2h-4.8c-1,0-1.7,0.6-1.9,1.5c-1.9-1.6-4.1-3.5-4.1-3.5l0.1,0.1c-0.7-0.7-1.8-0.8-2.7-0.1z"/>
+ <path style="&st2;" d="M22.9,7.1L5.1,21.8l0,0c-0.3,0.3-0.5,0.8-0.5,1.2c0,0.2,0,0.4,0.1,0.6c0.3,0.6,0.9,1,1.6,1c0,0,1.1,0,2.2,0c0,2.4,0,14.2,0,14.2c0,1.1,0.8,1.9,1.8,1.9h27.4c1.1,0,1.9-0.9,1.9-2c0,0,0-11.8,0-14.2c1,0,2,0,2,0c0.8,0,1.4-0.5,1.7-1.2
+ c0.1-0.2,0.1-0.4,0.1-0.6c0-0.5-0.2-1-0.7-1.4c0,0-3.6-3-4.5-3.7c0-1.2,0-6.9,0-6.9c0-1.2-0.8-2-2-2h-4.8c-1,0-1.7,0.6-1.9,1.5c-1.9-1.6-4.1-3.5-4.1-3.5l0.1,0.1c-0.7-0.7-1.8-0.8-2.7-0.1z"/>
+ <path style="&st2;" d="M41.8,22.8l-5.1-4.2v-0.1L31,13.7v0l-6.5-5.5C24.2,8,24,8,23.8,8.2L6.2,22.9c-0.1,0.1-0.1,0.3,0.1,0.3h1.6H10h28.1h1.2h2.3c0.2,0,0.4-0.2,0.2-0.4z"/>
+ <path d="M35.8,16.8l0-5.1c0-0.2-0.1-0.4-0.3-0.4h-3.2c-0.2,0-0.3,0.1-0.3,0.3v2.2l3.9,2.9z"/>
+ <path d="M11.9,24.7V37c0,0.3,0.1,0.4,0.3,0.4h23.6c0.3,0,0.4-0.2,0.4-0.4V24.7H11.9z"/>
+ </g>
+ </g>
+ <g id="crop_x0020_marks" style="&st5;">
+ <path style="&st1;" d="M48,48H0V0h48v48z"/>
+ </g>
+</svg>
diff --git a/tools/auto_index/doc/html/images/important.png b/tools/auto_index/doc/html/images/important.png
new file mode 100644
index 0000000000..12c90f607a
--- /dev/null
+++ b/tools/auto_index/doc/html/images/important.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/important.svg b/tools/auto_index/doc/html/images/important.svg
new file mode 100644
index 0000000000..dd84f3fe36
--- /dev/null
+++ b/tools/auto_index/doc/html/images/important.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 9.0, SVG Export Plug-In -->
+<!DOCTYPE svg [
+ <!ENTITY st0 "fill:#FFFFFF;stroke:none;">
+ <!ENTITY st1 "fill:#FFFFFF;stroke-width:6.6112;stroke-linecap:round;stroke-linejoin:round;">
+ <!ENTITY st2 "stroke:#FFFFFF;stroke-width:6.6112;">
+ <!ENTITY st3 "fill:none;stroke:none;">
+ <!ENTITY st4 "fill-rule:nonzero;clip-rule:nonzero;stroke:#000000;stroke-miterlimit:4;">
+ <!ENTITY st5 "stroke:none;">
+]>
+<svg width="48pt" height="48pt" viewBox="0 0 48 48" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+ <g id="Layer_x0020_3" style="&st4;">
+ <g>
+ <path style="&st2;" d="M41.7,35.3L26.6,9.4c-0.6-1-1.7-1.7-2.9-1.6c-1.2,0-2.3,0.7-2.9,1.7L6.3,35.4c-0.6,1-0.6,2.3,0,3.3c0.6,1,1.7,1.6,2.9,1.6h29.6c1.2,0,2.3-0.6,2.9-1.7c0.6-1,0.6-2.3,0-3.3z"/>
+ <path style="&st1;" d="M23.7,11L9.2,37h29.6L23.7,11z"/>
+ <path style="&st0;" d="M23.7,11.9L10.3,36.1h27.5l-14-24.1z"/>
+ <g>
+ <path style="&st5;" d="M24.1,34c-1.1,0-1.8-0.8-1.8-1.8c0-1.1,0.7-1.8,1.8-1.8c1.1,0,1.8,0.7,1.8,1.8c0,1-0.7,1.8-1.8,1.8h0z M22.9,29.3l-0.4-9.1h3.2l-0.4,9.1h-2.3z"/>
+ </g>
+ </g>
+ </g>
+ <g id="crop_x0020_marks" style="&st4;">
+ <path style="&st3;" d="M48,48H0V0h48v48z"/>
+ </g>
+</svg>
diff --git a/tools/auto_index/doc/html/images/next.png b/tools/auto_index/doc/html/images/next.png
new file mode 100644
index 0000000000..59800b4e87
--- /dev/null
+++ b/tools/auto_index/doc/html/images/next.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/next.svg b/tools/auto_index/doc/html/images/next.svg
new file mode 100644
index 0000000000..75fa83ed8c
--- /dev/null
+++ b/tools/auto_index/doc/html/images/next.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 9.0, SVG Export Plug-In -->
+<!DOCTYPE svg [
+ <!ENTITY st0 "fill:none;stroke:none;">
+ <!ENTITY st1 "fill:#FFFFFF;stroke:#FFFFFF;stroke-width:7.5901;stroke-linejoin:round;">
+ <!ENTITY st2 "fill-rule:nonzero;clip-rule:nonzero;stroke:#000000;stroke-miterlimit:4;">
+ <!ENTITY st3 "stroke:none;">
+]>
+<svg width="48pt" height="48pt" viewBox="0 0 48 48" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+ <g id="Layer_x0020_3" style="&st2;">
+ <g>
+ <path style="&st1;" d="M22.4,41.1c0,0.3,0.3,0.3,0.5,0.2l16.6-16.9c0.5-0.5,0.4-0.7,0-1L22.9,6.7c-0.1-0.1-0.4-0.1-0.4,0.1v10H8.9c-0.3,0-0.5,0.2-0.5,0.4l0,13.3C8.4,30.9,8.6,31,9,31h13.5l-0.1,10.1z"/>
+ <path style="&st3;" d="M22.4,41.1c0,0.3,0.3,0.3,0.5,0.2l16.6-16.9c0.5-0.5,0.4-0.7,0-1L22.9,6.7c-0.1-0.1-0.4-0.1-0.4,0.1v10H8.9c-0.3,0-0.5,0.2-0.5,0.4l0,13.3C8.4,30.9,8.6,31,9,31h13.5l-0.1,10.1z"/>
+ </g>
+ </g>
+ <g id="crop_x0020_marks" style="&st2;">
+ <path style="&st0;" d="M48,48H0V0h48v48z"/>
+ </g>
+</svg>
diff --git a/tools/auto_index/doc/html/images/next_disabled.png b/tools/auto_index/doc/html/images/next_disabled.png
new file mode 100644
index 0000000000..10a8c59d7b
--- /dev/null
+++ b/tools/auto_index/doc/html/images/next_disabled.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/note.png b/tools/auto_index/doc/html/images/note.png
new file mode 100644
index 0000000000..d0c3c645ab
--- /dev/null
+++ b/tools/auto_index/doc/html/images/note.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/note.svg b/tools/auto_index/doc/html/images/note.svg
new file mode 100644
index 0000000000..648299d26f
--- /dev/null
+++ b/tools/auto_index/doc/html/images/note.svg
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 9.0, SVG Export Plug-In -->
+<!DOCTYPE svg [
+ <!ENTITY st0 "fill:none;stroke:#FFFFFF;stroke-width:12.1438;stroke-linejoin:round;">
+ <!ENTITY st1 "fill:none;stroke-width:1.2429;">
+ <!ENTITY st2 "fill:#FFFFFF;stroke:none;">
+ <!ENTITY st3 "fill:none;stroke:#FFFFFF;stroke-width:12.7649;stroke-linejoin:round;">
+ <!ENTITY st4 "fill:#FFFFFF;stroke-width:6.3824;stroke-linejoin:round;">
+ <!ENTITY st5 "fill:none;stroke:none;">
+ <!ENTITY st6 "fill-rule:nonzero;clip-rule:nonzero;stroke:#000000;stroke-miterlimit:4;">
+ <!ENTITY st7 "fill:#FFFFFF;stroke:#FFFFFF;stroke-width:12.7649;stroke-linejoin:round;">
+ <!ENTITY st8 "stroke:none;">
+ <!ENTITY st9 "fill:none;stroke-width:4.9715;stroke-linejoin:round;">
+]>
+<svg xmlns="http://www.w3.org/2000/svg" width="48pt" height="48pt" viewBox="0 0 48 48" xml:space="preserve">
+ <g id="Layer_x0020_1" style="&st6;">
+ <path style="&st0;" d="M35.7,19.8v18.9H11V8.8h13.9l10.8,11z"/>
+ <path style="&st3;" d="M38.7,30.4L25,16.7l-7.7-3l2.7,8.7l13.3,13.4l5.4-5.4z"/>
+ <path style="&st7;" d="M35.7,8.8H11v29.9h24.7V8.8z"/>
+ <path style="&st4;" d="M35.7,8.8H11v29.9h24.7V8.8z"/>
+ <path style="&st2;" d="M35.7,8.8H11v29.9h24.7V8.8z"/>
+ </g>
+ <g id="Layer_x0020_4" style="&st6;">
+ <path style="&st9;" d="M38.7,30.4L25,16.7l-7.7-3l2.7,8.7l13.3,13.4l5.4-5.4z"/>
+ <path style="&st8;" d="M38.7,30.4L25,16.7l-7.7-3l2.7,8.7l13.3,13.4l5.4-5.4z"/>
+ <path style="&st8;" d="M20.6,14.7l-2.5,2.5L17,13.4l3.6,1.3z"/>
+ <path style="&st1;" d="M19.6,22.2l3-0.3l2.4-2.4l0.4-2.8"/>
+ <path style="&st2;" d="M20.4,14.9L18.3,17l1.6,5.2l2.7-0.3l2.4-2.4l0.3-2.4l-5-2.2z"/>
+ </g>
+ <g id="crop" style="&st6;">
+ <path style="&st5;" d="M48,48H0V0h48v48z"/>
+ </g>
+</svg>
diff --git a/tools/auto_index/doc/html/images/prev.png b/tools/auto_index/doc/html/images/prev.png
new file mode 100644
index 0000000000..d88a40f923
--- /dev/null
+++ b/tools/auto_index/doc/html/images/prev.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/prev.svg b/tools/auto_index/doc/html/images/prev.svg
new file mode 100644
index 0000000000..6d88ffdd0d
--- /dev/null
+++ b/tools/auto_index/doc/html/images/prev.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 9.0, SVG Export Plug-In -->
+<!DOCTYPE svg [
+ <!ENTITY st0 "fill:none;stroke:none;">
+ <!ENTITY st1 "fill:#FFFFFF;stroke:#FFFFFF;stroke-width:7.5901;stroke-linejoin:round;">
+ <!ENTITY st2 "fill-rule:nonzero;clip-rule:nonzero;stroke:#000000;stroke-miterlimit:4;">
+ <!ENTITY st3 "stroke:none;">
+]>
+<svg width="48pt" height="48pt" viewBox="0 0 48 48" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+ <g id="Layer_x0020_3" style="&st2;">
+ <g>
+ <path style="&st1;" d="M25.6,6.9c0-0.3-0.3-0.3-0.5-0.2L8.4,23.6c-0.5,0.5-0.4,0.7,0,1l16.6,16.6c0.1,0.1,0.4,0.1,0.4-0.1v-10h13.6c0.3,0,0.5-0.2,0.5-0.4l0-13.3c0-0.3-0.2-0.5-0.5-0.5H25.5l0.1-10.1z"/>
+ <path style="&st3;" d="M25.6,6.9c0-0.3-0.3-0.3-0.5-0.2L8.4,23.6c-0.5,0.5-0.4,0.7,0,1l16.6,16.6c0.1,0.1,0.4,0.1,0.4-0.1v-10h13.6c0.3,0,0.5-0.2,0.5-0.4l0-13.3c0-0.3-0.2-0.5-0.5-0.5H25.5l0.1-10.1z"/>
+ </g>
+ </g>
+ <g id="crop_x0020_marks" style="&st2;">
+ <path style="&st0;" d="M48,48H0V0h48v48z"/>
+ </g>
+</svg>
diff --git a/tools/auto_index/doc/html/images/prev_disabled.png b/tools/auto_index/doc/html/images/prev_disabled.png
new file mode 100644
index 0000000000..ab3c17e02d
--- /dev/null
+++ b/tools/auto_index/doc/html/images/prev_disabled.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/tip.png b/tools/auto_index/doc/html/images/tip.png
new file mode 100644
index 0000000000..5c4aab3bb3
--- /dev/null
+++ b/tools/auto_index/doc/html/images/tip.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/tip.svg b/tools/auto_index/doc/html/images/tip.svg
new file mode 100644
index 0000000000..cd437a5e85
--- /dev/null
+++ b/tools/auto_index/doc/html/images/tip.svg
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) --><svg height="1052.3622047" id="svg2" inkscape:version="0.42.2" sodipodi:docbase="/home/sergio/tmp/downloads" sodipodi:docname="lamp.svg" sodipodi:version="0.32" width="744.09448819" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <metadata>
+ <rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <cc:Work rdf:about="">
+ <dc:title>lamp</dc:title>
+ <dc:description></dc:description>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>office</rdf:li>
+ <rdf:li></rdf:li>
+ <rdf:li>lamp</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <dc:publisher>
+ <cc:Agent rdf:about="http://www.openclipart.org/">
+ <dc:title>Open Clip Art Library</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Sergio Luiz Araujo Silva</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights>
+ <cc:Agent>
+ <dc:title>Public Domain</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ <dc:date>set 2005</dc:date>
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
+ <dc:language>en</dc:language>
+ </cc:Work>
+ <cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
+ <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+ <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+ <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <defs id="defs4">
+ <linearGradient id="linearGradient13125">
+ <stop id="stop13127" offset="0.0000000" style="stop-color:#ffffff;stop-opacity:1.0000000;"/>
+ <stop id="stop13129" offset="1" style="stop-color:#fffeff;stop-opacity:0;"/>
+ </linearGradient>
+ <linearGradient id="linearGradient12389">
+ <stop id="stop12391" offset="0.0000000" style="stop-color:#fefefe;stop-opacity:1.0000000;"/>
+ <stop id="stop12393" offset="1.0000000" style="stop-color:#fffefe;stop-opacity:1.0000000;"/>
+ </linearGradient>
+ <radialGradient cx="358.25909" cy="186.06468" fx="358.25909" fy="186.06468" gradientTransform="matrix(1.000001,-8.244061e-7,3.143917e-7,0.381356,-4.028738e-4,115.1081)" gradientUnits="userSpaceOnUse" id="radialGradient13131" inkscape:collect="always" r="27.486719" xlink:href="#linearGradient13125"/>
+ <radialGradient cx="358.25909" cy="186.06468" fx="358.25909" fy="186.06468" gradientTransform="matrix(1.000001,-8.244061e-7,3.143917e-7,0.381356,-4.028738e-4,115.1081)" gradientUnits="userSpaceOnUse" id="radialGradient14587" inkscape:collect="always" r="27.486719" xlink:href="#linearGradient13125"/>
+ <radialGradient cx="358.25909" cy="186.06468" fx="358.25909" fy="186.06468" gradientTransform="matrix(1.000001,-8.244061e-7,3.143917e-7,0.381356,-4.028738e-4,115.1081)" gradientUnits="userSpaceOnUse" id="radialGradient15390" inkscape:collect="always" r="27.486719" xlink:href="#linearGradient13125"/>
+ <radialGradient cx="358.25909" cy="186.06468" fx="358.25909" fy="186.06468" gradientTransform="matrix(1.000001,-8.244061e-7,3.143917e-7,0.381356,-4.028738e-4,115.1081)" gradientUnits="userSpaceOnUse" id="radialGradient16141" inkscape:collect="always" r="27.486719" xlink:href="#linearGradient13125"/>
+ </defs>
+ <sodipodi:namedview bordercolor="#666666" borderopacity="1.0" id="base" inkscape:current-layer="layer1" inkscape:cx="344.34505" inkscape:cy="795.78292" inkscape:document-units="px" inkscape:guide-bbox="true" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="693" inkscape:window-width="1024" inkscape:window-x="0" inkscape:window-y="25" inkscape:zoom="0.72123084" pagecolor="#ffffff" showguides="true"/>
+ <g id="layer1" inkscape:groupmode="layer" inkscape:label="Layer 1">
+ <path d="M 369.44028,121.86683 C 302.64703,119.68096 242.59223,184.30679 250.47188,250.87980 C 252.47522,280.21980 267.84094,306.49880 285.94332,328.82253 C 303.71281,358.65039 312.13900,393.24133 313.51068,427.73030 C 317.00419,446.97288 338.01608,454.57063 355.35334,455.26572 C 375.18456,456.91501 395.94281,455.09265 414.43470,447.69729 C 430.92724,435.70557 427.37713,413.20597 430.74488,395.55648 C 434.70351,361.57615 449.78002,329.76555 471.07843,303.26619 C 504.41026,252.31528 488.56419,176.76397 437.75400,143.26422 C 417.82956,129.49394 393.70573,121.69096 369.44028,121.86683 z " id="path1384" style="opacity:1.0000000;fill:#f3f2f3;fill-opacity:0.83333331;stroke:#000000;stroke-width:0.58960420;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"/>
+ <path d="M 425.72698,154.07768 C 437.68158,164.87540 453.68534,182.03604 451.17873,203.82428 C 455.99913,200.54641 460.81954,197.26853 465.63995,193.99066 C 459.85546,170.27425 448.28648,162.75442 425.72698,154.07768 z " id="path2153" sodipodi:nodetypes="cccc" style="fill:#fefefe;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 506.99897 296.94009 A 37.120701 18.718985 0 1 1 432.75756,296.94009 A 37.120701 18.718985 0 1 1 506.99897 296.94009 z" id="path2881" sodipodi:cx="469.87827" sodipodi:cy="296.94009" sodipodi:rx="37.120701" sodipodi:ry="18.718985" sodipodi:type="arc" style="opacity:1.0000000;color:#000000;fill:#fefefe;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.64700001;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" transform="matrix(0.818103,0.000000,0.000000,0.896150,-13.89510,-26.68653)"/>
+ <path d="M 359.20536,314.30802 L 336.64585,244.31570 C 362.29042,230.62575 382.72895,234.28926 403.16748,243.15881 L 379.45107,315.46491 L 379.45107,315.46491" id="path3617" sodipodi:nodetypes="ccccc" style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#8f9595;stroke-width:0.91160071px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 513.73605 514.32300 A 52.508934 11.885468 0 1 1 408.71818,514.32300 A 52.508934 11.885468 0 1 1 513.73605 514.32300 z" id="path4361" sodipodi:cx="461.22711" sodipodi:cy="514.32300" sodipodi:rx="52.508934" sodipodi:ry="11.885468" sodipodi:type="arc" style="opacity:1.0000000;color:#000000;fill:#a0a0a0;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.64700001;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" transform="matrix(0.982435,0.000000,0.000000,1.387810,-83.52495,-281.2705)"/>
+ <path d="M 315.87677,433.07959 C 319.14672,442.90428 329.03398,448.82383 338.76816,450.68840 C 362.00206,456.37952 386.74882,455.38004 409.63484,448.57985 C 414.28840,447.19363 419.18392,445.42184 422.06530,441.25295 C 423.42527,439.84003 425.68582,434.46169 424.07088,434.30126 C 411.81432,444.17256 395.75685,447.78808 380.34111,448.56322 C 362.85475,449.05661 344.64886,448.26521 328.51659,440.79114 C 324.02706,438.71576 319.76022,436.14612 315.87677,433.07959 z " id="path4363" style="fill:#d6dee6;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 400.47436,522.16227 C 396.48542,528.09177 392.49650,534.02126 388.50756,539.95076 C 383.93367,541.47295 366.98819,546.44954 353.57745,538.01018 C 350.34318,532.29631 347.10892,526.58244 343.87465,520.86856 C 364.35835,531.64946 396.48542,523.99502 400.47436,522.16227 z " id="path5094" sodipodi:nodetypes="ccccc" style="fill:#090a0c;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.91160071px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 419.65600,444.27781 C 419.97026,446.39906 420.28452,448.52031 420.59878,450.64156 C 421.46299,450.95582 422.32720,451.27008 423.19142,451.58434 C 423.19142,452.91994 423.19142,454.25554 423.19142,455.59114 C 422.32720,455.98397 421.46299,456.37678 420.59878,456.76961 C 420.36308,459.20512 420.12739,461.64063 419.89170,464.07614 C 420.52021,464.23327 421.14873,464.39039 421.77725,464.54753 C 421.69869,466.59021 421.62012,468.63289 421.54156,470.67558 C 420.83447,471.46123 420.12739,472.24688 419.42030,473.03253 C 419.57744,474.05387 419.73456,475.07522 419.89170,476.09656 C 420.91303,477.11790 421.93438,478.13925 422.95572,479.16058 C 422.87716,480.18193 422.79859,481.20328 422.72003,482.22461 C 422.01294,483.01026 421.30586,483.79591 420.59878,484.58156 C 420.36308,485.05294 420.12739,485.52433 419.89170,485.99572 C 419.57744,486.70280 419.26317,487.40989 418.94892,488.11697 C 419.10605,489.05975 419.26317,490.00253 419.42030,490.94531 C 419.89170,491.65239 420.36308,492.35947 420.83447,493.06655 C 420.67734,494.71641 420.52021,496.36627 420.36308,498.01614 C 415.02067,505.24410 409.67827,512.47206 404.33587,519.70003 C 403.15740,520.24998 401.97892,520.79994 400.80045,521.34989 C 397.81498,522.29266 394.82952,523.23544 391.84406,524.17822 C 386.34452,524.80674 380.84498,525.43525 375.34545,526.06378 C 371.96717,525.90664 368.58887,525.74952 365.21059,525.59238 C 362.46082,525.51382 359.71105,525.43525 356.96128,525.35669 C 353.42587,524.49247 349.89045,523.62827 346.35503,522.76405 C 345.17656,521.82128 343.99809,520.87850 342.81962,519.93572 C 339.75559,517.81447 336.69157,515.69322 333.62754,513.57197 C 328.75652,508.30813 323.88551,503.04429 319.01448,497.78044 C 319.01448,496.52341 319.01448,495.26636 319.01448,494.00933 C 319.87870,494.00933 320.74291,494.00933 321.60712,494.00933 C 321.13574,492.83086 320.66435,491.65239 320.19296,490.47392 C 319.09305,488.19554 317.99314,485.91716 316.89323,483.63878 C 316.89323,482.93170 316.89323,482.22461 316.89323,481.51753 C 318.38597,480.26049 319.87869,479.00345 321.37143,477.74642 C 320.03583,475.54660 318.70022,473.34679 317.36462,471.14697 C 317.28606,470.83271 317.20748,470.51845 317.12892,470.20419 C 318.46453,468.39720 319.80013,466.59021 321.13574,464.78322 C 320.74291,463.68331 320.35009,462.58341 319.95726,461.48350 C 319.09305,460.38359 318.22883,459.28369 317.36462,458.18378 C 317.12892,457.31956 316.89323,456.45536 316.65753,455.59114 C 317.75744,454.17697 318.85735,452.76281 319.95726,451.34864 C 319.87870,450.01304 319.80013,448.67744 319.72157,447.34184 C 319.32874,446.71332 318.93592,446.08480 318.54310,445.45628 C 318.62166,444.74920 318.70023,444.04212 318.77879,443.33503 C 319.48588,443.25647 320.19296,443.17790 320.90004,443.09934 C 324.04263,445.22059 327.18523,447.34184 330.32782,449.46309 C 348.08347,456.92674 391.76550,461.09068 419.65600,444.27781 z " id="path7284" sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccc" style="fill:#fba246;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.91160071px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 389.86281,523.00744 C 389.46998,521.82897 391.23336,522.26765 390.84054,521.08918 C 383.37688,521.01061 375.91323,520.93205 368.44957,520.85348 C 368.44957,520.53923 368.44957,520.22496 368.44957,519.91070 C 374.10624,519.75357 379.76290,519.59645 385.41957,519.43932 C 388.24790,518.88937 391.07623,518.33941 393.90457,517.78946 C 395.39730,517.55377 396.89003,517.31807 398.38277,517.08237 C 401.44679,515.03969 404.51082,512.99701 407.57485,510.95432 C 407.49629,510.64006 407.41771,510.32580 407.33915,510.01153 C 401.36822,510.48292 395.39730,510.95432 389.42637,511.42571 C 387.30512,511.81853 385.18387,512.21135 383.06263,512.60418 C 379.13438,512.36849 375.20615,512.13279 371.27790,511.89710 C 369.78518,511.73997 368.29244,511.58284 366.79971,511.42571 C 364.44277,510.32580 362.08582,509.22589 359.72888,508.12598 C 376.54175,507.18320 396.89003,507.18320 415.11707,493.98432 C 391.31192,502.15506 371.27790,500.19093 355.01499,497.99112 C 375.91322,494.06288 396.57577,493.19867 417.00262,478.42849 C 387.38368,489.42756 366.24975,485.57788 349.35832,483.84946 C 371.51360,479.29269 403.56804,478.27136 414.40998,466.64376 C 383.06263,474.89306 355.95776,473.47890 338.75207,469.47210 C 352.81517,467.58654 366.87827,465.70098 380.94137,463.81543 C 374.10624,463.18691 367.27110,462.55840 360.43596,461.92988 C 373.32059,459.73006 386.20522,457.53024 399.08985,455.33043 C 381.88416,456.19465 346.53000,460.82997 319.89653,444.48849 C 323.66763,447.63108 328.61721,449.83090 331.20985,453.91627 C 327.28161,453.44487 323.35338,452.97349 319.42513,452.50210 C 319.66083,453.83770 319.89653,455.17330 320.13222,456.50890 C 324.13902,459.02298 328.14582,461.53704 332.15263,464.05112 C 327.43875,466.25093 322.72485,468.45075 318.01096,470.65057 C 323.90332,472.53612 329.79568,474.42169 335.68805,476.30724 C 330.03138,478.66418 322.48915,476.30724 318.71804,483.37807 C 325.55318,486.59923 335.21666,487.22774 339.22346,493.04154 C 333.33110,493.51293 326.73166,489.27043 321.54639,494.45571 C 327.67444,498.06968 333.80249,501.68367 339.93055,505.29765 C 336.55226,504.82626 333.17397,504.35487 329.79568,503.88348 C 334.58814,509.30445 341.26727,513.37780 346.05972,518.79877 C 362.00838,520.29150 373.91416,521.51471 389.86281,523.00744 z " id="path6556" sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccc" style="fill:#ffc080;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 410.63580,448.38806 C 375.91016,459.46570 347.07688,453.33765 330.49970,448.38806 C 332.54238,449.09515 334.58507,449.80223 336.62775,450.50931 C 365.30391,460.56561 396.80839,453.41621 407.80747,450.27362 C 408.75025,449.64510 409.69303,449.01658 410.63580,448.38806 z " id="path7286" sodipodi:nodetypes="ccccc" style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 431.22109,368.33927 C 427.74256,388.71364 424.26401,409.08801 420.78546,429.46237 C 416.60557,437.06563 407.94091,440.30372 400.07083,442.61238 C 391.48668,445.18530 382.40444,445.05799 373.54205,444.61656 C 371.08048,446.38986 364.99205,442.92177 370.06503,441.81235 C 377.17154,440.98795 384.60188,442.10538 391.38552,439.26558 C 401.04319,435.47671 410.26670,429.97354 417.05844,422.00834 C 421.19961,403.95301 425.34070,385.89766 429.48184,367.84233 C 430.06159,368.00798 430.64135,368.17360 431.22109,368.33927 z " id="path3629" style="fill:#ffffff;fill-opacity:0.64285713;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 353.42087,428.84088 L 351.10708,419.00725 L 351.68553,378.22661 L 353.13164,373.45440 L 353.05576,339.28565 L 349.95018,336.28751 L 349.37173,316.04336 C 363.86558,304.49563 376.56238,306.21837 388.70625,316.23514 L 388.12780,336.28907 L 385.23556,339.18131 L 384.65711,373.58108 L 386.39245,378.21491 L 385.81401,427.68398 L 382.34331,429.99778 L 374.24503,428.84088 L 371.35278,425.37019 L 366.14675,425.37019 L 360.94071,429.41933 L 353.42087,428.84088 z " id="path3619" sodipodi:nodetypes="ccccccccccccccccccc" style="fill:#c1c1c1;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#9b989f;stroke-width:0.91160071px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 358.25832,325.31572 L 358.25832,416.41507" id="path5096" style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.91160071px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 380.15345,325.31572 L 380.15345,416.41507" id="path5824" style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.91160071px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 361.91098,325.31572 L 361.91098,416.41507" id="path5826" style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#8f8f92;stroke-width:0.91160071px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 376.52161,325.31572 L 376.52161,416.41507" id="path6554" style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#8f8f92;stroke-width:0.91160071px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <g id="g9475" transform="matrix(0.911601,0.000000,0.000000,0.911601,328.5961,-156.2531)">
+ <path d="M 86.864034,673.56687 L 79.199560,676.97330 L 77.155700,678.67652 L 75.793127,679.69845 L 65.573829,679.35780 L 65.403508,678.33587 L 70.683478,676.97330 C 70.683478,676.97330 74.430554,676.63266 75.111841,676.46234 C 75.793127,676.29201 78.688595,674.92944 78.688595,674.92944 L 84.649852,671.52301 L 87.034355,671.52301 L 86.864034,673.56687 z " id="path8741" style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 91.973683,686.34099 L 88.056285,686.17067 L 85.331139,687.53324 L 81.073098,689.23646 L 77.836987,691.45064 L 75.111841,692.30225 L 70.853800,692.64289 L 69.320905,693.15386 L 71.024122,693.83514 L 75.963449,693.83514 L 80.221490,694.51643 L 83.627923,693.83514 L 87.545320,690.42871 C 87.545320,690.42871 90.270466,689.23646 90.951753,688.89581 C 91.633039,688.55517 93.165934,687.87388 93.165934,687.87388 L 91.973683,686.34099 z " id="path8743" style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 94.017542,700.30736 L 89.078215,703.03251 L 85.842104,705.07637 L 83.457601,706.94991 L 77.836987,708.14216 L 75.622806,708.14216 L 81.584063,710.01570 L 86.353069,707.97184 L 91.292396,705.58733 L 92.825291,704.05444 L 94.017542,700.30736 z " id="path8745" style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 91.462718,717.85049 C 91.462718,717.85049 81.924706,721.59757 81.584063,722.27885 C 81.243420,722.96014 78.688595,723.98207 78.688595,723.98207 L 72.897660,724.66336 L 71.024122,725.68529 L 76.644736,726.36657 L 82.435671,724.49304 L 86.693712,724.32271 L 89.929823,722.10853 L 91.462718,720.40532 L 91.462718,717.85049 z " id="path8747" style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ </g>
+ <path d="M 378.14273,525.28637 C 377.57434,530.51553 378.00099,537.83204 377.43261,543.06120 C 372.27918,543.00443 367.82875,543.82657 360.97078,541.72320 C 359.43614,536.89190 356.80919,529.30796 355.27454,524.47667 C 356.26507,524.72572 356.68741,524.86790 357.82038,524.93742 C 358.95335,525.00694 360.79692,524.96593 361.90337,525.03791 C 363.00981,525.10990 364.25012,525.06768 365.31257,525.13480 C 366.37503,525.20191 367.41113,525.22689 368.41214,525.28180 C 369.41314,525.33669 370.37905,525.38365 371.30113,525.41898 C 372.22321,525.45432 374.35115,525.55378 375.17683,525.56221 C 376.00251,525.57065 375.56381,525.48806 376.27564,525.46225 C 376.98745,525.43643 377.56225,525.35378 378.14273,525.28637 z " id="path10207" sodipodi:nodetypes="ccccsssssssc" style="fill:#ffffff;fill-opacity:0.31547615;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"/>
+ <path d="M 467.06377,199.37552 L 453.69293,208.53364 L 451.86130,221.53816 L 468.71223,214.21167 L 467.06377,199.37552 z " id="path16869" style="fill:#fefefe;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;opacity:1.0000000;color:#000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0;visibility:visible;display:inline;overflow:visible"/>
+ </g>
+</svg>
diff --git a/tools/auto_index/doc/html/images/toc-blank.png b/tools/auto_index/doc/html/images/toc-blank.png
new file mode 100644
index 0000000000..6ffad17a0c
--- /dev/null
+++ b/tools/auto_index/doc/html/images/toc-blank.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/toc-minus.png b/tools/auto_index/doc/html/images/toc-minus.png
new file mode 100644
index 0000000000..abbb020c8e
--- /dev/null
+++ b/tools/auto_index/doc/html/images/toc-minus.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/toc-plus.png b/tools/auto_index/doc/html/images/toc-plus.png
new file mode 100644
index 0000000000..941312ce0d
--- /dev/null
+++ b/tools/auto_index/doc/html/images/toc-plus.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/up.png b/tools/auto_index/doc/html/images/up.png
new file mode 100644
index 0000000000..17d9c3ec49
--- /dev/null
+++ b/tools/auto_index/doc/html/images/up.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/up.svg b/tools/auto_index/doc/html/images/up.svg
new file mode 100644
index 0000000000..d31aa9c809
--- /dev/null
+++ b/tools/auto_index/doc/html/images/up.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 9.0, SVG Export Plug-In -->
+<!DOCTYPE svg [
+ <!ENTITY st0 "fill:none;stroke:none;">
+ <!ENTITY st1 "fill:#FFFFFF;stroke:#FFFFFF;stroke-width:7.5901;stroke-linejoin:round;">
+ <!ENTITY st2 "fill-rule:nonzero;clip-rule:nonzero;stroke:#000000;stroke-miterlimit:4;">
+ <!ENTITY st3 "stroke:none;">
+]>
+<svg width="48pt" height="48pt" viewBox="0 0 48 48" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+ <g id="Layer_x0020_3" style="&st2;">
+ <g>
+ <path style="&st1;" d="M41.1,25.6c0.3,0,0.3-0.3,0.2-0.5L24.4,8.4c-0.5-0.5-0.7-0.4-1,0L6.7,25.1c-0.1,0.1-0.1,0.4,0.1,0.4h10v13.6c0,0.3,0.2,0.5,0.4,0.5l13.3,0c0.3,0,0.5-0.2,0.5-0.5V25.5l10.1,0.1z"/>
+ <path style="&st3;" d="M41.1,25.6c0.3,0,0.3-0.3,0.2-0.5L24.4,8.4c-0.5-0.5-0.7-0.4-1,0L6.7,25.1c-0.1,0.1-0.1,0.4,0.1,0.4h10v13.6c0,0.3,0.2,0.5,0.4,0.5l13.3,0c0.3,0,0.5-0.2,0.5-0.5V25.5l10.1,0.1z"/>
+ </g>
+ </g>
+ <g id="crop_x0020_marks" style="&st2;">
+ <path style="&st0;" d="M48,48H0V0h48v48z"/>
+ </g>
+</svg>
diff --git a/tools/auto_index/doc/html/images/up_disabled.png b/tools/auto_index/doc/html/images/up_disabled.png
new file mode 100644
index 0000000000..e22bc87121
--- /dev/null
+++ b/tools/auto_index/doc/html/images/up_disabled.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/warning.png b/tools/auto_index/doc/html/images/warning.png
new file mode 100644
index 0000000000..1c33db8f34
--- /dev/null
+++ b/tools/auto_index/doc/html/images/warning.png
Binary files differ
diff --git a/tools/auto_index/doc/html/images/warning.svg b/tools/auto_index/doc/html/images/warning.svg
new file mode 100644
index 0000000000..fc8d7484cb
--- /dev/null
+++ b/tools/auto_index/doc/html/images/warning.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 9.0, SVG Export Plug-In -->
+<!DOCTYPE svg [
+ <!ENTITY st0 "fill:#000000;stroke:#FFFFFF;stroke-width:7.9139;stroke-linejoin:round;">
+ <!ENTITY st1 "fill-rule:nonzero;clip-rule:nonzero;fill:#FFFFFF;stroke:#000000;stroke-miterlimit:4;">
+ <!ENTITY st2 "fill:none;stroke:none;">
+ <!ENTITY st3 "fill:#000000;">
+ <!ENTITY st4 "fill-rule:evenodd;clip-rule:evenodd;stroke:none;">
+ <!ENTITY st5 "fill-rule:nonzero;clip-rule:nonzero;stroke:#000000;stroke-miterlimit:4;">
+]>
+<svg width="48pt" height="48pt" viewBox="0 0 48 48" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+ <g id="Layer_x0020_4" style="&st1;">
+ <g style="&st4;">
+ <path style="&st0;" d="M16.4,42.3L5.7,31.6V16.4L16.4,5.7h15.2l10.7,10.7v15.2L31.6,42.3H16.4z"/>
+ <path style="&st3;" d="M16.4,42.3L5.7,31.6V16.4L16.4,5.7h15.2l10.7,10.7v15.2L31.6,42.3H16.4z"/>
+ <path d="M11.7,17.7l18.7,18.7l5.9-5.9L17.6,11.7l-5.9,5.9z"/>
+ <path d="M11.7,30.5l5.9,5.9l18.7-18.7l-5.9-5.9L11.7,30.5z"/>
+ </g>
+ </g>
+ <g id="crop_x0020_marks" style="&st5;">
+ <path style="&st2;" d="M48,48H0V0h48v48z"/>
+ </g>
+</svg>
diff --git a/tools/auto_index/doc/html/index.html b/tools/auto_index/doc/html/index.html
new file mode 100644
index 0000000000..80b322449b
--- /dev/null
+++ b/tools/auto_index/doc/html/index.html
@@ -0,0 +1,83 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Boost.AutoIndex</title>
+<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="index.html" title="Boost.AutoIndex">
+<link rel="next" href="boost_autoindex/overview.html" title="Overview">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
+<td align="center"><a href="../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav"><a accesskey="n" href="boost_autoindex/overview.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
+<div class="article">
+<div class="titlepage">
+<div>
+<div><h2 class="title">
+<a name="boost_autoindex"></a>Boost.AutoIndex</h2></div>
+<div><div class="authorgroup"><div class="author"><h3 class="author">
+<span class="firstname">John</span> <span class="surname">Maddock</span>
+</h3></div></div></div>
+<div><p class="copyright">Copyright &#169; 2008, 2011 John Maddock</p></div>
+<div><div class="legalnotice">
+<a name="id1003974"></a><p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></div>
+</div>
+<hr>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="section"><a href="boost_autoindex/overview.html">Overview</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/tut.html">Getting Started and Tutorial</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="boost_autoindex/tut/build.html">Step 1: Build the AutoIndex
+ tool</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/tut/configure.html">Step 2: Configure Boost.Build
+ jamfile to use AutoIndex</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="boost_autoindex/tut/configure/options.html">Available Indexing
+ Options</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/tut/configure/optional.html">Making AutoIndex
+ optional</a></span></dt>
+</dl></dd>
+<dt><span class="section"><a href="boost_autoindex/tut/add_indexes.html">Step 3: Add indexes
+ to your documentation</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/tut/script.html">Step 4: Create the .idx script
+ file - to control what to terms to index</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/tut/entries.html">Step 5: Add Manual Index
+ Entries to Docbook XML - Optional</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/tut/pis.html">Step 6: Using XML processing
+ instructions to control what gets indexed.</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/tut/build_docs.html">Step 7: Build the Docs</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/tut/refine.html">Step 8: Iterate - to refine
+ your index</a></span></dt>
+</dl></dd>
+<dt><span class="section"><a href="boost_autoindex/script_ref.html">Script File (.idx) Reference</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/workflow.html">Understanding The AutoIndex Workflow</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/xml.html">XML Handling</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/qbk.html">Quickbook Support</a></span></dt>
+<dt><span class="section"><a href="boost_autoindex/comm_ref.html">Command Line Reference</a></span></dt>
+<dt><span class="section"><a href="index/s08.html">Index</a></span></dt>
+</dl>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"><p><small>Last revised: July 14, 2011 at 15:55:33 GMT</small></p></td>
+<td align="right"><div class="copyright-footer"></div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav"><a accesskey="n" href="boost_autoindex/overview.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/index/s07.html b/tools/auto_index/doc/html/index/s07.html
new file mode 100644
index 0000000000..6701e5e946
--- /dev/null
+++ b/tools/auto_index/doc/html/index/s07.html
@@ -0,0 +1,585 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Index</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.74.0">
+<link rel="home" href="../index.html" title="AutoIndex">
+<link rel="up" href="../index.html" title="AutoIndex">
+<link rel="prev" href="../autoindex/comm_ref.html" title="Command Line Reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr><td valign="top"></td></tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../autoindex/comm_ref.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id1054189"></a>Index</h2></div></div></div>
+<p><a class="link" href="s07.html#idx_id_0">A</a> <a class="link" href="s07.html#idx_id_1">B</a> <a class="link" href="s07.html#idx_id_2">C</a> <a class="link" href="s07.html#idx_id_3">D</a> <a class="link" href="s07.html#idx_id_4">F</a> <a class="link" href="s07.html#idx_id_5">H</a> <a class="link" href="s07.html#idx_id_6">I</a> <a class="link" href="s07.html#idx_id_7">J</a> <a class="link" href="s07.html#idx_id_8">L</a> <a class="link" href="s07.html#idx_id_9">M</a> <a class="link" href="s07.html#idx_id_10">O</a> <a class="link" href="s07.html#idx_id_11">P</a> <a class="link" href="s07.html#idx_id_12">Q</a> <a class="link" href="s07.html#idx_id_13">S</a> <a class="link" href="s07.html#idx_id_14">T</a> <a class="link" href="s07.html#idx_id_15">U</a> <a class="link" href="s07.html#idx_id_16">V</a> <a class="link" href="s07.html#idx_id_17">X</a> </p>
+<div class="variablelist"><dl>
+<dt>
+<a name="idx_id_0"></a><span class="term">A</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">appendix</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">Command Line Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+</table></dd>
+<dt><span class="term">AutoIndex</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../index.html" title="AutoIndex">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Making AutoIndex optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool">Step 1: Build the AutoIndex tool</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">Step 4: Create the .idx script file - to control what to terms to index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional">Step 5: Add Manual Index Entries to Docbook XML - Optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">Step 6: Build the Docs</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">XML Handling</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Available Indexing Options</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">appendix</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">chapter</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">debug</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Docbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">page</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Quickbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">section</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">stylesheet</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">verbose</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">XML</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">XSL</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">XSL stylesheet</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_1"></a><span class="term">B</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">bjam</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Making AutoIndex optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool">Step 1: Build the AutoIndex tool</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">Step 6: Build the Docs</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Boost.Build</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Making AutoIndex optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">Step 6: Build the Docs</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Boostbook</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool">Step 1: Build the AutoIndex tool</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_2"></a><span class="term">C</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">C++</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">Step 4: Create the .idx script file - to control what to terms to index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+</table></dd>
+<dt><span class="term">chapter</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">Command Line Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+</table></dd>
+<dt><span class="term">class</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Command Line Reference</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">appendix</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">chapter</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">section</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">stylesheet</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">XML</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">XSL</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">XSL stylesheet</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_3"></a><span class="term">D</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">debug</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">Step 6: Build the Docs</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">Step 7: Iterate - to refine your index</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Docbook</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional">Step 5: Add Manual Index Entries to Docbook XML - Optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">Step 7: Iterate - to refine your index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Doxygen</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">Step 4: Create the .idx script file - to control what to terms to index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_4"></a><span class="term">F</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">function</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_5"></a><span class="term">H</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">html</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Making AutoIndex optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">Step 6: Build the Docs</a></p></td></tr>
+</table></dd>
+<dt><span class="term">hyperlink</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list"><tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr></table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_6"></a><span class="term">I</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">index</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">Command Line Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Making AutoIndex optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool">Step 1: Build the AutoIndex tool</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">Step 4: Create the .idx script file - to control what to terms to index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional">Step 5: Add Manual Index Entries to Docbook XML - Optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">Step 6: Build the Docs</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">Step 7: Iterate - to refine your index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">XML Handling</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_7"></a><span class="term">J</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">jamfile</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Making AutoIndex optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_8"></a><span class="term">L</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">log file</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Making AutoIndex optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">Step 6: Build the Docs</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_9"></a><span class="term">M</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">macro</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Making AutoIndex optional</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">bjam</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Boost.Build</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">html</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">jamfile</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">log file</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Quickbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">section</a></p></td></tr>
+</table></dd>
+<dt><span class="term">MSVC</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list"><tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr></table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_10"></a><span class="term">O</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">Overview</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">appendix</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Boost.Build</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Boostbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">C++</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">chapter</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">class</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Docbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Doxygen</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">function</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">html</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">hyperlink</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">jamfile</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">macro</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">page</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">PDF</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">plural</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Quickbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">section</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">stylesheet</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">typedef</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">XML</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">XSL</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">XSL stylesheet</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_11"></a><span class="term">P</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">page</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+</table></dd>
+<dt><span class="term">PDF</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">Step 6: Build the Docs</a></p></td></tr>
+</table></dd>
+<dt><span class="term">plural</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">Step 4: Create the .idx script file - to control what to terms to index</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_12"></a><span class="term">Q</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">Quickbook</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Making AutoIndex optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">Step 7: Iterate - to refine your index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_13"></a><span class="term">S</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">script</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">Command Line Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Making AutoIndex optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">Step 4: Create the .idx script file - to control what to terms to index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">Step 6: Build the Docs</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">Step 7: Iterate - to refine your index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">XML Handling</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Script File (.idx) Reference</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">C++</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">class</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">debug</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">function</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">log file</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">macro</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">plural</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">section</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">text</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">typedef</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">XML</a></p></td></tr>
+</table></dd>
+<dt><span class="term">section</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">Command Line Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure/optional.html" title="Making AutoIndex optional">Making AutoIndex optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">Step 4: Create the .idx script file - to control what to terms to index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">Step 7: Iterate - to refine your index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">XML Handling</a></p></td></tr>
+</table></dd>
+<dt><span class="term">side-by-side</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list"><tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr></table></dd>
+<dt><span class="term">Step 1: Build the AutoIndex tool</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool">bjam</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool">Boostbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool">index</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Boost.Build</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Boostbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">html</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">jamfile</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">log file</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">MSVC</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">PDF</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Quickbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">section</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">side-by-side</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">verbose</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Step 3: Add indexes to your documentation</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">appendix</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Boostbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">C++</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">chapter</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">class</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Docbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Doxygen</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">function</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">html</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">jamfile</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">macro</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">page</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">PDF</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Quickbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">section</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">stylesheet</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">typedef</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">XML</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">XSL</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">XSL stylesheet</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Step 4: Create the .idx script file - to control what to terms to index</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">C++</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">Doxygen</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">plural</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">section</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">text</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Step 5: Add Manual Index Entries to Docbook XML - Optional</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional">Docbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional">XML</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Step 6: Build the Docs</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">bjam</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">Boost.Build</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">debug</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">html</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">log file</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">PDF</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">verbose</a></p></td></tr>
+</table></dd>
+<dt><span class="term">Step 7: Iterate - to refine your index</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">debug</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">Docbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">Quickbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/refine.html" title="Step 7: Iterate - to refine your index">section</a></p></td></tr>
+</table></dd>
+<dt><span class="term">stylesheet</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">Command Line Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_14"></a><span class="term">T</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">text</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index">Step 4: Create the .idx script file - to control what to terms to index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">XML Handling</a></p></td></tr>
+</table></dd>
+<dt><span class="term">typedef</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_15"></a><span class="term">U</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">Understanding The AutoIndex Workflow</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Boostbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">C++</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Docbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Doxygen</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Quickbook</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">stylesheet</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">text</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">XML</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">XSL</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">XSL stylesheet</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_16"></a><span class="term">V</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">verbose</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex">Step 2: Configure Boost.Build jamfile to use AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/build_docs.html" title="Step 6: Build the Docs">Step 6: Build the Docs</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+<dt>
+<a name="idx_id_17"></a><span class="term">X</span>
+</dt>
+<dd><div class="variablelist"><dl>
+<dt><span class="term">XML</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">Command Line Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/script_ref.html" title="Script File (.idx) Reference">Script File (.idx) Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional">Step 5: Add Manual Index Entries to Docbook XML - Optional</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">XML Handling</a></p></td></tr>
+</table></dd>
+<dt><span class="term">XML Handling</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">AutoIndex</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">index</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">script</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">section</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">text</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/xml.html" title="XML Handling">XML</a></p></td></tr>
+</table></dd>
+<dt><span class="term">XSL</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">Command Line Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+</table></dd>
+<dt><span class="term">XSL stylesheet</span></dt>
+<dd><table class="simplelist" border="0" summary="Simple list">
+<tr><td><p><a class="link" href="../autoindex/tut/configure/options.html" title="Available Indexing Options">Available Indexing Options</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/comm_ref.html" title="Command Line Reference">Command Line Reference</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/overview.html" title="Overview">Overview</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation">Step 3: Add indexes to your documentation</a></p></td></tr>
+<tr><td><p><a class="link" href="../autoindex/workflow.html" title="Understanding The AutoIndex Workflow">Understanding The AutoIndex Workflow</a></p></td></tr>
+</table></dd>
+</dl></div></dd>
+</dl></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008 , 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../autoindex/comm_ref.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/index/s08.html b/tools/auto_index/doc/html/index/s08.html
new file mode 100644
index 0000000000..929b206bcc
--- /dev/null
+++ b/tools/auto_index/doc/html/index/s08.html
@@ -0,0 +1,718 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Index</title>
+<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="../index.html" title="Boost.AutoIndex">
+<link rel="up" href="../index.html" title="Boost.AutoIndex">
+<link rel="prev" href="../boost_autoindex/comm_ref.html" title="Command Line Reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center"><a href="../../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../boost_autoindex/comm_ref.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id1018804"></a>Index</h2></div></div></div>
+<p><a class="link" href="s08.html#idx_id_0">A</a> <a class="link" href="s08.html#idx_id_1">B</a> <a class="link" href="s08.html#idx_id_2">C</a> <a class="link" href="s08.html#idx_id_3">D</a> <a class="link" href="s08.html#idx_id_4">F</a> <a class="link" href="s08.html#idx_id_5">H</a> <a class="link" href="s08.html#idx_id_6">I</a> <a class="link" href="s08.html#idx_id_7">J</a> <a class="link" href="s08.html#idx_id_8">L</a> <a class="link" href="s08.html#idx_id_9">M</a> <a class="link" href="s08.html#idx_id_10">O</a> <a class="link" href="s08.html#idx_id_11">P</a> <a class="link" href="s08.html#idx_id_12">Q</a> <a class="link" href="s08.html#idx_id_13">S</a> <a class="link" href="s08.html#idx_id_14">T</a> <a class="link" href="s08.html#idx_id_15">U</a> <a class="link" href="s08.html#idx_id_16">V</a> <a class="link" href="s08.html#idx_id_17">X</a></p>
+<div class="variablelist"><dl>
+<dt>
+<a name="idx_id_0"></a><span class="term">A</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">appendix</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">Command Line Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">Step 6: Using XML processing instructions to control what gets indexed.</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">AutoIndex</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../index.html" title="Boost.AutoIndex"><span class="index-entry-level-1">Boost.AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">Command Line Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Making AutoIndex optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">Quickbook Support</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool"><span class="index-entry-level-1">Step 1: Build the AutoIndex tool</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">Step 4: Create the .idx script file - to control what to terms to index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional"><span class="index-entry-level-1">Step 5: Add Manual Index Entries to Docbook XML - Optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">Step 6: Using XML processing instructions to control what gets indexed.</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">Step 7: Build the Docs</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">XML Handling</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Available Indexing Options</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">appendix</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">chapter</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">debug</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Docbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">page</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Quickbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">section</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">stylesheet</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">verbose</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">XML</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">XSL</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">XSL stylesheet</span></a></p></li>
+</ul></div>
+</li>
+</ul></div></dd>
+<dt>
+<a name="idx_id_1"></a><span class="term">B</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">bjam</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Making AutoIndex optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool"><span class="index-entry-level-1">Step 1: Build the AutoIndex tool</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">Step 7: Build the Docs</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Boost.AutoIndex</span></p>
+<div class="index"><ul class="index" type="none" compact><li class="listitem" style="list-style-type: none"><p><a class="link" href="../index.html" title="Boost.AutoIndex"><span class="index-entry-level-1">AutoIndex</span></a></p></li></ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Boost.Build</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Making AutoIndex optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">Step 7: Build the Docs</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Boostbook</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool"><span class="index-entry-level-1">Step 1: Build the AutoIndex tool</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+</ul></div>
+</li>
+</ul></div></dd>
+<dt>
+<a name="idx_id_2"></a><span class="term">C</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">C++</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">Step 4: Create the .idx script file - to control what to terms to index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">chapter</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">Command Line Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">Step 6: Using XML processing instructions to control what gets indexed.</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">class</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">Quickbook Support</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Command Line Reference</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">appendix</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">chapter</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">section</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">stylesheet</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">XML</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">XSL</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">XSL stylesheet</span></a></p></li>
+</ul></div>
+</li>
+</ul></div></dd>
+<dt>
+<a name="idx_id_3"></a><span class="term">D</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">debug</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">Step 7: Build the Docs</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">Step 8: Iterate - to refine your index</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Docbook</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">Quickbook Support</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional"><span class="index-entry-level-1">Step 5: Add Manual Index Entries to Docbook XML - Optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">Step 8: Iterate - to refine your index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Doxygen</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">Step 4: Create the .idx script file - to control what to terms to index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+</ul></div>
+</li>
+</ul></div></dd>
+<dt>
+<a name="idx_id_4"></a><span class="term">F</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact><li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">function</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+</ul></div>
+</li></ul></div></dd>
+<dt>
+<a name="idx_id_5"></a><span class="term">H</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">html</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Making AutoIndex optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">Step 7: Build the Docs</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">hyperlink</span></p>
+<div class="index"><ul class="index" type="none" compact><li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li></ul></div>
+</li>
+</ul></div></dd>
+<dt>
+<a name="idx_id_6"></a><span class="term">I</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact><li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">index</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">Command Line Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Making AutoIndex optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">Quickbook Support</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool"><span class="index-entry-level-1">Step 1: Build the AutoIndex tool</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">Step 4: Create the .idx script file - to control what to terms to index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional"><span class="index-entry-level-1">Step 5: Add Manual Index Entries to Docbook XML - Optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">Step 6: Using XML processing instructions to control what gets indexed.</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">Step 7: Build the Docs</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">Step 8: Iterate - to refine your index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">XML Handling</span></a></p></li>
+</ul></div>
+</li></ul></div></dd>
+<dt>
+<a name="idx_id_7"></a><span class="term">J</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact><li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">jamfile</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Making AutoIndex optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">Quickbook Support</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+</ul></div>
+</li></ul></div></dd>
+<dt>
+<a name="idx_id_8"></a><span class="term">L</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact><li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">log file</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Making AutoIndex optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">Step 7: Build the Docs</span></a></p></li>
+</ul></div>
+</li></ul></div></dd>
+<dt>
+<a name="idx_id_9"></a><span class="term">M</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">macro</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Making AutoIndex optional</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">bjam</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Boost.Build</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">html</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">jamfile</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">log file</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Quickbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">section</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">MSVC</span></p>
+<div class="index"><ul class="index" type="none" compact><li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li></ul></div>
+</li>
+</ul></div></dd>
+<dt>
+<a name="idx_id_10"></a><span class="term">O</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact><li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Overview</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">appendix</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Boost.Build</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Boostbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">C++</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">chapter</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">class</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Docbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Doxygen</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">function</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">html</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">hyperlink</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">jamfile</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">macro</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">page</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">PDF</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">plural</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Quickbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">section</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">stylesheet</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">typedef</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">XML</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">XSL</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">XSL stylesheet</span></a></p></li>
+</ul></div>
+</li></ul></div></dd>
+<dt>
+<a name="idx_id_11"></a><span class="term">P</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">page</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">PDF</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">Step 7: Build the Docs</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">plural</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">Step 4: Create the .idx script file - to control what to terms to index</span></a></p></li>
+</ul></div>
+</li>
+</ul></div></dd>
+<dt>
+<a name="idx_id_12"></a><span class="term">Q</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Quickbook</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Making AutoIndex optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">Quickbook Support</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional"><span class="index-entry-level-1">Step 5: Add Manual Index Entries to Docbook XML - Optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">Step 6: Using XML processing instructions to control what gets indexed.</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">Step 8: Iterate - to refine your index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Quickbook Support</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">class</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">Docbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">jamfile</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">Quickbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">section</span></a></p></li>
+</ul></div>
+</li>
+</ul></div></dd>
+<dt>
+<a name="idx_id_13"></a><span class="term">S</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">script</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">Command Line Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Making AutoIndex optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">Step 4: Create the .idx script file - to control what to terms to index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">Step 7: Build the Docs</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">Step 8: Iterate - to refine your index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">XML Handling</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Script File (.idx) Reference</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">C++</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">class</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">debug</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">function</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">log file</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">macro</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">plural</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">section</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">text</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">typedef</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">XML</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">section</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">Command Line Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/optional.html" title="Making AutoIndex optional"><span class="index-entry-level-1">Making AutoIndex optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/qbk.html" title="Quickbook Support"><span class="index-entry-level-1">Quickbook Support</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">Step 4: Create the .idx script file - to control what to terms to index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">Step 6: Using XML processing instructions to control what gets indexed.</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">Step 8: Iterate - to refine your index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">XML Handling</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">side-by-side</span></p>
+<div class="index"><ul class="index" type="none" compact><li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li></ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Step 1: Build the AutoIndex tool</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool"><span class="index-entry-level-1">bjam</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool"><span class="index-entry-level-1">Boostbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build.html" title="Step 1: Build the AutoIndex tool"><span class="index-entry-level-1">index</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Boost.Build</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Boostbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">html</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">jamfile</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">log file</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">MSVC</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">PDF</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Quickbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">section</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">side-by-side</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">verbose</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Step 3: Add indexes to your documentation</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">appendix</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Boostbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">chapter</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">class</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Docbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Doxygen</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">function</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">html</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">jamfile</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">macro</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">page</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">PDF</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Quickbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">section</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">stylesheet</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">typedef</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">XML</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">XSL</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">XSL stylesheet</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Step 4: Create the .idx script file - to control what to terms to index</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">C++</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">Doxygen</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">plural</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">section</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">text</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Step 5: Add Manual Index Entries to Docbook XML - Optional</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional"><span class="index-entry-level-1">Docbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional"><span class="index-entry-level-1">Quickbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional"><span class="index-entry-level-1">XML</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Step 6: Using XML processing instructions to control what gets indexed.</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">appendix</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">chapter</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">Quickbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">section</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">text</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">XML</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Step 7: Build the Docs</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">bjam</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">Boost.Build</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">debug</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">html</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">log file</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">PDF</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">verbose</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Step 8: Iterate - to refine your index</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">debug</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">Docbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">Quickbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/refine.html" title="Step 8: Iterate - to refine your index"><span class="index-entry-level-1">section</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">stylesheet</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">Command Line Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+</ul></div>
+</li>
+</ul></div></dd>
+<dt>
+<a name="idx_id_14"></a><span class="term">T</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">text</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/script.html" title="Step 4: Create the .idx script file - to control what to terms to index"><span class="index-entry-level-1">Step 4: Create the .idx script file - to control what to terms to index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">Step 6: Using XML processing instructions to control what gets indexed.</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">XML Handling</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">typedef</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+</ul></div>
+</li>
+</ul></div></dd>
+<dt>
+<a name="idx_id_15"></a><span class="term">U</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact><li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">Understanding The AutoIndex Workflow</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Boostbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">C++</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Docbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Doxygen</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Quickbook</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">stylesheet</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">text</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">XML</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">XSL</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">XSL stylesheet</span></a></p></li>
+</ul></div>
+</li></ul></div></dd>
+<dt>
+<a name="idx_id_16"></a><span class="term">V</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact><li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">verbose</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure.html" title="Step 2: Configure Boost.Build jamfile to use AutoIndex"><span class="index-entry-level-1">Step 2: Configure Boost.Build jamfile to use AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/build_docs.html" title="Step 7: Build the Docs"><span class="index-entry-level-1">Step 7: Build the Docs</span></a></p></li>
+</ul></div>
+</li></ul></div></dd>
+<dt>
+<a name="idx_id_17"></a><span class="term">X</span>
+</dt>
+<dd><div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">XML</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">Command Line Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/script_ref.html" title="Script File (.idx) Reference"><span class="index-entry-level-1">Script File (.idx) Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/entries.html" title="Step 5: Add Manual Index Entries to Docbook XML - Optional"><span class="index-entry-level-1">Step 5: Add Manual Index Entries to Docbook XML - Optional</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/pis.html" title="Step 6: Using XML processing instructions to control what gets indexed."><span class="index-entry-level-1">Step 6: Using XML processing instructions to control what gets indexed.</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">XML Handling</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">XML Handling</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">AutoIndex</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">index</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">script</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">section</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">text</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/xml.html" title="XML Handling"><span class="index-entry-level-1">XML</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">XSL</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">Command Line Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+</ul></div>
+</li>
+<li class="listitem" style="list-style-type: none">
+<p><span class="index-entry-level-0">XSL stylesheet</span></p>
+<div class="index"><ul class="index" type="none" compact>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/configure/options.html" title="Available Indexing Options"><span class="index-entry-level-1">Available Indexing Options</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/comm_ref.html" title="Command Line Reference"><span class="index-entry-level-1">Command Line Reference</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/overview.html" title="Overview"><span class="index-entry-level-1">Overview</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/tut/add_indexes.html" title="Step 3: Add indexes to your documentation"><span class="index-entry-level-1">Step 3: Add indexes to your documentation</span></a></p></li>
+<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_autoindex/workflow.html" title="Understanding The AutoIndex Workflow"><span class="index-entry-level-1">Understanding The AutoIndex Workflow</span></a></p></li>
+</ul></div>
+</li>
+</ul></div></dd>
+</dl></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright &#169; 2008, 2011 John Maddock<p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../boost_autoindex/comm_ref.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a>
+</div>
+</body>
+</html>
diff --git a/tools/auto_index/doc/html/reference.css b/tools/auto_index/doc/html/reference.css
new file mode 100644
index 0000000000..6826962afc
--- /dev/null
+++ b/tools/auto_index/doc/html/reference.css
@@ -0,0 +1,11 @@
+/*============================================================================
+ Copyright 2003-2004 Douglas Gregor
+ Distributed under the Boost Software License, Version 1.0. (See accompany-
+ ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+============================================================================*/
+
+PRE.synopsis {
+ background-color: #e0ffff;
+ border: thin solid blue;
+ padding: 1em
+} \ No newline at end of file
diff --git a/tools/auto_index/doc/students_t_eg_1.png b/tools/auto_index/doc/students_t_eg_1.png
new file mode 100644
index 0000000000..485f1f1b9a
--- /dev/null
+++ b/tools/auto_index/doc/students_t_eg_1.png
Binary files differ
diff --git a/tools/auto_index/doc/students_t_eg_2.png b/tools/auto_index/doc/students_t_eg_2.png
new file mode 100644
index 0000000000..8149dcb67b
--- /dev/null
+++ b/tools/auto_index/doc/students_t_eg_2.png
Binary files differ
diff --git a/tools/auto_index/doc/students_t_eg_3.png b/tools/auto_index/doc/students_t_eg_3.png
new file mode 100644
index 0000000000..6fa55c116b
--- /dev/null
+++ b/tools/auto_index/doc/students_t_eg_3.png
Binary files differ
diff --git a/tools/auto_index/doc/students_t_eg_4.png b/tools/auto_index/doc/students_t_eg_4.png
new file mode 100644
index 0000000000..6f651ecc1a
--- /dev/null
+++ b/tools/auto_index/doc/students_t_eg_4.png
Binary files differ
diff --git a/tools/auto_index/include/auto_index_helpers.qbk b/tools/auto_index/include/auto_index_helpers.qbk
new file mode 100644
index 0000000000..086c916308
--- /dev/null
+++ b/tools/auto_index/include/auto_index_helpers.qbk
@@ -0,0 +1,19 @@
+
+
+[template index[]
+'''<index/>'''
+]
+
+[template named_index[type title]
+'''<index type="'''[type]'''"><title>'''[title]'''</title></index>'''
+]
+
+[template AutoIndex [Args] '''<?BoostAutoIndex ''' [Args]'''?>''']
+
+[template indexterm1 [primary] '''<indexterm><primary>'''[primary]'''</primary></indexterm>''']
+[template indexterm2 [primary secondary] '''<indexterm><primary>'''[primary]'''</primary><secondary>'''[secondary]'''</secondary></indexterm>''']
+[template indexterm3 [primary secondary tertiary] '''<indexterm><primary>'''[primary]'''</primary><secondary>'''[secondary]'''</secondary><tertiary>'''[tertiary]'''</tertiary></indexterm>''']
+
+[template typed_indexterm1 [type primary] '''<indexterm type="'''[type]'''"><primary>'''[primary]'''</primary></indexterm>''']
+[template typed_indexterm2 [type primary secondary] '''<indexterm type="'''[type]'''"><primary>'''[primary]'''</primary><secondary>'''[secondary]'''</secondary></indexterm>''']
+[template typed_indexterm3 [type primary secondary tertiary] '''<indexterm type="'''[type]'''"><primary>'''[primary]'''</primary><secondary>'''[secondary]'''</secondary><tertiary>'''[tertiary]'''</tertiary></indexterm>''']
diff --git a/tools/auto_index/index.html b/tools/auto_index/index.html
new file mode 100644
index 0000000000..df7430bd0e
--- /dev/null
+++ b/tools/auto_index/index.html
@@ -0,0 +1,15 @@
+<html>
+ <head>
+ <meta http-equiv="refresh" content="0; URL=doc/html/index.html">
+ </head>
+ <body>
+ <P>
+ Automatic redirection failed, please go to <a href="doc/html/index.html">doc/html/index.html</a>.
+ </P>
+ <P>Copyright&nbsp;John Maddock 2001</P>
+ <P>Distributed under the Boost Software License, Version 1.0. (See accompanying file <A href="../../LICENSE_1_0.txt">
+ LICENSE_1_0.txt</A> or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</A>).</P>
+ </body>
+</html>
+
+
diff --git a/tools/auto_index/src/auto_index.cpp b/tools/auto_index/src/auto_index.cpp
new file mode 100644
index 0000000000..f108885c79
--- /dev/null
+++ b/tools/auto_index/src/auto_index.cpp
@@ -0,0 +1,778 @@
+// Copyright 2008 John Maddock
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <set>
+#include <cstring>
+#include <boost/array.hpp>
+#include <boost/exception/all.hpp>
+#include <boost/program_options.hpp>
+#include "auto_index.hpp"
+
+std::string infile, outfile, prefix, last_primary, last_secondary, last_tertiary;
+std::set<index_info> index_terms;
+std::set<std::pair<std::string, std::string> > found_terms;
+bool no_duplicates = false;
+bool verbose = false;
+bool use_section_names = true;
+index_entry_set index_entries;
+boost::tiny_xml::element_list indexes;
+std::list<id_rewrite_rule> id_rewrite_list;
+bool internal_indexes = false;
+std::string internal_index_type = "section";
+boost::regex debug;
+file_scanner_set_type file_scanner_set;
+
+int help()
+{
+ std::cout << "Please refer to the documentation for the correct command line syntax" << std::endl;
+ return 1;
+}
+
+void eat_block(std::string& result, std::istream & is)
+{
+ //
+ // everything until we get to a closing '>':
+ //
+ char c;
+ while(is.get(c) && c != '>')
+ {
+ result += c;
+ if(c == '\\')
+ {
+ is.get(c);
+ result += c;
+ }
+ }
+ result += c;
+}
+
+std::string get_header(std::istream & is)
+{
+ //
+ // We need to get any leading <? and <! elements:
+ //
+ std::string result;
+ is >> std::ws;
+ if(is.get() != '<')
+ throw std::runtime_error("Invalid leading markup in XML file found");
+ char c = is.peek();
+ while((c == '?') || (c == '!'))
+ {
+ std::string temp;
+ std::getline(is, temp, '>');
+ result += '<' + temp + '>';
+ is >> std::ws;
+ if(is.get() != '<')
+ throw std::runtime_error("Invalid leading markup in XML file found");
+ c = is.peek();
+ result += '\n';
+ }
+ return result;
+}
+//
+// Find attribute named "name" in node "node":
+//
+const std::string* find_attr(boost::tiny_xml::element_ptr node, const char* name)
+{
+ for(boost::tiny_xml::attribute_list::const_iterator i = node->attributes.begin();
+ i != node->attributes.end(); ++i)
+ {
+ if(i->name == name)
+ return &(i->value);
+ }
+ return 0;
+}
+//
+// Get the ID of the current block scope, basically
+// move up the XML tree until we find a valid ID:
+//
+const std::string* get_current_block_id(node_id const* id)
+{
+ while((id->id == 0) && (id->prev))
+ id = id->prev;
+ return id->id;
+}
+//
+// Get the title of the current block scope, basically
+// move up the XML tree until we find a valid title:
+//
+const std::string& get_current_block_title(title_info const* id)
+{
+ while((id->title.size() == 0) && (id->prev))
+ id = id->prev;
+ return id->title;
+}
+//
+// Get all the content under this node, with any inline XML
+// stripped out:
+//
+std::string get_consolidated_content(boost::tiny_xml::element_ptr node)
+{
+ std::string result(node->content);
+ for(boost::tiny_xml::element_list::const_iterator i = node->elements.begin();
+ i != node->elements.end(); ++i)
+ {
+ result += " ";
+ result += get_consolidated_content(*i);
+ }
+ static const boost::regex e("(^[[:space:]]+)|([[:space:]]+)|([[:space:]]+$)");
+ return regex_replace(result, e, "(?2 )", boost::regex_constants::format_all);
+}
+//
+// Rewrite a title based on any rewrite rules we may have:
+//
+std::string rewrite_title(const std::string& title, const std::string& id)
+{
+ for(std::list<id_rewrite_rule>::const_iterator i = id_rewrite_list.begin(); i != id_rewrite_list.end(); ++i)
+ {
+ if(i->base_on_id)
+ {
+ if(regex_match(id, i->id))
+ return i->new_name;
+ }
+ else
+ {
+ if(regex_match(title, i->id))
+ return regex_replace(title, i->id, i->new_name);
+ }
+ }
+ return title;
+}
+
+struct string_cmp
+{
+ bool operator()(const char* a, const char* b)const
+ {
+ return std::strcmp(a, b) < 0;
+ }
+};
+//
+// Discover whether this node can contain a <title> or not, if not
+// we don't want to link to it, or the XSL HTML stylesheets may do strange
+// things, and at least emit copious messages. See https://sourceforge.net/tracker/?func=detail&aid=3325153&group_id=21935&atid=373747
+//
+bool can_contain_title(const char* name)
+{
+ static const boost::array<const char*, 103> names =
+ { {
+ "abstract", "appendix", "appendixinfo", "article", "articleinfo", "authorblurb", "bibliodiv", "biblioentry", "bibliography",
+ "bibliographyinfo", "bibliolist", "bibliomixed", "bibliomset", "biblioset", "blockinfo", "blockquote", "book", "bookinfo",
+ "calloutlist", "caution", "chapter", "chapterinfo", "colophon", "constraintdef", "dedication", "equation", "example", "figure",
+ "formalpara", "glossary", "glossaryinfo", "glossdiv", "glosslist", "important", "index", "indexdiv", "indexinfo", "itemizedlist",
+ "legalnotice", "lot", "msg", "msgexplan", "msgmain", "msgrel", "msgset", "msgsub", "note", "objectinfo", "orderedlist", "part",
+ "partinfo", "partintro", "personblurb", "preface", "prefaceinfo", "procedure", "productionset", "qandadiv", "qandaset",
+ "refentryinfo", "reference", "referenceinfo", "refsect1", "refsect1info", "refsect2", "refsect2info", "refsect3", "refsect3info",
+ "refsection", "refsectioninfo", "refsynopsisdiv", "refsynopsisdivinfo", "sect1", "sect1info", "sect2", "sect2info", "sect3",
+ "sect3info", "sect4", "sect4info", "sect5", "sect5info", "section", "sectioninfo", "segmentedlist", "set", "setindex",
+ "setindexinfo", "setinfo", "sidebar", "sidebarinfo", "simplesect", "step", "table", "task", "taskprerequisites",
+ "taskrelated", "tasksummary", "tip", "toc", "variablelist", "warning", "refentry"
+ } };
+ static std::set<const char*, string_cmp> permitted;
+
+ if(permitted.empty())
+ permitted.insert(names.begin(), names.end());
+
+ return 0 != permitted.count(name);
+}
+//
+// Determine whether this node can contain an indexterm or not:
+//
+bool can_contain_indexterm(const char* name)
+{
+ static const boost::array<const char*, 257> names =
+ { {
+ "abbrev", "accel", "ackno", "acronym", "action", "answer", "appendix", "appendixinfo", "application",
+ "article", "articleinfo", "artpagenums", "attribution", "authorinitials", "bibliocoverage", "bibliodiv",
+ "biblioentry", "bibliography", "bibliographyinfo", "biblioid", "bibliomisc", "bibliomixed", "bibliomset",
+ "bibliorelation", "biblioset", "bibliosource", "blockinfo", "blockquote", "bookinfo", "bridgehead", "callout",
+ "caution", "chapter", "chapterinfo", "citation", "citebiblioid", "citetitle", "city", "classname", "classsynopsisinfo",
+ "code", "collabname", "command", "computeroutput", "confdates", "confnum", "confsponsor", "conftitle", "constant",
+ "constraintdef", "contractnum", "contractsponsor", "contrib", "corpauthor", "corpcredit", "corpname", "country",
+ "database", "date", "dedication", "edition", "email", "emphasis", "entry", "envar", "errorcode", "errorname", "errortext",
+ "errortype", "example", "exceptionname", "fax", "figure", "filename", "firstname", "firstterm", "foreignphrase",
+ "formalpara", "funcparams", "funcsynopsisinfo", "function", "glossary", "glossaryinfo", "glossdef", "glossdiv",
+ "glossentry", "glosssee", "glossseealso", "glossterm", "guibutton", "guiicon", "guilabel", "guimenu", "guimenuitem",
+ "guisubmenu", "hardware", "highlights", "holder", "honorific", "important", "index", "indexinfo", "informalexample",
+ "informalfigure", "initializer", "interface", "interfacename", "invpartnumber", "isbn", "issn", "issuenum", "itemizedlist",
+ "itermset", "jobtitle", "keycap", "keycode", "keysym", "label", "legalnotice", "lineage", "lineannotation",
+ /*"link", */"listitem", "literal", "literallayout", "lotentry", "manvolnum", "markup", "medialabel", "member",
+ "methodname", "modespec", "modifier", "mousebutton", "msgaud", "msgexplan", "msglevel", "msgorig", "msgtext", "note",
+ "objectinfo", "olink", "option", "optional", "orderedlist", "orgdiv", "orgname", "otheraddr", "othername", "package",
+ "pagenums", "para", "parameter", "partinfo", "partintro", "phone", "phrase", "pob", "postcode", "preface", "prefaceinfo",
+ "procedure", "productname", "productnumber", "programlisting", "prompt", "property", "pubdate", "publishername",
+ "pubsnumber", "qandadiv", "qandaset", "question", "quote", "refentry", "refentryinfo", "refentrytitle", "referenceinfo",
+ "refmeta", "refmiscinfo", "refpurpose", "refsect1", "refsect1info", "refsect2", "refsect2info", "refsect3", "refsect3info",
+ "refsection", "refsectioninfo", "refsynopsisdiv", "refsynopsisdivinfo", "releaseinfo", "remark", "returnvalue",
+ "revdescription", "revnumber", "revremark", "screen", "screeninfo", "sect1", "sect1info", "sect2", "sect2info", "sect3",
+ "sect3info", "sect4", "sect4info", "sect5", "sect5info", "section", "sectioninfo", "seg", "segtitle", "seriesvolnums",
+ "setindex", "setindexinfo", "setinfo", "sgmltag", "shortaffil", "sidebar", "sidebarinfo", "simpara", "simplesect",
+ "state", "step", "street", "structfield", "structname", "subtitle", "surname", "symbol", "synopsis", "systemitem",
+ "table", "task", "taskprerequisites", "taskrelated", "tasksummary", "td", "term", "termdef", "th", "tip", /*"title",*/
+ "titleabbrev", "tocback", "tocentry", "tocfront", "token", "type", "ulink", "uri", "userinput", "variablelist",
+ "varname", "volumenum", "warning", "wordasword", "year"
+ } };
+ static std::set<const char*, string_cmp> permitted;
+
+ if(permitted.empty())
+ permitted.insert(names.begin(), names.end());
+
+ return 0 != permitted.count(name);
+}
+//
+// Decide whether to flatten this node for searching purposes:
+//
+bool should_flatten_node(const char* name)
+{
+ //
+ // The list of nodes to flatten is basically the list of elements that
+ // can appear inside a <section> - see http://www.docbook.org/tdg/en/html/section.html.
+ // In other words basically anything at the level of a paragraph/table/listing etc.
+ //
+ static const boost::array<const char*, 57> names =
+ { {
+ "title", "subtitle", "titleabbrev",
+ "toc", "lot", "glossary", "bibliography",
+ /*"calloutlist", "glosslist", "bibliolist", "itemizedlist", "orderedlist",
+ "segmentedlist", "simplelist", "variablelist",*/ "caution", "important", "note",
+ "tip", "warning", "literallayout", "programlisting", "programlistingco",
+ "screen", "screenco", "screenshot", "synopsis", "cmdsynopsis", "funcsynopsis",
+ "classsynopsis", "fieldsynopsis", "constructorsynopsis",
+ "destructorsynopsis", "methodsynopsis", "formalpara", "para", "simpara",
+ "address", "blockquote", "graphic", "graphicco", "mediaobject",
+ "mediaobjectco", "informalequation", "informalexample", "informalfigure",
+ "informaltable", "equation", "example", "figure", "table", "msgset", "procedure",
+ "sidebar", "qandaset", "task", "productionset", "constraintdef", "anchor",
+ "bridgehead", "remark", "highlights", "abstract", "authorblurb", "epigraph"
+ /*"biblioentry", "bibliomixed", "callout", "glossentry", "listitem", "seg", "seglistitem", "member",
+ "term", */
+ } };
+ static std::set<const char*, string_cmp> terminals;
+
+ if(terminals.empty())
+ terminals.insert(names.begin(), names.end());
+ return 0 != terminals.count(name);
+}
+std::string unescape_xml(const std::string& s)
+{
+ boost::regex e("&(?:(quot)|(amp)|(apos)|(lt)|(gt));");
+ return regex_replace(s, e, "(?1\")(?2&)(?3\')(?4<)(?5>)", boost::regex_constants::format_all);
+}
+//
+// Exception classes to propagate processing instruction info:
+//
+struct ignore_section{};
+struct ignore_block{};
+//
+// Check if we're in a section (or chapter etc) or not:
+//
+bool is_section(const std::string& name)
+{
+ static const boost::array<const char*, 19> data =
+ {{
+ "dedication", "toc", "lot", "glossary", "bibliography", "preface", "chapter",
+ "reference", "part", "article", "appendix", "index", "setindex", "colophon",
+ "sect1", "refentry", "simplesect", "section", "partintro"
+ }};
+ std::set<std::string> names;
+ if(names.empty())
+ names.insert(data.begin(), data.end());
+ return 0 != names.count(name);
+}
+//
+// Check if we're in a block/paragraph or not:
+//
+bool is_block(const std::string& name)
+{
+ static const boost::array<const char*, 58> data =
+ {{
+ "calloutlist", "glosslist", "bibliolist", "itemizedlist", "orderedlist",
+ "segmentedlist", "simplelist", "variablelist", "caution", "important", "note",
+ "tip", "warning", "literallayout", "programlisting", "programlistingco",
+ "screen", "screenco", "screenshot", "synopsis", "cmdsynopsis", "funcsynopsis",
+ "classsynopsis", "fieldsynopsis", "constructorsynopsis",
+ "destructorsynopsis", "methodsynopsis", "formalpara", "para", "simpara",
+ "address", "blockquote", "graphic", "graphicco", "mediaobject",
+ "mediaobjectco", "informalequation", "informalexample", "informalfigure",
+ "informaltable", "equation", "example", "figure", "table", "msgset", "procedure",
+ "sidebar", "qandaset", "task", "productionset", "constraintdef", "anchor",
+ "bridgehead", "remark", "highlights", "abstract", "authorblurb", "epigraph"
+ }};
+ std::set<std::string> names;
+ if(names.empty())
+ names.insert(data.begin(), data.end());
+ return 0 != names.count(name);
+}
+//
+// Helper proc to recurse through children:
+//
+void process_node(boost::tiny_xml::element_ptr node, node_id* prev, title_info* pt, bool seen);
+bool recurse_through_children(boost::tiny_xml::element_ptr node, node_id* id, title_info* pt, bool seen)
+{
+ try
+ {
+ for(boost::tiny_xml::element_list::const_iterator i = node->elements.begin();
+ i != node->elements.end(); ++i)
+ {
+ process_node(*i, id, pt, seen);
+ }
+ }
+ catch(const ignore_section&)
+ {
+ if(is_section(node->name))
+ return false;
+ else
+ throw;
+ }
+ catch(const ignore_block&)
+ {
+ if(is_block(node->name) || is_section(node->name))
+ return false;
+ else
+ throw;
+ }
+ return true;
+}
+//
+// This does most of the work: process the node pointed to, and any children
+// that it may have:
+//
+void process_node(boost::tiny_xml::element_ptr node, node_id* prev, title_info* pt, bool seen = false)
+{
+ //
+ // Store the current ID and title as nested scoped objects:
+ //
+ node_id id = { 0, prev };
+ if(can_contain_title(node->name.c_str()))
+ {
+ // Only set the ID to link to if the block can contain a title, see
+ // can_contain_title above for rationale.
+ id.id = find_attr(node, "id");
+ }
+ title_info title = { "", pt};
+ bool flatten = should_flatten_node(node->name.c_str());
+
+ if(node->name.size() && node->name[0] == '?')
+ {
+ if(node->name == "?BoostAutoIndex")
+ {
+ if(node->content == "IgnoreSection")
+ {
+ throw ignore_section();
+ }
+ else if(node->content == "IgnoreBlock")
+ {
+ throw ignore_block();
+ }
+ }
+ return; // Ignore processing instructions
+ }
+ else if((node->name == "title") && (id.prev->id))
+ {
+ //
+ // This actually sets the title of the enclosing scope,
+ // not this tag itself:
+ //
+ title.prev->title = get_consolidated_content(node);
+ if(verbose)
+ std::cout << "Indexing section: " << title.prev->title << std::endl;
+ }
+ else if((node->name == "refentrytitle") && (id.prev->prev->id))
+ {
+ //
+ // This actually sets the title of the enclosing refentry scope,
+ // not this tag itself:
+ //
+ title.prev->prev->title = get_consolidated_content(node);
+ if(verbose)
+ std::cout << "Indexing refentry: " << title.prev->prev->title << std::endl;
+ }
+ if(node->name == "anchor")
+ {
+ if(node->parent.lock()->name == "title")
+ {
+ // We have a title with a nested anchor ID, change the ID of our parents parent to match:
+ id.prev->prev->id = id.id;
+ }
+ }
+ else if(node->name == "index")
+ {
+ // Keep track of all the indexes we see:
+ indexes.push_back(node);
+ if(node->parent.lock()->name == "para")
+ node->parent.lock()->name = "";
+ }
+ else if(node->name == "primary")
+ {
+ last_primary = get_consolidated_content(node);
+ }
+ else if(node->name == "secondary")
+ {
+ last_secondary = get_consolidated_content(node);
+ }
+ else if(node->name == "tertiary")
+ {
+ last_tertiary = get_consolidated_content(node);
+ }
+ else if((node->name == "see") && internal_indexes)
+ {
+ std::cerr << "WARNING: <see> in XML source will be ignored for the index generation" << std::endl;
+ }
+ else if((node->name == "seealso") && internal_indexes)
+ {
+ std::cerr << "WARNING: <seealso> in XML source will be ignored for the index generation" << std::endl;
+ }
+
+ std::string flattenned_text;
+ const std::string* ptext;
+ if(flatten)
+ {
+ flattenned_text = unescape_xml(get_consolidated_content(node));
+ ptext = &flattenned_text;
+ //
+ // Recurse through children here if we're going to flatten the text, that way we see any processing instructions first:
+ //
+ if(!recurse_through_children(node, &id, &title, flatten || seen))
+ return;
+ }
+ else
+ {
+ ptext = &(node->content);
+ }
+
+ //
+ // Search content for items: we only search if the content is not empty,
+ // and the content is not whitespace alone, and we haven't already searched this
+ // text in one of our parent nodes that got flattened.
+ //
+ static const boost::regex space_re("[[:space:]]+");
+ if(!seen && ptext->size() && !regex_match(*ptext, space_re))
+ {
+ // Save block ID and title in case we find some hits:
+ const std::string* pid = get_current_block_id(&id);
+ const std::string& rtitle = get_current_block_title(&title);
+ const std::string simple_title = rewrite_title(rtitle, *pid);
+ // Scan for each index term:
+ for(std::set<index_info>::const_iterator i = index_terms.begin();
+ i != index_terms.end(); ++i)
+ {
+ if(regex_search(*ptext, i->search_text))
+ {
+ //
+ // We need to check to see if this term has already been indexed
+ // in this zone, in order to prevent duplicate entries, also check
+ // that any constrait placed on the term's ID is satisfied:
+ //
+ std::pair<std::string, std::string> item_index(*pid, i->term);
+ if(((no_duplicates == false) || (0 == found_terms.count(item_index)))
+ && (i->search_id.empty() || regex_match(*pid, i->search_id)))
+ {
+ // We have something to index!
+ found_terms.insert(item_index);
+
+ if(!debug.empty() && (regex_match(i->term, debug) || regex_match(rtitle, debug) || regex_match(simple_title, debug)))
+ {
+ std::cout << "Debug term found, in block with ID: " << *pid << std::endl;
+ std::cout << "Current section title is: " << rtitle << std::endl;
+ std::cout << "The main index entry will be : " << simple_title << std::endl;
+ std::cout << "The indexed term is: " << i->term << std::endl;
+ std::cout << "The search regex is: " << i->search_text << std::endl;
+ std::cout << "The section constraint is: " << i->search_id << std::endl;
+ std::cout << "The index type for this entry is: " << i->category << std::endl;
+ }
+
+ if(use_section_names && (simple_title != i->term))
+ {
+ //
+ // First off insert index entry with primary term
+ // consisting of the section title, and secondary term the
+ // actual index term, this gets skipped if the title and index
+ // term are the same:
+ //
+ if(internal_indexes == false)
+ {
+ // Insert an <indexterm> into the XML:
+ boost::tiny_xml::element_ptr p(new boost::tiny_xml::element());
+ p->name = "indexterm";
+ boost::tiny_xml::element_ptr prim(new boost::tiny_xml::element());
+ prim->name = "primary";
+ prim->elements.push_front(boost::tiny_xml::element_ptr(new boost::tiny_xml::element()));
+ prim->elements.front()->content = simple_title;
+ p->elements.push_front(prim);
+
+ boost::tiny_xml::element_ptr sec(new boost::tiny_xml::element());
+ sec->name = "secondary";
+ sec->elements.push_front(boost::tiny_xml::element_ptr(new boost::tiny_xml::element()));
+ sec->elements.front()->content = i->term;
+ p->elements.push_back(sec);
+ try{
+ // Insert the Indexterm:
+ boost::tiny_xml::element_ptr parent(node->parent);
+ while(!can_contain_indexterm(parent->name.c_str()))
+ parent = parent->parent.lock();
+ parent->elements.push_front(p);
+ }
+ catch(const std::exception&)
+ {
+ std::cerr << "Unable to find location to insert <indexterm>" << std::endl;
+ }
+ }
+ // Track the entry in our internal index:
+ index_entry_ptr item1(new index_entry(simple_title));
+ index_entry_ptr item2(new index_entry(i->term, *pid));
+ index_entry_set::iterator pos = index_entries.insert(item1).first;
+ (**pos).sub_keys.insert(item2);
+ }
+ //
+ // Now insert another index entry with the index term
+ // as the primary key, and the section title as the
+ // secondary key, this one gets assigned to the
+ // appropriate index category if there is one:
+ //
+ bool preferred_term = false;
+ if(internal_indexes == false)
+ {
+ // Insert <indexterm> into the XML:
+ boost::tiny_xml::element_ptr p2(new boost::tiny_xml::element());
+ p2->name = "indexterm";
+ if(i->category.size())
+ {
+ p2->attributes.push_back(boost::tiny_xml::attribute("type", i->category));
+ }
+ boost::tiny_xml::element_ptr prim2(new boost::tiny_xml::element());
+ prim2->name = "primary";
+ prim2->elements.push_front(boost::tiny_xml::element_ptr(new boost::tiny_xml::element()));
+ prim2->elements.front()->content = i->term;
+ p2->elements.push_front(prim2);
+
+ boost::tiny_xml::element_ptr sec2(new boost::tiny_xml::element());
+ sec2->name = "secondary";
+ sec2->elements.push_front(boost::tiny_xml::element_ptr(new boost::tiny_xml::element()));
+ sec2->elements.front()->content = rtitle;
+ p2->elements.push_back(sec2);
+ try{
+ // Insert the Indexterm:
+ boost::tiny_xml::element_ptr parent(node->parent);
+ while(!can_contain_indexterm(parent->name.c_str()))
+ {
+ // If the search text was found in a title then make it a preferred term:
+ if(parent->name == "title")
+ preferred_term = true;
+ parent = parent->parent.lock();
+ }
+ if(preferred_term)
+ {
+ boost::tiny_xml::attribute a("significance", "preferred");
+ p2->attributes.push_back(a);
+ }
+ parent->elements.push_front(p2);
+ }
+ catch(const std::exception&)
+ {
+ std::cerr << "Unable to find location to insert <indexterm>" << std::endl;
+ }
+ }
+
+ // Track the entry in our internal index:
+ try{
+ // figure out if it's preferred or not:
+ boost::tiny_xml::element_ptr parent(node->parent);
+ while(!can_contain_indexterm(parent->name.c_str()))
+ {
+ // If the search text was found in a title then make it a preferred term:
+ if(parent->name == "title")
+ {
+ preferred_term = true;
+ }
+ parent = parent->parent.lock();
+ }
+ }
+ catch(const std::exception&){}
+
+ index_entry_ptr item3(new index_entry(i->term));
+ if(i->category.size())
+ item3->category = i->category;
+ index_entry_ptr item4(new index_entry(rtitle, *pid));
+ item4->preferred = preferred_term;
+ index_entry_set::iterator pos = index_entries.insert(item3).first;
+ (**pos).sub_keys.insert(item4);
+ }
+ }
+ }
+ }
+ //
+ // Recurse through children, if not done already:
+ //
+ if(!flatten)
+ recurse_through_children(node, &id, &title, flatten || seen);
+ //
+ // Process manual index entries last of all:
+ //
+ if(node->name == "indexterm")
+ {
+ // Track the entry in our internal index:
+ const std::string* pid = get_current_block_id(&id);
+ const std::string* attr = find_attr(node, "type");
+ const std::string& rtitle = get_current_block_title(&title);
+ const std::string simple_title = rewrite_title(rtitle, *pid);
+ index_entry_ptr item1(new index_entry(last_primary, "", attr ? *attr : ""));
+ index_entry_set* parent = &((*index_entries.insert(item1).first)->sub_keys);
+
+ if(last_secondary.size())
+ {
+ item1.reset(new index_entry(last_secondary, "", attr ? *attr : ""));
+ parent = &((*parent->insert(item1).first)->sub_keys);
+ }
+ if(last_tertiary.size())
+ {
+ item1.reset(new index_entry(last_tertiary, "", attr ? *attr : ""));
+ parent = &((*parent->insert(item1).first)->sub_keys);
+ }
+ item1.reset(new index_entry(simple_title, *pid, attr ? *attr : ""));
+ parent->insert(item1);
+
+ last_primary = "";
+ last_secondary = "";
+ last_tertiary = "";
+ }
+}
+
+void process_nodes(boost::tiny_xml::element_ptr node)
+{
+ node_id id = { 0, };
+ title_info t = { "", 0 };
+ process_node(node, &id, &t);
+}
+
+int main(int argc, char* argv[])
+{
+ try{
+
+ namespace po = boost::program_options;
+ po::options_description desc("AutoIndex Allowed Options");
+ desc.add_options()
+ ("help", "Print help message")
+ ("in", po::value<std::string>(), "Set the input XML file.")
+ ("out", po::value<std::string>(), "Set output input XML file.")
+ ("scan", po::value<std::string>(), "Scan the specified file for terms to try and index.")
+ ("script", po::value<std::string>(), "Specifies the script file to use.")
+ ("no-duplicates", "Prevents duplicate index entries within the same section.")
+ ("no-section-names", "Suppresses use of section names as index entries.")
+ ("internal-index", "Causes AutoIndex to generate the index itself, rather than relying on the XSL stylesheets.")
+ ("verbose", "Turns on verbose mode.")
+ ("prefix", po::value<std::string>(), "Sets the prefix to be prepended to all file names and paths in the script file.")
+ ("index-type", po::value<std::string>(), "Sets the XML container type to use the index.")
+ ;
+
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //
+ // Process arguments:
+ //
+ if(vm.count("help"))
+ {
+ std::cout << desc;
+ return 0;
+ }
+ if(vm.count("in"))
+ {
+ infile = vm["in"].as<std::string>();
+ }
+ else
+ {
+ std::cerr << "No input XML file specified" << std::endl;
+ return 1;
+ }
+ if(vm.count("out"))
+ {
+ outfile = vm["out"].as<std::string>();
+ }
+ else
+ {
+ std::cerr << "No output XML file specified" << std::endl;
+ return 1;
+ }
+ if(vm.count("verbose"))
+ {
+ verbose = true;
+ }
+ if(vm.count("prefix"))
+ {
+ prefix = vm["prefix"].as<std::string>();
+ }
+ if(vm.count("scan"))
+ {
+ std::string f = vm["scan"].as<std::string>();
+ if(!exists(boost::filesystem::path(f)))
+ throw std::runtime_error("Error the file requested for scanning does not exist: " + f);
+ scan_file(f);
+ }
+ if(vm.count("script"))
+ {
+ process_script(vm["script"].as<std::string>());
+ }
+ if(vm.count("no-duplicates"))
+ {
+ no_duplicates = true;
+ }
+ if(vm.count("no-section-names"))
+ {
+ use_section_names = false;
+ }
+ if(vm.count("internal-index"))
+ {
+ internal_indexes = true;
+ }
+ if(vm.count("index-type"))
+ {
+ internal_index_type = vm["index-type"].as<std::string>();
+ }
+
+ std::ifstream is(infile.c_str());
+ if((0 == is.peek()) || !is.good())
+ {
+ std::cerr << "Unable to open XML data file " << argv[1] << std::endl;
+ return 1;
+ }
+ //
+ // We need to skip any leading <? and <! elements:
+ //
+ std::string header = get_header(is);
+ boost::tiny_xml::element_ptr xml = boost::tiny_xml::parse(is, "");
+ is.close();
+
+ std::cout << "Indexing " << index_terms.size() << " terms..." << std::endl;
+
+ process_nodes(xml);
+
+ if(internal_indexes)
+ generate_indexes();
+
+ std::ofstream os(outfile.c_str());
+ os << header << std::endl;
+ boost::tiny_xml::write(*xml, os);
+ std::cout << index_entries.size() << " Index entries were created." << std::endl;
+
+ }
+ catch(boost::exception& e)
+ {
+ std::cerr << diagnostic_information(e);
+ }
+ catch(const std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ return 1;
+ }
+ catch(const std::string& s)
+ {
+ std::cerr << s << std::endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/tools/auto_index/src/auto_index.hpp b/tools/auto_index/src/auto_index.hpp
new file mode 100644
index 0000000000..255b8575f5
--- /dev/null
+++ b/tools/auto_index/src/auto_index.hpp
@@ -0,0 +1,137 @@
+// Copyright 2008 John Maddock
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_AUTO_INDEX_HPP
+#define BOOST_AUTO_INDEX_HPP
+
+#include <boost/version.hpp>
+
+#if BOOST_VERSION < 104400
+# error "This tool requires Boost 1.44 or later to build."
+#endif
+
+#define BOOST_FILESYSTEM_VERSION 3
+
+#include "tiny_xml.hpp"
+#include <boost/regex.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string/case_conv.hpp>
+#include <fstream>
+#include <cctype>
+#include <map>
+#include <set>
+#include <sstream>
+
+struct index_info
+{
+ std::string term; // The term goes in the index entry
+ boost::regex search_text; // What to search for when indexing the term.
+ boost::regex search_id; // What id's this term may be indexed in.
+ std::string category; // Index category (function, class, macro etc).
+};
+inline bool operator < (const index_info& a, const index_info& b)
+{
+ return (a.term != b.term) ? (a.term < b.term) : (a.category < b.category);
+}
+
+
+struct index_entry;
+typedef boost::shared_ptr<index_entry> index_entry_ptr;
+bool operator < (const index_entry_ptr& a, const index_entry_ptr& b);
+typedef std::set<index_entry_ptr> index_entry_set;
+
+struct index_entry
+{
+ std::string key; // The index term.
+ std::string sort_key; // upper case version of term used for sorting.
+ std::string id; // The id of the block that we will link to.
+ std::string category; // The category of this entry (function, class, macro etc).
+ index_entry_set sub_keys; // All our sub-keys.
+ bool preferred; // This entry is the preferred one for this key
+
+ index_entry() : preferred(false) {}
+ index_entry(const std::string& k) : key(k), sort_key(k), preferred(false) { boost::to_upper(sort_key); }
+ index_entry(const std::string& k, const std::string& i) : key(k), sort_key(k), id(i), preferred(false) { boost::to_upper(sort_key); }
+ index_entry(const std::string& k, const std::string& i, const std::string& c) : key(k), sort_key(k), id(i), category(c), preferred(false) { boost::to_upper(sort_key); }
+};
+
+
+inline bool operator < (const index_entry_ptr& a, const index_entry_ptr& b)
+{
+ return ((a->sort_key != b->sort_key) ? (a->sort_key < b->sort_key) : (a->category < b->category));
+}
+
+struct id_rewrite_rule
+{
+ bool base_on_id; // rewrite the title if "id" matches the section id, otherwise rewrite if title matches "id".
+ boost::regex id; // regex for the id or title to match
+ std::string new_name; // either literal string or format string for the new name.
+
+ id_rewrite_rule(const std::string& i, const std::string& n, bool b)
+ : base_on_id(b), id(i), new_name(n) {}
+};
+
+struct node_id
+{
+ const std::string* id;
+ node_id* prev;
+};
+
+struct title_info
+{
+ std::string title;
+ title_info* prev;
+};
+
+struct file_scanner
+{
+ boost::regex scanner, file_name_filter, section_filter;
+ std::string format_string, type, term_formatter;
+};
+
+inline bool operator < (const file_scanner & a, const file_scanner& b)
+{
+ return a.type < b.type;
+}
+
+typedef std::multiset<file_scanner> file_scanner_set_type;
+
+void process_script(const std::string& script);
+void scan_dir(const std::string& dir, const std::string& mask, bool recurse);
+void scan_file(const std::string& file);
+void generate_indexes();
+const std::string* find_attr(boost::tiny_xml::element_ptr node, const char* name);
+
+extern file_scanner_set_type file_scanner_set;
+
+inline void add_file_scanner(const std::string& type, const std::string& scanner, const std::string& format, const std::string& term_formatter, const std::string& id_filter, const std::string& file_filter)
+{
+ file_scanner s;
+ s.type = type;
+ s.scanner = scanner;
+ s.format_string = format;
+ s.term_formatter = term_formatter;
+ if(file_filter.size())
+ s.file_name_filter = file_filter;
+ if(id_filter.size())
+ s.section_filter = id_filter;
+ file_scanner_set.insert(s);
+}
+
+extern std::set<index_info> index_terms;
+extern std::set<std::pair<std::string, std::string> > found_terms;
+extern bool no_duplicates;
+extern bool verbose;
+extern index_entry_set index_entries;
+extern boost::tiny_xml::element_list indexes;
+extern std::list<id_rewrite_rule> id_rewrite_list;
+extern bool internal_indexes;
+extern std::string prefix;
+extern std::string internal_index_type;
+extern boost::regex debug;
+
+#endif
diff --git a/tools/auto_index/src/file_scanning.cpp b/tools/auto_index/src/file_scanning.cpp
new file mode 100644
index 0000000000..c129db7ab8
--- /dev/null
+++ b/tools/auto_index/src/file_scanning.cpp
@@ -0,0 +1,495 @@
+// Copyright 2008 John Maddock
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "auto_index.hpp"
+
+bool need_defaults = true;
+
+void install_default_scanners()
+{
+ need_defaults = false;
+ //
+ // Set the default scanners if they're not defined already:
+ //
+ file_scanner s;
+ s.type = "class_name";
+ if(file_scanner_set.find(s) == file_scanner_set.end())
+ {
+ add_file_scanner(
+ "class_name", // Index type
+ // Header file scanner regex:
+ // possibly leading whitespace:
+ "^[[:space:]]*"
+ // possible template declaration:
+ "(template[[:space:]]*<[^;:{]+>[[:space:]]*)?"
+ // class or struct:
+ "(class|struct)[[:space:]]*"
+ // leading declspec macros etc:
+ "("
+ "\\<\\w+\\>"
+ "("
+ "[[:blank:]]*\\([^)]*\\)"
+ ")?"
+ "[[:space:]]*"
+ ")*"
+ // the class name
+ "(\\<\\w*\\>)[[:space:]]*"
+ // template specialisation parameters
+ "(<[^;:{]+>)?[[:space:]]*"
+ // terminate in { or :
+ "(\\{|:[^;\\{()]*\\{)",
+
+ "(?:class|struct)[^;{]+\\\\<\\5\\\\>[^;{]+\\\\{", // Format string to create indexing regex.
+ "\\5", // Format string to create index term.
+ "", // Filter regex for section id's.
+ "" // Filter regex for filenames.
+ );
+ }
+
+ s.type = "typedef_name";
+ if(file_scanner_set.find(s) == file_scanner_set.end())
+ {
+ add_file_scanner(
+ "typedef_name", // Index type
+ "typedef[^;{}#]+?(\\w+)\\s*;", // scanner regex
+ "typedef[^;]+\\\\<\\1\\\\>\\\\s*;", // Format string to create indexing regex.
+ "\\1", // Format string to create index term.
+ "", // Filter regex for section id's.
+ "" // Filter regex for filenames.
+ );
+ }
+
+ s.type = "macro_name";
+ if(file_scanner_set.find(s) == file_scanner_set.end())
+ {
+ add_file_scanner(
+ "macro_name", // Index type
+ "^\\s*#\\s*define\\s+(\\w+)", // scanner regex
+ "\\\\<\\1\\\\>", // Format string to create indexing regex.
+ "\\1", // Format string to create index term.
+ "", // Filter regex for section id's.
+ "" // Filter regex for filenames.
+ );
+ }
+
+ s.type = "function_name";
+ if(file_scanner_set.find(s) == file_scanner_set.end())
+ {
+ add_file_scanner(
+ "function_name", // Index type
+ "\\w+(?:\\s*<[^>]>)?[\\s&*]+?(\\w+)\\s*(?:BOOST_[[:upper:]_]+\\s*)?\\([^\\)]*\\)\\s*[;{]", // scanner regex
+ "\\\\<\\\\w+\\\\>(?:\\\\s+<[^>]*>)?[\\\\s&*]+\\\\<\\1\\\\>\\\\s*\\\\([^;{]*\\\\)", // Format string to create indexing regex.
+ "\\1", // Format string to create index term.
+ "", // Filter regex for section id's.
+ "" // Filter regex for filenames.
+ );
+ }
+}
+
+//
+// Helper to dump file contents into a std::string:
+//
+void load_file(std::string& s, std::istream& is)
+{
+ s.erase();
+ if(is.bad()) return;
+ s.reserve(is.rdbuf()->in_avail());
+ char c;
+ while(is.get(c))
+ {
+ if(s.capacity() == s.size())
+ s.reserve(s.capacity() * 3);
+ s.append(1, c);
+ }
+}
+//
+// Helper to convert string from external source into valid XML:
+//
+std::string escape_to_xml(const std::string& in)
+{
+ std::string result;
+ for(std::string::size_type i = 0; i < in.size(); ++i)
+ {
+ switch(in[i])
+ {
+ case '&':
+ result.append("&amp;");
+ break;
+ case '<':
+ result.append("&lt;");
+ break;
+ case '>':
+ result.append("&gt;");
+ break;
+ case '"':
+ result.append("&quot;");
+ break;
+ default:
+ result.append(1, in[i]);
+ }
+ }
+ return result;
+}
+//
+// Scan a source file for things to index:
+//
+void scan_file(const std::string& file)
+{
+ if(need_defaults)
+ install_default_scanners();
+ if(verbose)
+ std::cout << "Scanning file... " << file << std::endl;
+ std::string text;
+ std::ifstream is(file.c_str());
+ if(!is.peek() || !is.good())
+ throw std::runtime_error(std::string("Unable to read from file: ") + file);
+ load_file(text, is);
+
+ for(file_scanner_set_type::iterator pscan = file_scanner_set.begin(); pscan != file_scanner_set.end(); ++pscan)
+ {
+ bool need_debug = false;
+ if(!debug.empty() && regex_match(pscan->type, ::debug))
+ {
+ need_debug = true;
+ std::cout << "Processing scanner " << pscan->type << " on file " << file << std::endl;
+ std::cout << "Scanner regex:" << pscan->scanner << std::endl;
+ std::cout << "Scanner formatter (search regex):" << pscan->format_string << std::endl;
+ std::cout << "Scanner formatter (index term):" << pscan->term_formatter << std::endl;
+ std::cout << "Scanner file name filter:" << pscan->file_name_filter << std::endl;
+ std::cout << "Scanner section id filter:" << pscan->section_filter << std::endl;
+ }
+ if(!pscan->file_name_filter.empty())
+ {
+ if(!regex_match(file, pscan->file_name_filter))
+ {
+ if(need_debug)
+ {
+ std::cout << "File failed to match file name filter, this file will be skipped..." << std::endl;
+ }
+ continue; // skip this file
+ }
+ }
+ if(verbose && !need_debug)
+ std::cout << "Scanning for type \"" << (*pscan).type << "\" ... " << std::endl;
+ boost::sregex_iterator i(text.begin(), text.end(), (*pscan).scanner), j;
+ while(i != j)
+ {
+ try
+ {
+ index_info info;
+ info.term = escape_to_xml(i->format(pscan->term_formatter));
+ info.search_text = i->format(pscan->format_string);
+ info.category = pscan->type;
+ if(!pscan->section_filter.empty())
+ info.search_id = pscan->section_filter;
+ std::pair<std::set<index_info>::iterator, bool> pos = index_terms.insert(info);
+ if(pos.second)
+ {
+ if(verbose || need_debug)
+ std::cout << "Indexing " << info.term << " as type " << info.category << std::endl;
+ if(need_debug)
+ std::cout << "Search regex will be: \"" << info.search_text << "\"" <<
+ " ID constraint is: \"" << info.search_id << "\""
+ << "Found text was: " << i->str() << std::endl;
+ if(pos.first->search_text != info.search_text)
+ {
+ //
+ // Merge the search terms:
+ //
+ const_cast<boost::regex&>(pos.first->search_text) =
+ "(?:" + pos.first->search_text.str() + ")|(?:" + info.search_text.str() + ")";
+ }
+ if(pos.first->search_id != info.search_id)
+ {
+ //
+ // Merge the ID constraints:
+ //
+ const_cast<boost::regex&>(pos.first->search_id) =
+ "(?:" + pos.first->search_id.str() + ")|(?:" + info.search_id.str() + ")";
+ }
+ }
+ }
+ catch(const boost::regex_error& e)
+ {
+ std::cerr << "Unable to create regular expression from found index term:\""
+ << i->format(pscan->term_formatter) << "\" In file " << file << std::endl;
+ std::cerr << e.what() << std::endl;
+ }
+ catch(const std::exception& e)
+ {
+ std::cerr << "Unable to create index term:\""
+ << i->format(pscan->term_formatter) << "\" In file " << file << std::endl;
+ std::cerr << e.what() << std::endl;
+ throw;
+ }
+ ++i;
+ }
+ }
+}
+//
+// Scan a whole directory for files to search:
+//
+void scan_dir(const std::string& dir, const std::string& mask, bool recurse)
+{
+ using namespace boost::filesystem;
+ boost::regex e(mask);
+ directory_iterator i(dir), j;
+
+ while(i != j)
+ {
+ if(regex_match(i->path().filename().string(), e))
+ {
+ scan_file(i->path().string());
+ }
+ else if(recurse && is_directory(i->status()))
+ {
+ scan_dir(i->path().string(), mask, recurse);
+ }
+ ++i;
+ }
+}
+//
+// Remove quotes from a string:
+//
+std::string unquote(const std::string& s)
+{
+ std::string result(s);
+ if((s.size() >= 2) && (*s.begin() == '\"') && (*s.rbegin() == '\"'))
+ {
+ result.erase(result.begin());
+ result.erase(result.end() - 1);
+ }
+ return result;
+}
+//
+// Load and process a script file:
+//
+void process_script(const std::string& script)
+{
+ static const boost::regex comment_parser(
+ "\\s*(?:#.*)?$"
+ );
+ static const boost::regex scan_parser(
+ "!scan[[:space:]]+"
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")\\s*"
+ );
+ static const boost::regex scan_dir_parser(
+ "!scan-path[[:space:]]+"
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")"
+ "[[:space:]]+"
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")"
+ "(?:"
+ "[[:space:]]+"
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")"
+ ")?\\s*"
+ );
+ static const boost::regex entry_parser(
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")"
+ "(?:"
+ "[[:space:]]+"
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)*\")"
+ "(?:"
+ "[[:space:]]+"
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)*\")"
+ "(?:"
+ "[[:space:]]+"
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)*\")"
+ ")?"
+ ")?"
+ ")?"
+ "[[:space:]]*");
+ static const boost::regex rewrite_parser(
+ "!(rewrite-name|rewrite-id)\\s+"
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")\\s+"
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")\\s*"
+ );
+ static const boost::regex debug_parser(
+ "!debug\\s+"
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")\\s*"
+ );
+ static const boost::regex define_scanner_parser(
+ "!define-scanner\\s+"
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")\\s+" // type, index 1
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")\\s+" // scanner regex, index 2
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")\\s+" // format string, index 3
+ "([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")" // format string for name, index 4
+ "(?:"
+ "\\s+([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")" // id-filter, index 5
+ "(?:"
+ "\\s+([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")" // filename-filter, index 6
+ ")?"
+ ")?"
+ "\\s*"
+ );
+ static const boost::regex error_parser("!.*");
+
+ if(verbose)
+ std::cout << "Processing script " << script << std::endl;
+ boost::smatch what;
+ std::string line;
+ std::ifstream is(script.c_str());
+ if(is.bad() || !exists(boost::filesystem::path(script)))
+ {
+ throw std::runtime_error(std::string("Could not open script file: ") + script);
+ }
+ while(std::getline(is, line).good())
+ {
+ if(regex_match(line, what, comment_parser))
+ {
+ // Nothing to do here...
+ }
+ else if(regex_match(line, what, scan_parser))
+ {
+ std::string f = unquote(what[1].str());
+ if(!boost::filesystem::path(f).is_complete())
+ {
+ if(prefix.size())
+ {
+ boost::filesystem::path base(prefix);
+ base /= f;
+ f = base.string();
+ }
+ else
+ {
+ boost::filesystem::path base(script);
+ base.remove_filename();
+ base /= f;
+ f = base.string();
+ }
+ }
+ if(!exists(boost::filesystem::path(f)))
+ throw std::runtime_error("Error the file requested for scanning does not exist: " + f);
+ scan_file(f);
+ }
+ else if(regex_match(line, what, debug_parser))
+ {
+ debug = unquote(what[1].str());
+ }
+ else if(regex_match(line, what, define_scanner_parser))
+ {
+ add_file_scanner(unquote(what.str(1)), unquote(what.str(2)), unquote(what.str(3)),
+ unquote(what.str(4)), unquote(what.str(5)), unquote(what.str(6)));
+ }
+ else if(regex_match(line, what, scan_dir_parser))
+ {
+ std::string d = unquote(what[1].str());
+ std::string m = unquote(what[2].str());
+ bool r = unquote(what[3].str()) == "true";
+ if(!boost::filesystem::path(d).is_complete())
+ {
+ if(prefix.size())
+ {
+ boost::filesystem::path base(prefix);
+ base /= d;
+ d = base.string();
+ }
+ else
+ {
+ boost::filesystem::path base(script);
+ base.remove_filename();
+ base /= d;
+ d = base.string();
+ }
+ }
+ if(verbose)
+ std::cout << "Scanning directory " << d << std::endl;
+ if(!exists(boost::filesystem::path(d)))
+ throw std::runtime_error("Error the path requested for scanning does not exist: " + d);
+ scan_dir(d, m, r);
+ }
+ else if(regex_match(line, what, rewrite_parser))
+ {
+ bool id = what[1] == "rewrite-id";
+ std::string a = unquote(what[2].str());
+ std::string b = unquote(what[3].str());
+ id_rewrite_list.push_back(id_rewrite_rule(a, b, id));
+ }
+ else if(line.compare(0, 9, "!exclude ") == 0)
+ {
+ static const boost::regex delim("([^\"[:space:]]+|\"(?:[^\"\\\\]|\\\\.)+\")");
+ boost::sregex_token_iterator i(line.begin() + 9, line.end(), delim, 0), j;
+ while(i != j)
+ {
+ index_info info;
+ info.term = escape_to_xml(unquote(*i));
+ // Erase all entries that have a category in our scanner set,
+ // plus any entry with no category at all:
+ index_terms.erase(info);
+ for(file_scanner_set_type::iterator pscan = file_scanner_set.begin(); pscan != file_scanner_set.end(); ++pscan)
+ {
+ info.category = (*pscan).type;
+ index_terms.erase(info);
+ }
+ ++i;
+ }
+ }
+ else if(regex_match(line, error_parser))
+ {
+ std::cerr << "Error: Unable to process line: " << line << std::endl;
+ }
+ else if(regex_match(line, what, entry_parser))
+ {
+ try{
+ // what[1] is the Index entry
+ // what[2] is the regex to search for (optional)
+ // what[3] is a section id that must be matched
+ // in order for the term to be indexed (optional)
+ // what[4] is the index category to place the term in (optional).
+ index_info info;
+ info.term = escape_to_xml(unquote(what.str(1)));
+ std::string s = unquote(what.str(2));
+ if(s.size())
+ info.search_text = boost::regex(s, boost::regex::icase|boost::regex::perl);
+ else
+ info.search_text = boost::regex("\\<" + what.str(1) + "\\>", boost::regex::icase|boost::regex::perl);
+
+ s = unquote(what.str(3));
+ if(s.size())
+ info.search_id = s;
+ if(what[4].matched)
+ info.category = unquote(what.str(4));
+ std::pair<std::set<index_info>::iterator, bool> pos = index_terms.insert(info);
+ if(pos.second)
+ {
+ if(pos.first->search_text != info.search_text)
+ {
+ //
+ // Merge the search terms:
+ //
+ const_cast<boost::regex&>(pos.first->search_text) =
+ "(?:" + pos.first->search_text.str() + ")|(?:" + info.search_text.str() + ")";
+ }
+ if(pos.first->search_id != info.search_id)
+ {
+ //
+ // Merge the ID constraints:
+ //
+ const_cast<boost::regex&>(pos.first->search_id) =
+ "(?:" + pos.first->search_id.str() + ")|(?:" + info.search_id.str() + ")";
+ }
+ }
+ }
+ catch(const boost::regex_error&)
+ {
+ std::cerr << "Unable to process regular expression in script line:\n \""
+ << line << "\"" << std::endl;
+ throw;
+ }
+ catch(const std::exception&)
+ {
+ std::cerr << "Unable to process script line:\n \""
+ << line << "\"" << std::endl;
+ throw;
+ }
+ }
+ else
+ {
+ std::cerr << "Error: Unable to process line: " << line << std::endl;
+ }
+ }
+}
+
diff --git a/tools/auto_index/src/index_generator.cpp b/tools/auto_index/src/index_generator.cpp
new file mode 100644
index 0000000000..1b65f63c9a
--- /dev/null
+++ b/tools/auto_index/src/index_generator.cpp
@@ -0,0 +1,327 @@
+// Copyright 2008 John Maddock
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "auto_index.hpp"
+#include <boost/range.hpp>
+#include <boost/format.hpp>
+
+//
+// Get a numerical ID for the next item:
+//
+std::string get_next_index_id()
+{
+ static int index_id_count = 0;
+ std::stringstream s;
+ s << "idx_id_" << index_id_count;
+ ++index_id_count;
+ return s.str();
+}
+
+void raise_invalid_xml(const std::string& parent, const std::string& child)
+{
+ throw std::runtime_error("Error: element " + child + " can not appear inside the container " + parent + ": try using a different value for property \"auto-index-type\".");
+}
+//
+// Validate that the container for the Index is in a valid place:
+//
+void check_index_type_and_placement(const std::string& parent, const std::string& container)
+{
+ if(container == "section")
+ {
+ if((parent != "appendix")
+ && (parent != "article")
+ && (parent != "chapter")
+ && (parent != "partintro")
+ && (parent != "preface")
+ && (parent != "section"))
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "appendix")
+ {
+ if((parent != "article")
+ && (parent != "book")
+ && (parent != "part"))
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "index")
+ {
+ if((parent != "appendix")
+ && (parent != "article")
+ && (parent != "book")
+ && (parent != "chapter")
+ && (parent != "part")
+ && (parent != "preface")
+ && (parent != "sect1")
+ && (parent != "sect2")
+ && (parent != "sect3")
+ && (parent != "sect4")
+ && (parent != "sect5")
+ && (parent != "section")
+ )
+ raise_invalid_xml(parent, container);
+ }
+ else if((container == "article") || (container == "chapter") || (container == "reference"))
+ {
+ if((parent != "book")
+ && (parent != "part"))
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "part")
+ {
+ if(parent != "book")
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "refsect1")
+ {
+ if(parent != "refentry")
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "refsect2")
+ {
+ if(parent != "refsect1")
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "refsect3")
+ {
+ if(parent != "refsect2")
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "refsection")
+ {
+ if((parent != "refsection") && (parent != "refentry"))
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "sect1")
+ {
+ if((parent != "appendix")
+ && (parent != "article")
+ && (parent != "chapter")
+ && (parent != "partintro")
+ && (parent != "preface")
+ )
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "sect2")
+ {
+ if(parent != "sect1")
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "sect3")
+ {
+ if(parent != "sect2")
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "sect4")
+ {
+ if(parent != "sect3")
+ raise_invalid_xml(parent, container);
+ }
+ else if(container == "sect5")
+ {
+ if(parent != "sect4")
+ raise_invalid_xml(parent, container);
+ }
+ else
+ {
+ throw std::runtime_error("Error: element " + container + " is unknown, and can not be used as a container for an index: try using a different value for property \"auto-index-type\".");
+ }
+}
+
+boost::tiny_xml::element_ptr make_element(const std::string& name)
+{
+ boost::tiny_xml::element_ptr result(new boost::tiny_xml::element);
+ result->name = name;
+ return result;
+}
+
+boost::tiny_xml::element_ptr add_attribute(boost::tiny_xml::element_ptr ptr, const std::string& name, const std::string& value)
+{
+ boost::tiny_xml::attribute attr;
+ attr.name = name;
+ attr.value = value;
+ ptr->attributes.push_back(attr);
+ return ptr;
+}
+
+boost::regex make_primary_key_matcher(const std::string& s)
+{
+ static const boost::regex e("[-_[:space:]]+|([.\\[{}()\\*+?|^$])");
+ static const char* format = "(?1\\\\$1:[-_[:space:]]+)";
+ return boost::regex(regex_replace(s, e, format, boost::regex_constants::format_all), boost::regex::icase|boost::regex::perl);
+}
+
+//
+// Generate an index entry using our own internal method:
+//
+template <class Range>
+boost::tiny_xml::element_ptr generate_entry(const Range& range, const std::string* pcategory, int level = 0, const boost::regex* primary_key = 0)
+{
+ boost::tiny_xml::element_ptr list = add_attribute(add_attribute(::add_attribute(make_element("itemizedlist"), "mark", "none"), "spacing", "compact"), "role", "index");
+
+ for(typename boost::range_iterator<Range>::type i = boost::begin(range); i != boost::end(range);)
+ {
+ std::string key = (*i)->key;
+ index_entry_set entries;
+ bool preferred = false;
+ std::string id;
+ bool collapse = false;
+
+ //
+ // Create a regular expression for comparing key to other key's:
+ //
+ boost::regex key_regex;
+ if(level == 0)
+ {
+ key_regex = make_primary_key_matcher(key);
+ primary_key = &key_regex;
+ }
+ //
+ // Begin by consolidating entries with identical keys but possibly different categories:
+ //
+ while((i != boost::end(range)) && ((*i)->key == key))
+ {
+ if((0 == pcategory) || (pcategory->size() == 0) || (pcategory && (**i).category == *pcategory))
+ {
+ entries.insert((*i)->sub_keys.begin(), (*i)->sub_keys.end());
+ if((*i)->preferred)
+ preferred = true;
+ if((*i)->id.size())
+ {
+ if(id.size())
+ {
+ std::cerr << "WARNING: two identical index terms have different link destinations!!" << std::endl;
+ }
+ id = (*i)->id;
+ }
+ }
+ ++i;
+ }
+ //
+ // Only actually generate content if we have anything in the entries set:
+ //
+ if(entries.size() || id.size())
+ {
+ //
+ // See if we can collapse any sub-entries into this one:
+ //
+ if(entries.size() == 1)
+ {
+ if((regex_match((*entries.begin())->key, *primary_key) || ((*entries.begin())->key == key))
+ && ((*entries.begin())->id.size())
+ && ((*entries.begin())->id != id))
+ {
+ collapse = true;
+ id = (*entries.begin())->id;
+ }
+ }
+ //
+ // See if this key is the same as the primary key, if it is then make it prefered:
+ //
+ if(level && regex_match(key, *primary_key))
+ {
+ preferred = true;
+ }
+ boost::tiny_xml::element_ptr item = make_element("listitem");
+ boost::tiny_xml::element_ptr para = make_element("para");
+ item->elements.push_back(para);
+ list->elements.push_back(item);
+ if(preferred)
+ {
+ para->elements.push_back(add_attribute(make_element("emphasis"), "role", "bold"));
+ para = para->elements.back();
+ }
+ if(id.size())
+ {
+ boost::tiny_xml::element_ptr link = add_attribute(make_element("link"), "linkend", id);
+ para->elements.push_back(link);
+ para = link;
+ }
+ std::string classname = (boost::format("index-entry-level-%1%") % level).str();
+ para->elements.push_back(add_attribute(make_element("phrase"), "role", classname));
+ para = para->elements.back();
+ para->content = key;
+ if(!collapse && entries.size())
+ {
+ std::pair<index_entry_set::const_iterator, index_entry_set::const_iterator> subrange(entries.begin(), entries.end());
+ item->elements.push_back(generate_entry(subrange, 0, level+1, primary_key));
+ }
+ }
+ }
+ return list;
+}
+//
+// Generate indexes using our own internal method:
+//
+void generate_indexes()
+{
+ for(boost::tiny_xml::element_list::const_iterator i = indexes.begin(); i != indexes.end(); ++i)
+ {
+ boost::tiny_xml::element_ptr node = *i;
+ const std::string* category = find_attr(node, "type");
+ bool has_title = false;
+
+ for(boost::tiny_xml::element_list::const_iterator k = (*i)->elements.begin(); k != (*i)->elements.end(); ++k)
+ {
+ if((**k).name == "title")
+ {
+ has_title = true;
+ break;
+ }
+ }
+
+ boost::tiny_xml::element_ptr navbar = make_element("para");
+ node->elements.push_back(navbar);
+
+ index_entry_set::const_iterator m = index_entries.begin();
+ index_entry_set::const_iterator n = m;
+ boost::tiny_xml::element_ptr vlist = make_element("variablelist");
+ node->elements.push_back(vlist);
+ while(n != index_entries.end())
+ {
+ char current_letter = std::toupper((*n)->key[0]);
+ std::string id_name = get_next_index_id();
+ boost::tiny_xml::element_ptr entry = add_attribute(make_element("varlistentry"), "id", id_name);
+ boost::tiny_xml::element_ptr term = make_element("term");
+ term->content = std::string(1, current_letter);
+ entry->elements.push_back(term);
+ boost::tiny_xml::element_ptr item = make_element("listitem");
+ entry->elements.push_back(item);
+ while((n != index_entries.end()) && (std::toupper((*n)->key[0]) == current_letter))
+ ++n;
+ std::pair<index_entry_set::const_iterator, index_entry_set::const_iterator> range(m, n);
+ item->elements.push_back(generate_entry(range, category));
+ if(item->elements.size() && (*item->elements.begin())->elements.size())
+ {
+ vlist->elements.push_back(entry);
+ boost::tiny_xml::element_ptr p = make_element("");
+ p->content = " ";
+ if(navbar->elements.size())
+ {
+ navbar->elements.push_back(p);
+ }
+ p = add_attribute(make_element("link"), "linkend", id_name);
+ p->content = current_letter;
+ navbar->elements.push_back(p);
+ }
+ m = n;
+ }
+
+ node->name = internal_index_type;
+ boost::tiny_xml::element_ptr p(node->parent);
+ while(p->name.empty())
+ p = boost::tiny_xml::element_ptr(p->parent);
+ check_index_type_and_placement(p->name, node->name);
+ node->attributes.clear();
+ if(!has_title)
+ {
+ boost::tiny_xml::element_ptr t = make_element("title");
+ t->content = "Index";
+ node->elements.push_front(t);
+ }
+ }
+}
+
diff --git a/tools/auto_index/src/tiny_xml.cpp b/tools/auto_index/src/tiny_xml.cpp
new file mode 100644
index 0000000000..81b3b26d9d
--- /dev/null
+++ b/tools/auto_index/src/tiny_xml.cpp
@@ -0,0 +1,257 @@
+// tiny XML sub-set tools implementation -----------------------------------//
+
+// (C) Copyright Beman Dawes 2002. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "tiny_xml.hpp"
+#include <cassert>
+#include <cstring>
+
+namespace
+{
+
+ inline void eat_whitespace( char & c, std::istream & in )
+ {
+ while ( c == ' ' || c == '\r' || c == '\n' || c == '\t' )
+ in.get( c );
+ }
+
+ void eat_comment( char & c, std::istream & in )
+ {
+ in.get(c);
+ if(c != '-')
+ throw std::string("Invalid comment in XML");
+ in.get(c);
+ if(c != '-')
+ throw std::string("Invalid comment in XML");
+ do{
+ while(in.get(c) && (c != '-'));
+ in.get(c);
+ if(c != '-')
+ continue;
+ in.get(c);
+ if(c != '>')
+ continue;
+ else
+ break;
+ }
+ while(true);
+ }
+
+ std::string get_name( char & c, std::istream & in )
+ {
+ std::string result;
+ eat_whitespace( c, in );
+ while ( std::strchr(
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.:", c )
+ != 0 )
+ {
+ result += c;
+ if(!in.get( c ))
+ throw std::string("xml: unexpected eof");
+ }
+ return result;
+ }
+
+ void eat_delim( char & c, std::istream & in,
+ char delim, const std::string & msg )
+ {
+ eat_whitespace( c, in );
+ if ( c != delim )
+ throw std::string("xml syntax error, expected ") + delim
+ + " (" + msg + ")";
+ in.get( c );
+ }
+
+ std::string get_value( char & c, std::istream & in )
+ {
+ std::string result;
+ while ( c != '\"' )
+ {
+ result += c;
+ in.get( c );
+ }
+ in.get( c );
+ return result;
+ }
+
+}
+
+namespace boost
+{
+ namespace tiny_xml
+ {
+
+ // parse -----------------------------------------------------------------//
+
+ element_ptr parse( std::istream & in, const std::string & msg )
+ {
+ char c = 0; // current character
+ element_ptr e( new element );
+
+ if(!in.get( c ))
+ throw std::string("xml: unexpected eof");
+ if ( c == '<' )
+ if(!in.get( c ))
+ throw std::string("xml: unexpected eof");
+
+ if(c == '!')
+ {
+ eat_comment(c, in);
+ return e;
+ }
+ if(c == '?')
+ {
+ // XML processing instruction.
+ e->name += c;
+ if(!in.get( c )) // next char
+ throw std::string("xml: unexpected eof");
+ e->name += get_name(c, in);
+ in >> std::ws;
+ if(!in.get( c )) // next char
+ throw std::string("xml: unexpected eof");
+ while(c != '?')
+ {
+ e->content += c;
+ if(!in.get( c )) // next char
+ throw std::string("xml: unexpected eof");
+ }
+ if(!in.get( c )) // next char
+ throw std::string("xml: unexpected eof");
+ if(c != '>')
+ throw std::string("Invalid XML processing instruction.");
+ return e;
+ }
+
+ e->name = get_name( c, in );
+ eat_whitespace( c, in );
+
+ // attributes
+ while ( (c != '>') && (c != '/') )
+ {
+ attribute a;
+ a.name = get_name( c, in );
+
+ eat_delim( c, in, '=', msg );
+ eat_delim( c, in, '\"', msg );
+
+ a.value = get_value( c, in );
+
+ e->attributes.push_back( a );
+ eat_whitespace( c, in );
+ }
+ if(c == '/')
+ {
+ if(!in.get( c )) // next after '/'
+ throw std::string("xml: unexpected eof");
+ eat_whitespace( c, in );
+ if(c != '>')
+ throw std::string("xml: unexpected /");
+ return e;
+ }
+ if(!in.get( c )) // next after '>'
+ throw std::string("xml: unexpected eof");
+
+ //eat_whitespace( c, in );
+
+ do{
+ // sub-elements
+ while ( c == '<' )
+ {
+ if ( in.peek() == '/' )
+ break;
+ element_ptr child(parse( in, msg ));
+ child->parent = e;
+ e->elements.push_back(child);
+ in.get( c ); // next after '>'
+ //eat_whitespace( c, in );
+ }
+ if (( in.peek() == '/' ) && (c == '<'))
+ break;
+
+ // content
+ if ( (c != '<') )
+ {
+ element_ptr sub( new element );
+ while ( c != '<' )
+ {
+ sub->content += c;
+ if(!in.get( c ))
+ throw std::string("xml: unexpected eof");
+ }
+ sub->parent = e;
+ e->elements.push_back( sub );
+ }
+
+ assert( c == '<' );
+ if( in.peek() == '/' )
+ break;
+ }while(true);
+
+ in.get(c);
+ eat_delim( c, in, '/', msg );
+ std::string end_name( get_name( c, in ) );
+ if ( e->name != end_name )
+ throw std::string("xml syntax error: beginning name ")
+ + e->name + " did not match end name " + end_name
+ + " (" + msg + ")";
+
+ eat_delim( c, in, '>', msg );
+ if(c != '>')
+ {
+ // we've eaten one character past the >, put it back:
+ if(!in.putback(c))
+ throw std::string("Unable to put back character");
+ }
+ return e;
+ }
+
+ // write ---------------------------------------------------------------//
+
+ void write( const element & e, std::ostream & out )
+ {
+ if(e.name.size())
+ {
+ out << "<" << e.name;
+ if ( !e.attributes.empty() )
+ {
+ for( attribute_list::const_iterator itr = e.attributes.begin();
+ itr != e.attributes.end(); ++itr )
+ {
+ out << " " << itr->name << "=\"" << itr->value << "\"";
+ }
+ }
+ if(e.name[0] == '?')
+ {
+ out << " " << e.content << "?>";
+ return;
+ }
+ if(e.elements.empty() && e.content.empty())
+ {
+ out << "/>";
+ return;
+ }
+ out << ">";
+ }
+ if ( !e.elements.empty() )
+ {
+ for( element_list::const_iterator itr = e.elements.begin();
+ itr != e.elements.end(); ++itr )
+ {
+ write( **itr, out );
+ }
+ }
+ if ( !e.content.empty() )
+ {
+ out << e.content;
+ }
+ if(e.name.size() && (e.name[0] != '?'))
+ {
+ out << "</" << e.name << ">";
+ }
+ }
+
+ } // namespace tiny_xml
+} // namespace boost
+
diff --git a/tools/auto_index/src/tiny_xml.hpp b/tools/auto_index/src/tiny_xml.hpp
new file mode 100644
index 0000000000..5ecbd4ce26
--- /dev/null
+++ b/tools/auto_index/src/tiny_xml.hpp
@@ -0,0 +1,83 @@
+// tiny XML sub-set tools --------------------------------------------------//
+
+// (C) Copyright Beman Dawes 2002. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Provides self-contained tools for this XML sub-set:
+//
+// element ::= { "<" name { name "=" "\"" value "\"" } ">"
+// {element} [contents] "</" name ">" }
+//
+// The point of "self-contained" is to minimize tool-chain dependencies.
+
+#ifndef BOOST_TINY_XML_H
+#define BOOST_TINY_XML_H
+
+#include "boost/smart_ptr.hpp" // for shared_ptr
+#include "boost/utility.hpp" // for noncopyable
+#include <list>
+#include <iostream>
+#include <string>
+
+namespace boost
+{
+ namespace tiny_xml
+ {
+ class element;
+ struct attribute
+ {
+ std::string name;
+ std::string value;
+
+ attribute(){}
+ attribute( const std::string & name, const std::string & value )
+ : name(name), value(value) {}
+ };
+ typedef boost::shared_ptr< element > element_ptr;
+ typedef boost::weak_ptr< element > weak_element_ptr;
+ typedef std::list< element_ptr > element_list;
+ typedef std::list< attribute > attribute_list;
+
+ class element
+ : private boost::noncopyable // because deep copy semantics would be required
+ {
+ public:
+ // The name of the XML element, or "" if this is inline content,
+ // or begins with '?' if this is a processing instruction.
+ std::string name;
+ // List of attributes applied to this element
+ attribute_list attributes;
+ // List of sub-elements, this will be empty if the name is empty
+ // or starts with a '?'. Plain text content will be inside
+ // anonymous elements in this list - this preserves the order of
+ // plain text mixed with true XML <elements>.
+ element_list elements;
+ // The plain text content of this element, only present if the name is ""
+ // or if this is a processing instruction in which case it is the content
+ // after the name of the instruction.
+ std::string content;
+ // Pointer to our parent
+ weak_element_ptr parent;
+
+ element() {}
+ explicit element( const std::string & name ) : name(name) {}
+ };
+
+ // Precondition: stream positioned at either the initial "<"
+ // or the first character after the initial "<".
+ // Postcondition: stream positioned at the first character after final
+ // ">" (or eof).
+ // Returns: an element_ptr to an element representing the parsed stream.
+ // Throws: std::string on syntax error. msg appended to what() string.
+ element_ptr parse( std::istream & in, const std::string & msg );
+
+ void write( const element & e, std::ostream & out );
+
+ }
+}
+
+#endif // BOOST_TINY_XML_H
+
+
+
diff --git a/tools/auto_index/test/Jamfile.v2 b/tools/auto_index/test/Jamfile.v2
new file mode 100644
index 0000000000..4b1e60b567
--- /dev/null
+++ b/tools/auto_index/test/Jamfile.v2
@@ -0,0 +1,62 @@
+
+import feature ;
+import generators ;
+import modules ;
+import project ;
+import targets ;
+import testing ;
+import toolset ;
+import type ;
+
+alias line_compare_tool : ../../quickbook/test/src//line-compare-tool ;
+
+rule auto-index-test ( target-name : input-file : output-file ? : options * )
+{
+ local project = [ project.current ] ;
+
+ local t =
+ [ targets.create-typed-target RUN
+ : $(project)
+ : $(target-name)
+ : [ alias autoindex : ../build//auto_index : release ]
+ : $(requirements)
+ <location-prefix>$(target-name).test
+ <testing.arg>--prefix=../../..
+ <testing.arg>$(options)
+ <testing.arg>--in=$(input-file)
+ <testing.arg>--out=$(target-name).out
+ <preserve-test-targets>on
+ <dependency>Jamfile.v2
+ <dependency>$(input-file)
+ ]
+ ;
+
+ t +=
+ [ targets.create-typed-target RUN
+ : $(project)
+ : $(target-name)_check
+ : .//line_compare_tool
+ : $(requirements)
+ <location-prefix>$(target-name).test
+ <testing.arg>$(target-name).out
+ <testing.arg>$(target-name).gold
+ <preserve-test-targets>on
+ <dependency>$(target_name)
+ <implicit-dependency>$(target_name)
+ <dependency>Jamfile.v2
+ <dependency>$(input-file)
+ ]
+ ;
+
+ modules.poke testing : .all-tests : \$\(all-tests\) $(t) ;
+
+ return $(t) ;
+}
+
+auto-index-test test1 : type_traits.docbook : : --script=index.idx ;
+auto-index-test test2 : type_traits.docbook : : --internal-index --script=index.idx ;
+auto-index-test test3 : type_traits.docbook : : --internal-index --index-type=index --script=index.idx ;
+
+
+
+
diff --git a/tools/auto_index/test/index.idx b/tools/auto_index/test/index.idx
new file mode 100644
index 0000000000..52507c28a1
--- /dev/null
+++ b/tools/auto_index/test/index.idx
@@ -0,0 +1,26 @@
+
+!define-scanner class_name "BOOST_TT_AUX_TYPE_TRAIT_DEF\d\s*\(\s*(\w+)\s*[,)]" "(?:class|struct)[^;{]+\\<\1\\>[^;{]+\\{" \1
+!define-scanner class_name "BOOST_TT_AUX_BOOL_TRAIT_DEF\d\s*\(\s*(\w+)\s*[,)]" "(?:class|struct)[^;{]+\\<\1\\>[^;{]+\\{" \1
+!define-scanner class_name "BOOST_TT_AUX_SIZE_T_TRAIT_DEF\d\s*\(\s*(\w+)\s*[,)]" "(?:class|struct)[^;{]+\\<\1\\>[^;{]+\\{" \1
+
+!define-scanner class_name "^[[:space:]]*(template[[:space:]]*<[^;:{]+>[[:space:]]*)?(class|struct)[[:space:]]*(\<\w+\>([[:blank:]]*\([^)]*\))?[[:space:]]*)*(\<\w*\>)[[:space:]]*(<[^;:{]+>)?[[:space:]]*(\{|:[^;\{()]*\{)" "(?:class|struct)[^;{]+\\<\5\\>[^;{]+\\{" \5
+!define-scanner typedef_name "typedef[^;{}#]+?(\w+)\s*;" "typedef[^;]+\\<\1\\>\\s*;" "\1"
+!define-scanner "macro_name" "^\s*#\s*define\s+(\w+)" "\\<\1\\>" "\1"
+!define-scanner "function_name" "\w+\s+(\w+)\s*\([^\)]*\)\s*[;{]" "\\<\\w+\\>\\s+\\<\1\\>\\s*\\([^;{]*\\)\\s*[;{]" "\1"
+
+!scan-path boost/type_traits .*\.hpp true
+!scan boost/aligned_storage.hpp
+!scan boost/type_traits.hpp
+
+!exclude type arg1_type arg2_type arg3_type arg4_type arg5_type B D
+!exclude result
+
+!rewrite-name "(?:A|An|The)\s+(.*)" "\1"
+
+"Constrained Index Term" add_const "boost_typetraits\.reference.*" class_name
+"This term should not appear anywhere because of the ID constraint" strlen "(?!boost_typetraits.background).*" function_name
+
+
+type-traits "" ".*.intro" test_index_1
+type-traits "" ".*.background" test_index_2
+
diff --git a/tools/auto_index/test/test1.gold b/tools/auto_index/test/test1.gold
new file mode 100644
index 0000000000..b53ba13681
--- /dev/null
+++ b/tools/auto_index/test/test1.gold
@@ -0,0 +1,6671 @@
+<?xml version="1.0"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!--
+
+This file is based upon the type traits docs, but has had additional XML elements added to it
+to ensure complete testing.
+
+-->
+
+<chapter xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" id="boost_typetraits" rev:last-revision="$Date: 2008-11-28 12:41:45 +0000 (Fri, 28 Nov 2008) $">
+ <chapterinfo><author>
+ <firstname>various</firstname> <surname>authors</surname>
+ </author><copyright>
+ <year>2000</year> <year>2006</year> <holder>Adobe Systems Inc, David Abrahams,
+ Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant, Jesse Jones, Mat
+ Marcus, Itay Maman, John Maddock, Alexander Nasonov, Thorsten Ottosen, Robert
+ Ramey and Jeremy Siek</holder>
+ </copyright><legalnotice>
+ <para>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
+ </para>
+ </legalnotice></chapterinfo>
+ <title>Boost.TypeTraits</title>
+ <para>
+ A printer-friendly <ulink url="http://svn.boost.org/svn/boost/sandbox/pdf/type_traits/release/type_traits.pdf">PDF
+ version of this manual is also available</ulink>.
+ </para>
+ <section id="boost_typetraits.intro"><indexterm type="test_index_1"><primary>type-traits</primary><secondary>Introduction</secondary></indexterm><indexterm><primary>Introduction</primary><secondary>type-traits</secondary></indexterm><indexterm type="test_index_1"><primary>type-traits</primary><secondary>Introduction</secondary></indexterm><indexterm><primary>Introduction</primary><secondary>type-traits</secondary></indexterm><indexterm type="test_index_1"><primary>type-traits</primary><secondary>Introduction</secondary></indexterm><indexterm><primary>Introduction</primary><secondary>type-traits</secondary></indexterm>
+ <title><link linkend="boost_typetraits.intro"> Introduction</link></title>
+ <para>
+ The Boost type-traits library contains a set of very specific traits classes,
+ each of which encapsulate a single trait from the C++ type system; for example,
+ is a type a pointer or a reference type? Or does a type have a trivial constructor,
+ or a const-qualifier?
+ </para>
+ <para>
+ The type-traits classes share a unified design: each class inherits from a
+ the type <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the type has the specified property and inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ otherwise.
+ </para>
+ <para>
+ The type-traits library also contains a set of classes that perform a specific
+ transformation on a type; for example, they can remove a top-level const or
+ volatile qualifier from a type. Each class that performs a transformation defines
+ a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of the transformation.
+ </para>
+ </section>
+ <section id="boost_typetraits.background"><indexterm type="test_index_2"><primary>type-traits</primary><secondary>Background and Tutorial</secondary></indexterm><indexterm><primary>Background and Tutorial</primary><secondary>type-traits</secondary></indexterm><indexterm type="test_index_2"><primary>type-traits</primary><secondary>Background and Tutorial</secondary></indexterm><indexterm><primary>Background and Tutorial</primary><secondary>type-traits</secondary></indexterm><indexterm type="class_name"><primary>remove_extent</primary><secondary>Background and Tutorial</secondary></indexterm><indexterm><primary>Background and Tutorial</primary><secondary>remove_extent</secondary></indexterm><indexterm type="class_name"><primary>is_pointer</primary><secondary>Background and Tutorial</secondary></indexterm><indexterm><primary>Background and Tutorial</primary><secondary>is_pointer</secondary></indexterm><indexterm type="class_name"><primary>is_void</primary><secondary>Background and Tutorial</secondary></indexterm><indexterm><primary>Background and Tutorial</primary><secondary>is_void</secondary></indexterm><indexterm type="test_index_2"><primary>type-traits</primary><secondary>Background and Tutorial</secondary></indexterm><indexterm><primary>Background and Tutorial</primary><secondary>type-traits</secondary></indexterm><indexterm type="test_index_2"><primary>type-traits</primary><secondary>Background and Tutorial</secondary></indexterm><indexterm><primary>Background and Tutorial</primary><secondary>type-traits</secondary></indexterm><indexterm type="test_index_2"><primary>type-traits</primary><secondary>Background and Tutorial</secondary></indexterm><indexterm><primary>Background and Tutorial</primary><secondary>type-traits</secondary></indexterm>
+ <title><link linkend="boost_typetraits.background"> Background and Tutorial</link></title>
+ <para>
+ The following is an updated version of the article "C++ Type traits"
+ by John Maddock and Steve Cleary that appeared in the October 2000 issue of
+ <ulink url="http://www.ddj.com">Dr Dobb's Journal</ulink>.
+ </para>
+ <para>
+ Generic programming (writing code which works with any data type meeting a
+ set of requirements) has become the method of choice for providing reusable
+ code. However, there are times in generic programming when "generic"
+ just isn't good enough - sometimes the differences between types are too large
+ for an efficient generic implementation. This is when the traits technique
+ becomes important - by encapsulating those properties that need to be considered
+ on a type by type basis inside a traits class, we can minimize the amount of
+ code that has to differ from one type to another, and maximize the amount of
+ generic code.
+ </para>
+ <?dbfo keep-together="auto" ?>
+ <para>
+ <indexterm>
+ <primary>Foo1</primary>
+ </indexterm>
+ Consider an example: when working with character strings, one common operation
+ is to determine the length of a null terminated string. Clearly it's possible
+ to write generic code that can do this, but it turns out that there are much
+ more efficient methods available: for example, the C library functions <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">strlen</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">wcslen</phrase></computeroutput>
+ are usually written in assembler, and with suitable hardware support can be
+ considerably faster than a generic version written in C++. The authors of the
+ C++ standard library realized this, and abstracted the properties of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">wchar_t</phrase></computeroutput>
+ into the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput>.
+ Generic code that works with character strings can simply use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase><phrase role="special">&lt;&gt;::</phrase><phrase role="identifier">length</phrase></computeroutput> to determine the length of a null
+ terminated string, safe in the knowledge that specializations of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput> will use the most appropriate
+ method available to them.
+ </para>
+ <anchor id="boost_typetraits.background.type_traits"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.type_traits">Type Traits</link>
+ </bridgehead>
+ <para>
+ Class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput> is a classic
+ example of a collection of type specific properties wrapped up in a single
+ class - what Nathan Myers termed a <emphasis>baggage class</emphasis><link linkend="background.references">[1]</link>. In the Boost type-traits library,
+ we<link linkend="background.references">[2]</link> have written a set of very
+ specific traits classes, each of which encapsulate a single trait from the
+ C++ type system; for example, is a type a pointer or a reference type? Or does
+ a type have a trivial constructor, or a const-qualifier? The type-traits classes
+ share a unified design: each class inherits from a the type <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the type has the specified property and inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ otherwise. As we will show, these classes can be used in generic programming
+ to determine the properties of a given type and introduce optimizations that
+ are appropriate for that case.
+ </para>
+ <para>
+ The type-traits library also contains a set of classes that perform a specific
+ transformation on a type; for example, they can remove a top-level const or
+ volatile qualifier from a type. Each class that performs a transformation defines
+ a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of the transformation. All of the type-traits classes are
+ defined inside namespace <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase></computeroutput>;
+ for brevity, namespace-qualification is omitted in most of the code samples
+ given.
+ </para>
+ <anchor id="boost_typetraits.background.implementation"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.implementation">Implementation</link>
+ </bridgehead>
+ <para>
+ There are far too many separate classes contained in the type-traits library
+ to give a full implementation here - see the source code in the Boost library
+ for the full details - however, most of the implementation is fairly repetitive
+ anyway, so here we will just give you a flavor for how some of the classes
+ are implemented. Beginning with possibly the simplest class in the library,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits
+ from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ only if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>.
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ Here we define a primary version of the template class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_void">is_void</link></computeroutput>,
+ and provide a full-specialization when <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>. While full specialization
+ of a template class is an important technique, sometimes we need a solution
+ that is halfway between a fully generic solution, and a full specialization.
+ This is exactly the situation for which the standards committee defined partial
+ template-class specialization. As an example, consider the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput>:
+ here we needed a primary version that handles all the cases where T is not
+ a pointer, and a partial specialization to handle all the cases where T is
+ a pointer:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">*&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ The syntax for partial specialization is somewhat arcane and could easily occupy
+ an article in its own right; like full specialization, in order to write a
+ partial specialization for a class, you must first declare the primary template.
+ The partial specialization contains an extra &lt;...&gt; after the class name
+ that contains the partial specialization parameters; these define the types
+ that will bind to that partial specialization rather than the default template.
+ The rules for what can appear in a partial specialization are somewhat convoluted,
+ but as a rule of thumb if you can legally write two function overloads of the
+ form:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">);</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase><phrase role="identifier">U</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <para>
+ Then you can also write a partial specialization of the form:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <phrase role="identifier">c</phrase><phrase role="special">{</phrase> <phrase role="comment">/*details*/</phrase> <phrase role="special">};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <phrase role="identifier">c</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;{</phrase> <phrase role="comment">/*details*/</phrase> <phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ This rule is by no means foolproof, but it is reasonably simple to remember
+ and close enough to the actual rule to be useful for everyday use.
+ </para>
+ <para>
+ As a more complex example of partial specialization consider the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput>. This
+ class defines a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the same type as T but with any top-level array bounds removed; this
+ is an example of a traits class that performs a transformation on a type:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link>
+<phrase role="special">{</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">[</phrase><phrase role="identifier">N</phrase><phrase role="special">]&gt;</phrase>
+<phrase role="special">{</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ The aim of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.remove_extent">remove_extent</link></computeroutput>
+ is this: imagine a generic algorithm that is passed an array type as a template
+ parameter, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.remove_extent">remove_extent</link></computeroutput>
+ provides a means of determining the underlying type of the array. For example
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">][</phrase><phrase role="number">5</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> would evaluate to the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">5</phrase><phrase role="special">]</phrase></computeroutput>. This example also shows that the number of
+ template parameters in a partial specialization does not have to match the
+ number in the default template. However, the number of parameters that appear
+ after the class name do have to match the number and type of the parameters
+ in the default template.
+ </para>
+ <anchor id="boost_typetraits.background.optimized_copy"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.optimized_copy">Optimized copy</link>
+ </bridgehead>
+ <para>
+ As an example of how the type traits classes can be used, consider the standard
+ library algorithm copy:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Iter1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Iter2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">Iter2</phrase> <phrase role="identifier">copy</phrase><phrase role="special">(</phrase><phrase role="identifier">Iter1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">Iter1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">Iter2</phrase> <phrase role="identifier">out</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <para>
+ Obviously, there's no problem writing a generic version of copy that works
+ for all iterator types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput>; however, there are
+ some circumstances when the copy operation can best be performed by a call
+ to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>. In order to implement
+ copy in terms of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput> all
+ of the following conditions need to be met:
+ </para>
+ <itemizedlist>
+ <listitem>
+ Both of the iterator types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput> must be pointers.
+ </listitem>
+ <listitem>
+ Both <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput> must point to the same type - excluding
+ const and volatile-qualifiers.
+ </listitem>
+ <listitem>
+ The type pointed to by <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ must have a trivial assignment operator.
+ </listitem>
+ </itemizedlist>
+ <para>
+ By trivial assignment operator we mean that the type is either a scalar type<link linkend="background.references">[3]</link> or:
+ </para>
+ <itemizedlist>
+ <listitem>
+ The type has no user defined assignment operator.
+ </listitem>
+ <listitem>
+ The type does not have any data members that are references.
+ </listitem>
+ <listitem>
+ All base classes, and all data member objects must have trivial assignment
+ operators.
+ </listitem>
+ </itemizedlist>
+ <para>
+ If all these conditions are met then a type can be copied using <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput> rather than using a compiler generated
+ assignment operator. The type-traits library provides a class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>,
+ such that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is true only if T has a trivial assignment
+ operator. This class "just works" for scalar types, but has to be
+ explicitly specialised for class/struct types that also happen to have a trivial
+ assignment operator. In other words if <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link>
+ gives the wrong answer, it will give the "safe" wrong answer - that
+ trivial assignment is not allowable.
+ </para>
+ <para>
+ The code for an optimized version of copy that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>
+ where appropriate is given in <link linkend="boost_typetraits.examples.copy">the
+ examples</link>. The code begins by defining a template function <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">do_copy</phrase></computeroutput> that performs a "slow but safe"
+ copy. The last parameter passed to this function may be either a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ or a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">false_type</link></computeroutput>.
+ Following that there is an overload of do<emphasis role="underline">copy that
+ uses `memcpy`: this time the iterators are required to actually be pointers
+ to the same type, and the final parameter must be a `</emphasis>_true_type<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">.</phrase> <phrase role="identifier">Finally</phrase><phrase role="special">,</phrase> <phrase role="identifier">the</phrase> <phrase role="identifier">version</phrase>
+ <phrase role="identifier">of</phrase> </computeroutput>copy<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="identifier">calls</phrase>
+ </computeroutput>do<emphasis role="underline">copy`, passing `</emphasis>_has_trivial_assign&lt;value_type&gt;()`
+ as the final parameter: this will dispatch to the optimized version where appropriate,
+ otherwise it will call the "slow but safe version".
+ </para>
+ <anchor id="boost_typetraits.background.was_it_worth_it_"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.was_it_worth_it_">Was it worth it?</link>
+ </bridgehead>
+ <para>
+ It has often been repeated in these columns that "premature optimization
+ is the root of all evil" <link linkend="background.references">[4]</link>.
+ So the question must be asked: was our optimization premature? To put this
+ in perspective the timings for our version of copy compared a conventional
+ generic copy<link linkend="background.references">[5]</link> are shown in table
+ 1.
+ </para>
+ <para>
+ Clearly the optimization makes a difference in this case; but, to be fair,
+ the timings are loaded to exclude cache miss effects - without this accurate
+ comparison between algorithms becomes difficult. However, perhaps we can add
+ a couple of caveats to the premature optimization rule:
+ </para>
+ <itemizedlist>
+ <listitem>
+ If you use the right algorithm for the job in the first place then optimization
+ will not be required; in some cases, memcpy is the right algorithm.
+ </listitem>
+ <listitem>
+ If a component is going to be reused in many places by many people then optimizations
+ may well be worthwhile where they would not be so for a single case - in
+ other words, the likelihood that the optimization will be absolutely necessary
+ somewhere, sometime is that much higher. Just as importantly the perceived
+ value of the stock implementation will be higher: there is no point standardizing
+ an algorithm if users reject it on the grounds that there are better, more
+ heavily optimized versions available.
+ </listitem>
+ </itemizedlist>
+ <table frame="all"> <title>Time taken to copy 1000 elements using `copy&lt;const
+ T*, T*&gt;` (times in micro-seconds)</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Version
+ </para>
+ </entry><entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ Time
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ "Optimized" copy
+ </para>
+ </entry><entry>
+ <para>
+ char
+ </para>
+ </entry><entry>
+ <para>
+ 0.99
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Conventional copy
+ </para>
+ </entry><entry>
+ <para>
+ char
+ </para>
+ </entry><entry>
+ <para>
+ 8.07
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ "Optimized" copy
+ </para>
+ </entry><entry>
+ <para>
+ int
+ </para>
+ </entry><entry>
+ <para>
+ 2.52
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Conventional copy
+ </para>
+ </entry><entry>
+ <para>
+ int
+ </para>
+ </entry><entry>
+ <para>
+ 8.02
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table> <anchor id="boost_typetraits.background.pair_of_references"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.pair_of_references">Pair of References</link>
+ </bridgehead>
+ <para>
+ The optimized copy example shows how type traits may be used to perform optimization
+ decisions at compile-time. Another important usage of type traits is to allow
+ code to compile that otherwise would not do so unless excessive partial specialization
+ is used. This is possible by delegating partial specialization to the type
+ traits classes. Our example for this form of usage is a pair that can hold
+ references <link linkend="background.references">[6]</link>.
+ </para>
+ <para>
+ First, let us examine the definition of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase></computeroutput>, omitting
+ the comparison operators, default constructor, and template copy constructor
+ for simplicity:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">pair</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T1</phrase> <phrase role="identifier">first_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T2</phrase> <phrase role="identifier">second_type</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">T1</phrase> <phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">T2</phrase> <phrase role="identifier">second</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">pair</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">nfirst</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T2</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase>
+<phrase role="special">:</phrase><phrase role="identifier">first</phrase><phrase role="special">(</phrase><phrase role="identifier">nfirst</phrase><phrase role="special">),</phrase> <phrase role="identifier">second</phrase><phrase role="special">(</phrase><phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <phrase role="special">}</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ Now, this "pair" cannot hold references as it currently stands, because
+ the constructor would require taking a reference to a reference, which is currently
+ illegal <link linkend="background.references">[7]</link>. Let us consider what
+ the constructor's parameters would have to be in order to allow "pair"
+ to hold non-reference types, references, and constant references:
+ </para>
+ <table frame="all"> <title>Required Constructor Argument Types</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of parameter to initializing constructor
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ A little familiarity with the type traits classes allows us to construct a
+ single mapping that allows us to determine the type of parameter from the type
+ of the contained class. The type traits classes provide a transformation <link linkend="boost_typetraits.reference.add_reference">add_reference</link>, which
+ adds a reference to its type, unless it is already a reference.
+ </para>
+ <table frame="all"> <title>Using add_reference to synthesize the correct constructor
+ type</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ const T
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ T &amp; [8]
+ </para>
+ </entry><entry>
+ <para>
+ T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ This allows us to build a primary template definition for <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput>
+ that can contain non-reference types, reference types, and constant reference
+ types:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">pair</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T1</phrase> <phrase role="identifier">first_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T2</phrase> <phrase role="identifier">second_type</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">T1</phrase> <phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">T2</phrase> <phrase role="identifier">second</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">pair</phrase><phrase role="special">(</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">nfirst</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase>
+<phrase role="special">:</phrase><phrase role="identifier">first</phrase><phrase role="special">(</phrase><phrase role="identifier">nfirst</phrase><phrase role="special">),</phrase> <phrase role="identifier">second</phrase><phrase role="special">(</phrase><phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <phrase role="special">}</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ Add back in the standard comparison operators, default constructor, and template
+ copy constructor (which are all the same), and you have a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase></computeroutput> that
+ can hold reference types!
+ </para>
+ <para>
+ This same extension could have been done using partial template specialization
+ of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput>, but to specialize
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput> in this way would require
+ three partial specializations, plus the primary template. Type traits allows
+ us to define a single primary template that adjusts itself auto-magically to
+ any of these partial specializations, instead of a brute-force partial specialization
+ approach. Using type traits in this fashion allows programmers to delegate
+ partial specialization to the type traits classes, resulting in code that is
+ easier to maintain and easier to understand.
+ </para>
+ <anchor id="boost_typetraits.background.conclusion"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.conclusion">Conclusion</link>
+ </bridgehead>
+ <para>
+ We hope that in this article we have been able to give you some idea of what
+ type-traits are all about. A more complete listing of the available classes
+ are in the boost documentation, along with further examples using type traits.
+ Templates have enabled C++ uses to take the advantage of the code reuse that
+ generic programming brings; hopefully this article has shown that generic programming
+ does not have to sink to the lowest common denominator, and that templates
+ can be optimal as well as generic.
+ </para>
+ <anchor id="boost_typetraits.background.acknowledgements"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.acknowledgements">Acknowledgements</link>
+ </bridgehead>
+ <para>
+ The authors would like to thank Beman Dawes and Howard Hinnant for their helpful
+ comments when preparing this article.
+ </para>
+ <anchor id="background.references"/> <anchor id="boost_typetraits.background.references"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.references">References</link>
+ </bridgehead>
+ <orderedlist inheritnum="ignore" continuation="restarts">
+ <listitem>
+ Nathan C. Myers, C++ Report, June 1995.
+ </listitem>
+ <listitem>
+ The type traits library is based upon contributions by Steve Cleary, Beman
+ Dawes, Howard Hinnant and John Maddock: it can be found at www.boost.org.
+ </listitem>
+ <listitem>
+ A scalar type is an arithmetic type (i.e. a built-in integer or floating
+ point type), an enumeration type, a pointer, a pointer to member, or a const-
+ or volatile-qualified version of one of these types.
+ </listitem>
+ <listitem>
+ This quote is from Donald Knuth, ACM Computing Surveys, December 1974, pg
+ 268.
+ </listitem>
+ <listitem>
+ The test code is available as part of the boost utility library (see algo_opt_examples.cpp),
+ the code was compiled with gcc 2.95 with all optimisations turned on, tests
+ were conducted on a 400MHz Pentium II machine running Microsoft Windows 98.
+ </listitem>
+ <listitem>
+ John Maddock and Howard Hinnant have submitted a "compressed_pair"
+ library to Boost, which uses a technique similar to the one described here
+ to hold references. Their pair also uses type traits to determine if any
+ of the types are empty, and will derive instead of contain to conserve space
+ -- hence the name "compressed".
+ </listitem>
+ <listitem>
+ This is actually an issue with the C++ Core Language Working Group (issue
+ #106), submitted by Bjarne Stroustrup. The tentative resolution is to allow
+ a "reference to a reference to T" to mean the same thing as a "reference
+ to T", but only in template instantiation, in a method similar to multiple
+ cv-qualifiers.
+ </listitem>
+ <listitem>
+ For those of you who are wondering why this shouldn't be const-qualified,
+ remember that references are always implicitly constant (for example, you
+ can't re-assign a reference). Remember also that "const T &amp;"
+ is something completely different. For this reason, cv-qualifiers on template
+ type arguments that are references are ignored.
+ </listitem>
+ </orderedlist>
+ </section>
+ <section id="boost_typetraits.category">
+ <title><link linkend="boost_typetraits.category"> Type Traits by Category</link></title>
+ <section id="boost_typetraits.category.value_traits">
+ <title><link linkend="boost_typetraits.category.value_traits"> Type Traits
+ that Describe the Properties of a Type</link></title>
+ <para>
+ <indexterm>
+ <primary>Foo2</primary>
+ <secondary>Bar2</secondary>
+ </indexterm>
+ These traits are all <emphasis>value traits</emphasis>, which is to say the
+ traits classes all inherit from <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link>,
+ and are used to access some numerical property of a type. Often this is a
+ simple true or false Boolean value, but in a few cases may be some other
+ integer value (for example when dealing with type alignments, or array bounds:
+ see <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.alignment_of">alignment_of</link></computeroutput>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.rank">rank</link></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.extent">extent</link></computeroutput>).
+ </para>
+ <section id="boost_typetraits.category.value_traits.primary">
+ <title><link linkend="boost_typetraits.category.value_traits.primary"> Categorizing
+ a Type</link></title>
+ <para>
+ These traits identify what "kind" of type some type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is. These are split into two groups:
+ primary traits which are all mutually exclusive, and composite traits that
+ are compositions of one or more primary traits.
+ </para>
+ <para>
+ For any given type, exactly one primary type trait will inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ and all the others will inherit from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>,
+ in other words these traits are mutually exclusive.
+ </para>
+ <para>
+ This means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_integral">is_integral</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ will only ever be true for built-in types; if you want to check for a user-defined
+ class type that behaves "as if" it is an integral or floating
+ point type, then use the <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">numeric_limits</phrase>
+ <phrase role="keyword">template</phrase></computeroutput> instead.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_array">is_array</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_class">is_class</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_complex">is_complex</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_enum">is_enum</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_function">is_function</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_integral">is_integral</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_object_pointer">is_member_object_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_union">is_union</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ The following traits are made up of the union of one or more type categorizations.
+ A type may belong to more than one of these categories, in addition to
+ one of the primary categories.
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_arithmetic">is_arithmetic</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_compound">is_compound</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_fundamental">is_fundamental</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_object">is_object</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_scalar">is_scalar</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.value_traits.properties">
+ <title><link linkend="boost_typetraits.category.value_traits.properties">
+ General Type Properties</link></title>
+ <para>
+ The following templates describe the general properties of a type.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.alignment_of">alignment_of</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_assign">has_nothrow_assign</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_default_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_default_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_virtual_destructor">has_virtual_destructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_abstract">is_abstract</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_const">is_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_empty">is_empty</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_stateless">is_stateless</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_signed">is_signed</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_unsigned">is_unsigned</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_volatile">is_volatile</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.extent">extent</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.rank">rank</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.value_traits.relate">
+ <title><link linkend="boost_typetraits.category.value_traits.relate"> Relationships
+ Between Two Types</link></title>
+ <para>
+ These templates determine the whether there is a relationship between two
+ types:
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_base_of">is_base_of</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_same">is_same</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.category.transform"><indexterm type="macro_name"><primary>BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</primary><secondary>Type Traits that Transform One Type to Another</secondary></indexterm><indexterm><primary>Type Traits that Transform One Type to Another</primary><secondary>BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</primary><secondary>Type Traits that Transform One Type to Another</secondary></indexterm><indexterm><primary>Type Traits that Transform One Type to Another</primary><secondary>BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</secondary></indexterm>
+ <title><link linkend="boost_typetraits.category.transform"> Type Traits that
+ Transform One Type to Another</link></title>
+ <para>
+ The following templates transform one type to another, based upon some well-defined
+ rule. Each template has a single member called <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of applying the transformation to the template argument
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_const">add_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_cv">add_cv</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_pointer">add_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_volatile">add_volatile</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.decay">decay</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.floating_point_promotion">floating_point_promotion</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.integral_promotion">integral_promotion</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.make_signed">make_signed</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.make_unsigned">make_unsigned</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.promote">promote</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_all_extents">remove_all_extents</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_const">remove_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_cv">remove_cv</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_reference">remove_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_volatile">remove_volatile</link><phrase role="special">;</phrase>
+</programlisting>
+ <anchor id="boost_typetraits.category.transform.broken_compiler_workarounds_"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">Broken
+ Compiler Workarounds:</link>
+ </bridgehead>
+ <para>
+ For all of these templates support for partial specialization of class templates
+ is required to correctly implement the transformation. On the other hand,
+ practice shows that many of the templates from this category are very useful,
+ and often essential for implementing some generic libraries. Lack of these
+ templates is often one of the major limiting factors in porting those libraries
+ to compilers that do not yet support this language feature. As some of these
+ compilers are going to be around for a while, and at least one of them is
+ very wide-spread, it was decided that the library should provide workarounds
+ where possible.
+ </para>
+ <para>
+ The basic idea behind the workaround is to manually define full specializations
+ of all type transformation templates for all fundamental types, and all their
+ 1st and 2nd rank cv-[un]qualified derivative pointer types, and to provide
+ a user-level macro that will define all the explicit specializations needed
+ for any user-defined type T.
+ </para>
+ <para>
+ The first part guarantees the successful compilation of something like this:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">*,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="special">...</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+</programlisting>
+ <para>
+ and the second part provides the library's users with a mechanism to make
+ the above code work not only for <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput> or other built-in type,
+ but for their own types as well:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">namespace</phrase> <phrase role="identifier">myspace</phrase><phrase role="special">{</phrase>
+ <phrase role="keyword">struct</phrase> <phrase role="identifier">MyClass</phrase> <phrase role="special">{};</phrase>
+<phrase role="special">}</phrase>
+<phrase role="comment">// declare this at global scope:
+</phrase><phrase role="identifier">BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</phrase><phrase role="special">(</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">)</phrase>
+<phrase role="comment">// transformations on myspace::MyClass now work:
+</phrase><phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="comment">// etc.
+</phrase></programlisting>
+ <para>
+ Note that the macro BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION evaluates
+ to nothing on those compilers that <emphasis role="bold">do</emphasis> support
+ partial specialization.
+ </para>
+ </section>
+ <section id="boost_typetraits.category.alignment">
+ <title><link linkend="boost_typetraits.category.alignment"> Synthesizing Types
+ with Specific Alignments</link></title>
+ <para>
+ Some low level memory management routines need to synthesize a POD type with
+ specific alignment properties. The template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.type_with_alignment">type_with_alignment</link></computeroutput>
+ finds the smallest type with a specified alignment, while template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.aligned_storage">aligned_storage</link></computeroutput>
+ creates a type with a specific size and alignment.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.type_with_alignment">type_with_alignment</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.aligned_storage">aligned_storage</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.function">
+ <title><link linkend="boost_typetraits.category.function"> Decomposing Function
+ Types</link></title>
+ <para>
+ The class template <link linkend="boost_typetraits.reference.function_traits">function_traits</link>
+ extracts information from function types (see also <link linkend="boost_typetraits.reference.is_function">is_function</link>).
+ This traits class allows you to tell how many arguments a function takes,
+ what those argument types are, and what the return type is.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.function_traits">function_traits</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.user_defined"><indexterm type="class_name"><primary>is_union</primary><secondary>User Defined Specializations</secondary></indexterm><indexterm><primary>User Defined Specializations</primary><secondary>is_union</secondary></indexterm><indexterm type="class_name"><primary>is_pod</primary><secondary>User Defined Specializations</secondary></indexterm><indexterm><primary>User Defined Specializations</primary><secondary>is_pod</secondary></indexterm><indexterm type="class_name"><primary>is_class</primary><secondary>User Defined Specializations</secondary></indexterm><indexterm><primary>User Defined Specializations</primary><secondary>is_class</secondary></indexterm>
+ <title><link linkend="boost_typetraits.user_defined"> User Defined Specializations</link></title>
+ <para>
+ Occationally the end user may need to provide their own specialization for
+ one of the type traits - typically where intrinsic compiler support is required
+ to implement a specific trait fully. These specializations should derive from
+ boost::<link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ or boost::<link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ as appropriate:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pod</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_class</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_union</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">struct</phrase> <phrase role="identifier">my_pod</phrase><phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">my_union</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">char</phrase> <phrase role="identifier">c</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_pod</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_union">is_union</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_class">is_class</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.intrinsics"><indexterm type="macro_name"><primary>BOOST_IS_UNION</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_IS_UNION</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_IS_POLYMORPHIC</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_IS_POLYMORPHIC</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_IS_POD</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_IS_POD</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_IS_ENUM</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_IS_ENUM</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_IS_EMPTY</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_IS_EMPTY</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_IS_CONVERTIBLE</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_IS_CONVERTIBLE</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_IS_CLASS</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_IS_CLASS</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_IS_BASE_OF</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_IS_BASE_OF</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_IS_ABSTRACT</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_IS_ABSTRACT</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_HAS_VIRTUAL_DESTRUCTOR</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_HAS_VIRTUAL_DESTRUCTOR</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_HAS_TRIVIAL_DESTRUCTOR</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_HAS_TRIVIAL_DESTRUCTOR</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_HAS_TRIVIAL_COPY</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_HAS_TRIVIAL_COPY</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_HAS_TRIVIAL_CONSTRUCTOR</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_HAS_TRIVIAL_CONSTRUCTOR</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_HAS_TRIVIAL_ASSIGN</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_HAS_TRIVIAL_ASSIGN</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_HAS_NOTHROW_COPY</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_HAS_NOTHROW_COPY</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_HAS_NOTHROW_CONSTRUCTOR</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_HAS_NOTHROW_CONSTRUCTOR</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_HAS_NOTHROW_ASSIGN</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_HAS_NOTHROW_ASSIGN</secondary></indexterm><indexterm type="macro_name"><primary>BOOST_ALIGNMENT_OF</primary><secondary>Support for Compiler Intrinsics</secondary></indexterm><indexterm><primary>Support for Compiler Intrinsics</primary><secondary>BOOST_ALIGNMENT_OF</secondary></indexterm>
+ <title><link linkend="boost_typetraits.intrinsics"> Support for Compiler Intrinsics</link></title>
+ <para>
+ There are some traits that can not be implemented within the current C++ language:
+ to make these traits "just work" with user defined types, some kind
+ of additional help from the compiler is required. Currently (April 2008) Visual
+ C++ 8 and 9, GNU GCC 4.3 and MWCW 9 provide the necessary intrinsics, and other
+ compilers will no doubt follow in due course.
+ </para>
+ <para>
+ The Following traits classes always need compiler support to do the right thing
+ for all types (but all have safe fallback positions if this support is unavailable):
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_union">is_union</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_pod">is_pod</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_assign">has_nothrow_assign</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_virtual_destructor">has_virtual_destructor</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following traits classes can't be portably implemented in the C++ language,
+ although in practice, the implementations do in fact do the right thing on
+ all the compilers we know about:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_empty">is_empty</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following traits classes are dependent on one or more of the above:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_class">is_class</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_stateless">is_stateless</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The hooks for compiler-intrinsic support are defined in <ulink url="../../../../boost/type_traits/intrinsics.hpp">boost/type_traits/intrinsics.hpp</ulink>,
+ adding support for new compilers is simply a matter of defining one of more
+ of the following macros:
+ </para>
+ <table frame="all"> <title>Macros for Compiler Intrinsics</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_UNION(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a union type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_POD(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a POD type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_EMPTY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is an empty struct or union
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if the default constructor for T is trivial (i.e.
+ has no effect)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_COPY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial copy constructor (and can
+ therefore be replaced by a call to memcpy)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_ASSIGN(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial assignment operator (and can
+ therefore be replaced by a call to memcpy)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_DESTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial destructor (i.e. ~T() has
+ no effect)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_CONSTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="identifier">x</phrase><phrase role="special">;</phrase></computeroutput>
+ can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_COPY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase><phrase role="special">(</phrase><phrase role="identifier">t</phrase><phrase role="special">)</phrase></computeroutput> can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_ASSIGN(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="identifier">t</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">u</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">t</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">u</phrase></computeroutput> can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_VIRTUAL_DESTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true T has a virtual destructor
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_ABSTRACT(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is an abstract type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_BASE_OF(T,U)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a base class of U
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_CLASS(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a class type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_CONVERTIBLE(T,U)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is convertible to U
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_ENUM(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true is T is an enum
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_POLYMORPHIC(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a polymorphic type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_ALIGNMENT_OF(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to the alignment requirements of type T.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.mpl">
+ <title><link linkend="boost_typetraits.mpl"> MPL Interoperability</link></title>
+ <para>
+ All the value based traits in this library conform to MPL's requirements for
+ an <ulink url="../../../../libs/mpl/doc/refmanual/integral-constant.html">Integral
+ Constant type</ulink>: that includes a number of rather intrusive workarounds
+ for broken compilers.
+ </para>
+ <para>
+ Purely as an implementation detail, this means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/bool.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">true_</phrase></computeroutput></ulink>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">false_type</link></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/bool.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">false_</phrase></computeroutput></ulink>,
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">v</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/integral-c.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">integral_c</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">v</phrase><phrase role="special">&gt;</phrase></computeroutput></ulink>
+ (provided <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>)
+ </para>
+ </section>
+ <section id="boost_typetraits.examples">
+ <title><link linkend="boost_typetraits.examples"> Examples</link></title>
+ <section id="boost_typetraits.examples.copy">
+ <title><link linkend="boost_typetraits.examples.copy"> An Optimized Version
+ of std::copy</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">copy</phrase></computeroutput>
+ that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>
+ to determine whether to use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>
+ to optimise the copy operation (see <ulink url="../../examples/copy_example.cpp">copy_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// opt::copy
+</phrase><phrase role="comment">// same semantics as std::copy
+</phrase><phrase role="comment">// calls memcpy where appropriate.
+</phrase><phrase role="comment">//
+</phrase>
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">I2</phrase> <phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">out</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">out</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">out</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">memcpy</phrase><phrase role="special">(</phrase><phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="special">(</phrase><phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">)*</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">));</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">out</phrase><phrase role="special">+(</phrase><phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">copy</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">out</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// We can copy with memcpy if T has a trivial assignment operator,
+</phrase> <phrase role="comment">// and if the iterator arguments are actually pointers (this last
+</phrase> <phrase role="comment">// requirement we detect with overload resolution):
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">&lt;</phrase><phrase role="identifier">value_type</phrase><phrase role="special">&gt;());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.fill">
+ <title><link linkend="boost_typetraits.examples.fill"> An Optimised Version
+ of std::fill</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">fill</phrase></computeroutput>
+ that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>
+ to determine whether to use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memset</phrase></computeroutput>
+ to optimise the fill operation (see <ulink url="../../examples/fill_example.cpp">fill_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// fill
+</phrase><phrase role="comment">// same as std::fill, but uses memset where appropriate
+</phrase><phrase role="comment">//
+</phrase><phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">first</phrase> <phrase role="special">=</phrase> <phrase role="identifier">val</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memset</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">I</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">fill</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// We can do an optimised fill if T has a trivial assignment
+</phrase> <phrase role="comment">// operator and if it's size is one:
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase>
+ <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">(</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase> <phrase role="special">==</phrase> <phrase role="number">1</phrase><phrase role="special">)&gt;</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.destruct">
+ <title><link linkend="boost_typetraits.examples.destruct"> An Example that
+ Omits Destructor Calls For Types with Trivial Destructors</link></title>
+ <para>
+ Demonstrates a simple algorithm that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">__has_trivial_destruct</phrase></computeroutput>
+ to determine whether to destructors need to be called (see <ulink url="../../examples/trivial_destructor_example.cpp">trivial_destructor_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// algorithm destroy_array:
+</phrase><phrase role="comment">// The reverse of std::unitialized_copy, takes a block of
+</phrase><phrase role="comment">// initialized memory and calls destructors on all objects therein.
+</phrase><phrase role="comment">//
+</phrase>
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="identifier">first</phrase><phrase role="special">-&gt;~</phrase><phrase role="identifier">T</phrase><phrase role="special">();</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase> <phrase role="comment">// namespace detail
+</phrase>
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">p1</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">p2</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">p1</phrase><phrase role="special">,</phrase> <phrase role="identifier">p2</phrase><phrase role="special">,</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.iter">
+ <title><link linkend="boost_typetraits.examples.iter"> An improved Version
+ of std::iter_swap</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iter_swap</phrase></computeroutput>
+ that use type traits to determine whether an it's arguments are proxying
+ iterators or not, if they're not then it just does a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">swap</phrase></computeroutput>
+ of it's dereferenced arguments (the same as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iter_swap</phrase></computeroutput>
+ does), however if they are proxying iterators then takes special care over
+ the swap to ensure that the algorithm works correctly for both proxying iterators,
+ and even iterators of different types (see <ulink url="../../examples/iter_swap_example.cpp">iter_swap_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// iter_swap:
+</phrase><phrase role="comment">// tests whether iterator is a proxying iterator or not, and
+</phrase><phrase role="comment">// uses optimal form accordingly:
+</phrase><phrase role="comment">//
+</phrase><phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">static</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase> <phrase role="identifier">v_t</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">v_t</phrase> <phrase role="identifier">v</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">one</phrase><phrase role="special">;</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">one</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">two</phrase><phrase role="special">;</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">two</phrase> <phrase role="special">=</phrase> <phrase role="identifier">v</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">static</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">using</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">swap</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">swap</phrase><phrase role="special">(*</phrase><phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase><phrase role="identifier">two</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">iter_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">two</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// See is both arguments are non-proxying iterators,
+</phrase> <phrase role="comment">// and if both iterator the same type:
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">reference</phrase> <phrase role="identifier">r1_t</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I2</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">reference</phrase> <phrase role="identifier">r2_t</phrase><phrase role="special">;</phrase>
+
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase>
+ <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">&lt;</phrase><phrase role="identifier">r1_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">&lt;</phrase><phrase role="identifier">r2_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_same">is_same</link><phrase role="special">&lt;</phrase><phrase role="identifier">r1_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">r2_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">;</phrase>
+
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.to_double">
+ <title><link linkend="boost_typetraits.examples.to_double"> Convert Numeric
+ Types and Enums to double</link></title>
+ <para>
+ Demonstrates a conversion of <ulink url="../../../../libs/numeric/conversion/doc/html/boost_numericconversion/definitions.html#boost_numericconversion.definitions.numeric_types">Numeric
+ Types</ulink> and enum types to double:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">double</phrase> <phrase role="identifier">to_double</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">value</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">promoted</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">numeric</phrase><phrase role="special">::</phrase><phrase role="identifier">converter</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase><phrase role="identifier">promoted</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">convert</phrase><phrase role="special">(</phrase><phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.reference">
+ <title><link linkend="boost_typetraits.reference"> Alphabetical Reference</link></title>
+ <section id="boost_typetraits.reference.add_const"><indexterm type="class_name"><primary>Constrained Index Term</primary><secondary>add_const</secondary></indexterm><indexterm><primary>add_const</primary><secondary>Constrained Index Term</secondary></indexterm><indexterm type="class_name"><primary>Constrained Index Term</primary><secondary>add_const</secondary></indexterm><indexterm><primary>add_const</primary><secondary>Constrained Index Term</secondary></indexterm><indexterm type="class_name"><primary>add_const</primary><secondary>add_const</secondary></indexterm><indexterm type="class_name"><primary>Constrained Index Term</primary><secondary>add_const</secondary></indexterm><indexterm><primary>add_const</primary><secondary>Constrained Index Term</secondary></indexterm><indexterm type="class_name"><primary>Constrained Index Term</primary><secondary>add_const</secondary></indexterm><indexterm><primary>add_const</primary><secondary>Constrained Index Term</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.add_const"> add_const</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ <secondary>two</secondary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">const</phrase></computeroutput> for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_cv"><indexterm type="class_name"><primary>add_cv</primary><secondary>add_cv</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.add_cv"> add_cv</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ <secondary>two</secondary>
+ <tertiary>three</tertiary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_cv</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_cv</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_pointer"><indexterm type="class_name"><primary>add_pointer</primary><secondary>add_pointer</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.add_pointer"> add_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_pointer</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">*</phrase></computeroutput>.
+ </para>
+ <para>
+ The rationale for this template is that it produces the same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">TYPEOF</phrase><phrase role="special">(&amp;</phrase><phrase role="identifier">t</phrase><phrase role="special">)</phrase></computeroutput>, where
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">t</phrase></computeroutput> is an object of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">**</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">**</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_reference"><indexterm type="class_name"><primary>add_reference</primary><secondary>add_reference</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.add_reference"> add_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_reference</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is not a reference type then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase></computeroutput>, otherwise <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_volatile"><indexterm type="class_name"><primary>add_volatile</primary><secondary>add_volatile</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.add_volatile"> add_volatile</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput> for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.aligned_storage"><indexterm type="class_name"><primary>aligned_storage</primary><secondary>aligned_storage</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.aligned_storage"> aligned_storage</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">aligned_storage</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> a built-in or POD type with size
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Size</phrase></computeroutput> and an alignment that
+ is a multiple of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Align</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">aligned_storage</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.alignment_of"><indexterm type="class_name"><primary>integral_constant</primary><secondary>alignment_of</secondary></indexterm><indexterm><primary>alignment_of</primary><secondary>integral_constant</secondary></indexterm><indexterm type="class_name"><primary>alignment_of</primary><secondary>alignment_of</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.alignment_of"> alignment_of</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">alignment_of</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template alignment<emphasis role="underline">of inherits from `</emphasis>_integral_constant&lt;std::size_t,
+ ALIGNOF(T)&gt;<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">,</phrase> <phrase role="identifier">where</phrase>
+ </computeroutput>ALIGNOF(T)` is the alignment of type T.
+ </para>
+ <para>
+ <emphasis>Note: strictly speaking you should only rely on the value of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> being
+ a multiple of the true alignment of T, although in practice it does compute
+ the correct value in all the cases we know about.</emphasis>
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">alignment_of</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ with value <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.decay"><indexterm type="class_name"><primary>decay</primary><secondary>decay</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.decay"> decay</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">decay</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> Let <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>
+ be the result of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>, then if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>
+ is an array type, the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;*</phrase></computeroutput>,
+ otherwise if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput> is a function
+ type then the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase><phrase role="special">*</phrase></computeroutput>, otherwise the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">decay</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">(&amp;)[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">(&amp;)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.extent"><indexterm type="class_name"><primary>integral_constant</primary><secondary>extent</secondary></indexterm><indexterm><primary>extent</primary><secondary>integral_constant</secondary></indexterm><indexterm type="class_name"><primary>extent</primary><secondary>extent</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.extent"> extent</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">extent</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template extent inherits
+ from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)&gt;</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)</phrase></computeroutput> is the number of elements in the N'th array
+ dimention of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not an array type,
+ or if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">N</phrase> <phrase role="special">&gt;</phrase>
+ <link linkend="boost_typetraits.reference.rank">rank</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>, or if the N'th array bound is incomplete,
+ then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)</phrase></computeroutput> is zero.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">extent</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">1</phrase><phrase role="special">]&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">],</phrase>
+ <phrase role="number">1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">3</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>4</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">],</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>2</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.floating_point_promotion"><indexterm type="class_name"><primary>floating_point_promotion</primary><secondary>floating_point_promotion</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.floating_point_promotion">
+ floating_point_promotion</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">floating_point_promotion</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If floating point promotion can be
+ applied to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ then applies floating point promotion to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">float</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.function_traits"><indexterm type="typedef_name"><primary>result_type</primary><secondary>function_traits</secondary></indexterm><indexterm><primary>function_traits</primary><secondary>result_type</secondary></indexterm><indexterm type="class_name"><primary>function_traits</primary><secondary>function_traits</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.function_traits"> function_traits</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">F</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">function_traits</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">static</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">arity</phrase> <phrase role="special">=</phrase> <replaceable>see-below</replaceable><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">result_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> arg<replaceable>N</replaceable>_type<phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ The class template function_traits will only compile if:
+ </para>
+ <itemizedlist>
+ <listitem>
+ The compiler supports partial specialization of class templates.
+ </listitem>
+ <listitem>
+ The template argument <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>
+ is a <emphasis>function type</emphasis>, note that this <emphasis><emphasis role="bold">is not</emphasis></emphasis> the same thing as a <emphasis>pointer
+ to a function</emphasis>.
+ </listitem>
+ </itemizedlist>
+ <tip>
+ <para>
+ function_traits is intended to introspect only C++ functions of the form
+ R (), R( A1 ), R ( A1, ... etc. ) and not function pointers or class member
+ functions. To convert a function pointer type to a suitable type use <link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link>.
+ </para>
+ </tip>
+ <table frame="all"> <title>Function Traits Members</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Member
+ </para>
+ </entry><entry>
+ <para>
+ Description
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that gives the number of arguments
+ accepted by the function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type returned by function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase>arg<replaceable>N</replaceable>_type</computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The <replaceable>N</replaceable>th argument type of function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="number">1</phrase> <phrase role="special">&lt;=</phrase>
+ <phrase role="identifier">N</phrase> <phrase role="special">&lt;=</phrase>
+ <phrase role="identifier">arity</phrase></computeroutput> of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table> <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 0.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 1.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 4.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">long</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arg1_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arg4_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase><phrase role="special">*</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arg5_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A compiler error: there is no <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">arg5_type</phrase></computeroutput>
+ since there are only four arguments.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A compiler error: argument type is a <emphasis>function pointer</emphasis>,
+ and not a <emphasis>function type</emphasis>.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_assign"><indexterm type="class_name"><primary>has_nothrow_assign</primary><secondary>has_nothrow_assign</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.has_nothrow_assign"> has_nothrow_assign</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_assign</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing assignment-operator then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_assign</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing assignment-operator;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler support to ensure that this trait "just
+ works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_assign</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_constructor"><indexterm type="class_name"><primary>has_nothrow_default_constructor</primary><secondary>has_nothrow_constructor</secondary></indexterm><indexterm><primary>has_nothrow_constructor</primary><secondary>has_nothrow_default_constructor</secondary></indexterm><indexterm type="class_name"><primary>has_nothrow_constructor</primary><secondary>has_nothrow_constructor</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.has_nothrow_constructor">
+ has_nothrow_constructor</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_default_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing default-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_constructor</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing default-constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to ensure that this trait "just works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_constructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_copy"><indexterm type="class_name"><primary>has_nothrow_copy_constructor</primary><secondary>has_nothrow_copy</secondary></indexterm><indexterm><primary>has_nothrow_copy</primary><secondary>has_nothrow_copy_constructor</secondary></indexterm><indexterm type="class_name"><primary>has_nothrow_copy</primary><secondary>has_nothrow_copy</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.has_nothrow_copy"> has_nothrow_copy</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_copy</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_copy_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing copy-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_copy</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing copy-constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to ensure that this trait "just works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_copy</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_cp_cons">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_cp_cons"> has_nothrow_copy_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_no_throw_def_cons">
+ <title><link linkend="boost_typetraits.reference.has_no_throw_def_cons"> has_nothrow_default_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_assign"><indexterm type="class_name"><primary>has_trivial_assign</primary><secondary>has_trivial_assign</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.has_trivial_assign"> has_trivial_assign</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_assign</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial assignment-operator then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ If a type has a trivial assignment-operator then the operator has the same
+ effect as copying the bits of one object to the other: calls to the operator
+ can be safely replaced with a call to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_assign
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.8p11.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_constructor"><indexterm type="class_name"><primary>has_trivial_default_constructor</primary><secondary>has_trivial_constructor</secondary></indexterm><indexterm><primary>has_trivial_constructor</primary><secondary>has_trivial_default_constructor</secondary></indexterm><indexterm type="class_name"><primary>has_trivial_constructor</primary><secondary>has_trivial_constructor</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.has_trivial_constructor">
+ has_trivial_constructor</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_default_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial default-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ If a type has a trivial default-constructor then the constructor have no
+ effect: calls to the constructor can be safely omitted. Note that using meta-programming
+ to omit a call to a single trivial-constructor call is of no benefit whatsoever.
+ However, if loops and/or exception handling code can also be omitted, then
+ some benefit in terms of code size and speed can be obtained.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_constructor
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.1p6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_copy"><indexterm type="class_name"><primary>has_trivial_copy_constructor</primary><secondary>has_trivial_copy</secondary></indexterm><indexterm><primary>has_trivial_copy</primary><secondary>has_trivial_copy_constructor</secondary></indexterm><indexterm type="class_name"><primary>has_trivial_copy</primary><secondary>has_trivial_copy</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.has_trivial_copy"> has_trivial_copy</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_copy</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_copy_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial copy-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ If a type has a trivial copy-constructor then the constructor has the same
+ effect as copying the bits of one object to the other: calls to the constructor
+ can be safely replaced with a call to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_copy
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.8p6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_cp_cons">
+ <title><link linkend="boost_typetraits.reference.has_trivial_cp_cons"> has_trivial_copy_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_def_cons">
+ <title><link linkend="boost_typetraits.reference.has_trivial_def_cons"> has_trivial_default_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_destructor"><indexterm type="class_name"><primary>has_trivial_destructor</primary><secondary>has_trivial_destructor</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.has_trivial_destructor"> has_trivial_destructor</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_destructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial destructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ If a type has a trivial destructor then the destructor has no effect: calls
+ to the destructor can be safely omitted. Note that using meta-programming
+ to omit a call to a single trivial-constructor call is of no benefit whatsoever.
+ However, if loops and/or exception handling code can also be omitted, then
+ some benefit in terms of code size and speed can be obtained.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_destructor
+ will never report that a user-defined class or struct has a trivial destructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.4p3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_virtual_destructor"><indexterm type="class_name"><primary>has_virtual_destructor</primary><secondary>has_virtual_destructor</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.has_virtual_destructor"> has_virtual_destructor</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_virtual_destructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a virtual destructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> This trait is provided
+ for completeness, since it's part of the Technical Report on C++ Library
+ Extensions. However, there is currently no way to portably implement this
+ trait. The default version provided always inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>,
+ and has to be explicitly specialized for types with virtual destructors unless
+ the compiler used has compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ that enable the trait to do the right thing: currently (May 2005) only Visual
+ C++ 8 and GCC-4.3 have the necessary <link linkend="boost_typetraits.intrinsics">intrinsics</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.4.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_virtual_destructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.integral_constant"><indexterm type="typedef_name"><primary>true_type</primary><secondary>integral_constant</secondary></indexterm><indexterm><primary>integral_constant</primary><secondary>true_type</secondary></indexterm><indexterm type="class_name"><primary>integral_constant</primary><secondary>integral_constant</secondary></indexterm><indexterm type="typedef_name"><primary>false_type</primary><secondary>integral_constant</secondary></indexterm><indexterm><primary>integral_constant</primary><secondary>false_type</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.integral_constant"> integral_constant</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">val</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">integral_constant</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">static</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value</phrase> <phrase role="special">=</phrase> <phrase role="identifier">val</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">true_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="keyword">false</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">false_type</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ Class template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_constant</phrase></computeroutput>
+ is the common base class for all the value-based type traits. The two typedef's
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">true_type</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">false_type</phrase></computeroutput> are provided for convenience:
+ most of the value traits are Boolean properties and so will inherit from
+ one of these.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.integral_promotion"><indexterm type="class_name"><primary>integral_promotion</primary><secondary>integral_promotion</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.integral_promotion"> integral_promotion</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">integral_promotion</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If integral promotion can be applied
+ to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>, then
+ applies integral promotion to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.5 except 4.5/3
+ (integral bit-field).
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">integral_promotion</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">enum</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">float_round_style</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.is_abstract"><indexterm type="class_name"><primary>is_abstract</primary><secondary>is_abstract</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_abstract"> is_abstract</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_abstract</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ abstract type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_abstract</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> The compiler must
+ support DR337 (as of April 2005: GCC 3.4, VC++ 7.1 (and later), Intel C++
+ 7 (and later), and Comeau 4.3.2). Otherwise behaves the same as <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link>;
+ this is the "safe fallback position" for which polymorphic types
+ are always regarded as potentially abstract. The macro BOOST_NO_IS_ABSTRACT
+ is used to signify that the implementation is buggy, users should check for
+ this in their own code if the "safe fallback" is not suitable for
+ their particular use-case.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">abc</phrase><phrase role="special">{</phrase> <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">abc</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_arithmetic"><indexterm type="class_name"><primary>is_arithmetic</primary><secondary>is_arithmetic</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_arithmetic"> is_arithmetic</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_arithmetic</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ arithmetic type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Arithmetic types include integral and floating point types (see also <link linkend="boost_typetraits.reference.is_integral">is_integral</link> and
+ <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link>).
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p8.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_arithmetic</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_array"><indexterm type="class_name"><primary>is_array</primary><secondary>is_array</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_array"> is_array</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_array</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ array type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_array</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can give the wrong result with function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_base_of"><indexterm type="class_name"><primary>is_base_of</primary><secondary>is_base_of</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_base_of"> is_base_of</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_base_of</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If Base is base class of type
+ Derived or if both types are the same then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ This template will detect non-public base classes, and ambiguous base classes.
+ </para>
+ <para>
+ Note that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">X</phrase><phrase role="special">,</phrase><phrase role="identifier">X</phrase><phrase role="special">&gt;</phrase></computeroutput> will always inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>.
+ <emphasis role="bold">This is the case even if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">X</phrase></computeroutput>
+ is not a class type</emphasis>. This is a change in behaviour from Boost-1.33
+ in order to track the Technical Report on C++ Library Extensions.
+ </para>
+ <para>
+ Types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput> must not be incomplete types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_base_of</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types. There are some older compilers which
+ will produce compiler errors if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput>
+ is a private base class of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput>,
+ or if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput> is an ambiguous
+ base of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput>. These compilers
+ include Borland C++, older versions of Sun Forte C++, Digital Mars C++, and
+ older versions of EDG based compilers.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">{};</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase> <phrase role="special">:</phrase>
+ <phrase role="keyword">public</phrase> <phrase role="identifier">Base</phrase><phrase role="special">{};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Base</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>: a class is regarded as it's
+ own base.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_class"><indexterm type="class_name"><primary>is_class</primary><secondary>is_class</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_class"> is_class</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_class</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ class type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 9.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_class</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Without (some as
+ yet unspecified) help from the compiler, we cannot distinguish between union
+ and class types, as a result this type will erroneously inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link> for
+ union types. See also <link linkend="boost_typetraits.reference.is_union">is_union</link>.
+ Currently (May 2005) only Visual C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to correctly identify union types, and therefore make is_class function correctly.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">MyClass</phrase><phrase role="special">;</phrase></computeroutput> then:
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_complex"><indexterm type="class_name"><primary>is_complex</primary><secondary>is_complex</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_complex"> is_complex</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_complex</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is a complex number type then true (of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">complex</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ for some type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>), otherwise
+ false.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 26.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_complex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.is_compound"><indexterm type="class_name"><primary>is_compound</primary><secondary>is_compound</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_compound"> is_compound</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_compound</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ compound type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Any type that is not a fundamental type is a compound type (see also <link linkend="boost_typetraits.reference.is_fundamental">is_fundamental</link>).
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_compound</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyEnum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_const"><indexterm type="class_name"><primary>is_const</primary><secondary>is_const</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_const"> is_const</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_const</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (top level) const-qualified
+ type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the const-qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the const-qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_convertible"><indexterm type="class_name"><primary>is_convertible</primary><secondary>is_convertible</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_convertible"> is_convertible</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_convertible</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If an imaginary lvalue of type
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">From</phrase></computeroutput> is convertible to type
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput> then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ Type From must not be an incomplete type.
+ </para>
+ <para>
+ Type To must not be an incomplete, or function type.
+ </para>
+ <para>
+ No types are considered to be convertible to array types or abstract-class
+ types.
+ </para>
+ <para>
+ This template can not detect whether a converting-constructor is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">public</phrase></computeroutput> or not: if type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput>
+ has a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">private</phrase></computeroutput> converting constructor
+ from type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">From</phrase></computeroutput> then instantiating
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ will produce a compiler error. For this reason <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase></computeroutput>
+ can not be used to determine whether a type has a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">public</phrase></computeroutput>
+ copy-constructor or not.
+ </para>
+ <para>
+ This template will also produce compiler errors if the conversion is ambiguous,
+ for example:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">struct</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">B</phrase> <phrase role="special">:</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">C</phrase> <phrase role="special">:</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">D</phrase> <phrase role="special">:</phrase> <phrase role="identifier">B</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase> <phrase role="special">{};</phrase>
+<phrase role="comment">// This produces a compiler error, the conversion is ambiguous:
+</phrase><phrase role="keyword">bool</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">y</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">D</phrase><phrase role="special">*,</phrase><phrase role="identifier">A</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4 and 8.5.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> This template is
+ currently broken with Borland C++ Builder 5 (and earlier), for constructor-based
+ conversions, and for the Metrowerks 7 (and earlier) compiler in all cases.
+ If the compiler does not support <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_abstract">is_abstract</link></computeroutput>,
+ then the template parameter <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput>
+ must not be an abstract type.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_convertible</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*,</phrase> <phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the conversion would require a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const_cast</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_empty"><indexterm type="class_name"><primary>is_empty</primary><secondary>is_empty</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_empty"> is_empty</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_empty</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an empty class type then
+ inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10p5.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_empty</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> In order to correctly
+ detect empty classes this trait relies on either:
+ </para>
+ <itemizedlist>
+ <listitem>
+ the compiler implementing zero sized empty base classes, or
+ </listitem>
+ <listitem>
+ the compiler providing <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect empty classes.
+ </listitem>
+ </itemizedlist>
+ <para>
+ Can not be used with incomplete types.
+ </para>
+ <para>
+ Can not be used with union types, until is_union can be made to work.
+ </para>
+ <para>
+ If the compiler does not support partial-specialization of class templates,
+ then this template can not be used with abstract types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">struct</phrase> <phrase role="identifier">empty_class</phrase>
+ <phrase role="special">{};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_enum"><indexterm type="class_name"><primary>is_enum</primary><secondary>is_enum</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_enum"> is_enum</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_enum</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ enum type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_enum</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Requires a correctly
+ functioning <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link>
+ template; this means that is_enum is currently broken under Borland C++ Builder
+ 5, and for the Metrowerks compiler prior to version 8, other compilers should
+ handle this template just fine.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">enum</phrase> <phrase role="identifier">my_enum</phrase>
+ <phrase role="special">{</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">two</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_floating_point"><indexterm type="class_name"><primary>is_floating_point</primary><secondary>is_floating_point</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_floating_point"> is_floating_point</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_floating_point</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ floating point type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p8.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_floating_point</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_function"><indexterm type="function_name"><primary>int</primary><secondary>is_function</secondary></indexterm><indexterm><primary>is_function</primary><secondary>int</secondary></indexterm><indexterm type="class_name"><primary>is_function</primary><secondary>is_function</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_function"> is_function</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_function</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ function type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Note that this template does not detect <emphasis>pointers to functions</emphasis>,
+ or <emphasis>references to functions</emphasis>, these are detected by <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link> and <link linkend="boost_typetraits.reference.is_reference">is_reference</link> respectively:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">f1</phrase><phrase role="special">();</phrase> <phrase role="comment">// f1 is of function type.
+</phrase><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">f2</phrase><phrase role="special">*)();</phrase> <phrase role="comment">// f2 is a pointer to a function.
+</phrase><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">f3</phrase><phrase role="special">&amp;)();</phrase> <phrase role="comment">// f3 is a reference to a function.
+</phrase></programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2p1 and 8.3.5.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_function</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a pointer type, not a function type.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(&amp;)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a reference to a function, not a function type.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a pointer to a member function.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <tip>
+ <para>
+ Don't confuse function-types with pointers to functions:
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="identifier">f</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">);</phrase></computeroutput>
+ </para>
+ <para>
+ defines a function type,
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase> <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ declares a prototype for a function of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase></computeroutput>,
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase><phrase role="special">*</phrase>
+ <phrase role="identifier">pf</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase><phrase role="special">&amp;</phrase>
+ <phrase role="identifier">fr</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ declares a pointer and a reference to the function <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">foo</phrase></computeroutput>.
+ </para>
+ <para>
+ If you want to detect whether some type is a pointer-to-function then use:
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_function">is_function</link><phrase role="special">&lt;</phrase><link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ </para>
+ <para>
+ or for pointers to member functions you can just use <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link>
+ directly.
+ </para>
+ </tip>
+ </section>
+ <section id="boost_typetraits.reference.is_fundamental"><indexterm type="class_name"><primary>is_fundamental</primary><secondary>is_fundamental</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_fundamental"> is_fundamental</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_fundamental</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ fundamental type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Fundamental types include integral, floating point and void types (see also
+ <link linkend="boost_typetraits.reference.is_integral">is_integral</link>,
+ <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link>
+ and <link linkend="boost_typetraits.reference.is_void">is_void</link>)
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_fundamental</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_integral"><indexterm type="class_name"><primary>is_integral</primary><secondary>is_integral</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_integral"> is_integral</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_integral</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ integral type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p7.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_integral</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_function_pointer"><indexterm type="class_name"><primary>is_member_function_pointer</primary><secondary>is_member_function_pointer</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_member_function_pointer">
+ is_member_function_pointer</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_function_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member function then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the argument in this case is a pointer to a data member and not a member
+ function, see <link linkend="boost_typetraits.reference.is_member_object_pointer">is_member_object_pointer</link>
+ and <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_object_pointer"><indexterm type="class_name"><primary>is_member_object_pointer</primary><secondary>is_member_object_pointer</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_member_object_pointer">
+ is_member_object_pointer</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_object_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member object (a data member) then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the argument in this case is a pointer to a member function and not a
+ member object, see <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link>
+ and <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_pointer"><indexterm type="class_name"><primary>is_member_pointer</primary><secondary>is_member_pointer</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_member_pointer"> is_member_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member (either a function or a data member) then inherits from
+ <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_object"><indexterm type="class_name"><primary>is_object</primary><secondary>is_object</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_object"> is_object</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_object</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ object type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ All types are object types except references, void, and function types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p9.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_object</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: reference types are not
+ objects
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: function types are not
+ objects
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ void is not an object type
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_pod"><indexterm type="class_name"><primary>is_pod</primary><secondary>is_pod</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_pod"> is_pod</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_pod</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ POD type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ POD stands for "Plain old data". Arithmetic types, and enumeration
+ types, a pointers and pointer to members are all PODs. Classes and unions
+ can also be POD's if they have no non-static data members that are of reference
+ or non-POD type, no user defined constructors, no user defined assignment
+ operators, no private or protected non-static data members, no virtual functions
+ and no base classes. Finally, a cv-qualified POD is still a POD, as is an
+ array of PODs.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10 and 9p4 (Note
+ that POD's are also aggregates, see 8.5.1).
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, is<emphasis role="underline">pod
+ will never report that a class or struct is a POD; this is always safe, if
+ possibly sub-optimal. Currently (May 2005) only MWCW 9 and Visual C++ 8 have
+ the necessary compiler-</emphasis>_intrinsics.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pod</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_pointer"><indexterm type="class_name"><primary>is_pointer</primary><secondary>is_pointer</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_pointer"> is_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer type (includes function pointers, but excludes pointers to members)
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2p2 and 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <important>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase></computeroutput> detects "real"
+ pointer types only, and <emphasis>not</emphasis> smart pointers. Users
+ should not specialise <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase></computeroutput>
+ for smart pointer types, as doing so may cause Boost (and other third party)
+ code to fail to function correctly. Users wanting a trait to detect smart
+ pointers should create their own. However, note that there is no way in
+ general to auto-magically detect smart pointer types, so such a trait would
+ have to be partially specialised for each supported smart pointer type.
+ </para>
+ </important>
+ </section>
+ <section id="boost_typetraits.reference.is_polymorphic"><indexterm type="class_name"><primary>is_polymorphic</primary><secondary>is_polymorphic</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_polymorphic"> is_polymorphic</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_polymorphic</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ polymorphic type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> The implementation
+ requires some knowledge of the compilers ABI, it does actually seem to work
+ with the majority of compilers though.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_polymorphic</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">poly</phrase><phrase role="special">{</phrase> <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">poly</phrase><phrase role="special">();</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_same"><indexterm type="class_name"><primary>is_same</primary><secondary>is_same</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_same"> is_same</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_same</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T and U are the same types
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_same</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with abstract, incomplete or function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_scalar"><indexterm type="class_name"><primary>is_scalar</primary><secondary>is_scalar</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_scalar"> is_scalar</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_scalar</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ scalar type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Scalar types include integral, floating point, enumeration, pointer, and
+ pointer-to-member types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_scalar</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_signed"><indexterm type="class_name"><primary>is_signed</primary><secondary>is_signed</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_signed"> is_signed</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_signed</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an signed integer type
+ or an enumerated type with an underlying signed integer type, then inherits
+ from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1, 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_signed</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myclass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ whose value depends upon the signedness of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_stateless"><indexterm type="class_name"><primary>is_stateless</primary><secondary>is_stateless</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_stateless"> is_stateless</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_stateless</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Ff T is a stateless type then
+ inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ Type T must be a complete type.
+ </para>
+ <para>
+ A stateless type is a type that has no storage and whose constructors and
+ destructors are trivial. That means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_stateless</phrase></computeroutput>
+ only inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the following expression is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">true</phrase></computeroutput>:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_stateless</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, is_stateless will
+ never report that a class or struct is stateless; this is always safe, if
+ possibly sub-optimal. Currently (May 2005) only MWCW 9 and Visual C++ 8 have
+ the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to make this template work automatically.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.is_reference"><indexterm type="class_name"><primary>is_reference</primary><secondary>is_reference</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_reference"> is_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_reference</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a reference pointer type
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ may report the wrong result for function types, and for types that are both
+ const and volatile qualified.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(&amp;)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis> (the argument in this case
+ is a reference to a function).
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_union"><indexterm type="class_name"><primary>is_union</primary><secondary>is_union</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_union"> is_union</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_union</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ union type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Currently requires some kind of compiler support, otherwise unions are identified
+ as classes.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 9.5.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Without (some as
+ yet unspecified) help from the compiler, we cannot distinguish between union
+ and class types using only standard C++, as a result this type will never
+ inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ unless the user explicitly specializes the template for their user-defined
+ union types, or unless the compiler supplies some unspecified intrinsic that
+ implements this functionality. Currently (May 2005) only Visual C++ 8 has
+ the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to make this trait "just work" without user intervention.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_union</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_unsigned"><indexterm type="class_name"><primary>is_unsigned</primary><secondary>is_unsigned</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_unsigned"> is_unsigned</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_unsigned</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an unsigned integer type
+ or an enumerated type with an underlying unsigned integer type, then inherits
+ from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1, 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_unsigned</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myclass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ whose value depends upon the signedness of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase>
+ <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_void"><indexterm type="class_name"><primary>is_void</primary><secondary>is_void</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_void"> is_void</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_void</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ void type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p9.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_void</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_volatile"><indexterm type="class_name"><primary>is_volatile</primary><secondary>is_volatile</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.is_volatile"> is_volatile</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_volatile</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (top level) volatile-qualified
+ type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">volatile</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase>
+ <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the volatile qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.make_signed"><indexterm type="class_name"><primary>make_signed</primary><secondary>make_signed</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.make_signed"> make_signed</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">make_signed</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If T is a signed integer type then
+ the same type as T, if T is an unsigned integer type then the corresponding
+ signed type. Otherwise if T is an enumerated or character type (char or wchar_t)
+ then a signed integer type with the same width as T.
+ </para>
+ <para>
+ If T has any cv-qualifiers then these are also present on the result type.
+ </para>
+ <para>
+ <emphasis role="bold">Requires:</emphasis> T must be an integer or enumerated
+ type, and must not be the type bool.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">make_signed</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="keyword">long</phrase>
+ <phrase role="keyword">long</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A signed integer type with the same width as the enum.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A signed integer type with the same width as wchar_t.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.make_unsigned"><indexterm type="class_name"><primary>make_unsigned</primary><secondary>make_unsigned</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.make_unsigned"> make_unsigned</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">make_unsigned</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If T is a unsigned integer type then
+ the same type as T, if T is an signed integer type then the corresponding
+ unsigned type. Otherwise if T is an enumerated or character type (char or
+ wchar_t) then an unsigned integer type with the same width as T.
+ </para>
+ <para>
+ If T has any cv-qualifiers then these are also present on the result type.
+ </para>
+ <para>
+ <emphasis role="bold">Requires:</emphasis> T must be an integer or enumerated
+ type, and must not be the type bool.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">make_unsigned</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An unsigned integer type with the same width as the enum.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An unsigned integer type with the same width as wchar_t.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.promote"><indexterm type="class_name"><primary>promote</primary><secondary>promote</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.promote"> promote</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">promote</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If integral or floating point promotion
+ can be applied to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ then applies integral and floating point promotions to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ See also <link linkend="boost_typetraits.reference.integral_promotion">integral_promotion</link>
+ and <link linkend="boost_typetraits.reference.floating_point_promotion">floating_point_promotion</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.5 except 4.5/3
+ (integral bit-field) and 4.6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">promote</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.rank"><indexterm type="class_name"><primary>rank</primary><secondary>rank</secondary></indexterm><indexterm type="class_name"><primary>integral_constant</primary><secondary>rank</secondary></indexterm><indexterm><primary>rank</primary><secondary>integral_constant</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.rank"> rank</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">rank</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template rank inherits from
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> is the
+ number of array dimensions in type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not an array type,
+ then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> is zero.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">rank</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[]&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">3</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">1</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>1</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>2</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.remove_all_extents"><indexterm type="class_name"><primary>remove_all_extents</primary><secondary>remove_all_extents</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.remove_all_extents"> remove_all_extents</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_all_extents</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is an array type, then removes all of the array bounds on <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_all_extents</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_const"><indexterm type="class_name"><primary>remove_const</primary><secondary>remove_const</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.remove_const"> remove_const</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> const-qualifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_cv"><indexterm type="class_name"><primary>remove_cv</primary><secondary>remove_cv</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.remove_cv"> remove_cv</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_cv</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> cv-qualifiers removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_cv</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_extent"><indexterm type="class_name"><primary>remove_extent</primary><secondary>remove_extent</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.remove_extent"> remove_extent</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_extent</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is an array type, then removes the topmost array bound, otherwise leaves
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_extent</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">]</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_pointer"><indexterm type="class_name"><primary>remove_pointer</primary><secondary>remove_pointer</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.remove_pointer"> remove_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_pointer</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any pointer modifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">**&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_reference"><indexterm type="class_name"><primary>remove_reference</primary><secondary>remove_reference</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.remove_reference"> remove_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_reference</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any reference modifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_volatile"><indexterm type="class_name"><primary>remove_volatile</primary><secondary>remove_volatile</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.remove_volatile"> remove_volatile</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> volatile-qualifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.type_with_alignment"><indexterm type="class_name"><primary>type_with_alignment</primary><secondary>type_with_alignment</secondary></indexterm>
+ <title><link linkend="boost_typetraits.reference.type_with_alignment"> type_with_alignment</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">type_with_alignment</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> a built-in or POD type with an alignment
+ that is a multiple of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Align</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">type_with_alignment</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ </section>
+ <section id="boost_typetraits.credits">
+ <title><link linkend="boost_typetraits.credits"> Credits</link></title>
+ <para>
+ This documentation was pulled together by John Maddock, using <ulink url="../../../../doc/html/quickbook.html">Boost.Quickbook</ulink>
+ and <ulink url="../../../../doc/html/boostbook.html">Boost.DocBook</ulink>.
+ </para>
+ <para>
+ The original version of this library was created by Steve Cleary, Beman Dawes,
+ Howard Hinnant, and John Maddock. John Maddock is the current maintainer of
+ the library.
+ </para>
+ <para>
+ This version of type traits library is based on contributions by Adobe Systems
+ Inc, David Abrahams, Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant,
+ Jesse Jones, Mat Marcus, Itay Maman, John Maddock, Thorsten Ottosen, Robert
+ Ramey and Jeremy Siek.
+ </para>
+ <para>
+ Mat Marcus and Jesse Jones invented, and <ulink url="http://opensource.adobe.com/project4/project.shtml">published
+ a paper describing</ulink>, the partial specialization workarounds used in
+ this library.
+ </para>
+ <para>
+ Aleksey Gurtovoy added MPL integration to the library.
+ </para>
+ <para>
+ The <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link>
+ template is based on code originally devised by Andrei Alexandrescu, see "<ulink url="http://www.cuj.com/experts/1810/alexandr.htm?topic=experts">Generic&lt;Programming&gt;:
+ Mappings between Types and Values</ulink>".
+ </para>
+ <para>
+ The latest version of this library and documentation can be found at <ulink url="http://www.boost.org">www.boost.org</ulink>. Bugs, suggestions and discussion
+ should be directed to boost@lists.boost.org (see <ulink url="http://www.boost.org/more/mailing_lists.htm#main">www.boost.org/more/mailing_lists.htm#main</ulink>
+ for subscription details).
+ </para>
+ </section>
+
+ <section id="boost_typetraits.ignored_section">
+ <title>This section must not be indexed.</title>
+ <?BoostAutoIndex IgnoreSection?>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ </section>
+
+ <section id="boost_typetraits.ignored_block"><indexterm type="class_name"><primary>add_volatile</primary><secondary>This section contains one block that must not be indexed and one that should be.</secondary></indexterm><indexterm><primary>This section contains one block that must not be indexed and one that should be.</primary><secondary>add_volatile</secondary></indexterm>
+ <title>This section contains one block that must not be indexed and one that should be.</title>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">
+ <?BoostAutoIndex IgnoreBlock?>
+ template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">
+ template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ </section>
+
+
+ <index type="class_name">
+ <title>Class Index</title>
+ </index>
+ <index type="typedef_name">
+ <title>Typedef Index</title>
+ </index>
+ <index type="macro_name">
+ <title>Macro Index</title>
+ </index>
+ <index type="test_index_1">
+ <title>Index Test 1</title>
+ </index>
+ <index type="test_index_2">
+ <title>Index Test 2</title>
+ </index>
+ <index/>
+
+</chapter> \ No newline at end of file
diff --git a/tools/auto_index/test/test2.gold b/tools/auto_index/test/test2.gold
new file mode 100644
index 0000000000..154af9abf4
--- /dev/null
+++ b/tools/auto_index/test/test2.gold
@@ -0,0 +1,6671 @@
+<?xml version="1.0"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!--
+
+This file is based upon the type traits docs, but has had additional XML elements added to it
+to ensure complete testing.
+
+-->
+
+<chapter xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" id="boost_typetraits" rev:last-revision="$Date: 2008-11-28 12:41:45 +0000 (Fri, 28 Nov 2008) $">
+ <chapterinfo><author>
+ <firstname>various</firstname> <surname>authors</surname>
+ </author><copyright>
+ <year>2000</year> <year>2006</year> <holder>Adobe Systems Inc, David Abrahams,
+ Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant, Jesse Jones, Mat
+ Marcus, Itay Maman, John Maddock, Alexander Nasonov, Thorsten Ottosen, Robert
+ Ramey and Jeremy Siek</holder>
+ </copyright><legalnotice>
+ <para>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
+ </para>
+ </legalnotice></chapterinfo>
+ <title>Boost.TypeTraits</title>
+ <para>
+ A printer-friendly <ulink url="http://svn.boost.org/svn/boost/sandbox/pdf/type_traits/release/type_traits.pdf">PDF
+ version of this manual is also available</ulink>.
+ </para>
+ <section id="boost_typetraits.intro">
+ <title><link linkend="boost_typetraits.intro"> Introduction</link></title>
+ <para>
+ The Boost type-traits library contains a set of very specific traits classes,
+ each of which encapsulate a single trait from the C++ type system; for example,
+ is a type a pointer or a reference type? Or does a type have a trivial constructor,
+ or a const-qualifier?
+ </para>
+ <para>
+ The type-traits classes share a unified design: each class inherits from a
+ the type <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the type has the specified property and inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ otherwise.
+ </para>
+ <para>
+ The type-traits library also contains a set of classes that perform a specific
+ transformation on a type; for example, they can remove a top-level const or
+ volatile qualifier from a type. Each class that performs a transformation defines
+ a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of the transformation.
+ </para>
+ </section>
+ <section id="boost_typetraits.background">
+ <title><link linkend="boost_typetraits.background"> Background and Tutorial</link></title>
+ <para>
+ The following is an updated version of the article "C++ Type traits"
+ by John Maddock and Steve Cleary that appeared in the October 2000 issue of
+ <ulink url="http://www.ddj.com">Dr Dobb's Journal</ulink>.
+ </para>
+ <para>
+ Generic programming (writing code which works with any data type meeting a
+ set of requirements) has become the method of choice for providing reusable
+ code. However, there are times in generic programming when "generic"
+ just isn't good enough - sometimes the differences between types are too large
+ for an efficient generic implementation. This is when the traits technique
+ becomes important - by encapsulating those properties that need to be considered
+ on a type by type basis inside a traits class, we can minimize the amount of
+ code that has to differ from one type to another, and maximize the amount of
+ generic code.
+ </para>
+ <?dbfo keep-together="auto" ?>
+ <para>
+ <indexterm>
+ <primary>Foo1</primary>
+ </indexterm>
+ Consider an example: when working with character strings, one common operation
+ is to determine the length of a null terminated string. Clearly it's possible
+ to write generic code that can do this, but it turns out that there are much
+ more efficient methods available: for example, the C library functions <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">strlen</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">wcslen</phrase></computeroutput>
+ are usually written in assembler, and with suitable hardware support can be
+ considerably faster than a generic version written in C++. The authors of the
+ C++ standard library realized this, and abstracted the properties of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">wchar_t</phrase></computeroutput>
+ into the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput>.
+ Generic code that works with character strings can simply use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase><phrase role="special">&lt;&gt;::</phrase><phrase role="identifier">length</phrase></computeroutput> to determine the length of a null
+ terminated string, safe in the knowledge that specializations of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput> will use the most appropriate
+ method available to them.
+ </para>
+ <anchor id="boost_typetraits.background.type_traits"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.type_traits">Type Traits</link>
+ </bridgehead>
+ <para>
+ Class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput> is a classic
+ example of a collection of type specific properties wrapped up in a single
+ class - what Nathan Myers termed a <emphasis>baggage class</emphasis><link linkend="background.references">[1]</link>. In the Boost type-traits library,
+ we<link linkend="background.references">[2]</link> have written a set of very
+ specific traits classes, each of which encapsulate a single trait from the
+ C++ type system; for example, is a type a pointer or a reference type? Or does
+ a type have a trivial constructor, or a const-qualifier? The type-traits classes
+ share a unified design: each class inherits from a the type <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the type has the specified property and inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ otherwise. As we will show, these classes can be used in generic programming
+ to determine the properties of a given type and introduce optimizations that
+ are appropriate for that case.
+ </para>
+ <para>
+ The type-traits library also contains a set of classes that perform a specific
+ transformation on a type; for example, they can remove a top-level const or
+ volatile qualifier from a type. Each class that performs a transformation defines
+ a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of the transformation. All of the type-traits classes are
+ defined inside namespace <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase></computeroutput>;
+ for brevity, namespace-qualification is omitted in most of the code samples
+ given.
+ </para>
+ <anchor id="boost_typetraits.background.implementation"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.implementation">Implementation</link>
+ </bridgehead>
+ <para>
+ There are far too many separate classes contained in the type-traits library
+ to give a full implementation here - see the source code in the Boost library
+ for the full details - however, most of the implementation is fairly repetitive
+ anyway, so here we will just give you a flavor for how some of the classes
+ are implemented. Beginning with possibly the simplest class in the library,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits
+ from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ only if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>.
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ Here we define a primary version of the template class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_void">is_void</link></computeroutput>,
+ and provide a full-specialization when <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>. While full specialization
+ of a template class is an important technique, sometimes we need a solution
+ that is halfway between a fully generic solution, and a full specialization.
+ This is exactly the situation for which the standards committee defined partial
+ template-class specialization. As an example, consider the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput>:
+ here we needed a primary version that handles all the cases where T is not
+ a pointer, and a partial specialization to handle all the cases where T is
+ a pointer:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">*&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ The syntax for partial specialization is somewhat arcane and could easily occupy
+ an article in its own right; like full specialization, in order to write a
+ partial specialization for a class, you must first declare the primary template.
+ The partial specialization contains an extra &lt;...&gt; after the class name
+ that contains the partial specialization parameters; these define the types
+ that will bind to that partial specialization rather than the default template.
+ The rules for what can appear in a partial specialization are somewhat convoluted,
+ but as a rule of thumb if you can legally write two function overloads of the
+ form:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">);</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase><phrase role="identifier">U</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <para>
+ Then you can also write a partial specialization of the form:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <phrase role="identifier">c</phrase><phrase role="special">{</phrase> <phrase role="comment">/*details*/</phrase> <phrase role="special">};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <phrase role="identifier">c</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;{</phrase> <phrase role="comment">/*details*/</phrase> <phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ This rule is by no means foolproof, but it is reasonably simple to remember
+ and close enough to the actual rule to be useful for everyday use.
+ </para>
+ <para>
+ As a more complex example of partial specialization consider the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput>. This
+ class defines a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the same type as T but with any top-level array bounds removed; this
+ is an example of a traits class that performs a transformation on a type:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link>
+<phrase role="special">{</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">[</phrase><phrase role="identifier">N</phrase><phrase role="special">]&gt;</phrase>
+<phrase role="special">{</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ The aim of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.remove_extent">remove_extent</link></computeroutput>
+ is this: imagine a generic algorithm that is passed an array type as a template
+ parameter, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.remove_extent">remove_extent</link></computeroutput>
+ provides a means of determining the underlying type of the array. For example
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">][</phrase><phrase role="number">5</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> would evaluate to the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">5</phrase><phrase role="special">]</phrase></computeroutput>. This example also shows that the number of
+ template parameters in a partial specialization does not have to match the
+ number in the default template. However, the number of parameters that appear
+ after the class name do have to match the number and type of the parameters
+ in the default template.
+ </para>
+ <anchor id="boost_typetraits.background.optimized_copy"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.optimized_copy">Optimized copy</link>
+ </bridgehead>
+ <para>
+ As an example of how the type traits classes can be used, consider the standard
+ library algorithm copy:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Iter1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Iter2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">Iter2</phrase> <phrase role="identifier">copy</phrase><phrase role="special">(</phrase><phrase role="identifier">Iter1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">Iter1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">Iter2</phrase> <phrase role="identifier">out</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <para>
+ Obviously, there's no problem writing a generic version of copy that works
+ for all iterator types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput>; however, there are
+ some circumstances when the copy operation can best be performed by a call
+ to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>. In order to implement
+ copy in terms of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput> all
+ of the following conditions need to be met:
+ </para>
+ <itemizedlist>
+ <listitem>
+ Both of the iterator types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput> must be pointers.
+ </listitem>
+ <listitem>
+ Both <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput> must point to the same type - excluding
+ const and volatile-qualifiers.
+ </listitem>
+ <listitem>
+ The type pointed to by <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ must have a trivial assignment operator.
+ </listitem>
+ </itemizedlist>
+ <para>
+ By trivial assignment operator we mean that the type is either a scalar type<link linkend="background.references">[3]</link> or:
+ </para>
+ <itemizedlist>
+ <listitem>
+ The type has no user defined assignment operator.
+ </listitem>
+ <listitem>
+ The type does not have any data members that are references.
+ </listitem>
+ <listitem>
+ All base classes, and all data member objects must have trivial assignment
+ operators.
+ </listitem>
+ </itemizedlist>
+ <para>
+ If all these conditions are met then a type can be copied using <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput> rather than using a compiler generated
+ assignment operator. The type-traits library provides a class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>,
+ such that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is true only if T has a trivial assignment
+ operator. This class "just works" for scalar types, but has to be
+ explicitly specialised for class/struct types that also happen to have a trivial
+ assignment operator. In other words if <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link>
+ gives the wrong answer, it will give the "safe" wrong answer - that
+ trivial assignment is not allowable.
+ </para>
+ <para>
+ The code for an optimized version of copy that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>
+ where appropriate is given in <link linkend="boost_typetraits.examples.copy">the
+ examples</link>. The code begins by defining a template function <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">do_copy</phrase></computeroutput> that performs a "slow but safe"
+ copy. The last parameter passed to this function may be either a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ or a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">false_type</link></computeroutput>.
+ Following that there is an overload of do<emphasis role="underline">copy that
+ uses `memcpy`: this time the iterators are required to actually be pointers
+ to the same type, and the final parameter must be a `</emphasis>_true_type<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">.</phrase> <phrase role="identifier">Finally</phrase><phrase role="special">,</phrase> <phrase role="identifier">the</phrase> <phrase role="identifier">version</phrase>
+ <phrase role="identifier">of</phrase> </computeroutput>copy<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="identifier">calls</phrase>
+ </computeroutput>do<emphasis role="underline">copy`, passing `</emphasis>_has_trivial_assign&lt;value_type&gt;()`
+ as the final parameter: this will dispatch to the optimized version where appropriate,
+ otherwise it will call the "slow but safe version".
+ </para>
+ <anchor id="boost_typetraits.background.was_it_worth_it_"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.was_it_worth_it_">Was it worth it?</link>
+ </bridgehead>
+ <para>
+ It has often been repeated in these columns that "premature optimization
+ is the root of all evil" <link linkend="background.references">[4]</link>.
+ So the question must be asked: was our optimization premature? To put this
+ in perspective the timings for our version of copy compared a conventional
+ generic copy<link linkend="background.references">[5]</link> are shown in table
+ 1.
+ </para>
+ <para>
+ Clearly the optimization makes a difference in this case; but, to be fair,
+ the timings are loaded to exclude cache miss effects - without this accurate
+ comparison between algorithms becomes difficult. However, perhaps we can add
+ a couple of caveats to the premature optimization rule:
+ </para>
+ <itemizedlist>
+ <listitem>
+ If you use the right algorithm for the job in the first place then optimization
+ will not be required; in some cases, memcpy is the right algorithm.
+ </listitem>
+ <listitem>
+ If a component is going to be reused in many places by many people then optimizations
+ may well be worthwhile where they would not be so for a single case - in
+ other words, the likelihood that the optimization will be absolutely necessary
+ somewhere, sometime is that much higher. Just as importantly the perceived
+ value of the stock implementation will be higher: there is no point standardizing
+ an algorithm if users reject it on the grounds that there are better, more
+ heavily optimized versions available.
+ </listitem>
+ </itemizedlist>
+ <table frame="all"> <title>Time taken to copy 1000 elements using `copy&lt;const
+ T*, T*&gt;` (times in micro-seconds)</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Version
+ </para>
+ </entry><entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ Time
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ "Optimized" copy
+ </para>
+ </entry><entry>
+ <para>
+ char
+ </para>
+ </entry><entry>
+ <para>
+ 0.99
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Conventional copy
+ </para>
+ </entry><entry>
+ <para>
+ char
+ </para>
+ </entry><entry>
+ <para>
+ 8.07
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ "Optimized" copy
+ </para>
+ </entry><entry>
+ <para>
+ int
+ </para>
+ </entry><entry>
+ <para>
+ 2.52
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Conventional copy
+ </para>
+ </entry><entry>
+ <para>
+ int
+ </para>
+ </entry><entry>
+ <para>
+ 8.02
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table> <anchor id="boost_typetraits.background.pair_of_references"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.pair_of_references">Pair of References</link>
+ </bridgehead>
+ <para>
+ The optimized copy example shows how type traits may be used to perform optimization
+ decisions at compile-time. Another important usage of type traits is to allow
+ code to compile that otherwise would not do so unless excessive partial specialization
+ is used. This is possible by delegating partial specialization to the type
+ traits classes. Our example for this form of usage is a pair that can hold
+ references <link linkend="background.references">[6]</link>.
+ </para>
+ <para>
+ First, let us examine the definition of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase></computeroutput>, omitting
+ the comparison operators, default constructor, and template copy constructor
+ for simplicity:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">pair</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T1</phrase> <phrase role="identifier">first_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T2</phrase> <phrase role="identifier">second_type</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">T1</phrase> <phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">T2</phrase> <phrase role="identifier">second</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">pair</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">nfirst</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T2</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase>
+<phrase role="special">:</phrase><phrase role="identifier">first</phrase><phrase role="special">(</phrase><phrase role="identifier">nfirst</phrase><phrase role="special">),</phrase> <phrase role="identifier">second</phrase><phrase role="special">(</phrase><phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <phrase role="special">}</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ Now, this "pair" cannot hold references as it currently stands, because
+ the constructor would require taking a reference to a reference, which is currently
+ illegal <link linkend="background.references">[7]</link>. Let us consider what
+ the constructor's parameters would have to be in order to allow "pair"
+ to hold non-reference types, references, and constant references:
+ </para>
+ <table frame="all"> <title>Required Constructor Argument Types</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of parameter to initializing constructor
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ A little familiarity with the type traits classes allows us to construct a
+ single mapping that allows us to determine the type of parameter from the type
+ of the contained class. The type traits classes provide a transformation <link linkend="boost_typetraits.reference.add_reference">add_reference</link>, which
+ adds a reference to its type, unless it is already a reference.
+ </para>
+ <table frame="all"> <title>Using add_reference to synthesize the correct constructor
+ type</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ const T
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ T &amp; [8]
+ </para>
+ </entry><entry>
+ <para>
+ T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ This allows us to build a primary template definition for <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput>
+ that can contain non-reference types, reference types, and constant reference
+ types:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">pair</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T1</phrase> <phrase role="identifier">first_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T2</phrase> <phrase role="identifier">second_type</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">T1</phrase> <phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">T2</phrase> <phrase role="identifier">second</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">pair</phrase><phrase role="special">(</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">nfirst</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase>
+<phrase role="special">:</phrase><phrase role="identifier">first</phrase><phrase role="special">(</phrase><phrase role="identifier">nfirst</phrase><phrase role="special">),</phrase> <phrase role="identifier">second</phrase><phrase role="special">(</phrase><phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <phrase role="special">}</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ Add back in the standard comparison operators, default constructor, and template
+ copy constructor (which are all the same), and you have a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase></computeroutput> that
+ can hold reference types!
+ </para>
+ <para>
+ This same extension could have been done using partial template specialization
+ of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput>, but to specialize
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput> in this way would require
+ three partial specializations, plus the primary template. Type traits allows
+ us to define a single primary template that adjusts itself auto-magically to
+ any of these partial specializations, instead of a brute-force partial specialization
+ approach. Using type traits in this fashion allows programmers to delegate
+ partial specialization to the type traits classes, resulting in code that is
+ easier to maintain and easier to understand.
+ </para>
+ <anchor id="boost_typetraits.background.conclusion"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.conclusion">Conclusion</link>
+ </bridgehead>
+ <para>
+ We hope that in this article we have been able to give you some idea of what
+ type-traits are all about. A more complete listing of the available classes
+ are in the boost documentation, along with further examples using type traits.
+ Templates have enabled C++ uses to take the advantage of the code reuse that
+ generic programming brings; hopefully this article has shown that generic programming
+ does not have to sink to the lowest common denominator, and that templates
+ can be optimal as well as generic.
+ </para>
+ <anchor id="boost_typetraits.background.acknowledgements"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.acknowledgements">Acknowledgements</link>
+ </bridgehead>
+ <para>
+ The authors would like to thank Beman Dawes and Howard Hinnant for their helpful
+ comments when preparing this article.
+ </para>
+ <anchor id="background.references"/> <anchor id="boost_typetraits.background.references"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.references">References</link>
+ </bridgehead>
+ <orderedlist inheritnum="ignore" continuation="restarts">
+ <listitem>
+ Nathan C. Myers, C++ Report, June 1995.
+ </listitem>
+ <listitem>
+ The type traits library is based upon contributions by Steve Cleary, Beman
+ Dawes, Howard Hinnant and John Maddock: it can be found at www.boost.org.
+ </listitem>
+ <listitem>
+ A scalar type is an arithmetic type (i.e. a built-in integer or floating
+ point type), an enumeration type, a pointer, a pointer to member, or a const-
+ or volatile-qualified version of one of these types.
+ </listitem>
+ <listitem>
+ This quote is from Donald Knuth, ACM Computing Surveys, December 1974, pg
+ 268.
+ </listitem>
+ <listitem>
+ The test code is available as part of the boost utility library (see algo_opt_examples.cpp),
+ the code was compiled with gcc 2.95 with all optimisations turned on, tests
+ were conducted on a 400MHz Pentium II machine running Microsoft Windows 98.
+ </listitem>
+ <listitem>
+ John Maddock and Howard Hinnant have submitted a "compressed_pair"
+ library to Boost, which uses a technique similar to the one described here
+ to hold references. Their pair also uses type traits to determine if any
+ of the types are empty, and will derive instead of contain to conserve space
+ -- hence the name "compressed".
+ </listitem>
+ <listitem>
+ This is actually an issue with the C++ Core Language Working Group (issue
+ #106), submitted by Bjarne Stroustrup. The tentative resolution is to allow
+ a "reference to a reference to T" to mean the same thing as a "reference
+ to T", but only in template instantiation, in a method similar to multiple
+ cv-qualifiers.
+ </listitem>
+ <listitem>
+ For those of you who are wondering why this shouldn't be const-qualified,
+ remember that references are always implicitly constant (for example, you
+ can't re-assign a reference). Remember also that "const T &amp;"
+ is something completely different. For this reason, cv-qualifiers on template
+ type arguments that are references are ignored.
+ </listitem>
+ </orderedlist>
+ </section>
+ <section id="boost_typetraits.category">
+ <title><link linkend="boost_typetraits.category"> Type Traits by Category</link></title>
+ <section id="boost_typetraits.category.value_traits">
+ <title><link linkend="boost_typetraits.category.value_traits"> Type Traits
+ that Describe the Properties of a Type</link></title>
+ <para>
+ <indexterm>
+ <primary>Foo2</primary>
+ <secondary>Bar2</secondary>
+ </indexterm>
+ These traits are all <emphasis>value traits</emphasis>, which is to say the
+ traits classes all inherit from <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link>,
+ and are used to access some numerical property of a type. Often this is a
+ simple true or false Boolean value, but in a few cases may be some other
+ integer value (for example when dealing with type alignments, or array bounds:
+ see <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.alignment_of">alignment_of</link></computeroutput>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.rank">rank</link></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.extent">extent</link></computeroutput>).
+ </para>
+ <section id="boost_typetraits.category.value_traits.primary">
+ <title><link linkend="boost_typetraits.category.value_traits.primary"> Categorizing
+ a Type</link></title>
+ <para>
+ These traits identify what "kind" of type some type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is. These are split into two groups:
+ primary traits which are all mutually exclusive, and composite traits that
+ are compositions of one or more primary traits.
+ </para>
+ <para>
+ For any given type, exactly one primary type trait will inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ and all the others will inherit from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>,
+ in other words these traits are mutually exclusive.
+ </para>
+ <para>
+ This means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_integral">is_integral</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ will only ever be true for built-in types; if you want to check for a user-defined
+ class type that behaves "as if" it is an integral or floating
+ point type, then use the <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">numeric_limits</phrase>
+ <phrase role="keyword">template</phrase></computeroutput> instead.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_array">is_array</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_class">is_class</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_complex">is_complex</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_enum">is_enum</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_function">is_function</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_integral">is_integral</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_object_pointer">is_member_object_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_union">is_union</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ The following traits are made up of the union of one or more type categorizations.
+ A type may belong to more than one of these categories, in addition to
+ one of the primary categories.
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_arithmetic">is_arithmetic</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_compound">is_compound</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_fundamental">is_fundamental</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_object">is_object</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_scalar">is_scalar</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.value_traits.properties">
+ <title><link linkend="boost_typetraits.category.value_traits.properties">
+ General Type Properties</link></title>
+ <para>
+ The following templates describe the general properties of a type.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.alignment_of">alignment_of</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_assign">has_nothrow_assign</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_default_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_default_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_virtual_destructor">has_virtual_destructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_abstract">is_abstract</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_const">is_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_empty">is_empty</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_stateless">is_stateless</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_signed">is_signed</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_unsigned">is_unsigned</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_volatile">is_volatile</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.extent">extent</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.rank">rank</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.value_traits.relate">
+ <title><link linkend="boost_typetraits.category.value_traits.relate"> Relationships
+ Between Two Types</link></title>
+ <para>
+ These templates determine the whether there is a relationship between two
+ types:
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_base_of">is_base_of</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_same">is_same</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.category.transform">
+ <title><link linkend="boost_typetraits.category.transform"> Type Traits that
+ Transform One Type to Another</link></title>
+ <para>
+ The following templates transform one type to another, based upon some well-defined
+ rule. Each template has a single member called <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of applying the transformation to the template argument
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_const">add_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_cv">add_cv</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_pointer">add_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_volatile">add_volatile</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.decay">decay</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.floating_point_promotion">floating_point_promotion</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.integral_promotion">integral_promotion</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.make_signed">make_signed</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.make_unsigned">make_unsigned</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.promote">promote</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_all_extents">remove_all_extents</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_const">remove_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_cv">remove_cv</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_reference">remove_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_volatile">remove_volatile</link><phrase role="special">;</phrase>
+</programlisting>
+ <anchor id="boost_typetraits.category.transform.broken_compiler_workarounds_"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">Broken
+ Compiler Workarounds:</link>
+ </bridgehead>
+ <para>
+ For all of these templates support for partial specialization of class templates
+ is required to correctly implement the transformation. On the other hand,
+ practice shows that many of the templates from this category are very useful,
+ and often essential for implementing some generic libraries. Lack of these
+ templates is often one of the major limiting factors in porting those libraries
+ to compilers that do not yet support this language feature. As some of these
+ compilers are going to be around for a while, and at least one of them is
+ very wide-spread, it was decided that the library should provide workarounds
+ where possible.
+ </para>
+ <para>
+ The basic idea behind the workaround is to manually define full specializations
+ of all type transformation templates for all fundamental types, and all their
+ 1st and 2nd rank cv-[un]qualified derivative pointer types, and to provide
+ a user-level macro that will define all the explicit specializations needed
+ for any user-defined type T.
+ </para>
+ <para>
+ The first part guarantees the successful compilation of something like this:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">*,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="special">...</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+</programlisting>
+ <para>
+ and the second part provides the library's users with a mechanism to make
+ the above code work not only for <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput> or other built-in type,
+ but for their own types as well:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">namespace</phrase> <phrase role="identifier">myspace</phrase><phrase role="special">{</phrase>
+ <phrase role="keyword">struct</phrase> <phrase role="identifier">MyClass</phrase> <phrase role="special">{};</phrase>
+<phrase role="special">}</phrase>
+<phrase role="comment">// declare this at global scope:
+</phrase><phrase role="identifier">BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</phrase><phrase role="special">(</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">)</phrase>
+<phrase role="comment">// transformations on myspace::MyClass now work:
+</phrase><phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="comment">// etc.
+</phrase></programlisting>
+ <para>
+ Note that the macro BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION evaluates
+ to nothing on those compilers that <emphasis role="bold">do</emphasis> support
+ partial specialization.
+ </para>
+ </section>
+ <section id="boost_typetraits.category.alignment">
+ <title><link linkend="boost_typetraits.category.alignment"> Synthesizing Types
+ with Specific Alignments</link></title>
+ <para>
+ Some low level memory management routines need to synthesize a POD type with
+ specific alignment properties. The template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.type_with_alignment">type_with_alignment</link></computeroutput>
+ finds the smallest type with a specified alignment, while template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.aligned_storage">aligned_storage</link></computeroutput>
+ creates a type with a specific size and alignment.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.type_with_alignment">type_with_alignment</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.aligned_storage">aligned_storage</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.function">
+ <title><link linkend="boost_typetraits.category.function"> Decomposing Function
+ Types</link></title>
+ <para>
+ The class template <link linkend="boost_typetraits.reference.function_traits">function_traits</link>
+ extracts information from function types (see also <link linkend="boost_typetraits.reference.is_function">is_function</link>).
+ This traits class allows you to tell how many arguments a function takes,
+ what those argument types are, and what the return type is.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.function_traits">function_traits</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.user_defined">
+ <title><link linkend="boost_typetraits.user_defined"> User Defined Specializations</link></title>
+ <para>
+ Occationally the end user may need to provide their own specialization for
+ one of the type traits - typically where intrinsic compiler support is required
+ to implement a specific trait fully. These specializations should derive from
+ boost::<link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ or boost::<link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ as appropriate:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pod</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_class</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_union</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">struct</phrase> <phrase role="identifier">my_pod</phrase><phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">my_union</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">char</phrase> <phrase role="identifier">c</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_pod</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_union">is_union</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_class">is_class</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.intrinsics">
+ <title><link linkend="boost_typetraits.intrinsics"> Support for Compiler Intrinsics</link></title>
+ <para>
+ There are some traits that can not be implemented within the current C++ language:
+ to make these traits "just work" with user defined types, some kind
+ of additional help from the compiler is required. Currently (April 2008) Visual
+ C++ 8 and 9, GNU GCC 4.3 and MWCW 9 provide the necessary intrinsics, and other
+ compilers will no doubt follow in due course.
+ </para>
+ <para>
+ The Following traits classes always need compiler support to do the right thing
+ for all types (but all have safe fallback positions if this support is unavailable):
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_union">is_union</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_pod">is_pod</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_assign">has_nothrow_assign</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_virtual_destructor">has_virtual_destructor</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following traits classes can't be portably implemented in the C++ language,
+ although in practice, the implementations do in fact do the right thing on
+ all the compilers we know about:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_empty">is_empty</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following traits classes are dependent on one or more of the above:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_class">is_class</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_stateless">is_stateless</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The hooks for compiler-intrinsic support are defined in <ulink url="../../../../boost/type_traits/intrinsics.hpp">boost/type_traits/intrinsics.hpp</ulink>,
+ adding support for new compilers is simply a matter of defining one of more
+ of the following macros:
+ </para>
+ <table frame="all"> <title>Macros for Compiler Intrinsics</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_UNION(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a union type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_POD(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a POD type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_EMPTY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is an empty struct or union
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if the default constructor for T is trivial (i.e.
+ has no effect)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_COPY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial copy constructor (and can
+ therefore be replaced by a call to memcpy)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_ASSIGN(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial assignment operator (and can
+ therefore be replaced by a call to memcpy)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_DESTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial destructor (i.e. ~T() has
+ no effect)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_CONSTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="identifier">x</phrase><phrase role="special">;</phrase></computeroutput>
+ can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_COPY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase><phrase role="special">(</phrase><phrase role="identifier">t</phrase><phrase role="special">)</phrase></computeroutput> can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_ASSIGN(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="identifier">t</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">u</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">t</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">u</phrase></computeroutput> can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_VIRTUAL_DESTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true T has a virtual destructor
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_ABSTRACT(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is an abstract type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_BASE_OF(T,U)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a base class of U
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_CLASS(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a class type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_CONVERTIBLE(T,U)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is convertible to U
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_ENUM(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true is T is an enum
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_POLYMORPHIC(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a polymorphic type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_ALIGNMENT_OF(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to the alignment requirements of type T.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.mpl">
+ <title><link linkend="boost_typetraits.mpl"> MPL Interoperability</link></title>
+ <para>
+ All the value based traits in this library conform to MPL's requirements for
+ an <ulink url="../../../../libs/mpl/doc/refmanual/integral-constant.html">Integral
+ Constant type</ulink>: that includes a number of rather intrusive workarounds
+ for broken compilers.
+ </para>
+ <para>
+ Purely as an implementation detail, this means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/bool.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">true_</phrase></computeroutput></ulink>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">false_type</link></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/bool.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">false_</phrase></computeroutput></ulink>,
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">v</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/integral-c.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">integral_c</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">v</phrase><phrase role="special">&gt;</phrase></computeroutput></ulink>
+ (provided <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>)
+ </para>
+ </section>
+ <section id="boost_typetraits.examples">
+ <title><link linkend="boost_typetraits.examples"> Examples</link></title>
+ <section id="boost_typetraits.examples.copy">
+ <title><link linkend="boost_typetraits.examples.copy"> An Optimized Version
+ of std::copy</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">copy</phrase></computeroutput>
+ that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>
+ to determine whether to use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>
+ to optimise the copy operation (see <ulink url="../../examples/copy_example.cpp">copy_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// opt::copy
+</phrase><phrase role="comment">// same semantics as std::copy
+</phrase><phrase role="comment">// calls memcpy where appropriate.
+</phrase><phrase role="comment">//
+</phrase>
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">I2</phrase> <phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">out</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">out</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">out</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">memcpy</phrase><phrase role="special">(</phrase><phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="special">(</phrase><phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">)*</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">));</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">out</phrase><phrase role="special">+(</phrase><phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">copy</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">out</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// We can copy with memcpy if T has a trivial assignment operator,
+</phrase> <phrase role="comment">// and if the iterator arguments are actually pointers (this last
+</phrase> <phrase role="comment">// requirement we detect with overload resolution):
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">&lt;</phrase><phrase role="identifier">value_type</phrase><phrase role="special">&gt;());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.fill">
+ <title><link linkend="boost_typetraits.examples.fill"> An Optimised Version
+ of std::fill</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">fill</phrase></computeroutput>
+ that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>
+ to determine whether to use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memset</phrase></computeroutput>
+ to optimise the fill operation (see <ulink url="../../examples/fill_example.cpp">fill_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// fill
+</phrase><phrase role="comment">// same as std::fill, but uses memset where appropriate
+</phrase><phrase role="comment">//
+</phrase><phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">first</phrase> <phrase role="special">=</phrase> <phrase role="identifier">val</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memset</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">I</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">fill</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// We can do an optimised fill if T has a trivial assignment
+</phrase> <phrase role="comment">// operator and if it's size is one:
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase>
+ <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">(</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase> <phrase role="special">==</phrase> <phrase role="number">1</phrase><phrase role="special">)&gt;</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.destruct">
+ <title><link linkend="boost_typetraits.examples.destruct"> An Example that
+ Omits Destructor Calls For Types with Trivial Destructors</link></title>
+ <para>
+ Demonstrates a simple algorithm that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">__has_trivial_destruct</phrase></computeroutput>
+ to determine whether to destructors need to be called (see <ulink url="../../examples/trivial_destructor_example.cpp">trivial_destructor_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// algorithm destroy_array:
+</phrase><phrase role="comment">// The reverse of std::unitialized_copy, takes a block of
+</phrase><phrase role="comment">// initialized memory and calls destructors on all objects therein.
+</phrase><phrase role="comment">//
+</phrase>
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="identifier">first</phrase><phrase role="special">-&gt;~</phrase><phrase role="identifier">T</phrase><phrase role="special">();</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase> <phrase role="comment">// namespace detail
+</phrase>
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">p1</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">p2</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">p1</phrase><phrase role="special">,</phrase> <phrase role="identifier">p2</phrase><phrase role="special">,</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.iter">
+ <title><link linkend="boost_typetraits.examples.iter"> An improved Version
+ of std::iter_swap</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iter_swap</phrase></computeroutput>
+ that use type traits to determine whether an it's arguments are proxying
+ iterators or not, if they're not then it just does a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">swap</phrase></computeroutput>
+ of it's dereferenced arguments (the same as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iter_swap</phrase></computeroutput>
+ does), however if they are proxying iterators then takes special care over
+ the swap to ensure that the algorithm works correctly for both proxying iterators,
+ and even iterators of different types (see <ulink url="../../examples/iter_swap_example.cpp">iter_swap_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// iter_swap:
+</phrase><phrase role="comment">// tests whether iterator is a proxying iterator or not, and
+</phrase><phrase role="comment">// uses optimal form accordingly:
+</phrase><phrase role="comment">//
+</phrase><phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">static</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase> <phrase role="identifier">v_t</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">v_t</phrase> <phrase role="identifier">v</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">one</phrase><phrase role="special">;</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">one</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">two</phrase><phrase role="special">;</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">two</phrase> <phrase role="special">=</phrase> <phrase role="identifier">v</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">static</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">using</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">swap</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">swap</phrase><phrase role="special">(*</phrase><phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase><phrase role="identifier">two</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">iter_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">two</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// See is both arguments are non-proxying iterators,
+</phrase> <phrase role="comment">// and if both iterator the same type:
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">reference</phrase> <phrase role="identifier">r1_t</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I2</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">reference</phrase> <phrase role="identifier">r2_t</phrase><phrase role="special">;</phrase>
+
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase>
+ <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">&lt;</phrase><phrase role="identifier">r1_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">&lt;</phrase><phrase role="identifier">r2_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_same">is_same</link><phrase role="special">&lt;</phrase><phrase role="identifier">r1_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">r2_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">;</phrase>
+
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.to_double">
+ <title><link linkend="boost_typetraits.examples.to_double"> Convert Numeric
+ Types and Enums to double</link></title>
+ <para>
+ Demonstrates a conversion of <ulink url="../../../../libs/numeric/conversion/doc/html/boost_numericconversion/definitions.html#boost_numericconversion.definitions.numeric_types">Numeric
+ Types</ulink> and enum types to double:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">double</phrase> <phrase role="identifier">to_double</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">value</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">promoted</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">numeric</phrase><phrase role="special">::</phrase><phrase role="identifier">converter</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase><phrase role="identifier">promoted</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">convert</phrase><phrase role="special">(</phrase><phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.reference">
+ <title><link linkend="boost_typetraits.reference"> Alphabetical Reference</link></title>
+ <section id="boost_typetraits.reference.add_const">
+ <title><link linkend="boost_typetraits.reference.add_const"> add_const</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ <secondary>two</secondary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">const</phrase></computeroutput> for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_cv">
+ <title><link linkend="boost_typetraits.reference.add_cv"> add_cv</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ <secondary>two</secondary>
+ <tertiary>three</tertiary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_cv</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_cv</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_pointer">
+ <title><link linkend="boost_typetraits.reference.add_pointer"> add_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_pointer</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">*</phrase></computeroutput>.
+ </para>
+ <para>
+ The rationale for this template is that it produces the same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">TYPEOF</phrase><phrase role="special">(&amp;</phrase><phrase role="identifier">t</phrase><phrase role="special">)</phrase></computeroutput>, where
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">t</phrase></computeroutput> is an object of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">**</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">**</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_reference">
+ <title><link linkend="boost_typetraits.reference.add_reference"> add_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_reference</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is not a reference type then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase></computeroutput>, otherwise <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_volatile">
+ <title><link linkend="boost_typetraits.reference.add_volatile"> add_volatile</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput> for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.aligned_storage">
+ <title><link linkend="boost_typetraits.reference.aligned_storage"> aligned_storage</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">aligned_storage</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> a built-in or POD type with size
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Size</phrase></computeroutput> and an alignment that
+ is a multiple of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Align</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">aligned_storage</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.alignment_of">
+ <title><link linkend="boost_typetraits.reference.alignment_of"> alignment_of</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">alignment_of</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template alignment<emphasis role="underline">of inherits from `</emphasis>_integral_constant&lt;std::size_t,
+ ALIGNOF(T)&gt;<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">,</phrase> <phrase role="identifier">where</phrase>
+ </computeroutput>ALIGNOF(T)` is the alignment of type T.
+ </para>
+ <para>
+ <emphasis>Note: strictly speaking you should only rely on the value of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> being
+ a multiple of the true alignment of T, although in practice it does compute
+ the correct value in all the cases we know about.</emphasis>
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">alignment_of</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ with value <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.decay">
+ <title><link linkend="boost_typetraits.reference.decay"> decay</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">decay</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> Let <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>
+ be the result of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>, then if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>
+ is an array type, the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;*</phrase></computeroutput>,
+ otherwise if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput> is a function
+ type then the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase><phrase role="special">*</phrase></computeroutput>, otherwise the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">decay</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">(&amp;)[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">(&amp;)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.extent">
+ <title><link linkend="boost_typetraits.reference.extent"> extent</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">extent</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template extent inherits
+ from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)&gt;</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)</phrase></computeroutput> is the number of elements in the N'th array
+ dimention of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not an array type,
+ or if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">N</phrase> <phrase role="special">&gt;</phrase>
+ <link linkend="boost_typetraits.reference.rank">rank</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>, or if the N'th array bound is incomplete,
+ then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)</phrase></computeroutput> is zero.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">extent</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">1</phrase><phrase role="special">]&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">],</phrase>
+ <phrase role="number">1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">3</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>4</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">],</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>2</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.floating_point_promotion">
+ <title><link linkend="boost_typetraits.reference.floating_point_promotion">
+ floating_point_promotion</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">floating_point_promotion</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If floating point promotion can be
+ applied to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ then applies floating point promotion to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">float</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.function_traits">
+ <title><link linkend="boost_typetraits.reference.function_traits"> function_traits</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">F</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">function_traits</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">static</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">arity</phrase> <phrase role="special">=</phrase> <replaceable>see-below</replaceable><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">result_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> arg<replaceable>N</replaceable>_type<phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ The class template function_traits will only compile if:
+ </para>
+ <itemizedlist>
+ <listitem>
+ The compiler supports partial specialization of class templates.
+ </listitem>
+ <listitem>
+ The template argument <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>
+ is a <emphasis>function type</emphasis>, note that this <emphasis><emphasis role="bold">is not</emphasis></emphasis> the same thing as a <emphasis>pointer
+ to a function</emphasis>.
+ </listitem>
+ </itemizedlist>
+ <tip>
+ <para>
+ function_traits is intended to introspect only C++ functions of the form
+ R (), R( A1 ), R ( A1, ... etc. ) and not function pointers or class member
+ functions. To convert a function pointer type to a suitable type use <link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link>.
+ </para>
+ </tip>
+ <table frame="all"> <title>Function Traits Members</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Member
+ </para>
+ </entry><entry>
+ <para>
+ Description
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that gives the number of arguments
+ accepted by the function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type returned by function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase>arg<replaceable>N</replaceable>_type</computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The <replaceable>N</replaceable>th argument type of function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="number">1</phrase> <phrase role="special">&lt;=</phrase>
+ <phrase role="identifier">N</phrase> <phrase role="special">&lt;=</phrase>
+ <phrase role="identifier">arity</phrase></computeroutput> of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table> <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 0.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 1.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 4.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">long</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arg1_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arg4_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase><phrase role="special">*</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arg5_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A compiler error: there is no <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">arg5_type</phrase></computeroutput>
+ since there are only four arguments.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A compiler error: argument type is a <emphasis>function pointer</emphasis>,
+ and not a <emphasis>function type</emphasis>.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_assign">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_assign"> has_nothrow_assign</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_assign</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing assignment-operator then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_assign</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing assignment-operator;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler support to ensure that this trait "just
+ works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_assign</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_constructor">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_constructor">
+ has_nothrow_constructor</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_default_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing default-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_constructor</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing default-constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to ensure that this trait "just works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_constructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_copy">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_copy"> has_nothrow_copy</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_copy</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_copy_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing copy-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_copy</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing copy-constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to ensure that this trait "just works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_copy</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_cp_cons">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_cp_cons"> has_nothrow_copy_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_no_throw_def_cons">
+ <title><link linkend="boost_typetraits.reference.has_no_throw_def_cons"> has_nothrow_default_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_assign">
+ <title><link linkend="boost_typetraits.reference.has_trivial_assign"> has_trivial_assign</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_assign</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial assignment-operator then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ If a type has a trivial assignment-operator then the operator has the same
+ effect as copying the bits of one object to the other: calls to the operator
+ can be safely replaced with a call to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_assign
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.8p11.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_constructor">
+ <title><link linkend="boost_typetraits.reference.has_trivial_constructor">
+ has_trivial_constructor</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_default_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial default-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ If a type has a trivial default-constructor then the constructor have no
+ effect: calls to the constructor can be safely omitted. Note that using meta-programming
+ to omit a call to a single trivial-constructor call is of no benefit whatsoever.
+ However, if loops and/or exception handling code can also be omitted, then
+ some benefit in terms of code size and speed can be obtained.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_constructor
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.1p6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_copy">
+ <title><link linkend="boost_typetraits.reference.has_trivial_copy"> has_trivial_copy</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_copy</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_copy_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial copy-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ If a type has a trivial copy-constructor then the constructor has the same
+ effect as copying the bits of one object to the other: calls to the constructor
+ can be safely replaced with a call to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_copy
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.8p6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_cp_cons">
+ <title><link linkend="boost_typetraits.reference.has_trivial_cp_cons"> has_trivial_copy_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_def_cons">
+ <title><link linkend="boost_typetraits.reference.has_trivial_def_cons"> has_trivial_default_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_destructor">
+ <title><link linkend="boost_typetraits.reference.has_trivial_destructor"> has_trivial_destructor</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_destructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial destructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ If a type has a trivial destructor then the destructor has no effect: calls
+ to the destructor can be safely omitted. Note that using meta-programming
+ to omit a call to a single trivial-constructor call is of no benefit whatsoever.
+ However, if loops and/or exception handling code can also be omitted, then
+ some benefit in terms of code size and speed can be obtained.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_destructor
+ will never report that a user-defined class or struct has a trivial destructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.4p3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_virtual_destructor">
+ <title><link linkend="boost_typetraits.reference.has_virtual_destructor"> has_virtual_destructor</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_virtual_destructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a virtual destructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> This trait is provided
+ for completeness, since it's part of the Technical Report on C++ Library
+ Extensions. However, there is currently no way to portably implement this
+ trait. The default version provided always inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>,
+ and has to be explicitly specialized for types with virtual destructors unless
+ the compiler used has compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ that enable the trait to do the right thing: currently (May 2005) only Visual
+ C++ 8 and GCC-4.3 have the necessary <link linkend="boost_typetraits.intrinsics">intrinsics</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.4.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_virtual_destructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.integral_constant">
+ <title><link linkend="boost_typetraits.reference.integral_constant"> integral_constant</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">val</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">integral_constant</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">static</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value</phrase> <phrase role="special">=</phrase> <phrase role="identifier">val</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">true_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="keyword">false</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">false_type</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ Class template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_constant</phrase></computeroutput>
+ is the common base class for all the value-based type traits. The two typedef's
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">true_type</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">false_type</phrase></computeroutput> are provided for convenience:
+ most of the value traits are Boolean properties and so will inherit from
+ one of these.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.integral_promotion">
+ <title><link linkend="boost_typetraits.reference.integral_promotion"> integral_promotion</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">integral_promotion</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If integral promotion can be applied
+ to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>, then
+ applies integral promotion to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.5 except 4.5/3
+ (integral bit-field).
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">integral_promotion</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">enum</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">float_round_style</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.is_abstract">
+ <title><link linkend="boost_typetraits.reference.is_abstract"> is_abstract</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_abstract</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ abstract type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_abstract</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> The compiler must
+ support DR337 (as of April 2005: GCC 3.4, VC++ 7.1 (and later), Intel C++
+ 7 (and later), and Comeau 4.3.2). Otherwise behaves the same as <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link>;
+ this is the "safe fallback position" for which polymorphic types
+ are always regarded as potentially abstract. The macro BOOST_NO_IS_ABSTRACT
+ is used to signify that the implementation is buggy, users should check for
+ this in their own code if the "safe fallback" is not suitable for
+ their particular use-case.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">abc</phrase><phrase role="special">{</phrase> <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">abc</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_arithmetic">
+ <title><link linkend="boost_typetraits.reference.is_arithmetic"> is_arithmetic</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_arithmetic</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ arithmetic type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Arithmetic types include integral and floating point types (see also <link linkend="boost_typetraits.reference.is_integral">is_integral</link> and
+ <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link>).
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p8.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_arithmetic</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_array">
+ <title><link linkend="boost_typetraits.reference.is_array"> is_array</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_array</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ array type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_array</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can give the wrong result with function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_base_of">
+ <title><link linkend="boost_typetraits.reference.is_base_of"> is_base_of</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_base_of</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If Base is base class of type
+ Derived or if both types are the same then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ This template will detect non-public base classes, and ambiguous base classes.
+ </para>
+ <para>
+ Note that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">X</phrase><phrase role="special">,</phrase><phrase role="identifier">X</phrase><phrase role="special">&gt;</phrase></computeroutput> will always inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>.
+ <emphasis role="bold">This is the case even if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">X</phrase></computeroutput>
+ is not a class type</emphasis>. This is a change in behaviour from Boost-1.33
+ in order to track the Technical Report on C++ Library Extensions.
+ </para>
+ <para>
+ Types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput> must not be incomplete types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_base_of</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types. There are some older compilers which
+ will produce compiler errors if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput>
+ is a private base class of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput>,
+ or if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput> is an ambiguous
+ base of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput>. These compilers
+ include Borland C++, older versions of Sun Forte C++, Digital Mars C++, and
+ older versions of EDG based compilers.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">{};</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase> <phrase role="special">:</phrase>
+ <phrase role="keyword">public</phrase> <phrase role="identifier">Base</phrase><phrase role="special">{};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Base</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>: a class is regarded as it's
+ own base.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_class">
+ <title><link linkend="boost_typetraits.reference.is_class"> is_class</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_class</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ class type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 9.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_class</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Without (some as
+ yet unspecified) help from the compiler, we cannot distinguish between union
+ and class types, as a result this type will erroneously inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link> for
+ union types. See also <link linkend="boost_typetraits.reference.is_union">is_union</link>.
+ Currently (May 2005) only Visual C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to correctly identify union types, and therefore make is_class function correctly.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">MyClass</phrase><phrase role="special">;</phrase></computeroutput> then:
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_complex">
+ <title><link linkend="boost_typetraits.reference.is_complex"> is_complex</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_complex</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is a complex number type then true (of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">complex</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ for some type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>), otherwise
+ false.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 26.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_complex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.is_compound">
+ <title><link linkend="boost_typetraits.reference.is_compound"> is_compound</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_compound</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ compound type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Any type that is not a fundamental type is a compound type (see also <link linkend="boost_typetraits.reference.is_fundamental">is_fundamental</link>).
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_compound</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyEnum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_const">
+ <title><link linkend="boost_typetraits.reference.is_const"> is_const</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_const</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (top level) const-qualified
+ type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the const-qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the const-qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_convertible">
+ <title><link linkend="boost_typetraits.reference.is_convertible"> is_convertible</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_convertible</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If an imaginary lvalue of type
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">From</phrase></computeroutput> is convertible to type
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput> then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ Type From must not be an incomplete type.
+ </para>
+ <para>
+ Type To must not be an incomplete, or function type.
+ </para>
+ <para>
+ No types are considered to be convertible to array types or abstract-class
+ types.
+ </para>
+ <para>
+ This template can not detect whether a converting-constructor is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">public</phrase></computeroutput> or not: if type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput>
+ has a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">private</phrase></computeroutput> converting constructor
+ from type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">From</phrase></computeroutput> then instantiating
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ will produce a compiler error. For this reason <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase></computeroutput>
+ can not be used to determine whether a type has a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">public</phrase></computeroutput>
+ copy-constructor or not.
+ </para>
+ <para>
+ This template will also produce compiler errors if the conversion is ambiguous,
+ for example:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">struct</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">B</phrase> <phrase role="special">:</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">C</phrase> <phrase role="special">:</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">D</phrase> <phrase role="special">:</phrase> <phrase role="identifier">B</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase> <phrase role="special">{};</phrase>
+<phrase role="comment">// This produces a compiler error, the conversion is ambiguous:
+</phrase><phrase role="keyword">bool</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">y</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">D</phrase><phrase role="special">*,</phrase><phrase role="identifier">A</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4 and 8.5.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> This template is
+ currently broken with Borland C++ Builder 5 (and earlier), for constructor-based
+ conversions, and for the Metrowerks 7 (and earlier) compiler in all cases.
+ If the compiler does not support <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_abstract">is_abstract</link></computeroutput>,
+ then the template parameter <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput>
+ must not be an abstract type.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_convertible</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*,</phrase> <phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the conversion would require a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const_cast</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_empty">
+ <title><link linkend="boost_typetraits.reference.is_empty"> is_empty</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_empty</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an empty class type then
+ inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10p5.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_empty</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> In order to correctly
+ detect empty classes this trait relies on either:
+ </para>
+ <itemizedlist>
+ <listitem>
+ the compiler implementing zero sized empty base classes, or
+ </listitem>
+ <listitem>
+ the compiler providing <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect empty classes.
+ </listitem>
+ </itemizedlist>
+ <para>
+ Can not be used with incomplete types.
+ </para>
+ <para>
+ Can not be used with union types, until is_union can be made to work.
+ </para>
+ <para>
+ If the compiler does not support partial-specialization of class templates,
+ then this template can not be used with abstract types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">struct</phrase> <phrase role="identifier">empty_class</phrase>
+ <phrase role="special">{};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_enum">
+ <title><link linkend="boost_typetraits.reference.is_enum"> is_enum</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_enum</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ enum type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_enum</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Requires a correctly
+ functioning <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link>
+ template; this means that is_enum is currently broken under Borland C++ Builder
+ 5, and for the Metrowerks compiler prior to version 8, other compilers should
+ handle this template just fine.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">enum</phrase> <phrase role="identifier">my_enum</phrase>
+ <phrase role="special">{</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">two</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_floating_point">
+ <title><link linkend="boost_typetraits.reference.is_floating_point"> is_floating_point</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_floating_point</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ floating point type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p8.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_floating_point</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_function">
+ <title><link linkend="boost_typetraits.reference.is_function"> is_function</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_function</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ function type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Note that this template does not detect <emphasis>pointers to functions</emphasis>,
+ or <emphasis>references to functions</emphasis>, these are detected by <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link> and <link linkend="boost_typetraits.reference.is_reference">is_reference</link> respectively:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">f1</phrase><phrase role="special">();</phrase> <phrase role="comment">// f1 is of function type.
+</phrase><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">f2</phrase><phrase role="special">*)();</phrase> <phrase role="comment">// f2 is a pointer to a function.
+</phrase><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">f3</phrase><phrase role="special">&amp;)();</phrase> <phrase role="comment">// f3 is a reference to a function.
+</phrase></programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2p1 and 8.3.5.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_function</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a pointer type, not a function type.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(&amp;)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a reference to a function, not a function type.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a pointer to a member function.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <tip>
+ <para>
+ Don't confuse function-types with pointers to functions:
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="identifier">f</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">);</phrase></computeroutput>
+ </para>
+ <para>
+ defines a function type,
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase> <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ declares a prototype for a function of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase></computeroutput>,
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase><phrase role="special">*</phrase>
+ <phrase role="identifier">pf</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase><phrase role="special">&amp;</phrase>
+ <phrase role="identifier">fr</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ declares a pointer and a reference to the function <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">foo</phrase></computeroutput>.
+ </para>
+ <para>
+ If you want to detect whether some type is a pointer-to-function then use:
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_function">is_function</link><phrase role="special">&lt;</phrase><link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ </para>
+ <para>
+ or for pointers to member functions you can just use <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link>
+ directly.
+ </para>
+ </tip>
+ </section>
+ <section id="boost_typetraits.reference.is_fundamental">
+ <title><link linkend="boost_typetraits.reference.is_fundamental"> is_fundamental</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_fundamental</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ fundamental type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Fundamental types include integral, floating point and void types (see also
+ <link linkend="boost_typetraits.reference.is_integral">is_integral</link>,
+ <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link>
+ and <link linkend="boost_typetraits.reference.is_void">is_void</link>)
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_fundamental</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_integral">
+ <title><link linkend="boost_typetraits.reference.is_integral"> is_integral</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_integral</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ integral type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p7.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_integral</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_function_pointer">
+ <title><link linkend="boost_typetraits.reference.is_member_function_pointer">
+ is_member_function_pointer</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_function_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member function then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the argument in this case is a pointer to a data member and not a member
+ function, see <link linkend="boost_typetraits.reference.is_member_object_pointer">is_member_object_pointer</link>
+ and <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_object_pointer">
+ <title><link linkend="boost_typetraits.reference.is_member_object_pointer">
+ is_member_object_pointer</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_object_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member object (a data member) then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the argument in this case is a pointer to a member function and not a
+ member object, see <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link>
+ and <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_pointer">
+ <title><link linkend="boost_typetraits.reference.is_member_pointer"> is_member_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member (either a function or a data member) then inherits from
+ <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_object">
+ <title><link linkend="boost_typetraits.reference.is_object"> is_object</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_object</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ object type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ All types are object types except references, void, and function types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p9.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_object</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: reference types are not
+ objects
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: function types are not
+ objects
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ void is not an object type
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_pod">
+ <title><link linkend="boost_typetraits.reference.is_pod"> is_pod</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_pod</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ POD type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ POD stands for "Plain old data". Arithmetic types, and enumeration
+ types, a pointers and pointer to members are all PODs. Classes and unions
+ can also be POD's if they have no non-static data members that are of reference
+ or non-POD type, no user defined constructors, no user defined assignment
+ operators, no private or protected non-static data members, no virtual functions
+ and no base classes. Finally, a cv-qualified POD is still a POD, as is an
+ array of PODs.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10 and 9p4 (Note
+ that POD's are also aggregates, see 8.5.1).
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, is<emphasis role="underline">pod
+ will never report that a class or struct is a POD; this is always safe, if
+ possibly sub-optimal. Currently (May 2005) only MWCW 9 and Visual C++ 8 have
+ the necessary compiler-</emphasis>_intrinsics.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pod</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_pointer">
+ <title><link linkend="boost_typetraits.reference.is_pointer"> is_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer type (includes function pointers, but excludes pointers to members)
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2p2 and 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <important>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase></computeroutput> detects "real"
+ pointer types only, and <emphasis>not</emphasis> smart pointers. Users
+ should not specialise <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase></computeroutput>
+ for smart pointer types, as doing so may cause Boost (and other third party)
+ code to fail to function correctly. Users wanting a trait to detect smart
+ pointers should create their own. However, note that there is no way in
+ general to auto-magically detect smart pointer types, so such a trait would
+ have to be partially specialised for each supported smart pointer type.
+ </para>
+ </important>
+ </section>
+ <section id="boost_typetraits.reference.is_polymorphic">
+ <title><link linkend="boost_typetraits.reference.is_polymorphic"> is_polymorphic</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_polymorphic</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ polymorphic type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> The implementation
+ requires some knowledge of the compilers ABI, it does actually seem to work
+ with the majority of compilers though.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_polymorphic</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">poly</phrase><phrase role="special">{</phrase> <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">poly</phrase><phrase role="special">();</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_same">
+ <title><link linkend="boost_typetraits.reference.is_same"> is_same</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_same</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T and U are the same types
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_same</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with abstract, incomplete or function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_scalar">
+ <title><link linkend="boost_typetraits.reference.is_scalar"> is_scalar</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_scalar</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ scalar type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Scalar types include integral, floating point, enumeration, pointer, and
+ pointer-to-member types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_scalar</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_signed">
+ <title><link linkend="boost_typetraits.reference.is_signed"> is_signed</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_signed</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an signed integer type
+ or an enumerated type with an underlying signed integer type, then inherits
+ from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1, 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_signed</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myclass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ whose value depends upon the signedness of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_stateless">
+ <title><link linkend="boost_typetraits.reference.is_stateless"> is_stateless</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_stateless</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Ff T is a stateless type then
+ inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ Type T must be a complete type.
+ </para>
+ <para>
+ A stateless type is a type that has no storage and whose constructors and
+ destructors are trivial. That means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_stateless</phrase></computeroutput>
+ only inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the following expression is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">true</phrase></computeroutput>:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_stateless</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, is_stateless will
+ never report that a class or struct is stateless; this is always safe, if
+ possibly sub-optimal. Currently (May 2005) only MWCW 9 and Visual C++ 8 have
+ the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to make this template work automatically.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.is_reference">
+ <title><link linkend="boost_typetraits.reference.is_reference"> is_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_reference</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a reference pointer type
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ may report the wrong result for function types, and for types that are both
+ const and volatile qualified.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(&amp;)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis> (the argument in this case
+ is a reference to a function).
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_union">
+ <title><link linkend="boost_typetraits.reference.is_union"> is_union</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_union</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ union type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Currently requires some kind of compiler support, otherwise unions are identified
+ as classes.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 9.5.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Without (some as
+ yet unspecified) help from the compiler, we cannot distinguish between union
+ and class types using only standard C++, as a result this type will never
+ inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ unless the user explicitly specializes the template for their user-defined
+ union types, or unless the compiler supplies some unspecified intrinsic that
+ implements this functionality. Currently (May 2005) only Visual C++ 8 has
+ the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to make this trait "just work" without user intervention.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_union</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_unsigned">
+ <title><link linkend="boost_typetraits.reference.is_unsigned"> is_unsigned</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_unsigned</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an unsigned integer type
+ or an enumerated type with an underlying unsigned integer type, then inherits
+ from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1, 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_unsigned</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myclass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ whose value depends upon the signedness of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase>
+ <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_void">
+ <title><link linkend="boost_typetraits.reference.is_void"> is_void</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_void</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ void type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p9.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_void</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_volatile">
+ <title><link linkend="boost_typetraits.reference.is_volatile"> is_volatile</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_volatile</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (top level) volatile-qualified
+ type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">volatile</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase>
+ <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the volatile qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.make_signed">
+ <title><link linkend="boost_typetraits.reference.make_signed"> make_signed</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">make_signed</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If T is a signed integer type then
+ the same type as T, if T is an unsigned integer type then the corresponding
+ signed type. Otherwise if T is an enumerated or character type (char or wchar_t)
+ then a signed integer type with the same width as T.
+ </para>
+ <para>
+ If T has any cv-qualifiers then these are also present on the result type.
+ </para>
+ <para>
+ <emphasis role="bold">Requires:</emphasis> T must be an integer or enumerated
+ type, and must not be the type bool.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">make_signed</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="keyword">long</phrase>
+ <phrase role="keyword">long</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A signed integer type with the same width as the enum.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A signed integer type with the same width as wchar_t.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.make_unsigned">
+ <title><link linkend="boost_typetraits.reference.make_unsigned"> make_unsigned</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">make_unsigned</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If T is a unsigned integer type then
+ the same type as T, if T is an signed integer type then the corresponding
+ unsigned type. Otherwise if T is an enumerated or character type (char or
+ wchar_t) then an unsigned integer type with the same width as T.
+ </para>
+ <para>
+ If T has any cv-qualifiers then these are also present on the result type.
+ </para>
+ <para>
+ <emphasis role="bold">Requires:</emphasis> T must be an integer or enumerated
+ type, and must not be the type bool.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">make_unsigned</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An unsigned integer type with the same width as the enum.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An unsigned integer type with the same width as wchar_t.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.promote">
+ <title><link linkend="boost_typetraits.reference.promote"> promote</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">promote</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If integral or floating point promotion
+ can be applied to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ then applies integral and floating point promotions to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ See also <link linkend="boost_typetraits.reference.integral_promotion">integral_promotion</link>
+ and <link linkend="boost_typetraits.reference.floating_point_promotion">floating_point_promotion</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.5 except 4.5/3
+ (integral bit-field) and 4.6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">promote</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.rank">
+ <title><link linkend="boost_typetraits.reference.rank"> rank</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">rank</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template rank inherits from
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> is the
+ number of array dimensions in type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not an array type,
+ then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> is zero.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">rank</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[]&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">3</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">1</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>1</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>2</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.remove_all_extents">
+ <title><link linkend="boost_typetraits.reference.remove_all_extents"> remove_all_extents</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_all_extents</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is an array type, then removes all of the array bounds on <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_all_extents</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_const">
+ <title><link linkend="boost_typetraits.reference.remove_const"> remove_const</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> const-qualifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_cv">
+ <title><link linkend="boost_typetraits.reference.remove_cv"> remove_cv</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_cv</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> cv-qualifiers removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_cv</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_extent">
+ <title><link linkend="boost_typetraits.reference.remove_extent"> remove_extent</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_extent</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is an array type, then removes the topmost array bound, otherwise leaves
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_extent</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">]</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_pointer">
+ <title><link linkend="boost_typetraits.reference.remove_pointer"> remove_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_pointer</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any pointer modifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">**&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_reference">
+ <title><link linkend="boost_typetraits.reference.remove_reference"> remove_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_reference</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any reference modifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_volatile">
+ <title><link linkend="boost_typetraits.reference.remove_volatile"> remove_volatile</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> volatile-qualifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.type_with_alignment">
+ <title><link linkend="boost_typetraits.reference.type_with_alignment"> type_with_alignment</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">type_with_alignment</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> a built-in or POD type with an alignment
+ that is a multiple of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Align</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">type_with_alignment</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ </section>
+ <section id="boost_typetraits.credits">
+ <title><link linkend="boost_typetraits.credits"> Credits</link></title>
+ <para>
+ This documentation was pulled together by John Maddock, using <ulink url="../../../../doc/html/quickbook.html">Boost.Quickbook</ulink>
+ and <ulink url="../../../../doc/html/boostbook.html">Boost.DocBook</ulink>.
+ </para>
+ <para>
+ The original version of this library was created by Steve Cleary, Beman Dawes,
+ Howard Hinnant, and John Maddock. John Maddock is the current maintainer of
+ the library.
+ </para>
+ <para>
+ This version of type traits library is based on contributions by Adobe Systems
+ Inc, David Abrahams, Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant,
+ Jesse Jones, Mat Marcus, Itay Maman, John Maddock, Thorsten Ottosen, Robert
+ Ramey and Jeremy Siek.
+ </para>
+ <para>
+ Mat Marcus and Jesse Jones invented, and <ulink url="http://opensource.adobe.com/project4/project.shtml">published
+ a paper describing</ulink>, the partial specialization workarounds used in
+ this library.
+ </para>
+ <para>
+ Aleksey Gurtovoy added MPL integration to the library.
+ </para>
+ <para>
+ The <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link>
+ template is based on code originally devised by Andrei Alexandrescu, see "<ulink url="http://www.cuj.com/experts/1810/alexandr.htm?topic=experts">Generic&lt;Programming&gt;:
+ Mappings between Types and Values</ulink>".
+ </para>
+ <para>
+ The latest version of this library and documentation can be found at <ulink url="http://www.boost.org">www.boost.org</ulink>. Bugs, suggestions and discussion
+ should be directed to boost@lists.boost.org (see <ulink url="http://www.boost.org/more/mailing_lists.htm#main">www.boost.org/more/mailing_lists.htm#main</ulink>
+ for subscription details).
+ </para>
+ </section>
+
+ <section id="boost_typetraits.ignored_section">
+ <title>This section must not be indexed.</title>
+ <?BoostAutoIndex IgnoreSection?>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ </section>
+
+ <section id="boost_typetraits.ignored_block">
+ <title>This section contains one block that must not be indexed and one that should be.</title>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">
+ <?BoostAutoIndex IgnoreBlock?>
+ template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">
+ template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ </section>
+
+
+ <section>
+ <title>Class Index</title>
+ <para><link linkend="idx_id_0">A</link> <link linkend="idx_id_2">C</link> <link linkend="idx_id_3">D</link> <link linkend="idx_id_4">E</link> <link linkend="idx_id_5">F</link> <link linkend="idx_id_6">H</link> <link linkend="idx_id_7">I</link> <link linkend="idx_id_8">M</link> <link linkend="idx_id_9">O</link> <link linkend="idx_id_10">P</link> <link linkend="idx_id_11">R</link> <link linkend="idx_id_13">T</link></para><variablelist><varlistentry id="idx_id_0"><term>A</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-0">add_const</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_cv"><phrase role="index-entry-level-0">add_cv</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_pointer"><phrase role="index-entry-level-0">add_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_reference"><phrase role="index-entry-level-0">add_reference</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">add_volatile</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.add_volatile"><phrase role="index-entry-level-1">add_volatile</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.ignored_block"><phrase role="index-entry-level-1">This section contains one block that must not be indexed and one that should be.</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.aligned_storage"><phrase role="index-entry-level-0">aligned_storage</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.alignment_of"><phrase role="index-entry-level-0">alignment_of</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_2"><term>C</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">Constrained Index Term</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-1">add_const</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_3"><term>D</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.decay"><phrase role="index-entry-level-0">decay</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_4"><term>E</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.extent"><phrase role="index-entry-level-0">extent</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_5"><term>F</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.floating_point_promotion"><phrase role="index-entry-level-0">floating_point_promotion</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.function_traits"><phrase role="index-entry-level-0">function_traits</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_6"><term>H</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_assign"><phrase role="index-entry-level-0">has_nothrow_assign</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_constructor"><phrase role="index-entry-level-0">has_nothrow_constructor</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_copy"><phrase role="index-entry-level-0">has_nothrow_copy</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_copy_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_copy"><phrase role="index-entry-level-1">has_nothrow_copy</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_default_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_constructor"><phrase role="index-entry-level-1">has_nothrow_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_assign"><phrase role="index-entry-level-0">has_trivial_assign</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_constructor"><phrase role="index-entry-level-0">has_trivial_constructor</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_copy"><phrase role="index-entry-level-0">has_trivial_copy</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_copy_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_trivial_copy"><phrase role="index-entry-level-1">has_trivial_copy</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_default_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_trivial_constructor"><phrase role="index-entry-level-1">has_trivial_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_destructor"><phrase role="index-entry-level-0">has_trivial_destructor</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_virtual_destructor"><phrase role="index-entry-level-0">has_virtual_destructor</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_7"><term>I</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">integral_constant</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.alignment_of"><phrase role="index-entry-level-1">alignment_of</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.extent"><phrase role="index-entry-level-1">extent</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.rank"><phrase role="index-entry-level-1">rank</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.integral_promotion"><phrase role="index-entry-level-0">integral_promotion</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_abstract"><phrase role="index-entry-level-0">is_abstract</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_arithmetic"><phrase role="index-entry-level-0">is_arithmetic</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_array"><phrase role="index-entry-level-0">is_array</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_base_of"><phrase role="index-entry-level-0">is_base_of</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_class</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_class"><phrase role="index-entry-level-1">is_class</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_complex"><phrase role="index-entry-level-0">is_complex</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_compound"><phrase role="index-entry-level-0">is_compound</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_const"><phrase role="index-entry-level-0">is_const</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_convertible"><phrase role="index-entry-level-0">is_convertible</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_empty"><phrase role="index-entry-level-0">is_empty</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_enum"><phrase role="index-entry-level-0">is_enum</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_floating_point"><phrase role="index-entry-level-0">is_floating_point</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_function"><phrase role="index-entry-level-0">is_function</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_fundamental"><phrase role="index-entry-level-0">is_fundamental</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_integral"><phrase role="index-entry-level-0">is_integral</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_function_pointer"><phrase role="index-entry-level-0">is_member_function_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_object_pointer"><phrase role="index-entry-level-0">is_member_object_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_pointer"><phrase role="index-entry-level-0">is_member_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_object"><phrase role="index-entry-level-0">is_object</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_pod</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_pod"><phrase role="index-entry-level-1">is_pod</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">is_pointer</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_pointer"><phrase role="index-entry-level-1">is_pointer</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_polymorphic"><phrase role="index-entry-level-0">is_polymorphic</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_reference"><phrase role="index-entry-level-0">is_reference</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_same"><phrase role="index-entry-level-0">is_same</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_scalar"><phrase role="index-entry-level-0">is_scalar</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_signed"><phrase role="index-entry-level-0">is_signed</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_stateless"><phrase role="index-entry-level-0">is_stateless</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_union</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_union"><phrase role="index-entry-level-1">is_union</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_unsigned"><phrase role="index-entry-level-0">is_unsigned</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_void</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_void"><phrase role="index-entry-level-1">is_void</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_volatile"><phrase role="index-entry-level-0">is_volatile</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_8"><term>M</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.make_signed"><phrase role="index-entry-level-0">make_signed</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.make_unsigned"><phrase role="index-entry-level-0">make_unsigned</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_9"><term>O</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">one</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_volatile"><phrase role="index-entry-level-1">add_volatile</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-1">two</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-2">add_const</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-2">three</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_cv"><phrase role="index-entry-level-3">add_cv</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_10"><term>P</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.promote"><phrase role="index-entry-level-0">promote</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_11"><term>R</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.rank"><phrase role="index-entry-level-0">rank</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_all_extents"><phrase role="index-entry-level-0">remove_all_extents</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_const"><phrase role="index-entry-level-0">remove_const</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_cv"><phrase role="index-entry-level-0">remove_cv</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">remove_extent</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.remove_extent"><phrase role="index-entry-level-1">remove_extent</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_pointer"><phrase role="index-entry-level-0">remove_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_reference"><phrase role="index-entry-level-0">remove_reference</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_volatile"><phrase role="index-entry-level-0">remove_volatile</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_13"><term>T</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.type_with_alignment"><phrase role="index-entry-level-0">type_with_alignment</phrase></link></para></listitem></itemizedlist></listitem></varlistentry></variablelist></section>
+ <section>
+ <title>Typedef Index</title>
+ <para><link linkend="idx_id_20">F</link> <link linkend="idx_id_26">R</link> <link linkend="idx_id_28">T</link></para><variablelist><varlistentry id="idx_id_20"><term>F</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">false_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_26"><term>R</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">result_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.function_traits"><phrase role="index-entry-level-1">function_traits</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_28"><term>T</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">true_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry></variablelist></section>
+ <section>
+ <title>Macro Index</title>
+ <para><link linkend="idx_id_31">B</link></para><variablelist><varlistentry id="idx_id_31"><term>B</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">BOOST_ALIGNMENT_OF</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.category.transform"><phrase role="index-entry-level-1">Type Traits that Transform One Type to Another</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_ASSIGN</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_CONSTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_COPY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_ASSIGN</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_CONSTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_COPY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_DESTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_VIRTUAL_DESTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_ABSTRACT</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_BASE_OF</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_CLASS</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_CONVERTIBLE</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_EMPTY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_ENUM</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_POD</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_POLYMORPHIC</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_UNION</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry></variablelist></section>
+ <section>
+ <title>Index Test 1</title>
+ <para><link linkend="idx_id_58">T</link></para><variablelist><varlistentry id="idx_id_58"><term>T</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">type-traits</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intro"><phrase role="index-entry-level-1">Introduction</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry></variablelist></section>
+ <section>
+ <title>Index Test 2</title>
+ <para><link linkend="idx_id_73">T</link></para><variablelist><varlistentry id="idx_id_73"><term>T</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">type-traits</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry></variablelist></section>
+ <section><title>Index</title><para><link linkend="idx_id_75">A</link> <link linkend="idx_id_76">B</link> <link linkend="idx_id_77">C</link> <link linkend="idx_id_78">D</link> <link linkend="idx_id_79">E</link> <link linkend="idx_id_80">F</link> <link linkend="idx_id_81">H</link> <link linkend="idx_id_82">I</link> <link linkend="idx_id_83">M</link> <link linkend="idx_id_84">O</link> <link linkend="idx_id_85">P</link> <link linkend="idx_id_86">R</link> <link linkend="idx_id_87">S</link> <link linkend="idx_id_88">T</link> <link linkend="idx_id_89">U</link></para><variablelist><varlistentry id="idx_id_75"><term>A</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">add_const</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-1">add_const</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-1">Constrained Index Term</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.add_cv"><phrase role="index-entry-level-0">add_cv</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_pointer"><phrase role="index-entry-level-0">add_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_reference"><phrase role="index-entry-level-0">add_reference</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">add_volatile</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.add_volatile"><phrase role="index-entry-level-1">add_volatile</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.ignored_block"><phrase role="index-entry-level-1">This section contains one block that must not be indexed and one that should be.</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.aligned_storage"><phrase role="index-entry-level-0">aligned_storage</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">alignment_of</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.alignment_of"><phrase role="index-entry-level-1">alignment_of</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.alignment_of"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_76"><term>B</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">Background and Tutorial</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">is_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">is_void</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">remove_extent</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">type-traits</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_ALIGNMENT_OF</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.category.transform"><phrase role="index-entry-level-1">Type Traits that Transform One Type to Another</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_ASSIGN</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_CONSTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_COPY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_ASSIGN</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_CONSTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_COPY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_DESTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_VIRTUAL_DESTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_ABSTRACT</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_BASE_OF</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_CLASS</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_CONVERTIBLE</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_EMPTY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_ENUM</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_POD</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_POLYMORPHIC</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_UNION</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_77"><term>C</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">Constrained Index Term</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-1">add_const</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_78"><term>D</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.decay"><phrase role="index-entry-level-0">decay</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_79"><term>E</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">extent</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.extent"><phrase role="index-entry-level-1">extent</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.extent"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_80"><term>F</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">false_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.floating_point_promotion"><phrase role="index-entry-level-0">floating_point_promotion</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">Foo1</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">Foo2</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-1">Bar2</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.category.value_traits"><phrase role="index-entry-level-2">Type Traits that Describe the Properties of a Type</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">function_traits</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.function_traits"><phrase role="index-entry-level-1">function_traits</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.function_traits"><phrase role="index-entry-level-1">result_type</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_81"><term>H</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_assign"><phrase role="index-entry-level-0">has_nothrow_assign</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.has_nothrow_constructor"><phrase role="index-entry-level-1">has_nothrow_constructor</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_constructor"><phrase role="index-entry-level-1">has_nothrow_default_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_copy</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.has_nothrow_copy"><phrase role="index-entry-level-1">has_nothrow_copy</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_copy"><phrase role="index-entry-level-1">has_nothrow_copy_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_copy_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_copy"><phrase role="index-entry-level-1">has_nothrow_copy</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_default_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_constructor"><phrase role="index-entry-level-1">has_nothrow_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_assign"><phrase role="index-entry-level-0">has_trivial_assign</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.has_trivial_constructor"><phrase role="index-entry-level-1">has_trivial_constructor</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_constructor"><phrase role="index-entry-level-1">has_trivial_default_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_copy</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.has_trivial_copy"><phrase role="index-entry-level-1">has_trivial_copy</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_copy"><phrase role="index-entry-level-1">has_trivial_copy_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_copy_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_trivial_copy"><phrase role="index-entry-level-1">has_trivial_copy</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_default_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_trivial_constructor"><phrase role="index-entry-level-1">has_trivial_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_destructor"><phrase role="index-entry-level-0">has_trivial_destructor</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_virtual_destructor"><phrase role="index-entry-level-0">has_virtual_destructor</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_82"><term>I</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">int</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.is_function"><phrase role="index-entry-level-1">is_function</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">integral_constant</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.alignment_of"><phrase role="index-entry-level-1">alignment_of</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.extent"><phrase role="index-entry-level-1">extent</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">false_type</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.rank"><phrase role="index-entry-level-1">rank</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">true_type</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.integral_promotion"><phrase role="index-entry-level-0">integral_promotion</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">Introduction</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intro"><phrase role="index-entry-level-1">type-traits</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_abstract"><phrase role="index-entry-level-0">is_abstract</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_arithmetic"><phrase role="index-entry-level-0">is_arithmetic</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_array"><phrase role="index-entry-level-0">is_array</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_base_of"><phrase role="index-entry-level-0">is_base_of</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_class</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_class"><phrase role="index-entry-level-1">is_class</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_complex"><phrase role="index-entry-level-0">is_complex</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_compound"><phrase role="index-entry-level-0">is_compound</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_const"><phrase role="index-entry-level-0">is_const</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_convertible"><phrase role="index-entry-level-0">is_convertible</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_empty"><phrase role="index-entry-level-0">is_empty</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_enum"><phrase role="index-entry-level-0">is_enum</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_floating_point"><phrase role="index-entry-level-0">is_floating_point</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_function</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.is_function"><phrase role="index-entry-level-1">int</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_function"><phrase role="index-entry-level-1">is_function</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_fundamental"><phrase role="index-entry-level-0">is_fundamental</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_integral"><phrase role="index-entry-level-0">is_integral</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_function_pointer"><phrase role="index-entry-level-0">is_member_function_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_object_pointer"><phrase role="index-entry-level-0">is_member_object_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_pointer"><phrase role="index-entry-level-0">is_member_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_object"><phrase role="index-entry-level-0">is_object</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_pod</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_pod"><phrase role="index-entry-level-1">is_pod</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">is_pointer</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_pointer"><phrase role="index-entry-level-1">is_pointer</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_polymorphic"><phrase role="index-entry-level-0">is_polymorphic</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_reference"><phrase role="index-entry-level-0">is_reference</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_same"><phrase role="index-entry-level-0">is_same</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_scalar"><phrase role="index-entry-level-0">is_scalar</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_signed"><phrase role="index-entry-level-0">is_signed</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_stateless"><phrase role="index-entry-level-0">is_stateless</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_union</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_union"><phrase role="index-entry-level-1">is_union</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_unsigned"><phrase role="index-entry-level-0">is_unsigned</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_void</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_void"><phrase role="index-entry-level-1">is_void</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_volatile"><phrase role="index-entry-level-0">is_volatile</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_83"><term>M</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.make_signed"><phrase role="index-entry-level-0">make_signed</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.make_unsigned"><phrase role="index-entry-level-0">make_unsigned</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_84"><term>O</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">one</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_volatile"><phrase role="index-entry-level-1">add_volatile</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-1">two</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-2">add_const</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-2">three</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_cv"><phrase role="index-entry-level-3">add_cv</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_85"><term>P</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.promote"><phrase role="index-entry-level-0">promote</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_86"><term>R</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">rank</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.rank"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.rank"><phrase role="index-entry-level-1">rank</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_all_extents"><phrase role="index-entry-level-0">remove_all_extents</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_const"><phrase role="index-entry-level-0">remove_const</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_cv"><phrase role="index-entry-level-0">remove_cv</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">remove_extent</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.remove_extent"><phrase role="index-entry-level-1">remove_extent</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_pointer"><phrase role="index-entry-level-0">remove_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_reference"><phrase role="index-entry-level-0">remove_reference</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_volatile"><phrase role="index-entry-level-0">remove_volatile</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">result_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.function_traits"><phrase role="index-entry-level-1">function_traits</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_87"><term>S</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">Support for Compiler Intrinsics</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_ALIGNMENT_OF</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_NOTHROW_ASSIGN</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_NOTHROW_CONSTRUCTOR</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_NOTHROW_COPY</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_TRIVIAL_ASSIGN</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_TRIVIAL_CONSTRUCTOR</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_TRIVIAL_COPY</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_TRIVIAL_DESTRUCTOR</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_VIRTUAL_DESTRUCTOR</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_ABSTRACT</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_BASE_OF</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_CLASS</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_CONVERTIBLE</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_EMPTY</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_ENUM</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_POD</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_POLYMORPHIC</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_UNION</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_88"><term>T</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">This section contains one block that must not be indexed and one that should be.</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.ignored_block"><phrase role="index-entry-level-1">add_volatile</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">true_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">Type Traits that Transform One Type to Another</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.category.transform"><phrase role="index-entry-level-1">BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">type-traits</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intro"><phrase role="index-entry-level-1">Introduction</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.type_with_alignment"><phrase role="index-entry-level-0">type_with_alignment</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_89"><term>U</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">User Defined Specializations</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">is_class</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">is_pod</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">is_union</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry></variablelist></section>
+
+</chapter> \ No newline at end of file
diff --git a/tools/auto_index/test/test3.gold b/tools/auto_index/test/test3.gold
new file mode 100644
index 0000000000..ad7affeb0a
--- /dev/null
+++ b/tools/auto_index/test/test3.gold
@@ -0,0 +1,6671 @@
+<?xml version="1.0"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!--
+
+This file is based upon the type traits docs, but has had additional XML elements added to it
+to ensure complete testing.
+
+-->
+
+<chapter xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" id="boost_typetraits" rev:last-revision="$Date: 2008-11-28 12:41:45 +0000 (Fri, 28 Nov 2008) $">
+ <chapterinfo><author>
+ <firstname>various</firstname> <surname>authors</surname>
+ </author><copyright>
+ <year>2000</year> <year>2006</year> <holder>Adobe Systems Inc, David Abrahams,
+ Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant, Jesse Jones, Mat
+ Marcus, Itay Maman, John Maddock, Alexander Nasonov, Thorsten Ottosen, Robert
+ Ramey and Jeremy Siek</holder>
+ </copyright><legalnotice>
+ <para>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
+ </para>
+ </legalnotice></chapterinfo>
+ <title>Boost.TypeTraits</title>
+ <para>
+ A printer-friendly <ulink url="http://svn.boost.org/svn/boost/sandbox/pdf/type_traits/release/type_traits.pdf">PDF
+ version of this manual is also available</ulink>.
+ </para>
+ <section id="boost_typetraits.intro">
+ <title><link linkend="boost_typetraits.intro"> Introduction</link></title>
+ <para>
+ The Boost type-traits library contains a set of very specific traits classes,
+ each of which encapsulate a single trait from the C++ type system; for example,
+ is a type a pointer or a reference type? Or does a type have a trivial constructor,
+ or a const-qualifier?
+ </para>
+ <para>
+ The type-traits classes share a unified design: each class inherits from a
+ the type <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the type has the specified property and inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ otherwise.
+ </para>
+ <para>
+ The type-traits library also contains a set of classes that perform a specific
+ transformation on a type; for example, they can remove a top-level const or
+ volatile qualifier from a type. Each class that performs a transformation defines
+ a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of the transformation.
+ </para>
+ </section>
+ <section id="boost_typetraits.background">
+ <title><link linkend="boost_typetraits.background"> Background and Tutorial</link></title>
+ <para>
+ The following is an updated version of the article "C++ Type traits"
+ by John Maddock and Steve Cleary that appeared in the October 2000 issue of
+ <ulink url="http://www.ddj.com">Dr Dobb's Journal</ulink>.
+ </para>
+ <para>
+ Generic programming (writing code which works with any data type meeting a
+ set of requirements) has become the method of choice for providing reusable
+ code. However, there are times in generic programming when "generic"
+ just isn't good enough - sometimes the differences between types are too large
+ for an efficient generic implementation. This is when the traits technique
+ becomes important - by encapsulating those properties that need to be considered
+ on a type by type basis inside a traits class, we can minimize the amount of
+ code that has to differ from one type to another, and maximize the amount of
+ generic code.
+ </para>
+ <?dbfo keep-together="auto" ?>
+ <para>
+ <indexterm>
+ <primary>Foo1</primary>
+ </indexterm>
+ Consider an example: when working with character strings, one common operation
+ is to determine the length of a null terminated string. Clearly it's possible
+ to write generic code that can do this, but it turns out that there are much
+ more efficient methods available: for example, the C library functions <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">strlen</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">wcslen</phrase></computeroutput>
+ are usually written in assembler, and with suitable hardware support can be
+ considerably faster than a generic version written in C++. The authors of the
+ C++ standard library realized this, and abstracted the properties of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">wchar_t</phrase></computeroutput>
+ into the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput>.
+ Generic code that works with character strings can simply use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase><phrase role="special">&lt;&gt;::</phrase><phrase role="identifier">length</phrase></computeroutput> to determine the length of a null
+ terminated string, safe in the knowledge that specializations of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput> will use the most appropriate
+ method available to them.
+ </para>
+ <anchor id="boost_typetraits.background.type_traits"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.type_traits">Type Traits</link>
+ </bridgehead>
+ <para>
+ Class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput> is a classic
+ example of a collection of type specific properties wrapped up in a single
+ class - what Nathan Myers termed a <emphasis>baggage class</emphasis><link linkend="background.references">[1]</link>. In the Boost type-traits library,
+ we<link linkend="background.references">[2]</link> have written a set of very
+ specific traits classes, each of which encapsulate a single trait from the
+ C++ type system; for example, is a type a pointer or a reference type? Or does
+ a type have a trivial constructor, or a const-qualifier? The type-traits classes
+ share a unified design: each class inherits from a the type <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the type has the specified property and inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ otherwise. As we will show, these classes can be used in generic programming
+ to determine the properties of a given type and introduce optimizations that
+ are appropriate for that case.
+ </para>
+ <para>
+ The type-traits library also contains a set of classes that perform a specific
+ transformation on a type; for example, they can remove a top-level const or
+ volatile qualifier from a type. Each class that performs a transformation defines
+ a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of the transformation. All of the type-traits classes are
+ defined inside namespace <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase></computeroutput>;
+ for brevity, namespace-qualification is omitted in most of the code samples
+ given.
+ </para>
+ <anchor id="boost_typetraits.background.implementation"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.implementation">Implementation</link>
+ </bridgehead>
+ <para>
+ There are far too many separate classes contained in the type-traits library
+ to give a full implementation here - see the source code in the Boost library
+ for the full details - however, most of the implementation is fairly repetitive
+ anyway, so here we will just give you a flavor for how some of the classes
+ are implemented. Beginning with possibly the simplest class in the library,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits
+ from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ only if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>.
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ Here we define a primary version of the template class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_void">is_void</link></computeroutput>,
+ and provide a full-specialization when <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>. While full specialization
+ of a template class is an important technique, sometimes we need a solution
+ that is halfway between a fully generic solution, and a full specialization.
+ This is exactly the situation for which the standards committee defined partial
+ template-class specialization. As an example, consider the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput>:
+ here we needed a primary version that handles all the cases where T is not
+ a pointer, and a partial specialization to handle all the cases where T is
+ a pointer:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">*&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ The syntax for partial specialization is somewhat arcane and could easily occupy
+ an article in its own right; like full specialization, in order to write a
+ partial specialization for a class, you must first declare the primary template.
+ The partial specialization contains an extra &lt;...&gt; after the class name
+ that contains the partial specialization parameters; these define the types
+ that will bind to that partial specialization rather than the default template.
+ The rules for what can appear in a partial specialization are somewhat convoluted,
+ but as a rule of thumb if you can legally write two function overloads of the
+ form:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">);</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase><phrase role="identifier">U</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <para>
+ Then you can also write a partial specialization of the form:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <phrase role="identifier">c</phrase><phrase role="special">{</phrase> <phrase role="comment">/*details*/</phrase> <phrase role="special">};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <phrase role="identifier">c</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;{</phrase> <phrase role="comment">/*details*/</phrase> <phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ This rule is by no means foolproof, but it is reasonably simple to remember
+ and close enough to the actual rule to be useful for everyday use.
+ </para>
+ <para>
+ As a more complex example of partial specialization consider the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput>. This
+ class defines a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the same type as T but with any top-level array bounds removed; this
+ is an example of a traits class that performs a transformation on a type:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link>
+<phrase role="special">{</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">[</phrase><phrase role="identifier">N</phrase><phrase role="special">]&gt;</phrase>
+<phrase role="special">{</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ The aim of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.remove_extent">remove_extent</link></computeroutput>
+ is this: imagine a generic algorithm that is passed an array type as a template
+ parameter, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.remove_extent">remove_extent</link></computeroutput>
+ provides a means of determining the underlying type of the array. For example
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">][</phrase><phrase role="number">5</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> would evaluate to the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">5</phrase><phrase role="special">]</phrase></computeroutput>. This example also shows that the number of
+ template parameters in a partial specialization does not have to match the
+ number in the default template. However, the number of parameters that appear
+ after the class name do have to match the number and type of the parameters
+ in the default template.
+ </para>
+ <anchor id="boost_typetraits.background.optimized_copy"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.optimized_copy">Optimized copy</link>
+ </bridgehead>
+ <para>
+ As an example of how the type traits classes can be used, consider the standard
+ library algorithm copy:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Iter1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Iter2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">Iter2</phrase> <phrase role="identifier">copy</phrase><phrase role="special">(</phrase><phrase role="identifier">Iter1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">Iter1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">Iter2</phrase> <phrase role="identifier">out</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <para>
+ Obviously, there's no problem writing a generic version of copy that works
+ for all iterator types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput>; however, there are
+ some circumstances when the copy operation can best be performed by a call
+ to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>. In order to implement
+ copy in terms of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput> all
+ of the following conditions need to be met:
+ </para>
+ <itemizedlist>
+ <listitem>
+ Both of the iterator types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput> must be pointers.
+ </listitem>
+ <listitem>
+ Both <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput> must point to the same type - excluding
+ const and volatile-qualifiers.
+ </listitem>
+ <listitem>
+ The type pointed to by <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ must have a trivial assignment operator.
+ </listitem>
+ </itemizedlist>
+ <para>
+ By trivial assignment operator we mean that the type is either a scalar type<link linkend="background.references">[3]</link> or:
+ </para>
+ <itemizedlist>
+ <listitem>
+ The type has no user defined assignment operator.
+ </listitem>
+ <listitem>
+ The type does not have any data members that are references.
+ </listitem>
+ <listitem>
+ All base classes, and all data member objects must have trivial assignment
+ operators.
+ </listitem>
+ </itemizedlist>
+ <para>
+ If all these conditions are met then a type can be copied using <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput> rather than using a compiler generated
+ assignment operator. The type-traits library provides a class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>,
+ such that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is true only if T has a trivial assignment
+ operator. This class "just works" for scalar types, but has to be
+ explicitly specialised for class/struct types that also happen to have a trivial
+ assignment operator. In other words if <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link>
+ gives the wrong answer, it will give the "safe" wrong answer - that
+ trivial assignment is not allowable.
+ </para>
+ <para>
+ The code for an optimized version of copy that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>
+ where appropriate is given in <link linkend="boost_typetraits.examples.copy">the
+ examples</link>. The code begins by defining a template function <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">do_copy</phrase></computeroutput> that performs a "slow but safe"
+ copy. The last parameter passed to this function may be either a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ or a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">false_type</link></computeroutput>.
+ Following that there is an overload of do<emphasis role="underline">copy that
+ uses `memcpy`: this time the iterators are required to actually be pointers
+ to the same type, and the final parameter must be a `</emphasis>_true_type<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">.</phrase> <phrase role="identifier">Finally</phrase><phrase role="special">,</phrase> <phrase role="identifier">the</phrase> <phrase role="identifier">version</phrase>
+ <phrase role="identifier">of</phrase> </computeroutput>copy<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="identifier">calls</phrase>
+ </computeroutput>do<emphasis role="underline">copy`, passing `</emphasis>_has_trivial_assign&lt;value_type&gt;()`
+ as the final parameter: this will dispatch to the optimized version where appropriate,
+ otherwise it will call the "slow but safe version".
+ </para>
+ <anchor id="boost_typetraits.background.was_it_worth_it_"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.was_it_worth_it_">Was it worth it?</link>
+ </bridgehead>
+ <para>
+ It has often been repeated in these columns that "premature optimization
+ is the root of all evil" <link linkend="background.references">[4]</link>.
+ So the question must be asked: was our optimization premature? To put this
+ in perspective the timings for our version of copy compared a conventional
+ generic copy<link linkend="background.references">[5]</link> are shown in table
+ 1.
+ </para>
+ <para>
+ Clearly the optimization makes a difference in this case; but, to be fair,
+ the timings are loaded to exclude cache miss effects - without this accurate
+ comparison between algorithms becomes difficult. However, perhaps we can add
+ a couple of caveats to the premature optimization rule:
+ </para>
+ <itemizedlist>
+ <listitem>
+ If you use the right algorithm for the job in the first place then optimization
+ will not be required; in some cases, memcpy is the right algorithm.
+ </listitem>
+ <listitem>
+ If a component is going to be reused in many places by many people then optimizations
+ may well be worthwhile where they would not be so for a single case - in
+ other words, the likelihood that the optimization will be absolutely necessary
+ somewhere, sometime is that much higher. Just as importantly the perceived
+ value of the stock implementation will be higher: there is no point standardizing
+ an algorithm if users reject it on the grounds that there are better, more
+ heavily optimized versions available.
+ </listitem>
+ </itemizedlist>
+ <table frame="all"> <title>Time taken to copy 1000 elements using `copy&lt;const
+ T*, T*&gt;` (times in micro-seconds)</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Version
+ </para>
+ </entry><entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ Time
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ "Optimized" copy
+ </para>
+ </entry><entry>
+ <para>
+ char
+ </para>
+ </entry><entry>
+ <para>
+ 0.99
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Conventional copy
+ </para>
+ </entry><entry>
+ <para>
+ char
+ </para>
+ </entry><entry>
+ <para>
+ 8.07
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ "Optimized" copy
+ </para>
+ </entry><entry>
+ <para>
+ int
+ </para>
+ </entry><entry>
+ <para>
+ 2.52
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Conventional copy
+ </para>
+ </entry><entry>
+ <para>
+ int
+ </para>
+ </entry><entry>
+ <para>
+ 8.02
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table> <anchor id="boost_typetraits.background.pair_of_references"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.pair_of_references">Pair of References</link>
+ </bridgehead>
+ <para>
+ The optimized copy example shows how type traits may be used to perform optimization
+ decisions at compile-time. Another important usage of type traits is to allow
+ code to compile that otherwise would not do so unless excessive partial specialization
+ is used. This is possible by delegating partial specialization to the type
+ traits classes. Our example for this form of usage is a pair that can hold
+ references <link linkend="background.references">[6]</link>.
+ </para>
+ <para>
+ First, let us examine the definition of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase></computeroutput>, omitting
+ the comparison operators, default constructor, and template copy constructor
+ for simplicity:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">pair</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T1</phrase> <phrase role="identifier">first_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T2</phrase> <phrase role="identifier">second_type</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">T1</phrase> <phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">T2</phrase> <phrase role="identifier">second</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">pair</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">nfirst</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T2</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase>
+<phrase role="special">:</phrase><phrase role="identifier">first</phrase><phrase role="special">(</phrase><phrase role="identifier">nfirst</phrase><phrase role="special">),</phrase> <phrase role="identifier">second</phrase><phrase role="special">(</phrase><phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <phrase role="special">}</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ Now, this "pair" cannot hold references as it currently stands, because
+ the constructor would require taking a reference to a reference, which is currently
+ illegal <link linkend="background.references">[7]</link>. Let us consider what
+ the constructor's parameters would have to be in order to allow "pair"
+ to hold non-reference types, references, and constant references:
+ </para>
+ <table frame="all"> <title>Required Constructor Argument Types</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of parameter to initializing constructor
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ A little familiarity with the type traits classes allows us to construct a
+ single mapping that allows us to determine the type of parameter from the type
+ of the contained class. The type traits classes provide a transformation <link linkend="boost_typetraits.reference.add_reference">add_reference</link>, which
+ adds a reference to its type, unless it is already a reference.
+ </para>
+ <table frame="all"> <title>Using add_reference to synthesize the correct constructor
+ type</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ const T
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ T &amp; [8]
+ </para>
+ </entry><entry>
+ <para>
+ T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ This allows us to build a primary template definition for <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput>
+ that can contain non-reference types, reference types, and constant reference
+ types:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">pair</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T1</phrase> <phrase role="identifier">first_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T2</phrase> <phrase role="identifier">second_type</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">T1</phrase> <phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">T2</phrase> <phrase role="identifier">second</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">pair</phrase><phrase role="special">(</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">nfirst</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase>
+<phrase role="special">:</phrase><phrase role="identifier">first</phrase><phrase role="special">(</phrase><phrase role="identifier">nfirst</phrase><phrase role="special">),</phrase> <phrase role="identifier">second</phrase><phrase role="special">(</phrase><phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <phrase role="special">}</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ Add back in the standard comparison operators, default constructor, and template
+ copy constructor (which are all the same), and you have a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase></computeroutput> that
+ can hold reference types!
+ </para>
+ <para>
+ This same extension could have been done using partial template specialization
+ of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput>, but to specialize
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput> in this way would require
+ three partial specializations, plus the primary template. Type traits allows
+ us to define a single primary template that adjusts itself auto-magically to
+ any of these partial specializations, instead of a brute-force partial specialization
+ approach. Using type traits in this fashion allows programmers to delegate
+ partial specialization to the type traits classes, resulting in code that is
+ easier to maintain and easier to understand.
+ </para>
+ <anchor id="boost_typetraits.background.conclusion"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.conclusion">Conclusion</link>
+ </bridgehead>
+ <para>
+ We hope that in this article we have been able to give you some idea of what
+ type-traits are all about. A more complete listing of the available classes
+ are in the boost documentation, along with further examples using type traits.
+ Templates have enabled C++ uses to take the advantage of the code reuse that
+ generic programming brings; hopefully this article has shown that generic programming
+ does not have to sink to the lowest common denominator, and that templates
+ can be optimal as well as generic.
+ </para>
+ <anchor id="boost_typetraits.background.acknowledgements"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.acknowledgements">Acknowledgements</link>
+ </bridgehead>
+ <para>
+ The authors would like to thank Beman Dawes and Howard Hinnant for their helpful
+ comments when preparing this article.
+ </para>
+ <anchor id="background.references"/> <anchor id="boost_typetraits.background.references"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.references">References</link>
+ </bridgehead>
+ <orderedlist inheritnum="ignore" continuation="restarts">
+ <listitem>
+ Nathan C. Myers, C++ Report, June 1995.
+ </listitem>
+ <listitem>
+ The type traits library is based upon contributions by Steve Cleary, Beman
+ Dawes, Howard Hinnant and John Maddock: it can be found at www.boost.org.
+ </listitem>
+ <listitem>
+ A scalar type is an arithmetic type (i.e. a built-in integer or floating
+ point type), an enumeration type, a pointer, a pointer to member, or a const-
+ or volatile-qualified version of one of these types.
+ </listitem>
+ <listitem>
+ This quote is from Donald Knuth, ACM Computing Surveys, December 1974, pg
+ 268.
+ </listitem>
+ <listitem>
+ The test code is available as part of the boost utility library (see algo_opt_examples.cpp),
+ the code was compiled with gcc 2.95 with all optimisations turned on, tests
+ were conducted on a 400MHz Pentium II machine running Microsoft Windows 98.
+ </listitem>
+ <listitem>
+ John Maddock and Howard Hinnant have submitted a "compressed_pair"
+ library to Boost, which uses a technique similar to the one described here
+ to hold references. Their pair also uses type traits to determine if any
+ of the types are empty, and will derive instead of contain to conserve space
+ -- hence the name "compressed".
+ </listitem>
+ <listitem>
+ This is actually an issue with the C++ Core Language Working Group (issue
+ #106), submitted by Bjarne Stroustrup. The tentative resolution is to allow
+ a "reference to a reference to T" to mean the same thing as a "reference
+ to T", but only in template instantiation, in a method similar to multiple
+ cv-qualifiers.
+ </listitem>
+ <listitem>
+ For those of you who are wondering why this shouldn't be const-qualified,
+ remember that references are always implicitly constant (for example, you
+ can't re-assign a reference). Remember also that "const T &amp;"
+ is something completely different. For this reason, cv-qualifiers on template
+ type arguments that are references are ignored.
+ </listitem>
+ </orderedlist>
+ </section>
+ <section id="boost_typetraits.category">
+ <title><link linkend="boost_typetraits.category"> Type Traits by Category</link></title>
+ <section id="boost_typetraits.category.value_traits">
+ <title><link linkend="boost_typetraits.category.value_traits"> Type Traits
+ that Describe the Properties of a Type</link></title>
+ <para>
+ <indexterm>
+ <primary>Foo2</primary>
+ <secondary>Bar2</secondary>
+ </indexterm>
+ These traits are all <emphasis>value traits</emphasis>, which is to say the
+ traits classes all inherit from <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link>,
+ and are used to access some numerical property of a type. Often this is a
+ simple true or false Boolean value, but in a few cases may be some other
+ integer value (for example when dealing with type alignments, or array bounds:
+ see <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.alignment_of">alignment_of</link></computeroutput>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.rank">rank</link></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.extent">extent</link></computeroutput>).
+ </para>
+ <section id="boost_typetraits.category.value_traits.primary">
+ <title><link linkend="boost_typetraits.category.value_traits.primary"> Categorizing
+ a Type</link></title>
+ <para>
+ These traits identify what "kind" of type some type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is. These are split into two groups:
+ primary traits which are all mutually exclusive, and composite traits that
+ are compositions of one or more primary traits.
+ </para>
+ <para>
+ For any given type, exactly one primary type trait will inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ and all the others will inherit from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>,
+ in other words these traits are mutually exclusive.
+ </para>
+ <para>
+ This means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_integral">is_integral</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ will only ever be true for built-in types; if you want to check for a user-defined
+ class type that behaves "as if" it is an integral or floating
+ point type, then use the <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">numeric_limits</phrase>
+ <phrase role="keyword">template</phrase></computeroutput> instead.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_array">is_array</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_class">is_class</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_complex">is_complex</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_enum">is_enum</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_function">is_function</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_integral">is_integral</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_object_pointer">is_member_object_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_union">is_union</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ The following traits are made up of the union of one or more type categorizations.
+ A type may belong to more than one of these categories, in addition to
+ one of the primary categories.
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_arithmetic">is_arithmetic</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_compound">is_compound</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_fundamental">is_fundamental</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_object">is_object</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_scalar">is_scalar</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.value_traits.properties">
+ <title><link linkend="boost_typetraits.category.value_traits.properties">
+ General Type Properties</link></title>
+ <para>
+ The following templates describe the general properties of a type.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.alignment_of">alignment_of</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_assign">has_nothrow_assign</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_default_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_default_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_virtual_destructor">has_virtual_destructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_abstract">is_abstract</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_const">is_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_empty">is_empty</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_stateless">is_stateless</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_signed">is_signed</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_unsigned">is_unsigned</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_volatile">is_volatile</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.extent">extent</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.rank">rank</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.value_traits.relate">
+ <title><link linkend="boost_typetraits.category.value_traits.relate"> Relationships
+ Between Two Types</link></title>
+ <para>
+ These templates determine the whether there is a relationship between two
+ types:
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_base_of">is_base_of</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_same">is_same</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.category.transform">
+ <title><link linkend="boost_typetraits.category.transform"> Type Traits that
+ Transform One Type to Another</link></title>
+ <para>
+ The following templates transform one type to another, based upon some well-defined
+ rule. Each template has a single member called <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of applying the transformation to the template argument
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_const">add_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_cv">add_cv</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_pointer">add_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_volatile">add_volatile</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.decay">decay</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.floating_point_promotion">floating_point_promotion</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.integral_promotion">integral_promotion</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.make_signed">make_signed</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.make_unsigned">make_unsigned</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.promote">promote</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_all_extents">remove_all_extents</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_const">remove_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_cv">remove_cv</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_reference">remove_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_volatile">remove_volatile</link><phrase role="special">;</phrase>
+</programlisting>
+ <anchor id="boost_typetraits.category.transform.broken_compiler_workarounds_"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">Broken
+ Compiler Workarounds:</link>
+ </bridgehead>
+ <para>
+ For all of these templates support for partial specialization of class templates
+ is required to correctly implement the transformation. On the other hand,
+ practice shows that many of the templates from this category are very useful,
+ and often essential for implementing some generic libraries. Lack of these
+ templates is often one of the major limiting factors in porting those libraries
+ to compilers that do not yet support this language feature. As some of these
+ compilers are going to be around for a while, and at least one of them is
+ very wide-spread, it was decided that the library should provide workarounds
+ where possible.
+ </para>
+ <para>
+ The basic idea behind the workaround is to manually define full specializations
+ of all type transformation templates for all fundamental types, and all their
+ 1st and 2nd rank cv-[un]qualified derivative pointer types, and to provide
+ a user-level macro that will define all the explicit specializations needed
+ for any user-defined type T.
+ </para>
+ <para>
+ The first part guarantees the successful compilation of something like this:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">*,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="special">...</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+</programlisting>
+ <para>
+ and the second part provides the library's users with a mechanism to make
+ the above code work not only for <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput> or other built-in type,
+ but for their own types as well:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">namespace</phrase> <phrase role="identifier">myspace</phrase><phrase role="special">{</phrase>
+ <phrase role="keyword">struct</phrase> <phrase role="identifier">MyClass</phrase> <phrase role="special">{};</phrase>
+<phrase role="special">}</phrase>
+<phrase role="comment">// declare this at global scope:
+</phrase><phrase role="identifier">BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</phrase><phrase role="special">(</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">)</phrase>
+<phrase role="comment">// transformations on myspace::MyClass now work:
+</phrase><phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="comment">// etc.
+</phrase></programlisting>
+ <para>
+ Note that the macro BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION evaluates
+ to nothing on those compilers that <emphasis role="bold">do</emphasis> support
+ partial specialization.
+ </para>
+ </section>
+ <section id="boost_typetraits.category.alignment">
+ <title><link linkend="boost_typetraits.category.alignment"> Synthesizing Types
+ with Specific Alignments</link></title>
+ <para>
+ Some low level memory management routines need to synthesize a POD type with
+ specific alignment properties. The template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.type_with_alignment">type_with_alignment</link></computeroutput>
+ finds the smallest type with a specified alignment, while template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.aligned_storage">aligned_storage</link></computeroutput>
+ creates a type with a specific size and alignment.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.type_with_alignment">type_with_alignment</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.aligned_storage">aligned_storage</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.function">
+ <title><link linkend="boost_typetraits.category.function"> Decomposing Function
+ Types</link></title>
+ <para>
+ The class template <link linkend="boost_typetraits.reference.function_traits">function_traits</link>
+ extracts information from function types (see also <link linkend="boost_typetraits.reference.is_function">is_function</link>).
+ This traits class allows you to tell how many arguments a function takes,
+ what those argument types are, and what the return type is.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.function_traits">function_traits</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.user_defined">
+ <title><link linkend="boost_typetraits.user_defined"> User Defined Specializations</link></title>
+ <para>
+ Occationally the end user may need to provide their own specialization for
+ one of the type traits - typically where intrinsic compiler support is required
+ to implement a specific trait fully. These specializations should derive from
+ boost::<link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ or boost::<link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ as appropriate:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pod</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_class</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_union</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">struct</phrase> <phrase role="identifier">my_pod</phrase><phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">my_union</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">char</phrase> <phrase role="identifier">c</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_pod</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_union">is_union</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_class">is_class</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.intrinsics">
+ <title><link linkend="boost_typetraits.intrinsics"> Support for Compiler Intrinsics</link></title>
+ <para>
+ There are some traits that can not be implemented within the current C++ language:
+ to make these traits "just work" with user defined types, some kind
+ of additional help from the compiler is required. Currently (April 2008) Visual
+ C++ 8 and 9, GNU GCC 4.3 and MWCW 9 provide the necessary intrinsics, and other
+ compilers will no doubt follow in due course.
+ </para>
+ <para>
+ The Following traits classes always need compiler support to do the right thing
+ for all types (but all have safe fallback positions if this support is unavailable):
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_union">is_union</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_pod">is_pod</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_assign">has_nothrow_assign</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_virtual_destructor">has_virtual_destructor</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following traits classes can't be portably implemented in the C++ language,
+ although in practice, the implementations do in fact do the right thing on
+ all the compilers we know about:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_empty">is_empty</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following traits classes are dependent on one or more of the above:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_class">is_class</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_stateless">is_stateless</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The hooks for compiler-intrinsic support are defined in <ulink url="../../../../boost/type_traits/intrinsics.hpp">boost/type_traits/intrinsics.hpp</ulink>,
+ adding support for new compilers is simply a matter of defining one of more
+ of the following macros:
+ </para>
+ <table frame="all"> <title>Macros for Compiler Intrinsics</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_UNION(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a union type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_POD(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a POD type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_EMPTY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is an empty struct or union
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if the default constructor for T is trivial (i.e.
+ has no effect)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_COPY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial copy constructor (and can
+ therefore be replaced by a call to memcpy)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_ASSIGN(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial assignment operator (and can
+ therefore be replaced by a call to memcpy)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_DESTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial destructor (i.e. ~T() has
+ no effect)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_CONSTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="identifier">x</phrase><phrase role="special">;</phrase></computeroutput>
+ can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_COPY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase><phrase role="special">(</phrase><phrase role="identifier">t</phrase><phrase role="special">)</phrase></computeroutput> can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_ASSIGN(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="identifier">t</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">u</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">t</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">u</phrase></computeroutput> can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_VIRTUAL_DESTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true T has a virtual destructor
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_ABSTRACT(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is an abstract type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_BASE_OF(T,U)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a base class of U
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_CLASS(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a class type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_CONVERTIBLE(T,U)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is convertible to U
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_ENUM(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true is T is an enum
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_POLYMORPHIC(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a polymorphic type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_ALIGNMENT_OF(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to the alignment requirements of type T.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.mpl">
+ <title><link linkend="boost_typetraits.mpl"> MPL Interoperability</link></title>
+ <para>
+ All the value based traits in this library conform to MPL's requirements for
+ an <ulink url="../../../../libs/mpl/doc/refmanual/integral-constant.html">Integral
+ Constant type</ulink>: that includes a number of rather intrusive workarounds
+ for broken compilers.
+ </para>
+ <para>
+ Purely as an implementation detail, this means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/bool.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">true_</phrase></computeroutput></ulink>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">false_type</link></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/bool.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">false_</phrase></computeroutput></ulink>,
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">v</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/integral-c.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">integral_c</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">v</phrase><phrase role="special">&gt;</phrase></computeroutput></ulink>
+ (provided <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>)
+ </para>
+ </section>
+ <section id="boost_typetraits.examples">
+ <title><link linkend="boost_typetraits.examples"> Examples</link></title>
+ <section id="boost_typetraits.examples.copy">
+ <title><link linkend="boost_typetraits.examples.copy"> An Optimized Version
+ of std::copy</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">copy</phrase></computeroutput>
+ that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>
+ to determine whether to use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>
+ to optimise the copy operation (see <ulink url="../../examples/copy_example.cpp">copy_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// opt::copy
+</phrase><phrase role="comment">// same semantics as std::copy
+</phrase><phrase role="comment">// calls memcpy where appropriate.
+</phrase><phrase role="comment">//
+</phrase>
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">I2</phrase> <phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">out</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">out</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">out</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">memcpy</phrase><phrase role="special">(</phrase><phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="special">(</phrase><phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">)*</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">));</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">out</phrase><phrase role="special">+(</phrase><phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">copy</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">out</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// We can copy with memcpy if T has a trivial assignment operator,
+</phrase> <phrase role="comment">// and if the iterator arguments are actually pointers (this last
+</phrase> <phrase role="comment">// requirement we detect with overload resolution):
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">&lt;</phrase><phrase role="identifier">value_type</phrase><phrase role="special">&gt;());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.fill">
+ <title><link linkend="boost_typetraits.examples.fill"> An Optimised Version
+ of std::fill</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">fill</phrase></computeroutput>
+ that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>
+ to determine whether to use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memset</phrase></computeroutput>
+ to optimise the fill operation (see <ulink url="../../examples/fill_example.cpp">fill_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// fill
+</phrase><phrase role="comment">// same as std::fill, but uses memset where appropriate
+</phrase><phrase role="comment">//
+</phrase><phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">first</phrase> <phrase role="special">=</phrase> <phrase role="identifier">val</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memset</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">I</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">fill</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// We can do an optimised fill if T has a trivial assignment
+</phrase> <phrase role="comment">// operator and if it's size is one:
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase>
+ <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">(</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase> <phrase role="special">==</phrase> <phrase role="number">1</phrase><phrase role="special">)&gt;</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.destruct">
+ <title><link linkend="boost_typetraits.examples.destruct"> An Example that
+ Omits Destructor Calls For Types with Trivial Destructors</link></title>
+ <para>
+ Demonstrates a simple algorithm that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">__has_trivial_destruct</phrase></computeroutput>
+ to determine whether to destructors need to be called (see <ulink url="../../examples/trivial_destructor_example.cpp">trivial_destructor_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// algorithm destroy_array:
+</phrase><phrase role="comment">// The reverse of std::unitialized_copy, takes a block of
+</phrase><phrase role="comment">// initialized memory and calls destructors on all objects therein.
+</phrase><phrase role="comment">//
+</phrase>
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="identifier">first</phrase><phrase role="special">-&gt;~</phrase><phrase role="identifier">T</phrase><phrase role="special">();</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase> <phrase role="comment">// namespace detail
+</phrase>
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">p1</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">p2</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">p1</phrase><phrase role="special">,</phrase> <phrase role="identifier">p2</phrase><phrase role="special">,</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.iter">
+ <title><link linkend="boost_typetraits.examples.iter"> An improved Version
+ of std::iter_swap</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iter_swap</phrase></computeroutput>
+ that use type traits to determine whether an it's arguments are proxying
+ iterators or not, if they're not then it just does a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">swap</phrase></computeroutput>
+ of it's dereferenced arguments (the same as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iter_swap</phrase></computeroutput>
+ does), however if they are proxying iterators then takes special care over
+ the swap to ensure that the algorithm works correctly for both proxying iterators,
+ and even iterators of different types (see <ulink url="../../examples/iter_swap_example.cpp">iter_swap_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// iter_swap:
+</phrase><phrase role="comment">// tests whether iterator is a proxying iterator or not, and
+</phrase><phrase role="comment">// uses optimal form accordingly:
+</phrase><phrase role="comment">//
+</phrase><phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">static</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase> <phrase role="identifier">v_t</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">v_t</phrase> <phrase role="identifier">v</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">one</phrase><phrase role="special">;</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">one</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">two</phrase><phrase role="special">;</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">two</phrase> <phrase role="special">=</phrase> <phrase role="identifier">v</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">static</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">using</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">swap</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">swap</phrase><phrase role="special">(*</phrase><phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase><phrase role="identifier">two</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">iter_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">two</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// See is both arguments are non-proxying iterators,
+</phrase> <phrase role="comment">// and if both iterator the same type:
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">reference</phrase> <phrase role="identifier">r1_t</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I2</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">reference</phrase> <phrase role="identifier">r2_t</phrase><phrase role="special">;</phrase>
+
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase>
+ <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">&lt;</phrase><phrase role="identifier">r1_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">&lt;</phrase><phrase role="identifier">r2_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_same">is_same</link><phrase role="special">&lt;</phrase><phrase role="identifier">r1_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">r2_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">;</phrase>
+
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.to_double">
+ <title><link linkend="boost_typetraits.examples.to_double"> Convert Numeric
+ Types and Enums to double</link></title>
+ <para>
+ Demonstrates a conversion of <ulink url="../../../../libs/numeric/conversion/doc/html/boost_numericconversion/definitions.html#boost_numericconversion.definitions.numeric_types">Numeric
+ Types</ulink> and enum types to double:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">double</phrase> <phrase role="identifier">to_double</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">value</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">promoted</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">numeric</phrase><phrase role="special">::</phrase><phrase role="identifier">converter</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase><phrase role="identifier">promoted</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">convert</phrase><phrase role="special">(</phrase><phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.reference">
+ <title><link linkend="boost_typetraits.reference"> Alphabetical Reference</link></title>
+ <section id="boost_typetraits.reference.add_const">
+ <title><link linkend="boost_typetraits.reference.add_const"> add_const</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ <secondary>two</secondary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">const</phrase></computeroutput> for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_cv">
+ <title><link linkend="boost_typetraits.reference.add_cv"> add_cv</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ <secondary>two</secondary>
+ <tertiary>three</tertiary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_cv</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_cv</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_pointer">
+ <title><link linkend="boost_typetraits.reference.add_pointer"> add_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_pointer</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">*</phrase></computeroutput>.
+ </para>
+ <para>
+ The rationale for this template is that it produces the same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">TYPEOF</phrase><phrase role="special">(&amp;</phrase><phrase role="identifier">t</phrase><phrase role="special">)</phrase></computeroutput>, where
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">t</phrase></computeroutput> is an object of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">**</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">**</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_reference">
+ <title><link linkend="boost_typetraits.reference.add_reference"> add_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_reference</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is not a reference type then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase></computeroutput>, otherwise <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_volatile">
+ <title><link linkend="boost_typetraits.reference.add_volatile"> add_volatile</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput> for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.aligned_storage">
+ <title><link linkend="boost_typetraits.reference.aligned_storage"> aligned_storage</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">aligned_storage</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> a built-in or POD type with size
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Size</phrase></computeroutput> and an alignment that
+ is a multiple of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Align</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">aligned_storage</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.alignment_of">
+ <title><link linkend="boost_typetraits.reference.alignment_of"> alignment_of</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">alignment_of</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template alignment<emphasis role="underline">of inherits from `</emphasis>_integral_constant&lt;std::size_t,
+ ALIGNOF(T)&gt;<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">,</phrase> <phrase role="identifier">where</phrase>
+ </computeroutput>ALIGNOF(T)` is the alignment of type T.
+ </para>
+ <para>
+ <emphasis>Note: strictly speaking you should only rely on the value of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> being
+ a multiple of the true alignment of T, although in practice it does compute
+ the correct value in all the cases we know about.</emphasis>
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">alignment_of</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ with value <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.decay">
+ <title><link linkend="boost_typetraits.reference.decay"> decay</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">decay</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> Let <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>
+ be the result of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>, then if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>
+ is an array type, the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;*</phrase></computeroutput>,
+ otherwise if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput> is a function
+ type then the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase><phrase role="special">*</phrase></computeroutput>, otherwise the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">decay</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">(&amp;)[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">(&amp;)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.extent">
+ <title><link linkend="boost_typetraits.reference.extent"> extent</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">extent</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template extent inherits
+ from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)&gt;</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)</phrase></computeroutput> is the number of elements in the N'th array
+ dimention of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not an array type,
+ or if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">N</phrase> <phrase role="special">&gt;</phrase>
+ <link linkend="boost_typetraits.reference.rank">rank</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>, or if the N'th array bound is incomplete,
+ then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)</phrase></computeroutput> is zero.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">extent</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">1</phrase><phrase role="special">]&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">],</phrase>
+ <phrase role="number">1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">3</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>4</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">],</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>2</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.floating_point_promotion">
+ <title><link linkend="boost_typetraits.reference.floating_point_promotion">
+ floating_point_promotion</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">floating_point_promotion</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If floating point promotion can be
+ applied to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ then applies floating point promotion to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">float</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.function_traits">
+ <title><link linkend="boost_typetraits.reference.function_traits"> function_traits</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">F</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">function_traits</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">static</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">arity</phrase> <phrase role="special">=</phrase> <replaceable>see-below</replaceable><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">result_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> arg<replaceable>N</replaceable>_type<phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ The class template function_traits will only compile if:
+ </para>
+ <itemizedlist>
+ <listitem>
+ The compiler supports partial specialization of class templates.
+ </listitem>
+ <listitem>
+ The template argument <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>
+ is a <emphasis>function type</emphasis>, note that this <emphasis><emphasis role="bold">is not</emphasis></emphasis> the same thing as a <emphasis>pointer
+ to a function</emphasis>.
+ </listitem>
+ </itemizedlist>
+ <tip>
+ <para>
+ function_traits is intended to introspect only C++ functions of the form
+ R (), R( A1 ), R ( A1, ... etc. ) and not function pointers or class member
+ functions. To convert a function pointer type to a suitable type use <link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link>.
+ </para>
+ </tip>
+ <table frame="all"> <title>Function Traits Members</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Member
+ </para>
+ </entry><entry>
+ <para>
+ Description
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that gives the number of arguments
+ accepted by the function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type returned by function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase>arg<replaceable>N</replaceable>_type</computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The <replaceable>N</replaceable>th argument type of function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="number">1</phrase> <phrase role="special">&lt;=</phrase>
+ <phrase role="identifier">N</phrase> <phrase role="special">&lt;=</phrase>
+ <phrase role="identifier">arity</phrase></computeroutput> of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table> <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 0.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 1.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 4.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">long</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arg1_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arg4_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase><phrase role="special">*</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arg5_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A compiler error: there is no <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">arg5_type</phrase></computeroutput>
+ since there are only four arguments.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A compiler error: argument type is a <emphasis>function pointer</emphasis>,
+ and not a <emphasis>function type</emphasis>.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_assign">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_assign"> has_nothrow_assign</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_assign</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing assignment-operator then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_assign</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing assignment-operator;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler support to ensure that this trait "just
+ works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_assign</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_constructor">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_constructor">
+ has_nothrow_constructor</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_default_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing default-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_constructor</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing default-constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to ensure that this trait "just works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_constructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_copy">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_copy"> has_nothrow_copy</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_copy</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_copy_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing copy-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_copy</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing copy-constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to ensure that this trait "just works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_copy</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_cp_cons">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_cp_cons"> has_nothrow_copy_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_no_throw_def_cons">
+ <title><link linkend="boost_typetraits.reference.has_no_throw_def_cons"> has_nothrow_default_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_assign">
+ <title><link linkend="boost_typetraits.reference.has_trivial_assign"> has_trivial_assign</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_assign</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial assignment-operator then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ If a type has a trivial assignment-operator then the operator has the same
+ effect as copying the bits of one object to the other: calls to the operator
+ can be safely replaced with a call to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_assign
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.8p11.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_constructor">
+ <title><link linkend="boost_typetraits.reference.has_trivial_constructor">
+ has_trivial_constructor</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_default_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial default-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ If a type has a trivial default-constructor then the constructor have no
+ effect: calls to the constructor can be safely omitted. Note that using meta-programming
+ to omit a call to a single trivial-constructor call is of no benefit whatsoever.
+ However, if loops and/or exception handling code can also be omitted, then
+ some benefit in terms of code size and speed can be obtained.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_constructor
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.1p6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_copy">
+ <title><link linkend="boost_typetraits.reference.has_trivial_copy"> has_trivial_copy</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_copy</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_copy_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial copy-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ If a type has a trivial copy-constructor then the constructor has the same
+ effect as copying the bits of one object to the other: calls to the constructor
+ can be safely replaced with a call to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_copy
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.8p6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_cp_cons">
+ <title><link linkend="boost_typetraits.reference.has_trivial_cp_cons"> has_trivial_copy_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_def_cons">
+ <title><link linkend="boost_typetraits.reference.has_trivial_def_cons"> has_trivial_default_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_destructor">
+ <title><link linkend="boost_typetraits.reference.has_trivial_destructor"> has_trivial_destructor</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_destructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial destructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ If a type has a trivial destructor then the destructor has no effect: calls
+ to the destructor can be safely omitted. Note that using meta-programming
+ to omit a call to a single trivial-constructor call is of no benefit whatsoever.
+ However, if loops and/or exception handling code can also be omitted, then
+ some benefit in terms of code size and speed can be obtained.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_destructor
+ will never report that a user-defined class or struct has a trivial destructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.4p3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_virtual_destructor">
+ <title><link linkend="boost_typetraits.reference.has_virtual_destructor"> has_virtual_destructor</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_virtual_destructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a virtual destructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> This trait is provided
+ for completeness, since it's part of the Technical Report on C++ Library
+ Extensions. However, there is currently no way to portably implement this
+ trait. The default version provided always inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>,
+ and has to be explicitly specialized for types with virtual destructors unless
+ the compiler used has compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ that enable the trait to do the right thing: currently (May 2005) only Visual
+ C++ 8 and GCC-4.3 have the necessary <link linkend="boost_typetraits.intrinsics">intrinsics</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.4.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_virtual_destructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.integral_constant">
+ <title><link linkend="boost_typetraits.reference.integral_constant"> integral_constant</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">val</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">integral_constant</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">static</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value</phrase> <phrase role="special">=</phrase> <phrase role="identifier">val</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">true_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="keyword">false</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">false_type</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ Class template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_constant</phrase></computeroutput>
+ is the common base class for all the value-based type traits. The two typedef's
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">true_type</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">false_type</phrase></computeroutput> are provided for convenience:
+ most of the value traits are Boolean properties and so will inherit from
+ one of these.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.integral_promotion">
+ <title><link linkend="boost_typetraits.reference.integral_promotion"> integral_promotion</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">integral_promotion</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If integral promotion can be applied
+ to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>, then
+ applies integral promotion to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.5 except 4.5/3
+ (integral bit-field).
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">integral_promotion</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">enum</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">float_round_style</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.is_abstract">
+ <title><link linkend="boost_typetraits.reference.is_abstract"> is_abstract</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_abstract</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ abstract type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_abstract</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> The compiler must
+ support DR337 (as of April 2005: GCC 3.4, VC++ 7.1 (and later), Intel C++
+ 7 (and later), and Comeau 4.3.2). Otherwise behaves the same as <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link>;
+ this is the "safe fallback position" for which polymorphic types
+ are always regarded as potentially abstract. The macro BOOST_NO_IS_ABSTRACT
+ is used to signify that the implementation is buggy, users should check for
+ this in their own code if the "safe fallback" is not suitable for
+ their particular use-case.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">abc</phrase><phrase role="special">{</phrase> <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">abc</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_arithmetic">
+ <title><link linkend="boost_typetraits.reference.is_arithmetic"> is_arithmetic</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_arithmetic</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ arithmetic type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Arithmetic types include integral and floating point types (see also <link linkend="boost_typetraits.reference.is_integral">is_integral</link> and
+ <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link>).
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p8.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_arithmetic</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_array">
+ <title><link linkend="boost_typetraits.reference.is_array"> is_array</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_array</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ array type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_array</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can give the wrong result with function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_base_of">
+ <title><link linkend="boost_typetraits.reference.is_base_of"> is_base_of</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_base_of</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If Base is base class of type
+ Derived or if both types are the same then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ This template will detect non-public base classes, and ambiguous base classes.
+ </para>
+ <para>
+ Note that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">X</phrase><phrase role="special">,</phrase><phrase role="identifier">X</phrase><phrase role="special">&gt;</phrase></computeroutput> will always inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>.
+ <emphasis role="bold">This is the case even if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">X</phrase></computeroutput>
+ is not a class type</emphasis>. This is a change in behaviour from Boost-1.33
+ in order to track the Technical Report on C++ Library Extensions.
+ </para>
+ <para>
+ Types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput> must not be incomplete types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_base_of</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types. There are some older compilers which
+ will produce compiler errors if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput>
+ is a private base class of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput>,
+ or if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput> is an ambiguous
+ base of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput>. These compilers
+ include Borland C++, older versions of Sun Forte C++, Digital Mars C++, and
+ older versions of EDG based compilers.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">{};</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase> <phrase role="special">:</phrase>
+ <phrase role="keyword">public</phrase> <phrase role="identifier">Base</phrase><phrase role="special">{};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Base</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>: a class is regarded as it's
+ own base.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_class">
+ <title><link linkend="boost_typetraits.reference.is_class"> is_class</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_class</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ class type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 9.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_class</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Without (some as
+ yet unspecified) help from the compiler, we cannot distinguish between union
+ and class types, as a result this type will erroneously inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link> for
+ union types. See also <link linkend="boost_typetraits.reference.is_union">is_union</link>.
+ Currently (May 2005) only Visual C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to correctly identify union types, and therefore make is_class function correctly.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">MyClass</phrase><phrase role="special">;</phrase></computeroutput> then:
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_complex">
+ <title><link linkend="boost_typetraits.reference.is_complex"> is_complex</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_complex</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is a complex number type then true (of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">complex</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ for some type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>), otherwise
+ false.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 26.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_complex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.is_compound">
+ <title><link linkend="boost_typetraits.reference.is_compound"> is_compound</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_compound</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ compound type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Any type that is not a fundamental type is a compound type (see also <link linkend="boost_typetraits.reference.is_fundamental">is_fundamental</link>).
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_compound</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyEnum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_const">
+ <title><link linkend="boost_typetraits.reference.is_const"> is_const</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_const</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (top level) const-qualified
+ type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the const-qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the const-qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_convertible">
+ <title><link linkend="boost_typetraits.reference.is_convertible"> is_convertible</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_convertible</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If an imaginary lvalue of type
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">From</phrase></computeroutput> is convertible to type
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput> then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ Type From must not be an incomplete type.
+ </para>
+ <para>
+ Type To must not be an incomplete, or function type.
+ </para>
+ <para>
+ No types are considered to be convertible to array types or abstract-class
+ types.
+ </para>
+ <para>
+ This template can not detect whether a converting-constructor is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">public</phrase></computeroutput> or not: if type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput>
+ has a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">private</phrase></computeroutput> converting constructor
+ from type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">From</phrase></computeroutput> then instantiating
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ will produce a compiler error. For this reason <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase></computeroutput>
+ can not be used to determine whether a type has a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">public</phrase></computeroutput>
+ copy-constructor or not.
+ </para>
+ <para>
+ This template will also produce compiler errors if the conversion is ambiguous,
+ for example:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">struct</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">B</phrase> <phrase role="special">:</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">C</phrase> <phrase role="special">:</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">D</phrase> <phrase role="special">:</phrase> <phrase role="identifier">B</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase> <phrase role="special">{};</phrase>
+<phrase role="comment">// This produces a compiler error, the conversion is ambiguous:
+</phrase><phrase role="keyword">bool</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">y</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">D</phrase><phrase role="special">*,</phrase><phrase role="identifier">A</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4 and 8.5.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> This template is
+ currently broken with Borland C++ Builder 5 (and earlier), for constructor-based
+ conversions, and for the Metrowerks 7 (and earlier) compiler in all cases.
+ If the compiler does not support <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_abstract">is_abstract</link></computeroutput>,
+ then the template parameter <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput>
+ must not be an abstract type.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_convertible</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*,</phrase> <phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the conversion would require a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const_cast</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_empty">
+ <title><link linkend="boost_typetraits.reference.is_empty"> is_empty</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_empty</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an empty class type then
+ inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10p5.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_empty</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> In order to correctly
+ detect empty classes this trait relies on either:
+ </para>
+ <itemizedlist>
+ <listitem>
+ the compiler implementing zero sized empty base classes, or
+ </listitem>
+ <listitem>
+ the compiler providing <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect empty classes.
+ </listitem>
+ </itemizedlist>
+ <para>
+ Can not be used with incomplete types.
+ </para>
+ <para>
+ Can not be used with union types, until is_union can be made to work.
+ </para>
+ <para>
+ If the compiler does not support partial-specialization of class templates,
+ then this template can not be used with abstract types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">struct</phrase> <phrase role="identifier">empty_class</phrase>
+ <phrase role="special">{};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_enum">
+ <title><link linkend="boost_typetraits.reference.is_enum"> is_enum</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_enum</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ enum type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_enum</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Requires a correctly
+ functioning <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link>
+ template; this means that is_enum is currently broken under Borland C++ Builder
+ 5, and for the Metrowerks compiler prior to version 8, other compilers should
+ handle this template just fine.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">enum</phrase> <phrase role="identifier">my_enum</phrase>
+ <phrase role="special">{</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">two</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_floating_point">
+ <title><link linkend="boost_typetraits.reference.is_floating_point"> is_floating_point</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_floating_point</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ floating point type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p8.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_floating_point</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_function">
+ <title><link linkend="boost_typetraits.reference.is_function"> is_function</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_function</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ function type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Note that this template does not detect <emphasis>pointers to functions</emphasis>,
+ or <emphasis>references to functions</emphasis>, these are detected by <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link> and <link linkend="boost_typetraits.reference.is_reference">is_reference</link> respectively:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">f1</phrase><phrase role="special">();</phrase> <phrase role="comment">// f1 is of function type.
+</phrase><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">f2</phrase><phrase role="special">*)();</phrase> <phrase role="comment">// f2 is a pointer to a function.
+</phrase><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">f3</phrase><phrase role="special">&amp;)();</phrase> <phrase role="comment">// f3 is a reference to a function.
+</phrase></programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2p1 and 8.3.5.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_function</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a pointer type, not a function type.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(&amp;)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a reference to a function, not a function type.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a pointer to a member function.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <tip>
+ <para>
+ Don't confuse function-types with pointers to functions:
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="identifier">f</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">);</phrase></computeroutput>
+ </para>
+ <para>
+ defines a function type,
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase> <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ declares a prototype for a function of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase></computeroutput>,
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase><phrase role="special">*</phrase>
+ <phrase role="identifier">pf</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase><phrase role="special">&amp;</phrase>
+ <phrase role="identifier">fr</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ declares a pointer and a reference to the function <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">foo</phrase></computeroutput>.
+ </para>
+ <para>
+ If you want to detect whether some type is a pointer-to-function then use:
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_function">is_function</link><phrase role="special">&lt;</phrase><link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ </para>
+ <para>
+ or for pointers to member functions you can just use <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link>
+ directly.
+ </para>
+ </tip>
+ </section>
+ <section id="boost_typetraits.reference.is_fundamental">
+ <title><link linkend="boost_typetraits.reference.is_fundamental"> is_fundamental</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_fundamental</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ fundamental type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Fundamental types include integral, floating point and void types (see also
+ <link linkend="boost_typetraits.reference.is_integral">is_integral</link>,
+ <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link>
+ and <link linkend="boost_typetraits.reference.is_void">is_void</link>)
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_fundamental</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_integral">
+ <title><link linkend="boost_typetraits.reference.is_integral"> is_integral</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_integral</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ integral type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p7.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_integral</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_function_pointer">
+ <title><link linkend="boost_typetraits.reference.is_member_function_pointer">
+ is_member_function_pointer</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_function_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member function then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the argument in this case is a pointer to a data member and not a member
+ function, see <link linkend="boost_typetraits.reference.is_member_object_pointer">is_member_object_pointer</link>
+ and <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_object_pointer">
+ <title><link linkend="boost_typetraits.reference.is_member_object_pointer">
+ is_member_object_pointer</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_object_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member object (a data member) then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the argument in this case is a pointer to a member function and not a
+ member object, see <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link>
+ and <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_pointer">
+ <title><link linkend="boost_typetraits.reference.is_member_pointer"> is_member_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member (either a function or a data member) then inherits from
+ <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_object">
+ <title><link linkend="boost_typetraits.reference.is_object"> is_object</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_object</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ object type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ All types are object types except references, void, and function types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p9.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_object</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: reference types are not
+ objects
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: function types are not
+ objects
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ void is not an object type
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_pod">
+ <title><link linkend="boost_typetraits.reference.is_pod"> is_pod</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_pod</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ POD type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ POD stands for "Plain old data". Arithmetic types, and enumeration
+ types, a pointers and pointer to members are all PODs. Classes and unions
+ can also be POD's if they have no non-static data members that are of reference
+ or non-POD type, no user defined constructors, no user defined assignment
+ operators, no private or protected non-static data members, no virtual functions
+ and no base classes. Finally, a cv-qualified POD is still a POD, as is an
+ array of PODs.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10 and 9p4 (Note
+ that POD's are also aggregates, see 8.5.1).
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, is<emphasis role="underline">pod
+ will never report that a class or struct is a POD; this is always safe, if
+ possibly sub-optimal. Currently (May 2005) only MWCW 9 and Visual C++ 8 have
+ the necessary compiler-</emphasis>_intrinsics.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pod</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_pointer">
+ <title><link linkend="boost_typetraits.reference.is_pointer"> is_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer type (includes function pointers, but excludes pointers to members)
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2p2 and 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <important>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase></computeroutput> detects "real"
+ pointer types only, and <emphasis>not</emphasis> smart pointers. Users
+ should not specialise <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase></computeroutput>
+ for smart pointer types, as doing so may cause Boost (and other third party)
+ code to fail to function correctly. Users wanting a trait to detect smart
+ pointers should create their own. However, note that there is no way in
+ general to auto-magically detect smart pointer types, so such a trait would
+ have to be partially specialised for each supported smart pointer type.
+ </para>
+ </important>
+ </section>
+ <section id="boost_typetraits.reference.is_polymorphic">
+ <title><link linkend="boost_typetraits.reference.is_polymorphic"> is_polymorphic</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_polymorphic</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ polymorphic type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> The implementation
+ requires some knowledge of the compilers ABI, it does actually seem to work
+ with the majority of compilers though.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_polymorphic</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">poly</phrase><phrase role="special">{</phrase> <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">poly</phrase><phrase role="special">();</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_same">
+ <title><link linkend="boost_typetraits.reference.is_same"> is_same</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_same</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T and U are the same types
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_same</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with abstract, incomplete or function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_scalar">
+ <title><link linkend="boost_typetraits.reference.is_scalar"> is_scalar</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_scalar</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ scalar type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Scalar types include integral, floating point, enumeration, pointer, and
+ pointer-to-member types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_scalar</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_signed">
+ <title><link linkend="boost_typetraits.reference.is_signed"> is_signed</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_signed</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an signed integer type
+ or an enumerated type with an underlying signed integer type, then inherits
+ from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1, 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_signed</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myclass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ whose value depends upon the signedness of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_stateless">
+ <title><link linkend="boost_typetraits.reference.is_stateless"> is_stateless</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_stateless</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Ff T is a stateless type then
+ inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ Type T must be a complete type.
+ </para>
+ <para>
+ A stateless type is a type that has no storage and whose constructors and
+ destructors are trivial. That means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_stateless</phrase></computeroutput>
+ only inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the following expression is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">true</phrase></computeroutput>:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_stateless</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, is_stateless will
+ never report that a class or struct is stateless; this is always safe, if
+ possibly sub-optimal. Currently (May 2005) only MWCW 9 and Visual C++ 8 have
+ the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to make this template work automatically.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.is_reference">
+ <title><link linkend="boost_typetraits.reference.is_reference"> is_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_reference</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a reference pointer type
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ may report the wrong result for function types, and for types that are both
+ const and volatile qualified.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(&amp;)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis> (the argument in this case
+ is a reference to a function).
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_union">
+ <title><link linkend="boost_typetraits.reference.is_union"> is_union</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_union</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ union type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Currently requires some kind of compiler support, otherwise unions are identified
+ as classes.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 9.5.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Without (some as
+ yet unspecified) help from the compiler, we cannot distinguish between union
+ and class types using only standard C++, as a result this type will never
+ inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ unless the user explicitly specializes the template for their user-defined
+ union types, or unless the compiler supplies some unspecified intrinsic that
+ implements this functionality. Currently (May 2005) only Visual C++ 8 has
+ the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to make this trait "just work" without user intervention.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_union</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_unsigned">
+ <title><link linkend="boost_typetraits.reference.is_unsigned"> is_unsigned</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_unsigned</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an unsigned integer type
+ or an enumerated type with an underlying unsigned integer type, then inherits
+ from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1, 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_unsigned</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myclass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ whose value depends upon the signedness of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase>
+ <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_void">
+ <title><link linkend="boost_typetraits.reference.is_void"> is_void</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_void</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ void type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p9.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_void</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_volatile">
+ <title><link linkend="boost_typetraits.reference.is_volatile"> is_volatile</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_volatile</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (top level) volatile-qualified
+ type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">volatile</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase>
+ <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the volatile qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.make_signed">
+ <title><link linkend="boost_typetraits.reference.make_signed"> make_signed</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">make_signed</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If T is a signed integer type then
+ the same type as T, if T is an unsigned integer type then the corresponding
+ signed type. Otherwise if T is an enumerated or character type (char or wchar_t)
+ then a signed integer type with the same width as T.
+ </para>
+ <para>
+ If T has any cv-qualifiers then these are also present on the result type.
+ </para>
+ <para>
+ <emphasis role="bold">Requires:</emphasis> T must be an integer or enumerated
+ type, and must not be the type bool.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">make_signed</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="keyword">long</phrase>
+ <phrase role="keyword">long</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A signed integer type with the same width as the enum.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A signed integer type with the same width as wchar_t.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.make_unsigned">
+ <title><link linkend="boost_typetraits.reference.make_unsigned"> make_unsigned</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">make_unsigned</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If T is a unsigned integer type then
+ the same type as T, if T is an signed integer type then the corresponding
+ unsigned type. Otherwise if T is an enumerated or character type (char or
+ wchar_t) then an unsigned integer type with the same width as T.
+ </para>
+ <para>
+ If T has any cv-qualifiers then these are also present on the result type.
+ </para>
+ <para>
+ <emphasis role="bold">Requires:</emphasis> T must be an integer or enumerated
+ type, and must not be the type bool.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">make_unsigned</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An unsigned integer type with the same width as the enum.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An unsigned integer type with the same width as wchar_t.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.promote">
+ <title><link linkend="boost_typetraits.reference.promote"> promote</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">promote</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If integral or floating point promotion
+ can be applied to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ then applies integral and floating point promotions to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ See also <link linkend="boost_typetraits.reference.integral_promotion">integral_promotion</link>
+ and <link linkend="boost_typetraits.reference.floating_point_promotion">floating_point_promotion</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.5 except 4.5/3
+ (integral bit-field) and 4.6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">promote</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.rank">
+ <title><link linkend="boost_typetraits.reference.rank"> rank</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">rank</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template rank inherits from
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> is the
+ number of array dimensions in type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not an array type,
+ then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> is zero.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">rank</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[]&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">3</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">1</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>1</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>2</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.remove_all_extents">
+ <title><link linkend="boost_typetraits.reference.remove_all_extents"> remove_all_extents</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_all_extents</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is an array type, then removes all of the array bounds on <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_all_extents</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_const">
+ <title><link linkend="boost_typetraits.reference.remove_const"> remove_const</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> const-qualifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_cv">
+ <title><link linkend="boost_typetraits.reference.remove_cv"> remove_cv</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_cv</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> cv-qualifiers removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_cv</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_extent">
+ <title><link linkend="boost_typetraits.reference.remove_extent"> remove_extent</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_extent</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is an array type, then removes the topmost array bound, otherwise leaves
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_extent</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">]</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_pointer">
+ <title><link linkend="boost_typetraits.reference.remove_pointer"> remove_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_pointer</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any pointer modifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">**&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_reference">
+ <title><link linkend="boost_typetraits.reference.remove_reference"> remove_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_reference</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any reference modifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_volatile">
+ <title><link linkend="boost_typetraits.reference.remove_volatile"> remove_volatile</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> volatile-qualifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.type_with_alignment">
+ <title><link linkend="boost_typetraits.reference.type_with_alignment"> type_with_alignment</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">type_with_alignment</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> a built-in or POD type with an alignment
+ that is a multiple of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Align</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">type_with_alignment</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ </section>
+ <section id="boost_typetraits.credits">
+ <title><link linkend="boost_typetraits.credits"> Credits</link></title>
+ <para>
+ This documentation was pulled together by John Maddock, using <ulink url="../../../../doc/html/quickbook.html">Boost.Quickbook</ulink>
+ and <ulink url="../../../../doc/html/boostbook.html">Boost.DocBook</ulink>.
+ </para>
+ <para>
+ The original version of this library was created by Steve Cleary, Beman Dawes,
+ Howard Hinnant, and John Maddock. John Maddock is the current maintainer of
+ the library.
+ </para>
+ <para>
+ This version of type traits library is based on contributions by Adobe Systems
+ Inc, David Abrahams, Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant,
+ Jesse Jones, Mat Marcus, Itay Maman, John Maddock, Thorsten Ottosen, Robert
+ Ramey and Jeremy Siek.
+ </para>
+ <para>
+ Mat Marcus and Jesse Jones invented, and <ulink url="http://opensource.adobe.com/project4/project.shtml">published
+ a paper describing</ulink>, the partial specialization workarounds used in
+ this library.
+ </para>
+ <para>
+ Aleksey Gurtovoy added MPL integration to the library.
+ </para>
+ <para>
+ The <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link>
+ template is based on code originally devised by Andrei Alexandrescu, see "<ulink url="http://www.cuj.com/experts/1810/alexandr.htm?topic=experts">Generic&lt;Programming&gt;:
+ Mappings between Types and Values</ulink>".
+ </para>
+ <para>
+ The latest version of this library and documentation can be found at <ulink url="http://www.boost.org">www.boost.org</ulink>. Bugs, suggestions and discussion
+ should be directed to boost@lists.boost.org (see <ulink url="http://www.boost.org/more/mailing_lists.htm#main">www.boost.org/more/mailing_lists.htm#main</ulink>
+ for subscription details).
+ </para>
+ </section>
+
+ <section id="boost_typetraits.ignored_section">
+ <title>This section must not be indexed.</title>
+ <?BoostAutoIndex IgnoreSection?>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ </section>
+
+ <section id="boost_typetraits.ignored_block">
+ <title>This section contains one block that must not be indexed and one that should be.</title>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">
+ <?BoostAutoIndex IgnoreBlock?>
+ template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">
+ template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ </section>
+
+
+ <index>
+ <title>Class Index</title>
+ <para><link linkend="idx_id_0">A</link> <link linkend="idx_id_2">C</link> <link linkend="idx_id_3">D</link> <link linkend="idx_id_4">E</link> <link linkend="idx_id_5">F</link> <link linkend="idx_id_6">H</link> <link linkend="idx_id_7">I</link> <link linkend="idx_id_8">M</link> <link linkend="idx_id_9">O</link> <link linkend="idx_id_10">P</link> <link linkend="idx_id_11">R</link> <link linkend="idx_id_13">T</link></para><variablelist><varlistentry id="idx_id_0"><term>A</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-0">add_const</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_cv"><phrase role="index-entry-level-0">add_cv</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_pointer"><phrase role="index-entry-level-0">add_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_reference"><phrase role="index-entry-level-0">add_reference</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">add_volatile</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.add_volatile"><phrase role="index-entry-level-1">add_volatile</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.ignored_block"><phrase role="index-entry-level-1">This section contains one block that must not be indexed and one that should be.</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.aligned_storage"><phrase role="index-entry-level-0">aligned_storage</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.alignment_of"><phrase role="index-entry-level-0">alignment_of</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_2"><term>C</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">Constrained Index Term</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-1">add_const</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_3"><term>D</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.decay"><phrase role="index-entry-level-0">decay</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_4"><term>E</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.extent"><phrase role="index-entry-level-0">extent</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_5"><term>F</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.floating_point_promotion"><phrase role="index-entry-level-0">floating_point_promotion</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.function_traits"><phrase role="index-entry-level-0">function_traits</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_6"><term>H</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_assign"><phrase role="index-entry-level-0">has_nothrow_assign</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_constructor"><phrase role="index-entry-level-0">has_nothrow_constructor</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_copy"><phrase role="index-entry-level-0">has_nothrow_copy</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_copy_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_copy"><phrase role="index-entry-level-1">has_nothrow_copy</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_default_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_constructor"><phrase role="index-entry-level-1">has_nothrow_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_assign"><phrase role="index-entry-level-0">has_trivial_assign</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_constructor"><phrase role="index-entry-level-0">has_trivial_constructor</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_copy"><phrase role="index-entry-level-0">has_trivial_copy</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_copy_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_trivial_copy"><phrase role="index-entry-level-1">has_trivial_copy</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_default_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_trivial_constructor"><phrase role="index-entry-level-1">has_trivial_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_destructor"><phrase role="index-entry-level-0">has_trivial_destructor</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_virtual_destructor"><phrase role="index-entry-level-0">has_virtual_destructor</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_7"><term>I</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">integral_constant</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.alignment_of"><phrase role="index-entry-level-1">alignment_of</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.extent"><phrase role="index-entry-level-1">extent</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.rank"><phrase role="index-entry-level-1">rank</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.integral_promotion"><phrase role="index-entry-level-0">integral_promotion</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_abstract"><phrase role="index-entry-level-0">is_abstract</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_arithmetic"><phrase role="index-entry-level-0">is_arithmetic</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_array"><phrase role="index-entry-level-0">is_array</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_base_of"><phrase role="index-entry-level-0">is_base_of</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_class</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_class"><phrase role="index-entry-level-1">is_class</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_complex"><phrase role="index-entry-level-0">is_complex</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_compound"><phrase role="index-entry-level-0">is_compound</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_const"><phrase role="index-entry-level-0">is_const</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_convertible"><phrase role="index-entry-level-0">is_convertible</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_empty"><phrase role="index-entry-level-0">is_empty</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_enum"><phrase role="index-entry-level-0">is_enum</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_floating_point"><phrase role="index-entry-level-0">is_floating_point</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_function"><phrase role="index-entry-level-0">is_function</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_fundamental"><phrase role="index-entry-level-0">is_fundamental</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_integral"><phrase role="index-entry-level-0">is_integral</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_function_pointer"><phrase role="index-entry-level-0">is_member_function_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_object_pointer"><phrase role="index-entry-level-0">is_member_object_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_pointer"><phrase role="index-entry-level-0">is_member_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_object"><phrase role="index-entry-level-0">is_object</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_pod</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_pod"><phrase role="index-entry-level-1">is_pod</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">is_pointer</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_pointer"><phrase role="index-entry-level-1">is_pointer</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_polymorphic"><phrase role="index-entry-level-0">is_polymorphic</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_reference"><phrase role="index-entry-level-0">is_reference</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_same"><phrase role="index-entry-level-0">is_same</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_scalar"><phrase role="index-entry-level-0">is_scalar</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_signed"><phrase role="index-entry-level-0">is_signed</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_stateless"><phrase role="index-entry-level-0">is_stateless</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_union</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_union"><phrase role="index-entry-level-1">is_union</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_unsigned"><phrase role="index-entry-level-0">is_unsigned</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_void</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_void"><phrase role="index-entry-level-1">is_void</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_volatile"><phrase role="index-entry-level-0">is_volatile</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_8"><term>M</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.make_signed"><phrase role="index-entry-level-0">make_signed</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.make_unsigned"><phrase role="index-entry-level-0">make_unsigned</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_9"><term>O</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">one</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_volatile"><phrase role="index-entry-level-1">add_volatile</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-1">two</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-2">add_const</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-2">three</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_cv"><phrase role="index-entry-level-3">add_cv</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_10"><term>P</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.promote"><phrase role="index-entry-level-0">promote</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_11"><term>R</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.rank"><phrase role="index-entry-level-0">rank</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_all_extents"><phrase role="index-entry-level-0">remove_all_extents</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_const"><phrase role="index-entry-level-0">remove_const</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_cv"><phrase role="index-entry-level-0">remove_cv</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">remove_extent</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.remove_extent"><phrase role="index-entry-level-1">remove_extent</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_pointer"><phrase role="index-entry-level-0">remove_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_reference"><phrase role="index-entry-level-0">remove_reference</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_volatile"><phrase role="index-entry-level-0">remove_volatile</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_13"><term>T</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.type_with_alignment"><phrase role="index-entry-level-0">type_with_alignment</phrase></link></para></listitem></itemizedlist></listitem></varlistentry></variablelist></index>
+ <index>
+ <title>Typedef Index</title>
+ <para><link linkend="idx_id_20">F</link> <link linkend="idx_id_26">R</link> <link linkend="idx_id_28">T</link></para><variablelist><varlistentry id="idx_id_20"><term>F</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">false_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_26"><term>R</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">result_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.function_traits"><phrase role="index-entry-level-1">function_traits</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_28"><term>T</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">true_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry></variablelist></index>
+ <index>
+ <title>Macro Index</title>
+ <para><link linkend="idx_id_31">B</link></para><variablelist><varlistentry id="idx_id_31"><term>B</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">BOOST_ALIGNMENT_OF</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.category.transform"><phrase role="index-entry-level-1">Type Traits that Transform One Type to Another</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_ASSIGN</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_CONSTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_COPY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_ASSIGN</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_CONSTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_COPY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_DESTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_VIRTUAL_DESTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_ABSTRACT</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_BASE_OF</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_CLASS</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_CONVERTIBLE</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_EMPTY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_ENUM</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_POD</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_POLYMORPHIC</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_UNION</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry></variablelist></index>
+ <index>
+ <title>Index Test 1</title>
+ <para><link linkend="idx_id_58">T</link></para><variablelist><varlistentry id="idx_id_58"><term>T</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">type-traits</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intro"><phrase role="index-entry-level-1">Introduction</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry></variablelist></index>
+ <index>
+ <title>Index Test 2</title>
+ <para><link linkend="idx_id_73">T</link></para><variablelist><varlistentry id="idx_id_73"><term>T</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">type-traits</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry></variablelist></index>
+ <index><title>Index</title><para><link linkend="idx_id_75">A</link> <link linkend="idx_id_76">B</link> <link linkend="idx_id_77">C</link> <link linkend="idx_id_78">D</link> <link linkend="idx_id_79">E</link> <link linkend="idx_id_80">F</link> <link linkend="idx_id_81">H</link> <link linkend="idx_id_82">I</link> <link linkend="idx_id_83">M</link> <link linkend="idx_id_84">O</link> <link linkend="idx_id_85">P</link> <link linkend="idx_id_86">R</link> <link linkend="idx_id_87">S</link> <link linkend="idx_id_88">T</link> <link linkend="idx_id_89">U</link></para><variablelist><varlistentry id="idx_id_75"><term>A</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">add_const</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-1">add_const</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-1">Constrained Index Term</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.add_cv"><phrase role="index-entry-level-0">add_cv</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_pointer"><phrase role="index-entry-level-0">add_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.add_reference"><phrase role="index-entry-level-0">add_reference</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">add_volatile</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.add_volatile"><phrase role="index-entry-level-1">add_volatile</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.ignored_block"><phrase role="index-entry-level-1">This section contains one block that must not be indexed and one that should be.</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.aligned_storage"><phrase role="index-entry-level-0">aligned_storage</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">alignment_of</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.alignment_of"><phrase role="index-entry-level-1">alignment_of</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.alignment_of"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_76"><term>B</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">Background and Tutorial</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">is_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">is_void</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">remove_extent</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">type-traits</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_ALIGNMENT_OF</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.category.transform"><phrase role="index-entry-level-1">Type Traits that Transform One Type to Another</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_ASSIGN</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_CONSTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_NOTHROW_COPY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_ASSIGN</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_CONSTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_COPY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_TRIVIAL_DESTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_HAS_VIRTUAL_DESTRUCTOR</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_ABSTRACT</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_BASE_OF</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_CLASS</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_CONVERTIBLE</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_EMPTY</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_ENUM</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_POD</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_POLYMORPHIC</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">BOOST_IS_UNION</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">Support for Compiler Intrinsics</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_77"><term>C</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">Constrained Index Term</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-1">add_const</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_78"><term>D</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.decay"><phrase role="index-entry-level-0">decay</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_79"><term>E</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">extent</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.extent"><phrase role="index-entry-level-1">extent</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.extent"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_80"><term>F</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">false_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.floating_point_promotion"><phrase role="index-entry-level-0">floating_point_promotion</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">Foo1</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">Foo2</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-1">Bar2</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.category.value_traits"><phrase role="index-entry-level-2">Type Traits that Describe the Properties of a Type</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">function_traits</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.function_traits"><phrase role="index-entry-level-1">function_traits</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.function_traits"><phrase role="index-entry-level-1">result_type</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_81"><term>H</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_assign"><phrase role="index-entry-level-0">has_nothrow_assign</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.has_nothrow_constructor"><phrase role="index-entry-level-1">has_nothrow_constructor</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_constructor"><phrase role="index-entry-level-1">has_nothrow_default_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_copy</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.has_nothrow_copy"><phrase role="index-entry-level-1">has_nothrow_copy</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_copy"><phrase role="index-entry-level-1">has_nothrow_copy_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_copy_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_copy"><phrase role="index-entry-level-1">has_nothrow_copy</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_nothrow_default_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_nothrow_constructor"><phrase role="index-entry-level-1">has_nothrow_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_assign"><phrase role="index-entry-level-0">has_trivial_assign</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.has_trivial_constructor"><phrase role="index-entry-level-1">has_trivial_constructor</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_constructor"><phrase role="index-entry-level-1">has_trivial_default_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_copy</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.has_trivial_copy"><phrase role="index-entry-level-1">has_trivial_copy</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_copy"><phrase role="index-entry-level-1">has_trivial_copy_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_copy_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_trivial_copy"><phrase role="index-entry-level-1">has_trivial_copy</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">has_trivial_default_constructor</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.has_trivial_constructor"><phrase role="index-entry-level-1">has_trivial_constructor</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.has_trivial_destructor"><phrase role="index-entry-level-0">has_trivial_destructor</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.has_virtual_destructor"><phrase role="index-entry-level-0">has_virtual_destructor</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_82"><term>I</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">int</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.is_function"><phrase role="index-entry-level-1">is_function</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">integral_constant</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.alignment_of"><phrase role="index-entry-level-1">alignment_of</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.extent"><phrase role="index-entry-level-1">extent</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">false_type</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.reference.rank"><phrase role="index-entry-level-1">rank</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">true_type</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.integral_promotion"><phrase role="index-entry-level-0">integral_promotion</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">Introduction</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intro"><phrase role="index-entry-level-1">type-traits</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_abstract"><phrase role="index-entry-level-0">is_abstract</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_arithmetic"><phrase role="index-entry-level-0">is_arithmetic</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_array"><phrase role="index-entry-level-0">is_array</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_base_of"><phrase role="index-entry-level-0">is_base_of</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_class</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_class"><phrase role="index-entry-level-1">is_class</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_complex"><phrase role="index-entry-level-0">is_complex</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_compound"><phrase role="index-entry-level-0">is_compound</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_const"><phrase role="index-entry-level-0">is_const</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_convertible"><phrase role="index-entry-level-0">is_convertible</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_empty"><phrase role="index-entry-level-0">is_empty</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_enum"><phrase role="index-entry-level-0">is_enum</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_floating_point"><phrase role="index-entry-level-0">is_floating_point</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_function</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.is_function"><phrase role="index-entry-level-1">int</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_function"><phrase role="index-entry-level-1">is_function</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_fundamental"><phrase role="index-entry-level-0">is_fundamental</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_integral"><phrase role="index-entry-level-0">is_integral</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_function_pointer"><phrase role="index-entry-level-0">is_member_function_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_object_pointer"><phrase role="index-entry-level-0">is_member_object_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_member_pointer"><phrase role="index-entry-level-0">is_member_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_object"><phrase role="index-entry-level-0">is_object</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_pod</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_pod"><phrase role="index-entry-level-1">is_pod</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">is_pointer</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_pointer"><phrase role="index-entry-level-1">is_pointer</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_polymorphic"><phrase role="index-entry-level-0">is_polymorphic</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_reference"><phrase role="index-entry-level-0">is_reference</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_same"><phrase role="index-entry-level-0">is_same</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_scalar"><phrase role="index-entry-level-0">is_scalar</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_signed"><phrase role="index-entry-level-0">is_signed</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.is_stateless"><phrase role="index-entry-level-0">is_stateless</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_union</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_union"><phrase role="index-entry-level-1">is_union</phrase></link></emphasis></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">User Defined Specializations</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_unsigned"><phrase role="index-entry-level-0">is_unsigned</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">is_void</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.is_void"><phrase role="index-entry-level-1">is_void</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.is_volatile"><phrase role="index-entry-level-0">is_volatile</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_83"><term>M</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.make_signed"><phrase role="index-entry-level-0">make_signed</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.make_unsigned"><phrase role="index-entry-level-0">make_unsigned</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_84"><term>O</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">one</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_volatile"><phrase role="index-entry-level-1">add_volatile</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-1">two</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_const"><phrase role="index-entry-level-2">add_const</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-2">three</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.add_cv"><phrase role="index-entry-level-3">add_cv</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_85"><term>P</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.promote"><phrase role="index-entry-level-0">promote</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_86"><term>R</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">rank</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.rank"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.rank"><phrase role="index-entry-level-1">rank</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_all_extents"><phrase role="index-entry-level-0">remove_all_extents</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_const"><phrase role="index-entry-level-0">remove_const</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_cv"><phrase role="index-entry-level-0">remove_cv</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">remove_extent</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><emphasis role="bold"><link linkend="boost_typetraits.reference.remove_extent"><phrase role="index-entry-level-1">remove_extent</phrase></link></emphasis></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_pointer"><phrase role="index-entry-level-0">remove_pointer</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_reference"><phrase role="index-entry-level-0">remove_reference</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.reference.remove_volatile"><phrase role="index-entry-level-0">remove_volatile</phrase></link></para></listitem><listitem><para><phrase role="index-entry-level-0">result_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.function_traits"><phrase role="index-entry-level-1">function_traits</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_87"><term>S</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">Support for Compiler Intrinsics</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_ALIGNMENT_OF</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_NOTHROW_ASSIGN</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_NOTHROW_CONSTRUCTOR</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_NOTHROW_COPY</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_TRIVIAL_ASSIGN</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_TRIVIAL_CONSTRUCTOR</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_TRIVIAL_COPY</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_TRIVIAL_DESTRUCTOR</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_HAS_VIRTUAL_DESTRUCTOR</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_ABSTRACT</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_BASE_OF</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_CLASS</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_CONVERTIBLE</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_EMPTY</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_ENUM</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_POD</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_POLYMORPHIC</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intrinsics"><phrase role="index-entry-level-1">BOOST_IS_UNION</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_88"><term>T</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">This section contains one block that must not be indexed and one that should be.</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.ignored_block"><phrase role="index-entry-level-1">add_volatile</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">true_type</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.reference.integral_constant"><phrase role="index-entry-level-1">integral_constant</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">Type Traits that Transform One Type to Another</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.category.transform"><phrase role="index-entry-level-1">BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><phrase role="index-entry-level-0">type-traits</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.background"><phrase role="index-entry-level-1">Background and Tutorial</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.intro"><phrase role="index-entry-level-1">Introduction</phrase></link></para></listitem></itemizedlist></listitem><listitem><para><link linkend="boost_typetraits.reference.type_with_alignment"><phrase role="index-entry-level-0">type_with_alignment</phrase></link></para></listitem></itemizedlist></listitem></varlistentry><varlistentry id="idx_id_89"><term>U</term><listitem><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><phrase role="index-entry-level-0">User Defined Specializations</phrase></para><itemizedlist mark="none" spacing="compact" role="index"><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">is_class</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">is_pod</phrase></link></para></listitem><listitem><para><link linkend="boost_typetraits.user_defined"><phrase role="index-entry-level-1">is_union</phrase></link></para></listitem></itemizedlist></listitem></itemizedlist></listitem></varlistentry></variablelist></index>
+
+</chapter> \ No newline at end of file
diff --git a/tools/auto_index/test/type_traits.docbook b/tools/auto_index/test/type_traits.docbook
new file mode 100644
index 0000000000..64837d71a1
--- /dev/null
+++ b/tools/auto_index/test/type_traits.docbook
@@ -0,0 +1,6673 @@
+<?xml version="1.0"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+
+This file is based upon the type traits docs, but has had additional XML elements added to it
+to ensure complete testing.
+
+-->
+
+<chapter xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" id="boost_typetraits" rev:last-revision="$Date: 2008-11-28 12:41:45 +0000 (Fri, 28 Nov 2008) $">
+ <chapterinfo><author>
+ <firstname>various</firstname> <surname>authors</surname>
+ </author><copyright>
+ <year>2000</year> <year>2006</year> <holder>Adobe Systems Inc, David Abrahams,
+ Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant, Jesse Jones, Mat
+ Marcus, Itay Maman, John Maddock, Alexander Nasonov, Thorsten Ottosen, Robert
+ Ramey and Jeremy Siek</holder>
+ </copyright><legalnotice>
+ <para>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
+ </para>
+ </legalnotice></chapterinfo>
+ <title>Boost.TypeTraits</title>
+ <para>
+ A printer-friendly <ulink url="http://svn.boost.org/svn/boost/sandbox/pdf/type_traits/release/type_traits.pdf">PDF
+ version of this manual is also available</ulink>.
+ </para>
+ <section id="boost_typetraits.intro">
+ <title><link linkend="boost_typetraits.intro"> Introduction</link></title>
+ <para>
+ The Boost type-traits library contains a set of very specific traits classes,
+ each of which encapsulate a single trait from the C++ type system; for example,
+ is a type a pointer or a reference type? Or does a type have a trivial constructor,
+ or a const-qualifier?
+ </para>
+ <para>
+ The type-traits classes share a unified design: each class inherits from a
+ the type <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the type has the specified property and inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ otherwise.
+ </para>
+ <para>
+ The type-traits library also contains a set of classes that perform a specific
+ transformation on a type; for example, they can remove a top-level const or
+ volatile qualifier from a type. Each class that performs a transformation defines
+ a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of the transformation.
+ </para>
+ </section>
+ <section id="boost_typetraits.background">
+ <title><link linkend="boost_typetraits.background"> Background and Tutorial</link></title>
+ <para>
+ The following is an updated version of the article "C++ Type traits"
+ by John Maddock and Steve Cleary that appeared in the October 2000 issue of
+ <ulink url="http://www.ddj.com">Dr Dobb's Journal</ulink>.
+ </para>
+ <para>
+ Generic programming (writing code which works with any data type meeting a
+ set of requirements) has become the method of choice for providing reusable
+ code. However, there are times in generic programming when "generic"
+ just isn't good enough - sometimes the differences between types are too large
+ for an efficient generic implementation. This is when the traits technique
+ becomes important - by encapsulating those properties that need to be considered
+ on a type by type basis inside a traits class, we can minimize the amount of
+ code that has to differ from one type to another, and maximize the amount of
+ generic code.
+ </para>
+ <?dbfo keep-together="auto" ?>
+ <para>
+ <indexterm>
+ <primary>Foo1</primary>
+ </indexterm>
+ Consider an example: when working with character strings, one common operation
+ is to determine the length of a null terminated string. Clearly it's possible
+ to write generic code that can do this, but it turns out that there are much
+ more efficient methods available: for example, the C library functions <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">strlen</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">wcslen</phrase></computeroutput>
+ are usually written in assembler, and with suitable hardware support can be
+ considerably faster than a generic version written in C++. The authors of the
+ C++ standard library realized this, and abstracted the properties of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">wchar_t</phrase></computeroutput>
+ into the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput>.
+ Generic code that works with character strings can simply use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase><phrase role="special">&lt;&gt;::</phrase><phrase role="identifier">length</phrase></computeroutput> to determine the length of a null
+ terminated string, safe in the knowledge that specializations of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput> will use the most appropriate
+ method available to them.
+ </para>
+ <anchor id="boost_typetraits.background.type_traits"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.type_traits">Type Traits</link>
+ </bridgehead>
+ <para>
+ Class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">char_traits</phrase></computeroutput> is a classic
+ example of a collection of type specific properties wrapped up in a single
+ class - what Nathan Myers termed a <emphasis>baggage class</emphasis><link linkend="background.references">[1]</link>. In the Boost type-traits library,
+ we<link linkend="background.references">[2]</link> have written a set of very
+ specific traits classes, each of which encapsulate a single trait from the
+ C++ type system; for example, is a type a pointer or a reference type? Or does
+ a type have a trivial constructor, or a const-qualifier? The type-traits classes
+ share a unified design: each class inherits from a the type <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the type has the specified property and inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ otherwise. As we will show, these classes can be used in generic programming
+ to determine the properties of a given type and introduce optimizations that
+ are appropriate for that case.
+ </para>
+ <para>
+ The type-traits library also contains a set of classes that perform a specific
+ transformation on a type; for example, they can remove a top-level const or
+ volatile qualifier from a type. Each class that performs a transformation defines
+ a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of the transformation. All of the type-traits classes are
+ defined inside namespace <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase></computeroutput>;
+ for brevity, namespace-qualification is omitted in most of the code samples
+ given.
+ </para>
+ <anchor id="boost_typetraits.background.implementation"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.implementation">Implementation</link>
+ </bridgehead>
+ <para>
+ There are far too many separate classes contained in the type-traits library
+ to give a full implementation here - see the source code in the Boost library
+ for the full details - however, most of the implementation is fairly repetitive
+ anyway, so here we will just give you a flavor for how some of the classes
+ are implemented. Beginning with possibly the simplest class in the library,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits
+ from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ only if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>.
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ Here we define a primary version of the template class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_void">is_void</link></computeroutput>,
+ and provide a full-specialization when <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>. While full specialization
+ of a template class is an important technique, sometimes we need a solution
+ that is halfway between a fully generic solution, and a full specialization.
+ This is exactly the situation for which the standards committee defined partial
+ template-class specialization. As an example, consider the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput>:
+ here we needed a primary version that handles all the cases where T is not
+ a pointer, and a partial specialization to handle all the cases where T is
+ a pointer:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">*&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ The syntax for partial specialization is somewhat arcane and could easily occupy
+ an article in its own right; like full specialization, in order to write a
+ partial specialization for a class, you must first declare the primary template.
+ The partial specialization contains an extra &lt;...&gt; after the class name
+ that contains the partial specialization parameters; these define the types
+ that will bind to that partial specialization rather than the default template.
+ The rules for what can appear in a partial specialization are somewhat convoluted,
+ but as a rule of thumb if you can legally write two function overloads of the
+ form:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">);</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase><phrase role="identifier">U</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <para>
+ Then you can also write a partial specialization of the form:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <phrase role="identifier">c</phrase><phrase role="special">{</phrase> <phrase role="comment">/*details*/</phrase> <phrase role="special">};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <phrase role="identifier">c</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;{</phrase> <phrase role="comment">/*details*/</phrase> <phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ This rule is by no means foolproof, but it is reasonably simple to remember
+ and close enough to the actual rule to be useful for everyday use.
+ </para>
+ <para>
+ As a more complex example of partial specialization consider the class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></computeroutput>. This
+ class defines a single typedef-member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the same type as T but with any top-level array bounds removed; this
+ is an example of a traits class that performs a transformation on a type:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link>
+<phrase role="special">{</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">[</phrase><phrase role="identifier">N</phrase><phrase role="special">]&gt;</phrase>
+<phrase role="special">{</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ The aim of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.remove_extent">remove_extent</link></computeroutput>
+ is this: imagine a generic algorithm that is passed an array type as a template
+ parameter, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.remove_extent">remove_extent</link></computeroutput>
+ provides a means of determining the underlying type of the array. For example
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">][</phrase><phrase role="number">5</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> would evaluate to the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">5</phrase><phrase role="special">]</phrase></computeroutput>. This example also shows that the number of
+ template parameters in a partial specialization does not have to match the
+ number in the default template. However, the number of parameters that appear
+ after the class name do have to match the number and type of the parameters
+ in the default template.
+ </para>
+ <anchor id="boost_typetraits.background.optimized_copy"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.optimized_copy">Optimized copy</link>
+ </bridgehead>
+ <para>
+ As an example of how the type traits classes can be used, consider the standard
+ library algorithm copy:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Iter1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Iter2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">Iter2</phrase> <phrase role="identifier">copy</phrase><phrase role="special">(</phrase><phrase role="identifier">Iter1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">Iter1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">Iter2</phrase> <phrase role="identifier">out</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <para>
+ Obviously, there's no problem writing a generic version of copy that works
+ for all iterator types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput>; however, there are
+ some circumstances when the copy operation can best be performed by a call
+ to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>. In order to implement
+ copy in terms of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput> all
+ of the following conditions need to be met:
+ </para>
+ <itemizedlist>
+ <listitem>
+ Both of the iterator types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput> must be pointers.
+ </listitem>
+ <listitem>
+ Both <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter2</phrase></computeroutput> must point to the same type - excluding
+ const and volatile-qualifiers.
+ </listitem>
+ <listitem>
+ The type pointed to by <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Iter1</phrase></computeroutput>
+ must have a trivial assignment operator.
+ </listitem>
+ </itemizedlist>
+ <para>
+ By trivial assignment operator we mean that the type is either a scalar type<link linkend="background.references">[3]</link> or:
+ </para>
+ <itemizedlist>
+ <listitem>
+ The type has no user defined assignment operator.
+ </listitem>
+ <listitem>
+ The type does not have any data members that are references.
+ </listitem>
+ <listitem>
+ All base classes, and all data member objects must have trivial assignment
+ operators.
+ </listitem>
+ </itemizedlist>
+ <para>
+ If all these conditions are met then a type can be copied using <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput> rather than using a compiler generated
+ assignment operator. The type-traits library provides a class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>,
+ such that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is true only if T has a trivial assignment
+ operator. This class "just works" for scalar types, but has to be
+ explicitly specialised for class/struct types that also happen to have a trivial
+ assignment operator. In other words if <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link>
+ gives the wrong answer, it will give the "safe" wrong answer - that
+ trivial assignment is not allowable.
+ </para>
+ <para>
+ The code for an optimized version of copy that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>
+ where appropriate is given in <link linkend="boost_typetraits.examples.copy">the
+ examples</link>. The code begins by defining a template function <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">do_copy</phrase></computeroutput> that performs a "slow but safe"
+ copy. The last parameter passed to this function may be either a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ or a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">false_type</link></computeroutput>.
+ Following that there is an overload of do<emphasis role="underline">copy that
+ uses `memcpy`: this time the iterators are required to actually be pointers
+ to the same type, and the final parameter must be a `</emphasis>_true_type<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">.</phrase> <phrase role="identifier">Finally</phrase><phrase role="special">,</phrase> <phrase role="identifier">the</phrase> <phrase role="identifier">version</phrase>
+ <phrase role="identifier">of</phrase> </computeroutput>copy<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="identifier">calls</phrase>
+ </computeroutput>do<emphasis role="underline">copy`, passing `</emphasis>_has_trivial_assign&lt;value_type&gt;()`
+ as the final parameter: this will dispatch to the optimized version where appropriate,
+ otherwise it will call the "slow but safe version".
+ </para>
+ <anchor id="boost_typetraits.background.was_it_worth_it_"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.was_it_worth_it_">Was it worth it?</link>
+ </bridgehead>
+ <para>
+ It has often been repeated in these columns that "premature optimization
+ is the root of all evil" <link linkend="background.references">[4]</link>.
+ So the question must be asked: was our optimization premature? To put this
+ in perspective the timings for our version of copy compared a conventional
+ generic copy<link linkend="background.references">[5]</link> are shown in table
+ 1.
+ </para>
+ <para>
+ Clearly the optimization makes a difference in this case; but, to be fair,
+ the timings are loaded to exclude cache miss effects - without this accurate
+ comparison between algorithms becomes difficult. However, perhaps we can add
+ a couple of caveats to the premature optimization rule:
+ </para>
+ <itemizedlist>
+ <listitem>
+ If you use the right algorithm for the job in the first place then optimization
+ will not be required; in some cases, memcpy is the right algorithm.
+ </listitem>
+ <listitem>
+ If a component is going to be reused in many places by many people then optimizations
+ may well be worthwhile where they would not be so for a single case - in
+ other words, the likelihood that the optimization will be absolutely necessary
+ somewhere, sometime is that much higher. Just as importantly the perceived
+ value of the stock implementation will be higher: there is no point standardizing
+ an algorithm if users reject it on the grounds that there are better, more
+ heavily optimized versions available.
+ </listitem>
+ </itemizedlist>
+ <table frame="all"> <title>Time taken to copy 1000 elements using `copy&lt;const
+ T*, T*&gt;` (times in micro-seconds)</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Version
+ </para>
+ </entry><entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ Time
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ "Optimized" copy
+ </para>
+ </entry><entry>
+ <para>
+ char
+ </para>
+ </entry><entry>
+ <para>
+ 0.99
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Conventional copy
+ </para>
+ </entry><entry>
+ <para>
+ char
+ </para>
+ </entry><entry>
+ <para>
+ 8.07
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ "Optimized" copy
+ </para>
+ </entry><entry>
+ <para>
+ int
+ </para>
+ </entry><entry>
+ <para>
+ 2.52
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Conventional copy
+ </para>
+ </entry><entry>
+ <para>
+ int
+ </para>
+ </entry><entry>
+ <para>
+ 8.02
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table> <anchor id="boost_typetraits.background.pair_of_references"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.pair_of_references">Pair of References</link>
+ </bridgehead>
+ <para>
+ The optimized copy example shows how type traits may be used to perform optimization
+ decisions at compile-time. Another important usage of type traits is to allow
+ code to compile that otherwise would not do so unless excessive partial specialization
+ is used. This is possible by delegating partial specialization to the type
+ traits classes. Our example for this form of usage is a pair that can hold
+ references <link linkend="background.references">[6]</link>.
+ </para>
+ <para>
+ First, let us examine the definition of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase></computeroutput>, omitting
+ the comparison operators, default constructor, and template copy constructor
+ for simplicity:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">pair</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T1</phrase> <phrase role="identifier">first_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T2</phrase> <phrase role="identifier">second_type</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">T1</phrase> <phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">T2</phrase> <phrase role="identifier">second</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">pair</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">nfirst</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T2</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase>
+<phrase role="special">:</phrase><phrase role="identifier">first</phrase><phrase role="special">(</phrase><phrase role="identifier">nfirst</phrase><phrase role="special">),</phrase> <phrase role="identifier">second</phrase><phrase role="special">(</phrase><phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <phrase role="special">}</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ Now, this "pair" cannot hold references as it currently stands, because
+ the constructor would require taking a reference to a reference, which is currently
+ illegal <link linkend="background.references">[7]</link>. Let us consider what
+ the constructor's parameters would have to be in order to allow "pair"
+ to hold non-reference types, references, and constant references:
+ </para>
+ <table frame="all"> <title>Required Constructor Argument Types</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of parameter to initializing constructor
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ A little familiarity with the type traits classes allows us to construct a
+ single mapping that allows us to determine the type of parameter from the type
+ of the contained class. The type traits classes provide a transformation <link linkend="boost_typetraits.reference.add_reference">add_reference</link>, which
+ adds a reference to its type, unless it is already a reference.
+ </para>
+ <table frame="all"> <title>Using add_reference to synthesize the correct constructor
+ type</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ Type of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ T
+ </para>
+ </entry><entry>
+ <para>
+ const T
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ T &amp; [8]
+ </para>
+ </entry><entry>
+ <para>
+ T &amp;
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry><entry>
+ <para>
+ const T &amp;
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ This allows us to build a primary template definition for <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput>
+ that can contain non-reference types, reference types, and constant reference
+ types:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">pair</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T1</phrase> <phrase role="identifier">first_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">T2</phrase> <phrase role="identifier">second_type</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">T1</phrase> <phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">T2</phrase> <phrase role="identifier">second</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">pair</phrase><phrase role="special">(</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">nfirst</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T2</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase>
+<phrase role="special">:</phrase><phrase role="identifier">first</phrase><phrase role="special">(</phrase><phrase role="identifier">nfirst</phrase><phrase role="special">),</phrase> <phrase role="identifier">second</phrase><phrase role="special">(</phrase><phrase role="identifier">nsecond</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <phrase role="special">}</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ Add back in the standard comparison operators, default constructor, and template
+ copy constructor (which are all the same), and you have a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase></computeroutput> that
+ can hold reference types!
+ </para>
+ <para>
+ This same extension could have been done using partial template specialization
+ of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput>, but to specialize
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">pair</phrase></computeroutput> in this way would require
+ three partial specializations, plus the primary template. Type traits allows
+ us to define a single primary template that adjusts itself auto-magically to
+ any of these partial specializations, instead of a brute-force partial specialization
+ approach. Using type traits in this fashion allows programmers to delegate
+ partial specialization to the type traits classes, resulting in code that is
+ easier to maintain and easier to understand.
+ </para>
+ <anchor id="boost_typetraits.background.conclusion"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.conclusion">Conclusion</link>
+ </bridgehead>
+ <para>
+ We hope that in this article we have been able to give you some idea of what
+ type-traits are all about. A more complete listing of the available classes
+ are in the boost documentation, along with further examples using type traits.
+ Templates have enabled C++ uses to take the advantage of the code reuse that
+ generic programming brings; hopefully this article has shown that generic programming
+ does not have to sink to the lowest common denominator, and that templates
+ can be optimal as well as generic.
+ </para>
+ <anchor id="boost_typetraits.background.acknowledgements"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.acknowledgements">Acknowledgements</link>
+ </bridgehead>
+ <para>
+ The authors would like to thank Beman Dawes and Howard Hinnant for their helpful
+ comments when preparing this article.
+ </para>
+ <anchor id="background.references"/> <anchor id="boost_typetraits.background.references"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.background.references">References</link>
+ </bridgehead>
+ <orderedlist inheritnum="ignore" continuation="restarts">
+ <listitem>
+ Nathan C. Myers, C++ Report, June 1995.
+ </listitem>
+ <listitem>
+ The type traits library is based upon contributions by Steve Cleary, Beman
+ Dawes, Howard Hinnant and John Maddock: it can be found at www.boost.org.
+ </listitem>
+ <listitem>
+ A scalar type is an arithmetic type (i.e. a built-in integer or floating
+ point type), an enumeration type, a pointer, a pointer to member, or a const-
+ or volatile-qualified version of one of these types.
+ </listitem>
+ <listitem>
+ This quote is from Donald Knuth, ACM Computing Surveys, December 1974, pg
+ 268.
+ </listitem>
+ <listitem>
+ The test code is available as part of the boost utility library (see algo_opt_examples.cpp),
+ the code was compiled with gcc 2.95 with all optimisations turned on, tests
+ were conducted on a 400MHz Pentium II machine running Microsoft Windows 98.
+ </listitem>
+ <listitem>
+ John Maddock and Howard Hinnant have submitted a "compressed_pair"
+ library to Boost, which uses a technique similar to the one described here
+ to hold references. Their pair also uses type traits to determine if any
+ of the types are empty, and will derive instead of contain to conserve space
+ -- hence the name "compressed".
+ </listitem>
+ <listitem>
+ This is actually an issue with the C++ Core Language Working Group (issue
+ #106), submitted by Bjarne Stroustrup. The tentative resolution is to allow
+ a "reference to a reference to T" to mean the same thing as a "reference
+ to T", but only in template instantiation, in a method similar to multiple
+ cv-qualifiers.
+ </listitem>
+ <listitem>
+ For those of you who are wondering why this shouldn't be const-qualified,
+ remember that references are always implicitly constant (for example, you
+ can't re-assign a reference). Remember also that "const T &amp;"
+ is something completely different. For this reason, cv-qualifiers on template
+ type arguments that are references are ignored.
+ </listitem>
+ </orderedlist>
+ </section>
+ <section id="boost_typetraits.category">
+ <title><link linkend="boost_typetraits.category"> Type Traits by Category</link></title>
+ <section id="boost_typetraits.category.value_traits">
+ <title><link linkend="boost_typetraits.category.value_traits"> Type Traits
+ that Describe the Properties of a Type</link></title>
+ <para>
+ <indexterm>
+ <primary>Foo2</primary>
+ <secondary>Bar2</secondary>
+ </indexterm>
+ These traits are all <emphasis>value traits</emphasis>, which is to say the
+ traits classes all inherit from <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link>,
+ and are used to access some numerical property of a type. Often this is a
+ simple true or false Boolean value, but in a few cases may be some other
+ integer value (for example when dealing with type alignments, or array bounds:
+ see <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.alignment_of">alignment_of</link></computeroutput>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.rank">rank</link></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.extent">extent</link></computeroutput>).
+ </para>
+ <section id="boost_typetraits.category.value_traits.primary">
+ <title><link linkend="boost_typetraits.category.value_traits.primary"> Categorizing
+ a Type</link></title>
+ <para>
+ These traits identify what "kind" of type some type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is. These are split into two groups:
+ primary traits which are all mutually exclusive, and composite traits that
+ are compositions of one or more primary traits.
+ </para>
+ <para>
+ For any given type, exactly one primary type trait will inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ and all the others will inherit from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>,
+ in other words these traits are mutually exclusive.
+ </para>
+ <para>
+ This means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_integral">is_integral</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ will only ever be true for built-in types; if you want to check for a user-defined
+ class type that behaves "as if" it is an integral or floating
+ point type, then use the <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">numeric_limits</phrase>
+ <phrase role="keyword">template</phrase></computeroutput> instead.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_array">is_array</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_class">is_class</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_complex">is_complex</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_enum">is_enum</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_function">is_function</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_integral">is_integral</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_object_pointer">is_member_object_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_union">is_union</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_void">is_void</link><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ The following traits are made up of the union of one or more type categorizations.
+ A type may belong to more than one of these categories, in addition to
+ one of the primary categories.
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_arithmetic">is_arithmetic</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_compound">is_compound</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_fundamental">is_fundamental</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_object">is_object</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_scalar">is_scalar</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.value_traits.properties">
+ <title><link linkend="boost_typetraits.category.value_traits.properties">
+ General Type Properties</link></title>
+ <para>
+ The following templates describe the general properties of a type.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.alignment_of">alignment_of</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_assign">has_nothrow_assign</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_default_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_default_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy_constructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.has_virtual_destructor">has_virtual_destructor</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_abstract">is_abstract</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_const">is_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_empty">is_empty</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_stateless">is_stateless</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_signed">is_signed</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_unsigned">is_unsigned</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_volatile">is_volatile</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.extent">extent</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.rank">rank</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.value_traits.relate">
+ <title><link linkend="boost_typetraits.category.value_traits.relate"> Relationships
+ Between Two Types</link></title>
+ <para>
+ These templates determine the whether there is a relationship between two
+ types:
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_base_of">is_base_of</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_same">is_same</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.category.transform">
+ <title><link linkend="boost_typetraits.category.transform"> Type Traits that
+ Transform One Type to Another</link></title>
+ <para>
+ The following templates transform one type to another, based upon some well-defined
+ rule. Each template has a single member called <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ that is the result of applying the transformation to the template argument
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis:</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_const">add_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_cv">add_cv</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_pointer">add_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_reference">add_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.add_volatile">add_volatile</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.decay">decay</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.floating_point_promotion">floating_point_promotion</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.integral_promotion">integral_promotion</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.make_signed">make_signed</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.make_unsigned">make_unsigned</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.promote">promote</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_all_extents">remove_all_extents</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_const">remove_const</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_cv">remove_cv</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_extent">remove_extent</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_reference">remove_reference</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.remove_volatile">remove_volatile</link><phrase role="special">;</phrase>
+</programlisting>
+ <anchor id="boost_typetraits.category.transform.broken_compiler_workarounds_"/>
+ <bridgehead renderas="sect4">
+ <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">Broken
+ Compiler Workarounds:</link>
+ </bridgehead>
+ <para>
+ For all of these templates support for partial specialization of class templates
+ is required to correctly implement the transformation. On the other hand,
+ practice shows that many of the templates from this category are very useful,
+ and often essential for implementing some generic libraries. Lack of these
+ templates is often one of the major limiting factors in porting those libraries
+ to compilers that do not yet support this language feature. As some of these
+ compilers are going to be around for a while, and at least one of them is
+ very wide-spread, it was decided that the library should provide workarounds
+ where possible.
+ </para>
+ <para>
+ The basic idea behind the workaround is to manually define full specializations
+ of all type transformation templates for all fundamental types, and all their
+ 1st and 2nd rank cv-[un]qualified derivative pointer types, and to provide
+ a user-level macro that will define all the explicit specializations needed
+ for any user-defined type T.
+ </para>
+ <para>
+ The first part guarantees the successful compilation of something like this:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">*,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="special">...</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+</programlisting>
+ <para>
+ and the second part provides the library's users with a mechanism to make
+ the above code work not only for <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput> or other built-in type,
+ but for their own types as well:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">namespace</phrase> <phrase role="identifier">myspace</phrase><phrase role="special">{</phrase>
+ <phrase role="keyword">struct</phrase> <phrase role="identifier">MyClass</phrase> <phrase role="special">{};</phrase>
+<phrase role="special">}</phrase>
+<phrase role="comment">// declare this at global scope:
+</phrase><phrase role="identifier">BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION</phrase><phrase role="special">(</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">)</phrase>
+<phrase role="comment">// transformations on myspace::MyClass now work:
+</phrase><phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="identifier">BOOST_STATIC_ASSERT</phrase><phrase role="special">((</phrase><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">,</phrase> <phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myspace</phrase><phrase role="special">::</phrase><phrase role="identifier">MyClass</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">));</phrase>
+<phrase role="comment">// etc.
+</phrase></programlisting>
+ <para>
+ Note that the macro BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION evaluates
+ to nothing on those compilers that <emphasis role="bold">do</emphasis> support
+ partial specialization.
+ </para>
+ </section>
+ <section id="boost_typetraits.category.alignment">
+ <title><link linkend="boost_typetraits.category.alignment"> Synthesizing Types
+ with Specific Alignments</link></title>
+ <para>
+ Some low level memory management routines need to synthesize a POD type with
+ specific alignment properties. The template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.type_with_alignment">type_with_alignment</link></computeroutput>
+ finds the smallest type with a specified alignment, while template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.aligned_storage">aligned_storage</link></computeroutput>
+ creates a type with a specific size and alignment.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.type_with_alignment">type_with_alignment</link><phrase role="special">;</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.aligned_storage">aligned_storage</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.category.function">
+ <title><link linkend="boost_typetraits.category.function"> Decomposing Function
+ Types</link></title>
+ <para>
+ The class template <link linkend="boost_typetraits.reference.function_traits">function_traits</link>
+ extracts information from function types (see also <link linkend="boost_typetraits.reference.is_function">is_function</link>).
+ This traits class allows you to tell how many arguments a function takes,
+ what those argument types are, and what the return type is.
+ </para>
+ <para>
+ <emphasis role="bold">Synopsis</emphasis>
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.function_traits">function_traits</link><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.user_defined">
+ <title><link linkend="boost_typetraits.user_defined"> User Defined Specializations</link></title>
+ <para>
+ Occationally the end user may need to provide their own specialization for
+ one of the type traits - typically where intrinsic compiler support is required
+ to implement a specific trait fully. These specializations should derive from
+ boost::<link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ or boost::<link linkend="boost_typetraits.reference.integral_constant">false_type</link>
+ as appropriate:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pod</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_class</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_union</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">struct</phrase> <phrase role="identifier">my_pod</phrase><phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">my_union</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">char</phrase> <phrase role="identifier">c</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_pod</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_pod">is_pod</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_union">is_union</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">{};</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
+ <phrase role="keyword">struct</phrase> <link linkend="boost_typetraits.reference.is_class">is_class</link><phrase role="special">&lt;</phrase><phrase role="identifier">my_union</phrase><phrase role="special">&gt;</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">{};</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.intrinsics">
+ <title><link linkend="boost_typetraits.intrinsics"> Support for Compiler Intrinsics</link></title>
+ <para>
+ There are some traits that can not be implemented within the current C++ language:
+ to make these traits "just work" with user defined types, some kind
+ of additional help from the compiler is required. Currently (April 2008) Visual
+ C++ 8 and 9, GNU GCC 4.3 and MWCW 9 provide the necessary intrinsics, and other
+ compilers will no doubt follow in due course.
+ </para>
+ <para>
+ The Following traits classes always need compiler support to do the right thing
+ for all types (but all have safe fallback positions if this support is unavailable):
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_union">is_union</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_pod">is_pod</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_nothrow_assign">has_nothrow_assign</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.has_virtual_destructor">has_virtual_destructor</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following traits classes can't be portably implemented in the C++ language,
+ although in practice, the implementations do in fact do the right thing on
+ all the compilers we know about:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_empty">is_empty</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following traits classes are dependent on one or more of the above:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_class">is_class</link>
+ </listitem>
+ <listitem>
+ <link linkend="boost_typetraits.reference.is_stateless">is_stateless</link>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The hooks for compiler-intrinsic support are defined in <ulink url="../../../../boost/type_traits/intrinsics.hpp">boost/type_traits/intrinsics.hpp</ulink>,
+ adding support for new compilers is simply a matter of defining one of more
+ of the following macros:
+ </para>
+ <table frame="all"> <title>Macros for Compiler Intrinsics</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_UNION(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a union type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_POD(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a POD type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_EMPTY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is an empty struct or union
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if the default constructor for T is trivial (i.e.
+ has no effect)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_COPY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial copy constructor (and can
+ therefore be replaced by a call to memcpy)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_ASSIGN(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial assignment operator (and can
+ therefore be replaced by a call to memcpy)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_TRIVIAL_DESTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T has a trivial destructor (i.e. ~T() has
+ no effect)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_CONSTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="identifier">x</phrase><phrase role="special">;</phrase></computeroutput>
+ can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_COPY(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase><phrase role="special">(</phrase><phrase role="identifier">t</phrase><phrase role="special">)</phrase></computeroutput> can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_NOTHROW_ASSIGN(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="identifier">t</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">u</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">t</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">u</phrase></computeroutput> can not throw
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_HAS_VIRTUAL_DESTRUCTOR(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true T has a virtual destructor
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_ABSTRACT(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is an abstract type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_BASE_OF(T,U)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a base class of U
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_CLASS(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a class type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_CONVERTIBLE(T,U)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is convertible to U
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_ENUM(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true is T is an enum
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_IS_POLYMORPHIC(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to true if T is a polymorphic type
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ BOOST_ALIGNMENT_OF(T)
+ </para>
+ </entry><entry>
+ <para>
+ Should evaluate to the alignment requirements of type T.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.mpl">
+ <title><link linkend="boost_typetraits.mpl"> MPL Interoperability</link></title>
+ <para>
+ All the value based traits in this library conform to MPL's requirements for
+ an <ulink url="../../../../libs/mpl/doc/refmanual/integral-constant.html">Integral
+ Constant type</ulink>: that includes a number of rather intrusive workarounds
+ for broken compilers.
+ </para>
+ <para>
+ Purely as an implementation detail, this means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/bool.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">true_</phrase></computeroutput></ulink>,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">false_type</link></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/bool.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">false_</phrase></computeroutput></ulink>,
+ and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">v</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <ulink url="../../../../libs/mpl/doc/refmanual/integral-c.html"><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">integral_c</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">v</phrase><phrase role="special">&gt;</phrase></computeroutput></ulink>
+ (provided <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>)
+ </para>
+ </section>
+ <section id="boost_typetraits.examples">
+ <title><link linkend="boost_typetraits.examples"> Examples</link></title>
+ <section id="boost_typetraits.examples.copy">
+ <title><link linkend="boost_typetraits.examples.copy"> An Optimized Version
+ of std::copy</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">copy</phrase></computeroutput>
+ that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>
+ to determine whether to use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>
+ to optimise the copy operation (see <ulink url="../../examples/copy_example.cpp">copy_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// opt::copy
+</phrase><phrase role="comment">// same semantics as std::copy
+</phrase><phrase role="comment">// calls memcpy where appropriate.
+</phrase><phrase role="comment">//
+</phrase>
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">I2</phrase> <phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">out</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">out</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">out</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">memcpy</phrase><phrase role="special">(</phrase><phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="special">(</phrase><phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">)*</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">));</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">out</phrase><phrase role="special">+(</phrase><phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">copy</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I1</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">out</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// We can copy with memcpy if T has a trivial assignment operator,
+</phrase> <phrase role="comment">// and if the iterator arguments are actually pointers (this last
+</phrase> <phrase role="comment">// requirement we detect with overload resolution):
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">copy_imp</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">&lt;</phrase><phrase role="identifier">value_type</phrase><phrase role="special">&gt;());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.fill">
+ <title><link linkend="boost_typetraits.examples.fill"> An Optimised Version
+ of std::fill</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">fill</phrase></computeroutput>
+ that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link></computeroutput>
+ to determine whether to use <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memset</phrase></computeroutput>
+ to optimise the fill operation (see <ulink url="../../examples/fill_example.cpp">fill_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// fill
+</phrase><phrase role="comment">// same as std::fill, but uses memset where appropriate
+</phrase><phrase role="comment">//
+</phrase><phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="identifier">b</phrase><phrase role="special">&gt;&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">first</phrase> <phrase role="special">=</phrase> <phrase role="identifier">val</phrase><phrase role="special">;</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memset</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">-</phrase><phrase role="identifier">first</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">I</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">fill</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">val</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// We can do an optimised fill if T has a trivial assignment
+</phrase> <phrase role="comment">// operator and if it's size is one:
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase>
+ <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_assign">has_trivial_assign</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">(</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase> <phrase role="special">==</phrase> <phrase role="number">1</phrase><phrase role="special">)&gt;</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_fill</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">,</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.destruct">
+ <title><link linkend="boost_typetraits.examples.destruct"> An Example that
+ Omits Destructor Calls For Types with Trivial Destructors</link></title>
+ <para>
+ Demonstrates a simple algorithm that uses <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">__has_trivial_destruct</phrase></computeroutput>
+ to determine whether to destructors need to be called (see <ulink url="../../examples/trivial_destructor_example.cpp">trivial_destructor_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// algorithm destroy_array:
+</phrase><phrase role="comment">// The reverse of std::unitialized_copy, takes a block of
+</phrase><phrase role="comment">// initialized memory and calls destructors on all objects therein.
+</phrase><phrase role="comment">//
+</phrase>
+<phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="identifier">first</phrase><phrase role="special">-&gt;~</phrase><phrase role="identifier">T</phrase><phrase role="special">();</phrase>
+ <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">last</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase> <phrase role="comment">// namespace detail
+</phrase>
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">p1</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">p2</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_destroy_array</phrase><phrase role="special">(</phrase><phrase role="identifier">p1</phrase><phrase role="special">,</phrase> <phrase role="identifier">p2</phrase><phrase role="special">,</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.has_trivial_destructor">has_trivial_destructor</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.iter">
+ <title><link linkend="boost_typetraits.examples.iter"> An improved Version
+ of std::iter_swap</link></title>
+ <para>
+ Demonstrates a version of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iter_swap</phrase></computeroutput>
+ that use type traits to determine whether an it's arguments are proxying
+ iterators or not, if they're not then it just does a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">swap</phrase></computeroutput>
+ of it's dereferenced arguments (the same as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iter_swap</phrase></computeroutput>
+ does), however if they are proxying iterators then takes special care over
+ the swap to ensure that the algorithm works correctly for both proxying iterators,
+ and even iterators of different types (see <ulink url="../../examples/iter_swap_example.cpp">iter_swap_example.cpp</ulink>):
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="comment">//
+</phrase><phrase role="comment">// iter_swap:
+</phrase><phrase role="comment">// tests whether iterator is a proxying iterator or not, and
+</phrase><phrase role="comment">// uses optimal form accordingly:
+</phrase><phrase role="comment">//
+</phrase><phrase role="keyword">namespace</phrase> <phrase role="identifier">detail</phrase><phrase role="special">{</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">static</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">false_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase> <phrase role="identifier">v_t</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">v_t</phrase> <phrase role="identifier">v</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">one</phrase><phrase role="special">;</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">one</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase><phrase role="identifier">two</phrase><phrase role="special">;</phrase>
+ <phrase role="special">*</phrase><phrase role="identifier">two</phrase> <phrase role="special">=</phrase> <phrase role="identifier">v</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">static</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">true_type</link><phrase role="special">&amp;)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">using</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">swap</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">swap</phrase><phrase role="special">(*</phrase><phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase><phrase role="identifier">two</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">I1</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">I2</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">iter_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">I1</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">I2</phrase> <phrase role="identifier">two</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">//
+</phrase> <phrase role="comment">// See is both arguments are non-proxying iterators,
+</phrase> <phrase role="comment">// and if both iterator the same type:
+</phrase> <phrase role="comment">//
+</phrase> <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">reference</phrase> <phrase role="identifier">r1_t</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">I2</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">reference</phrase> <phrase role="identifier">r2_t</phrase><phrase role="special">;</phrase>
+
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase>
+ <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">&lt;</phrase><phrase role="identifier">r1_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_reference">is_reference</link><phrase role="special">&lt;</phrase><phrase role="identifier">r2_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><link linkend="boost_typetraits.reference.is_same">is_same</link><phrase role="special">&lt;</phrase><phrase role="identifier">r1_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">r2_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">;</phrase>
+
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">do_swap</phrase><phrase role="special">(</phrase><phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">two</phrase><phrase role="special">,</phrase> <phrase role="identifier">truth_type</phrase><phrase role="special">());</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="boost_typetraits.examples.to_double">
+ <title><link linkend="boost_typetraits.examples.to_double"> Convert Numeric
+ Types and Enums to double</link></title>
+ <para>
+ Demonstrates a conversion of <ulink url="../../../../libs/numeric/conversion/doc/html/boost_numericconversion/definitions.html#boost_numericconversion.definitions.numeric_types">Numeric
+ Types</ulink> and enum types to double:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">inline</phrase> <phrase role="keyword">double</phrase> <phrase role="identifier">to_double</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">value</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">promoted</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">numeric</phrase><phrase role="special">::</phrase><phrase role="identifier">converter</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase><phrase role="identifier">promoted</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">convert</phrase><phrase role="special">(</phrase><phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="boost_typetraits.reference">
+ <title><link linkend="boost_typetraits.reference"> Alphabetical Reference</link></title>
+ <section id="boost_typetraits.reference.add_const">
+ <title><link linkend="boost_typetraits.reference.add_const"> add_const</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ <secondary>two</secondary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">const</phrase></computeroutput> for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_cv">
+ <title><link linkend="boost_typetraits.reference.add_cv"> add_cv</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ <secondary>two</secondary>
+ <tertiary>three</tertiary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_cv</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_cv</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_pointer">
+ <title><link linkend="boost_typetraits.reference.add_pointer"> add_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_pointer</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">*</phrase></computeroutput>.
+ </para>
+ <para>
+ The rationale for this template is that it produces the same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">TYPEOF</phrase><phrase role="special">(&amp;</phrase><phrase role="identifier">t</phrase><phrase role="special">)</phrase></computeroutput>, where
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">t</phrase></computeroutput> is an object of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">**</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">**</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_reference">
+ <title><link linkend="boost_typetraits.reference.add_reference"> add_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_reference</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is not a reference type then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase></computeroutput>, otherwise <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.add_volatile">
+ <title><link linkend="boost_typetraits.reference.add_volatile"> add_volatile</link></title>
+ <indexterm type="class_name">
+ <primary>one</primary>
+ </indexterm>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput> for all <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">add_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">add_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.aligned_storage">
+ <title><link linkend="boost_typetraits.reference.aligned_storage"> aligned_storage</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">aligned_storage</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> a built-in or POD type with size
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Size</phrase></computeroutput> and an alignment that
+ is a multiple of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Align</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">aligned_storage</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.alignment_of">
+ <title><link linkend="boost_typetraits.reference.alignment_of"> alignment_of</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">alignment_of</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template alignment<emphasis role="underline">of inherits from `</emphasis>_integral_constant&lt;std::size_t,
+ ALIGNOF(T)&gt;<computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">,</phrase> <phrase role="identifier">where</phrase>
+ </computeroutput>ALIGNOF(T)` is the alignment of type T.
+ </para>
+ <para>
+ <emphasis>Note: strictly speaking you should only rely on the value of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> being
+ a multiple of the true alignment of T, although in practice it does compute
+ the correct value in all the cases we know about.</emphasis>
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">alignment_of</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ with value <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">ALIGNOF</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">alignment_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.decay">
+ <title><link linkend="boost_typetraits.reference.decay"> decay</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">decay</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> Let <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>
+ be the result of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>, then if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>
+ is an array type, the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;*</phrase></computeroutput>,
+ otherwise if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput> is a function
+ type then the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase><phrase role="special">*</phrase></computeroutput>, otherwise the result is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">decay</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">(&amp;)[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">(&amp;)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.extent">
+ <title><link linkend="boost_typetraits.reference.extent"> extent</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">N</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">extent</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template extent inherits
+ from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)&gt;</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)</phrase></computeroutput> is the number of elements in the N'th array
+ dimention of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not an array type,
+ or if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">N</phrase> <phrase role="special">&gt;</phrase>
+ <link linkend="boost_typetraits.reference.rank">rank</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>, or if the N'th array bound is incomplete,
+ then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">EXTENT</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase><phrase role="identifier">N</phrase><phrase role="special">)</phrase></computeroutput> is zero.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">extent</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">1</phrase><phrase role="special">]&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">],</phrase>
+ <phrase role="number">1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">3</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>4</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">],</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>2</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">extent</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.floating_point_promotion">
+ <title><link linkend="boost_typetraits.reference.floating_point_promotion">
+ floating_point_promotion</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">floating_point_promotion</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If floating point promotion can be
+ applied to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ then applies floating point promotion to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">float</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">floating_point_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.function_traits">
+ <title><link linkend="boost_typetraits.reference.function_traits"> function_traits</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">F</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">function_traits</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">static</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">arity</phrase> <phrase role="special">=</phrase> <replaceable>see-below</replaceable><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">result_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> arg<replaceable>N</replaceable>_type<phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ The class template function_traits will only compile if:
+ </para>
+ <itemizedlist>
+ <listitem>
+ The compiler supports partial specialization of class templates.
+ </listitem>
+ <listitem>
+ The template argument <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>
+ is a <emphasis>function type</emphasis>, note that this <emphasis><emphasis role="bold">is not</emphasis></emphasis> the same thing as a <emphasis>pointer
+ to a function</emphasis>.
+ </listitem>
+ </itemizedlist>
+ <tip>
+ <para>
+ function_traits is intended to introspect only C++ functions of the form
+ R (), R( A1 ), R ( A1, ... etc. ) and not function pointers or class member
+ functions. To convert a function pointer type to a suitable type use <link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link>.
+ </para>
+ </tip>
+ <table frame="all"> <title>Function Traits Members</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Member
+ </para>
+ </entry><entry>
+ <para>
+ Description
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that gives the number of arguments
+ accepted by the function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type returned by function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">F</phrase><phrase role="special">&gt;::</phrase>arg<replaceable>N</replaceable>_type</computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The <replaceable>N</replaceable>th argument type of function type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="number">1</phrase> <phrase role="special">&lt;=</phrase>
+ <phrase role="identifier">N</phrase> <phrase role="special">&lt;=</phrase>
+ <phrase role="identifier">arity</phrase></computeroutput> of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">F</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table> <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 0.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 1.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An integral constant expression that has the value 4.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">result_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">long</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arg1_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arg4_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ The type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">void</phrase><phrase role="special">*</phrase></computeroutput>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">long</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">*)&gt;::</phrase><phrase role="identifier">arg5_type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A compiler error: there is no <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">arg5_type</phrase></computeroutput>
+ since there are only four arguments.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">function_traits</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">arity</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A compiler error: argument type is a <emphasis>function pointer</emphasis>,
+ and not a <emphasis>function type</emphasis>.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_assign">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_assign"> has_nothrow_assign</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_assign</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing assignment-operator then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_assign</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing assignment-operator;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler support to ensure that this trait "just
+ works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_assign</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_constructor">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_constructor">
+ has_nothrow_constructor</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_default_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing default-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_constructor</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing default-constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to ensure that this trait "just works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_constructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_copy">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_copy"> has_nothrow_copy</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_copy</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_nothrow_copy_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a non-throwing copy-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_nothrow_copy</phrase></computeroutput>
+ will never report that a class or struct has a non-throwing copy-constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only Visual
+ C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to ensure that this trait "just works".
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_nothrow_copy</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_nothrow_cp_cons">
+ <title><link linkend="boost_typetraits.reference.has_nothrow_cp_cons"> has_nothrow_copy_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_nothrow_copy">has_nothrow_copy</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_no_throw_def_cons">
+ <title><link linkend="boost_typetraits.reference.has_no_throw_def_cons"> has_nothrow_default_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_nothrow_constructor">has_nothrow_constructor</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_assign">
+ <title><link linkend="boost_typetraits.reference.has_trivial_assign"> has_trivial_assign</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_assign</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial assignment-operator then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ If a type has a trivial assignment-operator then the operator has the same
+ effect as copying the bits of one object to the other: calls to the operator
+ can be safely replaced with a call to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_assign
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.8p11.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_assign</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_constructor">
+ <title><link linkend="boost_typetraits.reference.has_trivial_constructor">
+ has_trivial_constructor</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_default_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial default-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ If a type has a trivial default-constructor then the constructor have no
+ effect: calls to the constructor can be safely omitted. Note that using meta-programming
+ to omit a call to a single trivial-constructor call is of no benefit whatsoever.
+ However, if loops and/or exception handling code can also be omitted, then
+ some benefit in terms of code size and speed can be obtained.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_constructor
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.1p6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_copy">
+ <title><link linkend="boost_typetraits.reference.has_trivial_copy"> has_trivial_copy</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_copy</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+
+<phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_copy_constructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial copy-constructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ These two traits are synonyms for each other.
+ </para>
+ <para>
+ If a type has a trivial copy-constructor then the constructor has the same
+ effect as copying the bits of one object to the other: calls to the constructor
+ can be safely replaced with a call to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">memcpy</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_copy
+ will never report that a user-defined class or struct has a trivial constructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.8p6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_cp_cons">
+ <title><link linkend="boost_typetraits.reference.has_trivial_cp_cons"> has_trivial_copy_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_trivial_copy">has_trivial_copy</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_def_cons">
+ <title><link linkend="boost_typetraits.reference.has_trivial_def_cons"> has_trivial_default_constructor</link></title>
+ <para>
+ See <link linkend="boost_typetraits.reference.has_trivial_constructor">has_trivial_constructor</link>.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.has_trivial_destructor">
+ <title><link linkend="boost_typetraits.reference.has_trivial_destructor"> has_trivial_destructor</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_trivial_destructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a trivial destructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ If a type has a trivial destructor then the destructor has no effect: calls
+ to the destructor can be safely omitted. Note that using meta-programming
+ to omit a call to a single trivial-constructor call is of no benefit whatsoever.
+ However, if loops and/or exception handling code can also be omitted, then
+ some benefit in terms of code size and speed can be obtained.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, has_trivial_destructor
+ will never report that a user-defined class or struct has a trivial destructor;
+ this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW
+ 9 and Visual C++ 8 have the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect user-defined classes with trivial constructors.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.4p3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.has_virtual_destructor">
+ <title><link linkend="boost_typetraits.reference.has_virtual_destructor"> has_virtual_destructor</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_virtual_destructor</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ type with a virtual destructor then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> This trait is provided
+ for completeness, since it's part of the Technical Report on C++ Library
+ Extensions. However, there is currently no way to portably implement this
+ trait. The default version provided always inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>,
+ and has to be explicitly specialized for types with virtual destructors unless
+ the compiler used has compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ that enable the trait to do the right thing: currently (May 2005) only Visual
+ C++ 8 and GCC-4.3 have the necessary <link linkend="boost_typetraits.intrinsics">intrinsics</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 12.4.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">has_virtual_destructor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.integral_constant">
+ <title><link linkend="boost_typetraits.reference.integral_constant"> integral_constant</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">val</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">integral_constant</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">static</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value</phrase> <phrase role="special">=</phrase> <phrase role="identifier">val</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">true_type</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">typedef</phrase> <phrase role="identifier">integral_constant</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">,</phrase> <phrase role="keyword">false</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">false_type</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ Class template <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_constant</phrase></computeroutput>
+ is the common base class for all the value-based type traits. The two typedef's
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">true_type</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">false_type</phrase></computeroutput> are provided for convenience:
+ most of the value traits are Boolean properties and so will inherit from
+ one of these.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.integral_promotion">
+ <title><link linkend="boost_typetraits.reference.integral_promotion"> integral_promotion</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">integral_promotion</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If integral promotion can be applied
+ to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>, then
+ applies integral promotion to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.5 except 4.5/3
+ (integral bit-field).
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">integral_promotion</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">integral_promotion</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">enum</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">float_round_style</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.is_abstract">
+ <title><link linkend="boost_typetraits.reference.is_abstract"> is_abstract</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_abstract</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ abstract type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_abstract</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> The compiler must
+ support DR337 (as of April 2005: GCC 3.4, VC++ 7.1 (and later), Intel C++
+ 7 (and later), and Comeau 4.3.2). Otherwise behaves the same as <link linkend="boost_typetraits.reference.is_polymorphic">is_polymorphic</link>;
+ this is the "safe fallback position" for which polymorphic types
+ are always regarded as potentially abstract. The macro BOOST_NO_IS_ABSTRACT
+ is used to signify that the implementation is buggy, users should check for
+ this in their own code if the "safe fallback" is not suitable for
+ their particular use-case.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">abc</phrase><phrase role="special">{</phrase> <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">abc</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">abc</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_abstract</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_arithmetic">
+ <title><link linkend="boost_typetraits.reference.is_arithmetic"> is_arithmetic</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_arithmetic</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ arithmetic type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Arithmetic types include integral and floating point types (see also <link linkend="boost_typetraits.reference.is_integral">is_integral</link> and
+ <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link>).
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p8.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_arithmetic</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_arithmetic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_array">
+ <title><link linkend="boost_typetraits.reference.is_array"> is_array</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_array</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ array type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_array</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can give the wrong result with function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_array</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_base_of">
+ <title><link linkend="boost_typetraits.reference.is_base_of"> is_base_of</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_base_of</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If Base is base class of type
+ Derived or if both types are the same then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ This template will detect non-public base classes, and ambiguous base classes.
+ </para>
+ <para>
+ Note that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">X</phrase><phrase role="special">,</phrase><phrase role="identifier">X</phrase><phrase role="special">&gt;</phrase></computeroutput> will always inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>.
+ <emphasis role="bold">This is the case even if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">X</phrase></computeroutput>
+ is not a class type</emphasis>. This is a change in behaviour from Boost-1.33
+ in order to track the Technical Report on C++ Library Extensions.
+ </para>
+ <para>
+ Types <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput> must not be incomplete types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_base_of</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types. There are some older compilers which
+ will produce compiler errors if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput>
+ is a private base class of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput>,
+ or if <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Base</phrase></computeroutput> is an ambiguous
+ base of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Derived</phrase></computeroutput>. These compilers
+ include Borland C++, older versions of Sun Forte C++, Digital Mars C++, and
+ older versions of EDG based compilers.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="keyword">class</phrase> <phrase role="identifier">Base</phrase><phrase role="special">{};</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Derived</phrase> <phrase role="special">:</phrase>
+ <phrase role="keyword">public</phrase> <phrase role="identifier">Base</phrase><phrase role="special">{};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Derived</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Base</phrase><phrase role="special">,</phrase> <phrase role="identifier">Base</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>: a class is regarded as it's
+ own base.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_base_of</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_class">
+ <title><link linkend="boost_typetraits.reference.is_class"> is_class</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_class</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ class type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 9.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_class</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Without (some as
+ yet unspecified) help from the compiler, we cannot distinguish between union
+ and class types, as a result this type will erroneously inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link> for
+ union types. See also <link linkend="boost_typetraits.reference.is_union">is_union</link>.
+ Currently (May 2005) only Visual C++ 8 has the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to correctly identify union types, and therefore make is_class function correctly.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">MyClass</phrase><phrase role="special">;</phrase></computeroutput> then:
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_complex">
+ <title><link linkend="boost_typetraits.reference.is_complex"> is_complex</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_complex</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is a complex number type then true (of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">complex</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ for some type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">U</phrase></computeroutput>), otherwise
+ false.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 26.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_complex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.is_compound">
+ <title><link linkend="boost_typetraits.reference.is_compound"> is_compound</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_compound</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ compound type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Any type that is not a fundamental type is a compound type (see also <link linkend="boost_typetraits.reference.is_fundamental">is_fundamental</link>).
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_compound</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyEnum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_compound</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_const">
+ <title><link linkend="boost_typetraits.reference.is_const"> is_const</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_const</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (top level) const-qualified
+ type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the const-qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the const-qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_const</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_convertible">
+ <title><link linkend="boost_typetraits.reference.is_convertible"> is_convertible</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_convertible</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If an imaginary lvalue of type
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">From</phrase></computeroutput> is convertible to type
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput> then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ Type From must not be an incomplete type.
+ </para>
+ <para>
+ Type To must not be an incomplete, or function type.
+ </para>
+ <para>
+ No types are considered to be convertible to array types or abstract-class
+ types.
+ </para>
+ <para>
+ This template can not detect whether a converting-constructor is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">public</phrase></computeroutput> or not: if type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput>
+ has a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">private</phrase></computeroutput> converting constructor
+ from type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">From</phrase></computeroutput> then instantiating
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">From</phrase><phrase role="special">,</phrase> <phrase role="identifier">To</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ will produce a compiler error. For this reason <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase></computeroutput>
+ can not be used to determine whether a type has a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">public</phrase></computeroutput>
+ copy-constructor or not.
+ </para>
+ <para>
+ This template will also produce compiler errors if the conversion is ambiguous,
+ for example:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">struct</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">B</phrase> <phrase role="special">:</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">C</phrase> <phrase role="special">:</phrase> <phrase role="identifier">A</phrase> <phrase role="special">{};</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">D</phrase> <phrase role="special">:</phrase> <phrase role="identifier">B</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase> <phrase role="special">{};</phrase>
+<phrase role="comment">// This produces a compiler error, the conversion is ambiguous:
+</phrase><phrase role="keyword">bool</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">y</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">D</phrase><phrase role="special">*,</phrase><phrase role="identifier">A</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4 and 8.5.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> This template is
+ currently broken with Borland C++ Builder 5 (and earlier), for constructor-based
+ conversions, and for the Metrowerks 7 (and earlier) compiler in all cases.
+ If the compiler does not support <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_abstract">is_abstract</link></computeroutput>,
+ then the template parameter <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">To</phrase></computeroutput>
+ must not be an abstract type.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_convertible</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*,</phrase> <phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the conversion would require a <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const_cast</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_convertible</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_empty">
+ <title><link linkend="boost_typetraits.reference.is_empty"> is_empty</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_empty</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an empty class type then
+ inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10p5.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_empty</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> In order to correctly
+ detect empty classes this trait relies on either:
+ </para>
+ <itemizedlist>
+ <listitem>
+ the compiler implementing zero sized empty base classes, or
+ </listitem>
+ <listitem>
+ the compiler providing <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to detect empty classes.
+ </listitem>
+ </itemizedlist>
+ <para>
+ Can not be used with incomplete types.
+ </para>
+ <para>
+ Can not be used with union types, until is_union can be made to work.
+ </para>
+ <para>
+ If the compiler does not support partial-specialization of class templates,
+ then this template can not be used with abstract types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">struct</phrase> <phrase role="identifier">empty_class</phrase>
+ <phrase role="special">{};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">empty_class</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_enum">
+ <title><link linkend="boost_typetraits.reference.is_enum"> is_enum</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_enum</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ enum type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_enum</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Requires a correctly
+ functioning <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link>
+ template; this means that is_enum is currently broken under Borland C++ Builder
+ 5, and for the Metrowerks compiler prior to version 8, other compilers should
+ handle this template just fine.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">enum</phrase> <phrase role="identifier">my_enum</phrase>
+ <phrase role="special">{</phrase> <phrase role="identifier">one</phrase><phrase role="special">,</phrase> <phrase role="identifier">two</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_enum</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_floating_point">
+ <title><link linkend="boost_typetraits.reference.is_floating_point"> is_floating_point</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_floating_point</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ floating point type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p8.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_floating_point</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_floating_point</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_function">
+ <title><link linkend="boost_typetraits.reference.is_function"> is_function</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_function</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ function type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Note that this template does not detect <emphasis>pointers to functions</emphasis>,
+ or <emphasis>references to functions</emphasis>, these are detected by <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link> and <link linkend="boost_typetraits.reference.is_reference">is_reference</link> respectively:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">f1</phrase><phrase role="special">();</phrase> <phrase role="comment">// f1 is of function type.
+</phrase><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">f2</phrase><phrase role="special">*)();</phrase> <phrase role="comment">// f2 is a pointer to a function.
+</phrase><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">f3</phrase><phrase role="special">&amp;)();</phrase> <phrase role="comment">// f3 is a reference to a function.
+</phrase></programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2p1 and 8.3.5.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_function</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a pointer type, not a function type.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(&amp;)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a reference to a function, not a function type.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: the argument in this case
+ is a pointer to a member function.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_function</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <tip>
+ <para>
+ Don't confuse function-types with pointers to functions:
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="identifier">f</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">);</phrase></computeroutput>
+ </para>
+ <para>
+ defines a function type,
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase> <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ declares a prototype for a function of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase></computeroutput>,
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase><phrase role="special">*</phrase>
+ <phrase role="identifier">pf</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">f</phrase><phrase role="special">&amp;</phrase>
+ <phrase role="identifier">fr</phrase> <phrase role="special">=</phrase>
+ <phrase role="identifier">foo</phrase><phrase role="special">;</phrase></computeroutput>
+ </para>
+ <para>
+ declares a pointer and a reference to the function <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">foo</phrase></computeroutput>.
+ </para>
+ <para>
+ If you want to detect whether some type is a pointer-to-function then use:
+ </para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.is_function">is_function</link><phrase role="special">&lt;</phrase><link linkend="boost_typetraits.reference.remove_pointer">remove_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+ <phrase role="special">&amp;&amp;</phrase> <link linkend="boost_typetraits.reference.is_pointer">is_pointer</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ </para>
+ <para>
+ or for pointers to member functions you can just use <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link>
+ directly.
+ </para>
+ </tip>
+ </section>
+ <section id="boost_typetraits.reference.is_fundamental">
+ <title><link linkend="boost_typetraits.reference.is_fundamental"> is_fundamental</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_fundamental</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ fundamental type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Fundamental types include integral, floating point and void types (see also
+ <link linkend="boost_typetraits.reference.is_integral">is_integral</link>,
+ <link linkend="boost_typetraits.reference.is_floating_point">is_floating_point</link>
+ and <link linkend="boost_typetraits.reference.is_void">is_void</link>)
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_fundamental</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_fundamental</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_integral">
+ <title><link linkend="boost_typetraits.reference.is_integral"> is_integral</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_integral</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ integral type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p7.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_integral</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_integral</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_function_pointer">
+ <title><link linkend="boost_typetraits.reference.is_member_function_pointer">
+ is_member_function_pointer</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_function_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member function then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the argument in this case is a pointer to a data member and not a member
+ function, see <link linkend="boost_typetraits.reference.is_member_object_pointer">is_member_object_pointer</link>
+ and <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_function_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_object_pointer">
+ <title><link linkend="boost_typetraits.reference.is_member_object_pointer">
+ is_member_object_pointer</link></title>
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_object_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member object (a data member) then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the argument in this case is a pointer to a member function and not a
+ member object, see <link linkend="boost_typetraits.reference.is_member_function_pointer">is_member_function_pointer</link>
+ and <link linkend="boost_typetraits.reference.is_member_pointer">is_member_pointer</link>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_object_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_member_pointer">
+ <title><link linkend="boost_typetraits.reference.is_member_pointer"> is_member_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_member_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer to a member (either a function or a data member) then inherits from
+ <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_member_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">char</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_member_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_object">
+ <title><link linkend="boost_typetraits.reference.is_object"> is_object</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_object</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ object type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ All types are object types except references, void, and function types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p9.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_object</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase><phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: reference types are not
+ objects
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>: function types are not
+ objects
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ void is not an object type
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_object</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_pod">
+ <title><link linkend="boost_typetraits.reference.is_pod"> is_pod</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_pod</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ POD type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ POD stands for "Plain old data". Arithmetic types, and enumeration
+ types, a pointers and pointer to members are all PODs. Classes and unions
+ can also be POD's if they have no non-static data members that are of reference
+ or non-POD type, no user defined constructors, no user defined assignment
+ operators, no private or protected non-static data members, no virtual functions
+ and no base classes. Finally, a cv-qualified POD is still a POD, as is an
+ array of PODs.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10 and 9p4 (Note
+ that POD's are also aggregates, see 8.5.1).
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, is<emphasis role="underline">pod
+ will never report that a class or struct is a POD; this is always safe, if
+ possibly sub-optimal. Currently (May 2005) only MWCW 9 and Visual C++ 8 have
+ the necessary compiler-</emphasis>_intrinsics.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pod</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pod</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_pointer">
+ <title><link linkend="boost_typetraits.reference.is_pointer"> is_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_pointer</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ pointer type (includes function pointers, but excludes pointers to members)
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2p2 and 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <important>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase></computeroutput> detects "real"
+ pointer types only, and <emphasis>not</emphasis> smart pointers. Users
+ should not specialise <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_pointer</phrase></computeroutput>
+ for smart pointer types, as doing so may cause Boost (and other third party)
+ code to fail to function correctly. Users wanting a trait to detect smart
+ pointers should create their own. However, note that there is no way in
+ general to auto-magically detect smart pointer types, so such a trait would
+ have to be partially specialised for each supported smart pointer type.
+ </para>
+ </important>
+ </section>
+ <section id="boost_typetraits.reference.is_polymorphic">
+ <title><link linkend="boost_typetraits.reference.is_polymorphic"> is_polymorphic</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_polymorphic</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ polymorphic type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> must be a complete
+ type.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 10.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> The implementation
+ requires some knowledge of the compilers ABI, it does actually seem to work
+ with the majority of compilers though.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_polymorphic</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ Given: <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">class</phrase> <phrase role="identifier">poly</phrase><phrase role="special">{</phrase> <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">poly</phrase><phrase role="special">();</phrase> <phrase role="special">};</phrase></computeroutput>
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">poly</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_polymorphic</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_same">
+ <title><link linkend="boost_typetraits.reference.is_same"> is_same</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">U</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_same</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T and U are the same types
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_same</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with abstract, incomplete or function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;,</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_scalar">
+ <title><link linkend="boost_typetraits.reference.is_scalar"> is_scalar</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_scalar</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ scalar type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Scalar types include integral, floating point, enumeration, pointer, and
+ pointer-to-member types.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_scalar</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(</phrase><phrase role="identifier">MyClass</phrase><phrase role="special">::*)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_scalar</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_signed">
+ <title><link linkend="boost_typetraits.reference.is_signed"> is_signed</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_signed</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an signed integer type
+ or an enumerated type with an underlying signed integer type, then inherits
+ from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1, 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_signed</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myclass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ whose value depends upon the signedness of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_stateless">
+ <title><link linkend="boost_typetraits.reference.is_stateless"> is_stateless</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_stateless</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Ff T is a stateless type then
+ inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ Type T must be a complete type.
+ </para>
+ <para>
+ A stateless type is a type that has no storage and whose constructors and
+ destructors are trivial. That means that <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_stateless</phrase></computeroutput>
+ only inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>
+ if the following expression is <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">true</phrase></computeroutput>:
+ </para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_constructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_copy</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">has_trivial_destructor</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_class</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&amp;&amp;</phrase> <phrase role="special">::</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">is_empty</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9p10.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_stateless</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ can not be used with function types.
+ </para>
+ <para>
+ Without some (as yet unspecified) help from the compiler, is_stateless will
+ never report that a class or struct is stateless; this is always safe, if
+ possibly sub-optimal. Currently (May 2005) only MWCW 9 and Visual C++ 8 have
+ the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to make this template work automatically.
+ </para>
+ </section>
+ <section id="boost_typetraits.reference.is_reference">
+ <title><link linkend="boost_typetraits.reference.is_reference"> is_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_reference</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a reference pointer type
+ then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial-specialization of class templates, then this template
+ may report the wrong result for function types, and for types that are both
+ const and volatile qualified.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="special">(&amp;)(</phrase><phrase role="keyword">long</phrase><phrase role="special">)&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis> (the argument in this case
+ is a reference to a function).
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_reference</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_union">
+ <title><link linkend="boost_typetraits.reference.is_union"> is_union</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_union</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ union type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ Currently requires some kind of compiler support, otherwise unions are identified
+ as classes.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.2 and 9.5.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> Without (some as
+ yet unspecified) help from the compiler, we cannot distinguish between union
+ and class types using only standard C++, as a result this type will never
+ inherit from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ unless the user explicitly specializes the template for their user-defined
+ union types, or unless the compiler supplies some unspecified intrinsic that
+ implements this functionality. Currently (May 2005) only Visual C++ 8 has
+ the necessary compiler <link linkend="boost_typetraits.intrinsics">intrinsics</link>
+ to make this trait "just work" without user intervention.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_union</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_union</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_unsigned">
+ <title><link linkend="boost_typetraits.reference.is_unsigned"> is_unsigned</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_unsigned</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is an unsigned integer type
+ or an enumerated type with an underlying unsigned integer type, then inherits
+ from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1, 7.2.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_unsigned</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">myclass</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ whose value depends upon the signedness of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">char</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase>
+ <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_unsigned</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_void">
+ <title><link linkend="boost_typetraits.reference.is_void"> is_void</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_void</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (possibly cv-qualified)
+ void type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1p9.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_void</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>false</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_void</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.is_volatile">
+ <title><link linkend="boost_typetraits.reference.is_volatile"> is_volatile</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">is_volatile</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <replaceable><link linkend="boost_typetraits.reference.integral_constant">true_type</link>-or-<link linkend="boost_typetraits.reference.integral_constant">false_type</link></replaceable> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> If T is a (top level) volatile-qualified
+ type then inherits from <link linkend="boost_typetraits.reference.integral_constant">true_type</link>,
+ otherwise inherits from <link linkend="boost_typetraits.reference.integral_constant">false_type</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">is_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">volatile</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase></computeroutput> inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">volatile</phrase>
+ <phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">true_type</link></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>true</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>false</emphasis>:
+ the volatile qualifier is not at the top level in this case.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">is_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">bool</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.make_signed">
+ <title><link linkend="boost_typetraits.reference.make_signed"> make_signed</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">make_signed</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If T is a signed integer type then
+ the same type as T, if T is an unsigned integer type then the corresponding
+ signed type. Otherwise if T is an enumerated or character type (char or wchar_t)
+ then a signed integer type with the same width as T.
+ </para>
+ <para>
+ If T has any cv-qualifiers then these are also present on the result type.
+ </para>
+ <para>
+ <emphasis role="bold">Requires:</emphasis> T must be an integer or enumerated
+ type, and must not be the type bool.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">make_signed</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="keyword">long</phrase>
+ <phrase role="keyword">long</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A signed integer type with the same width as the enum.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ A signed integer type with the same width as wchar_t.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.make_unsigned">
+ <title><link linkend="boost_typetraits.reference.make_unsigned"> make_unsigned</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">make_unsigned</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If T is a unsigned integer type then
+ the same type as T, if T is an signed integer type then the corresponding
+ unsigned type. Otherwise if T is an enumerated or character type (char or
+ wchar_t) then an unsigned integer type with the same width as T.
+ </para>
+ <para>
+ If T has any cv-qualifiers then these are also present on the result type.
+ </para>
+ <para>
+ <emphasis role="bold">Requires:</emphasis> T must be an integer or enumerated
+ type, and must not be the type bool.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.1.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">make_unsigned</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase>
+ <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase>
+ <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_enum</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An unsigned integer type with the same width as the enum.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">make_signed</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ An unsigned integer type with the same width as wchar_t.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.promote">
+ <title><link linkend="boost_typetraits.reference.promote"> promote</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">promote</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If integral or floating point promotion
+ can be applied to an rvalue of type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ then applies integral and floating point promotions to <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ and keeps cv-qualifiers of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ See also <link linkend="boost_typetraits.reference.integral_promotion">integral_promotion</link>
+ and <link linkend="boost_typetraits.reference.floating_point_promotion">floating_point_promotion</link>.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 4.5 except 4.5/3
+ (integral bit-field) and 4.6.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">promote</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">double</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">promote</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">short</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.rank">
+ <title><link linkend="boost_typetraits.reference.rank"> rank</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">rank</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase> <phrase role="special">{};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">Inherits:</emphasis> Class template rank inherits from
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)&gt;</phrase></computeroutput>,
+ where <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> is the
+ number of array dimensions in type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>.
+ </para>
+ <para>
+ If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> is not an array type,
+ then <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">RANK</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></computeroutput> is zero.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">rank</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <para>
+ <emphasis role="bold">Examples:</emphasis>
+ </para>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[]&gt;</phrase></computeroutput>
+ inherits from <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">1</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost_typetraits.reference.integral_constant">integral_constant</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">,</phrase> <phrase role="number">3</phrase><phrase role="special">&gt;</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">1</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput>
+ is an integral constant expression that evaluates to <emphasis>1</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>2</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">value</phrase></computeroutput> is an integral constant expression
+ that evaluates to <emphasis>0</emphasis>.
+ </para>
+ </para>
+ </blockquote>
+ <blockquote>
+ <para>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">rank</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">value_type</phrase></computeroutput> is the type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase></computeroutput>.
+ </para>
+ </para>
+ </blockquote>
+ </section>
+ <section id="boost_typetraits.reference.remove_all_extents">
+ <title><link linkend="boost_typetraits.reference.remove_all_extents"> remove_all_extents</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_all_extents</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is an array type, then removes all of the array bounds on <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ otherwise leaves <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_all_extents</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">3</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_all_extents</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_const">
+ <title><link linkend="boost_typetraits.reference.remove_const"> remove_const</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> const-qualifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_const</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_const</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_cv">
+ <title><link linkend="boost_typetraits.reference.remove_cv"> remove_cv</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_cv</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> cv-qualifiers removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_cv</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_cv</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_extent">
+ <title><link linkend="boost_typetraits.reference.remove_extent"> remove_extent</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_extent</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> If <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ is an array type, then removes the topmost array bound, otherwise leaves
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput> unchanged.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.4.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_extent</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">][</phrase><phrase role="number">4</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">4</phrase><phrase role="special">]</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">[][</phrase><phrase role="number">2</phrase><phrase role="special">]&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">[</phrase><phrase role="number">2</phrase><phrase role="special">]</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_extent</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_pointer">
+ <title><link linkend="boost_typetraits.reference.remove_pointer"> remove_pointer</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_pointer</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any pointer modifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.1.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_pointer</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">**&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_pointer</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_reference">
+ <title><link linkend="boost_typetraits.reference.remove_reference"> remove_reference</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_reference</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any reference modifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 8.3.2.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_reference</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_reference</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">*&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.remove_volatile">
+ <title><link linkend="boost_typetraits.reference.remove_volatile"> remove_volatile</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">remove_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> The same type as <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>,
+ but with any <emphasis>top level</emphasis> volatile-qualifier removed.
+ </para>
+ <para>
+ <emphasis role="bold">C++ Standard Reference:</emphasis> 3.9.3.
+ </para>
+ <para>
+ <emphasis role="bold">Compiler Compatibility:</emphasis> If the compiler
+ does not support partial specialization of class-templates then this template
+ will compile, but the member <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">type</phrase></computeroutput>
+ will always be the same as type <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">T</phrase></computeroutput>
+ except where <link linkend="boost_typetraits.category.transform.broken_compiler_workarounds_">compiler
+ workarounds</link> have been applied.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">remove_volatile</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ <table frame="all"> <title>Examples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Expression
+ </para>
+ </entry><entry>
+ <para>
+ Result Type
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">volatile</phrase><phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">&amp;&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">remove_volatile</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase> <phrase role="keyword">volatile</phrase><phrase role="special">*&gt;::</phrase><phrase role="identifier">type</phrase></computeroutput>
+ </para>
+ </entry><entry>
+ <para>
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">int</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase></computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="boost_typetraits.reference.type_with_alignment">
+ <title><link linkend="boost_typetraits.reference.type_with_alignment"> type_with_alignment</link></title>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">Align</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">type_with_alignment</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <para>
+ <emphasis role="bold">type:</emphasis> a built-in or POD type with an alignment
+ that is a multiple of <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="identifier">Align</phrase></computeroutput>.
+ </para>
+ <para>
+ <emphasis role="bold">Header:</emphasis> <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase>
+ <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">/</phrase><phrase role="identifier">type_with_alignment</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ or <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"> <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">type_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase></computeroutput>
+ </para>
+ </section>
+ </section>
+ <section id="boost_typetraits.credits">
+ <title><link linkend="boost_typetraits.credits"> Credits</link></title>
+ <para>
+ This documentation was pulled together by John Maddock, using <ulink url="../../../../doc/html/quickbook.html">Boost.Quickbook</ulink>
+ and <ulink url="../../../../doc/html/boostbook.html">Boost.DocBook</ulink>.
+ </para>
+ <para>
+ The original version of this library was created by Steve Cleary, Beman Dawes,
+ Howard Hinnant, and John Maddock. John Maddock is the current maintainer of
+ the library.
+ </para>
+ <para>
+ This version of type traits library is based on contributions by Adobe Systems
+ Inc, David Abrahams, Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant,
+ Jesse Jones, Mat Marcus, Itay Maman, John Maddock, Thorsten Ottosen, Robert
+ Ramey and Jeremy Siek.
+ </para>
+ <para>
+ Mat Marcus and Jesse Jones invented, and <ulink url="http://opensource.adobe.com/project4/project.shtml">published
+ a paper describing</ulink>, the partial specialization workarounds used in
+ this library.
+ </para>
+ <para>
+ Aleksey Gurtovoy added MPL integration to the library.
+ </para>
+ <para>
+ The <link linkend="boost_typetraits.reference.is_convertible">is_convertible</link>
+ template is based on code originally devised by Andrei Alexandrescu, see "<ulink url="http://www.cuj.com/experts/1810/alexandr.htm?topic=experts">Generic&lt;Programming&gt;:
+ Mappings between Types and Values</ulink>".
+ </para>
+ <para>
+ The latest version of this library and documentation can be found at <ulink url="http://www.boost.org">www.boost.org</ulink>. Bugs, suggestions and discussion
+ should be directed to boost@lists.boost.org (see <ulink url="http://www.boost.org/more/mailing_lists.htm#main">www.boost.org/more/mailing_lists.htm#main</ulink>
+ for subscription details).
+ </para>
+ </section>
+
+ <section id="boost_typetraits.ignored_section">
+ <title>This section must not be indexed.</title>
+ <?BoostAutoIndex IgnoreSection?>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ </section>
+
+ <section id="boost_typetraits.ignored_block">
+ <title>This section contains one block that must not be indexed and one that should be.</title>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">
+ <?BoostAutoIndex IgnoreBlock?>
+ template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_const</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">
+ template</phrase> <phrase role="special">&lt;</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">add_volatile</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <replaceable>see-below</replaceable> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ </section>
+
+ <para>
+ <index type="class_name">
+ <title>Class Index</title>
+ </index>
+ <index type="typedef_name">
+ <title>Typedef Index</title>
+ </index>
+ <index type="macro_name">
+ <title>Macro Index</title>
+ </index>
+ <index type="test_index_1">
+ <title>Index Test 1</title>
+ </index>
+ <index type="test_index_2">
+ <title>Index Test 2</title>
+ </index>
+ <index/>
+ </para>
+</chapter>
+
diff --git a/tools/bcp/Jamfile.v2 b/tools/bcp/Jamfile.v2
new file mode 100644
index 0000000000..4f34b549aa
--- /dev/null
+++ b/tools/bcp/Jamfile.v2
@@ -0,0 +1,37 @@
+# (C) Copyright John Maddock 2006.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+exe bcp
+ :
+ add_dependent_lib.cpp add_path.cpp bcp_imp.cpp copy_path.cpp file_types.cpp
+ fileview.cpp main.cpp path_operations.cpp scan_cvs_path.cpp
+ licence_info.cpp scan_licence.cpp output_licence_info.cpp
+ /boost/filesystem//boost_filesystem
+ /boost/regex//boost_regex
+ /boost/test//boost_prg_exec_monitor
+ :
+ :
+ release
+ ;
+
+install dist-bin
+ :
+ bcp
+ :
+ <install-type>EXE
+ <location>../../dist/bin
+ :
+ release
+ ;
+
+install dist-lib
+ :
+ bcp
+ :
+ <install-type>LIB
+ <location>../../dist/lib
+ :
+ release
+ ;
+
diff --git a/tools/bcp/add_dependent_lib.cpp b/tools/bcp/add_dependent_lib.cpp
new file mode 100644
index 0000000000..bb1818a2e2
--- /dev/null
+++ b/tools/bcp/add_dependent_lib.cpp
@@ -0,0 +1,216 @@
+/*
+ *
+ * Copyright (c) 2009 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * This file implements the following:
+ * void bcp_implementation::add_path(const fs::path& p)
+ * void bcp_implementation::add_directory(const fs::path& p)
+ * void bcp_implementation::add_file(const fs::path& p)
+ * void bcp_implementation::add_dependent_lib(const std::string& libname, const fs::path& p, const fileview& view)
+ */
+
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <boost/regex.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/exception.hpp>
+#include <iostream>
+
+//
+// This file contains the code required to work out whether the source/header file being scanned
+// is actually dependent upon some library's source code or not.
+//
+
+static std::map<std::string, boost::regex> scanner;
+
+static std::map<std::string, std::set<std::string> > free_function_names;
+static std::map<std::string, std::set<std::string> > class_names;
+static std::map<std::string, std::set<std::string> > variable_names;
+
+static void init_library_scanner(const fs::path& p, bool cvs_mode, const std::string& libname, bool recurse = false)
+{
+ /*
+ if(free_function_names.count(libname) == 0)
+ {
+ free_function_names[libname] = "[\\x0]";
+ class_names[libname] = "[\\x0]";
+ variable_names[libname] = "[\\x0]";
+ }
+ */
+ //
+ // Don't add files created by build system:
+ //
+ if((p.leaf() == "bin") || (p.leaf() == "bin-stage"))
+ return;
+ //
+ // Don't add version control directories:
+ //
+ if((p.leaf() == "CVS") || (p.leaf() == ".svn"))
+ return;
+ //
+ // don't add directories not under version control:
+ //
+ if(cvs_mode && !fs::exists(p / "CVS/Entries"))
+ return;
+ if(cvs_mode && !fs::exists(p / ".svn/entries"))
+ return;
+ //
+ // Enumerate files and directories:
+ //
+ fs::directory_iterator i(p);
+ fs::directory_iterator j;
+ while(i != j)
+ {
+ if(fs::is_directory(*i))
+ init_library_scanner(*i, cvs_mode, libname, true);
+ if(bcp_implementation::is_source_file(*i))
+ {
+ static boost::regex function_scanner(
+ "(?|" // Branch reset group
+ "(?:\\<\\w+\\>[^>;{},:]*)" // Return type
+ "(?:"
+ "(\\<\\w+\\>)" // Maybe class name
+ "\\s*"
+ "(?:<[^>;{]*>)?" // Maybe template specialisation
+ "::\\s*)?"
+ "(\\<(?!throw|if|while|for|catch)\\w+\\>)" // function name
+ "\\s*"
+ "\\("
+ "[^\\(\\);{}]*" // argument list
+ "\\)"
+ "\\s*"
+ "\\{" // start of definition
+ "|"
+ "(\\<\\w+\\>)" // Maybe class name
+ "\\s*"
+ "(?:<[^>;{]*>)?" // Maybe template specialisation
+ "::\\s*"
+ "~?\\1" // function name, same as class name
+ "\\s*"
+ "\\("
+ "[^\\(\\);{}]*" // argument list
+ "\\)"
+ "\\s*"
+ "\\{" // start of definition
+ ")" // end branch reset
+ );
+ fileview view(*i);
+ boost::regex_iterator<const char*> a(view.begin(), view.end(), function_scanner);
+ boost::regex_iterator<const char*> b;
+ while(a != b)
+ {
+ if((*a)[1].matched)
+ {
+ std::string n = a->str(1);
+ class_names[libname].insert(n);
+ }
+ else
+ {
+ std::string n = a->str(2);
+ free_function_names[libname].insert(n);
+ }
+ ++a;
+ }
+ }
+ ++i;
+ }
+
+ if(recurse == false)
+ {
+ //
+ // Build the regular expressions:
+ //
+ const char* e1 =
+ "^(?>[[:blank:]]*)(?!#)[^;{}\\r\\n]*"
+ "(?|"
+ "(?:class|struct)[^:;{}#]*"
+ "(";
+ // list of class names goes here...
+ const char* e2 =
+ ")\\s*(?:<[^;{>]*>\\s*)?(?::[^;{]*)?\\{"
+ "|"
+ "\\<(?!return)\\w+\\>[^:;{}#=<>!~%.\\w]*(";
+ // List of function names goes here...
+ const char* e3 =
+ ")\\s*\\([^;()]*\\)\\s*;)";
+
+ std::string class_name_list;
+ std::set<std::string>::const_iterator i = class_names[libname].begin(), j = class_names[libname].end();
+ if(i != j)
+ {
+ class_name_list = *i;
+ ++i;
+ while(i != j)
+ {
+ class_name_list += "|" + *i;
+ ++i;
+ }
+ }
+ else
+ {
+ class_name_list = "[\\x0]";
+ }
+ std::string function_name_list;
+ i = free_function_names[libname].begin();
+ j = free_function_names[libname].end();
+ if(i != j)
+ {
+ function_name_list = *i;
+ ++i;
+ while(i != j)
+ {
+ function_name_list += "|" + *i;
+ ++i;
+ }
+ }
+ else
+ {
+ function_name_list = "[\\x0]";
+ }
+
+ scanner[libname] = boost::regex(e1 + class_name_list + e2 + function_name_list + e3);
+ }
+}
+
+void bcp_implementation::add_dependent_lib(const std::string& libname, const fs::path& p, const fileview& view)
+{
+ //
+ // if the boost library libname has source associated with it
+ // then add the source to our list:
+ //
+ if(fs::exists(m_boost_path / "libs" / libname / "src"))
+ {
+ if(!m_dependencies.count(fs::path("libs") / libname / "src"))
+ {
+ if(scanner.count(libname) == 0)
+ init_library_scanner(m_boost_path / "libs" / libname / "src", m_cvs_mode, libname);
+ boost::cmatch what;
+ if(regex_search(view.begin(), view.end(), what, scanner[libname]))
+ {
+ std::cout << "INFO: tracking source dependencies of library " << libname
+ << " due to presence of \"" << what << "\" in file " << p << std::endl;
+ //std::cout << "Full text match was: " << what << std::endl;
+ m_dependencies[fs::path("libs") / libname / "src"] = p; // set up dependency tree
+ add_path(fs::path("libs") / libname / "src");
+
+ if(fs::exists(m_boost_path / "libs" / libname / "build"))
+ {
+ if(!m_dependencies.count(fs::path("libs") / libname / "build"))
+ {
+ m_dependencies[fs::path("libs") / libname / "build"] = p; // set up dependency tree
+ add_path(fs::path("libs") / libname / "build");
+ //m_dependencies[fs::path("boost-build.jam")] = p;
+ //add_path(fs::path("boost-build.jam"));
+ m_dependencies[fs::path("Jamroot")] = p;
+ add_path(fs::path("Jamroot"));
+ //m_dependencies[fs::path("tools/build")] = p;
+ //add_path(fs::path("tools/build"));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tools/bcp/add_path.cpp b/tools/bcp/add_path.cpp
new file mode 100644
index 0000000000..3643bdb6c6
--- /dev/null
+++ b/tools/bcp/add_path.cpp
@@ -0,0 +1,535 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * This file implements the following:
+ * void bcp_implementation::add_path(const fs::path& p)
+ * void bcp_implementation::add_directory(const fs::path& p)
+ * void bcp_implementation::add_file(const fs::path& p)
+ * void bcp_implementation::add_dependent_lib(const std::string& libname, const fs::path& p, const fileview& view)
+ */
+
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <boost/regex.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/exception.hpp>
+#include <iostream>
+
+
+void bcp_implementation::add_path(const fs::path& p)
+{
+ fs::path normalized_path = p;
+ normalized_path.normalize();
+ if(fs::exists(m_boost_path / normalized_path))
+ {
+ if(fs::is_directory(m_boost_path / normalized_path))
+ add_directory(normalized_path);
+ else
+ add_file(normalized_path);
+ }
+ else
+ {
+ std::cerr << "CAUTION: dependent file " << p.string() << " does not exist." << std::endl;
+ std::cerr << " Found while scanning file " << m_dependencies[p].string() << std::endl;
+ }
+}
+
+void bcp_implementation::add_directory(const fs::path& p)
+{
+ //
+ // Don't add files created by build system:
+ //
+ if((p.leaf() == "bin") || (p.leaf() == "bin-stage"))
+ return;
+ //
+ // Don't add version control directories:
+ //
+ if((p.leaf() == "CVS") || (p.leaf() == ".svn"))
+ return;
+ //
+ // don't add directories not under version control:
+ //
+ if(m_cvs_mode && !fs::exists(m_boost_path / p / "CVS/Entries"))
+ return;
+ if(m_svn_mode && !fs::exists(m_boost_path / p / ".svn/entries"))
+ return;
+ //
+ // enermerate files and directories:
+ //
+ fs::directory_iterator i(m_boost_path / p);
+ fs::directory_iterator j;
+ while(i != j)
+ {
+ //
+ // we need to convert *i back into
+ // a relative path, what follows is a hack:
+ //
+ std::string s(i->path().string());
+ if(m_boost_path.string().size())
+ s.erase(0, m_boost_path.string().size() + 1);
+ fs::path np = s;
+ if(!m_dependencies.count(np))
+ {
+ m_dependencies[np] = p; // set up dependency tree
+ add_path(np);
+ }
+ ++i;
+ }
+}
+
+void bcp_implementation::add_file(const fs::path& p)
+{
+ //
+ // if the file does not exist in cvs then don't do anything with it:
+ //
+ if((m_cvs_mode || m_svn_mode) && (m_cvs_paths.find(p) == m_cvs_paths.end()))
+ return;
+ //
+ // if we've already seen the file return:
+ //
+ if(m_copy_paths.find(p) != m_copy_paths.end())
+ return;
+ //
+ // add the file to our list:
+ //
+ m_copy_paths.insert(p);
+ //
+ // if this is a source file, scan for dependencies:
+ //
+ if(is_source_file(p))
+ {
+ add_file_dependencies(p, false);
+ }
+ if(is_jam_file(p) && m_namespace_name.size() && ((std::distance(p.begin(), p.end()) < 3) || (*p.begin() != "tools") || (*++p.begin() != "build")))
+ {
+ //
+ // We're doing a rename of namespaces and library names
+ // so scan for names of libraries:
+ //
+ static const boost::regex e(
+ "\\<lib\\s+(boost\\w+)\\s+[:;]"
+ );
+
+ fileview view(m_boost_path / p);
+ boost::regex_token_iterator<const char*> i(view.begin(), view.end(), e, 1);
+ boost::regex_token_iterator<const char*> j;
+ while(i != j)
+ {
+ m_lib_names.insert(*i);
+ ++i;
+ }
+ static const std::pair<fs::path, std::string> specials_library_names[] = {
+ std::pair<fs::path, std::string>("libs/python/build/Jamfile.v2", "boost_python"),
+ std::pair<fs::path, std::string>("libs/python/build/Jamfile.v2", "boost_python3"),
+ };
+
+ for(unsigned int n = 0; n < (sizeof(specials_library_names)/sizeof(specials_library_names[0])); ++n)
+ {
+ if(0 == compare_paths(specials_library_names[n].first, p))
+ {
+ m_lib_names.insert(specials_library_names[n].second);
+ }
+ }
+ }
+ //
+ // if this is a html file, scan for dependencies:
+ //
+ if(is_html_file(p))
+ {
+ static const boost::regex e(
+ "<(?:img[^>]*src=|link[^>]*href=)(\"[^\"]+\"|\\w+)[^>]*>"
+ );
+
+ fileview view(m_boost_path / p);
+ boost::regex_token_iterator<const char*> i(view.begin(), view.end(), e, 1);
+ boost::regex_token_iterator<const char*> j;
+ while(i != j)
+ {
+ //
+ // extract the dependent name:
+ //
+ std::string s(*i);
+ if(s[0] == '\"')
+ {
+ // remove quotes:
+ assert(s.size() > 2);
+ s.erase(0, 1);
+ s.erase(s.size() - 1);
+ }
+ //
+ // Remove any target suffix:
+ //
+ std::string::size_type n = s.find('#');
+ if(n != std::string::npos)
+ {
+ s.erase(n);
+ }
+ //
+ // if the name starts with ./ remove it
+ // or we'll get an error:
+ if(s.compare(0, 2, "./") == 0)
+ s.erase(0, 2);
+ if(s.find(':') == std::string::npos)
+ {
+ // only concatonate if it's a relative path
+ // rather than a URL:
+ fs::path dep(p.branch_path() / s);
+ if(!m_dependencies.count(dep))
+ {
+ m_dependencies[dep] = p; // set up dependency tree
+ add_path(dep);
+ }
+ }
+ ++i;
+ }
+ }
+ //
+ // now scan for "special" dependencies:
+ // anything that we can't automatically detect...
+ //
+static const std::pair<fs::path, fs::path>
+ specials[] = {
+ std::pair<fs::path, fs::path>("boost/filesystem/convenience.hpp", "boost/filesystem.hpp"),
+ std::pair<fs::path, fs::path>("boost/filesystem/exception.hpp", "boost/filesystem.hpp"),
+ std::pair<fs::path, fs::path>("boost/filesystem/fstream.hpp", "boost/filesystem.hpp"),
+ std::pair<fs::path, fs::path>("boost/filesystem/operations.hpp", "boost/filesystem.hpp"),
+ std::pair<fs::path, fs::path>("boost/filesystem/path.hpp", "boost/filesystem.hpp"),
+ std::pair<fs::path, fs::path>("boost/filesystem.hpp", "libs/filesystem/build"),
+ std::pair<fs::path, fs::path>("boost/filesystem.hpp", "libs/filesystem/v2"),
+ std::pair<fs::path, fs::path>("boost/filesystem.hpp", "libs/filesystem/v3"),
+ std::pair<fs::path, fs::path>("boost/config.hpp", "boost/config"),
+ std::pair<fs::path, fs::path>("tools/build/allyourbase.jam", "Jamrules"),
+ std::pair<fs::path, fs::path>("tools/build/allyourbase.jam", "project-root.jam"),
+ std::pair<fs::path, fs::path>("tools/build/allyourbase.jam", "boost-build.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v1/allyourbase.jam", "Jamrules"),
+ std::pair<fs::path, fs::path>("tools/build/v1/allyourbase.jam", "project-root.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v1/allyourbase.jam", "boost-build.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "Jamrules"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "project-root.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "boost-build.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "Jamfile.v2"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "boostcpp.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "bootstrap.bat"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "bootstrap.sh"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "Jamroot"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "INSTALL"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "LICENSE_1_0.txt"),
+ std::pair<fs::path, fs::path>("boost/preprocessor/iterate.hpp", "boost/preprocessor/iteration"),
+ std::pair<fs::path, fs::path>("boost/preprocessor/slot/slot.hpp", "boost/preprocessor/slot/detail"),
+ std::pair<fs::path, fs::path>("boost/function.hpp", "boost/function/detail"),
+ std::pair<fs::path, fs::path>("boost/regex/config.hpp", "boost/regex/user.hpp"),
+ std::pair<fs::path, fs::path>("boost/signals/signal_template.hpp", "boost/function"),
+ std::pair<fs::path, fs::path>("boost/mpl/list.hpp", "boost/mpl/list"),
+ std::pair<fs::path, fs::path>("boost/mpl/list_c.hpp", "boost/mpl/list"),
+ std::pair<fs::path, fs::path>("boost/mpl/vector.hpp", "boost/mpl/vector"),
+ std::pair<fs::path, fs::path>("boost/mpl/deque.hpp", "boost/mpl/vector"),
+ std::pair<fs::path, fs::path>("boost/mpl/vector_c.hpp", "boost/mpl/vector"),
+ std::pair<fs::path, fs::path>("boost/mpl/map.hpp", "boost/mpl/map"),
+ std::pair<fs::path, fs::path>("boost/mpl/set.hpp", "boost/mpl/set"),
+ std::pair<fs::path, fs::path>("boost/mpl/set_c.hpp", "boost/mpl/set"),
+ std::pair<fs::path, fs::path>("boost/mpl/aux_/include_preprocessed.hpp", "boost/mpl/aux_/preprocessed"),
+ std::pair<fs::path, fs::path>("boost/mpl/vector/aux_/include_preprocessed.hpp", "boost/mpl/vector/aux_/preprocessed"),
+ std::pair<fs::path, fs::path>("boost/mpl/set/aux_/include_preprocessed.hpp", "boost/mpl/set/aux_/preprocessed"),
+ std::pair<fs::path, fs::path>("boost/mpl/map/aux_/include_preprocessed.hpp", "boost/mpl/map/aux_/preprocessed"),
+ std::pair<fs::path, fs::path>("boost/mpl/list/aux_/include_preprocessed.hpp", "boost/mpl/list/aux_/preprocessed"),
+ std::pair<fs::path, fs::path>("libs/graph/src/python/visitor.hpp", "libs/graph/src/python"),
+ std::pair<fs::path, fs::path>("boost/test/detail/config.hpp", "libs/test/src"),
+ std::pair<fs::path, fs::path>("boost/test/detail/config.hpp", "libs/test/build"),
+ std::pair<fs::path, fs::path>("boost/typeof.hpp", "boost/typeof/incr_registration_group.hpp"),
+ std::pair<fs::path, fs::path>("boost/function_types/detail/pp_loop.hpp", "boost/function_types/detail/pp_cc_loop"),
+ std::pair<fs::path, fs::path>("boost/function_types/components.hpp", "boost/function_types/detail/components_impl"),
+ std::pair<fs::path, fs::path>("boost/function_types/detail/pp_loop.hpp", "boost/function_types/detail"),
+ std::pair<fs::path, fs::path>("boost/math/tools/rational.hpp", "boost/math/tools/detail"),
+ std::pair<fs::path, fs::path>("boost/proto/repeat.hpp", "boost/proto/detail/local.hpp"),
+ std::pair<fs::path, fs::path>("boost/signals/signal_template.hpp", "boost/function"),
+ std::pair<fs::path, fs::path>("boost/preprocessor/slot/counter.hpp", "boost/preprocessor/slot/detail/counter.hpp"),
+ std::pair<fs::path, fs::path>("boost/graph/distributed/detail/tag_allocator.hpp", "libs/graph_parallel"),
+ std::pair<fs::path, fs::path>("boost/graph/distributed/mpi_process_group.hpp", "libs/graph_parallel"),
+ };
+
+ for(unsigned int n = 0; n < (sizeof(specials)/sizeof(specials[0])); ++n)
+ {
+ if(0 == compare_paths(specials[n].first, p))
+ {
+ if(!m_dependencies.count(specials[n].second))
+ {
+ m_dependencies[specials[n].second] = p; // set up dependency tree
+ add_path(specials[n].second);
+ }
+ }
+ }
+
+}
+
+void bcp_implementation::add_file_dependencies(const fs::path& p, bool scanfile)
+{
+ static const boost::regex e(
+ "^[[:blank:]]*(?://@bcp[[:blank:]]+([^\\n]*)\n)?#[[:blank:]]*include[[:blank:]]*[\"<]([^\">]+)[\">]"
+ );
+
+ if(!m_dependencies.count(p))
+ m_dependencies[p] = p; // set terminal dependency
+
+ fileview view;
+ if(scanfile)
+ view.open(p);
+ else
+ view.open(m_boost_path / p);
+ if(m_license_mode && !scanfile)
+ scan_license(p, view);
+ const int subs[] = { 1, 2 };
+ boost::regex_token_iterator<const char*> i(view.begin(), view.end(), e, subs);
+ boost::regex_token_iterator<const char*> j;
+ while(i != j)
+ {
+ //
+ // *i contains the name of the include file,
+ // check first for a file of that name in the
+ // same directory as the file we are scanning,
+ // and if that fails, then check the boost-root:
+ //
+ fs::path include_file;
+ try{
+ std::string discart_message = *i;
+ ++i;
+ if(discart_message.size())
+ {
+ // The include is optional and should be discarded:
+ std::cout << "Optional functionality won't be copied: " << discart_message << std::endl;
+ std::cout << "Add the file " << *i << " to the list of dependencies to extract to copy this functionality." << std::endl;
+ ++i;
+ continue;
+ }
+ include_file = i->str();
+ fs::path test_file(m_boost_path / p.branch_path() / include_file);
+ if(fs::exists(test_file) && !fs::is_directory(test_file) && (p.branch_path().string() != "boost"))
+ {
+ if(!m_dependencies.count(p.branch_path() / include_file))
+ {
+ m_dependencies[p.branch_path() / include_file] = p;
+ add_path(p.branch_path() / include_file);
+ }
+ }
+ else if(fs::exists(m_boost_path / include_file))
+ {
+ if(!m_dependencies.count(include_file))
+ {
+ m_dependencies[include_file] = p;
+ add_path(include_file);
+ }
+ }
+ ++i;
+ }
+ catch(const fs::filesystem_error&)
+ {
+ std::cerr << "Can't parse filename " << *i << " included by file " << p.string() << std::endl;
+ ++i;
+ continue;
+ }
+ }
+ //
+ // Now we need to scan for Boost.Preprocessor includes that
+ // are included via preprocessor iteration:
+ //
+ static const boost::regex ppfiles("^[[:blank:]]*#[[:blank:]]*define[[:blank:]]+(?:BOOST_PP_FILENAME|BOOST_PP_ITERATION_PARAMS|BOOST_PP_INDIRECT_SELF)(?:[^\\n]|\\\\\\n)+?[\"<]([^\">]+)[\">]");
+ i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), ppfiles, 1);
+ while(i != j)
+ {
+ //
+ // *i contains the name of the include file,
+ // check first for a file of that name in the
+ // same directory as the file we are scanning,
+ // and if that fails, then check the boost-root:
+ //
+ fs::path include_file;
+ try{
+ include_file = i->str();
+ }
+ catch(const fs::filesystem_error&)
+ {
+ std::cerr << "Can't parse filename " << *i << " included by file " << p.string() << std::endl;
+ ++i;
+ continue;
+ }
+ fs::path test_file(m_boost_path / p.branch_path() / include_file);
+ if(fs::exists(test_file) && !fs::is_directory(test_file) && (p.branch_path().string() != "boost"))
+ {
+ if(!m_dependencies.count(p.branch_path() / include_file))
+ {
+ m_dependencies[p.branch_path() / include_file] = p;
+ add_path(p.branch_path() / include_file);
+ }
+ }
+ else if(fs::exists(m_boost_path / include_file))
+ {
+ if(!m_dependencies.count(include_file))
+ {
+ m_dependencies[include_file] = p;
+ add_path(include_file);
+ }
+ }
+ else
+ {
+ std::cerr << "CAUTION: Boost.Preprocessor iterated file " << include_file.string() << " does not exist." << std::endl;
+ }
+ ++i;
+ }
+
+ //
+ // Scan for any #include MACRO includes that we don't recognise.
+ //
+ // Begin by declaring all of the macros that get #included that
+ // we know about and are correctly handled as special cases:
+ //
+ static const std::string known_macros[] = {
+ "AUX778076_INCLUDE_STRING",
+ "BOOST_PP_STRINGIZE(boost/mpl/aux_/preprocessed/AUX778076_PREPROCESSED_HEADER)",
+ "BOOST_USER_CONFIG",
+ "BOOST_COMPILER_CONFIG",
+ "BOOST_STDLIB_CONFIG",
+ "BOOST_PLATFORM_CONFIG",
+ "BOOST_PP_FILENAME_1",
+ "BOOST_PP_ITERATION_PARAMS_1",
+ "BOOST_PP_FILENAME_2",
+ "BOOST_PP_ITERATION_PARAMS_2",
+ "BOOST_PP_FILENAME_3",
+ "BOOST_PP_ITERATION_PARAMS_3",
+ "BOOST_PP_FILENAME_4",
+ "BOOST_PP_ITERATION_PARAMS_4",
+ "BOOST_PP_FILENAME_5",
+ "BOOST_PP_ITERATION_PARAMS_5",
+ "BOOST_PP_INDIRECT_SELF",
+ "BOOST_PP_INCLUDE_SELF()",
+ "BOOST_PP_ITERATE",
+ "BOOST_PP_LOCAL_ITERATE",
+ "BOOST_PP_ITERATE()",
+ "BOOST_PP_LOCAL_ITERATE()",
+ "BOOST_PP_ASSIGN_SLOT(1)",
+ "BOOST_PP_ASSIGN_SLOT(2)",
+ "BOOST_PP_ASSIGN_SLOT(3)",
+ "BOOST_PP_ASSIGN_SLOT(4)",
+ "BOOST_PP_ASSIGN_SLOT(5)",
+ "BOOST_ABI_PREFIX",
+ "BOOST_ABI_SUFFIX",
+ "BOOST_PP_STRINGIZE(boost/mpl/aux_/preprocessed/AUX_PREPROCESSED_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_LIST_C_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_LIST_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/map/aux_/preprocessed/AUX778076_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/map/AUX778076_MAP_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/set/aux_/preprocessed/AUX778076_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/set/AUX778076_SET_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/set/AUX778076_SET_C_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/vector/AUX778076_VECTOR_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/vector/aux_/preprocessed/AUX778076_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/vector/AUX778076_DEQUE_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/vector/AUX778076_VECTOR_C_HEADER)",
+ "BOOST_REGEX_USER_CONFIG",
+ "BGL_PYTHON_EVENTS_HEADER",
+ "B1",
+ "B2",
+ "BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()",
+ "BOOST_SLIST_HEADER",
+ "BOOST_HASH_SET_HEADER",
+ "BOOST_HASH_MAP_HEADER",
+ "BOOST_INTRUSIVE_INVARIANT_ASSERT_INCLUDE",
+ "BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT_INCLUDE",
+ "BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE",
+ "BOOST_FT_loop",
+ "BOOST_FT_AL_PREPROCESSED",
+ "BOOST_FT_AL_INCLUDE_FILE",
+ "__FILE__",
+ "BOOST_FT_cc_file",
+ "BOOST_FT_variate_file",
+ "BOOST_USER_CONFIG",
+ "BOOST_HEADER()",
+ "BOOST_TR1_STD_HEADER(utility)",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(tuple))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(random))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(array))",
+ "BOOST_TR1_HEADER(cmath)",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(complex))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(functional))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(memory))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(regex))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(type_traits))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(unordered_map))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(unordered_set))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(utility))",
+ "BOOST_PROTO_LOCAL_ITERATE()",
+ "BOOST_SIGNAL_FUNCTION_N_HEADER",
+ "BOOST_PP_UPDATE_COUNTER()",
+ };
+
+ static const boost::regex indirect_includes("^[[:blank:]]*#[[:blank:]]*include[[:blank:]]+([^\"<][^\n]*?)[[:blank:]]*$");
+ i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), indirect_includes, 1);
+ while(i != j)
+ {
+ const std::string* known_macros_end = known_macros + sizeof(known_macros)/sizeof(known_macros[0]);
+ if(known_macros_end == std::find(known_macros, known_macros_end, i->str()))
+ {
+ std::cerr << "CAUTION: don't know how to trace depenencies through macro: \"" << *i << "\" in file: " << p.string() << std::endl;
+ }
+ ++i;
+ }
+ //
+ // if the file contains a cpp_main / unit_test_main / test_main
+ // it is dependent upon Boost.test even if it doesn't
+ // include any of the Boost.test headers directly.
+ //
+ static const boost::regex m("^\\s*int\\s+(?:cpp_main|test_main|unit_test_main)");
+ boost::cmatch what;
+ if(boost::regex_search(view.begin(), view.end(), what, m))
+ {
+ add_dependent_lib("test", p, view);
+ }
+ if(!scanfile)
+ {
+ //
+ // grab the name of the library to which the header belongs,
+ // and if that library has source then add the source to our
+ // list:
+ //
+ // this regex catches boost/libname.hpp or boost/libname/whatever:
+ //
+ static const boost::regex lib1("boost/([^\\./]+)(?!detail).*");
+ boost::smatch swhat;
+ std::string gs(p.generic_string());
+ if(boost::regex_match(gs, swhat, lib1))
+ {
+ add_dependent_lib(swhat.str(1), p, view);
+ }
+ //
+ // and this one catches boost/x/y/whatever (for example numeric/ublas):
+ //
+ static const boost::regex lib2("boost/([^/]+/[^/]+)/(?!detail).*");
+ gs = p.generic_string();
+ if(boost::regex_match(gs, swhat, lib2))
+ {
+ add_dependent_lib(swhat.str(1), p, view);
+ }
+ }
+ if(m_list_namespaces)
+ {
+ //
+ // scan for top level namespaces and add to our list:
+ //
+ static const boost::regex namespace_scanner(
+ "^(?<!\\\\\\n)[[:blank:]]*+namespace\\s++(\\w++)\\s++(\\{[^{}]*(?:(?2)[^{}]*)*\\})"
+ );
+ i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), namespace_scanner, 1);
+ while(i != j)
+ {
+ if(m_top_namespaces.count(*i) == 0)
+ {
+ //std::cout << *i << " (Found in " << p << ")" << std::endl;
+ m_top_namespaces[*i] = p;
+ }
+ ++i;
+ }
+ }
+}
diff --git a/tools/bcp/bcp.hpp b/tools/bcp/bcp.hpp
new file mode 100644
index 0000000000..bec63641c0
--- /dev/null
+++ b/tools/bcp/bcp.hpp
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include <boost/shared_ptr.hpp>
+
+#if defined(BOOST_FILESYSTEM_VERSION) && (BOOST_FILESYSTEM_VERSION != 3)
+# error "This library must be built with Boost.Filesystem version 3"
+#else
+#define BOOST_FILESYSTEM_VERSION 3
+#endif
+
+class bcp_application;
+typedef boost::shared_ptr<bcp_application> pbcp_application;
+
+class bcp_application
+{
+public:
+ virtual ~bcp_application();
+
+ virtual void enable_list_mode() = 0;
+ virtual void enable_summary_list_mode() = 0;
+ virtual void enable_cvs_mode() = 0;
+ virtual void enable_svn_mode() = 0;
+ virtual void enable_unix_lines() = 0;
+ virtual void enable_scan_mode() = 0;
+ virtual void enable_license_mode() = 0;
+ virtual void enable_bsl_convert_mode() = 0;
+ virtual void enable_bsl_summary_mode() = 0;
+ virtual void set_boost_path(const char* p) = 0;
+ virtual void set_destination(const char* p) = 0;
+ virtual void add_module(const char* p) = 0;
+ virtual void set_namespace(const char* name) = 0;
+ virtual void set_namespace_alias(bool) = 0;
+ virtual void set_namespace_list(bool) = 0;
+
+ virtual int run() = 0;
+
+ static pbcp_application create();
+};
+
+
diff --git a/tools/bcp/bcp_imp.cpp b/tools/bcp/bcp_imp.cpp
new file mode 100644
index 0000000000..cfce215769
--- /dev/null
+++ b/tools/bcp/bcp_imp.cpp
@@ -0,0 +1,295 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * This file implements the bcp_implementation virtuals.
+ */
+
+#include "bcp_imp.hpp"
+#include "licence_info.hpp"
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <iostream>
+#include <stdexcept>
+#include <boost/regex.hpp>
+#include <string>
+
+bcp_implementation::bcp_implementation()
+ : m_list_mode(false), m_list_summary_mode(false), m_license_mode(false), m_cvs_mode(false),
+ m_svn_mode(false), m_unix_lines(false), m_scan_mode(false), m_bsl_convert_mode(false),
+ m_bsl_summary_mode(false), m_namespace_alias(false), m_list_namespaces(false)
+{
+}
+
+bcp_implementation::~bcp_implementation()
+{
+}
+
+bcp_application::~bcp_application()
+{
+}
+
+void bcp_implementation::enable_list_mode()
+{
+ m_list_mode = true;
+}
+
+void bcp_implementation::enable_summary_list_mode()
+{
+ m_list_mode = true;
+ m_list_summary_mode = true;
+}
+
+void bcp_implementation::enable_cvs_mode()
+{
+ m_cvs_mode = true;
+}
+
+void bcp_implementation::enable_svn_mode()
+{
+ m_svn_mode = true;
+}
+
+void bcp_implementation::enable_scan_mode()
+{
+ m_scan_mode = true;
+}
+
+void bcp_implementation::enable_license_mode()
+{
+ m_license_mode = true;
+}
+
+void bcp_implementation::enable_bsl_convert_mode()
+{
+ m_bsl_convert_mode = true;
+}
+
+void bcp_implementation::enable_bsl_summary_mode()
+{
+ m_bsl_summary_mode = true;
+}
+
+void bcp_implementation::enable_unix_lines()
+{
+ m_unix_lines = true;
+}
+
+void bcp_implementation::set_boost_path(const char* p)
+{
+ // Hack to strip trailing slashes from the path
+ m_boost_path = (fs::path(p) / "boost").parent_path();
+ fs::path check = m_boost_path / "boost" / "version.hpp";
+ if(!fs::exists(check))
+ {
+ std::string s = "The Boost path appears to have been incorrectly set: could not find boost/version.hpp in ";
+ s += m_boost_path.string();
+ std::runtime_error e(s);
+ throw e;
+ }
+}
+
+void bcp_implementation::set_destination(const char* p)
+{
+ m_dest_path = fs::path(p);
+}
+
+void bcp_implementation::add_module(const char* p)
+{
+ m_module_list.push_back(p);
+}
+
+void bcp_implementation::set_namespace(const char* name)
+{
+ m_namespace_name = name;
+}
+
+void bcp_implementation::set_namespace_alias(bool b)
+{
+ m_namespace_alias = b;
+}
+
+void bcp_implementation::set_namespace_list(bool b)
+{
+ m_list_namespaces = b;
+ m_list_mode = b;
+}
+
+fs::path get_short_path(const fs::path& p)
+{
+ // truncate path no more than "x/y":
+ std::string s = p.generic_string();
+ std::string::size_type n = s.find('/');
+ if(n != std::string::npos)
+ {
+ n = s.find('/', n+1);
+ if(n != std::string::npos)
+ s.erase(n);
+ }
+ return s;
+}
+
+int bcp_implementation::run()
+{
+ //
+ // check output path is OK:
+ //
+ if(!m_list_mode && !m_license_mode && !fs::exists(m_dest_path))
+ {
+ std::string msg("Destination path does not exist: ");
+ msg.append(m_dest_path.string());
+ std::runtime_error e(msg);
+ boost::throw_exception(e);
+ }
+ //
+ // Check Boost path is OK if it hasn't been checked already:
+ //
+ if(m_boost_path == "")
+ {
+ set_boost_path("");
+ }
+ // start by building a list of permitted files
+ // if m_cvs_mode is true:
+ if(m_cvs_mode)
+ {
+ std::cerr << "CAUTION: Boost is no longer in CVS, cvs mode may not work anymore!!!" << std::endl;
+ scan_cvs_path(fs::path());
+ }
+ if(m_svn_mode)
+ {
+ scan_svn_path(fs::path());
+ }
+ //
+ // if in license mode, try to load more/blanket_permission.txt
+ //
+ fs::path blanket_permission(m_boost_path / "more" / "blanket-permission.txt");
+ if (fs::exists(blanket_permission)) {
+ fs::ifstream in(blanket_permission);
+ std::string line;
+ while (std::getline(in, line)) {
+ static const boost::regex e("([^(]+)\\(");
+ boost::smatch result;
+ if (boost::regex_search(line, result, e))
+ m_bsl_authors.insert(format_authors_name(result[1]));
+ }
+ }
+
+ //
+ // scan through modules looking for the equivalent
+ // file to add to our list:
+ //
+ std::list<std::string>::const_iterator i = m_module_list.begin();
+ std::list<std::string>::const_iterator j = m_module_list.end();
+ while(i != j)
+ {
+ //
+ // convert *i to a path - could be native or portable:
+ //
+ fs::path module;
+ fs::path exmodule;
+ module = fs::path(*i);
+ exmodule = fs::path(*i + ".hpp");
+
+ if(m_scan_mode)
+ {
+ // in scan mode each module must be a real file:
+ add_file_dependencies(module, true);
+ }
+ else
+ {
+ int count = 0;
+ if(fs::exists(m_boost_path / "tools" / module))
+ {
+ add_path(fs::path("tools") / module);
+ ++count;
+ }
+ if(fs::exists(m_boost_path / "libs" / module))
+ {
+ add_path(fs::path("libs") / module);
+ ++count;
+ }
+ if(fs::exists(m_boost_path / "boost" / module))
+ {
+ add_path(fs::path("boost") / module);
+ ++count;
+ }
+ if(fs::exists(m_boost_path / "boost" / exmodule))
+ {
+ add_path(fs::path("boost") / exmodule);
+ ++count;
+ }
+ if(fs::exists(m_boost_path / module))
+ {
+ add_path(module);
+ ++count;
+ }
+ }
+ ++i;
+ }
+ //
+ // now perform output:
+ //
+ if(m_list_namespaces)
+ {
+ // List the namespaces, in two lists, headers and source files
+ // first, then everything else afterwards:
+ //
+ boost::regex important_file("boost/.*|libs/[^/]*/(?:[^/]*/)?/src/.*");
+ std::map<std::string, fs::path>::const_iterator i, j;
+ i = m_top_namespaces.begin();
+ j = m_top_namespaces.end();
+ std::cout << "\n\nThe top level namespaces found for header and source files were:\n";
+ while(i != j)
+ {
+ if(regex_match(i->second.generic_string(), important_file))
+ std::cout << i->first << " (from " << i->second << ")" << std::endl;
+ ++i;
+ }
+
+ i = m_top_namespaces.begin();
+ std::cout << "\n\nThe top level namespaces found for all other source files were:\n";
+ while(i != j)
+ {
+ if(!regex_match(i->second.generic_string(), important_file))
+ std::cout << i->first << " (from " << i->second << ")" << std::endl;
+ ++i;
+ }
+ return 0;
+ }
+ std::set<fs::path, path_less>::iterator m, n;
+ std::set<fs::path, path_less> short_paths;
+ m = m_copy_paths.begin();
+ n = m_copy_paths.end();
+ if(!m_license_mode)
+ {
+ while(m != n)
+ {
+ if(m_list_summary_mode)
+ {
+ fs::path p = get_short_path(*m);
+ if(short_paths.find(p) == short_paths.end())
+ {
+ short_paths.insert(p);
+ std::cout << p.string() << "\n";
+ }
+ }
+ else if(m_list_mode)
+ std::cout << m->string() << "\n";
+ else
+ copy_path(*m);
+ ++m;
+ }
+ }
+ else
+ output_license_info();
+ return 0;
+}
+
+pbcp_application bcp_application::create()
+{
+ pbcp_application result(static_cast<bcp_application*>(new bcp_implementation()));
+ return result;
+}
diff --git a/tools/bcp/bcp_imp.hpp b/tools/bcp/bcp_imp.hpp
new file mode 100644
index 0000000000..9f45915199
--- /dev/null
+++ b/tools/bcp/bcp_imp.hpp
@@ -0,0 +1,118 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "bcp.hpp"
+#include <string>
+#include <cstring>
+#include <list>
+#include <set>
+#include <map>
+#include <boost/filesystem/path.hpp>
+
+namespace fs = boost::filesystem;
+
+class fileview;
+
+//
+//path operations:
+//
+int compare_paths(const fs::path& a, const fs::path& b);
+inline bool equal_paths(const fs::path& a, const fs::path& b)
+{ return compare_paths(a, b) == 0; }
+
+struct path_less
+{
+ bool operator()(const fs::path& a, const fs::path& b)const
+ { return compare_paths(a, b) < 0; }
+};
+
+struct license_data
+{
+ std::set<fs::path, path_less> files;
+ std::set<std::string> authors;
+};
+
+class bcp_implementation
+ : public bcp_application
+{
+public:
+ bcp_implementation();
+ ~bcp_implementation();
+ static bool is_source_file(const fs::path& p);
+ static bool is_html_file(const fs::path& p);
+ static bool is_jam_file(const fs::path& p);
+private:
+ //
+ // the following are the overridden virtuals from the base class:
+ //
+ void enable_list_mode();
+ void enable_summary_list_mode();
+ void enable_cvs_mode();
+ void enable_svn_mode();
+ void enable_unix_lines();
+ void enable_scan_mode();
+ void enable_license_mode();
+ void enable_bsl_convert_mode();
+ void enable_bsl_summary_mode();
+ void set_boost_path(const char* p);
+ void set_destination(const char* p);
+ void add_module(const char* p);
+ void set_namespace(const char* name);
+ void set_namespace_alias(bool);
+ void set_namespace_list(bool);
+
+ virtual int run();
+
+ // internal helper functions:
+ bool is_binary_file(const fs::path& p);
+ void scan_cvs_path(const fs::path& p);
+ void scan_svn_path(const fs::path& p);
+ void add_path(const fs::path& p);
+ void add_directory(const fs::path& p);
+ void add_file(const fs::path& p);
+ void copy_path(const fs::path& p);
+ void add_file_dependencies(const fs::path& p, bool scanfile);
+ void add_dependent_lib(const std::string& libname, const fs::path& p, const fileview& view);
+ void create_path(const fs::path& p);
+ // license code:
+ void scan_license(const fs::path& p, const fileview& v);
+ void output_license_info();
+
+ std::list<std::string> m_module_list; // the modules to process
+ bool m_list_mode; // list files only
+ bool m_list_summary_mode; // list file summary only
+ bool m_license_mode; // generate license information for files listed
+ bool m_cvs_mode; // check cvs for files
+ bool m_svn_mode; // check svn for files
+ bool m_unix_lines; // fix line endings
+ bool m_scan_mode; // scan non-boost files.
+ bool m_bsl_convert_mode; // try to convert to the BSL
+ bool m_bsl_summary_mode; // summarise BSL issues only
+ bool m_namespace_alias; // make "boost" a namespace alias when doing a namespace rename.
+ bool m_list_namespaces; // list all the top level namespaces found.
+ fs::path m_boost_path; // the path to the boost root
+ fs::path m_dest_path; // the path to copy to
+ std::map<fs::path, bool, path_less> m_cvs_paths; // valid files under cvs control
+ std::set<fs::path, path_less> m_copy_paths; // list of files to copy
+ std::map<int, license_data> m_license_data; // licenses in use
+ std::set<fs::path, path_less> m_unknown_licenses; // files with no known license
+ std::set<fs::path, path_less> m_unknown_authors; // files with no known copyright/author
+ std::set<fs::path, path_less> m_can_migrate_to_bsl; // files that can migrate to the BSL
+ std::set<fs::path, path_less> m_cannot_migrate_to_bsl; // files that cannot migrate to the BSL
+ std::set<std::string> m_bsl_authors; // authors giving blanket permission to use the BSL
+ std::set<std::string> m_authors_for_bsl_migration; // authors we need for BSL migration
+ std::map<fs::path, std::pair<std::string, std::string>, path_less>
+ m_converted_to_bsl;
+ std::map<std::string, std::set<fs::path, path_less> > m_author_data; // all the authors
+ std::map<fs::path, fs::path, path_less> m_dependencies; // dependency information
+ std::string m_namespace_name; // namespace rename.
+ std::set<std::string> m_lib_names; // List of library binary names
+ std::map<std::string, fs::path> m_top_namespaces; // List of top level namespace names
+};
+
diff --git a/tools/bcp/copy_path.cpp b/tools/bcp/copy_path.cpp
new file mode 100644
index 0000000000..4fe897d43d
--- /dev/null
+++ b/tools/bcp/copy_path.cpp
@@ -0,0 +1,240 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * This file implements the following:
+ * void bcp_implementation::copy_path(const fs::path& p)
+ * void bcp_implementation::create_path(const fs::path& p)
+ */
+
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <boost/filesystem/operations.hpp>
+#include <boost/regex.hpp>
+#include <fstream>
+#include <iterator>
+#include <algorithm>
+#include <iostream>
+
+struct get_new_library_name
+{
+ get_new_library_name(const std::string& n) : m_new_name(n) {}
+ template <class I>
+ std::string operator()(const boost::match_results<I>& what)
+ {
+ std::string s = what[0];
+ std::string::size_type n = s.find("boost");
+ if(n == std::string::npos)
+ {
+ s.insert(0, m_new_name);
+ }
+ else
+ {
+ s.replace(n, 5, m_new_name);
+ }
+ return s;
+ }
+private:
+ std::string m_new_name;
+};
+
+void bcp_implementation::copy_path(const fs::path& p)
+{
+ assert(!fs::is_directory(m_boost_path / p));
+ if(fs::exists(m_dest_path / p))
+ {
+ std::cout << "Copying (and overwriting) file: " << p.string() << "\n";
+ fs::remove(m_dest_path / p);
+ }
+ else
+ std::cout << "Copying file: " << p.string() << "\n";
+ //
+ // create the path to the new file if it doesn't already exist:
+ //
+ create_path(p.branch_path());
+ //
+ // do text based copy if requested:
+ //
+ if(p.leaf() == "Jamroot")
+ {
+ static std::vector<char> v1, v2;
+ v1.clear();
+ v2.clear();
+ std::ifstream is((m_boost_path / p).c_str());
+ std::copy(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(), std::back_inserter(v1));
+
+ static boost::regex libname_matcher;
+ if(libname_matcher.empty())
+ {
+ libname_matcher.assign("boost_");
+ }
+
+ regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), libname_matcher, m_namespace_name + "_");
+ std::swap(v1, v2);
+ v2.clear();
+
+ std::ofstream os;
+ if(m_unix_lines)
+ os.open((m_dest_path / p).c_str(), std::ios_base::binary | std::ios_base::out);
+ else
+ os.open((m_dest_path / p).c_str(), std::ios_base::out);
+ os.write(&*v1.begin(), v1.size());
+ os.close();
+ }
+ else if(m_namespace_name.size() && m_lib_names.size() && is_jam_file(p))
+ {
+ static std::vector<char> v1, v2;
+ v1.clear();
+ v2.clear();
+ std::ifstream is((m_boost_path / p).c_str());
+ std::copy(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(), std::back_inserter(v1));
+
+ static boost::regex libname_matcher;
+ if(libname_matcher.empty())
+ {
+ std::string re = "\\<";
+ re += *m_lib_names.begin();
+ for(std::set<std::string>::const_iterator i = ++m_lib_names.begin(); i != m_lib_names.end(); ++i)
+ {
+ re += "|" + *i;
+ }
+ re += "\\>";
+ libname_matcher.assign(re);
+ }
+
+ regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), libname_matcher, get_new_library_name(m_namespace_name));
+ std::swap(v1, v2);
+ v2.clear();
+
+ std::ofstream os;
+ if(m_unix_lines)
+ os.open((m_dest_path / p).c_str(), std::ios_base::binary | std::ios_base::out);
+ else
+ os.open((m_dest_path / p).c_str(), std::ios_base::out);
+ os.write(&*v1.begin(), v1.size());
+ os.close();
+ }
+ else if(m_namespace_name.size() && is_source_file(p))
+ {
+ //
+ // v1 hold the current content, v2 is temp buffer.
+ // Each time we do a search and replace the new content
+ // ends up in v2: we then swap v1 and v2, and clear v2.
+ //
+ static std::vector<char> v1, v2;
+ v1.clear();
+ v2.clear();
+ std::ifstream is((m_boost_path / p).c_str());
+ std::copy(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(), std::back_inserter(v1));
+
+ static const boost::regex namespace_matcher(
+ "(?|"
+ "(namespace\\s+)boost(_\\w+)?(?:(\\s*::\\s*)phoenix)?"
+ "|"
+ "(namespace\\s+)(adstl|phoenix|rapidxml)\\>"
+ "|"
+ "()\\<boost((?:_(?!intrusive_tags)\\w+)?\\s*(?:::))(?:(\\s*)phoenix)?"
+ "|"
+ "()\\<((?:adstl|phoenix|rapidxml)\\s*(?:::))"
+ "|"
+ "(namespace\\s+\\w+\\s*=\\s*(?:::\\s*)?)boost(_\\w+)?(?:(\\s*::\\s*)phoenix)?"
+ "|"
+ "(namespace\\s+\\w+\\s*=\\s*(?:::\\s*)?(?:\\w+\\s*::\\s*)?)(adstl|phoenix|rapidxml)\\>"
+ "|"
+ "(^\\s*#\\s*define\\s+\\w+\\s+)boost((?:_\\w+)?\\s*)$"
+ "|"
+ "(^\\s*#\\s*define[^\\n]+)((?:adstl|phoenix|rapidxml)\\s*)$"
+ "|"
+ "()boost(_asio_detail_posix_thread_function|_regex_free_static_mutex)"
+ "|"
+ "()(lw_thread_routine|at_thread_exit|on_process_enter|on_process_exit|on_thread_enter|on_thread_exit|tss_cleanup_implemented)"
+ "|"
+ "(BOOST_CLASS_REQUIRE4?[^;]*)boost((?:_\\w+)?\\s*,)"
+ "|"
+ "(\\(\\s*)boost(\\s*\\))"
+ ")"
+ );
+
+ regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), namespace_matcher, "$1" + m_namespace_name + "$2(?3$3" + m_namespace_name + "phoenix)", boost::regex_constants::format_all);
+ std::swap(v1, v2);
+ v2.clear();
+
+ if(m_namespace_alias)
+ {
+ static const boost::regex namespace_alias(
+ /*
+ "namespace\\s+" + m_namespace_name +
+ "\\s*"
+ "("
+ "\\{"
+ "(?:"
+ "(?>[^\\{\\}/]+)"
+ "(?>"
+ "(?:"
+ "(?1)"
+ "|//[^\\n]+$"
+ "|/[^/]"
+ "|(?:^\\s*#[^\\n]*"
+ "(?:(?<=\\\\)\\n[^\\n]*)*)"
+ ")"
+ "[^\\{\\}]+"
+ ")*"
+ ")*"
+ "\\}"
+ ")"
+ */
+ /*
+ "(namespace\\s+" + m_namespace_name +
+ "\\s*\\{.*"
+ "\\})([^\\{\\};]*)\\z"
+ */
+ "namespace\\s+" + m_namespace_name +
+ "\\s*\\{"
+ );
+ regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), namespace_alias,
+ "namespace " + m_namespace_name + "{} namespace boost = " + m_namespace_name + "; namespace " + m_namespace_name + "{");
+ std::swap(v1, v2);
+ v2.clear();
+ }
+
+ std::ofstream os;
+ if(m_unix_lines)
+ os.open((m_dest_path / p).c_str(), std::ios_base::binary | std::ios_base::out);
+ else
+ os.open((m_dest_path / p).c_str(), std::ios_base::out);
+ if(v1.size())
+ os.write(&*v1.begin(), v1.size());
+ os.close();
+ }
+ else if(m_unix_lines && !is_binary_file(p))
+ {
+ std::ifstream is((m_boost_path / p).c_str());
+ std::istreambuf_iterator<char> isi(is);
+ std::istreambuf_iterator<char> end;
+
+ std::ofstream os((m_dest_path / p).c_str(), std::ios_base::binary | std::ios_base::out);
+ std::ostreambuf_iterator<char> osi(os);
+
+ std::copy(isi, end, osi);
+ }
+ else
+ {
+ // binary copy:
+ fs::copy_file(m_boost_path / p, m_dest_path / p);
+ }
+}
+
+void bcp_implementation::create_path(const fs::path& p)
+{
+ if(!fs::exists(m_dest_path / p))
+ {
+ // recurse then create the path:
+ create_path(p.branch_path());
+ fs::create_directory(m_dest_path / p);
+ }
+}
+
+
diff --git a/tools/bcp/doc/Jamfile.v2 b/tools/bcp/doc/Jamfile.v2
new file mode 100644
index 0000000000..95f18e40d3
--- /dev/null
+++ b/tools/bcp/doc/Jamfile.v2
@@ -0,0 +1,18 @@
+
+# Copyright John Maddock 2005. Use, modification, and distribution are
+# subject to the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+using quickbook ;
+
+xml bcp : bcp.qbk ;
+boostbook standalone
+ :
+ bcp
+ :
+ # How far down we chunk nested sections, basically all of them:
+ <xsl:param>chunk.section.depth=0
+ # Path for links to Boost:
+ <xsl:param>boost.root=../../../..
+ ;
+
diff --git a/tools/bcp/doc/bcp.qbk b/tools/bcp/doc/bcp.qbk
new file mode 100644
index 0000000000..905a201ada
--- /dev/null
+++ b/tools/bcp/doc/bcp.qbk
@@ -0,0 +1,211 @@
+
+[article BCP
+ [quickbook 1.4]
+ [copyright 2009 John Maddock]
+ [purpose Regular Expressions]
+ [license
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ [@http://www.boost.org/LICENSE_1_0.txt])
+ ]
+ [authors [Maddock, John]]
+ [category text]
+ [/last-revision $Date: 2008-02-21 12:58:15 +0000 (Thu, 21 Feb 2008) $]
+]
+
+[section:overview Overview]
+
+The bcp utility is a tool for extracting subsets of Boost, it's useful for Boost authors who want to distribute
+their library separately from Boost, and for Boost users who want to distribute a subset of Boost with their application.
+
+bcp can also report on which parts of Boost your code is dependent on, and what licences are used by those dependencies.
+
+[endsect]
+
+[section:examples Examples]
+
+[pre
+bcp scoped_ptr /foo
+]
+
+Copies boost/scoped_ptr.hpp and dependencies to /foo.
+
+[pre
+bcp boost/regex.hpp /foo
+]
+
+Copies boost/regex.hpp and all dependencies including the regex source code (in libs/regex/src) and
+build files (in libs/regex/build) to /foo. Does not copy the regex documentation, test, or example code.
+Also does not copy the Boost.Build system.
+
+[pre
+bcp regex /foo
+]
+
+Copies the full regex lib (in libs/regex) including dependencies (such as the boost.test source required
+by the regex test programs) to /foo. Does not copy the Boost.Build system.
+
+[pre
+bcp --namespace=myboost --namespace-alias regex config build /foo
+]
+
+Copies the full regex lib (in libs\/regex) plus the config lib (libs\/config) and the build system (tools\/build)
+to \/foo including all the dependencies. Also renames the boost namespace to /myboost/ and changes the filenames
+of binary libraries to begin with the prefix "myboost" rather than "boost". The --namespace-alias option makes
+`namespace boost` an alias of the new name.
+
+[pre
+bcp --scan --boost=/boost foo.cpp bar.cpp boost
+]
+
+Scans the [non-boost] files foo.cpp and bar.cpp for boost dependencies and copies those dependencies to the sub-directory boost.
+
+[pre
+bcp --report regex.hpp boost-regex-report.html
+]
+
+Creates a HTML report called boost-regex-report.html for the boost module regex.hpp. The report contains license information, author details, and file dependencies.
+
+[endsect]
+
+[section:syntax Syntax]
+
+[section:main Behaviour Selection]
+
+[pre
+bcp --list \[options\] module-list
+]
+
+Outputs a list of all the files in module-list including dependencies.
+
+[pre
+bcp \[options\] module-list output-path
+]
+
+Copies all the files found in module-list to output-path
+
+[pre
+bcp --report \[options\] module-list html-file
+]
+
+Outputs a html report file containing:
+
+* All the licenses in effect, plus the files using each license, and the copyright holders using each license.
+* Any files with no recognizable license (please report these to the boost mailing lists).
+* Any files with no recognizable copyright holders (please report these to the boost mailing lists).
+* All the copyright holders and the files on which they hold copyright.
+* File dependency information - indicates the reason for the inclusion of any particular file in the dependencies found.
+
+[endsect]
+
+[section:options Options]
+
+[pre
+--boost=path
+]
+
+Sets the location of the boost tree to path. If this option is not provided then the current path is assumed to be
+the root directory of the Boost tree.
+
+[pre --namespace=newname ]
+
+When copying files, all occurances of the boost namespace will get renamed to "newname". Also
+renames Boost binaries to use "newname" rather than "boost" as a prefix.
+
+Often used in conjunction with the --namespace-alias option, this allows two different Boost versions to be
+used in the same program, but not in the same translation unit.
+
+[pre --namespace-alias]
+
+When used in conjunction with the --namespace option, then `namespace boost` will be declared as an alias
+of the new namespace name. This allows existing code that relies on Boost code being in `namespace boost`
+to compile unchanged, while retaining the "strong versioning" that can be achieved with a namespace change.
+
+[pre
+--scan
+]
+
+Treats the module list as a list of (probably non-boost) files to scan for boost dependencies,
+the files listed in the module list are not copied (or listed), only the boost files upon which they depend.
+
+[pre
+--svn
+]
+
+Only copy files under svn version control.
+
+[pre
+--unix-lines
+]
+
+Make sure that all copied files use Unix style line endings.
+
+[endsect]
+
+[section:module module-list]
+
+When the --scan option is not used then a list of boost files or library names to copy, this can be:
+
+# The name of a tool: for example "build" will find "tools/build".
+# The name of a library: for example "regex".
+# The title of a header: for example "scoped_ptr" will find "boost/scoped_ptr.hpp".
+# The name of a header: for example "scoped_ptr.hpp" will find "boost/scoped_ptr.hpp".
+# The name of a file: for example "boost/regex.hpp".
+
+When the --scan option is used, then a list of (probably non-boost) files to scan for boost dependencies,
+the files in the module list are not therefore copied/listed.
+
+[endsect]
+
+[section:output output-path]
+
+The path to which files will be copied (this path must exist).
+
+[endsect]
+
+[section Dependencies]
+
+File dependencies are found as follows:
+
+* C++ source files are scanned for #includes, all #includes present in the boost source tree will then be scanned for
+their dependencies and so on.
+* C++ source files are associated with the name of a library, if that library has source code
+(and possibly build data), then include that source in the dependencies.
+* C++ source files are checked for dependencies on Boost.test (for example to see if they use cpp_main as an entry point).
+* HTML files are scanned for immediate dependencies (images and style sheets, but not links).
+
+It should be noted that in practice bcp can produce a rather "fat" list of dependencies, reasons for this include:
+* It searches for library names first, so using "regex" as a name will give you everything in the
+libs/regex directory and everything that depends on. This can be a long list as all the regex test and example
+programs will get scanned for their dependencies. If you want a more minimal list, then try using the
+names of the headers you are actually including, or use the --scan option to scan your source code.
+* If you include the header of a library with separate source, then you get that libraries source and all
+it's dependencies. This is deliberate and in general those extra dependencies are needed.
+* When you include a header, bcp doesn't know what compiler you're using, so it follows all
+possible preprocessor paths. If you're distributing a subset of Boost with you're application then that
+is what you want to have happen in general.
+
+The last point above can result in a substantial increase in the number of headers found compared to most
+peoples expectations. For example bcp finds 274 header dependencies for boost/shared_ptr.hpp: by
+running bcp in report mode we can see why all these headers have been found as dependencies:
+
+* All of the Config library headers get included (52 headers, would be about 6 for one compiler only).
+* A lot of MPL and type traits code that includes workarounds for broken compilers that you may or may not need.
+Tracing back through the code shows that most of these aren't needed unless the user has
+defined BOOST_SP_USE_QUICK_ALLOCATOR, however bcp isn't aware of whether that preprocessor path will be
+taken or not, so the headers get included just in case. This adds about 48 headers (type traits), plus another 49 from MPL.
+* The Preprocessor library gets used heavily by MPL: this adds another 96 headers.
+* The Shared Pointer library contains a lot of platform specific code, split up into around 22 headers:
+normally your compiler would need only a couple of these files.
+
+As you can see the number of dependencies found are much larger than those used by any single compiler,
+however if you want to distribute a subset of Boost that's usable in any configuration, by any compiler,
+on any platform then that's exactly what you need. If you want to figure out which Boost headers are
+being used by your specific compiler then the best way to find out is to prepocess the code and scan
+the output for boost header includes. You should be aware that the result will be very platform and compiler
+specific, and may not contain all the headers needed if you so much as change a compiler switch
+(for example turn on threading support).
+
+[endsect]
+[endsect]
+
diff --git a/tools/bcp/doc/html/index.html b/tools/bcp/doc/html/index.html
new file mode 100644
index 0000000000..c9530bfa23
--- /dev/null
+++ b/tools/bcp/doc/html/index.html
@@ -0,0 +1,347 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>BCP</title>
+<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
+<link rel="home" href="index.html" title="BCP">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
+<td align="center"><a href="../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav"></div>
+<div class="article">
+<div class="titlepage">
+<div>
+<div><h2 class="title">
+<a name="bcp"></a>BCP</h2></div>
+<div><div class="authorgroup"><div class="author"><h3 class="author">
+<span class="firstname">John</span> <span class="surname">Maddock</span>
+</h3></div></div></div>
+<div><p class="copyright">Copyright &#169; 2209 John Maddock</p></div>
+<div><div class="legalnotice">
+<a name="id917214"></a><p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></div>
+</div>
+<hr>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="section"><a href="index.html#bcp.overview">Overview</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.examples">Examples</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax">Syntax</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="index.html#bcp.syntax.main">Behaviour Selection</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.options">Options</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.module">module-list</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.output">output-path</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.dependencies">Dependencies</a></span></dt>
+</dl></dd>
+</dl>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="bcp.overview"></a><a class="link" href="index.html#bcp.overview" title="Overview">Overview</a>
+</h2></div></div></div>
+<p>
+ The bcp utility is a tool for extracting subsets of Boost, it's useful for
+ Boost authors who want to distribute their library separately from Boost, and
+ for Boost users who want to distribute a subset of Boost with their application.
+ </p>
+<p>
+ bcp can also report on which parts of Boost your code is dependent on, and
+ what licences are used by those dependencies.
+ </p>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="bcp.examples"></a><a class="link" href="index.html#bcp.examples" title="Examples">Examples</a>
+</h2></div></div></div>
+<pre class="programlisting">bcp scoped_ptr /foo
+</pre>
+<p>
+ Copies boost/scoped_ptr.hpp and dependencies to /foo.
+ </p>
+<pre class="programlisting">bcp boost/regex.hpp /foo
+</pre>
+<p>
+ Copies boost/regex.hpp and all dependencies including the regex source code
+ (in libs/regex/src) and build files (in libs/regex/build) to /foo. Does not
+ copy the regex documentation, test, or example code. Also does not copy the
+ Boost.Build system.
+ </p>
+<pre class="programlisting">bcp regex /foo
+</pre>
+<p>
+ Copies the full regex lib (in libs/regex) including dependencies (such as the
+ boost.test source required by the regex test programs) to /foo. Does not copy
+ the Boost.Build system.
+ </p>
+<pre class="programlisting">bcp --namespace=myboost --namespace-alias regex config build /foo
+</pre>
+<p>
+ Copies the full regex lib (in libs/regex) plus the config lib (libs/config)
+ and the build system (tools/build) to /foo including all the dependencies.
+ Also renames the boost namespace to <span class="emphasis"><em>myboost</em></span> and changes
+ the filenames of binary libraries to begin with the prefix "myboost"
+ rather than "boost". The --namespace-alias option makes <code class="computeroutput"><span class="keyword">namespace</span> <span class="identifier">boost</span></code>
+ an alias of the new name.
+ </p>
+<pre class="programlisting">bcp --scan --boost=/boost foo.cpp bar.cpp boost
+</pre>
+<p>
+ Scans the [non-boost] files foo.cpp and bar.cpp for boost dependencies and
+ copies those dependencies to the sub-directory boost.
+ </p>
+<pre class="programlisting">bcp --report regex.hpp boost-regex-report.html
+</pre>
+<p>
+ Creates a HTML report called boost-regex-report.html for the boost module regex.hpp.
+ The report contains license information, author details, and file dependencies.
+ </p>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="bcp.syntax"></a><a class="link" href="index.html#bcp.syntax" title="Syntax">Syntax</a>
+</h2></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section"><a href="index.html#bcp.syntax.main">Behaviour Selection</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.options">Options</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.module">module-list</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.output">output-path</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.dependencies">Dependencies</a></span></dt>
+</dl></div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bcp.syntax.main"></a><a class="link" href="index.html#bcp.syntax.main" title="Behaviour Selection">Behaviour Selection</a>
+</h3></div></div></div>
+<pre class="programlisting">bcp --list [options] module-list
+</pre>
+<p>
+ Outputs a list of all the files in module-list including dependencies.
+ </p>
+<pre class="programlisting">bcp [options] module-list output-path
+</pre>
+<p>
+ Copies all the files found in module-list to output-path
+ </p>
+<pre class="programlisting">bcp --report [options] module-list html-file
+</pre>
+<p>
+ Outputs a html report file containing:
+ </p>
+<div class="itemizedlist"><ul class="itemizedlist" type="disc">
+<li class="listitem">
+ All the licenses in effect, plus the files using each license, and the
+ copyright holders using each license.
+ </li>
+<li class="listitem">
+ Any files with no recognizable license (please report these to the boost
+ mailing lists).
+ </li>
+<li class="listitem">
+ Any files with no recognizable copyright holders (please report these
+ to the boost mailing lists).
+ </li>
+<li class="listitem">
+ All the copyright holders and the files on which they hold copyright.
+ </li>
+<li class="listitem">
+ File dependency information - indicates the reason for the inclusion
+ of any particular file in the dependencies found.
+ </li>
+</ul></div>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bcp.syntax.options"></a><a class="link" href="index.html#bcp.syntax.options" title="Options">Options</a>
+</h3></div></div></div>
+<pre class="programlisting">--boost=path
+</pre>
+<p>
+ Sets the location of the boost tree to path. If this option is not provided
+ then the current path is assumed to be the root directory of the Boost tree.
+ </p>
+<pre class="programlisting">--namespace=newname </pre>
+<p>
+ When copying files, all occurances of the boost namespace will get renamed
+ to "newname". Also renames Boost binaries to use "newname"
+ rather than "boost" as a prefix.
+ </p>
+<p>
+ Often used in conjunction with the --namespace-alias option, this allows
+ two different Boost versions to be used in the same program, but not in the
+ same translation unit.
+ </p>
+<pre class="programlisting">--namespace-alias</pre>
+<p>
+ When used in conjunction with the --namespace option, then <code class="computeroutput"><span class="keyword">namespace</span> <span class="identifier">boost</span></code>
+ will be declared as an alias of the new namespace name. This allows existing
+ code that relies on Boost code being in <code class="computeroutput"><span class="keyword">namespace</span>
+ <span class="identifier">boost</span></code> to compile unchanged, while
+ retaining the "strong versioning" that can be achieved with a namespace
+ change.
+ </p>
+<pre class="programlisting">--scan
+</pre>
+<p>
+ Treats the module list as a list of (probably non-boost) files to scan for
+ boost dependencies, the files listed in the module list are not copied (or
+ listed), only the boost files upon which they depend.
+ </p>
+<pre class="programlisting">--svn
+</pre>
+<p>
+ Only copy files under svn version control.
+ </p>
+<pre class="programlisting">--unix-lines
+</pre>
+<p>
+ Make sure that all copied files use Unix style line endings.
+ </p>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bcp.syntax.module"></a><a class="link" href="index.html#bcp.syntax.module" title="module-list">module-list</a>
+</h3></div></div></div>
+<p>
+ When the --scan option is not used then a list of boost files or library
+ names to copy, this can be:
+ </p>
+<div class="orderedlist"><ol class="orderedlist" type="1">
+<li class="listitem">
+ The name of a tool: for example "build" will find "tools/build".
+ </li>
+<li class="listitem">
+ The name of a library: for example "regex".
+ </li>
+<li class="listitem">
+ The title of a header: for example "scoped_ptr" will find "boost/scoped_ptr.hpp".
+ </li>
+<li class="listitem">
+ The name of a header: for example "scoped_ptr.hpp" will find
+ "boost/scoped_ptr.hpp".
+ </li>
+<li class="listitem">
+ The name of a file: for example "boost/regex.hpp".
+ </li>
+</ol></div>
+<p>
+ When the --scan option is used, then a list of (probably non-boost) files
+ to scan for boost dependencies, the files in the module list are not therefore
+ copied/listed.
+ </p>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bcp.syntax.output"></a><a class="link" href="index.html#bcp.syntax.output" title="output-path">output-path</a>
+</h3></div></div></div>
+<p>
+ The path to which files will be copied (this path must exist).
+ </p>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bcp.syntax.dependencies"></a><a class="link" href="index.html#bcp.syntax.dependencies" title="Dependencies">Dependencies</a>
+</h3></div></div></div>
+<p>
+ File dependencies are found as follows:
+ </p>
+<div class="itemizedlist"><ul class="itemizedlist" type="disc">
+<li class="listitem">
+ C++ source files are scanned for #includes, all #includes present in
+ the boost source tree will then be scanned for their dependencies and
+ so on.
+ </li>
+<li class="listitem">
+ C++ source files are associated with the name of a library, if that library
+ has source code (and possibly build data), then include that source in
+ the dependencies.
+ </li>
+<li class="listitem">
+ C++ source files are checked for dependencies on Boost.test (for example
+ to see if they use cpp_main as an entry point).
+ </li>
+<li class="listitem">
+ HTML files are scanned for immediate dependencies (images and style sheets,
+ but not links).
+ </li>
+</ul></div>
+<p>
+ It should be noted that in practice bcp can produce a rather "fat"
+ list of dependencies, reasons for this include: * It searches for library
+ names first, so using "regex" as a name will give you everything
+ in the libs/regex directory and everything that depends on. This can be a
+ long list as all the regex test and example programs will get scanned for
+ their dependencies. If you want a more minimal list, then try using the names
+ of the headers you are actually including, or use the --scan option to scan
+ your source code. * If you include the header of a library with separate
+ source, then you get that libraries source and all it's dependencies. This
+ is deliberate and in general those extra dependencies are needed. * When
+ you include a header, bcp doesn't know what compiler you're using, so it
+ follows all possible preprocessor paths. If you're distributing a subset
+ of Boost with you're application then that is what you want to have happen
+ in general.
+ </p>
+<p>
+ The last point above can result in a substantial increase in the number of
+ headers found compared to most peoples expectations. For example bcp finds
+ 274 header dependencies for boost/shared_ptr.hpp: by running bcp in report
+ mode we can see why all these headers have been found as dependencies:
+ </p>
+<div class="itemizedlist"><ul class="itemizedlist" type="disc">
+<li class="listitem">
+ All of the Config library headers get included (52 headers, would be
+ about 6 for one compiler only).
+ </li>
+<li class="listitem">
+ A lot of MPL and type traits code that includes workarounds for broken
+ compilers that you may or may not need. Tracing back through the code
+ shows that most of these aren't needed unless the user has defined BOOST_SP_USE_QUICK_ALLOCATOR,
+ however bcp isn't aware of whether that preprocessor path will be taken
+ or not, so the headers get included just in case. This adds about 48
+ headers (type traits), plus another 49 from MPL.
+ </li>
+<li class="listitem">
+ The Preprocessor library gets used heavily by MPL: this adds another
+ 96 headers.
+ </li>
+<li class="listitem">
+ The Shared Pointer library contains a lot of platform specific code,
+ split up into around 22 headers: normally your compiler would need only
+ a couple of these files.
+ </li>
+</ul></div>
+<p>
+ As you can see the number of dependencies found are much larger than those
+ used by any single compiler, however if you want to distribute a subset of
+ Boost that's usable in any configuration, by any compiler, on any platform
+ then that's exactly what you need. If you want to figure out which Boost
+ headers are being used by your specific compiler then the best way to find
+ out is to prepocess the code and scan the output for boost header includes.
+ You should be aware that the result will be very platform and compiler specific,
+ and may not contain all the headers needed if you so much as change a compiler
+ switch (for example turn on threading support).
+ </p>
+</div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"><p><small>Last revised: August 14, 2011 at 16:17:07 GMT</small></p></td>
+<td align="right"><div class="copyright-footer"></div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav"></div>
+</body>
+</html>
diff --git a/tools/bcp/file_types.cpp b/tools/bcp/file_types.cpp
new file mode 100644
index 0000000000..297d304cfc
--- /dev/null
+++ b/tools/bcp/file_types.cpp
@@ -0,0 +1,72 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * This file implements the following:
+ * void bcp_implementation::is_source_file(const fs::path& p)
+ * void bcp_implementation::is_html_file(const fs::path& p)
+ * void bcp_implementation::is_binary_file(const fs::path& p)
+ */
+
+#include "bcp_imp.hpp"
+#include <boost/regex.hpp>
+
+bool bcp_implementation::is_source_file(const fs::path& p)
+{
+ static const boost::regex e(
+ ".*\\."
+ "(?:"
+ "c|cxx|h|hxx|inc|inl|.?pp|yy?"
+ ")",
+ boost::regex::perl | boost::regex::icase
+ );
+ return boost::regex_match(p.filename().generic_string(), e);
+}
+
+bool bcp_implementation::is_html_file(const fs::path& p)
+{
+ static const boost::regex e(
+ ".*\\."
+ "(?:"
+ "html?|css"
+ ")"
+ );
+ return boost::regex_match(p.filename().generic_string(), e);
+}
+
+bool bcp_implementation::is_binary_file(const fs::path& p)
+{
+ if(m_cvs_mode || m_svn_mode)
+ {
+ std::map<fs::path, bool, path_less>::iterator pos = m_cvs_paths.find(p);
+ if(pos != m_cvs_paths.end()) return pos->second;
+ }
+ static const boost::regex e(
+ ".*\\."
+ "(?:"
+ "c|cxx|cpp|h|hxx|hpp|inc|html?|css|mak|in"
+ ")"
+ "|"
+ "(Jamfile|makefile|configure)",
+ boost::regex::perl | boost::regex::icase);
+ return !boost::regex_match(p.leaf().generic_string(), e);
+
+}
+
+bool bcp_implementation::is_jam_file(const fs::path& p)
+{
+ static const boost::regex e(
+ ".*\\."
+ "(?:"
+ "jam|v2"
+ ")"
+ "|"
+ "(Jamfile|Jamroot)\\.?",
+ boost::regex::perl | boost::regex::icase
+ );
+ return boost::regex_match(p.filename().generic_string(), e);
+}
+
diff --git a/tools/bcp/fileview.cpp b/tools/bcp/fileview.cpp
new file mode 100644
index 0000000000..761756c156
--- /dev/null
+++ b/tools/bcp/fileview.cpp
@@ -0,0 +1,142 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * This file implements the fileview class
+ */
+
+#include "fileview.hpp"
+#include <vector>
+#include <algorithm>
+#include <string>
+#include <fstream>
+#include <istream>
+#include <stdexcept>
+
+struct fileview::implementation
+{
+ std::vector<char> m_data;
+};
+
+
+// construct:
+fileview::fileview()
+{
+ pimpl.reset(new implementation());
+}
+
+fileview::fileview(const boost::filesystem::path& p)
+{
+ pimpl.reset(new implementation());
+ open(p);
+}
+
+fileview::~fileview()
+{
+}
+
+fileview::fileview(const fileview& that)
+{
+}
+
+fileview& fileview::operator=(const fileview& that)
+{
+ pimpl = that.pimpl;
+ return *this;
+}
+
+void fileview::close()
+{
+ cow();
+ pimpl->m_data.clear();
+}
+
+void fileview::open(const boost::filesystem::path& p)
+{
+ cow();
+ std::ifstream is(p.c_str());
+ if(!is)
+ {
+ std::string msg("Bad file name: ");
+ msg += p.string();
+ std::runtime_error e(msg);
+ boost::throw_exception(e);
+ }
+ std::istreambuf_iterator<char> in(is);
+ std::istreambuf_iterator<char> end;
+ std::copy(in, end, std::back_inserter(pimpl->m_data));
+}
+
+// iterators:
+fileview::const_iterator fileview::begin() const
+{
+ return pimpl->m_data.size() ? &(pimpl->m_data[0]) : 0;
+}
+
+fileview::const_iterator fileview::end() const
+{
+ return begin() + pimpl->m_data.size();
+}
+
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+fileview::const_reverse_iterator fileview::rbegin() const
+{
+ return const_reverse_iterator(end());
+}
+
+fileview::const_reverse_iterator fileview::rend() const
+{
+ return const_reverse_iterator(begin());
+}
+#endif
+
+// capacity:
+fileview::size_type fileview::size() const
+{
+ return pimpl->m_data.size();
+}
+
+fileview::size_type fileview::max_size() const
+{
+ return pimpl->m_data.max_size();
+}
+
+bool fileview::empty() const
+{
+ return pimpl->m_data.empty();
+}
+
+// element access:
+fileview::const_reference fileview::operator[](fileview::size_type n) const
+{
+ return pimpl->m_data[n];
+}
+
+fileview::const_reference fileview::at(size_type n) const
+{
+ return pimpl->m_data.at(n);
+}
+
+fileview::const_reference fileview::front() const
+{
+ return pimpl->m_data.front();
+}
+
+fileview::const_reference fileview::back() const
+{
+ return pimpl->m_data.back();
+}
+
+void fileview::swap(fileview& that)
+{
+ pimpl.swap(that.pimpl);
+}
+
+void fileview::cow()
+{
+ if(!pimpl.unique())
+ pimpl.reset(new implementation(*pimpl));
+}
diff --git a/tools/bcp/fileview.hpp b/tools/bcp/fileview.hpp
new file mode 100644
index 0000000000..fe76f84ea5
--- /dev/null
+++ b/tools/bcp/fileview.hpp
@@ -0,0 +1,72 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#if defined(BOOST_FILESYSTEM_VERSION) && (BOOST_FILESYSTEM_VERSION != 3)
+# error "This library must be built with Boost.Filesystem version 3"
+#else
+#define BOOST_FILESYSTEM_VERSION 3
+#endif
+
+#include <boost/shared_ptr.hpp>
+#include <boost/filesystem/path.hpp>
+
+class fileview
+{
+public:
+ // types:
+ typedef const char& reference;
+ typedef reference const_reference;
+ typedef const char* iterator; // See _lib.container.requirements_
+ typedef iterator const_iterator; // See _lib.container.requirements_
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef char value_type;
+ typedef const char* pointer;
+ typedef pointer const_pointer;
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+#endif
+
+ // construct:
+ fileview();
+ fileview(const boost::filesystem::path& p);
+ ~fileview();
+ fileview(const fileview& that);
+ fileview& operator=(const fileview& that);
+ void close();
+ void open(const boost::filesystem::path& p);
+
+ // iterators:
+ const_iterator begin() const;
+ const_iterator end() const;
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ const_reverse_iterator rbegin() const;
+ const_reverse_iterator rend() const;
+#endif
+
+ // capacity:
+ size_type size() const;
+ size_type max_size() const;
+ bool empty() const;
+
+ // element access:
+ const_reference operator[](size_type n) const;
+ const_reference at(size_type n) const;
+ const_reference front() const;
+ const_reference back() const;
+ void swap(fileview& that);
+
+private:
+ void cow();
+ struct implementation;
+ boost::shared_ptr<implementation> pimpl;
+};
+
+
diff --git a/tools/bcp/index.html b/tools/bcp/index.html
new file mode 100644
index 0000000000..34e938c601
--- /dev/null
+++ b/tools/bcp/index.html
@@ -0,0 +1,17 @@
+<html>
+ <head>
+ <meta http-equiv="refresh" content="0; URL=doc/html/index.html">
+ </head>
+ <body>
+ <p>
+ Automatic redirection failed, please go to <a href="doc/html/index.html">doc/html/index.html</a>.
+ </p>
+ <p>Copyright&nbsp;John Maddock 2007</p>
+ <p>Distributed under the Boost Software License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt">
+ LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>).</p>
+ </body>
+</html>
+
+
+
+
diff --git a/tools/bcp/licence_info.cpp b/tools/bcp/licence_info.cpp
new file mode 100644
index 0000000000..ab34b83c48
--- /dev/null
+++ b/tools/bcp/licence_info.cpp
@@ -0,0 +1,721 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * boostinspect:noascii
+ */
+
+#include "licence_info.hpp"
+
+
+std::pair<const license_info*, int> get_licenses()
+{
+ static const char* generic_author_sig =
+ "(?:"
+ "(?:"
+ "Copyright|\\(c\\)|\xA9"
+ ")[[:blank:]]+"
+ "){1,2}"
+ "(?:"
+ "\\d[^[:alpha:]]+"
+ "([[:alpha:]]"
+ "(?:"
+ "(?!Use\\b|Permission\\b|All\\b|<P|(?:-\\s*)\\w+(?:://|@)|\\\\"
+ ")[^\\n\\d]"
+ ")+"
+ ")"
+ "|"
+ "([[:alpha:]][^\\n\\d]+"
+ "(?:\\n[^\\n\\d]+"
+ ")??"
+ ")(?:19|20)\\d{2}"
+ ")"
+ "|"
+ "Authors:[[:blank:]]+"
+ "([[:alpha:]][^\\n\\d]+"
+ "|"
+ "((?:The|This) code is considered to be in the public domain)"
+ ")";
+
+ static const char* generic_author_format =
+ "(?1$1)(?2$2)(?3$3)(?4Public Domain)";
+
+ static const license_info licenses[] =
+ {
+ license_info( boost::regex("distributed\\W+under"
+ "(\\W+the)?[^\"[:word:]]+Boost\\W+Software\\W+License\\W+Version\\W+1.0", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost Software License, Version 1.0"
+ ,
+ "<P>Copyright (c) <I>Date</I> <I>Author</I></P>"
+ "<P>Distributed under the "
+ "Boost Software License, Version 1.0. (See accompanying file "
+ "LICENSE_1_0.txt or copy at <a href=\"http://www.boost.org/LICENSE_1_0.txt\">http://www.boost.org/LICENSE_1_0.txt)</a></P>"
+ )
+ ,
+ license_info( boost::regex("Use\\W+\\modification\\W+and\\W+distribution(\\W+is|\\W+are)\\W+subject\\W+to"
+ "(\\W+the)?[^\"[:word:]]+Boost\\W+Software\\W+License\\W+Version\\W+1.0", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost Software License, Version 1.0 (variant #1)"
+ ,
+ "<P>Copyright (c) <I>Date</I> <I>Author</I></P>"
+ "<P>Use, modification and distribution is subject to the "
+ "Boost Software License, Version 1.0. (See accompanying file "
+ "LICENSE_1_0.txt or copy at <a href=\"http://www.boost.org/LICENSE_1_0.txt\">http://www.boost.org/LICENSE_1_0.txt)</a></P>"
+ )
+ ,
+ license_info( boost::regex("(?!is)\\w\\w\\W+subject\\W+to"
+ "(\\W+the)?[^\"[:word:]]+Boost\\W+Software\\W+License\\W+Version\\W+1.0", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost Software License, Version 1.0 (variant #2)"
+ ,
+ "<P>Copyright (c) <I>Date</I> <I>Author</I></P>"
+ "<P>Subject to the "
+ "Boost Software License, Version 1.0. (See accompanying file "
+ "LICENSE_1_0.txt or copy at <a href=\"http://www.boost.org/LICENSE_1_0.txt\">http://www.boost.org/LICENSE_1_0.txt)</a></P>"
+ )
+ ,
+ license_info( boost::regex("Copyright\\W+(c)\\W+2001\\W+2002\\W+Python\\W+Software\\W+Foundation\\W+All\\W+Rights\\W+Reserved", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Python Software License"
+ ,
+ "<p>Copyright (c) 2001, 2002 Python Software Foundation;</p>"
+ "<P>All Rights Reserved</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+use\\W+copy\\W+modify\\W+distribute\\W+and\\W+sell\\W+this\\W+software\\W+and\\W+its\\W+documentation"
+ "\\W+for\\W+any\\W+purpose\\W+is\\W+hereby\\W+granted\\W+without\\W+fee"
+ "\\W+provided\\W+that\\W+the\\W+above\\W+copyright\\W+notice\\W+appears?\\W+in\\W+all\\W+copies\\W+and"
+ "\\W+that\\W+both\\W+(the|that)\\W+copyright\\W+notice\\W+and\\W+this\\W+permission\\W+notice\\W+appears?"
+ "\\W+in\\W+supporting\\W+documentation[^<>]{1, 100}\\W+no\\W+representations"
+ "\\W+(are\\W+made\\W+)?about\\W+the\\W+suitability\\W+of\\W+this\\W+software\\W+for\\W+any\\W+purpose"
+ "\\W+It\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "SGI Style License"
+ ,
+ "<P>Copyright (c) <I>Date</I><BR>"
+ "<I>Author</I><BR>"
+ "<BR>"
+ "Permission to use, copy, modify, distribute and sell this software "
+ "and its documentation for any purpose is hereby granted without fee, "
+ "provided that the above copyright notice appear in all copies and "
+ "that both that copyright notice and this permission notice appear "
+ "in supporting documentation. <I>Author</I> makes no representations "
+ "about the suitability of this software for any purpose. "
+ "It is provided \"as is\" without express or implied warranty.</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+use\\W+copy\\W+modify\\W+distribute\\W+and\\W+sell\\W+this\\W+software"
+ "\\W+for\\W+any\\W+purpose\\W+is\\W+hereby\\W+granted\\W+without\\W+fee"
+ "\\W+provided\\W+that\\W+the\\W+above\\W+copyright\\W+notice\\W+appears?\\W+in\\W+all\\W+copies\\W+and"
+ "\\W+that\\W+both\\W+(the|that)\\W+copyright\\W+notice\\W+and\\W+this\\W+permission\\W+notice\\W+appears?"
+ "\\W+in\\W+supporting\\W+documentation[^<>]{1, 100}\\W+no\\W+representations"
+ "\\W+(are\\W+made\\W+)?about\\W+the\\W+suitability\\W+of\\W+this\\W+software\\W+for\\W+any\\W+purpose"
+ "\\W+It\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express(ed)?\\W+or\\W+implied\\W+warranty", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #1"
+ ,
+ "<P>Copyright (c) <I>Date</I><BR>"
+ "<I>Author</I><BR>"
+ "<BR>"
+ "Permission to use, copy, modify, distribute and sell this software "
+ "for any purpose is hereby granted without fee, "
+ "provided that the above copyright notice appear in all copies and "
+ "that both that copyright notice and this permission notice appears? "
+ "in supporting documentation. <I>Author</I> makes no representations "
+ "about the suitability of this software for any purpose. "
+ "It is provided \"as is\" without express or implied warranty.</P>"
+ )
+ ,
+ license_info(
+ boost::regex(
+ "Permission\\W+to\\W+copy\\W+use\\W+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software"
+ "\\W+is\\W+granted\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied"
+ "\\W+warranty\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase
+ )
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #2"
+ ,
+ "<P>Copyright (c) <I>Date</I> <I>Author</I>.<BR><BR>\n"
+ "Permission to copy, use, modify, sell and distribute this software<BR>\n"
+ "is granted provided this copyright notice appears in all copies.<BR>\n"
+ "This software is provided \"as is\" without express or implied<BR>\n"
+ "warranty, and with no claim as to its suitability for any purpose.</P>\n"
+ )
+ ,
+ license_info(
+ boost::regex(
+ "Permission\\W+to\\W+copy\\W+use[^\"[:word:]]+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software\\W+is\\W+granted\\W+provided"
+ "\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+This\\W+software\\W+is"
+ "\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty\\W+and\\W+with"
+ "\\W+no\\W+claim\\W+at\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase
+ )
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #3"
+ ,
+ "<P>(C) Copyright <I>Author</I> <I>Date</I>. Permission to copy, use, "
+ "modify, sell, and distribute this software is granted provided "
+ "this copyright notice appears in all copies. This software is "
+ "provided \"as is\" without express or implied warranty, and with "
+ "no claim at to its suitability for any purpose.</p>\n"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+copy\\W+use\\W+sell\\W+and\\W+distribute\\W+this\\W+software\\W+is\\W+granted"
+ "\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute\\W+modified\\W+code\\W+is\\W+granted"
+ "\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+and\\W+a\\W+notice"
+ "\\W+that\\W+the\\W+code\\W+was\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+copyright\\W+notice"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #4"
+ ,
+ "<P>Copyright (C) <I>Date Author</I><BR>"
+ "<BR>"
+ "Permission to copy, use, sell and distribute this software is granted\n"
+ "provided this copyright notice appears in all copies.\n"
+ "Permission to modify the code and to distribute modified code is granted\n"
+ "provided this copyright notice appears in all copies, and a notice\n"
+ "that the code was modified is included with the copyright notice.</P>\n"
+ "<P>This software is provided \"as is\" without express or implied warranty,\n"
+ "and with no claim as to its suitability for any purpose.</P>"
+ )
+ ,
+ license_info( boost::regex("This\\W+file\\W+is\\W+part\\W+of\\W+the\\W+(Boost\\W+Graph|Generic\\W+Graph\\W+Component)\\W+Library"
+ "\\W+You\\W+should\\W+have\\W+received\\W+a\\W+copy\\W+of\\W+the\\W+License\\W+Agreement\\W+for\\W+the"
+ "\\W+(Boost|Generic)\\W+Graph\\W+(Component\\W+)?Library\\W+along\\W+with\\W+the\\W+software;\\W+see\\W+the\\W+file\\W+LICENSE"
+ "(\\W+If\\W+not\\W+contact\\W+Office\\W+of\\W+Research\\W+University\\W+of\\W+Notre\\W+Dame\\W+Notre"
+ "\\W+Dame\\W+IN\\W+46556)?"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute(\\W+modified|\\W+the)\\W+code\\W+is"
+ "\\W+granted\\W+provided\\W+the\\W+text\\W+of\\W+this\\W+NOTICE\\W+is\\W+retained\\W+a\\W+notice\\W+(that|if)"
+ "\\W+the\\W+code\\W+was\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+above\\W+COPYRIGHT\\W+NOTICE\\W+and"
+ "\\W+with\\W+the\\W+COPYRIGHT\\W+NOTICE\\W+in\\W+the\\W+LICENSE\\W+file\\W+and\\W+that\\W+the\\W+LICENSE"
+ "\\W+file\\W+is\\W+distributed\\W+with\\W+the\\W+modified\\W+code\\W+"
+ "\\W+LICENSOR\\W+MAKES\\W+NO\\W+REPRESENTATIONS\\W+OR\\W+WARRANTIES\\W+EXPRESS\\W+OR\\W+IMPLIED"
+ "\\W+By\\W+way\\W+of\\W+example\\W+but\\W+not\\W+limitation\\W+Licensor\\W+MAKES\\W+NO"
+ "\\W+REPRESENTATIONS\\W+OR\\W+WARRANTIES\\W+OF\\W+MERCHANTABILITY\\W+OR\\W+FITNESS\\W+FOR\\W+ANY"
+ "\\W+PARTICULAR\\W+PURPOSE\\W+OR\\W+THAT\\W+THE\\W+USE\\W+OF\\W+THE\\W+LICENSED\\W+SOFTWARE\\W+COMPONENTS"
+ "\\W+OR\\W+DOCUMENTATION\\W+WILL\\W+NOT\\W+INFRINGE\\W+ANY\\W+PATENTS\\W+COPYRIGHTS\\W+TRADEMARKS"
+ "\\W+OR\\W+OTHER\\W+RIGHTS"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost.Graph license (Notre Dame)"
+ ,
+ "<P>Copyright <I>Date</I> University of Notre Dame.<BR>"
+ "Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek</P>"
+ "<P>This file is part of the Boost Graph Library</P>"
+ "<P>You should have received a copy of the <A href=\"http://www.boost.org/libs/graph/LICENCE\">License Agreement</a> for the "
+ "Boost Graph Library along with the software; see the file <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a>. "
+ "If not, contact Office of Research, University of Notre Dame, Notre "
+ "Dame, IN 46556.</P>"
+ "<P>Permission to modify the code and to distribute modified code is "
+ "granted, provided the text of this NOTICE is retained, a notice that "
+ "the code was modified is included with the above COPYRIGHT NOTICE and "
+ "with the COPYRIGHT NOTICE in the <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a> file, and that the <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a> "
+ "file is distributed with the modified code.</P>"
+ "<P>LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.<BR> "
+ "By way of example, but not limitation, Licensor MAKES NO "
+ "REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY "
+ "PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS "
+ "OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS "
+ "OR OTHER RIGHTS.</P>"
+ )
+ ,
+ license_info( boost::regex("This\\W+file\\W+is\\W+part\\W+of\\W+the\\W+(Boost\\W+Graph|Generic\\W+Graph\\W+Component)\\W+Library"
+ "\\W+You\\W+should\\W+have\\W+received\\W+a\\W+copy\\W+of\\W+the\\W+License\\W+Agreement\\W+for\\W+the"
+ "\\W+(Boost|Generic)\\W+Graph\\W+(Component\\W+)?Library\\W+along\\W+with\\W+the\\W+software;\\W+see\\W+the\\W+file\\W+LICENSE"
+ "(\\W+If\\W+not\\W+contact\\W+Office\\W+of\\W+Research\\W+Indiana\\W+University\\W+Bloomington\\W+IN\\W+47405)?"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute(\\W+modified|\\W+the)\\W+code\\W+is"
+ "\\W+granted\\W+provided\\W+the\\W+text\\W+of\\W+this\\W+NOTICE\\W+is\\W+retained\\W+a\\W+notice\\W+(that|if)"
+ "\\W+the\\W+code\\W+was\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+above\\W+COPYRIGHT\\W+NOTICE\\W+and"
+ "\\W+with\\W+the\\W+COPYRIGHT\\W+NOTICE\\W+in\\W+the\\W+LICENSE\\W+file\\W+and\\W+that\\W+the\\W+LICENSE"
+ "\\W+file\\W+is\\W+distributed\\W+with\\W+the\\W+modified\\W+code\\W+"
+ "\\W+LICENSOR\\W+MAKES\\W+NO\\W+REPRESENTATIONS\\W+OR\\W+WARRANTIES\\W+EXPRESS\\W+OR\\W+IMPLIED"
+ "\\W+By\\W+way\\W+of\\W+example\\W+but\\W+not\\W+limitation\\W+Licensor\\W+MAKES\\W+NO"
+ "\\W+REPRESENTATIONS\\W+OR\\W+WARRANTIES\\W+OF\\W+MERCHANTABILITY\\W+OR\\W+FITNESS\\W+FOR\\W+ANY"
+ "\\W+PARTICULAR\\W+PURPOSE\\W+OR\\W+THAT\\W+THE\\W+USE\\W+OF\\W+THE\\W+LICENSED\\W+SOFTWARE\\W+COMPONENTS"
+ "\\W+OR\\W+DOCUMENTATION\\W+WILL\\W+NOT\\W+INFRINGE\\W+ANY\\W+PATENTS\\W+COPYRIGHTS\\W+TRADEMARKS"
+ "\\W+OR\\W+OTHER\\W+RIGHTS"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost.Graph license (Indiana University)"
+ ,
+ "<P>Copyright <I>Date</I> Indiana University.<BR>"
+ "Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek</P>"
+ "<P>This file is part of the Boost Graph Library</P>"
+ "<P>You should have received a copy of the <A href=\"http://www.boost.org/libs/graph/LICENCE\">License Agreement</a> for the "
+ "Boost Graph Library along with the software; see the file <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a>. "
+ "If not, contact Office of Research, Indiana University, Bloomington,"
+ "IN 47404.</P>"
+ "<P>Permission to modify the code and to distribute modified code is "
+ "granted, provided the text of this NOTICE is retained, a notice that "
+ "the code was modified is included with the above COPYRIGHT NOTICE and "
+ "with the COPYRIGHT NOTICE in the <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a> file, and that the <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a> "
+ "file is distributed with the modified code.</P>"
+ "<P>LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.<BR> "
+ "By way of example, but not limitation, Licensor MAKES NO "
+ "REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY "
+ "PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS "
+ "OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS "
+ "OR OTHER RIGHTS.</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+copy\\W+use\\W+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software\\W+is"
+ "[^\"[:word:]]+granted\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+and"
+ "\\W+modified\\W+version\\W+are\\W+clearly\\W+marked\\W+as\\W+such\\W+This\\W+software\\W+is\\W+provided"
+ "\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its"
+ "\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #5"
+ ,
+ "<P>Copyright (C) <I>Date Author</I></P>"
+ "<p>Permission to copy, use, modify, sell and distribute this software is "
+ "granted, provided this copyright notice appears in all copies and "
+ "modified version are clearly marked as such. This software is provided "
+ "\"as is\" without express or implied warranty, and with no claim as to its "
+ "suitability for any purpose.</P>"
+ )
+ ,
+ license_info( boost::regex("This\\W+file\\W+can\\W+be\\W+redistributed\\W+and\\W+or\\W+modified\\W+under\\W+the\\W+terms\\W+found"
+ "\\W+in\\W+copyright\\W+html"
+ "\\W+This\\W+software\\W+and\\W+its\\W+documentation\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or"
+ "\\W+implied\\W+warranty\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost.Pool license"
+ ,
+ "<P>This file can be redistributed and/or modified under the terms found "
+ "in <a href=\"http://www.boost.org/libs/pool/doc/copyright.html\">copyright.html</a></P>\n"
+ "<P>This software and its documentation is provided \"as is\" without express or "
+ "implied warranty, and with no claim as to its suitability for any purpose</P>"
+ )
+ ,
+ license_info(boost::regex("Permission\\W+to\\W+use\\W+copy\\W+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software"
+ "\\W+is\\W+hereby\\W+granted\\W+without\\W+fee\\W+provided\\W+that\\W+the\\W+above\\W+copyright\\W+notice"
+ "\\W+appears\\W+in\\W+all\\W+copies\\W+and\\W+that\\W+both\\W+that\\W+copyright\\W+notice\\W+and\\W+this"
+ "\\W+permission\\W+notice\\W+appear\\W+in\\W+supporting\\W+documentation"
+ "[^<>]{1,100}\\W+(make\\W+any\\W+representation|makes\\W+no\\W+representations)\\W+about\\W+the\\W+suitability\\W+of\\W+this"
+ "\\W+software\\W+for\\W+any\\W+purpose\\W+It\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or"
+ "\\W+implied\\W+warranty"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #6"
+ ,
+ "<P>Copyright <I>Author Data</I></P>"
+ "<P>Permission to use, copy, modify, sell, and distribute this software "
+ "is hereby granted without fee provided that the above copyright notice "
+ "appears in all copies and that both that copyright notice and this "
+ "permission notice appear in supporting documentation, "
+ "<I>Author</I> makes no representations about the suitability of this "
+ "software for any purpose. It is provided \"as is\" without express or "
+ "implied warranty.</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+copy"
+ "[^\"[:word:]]+use\\W+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software\\W+is\\W+granted\\W+provided"
+ "\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+of\\W+the\\W+source\\W+This"
+ "\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty"
+ "\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #7"
+ ,
+ "<P>Copyright <I>Author Date</I>. Permission to copy, "
+ "use, modify, sell and distribute this software is granted provided "
+ "this copyright notice appears in all copies of the source. This "
+ "software is provided \"as is\" without express or implied warranty, "
+ "and with no claim as to its suitability for any purpose."
+ )
+ ,
+ license_info(boost::regex("This\\W+software\\W+is\\W+provided\\W+as-is\\W+without\\W+any\\W+express\\W+or\\W+implied"
+ "\\W+warranty\\W+In\\W+no\\W+event\\W+will\\W+the\\W+copyright\\W+holder\\W+be\\W+held\\W+liable\\W+for"
+ "\\W+any\\W+damages\\W+arising\\W+from\\W+the\\W+use\\W+of\\W+this\\W+software"
+ "\\W+Permission\\W+is\\W+granted\\W+to\\W+anyone\\W+to\\W+use\\W+this\\W+software\\W+for\\W+any\\W+purpose"
+ "\\W+including\\W+commercial\\W+applications\\W+and\\W+to\\W+alter\\W+it\\W+and\\W+redistribute"
+ "\\W+it\\W+freely\\W+subject\\W+to\\W+the\\W+following\\W+restrictions:"
+ "\\W+1\\W+The\\W+origin\\W+of\\W+this\\W+software\\W+must\\W+not\\W+be\\W+misrepresented;\\W+you\\W+must"
+ "\\W+not\\W+claim\\W+that\\W+you\\W+wrote\\W+the\\W+original\\W+software\\W+If\\W+you\\W+use\\W+this"
+ "\\W+software\\W+in\\W+a\\W+product\\W+an\\W+acknowledgment\\W+in\\W+the\\W+product\\W+documentation"
+ "\\W+would\\W+be\\W+appreciated\\W+but\\W+is\\W+not\\W+required"
+ "\\W+2\\W+Altered\\W+source\\W+versions\\W+must\\W+be\\W+plainly\\W+marked\\W+as\\W+such\\W+and\\W+must"
+ "\\W+not\\W+be\\W+misrepresented\\W+as\\W+being\\W+the\\W+original\\W+software"
+ "\\W+3\\W+This\\W+notice\\W+may\\W+not\\W+be\\W+removed\\W+or\\W+altered\\W+from\\W+any\\W+source"
+ "\\W+distribution"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #8"
+ ,
+ "<P>Phoenix V0.9<BR>Copyright (c) <I>Date</I> Joel de Guzman</P>"
+ "<P>This software is provided 'as-is', without any express or implied "
+ "warranty. In no event will the copyright holder be held liable for "
+ "any damages arising from the use of this software.</P>"
+ "<P>Permission is granted to anyone to use this software for any purpose, "
+ "including commercial applications, and to alter it and redistribute "
+ "it freely, subject to the following restrictions:</P>"
+ "<P>1. The origin of this software must not be misrepresented; you must "
+ "not claim that you wrote the original software. If you use this "
+ "software in a product, an acknowledgment in the product documentation "
+ "would be appreciated but is not required.</P>"
+ "2. Altered source versions must be plainly marked as such, and must "
+ "not be misrepresented as being the original software. </P>"
+ "<P>3. This notice may not be removed or altered from any source "
+ "distribution. "
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+use\\W+copy\\W+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software"
+ "\\W+is\\W+hereby\\W+granted\\W+without\\W+fee\\W+provided\\W+that\\W+the\\W+above\\W+copyright\\W+notice"
+ "\\W+appears\\W+in\\W+all\\W+copies\\W+and\\W+that\\W+both\\W+that\\W+copyright\\W+notice\\W+and\\W+this"
+ "\\W+permission\\W+notice\\W+appear\\W+in\\W+supporting\\W+documentation"
+ "\\W+None\\W+of\\W+the\\W+above\\W+authors\\W+nor.{1,100}make\\W+any"
+ "\\W+representation\\W+about\\W+the\\W+suitability\\W+of\\W+this\\W+software\\W+for\\W+any"
+ "\\W+purpose\\W+It\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #9"
+ ,
+ "<P>Copyright <I> Author Date</I><BR>"
+ "Permission to use, copy, modify, sell, and distribute this software "
+ "is hereby granted without fee provided that the above copyright notice "
+ "appears in all copies and that both that copyright notice and this "
+ "permission notice appear in supporting documentation, <BR>"
+ "None of the above authors nor <I>Author's Organisation</I> make any "
+ "representation about the suitability of this software for any "
+ "purpose. It is provided \"as is\" without express or implied warranty."
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+use\\W+copy\\W+modify\\W+and\\W+distribute\\W+this\\W+software\\W+for\\W+any"
+ "\\W+purpose\\W+is\\W+hereby\\W+granted\\W+without\\W+fee\\W+provided\\W+that\\W+this\\W+copyright\\W+and"
+ "\\W+permissions\\W+notice\\W+appear\\W+in\\W+all\\W+copies\\W+and\\W+derivatives"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #10"
+ ,
+ "<P>Copyright <I>Author Date</I>. All rights reserved.</P>"
+ "<P>Permission to use, copy, modify, and distribute this software for any "
+ "purpose is hereby granted without fee, provided that this copyright and "
+ "permissions notice appear in all copies and derivatives.</P>"
+ "<P>This software is provided \"as is\" without express or implied warranty.</P>"
+ )
+ ,
+ license_info( boost::regex("This\\W+material\\W+is\\W+provided\\W+as\\W+is\\W+with\\W+absolutely\\W+no\\W+warranty\\W+expressed"
+ "\\W+or\\W+implied\\W+Any\\W+use\\W+is\\W+at\\W+your\\W+own\\W+risk"
+ "\\W+Permission\\W+to\\W+use\\W+or\\W+copy\\W+this\\W+software\\W+for\\W+any\\W+purpose\\W+is\\W+hereby\\W+granted"
+ "\\W+without\\W+fee\\W+provided\\W+the\\W+above\\W+notices\\W+are\\W+retained\\W+on\\W+all\\W+copies"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute\\W+modified\\W+code\\W+is\\W+granted"
+ "\\W+provided\\W+the\\W+above\\W+notices\\W+are\\W+retained\\W+and\\W+a\\W+notice\\W+that\\W+the\\W+code\\W+was"
+ "\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+above\\W+copyright\\W+notice"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #11"
+ ,
+ "<P>This material is provided \"as is\", with absolutely no warranty expressed "
+ "or implied. Any use is at your own risk.</P>"
+ "<P>Permission to use or copy this software for any purpose is hereby granted "
+ "without fee, provided the above notices are retained on all copies. "
+ "Permission to modify the code and to distribute modified code is granted, "
+ "provided the above notices are retained, and a notice that the code was "
+ "modified is included with the above copyright notice.</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+copy\\W+use\\W+and\\W+distribute\\W+this\\W+software\\W+is\\W+granted\\W+provided"
+ "\\W+that\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute\\W+modified\\W+code\\W+is\\W+granted"
+ "\\W+provided\\W+that\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+and\\W+a\\W+notice"
+ "\\W+that\\W+the\\W+code\\W+was\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+copyright\\W+notice"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty\\W+and"
+ "\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #12"
+ ,
+ "<P>Copyright (C) <I>Date Author</I></P><P>Permission to copy, use, and distribute this software is granted, provided "
+ "that this copyright notice appears in all copies.<BR>"
+ "Permission to modify the code and to distribute modified code is granted, "
+ "provided that this copyright notice appears in all copies, and a notice "
+ "that the code was modified is included with the copyright notice.</P>"
+ "<P>This software is provided \"as is\" without express or implied warranty, and "
+ "with no claim as to its suitability for any purpose.</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+copy\\W+and\\W+use\\W+this\\W+software\\W+is\\W+granted"
+ "\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute\\W+modified\\W+code\\W+is\\W+granted"
+ "\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+and\\W+a\\W+notice"
+ "\\W+that\\W+the\\W+code\\W+was\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+copyright\\W+notice"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty"
+ "\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #13"
+ ,
+ "<P>Copyright (C) <I>Date Author</I></P>"
+ "<P>Permission to copy and use this software is granted, "
+ "provided this copyright notice appears in all copies. "
+ "Permission to modify the code and to distribute modified code is granted, "
+ "provided this copyright notice appears in all copies, and a notice "
+ "that the code was modified is included with the copyright notice.</P>"
+ "<P>This software is provided \"as is\" without express or implied warranty, "
+ "and with no claim as to its suitability for any purpose.</P>"
+ )
+ ,
+ license_info( boost::regex("Copyright\\W+Kevlin\\W+Henney\\W+2000\\W+All\\W+rights\\W+reserved\\W+"
+ "Permission\\W+to\\W+use\\W+copy\\W+modify\\W+and\\W+distribute\\W+this\\W+software\\W+for\\W+any"
+ "\\W+purpose\\W+is\\W+hereby\\W+granted\\W+without\\W+fee\\W+provided\\W+that\\W+this\\W+copyright\\W+and"
+ "\\W+permissions\\W+notice\\W+appear\\W+in\\W+all\\W+copies\\W+and\\W+derivatives\\W+and\\W+that\\W+no"
+ "\\W+charge\\W+may\\W+be\\W+made\\W+for\\W+the\\W+software\\W+and\\W+its\\W+documentation\\W+except\\W+to\\W+cover"
+ "\\W+cost\\W+of\\W+distribution"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty\\W+"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #14"
+ ,
+ "<P>Copyright The Author, The Date. All rights reserved.</P>"
+ "<P>Permission to use, copy, modify, and distribute this software for any"
+ " purpose is hereby granted without fee, provided that this copyright and"
+ " permissions notice appear in all copies and derivatives, and that no"
+ " charge may be made for the software and its documentation except to cover"
+ " cost of distribution.</P>"
+ "<P>This software is provided \"as is\" without express or implied warranty.</P>"
+ )
+ ,
+ license_info( boost::regex("preprocessed\\W+version\\W+of\\W+boost/mpl/.*\\.hpp\\W+header\\W+see\\W+the\\W+original\\W+for\\W+copyright\\W+information", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "SGI Style Licence (MPL preprocessed file)"
+ ,
+ "<P>Copyright (c) <I>Date</I><BR>"
+ "<I>Author</I><BR>"
+ "<BR>"
+ "Permission to use, copy, modify, distribute and sell this software "
+ "and its documentation for any purpose is hereby granted without fee, "
+ "provided that the above copyright notice appear in all copies and "
+ "that both that copyright notice and this permission notice appear "
+ "in supporting documentation. <I>Author</I> makes no representations "
+ "about the suitability of this software for any purpose. "
+ "It is provided \"as is\" without express or implied warranty.</P>"
+ )
+ ,
+ license_info( boost::regex(
+ "This\\W+file\\W+is\\W+part\\W+of\\W+jam\\W+"
+ "License\\W+is\\W+hereby\\W+granted\\W+to\\W+use\\W+this\\W+software\\W+and\\W+distribute\\W+it\\W+"
+ "freely\\W+as\\W+long\\W+as\\W+this\\W+copyright\\W+notice\\W+is\\W+retained\\W+and\\W+modifications\\W+"
+ "are\\W+clearly\\W+marked\\W+"
+ "ALL\\W+WARRANTIES\\W+ARE\\W+HEREBY\\W+DISCLAIMED"
+ "|"
+ "This\\W+file\\W+is\\W+part\\W+of\\W+Jam\\W+see\\W+jam\\.c\\W+for\\W+Copyright\\W+information"
+ "|This file has been donated to Jam"
+ "|Generated by mkjambase from Jambase" , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig + std::string("|(Craig\\W+W\\W+McPheeters\\W+Alias\\W+Wavefront)|(Generated by mkjambase from Jambase)"), boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format + std::string("(?4Craig W. McPheeters, Alias|Wavefront)(?5Christopher Seiwald and Perforce Software, Inc)")
+ ,
+ "Perforce Jam License"
+ ,
+ "<P>Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.</P>"
+ "<P>This file is part of jam.</P>"
+ "<P>License is hereby granted to use this software and distribute it "
+ "freely, as long as this copyright notice is retained and modifications "
+ " are clearly marked.</P>"
+ "<P>ALL WARRANTIES ARE HEREBY DISCLAIMED</P>"
+ )
+ ,
+ license_info( boost::regex(
+ "Permission\\W+is\\W+granted\\W+to\\W+anyone\\W+to\\W+use\\W+this\\W+software\\W+for\\W+any\\W+"
+ "purpose\\W+on\\W+any\\W+computer\\W+system\\W+and\\W+to\\W+redistribute\\W+it\\W+freely\\W+"
+ "subject\\W+to\\W+the\\W+following\\W+restrictions\\W+"
+ "1\\W+The\\W+author\\W+is\\W+not\\W+responsible\\W+for\\W+the\\W+consequences\\W+of\\W+use\\W+of\\W+"
+ "this\\W+software\\W+no\\W+matter\\W+how\\W+awful\\W+even\\W+if\\W+they\\W+arise\\W+"
+ "from\\W+defects\\W+in\\W+it\\W+"
+ "2\\W+The\\W+origin\\W+of\\W+this\\W+software\\W+must\\W+not\\W+be\\W+misrepresented\\W+either\\W+"
+ "by\\W+explicit\\W+claim\\W+or\\W+by\\W+omission\\W+"
+ "3\\W+Altered\\W+versions\\W+must\\W+be\\W+plainly\\W+marked\\W+as\\W+such\\W+and\\W+must\\W+not\\W+"
+ "be\\W+misrepresented\\W+as\\W+being\\W+the\\W+original\\W+software"
+ "|Definitions\\W+etc\\W+for\\W+regexp\\W+3\\W+routines", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig + std::string("|(Definitions\\W+etc\\W+for\\W+regexp\\W+3\\W+routines)"), boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format + std::string("(?4University of Toronto)")
+ ,
+ "BSD Regex License"
+ ,
+ "<P>Copyright (c) 1986 by University of Toronto.</P>"
+ "<P>Written by Henry Spencer. Not derived from licensed software.</P>"
+ "<P>Permission is granted to anyone to use this software for any"
+ "purpose on any computer system, and to redistribute it freely,"
+ "subject to the following restrictions:</P>"
+ "<P>The author is not responsible for the consequences of use of"
+ "this software, no matter how awful, even if they arise"
+ "from defects in it.</P>"
+ "<p>The origin of this software must not be misrepresented, either"
+ "by explicit claim or by omission.</p>"
+ "<p>Altered versions must be plainly marked as such, and must not"
+ "be misrepresented as being the original software.</P>"
+ )
+ ,
+ license_info( boost::regex(
+ "Skeleton\\W+parser\\W+for\\W+Yacc\\W+like\\W+parsing\\W+with\\W+Bison\\W+"
+ "Copyright.{0,100}Free\\W+Software\\W+Foundation\\W+Inc\\W+"
+ "\\W+This\\W+program\\W+is\\W+free\\W+software\\W+you\\W+can\\W+redistribute\\W+it\\W+and\\W+or\\W+modify\\W+"
+ "it\\W+under\\W+the\\W+terms\\W+of\\W+the\\W+GNU\\W+General\\W+Public\\W+License\\W+as\\W+published\\W+by\\W+"
+ "the\\W+Free\\W+Software\\W+Foundation\\W+either\\W+version\\W+2\\W+or\\W+at\\W+your\\W+option\\W+"
+ "any\\W+later\\W+version"
+ "|"
+ // this part matches the start of jamgramtab.h which is under the same licence
+ // but bison does not output it's usual licence declaration:
+ "\\{\\s*\"!\"\\s*,\\s*_BANG_t\\s*\\}", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig + std::string("|(\\{\\s*\"!\"\\s*,\\s*_BANG_t\\s*\\})"), boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format + std::string("(?4Free Software Foundation, Inc)")
+ ,
+ "GNU Parser Licence"
+ ,
+ "<P>Skeleton parser for Yacc-like parsing with Bison,<BR>"
+ "Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.</P>"
+ "<P>This program is free software; you can redistribute it and/or modify"
+ "it under the terms of the GNU General Public License as published by"
+ "the Free Software Foundation; either version 2, or (at your option)"
+ "any later version.</P>"
+ "<P>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.</P>"
+ "<P>You should have received a copy of the GNU General Public License"
+ "along with this program; if not, write to the Free Software"
+ "Foundation, Inc., 59 Temple Place - Suite 330,"
+ "Boston, MA 02111-1307, USA.</P>"
+ "<P>As a special exception, when this file is copied by Bison into a"
+ "Bison output file, you may use that output file without restriction."
+ "This special exception was added by the Free Software Foundation"
+ "in version 1.24 of Bison.</P>"
+ )
+ ,
+ license_info( boost::regex(
+ "(?:The|This)\\W+code\\W+is\\W+considered\\W+to\\W+be\\W+in\\W+the\\W+public\\W+domain", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Public Domain"
+ ,
+ "<P>The code has no license terms, it has been explicity placed in the\n"
+ "public domain by it's author(s).</P>"
+ )
+ ,
+ };
+ return std::pair<const license_info*, int>(licenses, sizeof(licenses)/sizeof(licenses[0]));
+}
+
+std::string format_authors_name(const std::string& name)
+{
+ // put name into a consistent format, so that we don't get too much
+ // of a proliferation of names (lots of versions of the same basic form).
+
+ static const boost::regex e("(^)?[^-(<a-zA-ZÀ-þ]+(([(<].*)?$)?");
+ static const char* formatter = "(?1:(?2: ))";
+
+ return boost::regex_replace(name, e, formatter, boost::match_default | boost::format_all);
+}
+
diff --git a/tools/bcp/licence_info.hpp b/tools/bcp/licence_info.hpp
new file mode 100644
index 0000000000..e4ced2572a
--- /dev/null
+++ b/tools/bcp/licence_info.hpp
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include <boost/regex.hpp>
+#include <utility>
+
+struct license_info
+{
+ boost::regex license_signature;
+ boost::regex copyright_signature;
+ std::string copyright_formatter;
+ std::string license_name;
+ std::string license_text;
+ //
+ // we should really be able to initialize license_info as an
+ // aggregate, but some compilers reject this, so use a constructor
+ //instead:
+ //
+ license_info(const boost::regex& e1,
+ const boost::regex& e2,
+ const std::string& s1,
+ const std::string& s2,
+ const std::string& s3)
+ : license_signature(e1),
+ copyright_signature(e2),
+ copyright_formatter(s1),
+ license_name(s2),
+ license_text(s3){}
+};
+
+std::pair<const license_info*, int> get_licenses();
+
+std::string format_authors_name(const std::string& name);
diff --git a/tools/bcp/main.cpp b/tools/bcp/main.cpp
new file mode 100644
index 0000000000..28a5491e7c
--- /dev/null
+++ b/tools/bcp/main.cpp
@@ -0,0 +1,182 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * This file implements the cpp_main entry point
+ */
+
+
+#include <iostream>
+#include <cstring>
+#include <string>
+#include <list>
+#include "bcp.hpp"
+#include <boost/filesystem/path.hpp>
+#include <boost/version.hpp>
+
+#ifdef BOOST_NO_STDC_NAMESPACE
+namespace std{
+ using ::strcmp;
+ using ::strncmp;
+}
+#endif
+
+void show_usage()
+{
+ std::cout <<
+ "Usage:\n"
+ " bcp --list [options] module-list\n"
+ " bcp --list-short [options] module-list\n"
+ " bcp --report [options] module-list html-file\n"
+ " bcp [options] module-list output-path\n"
+ "\n"
+ "Options:\n"
+ " --boost=path sets the location of the boost tree to path\n"
+ " --scan treat the module list as a list of (possibly non-boost)\n"
+ " files to scan for boost dependencies\n"
+ " --svn only copy files under cvs version control\n"
+ " --unix-lines make sure that all copied files use Unix style line endings\n"
+ " --namespace=name rename the boost namespace to name (also changes library names).\n"
+ " --namespace-alias Makes namespace boost an alias of the namespace set with --namespace.\n"
+ "\n"
+ "module-list: a list of boost files or library names to copy\n"
+ "html-file: the name of a html file to which the report will be written\n"
+ "output-path: the path to which files will be copied\n";
+}
+
+bool filesystem_name_check( const std::string & name )
+{
+ return true;
+}
+
+int cpp_main(int argc, char* argv[])
+{
+ //
+ // Before anything else replace Boost.filesystem's file
+ // name checker with one that does nothing (we only deal
+ // with files that already exist, if they're not portable
+ // names it's too late for us to do anything about it).
+ //
+ /*boost::filesystem::path::default_name_check(filesystem_name_check);*/
+ //
+ // without arguments just show help:
+ //
+ if(argc < 2)
+ {
+ std::cout << "Error: insufficient arguments, don't know what to do." << std::endl;
+ show_usage();
+ return 1;
+ }
+ //
+ // create the application object:
+ //
+ pbcp_application papp(bcp_application::create());
+ //
+ // work through args, and tell the application
+ // object what ir needs to do:
+ //
+ bool list_mode = false;
+ std::list<const char*> positional_args;
+ for(int i = 1; i < argc; ++i)
+ {
+ if(0 == std::strcmp("-h", argv[i])
+ || 0 == std::strcmp("--help", argv[i]))
+ {
+ show_usage();
+ return 0;
+ }
+ if(0 == std::strcmp("-v", argv[i])
+ || 0 == std::strcmp("--version", argv[i]))
+ {
+ std::cout << "bcp " << (BOOST_VERSION / 100000) << "." << (BOOST_VERSION / 100 % 1000) << "." << (BOOST_VERSION % 100) << std::endl;
+ std::cout << __DATE__ << std::endl;
+ return 0;
+ }
+ else if(0 == std::strcmp("--list", argv[i]))
+ {
+ list_mode = true;
+ papp->enable_list_mode();
+ }
+ else if(0 == std::strcmp("--list-short", argv[i]))
+ {
+ list_mode = true;
+ papp->enable_summary_list_mode();
+ }
+ else if(0 == std::strcmp("--report", argv[i]))
+ {
+ papp->enable_license_mode();
+ }
+ else if(0 == std::strcmp("--cvs", argv[i]))
+ {
+ papp->enable_cvs_mode();
+ }
+ else if(0 == std::strcmp("--svn", argv[i]))
+ {
+ papp->enable_svn_mode();
+ }
+ else if(0 == std::strcmp("--scan", argv[i]))
+ {
+ papp->enable_scan_mode();
+ }
+ else if(0 == std::strcmp("--bsl-convert", argv[i]))
+ {
+ papp->enable_bsl_convert_mode();
+ }
+ else if(0 == std::strcmp("--bsl-summary", argv[i]))
+ {
+ papp->enable_bsl_summary_mode();
+ }
+ else if(0 == std::strcmp("--unix-lines", argv[i]))
+ {
+ papp->enable_unix_lines();
+ }
+ else if(0 == std::strncmp("--boost=", argv[i], 8))
+ {
+ papp->set_boost_path(argv[i] + 8);
+ }
+ else if(0 == std::strncmp("--namespace=", argv[i], 12))
+ {
+ papp->set_namespace(argv[i] + 12);
+ }
+ else if(0 == std::strncmp("--namespace-alias", argv[i], 17))
+ {
+ papp->set_namespace_alias(true);
+ }
+ else if(0 == std::strncmp("--list-namespaces", argv[i], 17))
+ {
+ list_mode = true;
+ papp->set_namespace_list(true);
+ }
+ else if(argv[i][0] == '-')
+ {
+ std::cout << "Error: Unknown argument " << argv[i] << std::endl;
+ show_usage();
+ return 1;
+ }
+ else
+ {
+ positional_args.push_back(argv[i]);
+ }
+ }
+ //
+ // Handle positional args last:
+ //
+ for(std::list<const char*>::const_iterator i = positional_args.begin();
+ i != positional_args.end(); ++i)
+ {
+ if(!list_mode && (i == --positional_args.end()))
+ papp->set_destination(*i);
+ else
+ papp->add_module(*i);
+ }
+ //
+ // run the application object:
+ //
+ return papp->run();
+}
+
+
+
diff --git a/tools/bcp/output_licence_info.cpp b/tools/bcp/output_licence_info.cpp
new file mode 100644
index 0000000000..2349acc83f
--- /dev/null
+++ b/tools/bcp/output_licence_info.cpp
@@ -0,0 +1,408 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "licence_info.hpp"
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <fstream>
+#include <iomanip>
+#include <cstring>
+#include <stdexcept>
+#include <boost/lexical_cast.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/throw_exception.hpp>
+
+//
+// split_path is a small helper for outputting a path name,
+// complete with a link to that path:
+//
+struct split_path
+{
+ const fs::path& root;
+ const fs::path& file;
+ split_path(const fs::path& r, const fs::path& f)
+ : root(r), file(f){}
+};
+
+std::ostream& operator << (std::ostream& os, const split_path& p)
+{
+ os << "<a href=\"" << (p.root / p.file).string() << "\">" << p.file.string() << "</a>";
+ return os;
+}
+
+std::string make_link_target(const std::string& s)
+{
+ // convert an arbitrary string into something suitable
+ // for an <a> name:
+ std::string result;
+ for(unsigned i = 0; i < s.size(); ++i)
+ {
+ result.append(1, static_cast<std::string::value_type>(std::isalnum(s[i]) ? s[i] : '_'));
+ }
+ return result;
+}
+
+
+void bcp_implementation::output_license_info()
+{
+ std::pair<const license_info*, int> licenses = get_licenses();
+
+ std::map<int, license_data>::const_iterator i, j;
+ i = m_license_data.begin();
+ j = m_license_data.end();
+
+ std::ofstream os(m_dest_path.string().c_str());
+ if(!os)
+ {
+ std::string msg("Error opening ");
+ msg += m_dest_path.string();
+ msg += " for output.";
+ std::runtime_error e(msg);
+ boost::throw_exception(e);
+ }
+ os <<
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"
+ "<html>\n"
+ "<head>\n"
+ "<title>Boost Licence Dependency Information";
+ if(m_module_list.size() == 1)
+ {
+ os << " for " << *(m_module_list.begin());
+ }
+ os <<
+ "</title>\n"
+ "</head>\n"
+ "<body>\n"
+ "<H1>Boost Licence Dependency Information";
+ if(m_module_list.size() == 1)
+ {
+ os << " for " << *(m_module_list.begin());
+ }
+ os <<
+ "</H1>\n"
+ "<H2>Contents</h2>\n"
+ "<pre><a href=\"#input\">Input Information</a>\n";
+ if(!m_bsl_summary_mode)
+ os << "<a href=\"#summary\">Licence Summary</a>\n";
+ os << "<a href=\"#details\">Licence Details</a>\n";
+
+ while(i != j)
+ {
+ // title:
+ os << " <A href=\"#" << make_link_target(licenses.first[i->first].license_name)
+ << "\">" << licenses.first[i->first].license_name << "</a>\n";
+ ++i;
+ }
+
+ os << "<a href=\"#files\">Files with no recognised license</a>\n"
+ "<a href=\"#authors\">Files with no recognised copyright holder</a>\n";
+ if(!m_bsl_summary_mode)
+ {
+ os <<
+ "Moving to the Boost Software License...\n"
+ " <a href=\"#bsl-converted\">Files that can be automatically converted to the Boost Software License</a>\n"
+ " <a href=\"#to-bsl\">Files that can be manually converted to the Boost Software License</a>\n"
+ " <a href=\"#not-to-bsl\">Files that can <b>NOT</b> be moved to the Boost Software License</a>\n"
+ " <a href=\"#need-bsl-authors\">Authors we need to move to the Boost Software License</a>\n"
+ "<a href=\"#copyright\">Copyright Holder Information</a>\n";
+ }
+ os <<
+ "<a href=\"#depend\">File Dependency Information</a>\n"
+ "</pre>";
+
+ //
+ // input Information:
+ //
+ os << "<a name=\"input\"></a><h2>Input Information</h2>\n";
+ if(m_scan_mode)
+ os << "<P>The following files were scanned for boost dependencies:<BR>";
+ else
+ os << "<P>The following Boost modules were checked:<BR>";
+
+ std::list<std::string>::const_iterator si = m_module_list.begin();
+ std::list<std::string>::const_iterator sj = m_module_list.end();
+ while(si != sj)
+ {
+ os << *si << "<BR>";
+ ++si;
+ }
+ os << "</p><p>The Boost path was: <code>" << m_boost_path.string() << "</code></P>";
+ //
+ // extract the boost version number from the boost directory tree,
+ // not from this app (which may have been built from a previous
+ // version):
+ //
+ fileview version_file(m_boost_path / "boost/version.hpp");
+ static const boost::regex version_regex(
+ "^[[:blank:]]*#[[:blank:]]*define[[:blank:]]+BOOST_VERSION[[:blank:]]+(\\d+)");
+ boost::cmatch what;
+ if(boost::regex_search(version_file.begin(), version_file.end(), what, version_regex))
+ {
+ int version = boost::lexical_cast<int>(what.str(1));
+ os << "<p>The Boost version is: " << version / 100000 << "." << version / 100 % 1000 << "." << version % 100 << "</P>\n";
+ }
+
+ //
+ // output each license:
+ //
+ i = m_license_data.begin();
+ j = m_license_data.end();
+ if(!m_bsl_summary_mode)
+ {
+ //
+ // start with the summary:
+ //
+ os << "<a name=\"summary\"></a><h2>Licence Summary</h2>\n";
+ while(i != j)
+ {
+ // title:
+ os <<
+ "<H3>" << licenses.first[i->first].license_name << "</H3>\n";
+ // license text:
+ os << "<BLOCKQUOTE>" << licenses.first[i->first].license_text << "</BLOCKQUOTE>";
+ // Copyright holders:
+ os << "<P>This license is used by " << i->second.authors.size()
+ << " authors and " << i->second.files.size()
+ << " files <a href=\"#" << make_link_target(licenses.first[i->first].license_name) << "\">(see details)</a>";
+ os << "</P></BLOCKQUOTE>\n";
+ ++i;
+ }
+ }
+ //
+ // and now the details:
+ //
+ i = m_license_data.begin();
+ j = m_license_data.end();
+ int license_index = 0;
+ os << "<a name=\"details\"></a><h2>Licence Details</h2>\n";
+ while(i != j)
+ {
+ // title:
+ os <<
+ "<H3><A name=\"" << make_link_target(licenses.first[i->first].license_name)
+ << "\"></a>" << licenses.first[i->first].license_name << "</H3>\n";
+ // license text:
+ os << "<BLOCKQUOTE>" << licenses.first[i->first].license_text << "</BLOCKQUOTE>";
+ if(!m_bsl_summary_mode || (license_index >= 3))
+ {
+ // Copyright holders:
+ os << "<P>This license is used by the following " << i->second.authors.size() << " copyright holders:</P>\n<BLOCKQUOTE><P>";
+ std::set<std::string>::const_iterator x, y;
+ x = i->second.authors.begin();
+ y = i->second.authors.end();
+ while(x != y)
+ {
+ os << *x << "<BR>\n";
+ ++x;
+ }
+ os << "</P></BLOCKQUOTE>\n";
+ // Files using this license:
+ os << "<P>This license applies to the following " << i->second.files.size() << " files:</P>\n<BLOCKQUOTE><P>";
+ std::set<fs::path, path_less>::const_iterator m, n;
+ m = i->second.files.begin();
+ n = i->second.files.end();
+ while(m != n)
+ {
+ os << split_path(m_boost_path, *m) << "<br>\n";
+ ++m;
+ }
+ os << "</P></BLOCKQUOTE>\n";
+ }
+ else
+ {
+ os << "<P>This license is used by " << i->second.authors.size() << " authors (list omitted for brevity).</P>\n";
+ os << "<P>This license applies to " << i->second.files.size() << " files (list omitted for brevity).</P>\n";
+ }
+ ++license_index;
+ ++i;
+ }
+ //
+ // Output list of files not found to be under license control:
+ //
+ os << "<h2><a name=\"files\"></a>Files With No Recognisable Licence</h2>\n"
+ "<P>The following " << m_unknown_licenses.size() << " files had no recognisable license information:</P><BLOCKQUOTE><P>\n";
+ std::set<fs::path, path_less>::const_iterator i2, j2;
+ i2 = m_unknown_licenses.begin();
+ j2 = m_unknown_licenses.end();
+ while(i2 != j2)
+ {
+ os << split_path(m_boost_path, *i2) << "<br>\n";
+ ++i2;
+ }
+ os << "</p></BLOCKQUOTE>";
+ //
+ // Output list of files with no found copyright holder:
+ //
+ os << "<h2><a name=\"authors\"></a>Files With No Recognisable Copyright Holder</h2>\n"
+ "<P>The following " << m_unknown_authors.size() << " files had no recognisable copyright holder:</P>\n<BLOCKQUOTE><P>";
+ i2 = m_unknown_authors.begin();
+ j2 = m_unknown_authors.end();
+ while(i2 != j2)
+ {
+ os << split_path(m_boost_path, *i2) << "<br>\n";
+ ++i2;
+ }
+ os << "</p></BLOCKQUOTE>";
+ if(!m_bsl_summary_mode)
+ {
+ //
+ // Output list of files that have been moved over to the Boost
+ // Software License, along with enough information for human
+ // verification.
+ //
+ os << "<h2><a name=\"bsl-converted\"></a>Files that can be automatically converted to the Boost Software License</h2>\n"
+ << "<P>The following " << m_converted_to_bsl.size() << " files can be automatically converted to the Boost Software License, but require manual verification before they can be committed to CVS:</P>\n";
+ if (!m_converted_to_bsl.empty())
+ {
+ typedef std::map<fs::path, std::pair<std::string, std::string>, path_less>
+ ::const_iterator conv_iterator;
+ conv_iterator i = m_converted_to_bsl.begin(),
+ ie = m_converted_to_bsl.end();
+ int file_num = 1;
+ while (i != ie)
+ {
+ os << "<P>[" << file_num << "] File: <tt>" << split_path(m_boost_path, i->first)
+ << "</tt><br>\n<table border=\"1\">\n <tr>\n <td><pre>"
+ << i->second.first << "</pre></td>\n <td><pre>"
+ << i->second.second << "</pre></td>\n </tr>\n</table>\n";
+ ++i;
+ ++file_num;
+ }
+ }
+ //
+ // Output list of files that could be moved over to the Boost Software License
+ //
+ os << "<h2><a name=\"to-bsl\"></a>Files that could be converted to the Boost Software License</h2>\n"
+ "<P>The following " << m_can_migrate_to_bsl.size() << " files could be manually converted to the Boost Software License, but have not yet been:</P>\n<BLOCKQUOTE><P>";
+ i2 = m_can_migrate_to_bsl.begin();
+ j2 = m_can_migrate_to_bsl.end();
+ while(i2 != j2)
+ {
+ os << split_path(m_boost_path, *i2) << "<br>\n";
+ ++i2;
+ }
+ os << "</p></BLOCKQUOTE>";
+ //
+ // Output list of files that can not be moved over to the Boost Software License
+ //
+ os << "<h2><a name=\"not-to-bsl\"></a>Files that can NOT be converted to the Boost Software License</h2>\n"
+ "<P>The following " << m_cannot_migrate_to_bsl.size() << " files cannot be converted to the Boost Software License because we need the permission of more authors:</P>\n<BLOCKQUOTE><P>";
+ i2 = m_cannot_migrate_to_bsl.begin();
+ j2 = m_cannot_migrate_to_bsl.end();
+ while(i2 != j2)
+ {
+ os << split_path(m_boost_path, *i2) << "<br>\n";
+ ++i2;
+ }
+ os << "</p></BLOCKQUOTE>";
+ //
+ // Output list of authors that we need permission for to move to the BSL
+ //
+ os << "<h2><a name=\"need-bsl-authors\"></a>Authors we need for the BSL</h2>\n"
+ "<P>Permission of the following authors is needed before we can convert to the Boost Software License. The list of authors that have given their permission is contained in <code>more/blanket-permission.txt</code>.</P>\n<BLOCKQUOTE><P>";
+ std::copy(m_authors_for_bsl_migration.begin(), m_authors_for_bsl_migration.end(),
+ std::ostream_iterator<std::string>(os, "<br>\n"));
+ os << "</p></BLOCKQUOTE>";
+ //
+ // output a table of copyright information:
+ //
+ os << "<H2><a name=\"copyright\"></a>Copyright Holder Information</H2><table border=\"1\">\n";
+ std::map<std::string, std::set<fs::path, path_less> >::const_iterator ad, ead;
+ ad = m_author_data.begin();
+ ead = m_author_data.end();
+ while(ad != ead)
+ {
+ os << "<tr><td>" << ad->first << "</td><td>";
+ std::set<fs::path, path_less>::const_iterator fi, efi;
+ fi = ad->second.begin();
+ efi = ad->second.end();
+ while(fi != efi)
+ {
+ os << split_path(m_boost_path, *fi) << " ";
+ ++fi;
+ }
+ os << "</td></tr>\n";
+ ++ad;
+ }
+ os << "</table>\n";
+ }
+
+ //
+ // output file dependency information:
+ //
+ os << "<H2><a name=\"depend\"></a>File Dependency Information</H2><BLOCKQUOTE><pre>\n";
+ std::map<fs::path, fs::path, path_less>::const_iterator dep, last_dep;
+ std::set<fs::path, path_less>::const_iterator fi, efi;
+ fi = m_copy_paths.begin();
+ efi = m_copy_paths.end();
+ // if in summary mode, just figure out the "bad" files and print those only:
+ std::set<fs::path, path_less> bad_paths;
+ if(m_bsl_summary_mode)
+ {
+ bad_paths.insert(m_unknown_licenses.begin(), m_unknown_licenses.end());
+ bad_paths.insert(m_unknown_authors.begin(), m_unknown_authors.end());
+ bad_paths.insert(m_can_migrate_to_bsl.begin(), m_can_migrate_to_bsl.end());
+ bad_paths.insert(m_cannot_migrate_to_bsl.begin(), m_cannot_migrate_to_bsl.end());
+ typedef std::map<fs::path, std::pair<std::string, std::string>, path_less>
+ ::const_iterator conv_iterator;
+ conv_iterator i = m_converted_to_bsl.begin(),
+ ie = m_converted_to_bsl.end();
+ while(i != ie)
+ {
+ bad_paths.insert(i->first);
+ ++i;
+ }
+ fi = bad_paths.begin();
+ efi = bad_paths.end();
+ os << "<P>For brevity, only files not under the BSL are shown</P>\n";
+ }
+ while(fi != efi)
+ {
+ os << split_path(m_boost_path, *fi);
+ dep = m_dependencies.find(*fi);
+ last_dep = m_dependencies.end();
+ std::set<fs::path, path_less> seen_deps;
+ if (dep != last_dep)
+ while(true)
+ {
+ os << " -> ";
+ if(fs::exists(m_boost_path / dep->second))
+ os << split_path(m_boost_path, dep->second);
+ else if(fs::exists(dep->second))
+ os << split_path(fs::path(), dep->second);
+ else
+ os << dep->second.string();
+ if(seen_deps.find(dep->second) != seen_deps.end())
+ {
+ os << " <I>(Circular dependency!)</I>";
+ break; // circular dependency!!!
+ }
+ seen_deps.insert(dep->second);
+ last_dep = dep;
+ dep = m_dependencies.find(dep->second);
+ if((dep == m_dependencies.end()) || (0 == compare_paths(dep->second, last_dep->second)))
+ break;
+ }
+ os << "\n";
+ ++fi;
+ }
+ os << "</pre></BLOCKQUOTE>\n";
+
+ os << "</body></html>\n";
+
+ if(!os)
+ {
+ std::string msg("Error writing to ");
+ msg += m_dest_path.string();
+ msg += ".";
+ std::runtime_error e(msg);
+ boost::throw_exception(e);
+ }
+
+}
diff --git a/tools/bcp/path_operations.cpp b/tools/bcp/path_operations.cpp
new file mode 100644
index 0000000000..aebbc4e6fd
--- /dev/null
+++ b/tools/bcp/path_operations.cpp
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * This file implements path comparisons
+ */
+
+
+#include "bcp_imp.hpp"
+#include <cctype>
+
+#ifdef BOOST_NO_STDC_NAMESPACE
+namespace std{
+ using ::tolower;
+}
+#endif
+
+
+int compare_paths(const fs::path& a, const fs::path& b)
+{
+ const std::string& as = a.generic_string();
+ const std::string& bs = b.generic_string();
+ std::string::const_iterator i, j, k, l;
+ i = as.begin();
+ j = as.end();
+ k = bs.begin();
+ l = bs.end();
+ while(i != j)
+ {
+ if(k == l)
+ return -1;
+ int r = std::tolower(*i) - std::tolower(*k);
+ if(r) return r;
+ ++i;
+ ++k;
+ }
+ return (k == l) ? 0 : 1;
+}
diff --git a/tools/bcp/scan_cvs_path.cpp b/tools/bcp/scan_cvs_path.cpp
new file mode 100644
index 0000000000..3c5eb2ea58
--- /dev/null
+++ b/tools/bcp/scan_cvs_path.cpp
@@ -0,0 +1,147 @@
+/*
+ *
+ * Copyright (c) 2003-7 John Maddock
+ * Copyright (c) 2007 Bjorn Roald
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * This file implements the following:
+ * void bcp_implementation::scan_cvs_path(const fs::path& p)
+ */
+
+
+
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <boost/regex.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/detail/workaround.hpp>
+#include <iostream>
+
+void bcp_implementation::scan_cvs_path(const fs::path& p)
+{
+ //
+ // scan through the cvs admin files to build a list
+ // of all the files under cvs version control
+ // and whether they are text or binary:
+ //
+ static const char* file_list[] = { "CVS/Entries", "CVS/Entries.Log" };
+ static const boost::regex file_expression("^(?:A\\s+)?/([^/\\n]+)/[^/\\n]*/[^/\\n]*/[^k/\\n]*(kb[^/\\n]*)?/[^/\\n]*");
+ static const boost::regex dir_expression("^(?:A\\s+)?D/([^/\\n]+)/");
+ static const int file_subs[] = {1,2,};
+
+ for(int entry = 0; entry < sizeof(file_list)/sizeof(file_list[0]); ++entry)
+ {
+ fs::path entries(m_boost_path / p / file_list[entry]);
+ if(fs::exists(entries))
+ {
+ fileview view(entries);
+ boost::regex_token_iterator<const char*> i(view.begin(), view.end(), dir_expression, 1);
+ boost::regex_token_iterator<const char*> j;
+ while(i != j)
+ {
+ fs::path recursion_dir(p / i->str());
+ scan_cvs_path(recursion_dir);
+ ++i;
+ }
+ #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
+ std::vector<int> v(file_subs, file_subs + 2);
+ i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), file_expression, v);
+ #else
+ i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), file_expression, file_subs);
+ #endif
+ while(i != j)
+ {
+ fs::path file = p / i->str();
+ ++i;
+ bool binary = i->length() ? true : false;
+ ++i;
+ m_cvs_paths[file] = binary;
+ }
+
+ }
+ }
+}
+
+void bcp_implementation::scan_svn_path(const fs::path& p)
+{
+ //
+ // scan through the svn entries files to build a list
+ // of all the files under svn version control
+ // and whether they are text or binary:
+ //
+ static const boost::regex entry_expression("^\\f([^\\f]*)");
+ static const boost::regex entry_line_expression("\\n[[:blank:]]*([^\\n]*)");
+ // static const boost::regex
+ // mime_type_expression("\\nsvn:mime-type\\nV [[digit]]*\\n([^/]*)[^\\n]*");
+
+ fs::path entries(m_boost_path / p / ".svn" / "entries");
+ if(fs::exists(entries))
+ {
+ fileview view(entries);
+ boost::cregex_token_iterator
+ i(view.begin(), view.end(), entry_expression, 1), j;
+
+ while(i != j) // entries
+ {
+ std::string entr = i->str();
+ boost::sregex_token_iterator
+ atr_it(entr.begin(), entr.end(), entry_line_expression, 1), atr_j;
+
+ if(atr_it != atr_j)
+ {
+ std::string name = atr_it->str(); // name of file or directory
+ fs::path fpath = p / name;
+ if(++atr_it != atr_j)
+ {
+ std::string kind = atr_it->str();
+ if(kind == "file")
+ {
+ // find if binary, we asume text unless mime type is
+ // set in property file
+ bool binary = false; //
+
+ // skip some lines type | example
+ if( ++atr_it != atr_j && // revnum |
+ ++atr_it != atr_j && // url |
+ ++atr_it != atr_j && // repos |
+ ++atr_it != atr_j && // scedule attr |
+ ++atr_it != atr_j && // text timestamp | 2007-09-02T...
+ ++atr_it != atr_j && // checksum | 58f4bfa7860...
+ ++atr_it != atr_j && // cmt_date | 2007-05-09T...
+ ++atr_it != atr_j && // cmt_rev | 37654
+ ++atr_it != atr_j && // cmt_author | dgregor
+ ++atr_it != atr_j ) // has_props | has-props
+ {
+ if(atr_it->str() == "has-props")
+ {
+ // we need to check properties file for mime-type
+ // that does not start with "text/", if found file is binary
+ fs::path properties(m_boost_path / p / ".svn" / "prop-base"
+ / (name + ".svn-base") );
+ if(fs::exists(properties))
+ {
+ fileview prop(properties);
+
+ static const boost::regex mime_type(
+ "svn:mime-type[[:blank:]]*(?:\\n|\\r|\\r\\n)[^\\r\\n]*(?:\\n|\\r|\\r\\n)[[:blank:]]*text/");
+ binary = regex_search(prop.begin(), prop.end(), mime_type) ? false : true;
+ }
+ }
+ }
+ m_cvs_paths[fpath] = binary;
+ } // kind == "file"
+ else if(kind == "dir")
+ {
+ scan_svn_path(fpath); // recursion for directory entries
+ }
+ // else
+ // std::cerr << "WARNING: unknown entry kind for entry " << name
+ // << "in " << entries << std::endl;
+ }
+ }
+ ++i;
+ } // while
+ }
+}
diff --git a/tools/bcp/scan_licence.cpp b/tools/bcp/scan_licence.cpp
new file mode 100644
index 0000000000..d1bf0bbebb
--- /dev/null
+++ b/tools/bcp/scan_licence.cpp
@@ -0,0 +1,275 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "licence_info.hpp"
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <fstream>
+#include <iostream>
+
+
+const int boost_license_lines = 3;
+static const std::string boost_license_text[boost_license_lines] = {
+ "Distributed under the Boost Software License, Version 1.0. (See",
+ "accompanying file LICENSE_1_0.txt or copy at",
+ "http://www.boost.org/LICENSE_1_0.txt)"
+};
+
+fileview::const_iterator
+context_before_license(const fileview& v, fileview::const_iterator start,
+ int context_lines = 3)
+{
+ char last_char = '\0';
+ while (start != v.begin() && context_lines >= 0) {
+ if (*start == '\r' || *start == '\n'
+ && (last_char == *start || (last_char != '\r' && last_char != '\n')))
+ --context_lines;
+
+ last_char = *start;
+ --start;
+ }
+
+ // Unless we hit the beginning, we need to step forward one to start
+ // on the next line.
+ if (start != v.begin()) ++start;
+
+ return start;
+}
+
+fileview::const_iterator
+context_after_license(const fileview& v, fileview::const_iterator end,
+ int context_lines = 3)
+{
+ char last_char = '\0';
+ while (end != v.end() && context_lines >= 0) {
+ if (*end == '\r' || *end == '\n'
+ && (last_char == *end || (last_char != '\r' && last_char != '\n')))
+ --context_lines;
+
+ last_char = *end;
+ ++end;
+ }
+
+ return end;
+}
+
+static std::string
+find_prefix(const fileview& v, fileview::const_iterator start_of_line)
+{
+ while (start_of_line != v.begin()
+ && *start_of_line != '\n'
+ && *start_of_line != '\r')
+ --start_of_line;
+ if (start_of_line != v.begin())
+ ++start_of_line;
+
+ fileview::const_iterator first_noncomment_char = start_of_line;
+ while (*first_noncomment_char == '/'
+ || *first_noncomment_char == '*'
+ || *first_noncomment_char == ' '
+ || *first_noncomment_char == '#')
+ ++first_noncomment_char;
+
+ return std::string(start_of_line, first_noncomment_char);
+}
+
+static std::string
+html_escape(fileview::const_iterator first, fileview::const_iterator last)
+{
+ std::string result;
+ while (first != last) {
+ switch (*first) {
+ case '<': result += "&lt;"; break;
+ case '>': result += "&gt;"; break;
+ case '&': result += "&amp;"; break;
+ default: result += *first;
+ }
+ ++first;
+ }
+ return result;
+}
+
+static bool is_non_bsl_license(int index)
+{
+ return index > 2;
+}
+
+void bcp_implementation::scan_license(const fs::path& p, const fileview& v)
+{
+ std::pair<const license_info*, int> licenses = get_licenses();
+ //
+ // scan file for all the licenses in the list:
+ //
+ int license_count = 0;
+ int author_count = 0;
+ int nonbsl_author_count = 0;
+ bool has_non_bsl_license = false;
+ fileview::const_iterator start_of_license = v.begin(),
+ end_of_license = v.end();
+ bool start_in_middle_of_line = false;
+
+ for(int i = 0; i < licenses.second; ++i)
+ {
+ boost::match_results<fileview::const_iterator> m;
+ if(boost::regex_search(v.begin(), v.end(), m, licenses.first[i].license_signature))
+ {
+ start_of_license = m[0].first;
+ end_of_license = m[0].second;
+
+ if (is_non_bsl_license(i) && i < licenses.second - 1)
+ has_non_bsl_license = true;
+
+ // add this license to the list:
+ m_license_data[i].files.insert(p);
+ ++license_count;
+ //
+ // scan for the associated copyright declarations:
+ //
+ boost::regex_iterator<const char*> cpy(v.begin(), v.end(), licenses.first[i].copyright_signature);
+ boost::regex_iterator<const char*> ecpy;
+ while(cpy != ecpy)
+ {
+#if 0
+ // Not dealing with copyrights because we don't have the years
+ if ((*cpy)[0].first < start_of_license)
+ start_of_license = (*cpy)[0].first;
+ if ((*cpy)[0].second > end_of_license)
+ end_of_license = (*cpy)[0].second;
+#endif
+
+ // extract the copy holders as a list:
+ std::string author_list = cpy->format(licenses.first[i].copyright_formatter, boost::format_all);
+ // now enumerate that list for all the names:
+ static const boost::regex author_separator("(?:\\s*,(?!\\s*(?:inc|ltd)\\b)\\s*|\\s+(,\\s*)?(and|&)\\s+)|by\\s+", boost::regex::perl | boost::regex::icase);
+ boost::regex_token_iterator<std::string::const_iterator> atr(author_list.begin(), author_list.end(), author_separator, -1);
+ boost::regex_token_iterator<std::string::const_iterator> eatr;
+ while(atr != eatr)
+ {
+ // get the reformatted authors name:
+ std::string name = format_authors_name(*atr);
+ // add to list of authors for this file:
+ if(name.size() && name[0] != '-')
+ {
+ m_license_data[i].authors.insert(name);
+ // add file to author index:
+ m_author_data[name].insert(p);
+ ++author_count;
+
+ // If this is not the Boost Software License (license 0), and the author hasn't given
+ // blanket permission, note this for the report.
+ if (has_non_bsl_license
+ && m_bsl_authors.find(name) == m_bsl_authors.end()) {
+ ++nonbsl_author_count;
+ m_authors_for_bsl_migration.insert(name);
+ }
+ }
+ ++atr;
+ }
+ ++cpy;
+ }
+
+ while (start_of_license != v.begin()
+ && *start_of_license != '\r'
+ && *start_of_license != '\n'
+ && *start_of_license != '.')
+ --start_of_license;
+
+ if (start_of_license != v.begin()) {
+ if (*start_of_license == '.')
+ start_in_middle_of_line = true;
+ ++start_of_license;
+ }
+
+ while (end_of_license != v.end()
+ && *end_of_license != '\r'
+ && *end_of_license != '\n')
+ ++end_of_license;
+ }
+ }
+ if(license_count == 0)
+ m_unknown_licenses.insert(p);
+ if(license_count && !author_count)
+ m_unknown_authors.insert(p);
+
+ if (has_non_bsl_license) {
+ bool converted = false;
+ if (nonbsl_author_count == 0
+ && license_count == 1) {
+ // Grab a few lines of context
+ fileview::const_iterator context_start =
+ context_before_license(v, start_of_license);
+ fileview::const_iterator context_end =
+ context_after_license(v, end_of_license);
+
+ // TBD: For files that aren't C++ code, this will have to
+ // change.
+ std::string prefix = find_prefix(v, start_of_license);
+
+ // Create enough information to permit manual verification of
+ // the correctness of the transformation
+ std::string before_conversion =
+ html_escape(context_start, start_of_license);
+ before_conversion += "<b>";
+ before_conversion += html_escape(start_of_license, end_of_license);
+ before_conversion += "</b>";
+ before_conversion += html_escape(end_of_license, context_end);
+
+ std::string after_conversion =
+ html_escape(context_start, start_of_license);
+ if (start_in_middle_of_line)
+ after_conversion += '\n';
+
+ after_conversion += "<b>";
+ for (int i = 0; i < boost_license_lines; ++i) {
+ if (i > 0) after_conversion += '\n';
+ after_conversion += prefix + boost_license_text[i];
+ }
+ after_conversion += "</b>";
+ after_conversion += html_escape(end_of_license, context_end);
+
+ m_converted_to_bsl[p] =
+ std::make_pair(before_conversion, after_conversion);
+
+ // Perform the actual conversion
+ if (m_bsl_convert_mode) {
+ try{
+ std::ofstream out((m_boost_path / p).string().c_str());
+ if (!out) {
+ std::string msg("Cannot open file for license conversion: ");
+ msg += p.string();
+ std::runtime_error e(msg);
+ boost::throw_exception(e);
+ }
+
+ out << std::string(v.begin(), start_of_license);
+ if (start_in_middle_of_line)
+ out << std::endl;
+
+ for (int j = 0; j < boost_license_lines; ++j) {
+ if (j > 0) out << std::endl;
+ out << prefix << boost_license_text[j];
+ }
+ out << std::string(end_of_license, v.end());
+
+ converted = true;
+ }
+ catch(const std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+ }
+ }
+
+ if (!converted) {
+ if (nonbsl_author_count > 0) m_cannot_migrate_to_bsl.insert(p);
+ else m_can_migrate_to_bsl.insert(p);
+ }
+ }
+}
+
diff --git a/tools/bcp/test/Jamfile.v2 b/tools/bcp/test/Jamfile.v2
new file mode 100644
index 0000000000..bea522489c
--- /dev/null
+++ b/tools/bcp/test/Jamfile.v2
@@ -0,0 +1,25 @@
+# (C) Copyright John Maddock 2006.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+path-constant boost-path : ../../.. ;
+
+run
+ # sources
+ ../add_dependent_lib.cpp ../add_path.cpp ../bcp_imp.cpp ../copy_path.cpp ../file_types.cpp
+ ../fileview.cpp ../main.cpp ../path_operations.cpp ../scan_cvs_path.cpp
+ ../licence_info.cpp ../scan_licence.cpp ../output_licence_info.cpp
+ /boost/filesystem//boost_filesystem
+ /boost/regex//boost_regex
+ /boost/test//boost_prg_exec_monitor
+ : # args
+ --boost=$(boost-path) --list boost
+ : # input-files
+ : # requirements
+ release
+ : # target-name
+ bcp-test
+ : # default-build
+ release
+ ;
+
diff --git a/tools/boostbook/doc/Jamfile.v2 b/tools/boostbook/doc/Jamfile.v2
new file mode 100644
index 0000000000..6c468cb883
--- /dev/null
+++ b/tools/boostbook/doc/Jamfile.v2
@@ -0,0 +1,13 @@
+# Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+project boost/doc ;
+import boostbook : boostbook ;
+
+boostbook boostbook : boostbook.xml :
+ <xsl:param>boost.root=../../../..
+ ;
+
diff --git a/tools/boostbook/doc/boostbook.xml b/tools/boostbook/doc/boostbook.xml
new file mode 100644
index 0000000000..d72373504e
--- /dev/null
+++ b/tools/boostbook/doc/boostbook.xml
@@ -0,0 +1,385 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<!DOCTYPE part PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<part xmlns:xi="http://www.w3.org/2001/XInclude" id="boostbook"
+ last-revision="$Date: 2010-07-19 19:29:09 -0400 (Mon, 19 Jul 2010) $">
+ <partinfo>
+ <author>
+ <firstname>Douglas</firstname>
+ <surname>Gregor</surname>
+ </author>
+
+ <copyright>
+ <year>2003</year>
+ <year>2004</year>
+ <year>2005</year>
+ <holder>Douglas Gregor</holder>
+ </copyright>
+
+ <legalnotice>
+ <para>Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>).
+ </para>
+ </legalnotice>
+ </partinfo>
+
+ <title>The BoostBook Documentation Format</title>
+
+ <chapter id="boostbook.introduction">
+ <title>Introduction</title>
+
+ <para>The BoostBook documentation format is an extension of <ulink
+ url="http://www.docbook.org">DocBook</ulink>, an SGML- or
+ XML-based format for describing documentation. BoostBook augments
+ DocBook with semantic markup that aids in the documentation of C++
+ libraries, specifically the <ulink
+ url="http://www.boost.org">Boost C++ libraries</ulink>, by
+ providing the ability to express and refer to C++ constructs such
+ as namespaces, classes, overloaded functions, templates, and
+ specializations.</para>
+
+ <para>
+ BoostBook offers additional features more specific to its use for
+ documenting the <ulink url="http://www.boost.org">Boost C++
+ libraries</ulink>. These features are intended to eliminate or
+ reduce the need for duplication of information and to aid in
+ documenting portions of Boost that might otherwise not be
+ documented. Examples of Boost-centric features include:
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="bold">Testsuites</emphasis>:
+ Testsuites in Boost are created by writing an appropriate
+ Jamfile and including that Jamfile in
+ <filename>status/Jamfile</filename>. If the testsuites are
+ documented (<ulink
+ url="http://www.boost.org/libs/multi_array/doc/test_cases.html">as
+ in the MultiArray library</ulink>), the documentation is
+ maintained separately from the testcase Jamfile, leading to
+ duplication of information and the possibility of having the
+ documentation out of sync with the Jamfile. BoostBook
+ contains elements that describe a testsuite for both
+ purposes: the BoostBook stylesheets can generate
+ documentation for the testcases and also generate an
+ appropriate Jamfile to integrate the testcases with the
+ regression testing system.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis role="bold">Example programs</emphasis>:
+ Example programs in documentation need to be duplicated in
+ testcases to ensure that the examples compile and execute
+ correctly. Keeping the two copies in sync is a tedious and
+ error-prone task. For instance, the following code snippet
+ persisted for six months:</para>
+<programlisting>
+std::cout &lt;&lt; f(5, 3) &gt;&gt; std::endl;
+</programlisting>
+ <para>The BoostBook format allows testcases to be generated
+ by weaving together program fragments from example programs
+ in the documentation. This capability is integrated with
+ testsuite generation so that example programs are normal
+ tests in BoostBook.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </chapter>
+
+ <chapter id="boostbook.getting.started">
+ <title>Getting Started</title>
+
+ <para>To use the Boost documentation tools, you will need several tools:</para>
+ <itemizedlist>
+ <listitem><simpara><command>xsltproc</command>:</simpara>
+ <itemizedlist>
+ <listitem>Windows with <ulink
+ url="http://www.cygwin.com/">Cygwin</ulink>: select the libxml2 and libxslt packages.</listitem>
+ <listitem>Windows without Cygwin: Download the <ulink url="http://www.zlatkovic.com/pub/libxml/">binary packages</ulink>
+ from Igor Zlatkovic. At the very least, you'll need iconv, zlib, libxml2 and libxslt.</listitem>
+ <listitem>Mac OS X with Fink: Get the <code>libxslt</code> package.</listitem>
+ <listitem>Mac OS X without Fink: <ulink url="http://www.zveno.com/open_source/libxml2xslt.html">Download the libxslt binaries</ulink></listitem>
+ <listitem>Any platform: <ulink
+ url="http://xmlsoft.org/XSLT/">libxslt source</ulink>.</listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem><simpara><command>doxygen</command>:</simpara> Available from <ulink url="http://www.doxygen.org">http://www.doxygen.org</ulink></listitem>
+ </itemizedlist>
+
+ <section id="boostbook.setup.autounix">
+ <title>Automatic setup for Unix-like systems</title>
+
+ <para>BoostBook provides a nearly-automatic setup script. Once
+ you have downloaded and
+ installed <command>xsltproc</command>, <command>doxygen</command>,
+ and (optionally) <command>java</command>, the setup script can
+ download the required DocBook stylesheets, DocBook DTD, and
+ (when Java is enabled) Apache FOP for PDF output. It will then
+ configure Boost.Build version 2 to build BoostBook
+ documentation.</para>
+
+ <para>The script requires: <command>sh</command>,
+ <command>curl</command> and <command>gunzip</command>.
+ To perform the installation, execute the
+ script <command>tools/boostbook/setup_boostbook.sh</command>
+ from a directory where you would like the resulting XSL, DTD,
+ and Apache FOP installations to occur. </para>
+ </section>
+
+ <section id="boostbook.setup.manual">
+ <title>Manual setup for all systems</title>
+
+ <para>This section describes how to manually configure Boost
+ Boost version 2 (BBv@) for BoostBook. If you can use the
+ automatic setup script, you should. All configuration will
+ happen in the BBv2 user configuration file,
+ <filename>user-config.jam</filename>. If you do not have a copy
+ of this file in your home directory, you should copy the one
+ that resides in <code>tools/build/v2</code> to your home
+ directory. Alternatively, you can edit
+ <filename>tools/build/v2/user-config.jam</filename> directly or
+ a site-wide <filename>site-config.jam</filename> file.</para>
+
+ <section id="boostbook.setup.xsltproc">
+ <title>Configuring <command>xsltproc</command></title>
+
+ <para>To configure <command>xsltproc</command> manually, you
+ will need to add a directive to
+ <filename>user-config.jam</filename> telling it where to find
+ <command>xsltproc</command>. If the program is in your path,
+ just add the following line to
+ <filename>user-config.jam</filename>:</para>
+
+<programlisting>using xsltproc ;</programlisting>
+
+ <para>If <command>xsltproc</command> is somewhere else, use
+ this directive, where <code>XSLTPROC</code> is the full
+ pathname to <command>xsltproc</command> (including
+ <command>xsltproc</command>):</para>
+
+<programlisting>using xsltproc : XSLTPROC ;</programlisting>
+ </section>
+
+ <section id="boostbook.setup.docbook">
+ <title>Configuring local DocBook XSL and DTD distributions</title>
+
+ <para>This section describes how to configure Boost.Build to
+ use local copies of the DocBook DTD and XSL stylesheets to
+ improve processing time. You will first need to download two
+ packages:
+
+ <itemizedlist>
+ <listitem><para>Norman Walsh's DocBook XSL stylesheets,
+ available at the <ulink
+ url="http://docbook.sourceforge.net">DocBook sourceforge
+ site</ulink>. Extract the DocBook XSL stylesheets to a
+ directory on your hard disk (which we'll refer to as the
+ <code>DOCBOOK_XSL_DIR</code>).</para>
+ </listitem>
+
+ <listitem><para>The DocBook DTD, available as a ZIP archive
+ at the <ulink
+ url="http://www.oasis-open.org/docbook/xml/4.2/">OASIS
+ DocBook site</ulink>. The package is called "DocBook XML
+ 4.2". Extract the DocBook DTD to a directory on your hard
+ disk (which we'll refer to as the
+ <code>DOCBOOK_DTD_DIR</code>). You will want to extract this
+ archive in a subdirectory!</para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>Add the following directive telling BBv2 where to find
+ the DocBook DTD and XSL stylesheets:</para>
+
+ <programlisting># BoostBook configuration
+using boostbook
+ : DOCBOOK_XSL_DIR
+ : DOCBOOK_DTD_DIR
+ ;</programlisting>
+
+ <para>Whenever you change this directive, you will need to
+ remove the <code>bin.v2</code> directory that BBv2 generates.
+ This is due to longstanding bug we are trying to fix.</para>
+
+ <para>At this point, you should be able to build HTML
+ documentation for libraries that do not require Doxygen. To
+ test this, change into the directory <filename
+ class="directory">$BOOST_ROOT/libs/function/doc</filename> and
+ run the command <code>bjam</code>: it should produce HTML
+ documentation for the Boost.Function library in the
+ <code>html</code> subdirectory.</para>
+ </section>
+
+ <section id="boostbook.setup.doxygen">
+ <title>Configuring Doxygen for Documentation Extraction</title>
+
+ <para>Doxygen is required to build the documentation for
+ several Boost libraries. You will need a recent version of
+ <ulink url="http://www.doxygen.org">Doxygen</ulink> (most of
+ the 1.3.x and 1.4.x versions will suffice). BBv2 by adding the
+ following directive to
+ <filename>user-config.jam</filename>:</para>
+
+ <programlisting>using doxygen : DOXYGEN ;</programlisting>
+
+ <para><filename>DOXYGEN</filename> should be replaced with the
+ name of the <command>doxygen</command> executable (with full
+ path name). If the right <command>doxygen</command> executable
+ can be found via the path, this parameter can be
+ omitted, e.g.</para>
+
+ <programlisting>using doxygen ;</programlisting>
+
+ <important>
+ <para>The relative order of declarations in
+ <filename>user-config.jam</filename> /
+ <filename>site-config.jam</filename> files is
+ significant. In particular, the <literal>using
+ doxygen</literal> line should come
+ <emphasis>after</emphasis> the <literal>using
+ boostbook</literal> declaration.
+ </para>
+ </important>
+ </section>
+
+ <section id="boostbook.setup.fop">
+ <title>Configuring Apache FOP</title>
+
+ <para>In order to generate PDF and PostScript output using
+ Apache FOP, you will need a <ulink
+ url="http://java.sun.com">Java interpreter</ulink> and <ulink
+ url="http://xml.apache.org/fop/download.html">Apache FOP</ulink>
+ (version 0.20.5 is best). Unpack Apache FOP to some
+ directory. The top level directory of the FOP tool should
+ contain a main script called <filename>fop.sh</filename> on Unix
+ and <filename>fop.bat</filename> on Windows. You need to specify
+ the location of that script and Java location to
+ Boost.Build. Add the following to your
+ <filename>user-config.jam</filename> or
+ <filename>site-config.jam</filename>:
+<programlisting>
+using fop : FOP_COMMAND
+ : JAVA_HOME
+ ;
+</programlisting> replacing
+ <code>FOP_COMMAND</code> with the full path to the FOP main script, and
+ replacing <code>JAVA_HOME</code> with the directory where Java is
+ installed. If the <envar>JAVA_HOME</envar> environment variable is
+ already set, you don't need to specify it above.
+ </para>
+
+ <para>
+ Proper generation of images in PDFs depends on the <ulink
+ url="http://java.sun.com/products/jimi/#">Jimi Image
+ Library</ulink>. To get FOP to use Jimi, extract the
+ <filename>JimiProClasses.zip</filename> file from the Jimi SDK
+ and rename it—if on Windows, to
+ <filename>jimi-1.0.jar</filename>, or if on *nix, to
+ <filename>JimiProClasses.jar</filename>—and place it in the
+ <filename>lib/</filename> subdirectory of your FOP
+ installation.
+ </para>
+
+ <para>To test PDF generation, switch to the directory <filename
+ class="directory">$BOOST_ROOT/libs/function/doc</filename> and
+ execute the command <command>bjam pdf</command>. In the
+ absence of any errors, Apache FOP will be executed to transform
+ the XSL:FO output of DocBook into a PDF file.</para>
+ </section>
+ </section>
+
+ <section id="boostbook.setup.running">
+ <title>Running BoostBook</title>
+
+ <para>Once BoostBook has been configured, we can build some
+ documentation. First, change to the directory
+ <code>$BOOST_ROOT/doc</code> and remove (or make writable) the
+ <code>.html</code> files in
+ <code>$BOOST_ROOT/doc/html</code>. Then, run <code>bjam</code>
+ to build HTML documentation. You should see several
+ warnings like these while DocBook documentation is being built
+ from BoostBook documentation:</para>
+
+ <programlisting>Cannot find function named 'checked_delete'
+Cannot find function named 'checked_array_delete'
+Cannot find function named 'next'</programlisting>
+
+ <para>These warnings are emitted when the Boost documentation
+ tools cannot find documentation for functions, methods, or classes
+ that are referenced in the source, and are not harmful in any
+ way. Once Boost.Jam has completed its execution, HTML
+ documentation for Boost will be available in
+ <code>$BOOST_ROOT/doc/html</code>. You can also create HTML
+ documentation in a single (large!) HTML file with the command line
+ <code>bjam onehtml</code>, or Unix man pages with the command
+ line <code>bjam man</code>. The complete list of output
+ formats is listed in <xref
+ linkend="boostbook.output.formats"/>. Several output formats can
+ be passed to a single invocation of <code>bjam</code>, e.g.,
+ <code>bjam html man docbook</code> would generate HTML
+ (multiple files), man pages, and DocBook documentation.</para>
+
+ <table id="boostbook.output.formats">
+ <title>BoostBook Output Formats</title>
+ <tgroup cols="2">
+ <thead>
+ <row><entry>Format</entry><entry>Description</entry></row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>html</entry>
+ <entry><simpara>HTML output (multiple files). This is the default</simpara></entry>
+ </row>
+ <row>
+ <entry>onehtml</entry>
+ <entry><simpara>HTML output in a single HTML file.</simpara></entry>
+ </row>
+ <row>
+ <entry>man</entry>
+ <entry><simpara>Unix man pages.</simpara></entry>
+ </row>
+ <row>
+ <entry>pdf</entry>
+ <entry><simpara>PDF. Requires <ulink url="http://xml.apache.org/fop/index.html">Apache FOP</ulink>.</simpara></entry>
+ </row>
+ <row>
+ <entry>ps</entry>
+ <entry><simpara>Postscript. Requires <ulink url="http://xml.apache.org/fop/index.html">Apache FOP</ulink>.</simpara></entry>
+ </row>
+ <row>
+ <entry>docbook</entry>
+ <entry><ulink url="http://www.docbook.org/">DocBook</ulink>.</entry>
+ </row>
+ <row>
+ <entry>fo</entry>
+ <entry><ulink url="http://www.w3.org/TR/xsl/">XSL Formatting Objects</ulink></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section id="boostbook.setup.troubleshooting">
+ <title>Troubleshooting</title>
+
+ <para>The Boost documentation tools are still in their early phase of
+ development, and some things don't work as seamlessly as we would like
+ them to, yet. In particular, error messages can be somewhat
+ uninformative at times. If you find yourself in the situation when
+ you have double checked everything, and yet things still don't work as
+ expected, consider helping the tools by deleting
+ <literal>bin.v2</literal> build directory.
+ </para>
+
+ </section>
+ </chapter>
+
+ <xi:include href="documenting.xml"/>
+ <xi:include href="together.xml"/>
+ <xi:include href="reference.xml"/>
+</part>
diff --git a/tools/boostbook/doc/documenting.xml b/tools/boostbook/doc/documenting.xml
new file mode 100644
index 0000000000..64b73a80f9
--- /dev/null
+++ b/tools/boostbook/doc/documenting.xml
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<chapter xmlns:xi="http://www.w3.org/2001/XInclude" id="boostbook.documenting"
+ last-revision="$Date: 2008-07-12 15:30:45 -0400 (Sat, 12 Jul 2008) $">
+ <title>Documenting libraries</title>
+
+ <para>BoostBook is an extension to <ulink
+ url="http://www.docbook.org">DocBook</ulink>, an XML format for
+ representing documentation. BoostBook inherits much of its
+ functionality and many elements from DocBook that are not
+ redocumented here. When writing BoostBook documentation, please
+ refer also to <ulink
+ url="http://docbook.org/tdg/en/index.html">DocBook: The Definitive
+ Guide</ulink>.</para>
+
+ <section id="boostbook.defining">
+ <title>Defining a BoostBook library</title>
+
+ <para>BoostBook library documentation is contained entirely within
+ a &lt;library&gt; XML element. To create a skeletal library, we
+ need to create a new XML document (call it <code>any.xml</code>)
+ that contains basic information about the library. The following
+ <link linkend="boostbook.documenting.skeletal">BoostBook XML
+ example</link> describes basic information about the <ulink
+ url="http://www.boost.org/libs/any/index.html">Boost.Any</ulink>
+ library:</para>
+
+ <example id="boostbook.documenting.skeletal">
+ <title>A Skeletal BoostBook Library</title>
+ <programlisting>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"&gt;
+&lt;library name="Any" dirname="any" xmlns:xi="http://www.w3.org/2001/XInclude"
+ id="any" last-revision="$Date: 2008-07-12 15:30:45 -0400 (Sat, 12 Jul 2008) $"&gt;
+ &lt;libraryinfo&gt;
+ &lt;author&gt;
+ &lt;firstname&gt;Kevlin&lt;/firstname&gt;
+ &lt;surname&gt;Henney&lt;/surname&gt;
+ &lt;/author&gt;
+ &lt;librarypurpose&gt;
+ Safe, generic container for single values of different value types
+ &lt;/librarypurpose&gt;
+ &lt;librarycategory name="category:data-structures"/&gt;
+ &lt;/libraryinfo&gt;
+&lt;/library&gt;
+</programlisting>
+ </example>
+
+ <para>The first three lines identify this document as a BoostBook
+ <ulink url="http://www.w3.org/XML/">XML</ulink> document. The
+ DOCTYPE line states that the document conforms to the BoostBook
+ DTD, and that the top-level element is a BoostBook
+ &lt;library&gt;.</para>
+
+ <para>The &lt;library&gt; element actually describes the aspects
+ of BoostBook library documentation. The attributes for the
+ &lt;library&gt; element are:</para>
+
+ <variablelist>
+ <title>Attributes for the &lt;library&gt; element</title>
+ <varlistentry>
+ <term><code>name</code></term>
+ <listitem>
+ <simpara>The full name of the library, e.g., "Any"</simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><code>dirname</code></term>
+ <listitem>
+ <simpara>The name of the directory, relative to
+ <code>boost/libs</code>, in which the library
+ resides. This name may be a relative path, such as
+ <code>math/octonion</code>, using "/" for the directory
+ separator.</simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><code>id</code></term>
+ <listitem>
+ <simpara>A short, unique name for the library. For libraries
+ with simple directory names (e.g., ones that do not contain
+ a "/"), this should be the same as the
+ <code>dirname</code>. This <code>id</code> will be used to
+ identify libraries and, for HTML output, will be used as the
+ base name for the HTML file in which the library's
+ documentation resides, so it should use only lowercase
+ alphanumeric characters and underscores.</simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><code>last-revision</code></term>
+ <listitem>
+ <simpara>Always set to <code>$Date: 2008-07-12 15:30:45 -0400 (Sat, 12 Jul 2008) $</code>, which is
+ expanded by CVS to include the date and time that the file
+ was last modified.</simpara>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>Inside the &lt;library&gt; element we have the
+ &lt;libraryinfo&gt; element, which gives information about the
+ library itself. It contains the author's name (there may be more
+ than one &lt;author&gt; element), followed by the purpose of the
+ library and the list of categorizations. The
+ &lt;librarypurpose&gt; element should always contain a very short
+ (single sentence) description of the library's purpose, and should
+ <emphasis>not</emphasis> terminate with a period.</para>
+
+ <para>The list of categories is specified by a set of
+ &lt;librarycategory&gt; elements. Each &lt;librarycategory&gt;
+ element has a <code>name</code> element that identifies one of the
+ categories. The actual list of categories is in the file
+ <filename>doc/src/boost.xml</filename>.
+ </para>
+
+ <para>At this point, we can apply the BoostBook XSL stylesheets to
+ <code>any.xml</code> (to DocBook) followed by a DocBook XSL
+ stylesheet to generate HTML output, as described in <xref
+ linkend="boostbook.getting.started"/>.</para>
+ </section>
+
+ <section>
+ <title>From HTML to BoostBook</title>
+
+ <para>Most library authors are comfortable with writing HTML
+ documentation. Writing <ulink
+ url="http://www.docbook.org">DocBook</ulink> documentation (and,
+ by extension, BoostBook documentation) is quite similar to writing
+ HTML, except that BoostBook uses different element names from HTML
+ (see <xref linkend="html.to.boostbook"/>) and BoostBook XML is a
+ much more rigid format than HTML.</para>
+
+ <para>One of the easiest ways to convert HTML documentation into
+ BoostBook documentation is to use <ulink
+ url="http://tidy.sourceforge.net/">HTML Tidy</ulink> to transform
+ your HTML into valid XHTML, which will make sure that all elements
+ are properly closed, then apply the transformations in <xref
+ linkend="html.to.boostbook"/> to the body of the XHTML
+ document. The following command uses HTML Tidy to transform HTML
+ into valid XHTML:</para>
+
+ <programlisting>
+ tidy -asxhtml input.html &gt; output.xhtml</programlisting>
+
+ <para>When converting documentation from HTML to BoostBook, note
+ that some redundant information that has to be manually maintained
+ in HTML is automatically generated in BoostBook: for instance, the
+ library categorizations, purpose, and author list described in
+ <xref linkend="boostbook.defining"/> are used both in the
+ documentation for the library and to build alphabetical and
+ categorized lists of known libraries; similarly, tables of
+ contents are built automatically from the titles of sections in
+ the BoostBook document.</para>
+
+ <table id="html.to.boostbook">
+ <title>Converting HTML elements to BoostBook</title>
+ <tgroup cols="2" align="left">
+ <thead>
+ <row>
+ <entry>HTML</entry>
+ <entry>BoostBook</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><simpara>&lt;h1&gt;, &lt;h2&gt;, etc.</simpara></entry>
+ <entry>
+<simpara>&lt;section&gt;, &lt;title&gt;; See <xref
+linkend="boostbook.sectioning"/></simpara>
+</entry>
+ </row>
+ <row>
+ <entry><simpara>&lt;i&gt;, &lt;em&gt;</simpara></entry>
+ <entry><simpara>&lt;emphasis&gt;</simpara></entry>
+ </row>
+ <row>
+ <entry><simpara>&lt;b&gt;</simpara></entry>
+ <entry><simpara>&lt;emphasis role="bold"&gt;</simpara></entry>
+ </row>
+ <row>
+ <entry><simpara>&lt;ol&gt;</simpara></entry>
+ <entry><simpara>&lt;orderedlist&gt;</simpara></entry>
+ </row>
+ <row>
+ <entry><simpara>&lt;ul&gt;</simpara></entry>
+ <entry><simpara>&lt;itemizedlist&gt;</simpara></entry>
+ </row>
+ <row>
+ <entry><simpara>&lt;li&gt;</simpara></entry>
+ <entry><simpara>&lt;listitem&gt;</simpara></entry>
+ </row>
+ <row>
+ <entry><simpara>&lt;pre&gt;</simpara></entry>
+ <entry><simpara>&lt;programlisting&gt;</simpara></entry>
+ </row>
+ <row>
+ <entry><simpara>&lt;code&gt;</simpara></entry>
+ <entry><simpara>&lt;computeroutput&gt;,&lt;code&gt;</simpara></entry>
+ </row>
+ <row>
+ <entry><simpara>&lt;p&gt;</simpara></entry>
+ <entry><simpara>&lt;para&gt;, &lt;simpara&gt;</simpara></entry>
+ </row>
+ <row>
+ <entry><simpara>&lt;a&gt;</simpara></entry>
+ <entry>
+<simpara>&lt;xref&gt;, &lt;link&gt;, &lt;ulink&gt;;, See <xref
+linkend="boostbook.linking"/></simpara></entry>
+ </row>
+ <row>
+ <entry><simpara>&lt;table&gt;, &lt;tr&gt;, &lt;th&gt;, &lt;td&gt;</simpara></entry>
+ <entry><simpara>&lt;table&gt;, &lt;informaltable&gt;, &lt;tgroup&gt;, &lt;thead&gt;, &lt;tfoot&gt;, &lt;tbody&gt;, &lt;row&gt;, &lt;entry&gt;, &lt;entrytbl&gt;; BoostBook tables are equivalent to DocBook tables, for which there is a good <ulink url="http://opensource.bureau-cornavin.com/crash-course/en/tables.html">tutorial here</ulink></simpara></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section id="boostbook.sectioning">
+ <title>Sectioning in BoostBook</title>
+ <para>"Sectioning" refers to organization of a document into separate sections, each with a title, some text, and possibly subsections. Each section is described in BoostBook via a &lt;section&gt; element. An introduction section may look like this:</para>
+ <programlisting>
+&lt;section id="any.intro"&gt;
+ &lt;title&gt;Introduction&lt;/title&gt;
+
+ &lt;para&gt;Introduction to a library...&lt;/para&gt;
+
+ &lt;section&gt;
+ &lt;title&gt;A Subsection&lt;/title&gt;
+ &lt;para&gt;Subsection information...&lt;/para&gt;
+ &lt;/section&gt;
+&lt;/section&gt;
+</programlisting>
+ <para>The &lt;section&gt; element contains all information that
+ should logically be grouped within that section. The title of the
+ section is placed within the &lt;title&gt; element, and any
+ paragraphs, programs, lists, tables, or subsections can occur
+ within the section. The <code>id</code> attribute of the
+ &lt;section&gt; element gives a unique ID to each section, so that
+ it may later be identified for linking. It is suggested that all
+ IDs start with the short name of a library followed by a period,
+ so that IDs do not conflict between libraries.</para>
+ </section>
+</chapter>
+
diff --git a/tools/boostbook/doc/reference.dtdxml b/tools/boostbook/doc/reference.dtdxml
new file mode 100644
index 0000000000..35267e8cdc
--- /dev/null
+++ b/tools/boostbook/doc/reference.dtdxml
@@ -0,0 +1,3480 @@
+<dtd version='1.0'
+ unexpanded='1'
+ title="?untitled?"
+ namecase-general="1"
+ namecase-entity="0"
+ xml="0"
+ system-id="boostbook.dtd"
+ public-id=""
+ declaration=""
+ created-by="DTDParse V2.00"
+ created-on="Wed Feb 18 23:39:45 2009"
+>
+<attpurpose name="id">A global identifier for this element</attpurpose>
+<attpurpose name="last-revision">Set to $Date: 2003/04/13 14:46:07 $ to keep "last revised" information in sync with CVS changes</attpurpose>
+<attpurpose name="xml:base">Implementation detail used by XIncludes</attpurpose>
+<attpurpose name="name">The name of the element being declared to referenced</attpurpose>
+<attpurpose name="filename">The name of the file associated with this element</attpurpose>
+<attpurpose name="specifiers">The specifiers for this function, e.g., <code>inline</code>, <code>static</code>, etc.</attpurpose>
+<attpurpose name="cv">cv-qualifiers for this method, e.g., <code>const volatile</code></attpurpose>
+<attpurpose name="pack">Set to '1' if the parameter is a parameter pack.</attpurpose>
+
+<entity name="boost.class.content"
+ type="param"
+>
+<text-expanded>template?, inherit*, purpose?, description?,
+ (static-constant|typedef|enum|
+ copy-assignment|constructor|destructor|method-group|
+ method|overloaded-method|data-member|class|class-specialization|struct|
+ struct-specialization|union|union-specialization|free-function-group|function|overloaded-function|access)*</text-expanded>
+<text>template?, inherit*, purpose?, description?,
+ (access|%boost.class.mix;)*</text>
+</entity>
+
+<entity name="boost.function.semantics"
+ type="param"
+>
+<text-expanded>purpose?, description?, requires?, effects?, postconditions?,
+ returns?, throws?, complexity?, notes?, rationale?</text-expanded>
+<text>purpose?, description?, requires?, effects?, postconditions?,
+ returns?, throws?, complexity?, notes?, rationale?</text>
+</entity>
+
+<entity name="parameter.module"
+ type="param"
+>
+<text-expanded>IGNORE</text-expanded>
+<text>IGNORE</text>
+</entity>
+
+<entity name="local.classname.attrib"
+ type="param"
+>
+<text-expanded>alt CDATA #IMPLIED</text-expanded>
+<text>alt CDATA #IMPLIED</text>
+</entity>
+
+<entity name="boost.namespace.mix"
+ type="param"
+>
+<text-expanded>class|class-specialization|struct|struct-specialization|
+ union|union-specialization|typedef|enum|
+ free-function-group|function|overloaded-function|
+ namespace</text-expanded>
+<text>class|class-specialization|struct|struct-specialization|
+ union|union-specialization|typedef|enum|
+ free-function-group|function|overloaded-function|
+ namespace</text>
+</entity>
+
+<entity name="boost.testsuite.test.content"
+ type="param"
+>
+<text-expanded>source*, lib*, requirement*, purpose, if-fails?</text-expanded>
+<text>source*, lib*, requirement*, purpose, if-fails?</text>
+</entity>
+
+<entity name="programlisting.module"
+ type="param"
+>
+<text-expanded>IGNORE</text-expanded>
+<text>IGNORE</text>
+</entity>
+
+<entity name="local.refentry.class"
+ type="param"
+>
+<text-expanded>|library-reference|testsuite</text-expanded>
+<text>|library-reference|testsuite</text>
+</entity>
+
+<entity name="boost.common.attrib"
+ type="param"
+>
+<text-expanded>xml:base CDATA #IMPLIED
+ last-revision CDATA #IMPLIED
+ id CDATA #IMPLIED</text-expanded>
+<text>%local.common.attrib;
+ id CDATA #IMPLIED</text>
+</entity>
+
+<entity name="boost.class.members"
+ type="param"
+>
+<text-expanded>static-constant|typedef|enum|
+ copy-assignment|constructor|destructor|method-group|
+ method|overloaded-method|data-member|class|class-specialization|struct|
+ struct-specialization|union|union-specialization</text-expanded>
+<text>static-constant|typedef|enum|
+ copy-assignment|constructor|destructor|method-group|
+ method|overloaded-method|data-member|class|class-specialization|struct|
+ struct-specialization|union|union-specialization</text>
+</entity>
+
+<entity name="boost.class.mix"
+ type="param"
+>
+<text-expanded>static-constant|typedef|enum|
+ copy-assignment|constructor|destructor|method-group|
+ method|overloaded-method|data-member|class|class-specialization|struct|
+ struct-specialization|union|union-specialization|free-function-group|function|overloaded-function</text-expanded>
+<text>%boost.class.members;|free-function-group|function|overloaded-function</text>
+</entity>
+
+<entity name="boost.testsuite.tests"
+ type="param"
+>
+<text-expanded>compile-test|link-test|run-test|
+ compile-fail-test|link-fail-test|run-fail-test</text-expanded>
+<text>compile-test|link-test|run-test|
+ compile-fail-test|link-fail-test|run-fail-test</text>
+</entity>
+
+<entity name="local.para.class"
+ type="param"
+>
+<text-expanded>|using-namespace|using-class|librarylist|librarycategorylist</text-expanded>
+<text>|using-namespace|using-class|librarylist|librarycategorylist</text>
+</entity>
+
+<entity name="DocBook"
+ type="param"
+ public="-//OASIS//DTD DocBook XML V4.2//EN"
+ system="http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+/>
+
+<entity name="local.title.char.mix"
+ type="param"
+>
+<text-expanded></text-expanded>
+<text></text>
+</entity>
+
+<entity name="local.methodname.attrib"
+ type="param"
+>
+<text-expanded>alt CDATA #IMPLIED</text-expanded>
+<text>alt CDATA #IMPLIED</text>
+</entity>
+
+<entity name="local.tech.char.class"
+ type="param"
+>
+<text-expanded>|functionname|libraryname|enumname|headername|macroname|code</text-expanded>
+<text>|functionname|libraryname|enumname|headername|macroname|code</text>
+</entity>
+
+<entity name="function.module"
+ type="param"
+>
+<text-expanded>IGNORE</text-expanded>
+<text>IGNORE</text>
+</entity>
+
+<entity name="boost.template.mix"
+ type="param"
+>
+<text-expanded>template-type-parameter|template-nontype-parameter|template-varargs</text-expanded>
+<text>template-type-parameter|template-nontype-parameter|template-varargs</text>
+</entity>
+
+<entity name="local.common.attrib"
+ type="param"
+>
+<text-expanded>xml:base CDATA #IMPLIED
+ last-revision CDATA #IMPLIED</text-expanded>
+<text>xml:base CDATA #IMPLIED
+ last-revision CDATA #IMPLIED</text>
+</entity>
+
+<entity name="type.module"
+ type="param"
+>
+<text-expanded>IGNORE</text-expanded>
+<text>IGNORE</text>
+</entity>
+
+<entity name="local.descobj.class"
+ type="param"
+>
+<text-expanded>|libraryinfo</text-expanded>
+<text>|libraryinfo</text>
+</entity>
+
+<entity name="boost.class-specialization.content"
+ type="param"
+>
+<text-expanded>template?, specialization?, inherit?, purpose?, description?,
+ (static-constant|typedef|enum|
+ copy-assignment|constructor|destructor|method-group|
+ method|overloaded-method|data-member|class|class-specialization|struct|
+ struct-specialization|union|union-specialization|free-function-group|function|overloaded-function|access)*</text-expanded>
+<text>template?, specialization?, inherit?, purpose?, description?,
+ (access|%boost.class.mix;)*</text>
+</entity>
+
+<entity name="library.content"
+ type="param"
+>
+<text-expanded>libraryinfo, (title, ((section|library-reference|testsuite))+)?</text-expanded>
+<text>libraryinfo, (title, ((section|library-reference|testsuite))+)?</text>
+</entity>
+
+<element name="class-specialization"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="specialization" occurrence="?"/>
+ <element-name name="inherit" occurrence="?"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <or-group occurrence="*">
+ <element-name name="access"/>
+ <element-name name="static-constant"/>
+ <element-name name="typedef"/>
+ <element-name name="enum"/>
+ <element-name name="copy-assignment"/>
+ <element-name name="constructor"/>
+ <element-name name="destructor"/>
+ <element-name name="method-group"/>
+ <element-name name="free-function-group"/>
+ <element-name name="function"/>
+ <element-name name="method"/>
+ <element-name name="overloaded-function"/>
+ <element-name name="overloaded-method"/>
+ <element-name name="data-member"/>
+ <element-name name="class"/>
+ <element-name name="class-specialization"/>
+ <element-name name="struct"/>
+ <element-name name="struct-specialization"/>
+ <element-name name="union"/>
+ <element-name name="union-specialization"/>
+ </or-group>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.class-specialization.content"/>
+ </sequence-group>
+</content-model>
+
+<purpose>A specialization (partial or full) of a class template</purpose>
+</element>
+
+<attlist name="class-specialization">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="link-test"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="source" occurrence="*"/>
+ <element-name name="lib" occurrence="*"/>
+ <element-name name="requirement" occurrence="*"/>
+ <element-name name="purpose"/>
+ <element-name name="if-fails" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.testsuite.test.content"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a test that should compile and link</purpose>
+</element>
+
+<attlist name="link-test">
+<attdecl>
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED</attdecl>
+<attribute name="filename"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="link-fail-test"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="source" occurrence="*"/>
+ <element-name name="lib" occurrence="*"/>
+ <element-name name="requirement" occurrence="*"/>
+ <element-name name="purpose"/>
+ <element-name name="if-fails" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.testsuite.test.content"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a test that should compile but fail to link</purpose>
+</element>
+
+<attlist name="link-fail-test">
+<attdecl>
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED</attdecl>
+<attribute name="filename"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="typedef"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="type"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="type"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a typedef</purpose>
+</element>
+
+<attlist name="typedef">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="static-constant"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="type"/>
+ <element-name name="default"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="type"/>
+ <element-name name="default"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a static constant, e.g., <code>const int foo = 5;</code>.</purpose>
+</element>
+
+<attlist name="static-constant">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="code"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>Mimics the <sgmltag>code</sgmltag> tag in HTML</purpose>
+<description>
+ <para>Text within a <sgmltag>code</sgmltag> tag is generally typeset
+ in a different, monospaced font so that it stands out as code. The
+ <sgmltag>code</sgmltag> tag in BoostBook is transformed directly
+ into the <sgmltag>computeroutput</sgmltag> tag in DocBook.</para>
+</description>
+</element>
+
+<attlist name="code">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="destructor"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <element-name name="requires" occurrence="?"/>
+ <element-name name="effects" occurrence="?"/>
+ <element-name name="postconditions" occurrence="?"/>
+ <element-name name="returns" occurrence="?"/>
+ <element-name name="throws" occurrence="?"/>
+ <element-name name="complexity" occurrence="?"/>
+ <element-name name="notes" occurrence="?"/>
+ <element-name name="rationale" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.function.semantics"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a destructor for the enclosing class</purpose>
+<description>
+ <para>General documentation on functions in BoostBook is provided in
+ the <link
+ linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</description>
+</element>
+
+<attlist name="destructor">
+<attdecl>
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="specifiers"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="template-type-parameter"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="default" occurrence="?"/>
+ <element-name name="purpose" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="default" occurrence="?"/>
+ <element-name name="purpose" occurrence="?"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a template type parameter</purpose>
+</element>
+
+<attlist name="template-type-parameter">
+<attdecl>
+ name CDATA #REQUIRED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="pack"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="description"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>Detailed description of a construct</purpose>
+<description>
+ <para>Although the context model for this element is
+ <code>ANY</code>, detailed descriptions should contain structured
+ DocBook elements that occur within sections, e.g., paragraphs
+ (<sgmltag>para</sgmltag>, <sgmltag>simpara</sgmltag>), lists
+ (<sgmltag>orderedlist</sgmltag>, <sgmltag>itemizedlist</sgmltag>),
+ tables (<sgmltag>informaltable</sgmltag>, <sgmltag>table</sgmltag>),
+ etc.</para>
+</description>
+</element>
+
+<attlist name="description">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="librarylist"
+ content-type="element">
+<content-model-expanded>
+ <empty/>
+</content-model-expanded>
+<content-model>
+ <empty/>
+</content-model>
+<purpose>Placeholder for an alphabetical list of libraries</purpose>
+<description>
+ <para>Developers aren't generally expected to use this element. Its existence is mainly as a placeholder in <filename>boost.xml</filename> for the alphabetical list of libraries.</para>
+</description>
+</element>
+
+<attlist name="librarylist">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="library-reference"
+ content-type="element">
+<!-- DPG brazenly modified the content model here, because "ANY" is
+ not a good idea and merging this document with another is, to say the
+ least, a PITA. -->
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="title" occurrence="?"/>
+ <element-name name="section" occurrence="*"/>
+ <or-group occurrence="*">
+ <element-name name="header"/>
+ <element-name name="library-reference"/>
+ </or-group>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="title" occurrence="?"/>
+ <element-name name="section" occurrence="*"/>
+ <or-group>
+ <element-name name="header" occurrence="*"/>
+ <element-name name="library-reference" occurrence="*"/>
+ </or-group>
+ </sequence-group>
+</content-model>
+<purpose>Declares the reference material for a library</purpose>
+<description>
+ <para>Reference documentation for a library is contained with a
+ &lt;library-reference&gt; element. The &lt;library-reference&gt;
+ element has no attributes, and contains as children only
+ &lt;header&gt; elements.</para>
+
+ <para>The &lt;header&gt; element defines a C++ header file. Within
+ each C++ header file lie the definitions of C++ constructs to be
+ documented. The <code>name</code> attribute of the &lt;header&gt;
+ element gives the name of the header, as one would specify when
+ including the header. For instance, the &lt;library-reference&gt;
+ for the <libraryname>Any</libraryname> library may look like
+ this:</para>
+
+ <programlisting>&lt;library-reference&gt;
+ &lt;header name="boost/any.hpp"&gt;
+ &lt;!-- C++ constructs in this header --&gt;
+ &lt;/header&gt;
+&lt;/library-reference&gt;</programlisting>
+
+ <para>If the <libraryname>Any</libraryname> library contained
+ multiple headers, we would list them all as children of the
+ &lt;library-reference&gt; element.</para>
+
+ <para><sgmltag>library-reference</sgmltag> elements can be nested,
+ so that reference material can be divided into separate sections
+ that each contain different headers.</para>
+</description>
+</element>
+
+<attlist name="library-reference">
+<attdecl>
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="boostbook"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="title"/>
+ <or-group occurrence="*">
+ <element-name name="chapter"/>
+ <element-name name="library"/>
+ </or-group>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="title"/>
+ <or-group occurrence="*">
+ <element-name name="chapter"/>
+ <element-name name="library"/>
+ </or-group>
+ </sequence-group>
+</content-model>
+<purpose>Defines a BoostBook book</purpose>
+<description>
+ <simpara>This element is the topmost level defined by
+ <filename>boost.xml</filename> for all Boost documentation. It will
+ not generally be used by developers.</simpara>
+</description>
+</element>
+
+<attlist name="boostbook">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="union"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="inherit" occurrence="*"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <or-group occurrence="*">
+ <element-name name="access"/>
+ <element-name name="static-constant"/>
+ <element-name name="typedef"/>
+ <element-name name="enum"/>
+ <element-name name="copy-assignment"/>
+ <element-name name="constructor"/>
+ <element-name name="destructor"/>
+ <element-name name="method-group"/>
+ <element-name name="free-function-group"/>
+ <element-name name="function"/>
+ <element-name name="method"/>
+ <element-name name="overloaded-function"/>
+ <element-name name="overloaded-method"/>
+ <element-name name="data-member"/>
+ <element-name name="class"/>
+ <element-name name="class-specialization"/>
+ <element-name name="struct"/>
+ <element-name name="struct-specialization"/>
+ <element-name name="union"/>
+ <element-name name="union-specialization"/>
+ </or-group>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.class.content"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a C++ union or union template</purpose>
+</element>
+
+<attlist name="union">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="inherit"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="type"/>
+ <element-name name="purpose" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="type"/>
+ <element-name name="purpose" occurrence="?"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a base class of the enclosing class or struct</purpose>
+
+<description>
+ <para>This element contains the type of the class inherited.</para>
+</description>
+</element>
+
+<attlist name="inherit">
+<attdecl>
+ access CDATA #IMPLIED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="access"
+ type="#IMPLIED"
+ value="CDATA"
+ default="">
+ <purpose>The access specifier ("public", "private", or "protected") of the inheritance.</purpose>
+</attribute>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="pack"
+ type="#IMPLIED"
+ value="CDATA"
+ default="">
+ <purpose>Set to '1' if this is a pack exapansion.</purpose>
+</attribute>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="template-varargs"
+ content-type="element">
+<content-model-expanded>
+ <empty/>
+</content-model-expanded>
+<content-model>
+ <empty/>
+</content-model>
+<purpose>Declares a variable-length list of template parameters</purpose>
+
+<description>
+ <para>Variable-length template parameter lists are not allowed in
+ C++, but because they are sometimes needed in documentation they are
+ allowed in BoostBook. This element generally expands to "..." and
+ can be used anywhere any other template parameter can be
+ used.</para>
+</description>
+</element>
+
+<attlist name="template-varargs">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="source"
+ content-type="mixed">
+<content-model-expanded>
+ <or-group occurrence="*">
+ <pcdata/>
+ <element-name name="snippet"/>
+ </or-group>
+</content-model-expanded>
+<content-model>
+ <or-group occurrence="*">
+ <pcdata/>
+ <element-name name="snippet"/>
+ </or-group>
+</content-model>
+<purpose>Defines source code for a test</purpose>
+
+<description>
+ <para>This element will contain the source code for a testcase that
+ will be generated from the documentation. To reduce the amount of escaping in the text, it is recommended to use CDATA sections, which look like this:
+
+ <programlisting>&lt;![CDATA[
+&lt;your program text here: no escaping needed!&gt;
+]]&gt;</programlisting>
+ </para>
+
+ <para>In addition to CDATA sections, code snippets can be pulled in
+ from <sgmltag>programlisting</sgmltag> elements using the <link
+ linkend="boostbook.dtd.snippet"><sgmltag>snippet</sgmltag></link>
+ element.</para>
+</description>
+
+</element>
+
+<element name="function"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="type"/>
+ <element-name name="parameter" occurrence="*"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <element-name name="requires" occurrence="?"/>
+ <element-name name="effects" occurrence="?"/>
+ <element-name name="postconditions" occurrence="?"/>
+ <element-name name="returns" occurrence="?"/>
+ <element-name name="throws" occurrence="?"/>
+ <element-name name="complexity" occurrence="?"/>
+ <element-name name="notes" occurrence="?"/>
+ <element-name name="rationale" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="type"/>
+ <element-name name="parameter" occurrence="*"/>
+ <parament-name name="boost.function.semantics"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a function</purpose>
+<description>
+ <para>BoostBook functions are documented by specifying the
+ function's interface (e.g., its C++ signature) and its
+ behavior. Constructors, destructors, member functions, and free
+ functions all use the same documentation method, although the
+ top-level tags differ.</para>
+
+ <para>The behavior of functions in BoostBook is documenting using a
+ style similar to that of the C++ standard, with clauses describing
+ the requirements, effects, postconditions, exception behavior, and
+ return values of functions.</para>
+
+ <para>The following example illustrates some constructors and a
+ destructor for <classname>boost::any</classname>. Note that one of
+ the constructors takes a single parameter whose name is "other" and
+ whose type, <code>const any&amp;</code> is contained in the
+ &lt;paramtype&gt; element; any number of parameters may be specified
+ in this way.</para>
+
+ <programlisting>&lt;class name="any"&gt;
+ &lt;constructor&gt;
+ &lt;postconditions&gt;&lt;para&gt;&lt;this-&gt;empty()&gt;&lt;/para&gt;&lt;/postconditions&gt;
+ &lt;/constructor&gt;
+
+ &lt;constructor&gt;
+ &lt;parameter name="other"&gt;
+ &lt;paramtype&gt;const &lt;classname&gt;any&lt;/classname&gt;&amp;amp;&lt;/paramtype&gt;
+ &lt;/parameter&gt;
+
+ &lt;effects&gt;
+ &lt;simpara&gt; Copy constructor that copies
+ content of &lt;code&gt;other&lt;/code&gt; into the new instance,
+ so that any content is equivalent in both type and value to the
+ content of &lt;code&gt;other&lt;/code&gt;, or empty if
+ &lt;code&gt;other&lt;/code&gt; is
+ empty.
+ &lt;/simpara&gt;
+ &lt;/effects&gt;
+
+ &lt;throws&gt;
+ &lt;simpara&gt;May fail with a
+ &lt;classname&gt;std::bad_alloc&lt;/classname&gt; exception or any
+ exceptions arising from the copy constructor of the
+ contained type.
+ &lt;/simpara&gt;
+ &lt;/throws&gt;
+ &lt;/constructor&gt;
+
+ &lt;destructor&gt;
+ &lt;effects&gt;&lt;simpara&gt;Releases any and all resources used in
+ management of instance.&lt;/simpara&gt;&lt;/effects&gt;
+
+ &lt;throws&gt;&lt;simpara&gt;Nothing.&lt;/simpara&gt;&lt;/throws&gt;
+ &lt;/destructor&gt;
+&lt;/class&gt;</programlisting>
+</description>
+</element>
+
+<attlist name="function">
+<attdecl>
+ name CDATA #REQUIRED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="specifiers"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="macroname"
+ content-type="mixed">
+<content-model-expanded>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model>
+<purpose>References a macro with the given name</purpose>
+</element>
+
+<attlist name="macroname">
+<attdecl>
+ alt CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="alt"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="postconditions"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>Conditions that must hold after the function returns</purpose>
+</element>
+
+<attlist name="postconditions">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="compile-test"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="source" occurrence="*"/>
+ <element-name name="lib" occurrence="*"/>
+ <element-name name="requirement" occurrence="*"/>
+ <element-name name="purpose"/>
+ <element-name name="if-fails" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.testsuite.test.content"/>
+ </sequence-group>
+</content-model>
+<purpose>A testcase that should compile correctly</purpose>
+</element>
+
+<attlist name="compile-test">
+<attdecl>
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED</attdecl>
+<attribute name="filename"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="method"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="type"/>
+ <element-name name="parameter" occurrence="*"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <element-name name="requires" occurrence="?"/>
+ <element-name name="effects" occurrence="?"/>
+ <element-name name="postconditions" occurrence="?"/>
+ <element-name name="returns" occurrence="?"/>
+ <element-name name="throws" occurrence="?"/>
+ <element-name name="complexity" occurrence="?"/>
+ <element-name name="notes" occurrence="?"/>
+ <element-name name="rationale" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="type"/>
+ <element-name name="parameter" occurrence="*"/>
+ <parament-name name="boost.function.semantics"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a method, i.e., a member function</purpose>
+<description>
+ <para>General documentation on functions in BoostBook is provided in
+ the <link
+ linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</description>
+</element>
+
+<attlist name="method">
+<attdecl>
+ name CDATA #REQUIRED
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="cv"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="specifiers"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="snippet"
+ content-type="element">
+<content-model-expanded>
+ <empty/>
+</content-model-expanded>
+<content-model>
+ <empty/>
+</content-model>
+<purpose>Pulls in a code snippet from a <sgmltag>programlisting</sgmltag> element</purpose>
+</element>
+
+<attlist name="snippet">
+<attdecl>
+ name CDATA #REQUIRED</attdecl>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default="">
+ <purpose>The name of the <sgmltag>programlisting</sgmltag> element to insert</purpose>
+</attribute>
+</attlist>
+
+<element name="constructor"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="parameter" occurrence="*"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <element-name name="requires" occurrence="?"/>
+ <element-name name="effects" occurrence="?"/>
+ <element-name name="postconditions" occurrence="?"/>
+ <element-name name="returns" occurrence="?"/>
+ <element-name name="throws" occurrence="?"/>
+ <element-name name="complexity" occurrence="?"/>
+ <element-name name="notes" occurrence="?"/>
+ <element-name name="rationale" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="parameter" occurrence="*"/>
+ <parament-name name="boost.function.semantics"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a constructor of the enclosing class</purpose>
+<description>
+ <para>General documentation on functions in BoostBook is provided in
+ the <link
+ linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</description>
+</element>
+
+<attlist name="constructor">
+<attdecl>
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="specifiers"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="namespace"
+ content-type="element">
+<content-model-expanded>
+ <or-group occurrence="*">
+ <element-name name="class"/>
+ <element-name name="class-specialization"/>
+ <element-name name="struct"/>
+ <element-name name="struct-specialization"/>
+ <element-name name="union"/>
+ <element-name name="union-specialization"/>
+ <element-name name="typedef"/>
+ <element-name name="enum"/>
+ <element-name name="free-function-group"/>
+ <element-name name="function"/>
+ <element-name name="overloaded-function"/>
+ <element-name name="namespace"/>
+ </or-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group occurrence="*">
+ <parament-name name="boost.namespace.mix"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a namespace</purpose>
+
+<description>
+ <para>BoostBook namespaces are declared via the &lt;namespace&gt;
+ element. As in C++, namespaces can be nested and contain other C++
+ constructs, such as classes or functions. The <code>name</code>
+ attribute of a &lt;namespace&gt; element gives the namespace name
+ (e.g., "boost"). The <libraryname>Any</libraryname> library is
+ defined entirely within namespace boost by:</para>
+
+ <programlisting>&lt;library-reference&gt;
+ &lt;header name="boost/any.hpp"&gt;
+ &lt;namespace name="boost"&gt;
+ &lt;!-- C++ constructs in the boost namespace --&gt;
+ &lt;/namespace&gt;
+ &lt;/header&gt;
+&lt;/library-reference&gt;</programlisting>
+</description>
+</element>
+
+<attlist name="namespace">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="if-fails"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>What it means when a testcase fails</purpose>
+<description>
+ <para>
+ Describes to the user the effect a certain failing testcase will
+ have on the usefulness of a library. This field is useful in cases
+ where a failed testcase does not mean that the library won't be
+ useful, but may mean that certain library features will not be
+ available.
+ </para>
+</description>
+</element>
+
+<element name="headername"
+ content-type="mixed">
+<content-model-expanded>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model>
+<purpose>References a C++ header with the given name</purpose>
+</element>
+
+<attlist name="headername">
+<attdecl>
+ alt CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="alt"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="free-function-group"
+ content-type="element">
+<content-model-expanded>
+ <or-group occurrence="*">
+ <element-name name="function"/>
+ <element-name name="overloaded-function"/>
+ </or-group>
+</content-model-expanded>
+<content-model>
+ <or-group occurrence="*">
+ <element-name name="function"/>
+ <element-name name="overloaded-function"/>
+ </or-group>
+</content-model>
+<purpose>A set of functions that are grouped together under one name</purpose>
+</element>
+
+<attlist name="free-function-group">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="functionname"
+ content-type="mixed">
+<content-model-expanded>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model>
+<purpose>References a function with the given name</purpose>
+<description>
+ <para>If a function (or overloaded function) with the given,
+ possibly-qualified name is found, this generates a link to that
+ function. Lookups obey currently-active <link
+ linkend="boostbook.dtd.using-class"><sgmltag>using-class</sgmltag></link>
+ and <link
+ linkend="boostbook.dtd.using-namespace"><sgmltag>using-namespace</sgmltag></link>
+ directives to aid in the search, along with searching within the
+ current scope.</para>
+</description>
+</element>
+
+<attlist name="functionname">
+<attdecl>
+ alt CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="alt"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="librarycategory"
+ content-type="mixed">
+<content-model-expanded>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model>
+<purpose>Declares that the enclosing library is in this category</purpose>
+</element>
+
+<attlist name="librarycategory">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="notes"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>Non-normative notes about a function's semantics</purpose>
+</element>
+
+<attlist name="notes">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="data-member"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="type"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="type"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a data member of a class</purpose>
+</element>
+
+<attlist name="data-member">
+<attdecl>
+ name CDATA #REQUIRED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="specifiers"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="specialization"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group occurrence="*">
+ <element-name name="template-arg"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group occurrence="*">
+ <element-name name="template-arg"/>
+ </sequence-group>
+</content-model>
+<purpose>Defines the specialization arguments for a class specialization</purpose>
+</element>
+
+<attlist name="specialization">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="union-specialization"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="specialization" occurrence="?"/>
+ <element-name name="inherit" occurrence="?"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <or-group occurrence="*">
+ <element-name name="access"/>
+ <element-name name="static-constant"/>
+ <element-name name="typedef"/>
+ <element-name name="enum"/>
+ <element-name name="copy-assignment"/>
+ <element-name name="constructor"/>
+ <element-name name="destructor"/>
+ <element-name name="method-group"/>
+ <element-name name="free-function-group"/>
+ <element-name name="function"/>
+ <element-name name="method"/>
+ <element-name name="overloaded-function"/>
+ <element-name name="overloaded-method"/>
+ <element-name name="data-member"/>
+ <element-name name="class"/>
+ <element-name name="class-specialization"/>
+ <element-name name="struct"/>
+ <element-name name="struct-specialization"/>
+ <element-name name="union"/>
+ <element-name name="union-specialization"/>
+ </or-group>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.class-specialization.content"/>
+ </sequence-group>
+</content-model>
+<purpose>A specialization (full or partial) of a union template</purpose>
+</element>
+
+<attlist name="union-specialization">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="throws"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>Description of the exceptions thrown by a function</purpose>
+</element>
+
+<attlist name="throws">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="template-arg"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>A template argument in a specialization</purpose>
+</element>
+
+<attlist name="template-arg">
+<attdecl>
+ pack CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="pack"
+ type="#IMPLIED"
+ value="CDATA"
+ default="">
+ <purpose>Set to '1' if this is a pack exapansion.</purpose>
+</attribute>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="globalname"
+ content-type="mixed">
+<content-model-expanded>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model>
+<purpose>References a global with the given name</purpose>
+</element>
+
+<attlist name="globalname">
+<attdecl>
+ alt CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="alt"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="method-group"
+ content-type="element">
+<content-model-expanded>
+ <or-group occurrence="*">
+ <element-name name="method"/>
+ <element-name name="overloaded-method"/>
+ </or-group>
+</content-model-expanded>
+<content-model>
+ <or-group occurrence="*">
+ <element-name name="method"/>
+ <element-name name="overloaded-method"/>
+ </or-group>
+</content-model>
+<purpose>A set of methods that are grouped together under one name</purpose>
+</element>
+
+<attlist name="method-group">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="requirement"
+ content-type="mixed">
+<content-model-expanded>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model>
+<purpose>A requirement/property in the Jamfile for a testcase</purpose>
+<description>
+ <para>A requirement is part of the dependencies of a target in a
+ Jamfile. The <code>name</code> attribute of a requirement element
+ gives the name of the Boost.Build feature and the content of the
+ requirement gives the value of that feature. A requirement such as
+ <code>&lt;includes&gt;foo.hpp</code> would be encoded as
+ <code>&lt;requirement
+ name="includes"&gt;foo.hpp&lt;/requirement&gt;</code>.</para>
+</description>
+</element>
+
+<attlist name="requirement">
+<attdecl>
+ name CDATA #REQUIRED</attdecl>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="precondition"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>Conditions that must be met prior to executing a function</purpose>
+</element>
+
+<attlist name="precondition">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="paramtype"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>The type of a function parameter</purpose>
+</element>
+
+<attlist name="paramtype">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="using-class"
+ content-type="element">
+<content-model-expanded>
+ <empty/>
+</content-model-expanded>
+<content-model>
+ <empty/>
+</content-model>
+<purpose>Injects the method and function names of a class into the local scope</purpose>
+</element>
+
+<attlist name="using-class">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="run-test"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="source" occurrence="*"/>
+ <element-name name="lib" occurrence="*"/>
+ <element-name name="requirement" occurrence="*"/>
+ <element-name name="purpose"/>
+ <element-name name="if-fails" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.testsuite.test.content"/>
+ </sequence-group>
+</content-model>
+<purpose>A testcase that should compile, link, and execute</purpose>
+</element>
+
+<attlist name="run-test">
+<attdecl>
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED</attdecl>
+<attribute name="filename"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="librarypurpose"
+ content-type="mixed">
+<content-model-expanded>
+ <or-group occurrence="*">
+ <pcdata/>
+ <element-name name="code"/>
+ <element-name name="ulink"/>
+ <element-name name="functionname"/>
+ <element-name name="methodname"/>
+ <element-name name="classname"/>
+ <element-name name="macroname"/>
+ <element-name name="headername"/>
+ <element-name name="enumname"/>
+ <element-name name="globalname"/>
+ </or-group>
+</content-model-expanded>
+<content-model>
+ <or-group occurrence="*">
+ <pcdata/>
+ <element-name name="code"/>
+ <element-name name="ulink"/>
+ <element-name name="functionname"/>
+ <element-name name="methodname"/>
+ <element-name name="classname"/>
+ <element-name name="macroname"/>
+ <element-name name="headername"/>
+ <element-name name="enumname"/>
+ <element-name name="globalname"/>
+ </or-group>
+</content-model>
+<purpose>Describes in one short sentence or phrase the purpose of a library</purpose>
+</element>
+
+<attlist name="librarypurpose">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="copy-assignment"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="type" occurrence="?"/>
+ <element-name name="parameter" occurrence="*"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <element-name name="requires" occurrence="?"/>
+ <element-name name="effects" occurrence="?"/>
+ <element-name name="postconditions" occurrence="?"/>
+ <element-name name="returns" occurrence="?"/>
+ <element-name name="throws" occurrence="?"/>
+ <element-name name="complexity" occurrence="?"/>
+ <element-name name="notes" occurrence="?"/>
+ <element-name name="rationale" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="type" occurrence="?"/>
+ <element-name name="parameter" occurrence="*"/>
+ <parament-name name="boost.function.semantics"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a copy-assignment operator</purpose>
+<description>
+ <para>The return type of the copy-assignment operator does not need
+ to be specified. If left unspecified, it will default to an
+ unqualified reference to the enclosing class type.</para>
+
+ <para>General documentation on functions in BoostBook is provided in
+ the <link
+ linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</description>
+</element>
+
+<attlist name="copy-assignment">
+<attdecl>
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="cv"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="specifiers"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="run-fail-test"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="source" occurrence="*"/>
+ <element-name name="lib" occurrence="*"/>
+ <element-name name="requirement" occurrence="*"/>
+ <element-name name="purpose"/>
+ <element-name name="if-fails" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.testsuite.test.content"/>
+ </sequence-group>
+</content-model>
+<purpose>A testcase that should compile and link, but fail on execution</purpose>
+</element>
+
+<attlist name="run-fail-test">
+<attdecl>
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED</attdecl>
+<attribute name="filename"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="template"
+ content-type="element">
+<content-model-expanded>
+ <or-group occurrence="*">
+ <element-name name="template-type-parameter"/>
+ <element-name name="template-nontype-parameter"/>
+ <element-name name="template-varargs"/>
+ </or-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group occurrence="*">
+ <parament-name name="boost.template.mix"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares the template parameters of a class or function</purpose>
+</element>
+
+<attlist name="template">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="compile-fail-test"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="source" occurrence="*"/>
+ <element-name name="lib" occurrence="*"/>
+ <element-name name="requirement" occurrence="*"/>
+ <element-name name="purpose"/>
+ <element-name name="if-fails" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.testsuite.test.content"/>
+ </sequence-group>
+</content-model>
+<purpose>A testcase that should fail to compile</purpose>
+</element>
+
+<attlist name="compile-fail-test">
+<attdecl>
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED</attdecl>
+<attribute name="filename"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="returns"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>Description of the return value of a function</purpose>
+</element>
+
+<attlist name="returns">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="default"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>The default value of a function or template parameter</purpose>
+</element>
+
+<attlist name="default">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="parameter"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="paramtype"/>
+ <element-name name="default" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="paramtype"/>
+ <element-name name="default" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model>
+<purpose>A function parameter</purpose>
+</element>
+
+<attlist name="parameter">
+<attdecl>
+ name CDATA #IMPLIED
+ pack CDATA #IMPLIED</attdecl>
+<attribute name="name"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="pack"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="signature"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="type"/>
+ <element-name name="parameter" occurrence="*"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="type"/>
+ <element-name name="parameter" occurrence="*"/>
+ </sequence-group>
+</content-model>
+<purpose>One signature of an overloaded function or method</purpose>
+<description>
+ <para>
+ A signature refers to one declaration of an overloaded function or
+ method. The signature itself has no name, because the name of the
+ overloaded function or method is used. An overloaded function or
+ method will have several signatures that will generally be typeset
+ together.
+ </para>
+</description>
+</element>
+
+<attlist name="signature">
+<attdecl>
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="cv"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="specifiers"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="overloaded-function"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="signature" occurrence="*"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <element-name name="requires" occurrence="?"/>
+ <element-name name="effects" occurrence="?"/>
+ <element-name name="postconditions" occurrence="?"/>
+ <element-name name="returns" occurrence="?"/>
+ <element-name name="throws" occurrence="?"/>
+ <element-name name="complexity" occurrence="?"/>
+ <element-name name="notes" occurrence="?"/>
+ <element-name name="rationale" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="signature" occurrence="*"/>
+ <parament-name name="boost.function.semantics"/>
+ </sequence-group>
+</content-model>
+<purpose>An overloaded function</purpose>
+<description>
+ <para>General documentation on functions in BoostBook is provided in
+ the <link
+ linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</description>
+</element>
+
+<attlist name="overloaded-function">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="access"
+ content-type="element">
+<content-model-expanded>
+ <or-group occurrence="+">
+ <element-name name="static-constant"/>
+ <element-name name="typedef"/>
+ <element-name name="enum"/>
+ <element-name name="copy-assignment"/>
+ <element-name name="constructor"/>
+ <element-name name="destructor"/>
+ <element-name name="method-group"/>
+ <element-name name="method"/>
+ <element-name name="overloaded-method"/>
+ <element-name name="data-member"/>
+ <element-name name="class"/>
+ <element-name name="class-specialization"/>
+ <element-name name="struct"/>
+ <element-name name="struct-specialization"/>
+ <element-name name="union"/>
+ <element-name name="union-specialization"/>
+ </or-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group occurrence="+">
+ <parament-name name="boost.class.members"/>
+ </sequence-group>
+</content-model>
+ <purpose>Declares an access specification for class members</purpose>
+
+ <description>
+ <para>The access specifications of class members (public, private, or protected) may be determined by enclosing them in an &lt;access&gt; element.</para>
+ </description>
+</element>
+
+<attlist name="access">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default="">
+ <purpose>The name of the access specification, e.g. "public", "private", or "protected".</purpose>
+</attribute>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="class"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="inherit" occurrence="*"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <or-group occurrence="*">
+ <element-name name="access"/>
+ <element-name name="static-constant"/>
+ <element-name name="typedef"/>
+ <element-name name="enum"/>
+ <element-name name="copy-assignment"/>
+ <element-name name="constructor"/>
+ <element-name name="destructor"/>
+ <element-name name="method-group"/>
+ <element-name name="free-function-group"/>
+ <element-name name="function"/>
+ <element-name name="method"/>
+ <element-name name="overloaded-function"/>
+ <element-name name="overloaded-method"/>
+ <element-name name="data-member"/>
+ <element-name name="class"/>
+ <element-name name="class-specialization"/>
+ <element-name name="struct"/>
+ <element-name name="struct-specialization"/>
+ <element-name name="union"/>
+ <element-name name="union-specialization"/>
+ </or-group>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.class.content"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a class or class template</purpose>
+
+<description>
+ <para>C++ classes and class templates are described via the
+ &lt;class&gt; element. Each class has a name (e.g., "any") given by
+ the <code>name</code> attribute, a purpose given by the
+ &lt;purpose&gt; element, documentation, and a set of types,
+ functions, base classes, and data members. Here is a minimal
+ definition of the <classname>boost::any</classname> class:</para>
+
+ <programlisting>&lt;namespace name="boost"&gt;
+ &lt;class name="any"&gt;
+ &lt;purpose&gt;
+ A class whose instances can hold instances of any type that satisfies
+ ValueType requirements.
+ &lt;/purpose&gt;
+ &lt;/class&gt;
+&lt;/namespace&gt;</programlisting>
+
+ <para>Additional class documentation can be contained in a
+ <sgmltag>description</sgmltag> element following the &lt;purpose&gt;
+ element. This documentation will be typeset prior to documentation
+ for specific elements in the class (e.g., constructors or
+ methods).</para>
+
+ <para>Class inheritance is described via the &lt;inherit&gt;
+ element. The &lt;inherit&gt; element requires an <code>access</code>
+ attribute which must be one of <emphasis>public</emphasis>,
+ <emphasis>protected</emphasis>, or <emphasis>private</emphasis>. The
+ content of the &lt;inherited&gt; element in C++ code that names the
+ class inherited, and may contain markup to link to the class. The
+ following description of the class
+ <classname>boost::bad_any_cast</classname> describes public
+ inheritance from the class <classname>std::bad_cast</classname>. It
+ also defines the &lt;purpose&gt; element, which contains a short
+ description of the use of the class.</para>
+
+ <programlisting>&lt;class name="bad_any_cast"&gt;
+ &lt;inherit access="public"&gt;&lt;classname&gt;std::bad_cast&lt;/classname&gt;&lt;/inherit&gt;
+ &lt;purpose&gt;&lt;para&gt;The exception thrown in the event of a failed
+ &lt;functionname&gt;any_cast&lt;/functionname&gt; of an
+ &lt;classname&gt;any&lt;/classname&gt; value.&lt;/para&gt;&lt;/purpose&gt;
+&lt;/class&gt;</programlisting>
+
+ <para>Class templates are defined by &lt;class&gt; elements with a
+ &lt;template&gt; child element at the beginning.</para>
+</description>
+</element>
+
+<attlist name="class">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="librarycategorydef"
+ content-type="mixed">
+<content-model-expanded>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model>
+<purpose>Defines a new library category</purpose>
+<description>
+ <para>All library category definitions should be in <filename>doc/src/boost.xml</filename>, and the names of categories must be prefixed with "<code>category:</code>".</para>
+</description>
+</element>
+
+<attlist name="librarycategorydef">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="type"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>The type of an element or return type of a function</purpose>
+</element>
+
+<attlist name="type">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="enumvalue"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="default" occurrence="?"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="default" occurrence="?"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model>
+<purpose>A single value of an enumeration</purpose>
+</element>
+
+<attlist name="enumvalue">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="overloaded-method"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="signature" occurrence="*"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <element-name name="requires" occurrence="?"/>
+ <element-name name="effects" occurrence="?"/>
+ <element-name name="postconditions" occurrence="?"/>
+ <element-name name="returns" occurrence="?"/>
+ <element-name name="throws" occurrence="?"/>
+ <element-name name="complexity" occurrence="?"/>
+ <element-name name="notes" occurrence="?"/>
+ <element-name name="rationale" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="signature" occurrence="*"/>
+ <parament-name name="boost.function.semantics"/>
+ </sequence-group>
+</content-model>
+<purpose>An overloaded method</purpose>
+<description>
+ <para>General documentation on functions in BoostBook is provided in
+ the <link
+ linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</description>
+</element>
+
+<attlist name="overloaded-method">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="programlisting"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>A sample of program code</purpose>
+</element>
+
+<attlist name="programlisting">
+<attdecl>
+ name CDATA #IMPLIED</attdecl>
+<attribute name="name"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="complexity"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>The time/space/etc. complexity of a function</purpose>
+</element>
+
+<attlist name="complexity">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="purpose"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>A short description of an entity's use</purpose>
+</element>
+
+<attlist name="purpose">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="template-nontype-parameter"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="type"/>
+ <element-name name="default" occurrence="?"/>
+ <element-name name="purpose" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="type"/>
+ <element-name name="default" occurrence="?"/>
+ <element-name name="purpose" occurrence="?"/>
+ </sequence-group>
+</content-model>
+<purpose>A nontype template parameter</purpose>
+</element>
+
+<attlist name="template-nontype-parameter">
+<attdecl>
+ name CDATA #REQUIRED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="pack"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="library"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="libraryinfo"/>
+ <sequence-group occurrence="?">
+ <element-name name="title"/>
+ <sequence-group occurrence="+">
+ <or-group>
+ <element-name name="section"/>
+ <element-name name="library-reference"/>
+ <element-name name="testsuite"/>
+ </or-group>
+ </sequence-group>
+ </sequence-group>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="library.content"/>
+ </sequence-group>
+</content-model>
+<purpose>Top-level element for a library</purpose>
+</element>
+
+<attlist name="library">
+<attdecl>
+ name CDATA #REQUIRED
+ dirname CDATA #REQUIRED
+ html-only CDATA #IMPLIED
+ url CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="dirname"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="url"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="html-only"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="librarycategorylist"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group occurrence="*">
+ <element-name name="librarycategorydef"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group occurrence="*">
+ <element-name name="librarycategorydef"/>
+ </sequence-group>
+</content-model>
+<purpose>Categorized listing of libraries</purpose>
+<description>
+ <para>This element is not intended for use by developers, but is
+ used by <filename>doc/src/boost.xml</filename> as a
+ placeholder.</para>
+</description>
+</element>
+
+<attlist name="librarycategorylist">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="using-namespace"
+ content-type="element">
+<content-model-expanded>
+ <empty/>
+</content-model-expanded>
+<content-model>
+ <empty/>
+</content-model>
+<purpose>Injects the declared names from a namespace into the local scope</purpose>
+</element>
+
+<attlist name="using-namespace">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="enumname"
+ content-type="mixed">
+<content-model-expanded>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model>
+<purpose>References an enumeration type with the given name</purpose>
+</element>
+
+<attlist name="enumname">
+<attdecl>
+ alt CDATA #IMPLIED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="alt"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="struct-specialization"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="specialization" occurrence="?"/>
+ <element-name name="inherit" occurrence="?"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <or-group occurrence="*">
+ <element-name name="access"/>
+ <element-name name="static-constant"/>
+ <element-name name="typedef"/>
+ <element-name name="enum"/>
+ <element-name name="copy-assignment"/>
+ <element-name name="constructor"/>
+ <element-name name="destructor"/>
+ <element-name name="method-group"/>
+ <element-name name="free-function-group"/>
+ <element-name name="function"/>
+ <element-name name="method"/>
+ <element-name name="overloaded-function"/>
+ <element-name name="overloaded-method"/>
+ <element-name name="data-member"/>
+ <element-name name="class"/>
+ <element-name name="class-specialization"/>
+ <element-name name="struct"/>
+ <element-name name="struct-specialization"/>
+ <element-name name="union"/>
+ <element-name name="union-specialization"/>
+ </or-group>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.class-specialization.content"/>
+ </sequence-group>
+</content-model>
+<purpose>A specialization (full or partial) of a struct template</purpose>
+</element>
+
+<attlist name="struct-specialization">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="struct"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="template" occurrence="?"/>
+ <element-name name="inherit" occurrence="*"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ <or-group occurrence="*">
+ <element-name name="access"/>
+ <element-name name="static-constant"/>
+ <element-name name="typedef"/>
+ <element-name name="enum"/>
+ <element-name name="copy-assignment"/>
+ <element-name name="constructor"/>
+ <element-name name="destructor"/>
+ <element-name name="method-group"/>
+ <element-name name="free-function-group"/>
+ <element-name name="function"/>
+ <element-name name="method"/>
+ <element-name name="overloaded-function"/>
+ <element-name name="overloaded-method"/>
+ <element-name name="data-member"/>
+ <element-name name="class"/>
+ <element-name name="class-specialization"/>
+ <element-name name="struct"/>
+ <element-name name="struct-specialization"/>
+ <element-name name="union"/>
+ <element-name name="union-specialization"/>
+ </or-group>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <parament-name name="boost.class.content"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a C++ struct</purpose>
+</element>
+
+<attlist name="struct">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="lib"
+ content-type="mixed">
+<content-model-expanded>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model>
+<purpose>A library dependency</purpose>
+<description>
+ <para>Declares a library dependency on the library named by the content of this element, to be emitted in a Jamfile.</para>
+</description>
+</element>
+
+<element name="enum"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="enumvalue" occurrence="*"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="enumvalue" occurrence="*"/>
+ <element-name name="purpose" occurrence="?"/>
+ <element-name name="description" occurrence="?"/>
+ </sequence-group>
+</content-model>
+<purpose>Declares an enumeration type</purpose>
+</element>
+
+<attlist name="enum">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="requires"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>Declares the requirements of a function</purpose>
+</element>
+
+<attlist name="requires">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="effects"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>Declares the side effects of a function</purpose>
+</element>
+
+<attlist name="effects">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="libraryname"
+ content-type="mixed">
+<content-model-expanded>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <pcdata/>
+ </sequence-group>
+</content-model>
+<purpose>References a library of the given name</purpose>
+</element>
+
+<attlist name="libraryname">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="libraryinfo"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <element-name name="author" occurrence="+"/>
+ <element-name name="copyright" occurrence="*"/>
+ <element-name name="legalnotice" occurrence="*"/>
+ <element-name name="librarypurpose"/>
+ <element-name name="librarycategory" occurrence="*"/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <element-name name="author" occurrence="+"/>
+ <element-name name="copyright" occurrence="*"/>
+ <element-name name="legalnotice" occurrence="*"/>
+ <element-name name="librarypurpose"/>
+ <element-name name="librarycategory" occurrence="*"/>
+ </sequence-group>
+</content-model>
+<purpose>Provides information about a library</purpose>
+</element>
+
+<attlist name="libraryinfo">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="testsuite"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <or-group occurrence="+">
+ <element-name name="compile-test"/>
+ <element-name name="link-test"/>
+ <element-name name="run-test"/>
+ <element-name name="compile-fail-test"/>
+ <element-name name="link-fail-test"/>
+ <element-name name="run-fail-test"/>
+ </or-group>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <sequence-group occurrence="+">
+ <parament-name name="boost.testsuite.tests"/>
+ </sequence-group>
+ </sequence-group>
+</content-model>
+<purpose>Describes a library testsuite</purpose>
+</element>
+
+<attlist name="testsuite">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="header"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>Declares a C++ header with the given name</purpose>
+</element>
+
+<attlist name="header">
+<attdecl>
+ name CDATA #REQUIRED
+ %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="name"
+ type="#REQUIRED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+
+<element name="rationale"
+ content-type="element">
+<content-model-expanded>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model-expanded>
+<content-model>
+ <sequence-group>
+ <any/>
+ </sequence-group>
+</content-model>
+<purpose>Describes the rationale for a particular function's design</purpose>
+</element>
+
+<attlist name="rationale">
+<attdecl> %boost.common.attrib;</attdecl>
+<attribute name="last-revision"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="id"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+<attribute name="xml:base"
+ type="#IMPLIED"
+ value="CDATA"
+ default=""/>
+</attlist>
+</dtd>
diff --git a/tools/boostbook/doc/reference.xml b/tools/boostbook/doc/reference.xml
new file mode 100644
index 0000000000..783e44d92e
--- /dev/null
+++ b/tools/boostbook/doc/reference.xml
@@ -0,0 +1,2951 @@
+<?xml version="1.0" standalone="yes"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<chapter id="reference">
+ <title>Reference</title>
+ <para>Elements:<itemizedlist spacing="compact"><listitem><simpara><link linkend="boostbook.dtd.access">Element <sgmltag>access</sgmltag> - Declares an access specification for class members</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.boostbook">Element <sgmltag>boostbook</sgmltag> - Defines a BoostBook book</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.class">Element <sgmltag>class</sgmltag> - Declares a class or class template</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.class-specialization">Element <sgmltag>class-specialization</sgmltag> - A specialization (partial or full) of a class template</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.code">Element <sgmltag>code</sgmltag> - Mimics the <sgmltag>code</sgmltag> tag in HTML</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.compile-fail-test">Element <sgmltag>compile-fail-test</sgmltag> - A testcase that should fail to compile</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.compile-test">Element <sgmltag>compile-test</sgmltag> - A testcase that should compile correctly</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.complexity">Element <sgmltag>complexity</sgmltag> - The time/space/etc. complexity of a function</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.constructor">Element <sgmltag>constructor</sgmltag> - Declares a constructor of the enclosing class</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.copy-assignment">Element <sgmltag>copy-assignment</sgmltag> - Declares a copy-assignment operator</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.data-member">Element <sgmltag>data-member</sgmltag> - Declares a data member of a class</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.default">Element <sgmltag>default</sgmltag> - The default value of a function or template parameter</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.description">Element <sgmltag>description</sgmltag> - Detailed description of a construct</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.destructor">Element <sgmltag>destructor</sgmltag> - Declares a destructor for the enclosing class</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.effects">Element <sgmltag>effects</sgmltag> - Declares the side effects of a function</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.enum">Element <sgmltag>enum</sgmltag> - Declares an enumeration type</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.enumname">Element <sgmltag>enumname</sgmltag> - References an enumeration type with the given name</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.enumvalue">Element <sgmltag>enumvalue</sgmltag> - A single value of an enumeration</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.free-function-group">Element <sgmltag>free-function-group</sgmltag> - A set of functions that are grouped together under one name</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.function">Element <sgmltag>function</sgmltag> - Declares a function</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.functionname">Element <sgmltag>functionname</sgmltag> - References a function with the given name</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.globalname">Element <sgmltag>globalname</sgmltag> - References a global with the given name</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.header">Element <sgmltag>header</sgmltag> - Declares a C++ header with the given name</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.headername">Element <sgmltag>headername</sgmltag> - References a C++ header with the given name</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.if-fails">Element <sgmltag>if-fails</sgmltag> - What it means when a testcase fails</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.inherit">Element <sgmltag>inherit</sgmltag> - Declares a base class of the enclosing class or struct</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.lib">Element <sgmltag>lib</sgmltag> - A library dependency</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.library">Element <sgmltag>library</sgmltag> - Top-level element for a library</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.library-reference">Element <sgmltag>library-reference</sgmltag> - Declares the reference material for a library</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.librarycategory">Element <sgmltag>librarycategory</sgmltag> - Declares that the enclosing library is in this category</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.librarycategorydef">Element <sgmltag>librarycategorydef</sgmltag> - Defines a new library category</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.librarycategorylist">Element <sgmltag>librarycategorylist</sgmltag> - Categorized listing of libraries</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.libraryinfo">Element <sgmltag>libraryinfo</sgmltag> - Provides information about a library</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.librarylist">Element <sgmltag>librarylist</sgmltag> - Placeholder for an alphabetical list of libraries</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.libraryname">Element <sgmltag>libraryname</sgmltag> - References a library of the given name</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.librarypurpose">Element <sgmltag>librarypurpose</sgmltag> - Describes in one short sentence or phrase the purpose of a library</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.link-fail-test">Element <sgmltag>link-fail-test</sgmltag> - Declares a test that should compile but fail to link</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.link-test">Element <sgmltag>link-test</sgmltag> - Declares a test that should compile and link</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.macroname">Element <sgmltag>macroname</sgmltag> - References a macro with the given name</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.method">Element <sgmltag>method</sgmltag> - Declares a method, i.e., a member function</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.method-group">Element <sgmltag>method-group</sgmltag> - A set of methods that are grouped together under one name</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.namespace">Element <sgmltag>namespace</sgmltag> - Declares a namespace</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.notes">Element <sgmltag>notes</sgmltag> - Non-normative notes about a function's semantics</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.overloaded-function">Element <sgmltag>overloaded-function</sgmltag> - An overloaded function</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.overloaded-method">Element <sgmltag>overloaded-method</sgmltag> - An overloaded method</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.parameter">Element <sgmltag>parameter</sgmltag> - A function parameter</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.paramtype">Element <sgmltag>paramtype</sgmltag> - The type of a function parameter</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.postconditions">Element <sgmltag>postconditions</sgmltag> - Conditions that must hold after the function returns</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.precondition">Element <sgmltag>precondition</sgmltag> - Conditions that must be met prior to executing a function</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.programlisting">Element <sgmltag>programlisting</sgmltag> - A sample of program code</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.purpose">Element <sgmltag>purpose</sgmltag> - A short description of an entity's use</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.rationale">Element <sgmltag>rationale</sgmltag> - Describes the rationale for a particular function's design</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.requirement">Element <sgmltag>requirement</sgmltag> - A requirement/property in the Jamfile for a testcase</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.requires">Element <sgmltag>requires</sgmltag> - Declares the requirements of a function</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.returns">Element <sgmltag>returns</sgmltag> - Description of the return value of a function</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.run-fail-test">Element <sgmltag>run-fail-test</sgmltag> - A testcase that should compile and link, but fail on execution</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.run-test">Element <sgmltag>run-test</sgmltag> - A testcase that should compile, link, and execute</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.signature">Element <sgmltag>signature</sgmltag> - One signature of an overloaded function or method</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.snippet">Element <sgmltag>snippet</sgmltag> - Pulls in a code snippet from a <sgmltag>programlisting</sgmltag> element</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.source">Element <sgmltag>source</sgmltag> - Defines source code for a test</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.specialization">Element <sgmltag>specialization</sgmltag> - Defines the specialization arguments for a class specialization</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.static-constant">Element <sgmltag>static-constant</sgmltag> - Declares a static constant, e.g., <code>const int foo = 5;</code>.</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.struct">Element <sgmltag>struct</sgmltag> - Declares a C++ struct</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.struct-specialization">Element <sgmltag>struct-specialization</sgmltag> - A specialization (full or partial) of a struct template</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.template">Element <sgmltag>template</sgmltag> - Declares the template parameters of a class or function</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.template-arg">Element <sgmltag>template-arg</sgmltag> - A template argument in a specialization</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.template-nontype-parameter">Element <sgmltag>template-nontype-parameter</sgmltag> - A nontype template parameter</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.template-type-parameter">Element <sgmltag>template-type-parameter</sgmltag> - Declares a template type parameter</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.template-varargs">Element <sgmltag>template-varargs</sgmltag> - Declares a variable-length list of template parameters</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.testsuite">Element <sgmltag>testsuite</sgmltag> - Describes a library testsuite</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.throws">Element <sgmltag>throws</sgmltag> - Description of the exceptions thrown by a function</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.type">Element <sgmltag>type</sgmltag> - The type of an element or return type of a function</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.typedef">Element <sgmltag>typedef</sgmltag> - Declares a typedef</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.union">Element <sgmltag>union</sgmltag> - Declares a C++ union or union template</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.union-specialization">Element <sgmltag>union-specialization</sgmltag> - A specialization (full or partial) of a union template</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.using-class">Element <sgmltag>using-class</sgmltag> - Injects the method and function names of a class into the local scope</link></simpara></listitem><listitem><simpara><link linkend="boostbook.dtd.using-namespace">Element <sgmltag>using-namespace</sgmltag> - Injects the declared names from a namespace into the local scope</link></simpara></listitem></itemizedlist></para>
+ <refentry id="boostbook.dtd.class-specialization">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>class-specialization</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>class-specialization</refname>
+ <refpurpose>A specialization (partial or full) of a class template</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>class-specialization ::=
+ (<link linkend="boostbook.dtd.template">template</link>?, <link linkend="boostbook.dtd.specialization">specialization</link>?, <link linkend="boostbook.dtd.inherit">inherit</link>?, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, (<link linkend="boostbook.dtd.access">access</link>| <link linkend="boostbook.dtd.static-constant">static-constant</link>| <link linkend="boostbook.dtd.typedef">typedef</link>| <link linkend="boostbook.dtd.enum">enum</link>| <link linkend="boostbook.dtd.copy-assignment">copy-assignment</link>| <link linkend="boostbook.dtd.constructor">constructor</link>| <link linkend="boostbook.dtd.destructor">destructor</link>| <link linkend="boostbook.dtd.method-group">method-group</link>| <link linkend="boostbook.dtd.free-function-group">free-function-group</link>| <link linkend="boostbook.dtd.function">function</link>| <link linkend="boostbook.dtd.method">method</link>| <link linkend="boostbook.dtd.overloaded-function">overloaded-function</link>| <link linkend="boostbook.dtd.overloaded-method">overloaded-method</link>| <link linkend="boostbook.dtd.data-member">data-member</link>| <link linkend="boostbook.dtd.class">class</link>| <link linkend="boostbook.dtd.class-specialization">class-specialization</link>| <link linkend="boostbook.dtd.struct">struct</link>| <link linkend="boostbook.dtd.struct-specialization">struct-specialization</link>| <link linkend="boostbook.dtd.union">union</link>| <link linkend="boostbook.dtd.union-specialization">union-specialization</link>)*)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.link-test">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>link-test</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>link-test</refname>
+ <refpurpose>Declares a test that should compile and link</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>link-test ::=
+ (<link linkend="boostbook.dtd.source">source</link>*, <link linkend="boostbook.dtd.lib">lib</link>*, <link linkend="boostbook.dtd.requirement">requirement</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>, <link linkend="boostbook.dtd.if-fails">if-fails</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>filename</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the file associated with this element</entry></row>
+<row><entry>name</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.link-fail-test">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>link-fail-test</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>link-fail-test</refname>
+ <refpurpose>Declares a test that should compile but fail to link</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>link-fail-test ::=
+ (<link linkend="boostbook.dtd.source">source</link>*, <link linkend="boostbook.dtd.lib">lib</link>*, <link linkend="boostbook.dtd.requirement">requirement</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>, <link linkend="boostbook.dtd.if-fails">if-fails</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>filename</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the file associated with this element</entry></row>
+<row><entry>name</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.typedef">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>typedef</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>typedef</refname>
+ <refpurpose>Declares a typedef</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>typedef ::=
+ (<link linkend="boostbook.dtd.type">type</link>, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.static-constant">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>static-constant</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>static-constant</refname>
+ <refpurpose>Declares a static constant, e.g., <code>const int foo = 5;</code>.</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>static-constant ::=
+ (<link linkend="boostbook.dtd.type">type</link>, <link linkend="boostbook.dtd.default">default</link>, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.code">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>code</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>code</refname>
+ <refpurpose>Mimics the <sgmltag>code</sgmltag> tag in HTML</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>code ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>Text within a <sgmltag>code</sgmltag> tag is generally typeset
+ in a different, monospaced font so that it stands out as code. The
+ <sgmltag>code</sgmltag> tag in BoostBook is transformed directly
+ into the <sgmltag>computeroutput</sgmltag> tag in DocBook.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.destructor">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>destructor</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>destructor</refname>
+ <refpurpose>Declares a destructor for the enclosing class</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>destructor ::=
+ (<link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, <link linkend="boostbook.dtd.requires">requires</link>?, <link linkend="boostbook.dtd.effects">effects</link>?, <link linkend="boostbook.dtd.postconditions">postconditions</link>?, <link linkend="boostbook.dtd.returns">returns</link>?, <link linkend="boostbook.dtd.throws">throws</link>?, <link linkend="boostbook.dtd.complexity">complexity</link>?, <link linkend="boostbook.dtd.notes">notes</link>?, <link linkend="boostbook.dtd.rationale">rationale</link>?)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>General documentation on functions in BoostBook is provided in
+ the <link linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>specifiers</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The specifiers for this function, e.g., inline, static, etc.</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.template-type-parameter">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>template-type-parameter</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>template-type-parameter</refname>
+ <refpurpose>Declares a template type parameter</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>template-type-parameter ::=
+ (<link linkend="boostbook.dtd.default">default</link>?, <link linkend="boostbook.dtd.purpose">purpose</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>pack</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to '1' if the parameter is a parameter pack.</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.description">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>description</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>description</refname>
+ <refpurpose>Detailed description of a construct</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>description ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>Although the context model for this element is
+ <code>ANY</code>, detailed descriptions should contain structured
+ DocBook elements that occur within sections, e.g., paragraphs
+ (<sgmltag>para</sgmltag>, <sgmltag>simpara</sgmltag>), lists
+ (<sgmltag>orderedlist</sgmltag>, <sgmltag>itemizedlist</sgmltag>),
+ tables (<sgmltag>informaltable</sgmltag>, <sgmltag>table</sgmltag>),
+ etc.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.librarylist">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>librarylist</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>librarylist</refname>
+ <refpurpose>Placeholder for an alphabetical list of libraries</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>librarylist ::=
+ EMPTY
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>Developers aren't generally expected to use this element. Its existence is mainly as a placeholder in <filename>boost.xml</filename> for the alphabetical list of libraries.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.library-reference">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>library-reference</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>library-reference</refname>
+ <refpurpose>Declares the reference material for a library</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>library-reference ::=
+ (title?, section*, (<link linkend="boostbook.dtd.header">header</link>| <link linkend="boostbook.dtd.library-reference">library-reference</link>)*)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>Reference documentation for a library is contained with a
+ &lt;library-reference&gt; element. The &lt;library-reference&gt;
+ element has no attributes, and contains as children only
+ &lt;header&gt; elements.</para>
+
+ <para>The &lt;header&gt; element defines a C++ header file. Within
+ each C++ header file lie the definitions of C++ constructs to be
+ documented. The <code>name</code> attribute of the &lt;header&gt;
+ element gives the name of the header, as one would specify when
+ including the header. For instance, the &lt;library-reference&gt;
+ for the <libraryname>Any</libraryname> library may look like
+ this:</para>
+
+ <programlisting>&lt;library-reference&gt;
+ &lt;header name="boost/any.hpp"&gt;
+ &lt;!-- C++ constructs in this header --&gt;
+ &lt;/header&gt;
+&lt;/library-reference&gt;</programlisting>
+
+ <para>If the <libraryname>Any</libraryname> library contained
+ multiple headers, we would list them all as children of the
+ &lt;library-reference&gt; element.</para>
+
+ <para><sgmltag>library-reference</sgmltag> elements can be nested,
+ so that reference material can be divided into separate sections
+ that each contain different headers.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.boostbook">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>boostbook</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>boostbook</refname>
+ <refpurpose>Defines a BoostBook book</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>boostbook ::=
+ (title, (chapter| <link linkend="boostbook.dtd.library">library</link>)*)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <simpara>This element is the topmost level defined by
+ <filename>boost.xml</filename> for all Boost documentation. It will
+ not generally be used by developers.</simpara>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.union">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>union</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>union</refname>
+ <refpurpose>Declares a C++ union or union template</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>union ::=
+ (<link linkend="boostbook.dtd.template">template</link>?, <link linkend="boostbook.dtd.inherit">inherit</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, (<link linkend="boostbook.dtd.access">access</link>| <link linkend="boostbook.dtd.static-constant">static-constant</link>| <link linkend="boostbook.dtd.typedef">typedef</link>| <link linkend="boostbook.dtd.enum">enum</link>| <link linkend="boostbook.dtd.copy-assignment">copy-assignment</link>| <link linkend="boostbook.dtd.constructor">constructor</link>| <link linkend="boostbook.dtd.destructor">destructor</link>| <link linkend="boostbook.dtd.method-group">method-group</link>| <link linkend="boostbook.dtd.free-function-group">free-function-group</link>| <link linkend="boostbook.dtd.function">function</link>| <link linkend="boostbook.dtd.method">method</link>| <link linkend="boostbook.dtd.overloaded-function">overloaded-function</link>| <link linkend="boostbook.dtd.overloaded-method">overloaded-method</link>| <link linkend="boostbook.dtd.data-member">data-member</link>| <link linkend="boostbook.dtd.class">class</link>| <link linkend="boostbook.dtd.class-specialization">class-specialization</link>| <link linkend="boostbook.dtd.struct">struct</link>| <link linkend="boostbook.dtd.struct-specialization">struct-specialization</link>| <link linkend="boostbook.dtd.union">union</link>| <link linkend="boostbook.dtd.union-specialization">union-specialization</link>)*)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.inherit">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>inherit</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>inherit</refname>
+ <refpurpose>Declares a base class of the enclosing class or struct</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>inherit ::=
+ (<link linkend="boostbook.dtd.type">type</link>, <link linkend="boostbook.dtd.purpose">purpose</link>?)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>This element contains the type of the class inherited.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>access</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The access specifier ("public", "private", or "protected") of the inheritance.</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>pack</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to '1' if this is a pack exapansion.</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.template-varargs">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>template-varargs</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>template-varargs</refname>
+ <refpurpose>Declares a variable-length list of template parameters</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>template-varargs ::=
+ EMPTY
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>Variable-length template parameter lists are not allowed in
+ C++, but because they are sometimes needed in documentation they are
+ allowed in BoostBook. This element generally expands to "..." and
+ can be used anywhere any other template parameter can be
+ used.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.source">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>source</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>source</refname>
+ <refpurpose>Defines source code for a test</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>source ::=
+ (#PCDATA| <link linkend="boostbook.dtd.snippet">snippet</link>)*
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>This element will contain the source code for a testcase that
+ will be generated from the documentation. To reduce the amount of escaping in the text, it is recommended to use CDATA sections, which look like this:
+
+ <programlisting>&lt;![CDATA[
+&lt;your program text here: no escaping needed!&gt;
+]]&gt;</programlisting>
+ </para>
+
+ <para>In addition to CDATA sections, code snippets can be pulled in
+ from <sgmltag>programlisting</sgmltag> elements using the <link linkend="boostbook.dtd.snippet"><sgmltag>snippet</sgmltag></link>
+ element.</para>
+</refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.function">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>function</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>function</refname>
+ <refpurpose>Declares a function</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>function ::=
+ (<link linkend="boostbook.dtd.template">template</link>?, <link linkend="boostbook.dtd.type">type</link>, <link linkend="boostbook.dtd.parameter">parameter</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, <link linkend="boostbook.dtd.requires">requires</link>?, <link linkend="boostbook.dtd.effects">effects</link>?, <link linkend="boostbook.dtd.postconditions">postconditions</link>?, <link linkend="boostbook.dtd.returns">returns</link>?, <link linkend="boostbook.dtd.throws">throws</link>?, <link linkend="boostbook.dtd.complexity">complexity</link>?, <link linkend="boostbook.dtd.notes">notes</link>?, <link linkend="boostbook.dtd.rationale">rationale</link>?)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>BoostBook functions are documented by specifying the
+ function's interface (e.g., its C++ signature) and its
+ behavior. Constructors, destructors, member functions, and free
+ functions all use the same documentation method, although the
+ top-level tags differ.</para>
+
+ <para>The behavior of functions in BoostBook is documenting using a
+ style similar to that of the C++ standard, with clauses describing
+ the requirements, effects, postconditions, exception behavior, and
+ return values of functions.</para>
+
+ <para>The following example illustrates some constructors and a
+ destructor for <classname>boost::any</classname>. Note that one of
+ the constructors takes a single parameter whose name is "other" and
+ whose type, <code>const any&amp;</code> is contained in the
+ &lt;paramtype&gt; element; any number of parameters may be specified
+ in this way.</para>
+
+ <programlisting>&lt;class name="any"&gt;
+ &lt;constructor&gt;
+ &lt;postconditions&gt;&lt;para&gt;&lt;this-&gt;empty()&gt;&lt;/para&gt;&lt;/postconditions&gt;
+ &lt;/constructor&gt;
+
+ &lt;constructor&gt;
+ &lt;parameter name="other"&gt;
+ &lt;paramtype&gt;const &lt;classname&gt;any&lt;/classname&gt;&amp;amp;&lt;/paramtype&gt;
+ &lt;/parameter&gt;
+
+ &lt;effects&gt;
+ &lt;simpara&gt; Copy constructor that copies
+ content of &lt;code&gt;other&lt;/code&gt; into the new instance,
+ so that any content is equivalent in both type and value to the
+ content of &lt;code&gt;other&lt;/code&gt;, or empty if
+ &lt;code&gt;other&lt;/code&gt; is
+ empty.
+ &lt;/simpara&gt;
+ &lt;/effects&gt;
+
+ &lt;throws&gt;
+ &lt;simpara&gt;May fail with a
+ &lt;classname&gt;std::bad_alloc&lt;/classname&gt; exception or any
+ exceptions arising from the copy constructor of the
+ contained type.
+ &lt;/simpara&gt;
+ &lt;/throws&gt;
+ &lt;/constructor&gt;
+
+ &lt;destructor&gt;
+ &lt;effects&gt;&lt;simpara&gt;Releases any and all resources used in
+ management of instance.&lt;/simpara&gt;&lt;/effects&gt;
+
+ &lt;throws&gt;&lt;simpara&gt;Nothing.&lt;/simpara&gt;&lt;/throws&gt;
+ &lt;/destructor&gt;
+&lt;/class&gt;</programlisting>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>specifiers</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The specifiers for this function, e.g., inline, static, etc.</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.macroname">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>macroname</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>macroname</refname>
+ <refpurpose/>
+ </refnamediv>
+ <refsynopsisdiv>macroname ::=
+ (#PCDATA)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>alt</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry/></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.postconditions">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>postconditions</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>postconditions</refname>
+ <refpurpose>Conditions that must hold after the function returns</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>postconditions ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.compile-test">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>compile-test</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>compile-test</refname>
+ <refpurpose>A testcase that should compile correctly</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>compile-test ::=
+ (<link linkend="boostbook.dtd.source">source</link>*, <link linkend="boostbook.dtd.lib">lib</link>*, <link linkend="boostbook.dtd.requirement">requirement</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>, <link linkend="boostbook.dtd.if-fails">if-fails</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>filename</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the file associated with this element</entry></row>
+<row><entry>name</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.method">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>method</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>method</refname>
+ <refpurpose>Declares a method, i.e., a member function</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>method ::=
+ (<link linkend="boostbook.dtd.template">template</link>?, <link linkend="boostbook.dtd.type">type</link>, <link linkend="boostbook.dtd.parameter">parameter</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, <link linkend="boostbook.dtd.requires">requires</link>?, <link linkend="boostbook.dtd.effects">effects</link>?, <link linkend="boostbook.dtd.postconditions">postconditions</link>?, <link linkend="boostbook.dtd.returns">returns</link>?, <link linkend="boostbook.dtd.throws">throws</link>?, <link linkend="boostbook.dtd.complexity">complexity</link>?, <link linkend="boostbook.dtd.notes">notes</link>?, <link linkend="boostbook.dtd.rationale">rationale</link>?)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>General documentation on functions in BoostBook is provided in
+ the <link linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>cv</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>cv-qualifiers for this method, e.g., const volatile</entry></row>
+<row><entry>specifiers</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The specifiers for this function, e.g., inline, static, etc.</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.snippet">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>snippet</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>snippet</refname>
+ <refpurpose>Pulls in a code snippet from a <sgmltag>programlisting</sgmltag> element</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>snippet ::=
+ EMPTY
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the <sgmltag>programlisting</sgmltag> element to insert</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.constructor">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>constructor</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>constructor</refname>
+ <refpurpose>Declares a constructor of the enclosing class</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>constructor ::=
+ (<link linkend="boostbook.dtd.template">template</link>?, <link linkend="boostbook.dtd.parameter">parameter</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, <link linkend="boostbook.dtd.requires">requires</link>?, <link linkend="boostbook.dtd.effects">effects</link>?, <link linkend="boostbook.dtd.postconditions">postconditions</link>?, <link linkend="boostbook.dtd.returns">returns</link>?, <link linkend="boostbook.dtd.throws">throws</link>?, <link linkend="boostbook.dtd.complexity">complexity</link>?, <link linkend="boostbook.dtd.notes">notes</link>?, <link linkend="boostbook.dtd.rationale">rationale</link>?)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>General documentation on functions in BoostBook is provided in
+ the <link linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>specifiers</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The specifiers for this function, e.g., inline, static, etc.</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.namespace">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>namespace</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>namespace</refname>
+ <refpurpose>Declares a namespace</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>namespace ::=
+ (<link linkend="boostbook.dtd.class">class</link>| <link linkend="boostbook.dtd.class-specialization">class-specialization</link>| <link linkend="boostbook.dtd.struct">struct</link>| <link linkend="boostbook.dtd.struct-specialization">struct-specialization</link>| <link linkend="boostbook.dtd.union">union</link>| <link linkend="boostbook.dtd.union-specialization">union-specialization</link>| <link linkend="boostbook.dtd.typedef">typedef</link>| <link linkend="boostbook.dtd.enum">enum</link>| <link linkend="boostbook.dtd.free-function-group">free-function-group</link>| <link linkend="boostbook.dtd.function">function</link>| <link linkend="boostbook.dtd.overloaded-function">overloaded-function</link>| <link linkend="boostbook.dtd.namespace">namespace</link>)*
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>BoostBook namespaces are declared via the &lt;namespace&gt;
+ element. As in C++, namespaces can be nested and contain other C++
+ constructs, such as classes or functions. The <code>name</code>
+ attribute of a &lt;namespace&gt; element gives the namespace name
+ (e.g., "boost"). The <libraryname>Any</libraryname> library is
+ defined entirely within namespace boost by:</para>
+
+ <programlisting>&lt;library-reference&gt;
+ &lt;header name="boost/any.hpp"&gt;
+ &lt;namespace name="boost"&gt;
+ &lt;!-- C++ constructs in the boost namespace --&gt;
+ &lt;/namespace&gt;
+ &lt;/header&gt;
+&lt;/library-reference&gt;</programlisting>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.if-fails">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>if-fails</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>if-fails</refname>
+ <refpurpose>What it means when a testcase fails</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>if-fails ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>
+ Describes to the user the effect a certain failing testcase will
+ have on the usefulness of a library. This field is useful in cases
+ where a failed testcase does not mean that the library won't be
+ useful, but may mean that certain library features will not be
+ available.
+ </para>
+</refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.headername">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>headername</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>headername</refname>
+ <refpurpose/>
+ </refnamediv>
+ <refsynopsisdiv>headername ::=
+ (#PCDATA)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>alt</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry/></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.free-function-group">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>free-function-group</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>free-function-group</refname>
+ <refpurpose>A set of functions that are grouped together under one name</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>free-function-group ::=
+ (<link linkend="boostbook.dtd.function">function</link>| <link linkend="boostbook.dtd.overloaded-function">overloaded-function</link>)*
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.functionname">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>functionname</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>functionname</refname>
+ <refpurpose>References a function with the given name</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>functionname ::=
+ (#PCDATA)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>If a function (or overloaded function) with the given,
+ possibly-qualified name is found, this generates a link to that
+ function. Lookups obey currently-active <link linkend="boostbook.dtd.using-class"><sgmltag>using-class</sgmltag></link>
+ and <link linkend="boostbook.dtd.using-namespace"><sgmltag>using-namespace</sgmltag></link>
+ directives to aid in the search, along with searching within the
+ current scope.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>alt</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry/></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.librarycategory">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>librarycategory</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>librarycategory</refname>
+ <refpurpose>Declares that the enclosing library is in this category</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>librarycategory ::=
+ (#PCDATA)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.notes">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>notes</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>notes</refname>
+ <refpurpose>Non-normative notes about a function's semantics</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>notes ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.data-member">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>data-member</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>data-member</refname>
+ <refpurpose>Declares a data member of a class</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>data-member ::=
+ (<link linkend="boostbook.dtd.type">type</link>, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>specifiers</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The specifiers for this function, e.g., inline, static, etc.</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.specialization">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>specialization</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>specialization</refname>
+ <refpurpose>Defines the specialization arguments for a class specialization</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>specialization ::=
+ (<link linkend="boostbook.dtd.template-arg">template-arg</link>)*
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.union-specialization">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>union-specialization</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>union-specialization</refname>
+ <refpurpose>A specialization (full or partial) of a union template</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>union-specialization ::=
+ (<link linkend="boostbook.dtd.template">template</link>?, <link linkend="boostbook.dtd.specialization">specialization</link>?, <link linkend="boostbook.dtd.inherit">inherit</link>?, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, (<link linkend="boostbook.dtd.access">access</link>| <link linkend="boostbook.dtd.static-constant">static-constant</link>| <link linkend="boostbook.dtd.typedef">typedef</link>| <link linkend="boostbook.dtd.enum">enum</link>| <link linkend="boostbook.dtd.copy-assignment">copy-assignment</link>| <link linkend="boostbook.dtd.constructor">constructor</link>| <link linkend="boostbook.dtd.destructor">destructor</link>| <link linkend="boostbook.dtd.method-group">method-group</link>| <link linkend="boostbook.dtd.free-function-group">free-function-group</link>| <link linkend="boostbook.dtd.function">function</link>| <link linkend="boostbook.dtd.method">method</link>| <link linkend="boostbook.dtd.overloaded-function">overloaded-function</link>| <link linkend="boostbook.dtd.overloaded-method">overloaded-method</link>| <link linkend="boostbook.dtd.data-member">data-member</link>| <link linkend="boostbook.dtd.class">class</link>| <link linkend="boostbook.dtd.class-specialization">class-specialization</link>| <link linkend="boostbook.dtd.struct">struct</link>| <link linkend="boostbook.dtd.struct-specialization">struct-specialization</link>| <link linkend="boostbook.dtd.union">union</link>| <link linkend="boostbook.dtd.union-specialization">union-specialization</link>)*)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.throws">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>throws</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>throws</refname>
+ <refpurpose>Description of the exceptions thrown by a function</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>throws ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.template-arg">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>template-arg</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>template-arg</refname>
+ <refpurpose>A template argument in a specialization</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>template-arg ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>pack</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to '1' if this is a pack exapansion.</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.globalname">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>globalname</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>globalname</refname>
+ <refpurpose/>
+ </refnamediv>
+ <refsynopsisdiv>globalname ::=
+ (#PCDATA)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>alt</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry/></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.method-group">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>method-group</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>method-group</refname>
+ <refpurpose>A set of methods that are grouped together under one name</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>method-group ::=
+ (<link linkend="boostbook.dtd.method">method</link>| <link linkend="boostbook.dtd.overloaded-method">overloaded-method</link>)*
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.requirement">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>requirement</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>requirement</refname>
+ <refpurpose>A requirement/property in the Jamfile for a testcase</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>requirement ::=
+ (#PCDATA)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>A requirement is part of the dependencies of a target in a
+ Jamfile. The <code>name</code> attribute of a requirement element
+ gives the name of the Boost.Build feature and the content of the
+ requirement gives the value of that feature. A requirement such as
+ <code>&lt;includes&gt;foo.hpp</code> would be encoded as
+ <code>&lt;requirement
+ name="includes"&gt;foo.hpp&lt;/requirement&gt;</code>.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.precondition">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>precondition</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>precondition</refname>
+ <refpurpose>Conditions that must be met prior to executing a function</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>precondition ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.paramtype">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>paramtype</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>paramtype</refname>
+ <refpurpose>The type of a function parameter</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>paramtype ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.using-class">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>using-class</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>using-class</refname>
+ <refpurpose>Injects the method and function names of a class into the local scope</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>using-class ::=
+ EMPTY
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.run-test">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>run-test</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>run-test</refname>
+ <refpurpose>A testcase that should compile, link, and execute</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>run-test ::=
+ (<link linkend="boostbook.dtd.source">source</link>*, <link linkend="boostbook.dtd.lib">lib</link>*, <link linkend="boostbook.dtd.requirement">requirement</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>, <link linkend="boostbook.dtd.if-fails">if-fails</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>filename</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the file associated with this element</entry></row>
+<row><entry>name</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.librarypurpose">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>librarypurpose</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>librarypurpose</refname>
+ <refpurpose>Describes in one short sentence or phrase the purpose of a library</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>librarypurpose ::=
+ (#PCDATA| <link linkend="boostbook.dtd.code">code</link>| ulink| <link linkend="boostbook.dtd.functionname">functionname</link>| methodname| classname| <link linkend="boostbook.dtd.macroname">macroname</link>| <link linkend="boostbook.dtd.headername">headername</link>| <link linkend="boostbook.dtd.enumname">enumname</link>| <link linkend="boostbook.dtd.globalname">globalname</link>)*
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.copy-assignment">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>copy-assignment</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>copy-assignment</refname>
+ <refpurpose>Declares a copy-assignment operator</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>copy-assignment ::=
+ (<link linkend="boostbook.dtd.template">template</link>?, <link linkend="boostbook.dtd.type">type</link>?, <link linkend="boostbook.dtd.parameter">parameter</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, <link linkend="boostbook.dtd.requires">requires</link>?, <link linkend="boostbook.dtd.effects">effects</link>?, <link linkend="boostbook.dtd.postconditions">postconditions</link>?, <link linkend="boostbook.dtd.returns">returns</link>?, <link linkend="boostbook.dtd.throws">throws</link>?, <link linkend="boostbook.dtd.complexity">complexity</link>?, <link linkend="boostbook.dtd.notes">notes</link>?, <link linkend="boostbook.dtd.rationale">rationale</link>?)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>The return type of the copy-assignment operator does not need
+ to be specified. If left unspecified, it will default to an
+ unqualified reference to the enclosing class type.</para>
+
+ <para>General documentation on functions in BoostBook is provided in
+ the <link linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>cv</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>cv-qualifiers for this method, e.g., const volatile</entry></row>
+<row><entry>specifiers</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The specifiers for this function, e.g., inline, static, etc.</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.run-fail-test">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>run-fail-test</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>run-fail-test</refname>
+ <refpurpose>A testcase that should compile and link, but fail on execution</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>run-fail-test ::=
+ (<link linkend="boostbook.dtd.source">source</link>*, <link linkend="boostbook.dtd.lib">lib</link>*, <link linkend="boostbook.dtd.requirement">requirement</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>, <link linkend="boostbook.dtd.if-fails">if-fails</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>filename</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the file associated with this element</entry></row>
+<row><entry>name</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.template">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>template</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>template</refname>
+ <refpurpose>Declares the template parameters of a class or function</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>template ::=
+ (<link linkend="boostbook.dtd.template-type-parameter">template-type-parameter</link>| <link linkend="boostbook.dtd.template-nontype-parameter">template-nontype-parameter</link>| <link linkend="boostbook.dtd.template-varargs">template-varargs</link>)*
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.compile-fail-test">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>compile-fail-test</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>compile-fail-test</refname>
+ <refpurpose>A testcase that should fail to compile</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>compile-fail-test ::=
+ (<link linkend="boostbook.dtd.source">source</link>*, <link linkend="boostbook.dtd.lib">lib</link>*, <link linkend="boostbook.dtd.requirement">requirement</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>, <link linkend="boostbook.dtd.if-fails">if-fails</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>filename</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the file associated with this element</entry></row>
+<row><entry>name</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.returns">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>returns</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>returns</refname>
+ <refpurpose>Description of the return value of a function</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>returns ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.default">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>default</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>default</refname>
+ <refpurpose>The default value of a function or template parameter</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>default ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.parameter">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>parameter</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>parameter</refname>
+ <refpurpose>A function parameter</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>parameter ::=
+ (<link linkend="boostbook.dtd.paramtype">paramtype</link>, <link linkend="boostbook.dtd.default">default</link>?, <link linkend="boostbook.dtd.description">description</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>name</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>pack</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to '1' if the parameter is a parameter pack.</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.signature">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>signature</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>signature</refname>
+ <refpurpose>One signature of an overloaded function or method</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>signature ::=
+ (<link linkend="boostbook.dtd.template">template</link>?, <link linkend="boostbook.dtd.type">type</link>, <link linkend="boostbook.dtd.parameter">parameter</link>*)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>
+ A signature refers to one declaration of an overloaded function or
+ method. The signature itself has no name, because the name of the
+ overloaded function or method is used. An overloaded function or
+ method will have several signatures that will generally be typeset
+ together.
+ </para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>cv</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>cv-qualifiers for this method, e.g., const volatile</entry></row>
+<row><entry>specifiers</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The specifiers for this function, e.g., inline, static, etc.</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.overloaded-function">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>overloaded-function</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>overloaded-function</refname>
+ <refpurpose>An overloaded function</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>overloaded-function ::=
+ (<link linkend="boostbook.dtd.signature">signature</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, <link linkend="boostbook.dtd.requires">requires</link>?, <link linkend="boostbook.dtd.effects">effects</link>?, <link linkend="boostbook.dtd.postconditions">postconditions</link>?, <link linkend="boostbook.dtd.returns">returns</link>?, <link linkend="boostbook.dtd.throws">throws</link>?, <link linkend="boostbook.dtd.complexity">complexity</link>?, <link linkend="boostbook.dtd.notes">notes</link>?, <link linkend="boostbook.dtd.rationale">rationale</link>?)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>General documentation on functions in BoostBook is provided in
+ the <link linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.access">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>access</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>access</refname>
+ <refpurpose>Declares an access specification for class members</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>access ::=
+ (<link linkend="boostbook.dtd.static-constant">static-constant</link>| <link linkend="boostbook.dtd.typedef">typedef</link>| <link linkend="boostbook.dtd.enum">enum</link>| <link linkend="boostbook.dtd.copy-assignment">copy-assignment</link>| <link linkend="boostbook.dtd.constructor">constructor</link>| <link linkend="boostbook.dtd.destructor">destructor</link>| <link linkend="boostbook.dtd.method-group">method-group</link>| <link linkend="boostbook.dtd.method">method</link>| <link linkend="boostbook.dtd.overloaded-method">overloaded-method</link>| <link linkend="boostbook.dtd.data-member">data-member</link>| <link linkend="boostbook.dtd.class">class</link>| <link linkend="boostbook.dtd.class-specialization">class-specialization</link>| <link linkend="boostbook.dtd.struct">struct</link>| <link linkend="boostbook.dtd.struct-specialization">struct-specialization</link>| <link linkend="boostbook.dtd.union">union</link>| <link linkend="boostbook.dtd.union-specialization">union-specialization</link>)+
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>The access specifications of class members (public, private, or protected) may be determined by enclosing them in an &lt;access&gt; element.</para>
+ </refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the access specification, e.g. "public", "private", or "protected".</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.class">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>class</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>class</refname>
+ <refpurpose>Declares a class or class template</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>class ::=
+ (<link linkend="boostbook.dtd.template">template</link>?, <link linkend="boostbook.dtd.inherit">inherit</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, (<link linkend="boostbook.dtd.access">access</link>| <link linkend="boostbook.dtd.static-constant">static-constant</link>| <link linkend="boostbook.dtd.typedef">typedef</link>| <link linkend="boostbook.dtd.enum">enum</link>| <link linkend="boostbook.dtd.copy-assignment">copy-assignment</link>| <link linkend="boostbook.dtd.constructor">constructor</link>| <link linkend="boostbook.dtd.destructor">destructor</link>| <link linkend="boostbook.dtd.method-group">method-group</link>| <link linkend="boostbook.dtd.free-function-group">free-function-group</link>| <link linkend="boostbook.dtd.function">function</link>| <link linkend="boostbook.dtd.method">method</link>| <link linkend="boostbook.dtd.overloaded-function">overloaded-function</link>| <link linkend="boostbook.dtd.overloaded-method">overloaded-method</link>| <link linkend="boostbook.dtd.data-member">data-member</link>| <link linkend="boostbook.dtd.class">class</link>| <link linkend="boostbook.dtd.class-specialization">class-specialization</link>| <link linkend="boostbook.dtd.struct">struct</link>| <link linkend="boostbook.dtd.struct-specialization">struct-specialization</link>| <link linkend="boostbook.dtd.union">union</link>| <link linkend="boostbook.dtd.union-specialization">union-specialization</link>)*)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>C++ classes and class templates are described via the
+ &lt;class&gt; element. Each class has a name (e.g., "any") given by
+ the <code>name</code> attribute, a purpose given by the
+ &lt;purpose&gt; element, documentation, and a set of types,
+ functions, base classes, and data members. Here is a minimal
+ definition of the <classname>boost::any</classname> class:</para>
+
+ <programlisting>&lt;namespace name="boost"&gt;
+ &lt;class name="any"&gt;
+ &lt;purpose&gt;
+ A class whose instances can hold instances of any type that satisfies
+ ValueType requirements.
+ &lt;/purpose&gt;
+ &lt;/class&gt;
+&lt;/namespace&gt;</programlisting>
+
+ <para>Additional class documentation can be contained in a
+ <sgmltag>description</sgmltag> element following the &lt;purpose&gt;
+ element. This documentation will be typeset prior to documentation
+ for specific elements in the class (e.g., constructors or
+ methods).</para>
+
+ <para>Class inheritance is described via the &lt;inherit&gt;
+ element. The &lt;inherit&gt; element requires an <code>access</code>
+ attribute which must be one of <emphasis>public</emphasis>,
+ <emphasis>protected</emphasis>, or <emphasis>private</emphasis>. The
+ content of the &lt;inherited&gt; element in C++ code that names the
+ class inherited, and may contain markup to link to the class. The
+ following description of the class
+ <classname>boost::bad_any_cast</classname> describes public
+ inheritance from the class <classname>std::bad_cast</classname>. It
+ also defines the &lt;purpose&gt; element, which contains a short
+ description of the use of the class.</para>
+
+ <programlisting>&lt;class name="bad_any_cast"&gt;
+ &lt;inherit access="public"&gt;&lt;classname&gt;std::bad_cast&lt;/classname&gt;&lt;/inherit&gt;
+ &lt;purpose&gt;&lt;para&gt;The exception thrown in the event of a failed
+ &lt;functionname&gt;any_cast&lt;/functionname&gt; of an
+ &lt;classname&gt;any&lt;/classname&gt; value.&lt;/para&gt;&lt;/purpose&gt;
+&lt;/class&gt;</programlisting>
+
+ <para>Class templates are defined by &lt;class&gt; elements with a
+ &lt;template&gt; child element at the beginning.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.librarycategorydef">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>librarycategorydef</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>librarycategorydef</refname>
+ <refpurpose>Defines a new library category</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>librarycategorydef ::=
+ (#PCDATA)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>All library category definitions should be in <filename>doc/src/boost.xml</filename>, and the names of categories must be prefixed with "<code>category:</code>".</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.type">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>type</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>type</refname>
+ <refpurpose>The type of an element or return type of a function</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>type ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.enumvalue">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>enumvalue</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>enumvalue</refname>
+ <refpurpose>A single value of an enumeration</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>enumvalue ::=
+ (<link linkend="boostbook.dtd.default">default</link>?, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.overloaded-method">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>overloaded-method</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>overloaded-method</refname>
+ <refpurpose>An overloaded method</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>overloaded-method ::=
+ (<link linkend="boostbook.dtd.signature">signature</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, <link linkend="boostbook.dtd.requires">requires</link>?, <link linkend="boostbook.dtd.effects">effects</link>?, <link linkend="boostbook.dtd.postconditions">postconditions</link>?, <link linkend="boostbook.dtd.returns">returns</link>?, <link linkend="boostbook.dtd.throws">throws</link>?, <link linkend="boostbook.dtd.complexity">complexity</link>?, <link linkend="boostbook.dtd.notes">notes</link>?, <link linkend="boostbook.dtd.rationale">rationale</link>?)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>General documentation on functions in BoostBook is provided in
+ the <link linkend="boostbook.dtd.function"><sgmltag>function</sgmltag></link>
+ element documentation.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.programlisting">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>programlisting</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>programlisting</refname>
+ <refpurpose>A sample of program code</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>programlisting ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>name</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.complexity">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>complexity</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>complexity</refname>
+ <refpurpose>The time/space/etc. complexity of a function</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>complexity ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.purpose">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>purpose</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>purpose</refname>
+ <refpurpose>A short description of an entity's use</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>purpose ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.template-nontype-parameter">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>template-nontype-parameter</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>template-nontype-parameter</refname>
+ <refpurpose>A nontype template parameter</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>template-nontype-parameter ::=
+ (<link linkend="boostbook.dtd.type">type</link>, <link linkend="boostbook.dtd.default">default</link>?, <link linkend="boostbook.dtd.purpose">purpose</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>pack</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to '1' if the parameter is a parameter pack.</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.library">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>library</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>library</refname>
+ <refpurpose>Top-level element for a library</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>library ::=
+ (<link linkend="boostbook.dtd.libraryinfo">libraryinfo</link>, (title, ((section| <link linkend="boostbook.dtd.library-reference">library-reference</link>| <link linkend="boostbook.dtd.testsuite">testsuite</link>))+)?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>dirname</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry/></row>
+<row><entry>url</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry/></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+<row><entry>html-only</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry/></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.librarycategorylist">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>librarycategorylist</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>librarycategorylist</refname>
+ <refpurpose>Categorized listing of libraries</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>librarycategorylist ::=
+ (<link linkend="boostbook.dtd.librarycategorydef">librarycategorydef</link>)*
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>This element is not intended for use by developers, but is
+ used by <filename>doc/src/boost.xml</filename> as a
+ placeholder.</para>
+</refsection>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.using-namespace">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>using-namespace</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>using-namespace</refname>
+ <refpurpose>Injects the declared names from a namespace into the local scope</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>using-namespace ::=
+ EMPTY
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.enumname">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>enumname</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>enumname</refname>
+ <refpurpose/>
+ </refnamediv>
+ <refsynopsisdiv>enumname ::=
+ (#PCDATA)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>alt</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry/></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.struct-specialization">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>struct-specialization</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>struct-specialization</refname>
+ <refpurpose>A specialization (full or partial) of a struct template</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>struct-specialization ::=
+ (<link linkend="boostbook.dtd.template">template</link>?, <link linkend="boostbook.dtd.specialization">specialization</link>?, <link linkend="boostbook.dtd.inherit">inherit</link>?, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, (<link linkend="boostbook.dtd.access">access</link>| <link linkend="boostbook.dtd.static-constant">static-constant</link>| <link linkend="boostbook.dtd.typedef">typedef</link>| <link linkend="boostbook.dtd.enum">enum</link>| <link linkend="boostbook.dtd.copy-assignment">copy-assignment</link>| <link linkend="boostbook.dtd.constructor">constructor</link>| <link linkend="boostbook.dtd.destructor">destructor</link>| <link linkend="boostbook.dtd.method-group">method-group</link>| <link linkend="boostbook.dtd.free-function-group">free-function-group</link>| <link linkend="boostbook.dtd.function">function</link>| <link linkend="boostbook.dtd.method">method</link>| <link linkend="boostbook.dtd.overloaded-function">overloaded-function</link>| <link linkend="boostbook.dtd.overloaded-method">overloaded-method</link>| <link linkend="boostbook.dtd.data-member">data-member</link>| <link linkend="boostbook.dtd.class">class</link>| <link linkend="boostbook.dtd.class-specialization">class-specialization</link>| <link linkend="boostbook.dtd.struct">struct</link>| <link linkend="boostbook.dtd.struct-specialization">struct-specialization</link>| <link linkend="boostbook.dtd.union">union</link>| <link linkend="boostbook.dtd.union-specialization">union-specialization</link>)*)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.struct">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>struct</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>struct</refname>
+ <refpurpose>Declares a C++ struct</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>struct ::=
+ (<link linkend="boostbook.dtd.template">template</link>?, <link linkend="boostbook.dtd.inherit">inherit</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?, (<link linkend="boostbook.dtd.access">access</link>| <link linkend="boostbook.dtd.static-constant">static-constant</link>| <link linkend="boostbook.dtd.typedef">typedef</link>| <link linkend="boostbook.dtd.enum">enum</link>| <link linkend="boostbook.dtd.copy-assignment">copy-assignment</link>| <link linkend="boostbook.dtd.constructor">constructor</link>| <link linkend="boostbook.dtd.destructor">destructor</link>| <link linkend="boostbook.dtd.method-group">method-group</link>| <link linkend="boostbook.dtd.free-function-group">free-function-group</link>| <link linkend="boostbook.dtd.function">function</link>| <link linkend="boostbook.dtd.method">method</link>| <link linkend="boostbook.dtd.overloaded-function">overloaded-function</link>| <link linkend="boostbook.dtd.overloaded-method">overloaded-method</link>| <link linkend="boostbook.dtd.data-member">data-member</link>| <link linkend="boostbook.dtd.class">class</link>| <link linkend="boostbook.dtd.class-specialization">class-specialization</link>| <link linkend="boostbook.dtd.struct">struct</link>| <link linkend="boostbook.dtd.struct-specialization">struct-specialization</link>| <link linkend="boostbook.dtd.union">union</link>| <link linkend="boostbook.dtd.union-specialization">union-specialization</link>)*)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.lib">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>lib</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>lib</refname>
+ <refpurpose>A library dependency</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>lib ::=
+ (#PCDATA)
+</refsynopsisdiv>
+ <refsection><title>Description</title>
+ <para>Declares a library dependency on the library named by the content of this element, to be emitted in a Jamfile.</para>
+</refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.enum">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>enum</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>enum</refname>
+ <refpurpose>Declares an enumeration type</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>enum ::=
+ (<link linkend="boostbook.dtd.enumvalue">enumvalue</link>*, <link linkend="boostbook.dtd.purpose">purpose</link>?, <link linkend="boostbook.dtd.description">description</link>?)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.requires">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>requires</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>requires</refname>
+ <refpurpose>Declares the requirements of a function</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>requires ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.effects">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>effects</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>effects</refname>
+ <refpurpose>Declares the side effects of a function</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>effects ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.libraryname">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>libraryname</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>libraryname</refname>
+ <refpurpose>References a library of the given name</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>libraryname ::=
+ (#PCDATA)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.libraryinfo">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>libraryinfo</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>libraryinfo</refname>
+ <refpurpose>Provides information about a library</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>libraryinfo ::=
+ (author+, copyright*, legalnotice*, <link linkend="boostbook.dtd.librarypurpose">librarypurpose</link>, <link linkend="boostbook.dtd.librarycategory">librarycategory</link>*)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.testsuite">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>testsuite</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>testsuite</refname>
+ <refpurpose>Describes a library testsuite</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>testsuite ::=
+ ((<link linkend="boostbook.dtd.compile-test">compile-test</link>| <link linkend="boostbook.dtd.link-test">link-test</link>| <link linkend="boostbook.dtd.run-test">run-test</link>| <link linkend="boostbook.dtd.compile-fail-test">compile-fail-test</link>| <link linkend="boostbook.dtd.link-fail-test">link-fail-test</link>| <link linkend="boostbook.dtd.run-fail-test">run-fail-test</link>)+)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.header">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>header</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>header</refname>
+ <refpurpose>Declares a C++ header with the given name</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>header ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>name</entry><entry>#REQUIRED</entry><entry>CDATA</entry><entry>The name of the element being declared to referenced</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+ <refentry id="boostbook.dtd.rationale">
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag>rationale</sgmltag></refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>rationale</refname>
+ <refpurpose>Describes the rationale for a particular function's design</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>rationale ::=
+ (ANY)
+</refsynopsisdiv>
+ <refsection>
+ <title>Attributes</title>
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+
+<row><entry>last-revision</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Set to $Date: 2009-10-10 10:53:46 -0400 (Sat, 10 Oct 2009) $ to keep "last revised" information in sync with CVS changes</entry></row>
+<row><entry>id</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>A global identifier for this element</entry></row>
+<row><entry>xml:base</entry><entry>#IMPLIED</entry><entry>CDATA</entry><entry>Implementation detail used by XIncludes</entry></row>
+</tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </refentry>
+</chapter>
+
diff --git a/tools/boostbook/doc/together.xml b/tools/boostbook/doc/together.xml
new file mode 100644
index 0000000000..2b35b7840c
--- /dev/null
+++ b/tools/boostbook/doc/together.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<chapter xmlns:xi="http://www.w3.org/2001/XInclude" id="boostbook.together"
+ last-revision="$Date: 2009-04-15 03:37:45 -0400 (Wed, 15 Apr 2009) $">
+ <title>Bringing Together a BoostBook Document</title>
+
+ <section id="boostbook.linking">
+ <title>Linking in BoostBook</title>
+
+ <para>How one links to another element in BoostBook depends
+ greatly on the nature of the element linked and how the link
+ should appear. There are three general linking elements:
+ &lt;xref&gt;, &lt;link&gt;, and &lt;ulink&gt;. Additionally, there
+ are linking elements for referencing specific types of entities,
+ such as classes (&lt;classname&gt;), functions
+ (&lt;functionname&gt;), or libraries (&lt;libraryname&gt;).</para>
+
+ <para>The &lt;xref&gt; element references elements that have an
+ <code>id</code> attribute and a title. The actual link text is
+ composed from title and type of the element referenced. To link to
+ a particular ID, create an &lt;xref&gt; element with the
+ <code>linkend</code> attribute set to the ID of the intended
+ target. For instance, this section's ID is
+ <code>boostbook.linking</code>, so we create a reference it to
+ with <code>&lt;xref linkend="boostbook.linking"/&gt;</code>, which
+ will look like this in the text: <xref
+ linkend="boostbook.linking"/>.</para>
+
+ <para>The &lt;link&gt; element references an ID in the same way as
+ &lt;xref&gt;, except that &lt;link&gt; does not generate any text
+ for the link, so text must be supplied within the element. For
+ instance, we can again link to this chapter but this time specify
+ our own text with <code>&lt;link
+ linkend="boostbook.linking"&gt;like this&lt;/link&gt;</code>. This
+ markup will result in a link to this chapter that looks <link
+ linkend="boostbook.linking">like this</link>.</para>
+
+ <para>The &lt;ulink&gt; element references a URL that is outside
+ of the DocBook document. The <code>url</code> attribute contains
+ the URL to link to, and the element data provides the link
+ text.For instance, we can link to the the Boost web site with
+ <code>&lt;ulink
+ url="http://www.boost.org"&gt;Boost&lt;/ulink&gt;,</code> which
+ appears in the document like this: <ulink
+ url="http://www.boost.org">Boost</ulink>.</para>
+
+ <para>In BoostBook, &lt;ulink&gt; supports a custom url schema for
+ linking to files within the boost distribution. This is formed by
+ setting the <code>url</code> attribute to <code>boost:</code>
+ followed by the file's path. For example, we can link to the
+ flyweight library with
+ <code>&lt;ulink
+ url="boost:/libs/flyweight/index.html"&gt;Boost.Flyweight&lt;/ulink&gt;</code>,
+ which will appear like this: <ulink
+ url="boost:/libs/flyweight/index.html">Boost.Flyweight</ulink>.
+ This schema is only supported for BoostBook &lt;ulink&gt; elements.
+ It isn't available for any other elements or in Docbook.</para>
+
+ <para>The &lt;classname&gt;, &lt;functionname&gt;,
+ &lt;methodname&gt;, and &lt;libraryname&gt; link to classes,
+ functions, methods, and libraries, respectively. The text of each
+ element gives both the name of the element to link to and the link
+ text. For instance, we can link to the Function library with
+ <code>&lt;libraryname&gt;Function&lt;/libraryname&gt;</code>,
+ which results in the following:
+ <libraryname>Function</libraryname>. In cases where the displayed
+ text is different from the actual name, the <code>alt</code>
+ attribute can be specified. For instance, the following XML
+ element references the <classname>boost::function</classname>
+ class template but displays the text <classname
+ alt="boost::function">function</classname>: <code>&lt;classname
+ alt="boost::function"&gt;function&lt;/classname&gt;</code>.</para>
+ </section>
+</chapter>
diff --git a/tools/boostbook/dtd/1.1/boost-no-inspect b/tools/boostbook/dtd/1.1/boost-no-inspect
new file mode 100644
index 0000000000..37dfd21c34
--- /dev/null
+++ b/tools/boostbook/dtd/1.1/boost-no-inspect
@@ -0,0 +1,4 @@
+Inspect complains that this directory is called '1.1', but that's the
+standard naming style for DTDs, and this needs to match the url of the
+DTD on the website. Any platform which has problems with this domain
+name probably won't be able to build the documentation anyway. \ No newline at end of file
diff --git a/tools/boostbook/dtd/1.1/boostbook.dtd b/tools/boostbook/dtd/1.1/boostbook.dtd
new file mode 100644
index 0000000000..85a73dd28f
--- /dev/null
+++ b/tools/boostbook/dtd/1.1/boostbook.dtd
@@ -0,0 +1,435 @@
+<!--
+ BoostBook DTD version 1.1
+
+ For further information, see: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost_Documentation_Format
+
+ Copyright (c) 2002 by Peter Simons <simons@cryp.to>
+ Copyright (c) 2003-2004 by Douglas Gregor <doug.gregor -at- gmail.com>
+ Copyright (c) 2007 by Frank Mori Hess <fmhess@users.sourceforge.net>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+ This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+ PUBLIC "-//Boost//DTD BoostBook XML V1.1//EN"
+ SYSTEM "http://www.boost.org/tools/boostbook/dtd/1.1/boostbook.dtd"
+
+ $Revision: 55188 $
+ $Date: 2009-07-26 16:11:03 -0400 (Sun, 26 Jul 2009) $
+-->
+
+<!--========== Define XInclude features. ==========-->
+<!-- This is not really integrated into the DTD yet. Needs more
+ research. -->
+<!--
+<!ELEMENT xi:include (xi:fallback)?>
+<!ATTLIST xi:include
+ xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
+ href CDATA #REQUIRED
+ parse (xml|text) "xml"
+ encoding CDATA #IMPLIED>
+
+<!ELEMENT xi:fallback ANY>
+<!ATTLIST xi:fallback
+ xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
+ -->
+
+<!ENTITY % local.common.attrib "last-revision CDATA #IMPLIED">
+
+<!--========== Define the BoostBook extensions ==========-->
+<!ENTITY % boost.common.attrib "%local.common.attrib;
+ id CDATA #IMPLIED">
+
+<!ENTITY % boost.namespace.mix
+ "class|class-specialization|struct|struct-specialization|
+ union|union-specialization|typedef|enum|
+ free-function-group|function|overloaded-function|
+ namespace">
+
+<!ENTITY % boost.template.mix
+ "template-type-parameter|template-nontype-parameter|template-varargs">
+
+<!ENTITY % boost.class.members
+ "static-constant|typedef|enum|
+ copy-assignment|constructor|destructor|method-group|
+ method|overloaded-method|data-member|class|class-specialization|struct|
+ struct-specialization|union|union-specialization">
+
+<!ENTITY % boost.class.mix
+ "%boost.class.members;|free-function-group|function|overloaded-function">
+
+<!ENTITY % boost.class.content
+ "template?, inherit*, purpose?, description?,
+ (%boost.class.mix;|access)*">
+
+<!ENTITY % boost.class-specialization.content
+ "template?, specialization?, inherit?, purpose?, description?,
+ (%boost.class.mix;|access)*">
+
+<!ENTITY % boost.function.semantics
+ "purpose?, description?, requires?, effects?, postconditions?,
+ returns?, throws?, complexity?, notes?, rationale?">
+
+<!ENTITY % library.content
+ "libraryinfo, (title, ((section|library-reference|testsuite))+)?">
+
+<!ELEMENT library (%library.content;)>
+<!ATTLIST library
+ name CDATA #REQUIRED
+ dirname CDATA #REQUIRED
+ html-only CDATA #IMPLIED
+ url CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT boostbook (title, (chapter|library)*)>
+<!ATTLIST boostbook %boost.common.attrib;>
+
+<!ELEMENT libraryinfo (author+, copyright*, legalnotice*, librarypurpose, librarycategory*)>
+<!ATTLIST libraryinfo %boost.common.attrib;>
+
+<!ELEMENT librarypurpose (#PCDATA|code|ulink|functionname|methodname|classname|macroname|headername|enumname|globalname)*>
+<!ATTLIST librarypurpose %boost.common.attrib;>
+
+<!ELEMENT librarycategory (#PCDATA)>
+<!ATTLIST librarycategory
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT libraryname (#PCDATA)>
+<!ATTLIST libraryname %boost.common.attrib;>
+
+<!ELEMENT library-reference ANY>
+<!ATTLIST library-reference
+ %boost.common.attrib;>
+
+<!ELEMENT librarylist EMPTY>
+<!ATTLIST librarylist %boost.common.attrib;>
+
+<!ELEMENT librarycategorylist (librarycategorydef)*>
+<!ATTLIST librarycategorylist %boost.common.attrib;>
+
+<!ELEMENT librarycategorydef (#PCDATA)>
+<!ATTLIST librarycategorydef
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT header ANY>
+<!ATTLIST header
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT namespace (%boost.namespace.mix;)*>
+<!ATTLIST namespace
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT class (%boost.class.content;)>
+<!ATTLIST class
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT struct (%boost.class.content;)>
+<!ATTLIST struct
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT union (%boost.class.content;)>
+<!ATTLIST union
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT class-specialization (%boost.class-specialization.content;)>
+<!ATTLIST class-specialization
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT struct-specialization (%boost.class-specialization.content;)>
+<!ATTLIST struct-specialization
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT union-specialization (%boost.class-specialization.content;)>
+<!ATTLIST union-specialization
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT access (%boost.class.members;)+>
+<!ATTLIST access
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!--========= C++ Templates =========-->
+<!ELEMENT template (%boost.template.mix;)*>
+<!ATTLIST template %boost.common.attrib;>
+
+<!ELEMENT template-type-parameter (default?, purpose?)>
+<!ATTLIST template-type-parameter
+ name CDATA #REQUIRED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT template-nontype-parameter (type, default?, purpose?)>
+<!ATTLIST template-nontype-parameter
+ name CDATA #REQUIRED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT template-varargs EMPTY>
+<!ATTLIST template-varargs %boost.common.attrib;>
+
+<!ELEMENT specialization (template-arg)*>
+<!ATTLIST specialization %boost.common.attrib;>
+
+<!ELEMENT template-arg ANY>
+<!ATTLIST template-arg
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT default ANY>
+<!ATTLIST default %boost.common.attrib;>
+
+<!ELEMENT inherit (type, purpose?)>
+<!ATTLIST inherit
+ access CDATA #IMPLIED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT purpose ANY>
+<!ATTLIST purpose %boost.common.attrib;>
+
+<!ELEMENT description ANY>
+<!ATTLIST description %boost.common.attrib;>
+
+<!ELEMENT type ANY>
+<!ATTLIST type %boost.common.attrib;>
+
+<!ELEMENT typedef (type, purpose?, description?)>
+<!ATTLIST typedef
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT enum (enumvalue*, purpose?, description?)>
+<!ATTLIST enum
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT enumvalue (default?, purpose?, description?)>
+<!ATTLIST enumvalue
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT static-constant (type, default, purpose?, description?)>
+<!ATTLIST static-constant
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT data-member (type, purpose?, description?)>
+<!ATTLIST data-member
+ name CDATA #REQUIRED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT paramtype ANY>
+<!ATTLIST paramtype %boost.common.attrib;>
+
+<!ELEMENT effects ANY>
+<!ATTLIST effects %boost.common.attrib;>
+
+<!ELEMENT postconditions ANY>
+<!ATTLIST postconditions %boost.common.attrib;>
+
+<!ELEMENT method-group (method|overloaded-method)*>
+<!ATTLIST method-group
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT constructor (template?, parameter*, %boost.function.semantics;)>
+<!ATTLIST constructor
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT destructor (%boost.function.semantics;)>
+<!ATTLIST destructor
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT method (template?, type, parameter*, %boost.function.semantics;)>
+<!ATTLIST method
+ name CDATA #REQUIRED
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT function (template?, type, parameter*, %boost.function.semantics;)>
+<!ATTLIST function
+ name CDATA #REQUIRED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT overloaded-method (signature*, %boost.function.semantics;)>
+<!ATTLIST overloaded-method
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT overloaded-function (signature*, %boost.function.semantics;)>
+<!ATTLIST overloaded-function
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT signature (template?, type, parameter*)>
+<!ATTLIST signature
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT requires ANY>
+<!ATTLIST requires %boost.common.attrib;>
+
+<!ELEMENT returns ANY>
+<!ATTLIST returns %boost.common.attrib;>
+
+<!ELEMENT throws ANY>
+<!ATTLIST throws %boost.common.attrib;>
+
+<!ELEMENT complexity ANY>
+<!ATTLIST complexity %boost.common.attrib;>
+
+<!ELEMENT notes ANY>
+<!ATTLIST notes %boost.common.attrib;>
+
+<!ELEMENT rationale ANY>
+<!ATTLIST rationale %boost.common.attrib;>
+
+<!ELEMENT functionname (#PCDATA)>
+<!ATTLIST functionname
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT enumname (#PCDATA)>
+<!ATTLIST enumname
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT macroname (#PCDATA)>
+<!ATTLIST macroname %boost.common.attrib;>
+
+<!ELEMENT headername (#PCDATA)>
+<!ATTLIST headername %boost.common.attrib;>
+
+<!ELEMENT globalname (#PCDATA)>
+<!ATTLIST globalname
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT copy-assignment
+ (template?, type?, parameter*, %boost.function.semantics;)>
+<!ATTLIST copy-assignment
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT free-function-group (function|overloaded-function)*>
+<!ATTLIST free-function-group
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT precondition ANY>
+<!ATTLIST precondition %boost.common.attrib;>
+
+<!ELEMENT code ANY>
+<!ATTLIST code %boost.common.attrib;>
+
+<!ELEMENT using-namespace EMPTY>
+<!ATTLIST using-namespace
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT using-class EMPTY>
+<!ATTLIST using-class
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!--========== Boost Testsuite Extensions ==========-->
+<!ENTITY % boost.testsuite.tests
+ "compile-test|link-test|run-test|
+ compile-fail-test|link-fail-test|run-fail-test">
+<!ENTITY % boost.testsuite.test.content
+ "source*, lib*, requirement*, purpose, if-fails?">
+
+<!ELEMENT testsuite ((%boost.testsuite.tests;)+)>
+<!ATTLIST testsuite %boost.common.attrib;>
+
+<!ELEMENT compile-test (%boost.testsuite.test.content;)>
+<!ATTLIST compile-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link-test (%boost.testsuite.test.content;)>
+<!ATTLIST link-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT run-test (%boost.testsuite.test.content;)>
+<!ATTLIST run-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT compile-fail-test (%boost.testsuite.test.content;)>
+<!ATTLIST compile-fail-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link-fail-test (%boost.testsuite.test.content;)>
+<!ATTLIST link-fail-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT run-fail-test (%boost.testsuite.test.content;)>
+<!ATTLIST run-fail-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT source (#PCDATA|snippet)*>
+
+<!ELEMENT snippet EMPTY>
+<!ATTLIST snippet
+ name CDATA #REQUIRED>
+
+<!ELEMENT lib (#PCDATA)>
+
+<!ELEMENT requirement (#PCDATA)>
+<!ATTLIST requirement
+ name CDATA #REQUIRED>
+
+<!ELEMENT if-fails ANY>
+
+<!ELEMENT parameter (paramtype, default?, description?)>
+<!ATTLIST parameter
+ name CDATA #IMPLIED
+ pack CDATA #IMPLIED>
+
+<!ELEMENT programlisting ANY>
+<!ATTLIST programlisting
+ name CDATA #IMPLIED>
+
+<!--========== Customize the DocBook DTD ==========-->
+<!ENTITY % local.tech.char.class "|functionname|libraryname|enumname|code">
+<!ENTITY % local.para.class
+ "|using-namespace|using-class|librarylist|librarycategorylist">
+<!ENTITY % local.descobj.class "|libraryinfo">
+<!ENTITY % local.classname.attrib "alt CDATA #IMPLIED">
+<!ENTITY % local.methodname.attrib "alt CDATA #IMPLIED">
+<!ENTITY % local.refentry.class "|library-reference|testsuite">
+<!ENTITY % local.title.char.mix "">
+<!ENTITY % programlisting.module "IGNORE">
+<!ENTITY % parameter.module "IGNORE">
+<!ENTITY % function.module "IGNORE">
+<!ENTITY % type.module "IGNORE">
+
+<!--========== Import DocBook DTD ==========-->
+<!ENTITY % DocBook PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+%DocBook;
diff --git a/tools/boostbook/dtd/boostbook.dtd b/tools/boostbook/dtd/boostbook.dtd
new file mode 100644
index 0000000000..df7db295a1
--- /dev/null
+++ b/tools/boostbook/dtd/boostbook.dtd
@@ -0,0 +1,439 @@
+<!--
+ BoostBook DTD - development version
+
+ For further information, see: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost_Documentation_Format
+
+ Copyright (c) 2002 by Peter Simons <simons@cryp.to>
+ Copyright (c) 2003-2004 by Douglas Gregor <doug.gregor -at- gmail.com>
+ Copyright (c) 2007 by Frank Mori Hess <fmhess@users.sourceforge.net>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+ The latest stable DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+ PUBLIC "-//Boost//DTD BoostBook XML V1.1//EN"
+ SYSTEM "http://www.boost.org/tools/boostbook/dtd/1.1/boostbook.dtd"
+
+ $Revision: 51774 $
+ $Date: 2009-03-14 07:42:38 -0400 (Sat, 14 Mar 2009) $
+-->
+
+<!--========== Define XInclude features. ==========-->
+<!-- This is not really integrated into the DTD yet. Needs more
+ research. -->
+<!--
+<!ELEMENT xi:include (xi:fallback)?>
+<!ATTLIST xi:include
+ xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
+ href CDATA #REQUIRED
+ parse (xml|text) "xml"
+ encoding CDATA #IMPLIED>
+
+<!ELEMENT xi:fallback ANY>
+<!ATTLIST xi:fallback
+ xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
+ -->
+
+<!ENTITY % local.common.attrib "last-revision CDATA #IMPLIED">
+
+<!--========== Define the BoostBook extensions ==========-->
+<!ENTITY % boost.common.attrib "%local.common.attrib;
+ id CDATA #IMPLIED">
+
+<!ENTITY % boost.namespace.mix
+ "class|class-specialization|struct|struct-specialization|
+ union|union-specialization|typedef|enum|
+ free-function-group|function|overloaded-function|
+ namespace">
+
+<!ENTITY % boost.template.mix
+ "template-type-parameter|template-nontype-parameter|template-varargs">
+
+<!ENTITY % boost.class.members
+ "static-constant|typedef|enum|
+ copy-assignment|constructor|destructor|method-group|
+ method|overloaded-method|data-member|class|class-specialization|struct|
+ struct-specialization|union|union-specialization">
+
+<!ENTITY % boost.class.mix
+ "%boost.class.members;|free-function-group|function|overloaded-function">
+
+<!ENTITY % boost.class.content
+ "template?, inherit*, purpose?, description?,
+ (%boost.class.mix;|access)*">
+
+<!ENTITY % boost.class-specialization.content
+ "template?, specialization?, inherit?, purpose?, description?,
+ (%boost.class.mix;|access)*">
+
+<!ENTITY % boost.function.semantics
+ "purpose?, description?, requires?, effects?, postconditions?,
+ returns?, throws?, complexity?, notes?, rationale?">
+
+<!ENTITY % library.content
+ "libraryinfo, (title, ((section|library-reference|testsuite))+)?">
+
+<!ELEMENT library (%library.content;)>
+<!ATTLIST library
+ name CDATA #REQUIRED
+ dirname CDATA #REQUIRED
+ html-only CDATA #IMPLIED
+ url CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT boostbook (title, (chapter|library)*)>
+<!ATTLIST boostbook %boost.common.attrib;>
+
+<!ELEMENT libraryinfo (author+, copyright*, legalnotice*, librarypurpose, librarycategory*)>
+<!ATTLIST libraryinfo %boost.common.attrib;>
+
+<!ELEMENT librarypurpose (#PCDATA|code|ulink|functionname|methodname|classname|macroname|headername|enumname|globalname)*>
+<!ATTLIST librarypurpose %boost.common.attrib;>
+
+<!ELEMENT librarycategory (#PCDATA)>
+<!ATTLIST librarycategory
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT libraryname (#PCDATA)>
+<!ATTLIST libraryname %boost.common.attrib;>
+
+<!ELEMENT library-reference ANY>
+<!ATTLIST library-reference
+ %boost.common.attrib;>
+
+<!ELEMENT librarylist EMPTY>
+<!ATTLIST librarylist %boost.common.attrib;>
+
+<!ELEMENT librarycategorylist (librarycategorydef)*>
+<!ATTLIST librarycategorylist %boost.common.attrib;>
+
+<!ELEMENT librarycategorydef (#PCDATA)>
+<!ATTLIST librarycategorydef
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT header ANY>
+<!ATTLIST header
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT namespace (%boost.namespace.mix;)*>
+<!ATTLIST namespace
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT class (%boost.class.content;)>
+<!ATTLIST class
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT struct (%boost.class.content;)>
+<!ATTLIST struct
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT union (%boost.class.content;)>
+<!ATTLIST union
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT class-specialization (%boost.class-specialization.content;)>
+<!ATTLIST class-specialization
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT struct-specialization (%boost.class-specialization.content;)>
+<!ATTLIST struct-specialization
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT union-specialization (%boost.class-specialization.content;)>
+<!ATTLIST union-specialization
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT access (%boost.class.members;)+>
+<!ATTLIST access
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!--========= C++ Templates =========-->
+<!ELEMENT template (%boost.template.mix;)*>
+<!ATTLIST template %boost.common.attrib;>
+
+<!ELEMENT template-type-parameter (default?, purpose?)>
+<!ATTLIST template-type-parameter
+ name CDATA #REQUIRED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT template-nontype-parameter (type, default?, purpose?)>
+<!ATTLIST template-nontype-parameter
+ name CDATA #REQUIRED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT template-varargs EMPTY>
+<!ATTLIST template-varargs %boost.common.attrib;>
+
+<!ELEMENT specialization (template-arg)*>
+<!ATTLIST specialization %boost.common.attrib;>
+
+<!ELEMENT template-arg ANY>
+<!ATTLIST template-arg
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT default ANY>
+<!ATTLIST default %boost.common.attrib;>
+
+<!ELEMENT inherit (type, purpose?)>
+<!ATTLIST inherit
+ access CDATA #IMPLIED
+ pack CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT purpose ANY>
+<!ATTLIST purpose %boost.common.attrib;>
+
+<!ELEMENT description ANY>
+<!ATTLIST description %boost.common.attrib;>
+
+<!ELEMENT type ANY>
+<!ATTLIST type %boost.common.attrib;>
+
+<!ELEMENT typedef (type, purpose?, description?)>
+<!ATTLIST typedef
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT enum (enumvalue*, purpose?, description?)>
+<!ATTLIST enum
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT enumvalue (default?, purpose?, description?)>
+<!ATTLIST enumvalue
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT static-constant (type, default, purpose?, description?)>
+<!ATTLIST static-constant
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT data-member (type, purpose?, description?)>
+<!ATTLIST data-member
+ name CDATA #REQUIRED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT paramtype ANY>
+<!ATTLIST paramtype %boost.common.attrib;>
+
+<!ELEMENT effects ANY>
+<!ATTLIST effects %boost.common.attrib;>
+
+<!ELEMENT postconditions ANY>
+<!ATTLIST postconditions %boost.common.attrib;>
+
+<!ELEMENT method-group (method|overloaded-method)*>
+<!ATTLIST method-group
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT constructor (template?, parameter*, %boost.function.semantics;)>
+<!ATTLIST constructor
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT destructor (%boost.function.semantics;)>
+<!ATTLIST destructor
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT method (template?, type, parameter*, %boost.function.semantics;)>
+<!ATTLIST method
+ name CDATA #REQUIRED
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT function (template?, type, parameter*, %boost.function.semantics;)>
+<!ATTLIST function
+ name CDATA #REQUIRED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT overloaded-method (signature*, %boost.function.semantics;)>
+<!ATTLIST overloaded-method
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT overloaded-function (signature*, %boost.function.semantics;)>
+<!ATTLIST overloaded-function
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT signature (template?, type, parameter*)>
+<!ATTLIST signature
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT requires ANY>
+<!ATTLIST requires %boost.common.attrib;>
+
+<!ELEMENT returns ANY>
+<!ATTLIST returns %boost.common.attrib;>
+
+<!ELEMENT throws ANY>
+<!ATTLIST throws %boost.common.attrib;>
+
+<!ELEMENT complexity ANY>
+<!ATTLIST complexity %boost.common.attrib;>
+
+<!ELEMENT notes ANY>
+<!ATTLIST notes %boost.common.attrib;>
+
+<!ELEMENT rationale ANY>
+<!ATTLIST rationale %boost.common.attrib;>
+
+<!ELEMENT functionname (#PCDATA)>
+<!ATTLIST functionname
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT enumname (#PCDATA)>
+<!ATTLIST enumname
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT macroname (#PCDATA)>
+<!ATTLIST macroname
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT headername (#PCDATA)>
+<!ATTLIST headername
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT globalname (#PCDATA)>
+<!ATTLIST globalname
+ alt CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT copy-assignment
+ (template?, type?, parameter*, %boost.function.semantics;)>
+<!ATTLIST copy-assignment
+ cv CDATA #IMPLIED
+ specifiers CDATA #IMPLIED
+ %boost.common.attrib;>
+
+<!ELEMENT free-function-group (function|overloaded-function)*>
+<!ATTLIST free-function-group
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT precondition ANY>
+<!ATTLIST precondition %boost.common.attrib;>
+
+<!ELEMENT code ANY>
+<!ATTLIST code %boost.common.attrib;>
+
+<!ELEMENT using-namespace EMPTY>
+<!ATTLIST using-namespace
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!ELEMENT using-class EMPTY>
+<!ATTLIST using-class
+ name CDATA #REQUIRED
+ %boost.common.attrib;>
+
+<!--========== Boost Testsuite Extensions ==========-->
+<!ENTITY % boost.testsuite.tests
+ "compile-test|link-test|run-test|
+ compile-fail-test|link-fail-test|run-fail-test">
+<!ENTITY % boost.testsuite.test.content
+ "source*, lib*, requirement*, purpose, if-fails?">
+
+<!ELEMENT testsuite ((%boost.testsuite.tests;)+)>
+<!ATTLIST testsuite %boost.common.attrib;>
+
+<!ELEMENT compile-test (%boost.testsuite.test.content;)>
+<!ATTLIST compile-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link-test (%boost.testsuite.test.content;)>
+<!ATTLIST link-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT run-test (%boost.testsuite.test.content;)>
+<!ATTLIST run-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT compile-fail-test (%boost.testsuite.test.content;)>
+<!ATTLIST compile-fail-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link-fail-test (%boost.testsuite.test.content;)>
+<!ATTLIST link-fail-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT run-fail-test (%boost.testsuite.test.content;)>
+<!ATTLIST run-fail-test
+ filename CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!ELEMENT source (#PCDATA|snippet)*>
+
+<!ELEMENT snippet EMPTY>
+<!ATTLIST snippet
+ name CDATA #REQUIRED>
+
+<!ELEMENT lib (#PCDATA)>
+
+<!ELEMENT requirement (#PCDATA)>
+<!ATTLIST requirement
+ name CDATA #REQUIRED>
+
+<!ELEMENT if-fails ANY>
+
+<!ELEMENT parameter (paramtype, default?, description?)>
+<!ATTLIST parameter
+ name CDATA #IMPLIED
+ pack CDATA #IMPLIED>
+
+<!ELEMENT programlisting ANY>
+<!ATTLIST programlisting
+ name CDATA #IMPLIED>
+
+<!--========== Customize the DocBook DTD ==========-->
+<!ENTITY % local.tech.char.class "|functionname|libraryname|enumname|headername|macroname|code">
+<!ENTITY % local.para.class
+ "|using-namespace|using-class|librarylist|librarycategorylist">
+<!ENTITY % local.descobj.class "|libraryinfo">
+<!ENTITY % local.classname.attrib "alt CDATA #IMPLIED">
+<!ENTITY % local.methodname.attrib "alt CDATA #IMPLIED">
+<!ENTITY % local.refentry.class "|library-reference|testsuite">
+<!ENTITY % local.title.char.mix "">
+<!ENTITY % programlisting.module "IGNORE">
+<!ENTITY % parameter.module "IGNORE">
+<!ENTITY % function.module "IGNORE">
+<!ENTITY % type.module "IGNORE">
+
+<!--========== Import DocBook DTD ==========-->
+<!ENTITY % DocBook PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+%DocBook;
diff --git a/tools/boostbook/index.html b/tools/boostbook/index.html
new file mode 100644
index 0000000000..5444113a77
--- /dev/null
+++ b/tools/boostbook/index.html
@@ -0,0 +1,21 @@
+<!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">
+<head>
+ <meta http-equiv="refresh" content=
+ "0; URL=../../doc/html/boostbook.html" /><!-- boostinspect:nolink -->
+ <!--
+ Copyright 2006 Rene Rivera.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ -->
+
+ <title></title>
+</head>
+
+<body>
+ Automatic redirection failed, please go to <a href=
+ "../../doc/html/boostbook.html">../../doc/html/boostbook.html</a>
+</body>
+</html>
diff --git a/tools/boostbook/setup_boostbook.py b/tools/boostbook/setup_boostbook.py
new file mode 100644
index 0000000000..b06736afc1
--- /dev/null
+++ b/tools/boostbook/setup_boostbook.py
@@ -0,0 +1,300 @@
+# Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# This is a rewrite of setup_boostbook.sh in Python
+# It will work on Posix and Windows systems
+# The rewrite is not finished yet, so please don't use it
+# right now it is used only be release scripts
+
+# User configuration
+# (MAINTANERS: please, keep in synch with setup_boostbook.sh)
+DOCBOOK_XSL_VERSION = "1.75.2"
+DOCBOOK_DTD_VERSION = "4.2"
+FOP_VERSION = "0.94"
+FOP_JDK_VERSION="1.4"
+# FOP_MIRROR = "http://mirrors.ibiblio.org/pub/mirrors/apache/xmlgraphics/fop/binaries"
+FOP_MIRROR = "http://archive.apache.org/dist/xmlgraphics/fop/binaries/"
+SOURCEFORGE_DOWNLOAD = "http://sourceforge.net/projects/docbook/files"
+
+# No user configuration below this point-------------------------------------
+
+import os
+import re
+import sys
+import optparse
+import shutil
+
+sys.path.append( os.path.join( os.path.dirname( sys.modules[ __name__ ].__file__ )
+ , "../regression/xsl_reports/utils" ) )
+
+import checked_system
+import urllib2
+import tarfile
+import zipfile
+
+def accept_args( args ):
+ parser = optparse.OptionParser()
+ parser.add_option( "-t", "--tools", dest="tools", help="directory downloaded tools will be installed into. Optional. Used by release scripts to put the tools separately from the tree to be archived." )
+ parser.usage = "setup_boostbook [options]"
+
+ ( options, args ) = parser.parse_args( args )
+ if options.tools is None:
+ options.tools = os.getcwd()
+
+
+ return options.tools
+
+def to_posix( path ):
+ return path.replace( "\\", "/" )
+
+def unzip( archive_path, result_dir ):
+ z = zipfile.ZipFile( archive_path, 'r', zipfile.ZIP_DEFLATED )
+ for f in z.infolist():
+ print f.filename
+ if not os.path.exists( os.path.join( result_dir, os.path.dirname( f.filename ) ) ):
+ os.makedirs( os.path.join( result_dir, os.path.dirname( f.filename ) ) )
+ result = open( os.path.join( result_dir, f.filename ), 'wb' )
+ result.write( z.read( f.filename ) )
+ result.close()
+
+ z.close()
+
+def gunzip( archive_path, result_dir ):
+ tar = tarfile.open( archive_path, 'r:gz' )
+ for tarinfo in tar:
+ tar.extract( tarinfo, result_dir )
+ tar.close()
+
+def http_get( file, url ):
+ f = open( file, "wb" )
+ f.write( urllib2.urlopen( url ).read() )
+ f.close()
+
+def find_executable( executable_name, env_variable, test_args, error_message ):
+ print "Looking for %s ..." % executable_name
+ if os.environ.has_key( env_variable ):
+ specified = os.environ[ env_variable ]
+ print " Trying %s specified in env. variable %s" % ( specified, env_variable )
+ if os.path.exists( specified ):
+ return specified.replace( "\\", "/" )
+ else:
+ print "Cannot find %s specified in env. variable %s" % ( specified, env_variable )
+
+ rc = checked_system.system( [ "%s %s" % ( executable_name, test_args ) ] )
+ print ""
+ if rc != 0:
+ print error_message
+ return None
+ else:
+ return executable_name.replace( "\\", "/" )
+
+def adjust_user_config( config_file
+ , docbook_xsl_dir
+ , docbook_dtd_dir
+ , xsltproc
+ , doxygen
+ , fop
+ , java
+ ):
+ print "Modifying user-config.jam ..."
+ r = []
+ using_boostbook = 0
+ eaten=0
+ lines = open( config_file, "r" ).readlines()
+ for line in lines:
+ if re.match( "^\s*using boostbook", line ):
+ using_boostbook = 1
+ r.append( "using boostbook\n" )
+ r.append( " : %s\n" % docbook_xsl_dir )
+ r.append( " : %s\n" % docbook_dtd_dir )
+ r.append( " ; \n" )
+ eaten = 1
+
+ elif using_boostbook == 1 and re.match( ";", line ):
+ using_boostbook = 2
+ elif using_boostbook == 1:
+ eaten=1
+ elif re.match( "^\s*using xsltproc.*$", line ):
+ eaten=1
+ elif re.match( "^\s*using doxygen.*$", line ):
+ eaten=1
+ elif re.match( "^\s*using fop.*$", line ):
+ eaten=1
+ else:
+ if eaten == 0:
+ r.append( line )
+ eaten=0
+
+ if using_boostbook==0:
+ r.append( "using boostbook\n" )
+ r.append( " : %s\n" % docbook_xsl_dir )
+ r.append( " : %s\n" % docbook_dtd_dir )
+ r.append( " ;\n" )
+
+ r.append( "using xsltproc : %s ;\n" % xsltproc )
+ if doxygen is not None:
+ r.append( "using doxygen : %s ;\n" % doxygen )
+ if fop is not None:
+ print r.append( "using fop : %s : : %s ;\n" % ( fop, java ) )
+
+ open( config_file + ".tmp", "w" ).writelines( r )
+ try:
+ os.rename( config_file + ".tmp", config_file )
+ except OSError, e:
+ os.unlink( config_file )
+ os.rename( config_file + ".tmp", config_file )
+
+
+def setup_docbook_xsl( tools_directory ):
+ print "DocBook XSLT Stylesheets ..."
+ DOCBOOK_XSL_TARBALL = os.path.join( tools_directory, "docbook-xsl-%s.tar.gz" % DOCBOOK_XSL_VERSION )
+ DOCBOOK_XSL_URL = "%s/docbook-xsl/%s/%s/download" % (SOURCEFORGE_DOWNLOAD, DOCBOOK_XSL_VERSION, os.path.basename( DOCBOOK_XSL_TARBALL ) )
+
+ if os.path.exists( DOCBOOK_XSL_TARBALL ):
+ print " Using existing DocBook XSLT Stylesheets (version %s)." % DOCBOOK_XSL_VERSION
+ else:
+ print " Downloading DocBook XSLT Stylesheets version %s..." % DOCBOOK_XSL_VERSION
+ print " from %s" % DOCBOOK_XSL_URL
+ http_get( DOCBOOK_XSL_TARBALL, DOCBOOK_XSL_URL )
+
+ DOCBOOK_XSL_DIR = to_posix( os.path.join( tools_directory, "docbook-xsl-%s" % DOCBOOK_XSL_VERSION ) )
+
+ if not os.path.exists( DOCBOOK_XSL_DIR ):
+ print " Expanding DocBook XSLT Stylesheets into %s..." % DOCBOOK_XSL_DIR
+ gunzip( DOCBOOK_XSL_TARBALL, tools_directory )
+ print " done."
+
+ return DOCBOOK_XSL_DIR
+
+def setup_docbook_dtd( tools_directory ):
+ print "DocBook DTD ..."
+ DOCBOOK_DTD_ZIP = to_posix( os.path.join( tools_directory, "docbook-xml-%s.zip" % DOCBOOK_DTD_VERSION ) )
+ DOCBOOK_DTD_URL = "http://www.oasis-open.org/docbook/xml/%s/%s" % ( DOCBOOK_DTD_VERSION, os.path.basename( DOCBOOK_DTD_ZIP ) )
+ if os.path.exists( DOCBOOK_DTD_ZIP ):
+ print " Using existing DocBook XML DTD (version %s)." % DOCBOOK_DTD_VERSION
+ else:
+ print " Downloading DocBook XML DTD version %s..." % DOCBOOK_DTD_VERSION
+ http_get( DOCBOOK_DTD_ZIP, DOCBOOK_DTD_URL )
+
+ DOCBOOK_DTD_DIR = to_posix( os.path.join( tools_directory, "docbook-dtd-%s" % DOCBOOK_DTD_VERSION ) )
+ if not os.path.exists( DOCBOOK_DTD_DIR ):
+ print "Expanding DocBook XML DTD into %s... " % DOCBOOK_DTD_DIR
+ unzip( DOCBOOK_DTD_ZIP, DOCBOOK_DTD_DIR )
+ print "done."
+
+ return DOCBOOK_DTD_DIR
+
+def find_xsltproc():
+ return to_posix( find_executable( "xsltproc", "XSLTPROC", "--version"
+ , "If you have already installed xsltproc, please set the environment\n"
+ + "variable XSLTPROC to the xsltproc executable. If you do not have\n"
+ + "xsltproc, you may download it from http://xmlsoft.org/XSLT/." ) )
+
+def find_doxygen():
+ return to_posix( find_executable( "doxygen", "DOXYGEN", "--version"
+ , "Warning: unable to find Doxygen executable. You will not be able to\n"
+ + " use Doxygen to generate BoostBook documentation. If you have Doxygen,\n"
+ + " please set the DOXYGEN environment variable to the path of the doxygen\n"
+ + " executable." ) )
+
+
+def find_java():
+ return to_posix( find_executable( "java", "JAVA", "-version"
+ , "Warning: unable to find Java executable. You will not be able to\n"
+ + " generate PDF documentation. If you have Java, please set the JAVA\n"
+ + " environment variable to the path of the java executable." ) )
+
+def setup_fop( tools_directory ):
+ print "FOP ..."
+ FOP_TARBALL = os.path.join( tools_directory, "fop-%s-bin-jdk%s.tar.gz" % ( FOP_VERSION, FOP_JDK_VERSION ) )
+ FOP_URL = "%s/%s" % ( FOP_MIRROR, os.path.basename( FOP_TARBALL ) )
+ FOP_DIR = to_posix( "%s/fop-%s" % ( tools_directory, FOP_VERSION ) )
+ if sys.platform == 'win32':
+ fop_driver = "fop.bat"
+ else:
+ fop_driver = "fop"
+
+ FOP = to_posix( os.path.join( FOP_DIR, fop_driver ) )
+
+ if os.path.exists( FOP_TARBALL ) :
+ print " Using existing FOP distribution (version %s)." % FOP_VERSION
+ else:
+ print " Downloading FOP distribution version %s..." % FOP_VERSION
+ http_get( FOP_TARBALL, FOP_URL )
+
+ if not os.path.exists( FOP_DIR ):
+ print " Expanding FOP distribution into %s... " % FOP_DIR
+ gunzip( FOP_TARBALL, tools_directory )
+ print " done."
+
+ return FOP
+
+def find_user_config():
+ print "Looking for user-config.jam ..."
+ JAM_CONFIG_OUT = os.path.join( os.environ[ "HOME" ], "user-config.jam" )
+ if os.path.exists( JAM_CONFIG_OUT ):
+ JAM_CONFIG_IN ="user-config-backup.jam"
+ print " Found user-config.jam in HOME directory (%s)" % JAM_CONFIG_IN
+ shutil.copyfile( JAM_CONFIG_OUT, os.path.join( os.environ[ "HOME" ], "user-config-backup.jam" ) )
+ JAM_CONFIG_IN_TEMP="yes"
+ print " Updating Boost.Jam configuration in %s... " % JAM_CONFIG_OUT
+ return JAM_CONFIG_OUT
+ elif os.environ.has_key( "BOOST_ROOT" ) and os.path.exists( os.path.join( os.environ[ "BOOST_ROOT" ], "tools/build/v2/user-config.jam" ) ):
+ JAM_CONFIG_IN=os.path.join( os.environ[ "BOOST_ROOT" ], "tools/build/v2/user-config.jam" )
+ print " Found user-config.jam in BOOST_ROOT directory (%s)" % JAM_CONFIG_IN
+ JAM_CONFIG_IN_TEMP="no"
+ print " Writing Boost.Jam configuration to %s... " % JAM_CONFIG_OUT
+ return JAM_CONFIG_IN
+ return None
+
+def setup_boostbook( tools_directory ):
+ print "Setting up boostbook tools..."
+ print "-----------------------------"
+ print ""
+
+ DOCBOOK_XSL_DIR = setup_docbook_xsl( tools_directory )
+ DOCBOOK_DTD_DIR = setup_docbook_dtd( tools_directory )
+ XSLTPROC = find_xsltproc()
+ DOXYGEN = find_doxygen()
+ JAVA = find_java()
+
+ FOP = None
+ if JAVA is not None:
+ print "Java is present."
+ FOP = setup_fop( tools_directory )
+
+ user_config = find_user_config()
+
+ # Find the input jamfile to configure
+
+ if user_config is None:
+ print "ERROR: Please set the BOOST_ROOT environment variable to refer to your"
+ print "Boost installation or copy user-config.jam into your home directory."
+ sys.exit()
+
+ adjust_user_config( config_file = user_config
+ , docbook_xsl_dir = DOCBOOK_XSL_DIR
+ , docbook_dtd_dir = DOCBOOK_DTD_DIR
+ , xsltproc = XSLTPROC
+ , doxygen = DOXYGEN
+ , fop = FOP
+ , java = JAVA
+ )
+
+ print "done."
+
+ print "Done! Execute \"bjam --v2\" in a documentation directory to generate"
+ print "documentation with BoostBook. If you have not already, you will need"
+ print "to compile Boost.Jam."
+
+def main():
+ ( tools_directory ) = accept_args( sys.argv[ 1: ] )
+ setup_boostbook( tools_directory )
+
+if __name__ == "__main__":
+ main()
+
+
diff --git a/tools/boostbook/setup_boostbook.sh b/tools/boostbook/setup_boostbook.sh
new file mode 100644
index 0000000000..0e79031573
--- /dev/null
+++ b/tools/boostbook/setup_boostbook.sh
@@ -0,0 +1,181 @@
+#!/bin/sh
+# Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# User configuration
+# (MAINTANERS: please, keep in synch with setup_boostbook.py)
+DOCBOOK_XSL_VERSION=1.75.2
+DOCBOOK_DTD_VERSION=4.2
+FOP_VERSION=0.94
+FOP_JDK_VERSION=1.4
+# FOP_MIRROR=http://mirrors.ibiblio.org/pub/mirrors/apache/xmlgraphics/fop/binaries
+FOP_MIRROR=http://archive.apache.org/dist/xmlgraphics/fop/binaries/
+SOURCEFORGE_DOWNLOAD=http://sourceforge.net/projects/docbook/files/
+HTTP_GET_CMD="curl -O -L"
+
+# No user configuration below this point-------------------------------------
+
+# Get the DocBook XSLT Stylesheets
+DOCBOOK_XSL_TARBALL=docbook-xsl-$DOCBOOK_XSL_VERSION.tar.gz
+DOCBOOK_XSL_URL=$SOURCEFORGE_DOWNLOAD/docbook-xsl/$DOCBOOK_XSL_VERSION/$DOCBOOK_XSL_TARBALL
+if test -f $DOCBOOK_XSL_TARBALL; then
+ echo "Using existing DocBook XSLT Stylesheets (version $DOCBOOK_XSL_VERSION)."
+else
+ echo "Downloading DocBook XSLT Stylesheets version $DOCBOOK_XSL_VERSION..."
+ $HTTP_GET_CMD $DOCBOOK_XSL_URL
+fi
+
+DOCBOOK_XSL_DIR="$PWD/docbook-xsl-$DOCBOOK_XSL_VERSION"
+if test ! -d docbook-xsl-$DOCBOOK_XSL_VERSION; then
+ echo -n "Expanding DocBook XSLT Stylesheets into $DOCBOOK_XSL_DIR..."
+ gunzip -cd $DOCBOOK_XSL_TARBALL | tar xf -
+ echo "done."
+fi
+
+# Get the DocBook DTD
+DOCBOOK_DTD_ZIP=docbook-xml-$DOCBOOK_DTD_VERSION.zip
+DOCBOOK_DTD_URL=http://www.oasis-open.org/docbook/xml/$DOCBOOK_DTD_VERSION/$DOCBOOK_DTD_ZIP
+if test -f $DOCBOOK_DTD_ZIP; then
+ echo "Using existing DocBook XML DTD (version $DOCBOOK_DTD_VERSION)."
+else
+ echo "Downloading DocBook XML DTD version $DOCBOOK_DTD_VERSION..."
+ $HTTP_GET_CMD $DOCBOOK_DTD_URL
+fi
+
+DOCBOOK_DTD_DIR="$PWD/docbook-dtd-$DOCBOOK_DTD_VERSION"
+if test ! -d docbook-dtd-$DOCBOOK_DTD_VERSION; then
+ echo -n "Expanding DocBook XML DTD into $DOCBOOK_DTD_DIR... "
+ unzip -q $DOCBOOK_DTD_ZIP -d $DOCBOOK_DTD_DIR
+ echo "done."
+fi
+
+# Find xsltproc, doxygen, and java
+OLD_IFS=$IFS
+IFS=:
+for dir in $PATH; do
+ if test -f $dir/xsltproc && test -x $dir/xsltproc; then
+ XSLTPROC="$dir/xsltproc"
+ fi
+ if test -f $dir/doxygen && test -x $dir/doxygen; then
+ DOXYGEN="$dir/doxygen"
+ fi
+ if test -f $dir/java && test -x $dir/java; then
+ JAVA="$dir/java"
+ fi
+done
+IFS=$OLD_IFS
+
+# Make sure we have xsltproc
+if test ! -f "$XSLTPROC" && test ! -x "$XSLTPROC"; then
+ echo "Searching for xsltproc... NOT FOUND.";
+ echo "ERROR: Unable to find xsltproc executable."
+ echo "If you have already installed xsltproc, please set the environment"
+ echo "variable XSLTPROC to the xsltproc executable. If you do not have"
+ echo "xsltproc, you may download it from http://xmlsoft.org/XSLT/."
+ exit 0;
+else
+ echo "Searching for xsltproc... $XSLTPROC.";
+fi
+
+# Just notify the user if we haven't found doxygen.
+if test ! -f "$DOXYGEN" && test ! -x "$DOXYGEN"; then
+ echo "Searching for Doxygen... not found.";
+ echo "Warning: unable to find Doxygen executable. You will not be able to"
+ echo " use Doxygen to generate BoostBook documentation. If you have Doxygen,"
+ echo " please set the DOXYGEN environment variable to the path of the doxygen"
+ echo " executable."
+ HAVE_DOXYGEN="no"
+else
+ echo "Searching for Doxygen... $DOXYGEN.";
+ HAVE_DOXYGEN="yes"
+fi
+
+# Just notify the user if we haven't found Java. Otherwise, go get FOP.
+if test ! -f "$JAVA" && test ! -x "$JAVA"; then
+ echo "Searching for Java... not found.";
+ echo "Warning: unable to find Java executable. You will not be able to"
+ echo " generate PDF documentation. If you have Java, please set the JAVA"
+ echo " environment variable to the path of the java executable."
+ HAVE_FOP="no"
+else
+ echo "Searching for Java... $JAVA.";
+ FOP_TARBALL="fop-$FOP_VERSION-bin-jdk$FOP_JDK_VERSION.tar.gz"
+ FOP_URL="$FOP_MIRROR/$FOP_TARBALL"
+ FOP_DIR="$PWD/fop-$FOP_VERSION"
+ FOP="$FOP_DIR/fop"
+ if test -f $FOP_TARBALL; then
+ echo "Using existing FOP distribution (version $FOP_VERSION)."
+ else
+ echo "Downloading FOP distribution version $FOP_VERSION..."
+ $HTTP_GET_CMD $FOP_URL
+ fi
+
+ if test ! -d $FOP_DIR; then
+ echo -n "Expanding FOP distribution into $FOP_DIR... ";
+ gunzip -cd $FOP_TARBALL | tar xf -
+ echo "done.";
+ fi
+ HAVE_FOP="yes"
+fi
+
+# Find the input jamfile to configure
+JAM_CONFIG_OUT="$HOME/user-config.jam"
+if test -r "$HOME/user-config.jam"; then
+ JAM_CONFIG_IN="user-config-backup.jam"
+ cp $JAM_CONFIG_OUT user-config-backup.jam
+ JAM_CONFIG_IN_TEMP="yes"
+ echo -n "Updating Boost.Jam configuration in $JAM_CONFIG_OUT... "
+
+elif test -r "$BOOST_ROOT/tools/build/v2/user-config.jam"; then
+ JAM_CONFIG_IN="$BOOST_ROOT/tools/build/v2/user-config.jam";
+ JAM_CONFIG_IN_TEMP="no"
+ echo -n "Writing Boost.Jam configuration to $JAM_CONFIG_OUT... "
+else
+ echo "ERROR: Please set the BOOST_ROOT environment variable to refer to your"
+ echo "Boost installation or copy user-config.jam into your home directory."
+ exit 0
+fi
+
+cat > setup_boostbook.awk <<EOF
+BEGIN { using_boostbook = 0; eaten=0 }
+
+/^\s*using boostbook/ {
+ using_boostbook = 1;
+ print "using boostbook";
+ print " : $DOCBOOK_XSL_DIR";
+ print " : $DOCBOOK_DTD_DIR";
+ eaten=1
+}
+
+using_boostbook==1 && /;/ { using_boostbook = 2 }
+using_boostbook==1 { eaten=1 }
+
+/^\s*using xsltproc.*$/ { eaten=1 }
+/^\s*using doxygen.*$/ { eaten=1 }
+/^\s*using fop.*$/ { eaten=1 }
+
+/^.*$/ { if (eaten == 0) print; eaten=0 }
+
+END {
+ if (using_boostbook==0) {
+ print "using boostbook";
+ print " : $DOCBOOK_XSL_DIR";
+ print " : $DOCBOOK_DTD_DIR";
+ print " ;"
+ }
+ print "using xsltproc : $XSLTPROC ;"
+ if ("$HAVE_DOXYGEN" == "yes") print "using doxygen : $DOXYGEN ;";
+ if ("$HAVE_FOP" == "yes") print "using fop : $FOP : : $JAVA ;";
+}
+EOF
+
+awk -f setup_boostbook.awk $JAM_CONFIG_IN > $JAM_CONFIG_OUT
+rm -f setup_boostbook.awk
+echo "done."
+
+echo "Done! Execute \"bjam --v2\" in a documentation directory to generate"
+echo "documentation with BoostBook. If you have not already, you will need"
+echo "to compile Boost.Jam."
diff --git a/tools/boostbook/test/Jamfile.v2 b/tools/boostbook/test/Jamfile.v2
new file mode 100644
index 0000000000..4699cd15c1
--- /dev/null
+++ b/tools/boostbook/test/Jamfile.v2
@@ -0,0 +1,13 @@
+# Copyright (c) 2009 Daniel James
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+project boost/test ;
+import boostbook : boostbook ;
+
+boostbook alt : alt.xml :
+ <xsl:param>boost.root=../../../..
+ ;
+
diff --git a/tools/boostbook/test/alt.xml b/tools/boostbook/test/alt.xml
new file mode 100644
index 0000000000..aed8a75f15
--- /dev/null
+++ b/tools/boostbook/test/alt.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright Daniel James 2009
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+-->
+
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+<!--
+ xmllint:
+
+ XML_CATALOG_FILES=../../../bin.v2/boostbook_catalog.xml xmllint -noout -valid alt.xml
+
+-->
+
+<library name="Example" id="test.alt" dirname="test/alt">
+ <libraryinfo>
+ <author>
+ <firstname>Daniel</firstname>
+ <surname>James</surname>
+ </author>
+ <librarypurpose>Fictional example</librarypurpose>
+ </libraryinfo>
+
+ <title>Fictional example library, for testing</title>
+
+ <section id="test.alt.tests">
+ <title>Alt Tests</title>
+
+ <para><headername alt="example.hpp">Example header</headername></para>
+ <para>Example header: <headername>example.hpp</headername></para>
+
+ <para><macroname alt="EXAMPLE">Example macro</macroname></para>
+ <para>Example macro: <macroname>EXAMPLE</macroname></para>
+ </section>
+
+ <library-reference>
+ <header name="example.hpp">
+ <macro name="EXAMPLE" kind="functionlike">
+ <purpose>Example macro</purpose>
+ </macro>
+ </header>
+ </library-reference>
+</library>
diff --git a/tools/boostbook/test/doxygen/Jamfile.v2 b/tools/boostbook/test/doxygen/Jamfile.v2
new file mode 100644
index 0000000000..d9f34f046b
--- /dev/null
+++ b/tools/boostbook/test/doxygen/Jamfile.v2
@@ -0,0 +1,41 @@
+
+# Copyright 2009 Daniel James.
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+using boostbook ;
+using doxygen ;
+import os ;
+
+doxygen autodoc
+ :
+ [ glob boost/*.hpp ]
+ :
+ <xsl:param>"boost.doxygen.reftitle=Example Reference"
+ ;
+
+if [ os.name ] = NT
+{
+ actions compare
+ {
+ comp /A $(>[1]) $(>[2]) && echo "Stamped" >$(<)
+ }
+
+}
+else
+{
+ actions compare
+ {
+ diff -u -w $(>[1]) $(>[2]) && echo "Stamped" >$(<)
+ }
+}
+
+make check : autodoc.xml autodoc.gold : @compare ;
+
+boostbook standalone
+ :
+ example.xml
+ :
+ <xsl:param>boost.root=../../../../..
+ <dependency>autodoc
+ ;
diff --git a/tools/boostbook/test/doxygen/autodoc.gold b/tools/boostbook/test/doxygen/autodoc.gold
new file mode 100644
index 0000000000..8ff920bd0d
--- /dev/null
+++ b/tools/boostbook/test/doxygen/autodoc.gold
@@ -0,0 +1,29 @@
+<?xml version="1.0" standalone="yes"?>
+<library-reference id="example_reference"><title>Example Reference</title><header name="boost/example.hpp"><namespace name="example"><class name="example"><purpose>Documentation for class example. </purpose><class name="inner_class"><data-member name="x"><type>int</type></data-member></class><enum name="class_enum"><enumvalue name="enumerator"/></enum><typedef name="documented_type1"><description><para>This type has documentation. </para></description><type>int</type></typedef><typedef name="documented_type2"><purpose>This type has documentation. </purpose><type>long</type></typedef><typedef name="documented_type3"><description><para>This type has documentation. </para></description><type>long double</type></typedef><typedef name="undocumented_type1"><type>short</type></typedef><typedef name="undocumented_type2"><type>double</type></typedef><data-member name="integer"><type>int</type></data-member><data-member name="mutable_integer" specifiers="mutable"><type>int</type></data-member><data-member name="const_integer"><type>const int</type></data-member><data-member name="static_integer" specifiers="static"><type>int</type></data-member><data-member name="static_const_integer" specifiers="static"><type>const int</type></data-member><method-group name="public member functions"><method name="conversion-operator" cv="" specifiers="explicit"><type>int</type></method></method-group></class><struct name="example_template"><template>
+ <template-type-parameter name="TypeParameter"><purpose><para>A template parameter </para></purpose></template-type-parameter>
+ <template-nontype-parameter name="NonTypeParameter"><type>int</type><purpose><para>This is a non-type template parameter </para></purpose></template-nontype-parameter>
+ <template-type-parameter name="TypeParameterWithDefault"><default>int</default><purpose><para>This is a template parameter with a default argument </para></purpose></template-type-parameter>
+ </template><description><para>Test some doxygen markup</para><para><warning><para>This is just an example.</para></warning>
+Embedded docbook list:</para><para>
+ <orderedlist><listitem><simpara>1</simpara></listitem><listitem><simpara>2</simpara></listitem></orderedlist>
+ </para><para><emphasis>Special</emphasis> <emphasis role="bold">Bold</emphasis> <computeroutput>Typewriter</computeroutput> <emphasis>Italics</emphasis> <emphasis>emphasis</emphasis> <computeroutput>parameter</computeroutput> </para><para><itemizedlist>
+<listitem><para>Arg1 first argument. </para></listitem>
+<listitem><para>Arg2 second argument.</para></listitem>
+</itemizedlist>
+<itemizedlist>
+<listitem><para>First list item. </para></listitem>
+<listitem><para>Second list item</para></listitem>
+</itemizedlist>
+Line 1<sbr/>
+ Line 2</para><para><programlisting> void foo() {}
+</programlisting></para><para>
+</para></description></struct><enum name="namespace_enum"><enumvalue name="enumerator"/></enum><data-member name="namespace_integer"><type>int</type></data-member><data-member name="namespace_static_integer" specifiers="static"><type>int</type></data-member><data-member name="namespace_const_integer"><type>const int</type></data-member><data-member name="namespace_static_const_integer" specifiers="static"><type>const int</type></data-member><function name="namespace_func"><type>int</type><parameter name="i"><paramtype>int</paramtype><description><para>A function parameter </para></description></parameter><parameter name="j"><paramtype>int</paramtype><description><para>Another </para></description></parameter><description><para>
+
+
+This is a test function. <classname alt="example::example">Link to class</classname> <classname alt="example::example_template">Link to class template</classname> <note><para>This is a note.</para></note>
+<para><emphasis role="bold">See Also:</emphasis><para><classname alt="example::example">example::example</classname> and <classname alt="example::example_template">example_template</classname> </para></para>
+</para></description><requires><para>i &gt; j</para></requires><returns><para>The answer </para></returns></function><function name="namespace_func_template"><type>void</type><template>
+ <template-type-parameter name="TypeParameter"><purpose><para>A template parameter </para></purpose></template-type-parameter>
+ <template-nontype-parameter name="NonTypeParameter"><type>int</type><purpose><para>This is a non-type template parameter </para></purpose></template-nontype-parameter>
+ </template><description><para>Testing a function template.
+</para></description></function></namespace><macro name="EXAMPLE" kind="functionlike"><macro-parameter name="m"/><purpose>Documentation for macro example. </purpose></macro></header></library-reference>
diff --git a/tools/boostbook/test/doxygen/boost/example.hpp b/tools/boostbook/test/doxygen/boost/example.hpp
new file mode 100644
index 0000000000..da5d36d85c
--- /dev/null
+++ b/tools/boostbook/test/doxygen/boost/example.hpp
@@ -0,0 +1,139 @@
+
+// Copyright 2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/*!
+ \class example::example
+
+ \brief Documentation for class example
+ */
+
+/*!
+ \def EXAMPLE
+
+ \brief Documentation for macro example
+ */
+
+int global_integer;
+static int global_static_integer;
+const int global_const_integer = 1;
+static const int global_static_const_integer = 2;
+enum global_enum { enumerator1 = 1, enumerator2 };
+
+namespace example
+{
+ int namespace_integer;
+ static int namespace_static_integer;
+ const int namespace_const_integer = 1;
+ static const int namespace_static_const_integer = 2;
+ enum namespace_enum { enumerator };
+
+ class example
+ {
+ public:
+ int integer;
+ static int static_integer;
+ mutable int mutable_integer;
+ const int const_integer;
+ static const int static_const_integer;
+
+ // Visual check of typedef alignment.
+ /** This type has documentation. */
+ typedef int documented_type1;
+ /** \brief This type has documentation. */
+ typedef long documented_type2;
+ /** This type has documentation. */
+ typedef long double documented_type3;
+ typedef short undocumented_type1;
+ typedef double undocumented_type2;
+
+ class inner_class {
+ public:
+ int x;
+ };
+
+ enum class_enum { enumerator };
+
+ /// INTERNAL ONLY
+ enum internal_enum { internal_enumerator };
+
+ explicit operator int();
+ protected:
+ int protected_integer;
+ static int protected_static_integer;
+ mutable int protected_mutable_integer;
+ const int protected_const_integer;
+ static const int protected_static_const_integer;
+
+ enum protected_class_enum { enumerator2 };
+ private:
+ int private_integer;
+ static int private_static_integer;
+ mutable int private_mutable_integer;
+ const int private_const_integer;
+ static const int private_static_const_integer;
+
+ enum private_class_enum { enumerator3 };
+ };
+
+ /**
+ * Test some doxygen markup
+ *
+ * \warning This is just an example.
+ *
+ * Embedded docbook list:
+ *
+ * \xmlonly
+ * <orderedlist><listitem><simpara>1</simpara></listitem><listitem><simpara>2</simpara></listitem></orderedlist>
+ * \endxmlonly
+ *
+ * \a Special \b Bold \c Typewriter \e Italics \em emphasis \p parameter
+ *
+ * \arg Arg1 first argument.
+ * \arg Arg2 second argument.
+ *
+ * \li First list item.
+ * \li Second list item
+ *
+ * Line 1\n
+ * Line 2
+ *
+ * \code
+ * void foo() {}
+ * \endcode
+ *
+ * \tparam TypeParameter A template parameter
+ * \tparam NonTypeParameter This is a non-type template parameter
+ * \tparam TypeParameterWithDefault This is a template parameter with a default argument
+ */
+
+ template <typename TypeParameter, int NonTypeParameter,
+ typename TypeParameterWithDefault = int>
+ struct example_template {};
+
+ /**
+ * \param i A function parameter
+ * \param j Another
+ * \return The answer
+ * \pre i > j
+ *
+ * This is a test function.
+ * \ref example::example "Link to class"
+ * \ref example_template "Link to class template"
+ * \note This is a note.
+ *
+ * \see example::example and example_template
+ */
+ int namespace_func(int i, int j);
+
+ /**
+ * Testing a function template.
+ * \tparam TypeParameter A template parameter
+ * \tparam NonTypeParameter This is a non-type template parameter
+ */
+ template <typename TypeParameter, int NonTypeParameter>
+ void namespace_func_template();
+}
+
+#define EXAMPLE(m) The macro
diff --git a/tools/boostbook/test/doxygen/example.xml b/tools/boostbook/test/doxygen/example.xml
new file mode 100644
index 0000000000..1858ce4c8a
--- /dev/null
+++ b/tools/boostbook/test/doxygen/example.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Copyright Daniel James 2009
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+-->
+
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<library id="example" name="Example" dirname="example" xmlns:xi="http://www.w3.org/2001/XInclude">
+<title>Example</title>
+<xi:include href="autodoc.xml" />
+</library>
diff --git a/tools/boostbook/test/more/run-tests.py b/tools/boostbook/test/more/run-tests.py
new file mode 100755
index 0000000000..2a56795426
--- /dev/null
+++ b/tools/boostbook/test/more/run-tests.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+
+# Copyright 2010 Daniel James.
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+"""Boostbook tests
+
+Usage: python build_docs.py [--generate-gold]
+"""
+
+import difflib, getopt, os, re, sys
+import lxml.ElementInclude
+from lxml import etree
+
+# Globals
+
+def usage_and_exit():
+ print __doc__
+ sys.exit(2)
+
+def main(argv):
+ script_directory = os.path.dirname(sys.argv[0])
+ boostbook_directory = os.path.join(script_directory, "../../xsl")
+
+ try:
+ opts, args = getopt.getopt(argv, "",
+ ["generate-gold"])
+ if(len(args)): usage_and_exit()
+ except getopt.GetoptError:
+ usage_and_exit()
+
+ generate_gold = False
+
+ for opt, arg in opts:
+ if opt == '--generate-gold':
+ generate_gold = True
+
+ # Walk the test directory
+
+ parser = etree.XMLParser()
+
+ try:
+ boostbook_xsl = etree.XSLT(
+ etree.parse(os.path.join(boostbook_directory, "docbook.xsl"), parser)
+ )
+ except lxml.etree.XMLSyntaxError, error:
+ print "Error parsing boostbook xsl:"
+ print error
+ sys.exit(1)
+
+ for root, dirs, files in os.walk(os.path.join(script_directory, 'tests')):
+ for filename in files:
+ (base, ext) = os.path.splitext(filename)
+ if (ext == '.xml'):
+ src_path = os.path.join(root, filename)
+ gold_path = os.path.join(root, base + '.gold')
+ try:
+ doc_text = run_boostbook(parser, boostbook_xsl, src_path)
+ except:
+ # TODO: Need better error reporting here:
+ print "Error running boostbook for " + src_path
+ continue
+
+ if (generate_gold):
+ file = open(gold_path, 'w')
+ try:
+ file.write(doc_text)
+ finally: file.close()
+ else:
+ file = open(gold_path, 'r')
+ try:
+ gold_text = file.read()
+ finally:
+ file.close()
+ compare_xml(filename, doc_text, gold_text)
+
+def run_boostbook(parser, boostbook_xsl, file):
+ doc = boostbook_xsl(etree.parse(file, parser))
+ normalize_boostbook_ids(doc)
+ return etree.tostring(doc)
+
+def normalize_boostbook_ids(doc):
+ ids = {}
+ id_bases = {}
+
+ for node in doc.xpath("//*[starts-with(@id, 'id') or contains(@id, '_id')]"):
+ id = node.get('id')
+
+ if(id in ids):
+ print 'Duplicate id: ' + id
+
+ match = re.match("(id|.+_id)(\d+)((?:-bb)?)", id)
+ if(match):
+ count = 1
+ if(match.group(1) in id_bases):
+ count = id_bases[match.group(1)] + 1
+ id_bases[match.group(1)] = count
+ ids[id] = match.group(1) + str(count) + match.group(3)
+
+ for node in doc.xpath("//*[@linkend or @id]"):
+ x = node.get('linkend')
+ if(x in ids): node.set('linkend', ids[x])
+ x = node.get('id')
+ if(x in ids): node.set('id', ids[x])
+
+def compare_xml(file, doc_text, gold_text):
+ # Had hoped to use xmldiff but it turned out to be a pain to install.
+ # So instead just do a text diff.
+
+ if (doc_text != gold_text):
+ print "Error: " + file
+ print
+ sys.stdout.writelines(
+ difflib.unified_diff(
+ gold_text.splitlines(True),
+ doc_text.splitlines(True)
+ )
+ )
+
+if __name__ == "__main__":
+ main(sys.argv[1:]) \ No newline at end of file
diff --git a/tools/boostbook/test/more/tests/book/boostbook.gold b/tools/boostbook/test/more/tests/book/boostbook.gold
new file mode 100644
index 0000000000..6f07643730
--- /dev/null
+++ b/tools/boostbook/test/more/tests/book/boostbook.gold
@@ -0,0 +1,4 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<book xmlns:xi="http://www.w3.org/2001/XInclude" id="test" lang="en">
+ <title>Test 'boostbook' root.</title>
+</book> \ No newline at end of file
diff --git a/tools/boostbook/test/more/tests/book/boostbook.xml b/tools/boostbook/test/more/tests/book/boostbook.xml
new file mode 100644
index 0000000000..0224eb1b4d
--- /dev/null
+++ b/tools/boostbook/test/more/tests/book/boostbook.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2010 Daniel James.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+-->
+<!DOCTYPE boostbook PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<boostbook id="test" xmlns:xi="http://www.w3.org/2001/XInclude"
+ last-revision="$Date: 2010-10-30 15:29:27 +0100 (Sat, 30 Oct 2010) $"
+ lang="en">
+ <title>Test 'boostbook' root.</title>
+</boostbook>
+
+
diff --git a/tools/boostbook/test/more/tests/book/chapter.gold b/tools/boostbook/test/more/tests/book/chapter.gold
new file mode 100644
index 0000000000..a57055bca9
--- /dev/null
+++ b/tools/boostbook/test/more/tests/book/chapter.gold
@@ -0,0 +1,4 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<chapter id="test" last-revision="$Date: 2010-10-30 15:29:27 +0100 (Sat, 30 Oct 2010) $" lang="en">
+ <title>Test 'boostbook' root.</title>
+</chapter> \ No newline at end of file
diff --git a/tools/boostbook/test/more/tests/book/chapter.xml b/tools/boostbook/test/more/tests/book/chapter.xml
new file mode 100644
index 0000000000..a24c129785
--- /dev/null
+++ b/tools/boostbook/test/more/tests/book/chapter.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2010 Daniel James.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+-->
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<chapter id="test" xmlns:xi="http://www.w3.org/2001/XInclude"
+ last-revision="$Date: 2010-10-30 15:29:27 +0100 (Sat, 30 Oct 2010) $"
+ lang="en">
+ <title>Test 'boostbook' root.</title>
+</chapter>
+
+
diff --git a/tools/boostbook/test/more/tests/book/library-autoid.gold b/tools/boostbook/test/more/tests/book/library-autoid.gold
new file mode 100644
index 0000000000..4a20eb2f23
--- /dev/null
+++ b/tools/boostbook/test/more/tests/book/library-autoid.gold
@@ -0,0 +1,4 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<chapter lang="en" id="id1-bb">
+ <title>Test 'boostbook' root.</title>
+</chapter> \ No newline at end of file
diff --git a/tools/boostbook/test/more/tests/book/library-autoid.xml b/tools/boostbook/test/more/tests/book/library-autoid.xml
new file mode 100644
index 0000000000..6561b66c35
--- /dev/null
+++ b/tools/boostbook/test/more/tests/book/library-autoid.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2010 Daniel James.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+-->
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<library lang="en">
+ <title>Test 'boostbook' root.</title>
+</library>
+
+
diff --git a/tools/boostbook/test/more/tests/book/library.gold b/tools/boostbook/test/more/tests/book/library.gold
new file mode 100644
index 0000000000..5fb2b49cab
--- /dev/null
+++ b/tools/boostbook/test/more/tests/book/library.gold
@@ -0,0 +1,4 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<chapter xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" id="test" rev:last-revision="$Date: 2010-10-30 15:29:27 +0100 (Sat, 30 Oct 2010) $">
+ <title>Test 'boostbook' root.</title>
+</chapter> \ No newline at end of file
diff --git a/tools/boostbook/test/more/tests/book/library.xml b/tools/boostbook/test/more/tests/book/library.xml
new file mode 100644
index 0000000000..25c67d1d5b
--- /dev/null
+++ b/tools/boostbook/test/more/tests/book/library.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2010 Daniel James.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+-->
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<library id="test" xmlns:xi="http://www.w3.org/2001/XInclude"
+ last-revision="$Date: 2010-10-30 15:29:27 +0100 (Sat, 30 Oct 2010) $">
+ <title>Test 'boostbook' root.</title>
+</library>
+
+
diff --git a/tools/boostbook/test/more/tests/libs/array.gold b/tools/boostbook/test/more/tests/libs/array.gold
new file mode 100644
index 0000000000..af1935031a
--- /dev/null
+++ b/tools/boostbook/test/more/tests/libs/array.gold
@@ -0,0 +1,311 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<chapter xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" id="array" rev:last-revision="$Date$">
+ <chapterinfo><author>
+ <firstname>Nicolai</firstname>
+ <surname>Josuttis</surname>
+ </author><copyright>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <year>2004</year>
+ <holder>Nicolai M. Josuttis</holder>
+ </copyright><legalnotice>
+ <para>Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
+ <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
+ </para>
+ </legalnotice></chapterinfo>
+
+ <title>Boost.Array</title>
+
+ <section id="array.intro">
+ <title>Introduction</title>
+
+
+
+
+ <para>The C++ Standard Template Library STL as part of the C++
+ Standard Library provides a framework for processing algorithms on
+ different kind of containers. However, ordinary arrays don't
+ provide the interface of STL containers (although, they provide
+ the iterator interface of STL containers).</para>
+
+ <para>As replacement for ordinary arrays, the STL provides class
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude">std::vector</computeroutput>. However,
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude">std::vector&lt;&gt;</computeroutput> provides
+ the semantics of dynamic arrays. Thus, it manages data to be able
+ to change the number of elements. This results in some overhead in
+ case only arrays with static size are needed.</para>
+
+ <para>In his book, <emphasis>Generic Programming and the
+ STL</emphasis>, Matthew H. Austern introduces a useful wrapper
+ class for ordinary arrays with static size, called
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude">block</computeroutput>. It is safer and has no worse performance than
+ ordinary arrays. In <emphasis>The C++ Programming
+ Language</emphasis>, 3rd edition, Bjarne Stroustrup introduces a
+ similar class, called <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude">c_array</computeroutput>, which I (<ulink url="http://www.josuttis.com">Nicolai Josuttis</ulink>) present
+ slightly modified in my book <emphasis>The C++ Standard Library -
+ A Tutorial and Reference</emphasis>, called
+ <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude">carray</computeroutput>. This is the essence of these approaches
+ spiced with many feedback from <ulink url="http://www.boost.org">boost</ulink>.</para>
+
+ <para>After considering different names, we decided to name this
+ class simply <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost.array">array</link></computeroutput>.</para>
+
+ <para>Note that this class is suggested to be part of the next
+ Technical Report, which will extend the C++ Standard (see
+ <ulink url="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1548.htm">http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1548.htm</ulink>).</para>
+
+ <para>Class <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost.array">array</link></computeroutput> fulfills most
+ but not all of the requirements of "reversible containers" (see
+ Section 23.1, [lib.container.requirements] of the C++
+ Standard). The reasons array is not an reversible STL container is
+ because:
+ <itemizedlist spacing="compact">
+ <listitem><simpara>No constructors are provided.</simpara></listitem>
+ <listitem><simpara>Elements may have an undetermined initial value (see <xref linkend="array.rationale"/>).</simpara></listitem>
+ <listitem><simpara><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="boost.array.swap">swap</link></computeroutput>() has no constant complexity.</simpara></listitem>
+ <listitem><simpara><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="id17-bb">size</link></computeroutput>() is always constant, based on the second template argument of the type.</simpara></listitem>
+ <listitem><simpara>The container provides no allocator support.</simpara></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>It doesn't fulfill the requirements of a "sequence" (see Section 23.1.1, [lib.sequence.reqmts] of the C++ Standard), except that:
+ <itemizedlist spacing="compact">
+ <listitem><simpara><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="id27-bb">front</link></computeroutput>() and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="id30-bb">back</link></computeroutput>() are provided.</simpara></listitem>
+ <listitem><simpara><computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="id21-bb">operator[]</link></computeroutput> and <computeroutput xmlns:xi="http://www.w3.org/2001/XInclude"><link linkend="id24-bb">at</link></computeroutput>() are provided.</simpara></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+
+ <section id="array.reference"><title>Reference</title>
+ <section id="header.boost.array_hpp"><title>Header &lt;<ulink url="../../boost/array.hpp">boost/array.hpp</ulink>&gt;</title><synopsis xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase> <phrase role="keyword">class</phrase> <link linkend="boost.array">array</link><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase> <phrase role="keyword">void</phrase> <link linkend="boost.array.swap"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator=="><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator!="><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id1"><phrase role="keyword">operator</phrase><phrase role="special">&lt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id2"><phrase role="keyword">operator</phrase><phrase role="special">&gt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id1"><phrase role="keyword">operator</phrase><phrase role="special">&lt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id2"><phrase role="keyword">operator</phrase><phrase role="special">&gt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase></synopsis>
+ <refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.array"><refmeta><refentrytitle>Class template array</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::array</refname><refpurpose>STL compliant container wrapper for arrays of constant size</refpurpose></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.array_hpp">boost/array.hpp</link>&gt;
+
+</phrase><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <link linkend="boost.array">array</link> <phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="comment">// types</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <anchor id="boost.array.value_type"/><phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <anchor id="boost.array.iterator"/><phrase role="identifier">iterator</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <anchor id="boost.array.const_iterator"/><phrase role="identifier">const_iterator</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> std::reverse_iterator<phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">&gt;</phrase> <anchor id="boost.array.reverse_iterator"/><phrase role="identifier">reverse_iterator</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> std::reverse_iterator<phrase role="special">&lt;</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">&gt;</phrase> <anchor id="boost.array.const_reverse_iterator"/><phrase role="identifier">const_reverse_iterator</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <anchor id="boost.array.reference"/><phrase role="identifier">reference</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <anchor id="boost.array.const_reference"/><phrase role="identifier">const_reference</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="boost.array.size_type"/><phrase role="identifier">size_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ptrdiff_t</phrase> <anchor id="boost.array.difference_type"/><phrase role="identifier">difference_type</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// static constants</phrase>
+ <phrase role="keyword">static</phrase> <phrase role="keyword">const</phrase> <phrase role="identifier">size_type</phrase> <phrase role="identifier">static_size</phrase> = <phrase role="identifier">N</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="boost.arrayconstruct-copy-destruct">construct/copy/destruct</link></phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> U<phrase role="special">&gt;</phrase> array&amp; <link linkend="id1-bb"><phrase role="keyword">operator</phrase><phrase role="special">=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id2-bb">iterator support</link></phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id4-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id5-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id7-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id8-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id9-bb">reverse iterator support</link></phrase>
+ <phrase role="identifier">reverse_iterator</phrase> <link linkend="id11-bb"><phrase role="identifier">rbegin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_reverse_iterator</phrase> <link linkend="id12-bb"><phrase role="identifier">rbegin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">reverse_iterator</phrase> <link linkend="id14-bb"><phrase role="identifier">rend</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_reverse_iterator</phrase> <link linkend="id15-bb"><phrase role="identifier">rend</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id16-bb">capacity</link></phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id17-bb"><phrase role="identifier">size</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="id18-bb"><phrase role="identifier">empty</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id19-bb"><phrase role="identifier">max_size</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id20-bb">element access</link></phrase>
+ <phrase role="identifier">reference</phrase> <link linkend="id22-bb"><phrase role="keyword">operator</phrase><phrase role="special">[</phrase><phrase role="special">]</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_reference</phrase> <link linkend="id23-bb"><phrase role="keyword">operator</phrase><phrase role="special">[</phrase><phrase role="special">]</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">reference</phrase> <link linkend="id25-bb"><phrase role="identifier">at</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_reference</phrase> <link linkend="id26-bb"><phrase role="identifier">at</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">reference</phrase> <link linkend="id28-bb"><phrase role="identifier">front</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_reference</phrase> <link linkend="id29-bb"><phrase role="identifier">front</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">reference</phrase> <link linkend="id31-bb"><phrase role="identifier">back</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_reference</phrase> <link linkend="id32-bb"><phrase role="identifier">back</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <link linkend="id33-bb"><phrase role="identifier">data</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <link linkend="id34-bb"><phrase role="identifier">c_array</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id35-bb">modifiers</link></phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id36-bb"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id37-bb"><phrase role="identifier">assign</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// public data members</phrase>
+ <phrase role="identifier">T</phrase> <phrase role="identifier">elems[N]</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase>
+
+<phrase role="comment">// <link linkend="id38-bb">specialized algorithms</link></phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase> <phrase role="keyword">void</phrase> <link linkend="boost.array.swap"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+<phrase role="comment">// <link linkend="id39-bb">comparisons</link></phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator=="><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator!="><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id1"><phrase role="keyword">operator</phrase><phrase role="special">&lt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_id2"><phrase role="keyword">operator</phrase><phrase role="special">&gt;</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id1"><phrase role="keyword">operator</phrase><phrase role="special">&lt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.array.operator_=_id2"><phrase role="keyword">operator</phrase><phrase role="special">&gt;=</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><refsect2><title><anchor id="boost.arrayconstruct-copy-destruct"/><computeroutput>array</computeroutput>
+ public
+ construct/copy/destruct</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> U<phrase role="special">&gt;</phrase> array&amp; <anchor id="id1-bb"/><phrase role="keyword">operator</phrase><phrase role="special">=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">U</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> other<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><simpara><computeroutput>std::copy(rhs.<link linkend="id3-bb">begin</link>(),rhs.<link linkend="id6-bb">end</link>(), <link linkend="id3-bb">begin</link>())</computeroutput></simpara></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id2-bb"/><computeroutput>array</computeroutput> iterator support</title><orderedlist><listitem><para><literallayout class="monospaced"><anchor id="id3-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id4-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id5-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara>iterator for the first element</simpara></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><simpara>will not throw</simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id6-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id7-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id8-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara>iterator for position after the last element</simpara></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><simpara>will not throw</simpara></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id9-bb"/><computeroutput>array</computeroutput> reverse iterator support</title><orderedlist><listitem><para><literallayout class="monospaced"><anchor id="id10-bb"/><phrase role="identifier">reverse_iterator</phrase> <anchor id="id11-bb"/><phrase role="identifier">rbegin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_reverse_iterator</phrase> <anchor id="id12-bb"/><phrase role="identifier">rbegin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara>reverse iterator for the first element of reverse iteration</simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id13-bb"/><phrase role="identifier">reverse_iterator</phrase> <anchor id="id14-bb"/><phrase role="identifier">rend</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_reverse_iterator</phrase> <anchor id="id15-bb"/><phrase role="identifier">rend</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara>reverse iterator for position after the last element in reverse iteration</simpara></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id16-bb"/><computeroutput>array</computeroutput> capacity</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id17-bb"/><phrase role="identifier">size</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>N</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">bool</phrase> <anchor id="id18-bb"/><phrase role="identifier">empty</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>N==0</computeroutput></simpara></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><simpara>will not throw</simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id19-bb"/><phrase role="identifier">max_size</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>N</computeroutput></simpara></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><simpara>will not throw</simpara></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id20-bb"/><computeroutput>array</computeroutput> element access</title><orderedlist><listitem><para><literallayout class="monospaced"><anchor id="id21-bb"/><phrase role="identifier">reference</phrase> <anchor id="id22-bb"/><phrase role="keyword">operator</phrase><phrase role="special">[</phrase><phrase role="special">]</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> i<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_reference</phrase> <anchor id="id23-bb"/><phrase role="keyword">operator</phrase><phrase role="special">[</phrase><phrase role="special">]</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> i<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><simpara><computeroutput>i &lt; N</computeroutput></simpara></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><simpara>element with index <computeroutput>i</computeroutput></simpara></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><simpara>will not throw.</simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id24-bb"/><phrase role="identifier">reference</phrase> <anchor id="id25-bb"/><phrase role="identifier">at</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> i<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_reference</phrase> <anchor id="id26-bb"/><phrase role="identifier">at</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> i<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara>element with index <computeroutput>i</computeroutput></simpara></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><simpara><computeroutput>std::range_error</computeroutput> if <computeroutput>i &gt;= N</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id27-bb"/><phrase role="identifier">reference</phrase> <anchor id="id28-bb"/><phrase role="identifier">front</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_reference</phrase> <anchor id="id29-bb"/><phrase role="identifier">front</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><simpara><computeroutput>N &gt; 0</computeroutput></simpara></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><simpara>the first element</simpara></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><simpara>will not throw</simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id30-bb"/><phrase role="identifier">reference</phrase> <anchor id="id31-bb"/><phrase role="identifier">back</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_reference</phrase> <anchor id="id32-bb"/><phrase role="identifier">back</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><simpara><computeroutput>N &gt; 0</computeroutput></simpara></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><simpara>the last element</simpara></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><simpara>will not throw</simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">*</phrase> <anchor id="id33-bb"/><phrase role="identifier">data</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>elems</computeroutput></simpara></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><simpara>will not throw</simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <anchor id="id34-bb"/><phrase role="identifier">c_array</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>elems</computeroutput></simpara></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><simpara>will not throw</simpara></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id35-bb"/><computeroutput>array</computeroutput> modifiers</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id36-bb"/><phrase role="identifier">swap</phrase><phrase role="special">(</phrase><link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> other<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><simpara><computeroutput>std::swap_ranges(<link linkend="id3-bb">begin</link>(), <link linkend="id6-bb">end</link>(), other.<link linkend="id3-bb">begin</link>())</computeroutput></simpara></listitem></varlistentry><varlistentry><term>Complexity:</term><listitem><simpara>linear in <computeroutput>N</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id37-bb"/><phrase role="identifier">assign</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> value<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><simpara><computeroutput>std::fill_n(<link linkend="id3-bb">begin</link>(), N, value)</computeroutput></simpara></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id38-bb"/><computeroutput>array</computeroutput> specialized algorithms</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase> <phrase role="keyword">void</phrase> <anchor id="boost.array.swap"/><phrase role="identifier">swap</phrase><phrase role="special">(</phrase><link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><simpara><computeroutput>x.<link linkend="id36-bb">swap</link>(y)</computeroutput></simpara></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><simpara>will not throw.</simpara></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id39-bb"/><computeroutput>array</computeroutput> comparisons</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator=="/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>std::equal(x.<link linkend="id3-bb">begin</link>(), x.<link linkend="id6-bb">end</link>(), y.<link linkend="id3-bb">begin</link>())</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator!="/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>!(x == y)</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_id1"/><phrase role="keyword">operator</phrase><phrase role="special">&lt;</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>std::lexicographical_compare(x.<link linkend="id3-bb">begin</link>(), x.<link linkend="id6-bb">end</link>(), y.<link linkend="id3-bb">begin</link>(), y.<link linkend="id6-bb">end</link>())</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_id2"/><phrase role="keyword">operator</phrase><phrase role="special">&gt;</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>y &lt; x</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_=_id1"/><phrase role="keyword">operator</phrase><phrase role="special">&lt;=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>!(y &lt; x)</computeroutput></simpara></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> N<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.array.operator_=_id2"/><phrase role="keyword">operator</phrase><phrase role="special">&gt;=</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="keyword">const</phrase> <link linkend="boost.array">array</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">N</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><simpara><computeroutput>!(x &lt; y)</computeroutput></simpara></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2></refsect1></refentry>
+ </section>
+ </section>
+
+<section id="array.rationale">
+ <title>Design Rationale</title>
+
+ <para>There was an important design tradeoff regarding the
+ constructors: We could implement array as an "aggregate" (see
+ Section 8.5.1, [dcl.init.aggr], of the C++ Standard). This would
+ mean:
+ <itemizedlist>
+ <listitem><simpara>An array can be initialized with a
+ brace-enclosing, comma-separated list of initializers for the
+ elements of the container, written in increasing subscript
+ order:</simpara>
+
+ <programlisting xmlns:xi="http://www.w3.org/2001/XInclude"><computeroutput><link linkend="boost.array">boost::array</link></computeroutput>&lt;int,4&gt; a = { { 1, 2, 3 } };</programlisting>
+
+ <simpara>Note that if there are fewer elements in the
+ initializer list, then each remaining element gets
+ default-initialized (thus, it has a defined value).</simpara>
+ </listitem></itemizedlist></para>
+
+ <para>However, this approach has its drawbacks: <emphasis role="bold"> passing no initializer list means that the elements
+ have an indetermined initial value</emphasis>, because the rule says
+ that aggregates may have:
+ <itemizedlist>
+ <listitem><simpara>No user-declared constructors.</simpara></listitem>
+ <listitem><simpara>No private or protected non-static data members.</simpara></listitem>
+ <listitem><simpara>No base classes.</simpara></listitem>
+ <listitem><simpara>No virtual functions.</simpara></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>Nevertheless, The current implementation uses this approach.</para>
+
+ <para>Note that for standard conforming compilers it is possible to
+ use fewer braces (according to 8.5.1 (11) of the Standard). That is,
+ you can initialize an array as follows:</para>
+
+<programlisting xmlns:xi="http://www.w3.org/2001/XInclude">
+<computeroutput><link linkend="boost.array">boost::array</link></computeroutput>&lt;int,4&gt; a = { 1, 2, 3 };
+</programlisting>
+
+ <para>I'd appreciate any constructive feedback. <emphasis role="bold">Please note: I don't have time to read all boost
+ mails. Thus, to make sure that feedback arrives to me, please send
+ me a copy of each mail regarding this class.</emphasis></para>
+
+ <para>The code is provided "as is" without expressed or implied
+ warranty.</para>
+
+</section>
+
+<section id="array.more.info">
+ <title>For more information...</title>
+ <para>To find more details about using ordinary arrays in C++ and
+ the framework of the STL, see e.g.
+
+ <literallayout>The C++ Standard Library - A Tutorial and Reference
+by Nicolai M. Josuttis
+Addison Wesley Longman, 1999
+ISBN 0-201-37926-0</literallayout>
+ </para>
+
+ <para><ulink url="http://www.josuttis.com/">Home Page of Nicolai
+ Josuttis</ulink></para>
+</section>
+
+<section id="array.ack">
+ <title>Acknowledgements</title>
+
+ <para>Doug Gregor ported the documentation to the BoostBook format.</para>
+</section>
+
+
+
+</chapter> \ No newline at end of file
diff --git a/tools/boostbook/test/more/tests/libs/array.xml b/tools/boostbook/test/more/tests/libs/array.xml
new file mode 100644
index 0000000000..ee4cbca863
--- /dev/null
+++ b/tools/boostbook/test/more/tests/libs/array.xml
@@ -0,0 +1,553 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2010 Daniel James.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+-->
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<library name="Array" dirname="array" id="array" last-revision="$Date$">
+ <libraryinfo>
+ <author>
+ <firstname>Nicolai</firstname>
+ <surname>Josuttis</surname>
+ </author>
+
+ <copyright>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <year>2004</year>
+ <holder>Nicolai M. Josuttis</holder>
+ </copyright>
+
+ <legalnotice>
+ <para>Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
+ <ulink
+ url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
+ </para>
+ </legalnotice>
+
+ <librarypurpose>STL compliant container wrapper for arrays of constant size</librarypurpose>
+ <librarycategory name="category:containers"/>
+ </libraryinfo>
+
+ <title>Boost.Array</title>
+
+ <section id="array.intro">
+ <title>Introduction</title>
+
+ <using-namespace name="boost"/>
+ <using-class name="array"/>
+
+ <para>The C++ Standard Template Library STL as part of the C++
+ Standard Library provides a framework for processing algorithms on
+ different kind of containers. However, ordinary arrays don't
+ provide the interface of STL containers (although, they provide
+ the iterator interface of STL containers).</para>
+
+ <para>As replacement for ordinary arrays, the STL provides class
+ <code><classname>std::vector</classname></code>. However,
+ <code><classname>std::vector&lt;&gt;</classname></code> provides
+ the semantics of dynamic arrays. Thus, it manages data to be able
+ to change the number of elements. This results in some overhead in
+ case only arrays with static size are needed.</para>
+
+ <para>In his book, <emphasis>Generic Programming and the
+ STL</emphasis>, Matthew H. Austern introduces a useful wrapper
+ class for ordinary arrays with static size, called
+ <code>block</code>. It is safer and has no worse performance than
+ ordinary arrays. In <emphasis>The C++ Programming
+ Language</emphasis>, 3rd edition, Bjarne Stroustrup introduces a
+ similar class, called <code>c_array</code>, which I (<ulink
+ url="http://www.josuttis.com">Nicolai Josuttis</ulink>) present
+ slightly modified in my book <emphasis>The C++ Standard Library -
+ A Tutorial and Reference</emphasis>, called
+ <code>carray</code>. This is the essence of these approaches
+ spiced with many feedback from <ulink
+ url="http://www.boost.org">boost</ulink>.</para>
+
+ <para>After considering different names, we decided to name this
+ class simply <code><classname>array</classname></code>.</para>
+
+ <para>Note that this class is suggested to be part of the next
+ Technical Report, which will extend the C++ Standard (see
+ <ulink url="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1548.htm">http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1548.htm</ulink>).</para>
+
+ <para>Class <code><classname>array</classname></code> fulfills most
+ but not all of the requirements of "reversible containers" (see
+ Section 23.1, [lib.container.requirements] of the C++
+ Standard). The reasons array is not an reversible STL container is
+ because:
+ <itemizedlist spacing="compact">
+ <listitem><simpara>No constructors are provided.</simpara></listitem>
+ <listitem><simpara>Elements may have an undetermined initial value (see <xref linkend="array.rationale"/>).</simpara></listitem>
+ <listitem><simpara><functionname>swap</functionname>() has no constant complexity.</simpara></listitem>
+ <listitem><simpara><methodname>size</methodname>() is always constant, based on the second template argument of the type.</simpara></listitem>
+ <listitem><simpara>The container provides no allocator support.</simpara></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>It doesn't fulfill the requirements of a "sequence" (see Section 23.1.1, [lib.sequence.reqmts] of the C++ Standard), except that:
+ <itemizedlist spacing="compact">
+ <listitem><simpara><methodname>front</methodname>() and <methodname>back</methodname>() are provided.</simpara></listitem>
+ <listitem><simpara><methodname>operator[]</methodname> and <methodname>at</methodname>() are provided.</simpara></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+
+ <library-reference>
+ <header name="boost/array.hpp">
+ <namespace name="boost">
+ <class name="array">
+ <template>
+ <template-type-parameter name="T"/>
+ <template-nontype-parameter name="N">
+ <type>std::size_t</type>
+ </template-nontype-parameter>
+ </template>
+
+ <purpose><para>STL compliant container wrapper for arrays of constant size</para></purpose>
+ <typedef name="value_type">
+ <type>T</type>
+ </typedef>
+ <typedef name="iterator">
+ <type>T*</type>
+ </typedef>
+ <typedef name="const_iterator">
+ <type>const T*</type>
+ </typedef>
+ <typedef name="reverse_iterator">
+ <type><classname>std::reverse_iterator</classname>&lt;iterator&gt;</type>
+ </typedef>
+ <typedef name="const_reverse_iterator">
+ <type><classname>std::reverse_iterator</classname>&lt;const_iterator&gt;</type>
+ </typedef>
+ <typedef name="reference">
+ <type>T&amp;</type>
+ </typedef>
+ <typedef name="const_reference">
+ <type>const T&amp;</type>
+ </typedef>
+ <typedef name="size_type">
+ <type>std::size_t</type>
+ </typedef>
+ <typedef name="difference_type">
+ <type>std::ptrdiff_t</type>
+ </typedef>
+
+ <static-constant name="static_size">
+ <type>size_type</type>
+ <default>N</default>
+ </static-constant>
+
+ <copy-assignment>
+ <template>
+ <template-type-parameter name="U"/>
+ </template>
+ <parameter name="other">
+ <paramtype>const <classname>array</classname>&lt;U, N&gt;&amp;</paramtype>
+ </parameter>
+ <effects><simpara><code>std::copy(rhs.<methodname>begin</methodname>(),rhs.<methodname>end</methodname>(), <methodname>begin</methodname>())</code></simpara></effects>
+ </copy-assignment>
+
+ <method-group name="iterator support">
+ <overloaded-method name="begin">
+ <signature>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <type>const_iterator</type>
+ </signature>
+
+ <returns><simpara>iterator for the first element</simpara></returns>
+ <throws><simpara>will not throw</simpara></throws>
+ </overloaded-method>
+
+ <overloaded-method name="end">
+ <signature>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <type>const_iterator</type>
+ </signature>
+
+ <returns><simpara>iterator for position after the last element</simpara></returns>
+ <throws><simpara>will not throw</simpara></throws>
+ </overloaded-method>
+ </method-group>
+
+ <method-group name="reverse iterator support">
+ <overloaded-method name="rbegin">
+ <signature>
+ <type>reverse_iterator</type>
+ </signature>
+ <signature cv="const">
+ <type>const_reverse_iterator</type>
+ </signature>
+
+ <returns><simpara>reverse iterator for the first element of reverse iteration</simpara></returns>
+ </overloaded-method>
+
+ <overloaded-method name="rend">
+ <signature>
+ <type>reverse_iterator</type>
+ </signature>
+ <signature cv="const">
+ <type>const_reverse_iterator</type>
+ </signature>
+
+ <returns><simpara>reverse iterator for position after the last element in reverse iteration</simpara></returns>
+ </overloaded-method>
+ </method-group>
+
+ <method-group name="capacity">
+ <method name="size">
+ <type>size_type</type>
+ <returns><simpara><code>N</code></simpara></returns>
+ </method>
+ <method name="empty">
+ <type>bool</type>
+ <returns><simpara><code>N==0</code></simpara></returns>
+ <throws><simpara>will not throw</simpara></throws>
+ </method>
+ <method name="max_size">
+ <type>size_type</type>
+ <returns><simpara><code>N</code></simpara></returns>
+ <throws><simpara>will not throw</simpara></throws>
+ </method>
+ </method-group>
+
+ <method-group name="element access">
+ <overloaded-method name="operator[]">
+ <signature>
+ <type>reference</type>
+ <parameter name="i">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ </signature>
+
+ <signature cv="const">
+ <type>const_reference</type>
+ <parameter name="i">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ </signature>
+
+ <requires><simpara><code>i &lt; N</code></simpara></requires>
+ <returns><simpara>element with index <code>i</code></simpara></returns>
+ <throws><simpara>will not throw.</simpara></throws>
+ </overloaded-method>
+
+ <overloaded-method name="at">
+ <signature>
+ <type>reference</type>
+ <parameter name="i">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ </signature>
+
+ <signature cv="const">
+ <type>const_reference</type>
+ <parameter name="i">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ </signature>
+
+ <returns><simpara>element with index <code>i</code></simpara></returns>
+ <throws><simpara><code><classname>std::range_error</classname></code> if <code>i &gt;= N</code></simpara></throws>
+ </overloaded-method>
+
+ <overloaded-method name="front">
+ <signature>
+ <type>reference</type>
+ </signature>
+ <signature cv="const">
+ <type>const_reference</type>
+ </signature>
+ <requires><simpara><code>N &gt; 0</code></simpara></requires>
+ <returns><simpara>the first element</simpara></returns>
+ <throws><simpara>will not throw</simpara></throws>
+ </overloaded-method>
+
+ <overloaded-method name="back">
+ <signature>
+ <type>reference</type>
+ </signature>
+ <signature cv="const">
+ <type>const_reference</type>
+ </signature>
+ <requires><simpara><code>N &gt; 0</code></simpara></requires>
+ <returns><simpara>the last element</simpara></returns>
+ <throws><simpara>will not throw</simpara></throws>
+ </overloaded-method>
+
+ <method name="data" cv="const">
+ <type>const T*</type>
+ <returns><simpara><code>elems</code></simpara></returns>
+ <throws><simpara>will not throw</simpara></throws>
+ </method>
+
+ <method name="c_array">
+ <type>T*</type>
+ <returns><simpara><code>elems</code></simpara></returns>
+ <throws><simpara>will not throw</simpara></throws>
+ </method>
+ </method-group>
+
+ <method-group name="modifiers">
+ <method name="swap">
+ <type>void</type>
+ <parameter name="other">
+ <paramtype><classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+ <effects><simpara><code>std::swap_ranges(<methodname>begin</methodname>(), <methodname>end</methodname>(), other.<methodname>begin</methodname>())</code></simpara></effects>
+ <complexity><simpara>linear in <code>N</code></simpara></complexity>
+ </method>
+ <method name="assign">
+ <type>void</type>
+ <parameter name="value">
+ <paramtype>const T&amp;</paramtype>
+ </parameter>
+ <effects><simpara><code>std::fill_n(<methodname>begin</methodname>(), N, value)</code></simpara></effects>
+ </method>
+ </method-group>
+
+ <data-member name="elems[N]"> <!-- HACK -->
+ <type>T</type>
+ </data-member>
+
+ <free-function-group name="specialized algorithms">
+ <function name="swap">
+ <template>
+ <template-type-parameter name="T"/>
+ <template-nontype-parameter name="N">
+ <type>std::size_t</type>
+ </template-nontype-parameter>
+ </template>
+
+ <type>void</type>
+
+ <parameter name="x">
+ <paramtype><classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype><classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+
+ <effects><simpara><code>x.<methodname>swap</methodname>(y)</code></simpara></effects>
+ <throws><simpara>will not throw.</simpara></throws>
+ </function>
+ </free-function-group>
+
+ <free-function-group name="comparisons">
+ <function name="operator==">
+ <template>
+ <template-type-parameter name="T"/>
+ <template-nontype-parameter name="N">
+ <type>std::size_t</type>
+ </template-nontype-parameter>
+ </template>
+
+ <type>bool</type>
+
+ <parameter name="x">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+
+ <returns><simpara><code>std::equal(x.<methodname>begin</methodname>(), x.<methodname>end</methodname>(), y.<methodname>begin</methodname>())</code></simpara>
+ </returns>
+ </function>
+
+ <function name="operator!=">
+ <template>
+ <template-type-parameter name="T"/>
+ <template-nontype-parameter name="N">
+ <type>std::size_t</type>
+ </template-nontype-parameter>
+ </template>
+
+ <type>bool</type>
+
+ <parameter name="x">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+
+ <returns><simpara><code>!(x == y)</code></simpara>
+ </returns>
+ </function>
+
+ <function name="operator&lt;">
+ <template>
+ <template-type-parameter name="T"/>
+ <template-nontype-parameter name="N">
+ <type>std::size_t</type>
+ </template-nontype-parameter>
+ </template>
+
+ <type>bool</type>
+
+ <parameter name="x">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+
+ <returns><simpara><code>std::lexicographical_compare(x.<methodname>begin</methodname>(), x.<methodname>end</methodname>(), y.<methodname>begin</methodname>(), y.<methodname>end</methodname>())</code></simpara>
+ </returns>
+ </function>
+
+ <function name="operator&gt;">
+ <template>
+ <template-type-parameter name="T"/>
+ <template-nontype-parameter name="N">
+ <type>std::size_t</type>
+ </template-nontype-parameter>
+ </template>
+
+ <type>bool</type>
+
+ <parameter name="x">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+
+ <returns><simpara><code>y &lt; x</code></simpara></returns>
+ </function>
+
+ <function name="operator&lt;=">
+ <template>
+ <template-type-parameter name="T"/>
+ <template-nontype-parameter name="N">
+ <type>std::size_t</type>
+ </template-nontype-parameter>
+ </template>
+
+ <type>bool</type>
+
+ <parameter name="x">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+
+ <returns><simpara><code>!(y &lt; x)</code></simpara></returns>
+ </function>
+
+ <function name="operator&gt;=">
+ <template>
+ <template-type-parameter name="T"/>
+ <template-nontype-parameter name="N">
+ <type>std::size_t</type>
+ </template-nontype-parameter>
+ </template>
+
+ <type>bool</type>
+
+ <parameter name="x">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>const <classname>array</classname>&lt;T, N&gt;&amp;</paramtype>
+ </parameter>
+
+ <returns><simpara><code>!(x &lt; y)</code></simpara></returns>
+ </function>
+ </free-function-group>
+ </class>
+ </namespace>
+ </header>
+ </library-reference>
+
+<section id="array.rationale">
+ <title>Design Rationale</title>
+
+ <para>There was an important design tradeoff regarding the
+ constructors: We could implement array as an "aggregate" (see
+ Section 8.5.1, [dcl.init.aggr], of the C++ Standard). This would
+ mean:
+ <itemizedlist>
+ <listitem><simpara>An array can be initialized with a
+ brace-enclosing, comma-separated list of initializers for the
+ elements of the container, written in increasing subscript
+ order:</simpara>
+
+ <programlisting><classname>boost::array</classname>&lt;int,4&gt; a = { { 1, 2, 3 } };</programlisting>
+
+ <simpara>Note that if there are fewer elements in the
+ initializer list, then each remaining element gets
+ default-initialized (thus, it has a defined value).</simpara>
+ </listitem></itemizedlist></para>
+
+ <para>However, this approach has its drawbacks: <emphasis
+ role="bold"> passing no initializer list means that the elements
+ have an indetermined initial value</emphasis>, because the rule says
+ that aggregates may have:
+ <itemizedlist>
+ <listitem><simpara>No user-declared constructors.</simpara></listitem>
+ <listitem><simpara>No private or protected non-static data members.</simpara></listitem>
+ <listitem><simpara>No base classes.</simpara></listitem>
+ <listitem><simpara>No virtual functions.</simpara></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>Nevertheless, The current implementation uses this approach.</para>
+
+ <para>Note that for standard conforming compilers it is possible to
+ use fewer braces (according to 8.5.1 (11) of the Standard). That is,
+ you can initialize an array as follows:</para>
+
+<programlisting>
+<classname>boost::array</classname>&lt;int,4&gt; a = { 1, 2, 3 };
+</programlisting>
+
+ <para>I'd appreciate any constructive feedback. <emphasis
+ role="bold">Please note: I don't have time to read all boost
+ mails. Thus, to make sure that feedback arrives to me, please send
+ me a copy of each mail regarding this class.</emphasis></para>
+
+ <para>The code is provided "as is" without expressed or implied
+ warranty.</para>
+
+</section>
+
+<section id="array.more.info">
+ <title>For more information...</title>
+ <para>To find more details about using ordinary arrays in C++ and
+ the framework of the STL, see e.g.
+
+ <literallayout>The C++ Standard Library - A Tutorial and Reference
+by Nicolai M. Josuttis
+Addison Wesley Longman, 1999
+ISBN 0-201-37926-0</literallayout>
+ </para>
+
+ <para><ulink url="http://www.josuttis.com/">Home Page of Nicolai
+ Josuttis</ulink></para>
+</section>
+
+<section id="array.ack">
+ <title>Acknowledgements</title>
+
+ <para>Doug Gregor ported the documentation to the BoostBook format.</para>
+</section>
+
+<!-- Notes:
+ empty() should return N != 0
+ size(), empty(), max_size() should be const
+ -->
+
+</library>
diff --git a/tools/boostbook/test/more/tests/libs/hash-ref.gold b/tools/boostbook/test/more/tests/libs/hash-ref.gold
new file mode 100644
index 0000000000..e88658044c
--- /dev/null
+++ b/tools/boostbook/test/more/tests/libs/hash-ref.gold
@@ -0,0 +1,397 @@
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<section><title>Reference</title>
+ <section id="hash.reference.specification">
+ <para>For the full specification, see section 6.3 of the
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">C++ Standard Library Technical Report</ulink>
+ and issue 6.18 of the
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf">Library Extension Technical Report Issues List</ulink> (page 63).
+ </para>
+ </section>
+ <section id="header.boost.functional.hash_hpp"><title>Header &lt;<ulink url="../../boost/functional/hash.hpp">boost/functional/hash.hpp</ulink>&gt;</title><para>
+ Defines <computeroutput><link xmlns:xi="http://www.w3.org/2001/XInclude" linkend="boost.hash">boost::hash</link></computeroutput>,
+ and helper functions.
+ </para><synopsis xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash">hash</link><phrase role="special">;</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_bool_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_char_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_signed_char_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned_char_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_wchar_t_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_short_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned_short_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_int_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned_int_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned_long_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_float_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_double_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_double_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_string_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_wstring_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <link linkend="boost.hash_T_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase><phrase role="special">&gt;</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id1-bb">Support functions (Boost extension).</link></phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase> <phrase role="keyword">void</phrase> <link linkend="boost.hash_combine"><phrase role="identifier">hash_combine</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> It<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id2-bb"><phrase role="identifier">hash_range</phrase></link><phrase role="special">(</phrase><phrase role="identifier">It</phrase><phrase role="special">,</phrase> <phrase role="identifier">It</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> It<phrase role="special">&gt;</phrase> <phrase role="keyword">void</phrase> <link linkend="id3-bb"><phrase role="identifier">hash_range</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">It</phrase><phrase role="special">,</phrase> <phrase role="identifier">It</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id4-bb">Overloadable hash implementation (Boost extension).</link></phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id5-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">bool</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id6-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id7-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id8-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id9-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id10-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">short</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id11-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id12-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id13-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id14-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">long</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id15-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id16-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id17-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id18-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">float</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id19-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id20-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id21-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">unsigned</phrase> N<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id22-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">T</phrase> <phrase role="special">(</phrase><phrase role="special">&amp;</phrase><phrase role="identifier">val</phrase><phrase role="special">)</phrase><phrase role="special">[</phrase><phrase role="identifier">N</phrase><phrase role="special">]</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">unsigned</phrase> N<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id23-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase> <phrase role="special">(</phrase><phrase role="special">&amp;</phrase><phrase role="identifier">val</phrase><phrase role="special">)</phrase><phrase role="special">[</phrase><phrase role="identifier">N</phrase><phrase role="special">]</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Ch<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id24-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_string</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Ch</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">char_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Ch</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> A<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> B<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id25-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">A</phrase><phrase role="special">,</phrase> <phrase role="identifier">B</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id26-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id27-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">list</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id28-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">deque</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> K<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> C<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id29-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">K</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> K<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> C<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id30-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">K</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> K<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> C<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id31-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">K</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> K<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> C<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id32-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">K</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id33-bb"><phrase role="identifier">hash_value</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">complex</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase></synopsis>
+
+
+ <refsect2 xmlns:xi="http://www.w3.org/2001/XInclude"><title><anchor id="id1-bb"/><computeroutput/> Support functions (Boost extension).</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase> <phrase role="keyword">void</phrase> <anchor id="boost.hash_combine"/><phrase role="identifier">hash_combine</phrase><phrase role="special">(</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">&amp;</phrase> seed<phrase role="special">,</phrase> <phrase role="identifier">T</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> v<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><simpara>
+ Called repeatedly to incrementally create a hash value from
+ several variables.
+ </simpara><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><programlisting><phrase role="identifier">seed</phrase> <phrase role="special">^=</phrase> <link linkend="boost.hash_value">hash_value</link><phrase role="special">(</phrase><phrase role="identifier">v</phrase><phrase role="special">)</phrase> <phrase role="special">+</phrase> <phrase role="number">0x9e3779b9</phrase> <phrase role="special">+</phrase> <phrase role="special">(</phrase><phrase role="identifier">seed</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="number">6</phrase><phrase role="special">)</phrase> <phrase role="special">+</phrase> <phrase role="special">(</phrase><phrase role="identifier">seed</phrase> <phrase role="special">&gt;&gt;</phrase> <phrase role="number">2</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></programlisting></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para><link linkend="boost.hash_value">hash_value</link> is called without
+ qualification, so that overloads can be found via ADL.</para><para>This is an extension to TR1</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem>
+ Only throws if <link linkend="boost.hash_value">hash_value</link>(T) throws.
+ Strong exception safety, as long as <link linkend="boost.hash_value">hash_value</link>(T)
+ also has strong exception safety.
+ </listitem></varlistentry></variablelist></listitem><listitem><para id="boost.hash_range"><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> It<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id2-bb"/><phrase role="identifier">hash_range</phrase><phrase role="special">(</phrase><phrase role="identifier">It</phrase> first<phrase role="special">,</phrase> <phrase role="identifier">It</phrase> last<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> It<phrase role="special">&gt;</phrase> <phrase role="keyword">void</phrase> <anchor id="id3-bb"/><phrase role="identifier">hash_range</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">&amp;</phrase> seed<phrase role="special">,</phrase> <phrase role="identifier">It</phrase> first<phrase role="special">,</phrase> <phrase role="identifier">It</phrase> last<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><simpara>
+ Calculate the combined hash value of the elements of an iterator
+ range.
+ </simpara><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><para>For the two argument overload:
+<programlisting>
+<phrase role="identifier">size_t</phrase> <phrase role="identifier">seed</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
+
+<phrase role="keyword">for</phrase><phrase role="special">(</phrase><phrase role="special">;</phrase> <phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <link linkend="boost.hash_combine">hash_combine</link><phrase role="special">(</phrase><phrase role="identifier">seed</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase><phrase role="identifier">first</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+
+<phrase role="keyword">return</phrase> <phrase role="identifier">seed</phrase><phrase role="special">;</phrase>
+</programlisting>
+ </para>For the three arguments overload:
+<programlisting>
+<phrase role="keyword">for</phrase><phrase role="special">(</phrase><phrase role="special">;</phrase> <phrase role="identifier">first</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">last</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">first</phrase><phrase role="special">)</phrase>
+<phrase role="special">{</phrase>
+ <link linkend="boost.hash_combine">hash_combine</link><phrase role="special">(</phrase><phrase role="identifier">seed</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase><phrase role="identifier">first</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting><para>
+ </para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ <computeroutput>hash_range</computeroutput> is sensitive to the order of the elements
+ so it wouldn't be appropriate to use this with an unordered
+ container.
+ </para><para>This is an extension to TR1</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>
+ Only throws if <computeroutput><link linkend="boost.hash_value">hash_value</link>(std::iterator_traits&lt;It&gt;::value_type)</computeroutput>
+ throws. <computeroutput>hash_range(std::size_t&amp;, It, It)</computeroutput> has basic exception safety as long as
+ <computeroutput><link linkend="boost.hash_value">hash_value</link>(std::iterator_traits&lt;It&gt;::value_type)</computeroutput>
+ has basic exception safety.
+ </para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2 xmlns:xi="http://www.w3.org/2001/XInclude"><title><anchor id="id4-bb"/><computeroutput/> Overloadable hash implementation (Boost extension).</title><orderedlist><listitem><para id="boost.hash_value"><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id5-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">bool</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id6-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">char</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id7-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id8-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id9-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">wchar_t</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id10-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">short</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id11-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id12-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id13-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id14-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">long</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id15-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id16-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id17-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id18-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">float</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id19-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id20-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id21-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">unsigned</phrase> N<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id22-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase> <phrase role="special">(</phrase><phrase role="special">&amp;</phrase><phrase role="identifier">val</phrase><phrase role="special">)</phrase><phrase role="special">[</phrase><phrase role="identifier">N</phrase><phrase role="special">]</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">unsigned</phrase> N<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id23-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">T</phrase> <phrase role="special">(</phrase><phrase role="special">&amp;</phrase><phrase role="identifier">val</phrase><phrase role="special">)</phrase><phrase role="special">[</phrase><phrase role="identifier">N</phrase><phrase role="special">]</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Ch<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id24-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_string</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Ch</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">char_traits</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Ch</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> A<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> B<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id25-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">A</phrase><phrase role="special">,</phrase> <phrase role="identifier">B</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id26-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id27-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">list</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id28-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">deque</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> K<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> C<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id29-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">K</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> K<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> C<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id30-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">K</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> K<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> C<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id31-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">K</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> K<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> T<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> C<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> A<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id32-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">K</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="identifier">C</phrase><phrase role="special">,</phrase> <phrase role="identifier">A</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id33-bb"/><phrase role="identifier">hash_value</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">complex</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><simpara>
+ Implementation of the hash function.
+ </simpara><para>
+ Generally shouldn't be called directly by users, instead they should use
+ <computeroutput><link linkend="boost.hash">boost::hash</link></computeroutput>, <computeroutput><link linkend="boost.hash_range">boost::hash_range</link></computeroutput>
+ or <computeroutput><link linkend="boost.hash_combine">boost::hash_combine</link></computeroutput> which
+ call <computeroutput>hash_value</computeroutput> without namespace qualification so that overloads
+ for custom types are found via ADL.
+ </para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is an extension to TR1</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem>
+ Only throws if a user supplied version of
+ <computeroutput><link linkend="boost.hash_value">hash_value</link></computeroutput>
+ throws for an element of a container, or
+ one of the types stored in a pair.
+ </listitem></varlistentry><varlistentry><term>Returns:</term><listitem><informaltable>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Types</entry>
+ <entry>Returns</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><computeroutput>bool</computeroutput>,
+ <computeroutput>char</computeroutput>, <computeroutput>signed char</computeroutput>, <computeroutput>unsigned char</computeroutput>, <computeroutput>wchar_t</computeroutput>,
+ <computeroutput>short</computeroutput>, <computeroutput>unsigned short</computeroutput>,
+ <computeroutput>int</computeroutput>, <computeroutput>unsigned int</computeroutput>, <computeroutput>long</computeroutput>, <computeroutput>unsigned long</computeroutput>
+ </entry>
+ <entry><computeroutput>val</computeroutput></entry>
+ </row>
+ <row>
+ <entry><computeroutput>long long</computeroutput>, <computeroutput>unsigned long long</computeroutput></entry>
+ <entry><computeroutput>val</computeroutput> when <computeroutput>abs(val) &lt;= std::numeric_limits&lt;std::size_t&gt;::max()</computeroutput>.</entry>
+ </row>
+ <row>
+ <entry><computeroutput>float</computeroutput>, <computeroutput>double</computeroutput>, <computeroutput>long double</computeroutput></entry>
+ <entry>An unspecified value, except that equal arguments shall yield the same result.</entry>
+ </row>
+ <row>
+ <entry><computeroutput>T*</computeroutput></entry>
+ <entry>An unspecified value, except that equal arguments shall yield the same result.</entry>
+ </row>
+ <row>
+ <entry>
+ <computeroutput>T&#160;val[N]</computeroutput>,
+ <computeroutput>const&#160;T&#160;val[N]</computeroutput>
+ </entry>
+ <entry><computeroutput>hash_range(val, val+N)</computeroutput></entry>
+ </row>
+ <row>
+ <entry>
+ <computeroutput>std:basic_string&lt;Ch,&#160;std::char_traits&lt;Ch&gt;,&#160;A&gt;</computeroutput>,
+ <computeroutput>std::vector&lt;T,&#160;A&gt;</computeroutput>,
+ <computeroutput>std::list&lt;T,&#160;A&gt;</computeroutput>,
+ <computeroutput>std::deque&lt;T,&#160;A&gt;</computeroutput>,
+ <computeroutput>std::set&lt;K,&#160;C,&#160;A&gt;</computeroutput>,
+ <computeroutput>std::multiset&lt;K,&#160;C,&#160;A&gt;</computeroutput>,
+ <computeroutput>std::map&lt;K,&#160;T,&#160;C,&#160;A&gt;</computeroutput>,
+ <computeroutput>std::multimap&lt;K,&#160;T,&#160;C,&#160;A&gt;</computeroutput>
+ </entry>
+ <entry><computeroutput>hash_range(val.begin(), val.end())</computeroutput></entry>
+ </row>
+ <row>
+ <entry><computeroutput>std::pair&lt;A, B&gt;</computeroutput></entry>
+ <entry><programlisting><phrase role="identifier">size_t</phrase> <phrase role="identifier">seed</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
+<link linkend="boost.hash_combine">hash_combine</link><phrase role="special">(</phrase><phrase role="identifier">seed</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">.</phrase><phrase role="identifier">first</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<link linkend="boost.hash_combine">hash_combine</link><phrase role="special">(</phrase><phrase role="identifier">seed</phrase><phrase role="special">,</phrase> <phrase role="identifier">val</phrase><phrase role="special">.</phrase><phrase role="identifier">second</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">return</phrase> <phrase role="identifier">seed</phrase><phrase role="special">;</phrase></programlisting></entry>
+ </row>
+ <row>
+ <entry>
+ <computeroutput>std::complex&lt;T&gt;</computeroutput>
+ </entry>
+ <entry>When <computeroutput>T</computeroutput> is a built in type and <computeroutput>val.imag() == 0</computeroutput>, the result is equal to <computeroutput>hash_value(val.real())</computeroutput>. Otherwise an unspecified value, except that equal arguments shall yield the same result.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash"><refmeta><refentrytitle>Struct template hash</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash</refname><refpurpose>A <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">TR1</ulink> compliant hash function object.</refpurpose></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash">hash</link> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> std::unary_function&lt;T, std::size_t&gt; <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id34-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="identifier">T</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id34-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>
+ <programlisting><link linkend="boost.hash_value">hash_value</link><phrase role="special">(</phrase><phrase role="identifier">val</phrase><phrase role="special">)</phrase></programlisting>
+ </para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ The call to <computeroutput><link linkend="boost.hash_value">hash_value</link></computeroutput>
+ is unqualified, so that custom overloads can be
+ found via argument dependent lookup.
+ </para><para>
+ This is not defined when the macro <computeroutput>BOOST_HASH_NO_EXTENSIONS</computeroutput>
+ is defined. The specializations are still defined, so only the specializations
+ required by TR1 are defined.
+ </para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>
+ Only throws if
+ <computeroutput><link linkend="boost.hash_value">hash_value</link>(T)</computeroutput> throws.
+ </para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_bool_id1"><refmeta><refentrytitle>Struct hash&lt;bool&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;bool&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_bool_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id35-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">bool</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id35-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">bool</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_char_id1"><refmeta><refentrytitle>Struct hash&lt;char&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;char&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_char_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id36-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id36-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">char</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_signed_char_id1"><refmeta><refentrytitle>Struct hash&lt;signed char&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;signed char&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_signed_char_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id37-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id37-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">signed</phrase> <phrase role="keyword">char</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_unsigned_char_id1"><refmeta><refentrytitle>Struct hash&lt;unsigned char&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned char&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned_char_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id38-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id38-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">char</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_wchar_t_id1"><refmeta><refentrytitle>Struct hash&lt;wchar_t&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;wchar_t&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_wchar_t_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id39-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">wchar_t</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id39-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">wchar_t</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_short_id1"><refmeta><refentrytitle>Struct hash&lt;short&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;short&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_short_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id40-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">short</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id40-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">short</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_unsigned_short_id1"><refmeta><refentrytitle>Struct hash&lt;unsigned short&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned short&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned_short_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id41-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id41-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">short</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_int_id1"><refmeta><refentrytitle>Struct hash&lt;int&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;int&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_int_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id42-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id42-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_unsigned_int_id1"><refmeta><refentrytitle>Struct hash&lt;unsigned int&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned int&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned_int_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id43-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id43-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_long_id1"><refmeta><refentrytitle>Struct hash&lt;long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id44-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">long</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id44-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">long</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_unsigned_long_id1"><refmeta><refentrytitle>Struct hash&lt;unsigned long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id45-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id45-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_long_long_id1"><refmeta><refentrytitle>Struct hash&lt;long long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;long long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id46-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id46-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_unsigned_long_long_id1"><refmeta><refentrytitle>Struct hash&lt;unsigned long long&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;unsigned long long&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_unsigned_long_long_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id47-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id47-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">unsigned</phrase> <phrase role="keyword">long</phrase> <phrase role="keyword">long</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_float_id1"><refmeta><refentrytitle>Struct hash&lt;float&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;float&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_float_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">float</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id48-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">float</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id48-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">float</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_double_id1"><refmeta><refentrytitle>Struct hash&lt;double&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;double&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_double_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id49-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">double</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id49-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">double</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_long_double_id1"><refmeta><refentrytitle>Struct hash&lt;long double&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;long double&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_long_double_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id50-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id50-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="keyword">long</phrase> <phrase role="keyword">double</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_std_string_id1"><refmeta><refentrytitle>Struct hash&lt;std::string&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;std::string&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_string_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id51-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id51-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_std_wstring_id1"><refmeta><refentrytitle>Struct hash&lt;std::wstring&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;std::wstring&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_std_wstring_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id52-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id52-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">wstring</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para><para><link linkend="boost.hash_value">hash_value</link>(val) in Boost.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.hash_T_id1"><refmeta><refentrytitle>Struct template hash&lt;T*&gt;</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::hash&lt;T*&gt;</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.functional.hash_hpp">boost/functional/hash.hpp</link>&gt;
+
+</phrase><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> T<phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <link linkend="boost.hash_T_id1">hash</link><phrase role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase><phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <link linkend="id53-bb"><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase></link><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <anchor id="id53-bb"/><phrase role="keyword">operator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> val<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Unspecified in TR1, except that equal arguments yield the same result.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Doesn't throw</para></listitem></varlistentry></variablelist></refsect1></refentry>
+ </section>
+</section> \ No newline at end of file
diff --git a/tools/boostbook/test/more/tests/libs/hash-ref.xml b/tools/boostbook/test/more/tests/libs/hash-ref.xml
new file mode 100644
index 0000000000..47a09d5b92
--- /dev/null
+++ b/tools/boostbook/test/more/tests/libs/hash-ref.xml
@@ -0,0 +1,810 @@
+
+<!--
+Copyright Daniel James 2005-2009
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+-->
+
+<library-reference>
+ <section id="hash.reference.specification">
+ <para>For the full specification, see section 6.3 of the
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">C++ Standard Library Technical Report</ulink>
+ and issue 6.18 of the
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf">Library Extension Technical Report Issues List</ulink> (page 63).
+ </para>
+ </section>
+ <header name="boost/functional/hash.hpp">
+ <para>
+ Defines <code><classname>boost::hash</classname></code>,
+ and helper functions.
+ </para>
+
+ <namespace name="boost">
+
+ <!--
+ boost::hash
+ -->
+
+ <struct name="hash">
+ <template>
+ <template-type-parameter name="T"/>
+ </template>
+
+ <inherit access="public">
+ <classname>std::unary_function&lt;T, std::size_t&gt;</classname>
+ </inherit>
+
+ <purpose><simpara>A <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">TR1</ulink> compliant hash function object.</simpara></purpose>
+
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>T const&amp;</paramtype>
+ </parameter>
+ <returns><para>
+ <programlisting><functionname>hash_value</functionname>(val)</programlisting>
+ </para></returns>
+ <notes>
+ <para>
+ The call to <code><functionname>hash_value</functionname></code>
+ is unqualified, so that custom overloads can be
+ found via argument dependent lookup.
+ </para>
+ <para>
+ This is not defined when the macro <code>BOOST_HASH_NO_EXTENSIONS</code>
+ is defined. The specializations are still defined, so only the specializations
+ required by TR1 are defined.
+ </para>
+ </notes>
+ <throws><para>
+ Only throws if
+ <code><functionname>hash_value</functionname>(T)</code> throws.
+ </para></throws>
+ </method>
+ </struct>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>bool</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>bool</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>char</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>char</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>signed char</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>signed char</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>unsigned char</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>unsigned char</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>wchar_t</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>wchar_t</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>short</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>short</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>unsigned short</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>unsigned short</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>int</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>int</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>unsigned int</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>unsigned int</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>long</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>long</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>unsigned long</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>unsigned long</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>long long</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>long long</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>unsigned long long</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>unsigned long long</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>float</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>float</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>double</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>double</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>long double</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>long double</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>std::string</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>std::string const&amp;</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template></template>
+ <specialization>
+ <template-arg>std::wstring</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>std::wstring const&amp;</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ <para><functionname>hash_value</functionname>(val) in Boost.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <struct-specialization name="hash">
+ <template>
+ <template-type-parameter name="T"/>
+ </template>
+ <specialization>
+ <template-arg>T*</template-arg>
+ </specialization>
+ <method name="operator()" cv="const">
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>T*</paramtype>
+ </parameter>
+ <returns>
+ <para>Unspecified in TR1, except that equal arguments yield the same result.</para>
+ </returns>
+ <throws><para>Doesn't throw</para></throws>
+ </method>
+ </struct-specialization>
+
+ <free-function-group name="Support functions (Boost extension).">
+
+ <!--
+ boost::hash_combine
+ -->
+
+ <function name="hash_combine">
+ <template>
+ <template-type-parameter name="T"/>
+ </template>
+ <type>void</type>
+ <parameter name="seed"><paramtype>size_t &amp;</paramtype></parameter>
+ <parameter name="v"><paramtype>T const&amp;</paramtype></parameter>
+ <purpose><simpara>
+ Called repeatedly to incrementally create a hash value from
+ several variables.
+ </simpara></purpose>
+ <effects><programlisting>seed ^= <functionname>hash_value</functionname>(v) + 0x9e3779b9 + (seed &lt;&lt; 6) + (seed &gt;&gt; 2);</programlisting></effects>
+ <notes>
+ <para><functionname>hash_value</functionname> is called without
+ qualification, so that overloads can be found via ADL.</para>
+ <para>This is an extension to TR1</para>
+ </notes>
+ <throws>
+ Only throws if <functionname>hash_value</functionname>(T) throws.
+ Strong exception safety, as long as <functionname>hash_value</functionname>(T)
+ also has strong exception safety.
+ </throws>
+ </function>
+
+ <!--
+ boost::hash_range
+ -->
+
+ <overloaded-function name="hash_range">
+ <signature>
+ <template>
+ <template-type-parameter name="It"/>
+ </template>
+ <type>std::size_t</type>
+ <parameter name="first"><paramtype>It</paramtype></parameter>
+ <parameter name="last"><paramtype>It</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="It"/>
+ </template>
+ <type>void</type>
+ <parameter name="seed"><paramtype>std::size_t&amp;</paramtype></parameter>
+ <parameter name="first"><paramtype>It</paramtype></parameter>
+ <parameter name="last"><paramtype>It</paramtype></parameter>
+ </signature>
+
+ <purpose><simpara>
+ Calculate the combined hash value of the elements of an iterator
+ range.
+ </simpara></purpose>
+ <effects>
+ <para>For the two argument overload:
+<programlisting>
+size_t seed = 0;
+
+for(; first != last; ++first)
+{
+ <functionname>hash_combine</functionname>(seed, *first);
+}
+
+return seed;
+</programlisting>
+ </para>For the three arguments overload:
+<programlisting>
+for(; first != last; ++first)
+{
+ <functionname>hash_combine</functionname>(seed, *first);
+}
+</programlisting>
+ <para>
+ </para>
+ </effects>
+ <notes>
+ <para>
+ <code>hash_range</code> is sensitive to the order of the elements
+ so it wouldn't be appropriate to use this with an unordered
+ container.
+ </para>
+ <para>This is an extension to TR1</para>
+ </notes>
+ <throws><para>
+ Only throws if <code><functionname>hash_value</functionname>(std::iterator_traits&lt;It&gt;::value_type)</code>
+ throws. <code>hash_range(std::size_t&amp;, It, It)</code> has basic exception safety as long as
+ <code><functionname>hash_value</functionname>(std::iterator_traits&lt;It&gt;::value_type)</code>
+ has basic exception safety.
+ </para></throws>
+ </overloaded-function>
+
+ </free-function-group>
+
+ <free-function-group name="Overloadable hash implementation (Boost extension).">
+
+ <!--
+ boost::hash_value - integers
+ -->
+
+ <overloaded-function name="hash_value">
+ <purpose><simpara>
+ Implementation of the hash function.
+ </simpara></purpose>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>bool</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>char</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>signed char</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>unsigned char</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>wchar_t</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>short</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>unsigned short</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>int</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>unsigned int</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>long</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>unsigned long</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>long long</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>unsigned long long</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>float</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>double</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>long double</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template><template-type-parameter name="T"/></template>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>T* const&amp;</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="T"/>
+ <template-nontype-parameter name="N"><type>unsigned</type></template-nontype-parameter>
+ </template>
+ <type>std::size_t</type>
+ <parameter><paramtype>T (&amp;val)[N]</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="T"/>
+ <template-nontype-parameter name="N"><type>unsigned</type></template-nontype-parameter>
+ </template>
+ <type>std::size_t</type>
+ <parameter><paramtype>const T (&amp;val)[N]</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="Ch"/>
+ <template-type-parameter name="A"/>
+ </template>
+ <type>std::size_t</type>
+ <parameter name="val">
+ <paramtype>std::basic_string&lt;Ch, std::char_traits&lt;Ch&gt;, A&gt; const&amp;</paramtype>
+ </parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="A"/>
+ <template-type-parameter name="B"/>
+ </template>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>std::pair&lt;A, B&gt; const&amp;</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="T"/>
+ <template-type-parameter name="A"/>
+ </template>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>std::vector&lt;T, A&gt; const&amp;</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="T"/>
+ <template-type-parameter name="A"/>
+ </template>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>std::list&lt;T, A&gt; const&amp;</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="T"/>
+ <template-type-parameter name="A"/>
+ </template>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>std::deque&lt;T, A&gt; const&amp;</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="K"/>
+ <template-type-parameter name="C"/>
+ <template-type-parameter name="A"/>
+ </template>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>std::set&lt;K, C, A&gt; const&amp;</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="K"/>
+ <template-type-parameter name="C"/>
+ <template-type-parameter name="A"/>
+ </template>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>std::multiset&lt;K, C, A&gt; const&amp;</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="K"/>
+ <template-type-parameter name="T"/>
+ <template-type-parameter name="C"/>
+ <template-type-parameter name="A"/>
+ </template>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>std::map&lt;K, T, C, A&gt; const&amp;</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="K"/>
+ <template-type-parameter name="T"/>
+ <template-type-parameter name="C"/>
+ <template-type-parameter name="A"/>
+ </template>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>std::multimap&lt;K, T, C, A&gt; const&amp;</paramtype></parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="T"/>
+ </template>
+ <type>std::size_t</type>
+ <parameter name="val"><paramtype>std::complex&lt;T&gt; const&amp;</paramtype></parameter>
+ </signature>
+
+ <description><para>
+ Generally shouldn't be called directly by users, instead they should use
+ <classname>boost::hash</classname>, <functionname>boost::hash_range</functionname>
+ or <functionname>boost::hash_combine</functionname> which
+ call <code>hash_value</code> without namespace qualification so that overloads
+ for custom types are found via ADL.
+ </para></description>
+
+ <notes>
+ <para>This is an extension to TR1</para>
+ </notes>
+
+ <throws>
+ Only throws if a user supplied version of
+ <code><functionname>hash_value</functionname></code>
+ throws for an element of a container, or
+ one of the types stored in a pair.
+ </throws>
+
+ <returns>
+ <informaltable>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Types</entry>
+ <entry>Returns</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><code>bool</code>,
+ <code>char</code>, <code>signed char</code>, <code>unsigned char</code>, <code>wchar_t</code>,
+ <code>short</code>, <code>unsigned short</code>,
+ <code>int</code>, <code>unsigned int</code>, <code>long</code>, <code>unsigned long</code>
+ </entry>
+ <entry><code>val</code></entry>
+ </row>
+ <row>
+ <entry><code>long long</code>, <code>unsigned long long</code></entry>
+ <entry><code>val</code> when <code>abs(val) &lt;= std::numeric_limits&lt;std::size_t&gt;::max()</code>.</entry>
+ </row>
+ <row>
+ <entry><code>float</code>, <code>double</code>, <code>long double</code></entry>
+ <entry>An unspecified value, except that equal arguments shall yield the same result.</entry>
+ </row>
+ <row>
+ <entry><code>T*</code></entry>
+ <entry>An unspecified value, except that equal arguments shall yield the same result.</entry>
+ </row>
+ <row>
+ <entry>
+ <code>T&#160;val[N]</code>,
+ <code>const&#160;T&#160;val[N]</code>
+ </entry>
+ <entry><code>hash_range(val, val+N)</code></entry>
+ </row>
+ <row>
+ <entry>
+ <code>std:basic_string&lt;Ch,&#160;std::char_traits&lt;Ch&gt;,&#160;A&gt;</code>,
+ <code>std::vector&lt;T,&#160;A&gt;</code>,
+ <code>std::list&lt;T,&#160;A&gt;</code>,
+ <code>std::deque&lt;T,&#160;A&gt;</code>,
+ <code>std::set&lt;K,&#160;C,&#160;A&gt;</code>,
+ <code>std::multiset&lt;K,&#160;C,&#160;A&gt;</code>,
+ <code>std::map&lt;K,&#160;T,&#160;C,&#160;A&gt;</code>,
+ <code>std::multimap&lt;K,&#160;T,&#160;C,&#160;A&gt;</code>
+ </entry>
+ <entry><code>hash_range(val.begin(), val.end())</code></entry>
+ </row>
+ <row>
+ <entry><code>std::pair&lt;A, B&gt;</code></entry>
+ <entry><programlisting>size_t seed = 0;
+<functionname>hash_combine</functionname>(seed, val.first);
+<functionname>hash_combine</functionname>(seed, val.second);
+return seed;</programlisting></entry>
+ </row>
+ <row>
+ <entry>
+ <code>std::complex&lt;T&gt;</code>
+ </entry>
+ <entry>When <code>T</code> is a built in type and <code>val.imag() == 0</code>, the result is equal to <code>hash_value(val.real())</code>. Otherwise an unspecified value, except that equal arguments shall yield the same result.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </returns>
+ </overloaded-function>
+ </free-function-group>
+ </namespace>
+ </header>
+</library-reference>
+
diff --git a/tools/boostbook/test/more/tests/libs/unordered-ref.gold b/tools/boostbook/test/more/tests/libs/unordered-ref.gold
new file mode 100644
index 0000000000..3498c4153f
--- /dev/null
+++ b/tools/boostbook/test/more/tests/libs/unordered-ref.gold
@@ -0,0 +1,1508 @@
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<section><title>Reference</title>
+ <section id="header.boost.unordered_set_hpp"><title>Header &lt;<ulink url="../../boost/unordered_set.hpp">boost/unordered_set.hpp</ulink>&gt;</title><synopsis xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">hash</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Pred <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">equal_to</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="keyword">class</phrase> <link linkend="boost.unordered_set">unordered_set</link><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="boost.unordered_set.swap_id1"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">hash</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Pred <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">equal_to</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="keyword">class</phrase> <link linkend="boost.unordered_multiset">unordered_multiset</link><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="boost.unordered_multiset.swap_id1"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase></synopsis>
+ <refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.unordered_set"><refmeta><refentrytitle>Class template unordered_set</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::unordered_set</refname><refpurpose>
+ An unordered associative container that stores unique values.
+ </refpurpose></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.unordered_set_hpp">boost/unordered_set.hpp</link>&gt;
+
+</phrase><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">hash</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Pred <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">equal_to</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <link linkend="boost.unordered_set">unordered_set</link> <phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="comment">// <link linkend="boost.unordered_settypes">types</link></phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Value</phrase> <anchor id="boost.unordered_set.key_type"/><phrase role="identifier">key_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Value</phrase> <anchor id="boost.unordered_set.value_type"/><phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Hash</phrase> <anchor id="boost.unordered_set.hasher"/><phrase role="identifier">hasher</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Pred</phrase> <anchor id="boost.unordered_set.key_equal"/><phrase role="identifier">key_equal</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Alloc</phrase> <anchor id="boost.unordered_set.allocator_type"/><phrase role="identifier">allocator_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">pointer</phrase> <anchor id="boost.unordered_set.pointer"/><phrase role="identifier">pointer</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">const_pointer</phrase> <anchor id="boost.unordered_set.const_pointer"/><phrase role="identifier">const_pointer</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">reference</phrase> <anchor id="boost.unordered_set.reference"/><phrase role="identifier">reference</phrase><phrase role="special">;</phrase> <phrase role="comment">// lvalue of value_type.</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">const_reference</phrase> <anchor id="boost.unordered_set.const_reference"/><phrase role="identifier">const_reference</phrase><phrase role="special">;</phrase> <phrase role="comment">// const lvalue of value_type.</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_set.size_type"><phrase role="identifier">size_type</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_set.difference_type"><phrase role="identifier">difference_type</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_set.iterator"><phrase role="identifier">iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_set.const_iterator"><phrase role="identifier">const_iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_set.local_iterator"><phrase role="identifier">local_iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_set.const_local_iterator"><phrase role="identifier">const_local_iterator</phrase></link><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="boost.unordered_setconstruct-copy-destruct">construct/copy/destruct</link></phrase>
+ <phrase role="keyword">explicit</phrase> <link linkend="id1-bb"><phrase role="identifier">unordered_set</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <link linkend="id2-bb"><phrase role="identifier">unordered_set</phrase></link><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">size_type</phrase> <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase> <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id3-bb"><phrase role="identifier">unordered_set</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id4-bb"><phrase role="identifier">unordered_set</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">explicit</phrase> <link linkend="id5-bb"><phrase role="identifier">unordered_set</phrase></link><phrase role="special">(</phrase><phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id6-bb"><phrase role="identifier">unordered_set</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id7-bb"><phrase role="special">~</phrase><phrase role="identifier">unordered_set</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">unordered_set</phrase><phrase role="special">&amp;</phrase> <link linkend="id8-bb"><phrase role="keyword">operator</phrase><phrase role="special">=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">unordered_set</phrase><phrase role="special">&amp;</phrase> <link linkend="id9-bb"><phrase role="keyword">operator</phrase><phrase role="special">=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">allocator_type</phrase> <link linkend="id10-bb"><phrase role="identifier">get_allocator</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id11-bb">size and capacity</link></phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="id12-bb"><phrase role="identifier">empty</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id13-bb"><phrase role="identifier">size</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id14-bb"><phrase role="identifier">max_size</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id15-bb">iterators</link></phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id17-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id18-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id20-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id21-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id22-bb"><phrase role="identifier">cbegin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id23-bb"><phrase role="identifier">cend</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id24-bb">modifiers</link></phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase> <link linkend="id25-bb"><phrase role="identifier">emplace</phrase></link><phrase role="special">(</phrase><phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">iterator</phrase> <link linkend="id26-bb"><phrase role="identifier">emplace_hint</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase> <link linkend="id27-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id28-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase> <phrase role="keyword">void</phrase> <link linkend="id29-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id30-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id31-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id32-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id33-bb"><phrase role="identifier">quick_erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id34-bb"><phrase role="identifier">erase_return_void</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id35-bb"><phrase role="identifier">clear</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id36-bb"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id37-bb">observers</link></phrase>
+ <phrase role="identifier">hasher</phrase> <link linkend="id38-bb"><phrase role="identifier">hash_function</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">key_equal</phrase> <link linkend="id39-bb"><phrase role="identifier">key_eq</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id40-bb">lookup</link></phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id42-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id43-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id44-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">const_iterator</phrase>
+ <link linkend="id45-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id46-bb"><phrase role="identifier">count</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">&gt;</phrase> <link linkend="id48-bb"><phrase role="identifier">equal_range</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">&gt;</phrase> <link linkend="id49-bb"><phrase role="identifier">equal_range</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id50-bb">bucket interface</link></phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id51-bb"><phrase role="identifier">bucket_count</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id52-bb"><phrase role="identifier">max_bucket_count</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id53-bb"><phrase role="identifier">bucket_size</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id54-bb"><phrase role="identifier">bucket</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">local_iterator</phrase> <link linkend="id56-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id57-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">local_iterator</phrase> <link linkend="id59-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id60-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id61-bb"><phrase role="identifier">cbegin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id62-bb"><phrase role="identifier">cend</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id63-bb">hash policy</link></phrase>
+ <phrase role="keyword">float</phrase> <link linkend="id64-bb"><phrase role="identifier">load_factor</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">float</phrase> <link linkend="id65-bb"><phrase role="identifier">max_load_factor</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id66-bb"><phrase role="identifier">max_load_factor</phrase></link><phrase role="special">(</phrase><phrase role="keyword">float</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id67-bb"><phrase role="identifier">rehash</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase>
+
+<phrase role="comment">// <link linkend="id68-bb">Equality Comparisons</link></phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_set.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+<phrase role="comment">// <link linkend="id69-bb">swap</link></phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="boost.unordered_set.swap_id1"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title>
+ <para>Based on chapter 23 of
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
+ But without the updated rules for allocators.
+ </para>
+ <para><emphasis role="bold">Template Parameters</emphasis>
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry><emphasis>Value</emphasis></entry>
+ <entry>Value must be Assignable and CopyConstructible</entry></row>
+ <row>
+ <entry><emphasis>Hash</emphasis></entry>
+ <entry>A unary function object type that acts a hash function for a <computeroutput>Value</computeroutput>. It takes a single argument of type <computeroutput>Value</computeroutput> and returns a value of type std::size_t.</entry></row>
+ <row>
+ <entry><emphasis>Pred</emphasis></entry>
+ <entry>A binary function object that implements an equivalence relation on values of type <computeroutput>Value</computeroutput>.
+ A binary function object that induces an equivalence relation on values of type Key.
+ It takes two arguments of type Key and returns a value of type bool.</entry></row>
+ <row>
+ <entry><emphasis>Alloc</emphasis></entry>
+ <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
+ <para>The elements are organized into buckets. Keys with the same hash code are stored in the same bucket.</para>
+ <para>The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash.</para>
+ <refsect2><title><anchor id="boost.unordered_settypes"/><computeroutput>unordered_set</computeroutput>
+ public
+ types</title><orderedlist><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_set.size_type"/><phrase role="identifier">size_type</phrase><phrase role="special">;</phrase></para>
+ <para>An unsigned integral type.</para>
+ <para>size_type can represent any non-negative value of difference_type.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_set.difference_type"/><phrase role="identifier">difference_type</phrase><phrase role="special">;</phrase></para>
+ <para>A signed integral type.</para>
+ <para>Is identical to the difference type of iterator and const_iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_set.iterator"/><phrase role="identifier">iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A constant iterator whose value type is value_type. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ <para>Convertible to const_iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_set.const_iterator"/><phrase role="identifier">const_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A constant iterator whose value type is value_type. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_set.local_iterator"/><phrase role="identifier">local_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>An iterator with the same value type, difference type and pointer and reference type as iterator.</para>
+ <para>A local_iterator object can be used to iterate through a single bucket.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_set.const_local_iterator"/><phrase role="identifier">const_local_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A constant iterator with the same value type, difference type and pointer and reference type as const_iterator.</para>
+ <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
+ </listitem></orderedlist></refsect2><refsect2><title><anchor id="boost.unordered_setconstruct-copy-destruct"/><computeroutput>unordered_set</computeroutput>
+ public
+ construct/copy/destruct</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">explicit</phrase> <anchor id="id1-bb"/><phrase role="identifier">unordered_set</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hf <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Postconditions:</term><listitem><computeroutput><link linkend="id13-bb">size</link>() == 0</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <anchor id="id2-bb"/><phrase role="identifier">unordered_set</phrase><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase> f<phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase> l<phrase role="special">,</phrase>
+ <phrase role="identifier">size_type</phrase> n <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hf <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id3-bb"/><phrase role="identifier">unordered_set</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>value_type</computeroutput> is copy constructible</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id4-bb"/><phrase role="identifier">unordered_set</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The move constructor.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is emulated on compilers without rvalue references.</para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para>
+ <computeroutput>value_type</computeroutput> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">explicit</phrase> <anchor id="id5-bb"/><phrase role="identifier">unordered_set</phrase><phrase role="special">(</phrase><phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container, using allocator <computeroutput>a</computeroutput>.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id6-bb"/><phrase role="identifier">unordered_set</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an container, copying <computeroutput>x</computeroutput>'s contained elements, hash function, predicate, maximum load factor, but using allocator <computeroutput>a</computeroutput>.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id7-bb"/><phrase role="special">~</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>The destructor is applied to every element, and all memory is deallocated</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><para><literallayout class="monospaced"><phrase role="identifier">unordered_set</phrase><phrase role="special">&amp;</phrase> <anchor id="id8-bb"/><phrase role="keyword">operator</phrase><phrase role="special">=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <computeroutput>operator=(unordered_set)</computeroutput>
+ in order to emulate move semantics.
+ </para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para><computeroutput>value_type</computeroutput> is copy constructible</para></listitem></varlistentry></variablelist><para><literallayout class="monospaced"><phrase role="identifier">unordered_set</phrase><phrase role="special">&amp;</phrase> <anchor id="id9-bb"/><phrase role="keyword">operator</phrase><phrase role="special">=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The move assignment operator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <computeroutput>operator=(unordered_set)</computeroutput>
+ in order to emulate move semantics.
+ </para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para>
+ <computeroutput>value_type</computeroutput> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para></listitem></varlistentry></variablelist><para><literallayout class="monospaced"><phrase role="identifier">allocator_type</phrase> <anchor id="id10-bb"/><phrase role="identifier">get_allocator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><refsect2><title><anchor id="id11-bb"/><computeroutput>unordered_set</computeroutput> size and capacity</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">bool</phrase> <anchor id="id12-bb"/><phrase role="identifier">empty</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput><link linkend="id13-bb">size</link>() == 0</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id13-bb"/><phrase role="identifier">size</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput>std::distance(<link linkend="id16-bb">begin</link>(), <link linkend="id19-bb">end</link>())</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id14-bb"/><phrase role="identifier">max_size</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput><link linkend="id13-bb">size</link>()</computeroutput> of the largest possible container.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id15-bb"/><computeroutput>unordered_set</computeroutput> iterators</title><orderedlist><listitem><para><literallayout class="monospaced"><anchor id="id16-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id17-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id18-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id19-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id20-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id21-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>An iterator which refers to the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_iterator</phrase> <anchor id="id22-bb"/><phrase role="identifier">cbegin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>A constant iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_iterator</phrase> <anchor id="id23-bb"/><phrase role="identifier">cend</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>A constant iterator which refers to the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id24-bb"/><computeroutput>unordered_set</computeroutput> modifiers</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase> <anchor id="id25-bb"/><phrase role="identifier">emplace</phrase><phrase role="special">(</phrase><phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase> args<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts an object, constructed with the arguments <computeroutput>args</computeroutput>, in the container if and only if there is no element in the container with an equivalent value.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The bool component of the return type is true if an insert took place.</para><para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para><para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <anchor id="id26-bb"/><phrase role="identifier">emplace_hint</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> hint<phrase role="special">,</phrase> <phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase> args<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts an object, constructed with the arguments <computeroutput>args</computeroutput>, in the container if and only if there is no element in the container with an equivalent value.</para><para>hint is a suggestion to where the element should be inserted.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same value. </para><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para><para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase> <anchor id="id27-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> obj<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts obj in the container if and only if there is no element in the container with an equivalent value.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The bool component of the return type is true if an insert took place.</para><para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id28-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> hint<phrase role="special">,</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> obj<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts obj in the container if and only if there is no element in the container with an equivalent value.</para><para>hint is a suggestion to where the element should be inserted.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same value. </para><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <anchor id="id29-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase> first<phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase> last<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent value.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>When inserting a single element, if an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id30-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The iterator following <computeroutput>position</computeroutput> before the erasure.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ When the number of elements is a lot smaller than the number of buckets
+ this function can be very inefficient as it has to search through empty
+ buckets for the next element, in order to return the iterator.
+ The method <link linkend="id33-bb">quick_erase</link> is faster, but has yet
+ to be standardized.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id31-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase all elements with key equivalent to <computeroutput>k</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of elements erased.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id32-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> first<phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase> last<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erases the elements in the range from <computeroutput>first</computeroutput> to <computeroutput>last</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The iterator following the erased elements - i.e. <computeroutput>last</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id33-bb"/><phrase role="identifier">quick_erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ This method is faster than <link linkend="id30-bb">erase</link> as
+ it doesn't have to find the next element in the container -
+ a potentially costly operation.
+ </para><para>
+ As it hasn't been standardized, it's likely that this may
+ change in the future.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id34-bb"/><phrase role="identifier">erase_return_void</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ This method is now deprecated, use
+ quick_return instead. Although be
+ warned that as that isn't standardized yet, it could also
+ change.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id35-bb"/><phrase role="identifier">clear</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erases all elements in the container.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Postconditions:</term><listitem><para><computeroutput><link linkend="id13-bb">size</link>() == 0</computeroutput></para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Never throws an exception.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id36-bb"/><phrase role="identifier">swap</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <computeroutput>key_equal</computeroutput> or <computeroutput>hasher</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id37-bb"/><computeroutput>unordered_set</computeroutput> observers</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="identifier">hasher</phrase> <anchor id="id38-bb"/><phrase role="identifier">hash_function</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>The container's hash function.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">key_equal</phrase> <anchor id="id39-bb"/><phrase role="identifier">key_eq</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>The container's key equality predicate.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id40-bb"/><computeroutput>unordered_set</computeroutput> lookup</title><orderedlist><listitem><para><literallayout class="monospaced"><anchor id="id41-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id42-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id43-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <anchor id="id44-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hash<phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">const_iterator</phrase>
+ <anchor id="id45-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hash<phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to an element with key equivalent to <computeroutput>k</computeroutput>, or <computeroutput>b.end()</computeroutput> if no such element exists.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ The templated overloads are a non-standard extensions which
+ allows you to use a compatible hash function and equality
+ predicate for a key of a different type in order to avoid
+ an expensive type cast. In general, its use is not encouraged.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id46-bb"/><phrase role="identifier">count</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of elements with key equivalent to <computeroutput>k</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id47-bb"/><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">&gt;</phrase> <anchor id="id48-bb"/><phrase role="identifier">equal_range</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">&gt;</phrase> <anchor id="id49-bb"/><phrase role="identifier">equal_range</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>A range containing all elements with key equivalent to <computeroutput>k</computeroutput>.
+ If the container doesn't container any such elements, returns
+ <computeroutput>std::make_pair(b.end(),b.end())</computeroutput>.
+ </para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id50-bb"/><computeroutput>unordered_set</computeroutput> bucket interface</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id51-bb"/><phrase role="identifier">bucket_count</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of buckets.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id52-bb"/><phrase role="identifier">max_bucket_count</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An upper bound on the number of buckets.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id53-bb"/><phrase role="identifier">bucket_size</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n &lt; <link linkend="id51-bb">bucket_count</link>()</computeroutput></para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>The number of elements in bucket <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id54-bb"/><phrase role="identifier">bucket</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The index of the bucket which would contain an element with key <computeroutput>k</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Postconditions:</term><listitem><para>The return value is less than <computeroutput>bucket_count()</computeroutput></para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id55-bb"/><phrase role="identifier">local_iterator</phrase> <anchor id="id56-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_local_iterator</phrase> <anchor id="id57-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A local iterator pointing the first element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id58-bb"/><phrase role="identifier">local_iterator</phrase> <anchor id="id59-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_local_iterator</phrase> <anchor id="id60-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A local iterator pointing the 'one past the end' element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_local_iterator</phrase> <anchor id="id61-bb"/><phrase role="identifier">cbegin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A constant local iterator pointing the first element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_local_iterator</phrase> <anchor id="id62-bb"/><phrase role="identifier">cend</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A constant local iterator pointing the 'one past the end' element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id63-bb"/><computeroutput>unordered_set</computeroutput> hash policy</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">float</phrase> <anchor id="id64-bb"/><phrase role="identifier">load_factor</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The average number of elements per bucket.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">float</phrase> <anchor id="id65-bb"/><phrase role="identifier">max_load_factor</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Returns the current maximum load factor.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id66-bb"/><phrase role="identifier">max_load_factor</phrase><phrase role="special">(</phrase><phrase role="keyword">float</phrase> z<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><para>Changes the container's maximum load factor, using <computeroutput>z</computeroutput> as a hint.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id67-bb"/><phrase role="identifier">rehash</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Changes the number of buckets so that there at least <computeroutput>n</computeroutput> buckets, and so that the load factor is less than the maximum load factor.</para><para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id68-bb"/><computeroutput>unordered_set</computeroutput> Equality Comparisons</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_set.operator==_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_set.operator!=_id1"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id69-bb"/><computeroutput>unordered_set</computeroutput> swap</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <anchor id="boost.unordered_set.swap_id1"/><phrase role="identifier">swap</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_set</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><para><computeroutput>x.swap(y)</computeroutput></para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <computeroutput>Hash</computeroutput> or <computeroutput>Pred</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.unordered_multiset"><refmeta><refentrytitle>Class template unordered_multiset</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::unordered_multiset</refname><refpurpose>
+ An unordered associative container that stores values. The same key can be stored multiple times.
+ </refpurpose></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.unordered_set_hpp">boost/unordered_set.hpp</link>&gt;
+
+</phrase><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">hash</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Pred <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">equal_to</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <link linkend="boost.unordered_multiset">unordered_multiset</link> <phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="comment">// <link linkend="boost.unordered_multisettypes">types</link></phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Value</phrase> <anchor id="boost.unordered_multiset.key_type"/><phrase role="identifier">key_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Value</phrase> <anchor id="boost.unordered_multiset.value_type"/><phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Hash</phrase> <anchor id="boost.unordered_multiset.hasher"/><phrase role="identifier">hasher</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Pred</phrase> <anchor id="boost.unordered_multiset.key_equal"/><phrase role="identifier">key_equal</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Alloc</phrase> <anchor id="boost.unordered_multiset.allocator_type"/><phrase role="identifier">allocator_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">pointer</phrase> <anchor id="boost.unordered_multiset.pointer"/><phrase role="identifier">pointer</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">const_pointer</phrase> <anchor id="boost.unordered_multiset.const_pointer"/><phrase role="identifier">const_pointer</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">reference</phrase> <anchor id="boost.unordered_multiset.reference"/><phrase role="identifier">reference</phrase><phrase role="special">;</phrase> <phrase role="comment">// lvalue of value_type.</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">const_reference</phrase> <anchor id="boost.unordered_multiset.const_reference"/><phrase role="identifier">const_reference</phrase><phrase role="special">;</phrase> <phrase role="comment">// const lvalue of value_type.</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multiset.size_type"><phrase role="identifier">size_type</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multiset.difference_type"><phrase role="identifier">difference_type</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multiset.iterator"><phrase role="identifier">iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multiset.const_iterator"><phrase role="identifier">const_iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multiset.local_iterator"><phrase role="identifier">local_iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multiset.const_local_iterator"><phrase role="identifier">const_local_iterator</phrase></link><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="boost.unordered_multisetconstruct-copy-destruct">construct/copy/destruct</link></phrase>
+ <phrase role="keyword">explicit</phrase> <link linkend="id70-bb"><phrase role="identifier">unordered_multiset</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <link linkend="id71-bb"><phrase role="identifier">unordered_multiset</phrase></link><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">size_type</phrase> <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id72-bb"><phrase role="identifier">unordered_multiset</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id73-bb"><phrase role="identifier">unordered_multiset</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">explicit</phrase> <link linkend="id74-bb"><phrase role="identifier">unordered_multiset</phrase></link><phrase role="special">(</phrase><phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id75-bb"><phrase role="identifier">unordered_multiset</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id76-bb"><phrase role="special">~</phrase><phrase role="identifier">unordered_multiset</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">unordered_multiset</phrase><phrase role="special">&amp;</phrase> <link linkend="id77-bb"><phrase role="keyword">operator</phrase><phrase role="special">=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">unordered_multiset</phrase><phrase role="special">&amp;</phrase> <link linkend="id78-bb"><phrase role="keyword">operator</phrase><phrase role="special">=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">allocator_type</phrase> <link linkend="id79-bb"><phrase role="identifier">get_allocator</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id80-bb">size and capacity</link></phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="id81-bb"><phrase role="identifier">empty</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id82-bb"><phrase role="identifier">size</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id83-bb"><phrase role="identifier">max_size</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id84-bb">iterators</link></phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id86-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id87-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id89-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id90-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id91-bb"><phrase role="identifier">cbegin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id92-bb"><phrase role="identifier">cend</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id93-bb">modifiers</link></phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">iterator</phrase> <link linkend="id94-bb"><phrase role="identifier">emplace</phrase></link><phrase role="special">(</phrase><phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">iterator</phrase> <link linkend="id95-bb"><phrase role="identifier">emplace_hint</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id96-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id97-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase> <phrase role="keyword">void</phrase> <link linkend="id98-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id99-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id100-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id101-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id102-bb"><phrase role="identifier">quick_erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id103-bb"><phrase role="identifier">erase_return_void</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id104-bb"><phrase role="identifier">clear</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id105-bb"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id106-bb">observers</link></phrase>
+ <phrase role="identifier">hasher</phrase> <link linkend="id107-bb"><phrase role="identifier">hash_function</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">key_equal</phrase> <link linkend="id108-bb"><phrase role="identifier">key_eq</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id109-bb">lookup</link></phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id111-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id112-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id113-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">const_iterator</phrase>
+ <link linkend="id114-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id115-bb"><phrase role="identifier">count</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">&gt;</phrase> <link linkend="id117-bb"><phrase role="identifier">equal_range</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">&gt;</phrase> <link linkend="id118-bb"><phrase role="identifier">equal_range</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id119-bb">bucket interface</link></phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id120-bb"><phrase role="identifier">bucket_count</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id121-bb"><phrase role="identifier">max_bucket_count</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id122-bb"><phrase role="identifier">bucket_size</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id123-bb"><phrase role="identifier">bucket</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">local_iterator</phrase> <link linkend="id125-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id126-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">local_iterator</phrase> <link linkend="id128-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id129-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id130-bb"><phrase role="identifier">cbegin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id131-bb"><phrase role="identifier">cend</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id132-bb">hash policy</link></phrase>
+ <phrase role="keyword">float</phrase> <link linkend="id133-bb"><phrase role="identifier">load_factor</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">float</phrase> <link linkend="id134-bb"><phrase role="identifier">max_load_factor</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id135-bb"><phrase role="identifier">max_load_factor</phrase></link><phrase role="special">(</phrase><phrase role="keyword">float</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id136-bb"><phrase role="identifier">rehash</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase>
+
+<phrase role="comment">// <link linkend="id137-bb">Equality Comparisons</link></phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multiset.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+<phrase role="comment">// <link linkend="id138-bb">swap</link></phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="boost.unordered_multiset.swap_id1"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title>
+ <para>Based on chapter 23 of
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
+ But without the updated rules for allocators.
+ </para>
+ <para><emphasis role="bold">Template Parameters</emphasis>
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry><emphasis>Value</emphasis></entry>
+ <entry>Value must be Assignable and CopyConstructible</entry></row>
+ <row>
+ <entry><emphasis>Hash</emphasis></entry>
+ <entry>A unary function object type that acts a hash function for a <computeroutput>Value</computeroutput>. It takes a single argument of type <computeroutput>Value</computeroutput> and returns a value of type std::size_t.</entry></row>
+ <row>
+ <entry><emphasis>Pred</emphasis></entry>
+ <entry>A binary function object that implements an equivalence relation on values of type <computeroutput>Value</computeroutput>.
+ A binary function object that induces an equivalence relation on values of type Key.
+ It takes two arguments of type Key and returns a value of type bool.</entry></row>
+ <row>
+ <entry><emphasis>Alloc</emphasis></entry>
+ <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
+ <para>The elements are organized into buckets. Keys with the same hash code are stored in the same bucket and elements with equivalent keys are stored next to each other.</para>
+ <para>The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash.</para>
+ <refsect2><title><anchor id="boost.unordered_multisettypes"/><computeroutput>unordered_multiset</computeroutput>
+ public
+ types</title><orderedlist><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multiset.size_type"/><phrase role="identifier">size_type</phrase><phrase role="special">;</phrase></para>
+ <para>An unsigned integral type.</para>
+ <para>size_type can represent any non-negative value of difference_type.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multiset.difference_type"/><phrase role="identifier">difference_type</phrase><phrase role="special">;</phrase></para>
+ <para>A signed integral type.</para>
+ <para>Is identical to the difference type of iterator and const_iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multiset.iterator"/><phrase role="identifier">iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A constant iterator whose value type is value_type. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ <para>Convertible to const_iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multiset.const_iterator"/><phrase role="identifier">const_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A constant iterator whose value type is value_type. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multiset.local_iterator"/><phrase role="identifier">local_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>An iterator with the same value type, difference type and pointer and reference type as iterator.</para>
+ <para>A local_iterator object can be used to iterate through a single bucket.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multiset.const_local_iterator"/><phrase role="identifier">const_local_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A constant iterator with the same value type, difference type and pointer and reference type as const_iterator.</para>
+ <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
+ </listitem></orderedlist></refsect2><refsect2><title><anchor id="boost.unordered_multisetconstruct-copy-destruct"/><computeroutput>unordered_multiset</computeroutput>
+ public
+ construct/copy/destruct</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">explicit</phrase> <anchor id="id70-bb"/><phrase role="identifier">unordered_multiset</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hf <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Postconditions:</term><listitem><computeroutput><link linkend="id82-bb">size</link>() == 0</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <anchor id="id71-bb"/><phrase role="identifier">unordered_multiset</phrase><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase> f<phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase> l<phrase role="special">,</phrase>
+ <phrase role="identifier">size_type</phrase> n <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hf <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id72-bb"/><phrase role="identifier">unordered_multiset</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>value_type</computeroutput> is copy constructible</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id73-bb"/><phrase role="identifier">unordered_multiset</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The move constructor.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is emulated on compilers without rvalue references.</para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para>
+ <computeroutput>value_type</computeroutput> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">explicit</phrase> <anchor id="id74-bb"/><phrase role="identifier">unordered_multiset</phrase><phrase role="special">(</phrase><phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container, using allocator <computeroutput>a</computeroutput>.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id75-bb"/><phrase role="identifier">unordered_multiset</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an container, copying <computeroutput>x</computeroutput>'s contained elements, hash function, predicate, maximum load factor, but using allocator <computeroutput>a</computeroutput>.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id76-bb"/><phrase role="special">~</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>The destructor is applied to every element, and all memory is deallocated</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><para><literallayout class="monospaced"><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&amp;</phrase> <anchor id="id77-bb"/><phrase role="keyword">operator</phrase><phrase role="special">=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <computeroutput>operator=(unordered_multiset)</computeroutput>
+ in order to emulate move semantics.
+ </para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para><computeroutput>value_type</computeroutput> is copy constructible</para></listitem></varlistentry></variablelist><para><literallayout class="monospaced"><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&amp;</phrase> <anchor id="id78-bb"/><phrase role="keyword">operator</phrase><phrase role="special">=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The move assignment operator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <computeroutput>operator=(unordered_multiset)</computeroutput>
+ in order to emulate move semantics.
+ </para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para>
+ <computeroutput>value_type</computeroutput> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para></listitem></varlistentry></variablelist><para><literallayout class="monospaced"><phrase role="identifier">allocator_type</phrase> <anchor id="id79-bb"/><phrase role="identifier">get_allocator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><refsect2><title><anchor id="id80-bb"/><computeroutput>unordered_multiset</computeroutput> size and capacity</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">bool</phrase> <anchor id="id81-bb"/><phrase role="identifier">empty</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput><link linkend="id82-bb">size</link>() == 0</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id82-bb"/><phrase role="identifier">size</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput>std::distance(<link linkend="id85-bb">begin</link>(), <link linkend="id88-bb">end</link>())</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id83-bb"/><phrase role="identifier">max_size</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput><link linkend="id82-bb">size</link>()</computeroutput> of the largest possible container.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id84-bb"/><computeroutput>unordered_multiset</computeroutput> iterators</title><orderedlist><listitem><para><literallayout class="monospaced"><anchor id="id85-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id86-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id87-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id88-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id89-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id90-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>An iterator which refers to the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_iterator</phrase> <anchor id="id91-bb"/><phrase role="identifier">cbegin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>A constant iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_iterator</phrase> <anchor id="id92-bb"/><phrase role="identifier">cend</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>A constant iterator which refers to the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id93-bb"/><computeroutput>unordered_multiset</computeroutput> modifiers</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">iterator</phrase> <anchor id="id94-bb"/><phrase role="identifier">emplace</phrase><phrase role="special">(</phrase><phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase> args<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts an object, constructed with the arguments <computeroutput>args</computeroutput>, in the container.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to the inserted element.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para><para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <anchor id="id95-bb"/><phrase role="identifier">emplace_hint</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> hint<phrase role="special">,</phrase> <phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase> args<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts an object, constructed with the arguments <computeroutput>args</computeroutput>, in the container.</para><para>hint is a suggestion to where the element should be inserted.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to the inserted element.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same value. </para><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para><para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id96-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> obj<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts obj in the container.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to the inserted element.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id97-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> hint<phrase role="special">,</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> obj<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts obj in the container.</para><para>hint is a suggestion to where the element should be inserted.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to the inserted element.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same value. </para><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <anchor id="id98-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase> first<phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase> last<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts a range of elements into the container.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>When inserting a single element, if an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id99-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The iterator following <computeroutput>position</computeroutput> before the erasure.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ When the number of elements is a lot smaller than the number of buckets
+ this function can be very inefficient as it has to search through empty
+ buckets for the next element, in order to return the iterator.
+ The method <link linkend="id102-bb">quick_erase</link> is faster, but has yet
+ to be standardized.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id100-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase all elements with key equivalent to <computeroutput>k</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of elements erased.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id101-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> first<phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase> last<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erases the elements in the range from <computeroutput>first</computeroutput> to <computeroutput>last</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The iterator following the erased elements - i.e. <computeroutput>last</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id102-bb"/><phrase role="identifier">quick_erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ This method is faster than <link linkend="id99-bb">erase</link> as
+ it doesn't have to find the next element in the container -
+ a potentially costly operation.
+ </para><para>
+ As it hasn't been standardized, it's likely that this may
+ change in the future.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id103-bb"/><phrase role="identifier">erase_return_void</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ This method is now deprecated, use
+ quick_return instead. Although be
+ warned that as that isn't standardized yet, it could also
+ change.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id104-bb"/><phrase role="identifier">clear</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erases all elements in the container.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Postconditions:</term><listitem><para><computeroutput><link linkend="id82-bb">size</link>() == 0</computeroutput></para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Never throws an exception.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id105-bb"/><phrase role="identifier">swap</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <computeroutput>key_equal</computeroutput> or <computeroutput>hasher</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id106-bb"/><computeroutput>unordered_multiset</computeroutput> observers</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="identifier">hasher</phrase> <anchor id="id107-bb"/><phrase role="identifier">hash_function</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>The container's hash function.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">key_equal</phrase> <anchor id="id108-bb"/><phrase role="identifier">key_eq</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>The container's key equality predicate.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id109-bb"/><computeroutput>unordered_multiset</computeroutput> lookup</title><orderedlist><listitem><para><literallayout class="monospaced"><anchor id="id110-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id111-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id112-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <anchor id="id113-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hash<phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">const_iterator</phrase>
+ <anchor id="id114-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hash<phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to an element with key equivalent to <computeroutput>k</computeroutput>, or <computeroutput>b.end()</computeroutput> if no such element exists.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ The templated overloads are a non-standard extensions which
+ allows you to use a compatible hash function and equality
+ predicate for a key of a different type in order to avoid
+ an expensive type cast. In general, its use is not encouraged.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id115-bb"/><phrase role="identifier">count</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of elements with key equivalent to <computeroutput>k</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id116-bb"/><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">&gt;</phrase> <anchor id="id117-bb"/><phrase role="identifier">equal_range</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">&gt;</phrase> <anchor id="id118-bb"/><phrase role="identifier">equal_range</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>A range containing all elements with key equivalent to <computeroutput>k</computeroutput>.
+ If the container doesn't container any such elements, returns
+ <computeroutput>std::make_pair(b.end(),b.end())</computeroutput>.
+ </para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id119-bb"/><computeroutput>unordered_multiset</computeroutput> bucket interface</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id120-bb"/><phrase role="identifier">bucket_count</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of buckets.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id121-bb"/><phrase role="identifier">max_bucket_count</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An upper bound on the number of buckets.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id122-bb"/><phrase role="identifier">bucket_size</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n &lt; <link linkend="id120-bb">bucket_count</link>()</computeroutput></para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>The number of elements in bucket <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id123-bb"/><phrase role="identifier">bucket</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The index of the bucket which would contain an element with key <computeroutput>k</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Postconditions:</term><listitem><para>The return value is less than <computeroutput>bucket_count()</computeroutput></para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id124-bb"/><phrase role="identifier">local_iterator</phrase> <anchor id="id125-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_local_iterator</phrase> <anchor id="id126-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A local iterator pointing the first element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id127-bb"/><phrase role="identifier">local_iterator</phrase> <anchor id="id128-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_local_iterator</phrase> <anchor id="id129-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A local iterator pointing the 'one past the end' element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_local_iterator</phrase> <anchor id="id130-bb"/><phrase role="identifier">cbegin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A constant local iterator pointing the first element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_local_iterator</phrase> <anchor id="id131-bb"/><phrase role="identifier">cend</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A constant local iterator pointing the 'one past the end' element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id132-bb"/><computeroutput>unordered_multiset</computeroutput> hash policy</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">float</phrase> <anchor id="id133-bb"/><phrase role="identifier">load_factor</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The average number of elements per bucket.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">float</phrase> <anchor id="id134-bb"/><phrase role="identifier">max_load_factor</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Returns the current maximum load factor.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id135-bb"/><phrase role="identifier">max_load_factor</phrase><phrase role="special">(</phrase><phrase role="keyword">float</phrase> z<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><para>Changes the container's maximum load factor, using <computeroutput>z</computeroutput> as a hint.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id136-bb"/><phrase role="identifier">rehash</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Changes the number of buckets so that there at least <computeroutput>n</computeroutput> buckets, and so that the load factor is less than the maximum load factor.</para><para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id137-bb"/><computeroutput>unordered_multiset</computeroutput> Equality Comparisons</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multiset.operator==_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multiset.operator!=_id1"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id138-bb"/><computeroutput>unordered_multiset</computeroutput> swap</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Value<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <anchor id="boost.unordered_multiset.swap_id1"/><phrase role="identifier">swap</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multiset</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Value</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><para><computeroutput>x.swap(y)</computeroutput></para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <computeroutput>Hash</computeroutput> or <computeroutput>Pred</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2></refsect1></refentry>
+ </section>
+ <section id="header.boost.unordered_map_hpp"><title>Header &lt;<ulink url="../../boost/unordered_map.hpp">boost/unordered_map.hpp</ulink>&gt;</title><synopsis xmlns:xi="http://www.w3.org/2001/XInclude"><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">hash</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Pred <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">equal_to</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="keyword">class</phrase> <link linkend="boost.unordered_map">unordered_map</link><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="boost.unordered_map.swap_id1"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">hash</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Pred <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">equal_to</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="keyword">class</phrase> <link linkend="boost.unordered_multimap">unordered_multimap</link><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="boost.unordered_multimap.swap_id1"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase></synopsis>
+ <refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.unordered_map"><refmeta><refentrytitle>Class template unordered_map</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::unordered_map</refname><refpurpose>
+ An unordered associative container that associates unique keys with another value.
+ </refpurpose></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.unordered_map_hpp">boost/unordered_map.hpp</link>&gt;
+
+</phrase><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">hash</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Pred <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">equal_to</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <link linkend="boost.unordered_map">unordered_map</link> <phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="comment">// <link linkend="boost.unordered_maptypes">types</link></phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Key</phrase> <anchor id="boost.unordered_map.key_type"/><phrase role="identifier">key_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">&gt;</phrase> <anchor id="boost.unordered_map.value_type"/><phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Mapped</phrase> <anchor id="boost.unordered_map.mapped_type"/><phrase role="identifier">mapped_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Hash</phrase> <anchor id="boost.unordered_map.hasher"/><phrase role="identifier">hasher</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Pred</phrase> <anchor id="boost.unordered_map.key_equal"/><phrase role="identifier">key_equal</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Alloc</phrase> <anchor id="boost.unordered_map.allocator_type"/><phrase role="identifier">allocator_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">pointer</phrase> <anchor id="boost.unordered_map.pointer"/><phrase role="identifier">pointer</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">const_pointer</phrase> <anchor id="boost.unordered_map.const_pointer"/><phrase role="identifier">const_pointer</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">reference</phrase> <anchor id="boost.unordered_map.reference"/><phrase role="identifier">reference</phrase><phrase role="special">;</phrase> <phrase role="comment">// lvalue of value_type.</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">const_reference</phrase> <anchor id="boost.unordered_map.const_reference"/><phrase role="identifier">const_reference</phrase><phrase role="special">;</phrase> <phrase role="comment">// const lvalue of value_type.</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_map.size_type"><phrase role="identifier">size_type</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_map.difference_type"><phrase role="identifier">difference_type</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_map.iterator"><phrase role="identifier">iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_map.const_iterator"><phrase role="identifier">const_iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_map.local_iterator"><phrase role="identifier">local_iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_map.const_local_iterator"><phrase role="identifier">const_local_iterator</phrase></link><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="boost.unordered_mapconstruct-copy-destruct">construct/copy/destruct</link></phrase>
+ <phrase role="keyword">explicit</phrase> <link linkend="id139-bb"><phrase role="identifier">unordered_map</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <link linkend="id140-bb"><phrase role="identifier">unordered_map</phrase></link><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">size_type</phrase> <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase> <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id141-bb"><phrase role="identifier">unordered_map</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id142-bb"><phrase role="identifier">unordered_map</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">explicit</phrase> <link linkend="id143-bb"><phrase role="identifier">unordered_map</phrase></link><phrase role="special">(</phrase><phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id144-bb"><phrase role="identifier">unordered_map</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id145-bb"><phrase role="special">~</phrase><phrase role="identifier">unordered_map</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">unordered_map</phrase><phrase role="special">&amp;</phrase> <link linkend="id146-bb"><phrase role="keyword">operator</phrase><phrase role="special">=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">unordered_map</phrase><phrase role="special">&amp;</phrase> <link linkend="id147-bb"><phrase role="keyword">operator</phrase><phrase role="special">=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">allocator_type</phrase> <link linkend="id148-bb"><phrase role="identifier">get_allocator</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id149-bb">size and capacity</link></phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="id150-bb"><phrase role="identifier">empty</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id151-bb"><phrase role="identifier">size</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id152-bb"><phrase role="identifier">max_size</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id153-bb">iterators</link></phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id155-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id156-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id158-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id159-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id160-bb"><phrase role="identifier">cbegin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id161-bb"><phrase role="identifier">cend</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id162-bb">modifiers</link></phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase> <link linkend="id163-bb"><phrase role="identifier">emplace</phrase></link><phrase role="special">(</phrase><phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">iterator</phrase> <link linkend="id164-bb"><phrase role="identifier">emplace_hint</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase> <link linkend="id165-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id166-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase> <phrase role="keyword">void</phrase> <link linkend="id167-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id168-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id169-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id170-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id171-bb"><phrase role="identifier">quick_erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id172-bb"><phrase role="identifier">erase_return_void</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id173-bb"><phrase role="identifier">clear</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id174-bb"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id175-bb">observers</link></phrase>
+ <phrase role="identifier">hasher</phrase> <link linkend="id176-bb"><phrase role="identifier">hash_function</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">key_equal</phrase> <link linkend="id177-bb"><phrase role="identifier">key_eq</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id178-bb">lookup</link></phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id180-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id181-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id182-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">const_iterator</phrase>
+ <link linkend="id183-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id184-bb"><phrase role="identifier">count</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">&gt;</phrase> <link linkend="id186-bb"><phrase role="identifier">equal_range</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">&gt;</phrase> <link linkend="id187-bb"><phrase role="identifier">equal_range</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">mapped_type</phrase><phrase role="special">&amp;</phrase> <link linkend="id188-bb"><phrase role="keyword">operator</phrase><phrase role="special">[</phrase><phrase role="special">]</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">Mapped</phrase><phrase role="special">&amp;</phrase> <link linkend="id190-bb"><phrase role="identifier">at</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">Mapped</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <link linkend="id191-bb"><phrase role="identifier">at</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id192-bb">bucket interface</link></phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id193-bb"><phrase role="identifier">bucket_count</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id194-bb"><phrase role="identifier">max_bucket_count</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id195-bb"><phrase role="identifier">bucket_size</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id196-bb"><phrase role="identifier">bucket</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">local_iterator</phrase> <link linkend="id198-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id199-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">local_iterator</phrase> <link linkend="id201-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id202-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id203-bb"><phrase role="identifier">cbegin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id204-bb"><phrase role="identifier">cend</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id205-bb">hash policy</link></phrase>
+ <phrase role="keyword">float</phrase> <link linkend="id206-bb"><phrase role="identifier">load_factor</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">float</phrase> <link linkend="id207-bb"><phrase role="identifier">max_load_factor</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id208-bb"><phrase role="identifier">max_load_factor</phrase></link><phrase role="special">(</phrase><phrase role="keyword">float</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id209-bb"><phrase role="identifier">rehash</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase>
+
+<phrase role="comment">// <link linkend="id210-bb">Equality Comparisons</link></phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_map.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+<phrase role="comment">// <link linkend="id211-bb">swap</link></phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="boost.unordered_map.swap_id1"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title>
+ <para>Based on chapter 23 of
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
+ But without the updated rules for allocators.
+ </para>
+ <para><emphasis role="bold">Template Parameters</emphasis>
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry><emphasis>Key</emphasis></entry>
+ <entry>Key must be Assignable and CopyConstructible.</entry></row>
+ <row>
+ <entry><emphasis>Mapped</emphasis></entry>
+ <entry>Mapped must be CopyConstructible</entry></row>
+ <row>
+ <entry><emphasis>Hash</emphasis></entry>
+ <entry>A unary function object type that acts a hash function for a <computeroutput>Key</computeroutput>. It takes a single argument of type <computeroutput>Key</computeroutput> and returns a value of type std::size_t.</entry></row>
+ <row>
+ <entry><emphasis>Pred</emphasis></entry>
+ <entry>A binary function object that implements an equivalence relation on values of type <computeroutput>Key</computeroutput>.
+ A binary function object that induces an equivalence relation on values of type Key.
+ It takes two arguments of type Key and returns a value of type bool.</entry></row>
+ <row>
+ <entry><emphasis>Alloc</emphasis></entry>
+ <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
+ <para>The elements are organized into buckets. Keys with the same hash code are stored in the same bucket.</para>
+ <para>The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash.</para>
+ <refsect2><title><anchor id="boost.unordered_maptypes"/><computeroutput>unordered_map</computeroutput>
+ public
+ types</title><orderedlist><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_map.size_type"/><phrase role="identifier">size_type</phrase><phrase role="special">;</phrase></para>
+ <para>An unsigned integral type.</para>
+ <para>size_type can represent any non-negative value of difference_type.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_map.difference_type"/><phrase role="identifier">difference_type</phrase><phrase role="special">;</phrase></para>
+ <para>A signed integral type.</para>
+ <para>Is identical to the difference type of iterator and const_iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_map.iterator"/><phrase role="identifier">iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A iterator whose value type is value_type. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ <para>Convertible to const_iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_map.const_iterator"/><phrase role="identifier">const_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A constant iterator whose value type is value_type. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_map.local_iterator"/><phrase role="identifier">local_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>An iterator with the same value type, difference type and pointer and reference type as iterator.</para>
+ <para>A local_iterator object can be used to iterate through a single bucket.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_map.const_local_iterator"/><phrase role="identifier">const_local_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A constant iterator with the same value type, difference type and pointer and reference type as const_iterator.</para>
+ <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
+ </listitem></orderedlist></refsect2><refsect2><title><anchor id="boost.unordered_mapconstruct-copy-destruct"/><computeroutput>unordered_map</computeroutput>
+ public
+ construct/copy/destruct</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">explicit</phrase> <anchor id="id139-bb"/><phrase role="identifier">unordered_map</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hf <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Postconditions:</term><listitem><computeroutput><link linkend="id151-bb">size</link>() == 0</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <anchor id="id140-bb"/><phrase role="identifier">unordered_map</phrase><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase> f<phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase> l<phrase role="special">,</phrase>
+ <phrase role="identifier">size_type</phrase> n <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hf <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id141-bb"/><phrase role="identifier">unordered_map</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>value_type</computeroutput> is copy constructible</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id142-bb"/><phrase role="identifier">unordered_map</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The move constructor.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is emulated on compilers without rvalue references.</para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para>
+ <computeroutput>value_type</computeroutput> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">explicit</phrase> <anchor id="id143-bb"/><phrase role="identifier">unordered_map</phrase><phrase role="special">(</phrase><phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container, using allocator <computeroutput>a</computeroutput>.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id144-bb"/><phrase role="identifier">unordered_map</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an container, copying <computeroutput>x</computeroutput>'s contained elements, hash function, predicate, maximum load factor, but using allocator <computeroutput>a</computeroutput>.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id145-bb"/><phrase role="special">~</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>The destructor is applied to every element, and all memory is deallocated</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><para><literallayout class="monospaced"><phrase role="identifier">unordered_map</phrase><phrase role="special">&amp;</phrase> <anchor id="id146-bb"/><phrase role="keyword">operator</phrase><phrase role="special">=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <computeroutput>operator=(unordered_map)</computeroutput>
+ in order to emulate move semantics.
+ </para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para><computeroutput>value_type</computeroutput> is copy constructible</para></listitem></varlistentry></variablelist><para><literallayout class="monospaced"><phrase role="identifier">unordered_map</phrase><phrase role="special">&amp;</phrase> <anchor id="id147-bb"/><phrase role="keyword">operator</phrase><phrase role="special">=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The move assignment operator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <computeroutput>operator=(unordered_map)</computeroutput>
+ in order to emulate move semantics.
+ </para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para>
+ <computeroutput>value_type</computeroutput> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para></listitem></varlistentry></variablelist><para><literallayout class="monospaced"><phrase role="identifier">allocator_type</phrase> <anchor id="id148-bb"/><phrase role="identifier">get_allocator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><refsect2><title><anchor id="id149-bb"/><computeroutput>unordered_map</computeroutput> size and capacity</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">bool</phrase> <anchor id="id150-bb"/><phrase role="identifier">empty</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput><link linkend="id151-bb">size</link>() == 0</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id151-bb"/><phrase role="identifier">size</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput>std::distance(<link linkend="id154-bb">begin</link>(), <link linkend="id157-bb">end</link>())</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id152-bb"/><phrase role="identifier">max_size</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput><link linkend="id151-bb">size</link>()</computeroutput> of the largest possible container.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id153-bb"/><computeroutput>unordered_map</computeroutput> iterators</title><orderedlist><listitem><para><literallayout class="monospaced"><anchor id="id154-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id155-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id156-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id157-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id158-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id159-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>An iterator which refers to the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_iterator</phrase> <anchor id="id160-bb"/><phrase role="identifier">cbegin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>A constant iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_iterator</phrase> <anchor id="id161-bb"/><phrase role="identifier">cend</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>A constant iterator which refers to the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id162-bb"/><computeroutput>unordered_map</computeroutput> modifiers</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase> <anchor id="id163-bb"/><phrase role="identifier">emplace</phrase><phrase role="special">(</phrase><phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase> args<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts an object, constructed with the arguments <computeroutput>args</computeroutput>, in the container if and only if there is no element in the container with an equivalent key.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The bool component of the return type is true if an insert took place.</para><para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para><para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <anchor id="id164-bb"/><phrase role="identifier">emplace_hint</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> hint<phrase role="special">,</phrase> <phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase> args<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts an object, constructed with the arguments <computeroutput>args</computeroutput>, in the container if and only if there is no element in the container with an equivalent key.</para><para>hint is a suggestion to where the element should be inserted.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. </para><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para><para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase><phrase role="special">&gt;</phrase> <anchor id="id165-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> obj<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts obj in the container if and only if there is no element in the container with an equivalent key.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The bool component of the return type is true if an insert took place.</para><para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id166-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> hint<phrase role="special">,</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> obj<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts obj in the container if and only if there is no element in the container with an equivalent key.</para><para>hint is a suggestion to where the element should be inserted.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. </para><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <anchor id="id167-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase> first<phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase> last<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>When inserting a single element, if an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id168-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The iterator following <computeroutput>position</computeroutput> before the erasure.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ When the number of elements is a lot smaller than the number of buckets
+ this function can be very inefficient as it has to search through empty
+ buckets for the next element, in order to return the iterator.
+ The method <link linkend="id171-bb">quick_erase</link> is faster, but has yet
+ to be standardized.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id169-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase all elements with key equivalent to <computeroutput>k</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of elements erased.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id170-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> first<phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase> last<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erases the elements in the range from <computeroutput>first</computeroutput> to <computeroutput>last</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The iterator following the erased elements - i.e. <computeroutput>last</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id171-bb"/><phrase role="identifier">quick_erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ This method is faster than <link linkend="id168-bb">erase</link> as
+ it doesn't have to find the next element in the container -
+ a potentially costly operation.
+ </para><para>
+ As it hasn't been standardized, it's likely that this may
+ change in the future.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id172-bb"/><phrase role="identifier">erase_return_void</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ This method is now deprecated, use
+ quick_return instead. Although be
+ warned that as that isn't standardized yet, it could also
+ change.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id173-bb"/><phrase role="identifier">clear</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erases all elements in the container.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Postconditions:</term><listitem><para><computeroutput><link linkend="id151-bb">size</link>() == 0</computeroutput></para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Never throws an exception.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id174-bb"/><phrase role="identifier">swap</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <computeroutput>key_equal</computeroutput> or <computeroutput>hasher</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id175-bb"/><computeroutput>unordered_map</computeroutput> observers</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="identifier">hasher</phrase> <anchor id="id176-bb"/><phrase role="identifier">hash_function</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>The container's hash function.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">key_equal</phrase> <anchor id="id177-bb"/><phrase role="identifier">key_eq</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>The container's key equality predicate.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id178-bb"/><computeroutput>unordered_map</computeroutput> lookup</title><orderedlist><listitem><para><literallayout class="monospaced"><anchor id="id179-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id180-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id181-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <anchor id="id182-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hash<phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">const_iterator</phrase>
+ <anchor id="id183-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hash<phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to an element with key equivalent to <computeroutput>k</computeroutput>, or <computeroutput>b.end()</computeroutput> if no such element exists.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ The templated overloads are a non-standard extensions which
+ allows you to use a compatible hash function and equality
+ predicate for a key of a different type in order to avoid
+ an expensive type cast. In general, its use is not encouraged.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id184-bb"/><phrase role="identifier">count</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of elements with key equivalent to <computeroutput>k</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id185-bb"/><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">&gt;</phrase> <anchor id="id186-bb"/><phrase role="identifier">equal_range</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">&gt;</phrase> <anchor id="id187-bb"/><phrase role="identifier">equal_range</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>A range containing all elements with key equivalent to <computeroutput>k</computeroutput>.
+ If the container doesn't container any such elements, returns
+ <computeroutput>std::make_pair(b.end(),b.end())</computeroutput>.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">mapped_type</phrase><phrase role="special">&amp;</phrase> <anchor id="id188-bb"/><phrase role="keyword">operator</phrase><phrase role="special">[</phrase><phrase role="special">]</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><para>If the container does not already contain an elements with a key equivalent to <computeroutput>k</computeroutput>, inserts the value <computeroutput>std::pair&lt;key_type const, mapped_type&gt;(k, mapped_type())</computeroutput></para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A reference to <computeroutput>x.second</computeroutput> where x is the element already in the container, or the newly inserted element with a key equivalent to <computeroutput>k</computeroutput></para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id189-bb"/><phrase role="identifier">Mapped</phrase><phrase role="special">&amp;</phrase> <anchor id="id190-bb"/><phrase role="identifier">at</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">Mapped</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <anchor id="id191-bb"/><phrase role="identifier">at</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>A reference to <computeroutput>x.second</computeroutput> where <computeroutput>x</computeroutput> is the (unique) element whose key is equivalent to <computeroutput>k</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>An exception object of type <computeroutput>std::out_of_range</computeroutput> if no such element is present.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>This is not specified in the draft standard, but that is probably an oversight. The issue has been raised in
+ <ulink url="http://groups.google.com/group/comp.std.c++/browse_thread/thread/ab7c22a868fd370b">comp.std.c++</ulink>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id192-bb"/><computeroutput>unordered_map</computeroutput> bucket interface</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id193-bb"/><phrase role="identifier">bucket_count</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of buckets.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id194-bb"/><phrase role="identifier">max_bucket_count</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An upper bound on the number of buckets.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id195-bb"/><phrase role="identifier">bucket_size</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n &lt; <link linkend="id193-bb">bucket_count</link>()</computeroutput></para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>The number of elements in bucket <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id196-bb"/><phrase role="identifier">bucket</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The index of the bucket which would contain an element with key <computeroutput>k</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Postconditions:</term><listitem><para>The return value is less than <computeroutput>bucket_count()</computeroutput></para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id197-bb"/><phrase role="identifier">local_iterator</phrase> <anchor id="id198-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_local_iterator</phrase> <anchor id="id199-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A local iterator pointing the first element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id200-bb"/><phrase role="identifier">local_iterator</phrase> <anchor id="id201-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_local_iterator</phrase> <anchor id="id202-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A local iterator pointing the 'one past the end' element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_local_iterator</phrase> <anchor id="id203-bb"/><phrase role="identifier">cbegin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A constant local iterator pointing the first element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_local_iterator</phrase> <anchor id="id204-bb"/><phrase role="identifier">cend</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A constant local iterator pointing the 'one past the end' element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id205-bb"/><computeroutput>unordered_map</computeroutput> hash policy</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">float</phrase> <anchor id="id206-bb"/><phrase role="identifier">load_factor</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The average number of elements per bucket.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">float</phrase> <anchor id="id207-bb"/><phrase role="identifier">max_load_factor</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Returns the current maximum load factor.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id208-bb"/><phrase role="identifier">max_load_factor</phrase><phrase role="special">(</phrase><phrase role="keyword">float</phrase> z<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><para>Changes the container's maximum load factor, using <computeroutput>z</computeroutput> as a hint.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id209-bb"/><phrase role="identifier">rehash</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Changes the number of buckets so that there at least <computeroutput>n</computeroutput> buckets, and so that the load factor is less than the maximum load factor.</para><para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id210-bb"/><computeroutput>unordered_map</computeroutput> Equality Comparisons</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_map.operator==_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_map.operator!=_id1"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id211-bb"/><computeroutput>unordered_map</computeroutput> swap</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <anchor id="boost.unordered_map.swap_id1"/><phrase role="identifier">swap</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_map</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><para><computeroutput>x.swap(y)</computeroutput></para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <computeroutput>Hash</computeroutput> or <computeroutput>Pred</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2></refsect1></refentry><refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="boost.unordered_multimap"><refmeta><refentrytitle>Class template unordered_multimap</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>boost::unordered_multimap</refname><refpurpose>
+ An unordered associative container that associates keys with another value. The same key can be stored multiple times.
+ </refpurpose></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.boost.unordered_map_hpp">boost/unordered_map.hpp</link>&gt;
+
+</phrase><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">hash</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Pred <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">equal_to</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">&gt;</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <link linkend="boost.unordered_multimap">unordered_multimap</link> <phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="comment">// <link linkend="boost.unordered_multimaptypes">types</link></phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Key</phrase> <anchor id="boost.unordered_multimap.key_type"/><phrase role="identifier">key_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase> <phrase role="keyword">const</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">&gt;</phrase> <anchor id="boost.unordered_multimap.value_type"/><phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Mapped</phrase> <anchor id="boost.unordered_multimap.mapped_type"/><phrase role="identifier">mapped_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Hash</phrase> <anchor id="boost.unordered_multimap.hasher"/><phrase role="identifier">hasher</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Pred</phrase> <anchor id="boost.unordered_multimap.key_equal"/><phrase role="identifier">key_equal</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="identifier">Alloc</phrase> <anchor id="boost.unordered_multimap.allocator_type"/><phrase role="identifier">allocator_type</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">pointer</phrase> <anchor id="boost.unordered_multimap.pointer"/><phrase role="identifier">pointer</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">const_pointer</phrase> <anchor id="boost.unordered_multimap.const_pointer"/><phrase role="identifier">const_pointer</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">reference</phrase> <anchor id="boost.unordered_multimap.reference"/><phrase role="identifier">reference</phrase><phrase role="special">;</phrase> <phrase role="comment">// lvalue of value_type.</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">::</phrase><phrase role="identifier">const_reference</phrase> <anchor id="boost.unordered_multimap.const_reference"/><phrase role="identifier">const_reference</phrase><phrase role="special">;</phrase> <phrase role="comment">// const lvalue of value_type.</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multimap.size_type"><phrase role="identifier">size_type</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multimap.difference_type"><phrase role="identifier">difference_type</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multimap.iterator"><phrase role="identifier">iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multimap.const_iterator"><phrase role="identifier">const_iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multimap.local_iterator"><phrase role="identifier">local_iterator</phrase></link><phrase role="special">;</phrase>
+ <phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <link linkend="boost.unordered_multimap.const_local_iterator"><phrase role="identifier">const_local_iterator</phrase></link><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="boost.unordered_multimapconstruct-copy-destruct">construct/copy/destruct</link></phrase>
+ <phrase role="keyword">explicit</phrase> <link linkend="id212-bb"><phrase role="identifier">unordered_multimap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <link linkend="id213-bb"><phrase role="identifier">unordered_multimap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">size_type</phrase> <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id214-bb"><phrase role="identifier">unordered_multimap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id215-bb"><phrase role="identifier">unordered_multimap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">explicit</phrase> <link linkend="id216-bb"><phrase role="identifier">unordered_multimap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id217-bb"><phrase role="identifier">unordered_multimap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <link linkend="id218-bb"><phrase role="special">~</phrase><phrase role="identifier">unordered_multimap</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">unordered_multimap</phrase><phrase role="special">&amp;</phrase> <link linkend="id219-bb"><phrase role="keyword">operator</phrase><phrase role="special">=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">unordered_multimap</phrase><phrase role="special">&amp;</phrase> <link linkend="id220-bb"><phrase role="keyword">operator</phrase><phrase role="special">=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">allocator_type</phrase> <link linkend="id221-bb"><phrase role="identifier">get_allocator</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id222-bb">size and capacity</link></phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="id223-bb"><phrase role="identifier">empty</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id224-bb"><phrase role="identifier">size</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id225-bb"><phrase role="identifier">max_size</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id226-bb">iterators</link></phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id228-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id229-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id231-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id232-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id233-bb"><phrase role="identifier">cbegin</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id234-bb"><phrase role="identifier">cend</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id235-bb">modifiers</link></phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">iterator</phrase> <link linkend="id236-bb"><phrase role="identifier">emplace</phrase></link><phrase role="special">(</phrase><phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">iterator</phrase> <link linkend="id237-bb"><phrase role="identifier">emplace_hint</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id238-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id239-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase> <phrase role="keyword">void</phrase> <link linkend="id240-bb"><phrase role="identifier">insert</phrase></link><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id241-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id242-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id243-bb"><phrase role="identifier">erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id244-bb"><phrase role="identifier">quick_erase</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id245-bb"><phrase role="identifier">erase_return_void</phrase></link><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id246-bb"><phrase role="identifier">clear</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id247-bb"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id248-bb">observers</link></phrase>
+ <phrase role="identifier">hasher</phrase> <link linkend="id249-bb"><phrase role="identifier">hash_function</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">key_equal</phrase> <link linkend="id250-bb"><phrase role="identifier">key_eq</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id251-bb">lookup</link></phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id253-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_iterator</phrase> <link linkend="id254-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <link linkend="id255-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">const_iterator</phrase>
+ <link linkend="id256-bb"><phrase role="identifier">find</phrase></link><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id257-bb"><phrase role="identifier">count</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">&gt;</phrase> <link linkend="id259-bb"><phrase role="identifier">equal_range</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">&gt;</phrase> <link linkend="id260-bb"><phrase role="identifier">equal_range</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id261-bb">bucket interface</link></phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id262-bb"><phrase role="identifier">bucket_count</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id263-bb"><phrase role="identifier">max_bucket_count</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id264-bb"><phrase role="identifier">bucket_size</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">size_type</phrase> <link linkend="id265-bb"><phrase role="identifier">bucket</phrase></link><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">local_iterator</phrase> <link linkend="id267-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id268-bb"><phrase role="identifier">begin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">local_iterator</phrase> <link linkend="id270-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id271-bb"><phrase role="identifier">end</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id272-bb"><phrase role="identifier">cbegin</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="identifier">const_local_iterator</phrase> <link linkend="id273-bb"><phrase role="identifier">cend</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+ <phrase role="comment">// <link linkend="id274-bb">hash policy</link></phrase>
+ <phrase role="keyword">float</phrase> <link linkend="id275-bb"><phrase role="identifier">load_factor</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">float</phrase> <link linkend="id276-bb"><phrase role="identifier">max_load_factor</phrase></link><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id277-bb"><phrase role="identifier">max_load_factor</phrase></link><phrase role="special">(</phrase><phrase role="keyword">float</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="id278-bb"><phrase role="identifier">rehash</phrase></link><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase><phrase role="special">;</phrase>
+
+<phrase role="comment">// <link linkend="id279-bb">Equality Comparisons</link></phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operator==_id1"><phrase role="keyword">operator</phrase><phrase role="special">==</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <link linkend="boost.unordered_multimap.operator!=_id1"><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+
+<phrase role="comment">// <link linkend="id280-bb">swap</link></phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <link linkend="boost.unordered_multimap.swap_id1"><phrase role="identifier">swap</phrase></link><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></synopsis></refsynopsisdiv><refsect1><title>Description</title>
+ <para>Based on chapter 23 of
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
+ But without the updated rules for allocators.
+ </para>
+ <para><emphasis role="bold">Template Parameters</emphasis>
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry><emphasis>Key</emphasis></entry>
+ <entry>Key must be Assignable and CopyConstructible.</entry></row>
+ <row>
+ <entry><emphasis>Mapped</emphasis></entry>
+ <entry>Mapped must be CopyConstructible</entry></row>
+ <row>
+ <entry><emphasis>Hash</emphasis></entry>
+ <entry>A unary function object type that acts a hash function for a <computeroutput>Key</computeroutput>. It takes a single argument of type <computeroutput>Key</computeroutput> and returns a value of type std::size_t.</entry></row>
+ <row>
+ <entry><emphasis>Pred</emphasis></entry>
+ <entry>A binary function object that implements an equivalence relation on values of type <computeroutput>Key</computeroutput>.
+ A binary function object that induces an equivalence relation on values of type Key.
+ It takes two arguments of type Key and returns a value of type bool.</entry></row>
+ <row>
+ <entry><emphasis>Alloc</emphasis></entry>
+ <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
+ <para>The elements are organized into buckets. Keys with the same hash code are stored in the same bucket and elements with equivalent keys are stored next to each other.</para>
+ <para>The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash.</para>
+ <refsect2><title><anchor id="boost.unordered_multimaptypes"/><computeroutput>unordered_multimap</computeroutput>
+ public
+ types</title><orderedlist><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multimap.size_type"/><phrase role="identifier">size_type</phrase><phrase role="special">;</phrase></para>
+ <para>An unsigned integral type.</para>
+ <para>size_type can represent any non-negative value of difference_type.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multimap.difference_type"/><phrase role="identifier">difference_type</phrase><phrase role="special">;</phrase></para>
+ <para>A signed integral type.</para>
+ <para>Is identical to the difference type of iterator and const_iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multimap.iterator"/><phrase role="identifier">iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A iterator whose value type is value_type. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ <para>Convertible to const_iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multimap.const_iterator"/><phrase role="identifier">const_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A constant iterator whose value type is value_type. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multimap.local_iterator"/><phrase role="identifier">local_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>An iterator with the same value type, difference type and pointer and reference type as iterator.</para>
+ <para>A local_iterator object can be used to iterate through a single bucket.</para>
+ </listitem><listitem><para>
+<phrase role="keyword">typedef</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis> <anchor id="boost.unordered_multimap.const_local_iterator"/><phrase role="identifier">const_local_iterator</phrase><phrase role="special">;</phrase></para>
+ <para>A constant iterator with the same value type, difference type and pointer and reference type as const_iterator.</para>
+ <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
+ </listitem></orderedlist></refsect2><refsect2><title><anchor id="boost.unordered_multimapconstruct-copy-destruct"/><computeroutput>unordered_multimap</computeroutput>
+ public
+ construct/copy/destruct</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">explicit</phrase> <anchor id="id212-bb"/><phrase role="identifier">unordered_multimap</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hf <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Postconditions:</term><listitem><computeroutput><link linkend="id224-bb">size</link>() == 0</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <anchor id="id213-bb"/><phrase role="identifier">unordered_multimap</phrase><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase> f<phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase> l<phrase role="special">,</phrase>
+ <phrase role="identifier">size_type</phrase> n <phrase role="special">=</phrase> <emphasis><phrase role="identifier">implementation</phrase><phrase role="special">-</phrase><phrase role="identifier">defined</phrase></emphasis><phrase role="special">,</phrase>
+ <phrase role="identifier">hasher</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hf <phrase role="special">=</phrase> <phrase role="identifier">hasher</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">key_equal</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq <phrase role="special">=</phrase> <phrase role="identifier">key_equal</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">allocator_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a <phrase role="special">=</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id214-bb"/><phrase role="identifier">unordered_multimap</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>value_type</computeroutput> is copy constructible</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id215-bb"/><phrase role="identifier">unordered_multimap</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The move constructor.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is emulated on compilers without rvalue references.</para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para>
+ <computeroutput>value_type</computeroutput> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">explicit</phrase> <anchor id="id216-bb"/><phrase role="identifier">unordered_multimap</phrase><phrase role="special">(</phrase><phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an empty container, using allocator <computeroutput>a</computeroutput>.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id217-bb"/><phrase role="identifier">unordered_multimap</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> a<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Constructs an container, copying <computeroutput>x</computeroutput>'s contained elements, hash function, predicate, maximum load factor, but using allocator <computeroutput>a</computeroutput>.</para></listitem><listitem><para><literallayout class="monospaced"><anchor id="id218-bb"/><phrase role="special">~</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>The destructor is applied to every element, and all memory is deallocated</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><para><literallayout class="monospaced"><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&amp;</phrase> <anchor id="id219-bb"/><phrase role="keyword">operator</phrase><phrase role="special">=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <computeroutput>operator=(unordered_multimap)</computeroutput>
+ in order to emulate move semantics.
+ </para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para><computeroutput>value_type</computeroutput> is copy constructible</para></listitem></varlistentry></variablelist><para><literallayout class="monospaced"><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&amp;</phrase> <anchor id="id220-bb"/><phrase role="keyword">operator</phrase><phrase role="special">=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase> <phrase role="special">&amp;&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>The move assignment operator.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <computeroutput>operator=(unordered_multimap)</computeroutput>
+ in order to emulate move semantics.
+ </para></listitem></varlistentry><varlistentry><term>Requires:</term><listitem><para>
+ <computeroutput>value_type</computeroutput> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para></listitem></varlistentry></variablelist><para><literallayout class="monospaced"><phrase role="identifier">allocator_type</phrase> <anchor id="id221-bb"/><phrase role="identifier">get_allocator</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><refsect2><title><anchor id="id222-bb"/><computeroutput>unordered_multimap</computeroutput> size and capacity</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">bool</phrase> <anchor id="id223-bb"/><phrase role="identifier">empty</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput><link linkend="id224-bb">size</link>() == 0</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id224-bb"/><phrase role="identifier">size</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput>std::distance(<link linkend="id227-bb">begin</link>(), <link linkend="id230-bb">end</link>())</computeroutput></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id225-bb"/><phrase role="identifier">max_size</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><computeroutput><link linkend="id224-bb">size</link>()</computeroutput> of the largest possible container.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id226-bb"/><computeroutput>unordered_multimap</computeroutput> iterators</title><orderedlist><listitem><para><literallayout class="monospaced"><anchor id="id227-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id228-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id229-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id230-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id231-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id232-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>An iterator which refers to the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_iterator</phrase> <anchor id="id233-bb"/><phrase role="identifier">cbegin</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>A constant iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_iterator</phrase> <anchor id="id234-bb"/><phrase role="identifier">cend</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>A constant iterator which refers to the past-the-end value for the container.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id235-bb"/><computeroutput>unordered_multimap</computeroutput> modifiers</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase> <phrase role="identifier">iterator</phrase> <anchor id="id236-bb"/><phrase role="identifier">emplace</phrase><phrase role="special">(</phrase><phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase> args<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts an object, constructed with the arguments <computeroutput>args</computeroutput>, in the container.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to the inserted element.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para><para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase><phrase role="special">...</phrase> Args<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <anchor id="id237-bb"/><phrase role="identifier">emplace_hint</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> hint<phrase role="special">,</phrase> <phrase role="identifier">Args</phrase><phrase role="special">&amp;&amp;</phrase><phrase role="special">...</phrase> args<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts an object, constructed with the arguments <computeroutput>args</computeroutput>, in the container.</para><para>hint is a suggestion to where the element should be inserted.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to the inserted element.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. </para><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para><para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id238-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> obj<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts obj in the container.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to the inserted element.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id239-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> hint<phrase role="special">,</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> obj<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts obj in the container.</para><para>hint is a suggestion to where the element should be inserted.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to the inserted element.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. </para><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> InputIterator<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <anchor id="id240-bb"/><phrase role="identifier">insert</phrase><phrase role="special">(</phrase><phrase role="identifier">InputIterator</phrase> first<phrase role="special">,</phrase> <phrase role="identifier">InputIterator</phrase> last<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Inserts a range of elements into the container.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>When inserting a single element, if an exception is thrown by an operation other than a call to <computeroutput>hasher</computeroutput> the function has no effect.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para><para>Pointers and references to elements are never invalidated.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id241-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The iterator following <computeroutput>position</computeroutput> before the erasure.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ When the number of elements is a lot smaller than the number of buckets
+ this function can be very inefficient as it has to search through empty
+ buckets for the next element, in order to return the iterator.
+ The method <link linkend="id244-bb">quick_erase</link> is faster, but has yet
+ to be standardized.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id242-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase all elements with key equivalent to <computeroutput>k</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of elements erased.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">iterator</phrase> <anchor id="id243-bb"/><phrase role="identifier">erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> first<phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase> last<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erases the elements in the range from <computeroutput>first</computeroutput> to <computeroutput>last</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The iterator following the erased elements - i.e. <computeroutput>last</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id244-bb"/><phrase role="identifier">quick_erase</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ This method is faster than <link linkend="id241-bb">erase</link> as
+ it doesn't have to find the next element in the container -
+ a potentially costly operation.
+ </para><para>
+ As it hasn't been standardized, it's likely that this may
+ change in the future.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id245-bb"/><phrase role="identifier">erase_return_void</phrase><phrase role="special">(</phrase><phrase role="identifier">const_iterator</phrase> position<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erase the element pointed to by <computeroutput>position</computeroutput>.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>Only throws an exception if it is thrown by <computeroutput>hasher</computeroutput> or <computeroutput>key_equal</computeroutput>.</para><para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ This method is now deprecated, use
+ quick_return instead. Although be
+ warned that as that isn't standardized yet, it could also
+ change.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id246-bb"/><phrase role="identifier">clear</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Erases all elements in the container.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Postconditions:</term><listitem><para><computeroutput><link linkend="id224-bb">size</link>() == 0</computeroutput></para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>Never throws an exception.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id247-bb"/><phrase role="identifier">swap</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&amp;</phrase><phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <computeroutput>key_equal</computeroutput> or <computeroutput>hasher</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id248-bb"/><computeroutput>unordered_multimap</computeroutput> observers</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="identifier">hasher</phrase> <anchor id="id249-bb"/><phrase role="identifier">hash_function</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>The container's hash function.
+ </listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">key_equal</phrase> <anchor id="id250-bb"/><phrase role="identifier">key_eq</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem>The container's key equality predicate.
+ </listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id251-bb"/><computeroutput>unordered_multimap</computeroutput> lookup</title><orderedlist><listitem><para><literallayout class="monospaced"><anchor id="id252-bb"/><phrase role="identifier">iterator</phrase> <anchor id="id253-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_iterator</phrase> <anchor id="id254-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">iterator</phrase> <anchor id="id255-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hash<phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> CompatibleKey<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> CompatibleHash<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> CompatiblePredicate<phrase role="special">&gt;</phrase>
+ <phrase role="identifier">const_iterator</phrase>
+ <anchor id="id256-bb"/><phrase role="identifier">find</phrase><phrase role="special">(</phrase><phrase role="identifier">CompatibleKey</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">,</phrase> <phrase role="identifier">CompatibleHash</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> hash<phrase role="special">,</phrase>
+ <phrase role="identifier">CompatiblePredicate</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> eq<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An iterator pointing to an element with key equivalent to <computeroutput>k</computeroutput>, or <computeroutput>b.end()</computeroutput> if no such element exists.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>
+ The templated overloads are a non-standard extensions which
+ allows you to use a compatible hash function and equality
+ predicate for a key of a different type in order to avoid
+ an expensive type cast. In general, its use is not encouraged.
+ </para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id257-bb"/><phrase role="identifier">count</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of elements with key equivalent to <computeroutput>k</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id258-bb"/><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">&gt;</phrase> <anchor id="id259-bb"/><phrase role="identifier">equal_range</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">const_iterator</phrase><phrase role="special">,</phrase> <phrase role="identifier">const_iterator</phrase><phrase role="special">&gt;</phrase> <anchor id="id260-bb"/><phrase role="identifier">equal_range</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>A range containing all elements with key equivalent to <computeroutput>k</computeroutput>.
+ If the container doesn't container any such elements, returns
+ <computeroutput>std::make_pair(b.end(),b.end())</computeroutput>.
+ </para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id261-bb"/><computeroutput>unordered_multimap</computeroutput> bucket interface</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id262-bb"/><phrase role="identifier">bucket_count</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The number of buckets.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id263-bb"/><phrase role="identifier">max_bucket_count</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>An upper bound on the number of buckets.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id264-bb"/><phrase role="identifier">bucket_size</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n &lt; <link linkend="id262-bb">bucket_count</link>()</computeroutput></para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>The number of elements in bucket <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">size_type</phrase> <anchor id="id265-bb"/><phrase role="identifier">bucket</phrase><phrase role="special">(</phrase><phrase role="identifier">key_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> k<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The index of the bucket which would contain an element with key <computeroutput>k</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Postconditions:</term><listitem><para>The return value is less than <computeroutput>bucket_count()</computeroutput></para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id266-bb"/><phrase role="identifier">local_iterator</phrase> <anchor id="id267-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_local_iterator</phrase> <anchor id="id268-bb"/><phrase role="identifier">begin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A local iterator pointing the first element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><anchor id="id269-bb"/><phrase role="identifier">local_iterator</phrase> <anchor id="id270-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">const_local_iterator</phrase> <anchor id="id271-bb"/><phrase role="identifier">end</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A local iterator pointing the 'one past the end' element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_local_iterator</phrase> <anchor id="id272-bb"/><phrase role="identifier">cbegin</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A constant local iterator pointing the first element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="identifier">const_local_iterator</phrase> <anchor id="id273-bb"/><phrase role="identifier">cend</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Requires:</term><listitem><para><computeroutput>n</computeroutput> shall be in the range <computeroutput>[0, bucket_count())</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Returns:</term><listitem><para>A constant local iterator pointing the 'one past the end' element in the bucket with index <computeroutput>n</computeroutput>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id274-bb"/><computeroutput>unordered_multimap</computeroutput> hash policy</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">float</phrase> <anchor id="id275-bb"/><phrase role="identifier">load_factor</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>The average number of elements per bucket.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">float</phrase> <anchor id="id276-bb"/><phrase role="identifier">max_load_factor</phrase><phrase role="special">(</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Returns:</term><listitem><para>Returns the current maximum load factor.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id277-bb"/><phrase role="identifier">max_load_factor</phrase><phrase role="special">(</phrase><phrase role="keyword">float</phrase> z<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><para>Changes the container's maximum load factor, using <computeroutput>z</computeroutput> as a hint.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">void</phrase> <anchor id="id278-bb"/><phrase role="identifier">rehash</phrase><phrase role="special">(</phrase><phrase role="identifier">size_type</phrase> n<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><para>Changes the number of buckets so that there at least <computeroutput>n</computeroutput> buckets, and so that the load factor is less than the maximum load factor.</para><para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Throws:</term><listitem><para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id279-bb"/><computeroutput>unordered_multimap</computeroutput> Equality Comparisons</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multimap.operator==_id1"/><phrase role="keyword">operator</phrase><phrase role="special">==</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <anchor id="boost.unordered_multimap.operator!=_id1"/><phrase role="keyword">operator</phrase><phrase role="special">!=</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Notes:</term><listitem><para>This is a boost extension.</para><para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2><refsect2><title><anchor id="id280-bb"/><computeroutput>unordered_multimap</computeroutput> swap</title><orderedlist><listitem><para><literallayout class="monospaced"><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">typename</phrase> Key<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Mapped<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Hash<phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> Pred<phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> Alloc<phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <anchor id="boost.unordered_multimap.swap_id1"/><phrase role="identifier">swap</phrase><phrase role="special">(</phrase><phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> x<phrase role="special">,</phrase>
+ <phrase role="identifier">unordered_multimap</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">Key</phrase><phrase role="special">,</phrase> <phrase role="identifier">Mapped</phrase><phrase role="special">,</phrase> <phrase role="identifier">Hash</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">,</phrase> <phrase role="identifier">Alloc</phrase><phrase role="special">&gt;</phrase><phrase role="special">&amp;</phrase> y<phrase role="special">)</phrase><phrase role="special">;</phrase></literallayout></para><variablelist spacing="compact"><?dbhtml
+ list-presentation="table"
+ ?><varlistentry><term>Effects:</term><listitem><para><computeroutput>x.swap(y)</computeroutput></para></listitem></varlistentry><varlistentry><term>Throws:</term><listitem><para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <computeroutput>Hash</computeroutput> or <computeroutput>Pred</computeroutput>.</para></listitem></varlistentry><varlistentry><term>Notes:</term><listitem><para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para></listitem></varlistentry></variablelist></listitem></orderedlist></refsect2></refsect1></refentry>
+ </section>
+ </section> \ No newline at end of file
diff --git a/tools/boostbook/test/more/tests/libs/unordered-ref.xml b/tools/boostbook/test/more/tests/libs/unordered-ref.xml
new file mode 100644
index 0000000000..92aaffa7d2
--- /dev/null
+++ b/tools/boostbook/test/more/tests/libs/unordered-ref.xml
@@ -0,0 +1,3629 @@
+<!--
+Copyright Daniel James 2006-2009
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+--><library-reference>
+ <header name="boost/unordered_set.hpp">
+ <namespace name="boost">
+ <class name="unordered_set">
+ <template>
+ <template-type-parameter name="Value">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ <default><type>boost::hash&lt;Value&gt;</type></default>
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ <default><type>std::equal_to&lt;Value&gt;</type></default>
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ <default><type>std::allocator&lt;Value&gt;</type></default>
+ </template-type-parameter>
+ </template>
+ <purpose><simpara>
+ An unordered associative container that stores unique values.
+ </simpara></purpose>
+ <description>
+ <para>Based on chapter 23 of
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
+ But without the updated rules for allocators.
+ </para>
+ <para><emphasis role="bold">Template Parameters</emphasis>
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry><emphasis>Value</emphasis></entry>
+ <entry>Value must be Assignable and CopyConstructible</entry></row>
+ <row>
+ <entry><emphasis>Hash</emphasis></entry>
+ <entry>A unary function object type that acts a hash function for a <code>Value</code>. It takes a single argument of type <code>Value</code> and returns a value of type std::size_t.</entry></row>
+ <row>
+ <entry><emphasis>Pred</emphasis></entry>
+ <entry>A binary function object that implements an equivalence relation on values of type <code>Value</code>.
+ A binary function object that induces an equivalence relation on values of type Key.
+ It takes two arguments of type Key and returns a value of type bool.</entry></row>
+ <row>
+ <entry><emphasis>Alloc</emphasis></entry>
+ <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
+ <para>The elements are organized into buckets. Keys with the same hash code are stored in the same bucket.</para>
+ <para>The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash.</para>
+ </description>
+ <typedef name="key_type">
+ <type>Value</type>
+ </typedef>
+ <typedef name="value_type">
+ <type>Value</type>
+ </typedef>
+ <typedef name="hasher">
+ <type>Hash</type>
+ </typedef>
+ <typedef name="key_equal">
+ <type>Pred</type>
+ </typedef>
+ <typedef name="allocator_type">
+ <type>Alloc</type>
+ </typedef>
+ <typedef name="pointer">
+ <type>typename allocator_type::pointer</type>
+ </typedef>
+ <typedef name="const_pointer">
+ <type>typename allocator_type::const_pointer</type>
+ </typedef>
+ <typedef name="reference">
+ <type>typename allocator_type::reference</type>
+ <purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
+ </typedef>
+ <typedef name="const_reference">
+ <type>typename allocator_type::const_reference</type>
+ <purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
+ </typedef>
+ <typedef name="size_type">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>An unsigned integral type.</para>
+ <para><type>size_type</type> can represent any non-negative value of <type>difference_type</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="difference_type">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A signed integral type.</para>
+ <para>Is identical to the difference type of <type>iterator</type> and <type>const_iterator</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A constant iterator whose value type is <type>value_type</type>. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ <para>Convertible to <type>const_iterator</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="const_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A constant iterator whose value type is <type>value_type</type>. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ </description>
+ </typedef>
+ <typedef name="local_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>An iterator with the same value type, difference type and pointer and reference type as <type>iterator</type>.</para>
+ <para>A local_iterator object can be used to iterate through a single bucket.</para>
+ </description>
+ </typedef>
+ <typedef name="const_local_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A constant iterator with the same value type, difference type and pointer and reference type as <type>const_iterator</type>.</para>
+ <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
+ </description>
+ </typedef>
+ <constructor specifiers="explicit">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ <default><emphasis>implementation-defined</emphasis></default>
+ </parameter>
+ <parameter name="hf">
+ <paramtype>hasher const&amp;</paramtype>
+ <default>hasher()</default>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>key_equal const&amp;</paramtype>
+ <default>key_equal()</default>
+ </parameter>
+ <parameter name="a">
+ <paramtype>allocator_type const&amp;</paramtype>
+ <default>allocator_type()</default>
+ </parameter>
+ <postconditions>
+ <code><methodname>size</methodname>() == 0</code>
+ </postconditions>
+ <description>
+ <para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <template>
+ <template-type-parameter name="InputIterator">
+ </template-type-parameter>
+ </template>
+ <parameter name="f">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="l">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ <default><emphasis>implementation-defined</emphasis></default>
+ </parameter>
+ <parameter name="hf">
+ <paramtype>hasher const&amp;</paramtype>
+ <default>hasher()</default>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>key_equal const&amp;</paramtype>
+ <default>key_equal()</default>
+ </parameter>
+ <parameter name="a">
+ <paramtype>allocator_type const&amp;</paramtype>
+ <default>allocator_type()</default>
+ </parameter>
+ <description>
+ <para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <parameter>
+ <paramtype>unordered_set const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
+ </description>
+ <requires>
+ <para><code>value_type</code> is copy constructible</para>
+ </requires>
+ </constructor>
+ <constructor>
+ <parameter>
+ <paramtype>unordered_set &amp;&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>The move constructor.</para>
+ </description>
+ <notes>
+ <para>This is emulated on compilers without rvalue references.</para>
+ </notes>
+ <requires>
+ <para>
+ <code>value_type</code> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para>
+ </requires>
+ </constructor>
+ <constructor specifiers="explicit">
+ <parameter name="a">
+ <paramtype>Allocator const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>Constructs an empty container, using allocator <code>a</code>.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <parameter name="x">
+ <paramtype>unordered_set const&amp;</paramtype>
+ </parameter>
+ <parameter name="a">
+ <paramtype>Allocator const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>Constructs an container, copying <code>x</code>'s contained elements, hash function, predicate, maximum load factor, but using allocator <code>a</code>.</para>
+ </description>
+ </constructor>
+ <destructor>
+ <notes>
+ <para>The destructor is applied to every element, and all memory is deallocated</para>
+ </notes>
+ </destructor>
+ <method name="operator=">
+ <parameter>
+ <paramtype>unordered_set const&amp;</paramtype>
+ </parameter>
+ <type>unordered_set&amp;</type>
+ <description>
+ <para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
+ </description>
+ <notes>
+ <para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <code>operator=(unordered_set)</code>
+ in order to emulate move semantics.
+ </para>
+ </notes>
+ <requires>
+ <para><code>value_type</code> is copy constructible</para>
+ </requires>
+ </method>
+ <method name="operator=">
+ <parameter>
+ <paramtype>unordered_set &amp;&amp;</paramtype>
+ </parameter>
+ <type>unordered_set&amp;</type>
+ <description>
+ <para>The move assignment operator.</para>
+ </description>
+ <notes>
+ <para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <code>operator=(unordered_set)</code>
+ in order to emulate move semantics.
+ </para>
+ </notes>
+ <requires>
+ <para>
+ <code>value_type</code> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para>
+ </requires>
+ </method>
+ <method name="get_allocator" cv="const">
+ <type>allocator_type</type>
+ </method>
+ <method-group name="size and capacity">
+ <method name="empty" cv="const">
+ <type>bool</type>
+ <returns>
+ <code><methodname>size</methodname>() == 0</code>
+ </returns>
+ </method>
+ <method name="size" cv="const">
+ <type>size_type</type>
+ <returns>
+ <code>std::distance(<methodname>begin</methodname>(), <methodname>end</methodname>())</code>
+ </returns>
+ </method>
+ <method name="max_size" cv="const">
+ <type>size_type</type>
+ <returns><code><methodname>size</methodname>()</code> of the largest possible container.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="iterators">
+ <overloaded-method name="begin">
+ <signature><type>iterator</type></signature>
+ <signature cv="const"><type>const_iterator</type></signature>
+ <returns>An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </returns>
+ </overloaded-method>
+ <overloaded-method name="end">
+ <signature>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <type>const_iterator</type>
+ </signature>
+ <returns>An iterator which refers to the past-the-end value for the container.
+ </returns>
+ </overloaded-method>
+ <method name="cbegin" cv="const">
+ <type>const_iterator</type>
+ <returns>A constant iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </returns>
+ </method>
+ <method name="cend" cv="const">
+ <type>const_iterator</type>
+ <returns>A constant iterator which refers to the past-the-end value for the container.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="modifiers">
+ <method name="emplace">
+ <template>
+ <template-type-parameter name="Args" pack="1">
+ </template-type-parameter>
+ </template>
+ <parameter name="args" pack="1">
+ <paramtype>Args&amp;&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;iterator, bool&gt;</type>
+ <description>
+ <para>Inserts an object, constructed with the arguments <code>args</code>, in the container if and only if there is no element in the container with an equivalent value.</para>
+ </description>
+ <returns>
+ <para>The bool component of the return type is true if an insert took place.</para>
+ <para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ <para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para>
+ </notes>
+ </method>
+ <method name="emplace_hint">
+ <template>
+ <template-type-parameter name="Args" pack="1">
+ </template-type-parameter>
+ </template>
+ <parameter name="hint">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="args" pack="1">
+ <paramtype>Args&amp;&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts an object, constructed with the arguments <code>args</code>, in the container if and only if there is no element in the container with an equivalent value.</para>
+ <para>hint is a suggestion to where the element should be inserted.</para>
+ </description>
+ <returns>
+ <para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same value. </para>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ <para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <parameter name="obj">
+ <paramtype>value_type const&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;iterator, bool&gt;</type>
+ <description>
+ <para>Inserts obj in the container if and only if there is no element in the container with an equivalent value.</para>
+ </description>
+ <returns>
+ <para>The bool component of the return type is true if an insert took place.</para>
+ <para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <parameter name="hint">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="obj">
+ <paramtype>value_type const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts obj in the container if and only if there is no element in the container with an equivalent value.</para>
+ <para>hint is a suggestion to where the element should be inserted.</para>
+ </description>
+ <returns>
+ <para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same value. </para>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <template>
+ <template-type-parameter name="InputIterator">
+ </template-type-parameter>
+ </template>
+ <parameter name="first">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="last">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent value.</para>
+ </description>
+ <throws>
+ <para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="erase">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <returns>
+ <para>The iterator following <code>position</code> before the erasure.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ When the number of elements is a lot smaller than the number of buckets
+ this function can be very inefficient as it has to search through empty
+ buckets for the next element, in order to return the iterator.
+ The method <methodname>quick_erase</methodname> is faster, but has yet
+ to be standardized.
+ </para>
+ </notes>
+ </method>
+ <method name="erase">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <description>
+ <para>Erase all elements with key equivalent to <code>k</code>.</para>
+ </description>
+ <returns>
+ <para>The number of elements erased.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ </throws>
+ </method>
+ <method name="erase">
+ <parameter name="first">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="last">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Erases the elements in the range from <code>first</code> to <code>last</code>.</para>
+ </description>
+ <returns>
+ <para>The iterator following the erased elements - i.e. <code>last</code>.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ </method>
+ <method name="quick_erase">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ This method is faster than <methodname>erase</methodname> as
+ it doesn't have to find the next element in the container -
+ a potentially costly operation.
+ </para>
+ <para>
+ As it hasn't been standardized, it's likely that this may
+ change in the future.
+ </para>
+ </notes>
+ </method>
+ <method name="erase_return_void">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ This method is now deprecated, use
+ <methodname>quick_return</methodname> instead. Although be
+ warned that as that isn't standardized yet, it could also
+ change.
+ </para>
+ </notes>
+ </method>
+ <method name="clear">
+ <type>void</type>
+ <description>
+ <para>Erases all elements in the container.</para>
+ </description>
+ <postconditions>
+ <para><code><methodname>size</methodname>() == 0</code></para>
+ </postconditions>
+ <throws>
+ <para>Never throws an exception.</para>
+ </throws>
+ </method>
+ <method name="swap">
+ <parameter>
+ <paramtype>unordered_set&amp;</paramtype>
+ </parameter>
+ <type>void</type>
+ <throws>
+ <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
+ </throws>
+ <notes>
+ <para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
+ </notes>
+ </method>
+ </method-group>
+ <method-group name="observers">
+ <method name="hash_function" cv="const">
+ <type>hasher</type>
+ <returns>The container's hash function.
+ </returns>
+ </method>
+ <method name="key_eq" cv="const">
+ <type>key_equal</type>
+ <returns>The container's key equality predicate.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="lookup">
+ <overloaded-method name="find">
+ <signature>
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>const_iterator</type>
+ </signature>
+ <signature>
+ <template>
+ <template-type-parameter name="CompatibleKey"/>
+ <template-type-parameter name="CompatibleHash"/>
+ <template-type-parameter name="CompatiblePredicate"/>
+ </template>
+ <parameter name="k">
+ <paramtype>CompatibleKey const&amp;</paramtype>
+ </parameter>
+ <parameter name="hash">
+ <paramtype>CompatibleHash const&amp;</paramtype>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>CompatiblePredicate const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <template>
+ <template-type-parameter name="CompatibleKey"/>
+ <template-type-parameter name="CompatibleHash"/>
+ <template-type-parameter name="CompatiblePredicate"/>
+ </template>
+ <parameter name="k">
+ <paramtype>CompatibleKey const&amp;</paramtype>
+ </parameter>
+ <parameter name="hash">
+ <paramtype>CompatibleHash const&amp;</paramtype>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>CompatiblePredicate const&amp;</paramtype>
+ </parameter>
+ <type>const_iterator</type>
+ </signature>
+ <returns>
+ <para>An iterator pointing to an element with key equivalent to <code>k</code>, or <code>b.end()</code> if no such element exists.</para>
+ </returns>
+ <notes><para>
+ The templated overloads are a non-standard extensions which
+ allows you to use a compatible hash function and equality
+ predicate for a key of a different type in order to avoid
+ an expensive type cast. In general, its use is not encouraged.
+ </para></notes>
+ </overloaded-method>
+ <method name="count" cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <returns>
+ <para>The number of elements with key equivalent to <code>k</code>.</para>
+ </returns>
+ </method>
+ <overloaded-method name="equal_range">
+ <signature>
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;iterator, iterator&gt;</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;const_iterator, const_iterator&gt;</type>
+ </signature>
+ <returns>
+ <para>A range containing all elements with key equivalent to <code>k</code>.
+ If the container doesn't container any such elements, returns
+ <code><functionname>std::make_pair</functionname>(<methodname>b.end</methodname>(),<methodname>b.end</methodname>())</code>.
+ </para>
+ </returns>
+ </overloaded-method>
+ </method-group>
+ <method-group name="bucket interface">
+ <method name="bucket_count" cv="const">
+ <type>size_type</type>
+ <returns>
+ <para>The number of buckets.</para>
+ </returns>
+ </method>
+ <method name="max_bucket_count" cv="const">
+ <type>size_type</type>
+ <returns>
+ <para>An upper bound on the number of buckets.</para>
+ </returns>
+ </method>
+ <method name="bucket_size" cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <requires>
+ <para><code>n &lt; <methodname>bucket_count</methodname>()</code></para>
+ </requires>
+ <returns>
+ <para>The number of elements in bucket <code>n</code>.</para>
+ </returns>
+ </method>
+ <method name="bucket" cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <returns>
+ <para>The index of the bucket which would contain an element with key <code>k</code>.</para>
+ </returns>
+ <postconditions>
+ <para>The return value is less than <code>bucket_count()</code></para>
+ </postconditions>
+ </method>
+ <overloaded-method name="begin">
+ <signature>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>local_iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ </signature>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A local iterator pointing the first element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </overloaded-method>
+ <overloaded-method name="end">
+ <signature>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>local_iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ </signature>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A local iterator pointing the 'one past the end' element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </overloaded-method>
+ <method name="cbegin" cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A constant local iterator pointing the first element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </method>
+ <method name="cend">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A constant local iterator pointing the 'one past the end' element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="hash policy">
+ <method name="load_factor" cv="const">
+ <type>float</type>
+ <returns>
+ <para>The average number of elements per bucket.</para>
+ </returns>
+ </method>
+ <method name="max_load_factor" cv="const">
+ <type>float</type>
+ <returns>
+ <para>Returns the current maximum load factor.</para>
+ </returns>
+ </method>
+ <method name="max_load_factor">
+ <parameter name="z">
+ <paramtype>float</paramtype>
+ </parameter>
+ <type>void</type>
+ <effects>
+ <para>Changes the container's maximum load factor, using <code>z</code> as a hint.</para>
+ </effects>
+ </method>
+ <method name="rehash">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Changes the number of buckets so that there at least <code>n</code> buckets, and so that the load factor is less than the maximum load factor.</para>
+ <para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
+ </description>
+ <throws>
+ <para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
+ </throws>
+ </method>
+ </method-group>
+ <free-function-group name="Equality Comparisons">
+ <function name="operator==">
+ <template>
+ <template-type-parameter name="Value">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_set&lt;Value, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_set&lt;Value, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <type>bool</type>
+ <notes>
+ <para>This is a boost extension.</para>
+ <para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para>
+ </notes>
+ </function>
+ <function name="operator!=">
+ <template>
+ <template-type-parameter name="Value">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_set&lt;Value, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_set&lt;Value, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <type>bool</type>
+ <notes>
+ <para>This is a boost extension.</para>
+ <para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para>
+ </notes>
+ </function>
+ </free-function-group>
+ <free-function-group name="swap">
+ <function name="swap">
+ <template>
+ <template-type-parameter name="Value">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_set&lt;Value, Hash, Pred, Alloc&gt;&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_set&lt;Value, Hash, Pred, Alloc&gt;&amp;</paramtype>
+ </parameter>
+ <type>void</type>
+ <effects>
+ <para><code>x.swap(y)</code></para>
+ </effects>
+ <throws>
+ <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
+ </throws>
+ <notes>
+ <para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
+ </notes>
+ </function>
+ </free-function-group>
+ </class>
+ <class name="unordered_multiset">
+ <template>
+ <template-type-parameter name="Value">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ <default><type>boost::hash&lt;Value&gt;</type></default>
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ <default><type>std::equal_to&lt;Value&gt;</type></default>
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ <default><type>std::allocator&lt;Value&gt;</type></default>
+ </template-type-parameter>
+ </template>
+ <purpose><simpara>
+ An unordered associative container that stores values. The same key can be stored multiple times.
+ </simpara></purpose>
+ <description>
+ <para>Based on chapter 23 of
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
+ But without the updated rules for allocators.
+ </para>
+ <para><emphasis role="bold">Template Parameters</emphasis>
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry><emphasis>Value</emphasis></entry>
+ <entry>Value must be Assignable and CopyConstructible</entry></row>
+ <row>
+ <entry><emphasis>Hash</emphasis></entry>
+ <entry>A unary function object type that acts a hash function for a <code>Value</code>. It takes a single argument of type <code>Value</code> and returns a value of type std::size_t.</entry></row>
+ <row>
+ <entry><emphasis>Pred</emphasis></entry>
+ <entry>A binary function object that implements an equivalence relation on values of type <code>Value</code>.
+ A binary function object that induces an equivalence relation on values of type Key.
+ It takes two arguments of type Key and returns a value of type bool.</entry></row>
+ <row>
+ <entry><emphasis>Alloc</emphasis></entry>
+ <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
+ <para>The elements are organized into buckets. Keys with the same hash code are stored in the same bucket and elements with equivalent keys are stored next to each other.</para>
+ <para>The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash.</para>
+ </description>
+ <typedef name="key_type">
+ <type>Value</type>
+ </typedef>
+ <typedef name="value_type">
+ <type>Value</type>
+ </typedef>
+ <typedef name="hasher">
+ <type>Hash</type>
+ </typedef>
+ <typedef name="key_equal">
+ <type>Pred</type>
+ </typedef>
+ <typedef name="allocator_type">
+ <type>Alloc</type>
+ </typedef>
+ <typedef name="pointer">
+ <type>typename allocator_type::pointer</type>
+ </typedef>
+ <typedef name="const_pointer">
+ <type>typename allocator_type::const_pointer</type>
+ </typedef>
+ <typedef name="reference">
+ <type>typename allocator_type::reference</type>
+ <purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
+ </typedef>
+ <typedef name="const_reference">
+ <type>typename allocator_type::const_reference</type>
+ <purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
+ </typedef>
+ <typedef name="size_type">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>An unsigned integral type.</para>
+ <para><type>size_type</type> can represent any non-negative value of <type>difference_type</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="difference_type">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A signed integral type.</para>
+ <para>Is identical to the difference type of <type>iterator</type> and <type>const_iterator</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A constant iterator whose value type is <type>value_type</type>. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ <para>Convertible to <type>const_iterator</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="const_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A constant iterator whose value type is <type>value_type</type>. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ </description>
+ </typedef>
+ <typedef name="local_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>An iterator with the same value type, difference type and pointer and reference type as <type>iterator</type>.</para>
+ <para>A local_iterator object can be used to iterate through a single bucket.</para>
+ </description>
+ </typedef>
+ <typedef name="const_local_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A constant iterator with the same value type, difference type and pointer and reference type as <type>const_iterator</type>.</para>
+ <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
+ </description>
+ </typedef>
+ <constructor specifiers="explicit">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ <default><emphasis>implementation-defined</emphasis></default>
+ </parameter>
+ <parameter name="hf">
+ <paramtype>hasher const&amp;</paramtype>
+ <default>hasher()</default>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>key_equal const&amp;</paramtype>
+ <default>key_equal()</default>
+ </parameter>
+ <parameter name="a">
+ <paramtype>allocator_type const&amp;</paramtype>
+ <default>allocator_type()</default>
+ </parameter>
+ <postconditions>
+ <code><methodname>size</methodname>() == 0</code>
+ </postconditions>
+ <description>
+ <para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <template>
+ <template-type-parameter name="InputIterator">
+ </template-type-parameter>
+ </template>
+ <parameter name="f">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="l">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ <default><emphasis>implementation-defined</emphasis></default>
+ </parameter>
+ <parameter name="hf">
+ <paramtype>hasher const&amp;</paramtype>
+ <default>hasher()</default>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>key_equal const&amp;</paramtype>
+ <default>key_equal()</default>
+ </parameter>
+ <parameter name="a">
+ <paramtype>allocator_type const&amp;</paramtype>
+ <default>allocator_type()</default>
+ </parameter>
+ <description>
+ <para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <parameter>
+ <paramtype>unordered_multiset const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
+ </description>
+ <requires>
+ <para><code>value_type</code> is copy constructible</para>
+ </requires>
+ </constructor>
+ <constructor>
+ <parameter>
+ <paramtype>unordered_multiset &amp;&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>The move constructor.</para>
+ </description>
+ <notes>
+ <para>This is emulated on compilers without rvalue references.</para>
+ </notes>
+ <requires>
+ <para>
+ <code>value_type</code> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para>
+ </requires>
+ </constructor>
+ <constructor specifiers="explicit">
+ <parameter name="a">
+ <paramtype>Allocator const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>Constructs an empty container, using allocator <code>a</code>.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <parameter name="x">
+ <paramtype>unordered_multiset const&amp;</paramtype>
+ </parameter>
+ <parameter name="a">
+ <paramtype>Allocator const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>Constructs an container, copying <code>x</code>'s contained elements, hash function, predicate, maximum load factor, but using allocator <code>a</code>.</para>
+ </description>
+ </constructor>
+ <destructor>
+ <notes>
+ <para>The destructor is applied to every element, and all memory is deallocated</para>
+ </notes>
+ </destructor>
+ <method name="operator=">
+ <parameter>
+ <paramtype>unordered_multiset const&amp;</paramtype>
+ </parameter>
+ <type>unordered_multiset&amp;</type>
+ <description>
+ <para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
+ </description>
+ <notes>
+ <para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <code>operator=(unordered_multiset)</code>
+ in order to emulate move semantics.
+ </para>
+ </notes>
+ <requires>
+ <para><code>value_type</code> is copy constructible</para>
+ </requires>
+ </method>
+ <method name="operator=">
+ <parameter>
+ <paramtype>unordered_multiset &amp;&amp;</paramtype>
+ </parameter>
+ <type>unordered_multiset&amp;</type>
+ <description>
+ <para>The move assignment operator.</para>
+ </description>
+ <notes>
+ <para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <code>operator=(unordered_multiset)</code>
+ in order to emulate move semantics.
+ </para>
+ </notes>
+ <requires>
+ <para>
+ <code>value_type</code> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para>
+ </requires>
+ </method>
+ <method name="get_allocator" cv="const">
+ <type>allocator_type</type>
+ </method>
+ <method-group name="size and capacity">
+ <method name="empty" cv="const">
+ <type>bool</type>
+ <returns>
+ <code><methodname>size</methodname>() == 0</code>
+ </returns>
+ </method>
+ <method name="size" cv="const">
+ <type>size_type</type>
+ <returns>
+ <code>std::distance(<methodname>begin</methodname>(), <methodname>end</methodname>())</code>
+ </returns>
+ </method>
+ <method name="max_size" cv="const">
+ <type>size_type</type>
+ <returns><code><methodname>size</methodname>()</code> of the largest possible container.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="iterators">
+ <overloaded-method name="begin">
+ <signature><type>iterator</type></signature>
+ <signature cv="const"><type>const_iterator</type></signature>
+ <returns>An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </returns>
+ </overloaded-method>
+ <overloaded-method name="end">
+ <signature>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <type>const_iterator</type>
+ </signature>
+ <returns>An iterator which refers to the past-the-end value for the container.
+ </returns>
+ </overloaded-method>
+ <method name="cbegin" cv="const">
+ <type>const_iterator</type>
+ <returns>A constant iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </returns>
+ </method>
+ <method name="cend" cv="const">
+ <type>const_iterator</type>
+ <returns>A constant iterator which refers to the past-the-end value for the container.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="modifiers">
+ <method name="emplace">
+ <template>
+ <template-type-parameter name="Args" pack="1">
+ </template-type-parameter>
+ </template>
+ <parameter name="args" pack="1">
+ <paramtype>Args&amp;&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts an object, constructed with the arguments <code>args</code>, in the container.</para>
+ </description>
+ <returns>
+ <para>An iterator pointing to the inserted element.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ <para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para>
+ </notes>
+ </method>
+ <method name="emplace_hint">
+ <template>
+ <template-type-parameter name="Args" pack="1">
+ </template-type-parameter>
+ </template>
+ <parameter name="hint">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="args" pack="1">
+ <paramtype>Args&amp;&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts an object, constructed with the arguments <code>args</code>, in the container.</para>
+ <para>hint is a suggestion to where the element should be inserted.</para>
+ </description>
+ <returns>
+ <para>An iterator pointing to the inserted element.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same value. </para>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ <para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <parameter name="obj">
+ <paramtype>value_type const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts obj in the container.</para>
+ </description>
+ <returns>
+ <para>An iterator pointing to the inserted element.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <parameter name="hint">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="obj">
+ <paramtype>value_type const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts obj in the container.</para>
+ <para>hint is a suggestion to where the element should be inserted.</para>
+ </description>
+ <returns>
+ <para>An iterator pointing to the inserted element.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same value. </para>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <template>
+ <template-type-parameter name="InputIterator">
+ </template-type-parameter>
+ </template>
+ <parameter name="first">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="last">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Inserts a range of elements into the container.</para>
+ </description>
+ <throws>
+ <para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="erase">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <returns>
+ <para>The iterator following <code>position</code> before the erasure.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ When the number of elements is a lot smaller than the number of buckets
+ this function can be very inefficient as it has to search through empty
+ buckets for the next element, in order to return the iterator.
+ The method <methodname>quick_erase</methodname> is faster, but has yet
+ to be standardized.
+ </para>
+ </notes>
+ </method>
+ <method name="erase">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <description>
+ <para>Erase all elements with key equivalent to <code>k</code>.</para>
+ </description>
+ <returns>
+ <para>The number of elements erased.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ </throws>
+ </method>
+ <method name="erase">
+ <parameter name="first">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="last">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Erases the elements in the range from <code>first</code> to <code>last</code>.</para>
+ </description>
+ <returns>
+ <para>The iterator following the erased elements - i.e. <code>last</code>.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ </method>
+ <method name="quick_erase">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ This method is faster than <methodname>erase</methodname> as
+ it doesn't have to find the next element in the container -
+ a potentially costly operation.
+ </para>
+ <para>
+ As it hasn't been standardized, it's likely that this may
+ change in the future.
+ </para>
+ </notes>
+ </method>
+ <method name="erase_return_void">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ This method is now deprecated, use
+ <methodname>quick_return</methodname> instead. Although be
+ warned that as that isn't standardized yet, it could also
+ change.
+ </para>
+ </notes>
+ </method>
+ <method name="clear">
+ <type>void</type>
+ <description>
+ <para>Erases all elements in the container.</para>
+ </description>
+ <postconditions>
+ <para><code><methodname>size</methodname>() == 0</code></para>
+ </postconditions>
+ <throws>
+ <para>Never throws an exception.</para>
+ </throws>
+ </method>
+ <method name="swap">
+ <parameter>
+ <paramtype>unordered_multiset&amp;</paramtype>
+ </parameter>
+ <type>void</type>
+ <throws>
+ <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
+ </throws>
+ <notes>
+ <para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
+ </notes>
+ </method>
+ </method-group>
+ <method-group name="observers">
+ <method name="hash_function" cv="const">
+ <type>hasher</type>
+ <returns>The container's hash function.
+ </returns>
+ </method>
+ <method name="key_eq" cv="const">
+ <type>key_equal</type>
+ <returns>The container's key equality predicate.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="lookup">
+ <overloaded-method name="find">
+ <signature>
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>const_iterator</type>
+ </signature>
+ <signature>
+ <template>
+ <template-type-parameter name="CompatibleKey"/>
+ <template-type-parameter name="CompatibleHash"/>
+ <template-type-parameter name="CompatiblePredicate"/>
+ </template>
+ <parameter name="k">
+ <paramtype>CompatibleKey const&amp;</paramtype>
+ </parameter>
+ <parameter name="hash">
+ <paramtype>CompatibleHash const&amp;</paramtype>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>CompatiblePredicate const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <template>
+ <template-type-parameter name="CompatibleKey"/>
+ <template-type-parameter name="CompatibleHash"/>
+ <template-type-parameter name="CompatiblePredicate"/>
+ </template>
+ <parameter name="k">
+ <paramtype>CompatibleKey const&amp;</paramtype>
+ </parameter>
+ <parameter name="hash">
+ <paramtype>CompatibleHash const&amp;</paramtype>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>CompatiblePredicate const&amp;</paramtype>
+ </parameter>
+ <type>const_iterator</type>
+ </signature>
+ <returns>
+ <para>An iterator pointing to an element with key equivalent to <code>k</code>, or <code>b.end()</code> if no such element exists.</para>
+ </returns>
+ <notes><para>
+ The templated overloads are a non-standard extensions which
+ allows you to use a compatible hash function and equality
+ predicate for a key of a different type in order to avoid
+ an expensive type cast. In general, its use is not encouraged.
+ </para></notes>
+ </overloaded-method>
+ <method name="count" cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <returns>
+ <para>The number of elements with key equivalent to <code>k</code>.</para>
+ </returns>
+ </method>
+ <overloaded-method name="equal_range">
+ <signature>
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;iterator, iterator&gt;</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;const_iterator, const_iterator&gt;</type>
+ </signature>
+ <returns>
+ <para>A range containing all elements with key equivalent to <code>k</code>.
+ If the container doesn't container any such elements, returns
+ <code><functionname>std::make_pair</functionname>(<methodname>b.end</methodname>(),<methodname>b.end</methodname>())</code>.
+ </para>
+ </returns>
+ </overloaded-method>
+ </method-group>
+ <method-group name="bucket interface">
+ <method name="bucket_count" cv="const">
+ <type>size_type</type>
+ <returns>
+ <para>The number of buckets.</para>
+ </returns>
+ </method>
+ <method name="max_bucket_count" cv="const">
+ <type>size_type</type>
+ <returns>
+ <para>An upper bound on the number of buckets.</para>
+ </returns>
+ </method>
+ <method name="bucket_size" cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <requires>
+ <para><code>n &lt; <methodname>bucket_count</methodname>()</code></para>
+ </requires>
+ <returns>
+ <para>The number of elements in bucket <code>n</code>.</para>
+ </returns>
+ </method>
+ <method name="bucket" cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <returns>
+ <para>The index of the bucket which would contain an element with key <code>k</code>.</para>
+ </returns>
+ <postconditions>
+ <para>The return value is less than <code>bucket_count()</code></para>
+ </postconditions>
+ </method>
+ <overloaded-method name="begin">
+ <signature>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>local_iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ </signature>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A local iterator pointing the first element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </overloaded-method>
+ <overloaded-method name="end">
+ <signature>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>local_iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ </signature>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A local iterator pointing the 'one past the end' element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </overloaded-method>
+ <method name="cbegin" cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A constant local iterator pointing the first element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </method>
+ <method name="cend">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A constant local iterator pointing the 'one past the end' element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="hash policy">
+ <method name="load_factor" cv="const">
+ <type>float</type>
+ <returns>
+ <para>The average number of elements per bucket.</para>
+ </returns>
+ </method>
+ <method name="max_load_factor" cv="const">
+ <type>float</type>
+ <returns>
+ <para>Returns the current maximum load factor.</para>
+ </returns>
+ </method>
+ <method name="max_load_factor">
+ <parameter name="z">
+ <paramtype>float</paramtype>
+ </parameter>
+ <type>void</type>
+ <effects>
+ <para>Changes the container's maximum load factor, using <code>z</code> as a hint.</para>
+ </effects>
+ </method>
+ <method name="rehash">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Changes the number of buckets so that there at least <code>n</code> buckets, and so that the load factor is less than the maximum load factor.</para>
+ <para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
+ </description>
+ <throws>
+ <para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
+ </throws>
+ </method>
+ </method-group>
+ <free-function-group name="Equality Comparisons">
+ <function name="operator==">
+ <template>
+ <template-type-parameter name="Value">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_multiset&lt;Value, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_multiset&lt;Value, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <type>bool</type>
+ <notes>
+ <para>This is a boost extension.</para>
+ <para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para>
+ </notes>
+ </function>
+ <function name="operator!=">
+ <template>
+ <template-type-parameter name="Value">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_multiset&lt;Value, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_multiset&lt;Value, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <type>bool</type>
+ <notes>
+ <para>This is a boost extension.</para>
+ <para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para>
+ </notes>
+ </function>
+ </free-function-group>
+ <free-function-group name="swap">
+ <function name="swap">
+ <template>
+ <template-type-parameter name="Value">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_multiset&lt;Value, Hash, Pred, Alloc&gt;&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_multiset&lt;Value, Hash, Pred, Alloc&gt;&amp;</paramtype>
+ </parameter>
+ <type>void</type>
+ <effects>
+ <para><code>x.swap(y)</code></para>
+ </effects>
+ <throws>
+ <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
+ </throws>
+ <notes>
+ <para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
+ </notes>
+ </function>
+ </free-function-group>
+ </class>
+ </namespace>
+ </header>
+ <header name="boost/unordered_map.hpp">
+ <namespace name="boost">
+ <class name="unordered_map">
+ <template>
+ <template-type-parameter name="Key">
+ </template-type-parameter>
+ <template-type-parameter name="Mapped">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ <default><type>boost::hash&lt;Key&gt;</type></default>
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ <default><type>std::equal_to&lt;Key&gt;</type></default>
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ <default><type>std::allocator&lt;std::pair&lt;Key const, Mapped&gt; &gt;</type></default>
+ </template-type-parameter>
+ </template>
+ <purpose><simpara>
+ An unordered associative container that associates unique keys with another value.
+ </simpara></purpose>
+ <description>
+ <para>Based on chapter 23 of
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
+ But without the updated rules for allocators.
+ </para>
+ <para><emphasis role="bold">Template Parameters</emphasis>
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry><emphasis>Key</emphasis></entry>
+ <entry>Key must be Assignable and CopyConstructible.</entry></row>
+ <row>
+ <entry><emphasis>Mapped</emphasis></entry>
+ <entry>Mapped must be CopyConstructible</entry></row>
+ <row>
+ <entry><emphasis>Hash</emphasis></entry>
+ <entry>A unary function object type that acts a hash function for a <code>Key</code>. It takes a single argument of type <code>Key</code> and returns a value of type std::size_t.</entry></row>
+ <row>
+ <entry><emphasis>Pred</emphasis></entry>
+ <entry>A binary function object that implements an equivalence relation on values of type <code>Key</code>.
+ A binary function object that induces an equivalence relation on values of type Key.
+ It takes two arguments of type Key and returns a value of type bool.</entry></row>
+ <row>
+ <entry><emphasis>Alloc</emphasis></entry>
+ <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
+ <para>The elements are organized into buckets. Keys with the same hash code are stored in the same bucket.</para>
+ <para>The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash.</para>
+ </description>
+ <typedef name="key_type">
+ <type>Key</type>
+ </typedef>
+ <typedef name="value_type">
+ <type>std::pair&lt;Key const, Mapped&gt;</type>
+ </typedef>
+ <typedef name="mapped_type">
+ <type>Mapped</type>
+ </typedef>
+ <typedef name="hasher">
+ <type>Hash</type>
+ </typedef>
+ <typedef name="key_equal">
+ <type>Pred</type>
+ </typedef>
+ <typedef name="allocator_type">
+ <type>Alloc</type>
+ </typedef>
+ <typedef name="pointer">
+ <type>typename allocator_type::pointer</type>
+ </typedef>
+ <typedef name="const_pointer">
+ <type>typename allocator_type::const_pointer</type>
+ </typedef>
+ <typedef name="reference">
+ <type>typename allocator_type::reference</type>
+ <purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
+ </typedef>
+ <typedef name="const_reference">
+ <type>typename allocator_type::const_reference</type>
+ <purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
+ </typedef>
+ <typedef name="size_type">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>An unsigned integral type.</para>
+ <para><type>size_type</type> can represent any non-negative value of <type>difference_type</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="difference_type">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A signed integral type.</para>
+ <para>Is identical to the difference type of <type>iterator</type> and <type>const_iterator</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A iterator whose value type is <type>value_type</type>. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ <para>Convertible to <type>const_iterator</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="const_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A constant iterator whose value type is <type>value_type</type>. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ </description>
+ </typedef>
+ <typedef name="local_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>An iterator with the same value type, difference type and pointer and reference type as <type>iterator</type>.</para>
+ <para>A local_iterator object can be used to iterate through a single bucket.</para>
+ </description>
+ </typedef>
+ <typedef name="const_local_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A constant iterator with the same value type, difference type and pointer and reference type as <type>const_iterator</type>.</para>
+ <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
+ </description>
+ </typedef>
+ <constructor specifiers="explicit">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ <default><emphasis>implementation-defined</emphasis></default>
+ </parameter>
+ <parameter name="hf">
+ <paramtype>hasher const&amp;</paramtype>
+ <default>hasher()</default>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>key_equal const&amp;</paramtype>
+ <default>key_equal()</default>
+ </parameter>
+ <parameter name="a">
+ <paramtype>allocator_type const&amp;</paramtype>
+ <default>allocator_type()</default>
+ </parameter>
+ <postconditions>
+ <code><methodname>size</methodname>() == 0</code>
+ </postconditions>
+ <description>
+ <para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <template>
+ <template-type-parameter name="InputIterator">
+ </template-type-parameter>
+ </template>
+ <parameter name="f">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="l">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ <default><emphasis>implementation-defined</emphasis></default>
+ </parameter>
+ <parameter name="hf">
+ <paramtype>hasher const&amp;</paramtype>
+ <default>hasher()</default>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>key_equal const&amp;</paramtype>
+ <default>key_equal()</default>
+ </parameter>
+ <parameter name="a">
+ <paramtype>allocator_type const&amp;</paramtype>
+ <default>allocator_type()</default>
+ </parameter>
+ <description>
+ <para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <parameter>
+ <paramtype>unordered_map const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
+ </description>
+ <requires>
+ <para><code>value_type</code> is copy constructible</para>
+ </requires>
+ </constructor>
+ <constructor>
+ <parameter>
+ <paramtype>unordered_map &amp;&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>The move constructor.</para>
+ </description>
+ <notes>
+ <para>This is emulated on compilers without rvalue references.</para>
+ </notes>
+ <requires>
+ <para>
+ <code>value_type</code> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para>
+ </requires>
+ </constructor>
+ <constructor specifiers="explicit">
+ <parameter name="a">
+ <paramtype>Allocator const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>Constructs an empty container, using allocator <code>a</code>.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <parameter name="x">
+ <paramtype>unordered_map const&amp;</paramtype>
+ </parameter>
+ <parameter name="a">
+ <paramtype>Allocator const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>Constructs an container, copying <code>x</code>'s contained elements, hash function, predicate, maximum load factor, but using allocator <code>a</code>.</para>
+ </description>
+ </constructor>
+ <destructor>
+ <notes>
+ <para>The destructor is applied to every element, and all memory is deallocated</para>
+ </notes>
+ </destructor>
+ <method name="operator=">
+ <parameter>
+ <paramtype>unordered_map const&amp;</paramtype>
+ </parameter>
+ <type>unordered_map&amp;</type>
+ <description>
+ <para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
+ </description>
+ <notes>
+ <para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <code>operator=(unordered_map)</code>
+ in order to emulate move semantics.
+ </para>
+ </notes>
+ <requires>
+ <para><code>value_type</code> is copy constructible</para>
+ </requires>
+ </method>
+ <method name="operator=">
+ <parameter>
+ <paramtype>unordered_map &amp;&amp;</paramtype>
+ </parameter>
+ <type>unordered_map&amp;</type>
+ <description>
+ <para>The move assignment operator.</para>
+ </description>
+ <notes>
+ <para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <code>operator=(unordered_map)</code>
+ in order to emulate move semantics.
+ </para>
+ </notes>
+ <requires>
+ <para>
+ <code>value_type</code> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para>
+ </requires>
+ </method>
+ <method name="get_allocator" cv="const">
+ <type>allocator_type</type>
+ </method>
+ <method-group name="size and capacity">
+ <method name="empty" cv="const">
+ <type>bool</type>
+ <returns>
+ <code><methodname>size</methodname>() == 0</code>
+ </returns>
+ </method>
+ <method name="size" cv="const">
+ <type>size_type</type>
+ <returns>
+ <code>std::distance(<methodname>begin</methodname>(), <methodname>end</methodname>())</code>
+ </returns>
+ </method>
+ <method name="max_size" cv="const">
+ <type>size_type</type>
+ <returns><code><methodname>size</methodname>()</code> of the largest possible container.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="iterators">
+ <overloaded-method name="begin">
+ <signature><type>iterator</type></signature>
+ <signature cv="const"><type>const_iterator</type></signature>
+ <returns>An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </returns>
+ </overloaded-method>
+ <overloaded-method name="end">
+ <signature>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <type>const_iterator</type>
+ </signature>
+ <returns>An iterator which refers to the past-the-end value for the container.
+ </returns>
+ </overloaded-method>
+ <method name="cbegin" cv="const">
+ <type>const_iterator</type>
+ <returns>A constant iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </returns>
+ </method>
+ <method name="cend" cv="const">
+ <type>const_iterator</type>
+ <returns>A constant iterator which refers to the past-the-end value for the container.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="modifiers">
+ <method name="emplace">
+ <template>
+ <template-type-parameter name="Args" pack="1">
+ </template-type-parameter>
+ </template>
+ <parameter name="args" pack="1">
+ <paramtype>Args&amp;&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;iterator, bool&gt;</type>
+ <description>
+ <para>Inserts an object, constructed with the arguments <code>args</code>, in the container if and only if there is no element in the container with an equivalent key.</para>
+ </description>
+ <returns>
+ <para>The bool component of the return type is true if an insert took place.</para>
+ <para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ <para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para>
+ </notes>
+ </method>
+ <method name="emplace_hint">
+ <template>
+ <template-type-parameter name="Args" pack="1">
+ </template-type-parameter>
+ </template>
+ <parameter name="hint">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="args" pack="1">
+ <paramtype>Args&amp;&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts an object, constructed with the arguments <code>args</code>, in the container if and only if there is no element in the container with an equivalent key.</para>
+ <para>hint is a suggestion to where the element should be inserted.</para>
+ </description>
+ <returns>
+ <para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. </para>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ <para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <parameter name="obj">
+ <paramtype>value_type const&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;iterator, bool&gt;</type>
+ <description>
+ <para>Inserts obj in the container if and only if there is no element in the container with an equivalent key.</para>
+ </description>
+ <returns>
+ <para>The bool component of the return type is true if an insert took place.</para>
+ <para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <parameter name="hint">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="obj">
+ <paramtype>value_type const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts obj in the container if and only if there is no element in the container with an equivalent key.</para>
+ <para>hint is a suggestion to where the element should be inserted.</para>
+ </description>
+ <returns>
+ <para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. </para>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <template>
+ <template-type-parameter name="InputIterator">
+ </template-type-parameter>
+ </template>
+ <parameter name="first">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="last">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.</para>
+ </description>
+ <throws>
+ <para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="erase">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <returns>
+ <para>The iterator following <code>position</code> before the erasure.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ When the number of elements is a lot smaller than the number of buckets
+ this function can be very inefficient as it has to search through empty
+ buckets for the next element, in order to return the iterator.
+ The method <methodname>quick_erase</methodname> is faster, but has yet
+ to be standardized.
+ </para>
+ </notes>
+ </method>
+ <method name="erase">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <description>
+ <para>Erase all elements with key equivalent to <code>k</code>.</para>
+ </description>
+ <returns>
+ <para>The number of elements erased.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ </throws>
+ </method>
+ <method name="erase">
+ <parameter name="first">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="last">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Erases the elements in the range from <code>first</code> to <code>last</code>.</para>
+ </description>
+ <returns>
+ <para>The iterator following the erased elements - i.e. <code>last</code>.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ </method>
+ <method name="quick_erase">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ This method is faster than <methodname>erase</methodname> as
+ it doesn't have to find the next element in the container -
+ a potentially costly operation.
+ </para>
+ <para>
+ As it hasn't been standardized, it's likely that this may
+ change in the future.
+ </para>
+ </notes>
+ </method>
+ <method name="erase_return_void">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ This method is now deprecated, use
+ <methodname>quick_return</methodname> instead. Although be
+ warned that as that isn't standardized yet, it could also
+ change.
+ </para>
+ </notes>
+ </method>
+ <method name="clear">
+ <type>void</type>
+ <description>
+ <para>Erases all elements in the container.</para>
+ </description>
+ <postconditions>
+ <para><code><methodname>size</methodname>() == 0</code></para>
+ </postconditions>
+ <throws>
+ <para>Never throws an exception.</para>
+ </throws>
+ </method>
+ <method name="swap">
+ <parameter>
+ <paramtype>unordered_map&amp;</paramtype>
+ </parameter>
+ <type>void</type>
+ <throws>
+ <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
+ </throws>
+ <notes>
+ <para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
+ </notes>
+ </method>
+ </method-group>
+ <method-group name="observers">
+ <method name="hash_function" cv="const">
+ <type>hasher</type>
+ <returns>The container's hash function.
+ </returns>
+ </method>
+ <method name="key_eq" cv="const">
+ <type>key_equal</type>
+ <returns>The container's key equality predicate.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="lookup">
+ <overloaded-method name="find">
+ <signature>
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>const_iterator</type>
+ </signature>
+ <signature>
+ <template>
+ <template-type-parameter name="CompatibleKey"/>
+ <template-type-parameter name="CompatibleHash"/>
+ <template-type-parameter name="CompatiblePredicate"/>
+ </template>
+ <parameter name="k">
+ <paramtype>CompatibleKey const&amp;</paramtype>
+ </parameter>
+ <parameter name="hash">
+ <paramtype>CompatibleHash const&amp;</paramtype>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>CompatiblePredicate const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <template>
+ <template-type-parameter name="CompatibleKey"/>
+ <template-type-parameter name="CompatibleHash"/>
+ <template-type-parameter name="CompatiblePredicate"/>
+ </template>
+ <parameter name="k">
+ <paramtype>CompatibleKey const&amp;</paramtype>
+ </parameter>
+ <parameter name="hash">
+ <paramtype>CompatibleHash const&amp;</paramtype>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>CompatiblePredicate const&amp;</paramtype>
+ </parameter>
+ <type>const_iterator</type>
+ </signature>
+ <returns>
+ <para>An iterator pointing to an element with key equivalent to <code>k</code>, or <code>b.end()</code> if no such element exists.</para>
+ </returns>
+ <notes><para>
+ The templated overloads are a non-standard extensions which
+ allows you to use a compatible hash function and equality
+ predicate for a key of a different type in order to avoid
+ an expensive type cast. In general, its use is not encouraged.
+ </para></notes>
+ </overloaded-method>
+ <method name="count" cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <returns>
+ <para>The number of elements with key equivalent to <code>k</code>.</para>
+ </returns>
+ </method>
+ <overloaded-method name="equal_range">
+ <signature>
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;iterator, iterator&gt;</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;const_iterator, const_iterator&gt;</type>
+ </signature>
+ <returns>
+ <para>A range containing all elements with key equivalent to <code>k</code>.
+ If the container doesn't container any such elements, returns
+ <code><functionname>std::make_pair</functionname>(<methodname>b.end</methodname>(),<methodname>b.end</methodname>())</code>.
+ </para>
+ </returns>
+ </overloaded-method>
+ <method name="operator[]">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>mapped_type&amp;</type>
+ <effects>
+ <para>If the container does not already contain an elements with a key equivalent to <code>k</code>, inserts the value <code>std::pair&lt;key_type const, mapped_type&gt;(k, mapped_type())</code></para>
+ </effects>
+ <returns>
+ <para>A reference to <code>x.second</code> where x is the element already in the container, or the newly inserted element with a key equivalent to <code>k</code></para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <overloaded-method name="at">
+ <signature><type>Mapped&amp;</type>
+ <parameter name="k"><paramtype>key_type const&amp;</paramtype></parameter></signature>
+ <signature cv="const"><type>Mapped const&amp;</type>
+ <parameter name="k"><paramtype>key_type const&amp;</paramtype></parameter></signature>
+ <returns>
+ <para>A reference to <code>x.second</code> where <code>x</code> is the (unique) element whose key is equivalent to <code>k</code>.</para>
+ </returns>
+ <throws>
+ <para>An exception object of type <code>std::out_of_range</code> if no such element is present.</para>
+ </throws>
+ <notes>
+ <para>This is not specified in the draft standard, but that is probably an oversight. The issue has been raised in
+ <ulink url="http://groups.google.com/group/comp.std.c++/browse_thread/thread/ab7c22a868fd370b">comp.std.c++</ulink>.</para>
+ </notes>
+ </overloaded-method>
+ </method-group>
+ <method-group name="bucket interface">
+ <method name="bucket_count" cv="const">
+ <type>size_type</type>
+ <returns>
+ <para>The number of buckets.</para>
+ </returns>
+ </method>
+ <method name="max_bucket_count" cv="const">
+ <type>size_type</type>
+ <returns>
+ <para>An upper bound on the number of buckets.</para>
+ </returns>
+ </method>
+ <method name="bucket_size" cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <requires>
+ <para><code>n &lt; <methodname>bucket_count</methodname>()</code></para>
+ </requires>
+ <returns>
+ <para>The number of elements in bucket <code>n</code>.</para>
+ </returns>
+ </method>
+ <method name="bucket" cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <returns>
+ <para>The index of the bucket which would contain an element with key <code>k</code>.</para>
+ </returns>
+ <postconditions>
+ <para>The return value is less than <code>bucket_count()</code></para>
+ </postconditions>
+ </method>
+ <overloaded-method name="begin">
+ <signature>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>local_iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ </signature>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A local iterator pointing the first element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </overloaded-method>
+ <overloaded-method name="end">
+ <signature>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>local_iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ </signature>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A local iterator pointing the 'one past the end' element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </overloaded-method>
+ <method name="cbegin" cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A constant local iterator pointing the first element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </method>
+ <method name="cend">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A constant local iterator pointing the 'one past the end' element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="hash policy">
+ <method name="load_factor" cv="const">
+ <type>float</type>
+ <returns>
+ <para>The average number of elements per bucket.</para>
+ </returns>
+ </method>
+ <method name="max_load_factor" cv="const">
+ <type>float</type>
+ <returns>
+ <para>Returns the current maximum load factor.</para>
+ </returns>
+ </method>
+ <method name="max_load_factor">
+ <parameter name="z">
+ <paramtype>float</paramtype>
+ </parameter>
+ <type>void</type>
+ <effects>
+ <para>Changes the container's maximum load factor, using <code>z</code> as a hint.</para>
+ </effects>
+ </method>
+ <method name="rehash">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Changes the number of buckets so that there at least <code>n</code> buckets, and so that the load factor is less than the maximum load factor.</para>
+ <para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
+ </description>
+ <throws>
+ <para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
+ </throws>
+ </method>
+ </method-group>
+ <free-function-group name="Equality Comparisons">
+ <function name="operator==">
+ <template>
+ <template-type-parameter name="Key">
+ </template-type-parameter>
+ <template-type-parameter name="Mapped">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_map&lt;Key, Mapped, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_map&lt;Key, Mapped, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <type>bool</type>
+ <notes>
+ <para>This is a boost extension.</para>
+ <para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para>
+ </notes>
+ </function>
+ <function name="operator!=">
+ <template>
+ <template-type-parameter name="Key">
+ </template-type-parameter>
+ <template-type-parameter name="Mapped">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_map&lt;Key, Mapped, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_map&lt;Key, Mapped, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <type>bool</type>
+ <notes>
+ <para>This is a boost extension.</para>
+ <para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para>
+ </notes>
+ </function>
+ </free-function-group>
+ <free-function-group name="swap">
+ <function name="swap">
+ <template>
+ <template-type-parameter name="Key">
+ </template-type-parameter>
+ <template-type-parameter name="Mapped">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_map&lt;Key, Mapped, Hash, Pred, Alloc&gt;&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_map&lt;Key, Mapped, Hash, Pred, Alloc&gt;&amp;</paramtype>
+ </parameter>
+ <type>void</type>
+ <effects>
+ <para><code>x.swap(y)</code></para>
+ </effects>
+ <throws>
+ <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
+ </throws>
+ <notes>
+ <para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
+ </notes>
+ </function>
+ </free-function-group>
+ </class>
+ <class name="unordered_multimap">
+ <template>
+ <template-type-parameter name="Key">
+ </template-type-parameter>
+ <template-type-parameter name="Mapped">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ <default><type>boost::hash&lt;Key&gt;</type></default>
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ <default><type>std::equal_to&lt;Key&gt;</type></default>
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ <default><type>std::allocator&lt;std::pair&lt;Key const, Mapped&gt; &gt;</type></default>
+ </template-type-parameter>
+ </template>
+ <purpose><simpara>
+ An unordered associative container that associates keys with another value. The same key can be stored multiple times.
+ </simpara></purpose>
+ <description>
+ <para>Based on chapter 23 of
+ <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
+ But without the updated rules for allocators.
+ </para>
+ <para><emphasis role="bold">Template Parameters</emphasis>
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry><emphasis>Key</emphasis></entry>
+ <entry>Key must be Assignable and CopyConstructible.</entry></row>
+ <row>
+ <entry><emphasis>Mapped</emphasis></entry>
+ <entry>Mapped must be CopyConstructible</entry></row>
+ <row>
+ <entry><emphasis>Hash</emphasis></entry>
+ <entry>A unary function object type that acts a hash function for a <code>Key</code>. It takes a single argument of type <code>Key</code> and returns a value of type std::size_t.</entry></row>
+ <row>
+ <entry><emphasis>Pred</emphasis></entry>
+ <entry>A binary function object that implements an equivalence relation on values of type <code>Key</code>.
+ A binary function object that induces an equivalence relation on values of type Key.
+ It takes two arguments of type Key and returns a value of type bool.</entry></row>
+ <row>
+ <entry><emphasis>Alloc</emphasis></entry>
+ <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
+ <para>The elements are organized into buckets. Keys with the same hash code are stored in the same bucket and elements with equivalent keys are stored next to each other.</para>
+ <para>The number of buckets can be automatically increased by a call to insert, or as the result of calling rehash.</para>
+ </description>
+ <typedef name="key_type">
+ <type>Key</type>
+ </typedef>
+ <typedef name="value_type">
+ <type>std::pair&lt;Key const, Mapped&gt;</type>
+ </typedef>
+ <typedef name="mapped_type">
+ <type>Mapped</type>
+ </typedef>
+ <typedef name="hasher">
+ <type>Hash</type>
+ </typedef>
+ <typedef name="key_equal">
+ <type>Pred</type>
+ </typedef>
+ <typedef name="allocator_type">
+ <type>Alloc</type>
+ </typedef>
+ <typedef name="pointer">
+ <type>typename allocator_type::pointer</type>
+ </typedef>
+ <typedef name="const_pointer">
+ <type>typename allocator_type::const_pointer</type>
+ </typedef>
+ <typedef name="reference">
+ <type>typename allocator_type::reference</type>
+ <purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
+ </typedef>
+ <typedef name="const_reference">
+ <type>typename allocator_type::const_reference</type>
+ <purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
+ </typedef>
+ <typedef name="size_type">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>An unsigned integral type.</para>
+ <para><type>size_type</type> can represent any non-negative value of <type>difference_type</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="difference_type">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A signed integral type.</para>
+ <para>Is identical to the difference type of <type>iterator</type> and <type>const_iterator</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A iterator whose value type is <type>value_type</type>. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ <para>Convertible to <type>const_iterator</type>.</para>
+ </description>
+ </typedef>
+ <typedef name="const_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A constant iterator whose value type is <type>value_type</type>. </para>
+ <para>The iterator category is at least a forward iterator.</para>
+ </description>
+ </typedef>
+ <typedef name="local_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>An iterator with the same value type, difference type and pointer and reference type as <type>iterator</type>.</para>
+ <para>A local_iterator object can be used to iterate through a single bucket.</para>
+ </description>
+ </typedef>
+ <typedef name="const_local_iterator">
+ <type><emphasis>implementation-defined</emphasis></type>
+ <description>
+ <para>A constant iterator with the same value type, difference type and pointer and reference type as <type>const_iterator</type>.</para>
+ <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
+ </description>
+ </typedef>
+ <constructor specifiers="explicit">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ <default><emphasis>implementation-defined</emphasis></default>
+ </parameter>
+ <parameter name="hf">
+ <paramtype>hasher const&amp;</paramtype>
+ <default>hasher()</default>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>key_equal const&amp;</paramtype>
+ <default>key_equal()</default>
+ </parameter>
+ <parameter name="a">
+ <paramtype>allocator_type const&amp;</paramtype>
+ <default>allocator_type()</default>
+ </parameter>
+ <postconditions>
+ <code><methodname>size</methodname>() == 0</code>
+ </postconditions>
+ <description>
+ <para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <template>
+ <template-type-parameter name="InputIterator">
+ </template-type-parameter>
+ </template>
+ <parameter name="f">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="l">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ <default><emphasis>implementation-defined</emphasis></default>
+ </parameter>
+ <parameter name="hf">
+ <paramtype>hasher const&amp;</paramtype>
+ <default>hasher()</default>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>key_equal const&amp;</paramtype>
+ <default>key_equal()</default>
+ </parameter>
+ <parameter name="a">
+ <paramtype>allocator_type const&amp;</paramtype>
+ <default>allocator_type()</default>
+ </parameter>
+ <description>
+ <para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <parameter>
+ <paramtype>unordered_multimap const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
+ </description>
+ <requires>
+ <para><code>value_type</code> is copy constructible</para>
+ </requires>
+ </constructor>
+ <constructor>
+ <parameter>
+ <paramtype>unordered_multimap &amp;&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>The move constructor.</para>
+ </description>
+ <notes>
+ <para>This is emulated on compilers without rvalue references.</para>
+ </notes>
+ <requires>
+ <para>
+ <code>value_type</code> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para>
+ </requires>
+ </constructor>
+ <constructor specifiers="explicit">
+ <parameter name="a">
+ <paramtype>Allocator const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>Constructs an empty container, using allocator <code>a</code>.</para>
+ </description>
+ </constructor>
+ <constructor>
+ <parameter name="x">
+ <paramtype>unordered_multimap const&amp;</paramtype>
+ </parameter>
+ <parameter name="a">
+ <paramtype>Allocator const&amp;</paramtype>
+ </parameter>
+ <description>
+ <para>Constructs an container, copying <code>x</code>'s contained elements, hash function, predicate, maximum load factor, but using allocator <code>a</code>.</para>
+ </description>
+ </constructor>
+ <destructor>
+ <notes>
+ <para>The destructor is applied to every element, and all memory is deallocated</para>
+ </notes>
+ </destructor>
+ <method name="operator=">
+ <parameter>
+ <paramtype>unordered_multimap const&amp;</paramtype>
+ </parameter>
+ <type>unordered_multimap&amp;</type>
+ <description>
+ <para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
+ </description>
+ <notes>
+ <para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <code>operator=(unordered_multimap)</code>
+ in order to emulate move semantics.
+ </para>
+ </notes>
+ <requires>
+ <para><code>value_type</code> is copy constructible</para>
+ </requires>
+ </method>
+ <method name="operator=">
+ <parameter>
+ <paramtype>unordered_multimap &amp;&amp;</paramtype>
+ </parameter>
+ <type>unordered_multimap&amp;</type>
+ <description>
+ <para>The move assignment operator.</para>
+ </description>
+ <notes>
+ <para>
+ On compilers without rvalue references, there is a single assignment
+ operator with the signature <code>operator=(unordered_multimap)</code>
+ in order to emulate move semantics.
+ </para>
+ </notes>
+ <requires>
+ <para>
+ <code>value_type</code> is move constructible.
+ (TODO: This is not actually required in this implementation).
+ </para>
+ </requires>
+ </method>
+ <method name="get_allocator" cv="const">
+ <type>allocator_type</type>
+ </method>
+ <method-group name="size and capacity">
+ <method name="empty" cv="const">
+ <type>bool</type>
+ <returns>
+ <code><methodname>size</methodname>() == 0</code>
+ </returns>
+ </method>
+ <method name="size" cv="const">
+ <type>size_type</type>
+ <returns>
+ <code>std::distance(<methodname>begin</methodname>(), <methodname>end</methodname>())</code>
+ </returns>
+ </method>
+ <method name="max_size" cv="const">
+ <type>size_type</type>
+ <returns><code><methodname>size</methodname>()</code> of the largest possible container.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="iterators">
+ <overloaded-method name="begin">
+ <signature><type>iterator</type></signature>
+ <signature cv="const"><type>const_iterator</type></signature>
+ <returns>An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </returns>
+ </overloaded-method>
+ <overloaded-method name="end">
+ <signature>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <type>const_iterator</type>
+ </signature>
+ <returns>An iterator which refers to the past-the-end value for the container.
+ </returns>
+ </overloaded-method>
+ <method name="cbegin" cv="const">
+ <type>const_iterator</type>
+ <returns>A constant iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container.
+ </returns>
+ </method>
+ <method name="cend" cv="const">
+ <type>const_iterator</type>
+ <returns>A constant iterator which refers to the past-the-end value for the container.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="modifiers">
+ <method name="emplace">
+ <template>
+ <template-type-parameter name="Args" pack="1">
+ </template-type-parameter>
+ </template>
+ <parameter name="args" pack="1">
+ <paramtype>Args&amp;&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts an object, constructed with the arguments <code>args</code>, in the container.</para>
+ </description>
+ <returns>
+ <para>An iterator pointing to the inserted element.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ <para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para>
+ </notes>
+ </method>
+ <method name="emplace_hint">
+ <template>
+ <template-type-parameter name="Args" pack="1">
+ </template-type-parameter>
+ </template>
+ <parameter name="hint">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="args" pack="1">
+ <paramtype>Args&amp;&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts an object, constructed with the arguments <code>args</code>, in the container.</para>
+ <para>hint is a suggestion to where the element should be inserted.</para>
+ </description>
+ <returns>
+ <para>An iterator pointing to the inserted element.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. </para>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ <para>If the compiler doesn't support variadic template arguments or rvalue
+ references, this is emulated for up to 10 arguments, with no support
+ for rvalue references or move semantics.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <parameter name="obj">
+ <paramtype>value_type const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts obj in the container.</para>
+ </description>
+ <returns>
+ <para>An iterator pointing to the inserted element.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <parameter name="hint">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="obj">
+ <paramtype>value_type const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Inserts obj in the container.</para>
+ <para>hint is a suggestion to where the element should be inserted.</para>
+ </description>
+ <returns>
+ <para>An iterator pointing to the inserted element.</para>
+ </returns>
+ <throws>
+ <para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. </para>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="insert">
+ <template>
+ <template-type-parameter name="InputIterator">
+ </template-type-parameter>
+ </template>
+ <parameter name="first">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <parameter name="last">
+ <paramtype>InputIterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Inserts a range of elements into the container.</para>
+ </description>
+ <throws>
+ <para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
+ </throws>
+ <notes>
+ <para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
+ <para>Pointers and references to elements are never invalidated.</para>
+ </notes>
+ </method>
+ <method name="erase">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <returns>
+ <para>The iterator following <code>position</code> before the erasure.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ When the number of elements is a lot smaller than the number of buckets
+ this function can be very inefficient as it has to search through empty
+ buckets for the next element, in order to return the iterator.
+ The method <methodname>quick_erase</methodname> is faster, but has yet
+ to be standardized.
+ </para>
+ </notes>
+ </method>
+ <method name="erase">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <description>
+ <para>Erase all elements with key equivalent to <code>k</code>.</para>
+ </description>
+ <returns>
+ <para>The number of elements erased.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ </throws>
+ </method>
+ <method name="erase">
+ <parameter name="first">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <parameter name="last">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>iterator</type>
+ <description>
+ <para>Erases the elements in the range from <code>first</code> to <code>last</code>.</para>
+ </description>
+ <returns>
+ <para>The iterator following the erased elements - i.e. <code>last</code>.</para>
+ </returns>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ </method>
+ <method name="quick_erase">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ This method is faster than <methodname>erase</methodname> as
+ it doesn't have to find the next element in the container -
+ a potentially costly operation.
+ </para>
+ <para>
+ As it hasn't been standardized, it's likely that this may
+ change in the future.
+ </para>
+ </notes>
+ </method>
+ <method name="erase_return_void">
+ <parameter name="position">
+ <paramtype>const_iterator</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Erase the element pointed to by <code>position</code>.</para>
+ </description>
+ <throws>
+ <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
+ <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
+ </throws>
+ <notes>
+ <para>
+ This method is now deprecated, use
+ <methodname>quick_return</methodname> instead. Although be
+ warned that as that isn't standardized yet, it could also
+ change.
+ </para>
+ </notes>
+ </method>
+ <method name="clear">
+ <type>void</type>
+ <description>
+ <para>Erases all elements in the container.</para>
+ </description>
+ <postconditions>
+ <para><code><methodname>size</methodname>() == 0</code></para>
+ </postconditions>
+ <throws>
+ <para>Never throws an exception.</para>
+ </throws>
+ </method>
+ <method name="swap">
+ <parameter>
+ <paramtype>unordered_multimap&amp;</paramtype>
+ </parameter>
+ <type>void</type>
+ <throws>
+ <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
+ </throws>
+ <notes>
+ <para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
+ </notes>
+ </method>
+ </method-group>
+ <method-group name="observers">
+ <method name="hash_function" cv="const">
+ <type>hasher</type>
+ <returns>The container's hash function.
+ </returns>
+ </method>
+ <method name="key_eq" cv="const">
+ <type>key_equal</type>
+ <returns>The container's key equality predicate.
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="lookup">
+ <overloaded-method name="find">
+ <signature>
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>const_iterator</type>
+ </signature>
+ <signature>
+ <template>
+ <template-type-parameter name="CompatibleKey"/>
+ <template-type-parameter name="CompatibleHash"/>
+ <template-type-parameter name="CompatiblePredicate"/>
+ </template>
+ <parameter name="k">
+ <paramtype>CompatibleKey const&amp;</paramtype>
+ </parameter>
+ <parameter name="hash">
+ <paramtype>CompatibleHash const&amp;</paramtype>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>CompatiblePredicate const&amp;</paramtype>
+ </parameter>
+ <type>iterator</type>
+ </signature>
+ <signature cv="const">
+ <template>
+ <template-type-parameter name="CompatibleKey"/>
+ <template-type-parameter name="CompatibleHash"/>
+ <template-type-parameter name="CompatiblePredicate"/>
+ </template>
+ <parameter name="k">
+ <paramtype>CompatibleKey const&amp;</paramtype>
+ </parameter>
+ <parameter name="hash">
+ <paramtype>CompatibleHash const&amp;</paramtype>
+ </parameter>
+ <parameter name="eq">
+ <paramtype>CompatiblePredicate const&amp;</paramtype>
+ </parameter>
+ <type>const_iterator</type>
+ </signature>
+ <returns>
+ <para>An iterator pointing to an element with key equivalent to <code>k</code>, or <code>b.end()</code> if no such element exists.</para>
+ </returns>
+ <notes><para>
+ The templated overloads are a non-standard extensions which
+ allows you to use a compatible hash function and equality
+ predicate for a key of a different type in order to avoid
+ an expensive type cast. In general, its use is not encouraged.
+ </para></notes>
+ </overloaded-method>
+ <method name="count" cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <returns>
+ <para>The number of elements with key equivalent to <code>k</code>.</para>
+ </returns>
+ </method>
+ <overloaded-method name="equal_range">
+ <signature>
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;iterator, iterator&gt;</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>std::pair&lt;const_iterator, const_iterator&gt;</type>
+ </signature>
+ <returns>
+ <para>A range containing all elements with key equivalent to <code>k</code>.
+ If the container doesn't container any such elements, returns
+ <code><functionname>std::make_pair</functionname>(<methodname>b.end</methodname>(),<methodname>b.end</methodname>())</code>.
+ </para>
+ </returns>
+ </overloaded-method>
+ </method-group>
+ <method-group name="bucket interface">
+ <method name="bucket_count" cv="const">
+ <type>size_type</type>
+ <returns>
+ <para>The number of buckets.</para>
+ </returns>
+ </method>
+ <method name="max_bucket_count" cv="const">
+ <type>size_type</type>
+ <returns>
+ <para>An upper bound on the number of buckets.</para>
+ </returns>
+ </method>
+ <method name="bucket_size" cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <requires>
+ <para><code>n &lt; <methodname>bucket_count</methodname>()</code></para>
+ </requires>
+ <returns>
+ <para>The number of elements in bucket <code>n</code>.</para>
+ </returns>
+ </method>
+ <method name="bucket" cv="const">
+ <parameter name="k">
+ <paramtype>key_type const&amp;</paramtype>
+ </parameter>
+ <type>size_type</type>
+ <returns>
+ <para>The index of the bucket which would contain an element with key <code>k</code>.</para>
+ </returns>
+ <postconditions>
+ <para>The return value is less than <code>bucket_count()</code></para>
+ </postconditions>
+ </method>
+ <overloaded-method name="begin">
+ <signature>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>local_iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ </signature>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A local iterator pointing the first element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </overloaded-method>
+ <overloaded-method name="end">
+ <signature>
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>local_iterator</type>
+ </signature>
+ <signature cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ </signature>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A local iterator pointing the 'one past the end' element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </overloaded-method>
+ <method name="cbegin" cv="const">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A constant local iterator pointing the first element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </method>
+ <method name="cend">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>const_local_iterator</type>
+ <requires>
+ <para><code>n</code> shall be in the range <code>[0, bucket_count())</code>.</para>
+ </requires>
+ <returns>
+ <para>A constant local iterator pointing the 'one past the end' element in the bucket with index <code>n</code>.</para>
+ </returns>
+ </method>
+ </method-group>
+ <method-group name="hash policy">
+ <method name="load_factor" cv="const">
+ <type>float</type>
+ <returns>
+ <para>The average number of elements per bucket.</para>
+ </returns>
+ </method>
+ <method name="max_load_factor" cv="const">
+ <type>float</type>
+ <returns>
+ <para>Returns the current maximum load factor.</para>
+ </returns>
+ </method>
+ <method name="max_load_factor">
+ <parameter name="z">
+ <paramtype>float</paramtype>
+ </parameter>
+ <type>void</type>
+ <effects>
+ <para>Changes the container's maximum load factor, using <code>z</code> as a hint.</para>
+ </effects>
+ </method>
+ <method name="rehash">
+ <parameter name="n">
+ <paramtype>size_type</paramtype>
+ </parameter>
+ <type>void</type>
+ <description>
+ <para>Changes the number of buckets so that there at least <code>n</code> buckets, and so that the load factor is less than the maximum load factor.</para>
+ <para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
+ </description>
+ <throws>
+ <para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
+ </throws>
+ </method>
+ </method-group>
+ <free-function-group name="Equality Comparisons">
+ <function name="operator==">
+ <template>
+ <template-type-parameter name="Key">
+ </template-type-parameter>
+ <template-type-parameter name="Mapped">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_multimap&lt;Key, Mapped, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_multimap&lt;Key, Mapped, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <type>bool</type>
+ <notes>
+ <para>This is a boost extension.</para>
+ <para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para>
+ </notes>
+ </function>
+ <function name="operator!=">
+ <template>
+ <template-type-parameter name="Key">
+ </template-type-parameter>
+ <template-type-parameter name="Mapped">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_multimap&lt;Key, Mapped, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_multimap&lt;Key, Mapped, Hash, Pred, Alloc&gt; const&amp;</paramtype>
+ </parameter>
+ <type>bool</type>
+ <notes>
+ <para>This is a boost extension.</para>
+ <para>Behavior is undefined if the two containers don't have
+ equivalent equality predicates.</para>
+ </notes>
+ </function>
+ </free-function-group>
+ <free-function-group name="swap">
+ <function name="swap">
+ <template>
+ <template-type-parameter name="Key">
+ </template-type-parameter>
+ <template-type-parameter name="Mapped">
+ </template-type-parameter>
+ <template-type-parameter name="Hash">
+ </template-type-parameter>
+ <template-type-parameter name="Pred">
+ </template-type-parameter>
+ <template-type-parameter name="Alloc">
+ </template-type-parameter>
+ </template>
+ <parameter name="x">
+ <paramtype>unordered_multimap&lt;Key, Mapped, Hash, Pred, Alloc&gt;&amp;</paramtype>
+ </parameter>
+ <parameter name="y">
+ <paramtype>unordered_multimap&lt;Key, Mapped, Hash, Pred, Alloc&gt;&amp;</paramtype>
+ </parameter>
+ <type>void</type>
+ <effects>
+ <para><code>x.swap(y)</code></para>
+ </effects>
+ <throws>
+ <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
+ </throws>
+ <notes>
+ <para>For a discussion of the behavior when allocators aren't equal see
+ <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
+ </notes>
+ </function>
+ </free-function-group>
+ </class>
+ </namespace>
+ </header>
+ </library-reference>
diff --git a/tools/boostbook/test/more/tests/misc/processing.gold b/tools/boostbook/test/more/tests/misc/processing.gold
new file mode 100644
index 0000000000..2bf9710958
--- /dev/null
+++ b/tools/boostbook/test/more/tests/misc/processing.gold
@@ -0,0 +1,5 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<book xmlns:xi="http://www.w3.org/2001/XInclude" id="test" lang="en">
+ <title>Test processing instructions</title>
+ <para><?dbtimestamp format="Y-m-d H:M:S"?></para>
+</book> \ No newline at end of file
diff --git a/tools/boostbook/test/more/tests/misc/processing.xml b/tools/boostbook/test/more/tests/misc/processing.xml
new file mode 100644
index 0000000000..692ef9c735
--- /dev/null
+++ b/tools/boostbook/test/more/tests/misc/processing.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2011 Daniel James.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+-->
+<!DOCTYPE boostbook PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<boostbook id="test" xmlns:xi="http://www.w3.org/2001/XInclude"
+ last-revision="$Date: 2010-10-30 15:29:27 +0100 (Sat, 30 Oct 2010) $"
+ lang="en">
+ <title>Test processing instructions</title>
+ <para><?dbtimestamp format="Y-m-d H:M:S"?></para>
+</boostbook>
+
+
diff --git a/tools/boostbook/test/more/tests/syntax-highlight/comments.gold b/tools/boostbook/test/more/tests/syntax-highlight/comments.gold
new file mode 100644
index 0000000000..a2b1633ef6
--- /dev/null
+++ b/tools/boostbook/test/more/tests/syntax-highlight/comments.gold
@@ -0,0 +1,26 @@
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<section id="header.example_hpp"><title>Header &lt;<ulink url="../../example.hpp">example.hpp</ulink>&gt;</title><para>
+ Fake reference documentation, so that the syntax highlighter will kick in.
+ </para><synopsis xmlns:xi="http://www.w3.org/2001/XInclude">
+
+<link linkend="foo">foo</link></synopsis>
+
+
+ <refentry xmlns:xi="http://www.w3.org/2001/XInclude" id="foo"><refmeta><refentrytitle>Macro foo</refentrytitle><manvolnum>3</manvolnum></refmeta><refnamediv><refname>foo</refname><refpurpose/></refnamediv><refsynopsisdiv><synopsis><phrase role="comment">// In header: &lt;<link linkend="header.example_hpp">example.hpp</link>&gt;
+
+</phrase>foo</synopsis></refsynopsisdiv><refsect1><title>Description</title>
+ <programlisting><phrase role="comment">/* C style comment */</phrase></programlisting>
+ <programlisting><phrase role="comment">/* Broken C style comment</phrase></programlisting>
+ <programlisting>
+<phrase role="comment">/* Multi-line
+ *comment
+ */</phrase></programlisting>
+ <programlisting><phrase role="comment">/*/ Tricky comment */</phrase></programlisting>
+ <programlisting><phrase role="comment">/**/</phrase></programlisting>
+ <programlisting><phrase role="comment">/***/</phrase></programlisting>
+ <programlisting><phrase role="comment">// Single line comment</phrase></programlisting>
+ <programlisting><phrase role="comment">// Single line comment</phrase>
+</programlisting>
+ </refsect1></refentry>
+
+</section> \ No newline at end of file
diff --git a/tools/boostbook/test/more/tests/syntax-highlight/comments.xml b/tools/boostbook/test/more/tests/syntax-highlight/comments.xml
new file mode 100644
index 0000000000..061870db17
--- /dev/null
+++ b/tools/boostbook/test/more/tests/syntax-highlight/comments.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2010 Daniel James.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+-->
+<header name="example.hpp">
+ <para>
+ Fake reference documentation, so that the syntax highlighter will kick in.
+ </para>
+
+ <macro name="foo">
+ <description>
+ <programlisting>/* C style comment */</programlisting>
+ <programlisting>/* Broken C style comment</programlisting>
+ <programlisting>
+/* Multi-line
+ *comment
+ */</programlisting>
+ <programlisting>/*/ Tricky comment */</programlisting>
+ <programlisting>/**/</programlisting>
+ <programlisting>/***/</programlisting>
+ <programlisting>// Single line comment</programlisting>
+ <programlisting>// Single line comment
+</programlisting>
+ </description>
+ </macro>
+
+</header>
diff --git a/tools/boostbook/xsl/admon.xsl b/tools/boostbook/xsl/admon.xsl
new file mode 100644
index 0000000000..d29053ac16
--- /dev/null
+++ b/tools/boostbook/xsl/admon.xsl
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/admon.xsl"/>
+
+<!-- Already included in the main style sheet -->
+<!-- <xsl:import href="relative-href.xsl"/> -->
+
+<xsl:template name="admon.graphic">
+ <xsl:param name="node" select="."/>
+
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="$admon.graphics.path"/>
+ </xsl:call-template>
+
+ <xsl:choose>
+ <xsl:when test="local-name($node)='note'">note</xsl:when>
+ <xsl:when test="local-name($node)='warning'">warning</xsl:when>
+ <xsl:when test="local-name($node)='caution'">caution</xsl:when>
+ <xsl:when test="local-name($node)='tip'">tip</xsl:when>
+ <xsl:when test="local-name($node)='important'">important</xsl:when>
+ <xsl:otherwise>note</xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:value-of select="$admon.graphics.extension"/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/annotation.xsl b/tools/boostbook/xsl/annotation.xsl
new file mode 100644
index 0000000000..9f5a178586
--- /dev/null
+++ b/tools/boostbook/xsl/annotation.xsl
@@ -0,0 +1,437 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:variable name="uppercase-letters" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
+ <xsl:variable name="lowercase-letters" select="'abcdefghijklmnopqrstuvwxyz'"/>
+
+ <xsl:key name="classes" match="class|struct|union|typedef" use="@name"/>
+ <xsl:key name="methods" match="method|overloaded-method" use="@name"/>
+ <xsl:key name="functions" match="function|overloaded-function" use="@name"/>
+ <xsl:key name="enums" match="enum" use="@name"/>
+ <xsl:key name="concepts" match="concept" use="@name"/>
+ <xsl:key name="libraries" match="library" use="@name"/>
+ <xsl:key name="macros" match="macro" use="@name"/>
+ <xsl:key name="headers" match="header" use="@name"/>
+ <xsl:key name="globals" match="namespace/data-member|header/data-member" use="@name"/>
+ <xsl:key name="named-entities" match="class|struct|union|concept|function|overloaded-function|macro|library|namespace/data-member|header/data-member|*[attribute::id]" use="translate(@name|@id, $uppercase-letters, $lowercase-letters)"/>
+
+ <xsl:template match="function|overloaded-function" mode="generate.id">
+ <xsl:call-template name="fully-qualified-id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="classname" mode="annotation">
+ <!-- Determine the (possibly qualified) class name we are looking for -->
+ <xsl:variable name="fullname">
+ <xsl:choose>
+ <xsl:when test="@alt">
+ <xsl:value-of select="@alt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string(.)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Strip off any instantiation -->
+ <xsl:variable name="name">
+ <xsl:choose>
+ <xsl:when test="contains($fullname, '&lt;')">
+ <xsl:value-of select="substring-before($fullname, '&lt;')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$fullname"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Determine the unqualified name -->
+ <xsl:variable name="unqualified-name">
+ <xsl:call-template name="strip-qualifiers">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:call-template name="cxx-link-name">
+ <xsl:with-param name="lookup" select="."/>
+ <xsl:with-param name="type" select="'class'"/>
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="display-name" select="string(.)"/>
+ <xsl:with-param name="unqualified-name" select="$unqualified-name"/>
+ <xsl:with-param name="nodes" select="key('classes', $unqualified-name)"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="globalname" mode="annotation">
+ <!-- Determine the (possibly qualified) global name we are looking for -->
+ <xsl:variable name="name">
+ <xsl:choose>
+ <xsl:when test="@alt">
+ <xsl:value-of select="@alt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string(.)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Determine the unqualified name -->
+ <xsl:variable name="unqualified-name">
+ <xsl:call-template name="strip-qualifiers">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:call-template name="cxx-link-name">
+ <xsl:with-param name="lookup" select="."/>
+ <xsl:with-param name="type" select="'data-member'"/>
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="display-name" select="string(.)"/>
+ <xsl:with-param name="unqualified-name" select="$unqualified-name"/>
+ <xsl:with-param name="nodes" select="key('globals', $unqualified-name)"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="methodname" mode="annotation">
+ <!-- Determine the (possibly qualified) method name we are looking for -->
+ <xsl:variable name="fullname">
+ <xsl:choose>
+ <xsl:when test="@alt">
+ <xsl:value-of select="@alt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string(.)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Strip off any call -->
+ <xsl:variable name="name">
+ <xsl:choose>
+ <xsl:when test="contains($fullname, '(')">
+ <xsl:value-of select="substring-before($fullname, '(')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$fullname"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Determine the unqualified name -->
+ <xsl:variable name="unqualified-name">
+ <xsl:call-template name="strip-qualifiers">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:call-template name="cxx-link-name">
+ <xsl:with-param name="lookup" select="."/>
+ <xsl:with-param name="type" select="'method'"/>
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="display-name" select="string(.)"/>
+ <xsl:with-param name="unqualified-name" select="$unqualified-name"/>
+ <xsl:with-param name="nodes" select="key('methods', $unqualified-name)"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="functionname" mode="annotation">
+ <!-- Determine the (possibly qualified) function name we are
+ looking for -->
+ <xsl:variable name="fullname">
+ <xsl:choose>
+ <xsl:when test="@alt">
+ <xsl:value-of select="@alt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string(.)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Strip off any call -->
+ <xsl:variable name="name">
+ <xsl:choose>
+ <xsl:when test="contains($fullname, '(')">
+ <xsl:value-of select="substring-before($fullname, '(')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$fullname"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Determine the unqualified name -->
+ <xsl:variable name="unqualified-name">
+ <xsl:call-template name="strip-qualifiers">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:call-template name="cxx-link-name">
+ <xsl:with-param name="lookup" select="."/>
+ <xsl:with-param name="type" select="'function'"/>
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="display-name" select="string(.)"/>
+ <xsl:with-param name="unqualified-name" select="$unqualified-name"/>
+ <xsl:with-param name="nodes"
+ select="key('functions', $unqualified-name)"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="enumname" mode="annotation">
+ <!-- Determine the (possibly qualified) enum name we are
+ looking for -->
+ <xsl:variable name="fullname">
+ <xsl:choose>
+ <xsl:when test="@alt">
+ <xsl:value-of select="@alt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string(.)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Strip off any call -->
+ <xsl:variable name="name">
+ <xsl:choose>
+ <xsl:when test="contains($fullname, '(')">
+ <xsl:value-of select="substring-before($fullname, '(')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$fullname"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Determine the unqualified name -->
+ <xsl:variable name="unqualified-name">
+ <xsl:call-template name="strip-qualifiers">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:call-template name="cxx-link-name">
+ <xsl:with-param name="lookup" select="."/>
+ <xsl:with-param name="type" select="'enum'"/>
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="display-name" select="string(.)"/>
+ <xsl:with-param name="unqualified-name" select="$unqualified-name"/>
+ <xsl:with-param name="nodes"
+ select="key('enums', $unqualified-name)"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="libraryname" mode="annotation">
+ <xsl:variable name="name">
+ <xsl:choose>
+ <xsl:when test="@alt">
+ <xsl:value-of select="@alt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="text()"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="node" select="key('libraries', $name)"/>
+
+ <xsl:choose>
+ <xsl:when test="count($node)=0">
+ <xsl:message>
+ <xsl:text>warning: Cannot find library '</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>'</xsl:text>
+ </xsl:message>
+ <xsl:value-of select="$name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="library.link">
+ <xsl:with-param name="node" select="$node"/>
+ <xsl:with-param name="name" select="text()"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="conceptname" mode="annotation">
+ <xsl:param name="name" select="text()"/>
+
+ <xsl:call-template name="concept.link">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="macroname" mode="annotation">
+ <xsl:param name="name">
+ <xsl:choose>
+ <xsl:when test="@alt">
+ <xsl:value-of select="@alt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string(.)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:param>
+
+ <xsl:variable name="node" select="key('macros', $name)"/>
+ <xsl:choose>
+ <xsl:when test="count($node) = 0">
+ <xsl:message>
+ <xsl:text>warning: cannot find macro `</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>'</xsl:text>
+ </xsl:message>
+ <xsl:value-of select="$name"/>
+ </xsl:when>
+
+ <xsl:when test="count($node) = 1">
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="string(.)"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:message>
+ <xsl:text>error: macro `</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>' is multiply defined.</xsl:text>
+ </xsl:message>
+ <xsl:value-of select="$node"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="headername" mode="annotation">
+ <xsl:variable name="name">
+ <xsl:choose>
+ <xsl:when test="@alt">
+ <xsl:value-of select="@alt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string(.)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="node" select="key('headers', $name)"/>
+ <xsl:choose>
+ <xsl:when test="count($node) = 0">
+ <xsl:message>
+ <xsl:text>warning: cannot find header `</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>'</xsl:text>
+ </xsl:message>
+ <xsl:value-of select="$name"/>
+ </xsl:when>
+
+ <xsl:when test="count($node) = 1">
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="string(.)"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:message>
+ <xsl:text>error: header `</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>' is multiply defined.</xsl:text>
+ </xsl:message>
+ <xsl:value-of select="$node"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="text()" mode="annotation">
+ <xsl:param name="highlight" select="false()"/>
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="."/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="programlisting" mode="annotation">
+ <programlisting>
+ <xsl:apply-templates mode="annotation">
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:apply-templates>
+ </programlisting>
+ </xsl:template>
+
+ <xsl:template match="code" mode="annotation">
+ <computeroutput>
+ <xsl:apply-templates mode="annotation"/>
+ </computeroutput>
+ </xsl:template>
+
+ <xsl:template match="bold" mode="annotation">
+ <emphasis role="bold">
+ <xsl:apply-templates mode="annotation"/>
+ </emphasis>
+ </xsl:template>
+
+ <xsl:template match="description" mode="annotation">
+ <xsl:apply-templates mode="annotation"/>
+ </xsl:template>
+
+ <xsl:template match="type" mode="annotation">
+ <xsl:apply-templates mode="annotation"/>
+ </xsl:template>
+
+ <xsl:template match="comment()" mode="annotation">
+ <xsl:copy/>
+ </xsl:template>
+
+ <xsl:template match="node()" mode="annotation">
+ <xsl:param name="highlight" select="false()"/>
+
+ <xsl:element name="{name(.)}">
+ <xsl:for-each select="./@*">
+ <xsl:attribute name="{name(.)}">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:for-each>
+ <xsl:apply-templates select="./*|./text()" mode="annotation">
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:template>
+
+ <!-- The "purpose" mode strips simpara/para elements so that we can
+ place the resulting text into a comment in the synopsis. -->
+ <xsl:template match="para|simpara" mode="purpose">
+ <xsl:apply-templates mode="annotation"/>
+ </xsl:template>
+
+ <xsl:template match="*" mode="purpose">
+ <xsl:apply-templates select="." mode="annotation"/>
+ </xsl:template>
+
+ <xsl:template match="text()" mode="purpose">
+ <xsl:apply-templates select="." mode="annotation"/>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/callout.xsl b/tools/boostbook/xsl/callout.xsl
new file mode 100644
index 0000000000..8faa5340bb
--- /dev/null
+++ b/tools/boostbook/xsl/callout.xsl
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2007 Joel de Guzman <djowel -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/callout.xsl"/>
+
+<!-- Already included in the main style sheet -->
+<!-- <xsl:import href="relative-href.xsl"/> -->
+
+<xsl:template name="callout-bug">
+ <xsl:param name="conum" select='1'/>
+
+ <xsl:choose>
+ <xsl:when test="$callout.graphics != 0
+ and $conum &lt;= $callout.graphics.number.limit">
+
+ <xsl:variable name="relative_callout_graphics_path">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="$callout.graphics.path"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <img src="{$relative_callout_graphics_path}{$conum}{$callout.graphics.extension}"
+ alt="{$conum}" border="0"/>
+ </xsl:when>
+
+ <xsl:when test="$callout.unicode != 0
+ and $conum &lt;= $callout.unicode.number.limit">
+ <xsl:choose>
+ <xsl:when test="$callout.unicode.start.character = 10102">
+ <xsl:choose>
+ <xsl:when test="$conum = 1">&#10102;</xsl:when>
+ <xsl:when test="$conum = 2">&#10103;</xsl:when>
+ <xsl:when test="$conum = 3">&#10104;</xsl:when>
+ <xsl:when test="$conum = 4">&#10105;</xsl:when>
+ <xsl:when test="$conum = 5">&#10106;</xsl:when>
+ <xsl:when test="$conum = 6">&#10107;</xsl:when>
+ <xsl:when test="$conum = 7">&#10108;</xsl:when>
+ <xsl:when test="$conum = 8">&#10109;</xsl:when>
+ <xsl:when test="$conum = 9">&#10110;</xsl:when>
+ <xsl:when test="$conum = 10">&#10111;</xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>
+ <xsl:text>Don't know how to generate Unicode callouts </xsl:text>
+ <xsl:text>when $callout.unicode.start.character is </xsl:text>
+ <xsl:value-of select="$callout.unicode.start.character"/>
+ </xsl:message>
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$conum"/>
+ <xsl:text>)</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$conum"/>
+ <xsl:text>)</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/caramel/LICENSE b/tools/boostbook/xsl/caramel/LICENSE
new file mode 100644
index 0000000000..d26de04a0d
--- /dev/null
+++ b/tools/boostbook/xsl/caramel/LICENSE
@@ -0,0 +1,58 @@
+Software License, Version 1.0
+
+Copyright 2002-2003, Trustees of Indiana University.
+Copyright 2000-2001, University of Notre Dame.
+All rights reserved.
+
+Indiana University has the exclusive rights to license this product under the
+following license.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * All redistributions of source code must retain the above copyright notice,
+ the list of authors in the original source code, this list of conditions
+ and the disclaimer listed in this license;
+
+ * All redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the disclaimer listed in this license
+ in the documentation and/or other materials provided with the distribution;
+
+ * Any documentation included with all redistributions must include the
+ following acknowledgement:
+
+ "This product includes software developed at the University of Notre Dame
+ and the Pervasive Technology Labs at Indiana University. For technical
+ information contact Andrew Lumsdaine at the Pervasive Technology Labs at
+ Indiana University. For administrative and license questions contact the
+ Advanced Research and Technology Institute at 351 West 10th Street.
+ Indianapolis, Indiana 46202, phone 317-278-4100, fax 317-274-5902."
+
+ Alternatively, this acknowledgement may appear in the software itself, and
+ wherever such third-party acknowledgments normally appear.
+
+ * The name Indiana University, the University of Notre Dame or "Caramel"
+ shall not be used to endorse or promote products derived from this software
+ without prior written permission from Indiana University. For written
+ permission, please contact Indiana University Advanced Research &
+ Technology Institute.
+
+ * Products derived from this software may not be called "Caramel", nor may
+ Indiana University, the University of Notre Dame or "Caramel" appear in
+ their name, without prior written permission of Indiana University Advanced
+ Research & Technology Institute.
+
+Indiana University provides no reassurances that the source code provided does
+not infringe the patent or any other intellectual property rights of any other
+entity. Indiana University disclaims any liability to any recipient for claims
+brought by any other entity based on infringement of intellectual property
+rights or otherwise.
+
+LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO WARRANTIES
+AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES NO WARRANTIES
+AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF INFRINGEMENT OF THIRD
+PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. INDIANA UNIVERSITY MAKES
+NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", "VIRUSES", "TROJAN HORSES",
+"TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE. LICENSEE ASSUMES THE ENTIRE RISK
+AS TO THE PERFORMANCE OF SOFTWARE AND/OR ASSOCIATED MATERIALS, AND TO THE
+PERFORMANCE AND VALIDITY OF INFORMATION GENERATED USING SOFTWARE.
diff --git a/tools/boostbook/xsl/caramel/concept2docbook.xsl b/tools/boostbook/xsl/caramel/concept2docbook.xsl
new file mode 100644
index 0000000000..6554980665
--- /dev/null
+++ b/tools/boostbook/xsl/caramel/concept2docbook.xsl
@@ -0,0 +1,812 @@
+<?xml version="1.0" ?>
+
+<!--
+Copyright (c) 2002-2003 The Trustees of Indiana University.
+ All rights reserved.
+Copyright (c) 2000-2001 University of Notre Dame. All rights reserved.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:strip-space elements="* xsl:*"/>
+
+ <xsl:include href="unparser.xsl"/>
+
+ <xsl:key name="concepts" match="concept" use="@name"/>
+
+ <!-- The layout type to use for concept descriptions. Can be one of:
+ sgi: simulate the SGI STL documentation
+ austern: simulate the documentation in Generic Programming and the STL,
+ by Matthew H. Austern
+ caramel: simulate the formatting from Caramel
+ -->
+ <xsl:param name="boost.concept.layout" select="'austern'"/>
+
+ <xsl:template match="concept">
+ <refentry>
+ <xsl:attribute name="id">
+ <xsl:call-template name="generate.id"/>
+ </xsl:attribute>
+
+ <refmeta>
+ <refentrytitle>Concept <xsl:value-of select="@name"/></refentrytitle>
+ <manvolnum>7</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname><xsl:value-of select="@name"/></refname>
+ <xsl:if test="purpose">
+ <refpurpose>
+ <xsl:apply-templates select="purpose/*|purpose/text()"/>
+ </refpurpose>
+ </xsl:if>
+ </refnamediv>
+
+ <!--
+ <refentryinfo>
+ <xsl:for-each select="copyright | copyright-include | legalnotice">
+ <xsl:choose>
+ <xsl:when test="name(.)='copyright'">
+ <copyright><xsl:copy-of select="./node()"/></copyright>
+ </xsl:when>
+ <xsl:when test="name(.)='legalnotice'">
+ <legalnotice><xsl:copy-of select="./node()"/></legalnotice>
+ </xsl:when>
+ <xsl:when test="name(.)='copyright-include'">
+ <copyright><xsl:copy-of select="document(concat('../concepts/', @file))/copyright/node()"/></copyright>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </refentryinfo>
+-->
+
+ <xsl:if test="description">
+ <xsl:if test="description">
+ <refsect1>
+ <title>Description</title>
+ <xsl:for-each select="description">
+ <xsl:apply-templates/>
+ </xsl:for-each>
+ </refsect1>
+ </xsl:if>
+ </xsl:if>
+
+ <xsl:if test="refines | refines-when-mutable">
+ <refsect1>
+ <title>Refinement of</title>
+ <itemizedlist>
+ <xsl:if test="refines">
+ <xsl:for-each select="refines">
+ <listitem>
+ <para>
+ <xsl:call-template name="concept.link">
+ <xsl:with-param name="name" select="@concept"/>
+ </xsl:call-template>
+ </para>
+ </listitem>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="refines-when-mutable">
+ <xsl:for-each select="refines-when-mutable">
+ <listitem>
+ <para>
+ <xsl:text>When mutable: </xsl:text>
+ <xsl:call-template name="concept.link">
+ <xsl:with-param name="name" select="@concept"/>
+ </xsl:call-template>
+ </para>
+ </listitem>
+ </xsl:for-each>
+ </xsl:if>
+ </itemizedlist>
+ </refsect1>
+ </xsl:if>
+
+ <!-- This part must be run even if there are no associated types to print out, so the hidden type definitions can be found -->
+ <xsl:variable name="definition_list">
+ <xsl:call-template name="make-definition-list">
+ <xsl:with-param name="typedefs" select="define-type | associated-type"/>
+ <xsl:with-param name="definition_list">
+ <xsl:for-each select="param/@name">
+ @(@<xsl:value-of select="."/>=<xsl:value-of select="."/>@)@
+ </xsl:for-each>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <!-- <xsl:message>Definition list: <xsl:value-of select="$definition_list"/></xsl:message> -->
+
+ <xsl:call-template name="print-associated-types">
+ <xsl:with-param name="typedefs" select="associated-type"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="concept.notation">
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ </xsl:call-template>
+
+ <xsl:variable name="notations">
+ <xsl:for-each select="notation">
+ @@(@@<xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="*[1]"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="ignore-cv" select="true()"/>
+ <xsl:with-param name="ignore-references" select="true()"/>
+ </xsl:call-template>@@=@@<xsl:value-of select="normalize-space(@variables)"/>@@)@@
+ </xsl:for-each>
+ </xsl:variable>
+
+ <!-- <xsl:message>Notations: <xsl:value-of select="normalize-space($notations)"/> End notations</xsl:message> -->
+
+ <xsl:if test="definition">
+ <refsect1>
+ <title>Definitions</title>
+ <xsl:for-each select="definition">
+ <p><xsl:apply-templates/></p>
+ </xsl:for-each>
+ </refsect1>
+ </xsl:if>
+
+ <xsl:if test="valid-type-expression | models | models-when-mutable">
+ <refsect1>
+ <title>Type expressions</title>
+ <variablelist>
+ <xsl:for-each select="models">
+ <varlistentry>
+ <term/>
+ <listitem>
+ <para>
+ <xsl:call-template name="unparse-operator-definition">
+ <xsl:with-param name="typeref" select="."/>
+ <xsl:with-param name="operator_nodeset" select="key('concepts', @concept)/models-sentence/node()"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="$notations"/>
+ <xsl:with-param name="ignore-cv" select="false()"/>
+ <xsl:with-param name="self" select="@concept"/>
+ <xsl:with-param name="use-code-block" select="true()"/>
+ </xsl:call-template>
+ </para>
+ </listitem>
+ </varlistentry>
+ </xsl:for-each>
+ <xsl:for-each select="models-when-mutable">
+ <varlistentry>
+ <term>Only when mutable</term>
+ <listitem>
+ <para>
+ <xsl:call-template name="unparse-operator-definition">
+ <xsl:with-param name="typeref" select="."/>
+ <xsl:with-param name="operator_nodeset" select="key('concepts', @concept)/models-sentence/node()"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="$notations"/>
+ <xsl:with-param name="ignore-cv" select="false()"/>
+ <xsl:with-param name="self" select="@concept"/>
+ <xsl:with-param name="use-code-block" select="true()"/>
+ </xsl:call-template>
+ </para>
+ </listitem>
+ </varlistentry>
+ </xsl:for-each>
+ <xsl:for-each select="valid-type-expression">
+ <varlistentry>
+ <term><xsl:value-of select="@name"/></term>
+ <listitem>
+ <para>
+ <type>
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="*[2]"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="normalize-space($notations)"/>
+ </xsl:call-template>
+ </type>
+
+ <xsl:comment/> must be
+ <xsl:for-each select="return-type/*">
+ <xsl:if test="position()!=1 and last()!=2">, </xsl:if>
+ <xsl:if test="position()=last() and last()!=1"> and </xsl:if>
+ <xsl:call-template name="unparse-constraint">
+ <xsl:with-param name="constraint" select="."/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="type-expr-mode" select="true()"/>
+ </xsl:call-template>
+ </xsl:for-each><xsl:comment/>.
+ </para>
+
+ <xsl:if test="description">
+ <xsl:for-each select="description">
+ <xsl:apply-templates/>
+ </xsl:for-each>
+ </xsl:if>
+ </listitem>
+ </varlistentry>
+ </xsl:for-each>
+ </variablelist>
+ </refsect1>
+ </xsl:if>
+
+ <xsl:if test="valid-expression">
+ <refsect1>
+ <title>Valid expressions</title>
+
+ <xsl:variable name="columns">
+ <xsl:if test="valid-expression/return-type">
+ <xsl:text>T</xsl:text>
+ </xsl:if>
+ <xsl:if test="valid-expression/precondition">
+ <xsl:text>P</xsl:text>
+ </xsl:if>
+ <xsl:if test="valid-expression/semantics">
+ <xsl:text>S</xsl:text>
+ </xsl:if>
+ <xsl:if test="valid-expression/postcondition">
+ <xsl:text>O</xsl:text>
+ </xsl:if>
+ </xsl:variable>
+
+ <informaltable>
+ <tgroup>
+ <xsl:attribute name="cols">
+ <xsl:value-of select="string-length($columns) + 2"/>
+ </xsl:attribute>
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Expression</entry>
+ <xsl:if test="contains($columns, 'T')">
+ <entry>Type</entry>
+ </xsl:if>
+ <xsl:if test="contains($columns, 'P')">
+ <entry>Precondition</entry>
+ </xsl:if>
+ <xsl:if test="contains($columns, 'S')">
+ <entry>Semantics</entry>
+ </xsl:if>
+ <xsl:if test="contains($columns, 'O')">
+ <entry>Postcondition</entry>
+ </xsl:if>
+ </row>
+ </thead>
+ <tbody>
+ <xsl:apply-templates select="valid-expression">
+ <xsl:with-param name="definition_list"
+ select="$definition_list"/>
+ <xsl:with-param name="notations"
+ select="normalize-space($notations)"/>
+ <xsl:with-param name="columns" select="$columns"/>
+ </xsl:apply-templates>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <!-- Doug prefers the table
+ <variablelist>
+ <xsl:for-each select="valid-expression">
+ <xsl:variable name="as-cxx-value">
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="*[1]"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="normalize-space($notations)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <varlistentry>
+ <term><xsl:value-of select="@name"/>: <literal><xsl:value-of select="$as-cxx-value"/></literal></term>
+ <listitem><variablelist>
+ <xsl:if test="return-type/*">
+ <varlistentry><term>Return value</term><listitem><para>
+ <xsl:for-each select="return-type/*">
+ <xsl:if test="position()!=1 and last()!=2">, </xsl:if>
+ <xsl:if test="position()=last() and last()!=1"> and </xsl:if>
+ <xsl:call-template name="unparse-constraint">
+ <xsl:with-param name="constraint" select="."/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="capitalize" select="position()=1"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </para></listitem></varlistentry>
+ </xsl:if>
+
+ <xsl:for-each select="precondition">
+ <varlistentry><term>Precondition</term><listitem><para>
+ <xsl:apply-templates/>
+ </para></listitem></varlistentry>
+ </xsl:for-each>
+
+ <xsl:for-each select="semantics">
+ <varlistentry><term>Semantics</term><listitem><para>
+ <xsl:apply-templates/>
+ </para></listitem></varlistentry>
+ </xsl:for-each>
+
+ <xsl:for-each select="postcondition">
+ <varlistentry><term>Postcondition</term><listitem><para>
+ <xsl:apply-templates/>
+ </para></listitem></varlistentry>
+ </xsl:for-each>
+
+ </variablelist></listitem>
+ </varlistentry>
+
+ </xsl:for-each>
+ </variablelist>
+-->
+ </refsect1>
+ </xsl:if>
+
+ <xsl:if test="complexity">
+ <refsect1>
+ <title>Complexity</title>
+ <xsl:for-each select="complexity">
+ <para><xsl:apply-templates/></para>
+ </xsl:for-each>
+ </refsect1>
+ </xsl:if>
+
+ <xsl:if test="invariant">
+ <refsect1>
+ <title>Invariants</title>
+ <variablelist>
+ <xsl:for-each select="invariant">
+ <varlistentry>
+ <term><xsl:value-of select="@name"/></term>
+ <listitem>
+ <para><xsl:apply-templates/></para>
+ </listitem>
+ </varlistentry>
+ </xsl:for-each>
+ </variablelist>
+ </refsect1>
+ </xsl:if>
+
+ <xsl:if test="example-model">
+ <refsect1>
+ <title>Models</title>
+ <itemizedlist>
+ <xsl:for-each select="example-model">
+ <listitem>
+ <simplelist type="inline">
+ <xsl:for-each select="*">
+ <xsl:variable name="example-value">
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="."/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <member><type><xsl:value-of select="$example-value"/></type></member>
+ </xsl:for-each>
+ </simplelist>
+ </listitem>
+ </xsl:for-each>
+ </itemizedlist>
+ </refsect1>
+ </xsl:if>
+
+ <xsl:variable name="see-also-list-0" select="concept-ref | see-also | refines | refines-when-mutable | models-as-first-arg | models | models-when-mutable"/>
+ <xsl:variable name="see-also-list-1" select="$see-also-list-0[string(@name | @concept) != string(../@name)]"/>
+ <xsl:variable name="see-also-list" select="$see-also-list-1[not(string(@name|@concept) = (preceding::*/@name | preceding::*/@concept | ancestor::*/@name | ancestor::*/@concept))]"/>
+ <xsl:if test="$see-also-list">
+ <refsect1>
+ <title>See also</title>
+ <itemizedlist>
+ <xsl:for-each select="$see-also-list">
+ <xsl:sort select="string(@name|@concept)" data-type="text"/>
+ <listitem>
+ <para>
+ <xsl:call-template name="concept.link">
+ <xsl:with-param name="name" select="@name|@concept"/>
+ </xsl:call-template>
+ </para>
+ </listitem>
+ </xsl:for-each>
+ </itemizedlist>
+ </refsect1>
+ </xsl:if>
+
+ </refentry>
+ </xsl:template>
+
+ <xsl:template name="unparse-constraint">
+ <xsl:param name="constraint"/>
+ <xsl:param name="definition_list"/>
+ <xsl:param name="type-expr-mode" select="false()"/>
+ <xsl:param name="capitalize" select="true()"/>
+
+ <xsl:choose>
+
+ <xsl:when test="name($constraint)='require-same-type'">
+ <xsl:if test="$type-expr-mode">identical to </xsl:if>
+ <type>
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="$constraint/*[1]"/>
+ <xsl:with-param name="definition_list" select="definition_list"/>
+ </xsl:call-template>
+ </type>
+ </xsl:when>
+
+ <xsl:when test="name($constraint)='convertible-to'">
+ <xsl:choose>
+ <xsl:when test="$type-expr-mode">convertible to </xsl:when>
+ <xsl:when test="not($type-expr-mode) and $capitalize">Convertible to </xsl:when>
+ <xsl:when test="not($type-expr-mode) and not($capitalize)">convertible to </xsl:when>
+ </xsl:choose>
+ <type>
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="$constraint/*[1]"/>
+ <xsl:with-param name="definition_list" select="definition_list"/>
+ </xsl:call-template>
+ </type>
+ </xsl:when>
+
+ <xsl:when test="name($constraint)='derived-from'">
+ <xsl:choose>
+ <xsl:when test="$type-expr-mode">derived from </xsl:when>
+ <xsl:when test="not($type-expr-mode) and $capitalize">Derived from </xsl:when>
+ <xsl:when test="not($type-expr-mode) and not($capitalize)">derived from </xsl:when>
+ </xsl:choose>
+ <type>
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="$constraint/*[1]"/>
+ <xsl:with-param name="definition_list" select="definition_list"/>
+ </xsl:call-template>
+ </type>
+ </xsl:when>
+
+ <xsl:when test="name($constraint)='assignable-to'">
+ <xsl:choose>
+ <xsl:when test="$type-expr-mode">assignable to </xsl:when>
+ <xsl:when test="not($type-expr-mode) and $capitalize">Assignable to </xsl:when>
+ <xsl:when test="not($type-expr-mode) and not($capitalize)">assignable to </xsl:when>
+ </xsl:choose>
+ <type>
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="$constraint/*[1]"/>
+ <xsl:with-param name="definition_list" select="definition_list"/>
+ </xsl:call-template>
+ </type>
+ </xsl:when>
+
+ <xsl:when test="name($constraint)='models-as-first-arg'">
+ <xsl:choose>
+ <xsl:when test="$type-expr-mode"> a model </xsl:when>
+ <xsl:when test="not($type-expr-mode) and $capitalize"> Models </xsl:when>
+ <xsl:when test="not($type-expr-mode) and not($capitalize)"> models </xsl:when>
+ </xsl:choose>
+ <xsl:if test="$constraint/*"><xsl:comment/>
+ (along with <xsl:for-each select="$constraint/*"><type>
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="."/>
+ <xsl:with-param name="definition_list" select="definition_list"/>
+ </xsl:call-template>
+ </type>
+ <xsl:choose>
+ <xsl:when test="position()=last()"/>
+ <xsl:when test="position()=last()-1 and last()=2"> and </xsl:when>
+ <xsl:when test="position()=last()-1 and last()!=2">, and </xsl:when>
+ <xsl:otherwise>, </xsl:otherwise>
+ </xsl:choose><xsl:comment/>
+ </xsl:for-each><xsl:comment/>) <xsl:comment/>
+ </xsl:if><xsl:comment/>
+ <xsl:if test="$type-expr-mode"> of </xsl:if>
+ <xsl:call-template name="concept.link">
+ <xsl:with-param name="name" select="$constraint/@concept"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="make-definition-list">
+ <xsl:param name="typedefs"/>
+ <xsl:param name="definition_list"/>
+
+ <xsl:choose>
+ <xsl:when test="$typedefs">
+ <xsl:variable name="type_definition">
+ <xsl:if test="name($typedefs[1]/*[1])!='description'">
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="$typedefs[1]/*[1]"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:variable name="new_type_definition">
+ <xsl:choose>
+ <xsl:when test="name($typedefs[1])='associated-type'">
+ <xsl:value-of select="$typedefs[1]/@name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$type_definition"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:call-template name="make-definition-list">
+ <xsl:with-param name="typedefs" select="$typedefs[position()!=1]"/>
+ <xsl:with-param name="definition_list" select="concat($definition_list, ' @(@', $typedefs[1]/@name, '=', $new_type_definition, '@)@')"/>
+ </xsl:call-template>
+
+ </xsl:when>
+
+ <xsl:otherwise> <!-- End of expression list, emit the results that have accumulated -->
+ <xsl:value-of select="$definition_list"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="print-associated-types">
+ <xsl:param name="typedefs"/>
+ <xsl:param name="definition_list"/>
+
+ <xsl:if test="$typedefs">
+ <refsect1>
+ <title>Associated types</title>
+
+ <xsl:choose>
+ <xsl:when test="$boost.concept.layout='sgi'">
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+ <xsl:apply-templates select="associated-type" mode="sgi">
+ <xsl:with-param name="definition_list"
+ select="$definition_list"/>
+ </xsl:apply-templates>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </xsl:when>
+ <xsl:when test="$boost.concept.layout='austern'">
+ <itemizedlist>
+ <xsl:apply-templates select="associated-type" mode="austern">
+ <xsl:with-param name="definition_list"
+ select="$definition_list"/>
+ </xsl:apply-templates>
+ </itemizedlist>
+ </xsl:when>
+ <xsl:when test="$boost.concept.layout='caramel'">
+ <segmentedlist>
+ <segtitle>Name</segtitle>
+ <segtitle>Code</segtitle>
+ <segtitle>Description</segtitle>
+ <xsl:for-each select="$typedefs">
+ <xsl:variable name="type_definition">
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="*[1]"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <seglistitem>
+ <seg><xsl:value-of select="@name"/></seg>
+ <seg><xsl:value-of select="$type_definition"/></seg>
+ <seg>
+ <xsl:for-each select="description">
+ <xsl:call-template name="description"/>
+ </xsl:for-each>
+ </seg>
+ </seglistitem>
+ </xsl:for-each>
+ </segmentedlist>
+ </xsl:when>
+ </xsl:choose>
+ </refsect1>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="comma-list">
+ <xsl:param name="list"/>
+
+ <xsl:if test="$list!=''">
+ <term><varname>
+ <xsl:if test="substring-before($list,' ')=''"><xsl:value-of select="$list"/></xsl:if>
+ <xsl:value-of select="substring-before($list,' ')"/>
+ </varname></term>
+ <xsl:call-template name="comma-list">
+ <xsl:with-param name="list" select="substring-after($list,' ')"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="associated-type" mode="sgi">
+ <row>
+ <entry><simpara><xsl:value-of select="@name"/></simpara></entry>
+
+ <entry>
+ <para>
+ <xsl:for-each select="description">
+ <xsl:apply-templates/>
+ </xsl:for-each>
+ </para>
+ </entry>
+ </row>
+ </xsl:template>
+
+ <xsl:template match="associated-type" mode="austern">
+ <xsl:param name="definition_list" select="''"/>
+
+ <listitem>
+ <para>
+ <emphasis role="bold"><xsl:value-of select="@name"/></emphasis>
+
+ <xsl:call-template name="preformatted">
+ <xsl:with-param name="text">
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="*[1]"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+
+ <xsl:for-each select="description">
+ <xsl:apply-templates/>
+ </xsl:for-each>
+ </para>
+ </listitem>
+ </xsl:template>
+
+ <xsl:template match="valid-expression">
+ <xsl:param name="definition_list"/>
+ <xsl:param name="notations"/>
+ <xsl:param name="columns"/>
+
+ <row>
+ <entry><simpara><xsl:value-of select="@name"/></simpara></entry>
+
+ <entry>
+ <simpara>
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="*[1]"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="$notations"/>
+ </xsl:call-template>
+ </simpara>
+ </entry>
+
+ <xsl:if test="contains($columns, 'T')">
+ <entry>
+ <simpara>
+ <xsl:for-each select="return-type/*">
+ <xsl:if test="position()!=1 and last()!=2">, </xsl:if>
+ <xsl:if test="position()=last() and last()!=1"> and </xsl:if>
+ <xsl:call-template name="unparse-constraint">
+ <xsl:with-param name="constraint" select="."/>
+ <xsl:with-param name="definition_list"
+ select="$definition_list"/>
+ <xsl:with-param name="capitalize" select="position()=1"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </simpara>
+ </entry>
+ </xsl:if>
+
+ <xsl:if test="contains($columns, 'P')">
+ <entry>
+ <xsl:for-each select="precondition">
+ <simpara><xsl:apply-templates/></simpara>
+ </xsl:for-each>
+ </entry>
+ </xsl:if>
+
+ <xsl:if test="contains($columns, 'S')">
+ <entry>
+ <xsl:for-each select="semantics">
+ <simpara><xsl:apply-templates/></simpara>
+ </xsl:for-each>
+ </entry>
+ </xsl:if>
+
+ <xsl:if test="contains($columns, 'O')">
+ <entry>
+ <xsl:for-each select="postcondition">
+ <simpara><xsl:apply-templates/></simpara>
+ </xsl:for-each>
+ </entry>
+ </xsl:if>
+ </row>
+ </xsl:template>
+
+ <xsl:template name="concept.notation">
+ <xsl:param name="definition_list"/>
+
+ <refsect1>
+ <title>Notation</title>
+ <variablelist>
+ <xsl:for-each select="param">
+ <varlistentry>
+ <term><xsl:value-of select="@name"/></term>
+ <listitem>
+ <simpara>
+ <xsl:text>A type playing the role of </xsl:text>
+ <xsl:value-of select="@role"/>
+ <xsl:text> in the </xsl:text>
+ <xsl:call-template name="concept.link">
+ <xsl:with-param name="name" select="../@name"/>
+ </xsl:call-template>
+ <xsl:text> concept.</xsl:text>
+ </simpara>
+ </listitem>
+ </varlistentry>
+ </xsl:for-each>
+ <xsl:for-each select="notation">
+ <xsl:variable name="notation_name">
+ <xsl:call-template name="comma-list">
+ <xsl:with-param name="list"
+ select="normalize-space(@variables)"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <varlistentry>
+ <xsl:copy-of select="$notation_name"/>
+ <listitem>
+ <simpara>
+ <xsl:variable name="output-plural" select="substring-before(normalize-space(@variables),' ')!=''"/>
+ <xsl:if test="name(*[1])='sample-value'">Object<xsl:if test="$output-plural">s</xsl:if> of type </xsl:if>
+ <xsl:variable name="typeref-to-print" select="*[name()!='sample-value'] | sample-value/*[name()!='sample-value']"/>
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="$typeref-to-print"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="ignore-cv" select="true()"/>
+ <xsl:with-param name="ignore-references" select="true()"/>
+ </xsl:call-template>
+ </simpara>
+ </listitem>
+ </varlistentry>
+ </xsl:for-each>
+ </variablelist>
+ </refsect1>
+ </xsl:template>
+
+ <xsl:template name="concept.link">
+ <xsl:param name="name" select="text()"/>
+ <xsl:param name="warn" select="true()"/>
+ <xsl:param name="text" select="$name"/>
+ <xsl:variable name="node" select="key('concepts', $name)"/>
+
+ <xsl:choose>
+ <xsl:when test="count($node)=0">
+ <xsl:if test="$warn">
+ <xsl:message>
+ <xsl:text>warning: cannot find concept '</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>'</xsl:text>
+ </xsl:message>
+ </xsl:if>
+ <xsl:value-of select="$text"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="remove-whitespace">
+ <xsl:param name="text" select="text()"/>
+
+ <xsl:variable name="normalized" select="normalize-space($text)"/>
+ <xsl:choose>
+ <xsl:when test="contains($normalized, ' ')">
+ <xsl:value-of select="substring-before($normalized, ' ')"/>
+ <xsl:call-template name="remove-whitespace">
+ <xsl:with-param name="text"
+ select="substring-after($normalized, ' ')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$normalized"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="concept" mode="generate.id">
+ <xsl:call-template name="remove-whitespace">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/caramel/cpp-operators.xml b/tools/boostbook/xsl/caramel/cpp-operators.xml
new file mode 100644
index 0000000000..68626acbb5
--- /dev/null
+++ b/tools/boostbook/xsl/caramel/cpp-operators.xml
@@ -0,0 +1,288 @@
+<?xml version="1.0" ?>
+
+<!--
+Copyright (c) 2002-2003 The Trustees of Indiana University.
+ All rights reserved.
+Copyright (c) 2000-2001 University of Notre Dame. All rights reserved.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt) -->
+
+<operator-list>
+ <!-- This list is from Pohl's book, and needs to be checked for accuracy -->
+
+ <op name="postincrement">
+ <apply priority="100"><arg num="1"/>++</apply> <!-- No assoc - always use parentheses -->
+ <impl position="method">operator++(int)</impl>
+ </op>
+
+ <op name="postdecrement">
+ <apply priority="100"><arg num="1"/>--</apply>
+ <impl position="method">operator--(int)</impl>
+ </op>
+
+ <op name="apply-function">
+ <apply priority="100"><name/>(<arg-list start="1" priority="30"/>)</apply>
+ <impl position="freestanding"><name/>(<arg-list/>)</impl>
+ </op>
+
+ <op name="apply-method">
+ <apply priority="100" assoc="1"><arg num="1"/>.<name/>(<arg-list start="2" priority="30"/>)</apply>
+ <impl position="method"><name/>(<arg-list/>)</impl>
+ </op>
+
+ <op name="pointer-apply-method">
+ <apply priority="100" assoc="1"><arg num="1"/>-&gt;<name/>(<arg-list start="2" priority="30"/>)</apply>
+ <impl>Error</impl>
+ </op>
+
+ <op name="apply-funcobj">
+ <apply priority="100" assoc="1"><arg num="1"/>(<arg-list start="2" priority="30"/>)</apply>
+ <impl position="method">operator()(<arg-list/>)</impl>
+ </op>
+
+ <op name="construct">
+ <apply priority="100"><arg num="1"/>(<arg-list start="2" priority="30"/>)</apply>
+ <impl position="method"><self/>(<arg-list/>)</impl>
+ </op>
+
+ <op name="subscript">
+ <apply priority="100" assoc="1"><arg num="1"/>[<arg num="2" priority="0"/>]</apply>
+ <impl position="method">operator[](<arg-list/>)</impl>
+ </op>
+
+ <op name="class-member">
+ <apply priority="100" assoc="1"><arg num="1"/>.<name/></apply>
+ <impl>Error</impl>
+ </op>
+
+ <op name="pointer-member">
+ <!-- Note: non-testable constraint -->
+ <apply priority="100"><arg num="1" assoc="1"/>-&gt;{member-name} (return type is pointer-to-object type)</apply>
+ <impl>operator-&gt;(<arg-list/>)</impl>
+ </op>
+
+ <op name="preincrement">
+ <apply priority="95">++<arg num="1"/></apply>
+ <impl position="method">operator++(<arg-list/>)</impl>
+ </op>
+
+ <op name="predecrement">
+ <apply priority="95">--<arg num="1"/></apply>
+ <impl position="method">operator--(<arg-list/>)</impl>
+ </op>
+
+ <op name="logical-not">
+ <apply priority="95" assoc="1">!<arg num="1"/></apply>
+ <impl position="method">operator!(<arg-list/>)</impl>
+ </op>
+
+ <op name="bitwise-not">
+ <apply priority="95" assoc="1">~<arg num="1"/></apply>
+ <impl position="method">operator~(<arg-list/>)</impl>
+ </op>
+
+ <op name="address-of">
+ <apply priority="95">&amp;<arg num="1"/></apply>
+ <impl position="method">operator&amp;(<arg-list/>)</impl>
+ </op>
+
+ <op name="dereference">
+ <apply priority="95" assoc="1">*<arg num="1"/></apply>
+ <impl position="method">operator*(<arg-list/>)</impl>
+ </op>
+
+ <op name="unary-plus">
+ <apply priority="95">+<arg num="1"/></apply>
+ <impl position="method">operator+(<arg-list/>)</impl>
+ </op>
+
+ <op name="unary-minus">
+ <apply priority="95">-<arg num="1"/></apply>
+ <impl position="method">operator-(<arg-list/>)</impl>
+ </op>
+
+ <op name="class-member-ptr">
+ <apply priority="90" assoc="1"><arg num="1"/>.*<arg num="2"/></apply>
+ <impl>Error</impl>
+ </op>
+
+ <op name="pointer-member-ptr">
+ <apply priority="90" assoc="1"><arg num="1"/>-&gt;*<arg num="2"/></apply>
+ <impl position="method">operator-&gt;*(<arg-list/>)</impl>
+ </op>
+
+ <op name="multiply">
+ <apply priority="90" assoc="1"><arg num="1"/> * <arg num="2"/></apply>
+ <impl position="freestanding">operator * (<arg-list/>)</impl>
+ </op>
+
+ <op name="divide">
+ <apply priority="90" assoc="1"><arg num="1"/> / <arg num="2"/></apply>
+ <impl position="freestanding">operator / (<arg-list/>)</impl>
+ </op>
+
+ <op name="modulus">
+ <apply priority="90" assoc="1"><arg num="1"/> % <arg num="2"/></apply>
+ <impl position="freestanding">operator % (<arg-list/>)</impl>
+ </op>
+
+ <op name="add">
+ <apply priority="85" assoc="1"><arg num="1"/> + <arg num="2"/></apply>
+ <impl position="freestanding">operator + (<arg-list/>)</impl>
+ </op>
+
+ <op name="subtract">
+ <apply priority="85" assoc="1"><arg num="1"/> - <arg num="2"/></apply>
+ <impl position="freestanding">operator - (<arg-list/>)</impl>
+ </op>
+
+ <op name="shift-left">
+ <apply priority="80" assoc="1"><arg num="1"/> &lt;&lt; <arg num="2"/></apply>
+ <impl position="freestanding">operator &lt;&lt; (<arg-list/>)</impl>
+ </op>
+
+ <op name="shift-right">
+ <apply priority="80" assoc="1"><arg num="1"/> &gt;&gt; <arg num="2"/></apply>
+ <impl position="freestanding">operator &gt;&gt; (<arg-list/>)</impl>
+ </op>
+
+ <op name="less-than">
+ <apply priority="75"><arg num="1"/> &lt; <arg num="2"/></apply>
+ <impl position="freestanding">operator &lt; (<arg-list/>)</impl>
+ </op>
+
+ <op name="greater-than">
+ <apply priority="75"><arg num="1"/> &gt; <arg num="2"/></apply>
+ <impl position="freestanding">operator &gt; (<arg-list/>)</impl>
+ </op>
+
+ <op name="less-than-or-equal">
+ <apply priority="75"><arg num="1"/> &lt;= <arg num="2"/></apply>
+ <impl position="freestanding">operator &lt;= (<arg-list/>)</impl>
+ </op>
+
+ <op name="greater-than-or-equal">
+ <apply priority="75"><arg num="1"/> &gt;= <arg num="2"/></apply>
+ <impl position="freestanding">operator &gt;= (<arg-list/>)</impl>
+ </op>
+
+ <op name="equal-to">
+ <apply priority="70"><arg num="1"/> == <arg num="2"/></apply>
+ <impl position="freestanding">operator == (<arg-list/>)</impl>
+ </op>
+
+ <op name="not-equal-to">
+ <apply priority="70"><arg num="1"/> != <arg num="2"/></apply>
+ <impl position="freestanding">operator != (<arg-list/>)</impl>
+ </op>
+
+ <op name="bitwise-and">
+ <apply priority="65" assoc="1"><arg num="1"/> &amp; <arg num="2"/></apply>
+ <impl position="freestanding">operator &amp; (<arg-list/>)</impl>
+ </op>
+
+ <op name="bitwise-or">
+ <apply priority="60" assoc="1"><arg num="1"/> | <arg num="2"/></apply>
+ <impl position="freestanding">operator | (<arg-list/>)</impl>
+ </op>
+
+ <op name="bitwise-xor">
+ <apply priority="55" assoc="1"><arg num="1"/> ^ <arg num="2"/></apply>
+ <impl position="freestanding">operator ^ (<arg-list/>)</impl>
+ </op>
+
+ <op name="logical-and">
+ <apply priority="50" assoc="1"><arg num="1"/> &amp;&amp; <arg num="2"/></apply>
+ <impl position="freestanding">operator &amp;&amp; (<arg-list/>)</impl>
+ </op>
+
+ <op name="logical-or">
+ <apply priority="45" assoc="1"><arg num="1"/> || <arg num="2"/></apply>
+ <impl position="freestanding">operator || (<arg-list/>)</impl>
+ </op>
+
+ <op name="conditional">
+ <apply priority="40" assoc="3"><arg num="1"/> ? <arg num="2"/> : <arg num="3"/></apply>
+ <impl>Error</impl>
+ </op>
+
+ <op name="assign">
+ <apply priority="35" assoc="2"><arg num="1"/> = <arg num="2"/></apply>
+ <impl position="method">operator = (<arg-list/>)</impl>
+ </op>
+
+ <op name="add-assign">
+ <apply priority="35" assoc="2"><arg num="1"/> += <arg num="2"/></apply>
+ <impl position="method">operator += (<arg-list/>)</impl>
+ </op>
+
+ <op name="subtract-assign">
+ <apply priority="35" assoc="2"><arg num="1"/> -= <arg num="2"/></apply>
+ <impl position="method">operator -= (<arg-list/>)</impl>
+ </op>
+
+ <op name="multiply-assign">
+ <apply priority="35" assoc="2"><arg num="1"/> *= <arg num="2"/></apply>
+ <impl position="method">operator *= (<arg-list/>)</impl>
+ </op>
+
+ <op name="divide-assign">
+ <apply priority="35" assoc="2"><arg num="1"/> /= <arg num="2"/></apply>
+ <impl position="method">operator /= (<arg-list/>)</impl>
+ </op>
+
+ <op name="modulus-assign">
+ <apply priority="35" assoc="2"><arg num="1"/> %= <arg num="2"/></apply>
+ <impl position="method">operator %= (<arg-list/>)</impl>
+ </op>
+
+ <op name="shift-left-assign">
+ <apply priority="35" assoc="2"><arg num="1"/> &lt;&lt;= <arg num="2"/></apply>
+ <impl position="method">operator &lt;&lt;= (<arg-list/>)</impl>
+ </op>
+
+ <op name="shift-right-assign">
+ <apply priority="35" assoc="2"><arg num="1"/> &gt;&gt;= <arg num="2"/></apply>
+ <impl position="method">operator &gt;&gt;= (<arg-list/>)</impl>
+ </op>
+
+ <op name="bitwise-and-assign">
+ <apply priority="35" assoc="2"><arg num="1"/> &amp;= <arg num="2"/></apply>
+ <impl position="method">operator &amp;= (<arg-list/>)</impl>
+ </op>
+
+ <op name="bitwise-or-assign">
+ <apply priority="35" assoc="2"><arg num="1"/> |= <arg num="2"/></apply>
+ <impl position="method">operator |= (<arg-list/>)</impl>
+ </op>
+
+ <op name="bitwise-xor-assign">
+ <apply priority="35" assoc="2"><arg num="1"/> ^= <arg num="2"/></apply>
+ <impl position="method">operator ^= (<arg-list/>)</impl>
+ </op>
+
+ <op name="comma">
+ <apply priority="20"><arg num="1"/>, <arg num="2"/></apply>
+ <impl position="freestanding">operator , (<arg-list/>)</impl>
+ </op>
+
+ <op name="function-pointer">
+ <apply><arg num="1"/> (*)(<arg-list start="2" priority="30"/>)</apply>
+ <impl>Error</impl>
+ </op>
+
+ <op name="functorize-operator">
+ <!-- Note: non-testable constraint -->
+ <apply>functorization of operator <name/> on arguments {<arg-list start="1"/>}</apply>
+ <impl>Error</impl>
+ </op>
+
+ <op name="functorize-function">
+ <!-- Note: non-testable constraint -->
+ <apply>functorization of function <name/> on arguments {<arg-list start="1"/>}</apply>
+ <impl>Error</impl>
+ </op>
+
+</operator-list>
diff --git a/tools/boostbook/xsl/caramel/unparser.xsl b/tools/boostbook/xsl/caramel/unparser.xsl
new file mode 100644
index 0000000000..63db55fff4
--- /dev/null
+++ b/tools/boostbook/xsl/caramel/unparser.xsl
@@ -0,0 +1,497 @@
+<?xml version="1.0" ?>
+
+<!--
+Copyright (c) 2002-2003 The Trustees of Indiana University.
+ All rights reserved.
+Copyright (c) 2000-2001 University of Notre Dame. All rights reserved.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt) -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:template name="unparse-cpp">
+ <xsl:param name="typeref"/>
+ <xsl:param name="definition_list"/>
+ <xsl:param name="priority">0</xsl:param>
+ <xsl:param name="ignore-cv" select="false()"/>
+ <xsl:param name="ignore-references" select="false()"/>
+ <xsl:param name="notations"/>
+ <xsl:param name="ignore-notation" select="false()"/>
+ <xsl:param name="print-updated-notation" select="false()"/>
+ <xsl:param name="use-typename" select="false()"/>
+ <xsl:param name="const-if-not-mutable-value" select="'const-if-not-mutable'"/>
+
+ <xsl:variable name="notation_check">
+ <xsl:if test="not($ignore-notation)"> <!-- Prevent infinite recursion -->
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="$typeref"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="priority">0</xsl:with-param>
+ <xsl:with-param name="ignore-cv" select="true()"/>
+ <xsl:with-param name="ignore-references" select="true()"/>
+ <xsl:with-param name="notations" select="$notations"/>
+ <xsl:with-param name="ignore-notation" select="true()"/>
+ <xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+
+ <!--
+ <xsl:message>Notation check: <xsl:value-of select="$notation_check"/>
+ Notations: <xsl:value-of select="$notations"/>
+ </xsl:message> -->
+
+ <xsl:variable name="this_op_priority" select="document('cpp-operators.xml')/operator-list/op[@name=name($typeref)]/apply/@priority"/>
+
+ <xsl:variable name="result">
+
+ <xsl:variable name="subcall_priority">
+ <xsl:choose>
+ <xsl:when test="true() or ($this_op_priority &gt; $priority)">
+ <xsl:value-of select="$this_op_priority"/>
+ </xsl:when>
+ <!-- <xsl:otherwise>0</xsl:otherwise> -->
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:if test="$this_op_priority &lt;= $priority">(</xsl:if>
+
+ <xsl:choose>
+
+ <xsl:when test="name($typeref)='sample-value'"
+ >boost::sample_value &lt; <xsl:call-template name="unparse-cpp"><xsl:with-param name="typeref" select="$typeref/*[1]"/><xsl:with-param name="definition_list" select="$definition_list"/><xsl:with-param name="ignore-cv" select="$ignore-cv"/><xsl:with-param name="notations" select="$notations"/><xsl:with-param name="ignore-references" select="$ignore-references"/><xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/></xsl:call-template> &gt;()</xsl:when>
+
+ <xsl:when test="name($typeref)='reference-to'"
+ ><xsl:call-template name="unparse-cpp"><xsl:with-param name="typeref" select="$typeref/*[1]"/><xsl:with-param name="definition_list" select="$definition_list"/><xsl:with-param name="priority" select="$subcall_priority"/><xsl:with-param name="ignore-cv" select="$ignore-cv"/><xsl:with-param name="notations" select="$notations"/><xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/></xsl:call-template><xsl:if test="not($ignore-references)"> &amp;</xsl:if></xsl:when>
+
+ <xsl:when test="name($typeref)='pointer-to'"
+ ><xsl:call-template name="unparse-cpp"><xsl:with-param name="typeref" select="$typeref/*[1]"/><xsl:with-param name="definition_list" select="$definition_list"/><xsl:with-param name="priority" select="$subcall_priority"/><xsl:with-param name="ignore-cv" select="$ignore-cv"/><xsl:with-param name="notations" select="$notations"/></xsl:call-template> *</xsl:when>
+
+ <xsl:when test="name($typeref)='const'"
+ ><xsl:if test="not($ignore-cv)">const </xsl:if><xsl:call-template name="unparse-cpp"><xsl:with-param name="typeref" select="$typeref/*[1]"/><xsl:with-param name="definition_list" select="$definition_list"/><xsl:with-param name="priority" select="$subcall_priority"/><xsl:with-param name="ignore-cv" select="$ignore-cv"/><xsl:with-param name="notations" select="$notations"/><xsl:with-param name="ignore-references" select="$ignore-references"/><xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/></xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="name($typeref)='const-if-not-mutable'"
+ ><xsl:if test="not($ignore-cv)"><xsl:value-of select="$const-if-not-mutable-value"/><xsl:if test="$const-if-not-mutable-value"><xsl:text> </xsl:text></xsl:if></xsl:if><xsl:call-template name="unparse-cpp"><xsl:with-param name="typeref" select="$typeref/*[1]"/><xsl:with-param name="definition_list" select="$definition_list"/><xsl:with-param name="priority" select="$subcall_priority"/><xsl:with-param name="ignore-cv" select="$ignore-cv"/><xsl:with-param name="notations" select="$notations"/><xsl:with-param name="ignore-references" select="$ignore-references"/><xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/></xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="name($typeref)='volatile'"
+ ><xsl:if test="not($ignore-cv)">volatile </xsl:if><xsl:call-template name="unparse-cpp"><xsl:with-param name="typeref" select="$typeref/*[1]"/><xsl:with-param name="definition_list" select="$definition_list"/><xsl:with-param name="priority" select="$subcall_priority"/><xsl:with-param name="ignore-cv" select="$ignore-cv"/><xsl:with-param name="notations" select="$notations"/><xsl:with-param name="ignore-references" select="$ignore-references"/><xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/></xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="name($typeref)='apply-template'">
+ <xsl:value-of select="$typeref/@name"/>&lt;<xsl:for-each select="$typeref/*">
+ <xsl:if test="position()!=1">, </xsl:if><xsl:comment/>
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="."/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="ignore-cv" select="$ignore-cv"/>
+ <xsl:with-param name="notations" select="$notations"/>
+ <xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/>
+ </xsl:call-template></xsl:for-each
+ ><xsl:comment/>&gt;</xsl:when>
+
+ <xsl:when test="name($typeref)='get-member-type'">
+ <xsl:call-template name="unparse-cpp"><xsl:with-param name="typeref" select="$typeref/*[1]"/><xsl:with-param name="definition_list" select="$definition_list"/><xsl:with-param name="ignore-cv" select="$ignore-cv"/><xsl:with-param name="notations" select="$notations"/><xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/></xsl:call-template>::<xsl:value-of select="$typeref/@name"/>
+ </xsl:when>
+
+ <xsl:when test="name($typeref)='type'">
+ <xsl:variable name="typeref_value" select="normalize-space(substring-before(substring-after($definition_list,concat('@(@',$typeref/@name,'=')),'@)@'))"/>
+ <xsl:choose>
+ <xsl:when test="$typeref_value=''">
+ <xsl:value-of select="$typeref/@name"/><xsl:comment/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$typeref_value"/><xsl:comment/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+
+ <xsl:when test="name($typeref)='documentation'"/>
+
+ <xsl:when test="document('cpp-operators.xml')/operator-list/op[@name=name($typeref)]">
+ <xsl:variable name="op_file" select="document('cpp-operators.xml')/operator-list"/>
+ <xsl:variable name="op_info" select="$op_file/op[@name=name($typeref)]/apply/."/>
+
+ <xsl:call-template name="unparse-operator-definition">
+ <xsl:with-param name="typeref" select="$typeref"/>
+ <xsl:with-param name="operator_nodeset" select="$op_info/child::node()"/>
+ <xsl:with-param name="my_priority" select="$subcall_priority"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="$notations"/>
+ <xsl:with-param name="ignore-cv" select="$ignore-cv"/>
+ <xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/>
+ <xsl:with-param name="print-updated-notation" select="$print-updated-notation"/>
+ </xsl:call-template>
+
+ </xsl:when>
+
+ <xsl:otherwise>
+ (Unrecognized tag <xsl:value-of select="name($typeref)"/>)
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <!-- Close parenthesis code moved below -->
+
+ </xsl:variable>
+
+ <!-- <xsl:message>ignore-notation = <xsl:value-of select="$ignore-notation"/></xsl:message> -->
+ <!-- <xsl:message>notation_check = <xsl:value-of select="$notation_check"/></xsl:message> -->
+ <!-- <xsl:message>notations = <xsl:value-of select="$notations"/></xsl:message> -->
+ <!-- <xsl:message>result = <xsl:value-of select="$result"/></xsl:message> -->
+
+ <xsl:variable name="used_notation" select="boolean($notation_check) and boolean(substring-before(substring-after($notations, concat('@@(@@', $notation_check, '@@=@@')),'@@)@@'))"/>
+
+ <xsl:variable name="notations2">
+ <!-- Possibly replace from result of unparse-operator-definition -->
+ <xsl:choose>
+ <xsl:when test="contains($result, ' *@@@* ')">
+ <xsl:value-of select="substring-after($result, ' *@@@* ')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$notations"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="result2">
+ <!-- Possibly replace from result of unparse-operator-definition -->
+ <xsl:choose>
+ <xsl:when test="contains($result, ' *@@@* ')">
+ <xsl:value-of select="substring-before($result, ' *@@@* ')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$result"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- Close parenthesis code -->
+ <xsl:if test="$this_op_priority &lt;= $priority">)</xsl:if>
+ </xsl:variable>
+
+ <xsl:variable name="notation_varlist">
+ <xsl:choose>
+ <xsl:when test="$used_notation">
+ <xsl:value-of select="substring-before(substring-after($notations2, concat('@@(@@', $notation_check, '@@=@@')), '@@)@@')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$result2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="new_varlist" select="substring-after(normalize-space($notation_varlist), ' ')"/>
+
+ <xsl:variable name="notation_var">
+ <xsl:choose>
+ <xsl:when test="not($used_notation)">
+ <xsl:value-of select="$result2"/>
+ </xsl:when>
+ <xsl:when test="$new_varlist=''">
+ <xsl:value-of select="$notation_varlist"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before(normalize-space($notation_varlist), ' ')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Generate new notation list -->
+ <xsl:variable name="new_notations">
+ <xsl:choose>
+ <xsl:when test="$used_notation">
+ <xsl:value-of select="normalize-space(concat('@@(@@', $notation_check, '@@=@@', $new_varlist, '@@)@@', $notations2))"/>
+ <!-- Duplicate entries always use first occurrance, so I can optimize this -->
+ </xsl:when>
+ <xsl:otherwise><xsl:value-of select="$notations2"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- <xsl:message>final_result = <xsl:value-of select="normalize-space($final_result)"/></xsl:message> -->
+
+ <xsl:call-template name="add-typename"><xsl:with-param name="really-do-it" select="$use-typename"/><xsl:with-param name="type"><xsl:value-of select="normalize-space($notation_var)"/></xsl:with-param></xsl:call-template><xsl:if test="$print-updated-notation"> *@@@* <xsl:value-of select="$new_notations"/></xsl:if>
+
+ </xsl:template>
+
+ <xsl:template name="unparse-operator-definition">
+ <xsl:param name="typeref"/>
+ <xsl:param name="operator_nodeset"/>
+ <xsl:param name="current_start">1</xsl:param>
+ <xsl:param name="my_priority"/>
+ <xsl:param name="definition_list"/>
+ <xsl:param name="notations"/>
+ <xsl:param name="ignore-cv"/>
+ <xsl:param name="self"/>
+ <xsl:param name="use-code-block" select="false()"/>
+ <xsl:param name="print-updated-notation" select="false()"/>
+ <xsl:param name="const-if-not-mutable-value"/>
+
+ <xsl:variable name="op_current" select="$operator_nodeset[position()=1]"/>
+ <xsl:variable name="op_rest" select="$operator_nodeset[position()!=1]"/>
+
+ <xsl:choose>
+
+ <xsl:when test="count($operator_nodeset)=0">
+ <xsl:if test="$print-updated-notation"> *@@@* <xsl:value-of select="$notations"/></xsl:if>
+ </xsl:when>
+
+ <xsl:when test="$op_current != $op_current/../*"> <!-- If I am not an element -->
+ <xsl:value-of select="$op_current"/>
+ <xsl:call-template name="unparse-operator-definition">
+ <xsl:with-param name="typeref" select="$typeref"/>
+ <xsl:with-param name="operator_nodeset" select="$op_rest"/>
+ <xsl:with-param name="my_priority" select="$my_priority"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="$notations"/>
+ <xsl:with-param name="self" select="$self"/>
+ <xsl:with-param name="use-code-block" select="$use-code-block"/>
+ <xsl:with-param name="print-updated-notation" select="$print-updated-notation"/>
+ <xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="name($op_current)='name'">
+ <xsl:value-of select="$typeref/@name"/>
+ <xsl:call-template name="unparse-operator-definition">
+ <xsl:with-param name="typeref" select="$typeref"/>
+ <xsl:with-param name="operator_nodeset" select="$op_rest"/>
+ <xsl:with-param name="my_priority" select="$my_priority"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="$notations"/>
+ <xsl:with-param name="ignore-cv" select="$ignore-cv"/>
+ <xsl:with-param name="self" select="$self"/>
+ <xsl:with-param name="use-code-block" select="$use-code-block"/>
+ <xsl:with-param name="print-updated-notation" select="$print-updated-notation"/>
+ <xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="name($op_current)='self'">
+ <xsl:call-template name="concept.link">
+ <xsl:with-param name="name" select="string($self)"/>
+ </xsl:call-template>
+ <xsl:call-template name="unparse-operator-definition">
+ <xsl:with-param name="typeref" select="$typeref"/>
+ <xsl:with-param name="operator_nodeset" select="$op_rest"/>
+ <xsl:with-param name="my_priority" select="$my_priority"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="$notations"/>
+ <xsl:with-param name="ignore-cv" select="$ignore-cv"/>
+ <xsl:with-param name="self" select="$self"/>
+ <xsl:with-param name="use-code-block" select="$use-code-block"/>
+ <xsl:with-param name="print-updated-notation" select="$print-updated-notation"/>
+ <xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="name($op_current)='arg'">
+ <xsl:variable name="num" select="$op_current/@num"/>
+ <xsl:variable name="assoc" select="$op_current/../@assoc"/>
+ <xsl:variable name="my_priority_before" select="$my_priority"/>
+ <xsl:variable name="my_priority">
+ <xsl:choose>
+ <xsl:when test="count($op_current/@priority)">
+ <xsl:value-of select="$op_current/@priority"/>
+ </xsl:when>
+ <xsl:when test="$assoc and ($num = $assoc)">
+ <xsl:value-of select="$my_priority_before - 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$my_priority"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="typeref-result">
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="$typeref/*[position()=$num]"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="priority" select="$my_priority"/>
+ <xsl:with-param name="ignore-cv" select="$ignore-cv"/>
+ <xsl:with-param name="notations" select="$notations"/>
+ <xsl:with-param name="print-updated-notation" select="true()"/>
+ <xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="typeref-print" select="normalize-space(substring-before($typeref-result, ' *@@@* '))"/>
+ <xsl:variable name="new_notations" select="normalize-space(substring-after($typeref-result, ' *@@@* '))"/>
+
+ <xsl:choose>
+ <xsl:when test="$use-code-block">
+ <type><xsl:value-of select="$typeref-print"/></type>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$typeref-print"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:call-template name="unparse-operator-definition">
+ <xsl:with-param name="typeref" select="$typeref"/>
+ <xsl:with-param name="operator_nodeset" select="$op_rest"/>
+ <xsl:with-param name="my_priority" select="$my_priority_before"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="$new_notations"/>
+ <xsl:with-param name="ignore-cv" select="$ignore-cv"/>
+ <xsl:with-param name="self" select="$self"/>
+ <xsl:with-param name="use-code-block" select="$use-code-block"/>
+ <xsl:with-param name="print-updated-notation" select="$print-updated-notation"/>
+ <xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="name($op_current)='arg-list'">
+ <xsl:variable name="start" select="$op_current/@start"/>
+ <xsl:variable name="typeref-result">
+ <xsl:choose>
+ <xsl:when test="$current_start &gt;= $start">
+ <xsl:call-template name="unparse-cpp">
+ <xsl:with-param name="typeref" select="$typeref/*[$current_start]"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="priority" select="$my_priority"/>
+ <xsl:with-param name="ignore-cv" select="$ignore-cv"/>
+ <xsl:with-param name="notations" select="$notations"/>
+ <xsl:with-param name="print-updated-notation" select="true()"/>
+ <xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ *@@@* <xsl:value-of select="$notations"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="typeref-print" select="normalize-space(substring-before($typeref-result, ' *@@@* '))"/>
+ <xsl:variable name="new_notations" select="normalize-space(substring-after($typeref-result, ' *@@@* '))"/>
+
+ <xsl:choose>
+ <xsl:when test="$use-code-block">
+ <type><xsl:value-of select="$typeref-print"/></type>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$typeref-print"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="$current_start &gt;= $start">
+ <xsl:if test="$current_start!=count($typeref/*)">, </xsl:if>
+ </xsl:if>
+
+ <xsl:choose>
+ <xsl:when test="$current_start != count($typeref/*)">
+ <xsl:call-template name="unparse-operator-definition">
+ <xsl:with-param name="typeref" select="$typeref"/>
+ <xsl:with-param name="operator_nodeset" select="$operator_nodeset"/>
+ <xsl:with-param name="current_start" select="$current_start + 1"/>
+ <xsl:with-param name="my_priority" select="$my_priority"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="$new_notations"/>
+ <xsl:with-param name="ignore-cv" select="$ignore-cv"/>
+ <xsl:with-param name="self" select="$self"/>
+ <xsl:with-param name="use-code-block" select="$use-code-block"/>
+ <xsl:with-param name="print-updated-notation" select="$print-updated-notation"/>
+ <xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="unparse-operator-definition">
+ <xsl:with-param name="typeref" select="$typeref"/>
+ <xsl:with-param name="operator_nodeset" select="$op_rest"/>
+ <xsl:with-param name="my_priority" select="$my_priority"/>
+ <xsl:with-param name="definition_list" select="$definition_list"/>
+ <xsl:with-param name="notations" select="$new_notations"/>
+ <xsl:with-param name="ignore-cv" select="$ignore-cv"/>
+ <xsl:with-param name="self" select="$self"/>
+ <xsl:with-param name="use-code-block" select="$use-code-block"/>
+ <xsl:with-param name="const-if-not-mutable-value" select="$const-if-not-mutable-value"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+
+ <xsl:otherwise>Invalid tag in operator definition: <xsl:value-of select="name($op_current)"/></xsl:otherwise>
+
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="add-typename">
+ <!-- Adds typename to the front of a string if it is necessary. -->
+ <xsl:param name="type"/> <!-- string to prepend to -->
+ <xsl:param name="params" select="/concept/param | /concept/define-type | /concept/associated-type"/>
+ <!-- nodeset of param tags for concept -->
+ <!-- associated types are assumed to be dependent -->
+ <xsl:param name="really-do-it"/> <!-- really change anything? -->
+
+ <xsl:variable name="type-after-last-scope">
+ <xsl:call-template name="substring-before-last">
+ <xsl:with-param name="string" select="$type"/>
+ <xsl:with-param name="to-find" select="'::'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="tokenized-type-after-last-scope">
+ <xsl:call-template name="rough-tokenize">
+ <xsl:with-param name="string" select="$type-after-last-scope"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="$really-do-it and boolean($params[contains($tokenized-type-after-last-scope, concat(' ', @name, ' '))])">
+ <!-- If the tokenized string contains any of the param names in a
+ token by itself, return true. Return false otherwise -->
+ <xsl:comment/>typename <xsl:value-of select="$type"/><xsl:comment/>
+ </xsl:when>
+ <xsl:otherwise><xsl:value-of select="$type"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="substring-before-last">
+ <xsl:param name="string"/>
+ <xsl:param name="to-find"/>
+ <xsl:param name="string-processed-so-far"/> <!-- internal -->
+ <!-- Find the substring of $string before the last occurrance of
+ $to-find, returning '' if it was not found. -->
+
+ <xsl:choose>
+ <xsl:when test="contains($string, $to-find)">
+ <xsl:call-template name="substring-before-last">
+ <xsl:with-param name="string" select="substring-after($string, $to-find)"/>
+ <xsl:with-param name="to-find" select="$to-find"/>
+ <xsl:with-param name="string-processed-so-far" select="concat($string-processed-so-far, substring-before($string, $to-find), $to-find)"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:value-of select="substring($string-processed-so-far, 1, string-length($string-processed-so-far)-(string-length($to-find)))"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="substring-after-last">
+ <xsl:param name="string"/>
+ <xsl:param name="to-find"/>
+ <!-- Find the substring of $string after the last occurrance of
+ $to-find, returning the original string if it was not found. -->
+
+ <xsl:choose>
+ <xsl:when test="contains($string, $to-find)">
+ <xsl:call-template name="substring-after-last">
+ <xsl:with-param name="string" select="substring-after($string, $to-find)"/>
+ <xsl:with-param name="to-find" select="$to-find"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:value-of select="$string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="rough-tokenize">
+ <xsl:param name="string"/>
+ <!-- Do a rough tokenization of the string. Right now, just translate
+ all non-token-chars to spaces, normalize-space the result, and prepend
+ and append spaces. -->
+
+ <xsl:value-of select="concat(' ', normalize-space(translate($string, '&lt;&gt;,./?;:[]{}-=\\_+|!@#$%^&amp;*()', ' ')), ' ')"/>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/chunk-common.xsl b/tools/boostbook/xsl/chunk-common.xsl
new file mode 100644
index 0000000000..e3a04a2071
--- /dev/null
+++ b/tools/boostbook/xsl/chunk-common.xsl
@@ -0,0 +1,126 @@
+<?xml version="1.0"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+<!-- Import the HTML chunking stylesheet -->
+
+<!-- Watch out that we don't override chunk.xsl -->
+<!--
+<xsl:import
+ href="http://docbook.sourceforge.net/release/xsl/current/html/chunk-common.xsl"/> -->
+
+<!-- Already included in the main stylesheet -->
+<!-- <xsl:import href="relative-href.xsl"/> -->
+
+<!-- ==================================================================== -->
+
+<xsl:template match="*" mode="recursive-chunk-filename">
+ <xsl:param name="recursive" select="false()"/>
+
+ <xsl:variable name="their">
+ <xsl:apply-imports mode="recursive-chunk-filename" select="."/>
+ </xsl:variable>
+
+ <xsl:variable name="basename" select="substring-before( $their, $html.ext )"/>
+ <xsl:choose>
+ <xsl:when test="not($recursive)">
+ <!-- translate dots into directory separators, and replace illegal file path characters with underscores -->
+ <xsl:value-of select="translate($basename, '.&lt;&gt;\:*?&quot;|,()!+=&amp;', '/_______________' )"/>
+ <xsl:value-of select="$html.ext"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$basename"/>
+ <xsl:value-of select="'.'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+</xsl:template>
+
+<!-- ==================================================================== -->
+
+<xsl:template name="navig.content">
+ <xsl:param name="direction" select="next"/>
+ <xsl:variable name="navtext">
+ <xsl:choose>
+ <xsl:when test="$direction = 'prev'">
+ <xsl:call-template name="gentext.nav.prev"/>
+ </xsl:when>
+ <xsl:when test="$direction = 'next'">
+ <xsl:call-template name="gentext.nav.next"/>
+ </xsl:when>
+ <xsl:when test="$direction = 'up'">
+ <xsl:call-template name="gentext.nav.up"/>
+ </xsl:when>
+ <xsl:when test="$direction = 'home'">
+ <xsl:call-template name="gentext.nav.home"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>xxx</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="$navtext = 'xxx'">
+ <xsl:value-of select="$direction"/>
+ </xsl:when>
+ <xsl:when test="$navig.graphics != 0">
+ <img>
+ <xsl:attribute name="src">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="$navig.graphics.path"/>
+ </xsl:call-template>
+ <xsl:value-of select="$direction"/>
+ <xsl:value-of select="$navig.graphics.extension"/>
+ </xsl:attribute>
+ <xsl:attribute name="alt">
+ <xsl:value-of select="$navtext"/>
+ </xsl:attribute>
+ </img>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$navtext"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+<!-- ====================================================================== -->
+
+<xsl:template match="@fileref">
+ <xsl:choose>
+ <xsl:when test="contains(., ':')">
+ <xsl:value-of select="."/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="."/>
+ <xsl:with-param name="context" select=".."/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="@url">
+ <xsl:choose>
+ <xsl:when test="contains(., ':')">
+ <xsl:value-of select="."/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>XXX</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>XXX</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/docbook-layout.xsl b/tools/boostbook/xsl/docbook-layout.xsl
new file mode 100644
index 0000000000..dfd5afd0af
--- /dev/null
+++ b/tools/boostbook/xsl/docbook-layout.xsl
@@ -0,0 +1,211 @@
+<?xml version = "1.0" encoding = "utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+
+<xsl:stylesheet version = "1.0"
+ xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
+>
+ <!-- needed for calsTable template -->
+
+ <xsl:import
+ href="http://docbook.sourceforge.net/release/xsl/current/html/formal.xsl"/>
+
+ <!--
+ Override the behaviour of some DocBook elements for better
+ integration with the new look & feel.
+ -->
+
+ <xsl:template match = "programlisting[ancestor::informaltable]">
+ <pre class = "table-{name(.)}"><xsl:apply-templates/></pre>
+ </xsl:template>
+
+ <xsl:template match = "refsynopsisdiv">
+ <h2 class = "{name(.)}-title">Synopsis</h2>
+ <div class = "{name(.)}"><xsl:apply-templates/></div>
+ </xsl:template>
+
+ <!-- table: remove border = '1' -->
+
+ <xsl:template match = "table|informaltable">
+ <xsl:choose>
+ <xsl:when test = "self::table and tgroup|mediaobject|graphic">
+ <xsl:apply-imports/>
+ </xsl:when><xsl:when test = "self::informaltable and tgroup|mediaobject|graphic">
+ <xsl:call-template name = "informal.object">
+ <xsl:with-param name = "class"><xsl:choose>
+ <xsl:when test = "@tabstyle">
+ <xsl:value-of select = "@tabstyle"/>
+ </xsl:when><xsl:otherwise>
+ <xsl:value-of select = "local-name(.)"/>
+ </xsl:otherwise>
+ </xsl:choose></xsl:with-param>
+ </xsl:call-template>
+ </xsl:when><xsl:otherwise>
+ <table class = "table"><xsl:copy-of select = "@*[not(local-name(.)='border')]"/>
+ <xsl:call-template name = "htmlTable"/>
+ </table>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match = "tgroup" name = "tgroup">
+ <xsl:variable name="summary"><xsl:call-template name="dbhtml-attribute">
+ <xsl:with-param name="pis" select="processing-instruction('dbhtml')"/>
+ <xsl:with-param name="attribute" select="'table-summary'"/>
+ </xsl:call-template></xsl:variable>
+
+ <xsl:variable name="cellspacing"><xsl:call-template name="dbhtml-attribute">
+ <xsl:with-param name="pis" select="processing-instruction('dbhtml')"/>
+ <xsl:with-param name="attribute" select="'cellspacing'"/>
+ </xsl:call-template></xsl:variable>
+
+ <xsl:variable name="cellpadding"><xsl:call-template name="dbhtml-attribute">
+ <xsl:with-param name="pis" select="processing-instruction('dbhtml')[1]"/>
+ <xsl:with-param name="attribute" select="'cellpadding'"/>
+ </xsl:call-template></xsl:variable>
+
+ <table class = "table">
+ <xsl:choose>
+ <xsl:when test="../textobject/phrase">
+ <xsl:attribute name="summary">
+ <xsl:value-of select="../textobject/phrase"/>
+ </xsl:attribute>
+ </xsl:when><xsl:when test="$summary != ''">
+ <xsl:attribute name="summary">
+ <xsl:value-of select="$summary"/>
+ </xsl:attribute>
+ </xsl:when><xsl:when test="../title">
+ <xsl:attribute name="summary">
+ <xsl:value-of select="string(../title)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose><xsl:if test="$cellspacing != '' or $html.cellspacing != ''">
+ <xsl:attribute name="cellspacing"><xsl:choose>
+ <xsl:when test="$cellspacing != ''"><xsl:value-of select="$cellspacing"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="$html.cellspacing"/></xsl:otherwise>
+ </xsl:choose></xsl:attribute>
+ </xsl:if><xsl:if test="$cellpadding != '' or $html.cellpadding != ''">
+ <xsl:attribute name="cellpadding"><xsl:choose>
+ <xsl:when test="$cellpadding != ''"><xsl:value-of select="$cellpadding"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="$html.cellpadding"/></xsl:otherwise>
+ </xsl:choose></xsl:attribute>
+ </xsl:if><xsl:if test="../@pgwide=1">
+ <xsl:attribute name="width">100%</xsl:attribute>
+ </xsl:if>
+
+ <xsl:variable name="colgroup">
+ <colgroup><xsl:call-template name="generate.colgroup">
+ <xsl:with-param name="cols" select="@cols"/>
+ </xsl:call-template></colgroup>
+ </xsl:variable>
+
+ <xsl:variable name="explicit.table.width"><xsl:call-template name="dbhtml-attribute">
+ <xsl:with-param name="pis" select="../processing-instruction('dbhtml')[1]"/>
+ <xsl:with-param name="attribute" select="'table-width'"/>
+ </xsl:call-template></xsl:variable>
+
+ <xsl:variable name="table.width"><xsl:choose>
+ <xsl:when test="$explicit.table.width != ''">
+ <xsl:value-of select="$explicit.table.width"/>
+ </xsl:when><xsl:when test="$default.table.width = ''">
+ <xsl:text>100%</xsl:text>
+ </xsl:when><xsl:otherwise>
+ <xsl:value-of select="$default.table.width"/>
+ </xsl:otherwise>
+ </xsl:choose></xsl:variable>
+
+ <xsl:if test="$default.table.width != '' or $explicit.table.width != ''">
+ <xsl:attribute name="width"><xsl:choose>
+ <xsl:when test="contains($table.width, '%')">
+ <xsl:value-of select="$table.width"/>
+ </xsl:when><xsl:when test="$use.extensions != 0 and $tablecolumns.extension != 0">
+ <xsl:choose>
+ <xsl:when test="function-available('stbl:convertLength')">
+ <xsl:value-of select="stbl:convertLength($table.width)"/>
+ </xsl:when><xsl:when test="function-available('xtbl:convertLength')">
+ <xsl:value-of select="xtbl:convertLength($table.width)"/>
+ </xsl:when><xsl:otherwise>
+ <xsl:message terminate="yes">
+ <xsl:text>No convertLength function available.</xsl:text>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when><xsl:otherwise>
+ <xsl:value-of select="$table.width"/>
+ </xsl:otherwise>
+ </xsl:choose></xsl:attribute>
+ </xsl:if>
+
+ <xsl:choose>
+ <xsl:when test="$use.extensions != 0 and $tablecolumns.extension != 0">
+ <xsl:choose>
+ <xsl:when test="function-available('stbl:adjustColumnWidths')">
+ <xsl:copy-of select="stbl:adjustColumnWidths($colgroup)"/>
+ </xsl:when><xsl:when test="function-available('xtbl:adjustColumnWidths')">
+ <xsl:copy-of select="xtbl:adjustColumnWidths($colgroup)"/>
+ </xsl:when><xsl:when test="function-available('ptbl:adjustColumnWidths')">
+ <xsl:copy-of select="ptbl:adjustColumnWidths($colgroup)"/>
+ </xsl:when><xsl:otherwise>
+ <xsl:message terminate="yes">
+ <xsl:text>No adjustColumnWidths function available.</xsl:text>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when><xsl:otherwise>
+ <xsl:copy-of select="$colgroup"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:apply-templates select="thead"/>
+ <xsl:apply-templates select="tfoot"/>
+ <xsl:apply-templates select="tbody"/>
+
+ <xsl:if test=".//footnote"><tbody class="footnotes">
+ <tr><td colspan="{@cols}">
+ <xsl:apply-templates select=".//footnote" mode="table.footnote.mode"/>
+ </td></tr>
+ </tbody></xsl:if>
+ </table>
+ </xsl:template>
+
+ <!-- table of contents
+
+ The standard Docbook template selects, amoung others,
+ the 'refentry' element for inclusion in TOC. In some
+ cases, this creates empty TOC. The most possible reason
+ is that there's 'refentry' element without 'refentrytitle',
+ but it's a mistery why it occurs. Even if we fix that
+ problem, we'll get non-empty TOC where no TOC is desired
+ (e.g. for section corresponding to each header file in
+ library doc). So, don't bother for now.
+ -->
+
+ <xsl:template name="section.toc">
+ <xsl:param name="toc-context" select="."/>
+ <xsl:param name="toc.title.p" select="true()"/>
+
+ <xsl:call-template name="make.toc">
+ <xsl:with-param name="toc-context" select="$toc-context"/>
+ <xsl:with-param name="toc.title.p" select="$toc.title.p"/>
+ <xsl:with-param name="nodes" select="
+ section|sect1|sect2|sect3|sect4|sect5|
+ bridgehead[$bridgehead.in.toc != 0]
+ "/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- When there is both a title and a caption for a table, only use the
+ title. -->
+ <xsl:template match="table" mode="title.markup">
+ <xsl:param name="allow-anchors" select="0"/>
+ <xsl:apply-templates select="(title|caption)[1]" mode="title.markup">
+ <xsl:with-param name="allow-anchors" select="$allow-anchors"/>
+ </xsl:apply-templates>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/docbook.xsl b/tools/boostbook/xsl/docbook.xsl
new file mode 100644
index 0000000000..c2ad5218be
--- /dev/null
+++ b/tools/boostbook/xsl/docbook.xsl
@@ -0,0 +1,527 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ version="1.0">
+ <xsl:include href="reference.xsl"/>
+
+ <xsl:output method="xml"
+ doctype-public="-//OASIS//DTD DocBook XML V4.2//EN"
+ doctype-system="http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"/>
+
+ <!-- The maximum number of columns allowed in preformatted text -->
+ <xsl:param name="max-columns" select="78"/>
+
+ <!-- The root of the Boost directory -->
+ <xsl:param name="boost.root" select="'../..'"/>
+
+ <!-- A space-separated list of libraries to include in the
+ output. If this list is empty, all libraries will be included. -->
+ <xsl:param name="boost.include.libraries" select="''"/>
+
+ <!-- Whether to rewrite relative URL's to point to the website -->
+ <xsl:param name="boost.url.prefix"/>
+
+ <!-- A space-separated list of xml elements in the input file for which
+ whitespace should be preserved -->
+ <xsl:preserve-space elements="*"/>
+
+ <!-- The root for boost headers -->
+ <xsl:param name="boost.header.root">
+ <xsl:if test="$boost.url.prefix">
+ <xsl:value-of select="$boost.url.prefix"/>
+ <xsl:text>/</xsl:text>
+ </xsl:if>
+ <xsl:value-of select="$boost.root"/>
+ </xsl:param>
+
+ <!-- The prefix for 'boost:' links. -->
+ <xsl:variable name="boost.protocol.text">
+ <xsl:if test="($boost.url.prefix != '') and (contains($boost.root, '://') = 0)">
+ <xsl:value-of select="concat($boost.url.prefix, '/', $boost.root)"/>
+ </xsl:if>
+ <xsl:if test="($boost.url.prefix = '') or contains($boost.root, '://')">
+ <xsl:value-of select="$boost.root"/>
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:template match="library-reference">
+ <xsl:choose>
+ <xsl:when test="ancestor::library-reference">
+ <xsl:apply-templates/>
+ </xsl:when>
+ <xsl:otherwise>
+ <section>
+ <xsl:choose>
+ <xsl:when test="@id">
+ <xsl:attribute name="id">
+ <xsl:value-of select="@id"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="ancestor::library/attribute::id">
+ <xsl:attribute name="id">
+ <xsl:value-of select="ancestor::library/attribute::id"/>
+ <xsl:text>.reference</xsl:text>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="not(title)">
+ <title>
+ <xsl:text>Reference</xsl:text>
+ </title>
+ </xsl:if>
+
+ <xsl:if test="concept">
+ <section>
+ <xsl:choose>
+ <xsl:when test="@id">
+ <xsl:attribute name="id">
+ <xsl:value-of select="@id"/>
+ <xsl:text>.concepts</xsl:text>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="ancestor::library/attribute::id">
+ <xsl:attribute name="id">
+ <xsl:value-of select="ancestor::library/attribute::id"/>
+ <xsl:text>.concepts</xsl:text>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+
+ <title>Concepts</title>
+
+ <itemizedlist>
+ <xsl:for-each select="concept">
+ <listitem><simpara>
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </simpara></listitem>
+ </xsl:for-each>
+ </itemizedlist>
+ </section>
+ </xsl:if>
+
+ <xsl:apply-templates/>
+ </section>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="header">
+ <xsl:if test="*">
+ <section>
+ <xsl:attribute name="id">
+ <xsl:call-template name="generate.id"/>
+ </xsl:attribute>
+
+ <title>
+ <xsl:text>Header &lt;</xsl:text>
+ <ulink>
+ <xsl:attribute name="url">
+ <xsl:value-of select="$boost.header.root"/>
+ <xsl:text>/</xsl:text>
+ <xsl:value-of select="@name"/>
+ </xsl:attribute>
+ <xsl:value-of select="@name"/>
+ </ulink>
+ <xsl:text>&gt;</xsl:text>
+ </title>
+
+ <xsl:apply-templates select="para|section" mode="annotation"/>
+
+ <xsl:if test="macro">
+ <xsl:call-template name="synopsis">
+ <xsl:with-param name="text">
+ <xsl:apply-templates mode="synopsis" select="macro">
+ <xsl:with-param name="indentation" select="0"/>
+ </xsl:apply-templates>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+
+ <xsl:if test="descendant::class|descendant::struct|descendant::union
+ |descendant::function|descendant::free-function-group
+ |descendant::overloaded-function|descendant::enum
+ |descendant::typedef">
+ <xsl:call-template name="synopsis">
+ <xsl:with-param name="text">
+ <xsl:apply-templates mode="synopsis"
+ select="namespace|class|struct|union
+ |function|free-function-group
+ |overloaded-function|enum
+ |typedef">
+ <xsl:with-param name="indentation" select="0"/>
+ </xsl:apply-templates>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+
+ <xsl:apply-templates mode="namespace-reference"/>
+ </section>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="header" mode="generate.id">
+ <xsl:text>header.</xsl:text>
+ <xsl:value-of select="translate(@name, '/.', '._')"/>
+ </xsl:template>
+
+ <xsl:template match="*" mode="passthrough">
+ <xsl:copy-of select="."/>
+ </xsl:template>
+
+ <xsl:template name="monospaced">
+ <xsl:param name="text"/>
+ <computeroutput><xsl:value-of select="$text"/></computeroutput>
+ </xsl:template>
+
+ <!-- Linking -->
+ <xsl:template match="ulink">
+ <xsl:copy>
+ <xsl:copy-of select="@*"/>
+ <xsl:attribute name="url">
+ <xsl:choose>
+ <xsl:when test="starts-with(@url, 'boost:/')">
+ <xsl:value-of select="concat($boost.protocol.text, substring-after(@url, 'boost:'))"/>
+ </xsl:when>
+ <xsl:when test="starts-with(@url, 'boost:')">
+ <xsl:value-of select="concat($boost.protocol.text, '/', substring-after(@url, 'boost:'))"/>
+ </xsl:when>
+ <xsl:when test="$boost.url.prefix != '' and not(contains(@url, ':') or starts-with(@url, '//'))">
+ <xsl:value-of select="concat($boost.url.prefix, '/', @url)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@url"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:copy>
+ </xsl:template>
+ <xsl:template name="internal-link">
+ <xsl:param name="to"/>
+ <xsl:param name="text"/>
+ <xsl:param name="highlight" select="false()"/>
+
+ <link linkend="{$to}">
+ <xsl:if test="$highlight">
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="not($highlight)">
+ <xsl:value-of select="string($text)"/>
+ </xsl:if>
+ </link>
+ </xsl:template>
+
+ <xsl:template name="anchor">
+ <xsl:param name="to"/>
+ <xsl:param name="text"/>
+ <xsl:param name="highlight" select="false()"/>
+
+ <anchor id="{$to}"/>
+ <xsl:if test="$highlight">
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="not($highlight)">
+ <xsl:value-of select="$text"/>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="link-or-anchor">
+ <xsl:param name="to"/>
+ <xsl:param name="text"/>
+
+ <!-- True if we should create an anchor, otherwise we will create
+ a link. If you require more control (e.g., with the possibility of
+ having no link or anchor), set link-type instead: if present, it
+ takes precedence. -->
+ <xsl:param name="is-anchor"/>
+
+ <!-- 'anchor', 'link', or 'none' -->
+ <xsl:param name="link-type">
+ <xsl:choose>
+ <xsl:when test="$is-anchor">
+ <xsl:text>anchor</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>link</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:param>
+
+ <xsl:param name="highlight" select="false()"/>
+
+ <xsl:choose>
+ <xsl:when test="$link-type='anchor'">
+ <xsl:call-template name="anchor">
+ <xsl:with-param name="to" select="$to"/>
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$link-type='link'">
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to" select="$to"/>
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$link-type='none'">
+ <xsl:if test="$highlight">
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="not($highlight)">
+ <xsl:value-of select="$text"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>
+Error: XSL template 'link-or-anchor' called with invalid link-type '<xsl:value-of select="$link-type"/>'
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="separator"/>
+
+ <xsl:template name="reference-documentation">
+ <xsl:param name="name"/>
+ <xsl:param name="refname"/>
+ <xsl:param name="purpose"/>
+ <xsl:param name="anchor"/>
+ <xsl:param name="synopsis"/>
+ <xsl:param name="text"/>
+
+ <refentry id="{$anchor}">
+ <refmeta>
+ <refentrytitle><xsl:value-of select="$name"/></refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname><xsl:value-of select="$refname"/></refname>
+ <refpurpose>
+ <xsl:apply-templates mode="purpose" select="$purpose"/>
+ </refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <synopsis>
+ <xsl:copy-of select="$synopsis"/>
+ </synopsis>
+ </refsynopsisdiv>
+ <xsl:if test="not(string($text)='')">
+ <refsect1>
+ <title>Description</title>
+ <xsl:copy-of select="$text"/>
+ </refsect1>
+ </xsl:if>
+ </refentry>
+ </xsl:template>
+
+ <xsl:template name="member-documentation">
+ <xsl:param name="name"/>
+ <xsl:param name="text"/>
+
+ <refsect2>
+ <title><xsl:copy-of select="$name"/></title>
+ <xsl:copy-of select="$text"/>
+ </refsect2>
+ </xsl:template>
+
+ <xsl:template name="preformatted">
+ <xsl:param name="text"/>
+
+ <literallayout class="monospaced">
+ <xsl:copy-of select="$text"/>
+ </literallayout>
+ </xsl:template>
+
+ <xsl:template name="synopsis">
+ <xsl:param name="text"/>
+
+ <synopsis>
+ <xsl:copy-of select="$text"/>
+ </synopsis>
+ </xsl:template>
+
+ <!-- Fallthrough for DocBook elements -->
+ <xsl:template match="*">
+ <xsl:element name="{name(.)}">
+ <xsl:for-each select="./@*">
+ <xsl:choose>
+ <xsl:when test="local-name(.)='last-revision'">
+ <xsl:attribute
+ name="rev:last-revision"
+ namespace="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{name(.)}">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="processing-instruction()">
+ <xsl:copy/>
+ </xsl:template>
+
+ <xsl:template match="code">
+ <computeroutput>
+ <xsl:apply-templates mode="annotation"/>
+ </computeroutput>
+ </xsl:template>
+
+ <xsl:template match="bold">
+ <emphasis role="bold">
+ <xsl:apply-templates mode="annotation"/>
+ </emphasis>
+ </xsl:template>
+
+ <xsl:template match="library">
+ <xsl:if test="not(@html-only = 1) and
+ ($boost.include.libraries='' or
+ contains($boost.include.libraries, @id))">
+ <chapter>
+ <xsl:copy-of select="@*[not(contains(' last-revision name dirname html-only url ', concat(' ',local-name(),' ')))]"/>
+ <xsl:if test="not(@id)">
+ <xsl:attribute name="id">
+ <xsl:call-template name="generate.id"/>
+ </xsl:attribute>
+ </xsl:if>
+
+ <xsl:if test="@last-revision">
+ <xsl:attribute
+ name="rev:last-revision"
+ namespace="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision">
+ <xsl:value-of select="@last-revision"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates/>
+ </chapter>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="chapter">
+ <xsl:if test="$boost.include.libraries=''">
+ <chapter>
+ <xsl:for-each select="./@*">
+ <xsl:attribute name="{name(.)}">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:for-each>
+
+ <xsl:apply-templates/>
+ </chapter>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="boostbook">
+ <book>
+ <xsl:copy-of select="@*[not(contains(' last-revision name dirname html-only url ', concat(' ',local-name(),' ')))]"/>
+ <xsl:apply-templates/>
+ </book>
+ </xsl:template>
+
+ <xsl:template match="programlisting">
+ <programlisting><xsl:apply-templates/></programlisting>
+ </xsl:template>
+
+ <!-- These DocBook elements have special meaning. Use the annotation mode -->
+ <xsl:template match="classname|methodname|functionname|enumname|
+ macroname|headername|globalname">
+ <computeroutput>
+ <xsl:apply-templates select="." mode="annotation"/>
+ </computeroutput>
+ </xsl:template>
+
+ <xsl:template match="libraryname|conceptname">
+ <xsl:apply-templates select="." mode="annotation"/>
+ </xsl:template>
+
+ <xsl:template match="description">
+ <xsl:apply-templates mode="annotation"/>
+ </xsl:template>
+
+ <!-- Swallow using-namespace and using-class directives along with
+ last-revised elements -->
+ <xsl:template match="using-namespace|using-class|last-revised"/>
+
+ <!-- If there is no "namespace-reference" mode, forward to
+ "reference" mode -->
+ <xsl:template match="*" mode="namespace-reference">
+ <xsl:apply-templates select="." mode="reference"/>
+ </xsl:template>
+
+ <!-- Make the various blocks immediately below a "part" be
+ "chapter"-s. Must also take into account turning
+ chapters within chpaters into sections. -->
+ <xsl:template match="part/part|part/article">
+ <chapter>
+ <xsl:for-each select="./@*">
+ <xsl:attribute name="{name(.)}">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:for-each>
+ <xsl:apply-templates/>
+ </chapter>
+ </xsl:template>
+ <xsl:template match="part/part/partinfo|part/article/articleinfo">
+ <chapterinfo><xsl:apply-templates/></chapterinfo>
+ </xsl:template>
+ <xsl:template match="part/part/chapter|part/part/appendix">
+ <section>
+ <xsl:for-each select="./@*">
+ <xsl:attribute name="{name(.)}">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:for-each>
+ <xsl:apply-templates/>
+ </section>
+ </xsl:template>
+ <xsl:template match="part/part/chapter/chapterinfo|part/part/appendix/appendixinfo">
+ <sectioninfo><xsl:apply-templates/></sectioninfo>
+ </xsl:template>
+
+ <!-- Header link comment to be inserted at the start of a reference page's
+ synopsis -->
+ <xsl:template name="header-link">
+ <xsl:if test="ancestor::header">
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// In header: &lt;</xsl:text>
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="ancestor::header[1]"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="ancestor::header[1]/@name" />
+ </xsl:call-template>
+ <xsl:text>&gt;&#10;&#10;</xsl:text>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+</xsl:stylesheet>
+
diff --git a/tools/boostbook/xsl/doxygen/collect.xsl b/tools/boostbook/xsl/doxygen/collect.xsl
new file mode 100644
index 0000000000..3ec164bed6
--- /dev/null
+++ b/tools/boostbook/xsl/doxygen/collect.xsl
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" version="1.0" indent="yes" standalone="yes" />
+
+ <xsl:template match="/">
+ <doxygen>
+ <xsl:attribute name="version">
+ <xsl:choose>
+ <xsl:when test="doxygen">
+ <xsl:value-of select="doxygen/attribute::version"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="doxygenindex/attribute::version"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+
+ <!-- Load all doxgen generated xml files -->
+ <xsl:for-each select="doxygen/compound">
+ <xsl:variable name="id">
+ <xsl:choose>
+ <xsl:when test="@refid">
+ <xsl:value-of select="@refid"/>
+ </xsl:when>
+ <xsl:when test="@id">
+ <xsl:value-of select="@id"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$id">
+ <xsl:copy-of select="document( concat( $id, '.xml' ), / )/doxygen/*" />
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="doxygenindex/compound">
+ <xsl:variable name="id">
+ <xsl:choose>
+ <xsl:when test="@refid">
+ <xsl:value-of select="@refid"/>
+ </xsl:when>
+ <xsl:when test="@id">
+ <xsl:value-of select="@id"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$id">
+ <xsl:copy-of select="document( concat($id, '.xml'), /)/doxygen/*" />
+ </xsl:if>
+ </xsl:for-each>
+ </doxygen>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/doxygen/doxygen2boostbook.xsl b/tools/boostbook/xsl/doxygen/doxygen2boostbook.xsl
new file mode 100644
index 0000000000..da5a996af6
--- /dev/null
+++ b/tools/boostbook/xsl/doxygen/doxygen2boostbook.xsl
@@ -0,0 +1,1620 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:import href="../lookup.xsl"/>
+
+ <!-- Set this parameter to a space-separated list of headers that
+ will be included in the output (all others are ignored). If this
+ parameter is omitted or left as the empty string, all headers will
+ be output. -->
+ <xsl:param name="boost.doxygen.headers" select="''"/>
+
+ <!-- The common prefix to all headers -->
+ <xsl:param name="boost.doxygen.header.prefix" select="'boost'"/>
+
+ <!-- The text that Doxygen places in overloaded functions. Damn them
+ for forcing us to compare TEXT just to figure out what's overloaded
+ and what isn't. -->
+ <xsl:param name="boost.doxygen.overload">
+ This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
+ </xsl:param>
+
+ <!-- The namespace used to identify code that should not be
+ processed at all. -->
+ <xsl:param name="boost.doxygen.detailns">detail</xsl:param>
+
+ <!-- The substring used to identify unspecified types that we can't
+ mask from within Doxygen. This is a hack (big surprise). -->
+ <xsl:param name="boost.doxygen.detail"><xsl:value-of select="$boost.doxygen.detailns"/>::</xsl:param>
+
+ <!-- The title that will be used for the BoostBook library reference emitted.
+ If left blank, BoostBook will assign a default title. -->
+ <xsl:param name="boost.doxygen.reftitle" select="''"/>
+
+ <!-- The id used for the library-reference. By default, it is the normalized
+ form of the reftitle. -->
+ <xsl:param name="boost.doxygen.refid" select="''"/>
+
+ <!-- The directory into which png files corresponding to LaTeX formulas will be found. -->
+ <xsl:param name="boost.doxygen.formuladir" select="'images/'"/>
+
+ <xsl:output method="xml" indent="no" standalone="yes"/>
+
+ <xsl:key name="compounds-by-kind" match="compounddef" use="@kind"/>
+ <xsl:key name="compounds-by-id" match="compounddef" use="@id"/>
+ <xsl:key name="members-by-id" match="memberdef" use="@id" />
+
+ <xsl:strip-space elements="briefdescription detaileddescription inbodydescription"/>
+
+ <xsl:template name="kind-error-message">
+ <xsl:param name="message"/>
+
+ <xsl:variable name="location" select=".//location[1]" />
+ <xsl:variable name="name" select="./name" />
+
+ <xsl:message>
+ <xsl:if test="$location">
+ <xsl:value-of select="concat($location/@file, ':', $location/@line, ': ')" />
+ </xsl:if>
+ <xsl:value-of select="concat($message, ' with kind=', @kind)" />
+ <xsl:if test="$name">
+ <xsl:value-of select="concat(' (name=', $name, ') ')" />
+ </xsl:if>
+ </xsl:message>
+ </xsl:template>
+
+ <!-- translate-name: given a string, return a string suitable for use as a refid -->
+ <xsl:template name="translate-name">
+ <xsl:param name="name"/>
+ <xsl:value-of select="translate($name,
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ~!%^&amp;*()[].,&lt;&gt;|/ +-=',
+ 'abcdefghijklmnopqrstuvwxyz_____________________')"/>
+ </xsl:template>
+
+ <xsl:template match="/">
+ <xsl:apply-templates select="doxygen"/>
+ </xsl:template>
+
+ <xsl:template match="doxygen">
+ <library-reference>
+ <xsl:if test="string($boost.doxygen.reftitle) != ''">
+ <!-- when a reference section has a reftitle, also give it a refid. The id
+ is determined by the boost.doxygen.refid param, which defaults to a
+ normalized form of the boost.doxygen.reftitle -->
+ <xsl:attribute name="id">
+ <xsl:choose>
+ <xsl:when test="string($boost.doxygen.refid) != ''">
+ <xsl:value-of select="$boost.doxygen.refid"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="translate-name">
+ <xsl:with-param name="name" select="$boost.doxygen.reftitle"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+
+ <title><xsl:copy-of select="$boost.doxygen.reftitle"/></title>
+ </xsl:if>
+ <xsl:apply-templates select="key('compounds-by-kind', 'file')"/>
+ </library-reference>
+ </xsl:template>
+
+ <xsl:template match="compounddef">
+ <!-- The set of innernamespace nodes that limits our search -->
+ <xsl:param name="with-namespace-refs"/>
+ <xsl:param name="in-file"/>
+
+ <xsl:choose>
+ <!-- If the string INTERNAL ONLY is in the description, don't
+ emit this entity. This hack is necessary because Doxygen doesn't
+ tell us what is \internal and what isn't. -->
+ <xsl:when test="contains(detaileddescription/para, 'INTERNAL ONLY')"/>
+ <xsl:when test="contains(briefdescription/para, 'INTERNAL ONLY')"/>
+ <xsl:when test="contains(inbodydescription/para, 'INTERNAL ONLY')"/>
+
+ <xsl:when test="@kind='file'">
+ <xsl:call-template name="file"/>
+ </xsl:when>
+ <xsl:when test="@kind='namespace'">
+ <xsl:call-template name="namespace">
+ <xsl:with-param name="with-namespace-refs"
+ select="$with-namespace-refs"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="@kind='class'">
+ <xsl:call-template name="class">
+ <xsl:with-param name="class-key" select="'class'"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="@kind='struct'">
+ <xsl:call-template name="class">
+ <xsl:with-param name="class-key" select="'struct'"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="@kind='union'">
+ <xsl:call-template name="class">
+ <xsl:with-param name="class-key" select="'union'"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="kind-error-message">
+ <xsl:with-param name="message" select="'Cannot handle compounddef'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="namespace">
+ <!-- The set of innernamespace nodes that limits our search -->
+ <xsl:param name="with-namespace-refs"/>
+ <xsl:param name="in-file"/>
+
+ <xsl:variable name="fullname" select="string(compoundname)"/>
+
+ <xsl:if test="$with-namespace-refs[string(text())=$fullname]
+ and not(contains($fullname, $boost.doxygen.detailns))">
+ <!-- Namespace without the prefix -->
+ <xsl:variable name="rest">
+ <xsl:call-template name="strip-qualifiers">
+ <xsl:with-param name="name" select="compoundname"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <!-- Grab only the namespace name, not any further nested namespaces -->
+ <xsl:variable name="name">
+ <xsl:choose>
+ <xsl:when
+ test="contains($rest, '::')">
+ <xsl:value-of select="substring-before($rest, '::')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$rest"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <namespace>
+ <xsl:attribute name="name">
+ <xsl:value-of select="$name"/>
+ </xsl:attribute>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="with-namespace-refs"
+ select="$with-namespace-refs"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </namespace>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="class">
+ <xsl:param name="class-key"/>
+ <xsl:param name="in-file"/>
+ <xsl:param name="with-namespace-refs"/>
+
+ <xsl:if test="string(location/attribute::file)=$in-file">
+
+ <!-- The short name of this class -->
+ <xsl:variable name="name-with-spec">
+ <xsl:call-template name="strip-qualifiers">
+ <xsl:with-param name="name" select="compoundname"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="name">
+ <xsl:choose>
+ <xsl:when test="contains($name-with-spec, '&lt;')">
+ <xsl:value-of select="substring-before($name-with-spec, '&lt;')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$name-with-spec"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="specialization">
+ <xsl:if test="contains($name-with-spec, '&lt;')">
+ <xsl:variable name="spec-with-gt"
+ select="substring-after($name-with-spec, '&lt;')"/>
+ <xsl:value-of select="substring($spec-with-gt, 1,
+ string-length($spec-with-gt)-1)"/>
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:variable name="actual-class-key">
+ <xsl:value-of select="$class-key"/>
+ <xsl:if test="string-length($specialization) &gt; 0">
+ <xsl:text>-specialization</xsl:text>
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:element name="{$actual-class-key}">
+ <xsl:attribute name="name">
+ <xsl:value-of select="$name"/>
+ </xsl:attribute>
+
+ <xsl:apply-templates select="templateparamlist" mode="template"/>
+
+ <xsl:if test="string-length($specialization) &gt; 0">
+ <specialization>
+ <xsl:call-template name="specialization">
+ <xsl:with-param name="specialization" select="$specialization"/>
+ </xsl:call-template>
+ </specialization>
+ </xsl:if>
+
+ <xsl:apply-templates select="basecompoundref" mode="inherit"/>
+
+ <xsl:apply-templates select="briefdescription" mode="passthrough"/>
+ <xsl:apply-templates select="detaileddescription" mode="passthrough"/>
+ <xsl:apply-templates select="inbodydescription" mode="passthrough"/>
+ <xsl:apply-templates>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="enum">
+ <xsl:param name="in-file"/>
+
+ <xsl:if test="string(location/attribute::file)=$in-file">
+ <xsl:variable name="name">
+ <xsl:call-template name="strip-qualifiers">
+ <xsl:with-param name="name" select="name"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <enum>
+ <xsl:attribute name="name">
+ <xsl:value-of select="$name"/>
+ </xsl:attribute>
+
+ <xsl:apply-templates select="enumvalue"/>
+
+ <xsl:apply-templates select="briefdescription" mode="passthrough"/>
+ <xsl:apply-templates select="detaileddescription" mode="passthrough"/>
+ <xsl:apply-templates select="inbodydescription" mode="passthrough"/>
+ </enum>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="enumvalue">
+ <xsl:choose>
+ <!-- If the string INTERNAL ONLY is in the description, don't
+ emit this entity. This hack is necessary because Doxygen doesn't
+ tell us what is \internal and what isn't. -->
+ <xsl:when test="contains(detaileddescription/para, 'INTERNAL ONLY')"/>
+ <xsl:when test="contains(briefdescription/para, 'INTERNAL ONLY')"/>
+ <xsl:when test="contains(inbodydescription/para, 'INTERNAL ONLY')"/>
+ <xsl:otherwise>
+
+ <enumvalue>
+ <xsl:attribute name="name">
+ <xsl:value-of select="name"/>
+ </xsl:attribute>
+
+ <xsl:if test="initializer">
+ <default>
+ <xsl:apply-templates select="initializer/*|initializer/text()" mode="passthrough"/>
+ </default>
+ </xsl:if>
+
+ <xsl:apply-templates select="briefdescription" mode="passthrough"/>
+ <xsl:apply-templates select="detaileddescription" mode="passthrough"/>
+ <xsl:apply-templates select="inbodydescription" mode="passthrough"/>
+ </enumvalue>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="doxygen.include.header.rec">
+ <xsl:param name="name"/>
+ <xsl:param name="header-list" select="$boost.doxygen.headers"/>
+
+ <xsl:choose>
+ <xsl:when test="contains($header-list, ' ')">
+ <xsl:variable name="header"
+ select="substring-before($header-list, ' ')"/>
+ <xsl:variable name="rest" select="substring-after($header-list, ' ')"/>
+
+ <xsl:choose>
+ <xsl:when test="$name=$header">
+ <xsl:text>yes</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="doxygen.include.header.rec">
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="header-list" select="$rest"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$name=$header-list">
+ <xsl:text>yes</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="doxygen.include.header">
+ <xsl:param name="name"/>
+
+ <xsl:if test="$boost.doxygen.headers=''">
+ <xsl:text>yes</xsl:text>
+ </xsl:if>
+ <xsl:if test="not($boost.doxygen.headers='')">
+ <xsl:call-template name="doxygen.include.header.rec">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="file">
+ <xsl:variable name="include-header">
+ <xsl:call-template name="doxygen.include.header">
+ <xsl:with-param name="name" select="string(compoundname)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$include-header='yes'">
+ <header>
+ <xsl:attribute name="name">
+ <xsl:call-template name="shorten.header.name">
+ <xsl:with-param name="header" select="location/attribute::file"/>
+ </xsl:call-template>
+ </xsl:attribute>
+
+ <xsl:if test="briefdescription/*|detaileddescription/*|inbodydescription/*">
+ <xsl:apply-templates select="briefdescription/*" mode="passthrough"/>
+ <xsl:apply-templates select="detaileddescription/*" mode="passthrough"/>
+ <xsl:apply-templates select="inbdoydescription/*" mode="passthrough"/>
+ </xsl:if>
+
+ <xsl:apply-templates mode="toplevel">
+ <xsl:with-param name="with-namespace-refs"
+ select="innernamespace"/>
+ <xsl:with-param name="in-file" select="location/attribute::file"/>
+ </xsl:apply-templates>
+ </header>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="shorten.header.name">
+ <xsl:param name="header"/>
+
+ <xsl:variable name="prefix">
+ <xsl:value-of select="concat($boost.doxygen.header.prefix, '/')"/>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="contains($header, $prefix)">
+ <xsl:variable name="rest" select="substring-after($header, $prefix)"/>
+ <xsl:choose>
+ <xsl:when test="contains($rest, $prefix)">
+ <xsl:call-template name="shorten.header.name">
+ <xsl:with-param name="header" select="$rest"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$prefix"/>
+ <xsl:value-of select="$rest"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$header"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template match="innernamespace">
+ <xsl:param name="with-namespace-refs"/>
+ <xsl:param name="in-file"/>
+
+ <xsl:apply-templates select="key('compounds-by-id', @refid)">
+ <xsl:with-param name="with-namespace-refs"
+ select="$with-namespace-refs"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="innernamespace" mode="toplevel">
+ <!-- The set of innernamespace nodes that limits our search -->
+ <xsl:param name="with-namespace-refs"/>
+ <xsl:param name="in-file"/>
+
+ <!-- The full name of the namespace we are referring to -->
+ <xsl:variable name="fullname"
+ select="string(key('compounds-by-id', @refid)/compoundname)"/>
+
+ <!-- Only pass on top-level namespaces -->
+ <xsl:if test="not(contains($fullname, '::'))">
+ <xsl:apply-templates select="key('compounds-by-id', @refid)">
+ <xsl:with-param name="with-namespace-refs"
+ select="$with-namespace-refs"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="sectiondef" mode="toplevel">
+ <xsl:param name="in-file" select="''"/>
+
+ <xsl:apply-templates mode="toplevel"
+ select="memberdef[generate-id() =
+ generate-id(key('members-by-id', @id))]">
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="memberdef" mode="toplevel">
+ <xsl:param name="with-namespace-refs"/>
+ <xsl:param name="in-file"/>
+
+ <xsl:choose>
+ <!-- If the string INTERNAL ONLY is in the description, don't
+ emit this entity. This hack is necessary because Doxygen doesn't
+ tell us what is \internal and what isn't. -->
+ <xsl:when test="contains(detaileddescription/para, 'INTERNAL ONLY')"/>
+ <xsl:when test="contains(briefdescription/para, 'INTERNAL ONLY')"/>
+ <xsl:when test="contains(inbodydescription/para, 'INTERNAL ONLY')"/>
+
+ <xsl:when test="@kind='define'">
+ <macro>
+ <xsl:attribute name="name">
+ <xsl:value-of select="name/text()"/>
+ </xsl:attribute>
+
+ <xsl:if test="param">
+ <xsl:attribute name="kind">
+ <xsl:value-of select="'functionlike'"/>
+ </xsl:attribute>
+ </xsl:if>
+
+ <xsl:for-each select="param">
+ <macro-parameter>
+ <xsl:attribute name="name">
+ <xsl:value-of select="defname/text()"/>
+ </xsl:attribute>
+ </macro-parameter>
+ </xsl:for-each>
+
+ <xsl:apply-templates select="briefdescription" mode="passthrough"/>
+ <xsl:apply-templates select="detaileddescription" mode="passthrough"/>
+ <xsl:apply-templates select="inbodydescription" mode="passthrough"/>
+ </macro>
+ </xsl:when>
+
+ <xsl:when test="@kind='function'">
+ <xsl:call-template name="function">
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="@kind='typedef'">
+ <xsl:call-template name="typedef">
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="@kind='variable'">
+ <xsl:call-template name="variable" />
+ </xsl:when>
+
+ <xsl:when test="@kind='enum'">
+ <xsl:call-template name="enum" />
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:call-template name="kind-error-message">
+ <xsl:with-param name="message" select="'Cannot handle toplevel memberdef element'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="innerclass" mode="toplevel">
+ <xsl:param name="with-namespace-refs"/>
+ <xsl:param name="in-file"/>
+
+ <xsl:variable name="name">
+ <xsl:call-template name="strip-qualifiers">
+ <xsl:with-param name="name" select="."/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <!-- Only process this if it is indeed global -->
+ <xsl:if test=".=$name">
+ <xsl:apply-templates select="key('compounds-by-id', @refid)">
+ <xsl:with-param name="with-namespace-refs"
+ select="$with-namespace-refs"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="innerclass">
+ <xsl:param name="with-namespace-refs"/>
+ <xsl:param name="in-file"/>
+
+ <xsl:apply-templates select="key('compounds-by-id', @refid)">
+ <xsl:with-param name="with-namespace-refs"
+ select="$with-namespace-refs"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <!-- Classes -->
+ <xsl:template match="templateparamlist" mode="template">
+ <template>
+ <xsl:apply-templates mode="template"/>
+ </template>
+ </xsl:template>
+
+ <xsl:template match="param" mode="template">
+ <xsl:choose>
+ <xsl:when test="string(type)='class' or string(type)='typename'">
+ <xsl:variable name="name" select="normalize-space(string(declname))"/>
+ <template-type-parameter>
+ <xsl:attribute name="name">
+ <xsl:value-of select="normalize-space(string(declname))"/>
+ </xsl:attribute>
+ <xsl:if test="defval">
+ <default>
+ <xsl:apply-templates select="defval/*|defval/text()"
+ mode="passthrough"/>
+ </default>
+ </xsl:if>
+ <xsl:for-each select="../../detaileddescription//parameterlist[@kind='templateparam']/parameteritem">
+ <xsl:if test="string(parameternamelist/parametername)=$name">
+ <purpose>
+ <xsl:apply-templates select="parameterdescription/para" mode="passthrough"/>
+ </purpose>
+ </xsl:if>
+ </xsl:for-each>
+ </template-type-parameter>
+ </xsl:when>
+ <!-- Doxygen 1.5.8 generates odd xml for template type parameters.
+ This deals with that -->
+ <xsl:when test="not(declname) and
+ (starts-with(string(type), 'class ') or starts-with(string(type), 'typename '))">
+ <template-type-parameter>
+ <xsl:variable name="name">
+ <xsl:value-of select="normalize-space(substring-after(string(type), ' '))"/>
+ </xsl:variable>
+ <xsl:attribute name="name">
+ <xsl:value-of select="$name"/>
+ </xsl:attribute>
+ <xsl:if test="defval">
+ <default>
+ <xsl:apply-templates select="defval/*|defval/text()"
+ mode="passthrough"/>
+ </default>
+ </xsl:if>
+ <xsl:for-each select="../../detaileddescription//parameterlist[@kind='templateparam']/parameteritem">
+ <xsl:if test="string(parameternamelist/parametername)=$name">
+ <purpose>
+ <xsl:apply-templates select="parameterdescription/para" mode="passthrough"/>
+ </purpose>
+ </xsl:if>
+ </xsl:for-each>
+ </template-type-parameter>
+ </xsl:when>
+ <xsl:otherwise>
+ <template-nontype-parameter>
+ <xsl:variable name="name">
+ <xsl:value-of select="normalize-space(string(declname))"/>
+ </xsl:variable>
+ <xsl:attribute name="name">
+ <xsl:value-of select="$name"/>
+ </xsl:attribute>
+ <type>
+ <xsl:apply-templates select="type"/>
+ </type>
+ <xsl:if test="defval">
+ <default>
+ <xsl:apply-templates select="defval/*|defval/text()"
+ mode="passthrough"/>
+ </default>
+ </xsl:if>
+ <xsl:for-each select="../../detaileddescription//parameterlist[@kind='templateparam']/parameteritem">
+ <xsl:if test="string(parameternamelist/parametername)=$name">
+ <purpose>
+ <xsl:apply-templates select="parameterdescription/para" mode="passthrough"/>
+ </purpose>
+ </xsl:if>
+ </xsl:for-each>
+ </template-nontype-parameter>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="templateparamlist"/>
+
+ <!-- "Parse" a specialization from part of a name -->
+ <xsl:template name="specialization">
+ <xsl:param name="specialization"/>
+
+ <xsl:choose>
+ <xsl:when test="contains($specialization, ',')">
+ <template-arg>
+ <xsl:value-of
+ select="normalize-space(substring-before($specialization, ','))"/>
+ </template-arg>
+ <xsl:call-template name="specialization">
+ <xsl:with-param name="specialization"
+ select="substring-after($specialization, ',')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <template-arg>
+ <xsl:value-of select="normalize-space($specialization)"/>
+ </template-arg>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Inheritance -->
+ <xsl:template match="basecompoundref" mode="inherit">
+ <xsl:choose>
+ <xsl:when test="contains(string(.), $boost.doxygen.detail)"/>
+ <xsl:otherwise>
+ <inherit>
+ <!-- Access specifier for inheritance -->
+ <xsl:attribute name="access">
+ <xsl:value-of select="@prot"/>
+ </xsl:attribute>
+ <!-- TBD: virtual vs. non-virtual inheritance -->
+
+ <xsl:apply-templates mode="passthrough"/>
+ </inherit>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="basecompoundref"/>
+
+ <!-- Skip over sections: they aren't very useful at all -->
+ <xsl:template match="sectiondef">
+ <xsl:param name="in-file" select="''"/>
+
+ <xsl:choose>
+ <xsl:when test="@kind='public-static-func'">
+ <!-- TBD: pass on the fact that these are static functions -->
+ <method-group name="public static functions">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-section" select="true()"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </method-group>
+ </xsl:when>
+ <xsl:when test="@kind='protected-static-func'">
+ <!-- TBD: pass on the fact that these are static functions -->
+ <method-group name="protected static functions">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-section" select="true()"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </method-group>
+ </xsl:when>
+ <xsl:when test="@kind='private-static-func'">
+ <!-- TBD: pass on the fact that these are static functions -->
+ <method-group name="private static functions">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-section" select="true()"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </method-group>
+ </xsl:when>
+ <xsl:when test="@kind='public-func'">
+ <xsl:variable name="members" select="./memberdef"/>
+ <xsl:variable name="num-internal-only">
+ <xsl:value-of
+ select="count($members[contains(detaileddescription/para,
+ 'INTERNAL ONLY')])"/>
+ </xsl:variable>
+ <xsl:if test="$num-internal-only &lt; count($members)">
+ <method-group name="public member functions">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-section" select="true()"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </method-group>
+ <xsl:apply-templates/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="@kind='protected-func'">
+ <method-group name="protected member functions">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-section" select="true()"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </method-group>
+ <xsl:apply-templates/>
+ </xsl:when>
+ <xsl:when test="@kind='private-func'">
+ <xsl:variable name="members" select="./memberdef"/>
+ <xsl:variable name="num-internal-only">
+ <xsl:value-of
+ select="count($members[contains(detaileddescription/para,
+ 'INTERNAL ONLY')])"/>
+ </xsl:variable>
+ <xsl:if test="$num-internal-only &lt; count($members)">
+ <method-group name="private member functions">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-section" select="true()"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </method-group>
+ </xsl:if>
+ <xsl:apply-templates/>
+ </xsl:when>
+ <xsl:when test="@kind='friend'">
+ <xsl:if test="./memberdef/detaileddescription/para or ./memberdef/briefdescription/para">
+ <method-group name="friend functions">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-section" select="true()"/>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </method-group>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="@kind='public-static-attrib' or @kind='public-attrib'">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="@kind='public-type'">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="@kind='private-type'">
+ <!--skip private members-->
+ </xsl:when>
+ <xsl:when test="@kind='private-static-attrib' or @kind='private-attrib'">
+ <!--skip private members-->
+ </xsl:when>
+ <xsl:when test="@kind='func'">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="@kind='typedef'">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="@kind='var'">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="@kind='enum'">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="@kind='user-defined'">
+ <xsl:apply-templates>
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="@kind=''">
+ <xsl:apply-templates select="memberdef[generate-id() =
+ generate-id(key('members-by-id', @id))]">
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="kind-error-message">
+ <xsl:with-param name="message" select="'Cannot handle sectiondef'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Handle member definitions -->
+ <xsl:template match="memberdef">
+ <!-- True when we're inside a section -->
+ <xsl:param name="in-section" select="false()"/>
+ <xsl:param name="in-file" select="''"/>
+
+ <xsl:choose>
+ <!-- If the string INTERNAL ONLY is in the description, don't
+ emit this entity. This hack is necessary because Doxygen doesn't
+ tell us what is \internal and what isn't. -->
+ <xsl:when test="contains(detaileddescription/para, 'INTERNAL ONLY')"/>
+ <xsl:when test="contains(briefdescription/para, 'INTERNAL ONLY')"/>
+ <xsl:when test="contains(inbodydescription/para, 'INTERNAL ONLY')"/>
+
+ <xsl:when test="@kind='typedef'">
+ <xsl:call-template name="typedef">
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="@kind='function'">
+ <xsl:choose>
+ <xsl:when test="ancestor::compounddef/attribute::kind='namespace'">
+ <xsl:call-template name="function">
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- We are in a class -->
+ <!-- The name of the class we are in -->
+ <xsl:variable name="in-class">
+ <xsl:call-template name="strip-qualifiers">
+ <xsl:with-param name="name"
+ select="string(ancestor::compounddef/compoundname/text())"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="string(name/text())=$in-class">
+ <xsl:if test="not ($in-section)">
+ <xsl:call-template name="constructor"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="string(name/text())=concat('~',$in-class)">
+ <xsl:if test="not ($in-section)">
+ <xsl:call-template name="destructor"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="string(name/text())='operator='">
+ <xsl:if test="not ($in-section)">
+ <xsl:call-template name="copy-assignment"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="normalize-space(string(type))=''
+ and contains(name/text(), 'operator ')">
+ <xsl:if test="$in-section">
+ <xsl:call-template name="conversion-operator"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$in-section">
+ <xsl:call-template name="method"/>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@kind='friend'">
+ <xsl:if test="./detaileddescription/para or ./briefdescription/para">
+ <xsl:call-template name="method"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="@kind='enum'">
+ <xsl:call-template name="enum">
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="@kind='variable'">
+ <xsl:call-template name="variable">
+ <xsl:with-param name="in-file" select="$in-file"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="kind-error-message">
+ <xsl:with-param name="message" select="'Cannot handle memberdef element'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Display typedefs -->
+ <xsl:template name="typedef">
+ <xsl:param name="in-file" select="''"/>
+
+ <xsl:if test="string(location/attribute::file)=$in-file">
+ <!-- TBD: Handle public/protected/private -->
+ <typedef>
+ <!-- Name of the type -->
+ <xsl:attribute name="name">
+ <xsl:value-of select="name/text()"/>
+ </xsl:attribute>
+
+ <xsl:apply-templates select="briefdescription" mode="passthrough"/>
+ <xsl:apply-templates select="detaileddescription" mode="passthrough"/>
+ <xsl:apply-templates select="inbodydescription" mode="passthrough"/>
+
+ <type><xsl:apply-templates select="type"/></type>
+ </typedef>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Handle function parameters -->
+ <xsl:template match="param" mode="function">
+ <parameter>
+ <!-- Parameter name -->
+ <xsl:attribute name="name">
+ <xsl:value-of select="normalize-space(declname/text())"/>
+ </xsl:attribute>
+
+ <!-- Parameter type -->
+ <paramtype><xsl:apply-templates select="type"/></paramtype>
+
+ <!-- Default argument -->
+ <xsl:if test="defval">
+ <default>
+ <xsl:choose>
+ <xsl:when test="contains(string(defval), $boost.doxygen.detail)">
+ <emphasis>unspecified</emphasis>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="defval/*|defval/text()"
+ mode="passthrough"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </default>
+ </xsl:if>
+
+ <!-- Parameter description -->
+ <xsl:variable name="name">
+ <xsl:value-of select="normalize-space(declname/text())"/>
+ </xsl:variable>
+
+ <xsl:apply-templates select="../*[self::detaileddescription or self::inbodydescription]//parameterlist[attribute::kind='param']/*"
+ mode="parameter.description">
+ <xsl:with-param name="name">
+ <xsl:value-of select="$name"/>
+ </xsl:with-param>
+ </xsl:apply-templates>
+ </parameter>
+ </xsl:template>
+
+ <xsl:template match="parameteritem" mode="parameter.description">
+ <!-- The parameter name we are looking for -->
+ <xsl:param name="name"/>
+
+ <xsl:if test="string(parameternamelist/parametername) = $name">
+ <description>
+ <xsl:apply-templates select="parameterdescription/para" mode="passthrough"/>
+ </description>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- For older versions of Doxygen, which didn't use parameteritem -->
+ <xsl:template match="parameterdescription" mode="parameter.description">
+ <!-- The parameter name we are looking for -->
+ <xsl:param name="name"/>
+
+ <!-- The parametername node associated with this description -->
+ <xsl:variable name="name-node" select="preceding-sibling::*[1]"/>
+
+ <xsl:if test="string($name-node/text()) = $name">
+ <description>
+ <xsl:apply-templates select="para" mode="passthrough"/>
+ </description>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Handle function children -->
+ <xsl:template name="function.children">
+ <xsl:param name="is-overloaded" select="false()"/>
+
+ <xsl:if test="not($is-overloaded)">
+ <!-- Emit template header -->
+ <xsl:apply-templates select="templateparamlist" mode="template"/>
+
+ <!-- Emit function parameters -->
+ <xsl:apply-templates select="param" mode="function"/>
+ </xsl:if>
+
+ <!-- The description -->
+ <xsl:apply-templates select="briefdescription" mode="passthrough"/>
+ <xsl:apply-templates select="detaileddescription" mode="passthrough"/>
+ <xsl:apply-templates select="inbodydescription" mode="passthrough"/>
+
+ <xsl:apply-templates
+ select="*[self::detaileddescription or self::inbodydescription]/para/simplesect[@kind='pre']"
+ mode="function-clauses"/>
+ <xsl:apply-templates
+ select="*[self::detaileddescription or self::inbodydescription]/para/simplesect[@kind='post']"
+ mode="function-clauses"/>
+ <xsl:apply-templates
+ select="*[self::detaileddescription or self::inbodydescription]/para/simplesect[@kind='return']"
+ mode="function-clauses"/>
+ <xsl:if test="*[self::detaileddescription or self::inbodydescription]/para/parameterlist[@kind='exception']">
+ <throws>
+ <xsl:apply-templates
+ select="*[self::detaileddescription or self::inbodydescription]/para/parameterlist[@kind='exception']"
+ mode="function-clauses"/>
+ </throws>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Handle free functions -->
+ <xsl:template name="function">
+ <xsl:param name="in-file" select="''"/>
+
+ <xsl:variable name="firstpara"
+ select="normalize-space(detaileddescription/para[1])"/>
+ <xsl:if test="string(location/attribute::file)=$in-file
+ and
+ not($firstpara=normalize-space($boost.doxygen.overload))">
+
+ <xsl:variable name="next-node" select="following-sibling::*[1]"/>
+ <xsl:variable name="has-overload">
+ <xsl:if test="not(local-name($next-node)='memberdef')">
+ false
+ </xsl:if>
+ <xsl:if test="not(string($next-node/name/text())=string(name/text()))">
+ false
+ </xsl:if>
+ <xsl:if
+ test="not(normalize-space($next-node/detaileddescription/para[1])
+ =normalize-space($boost.doxygen.overload))">
+ false
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="not(contains($has-overload, 'false'))">
+ <overloaded-function>
+ <xsl:attribute name="name">
+ <xsl:call-template name="normalize-name"/>
+ </xsl:attribute>
+
+ <xsl:call-template name="overload-signatures"/>
+ <xsl:call-template name="function.children">
+ <xsl:with-param name="is-overloaded" select="true()"/>
+ </xsl:call-template>
+ </overloaded-function>
+ </xsl:when>
+ <xsl:otherwise>
+ <function>
+ <xsl:attribute name="name">
+ <xsl:call-template name="normalize-name"/>
+ </xsl:attribute>
+
+ <!-- Return type -->
+ <type><xsl:apply-templates select="type"/></type>
+
+ <xsl:call-template name="function.children"/>
+ </function>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Emit overload signatures -->
+ <xsl:template name="overload-signatures">
+ <xsl:param name="node" select="."/>
+ <xsl:param name="name" select="string(name/text())"/>
+ <xsl:param name="first" select="true()"/>
+
+ <xsl:choose>
+ <xsl:when test="not(local-name($node)='memberdef')"/>
+ <xsl:when test="not(string($node/name/text())=$name)"/>
+ <xsl:when test="not(normalize-space($node/detaileddescription/para[1])
+ =normalize-space($boost.doxygen.overload))
+ and not($first)"/>
+ <xsl:otherwise>
+ <signature>
+ <type>
+ <xsl:apply-templates select="$node/type"/>
+ </type>
+ <xsl:apply-templates select="$node/templateparamlist"
+ mode="template"/>
+ <xsl:apply-templates select="$node/param" mode="function"/>
+ </signature>
+
+ <xsl:call-template name="overload-signatures">
+ <xsl:with-param name="node" select="$node/following-sibling::*[1]"/>
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="first" select="false()"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Handle constructors -->
+ <xsl:template name="constructor">
+ <constructor>
+ <xsl:if test="@explicit = 'yes'">
+ <xsl:attribute name="specifiers">explicit</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="function.children"/>
+ </constructor>
+ </xsl:template>
+
+ <!-- Handle Destructors -->
+ <xsl:template name="destructor">
+ <destructor>
+ <xsl:call-template name="function.children"/>
+ </destructor>
+ </xsl:template>
+
+ <!-- Handle Copy Assignment -->
+ <xsl:template name="copy-assignment">
+ <copy-assignment>
+ <xsl:call-template name="function.children"/>
+ </copy-assignment>
+ </xsl:template>
+
+ <!-- Handle conversion operator -->
+ <xsl:template name="conversion-operator">
+ <method>
+ <xsl:attribute name="name">
+ <xsl:text>conversion-operator</xsl:text>
+ </xsl:attribute>
+
+ <!-- CV Qualifiers -->
+ <xsl:if test="not (@const='no' and @volatile='no')">
+ <xsl:attribute name="cv">
+ <xsl:if test="@const='yes'">
+ <xsl:text>const</xsl:text>
+ </xsl:if>
+ <xsl:if test="@volatile='yes'">
+ <xsl:if test="@const='yes'">
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ <xsl:text>volatile</xsl:text>
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:if>
+
+ <xsl:if test="@explicit = 'yes'">
+ <xsl:attribute name="specifiers">explicit</xsl:attribute>
+ </xsl:if>
+
+ <!-- Conversion type -->
+ <type>
+ <xsl:value-of select="substring-after(name/text(), 'operator ')"/>
+ </type>
+
+ <xsl:call-template name="function.children"/>
+ </method>
+ </xsl:template>
+
+ <!-- Handle methods -->
+ <xsl:template name="method">
+ <method>
+ <xsl:attribute name="name">
+ <xsl:value-of select="name/text()"/>
+ </xsl:attribute>
+
+ <!-- CV Qualifiers -->
+ <xsl:if test="not (@const='no' and @volatile='no')">
+ <xsl:attribute name="cv">
+ <xsl:if test="@const='yes'">
+ <xsl:text>const</xsl:text>
+ </xsl:if>
+ <xsl:if test="@volatile='yes'">
+ <xsl:if test="@const='yes'">
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ <xsl:text>volatile</xsl:text>
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:if>
+
+ <!-- Return type -->
+ <xsl:element name="type">
+ <!-- Cheat on virtual and static by dropping them into the type -->
+ <xsl:if test="@static='yes'">
+ <xsl:text>static </xsl:text>
+ </xsl:if>
+
+ <xsl:if test="@virtual='yes'">
+ <xsl:text>virtual </xsl:text>
+ </xsl:if>
+
+ <xsl:apply-templates select="type"/>
+ </xsl:element>
+
+ <xsl:call-template name="function.children"/>
+ </method>
+ </xsl:template>
+
+ <!-- Handle member variables -->
+ <xsl:template name="variable">
+ <xsl:param name="in-file"/>
+ <xsl:if test="string(location/attribute::file)=$in-file">
+ <data-member>
+ <xsl:attribute name="name">
+ <xsl:value-of select="name/text()"/>
+ </xsl:attribute>
+
+ <!-- Specifiers -->
+ <xsl:if test="@static = 'yes'">
+ <xsl:attribute name="specifiers">static</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@mutable = 'yes'">
+ <xsl:attribute name="specifiers">mutable</xsl:attribute>
+ </xsl:if>
+
+ <type>
+ <xsl:apply-templates select="type"/>
+ </type>
+
+ <xsl:apply-templates select="briefdescription" mode="passthrough"/>
+ <xsl:apply-templates select="detaileddescription" mode="passthrough"/>
+ <xsl:apply-templates select="inbodydescription" mode="passthrough"/>
+ </data-member>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Things we ignore directly -->
+ <xsl:template match="compoundname" mode="toplevel"/>
+ <xsl:template match="includes|includedby|incdepgraph|invincdepgraph" mode="toplevel"/>
+ <xsl:template match="programlisting" mode="toplevel"/>
+ <xsl:template match="text()" mode="toplevel"/>
+
+ <xsl:template match="text()"/>
+
+ <!-- Passthrough of text -->
+ <xsl:template match="text()" mode="passthrough">
+ <xsl:value-of select="."/>
+ </xsl:template>
+ <xsl:template match="para" mode="passthrough">
+ <para>
+ <xsl:apply-templates mode="passthrough"/>
+ </para>
+ </xsl:template>
+ <xsl:template match="copydoc" mode="passthrough">
+ <xsl:apply-templates mode="passthrough"/>
+ </xsl:template>
+ <xsl:template match="verbatim" mode="passthrough">
+ <xsl:copy-of select="node()"/>
+ </xsl:template>
+
+ <xsl:template match="para/simplesect" mode="passthrough">
+ <xsl:if test="not (@kind='pre') and
+ not (@kind='return') and
+ not (@kind='post') and
+ not (@kind='attention') and
+ not (@kind='see') and
+ not (@kind='warning')
+ ">
+ <xsl:apply-templates mode="passthrough"/>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="para/simplesect[@kind='note' or @kind='attention']" mode="passthrough">
+ <note>
+ <xsl:apply-templates mode="passthrough"/>
+ </note>
+ </xsl:template>
+
+ <xsl:template match="para/simplesect[@kind='warning']" mode="passthrough">
+ <warning>
+ <xsl:apply-templates mode="passthrough"/>
+ </warning>
+ </xsl:template>
+
+ <xsl:template match="para/simplesect[@kind='par']" mode="passthrough">
+ <formalpara>
+ <xsl:apply-templates mode="passthrough"/>
+ </formalpara>
+ </xsl:template>
+
+ <xsl:template match="para/simplesect[@kind='see']" mode="passthrough">
+ <para>
+ <emphasis role="bold">
+ <xsl:text>See Also:</xsl:text>
+ </emphasis>
+ <xsl:apply-templates mode="passthrough"/>
+ </para>
+ </xsl:template>
+
+ <xsl:template match="simplesectsep" mode="passthrough">
+ <xsl:apply-templates mode="passthrough"/>
+ </xsl:template>
+
+ <xsl:template match="*" mode="passthrough">
+ <xsl:copy>
+ <xsl:copy-of select="@*"/>
+ <xsl:apply-templates mode="passthrough"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="parameterlist" mode="passthrough"/>
+
+ <xsl:template match="bold" mode="passthrough">
+ <emphasis role="bold">
+ <xsl:apply-templates mode="passthrough"/>
+ </emphasis>
+ </xsl:template>
+
+ <xsl:template match="linebreak" mode="passthrough">
+ <sbr/>
+ </xsl:template>
+
+ <xsl:template match="briefdescription" mode="passthrough">
+ <xsl:if test="text()|*">
+ <purpose>
+ <xsl:apply-templates mode="purpose"/>
+ </purpose>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="detaileddescription" mode="passthrough">
+ <xsl:if test="text()|*">
+ <description>
+ <xsl:apply-templates mode="passthrough"/>
+ </description>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="inbodydescription" mode="passthrough">
+ <xsl:if test="text()|*">
+ <description>
+ <xsl:apply-templates mode="passthrough"/>
+ </description>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Ignore ref elements for now, as there is a lot of documentation which
+ will have incorrect ref elements at the moment -->
+ <xsl:template match="ref" mode="passthrough">
+ <xsl:variable name="as-class" select="key('compounds-by-id', @refid)[@kind='class' or @kind='struct']"/>
+ <xsl:choose>
+ <xsl:when test="$as-class">
+ <classname>
+ <xsl:attribute name="alt">
+ <xsl:value-of select="$as-class/compoundname/text()"/>
+ </xsl:attribute>
+ <xsl:value-of select="text()"/>
+ </classname>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates mode="passthrough"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Handle function clauses -->
+ <xsl:template match="simplesect" mode="function-clauses">
+ <xsl:if test="@kind='pre'">
+ <requires>
+ <xsl:apply-templates mode="passthrough"/>
+ </requires>
+ </xsl:if>
+ <xsl:if test="@kind='return'">
+ <returns>
+ <xsl:apply-templates mode="passthrough"/>
+ </returns>
+ </xsl:if>
+ <xsl:if test="@kind='post'">
+ <postconditions>
+ <xsl:apply-templates mode="passthrough"/>
+ </postconditions>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="parameterlist" mode="function-clauses">
+ <xsl:if test="@kind='exception'">
+ <simpara>
+ <xsl:choose>
+ <xsl:when test="normalize-space(.//parametername//text())='nothrow'">
+ <xsl:text>Will not throw.</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <classname>
+ <xsl:value-of select=".//parametername//text()"/>
+ </classname>
+ <xsl:text> </xsl:text>
+ <xsl:apply-templates
+ select=".//parameterdescription/para/text()
+ |.//parameterdescription/para/*"
+ mode="passthrough"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </simpara>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="type">
+ <xsl:choose>
+ <xsl:when test="contains(string(.), $boost.doxygen.detail)">
+ <emphasis>unspecified</emphasis>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates mode="type"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="ref" mode="type">
+ <xsl:choose>
+ <xsl:when test="@kindref='compound'">
+ <classname>
+ <xsl:value-of select="text()"/>
+ </classname>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="text()"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="*" mode="type">
+ <xsl:value-of select="."/>
+ </xsl:template>
+
+ <!-- Normalize the names of functions, because Doxygen sometimes
+ puts in an obnoixous space. -->
+ <xsl:template name="normalize-name">
+ <xsl:param name="name" select="name/text()"/>
+
+ <xsl:choose>
+ <xsl:when test="contains($name, ' ')">
+ <xsl:value-of select="substring-before($name, ' ')"/>
+ <xsl:value-of select="substring-after($name, ' ')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Convert HTML tables into DocBook format -->
+ <xsl:template match="table" mode="passthrough">
+ <informaltable>
+ <tgroup>
+ <xsl:attribute name="cols">
+ <xsl:value-of select="@cols"/>
+ </xsl:attribute>
+
+ <tbody>
+ <xsl:apply-templates mode="table"/>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </xsl:template>
+
+ <xsl:template match="row" mode="table">
+ <row>
+ <xsl:apply-templates mode="table"/>
+ </row>
+ </xsl:template>
+
+ <xsl:template match="entry" mode="table">
+ <entry>
+ <xsl:if test="para/center">
+ <xsl:attribute name="valign">
+ <xsl:value-of select="'middle'"/>
+ </xsl:attribute>
+ <xsl:attribute name="align">
+ <xsl:value-of select="'center'"/>
+ </xsl:attribute>
+ </xsl:if>
+
+ <xsl:choose>
+ <xsl:when test="@thead='yes'">
+ <emphasis role="bold">
+ <xsl:call-template name="table-entry"/>
+ </emphasis>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="table-entry"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </entry>
+ </xsl:template>
+
+ <xsl:template name="table-entry">
+ <xsl:choose>
+ <xsl:when test="para/center">
+ <xsl:apply-templates select="para/center/*|para/center/text()"
+ mode="passthrough"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="para/*|para/text()" mode="passthrough"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Handle program listings -->
+ <xsl:template match="programlisting" mode="passthrough">
+ <programlisting>
+ <xsl:apply-templates mode="programlisting"/>
+ </programlisting>
+ </xsl:template>
+
+ <xsl:template match="highlight|codeline" mode="programlisting">
+ <xsl:apply-templates mode="programlisting"/>
+ </xsl:template>
+
+ <xsl:template match="sp" mode="programlisting">
+ <xsl:text> </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="*" mode="programlisting">
+ <xsl:apply-templates select="." mode="passthrough"/>
+ </xsl:template>
+
+ <!-- Replace top-level "para" elements with "simpara" elements in
+ the purpose -->
+ <xsl:template match="*" mode="purpose">
+ <xsl:apply-templates mode="passthrough"/>
+ </xsl:template>
+
+ <xsl:template match="text()" mode="purpose">
+ <xsl:apply-templates mode="passthrough"/>
+ </xsl:template>
+
+ <xsl:template match="para" mode="purpose">
+ <xsl:apply-templates select="*|text()" mode="passthrough"/>
+ </xsl:template>
+
+ <!--
+ Eric Niebler: Jan-8-2008
+ Here is some 3/4-baked support for LaTeX formulas in
+ Doxygen comments. Doxygen doesn't generate the PNG files
+ when outputting XML. In order to use this code, you must
+ run Doxygen first to generate HTML (and the PNG files for
+ the formulas). You can do this in a Jamfile with
+ "doxygen foo.html : <sources, etc...> ; ", where the ".html"
+ is significant. Then the png files should be copied into the
+ images/ directory (or another place relative to the html/
+ directory, as specified by $boost.doxygen.formuladir XSL
+ parameter). This can be done with a custom action in a
+ Jamfile. Finally, the docs can be built as normal.
+ See libs/accumulators/doc/Jamfile.v2 for a working example.
+ -->
+ <xsl:template match="formula" mode="passthrough">
+ <xsl:choose>
+ <xsl:when test="substring(*|text(), 1, 2) = '\['">
+ <equation>
+ <title/>
+ <alt>
+ <xsl:value-of select="*|text()"/>
+ </alt>
+ <mediaobject>
+ <imageobject role="html">
+ <imagedata format="PNG" align="center">
+ <xsl:attribute name="fileref">
+ <xsl:value-of select="concat(concat(concat($boost.doxygen.formuladir, 'form_'), @id), '.png')"/>
+ </xsl:attribute>
+ </imagedata>
+ </imageobject>
+ <textobject role="tex">
+ <phrase>
+ <xsl:value-of select="*|text()"/>
+ </phrase>
+ </textobject>
+ </mediaobject>
+ </equation>
+ </xsl:when>
+ <xsl:otherwise>
+ <inlineequation>
+ <alt>
+ <xsl:value-of select="*|text()"/>
+ </alt>
+ <inlinemediaobject>
+ <imageobject role="html">
+ <imagedata format="PNG">
+ <xsl:attribute name="fileref">
+ <xsl:value-of select="concat(concat(concat($boost.doxygen.formuladir, 'form_'), @id), '.png')"/>
+ </xsl:attribute>
+ </imagedata>
+ </imageobject>
+ <textobject role="tex">
+ <phrase>
+ <xsl:value-of select="*|text()"/>
+ </phrase>
+ </textobject>
+ </inlinemediaobject>
+ </inlineequation>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ </xsl:stylesheet>
diff --git a/tools/boostbook/xsl/dtd/dtd2boostbook.xsl b/tools/boostbook/xsl/dtd/dtd2boostbook.xsl
new file mode 100644
index 0000000000..38bf815fab
--- /dev/null
+++ b/tools/boostbook/xsl/dtd/dtd2boostbook.xsl
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+ <xsl:output method="xml" indent="yes" standalone="yes"/>
+
+ <xsl:strip-space elements="sequence-group or-group element element-name"/>
+
+ <xsl:key name="elements" match="element" use="@name"/>
+ <xsl:key name="attributes" match="attlist" use="@name"/>
+ <xsl:key name="attribute-purposes" match="attpurpose" use="@name"/>
+
+ <xsl:template match="dtd">
+ <section id="reference">
+ <title>Reference</title>
+ <para>
+ <xsl:text>Elements:</xsl:text>
+ <itemizedlist spacing="compact">
+ <xsl:apply-templates select="element" mode="synopsis">
+ <xsl:sort select="@name"/>
+ </xsl:apply-templates>
+ </itemizedlist>
+ </para>
+ <xsl:apply-templates select="element"/>
+ </section>
+ </xsl:template>
+
+ <!-- Element synopsis -->
+ <xsl:template match="element" mode="synopsis">
+ <listitem>
+ <simpara>
+ <link>
+ <xsl:attribute name="linkend">
+ <xsl:value-of select="concat('boostbook.dtd.',@name)"/>
+ </xsl:attribute>
+ <xsl:text>Element </xsl:text>
+ <sgmltag><xsl:value-of select="@name"/></sgmltag>
+ <xsl:text> - </xsl:text>
+ <xsl:apply-templates select="purpose"/>
+ </link>
+ </simpara>
+ </listitem>
+ </xsl:template>
+
+ <!-- Elements are transformed into DocBook refentry elements -->
+ <xsl:template match="element">
+ <refentry>
+ <xsl:attribute name="id">
+ <xsl:value-of select="concat('boostbook.dtd.',@name)"/>
+ </xsl:attribute>
+
+ <refmeta>
+ <refentrytitle>
+ BoostBook element <sgmltag><xsl:value-of select="@name"/></sgmltag>
+ </refentrytitle>
+ <manvolnum>9</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname><xsl:value-of select="@name"/></refname>
+ <refpurpose><xsl:apply-templates select="purpose"/></refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <xsl:value-of select="@name"/><xsl:text> ::= </xsl:text>
+ <xsl:apply-templates select="content-model-expanded"/>
+ </refsynopsisdiv>
+ <xsl:apply-templates select="description"/>
+ <xsl:apply-templates select="key('attributes', @name)"/>
+ </refentry>
+ </xsl:template>
+
+ <xsl:template match="content-model-expanded">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <!-- Sequences -->
+ <xsl:template match="sequence-group">
+ <xsl:param name="separator" select="''"/>
+
+ <xsl:if test="preceding-sibling::*">
+ <xsl:value-of select="$separator"/>
+ </xsl:if>
+ <xsl:text>(</xsl:text>
+ <xsl:apply-templates>
+ <xsl:with-param name="separator" select="', '"/>
+ </xsl:apply-templates>
+ <xsl:text>)</xsl:text>
+ <xsl:value-of select="@occurrence"/>
+ </xsl:template>
+
+ <!-- Alternatives -->
+ <xsl:template match="or-group">
+ <xsl:param name="separator" select="''"/>
+
+ <xsl:if test="preceding-sibling::*">
+ <xsl:value-of select="$separator"/>
+ </xsl:if>
+ <xsl:text>(</xsl:text>
+ <xsl:apply-templates>
+ <xsl:with-param name="separator" select="'| '"/>
+ </xsl:apply-templates>
+ <xsl:text>)</xsl:text>
+ <xsl:value-of select="@occurrence"/>
+ </xsl:template>
+
+ <!-- Element references -->
+ <xsl:template match="element-name">
+ <xsl:param name="separator" select="''"/>
+
+ <xsl:if test="preceding-sibling::*">
+ <xsl:value-of select="$separator"/>
+ </xsl:if>
+
+ <xsl:variable name="element-node" select="key('elements', @name)"/>
+
+ <xsl:choose>
+ <xsl:when test="$element-node">
+ <link>
+ <xsl:attribute name="linkend">
+ <xsl:value-of select="concat('boostbook.dtd.',@name)"/>
+ </xsl:attribute>
+ <xsl:value-of select="@name"/>
+ </link>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:value-of select="@occurrence"/>
+ </xsl:template>
+
+ <!-- #PCDATA -->
+ <xsl:template match="pcdata">
+ <xsl:param name="separator" select="''"/>
+
+ <xsl:if test="preceding-sibling::*">
+ <xsl:value-of select="$separator"/>
+ </xsl:if>
+
+ <xsl:text>#PCDATA</xsl:text>
+ </xsl:template>
+
+ <!-- ANY -->
+ <xsl:template match="any">
+ <xsl:text>ANY</xsl:text>
+ </xsl:template>
+
+ <!-- EMPTY -->
+ <xsl:template match="empty">
+ <xsl:text>EMPTY</xsl:text>
+ </xsl:template>
+
+ <!-- Just copy anything in a purpose element -->
+ <xsl:template match="purpose">
+ <xsl:copy-of select="text()|*"/>
+ </xsl:template>
+
+ <!-- Just copy anything in a description element, but place it in a
+ section. -->
+ <xsl:template match="description">
+ <refsection>
+ <title>Description</title>
+ <xsl:copy-of select="text()|*"/>
+ </refsection>
+ </xsl:template>
+
+ <!-- Attributes -->
+ <xsl:template match="attlist">
+ <refsection>
+ <title>Attributes</title>
+
+ <informaltable>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>Value</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+ <xsl:apply-templates/>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </refsection>
+ </xsl:template>
+
+ <!-- Attribute -->
+ <xsl:template match="attribute">
+ <row>
+ <entry><xsl:value-of select="@name"/></entry>
+ <entry><xsl:value-of select="@type"/></entry>
+ <entry><xsl:value-of select="@value"/></entry>
+ <entry>
+ <xsl:choose>
+ <xsl:when test="purpose">
+ <xsl:apply-templates select="purpose"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="key('attribute-purposes', @name)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </entry>
+ </row>
+ </xsl:template>
+
+ <!-- Eat attribute declarations -->
+ <xsl:template match="attdecl"/>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/error.xsl b/tools/boostbook/xsl/error.xsl
new file mode 100644
index 0000000000..a1c160107a
--- /dev/null
+++ b/tools/boostbook/xsl/error.xsl
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:template name="print.warning.context">
+ <xsl:message>
+ <xsl:text> In </xsl:text>
+ <xsl:call-template name="fully-qualified-name">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:message>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/fo.xsl b/tools/boostbook/xsl/fo.xsl
new file mode 100644
index 0000000000..422811cb80
--- /dev/null
+++ b/tools/boostbook/xsl/fo.xsl
@@ -0,0 +1,395 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2003 Douglas Gregor -->
+<!-- Distributed under the Boost Software License, Version 1.0. -->
+<!-- (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ version="1.0">
+
+ <!-- Import the FO stylesheet -->
+ <xsl:import
+ href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl"/>
+
+ <xsl:param name="chapter.autolabel" select="0"/>
+ <xsl:param name="refentry.generate.name" select="0"/>
+ <xsl:param name="refentry.generate.title" select="1"/>
+ <xsl:param name="fop1.extensions" select="1"/>
+ <xsl:param name="make.year.ranges" select="1"/>
+ <xsl:param name="ulink.show" select="0"/>
+
+
+ <!--
+ The following code sets which sections start new pages in the PDF document flow.
+
+ The parameter "boost.section.newpage.depth" set how far down the hierarchy the
+ page breaks go. Defaults to 1 (the same as html chunking), in which case only
+ top level sections start a new page, set to a higher value to force nested sections
+ onto new pages as well.
+
+ For top level sections (level 1), we use "break-before" which forces the very first
+ section onto a separate page from the TOC.
+
+ For nested sections (level 2 and greater) we use "break-after" which keeps nested
+ sections together with their enclosing section (rationale: the enclosing section
+ often has nothing but a title, and no content except the nested sections, and we
+ don't want a page break right after a section title!).
+
+ For reference sections, we turn page breaks *off* by setting "refentry.pagebreak" to 0.
+ This is for the same reason we use "break-after" for nested sections - we want reference
+ entries to be on the same page as the title and synopsis which encloses them. Ideally
+ we'd use "break-after" here too, but I can't find an easy to to fix that.
+
+ Finally note that TOC's and Indexes don't get page breaks forced after them.
+ Again there's no easy fix here, *except* for the top level TOC which gets a page break
+ after it thanks to the "break-before" on level 1 sections. Unfortunately this means
+ there's no break after the last section and before the first Index, *unless* the
+ final section has nested sections which may then trigger one!
+
+ We could fix all this by cut-and-pasting the relevant XSL from the stylesheets to here
+ and making sure everything uses "break-after", but whether it's worth it is questionable...?
+
+ -->
+
+ <xsl:param name="boost.section.newpage.depth" select="1"/>
+ <xsl:param name="refentry.pagebreak" select="0"/>
+
+ <xsl:attribute-set name="section.level1.properties" use-attribute-sets="section.properties">
+ <xsl:attribute name="break-before">
+ <xsl:if test="($boost.section.newpage.depth &gt; 0)">
+ page
+ </xsl:if>
+ <xsl:if test="not($boost.section.newpage.depth &gt; 0)">
+ auto
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:attribute-set>
+
+ <xsl:attribute-set name="section.level2.properties" use-attribute-sets="section.properties">
+ <xsl:attribute name="break-after">
+ <xsl:if test="($boost.section.newpage.depth &gt; 1)">
+ page
+ </xsl:if>
+ <xsl:if test="not($boost.section.newpage.depth &gt; 1)">
+ auto
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:attribute-set>
+
+ <xsl:attribute-set name="section.level3.properties" use-attribute-sets="section.properties">
+ <xsl:attribute name="break-after">
+ <xsl:if test="($boost.section.newpage.depth &gt; 2)">
+ page
+ </xsl:if>
+ <xsl:if test="not($boost.section.newpage.depth &gt; 2)">
+ auto
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:attribute-set>
+
+ <xsl:attribute-set name="section.level4.properties" use-attribute-sets="section.properties">
+ <xsl:attribute name="break-after">
+ <xsl:if test="($boost.section.newpage.depth &gt; 3)">
+ page
+ </xsl:if>
+ <xsl:if test="not($boost.section.newpage.depth &gt; 3)">
+ auto
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:attribute-set>
+
+ <xsl:attribute-set name="section.level5.properties" use-attribute-sets="section.properties">
+ <xsl:attribute name="break-after">
+ <xsl:if test="($boost.section.newpage.depth &gt; 4)">
+ page
+ </xsl:if>
+ <xsl:if test="not($boost.section.newpage.depth &gt; 4)">
+ auto
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:attribute-set>
+
+ <xsl:attribute-set name="section.level6.properties" use-attribute-sets="section.properties">
+ <xsl:attribute name="break-after">
+ <xsl:if test="($boost.section.newpage.depth &gt; 5)">
+ page
+ </xsl:if>
+ <xsl:if test="not($boost.section.newpage.depth &gt; 5)">
+ auto
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:attribute-set>
+
+ <!-- The question and answer templates are copied here from the
+ 1.61.3 DocBook XSL stylesheets so that we can eliminate the emission
+ of id attributes in the emitted fo:list-item-label elements. FOP
+ 0.20.5 has problems with these id attributes, and they are otherwise
+ unused. -->
+<xsl:template match="question">
+ <xsl:variable name="id"><xsl:call-template name="object.id"/></xsl:variable>
+
+ <xsl:variable name="entry.id">
+ <xsl:call-template name="object.id">
+ <xsl:with-param name="object" select="parent::*"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="deflabel">
+ <xsl:choose>
+ <xsl:when test="ancestor-or-self::*[@defaultlabel]">
+ <xsl:value-of select="(ancestor-or-self::*[@defaultlabel])[last()]
+ /@defaultlabel"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$qanda.defaultlabel"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <fo:list-item id="{$entry.id}" xsl:use-attribute-sets="list.item.spacing">
+ <fo:list-item-label end-indent="label-end()">
+ <xsl:choose>
+ <xsl:when test="$deflabel = 'none'">
+ <fo:block/>
+ </xsl:when>
+ <xsl:otherwise>
+ <fo:block>
+ <xsl:apply-templates select="." mode="label.markup"/>
+ <xsl:text>.</xsl:text> <!-- FIXME: Hack!!! This should be in the locale! -->
+ </fo:block>
+ </xsl:otherwise>
+ </xsl:choose>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <xsl:choose>
+ <xsl:when test="$deflabel = 'none'">
+ <fo:block font-weight="bold">
+ <xsl:apply-templates select="*[local-name(.)!='label']"/>
+ </fo:block>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="*[local-name(.)!='label']"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </fo:list-item-body>
+ </fo:list-item>
+</xsl:template>
+
+<xsl:template match="answer">
+ <xsl:variable name="id"><xsl:call-template name="object.id"/></xsl:variable>
+ <xsl:variable name="entry.id">
+ <xsl:call-template name="object.id">
+ <xsl:with-param name="object" select="parent::*"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="deflabel">
+ <xsl:choose>
+ <xsl:when test="ancestor-or-self::*[@defaultlabel]">
+ <xsl:value-of select="(ancestor-or-self::*[@defaultlabel])[last()]
+ /@defaultlabel"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$qanda.defaultlabel"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <fo:list-item xsl:use-attribute-sets="list.item.spacing">
+ <fo:list-item-label end-indent="label-end()">
+ <xsl:choose>
+ <xsl:when test="$deflabel = 'none'">
+ <fo:block/>
+ </xsl:when>
+ <xsl:otherwise>
+ <fo:block>
+ <!-- FIXME: Hack!!! This should be in the locale! -->
+ <xsl:variable name="answer.label">
+ <xsl:apply-templates select="." mode="label.markup"/>
+ </xsl:variable>
+ <xsl:copy-of select="$answer.label"/>
+ <xsl:if test="string($answer.label) != ''">
+ <xsl:text>.</xsl:text>
+ </xsl:if>
+ </fo:block>
+ </xsl:otherwise>
+ </xsl:choose>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <xsl:apply-templates select="*[local-name(.)!='label']"/>
+ </fo:list-item-body>
+ </fo:list-item>
+</xsl:template>
+
+<!--
+
+ The following rules apply syntax highlighting to phrases
+ that have been appropriately marked up, the highlighting
+ used is the same as that used by our CSS style sheets,
+ but potentially we have the option to do better here
+ since we can add bold and italic formatting quite easily
+
+ -->
+
+<xsl:template match="//phrase[@role='keyword' and
+ (ancestor::programlisting or
+ ancestor::synopsis or
+ ancestor::literallayout)]">
+ <fo:inline color="#0000AA"><xsl:apply-templates/></fo:inline>
+</xsl:template>
+<xsl:template match="//phrase[@role='special' and
+ (ancestor::programlisting or
+ ancestor::synopsis or
+ ancestor::literallayout)]">
+ <fo:inline color="#707070"><xsl:apply-templates/></fo:inline>
+</xsl:template>
+<xsl:template match="//phrase[@role='preprocessor' and
+ (ancestor::programlisting or
+ ancestor::synopsis or
+ ancestor::literallayout)]">
+ <fo:inline color="#402080"><xsl:apply-templates/></fo:inline>
+</xsl:template>
+<xsl:template match="//phrase[@role='char' and
+ (ancestor::programlisting or
+ ancestor::synopsis or
+ ancestor::literallayout)]">
+ <fo:inline color="teal"><xsl:apply-templates/></fo:inline>
+</xsl:template>
+<xsl:template match="//phrase[@role='comment' and
+ (ancestor::programlisting or
+ ancestor::synopsis or
+ ancestor::literallayout)]">
+ <fo:inline color="#800000"><xsl:apply-templates/></fo:inline>
+</xsl:template>
+<xsl:template match="//phrase[@role='string' and
+ (ancestor::programlisting or
+ ancestor::synopsis or
+ ancestor::literallayout)]">
+ <fo:inline color="teal"><xsl:apply-templates/></fo:inline>
+</xsl:template>
+<xsl:template match="//phrase[@role='number' and
+ (ancestor::programlisting or
+ ancestor::synopsis or
+ ancestor::literallayout)]">
+ <fo:inline color="teal"><xsl:apply-templates/></fo:inline>
+</xsl:template>
+<xsl:template match="//phrase[@role='white_bkd' and
+ (ancestor::programlisting or
+ ancestor::synopsis or
+ ancestor::literallayout)]">
+ <fo:inline color="#FFFFFF"><xsl:apply-templates/></fo:inline>
+</xsl:template>
+<xsl:template match="//phrase[@role='dk_grey_bkd' and
+ (ancestor::programlisting or
+ ancestor::synopsis or
+ ancestor::literallayout)]">
+ <fo:inline color="#999999"><xsl:apply-templates/></fo:inline>
+</xsl:template>
+
+<!--
+Make all hyperlinks blue colored:
+-->
+<xsl:attribute-set name="xref.properties">
+ <xsl:attribute name="color">blue</xsl:attribute>
+</xsl:attribute-set>
+
+<!--
+Put a box around admonishments and keep them together:
+-->
+<xsl:attribute-set name="graphical.admonition.properties">
+ <xsl:attribute name="border-color">#FF8080</xsl:attribute>
+ <xsl:attribute name="border-width">1px</xsl:attribute>
+ <xsl:attribute name="border-style">solid</xsl:attribute>
+ <xsl:attribute name="padding-left">0.2cm</xsl:attribute>
+ <xsl:attribute name="padding-right">0.2cm</xsl:attribute>
+ <xsl:attribute name="padding-top">0.2cm</xsl:attribute>
+ <xsl:attribute name="padding-bottom">0.2cm</xsl:attribute>
+ <xsl:attribute name="keep-together.within-page">1</xsl:attribute>
+ <xsl:attribute name="margin-left">0pt</xsl:attribute>
+ <xsl:attribute name="margin-right">0pt</xsl:attribute>
+</xsl:attribute-set>
+
+<!--
+Put a box around code blocks, also set the font size
+and keep the block together if we can using the widows
+and orphans controls. Hyphenation and line wrapping
+is also turned on, so that long lines of code don't
+bleed off the edge of the page, a carriage return
+symbol is used as the hyphenation character:
+-->
+<xsl:attribute-set name="monospace.verbatim.properties">
+ <xsl:attribute name="border-color">#DCDCDC</xsl:attribute>
+ <xsl:attribute name="border-width">1px</xsl:attribute>
+ <xsl:attribute name="border-style">solid</xsl:attribute>
+ <xsl:attribute name="padding-left">0.2cm</xsl:attribute>
+ <xsl:attribute name="padding-right">0.2cm</xsl:attribute>
+ <xsl:attribute name="padding-top">0.2cm</xsl:attribute>
+ <xsl:attribute name="padding-bottom">0.2cm</xsl:attribute>
+ <xsl:attribute name="widows">6</xsl:attribute>
+ <xsl:attribute name="orphans">40</xsl:attribute>
+ <xsl:attribute name="font-size">9pt</xsl:attribute>
+ <xsl:attribute name="hyphenate">true</xsl:attribute>
+ <xsl:attribute name="wrap-option">wrap</xsl:attribute>
+ <xsl:attribute name="hyphenation-character">&#x21B5;</xsl:attribute>
+ <xsl:attribute name="margin-left">0pt</xsl:attribute>
+ <xsl:attribute name="margin-right">0pt</xsl:attribute>
+</xsl:attribute-set>
+
+<xsl:param name="hyphenate.verbatim" select="1"></xsl:param>
+<xsl:param name="monospace.font.family">monospace,Symbol</xsl:param>
+
+ <!--Regular monospace text should have the same font size as code blocks etc-->
+<xsl:attribute-set name="monospace.properties">
+ <xsl:attribute name="font-size">9pt</xsl:attribute>
+</xsl:attribute-set>
+
+<!--
+Put some small amount of padding around table cells, and keep tables
+together on one page if possible:
+-->
+<xsl:attribute-set name="table.cell.padding">
+ <xsl:attribute name="padding-left">0.2cm</xsl:attribute>
+ <xsl:attribute name="padding-right">0.2cm</xsl:attribute>
+ <xsl:attribute name="padding-top">0.2cm</xsl:attribute>
+ <xsl:attribute name="padding-bottom">0.2cm</xsl:attribute>
+</xsl:attribute-set>
+
+ <!--Formal and informal tables have the same properties
+ Using widow-and-orphan control here gives much better
+ results for very large tables than a simple "keep-together"
+ instruction-->
+<xsl:attribute-set name="table.properties">
+ <xsl:attribute name="keep-together.within-page">1</xsl:attribute>
+</xsl:attribute-set>
+<xsl:attribute-set name="informaltable.properties">
+ <xsl:attribute name="keep-together.within-page">1</xsl:attribute>
+</xsl:attribute-set>
+
+<!--
+General default options go here:
+* Borders are mid-grey.
+* Body text is not indented compared to the titles.
+* Page margins are a rather small 0.5in, but we need
+ all the space we can get for code blocks.
+* Paper size is A4: an ISO standard, slightly taller and narrower than US Letter.
+* Use SVG graphics for admonishments: the bitmaps look awful in PDF's.
+* Disable draft mode so we're not constantly trying to download the necessary graphic.
+* Set default image paths to pull down direct from SVN: individual Jamfiles can override this
+ and pass an absolute path to local versions of the images, but we can't get that here, so
+ we'll use SVN instead so that most things "just work".
+-->
+<xsl:param name="table.frame.border.color">#DCDCDC</xsl:param>
+<xsl:param name="table.cell.border.color">#DCDCDC</xsl:param>
+<xsl:param name="body.start.indent">0pt</xsl:param>
+<xsl:param name="page.margin.inner">0.5in</xsl:param>
+<xsl:param name="page.margin.outer">0.5in</xsl:param>
+<xsl:param name="paper.type">A4</xsl:param>
+<xsl:param name="admon.graphics">1</xsl:param>
+<xsl:param name="admon.graphics.extension">.svg</xsl:param>
+<xsl:param name="draft.mode">no</xsl:param>
+<xsl:param name="admon.graphics.path">http://svn.boost.org/svn/boost/trunk/doc/src/images/</xsl:param>
+<xsl:param name="callout.graphics.path">http://svn.boost.org/svn/boost/trunk/doc/src/images/callouts/</xsl:param>
+<xsl:param name="img.src.path">http://svn.boost.org/svn/boost/trunk/doc/html/</xsl:param>
+
+</xsl:stylesheet>
+
diff --git a/tools/boostbook/xsl/function.xsl b/tools/boostbook/xsl/function.xsl
new file mode 100644
index 0000000000..edba8ed1ce
--- /dev/null
+++ b/tools/boostbook/xsl/function.xsl
@@ -0,0 +1,1217 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+ <xsl:strip-space elements="requires effects postconditions returns throws
+ complexity notes rationale purpose"/>
+
+ <!-- When true, the stylesheet will emit compact definitions of
+ functions when the function does not have any detailed
+ description. -->
+ <xsl:param name="boost.compact.function">1</xsl:param>
+
+ <!-- The longest type length that is considered "short" for the
+ layout of function return types. When the length of the result type
+ and any storage specifiers is greater than this length, they will be
+ placed on a separate line from the function name and parameters
+ unless everything fits on a single line. -->
+ <xsl:param name="boost.short.result.type">12</xsl:param>
+
+ <!-- Display a function declaration -->
+ <xsl:template name="function">
+ <xsl:param name="indentation"/>
+ <xsl:param name="is-reference"/>
+
+ <!-- Whether or not we should include parameter names in the output -->
+ <xsl:param name="include-names" select="$is-reference"/>
+
+ <!-- What type of link the function name should have. This shall
+ be one of 'anchor' (the function output will be the target of
+ links), 'link' (the function output will link to a definition), or
+ 'none' (the function output will not be either a link or a link
+ target) -->
+ <xsl:param name="link-type">
+ <xsl:choose>
+ <xsl:when test="$is-reference">
+ <xsl:text>anchor</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>link</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:param>
+
+ <!-- The id we should link to or anchor as -->
+ <xsl:param name="link-to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:param>
+
+ <!-- If we are printing a constructor -->
+ <xsl:param name="constructor-for"/>
+
+ <!-- If we are printing a destructor -->
+ <xsl:param name="destructor-for"/>
+
+ <!-- If we are printing a copy assignment operator -->
+ <xsl:param name="copy-assign-for"/>
+
+ <!-- The name of this function -->
+ <xsl:param name="name" select="@name"/>
+
+ <!-- True if this is the function's separate documentation -->
+ <xsl:param name="standalone" select="false()"/>
+
+ <!-- True if we should suppress the template header -->
+ <xsl:param name="suppress-template" select="false()"/>
+
+ <!-- Calculate the specifiers -->
+ <xsl:variable name="specifiers">
+ <xsl:if test="@specifiers">
+ <xsl:value-of select="concat(@specifiers, ' ')"/>
+ </xsl:if>
+ </xsl:variable>
+
+ <!-- Calculate the type -->
+ <xsl:variable name="type">
+ <xsl:value-of select="$specifiers"/>
+
+ <xsl:choose>
+ <!-- Conversion operators have an empty type, because the return
+ type is part of the name -->
+ <xsl:when test="$name='conversion-operator'"/>
+
+ <!-- Constructors and destructors have no return type -->
+ <xsl:when test="$constructor-for or $destructor-for"/>
+
+ <!-- Copy assignment operators return a reference to the class
+ they are in, unless another type has been explicitly
+ provided in the element. -->
+ <xsl:when test="$copy-assign-for and not(type)">
+ <xsl:value-of select="concat($copy-assign-for, '&amp; ')"/>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:apply-templates select="type" mode="annotation"/>
+ <xsl:text> </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Build the function name with return type -->
+ <xsl:variable name="function-name">
+ <xsl:choose>
+ <xsl:when test="$constructor-for">
+ <xsl:value-of select="$constructor-for"/>
+ </xsl:when>
+ <xsl:when test="$destructor-for">
+ <xsl:value-of select="concat('~',$destructor-for)"/>
+ </xsl:when>
+ <xsl:when test="$copy-assign-for">
+ <xsl:value-of select="'operator='"/>
+ </xsl:when>
+ <xsl:when test="$name='conversion-operator'">
+ <xsl:text>operator </xsl:text>
+ <xsl:apply-templates select="type" mode="annotation"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:if test="not ($standalone) or
+ (local-name(.)='signature' and (position() &gt; 1))
+ or $suppress-template">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+
+ <!-- Indent this declaration -->
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+
+ <!-- Build the template header -->
+ <xsl:variable name="template-length">
+ <xsl:choose>
+ <xsl:when test="$suppress-template">
+ 0
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="template.synopsis.length"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Build a full parameter string (without line breaks) -->
+ <xsl:variable name="param-string">
+ <xsl:text>(</xsl:text>
+ <xsl:call-template name="function-parameters">
+ <xsl:with-param name="include-names" select="$include-names"/>
+ <xsl:with-param name="wrap" select="false()"/>
+ </xsl:call-template>
+ <xsl:text>)</xsl:text>
+ </xsl:variable>
+
+ <!-- Build the text that follows the declarator-->
+ <xsl:variable name="postdeclarator">
+ <xsl:if test="@cv and @cv != ''">
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@cv"/>
+ </xsl:if>
+ </xsl:variable>
+
+ <!-- Build the full declaration text -->
+ <xsl:variable name="decl-string"
+ select="concat($type, $function-name, $param-string, $postdeclarator)"/>
+ <xsl:variable name="end-column"
+ select="$template-length + string-length($decl-string) + $indentation"/>
+
+ <xsl:choose>
+ <!-- Check if we should put the template header on its own line to
+ save horizontal space. -->
+ <xsl:when test="($template-length &gt; 0) and
+ ($end-column &gt; $max-columns)">
+ <!-- Emit template header on its own line -->
+ <xsl:apply-templates select="template" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:apply-templates>
+
+ <!-- Emit the rest of the function declaration (without the
+ template header) indented two extra spaces. -->
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ <xsl:with-param name="is-reference" select="$is-reference"/>
+ <xsl:with-param name="include-names" select="$include-names"/>
+ <xsl:with-param name="link-type" select="$link-type"/>
+ <xsl:with-param name="link-to" select="$link-to"/>
+ <xsl:with-param name="constructor-for" select="$constructor-for"/>
+ <xsl:with-param name="destructor-for" select="$destructor-for"/>
+ <xsl:with-param name="copy-assign-for" select="$copy-assign-for"/>
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="standalone" select="$standalone"/>
+ <xsl:with-param name="suppress-template" select="true()"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <!-- Check if we can put the entire declaration on a single
+ line. -->
+ <xsl:when test="not($end-column &gt; $max-columns)">
+ <!-- Emit template header, if not suppressed -->
+ <xsl:if test="not($suppress-template)">
+ <xsl:apply-templates select="template" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="wrap" select="false()"/>
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:apply-templates>
+ </xsl:if>
+
+ <!-- Emit specifiers -->
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="$specifiers"/>
+ </xsl:call-template>
+
+ <!-- Emit type, if any -->
+ <xsl:choose>
+ <!-- Conversion operators have an empty type, because the return
+ type is part of the name -->
+ <xsl:when test="$name='conversion-operator'"/>
+
+ <!-- Constructors and destructors have no return type -->
+ <xsl:when test="$constructor-for or $destructor-for"/>
+
+ <!-- Copy assignment operators return a reference to the class
+ they are in, unless another type has been explicitly
+ provided in the element. -->
+ <xsl:when test="$copy-assign-for and not(type)">
+ <xsl:value-of select="concat($copy-assign-for, '&amp; ')"/>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:apply-templates select="type" mode="highlight"/>
+ <xsl:text> </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:call-template name="link-or-anchor">
+ <xsl:with-param name="to" select="$link-to"/>
+ <xsl:with-param name="text" select="$function-name"/>
+ <xsl:with-param name="link-type" select="$link-type"/>
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'('"/>
+ </xsl:call-template>
+ <xsl:call-template name="function-parameters">
+ <xsl:with-param name="include-names" select="$include-names"/>
+ <xsl:with-param name="indentation"
+ select="$indentation + $template-length + string-length($type)
+ + string-length($function-name) + 1"/>
+ <xsl:with-param name="final" select="true()"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="')'"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="$postdeclarator"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="';'"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <!-- This declaration will take multiple lines -->
+ <xsl:otherwise>
+ <!-- Emit specifiers -->
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="$specifiers"/>
+ </xsl:call-template>
+
+ <!-- Emit type, if any -->
+ <xsl:choose>
+ <!-- Conversion operators have an empty type, because the return
+ type is part of the name -->
+ <xsl:when test="$name='conversion-operator'"/>
+
+ <!-- Constructors and destructors have no return type -->
+ <xsl:when test="$constructor-for or $destructor-for"/>
+
+ <!-- Copy assignment operators return a reference to the class
+ they are in, unless another type has been explicitly
+ provided in the element. -->
+ <xsl:when test="$copy-assign-for and not(type)">
+ <xsl:value-of select="concat($copy-assign-for, '&amp; ')"/>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:apply-templates select="type" mode="highlight"/>
+ <xsl:text> </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="string-length($type) &gt; $boost.short.result.type">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:if>
+
+ <!-- Determine how many columns the type and storage
+ specifiers take on the same line as the function name. -->
+ <xsl:variable name="type-length">
+ <xsl:choose>
+ <xsl:when test="string-length($type) &gt; $boost.short.result.type">
+ 0
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string-length($type)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:call-template name="link-or-anchor">
+ <xsl:with-param name="to" select="$link-to"/>
+ <xsl:with-param name="text" select="$function-name"/>
+ <xsl:with-param name="link-type" select="$link-type"/>
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'('"/>
+ </xsl:call-template>
+ <xsl:call-template name="function-parameters">
+ <xsl:with-param name="include-names" select="$include-names"/>
+ <xsl:with-param name="indentation"
+ select="$indentation + $type-length
+ + string-length($function-name) + 1"/>
+ <xsl:with-param name="final" select="true()"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="')'"/>
+ </xsl:call-template>
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="$postdeclarator"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="';'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Synopsis of function parameters, e.g., "(const T&, int x = 5)" -->
+ <xsl:template name="function-parameters">
+ <!-- Indentation level of this parameter list -->
+ <xsl:param name="indentation"/>
+
+ <!-- True if we should include parameter names -->
+ <xsl:param name="include-names" select="true()"/>
+
+ <!-- True if we should wrap function parameters to the next line -->
+ <xsl:param name="wrap" select="true()"/>
+
+ <!-- True if we are printing the final output -->
+ <xsl:param name="final" select="false()"/>
+
+ <!-- Internal: The prefix to emit before a parameter -->
+ <xsl:param name="prefix" select="''"/>
+
+ <!-- Internal: The list of parameters -->
+ <xsl:param name="parameters" select="parameter"/>
+
+ <!-- Internal: The column we are on -->
+ <xsl:param name="column" select="$indentation"/>
+
+ <!-- Internal: Whether this is the first parameter on this line or not -->
+ <xsl:param name="first-on-line" select="true()"/>
+
+ <xsl:if test="$parameters">
+ <!-- Information for this parameter -->
+ <xsl:variable name="parameter" select="$parameters[position()=1]"/>
+ <xsl:variable name="pack">
+ <xsl:if test="$parameter/@pack=1">
+ <xsl:choose>
+ <xsl:when test="$final">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'...'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>...</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="name">
+ <xsl:if test="$include-names and $parameter/@name != ''">
+ <xsl:text> </xsl:text><xsl:value-of select="$parameter/@name"/>
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:variable name="type" select="string($parameter/paramtype)"/>
+
+ <xsl:variable name="default">
+ <xsl:choose>
+ <xsl:when test="$parameter/@default">
+ <xsl:choose>
+ <xsl:when test="$final">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="concat(' = ', $parameter/@default)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text> = </xsl:text>
+ <xsl:value-of select="$parameter/@default"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$parameter/default">
+ <xsl:choose>
+ <xsl:when test="$final">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="' = '"/>
+ </xsl:call-template>
+ <xsl:apply-templates
+ select="$parameter/default/*|$parameter/default/text()"
+ mode="annotation">
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text> = </xsl:text>
+ <xsl:value-of select="string($parameter/default)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="text" select="concat($type, $pack, $name, $default)"/>
+
+ <xsl:variable name="end-column"
+ select="$column + string-length($prefix) + string-length($text)"/>
+
+ <xsl:choose>
+ <!-- Parameter goes on this line -->
+ <xsl:when test="$first-on-line or ($end-column &lt; $max-columns)
+ or not($wrap)">
+ <xsl:choose>
+ <xsl:when test="$final">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="$prefix"/>
+ </xsl:call-template>
+ <xsl:apply-templates
+ select="$parameter/paramtype/*|$parameter/paramtype/text()"
+ mode="annotation">
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:apply-templates>
+ <xsl:copy-of select="$pack"/>
+ <xsl:value-of select="$name"/>
+ <xsl:copy-of select="$default"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($prefix, $text)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:call-template name="function-parameters">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="include-names" select="$include-names"/>
+ <xsl:with-param name="wrap" select="$wrap"/>
+ <xsl:with-param name="final" select="$final"/>
+ <xsl:with-param name="parameters"
+ select="$parameters[position()!=1]"/>
+ <xsl:with-param name="prefix" select="', '"/>
+ <xsl:with-param name="column" select="$end-column"/>
+ <xsl:with-param name="first-on-line" select="false()"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- Parameter goes on next line -->
+ <xsl:otherwise>
+ <!-- The comma goes on this line -->
+ <xsl:choose>
+ <xsl:when test="$final">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="$prefix"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$prefix"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>&#10;</xsl:text>
+
+ <!-- Indent and print the parameter -->
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:choose>
+ <xsl:when test="$final">
+ <xsl:apply-templates
+ select="$parameter/paramtype/*|$parameter/paramtype/text()"
+ mode="annotation">
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:apply-templates>
+ <xsl:copy-of select="$pack"/>
+ <xsl:value-of select="$name"/>
+ <xsl:copy-of select="$default"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($prefix, $text)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <!-- Emit next parameter -->
+ <xsl:call-template name="function-parameters">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="include-names" select="$include-names"/>
+ <xsl:with-param name="wrap" select="$wrap"/>
+ <xsl:with-param name="final" select="$final"/>
+ <xsl:with-param name="parameters"
+ select="$parameters[position()!=1]"/>
+ <xsl:with-param name="prefix" select="', '"/>
+ <xsl:with-param name="column"
+ select="1 + string-length($text) + $indentation"/>
+ <xsl:with-param name="first-on-line" select="false()"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Function synopsis -->
+ <xsl:template match="function|method" mode="synopsis">
+ <xsl:param name="indentation"/>
+
+ <!-- True if we should compact this function -->
+ <xsl:variable name="compact"
+ select="not (para|description|requires|effects|postconditions|returns|
+ throws|complexity|notes|rationale) and
+ ($boost.compact.function='1') and
+ not (local-name(.)='method')"/>
+
+ <xsl:choose>
+ <xsl:when test="$compact">
+ <xsl:if test="purpose">
+ <!-- Compact display outputs the purpose as a comment (if
+ there is one) and the entire function declaration. -->
+ <xsl:text>&#10;&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:apply-templates select="purpose/*|purpose/text()"
+ mode="purpose"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="is-reference" select="false()"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="overloaded-function|overloaded-method" mode="synopsis">
+ <xsl:param name="indentation"/>
+
+ <xsl:variable name="name" select="@name"/>
+
+ <!-- True if we should compact this function -->
+ <xsl:variable name="compact"
+ select="not (para|description|requires|effects|postconditions|returns|
+ throws|complexity|notes|rationale) and
+ ($boost.compact.function='1') and
+ not (local-name(.)='overloaded-method')"/>
+
+ <xsl:choose>
+ <xsl:when test="$compact">
+ <xsl:if test="purpose">
+ <!-- Compact display outputs the purpose as a comment (if
+ there is one) and the entire function declaration. -->
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:apply-templates select="purpose" mode="annotation"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+
+ <xsl:for-each select="signature">
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="local-name(..)='namespace'">
+ <xsl:variable name="link-to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:variable>
+
+ <xsl:for-each select="signature">
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="is-reference" select="false()"/>
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="link-to" select="$link-to"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="signature">
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="is-reference" select="false()"/>
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Group free functions together under a category name (header synopsis)-->
+ <xsl:template match="free-function-group" mode="header-synopsis">
+ <xsl:param name="class"/>
+ <xsl:param name="indentation"/>
+ <xsl:apply-templates select="function|overloaded-function" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <!-- Constructors, destructor, and assignment operators -->
+ <xsl:template name="construct-copy-destruct-synopsis">
+ <xsl:param name="indentation"/>
+ <xsl:if test="constructor|copy-assignment|destructor">
+ <xsl:if test="typedef|static-constant">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ <xsl:text>construct-copy-destruct</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="'construct/copy/destruct'"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:apply-templates select="constructor" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="copy-assignment" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="destructor" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="construct-copy-destruct-reference">
+ <xsl:if test="constructor|copy-assignment|destructor">
+ <xsl:call-template name="member-documentation">
+ <xsl:with-param name="name">
+ <xsl:call-template name="anchor">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ <xsl:text>construct-copy-destruct</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="''"/>
+ </xsl:call-template>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text">
+ <xsl:call-template name="object-name"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="access-name"/>
+ <xsl:text> construct/copy/destruct</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <orderedlist>
+ <xsl:apply-templates select="constructor" mode="reference"/>
+ <xsl:apply-templates select="copy-assignment" mode="reference"/>
+ <xsl:apply-templates select="destructor" mode="reference"/>
+ </orderedlist>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="constructor" mode="reference">
+ <xsl:call-template name="function.documentation">
+ <xsl:with-param name="text">
+ <para>
+ <xsl:call-template name="preformatted">
+ <xsl:with-param name="text">
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="0"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ <xsl:with-param name="constructor-for">
+ <xsl:call-template name="object-name"/>
+ </xsl:with-param>
+ <xsl:with-param name="standalone" select="true()"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </para>
+ <xsl:call-template name="function-requirements"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="copy-assignment" mode="reference">
+ <xsl:call-template name="function.documentation">
+ <xsl:with-param name="text">
+ <para>
+ <xsl:call-template name="preformatted">
+ <xsl:with-param name="text">
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="0"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ <xsl:with-param name="copy-assign-for">
+ <xsl:call-template name="object-name"/>
+ </xsl:with-param>
+ <xsl:with-param name="standalone" select="true()"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </para>
+ <xsl:call-template name="function-requirements"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="destructor" mode="reference">
+ <xsl:call-template name="function.documentation">
+ <xsl:with-param name="text">
+ <para>
+ <xsl:call-template name="preformatted">
+ <xsl:with-param name="text">
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="0"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ <xsl:with-param name="destructor-for">
+ <xsl:call-template name="object-name"/>
+ </xsl:with-param>
+ <xsl:with-param name="standalone" select="true()"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </para>
+ <xsl:call-template name="function-requirements"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- Templates for functions -->
+ <xsl:template name="function.documentation">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="count(ancestor::free-function-group) &gt; 0
+ or count(ancestor::method-group) &gt; 0
+ or local-name(.)='constructor'
+ or local-name(.)='copy-assignment'
+ or local-name(.)='destructor'">
+ <listitem><xsl:copy-of select="$text"/></listitem>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Semantic descriptions of functions -->
+ <xsl:template name="function-requirements">
+ <xsl:param name="namespace-reference" select="false()"/>
+
+ <xsl:if test="$namespace-reference=false()">
+ <xsl:apply-templates select="purpose/*|purpose/text()"/>
+ </xsl:if>
+
+ <xsl:apply-templates select="description/*"/>
+
+ <xsl:if test="parameter/description|signature/parameter/description|
+ template/template-type-parameter/purpose|
+ template/template-nontype-parameter/purpose|
+ requires|effects|postconditions|returns|throws|complexity|
+ notes|rationale">
+ <variablelist spacing="compact">
+ <xsl:processing-instruction name="dbhtml">
+ list-presentation="table"
+ </xsl:processing-instruction>
+
+ <!-- Document parameters -->
+ <xsl:if test="parameter/description|signature/parameter/description">
+ <varlistentry>
+ <term>Parameters:</term>
+ <listitem>
+ <variablelist spacing="compact">
+ <xsl:processing-instruction name="dbhtml">
+ list-presentation="table"
+ </xsl:processing-instruction>
+ <xsl:for-each select="parameter|signature/parameter">
+ <xsl:sort select="attribute::name"/>
+ <xsl:if test="description">
+ <varlistentry>
+ <term>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </term>
+ <listitem>
+ <xsl:apply-templates select="description/*"/>
+ </listitem>
+ </varlistentry>
+ </xsl:if>
+ </xsl:for-each>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ </xsl:if>
+
+ <!-- Document template parameters -->
+ <xsl:if test="template/template-type-parameter/purpose|
+ template/template-nontype-parameter/purpose">
+ <varlistentry>
+ <term>Template Parameters:</term>
+ <listitem>
+ <variablelist spacing="compact">
+ <xsl:processing-instruction name="dbhtml">
+ list-presentation="table"
+ </xsl:processing-instruction>
+ <xsl:for-each select="template/template-type-parameter|
+ template/template-nontype-parameter">
+ <xsl:sort select="attribute::name"/>
+ <xsl:if test="purpose">
+ <varlistentry>
+ <term>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </term>
+ <listitem>
+ <xsl:apply-templates select="purpose/*"/>
+ </listitem>
+ </varlistentry>
+ </xsl:if>
+ </xsl:for-each>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ </xsl:if>
+
+ <!-- Document rest of function's contract -->
+ <xsl:for-each select="requires|effects|postconditions|returns|throws|complexity|
+ notes|rationale">
+ <varlistentry>
+ <term><xsl:call-template name="function.requirement.name"/>:</term>
+ <listitem>
+ <xsl:apply-templates select="./*|./text()" mode="annotation"/>
+ </listitem>
+ </varlistentry>
+ </xsl:for-each>
+
+ </variablelist>
+ </xsl:if>
+
+ <xsl:if test="para">
+ <xsl:message>
+ <xsl:text>Warning: Use of 'para' elements in a function is deprecated.&#10;</xsl:text>
+ <xsl:text> Wrap them in a 'description' element.</xsl:text>
+ </xsl:message>
+ <xsl:call-template name="print.warning.context"/>
+ <xsl:apply-templates select="para"/>
+ </xsl:if>
+
+ </xsl:template>
+
+ <xsl:template name="function.requirement.name">
+ <xsl:param name="node" select="."/>
+ <xsl:choose>
+ <xsl:when test="local-name($node)='requires'">Requires</xsl:when>
+ <xsl:when test="local-name($node)='effects'">Effects</xsl:when>
+ <xsl:when test="local-name($node)='postconditions'">
+ <xsl:text>Postconditions</xsl:text>
+ </xsl:when>
+ <xsl:when test="local-name($node)='returns'">Returns</xsl:when>
+ <xsl:when test="local-name($node)='throws'">Throws</xsl:when>
+ <xsl:when test="local-name($node)='complexity'">Complexity</xsl:when>
+ <xsl:when test="local-name($node)='notes'">Notes</xsl:when>
+ <xsl:when test="local-name($node)='rationale'">Rationale</xsl:when>
+ <xsl:otherwise>
+ <xsl:message>
+ <xsl:text>Error: unhandled node type `</xsl:text>
+ <xsl:value-of select="local-name($node)"/>
+ <xsl:text>' in template function.requirement.name.</xsl:text>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Function reference -->
+ <xsl:template match="function|method" mode="reference">
+ <!-- True if we should compact this function -->
+ <xsl:variable name="compact"
+ select="not (para|description|requires|effects|postconditions|returns|
+ throws|complexity|notes|rationale) and
+ ($boost.compact.function='1') and
+ not (local-name(.)='method')"/>
+
+ <xsl:if test="not ($compact)">
+ <xsl:call-template name="function.documentation">
+ <xsl:with-param name="text">
+ <para>
+ <xsl:call-template name="preformatted">
+ <xsl:with-param name="text">
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="0"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ <xsl:with-param name="link-type" select="'anchor'"/>
+ <xsl:with-param name="standalone" select="true()"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </para>
+ <xsl:call-template name="function-requirements"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Reference for functions at namespace level -->
+ <xsl:template match="function" mode="namespace-reference">
+ <!-- True if we should compact this function -->
+ <xsl:variable name="compact"
+ select="not (para|description|requires|effects|postconditions|returns|
+ throws|complexity|notes|rationale) and
+ ($boost.compact.function='1')"/>
+
+ <xsl:if test="not ($compact)">
+ <xsl:call-template name="reference-documentation">
+ <xsl:with-param name="name">
+ <xsl:text>Function </xsl:text>
+ <xsl:if test="template">
+ <xsl:text>template </xsl:text>
+ </xsl:if>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="refname">
+ <xsl:call-template name="fully-qualified-name">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="purpose" select="purpose/*|purpose/text()"/>
+ <xsl:with-param name="anchor">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ <xsl:with-param name="synopsis">
+ <xsl:call-template name="header-link"/>
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="0"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ <xsl:with-param name="link-type" select="'none'"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <xsl:call-template name="function-requirements">
+ <xsl:with-param name="namespace-reference" select="true()"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="overloaded-function" mode="reference">
+ <xsl:variable name="name" select="@name"/>
+
+ <!-- True if we should compact this function -->
+ <xsl:variable name="compact"
+ select="not (para|description|requires|effects|postconditions|returns|
+ throws|complexity|notes|rationale) and
+ ($boost.compact.function='1')"/>
+
+ <xsl:if test="not ($compact)">
+ <xsl:call-template name="function.documentation">
+ <xsl:with-param name="text">
+ <para>
+ <xsl:attribute name="id">
+ <xsl:call-template name="generate.id"/>
+ </xsl:attribute>
+
+ <xsl:call-template name="preformatted">
+ <xsl:with-param name="text">
+ <xsl:for-each select="signature">
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="0"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="standalone" select="true()"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:with-param>
+ </xsl:call-template>
+ </para>
+ <xsl:call-template name="function-requirements"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="overloaded-function" mode="namespace-reference">
+ <!-- True if we should compact this function -->
+ <xsl:variable name="compact"
+ select="not (para|description|requires|effects|postconditions|returns|
+ throws|complexity|notes|rationale) and
+ ($boost.compact.function='1')"/>
+
+ <xsl:variable name="name" select="@name"/>
+
+ <xsl:if test="not ($compact)">
+ <xsl:call-template name="reference-documentation">
+ <xsl:with-param name="name">
+ <xsl:text>Function </xsl:text>
+ <xsl:if test="template">
+ <xsl:text>template </xsl:text>
+ </xsl:if>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="refname">
+ <xsl:call-template name="fully-qualified-name">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="purpose" select="purpose/*|purpose/text()"/>
+ <xsl:with-param name="anchor">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ <xsl:with-param name="synopsis">
+ <xsl:call-template name="header-link"/>
+ <xsl:for-each select="signature">
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="0"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ <xsl:with-param name="link-type" select="'none'"/>
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <xsl:call-template name="function-requirements">
+ <xsl:with-param name="namespace-reference" select="true()"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="overloaded-method" mode="reference">
+ <xsl:variable name="name" select="@name"/>
+
+ <xsl:call-template name="function.documentation">
+ <xsl:with-param name="text">
+ <para>
+ <xsl:call-template name="preformatted">
+ <xsl:with-param name="text">
+ <xsl:call-template name="anchor">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:for-each select="signature">
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="0"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="standalone" select="true()"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:with-param>
+ </xsl:call-template>
+ </para>
+ <xsl:call-template name="function-requirements"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- Group member functions together under a category name (synopsis)-->
+ <xsl:template match="method-group" mode="synopsis">
+ <xsl:param name="indentation"/>
+ <xsl:if test="count(child::*) &gt; 0">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="string(@name)"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:apply-templates select="method|overloaded-method"
+ mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Group member functions together under a category name (reference)-->
+ <xsl:template match="method-group" mode="reference">
+ <xsl:if test="count(child::*) &gt; 0">
+ <xsl:call-template name="member-documentation">
+ <xsl:with-param name="name">
+ <xsl:call-template name="anchor">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="''"/>
+ </xsl:call-template>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text">
+ <xsl:call-template name="object-name"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <orderedlist>
+ <xsl:apply-templates select="method|overloaded-method"
+ mode="reference"/>
+ </orderedlist>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Group free functions together under a category name (synopsis)-->
+ <xsl:template match="free-function-group" mode="synopsis">
+ <xsl:param name="class"/>
+ <xsl:param name="indentation"/>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="string(@name)"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:apply-templates select="function|overloaded-function" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <!-- Group free functions together under a category name (reference)-->
+ <xsl:template match="free-function-group" mode="reference">
+ <xsl:param name="class"/>
+ <xsl:call-template name="member-documentation">
+ <xsl:with-param name="name">
+ <xsl:call-template name="anchor">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="''"/>
+ </xsl:call-template>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text" select="$class"/>
+ </xsl:call-template>
+ <xsl:value-of select="concat(' ',@name)"/>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <orderedlist>
+ <xsl:apply-templates select="function|overloaded-function"
+ mode="reference"/>
+ </orderedlist>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/global.xsl b/tools/boostbook/xsl/global.xsl
new file mode 100644
index 0000000000..bb22160abd
--- /dev/null
+++ b/tools/boostbook/xsl/global.xsl
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:template name="global-synopsis">
+ <xsl:param name="indentation" select="0" />
+ <xsl:if test="not(local-name(preceding-sibling::*[position()=1])=local-name(.)) and (position() &gt; 1)">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation" />
+ </xsl:call-template>
+ <xsl:call-template name="global-synopsis-impl">
+ <xsl:with-param name="link-type" select="'link'" />
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="global-reference">
+ <xsl:call-template name="reference-documentation">
+ <xsl:with-param name="refname">
+ <xsl:call-template name="fully-qualified-name">
+ <xsl:with-param name="node" select="." />
+ </xsl:call-template>
+ <xsl:apply-templates select="specialization" />
+ </xsl:with-param>
+ <xsl:with-param name="purpose" select="purpose/*|purpose/text()" />
+ <xsl:with-param name="anchor">
+ <xsl:call-template name="generate.id" />
+ </xsl:with-param>
+ <xsl:with-param name="name">
+ <xsl:text>Global </xsl:text>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text" select="@name" />
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="synopsis">
+ <xsl:call-template name="header-link"/>
+ <xsl:call-template name="global-synopsis-impl">
+ <xsl:with-param name="link-type" select="'none'" />
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <xsl:apply-templates select="description" />
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="global-synopsis-impl">
+ <xsl:param name="link-type" />
+ <xsl:if test="@specifiers">
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="@specifiers" />
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ <xsl:apply-templates select="type/*|type/text()" mode="annotation">
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:apply-templates>
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="link-or-anchor">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id" select="." />
+ </xsl:with-param>
+ <xsl:with-param name="text" select="@name" />
+ <xsl:with-param name="link-type" select="$link-type" />
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="';'"/>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template match="data-member" mode="generate.id">
+ <xsl:call-template name="fully-qualified-id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/html-base.xsl b/tools/boostbook/xsl/html-base.xsl
new file mode 100644
index 0000000000..30442b1f64
--- /dev/null
+++ b/tools/boostbook/xsl/html-base.xsl
@@ -0,0 +1,383 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision"
+ version="1.0">
+
+ <xsl:param name="html.stylesheet">
+ <xsl:choose>
+ <xsl:when test = "$boost.defaults = 'Boost'">
+ <xsl:value-of select = "concat($boost.root, '/doc/src/boostbook.css')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ boostbook.css
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:param>
+
+ <xsl:param name="boost.graphics.root">
+ <xsl:choose>
+ <xsl:when test = "$boost.defaults = 'Boost'">
+ <xsl:value-of select = "concat($boost.root, '/doc/src/images/')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select = "'images/'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:param>
+
+ <xsl:param name="boost.mathjax" select="0"/>
+ <xsl:param name="boost.mathjax.script"
+ select="'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'"/>
+
+ <xsl:param name="admon.style"/>
+ <xsl:param name="admon.graphics">1</xsl:param>
+ <xsl:param name="boostbook.verbose" select="0"/>
+ <xsl:param name="navig.graphics" select="1"/>
+ <xsl:param name="navig.graphics.extension" select="'.png'"/>
+ <xsl:param name="chapter.autolabel" select="1"/>
+ <xsl:param name="use.id.as.filename" select="1"/>
+ <xsl:param name="refentry.generate.name" select="0"/>
+ <xsl:param name="refentry.generate.title" select="1"/>
+ <xsl:param name="make.year.ranges" select="1"/>
+ <xsl:param name="generate.manifest" select="1"/>
+ <xsl:param name="generate.section.toc.level" select="3"/>
+ <xsl:param name="doc.standalone">false</xsl:param>
+ <xsl:param name="chunker.output.indent">yes</xsl:param>
+ <xsl:param name="chunker.output.encoding">US-ASCII</xsl:param>
+ <xsl:param name="chunk.quietly" select="not(number($boostbook.verbose))"/>
+ <xsl:param name="toc.max.depth">2</xsl:param>
+ <xsl:param name="callout.graphics.number.limit">15</xsl:param>
+ <xsl:param name = "admon.graphics.path" select="$boost.graphics.root" />
+ <xsl:param name = "navig.graphics.path" select="$boost.graphics.root" />
+ <xsl:param name = "callout.graphics.path"
+ select = "concat($boost.graphics.root, 'callouts/')"/>
+
+
+ <xsl:param name="admon.style">
+ <!-- Remove the style. Let the CSS do the styling -->
+</xsl:param>
+
+<!-- Always have graphics -->
+<xsl:param name="admon.graphics" select="1"/>
+
+ <xsl:param name="generate.toc">
+appendix toc,title
+article/appendix nop
+article toc,title
+book toc,title
+chapter toc,title
+part toc,title
+preface toc,title
+qandadiv toc
+qandaset toc
+reference toc,title
+sect1 toc
+sect2 toc
+sect3 toc
+sect4 toc
+sect5 toc
+section toc
+set toc,title
+ </xsl:param>
+
+
+ <xsl:template name="format.cvs.revision">
+ <xsl:param name="text"/>
+
+ <!-- Remove the "$Date: " -->
+ <xsl:variable name="text.noprefix"
+ select="substring-after($text, '$Date: ')"/>
+
+ <!-- Grab the year -->
+ <xsl:variable name="year" select="substring-before($text.noprefix, '/')"/>
+ <xsl:variable name="text.noyear"
+ select="substring-after($text.noprefix, '/')"/>
+
+ <!-- Grab the month -->
+ <xsl:variable name="month" select="substring-before($text.noyear, '/')"/>
+ <xsl:variable name="text.nomonth"
+ select="substring-after($text.noyear, '/')"/>
+
+ <!-- Grab the year -->
+ <xsl:variable name="day" select="substring-before($text.nomonth, ' ')"/>
+ <xsl:variable name="text.noday"
+ select="substring-after($text.nomonth, ' ')"/>
+
+ <!-- Get the time -->
+ <xsl:variable name="time" select="substring-before($text.noday, ' ')"/>
+
+ <xsl:variable name="month.name">
+ <xsl:choose>
+ <xsl:when test="$month=1">January</xsl:when>
+ <xsl:when test="$month=2">February</xsl:when>
+ <xsl:when test="$month=3">March</xsl:when>
+ <xsl:when test="$month=4">April</xsl:when>
+ <xsl:when test="$month=5">May</xsl:when>
+ <xsl:when test="$month=6">June</xsl:when>
+ <xsl:when test="$month=7">July</xsl:when>
+ <xsl:when test="$month=8">August</xsl:when>
+ <xsl:when test="$month=9">September</xsl:when>
+ <xsl:when test="$month=10">October</xsl:when>
+ <xsl:when test="$month=11">November</xsl:when>
+ <xsl:when test="$month=12">December</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:value-of select="concat($month.name, ' ', $day, ', ', $year, ' at ',
+ $time, ' GMT')"/>
+ </xsl:template>
+
+
+ <xsl:template name="format.svn.revision">
+ <xsl:param name="text"/>
+
+ <!-- Remove the "$Date: " -->
+ <xsl:variable name="text.noprefix"
+ select="substring-after($text, '$Date: ')"/>
+
+ <!-- Grab the year -->
+ <xsl:variable name="year" select="substring-before($text.noprefix, '-')"/>
+ <xsl:variable name="text.noyear"
+ select="substring-after($text.noprefix, '-')"/>
+
+ <!-- Grab the month -->
+ <xsl:variable name="month" select="substring-before($text.noyear, '-')"/>
+ <xsl:variable name="text.nomonth"
+ select="substring-after($text.noyear, '-')"/>
+
+ <!-- Grab the year -->
+ <xsl:variable name="day" select="substring-before($text.nomonth, ' ')"/>
+ <xsl:variable name="text.noday"
+ select="substring-after($text.nomonth, ' ')"/>
+
+ <!-- Get the time -->
+ <xsl:variable name="time" select="substring-before($text.noday, ' ')"/>
+ <xsl:variable name="text.notime"
+ select="substring-after($text.noday, ' ')"/>
+
+ <!-- Get the timezone -->
+ <xsl:variable name="timezone" select="substring-before($text.notime, ' ')"/>
+
+ <xsl:variable name="month.name">
+ <xsl:choose>
+ <xsl:when test="$month=1">January</xsl:when>
+ <xsl:when test="$month=2">February</xsl:when>
+ <xsl:when test="$month=3">March</xsl:when>
+ <xsl:when test="$month=4">April</xsl:when>
+ <xsl:when test="$month=5">May</xsl:when>
+ <xsl:when test="$month=6">June</xsl:when>
+ <xsl:when test="$month=7">July</xsl:when>
+ <xsl:when test="$month=8">August</xsl:when>
+ <xsl:when test="$month=9">September</xsl:when>
+ <xsl:when test="$month=10">October</xsl:when>
+ <xsl:when test="$month=11">November</xsl:when>
+ <xsl:when test="$month=12">December</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:value-of select="concat($month.name, ' ', $day, ', ', $year, ' at ',
+ $time, ' ', $timezone)"/>
+ </xsl:template>
+
+ <!-- Footer Copyright -->
+ <xsl:template match="copyright" mode="boost.footer">
+ <xsl:if test="position() &gt; 1">
+ <br/>
+ </xsl:if>
+ <xsl:call-template name="gentext">
+ <xsl:with-param name="key" select="'Copyright'"/>
+ </xsl:call-template>
+ <xsl:call-template name="gentext.space"/>
+ <xsl:call-template name="dingbat">
+ <xsl:with-param name="dingbat">copyright</xsl:with-param>
+ </xsl:call-template>
+ <xsl:call-template name="gentext.space"/>
+ <xsl:call-template name="copyright.years">
+ <xsl:with-param name="years" select="year"/>
+ <xsl:with-param name="print.ranges" select="$make.year.ranges"/>
+ <xsl:with-param name="single.year.ranges"
+ select="$make.single.year.ranges"/>
+ </xsl:call-template>
+ <xsl:call-template name="gentext.space"/>
+ <xsl:apply-templates select="holder" mode="titlepage.mode"/>
+ </xsl:template>
+
+ <!-- Footer License -->
+ <xsl:template match="legalnotice" mode="boost.footer">
+ <xsl:apply-templates select="para" mode="titlepage.mode" />
+ </xsl:template>
+
+ <xsl:template name="user.footer.content">
+ <table width="100%">
+ <tr>
+ <td align="left">
+ <xsl:variable name="revision-nodes"
+ select="ancestor-or-self::*
+ [not (attribute::rev:last-revision='')]"/>
+ <xsl:if test="count($revision-nodes) &gt; 0">
+ <xsl:variable name="revision-node"
+ select="$revision-nodes[last()]"/>
+ <xsl:variable name="revision-text">
+ <xsl:value-of
+ select="normalize-space($revision-node/attribute::rev:last-revision)"/>
+ </xsl:variable>
+ <xsl:if test="string-length($revision-text) &gt; 0">
+ <p>
+ <small>
+ <xsl:text>Last revised: </xsl:text>
+ <xsl:choose>
+ <xsl:when test="contains($revision-text, '/')">
+ <xsl:call-template name="format.cvs.revision">
+ <xsl:with-param name="text" select="$revision-text"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="format.svn.revision">
+ <xsl:with-param name="text" select="$revision-text"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </small>
+ </p>
+ </xsl:if>
+ </xsl:if>
+ </td>
+ <td align="right">
+ <div class = "copyright-footer">
+ <xsl:apply-templates select="ancestor::*/*/copyright"
+ mode="boost.footer"/>
+ <xsl:apply-templates select="ancestor::*/*/legalnotice"
+ mode="boost.footer"/>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </xsl:template>
+
+ <!-- We don't want refentry's to show up in the TOC because they
+ will merely be redundant with the synopsis. -->
+ <xsl:template match="refentry" mode="toc"/>
+
+ <!-- override the behaviour of some DocBook elements for better
+ rendering facilities -->
+
+ <xsl:template match = "programlisting[ancestor::informaltable]">
+ <pre class = "table-{name(.)}"><xsl:apply-templates/></pre>
+ </xsl:template>
+
+ <xsl:template match = "refsynopsisdiv">
+ <h2 class = "{name(.)}-title">Synopsis</h2>
+ <div class = "{name(.)}">
+ <xsl:apply-templates/>
+ </div>
+ </xsl:template>
+
+ <xsl:template name="generate.html.title"/>
+
+ <xsl:template match="*" mode="detect-math">
+ <xsl:variable name="is-chunk">
+ <xsl:call-template name="chunk"/>
+ </xsl:variable>
+ <xsl:if test="$is-chunk = '0'">
+ <xsl:apply-templates mode="detect-math"/>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="text()" mode="detect-math"/>
+
+ <xsl:template match="textobject[@role='tex']" mode="detect-math">
+ <xsl:text>1</xsl:text>
+ </xsl:template>
+
+ <xsl:template name="user.head.content">
+ <xsl:if test="$boost.mathjax = 1">
+ <xsl:variable name="has-math">
+ <xsl:apply-templates mode="detect-math" select="*"/>
+ </xsl:variable>
+ <xsl:if test="string($has-math) != ''">
+ <script type="text/javascript" src="{$boost.mathjax.script}"/>
+ </xsl:if>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="inlinemediaobject">
+ <xsl:choose>
+ <xsl:when test="$boost.mathjax = 1 and textobject[@role='tex']">
+ <xsl:variable name="content" select="string(textobject[@role='tex'])"/>
+ <xsl:variable name="plain-content">
+ <xsl:choose>
+ <!--strip $$-->
+ <xsl:when test="substring($content, 1, 1) = '$' and
+ substring($content, string-length($content), 1) = '$'">
+ <xsl:value-of select="substring($content, 2, string-length($content) - 2)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$content"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <script type="math/tex">
+ <xsl:value-of select="$plain-content"/>
+ </script>
+ <noscript>
+ <xsl:apply-imports/>
+ </noscript>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-imports/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+<!-- ============================================================ -->
+
+<xsl:template name="output.html.stylesheets">
+ <xsl:param name="stylesheets" select="''"/>
+
+ <xsl:choose>
+ <xsl:when test="contains($stylesheets, ' ')">
+ <link rel="stylesheet">
+ <xsl:attribute name="href">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="substring-before($stylesheets, ' ')"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="$html.stylesheet.type != ''">
+ <xsl:attribute name="type">
+ <xsl:value-of select="$html.stylesheet.type"/>
+ </xsl:attribute>
+ </xsl:if>
+ </link>
+ <xsl:call-template name="output.html.stylesheets">
+ <xsl:with-param name="stylesheets" select="substring-after($stylesheets, ' ')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$stylesheets != ''">
+ <link rel="stylesheet">
+ <xsl:attribute name="href">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="$stylesheets"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="$html.stylesheet.type != ''">
+ <xsl:attribute name="type">
+ <xsl:value-of select="$html.stylesheet.type"/>
+ </xsl:attribute>
+ </xsl:if>
+ </link>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="itemizedlist[@role = 'index']" mode="class.value">
+ <xsl:value-of select="'index'"/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/html-help.xsl b/tools/boostbook/xsl/html-help.xsl
new file mode 100644
index 0000000000..9b9978943b
--- /dev/null
+++ b/tools/boostbook/xsl/html-help.xsl
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision"
+ version="1.0">
+
+ <!-- Import the HTML chunking stylesheet -->
+ <xsl:import
+ href="http://docbook.sourceforge.net/release/xsl/current/htmlhelp/htmlhelp.xsl"/>
+
+ <xsl:param name="admon.style"/>
+ <xsl:param name="admon.graphics">1</xsl:param>
+ <xsl:param name="boostbook.verbose" select="0"/>
+ <xsl:param name="html.stylesheet" select="'boostbook.css'"/>
+ <xsl:param name="chapter.autolabel" select="1"/>
+ <xsl:param name="use.id.as.filename" select="1"/>
+ <xsl:param name="refentry.generate.name" select="0"/>
+ <xsl:param name="refentry.generate.title" select="1"/>
+ <xsl:param name="make.year.ranges" select="1"/>
+ <xsl:param name="generate.manifest" select="1"/>
+ <xsl:param name="callout.graphics.number.limit">15</xsl:param>
+ <xsl:param name="draft.mode">no</xsl:param>
+ <xsl:param name="admon.graphics" select="1"/>
+
+ <xsl:template name="format.cvs.revision">
+ <xsl:param name="text"/>
+
+ <!-- Remove the "$Date: " -->
+ <xsl:variable name="text.noprefix"
+ select="substring-after($text, '$Date: ')"/>
+
+ <!-- Grab the year -->
+ <xsl:variable name="year" select="substring-before($text.noprefix, '/')"/>
+ <xsl:variable name="text.noyear"
+ select="substring-after($text.noprefix, '/')"/>
+
+ <!-- Grab the month -->
+ <xsl:variable name="month" select="substring-before($text.noyear, '/')"/>
+ <xsl:variable name="text.nomonth"
+ select="substring-after($text.noyear, '/')"/>
+
+ <!-- Grab the year -->
+ <xsl:variable name="day" select="substring-before($text.nomonth, ' ')"/>
+ <xsl:variable name="text.noday"
+ select="substring-after($text.nomonth, ' ')"/>
+
+ <!-- Get the time -->
+ <xsl:variable name="time" select="substring-before($text.noday, ' ')"/>
+
+ <xsl:variable name="month.name">
+ <xsl:choose>
+ <xsl:when test="$month=1">January</xsl:when>
+ <xsl:when test="$month=2">February</xsl:when>
+ <xsl:when test="$month=3">March</xsl:when>
+ <xsl:when test="$month=4">April</xsl:when>
+ <xsl:when test="$month=5">May</xsl:when>
+ <xsl:when test="$month=6">June</xsl:when>
+ <xsl:when test="$month=7">July</xsl:when>
+ <xsl:when test="$month=8">August</xsl:when>
+ <xsl:when test="$month=9">September</xsl:when>
+ <xsl:when test="$month=10">October</xsl:when>
+ <xsl:when test="$month=11">November</xsl:when>
+ <xsl:when test="$month=12">December</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:value-of select="concat($month.name, ' ', $day, ', ', $year, ' at ',
+ $time, ' GMT')"/>
+ </xsl:template>
+
+
+ <xsl:template name="format.svn.revision">
+ <xsl:param name="text"/>
+
+ <!-- Remove the "$Date: " -->
+ <xsl:variable name="text.noprefix"
+ select="substring-after($text, '$Date: ')"/>
+
+ <!-- Grab the year -->
+ <xsl:variable name="year" select="substring-before($text.noprefix, '-')"/>
+ <xsl:variable name="text.noyear"
+ select="substring-after($text.noprefix, '-')"/>
+
+ <!-- Grab the month -->
+ <xsl:variable name="month" select="substring-before($text.noyear, '-')"/>
+ <xsl:variable name="text.nomonth"
+ select="substring-after($text.noyear, '-')"/>
+
+ <!-- Grab the year -->
+ <xsl:variable name="day" select="substring-before($text.nomonth, ' ')"/>
+ <xsl:variable name="text.noday"
+ select="substring-after($text.nomonth, ' ')"/>
+
+ <!-- Get the time -->
+ <xsl:variable name="time" select="substring-before($text.noday, ' ')"/>
+ <xsl:variable name="text.notime"
+ select="substring-after($text.noday, ' ')"/>
+
+ <!-- Get the timezone -->
+ <xsl:variable name="timezone" select="substring-before($text.notime, ' ')"/>
+
+ <xsl:variable name="month.name">
+ <xsl:choose>
+ <xsl:when test="$month=1">January</xsl:when>
+ <xsl:when test="$month=2">February</xsl:when>
+ <xsl:when test="$month=3">March</xsl:when>
+ <xsl:when test="$month=4">April</xsl:when>
+ <xsl:when test="$month=5">May</xsl:when>
+ <xsl:when test="$month=6">June</xsl:when>
+ <xsl:when test="$month=7">July</xsl:when>
+ <xsl:when test="$month=8">August</xsl:when>
+ <xsl:when test="$month=9">September</xsl:when>
+ <xsl:when test="$month=10">October</xsl:when>
+ <xsl:when test="$month=11">November</xsl:when>
+ <xsl:when test="$month=12">December</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:value-of select="concat($month.name, ' ', $day, ', ', $year, ' at ',
+ $time, ' ', $timezone)"/>
+ </xsl:template>
+
+ <!-- We don't want refentry's to show up in the TOC because they
+ will merely be redundant with the synopsis. -->
+ <xsl:template match="refentry" mode="toc"/>
+
+ <!-- override the behaviour of some DocBook elements for better
+ rendering facilities -->
+
+ <xsl:template match = "programlisting[ancestor::informaltable]">
+ <pre class = "table-{name(.)}"><xsl:apply-templates/></pre>
+ </xsl:template>
+
+ <xsl:template match = "refsynopsisdiv">
+ <h2 class = "{name(.)}-title">Synopsis</h2>
+ <div class = "{name(.)}">
+ <xsl:apply-templates/>
+ </div>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/html-single.xsl b/tools/boostbook/xsl/html-single.xsl
new file mode 100644
index 0000000000..d453a84cca
--- /dev/null
+++ b/tools/boostbook/xsl/html-single.xsl
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision"
+ version="1.0">
+
+ <!-- Import the HTML stylesheet -->
+ <xsl:import
+ href="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl"/>
+ <xsl:import href="admon.xsl"/>
+ <xsl:import href="relative-href.xsl"/>
+
+ <xsl:param name="admon.style"/>
+ <xsl:param name="admon.graphics">1</xsl:param>
+ <xsl:param name="chapter.autolabel" select="0"/>
+ <xsl:param name="refentry.generate.name" select="0"/>
+ <xsl:param name="refentry.generate.title" select="1"/>
+ <xsl:param name="make.year.ranges" select="1"/>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/html.xsl b/tools/boostbook/xsl/html.xsl
new file mode 100644
index 0000000000..11a110b9a7
--- /dev/null
+++ b/tools/boostbook/xsl/html.xsl
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision"
+ version="1.0">
+
+ <!-- Import the HTML chunking stylesheet -->
+ <xsl:import
+ href="http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl"/>
+ <xsl:import
+ href="http://docbook.sourceforge.net/release/xsl/current/html/math.xsl"/>
+
+ <!-- Bring in the fast chunking overrides. There's nothing
+ that we need to override, so include instead of importing it. -->
+ <xsl:include
+ href="http://docbook.sourceforge.net/release/xsl/current/html/chunkfast.xsl"/>
+
+ <!-- We have to make sure that our templates override all
+ docbook templates. Therefore, we include our own templates
+ instead of importing them. In order for this to work,
+ the stylesheets included here cannot also include each other -->
+ <xsl:include href="chunk-common.xsl"/>
+ <xsl:include href="docbook-layout.xsl"/>
+ <xsl:include href="navbar.xsl"/>
+ <xsl:include href="admon.xsl"/>
+ <xsl:include href="xref.xsl"/>
+ <xsl:include href="relative-href.xsl"/>
+ <xsl:include href="callout.xsl"/>
+ <xsl:include href="html-base.xsl"/>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/index.xsl b/tools/boostbook/xsl/index.xsl
new file mode 100644
index 0000000000..3a9319395a
--- /dev/null
+++ b/tools/boostbook/xsl/index.xsl
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:template match="class-index">
+
+ </xsl:template>
+
+ <xsl:template match="function-index">
+
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/library.xsl b/tools/boostbook/xsl/library.xsl
new file mode 100644
index 0000000000..4d299feedc
--- /dev/null
+++ b/tools/boostbook/xsl/library.xsl
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:key name="library-categories" match="library"
+ use="libraryinfo/librarycategory/@name"/>
+
+ <xsl:template match="librarylist">
+ <itemizedlist spacing="compact">
+ <xsl:apply-templates select="//library"
+ mode="build-library-list">
+ <xsl:sort select="@name"/>
+ </xsl:apply-templates>
+ </itemizedlist>
+ </xsl:template>
+
+ <xsl:template name="library.link">
+ <xsl:param name="node" select="."/>
+ <xsl:param name="name" select="$node/attribute::name"/>
+
+ <xsl:choose>
+ <xsl:when test="$node/attribute::html-only = 1">
+ <xsl:variable name="url">
+ <xsl:choose>
+ <xsl:when test="$node/attribute::url">
+ <xsl:value-of select="$node/attribute::url"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($boost.root,
+ '/libs/',
+ $node/attribute::dirname,
+ '/index.html')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <ulink>
+ <xsl:attribute name="url">
+ <xsl:value-of select="$url"/>
+ </xsl:attribute>
+ <xsl:value-of select="$name"/>
+ </ulink>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:choose>
+ <xsl:when test="$node/attribute::id">
+ <xsl:value-of select="$node/attribute::id"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="$name"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="library" mode="build-library-list">
+ <listitem>
+ <simpara>
+ <xsl:call-template name="library.link"/>
+ <xsl:text> - </xsl:text>
+ <xsl:apply-templates select="libraryinfo/librarypurpose"
+ mode="build-library-list"/>
+ </simpara>
+ </listitem>
+ </xsl:template>
+
+ <xsl:template match="librarypurpose" mode="build-library-list">
+ <xsl:apply-templates/>
+ <xsl:text>, from </xsl:text>
+ <xsl:apply-templates select="../author" mode="display-author-list"/>
+ </xsl:template>
+
+ <xsl:template match="author" mode="display-author-list">
+ <xsl:if test="(position() &gt; 1) and (count(../author) &gt; 2)">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ <xsl:if test="(position() = count(../author)) and (position() &gt; 1)">
+ <xsl:if test="position() &lt; 3">
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ <xsl:text>and </xsl:text>
+ </xsl:if>
+ <xsl:apply-templates select="firstname/text()"/>
+ <xsl:text> </xsl:text>
+ <xsl:apply-templates select="surname/text()"/>
+ <xsl:if test="(position() = count(../author))">
+ <xsl:text>.</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="librarycategorylist">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="librarycategorydef">
+ <section>
+ <title><xsl:apply-templates/></title>
+ <xsl:variable name="name" select="@name"/>
+ <itemizedlist spacing="compact">
+ <xsl:apply-templates select="key('library-categories', $name)"
+ mode="build-library-list">
+ <xsl:sort select="@name"/>
+ </xsl:apply-templates>
+ </itemizedlist>
+ </section>
+ </xsl:template>
+
+ <xsl:template match="libraryinfo">
+ <chapterinfo>
+ <xsl:apply-templates select="author|authorgroup/author|copyright|legalnotice"/>
+ </chapterinfo>
+ </xsl:template>
+
+ <xsl:template match="librarypurpose|librarycategory"/>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/lookup.xsl b/tools/boostbook/xsl/lookup.xsl
new file mode 100644
index 0000000000..d37e787a7a
--- /dev/null
+++ b/tools/boostbook/xsl/lookup.xsl
@@ -0,0 +1,424 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ version="1.0">
+
+ <!-- Maximum length of directory and file names is 31 characters.
+ '.html' uses 5 characters.
+ 31 - 5 = 26 -->
+ <xsl:param name="boost.max.id.part.length">26</xsl:param>
+
+ <!-- Generate an ID for the entity referenced -->
+ <xsl:template name="generate.id">
+ <xsl:param name="node" select="."/>
+ <xsl:apply-templates select="$node" mode="generate.id"/>
+ </xsl:template>
+
+ <xsl:template match="*" mode="generate.id">
+ <xsl:value-of select="generate-id(.)"/>
+ <xsl:text>-bb</xsl:text>
+ </xsl:template>
+
+ <xsl:template name="strip-qualifiers-non-template">
+ <xsl:param name="name"/>
+ <xsl:choose>
+ <xsl:when test="contains($name, '&gt;')">
+ <xsl:call-template name="strip-qualifiers-non-template">
+ <xsl:with-param name="name" select="substring-after($name, '&gt;')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains($name, '::')">
+ <xsl:call-template name="strip-qualifiers-non-template">
+ <xsl:with-param name="name" select="substring-after($name, '::')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="strip-balanced">
+ <xsl:param name="name"/>
+ <xsl:param name="open" select="'&lt;'"/>
+ <xsl:param name="close" select="'&gt;'"/>
+ <xsl:param name="depth" select="0"/>
+ <xsl:choose>
+ <xsl:when test="contains($name, $open)
+ and not(contains(substring-before($name, $open), $close))">
+ <xsl:call-template name="strip-balanced">
+ <xsl:with-param name="name" select="substring-after($name, $open)"/>
+ <xsl:with-param name="open" select="$open"/>
+ <xsl:with-param name="close" select="$close"/>
+ <xsl:with-param name="depth" select="$depth + 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains($name, $close) and ($depth &gt; 1)">
+ <xsl:call-template name="strip-balanced">
+ <xsl:with-param name="name" select="substring-after($name, $close)"/>
+ <xsl:with-param name="open" select="$open"/>
+ <xsl:with-param name="close" select="$close"/>
+ <xsl:with-param name="depth" select="$depth - 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-after($name, $close)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="strip-qualifiers-template">
+ <xsl:param name="name"/>
+ <xsl:choose>
+ <xsl:when test="contains($name, '::')
+ and not(contains(substring-before($name, '::'), '&lt;'))">
+ <xsl:call-template name="strip-qualifiers-template">
+ <xsl:with-param name="name" select="substring-after($name, '::')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="rest">
+ <xsl:call-template name="strip-balanced">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$rest != ''">
+ <xsl:call-template name="strip-qualifiers-template">
+ <xsl:with-param name="name" select="$rest"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Strip the qualifiers off a qualified name and return the unqualified
+ name. For instance, "boost::python::function" would become just
+ "function".
+ Must handle ns::foo -> foo
+ Must handle ns::foo<bar::baz> -> foo<bar::baz>
+ Must handle ns::foo<bar::baz>::nested -> nested
+ Must handle ns::foo<x>::bar<y> -> bar<y> -->
+ <xsl:template name="strip-qualifiers">
+ <xsl:param name="name"/>
+ <xsl:choose>
+ <xsl:when test="substring($name, string-length($name)) = '&gt;'">
+ <xsl:call-template name="strip-qualifiers-template">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="strip-qualifiers-non-template">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Build the fully-qualified id of the given node -->
+ <xsl:template name="fully-qualified-id">
+ <xsl:param name="node"/>
+
+ <xsl:apply-templates select="$node" mode="fully-qualified-name">
+ <xsl:with-param name="is.id" select="true()"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <!-- Build the fully-qualified name of the given node -->
+ <xsl:template name="fully-qualified-name">
+ <xsl:param name="node"/>
+ <xsl:apply-templates select="$node" mode="fully-qualified-name"/>
+ </xsl:template>
+
+ <!-- Hack to make the node we are building the current node so that the
+ ancestor:: syntax will work -->
+ <xsl:template match="*" mode="fully-qualified-name">
+ <xsl:param name="is.id" select="false()" />
+ <xsl:call-template name="build-fully-qualified-name">
+ <xsl:with-param name="is.id" select="$is.id"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- The real routine that builds a fully-qualified name for the current
+ node. -->
+ <xsl:template name="build-fully-qualified-name">
+ <xsl:param name="is.id" select="false()" />
+
+ <!-- Determine the set of ancestor namespaces -->
+ <xsl:variable name="ancestors"
+ select="ancestor::namespace|
+ ancestor::class|ancestor::struct|ancestor::union|
+ ancestor::class-specialization|ancestor::struct-specialization|ancestor::union-specialization"/>
+
+ <xsl:for-each select="$ancestors">
+ <xsl:apply-templates select="." mode="fast-print-id-part">
+ <xsl:with-param name="is.id" select="$is.id"/>
+ </xsl:apply-templates>
+ <xsl:choose>
+ <xsl:when test="$is.id"><xsl:text>.</xsl:text></xsl:when>
+ <xsl:otherwise><xsl:text>::</xsl:text></xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ <xsl:apply-templates select="." mode="fast-print-id-part">
+ <xsl:with-param name="is.id" select="$is.id"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:variable name="elements-with-ids">
+ <xsl:apply-templates select="namespace|class|struct|union|class-specialization|struct-specialization|union-specialization"
+ mode="preprocess-ids"/>
+ </xsl:variable>
+
+ <xsl:variable name="fast-elements" select="exsl:node-set($elements-with-ids)"/>
+
+ <xsl:template match="*" mode="preprocess-ids">
+ <element>
+ <xsl:attribute name="id">
+ <xsl:value-of select="generate-id()"/>
+ </xsl:attribute>
+ <xsl:attribute name="part-id">
+ <xsl:call-template name="print-id-part"/>
+ </xsl:attribute>
+ </element>
+ </xsl:template>
+
+ <xsl:template name="print-id-part">
+ <xsl:apply-templates select="." mode="print-id-part"/>
+ </xsl:template>
+
+ <xsl:template match="*" mode="fast-print-id-part">
+ <xsl:param name="is.id"/>
+ <xsl:choose>
+ <xsl:when test="not($is.id)">
+ <xsl:apply-templates select="." mode="print-name"/>
+ </xsl:when>
+ <xsl:when test="$fast-elements[@id=generate-id()]">
+ <xsl:value-of select="$fast-elements[@id=generate-id()]/@part-id"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="." mode="print-id-part">
+ <xsl:with-param name="is.id" select="$is.id"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Print the part of a fully qualified name for a single element -->
+ <xsl:template match="*" mode="print-id-part">
+ <xsl:param name="is.id"/>
+
+ <xsl:variable name="part">
+ <xsl:apply-templates select="." mode="print-name"/>
+ </xsl:variable>
+
+ <xsl:variable name="unique-name">
+ <xsl:apply-templates select="." mode="unique.name"/>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test=
+ "$is.id and (
+ string-length($part) &gt; $boost.max.id.part.length or
+ $unique-name = 0 or
+ translate($part, '.&lt;&gt;;\:*?&quot;| ', '') != $part
+ )">
+ <xsl:variable name="normalized" select="translate(normalize-space(translate($part, '.&lt;&gt;;\:*?&quot;|_', ' ')), ' ', '_')"/>
+ <xsl:value-of select =
+ "concat(
+ substring($normalized, 1, $boost.max.id.part.length - string-length(generate-id(.) - 1)),
+ concat('_', generate-id(.)))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$part"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Override this if an id might not be unique -->
+ <xsl:template match="*" mode="unique.name">
+ <xsl:value-of select="1"/>
+ </xsl:template>
+
+ <xsl:template match="function|overloaded-function" mode="unique.name">
+ <xsl:value-of select="number(count(key('named-entities',
+ translate(@name, $uppercase-letters, $lowercase-letters))) = 1)"/>
+ </xsl:template>
+
+ <!-- Print the name of the current node -->
+ <xsl:template match="*" mode="print-name">
+ <xsl:value-of select="@name"/>
+ </xsl:template>
+
+ <xsl:template match="template-arg" mode="print-name">
+ <xsl:if test="position() &gt; 1">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ <xsl:value-of select="text()"/>
+ <xsl:if test="@pack=1">
+ <xsl:text>...</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template
+ match="struct-specialization|class-specialization|union-specialization"
+ mode="print-name">
+ <xsl:value-of select="@name"/>
+ <xsl:text>&lt;</xsl:text>
+ <xsl:apply-templates select="specialization/template-arg" mode="print-name"/>
+ <xsl:text>&gt;</xsl:text>
+ </xsl:template>
+
+ <xsl:template name="concat-directives">
+ <xsl:param name="directives"/>
+ <xsl:for-each select="$directives">
+ <xsl:apply-templates select="." mode="print-name"/>
+ <xsl:text>::</xsl:text>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="find-nodes-matching-name">
+ <!-- The name we are looking for -->
+ <xsl:param name="name"/>
+
+ <!-- The context in which this name occurs -->
+ <xsl:param name="context"/>
+
+ <!-- The node that we are checking against -->
+ <xsl:param name="nodes"/>
+
+ <!-- The set of using directives for this context node -->
+ <xsl:variable name="directives"
+ select="$context/ancestor::*/using-namespace |
+ $context/ancestor::namespace |
+ $context/ancestor::*/using-class |
+ $context/ancestor::class |
+ $context/ancestor::struct"/>
+
+ <xsl:variable name="directives-str">
+ <xsl:call-template name="concat-directives">
+ <xsl:with-param name="directives" select="$directives"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:apply-templates select="$nodes" mode="generate-cxx-links">
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="directives-str" select="$directives-str"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="*" mode="generate-cxx-links">
+ <xsl:param name="name"/>
+ <xsl:param name="directives-str"/>
+
+ <xsl:variable name="node-name">
+ <xsl:call-template name="fully-qualified-name">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="leading-chars"
+ select="string-length($node-name) - string-length($name)"/>
+
+ <!-- Check if this node matches any visible namespace -->
+ <xsl:if test="string-length($node-name) &gt;= string-length($name) and
+ substring($node-name, $leading-chars + 1,
+ string-length($name)) = $name">
+ <xsl:variable name="qualifiers"
+ select="substring($node-name, 1, $leading-chars)"/>
+ <xsl:if test="contains($directives-str, $qualifiers)">
+ <xsl:variable name="myid">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:variable>
+ <cxx-link-helper>
+ <xsl:attribute name="id">
+ <xsl:value-of select="$myid"/>
+ </xsl:attribute>
+ <xsl:attribute name="namespace">
+ <xsl:value-of select="$qualifiers"/>
+ </xsl:attribute>
+ <xsl:text>random text</xsl:text>
+ </cxx-link-helper>
+ </xsl:if>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="cxx-link-name">
+ <!-- The actual lookup node -->
+ <xsl:param name="lookup"/>
+
+ <!-- The type of name to lookup (e.g., class) -->
+ <xsl:param name="type"/>
+
+ <!-- The name we are looking for -->
+ <xsl:param name="name"/>
+
+ <!-- The name we will display -->
+ <xsl:param name="display-name"/>
+
+ <!-- The name we are looking for (unqualified)-->
+ <xsl:param name="unqualified-name"/>
+
+ <!-- The list of nodes that match the lookup node in both name and type -->
+ <xsl:param name="nodes"/>
+
+ <!-- Filter the nodes to leave only the ones that are in scope. -->
+ <xsl:variable name="matches1">
+ <xsl:call-template name="find-nodes-matching-name">
+ <xsl:with-param name="name" select="$name"/>
+ <xsl:with-param name="nodes" select="$nodes"/>
+ <xsl:with-param name="context" select="$lookup"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="matches" select="exsl:node-set($matches1)//cxx-link-helper"/>
+
+ <xsl:choose>
+ <xsl:when test="count($matches) = 0">
+ <xsl:message>
+ <xsl:text>Cannot find </xsl:text>
+ <xsl:value-of select="$type"/>
+ <xsl:text> named '</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>'</xsl:text>
+ </xsl:message>
+ <xsl:value-of select="$display-name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- If we found more than one, print a message and take the first -->
+ <xsl:if test="count($matches) &gt; 1">
+ <xsl:message>
+ <xsl:text>Reference to </xsl:text>
+ <xsl:value-of select="$type"/>
+ <xsl:text> '</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>' is ambiguous. Found:</xsl:text>
+ <xsl:for-each select="$matches">
+ <xsl:text>
+ Match in namespace ::</xsl:text>
+ <xsl:value-of select="@namespace"/>
+ </xsl:for-each>
+ </xsl:message>
+ </xsl:if>
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:value-of select="$matches[position() = 1]/@id"/>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="$display-name"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/macro.xsl b/tools/boostbook/xsl/macro.xsl
new file mode 100644
index 0000000000..e3962954b2
--- /dev/null
+++ b/tools/boostbook/xsl/macro.xsl
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:template match="macro" mode="synopsis">
+ <xsl:param name="indentation" select="0"/>
+
+ <xsl:text>&#10;</xsl:text>
+ <xsl:if
+ test="not(local-name(preceding-sibling::*[position()=1])=local-name(.))">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="macro-synopsis">
+ <xsl:with-param name="link-type" select="'link'"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="macro" mode="reference">
+ <xsl:call-template name="reference-documentation">
+ <xsl:with-param name="refname" select="@name"/>
+ <xsl:with-param name="purpose" select="purpose/*|purpose/text()"/>
+ <xsl:with-param name="anchor">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ <xsl:with-param name="name">
+ <xsl:text>Macro </xsl:text>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="synopsis">
+ <xsl:call-template name="header-link"/>
+ <xsl:call-template name="macro-synopsis">
+ <xsl:with-param name="link-type" select="'none'"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <xsl:apply-templates select="description"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template name="macro-synopsis">
+ <xsl:param name="link-type"/>
+
+ <xsl:call-template name="link-or-anchor">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id" select="."/>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="@name"/>
+ <xsl:with-param name="link-type" select="$link-type"/>
+ </xsl:call-template>
+
+ <xsl:if test="@kind='functionlike'">
+ <xsl:text>(</xsl:text>
+ <xsl:for-each select="macro-parameter">
+ <xsl:if test="position() &gt; 1">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ <xsl:value-of select="@name"/>
+ </xsl:for-each>
+ <xsl:text>)</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="macro" mode="generate.id">
+ <xsl:value-of select="@name"/>
+ <xsl:if test="count(key('named-entities',
+ translate(@name, $uppercase-letters, $lowercase-letters)))!=1">
+ <xsl:text>_</xsl:text>
+ <xsl:value-of select="generate-id(.)"/>
+ </xsl:if>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/manpages.xsl b/tools/boostbook/xsl/manpages.xsl
new file mode 100644
index 0000000000..2f781c2992
--- /dev/null
+++ b/tools/boostbook/xsl/manpages.xsl
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+ <!-- Import the man pages stylesheet -->
+ <xsl:import
+ href="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"/>
+
+ <xsl:param name="generate.manifest" select="1"/>
+ <xsl:param name="manifest">man.manifest</xsl:param>
+
+ <xsl:template match="literallayout">
+ <xsl:text>&#10;.nf&#10;</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>&#10;.fi&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="para|simpara|remark" mode="list">
+ <xsl:variable name="foo">
+ <xsl:apply-templates/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="literallayout">
+ <xsl:copy-of select="$foo"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="normalize-space($foo)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:if test="following-sibling::para or following-sibling::simpara or
+ following-sibling::remark">
+ <!-- Make sure multiple paragraphs within a list item don't -->
+ <!-- merge together. -->
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="build.refentry.filename">
+ <xsl:param name="node" select="."/>
+ <xsl:variable name="section" select="$node/refmeta/manvolnum"/>
+ <xsl:variable name="name" select="$node/refnamediv/refname[1]"/>
+ <xsl:value-of select="concat('man', $section, '/',
+ translate(normalize-space($name),
+ '&lt;&gt;', '__'),
+ '.', $section)"/>
+
+ </xsl:template>
+
+ <xsl:template match="refentry" mode="manifest">
+ <xsl:call-template name="build.refentry.filename"/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="/">
+ <xsl:choose>
+ <xsl:when test="//refentry">
+ <xsl:apply-templates select="//refentry"/>
+ <xsl:if test="$generate.manifest=1">
+ <xsl:call-template name="write.text.chunk">
+ <xsl:with-param name="filename" select="$manifest"/>
+ <xsl:with-param name="content">
+ <xsl:value-of select="$manifest"/>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:apply-templates select="//refentry" mode="manifest"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>No refentry elements!</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+<xsl:template match="refentry">
+ <xsl:variable name="section" select="refmeta/manvolnum"/>
+ <xsl:variable name="name" select="refnamediv/refname[1]"/>
+
+ <!-- standard man page width is 64 chars; 6 chars needed for the two
+ (x) volume numbers, and 2 spaces, leaves 56 -->
+ <xsl:variable name="twidth" select="(56 - string-length(refmeta/refentrytitle)) div 2"/>
+
+ <xsl:variable name="reftitle"
+ select="substring(refmeta/refentrytitle, 1, $twidth)"/>
+
+ <xsl:variable name="title">
+ <xsl:choose>
+ <xsl:when test="refentryinfo/title">
+ <xsl:value-of select="refentryinfo/title"/>
+ </xsl:when>
+ <xsl:when test="../referenceinfo/title">
+ <xsl:value-of select="../referenceinfo/title"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="date">
+ <xsl:choose>
+ <xsl:when test="refentryinfo/date">
+ <xsl:value-of select="refentryinfo/date"/>
+ </xsl:when>
+ <xsl:when test="../referenceinfo/date">
+ <xsl:value-of select="../referenceinfo/date"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="productname">
+ <xsl:choose>
+ <xsl:when test="refentryinfo/productname">
+ <xsl:value-of select="refentryinfo/productname"/>
+ </xsl:when>
+ <xsl:when test="../referenceinfo/productname">
+ <xsl:value-of select="../referenceinfo/productname"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:call-template name="write.text.chunk">
+ <xsl:with-param name="filename">
+ <xsl:call-template name="build.refentry.filename"/>
+ </xsl:with-param>
+ <xsl:with-param name="content">
+ <xsl:text>.\"Generated by db2man.xsl. Don't modify this, modify the source.
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "</xsl:text>
+ <xsl:value-of select="translate($reftitle,'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
+ <xsl:text>" </xsl:text>
+ <xsl:value-of select="refmeta/manvolnum[1]"/>
+ <xsl:text> "</xsl:text>
+ <xsl:value-of select="normalize-space($date)"/>
+ <xsl:text>" "</xsl:text>
+ <xsl:value-of select="normalize-space($productname)"/>
+ <xsl:text>" "</xsl:text>
+ <xsl:value-of select="$title"/>
+ <xsl:text>"
+</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>&#10;</xsl:text>
+
+ <!-- Author section -->
+ <xsl:choose>
+ <xsl:when test="refentryinfo//author">
+ <xsl:apply-templates select="refentryinfo" mode="authorsect"/>
+ </xsl:when>
+ <xsl:when test="/book/bookinfo//author">
+ <xsl:apply-templates select="/book/bookinfo" mode="authorsect"/>
+ </xsl:when>
+ <xsl:when test="/article/articleinfo//author">
+ <xsl:apply-templates select="/article/articleinfo" mode="authorsect"/>
+ </xsl:when>
+ </xsl:choose>
+
+ </xsl:with-param>
+ </xsl:call-template>
+ <!-- Now generate stub include pages for every page documented in
+ this refentry (except the page itself) -->
+ <xsl:for-each select="refnamediv/refname">
+ <xsl:if test=". != $name">
+ <xsl:call-template name="write.text.chunk">
+ <xsl:with-param name="filename"
+ select="concat(normalize-space(.), '.', $section)"/>
+ <xsl:with-param name="content" select="concat('.so man',
+ $section, '/', $name, '.', $section, '&#10;')"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/navbar.xsl b/tools/boostbook/xsl/navbar.xsl
new file mode 100644
index 0000000000..ffbbbcb5ea
--- /dev/null
+++ b/tools/boostbook/xsl/navbar.xsl
@@ -0,0 +1,409 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+<!-- Already included in the main style sheet -->
+<!-- <xsl:import href="relative-href.xsl"/> -->
+
+ <!--
+ boost.defaults:
+ *none - only use explicitly set parameters
+ Boost - use standard boost settings, can be overridden
+ -->
+ <xsl:param name = "boost.defaults" select = "'none'"/>
+
+ <!--
+ how to render the Home | Libraries | ... | More contents
+ *none - do not display ("standalone" mode)
+ horizontal - display in old-Boost style format (default for Boost)
+ vertical - like the new Getting Started layout
+ -->
+ <xsl:param name = "nav.layout">
+ <xsl:choose>
+ <xsl:when test = "$boost.defaults='Boost'">horizontal</xsl:when>
+ <xsl:otherwise>none</xsl:otherwise>
+ </xsl:choose>
+ </xsl:param>
+ <!--
+ header border layout
+ Boost - place the old-Boost border around the header
+ *none - do not place a border around the header
+ -->
+ <xsl:param name = "nav.border" select = "'none'" />
+
+ <!--
+ nav.flow:
+ none - do not display navigation at the header
+ DocBook - display the navigation after the header
+ *Spirit - display "mini" navigation on the right
+ -->
+ <xsl:param name = "nav.flow" select = "'Spirit'"/>
+
+ <!-- location of the various Boost elements -->
+
+ <xsl:param name = "boost.root" select = "'../..'"/>
+ <xsl:param name = "boost.website" select = "'http://www.boost.org'"/>
+ <!-- Logo image location, leave empty for no logo -->
+ <xsl:param name = "boost.image.src">
+ <xsl:if test = "$boost.defaults = 'Boost'">
+ <xsl:value-of select = "concat($boost.root, '/boost.png')"/>
+ </xsl:if>
+ </xsl:param>
+ <xsl:param name = "boost.image.alt">
+ <xsl:if test = "$boost.defaults = 'Boost'">
+ <xsl:value-of select = "'Boost C++ Libraries'"/>
+ </xsl:if>
+ </xsl:param>
+ <xsl:param name = "boost.image.w">
+ <xsl:if test = "$boost.defaults = 'Boost'">
+ <xsl:value-of select = "277"/>
+ </xsl:if>
+ </xsl:param>
+ <xsl:param name = "boost.image.h">
+ <xsl:if test = "$boost.defaults = 'Boost'">
+ <xsl:value-of select = "86"/>
+ </xsl:if>
+ </xsl:param>
+ <xsl:param name = "boost.libraries">
+ <xsl:if test = "$boost.defaults = 'Boost'">
+ <xsl:value-of select = "concat($boost.root, '/libs/libraries.htm')"/>
+ </xsl:if>
+ </xsl:param>
+
+ <!-- header -->
+
+ <xsl:template name = "header.navigation">
+ <xsl:param name = "prev" select = "/foo"/>
+ <xsl:param name = "next" select = "/foo"/>
+ <xsl:param name = "nav.context"/>
+
+ <xsl:variable name = "home" select = "/*[1]"/>
+ <xsl:variable name = "up" select = "parent::*"/>
+
+ <xsl:if test = "boolean(normalize-space($boost.image.src)) or $nav.layout != 'none'">
+ <table cellpadding = "2" width = "100%"><tr>
+ <xsl:if test = "$nav.border = 'Boost'">
+ <xsl:attribute name = "class">boost-head</xsl:attribute>
+ </xsl:if>
+
+ <td valign = "top">
+ <xsl:if test = "$nav.border = 'Boost'">
+ <xsl:attribute name = "style">background-color: white; width: 50%;</xsl:attribute>
+ </xsl:if>
+ <xsl:if test = "boolean(normalize-space($boost.image.src))">
+ <img alt="{$boost.image.alt}" width="{$boost.image.w}" height="{$boost.image.h}">
+ <xsl:attribute name="src">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="$boost.image.src"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </img>
+ </xsl:if>
+ </td><xsl:choose>
+ <xsl:when test = "$nav.layout = 'horizontal'">
+ <xsl:call-template name = "header.navdata-horiz"/>
+ </xsl:when><xsl:when test = "$nav.layout = 'vertical'">
+ <xsl:call-template name = "header.navdata-vert"/>
+ </xsl:when>
+ </xsl:choose>
+ </tr></table>
+ <hr/>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test = "$nav.flow = 'DocBook'">
+ <table width = "100%" class = "navheader">
+ <xsl:call-template name = "navbar.docbook-homeinfo">
+ <xsl:with-param name = "prev" select = "$prev"/>
+ <xsl:with-param name = "next" select = "$next"/>
+ <xsl:with-param name = "nav.context" select = "$nav.context"/>
+ </xsl:call-template>
+ <xsl:call-template name = "navbar.docbook-prevnext">
+ <xsl:with-param name = "prev" select = "$prev"/>
+ <xsl:with-param name = "next" select = "$next"/>
+ <xsl:with-param name = "nav.context" select = "$nav.context"/>
+ </xsl:call-template>
+ </table>
+ </xsl:when><xsl:when test = "$nav.flow = 'Spirit'">
+ <xsl:call-template name = "navbar.spirit">
+ <xsl:with-param name = "prev" select = "$prev"/>
+ <xsl:with-param name = "next" select = "$next"/>
+ <xsl:with-param name = "nav.context" select = "$nav.context"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name = "header.navdata-horiz">
+ <xsl:variable name="home_link">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="concat( $boost.root, '/index.html' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="libraries_link">
+ <xsl:if test = "boolean($boost.libraries)">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="$boost.libraries"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="people_link">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="concat( $boost.website, '/users/people.html' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="faq_link">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="concat( $boost.website, '/users/faq.html' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="more_link">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="concat( $boost.root, '/more/index.htm' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test = "$nav.border = 'Boost'">
+ <td align = "center" class = "boost-headtd"><a href = "{$home_link}" class = "boost-headelem">Home</a></td>
+ <xsl:if test = "boolean($libraries_link)">
+ <td align = "center" class = "boost-headtd"><a href = "{$libraries_link}" class = "boost-headelem">Libraries</a></td>
+ </xsl:if>
+ <td align = "center" class = "boost-headtd"><a href = "{$people_link}" class = "boost-headelem">People</a></td>
+ <td align = "center" class = "boost-headtd"><a href = "{$faq_link}" class = "boost-headelem">FAQ</a></td>
+ <td align = "center" class = "boost-headtd"><a href = "{$more_link}" class = "boost-headelem">More</a></td>
+ </xsl:when><xsl:otherwise>
+ <td align = "center"><a href = "{$home_link}">Home</a></td>
+ <td align = "center"><a href = "{$libraries_link}">Libraries</a></td>
+ <td align = "center"><a href = "{$people_link}">People</a></td>
+ <td align = "center"><a href = "{$faq_link}">FAQ</a></td>
+ <td align = "center"><a href = "{$more_link}">More</a></td>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name = "header.navdata-vert">
+ <xsl:variable name="home_link">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="concat( $boost.root, '/index.html' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="libraries_link">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="$boost.libraries"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="people_link">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="concat( $boost.website, '/users/people.html' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="faq_link">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="concat( $boost.website, '/users/faq.html' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="more_link">
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="concat( $boost.root, '/more/index.htm' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <td><div>
+ <xsl:if test = "$nav.border != 'Boost'">
+ <xsl:attribute name = "class">boost-toc</xsl:attribute>
+ </xsl:if>
+ <div><a href = "{$home_link}">Home</a></div>
+ <div><a href = "{$libraries_link}">Libraries</a></div>
+ <div><a href = "{$people_link}">People</a></div>
+ <div><a href = "{$faq_link}">FAQ</a></div>
+ <div><a href = "{$more_link}">More</a></div>
+ </div></td>
+ </xsl:template>
+
+
+ <!-- footer -->
+
+ <xsl:template name = "footer.navigation">
+ <xsl:param name = "prev" select = "/foo"/>
+ <xsl:param name = "next" select = "/foo"/>
+ <xsl:param name = "nav.context"/>
+
+ <hr/>
+ <xsl:choose>
+ <xsl:when test = "$nav.flow = 'DocBook'">
+ <table width = "100%" class = "navheader">
+ <xsl:call-template name = "navbar.docbook-prevnext">
+ <xsl:with-param name = "prev" select = "$prev"/>
+ <xsl:with-param name = "next" select = "$next"/>
+ <xsl:with-param name = "nav.context" select = "$nav.context"/>
+ </xsl:call-template>
+ <xsl:call-template name = "navbar.docbook-homeinfo">
+ <xsl:with-param name = "prev" select = "$prev"/>
+ <xsl:with-param name = "next" select = "$next"/>
+ <xsl:with-param name = "nav.context" select = "$nav.context"/>
+ </xsl:call-template>
+ </table>
+ </xsl:when><xsl:when test = "$nav.flow = 'Spirit'">
+ <xsl:call-template name = "navbar.spirit">
+ <xsl:with-param name = "prev" select = "$prev"/>
+ <xsl:with-param name = "next" select = "$next"/>
+ <xsl:with-param name = "nav.context" select = "$nav.context"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- navbar -->
+
+ <xsl:template name = "navbar.docbook-homeinfo">
+ <xsl:param name = "prev" select = "/foo"/>
+ <xsl:param name = "next" select = "/foo"/>
+ <xsl:param name = "nav.context"/>
+
+ <xsl:variable name = "home" select = "/*[1]"/>
+ <tr>
+ <td align = "left" width = "40%">
+ <xsl:if test = "$navig.showtitles != 0"> <!-- prev:name -->
+ <xsl:apply-templates select = "$prev" mode = "object.title.markup"/>
+ </xsl:if>
+ </td><td align = "center" width = "20%">
+ <!-- home -->
+ <xsl:if test = "$home != . or $nav.context = 'toc'">
+ <a accesskey = "h">
+ <xsl:attribute name = "href"><xsl:call-template name = "href.target">
+ <xsl:with-param name = "object" select = "$home"/>
+ </xsl:call-template></xsl:attribute>
+ <xsl:call-template name = "navig.content">
+ <xsl:with-param name = "direction" select = "'home'"/>
+ </xsl:call-template>
+ </a>
+ <xsl:if test = "$chunk.tocs.and.lots != 0 and $nav.context != 'toc'">
+ <xsl:text>|</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test = "$chunk.tocs.and.lots != 0 and $nav.context != 'toc'"><a accesskey = "t">
+ <xsl:attribute name = "href">
+ <xsl:apply-templates select = "/*[1]" mode = "recursive-chunk-filename"/>
+ <xsl:text>-toc</xsl:text>
+ <xsl:value-of select = "$html.ext"/>
+ </xsl:attribute>
+ <xsl:call-template name = "gentext">
+ <xsl:with-param name = "key" select = "'nav-toc'"/>
+ </xsl:call-template>
+ </a></xsl:if>
+ </td><td align = "right" width = "40%">
+ <xsl:if test = "$navig.showtitles != 0"> <!-- next:name -->
+ <xsl:apply-templates select = "$next" mode = "object.title.markup"/>
+ </xsl:if>
+ </td>
+ </tr>
+ </xsl:template>
+
+ <xsl:template name = "navbar.docbook-prevnext">
+ <xsl:param name = "prev" select = "/foo"/>
+ <xsl:param name = "next" select = "/foo"/>
+ <xsl:param name = "nav.context"/>
+
+ <xsl:variable name = "up" select = "parent::*"/>
+ <tr>
+ <td align = "left" width = "40%">
+ <xsl:if test = "count($prev)>0"><a accesskey = "p"> <!-- prev -->
+ <xsl:attribute name = "href"><xsl:call-template name = "href.target">
+ <xsl:with-param name = "object" select = "$prev"/>
+ </xsl:call-template></xsl:attribute>
+ <xsl:call-template name = "navig.content">
+ <xsl:with-param name = "direction" select = "'prev'"/>
+ </xsl:call-template>
+ </a></xsl:if>
+ </td><td align = "center" width = "20%">
+ <xsl:if test = "count($up)>0"><a accesskey = "u"> <!-- up -->
+ <xsl:attribute name = "href"><xsl:call-template name = "href.target">
+ <xsl:with-param name = "object" select = "$up"/>
+ </xsl:call-template></xsl:attribute>
+ <xsl:call-template name = "navig.content">
+ <xsl:with-param name = "direction" select = "'up'"/>
+ </xsl:call-template>
+ </a></xsl:if>
+ </td><td align = "right" width = "40%">
+ <xsl:if test = "count($next)>0"><a accesskey = "n"> <!-- next -->
+ <xsl:attribute name = "href"><xsl:call-template name = "href.target">
+ <xsl:with-param name = "object" select = "$next"/>
+ </xsl:call-template></xsl:attribute>
+ <xsl:call-template name = "navig.content">
+ <xsl:with-param name = "direction" select = "'next'"/>
+ </xsl:call-template>
+ </a></xsl:if>
+ </td>
+ </tr>
+ </xsl:template>
+
+ <xsl:template name = "navbar.spirit">
+ <xsl:param name = "prev" select = "/foo"/>
+ <xsl:param name = "next" select = "/foo"/>
+ <xsl:param name = "nav.context"/>
+
+ <xsl:variable name = "home" select = "/*[1]"/>
+ <xsl:variable name = "up" select = "parent::*"/>
+
+ <div class = "spirit-nav">
+ <!-- prev -->
+ <xsl:if test = "count($prev)>0"><a accesskey = "p">
+ <xsl:attribute name = "href"><xsl:call-template name = "href.target">
+ <xsl:with-param name = "object" select = "$prev"/>
+ </xsl:call-template></xsl:attribute>
+ <xsl:call-template name = "navig.content">
+ <xsl:with-param name = "direction" select = "'prev'"/>
+ </xsl:call-template>
+ </a></xsl:if>
+ <!-- up -->
+ <xsl:if test = "count($up)>0"><a accesskey = "u">
+ <xsl:attribute name = "href"><xsl:call-template name = "href.target">
+ <xsl:with-param name = "object" select = "$up"/>
+ </xsl:call-template></xsl:attribute>
+ <xsl:call-template name = "navig.content">
+ <xsl:with-param name = "direction" select = "'up'"/>
+ </xsl:call-template>
+ </a></xsl:if>
+ <!-- home -->
+ <xsl:if test = "generate-id($home) != generate-id(.) or $nav.context = 'toc'">
+ <a accesskey = "h">
+ <xsl:attribute name = "href"><xsl:call-template name = "href.target">
+ <xsl:with-param name = "object" select = "$home"/>
+ </xsl:call-template></xsl:attribute>
+ <xsl:call-template name = "navig.content">
+ <xsl:with-param name = "direction" select = "'home'"/>
+ </xsl:call-template>
+ </a>
+ <xsl:if test = "$chunk.tocs.and.lots != 0 and $nav.context != 'toc'">
+ <xsl:text>|</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test = "$chunk.tocs.and.lots != 0 and $nav.context != 'toc'"><a accesskey = "t">
+ <xsl:attribute name = "href">
+ <xsl:apply-templates select = "/*[1]" mode = "recursive-chunk-filename"/>
+ <xsl:text>-toc</xsl:text>
+ <xsl:value-of select = "$html.ext"/>
+ </xsl:attribute>
+ <xsl:call-template name = "gentext">
+ <xsl:with-param name = "key" select = "'nav-toc'"/>
+ </xsl:call-template>
+ </a></xsl:if>
+ <!-- next -->
+ <xsl:if test = "count($next)>0"><a accesskey = "n">
+ <xsl:attribute name = "href"><xsl:call-template name = "href.target">
+ <xsl:with-param name = "object" select = "$next"/>
+ </xsl:call-template></xsl:attribute>
+ <xsl:call-template name = "navig.content">
+ <xsl:with-param name = "direction" select = "'next'"/>
+ </xsl:call-template>
+ </a></xsl:if>
+ </div>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/reference.xsl b/tools/boostbook/xsl/reference.xsl
new file mode 100644
index 0000000000..b46e591b32
--- /dev/null
+++ b/tools/boostbook/xsl/reference.xsl
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:include href="annotation.xsl"/>
+ <xsl:include href="template.xsl"/>
+ <xsl:include href="function.xsl"/>
+ <xsl:include href="type.xsl"/>
+ <xsl:include href="source-highlight.xsl"/>
+ <xsl:include href="utility.xsl"/>
+ <xsl:include href="lookup.xsl"/>
+ <xsl:include href="library.xsl"/>
+ <xsl:include href="index.xsl"/>
+ <xsl:include href="error.xsl"/>
+ <xsl:include href="macro.xsl"/>
+ <xsl:include href="testing/testsuite.xsl"/>
+ <xsl:include href="caramel/concept2docbook.xsl"/>
+
+ <xsl:template name="namespace-synopsis">
+ <xsl:param name="indentation" select="0"/>
+ <!-- Open namespace-->
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="concat('namespace ',@name, ' {')"/>
+ </xsl:call-template>
+
+ <!-- Emit namespace types -->
+ <xsl:apply-templates select="class|class-specialization|
+ struct|struct-specialization|
+ union|union-specialization|
+ typedef|enum|data-member" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:apply-templates>
+
+ <!-- Emit namespace functions -->
+ <xsl:apply-templates
+ select="free-function-group|function|overloaded-function"
+ mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:apply-templates>
+
+ <!-- Emit namespaces -->
+ <xsl:apply-templates select="namespace" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:apply-templates>
+
+ <!-- Close namespace -->
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'}'"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- Emit namespace synopsis -->
+ <xsl:template match="namespace" mode="synopsis">
+ <xsl:param name="indentation" select="0"/>
+
+ <xsl:choose>
+ <xsl:when test="count(ancestor::namespace)=0">
+ <xsl:call-template name="namespace-synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="namespace-synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Emit namespace reference -->
+ <xsl:template match="namespace" mode="reference">
+ <xsl:apply-templates select="namespace|free-function-group"
+ mode="reference">
+ <xsl:with-param name="indentation" select="0"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="class|class-specialization|
+ struct|struct-specialization|
+ union|union-specialization|enum|function|
+ overloaded-function|data-member|typedef"
+ mode="namespace-reference"/>
+ </xsl:template>
+
+ <!-- Eat extra documentation when in the synopsis or reference sections -->
+ <xsl:template match="para|section" mode="synopsis"/>
+ <xsl:template match="para|section" mode="reference"/>
+
+ <xsl:template name="find-wrap-point">
+ <xsl:param name="text"/>
+ <xsl:param name="prefix"/>
+ <xsl:param name="result" select="0"/>
+ <xsl:param name="default" select="$max-columns - string-length($prefix)"/>
+ <xsl:variable name="s" select="substring($text, 2)"/>
+ <xsl:variable name="candidate">
+ <xsl:choose>
+ <xsl:when test="contains($s, ' ')">
+ <xsl:value-of select="string-length(substring-before($s, ' ')) + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string-length($text)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($prefix) + $result + $candidate &lt;= $max-columns">
+ <xsl:call-template name="find-wrap-point">
+ <xsl:with-param name="text" select="substring($text, $candidate + 1)"/>
+ <xsl:with-param name="prefix" select="$prefix"/>
+ <xsl:with-param name="result" select="$result + $candidate"/>
+ <xsl:with-param name="default" select="$result + $candidate"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$default"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="wrap-comment">
+ <xsl:param name="prefix"/>
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="string-length($prefix) + string-length($text) &lt;= $max-columns">
+ <xsl:value-of select="$text"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="size">
+ <xsl:call-template name="find-wrap-point">
+ <xsl:with-param name="prefix" select="$prefix"/>
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="substring($text, 1, $size)"/>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:value-of select="$prefix"/>
+ <xsl:call-template name="wrap-comment">
+ <xsl:with-param name="prefix" select="$prefix"/>
+ <xsl:with-param name="text" select="normalize-space(substring($text, $size + 1))"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Comment mode tries to wipe out any extra spacing in the output -->
+ <xsl:template match="purpose" mode="comment">
+ <xsl:param name="wrap" select="false()"/>
+ <xsl:param name="prefix"/>
+ <xsl:apply-templates mode="comment">
+ <xsl:with-param name="wrap"
+ select="$wrap and count(text()|*) = 1"/>
+ <xsl:with-param name="prefix" select="$prefix"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="simpara|para" mode="comment">
+ <xsl:param name="wrap" select="false()"/>
+ <xsl:param name="prefix"/>
+ <xsl:apply-templates select="text()|*" mode="comment">
+ <xsl:with-param name="wrap"
+ select="$wrap and count(text()|*) = 1"/>
+ <xsl:with-param name="prefix" select="$prefix"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="text()" mode="comment">
+ <xsl:param name="wrap" select="false()"/>
+ <xsl:param name="prefix"/>
+ <xsl:variable name="stripped" select="normalize-space(.)"/>
+ <xsl:choose>
+ <xsl:when test="$wrap">
+ <xsl:call-template name="wrap-comment">
+ <xsl:with-param name="prefix" select="$prefix"/>
+ <xsl:with-param name="text" select="$stripped"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="*" mode="comment">
+ <xsl:apply-templates select="." mode="annotation"/>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/relative-href.xsl b/tools/boostbook/xsl/relative-href.xsl
new file mode 100644
index 0000000000..8218d2f4c5
--- /dev/null
+++ b/tools/boostbook/xsl/relative-href.xsl
@@ -0,0 +1,98 @@
+<?xml version="1.0"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/lib/lib.xsl"/>
+
+<!-- ==================================================================== -->
+
+<!-- Check if path is absolute
+
+ Not attempting to fully parse or validate absolute vs. relative URI.
+ Assumes an absolute url when $target matches the regex '^[a-zA-Z.+-]*:'
+
+ According to RFC1808, however, the colon (':') may also appear in a relative
+ URL. To workaround this limitation for relative links containing colons one
+ may use the alternatives below, instead.
+
+ For the relative URI this:that use ./this:that or this%3Athat, instead.
+-->
+<xsl:template name="is.absolute.uri">
+ <xsl:param name="uri"/>
+
+ <xsl:variable name="scheme1" select="substring-before($uri, ':')"/>
+ <xsl:variable name="scheme2" select="translate($scheme1, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-.', '')"/>
+
+ <xsl:choose>
+ <xsl:when test="$scheme1 and not($scheme2)">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="href.target.relative">
+ <xsl:param name="target"/>
+ <xsl:param name="context" select="."/>
+
+ <xsl:variable name="isabsoluteuri">
+ <xsl:call-template name="is.absolute.uri">
+ <xsl:with-param name="uri" select="$target"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="$isabsoluteuri='1'">
+ <xsl:value-of select="$target"/>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:variable name="href.to.uri" select="$target"/>
+ <xsl:variable name="href.from.uri">
+ <xsl:call-template name="href.target.uri">
+ <xsl:with-param name="object" select="$context"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="href.to">
+ <xsl:call-template name="trim.common.uri.paths">
+ <xsl:with-param name="uriA" select="$href.to.uri"/>
+ <xsl:with-param name="uriB" select="$href.from.uri"/>
+ <xsl:with-param name="return" select="'A'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="href.from">
+ <xsl:call-template name="trim.common.uri.paths">
+ <xsl:with-param name="uriA" select="$href.to.uri"/>
+ <xsl:with-param name="uriB" select="$href.from.uri"/>
+ <xsl:with-param name="return" select="'B'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="depth">
+ <xsl:call-template name="count.uri.path.depth">
+ <xsl:with-param name="filename" select="$href.from"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="href">
+ <xsl:call-template name="copy-string">
+ <xsl:with-param name="string" select="'../'"/>
+ <xsl:with-param name="count" select="$depth"/>
+ </xsl:call-template>
+ <xsl:value-of select="$href.to"/>
+ </xsl:variable>
+
+ <xsl:value-of select="$href"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/source-highlight.xsl b/tools/boostbook/xsl/source-highlight.xsl
new file mode 100644
index 0000000000..b3903e5ba6
--- /dev/null
+++ b/tools/boostbook/xsl/source-highlight.xsl
@@ -0,0 +1,484 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:param name="boost.syntax.highlight">1</xsl:param>
+
+ <xsl:template name="source-highlight">
+ <xsl:param name="text" select="."/>
+ <xsl:choose>
+ <xsl:when test="$boost.syntax.highlight='1'">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:variable name="id-start-chars" select="'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_'"/>
+ <xsl:variable name="id-chars" select="'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_'"/>
+ <xsl:variable name="digits" select="'1234567890'"/>
+ <xsl:variable name="number-chars" select="'1234567890abcdefABCDEFxX.'"/>
+ <xsl:variable name="keywords"
+ select="' asm auto bool break case catch char class const const_cast continue default delete do double dynamic_cast else enum explicit export extern false float for friend goto if inline int long mutable namespace new operator private protected public register reinterpret_cast return short signed sizeof static static_cast struct switch template this throw true try typedef typeid typename union unsigned using virtual void volatile wchar_t while '"/>
+ <xsl:variable name="operators4" select="'%:%:'"/>
+ <xsl:variable name="operators3" select="'&gt;&gt;= &lt;&lt;= -&gt;* ...'"/>
+ <xsl:variable name="operators2" select="'.* :: ## &lt;: :&gt; &lt;% %&gt; %: += -= *= /= %= ^= &amp;= |= &lt;&lt; &gt;&gt; == != &lt;= &gt;= &amp;&amp; || ++ -- -&gt;'"/>
+ <xsl:variable name="operators1" select="'. ? { } [ ] # ( ) ; : + - * / % ^ &amp; | ~ ! = &lt; &gt; ,'"/>
+ <xsl:variable name="single-quote">'</xsl:variable>
+
+ <!-- Syntax highlighting -->
+ <xsl:template name="highlight-keyword">
+ <xsl:param name="keyword"/>
+ <xsl:choose>
+ <xsl:when test="$boost.syntax.highlight='1'">
+ <phrase role="keyword">
+ <xsl:value-of select="$keyword"/>
+ </phrase>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$keyword"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-identifier">
+ <xsl:param name="identifier"/>
+ <xsl:choose>
+ <xsl:when test="contains($keywords, concat(' ', $identifier, ' '))">
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="$identifier"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$boost.syntax.highlight='1'">
+ <phrase role="identifier">
+ <xsl:value-of select="$identifier"/>
+ </phrase>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$identifier"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-comment">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="$boost.syntax.highlight='1'">
+ <phrase role="comment">
+ <xsl:copy-of select="$text"/>
+ </phrase>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-special">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="$boost.syntax.highlight='1'">
+ <phrase role="special">
+ <xsl:value-of select="$text"/>
+ </phrase>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-number">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="$boost.syntax.highlight='1'">
+ <phrase role="number">
+ <xsl:value-of select="$text"/>
+ </phrase>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-string">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="$boost.syntax.highlight='1'">
+ <phrase role="string">
+ <xsl:value-of select="$text"/>
+ </phrase>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-char">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="$boost.syntax.highlight='1'">
+ <phrase role="char">
+ <xsl:value-of select="$text"/>
+ </phrase>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-pp-directive">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="$boost.syntax.highlight='1'">
+ <phrase role="preprocessor">
+ <xsl:value-of select="$text"/>
+ </phrase>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-text-ident-length">
+ <xsl:param name="text"/>
+ <xsl:param name="pos" select="1"/>
+ <xsl:choose>
+ <xsl:when test="string-length($text) + 1 = $pos">
+ <xsl:value-of select="$pos - 1"/>
+ </xsl:when>
+ <xsl:when test="contains($id-chars, substring($text, $pos, 1))">
+ <xsl:call-template name ="highlight-text-ident-length">
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="pos" select="$pos + 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$pos - 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-text-number-length">
+ <xsl:param name="text"/>
+ <xsl:param name="pos" select="1"/>
+ <xsl:choose>
+ <xsl:when test="string-length($text) + 1 = $pos">
+ <xsl:value-of select="$pos - 1"/>
+ </xsl:when>
+ <xsl:when test="contains($number-chars, substring($text, $pos, 1))">
+ <xsl:call-template name ="highlight-text-ident-length">
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="pos" select="$pos + 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$pos - 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-text-string-length">
+ <xsl:param name="text"/>
+ <xsl:param name="terminator"/>
+ <xsl:param name="pos" select="2"/>
+ <xsl:choose>
+ <xsl:when test="string-length($text) + 1 = $pos">
+ <xsl:value-of select="$pos - 1"/>
+ </xsl:when>
+ <xsl:when test="substring($text, $pos, 1) = $terminator">
+ <xsl:value-of select="$pos"/>
+ </xsl:when>
+ <xsl:when test="substring($text, $pos, 1) = '\' and
+ string-length($text) != $pos">
+ <xsl:call-template name="highlight-text-string-length">
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="terminator" select="$terminator"/>
+ <xsl:with-param name="pos" select="$pos + 2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="highlight-text-string-length">
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="terminator" select="$terminator"/>
+ <xsl:with-param name="pos" select="$pos + 1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-text-operator-length">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="string-length($text) &gt;= 4 and
+ not(contains(substring($text, 1, 4), ' ')) and
+ contains($operators4, substring($text, 1, 4))">
+ <xsl:value-of select="4"/>
+ </xsl:when>
+ <xsl:when test="string-length($text) &gt;= 3 and
+ not(contains(substring($text, 1, 3), ' ')) and
+ contains($operators3, substring($text, 1, 3))">
+ <xsl:value-of select="3"/>
+ </xsl:when>
+ <xsl:when test="string-length($text) &gt;= 2 and
+ not(contains(substring($text, 1, 2), ' ')) and
+ contains($operators2, substring($text, 1, 2))">
+ <xsl:value-of select="2"/>
+ </xsl:when>
+ <xsl:when test="string-length($text) &gt;= 1 and
+ not(contains(substring($text, 1, 1), ' ')) and
+ contains($operators1, substring($text, 1, 1))">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="0"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-text-pp-directive-length">
+ <xsl:param name="text"/>
+ <!-- Assume that the first character is a # -->
+ <xsl:param name="pos" select="2"/>
+ <xsl:choose>
+ <xsl:when test="contains($id-chars, substring($text, $pos, 1))">
+ <xsl:call-template name="highlight-text-ident-length">
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="pos" select="$pos + 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains(' &#x9;', substring($text, $pos, 1))">
+ <xsl:call-template name="highlight-text-pp-directive-length">
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="pos" select="$pos + 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$pos - 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-text-impl-leading-whitespace">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="string-length($text) = 0"/>
+ <xsl:when test="contains(' &#xA;&#xD;&#x9;', substring($text, 1, 1))">
+ <xsl:value-of select="substring($text, 1, 1)"/>
+ <xsl:call-template name="highlight-text-impl-leading-whitespace">
+ <xsl:with-param name="text" select="substring($text, 2)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="'#' = substring($text, 1, 1)">
+ <xsl:variable name="pp-length">
+ <xsl:call-template name="highlight-text-pp-directive-length">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="highlight-pp-directive">
+ <xsl:with-param name="text" select="substring($text, 1, $pp-length)"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text-impl-root">
+ <xsl:with-param name="text" select="substring($text, $pp-length + 1)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="highlight-text-impl-root">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-text-impl-root">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="string-length($text) = 0"/>
+ <xsl:when test="contains($id-start-chars, substring($text, 1, 1))">
+ <xsl:variable name="ident-length">
+ <xsl:call-template name="highlight-text-ident-length">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="highlight-identifier">
+ <xsl:with-param name="identifier" select="substring($text, 1, $ident-length)"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text-impl-root">
+ <xsl:with-param name="text" select="substring($text, $ident-length + 1)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains($digits, substring($text, 1, 1))">
+ <xsl:variable name="number-length">
+ <xsl:call-template name="highlight-text-number-length">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="highlight-number">
+ <xsl:with-param name="text" select="substring($text, 1, $number-length)"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text-impl-root">
+ <xsl:with-param name="text" select="substring($text, $number-length + 1)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="substring($text, 1, 1) = '&#x22;'">
+ <xsl:variable name="string-length">
+ <xsl:call-template name="highlight-text-string-length">
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="terminator" select="'&#x22;'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="highlight-string">
+ <xsl:with-param name="text" select="substring($text, 1, $string-length)"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text-impl-root">
+ <xsl:with-param name="text" select="substring($text, $string-length + 1)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="substring($text, 1, 1) = $single-quote">
+ <xsl:variable name="char-length">
+ <xsl:call-template name="highlight-text-string-length">
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="terminator" select="$single-quote"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="highlight-char">
+ <xsl:with-param name="text" select="substring($text, 1, $char-length)"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text-impl-root">
+ <xsl:with-param name="text" select="substring($text, $char-length + 1)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="substring($text, 1, 2) = '//'">
+ <xsl:choose>
+ <xsl:when test="contains($text, '&#xA;')">
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text" select="substring-before($text, '&#xA;')"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text-impl-root">
+ <xsl:with-param name="text" select="concat('&#xA;', substring-after($text, '&#xA;'))"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="substring($text, 1, 2) = '/*'">
+ <xsl:variable name="after-start" select="substring($text, 3)" />
+ <xsl:choose>
+ <xsl:when test="contains($after-start, '*/')">
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text" select="concat('/*', substring-before($after-start, '*/'), '*/')"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text-impl-root">
+ <xsl:with-param name="text" select="substring-after($after-start, '*/')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="contains('&#xA;&#xD;', substring($text, 1, 1))">
+ <xsl:value-of select="substring($text, 1, 1)"/>
+ <xsl:call-template name="highlight-text-impl-leading-whitespace">
+ <xsl:with-param name="text" select="substring($text, 2)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains(' &#x9;', substring($text, 1, 1))">
+ <xsl:value-of select="substring($text, 1, 1)"/>
+ <xsl:call-template name="highlight-text-impl-root">
+ <xsl:with-param name="text" select="substring($text, 2)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="operator-length">
+ <xsl:call-template name="highlight-text-operator-length">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$operator-length = 0">
+ <xsl:value-of select="substring($text, 1, 1)"/>
+ <xsl:call-template name="highlight-text-impl-root">
+ <xsl:with-param name="text" select="substring($text, 2)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="substring($text, 1, $operator-length)"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text-impl-root">
+ <xsl:with-param name="text" select="substring($text, $operator-length + 1)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Perform C++ syntax highlighting on the given text -->
+ <xsl:template name="highlight-text">
+ <xsl:param name="text" select="."/>
+ <xsl:call-template name="highlight-text-impl-leading-whitespace">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="*" mode="highlight">
+ <xsl:element name="{name(.)}">
+ <xsl:for-each select="./@*">
+ <xsl:choose>
+ <xsl:when test="local-name(.)='last-revision'">
+ <xsl:attribute
+ name="rev:last-revision"
+ namespace="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision"
+>
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{name(.)}">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ <xsl:apply-templates mode="highlight"/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="text()" mode="highlight">
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="."/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="classname|methodname|functionname|libraryname|enumname|
+ conceptname|macroname|globalname" mode="highlight">
+ <xsl:apply-templates select="." mode="annotation"/>
+ </xsl:template>
+
+ <xsl:template match="type" mode="highlight">
+ <xsl:apply-templates mode="highlight"/>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/template.xsl b/tools/boostbook/xsl/template.xsl
new file mode 100644
index 0000000000..2e7d609931
--- /dev/null
+++ b/tools/boostbook/xsl/template.xsl
@@ -0,0 +1,601 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+ <xsl:param name="template.param.brief" select="false()"/>
+
+ <!-- Determine the length of a template header synopsis -->
+ <xsl:template name="template.synopsis.length">
+ <xsl:variable name="text">
+ <xsl:apply-templates select="template" mode="synopsis">
+ <xsl:with-param name="indentation" select="0"/>
+ <xsl:with-param name="wrap" select="false()"/>
+ <xsl:with-param name="highlight" select="false()"/>
+ </xsl:apply-templates>
+ </xsl:variable>
+ <xsl:value-of select="string-length($text)"/>
+ </xsl:template>
+
+ <!-- Determine the length of a template header reference -->
+ <xsl:template name="template.reference.length">
+ <xsl:choose>
+ <xsl:when test="not(template)">
+ 0
+ </xsl:when>
+ <xsl:when test="template/*/purpose">
+ <!-- TBD: The resulting value need only be greater than the number of
+ columns. We chose to add 17 because it's funny for C++
+ programmers. :) -->
+ <xsl:value-of select="$max-columns + 17"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="template.synopsis.length"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Output a template header in synopsis mode -->
+ <xsl:template match="template" mode="synopsis">
+ <xsl:param name="indentation" select="0"/>
+ <xsl:param name="wrap" select="true()"/>
+ <xsl:param name="highlight" select="true()"/>
+
+ <xsl:call-template name="template.synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="wrap" select="$wrap"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- Output a template header in reference mode -->
+ <xsl:template match="template" mode="reference">
+ <xsl:param name="indentation" select="0"/>
+ <xsl:param name="highlight" select="true()"/>
+ <xsl:call-template name="template.reference">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- Emit a template header synopsis -->
+ <xsl:template name="template.synopsis">
+ <xsl:param name="indentation" select="0"/>
+ <xsl:param name="wrap" select="true()"/>
+ <xsl:param name="highlight" select="true()"/>
+
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="'template'"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="'&lt;'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>template</xsl:text>
+ <xsl:text>&lt;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="template.synopsis.parameters">
+ <xsl:with-param name="indentation" select="$indentation + 9"/>
+ <xsl:with-param name="wrap" select="$wrap"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="'&gt;'"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&gt; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Display a list of template parameters for a synopsis (no comments) -->
+ <xsl:template name="template.synopsis.parameters">
+ <xsl:param name="indentation"/>
+ <xsl:param name="wrap" select="true()"/>
+ <xsl:param name="highlight" select="true()"/>
+
+ <xsl:param name="column" select="$indentation"/>
+ <xsl:param name="prefix" select="''"/>
+ <xsl:param name="parameters" select="template-type-parameter|template-varargs|template-nontype-parameter"/>
+ <xsl:param name="first-on-line" select="true()"/>
+
+ <xsl:if test="$parameters">
+ <!-- Emit the prefix (either a comma-space, or empty if this is
+ the first parameter) -->
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="$prefix"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$prefix"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <!-- Get the actual parameter and its attributes -->
+ <xsl:variable name="parameter" select="$parameters[position()=1]"/>
+ <xsl:variable name="rest" select="$parameters[position()!=1]"/>
+
+ <!-- Compute the actual text of this parameter -->
+ <xsl:variable name="text">
+ <xsl:call-template name="template.parameter">
+ <xsl:with-param name="parameter" select="$parameter"/>
+ <xsl:with-param name="is-last" select="not(rest)"/>
+ <xsl:with-param name="highlight" select="false()"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <!-- Where will this template parameter finish? -->
+ <xsl:variable name="end-column"
+ select="$column + string-length($prefix) + string-length($text)"/>
+
+ <!-- Should the text go on this line or on the next? -->
+ <xsl:choose>
+ <xsl:when test="$first-on-line or ($end-column &lt; $max-columns) or
+ not($wrap)">
+ <!-- Print on this line -->
+ <xsl:call-template name="template.parameter">
+ <xsl:with-param name="parameter" select="$parameter"/>
+ <xsl:with-param name="is-last" select="not($rest)"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+
+ <!-- Recurse -->
+ <xsl:call-template name="template.synopsis.parameters">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="wrap" select="$wrap"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ <xsl:with-param name="column" select="$end-column"/>
+ <xsl:with-param name="prefix" select="', '"/>
+ <xsl:with-param name="parameters" select="$rest"/>
+ <xsl:with-param name="first-on-line" select="false()"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Print on next line -->
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="template.parameter">
+ <xsl:with-param name="parameter" select="$parameter"/>
+ <xsl:with-param name="is-last" select="not($rest)"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="template.synopsis.parameters">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="wrap" select="$wrap"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ <xsl:with-param name="column"
+ select="$indentation + string-length($text)"/>
+ <xsl:with-param name="prefix" select="', '"/>
+ <xsl:with-param name="parameters" select="$rest"/>
+ <xsl:with-param name="first-on-line" select="false()"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Emit a template header reference -->
+ <xsl:template name="template.reference">
+ <xsl:param name="indentation" select="0"/>
+ <xsl:param name="highlight" select="true()"/>
+
+ <xsl:if test="template-type-parameter|template-varargs|template-nontype-parameter">
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="'template'"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="'&lt;'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>template</xsl:text>
+ <xsl:text>&lt;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="template.reference.parameters">
+ <xsl:with-param name="indentation" select="$indentation + 9"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="'&gt;'"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&gt; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Display a set of template parameters for a reference -->
+ <xsl:template name="template.reference.parameters">
+ <xsl:param name="indentation"/>
+ <xsl:param name="highlight" select="true()"/>
+ <xsl:param name="parameters" select="template-type-parameter|template-varargs|template-nontype-parameter"/>
+
+ <xsl:choose>
+ <xsl:when test="$parameters/purpose and $template.param.brief">
+ <xsl:call-template name="template.reference.parameters.comments">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="template.synopsis.parameters">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="wrap" select="true()"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Output template parameters when there are comments with the parameters.
+ For clarity, we output each template parameter on a separate line. -->
+ <xsl:template name="template.reference.parameters.comments">
+ <xsl:param name="indentation"/>
+ <xsl:param name="highlight" select="true()"/>
+ <xsl:param name="parameters" select="template-type-parameter|template-varargs|template-nontype-parameter"/>
+
+ <xsl:if test="$parameters">
+ <!-- Get the actual parameter and its attributes -->
+ <xsl:variable name="parameter" select="$parameters[position()=1]"/>
+ <xsl:variable name="rest" select="$parameters[position()!=1]"/>
+
+ <!-- Display the parameter -->
+ <xsl:call-template name="template.parameter">
+ <xsl:with-param name="parameter" select="$parameter"/>
+ <xsl:with-param name="is-last" select="not($rest)"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+
+ <xsl:if test="$rest">
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="', '"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>, </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+
+ <!-- Display the comment -->
+ <xsl:if test="$parameter/purpose">
+ <xsl:variable name="param-text">
+ <!-- Display the parameter -->
+ <xsl:call-template name="template.parameter">
+ <xsl:with-param name="parameter" select="$parameter"/>
+ <xsl:with-param name="is-last" select="not($rest)"/>
+ <xsl:with-param name="highlight" select="false()"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text> // </xsl:text>
+ <xsl:apply-templates
+ select="$parameter/purpose/*|$parameter/purpose/text()" mode="comment">
+ <xsl:with-param name="wrap" select="true()"/>
+ <xsl:with-param name="prefix">
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation + string-length($param-text)"/>
+ </xsl:call-template>
+ <xsl:if test="$rest">
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ <xsl:text> // </xsl:text>
+ </xsl:with-param>
+ </xsl:apply-templates>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+
+ <!-- Indent the next line -->
+ <xsl:if test="$parameter/purpose or $rest">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:if>
+
+ <!-- Recurse to print the rest of the parameters -->
+ <xsl:call-template name="template.reference.parameters.comments">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ <xsl:with-param name="parameters" select="$rest"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Print a template parameter -->
+ <xsl:template name="template.parameter">
+ <xsl:param name="parameter"/>
+ <xsl:param name="is-last"/>
+ <xsl:param name="highlight" select="true()"/>
+ <xsl:apply-templates select="$parameter"
+ mode="print.parameter">
+ <xsl:with-param name="parameter" select="$parameter"/>
+ <xsl:with-param name="is-last" select="$is-last"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template name="template.parameter.name">
+ <xsl:param name="name" select="@name"/>
+ <xsl:param name="highlight" select="true()"/>
+
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="concept.link">
+ <xsl:with-param name="name"
+ select="translate($name, '0123456789', '')"/>
+ <xsl:with-param name="text" select="$name"/>
+ <xsl:with-param name="warn" select="false"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="template-type-parameter" mode="print.parameter">
+ <xsl:param name="parameter"/>
+ <xsl:param name="is-last"/>
+ <xsl:param name="highlight"/>
+
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="'typename'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>typename</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="$parameter/@pack=1">
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'...'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>...</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:text> </xsl:text>
+
+ <xsl:call-template name="template.parameter.name">
+ <xsl:with-param name="name" select="$parameter/@name"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+
+ <xsl:variable name="def">
+ <xsl:choose>
+ <xsl:when test="$parameter/@default">
+ <xsl:message>
+ <xsl:text>Warning: 'default' attribute of template parameter element is deprecated. Use 'default' element.</xsl:text>
+ <xsl:call-template name="print.warning.context"/>
+ </xsl:message>
+ <xsl:choose>
+ <xsl:when test="$highlight and false()">
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text">
+ <xsl:value-of select="$parameter/@default"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$parameter/@default"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$parameter/default">
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:apply-templates
+ select="$parameter/default/*|$parameter/default/text()"
+ mode="highlight"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string($parameter/default)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:if test="not($def='')">
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="' = '"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text> = </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:copy-of select="$def"/>
+
+ <!-- If this is the last parameter, add an extra space to
+ avoid printing >> -->
+ <xsl:if
+ test="$is-last and (substring($def, string-length($def))='&gt;')">
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="template-nontype-parameter" mode="print.parameter">
+ <xsl:param name="parameter"/>
+ <xsl:param name="is-last"/>
+ <xsl:param name="highlight"/>
+
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text">
+ <xsl:apply-templates
+ select="$parameter/type/*|$parameter/type/text()"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$parameter/type/*|$parameter/type/text()"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="$parameter/@pack=1">
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'...'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>...</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:text> </xsl:text>
+
+ <xsl:call-template name="template.parameter.name">
+ <xsl:with-param name="name" select="$parameter/@name"/>
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:call-template>
+
+ <xsl:variable name="def">
+ <xsl:value-of select="string($parameter/default)"/>
+ </xsl:variable>
+
+ <xsl:if test="not($def='')">
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="' = '"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text> = </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:apply-templates select="$parameter/default/*|$parameter/default/text()" mode="highlight"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$def"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <!-- If this is the last parameter, add an extra space to
+ avoid printing >> -->
+ <xsl:if
+ test="$is-last and (substring($def, string-length($def))='&gt;')">
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="template-varargs" mode="print.parameter">
+ <xsl:param name="highlight" select="true()"/>
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'...'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>...</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="specialization">
+ <xsl:param name="highlight" select="true()"/>
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'&lt;'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&lt;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:apply-templates select="template-arg">
+ <xsl:with-param name="highlight" select="$highlight"/>
+ </xsl:apply-templates>
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'&gt;'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&gt;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="template-arg">
+ <xsl:param name="highlight" select="true()"/>
+ <xsl:if test="position() &gt; 1">
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="', '"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>, </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:apply-templates mode="highlight"/>
+ <xsl:if test="@pack=1">
+ <xsl:choose>
+ <xsl:when test="$highlight">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'...'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>...</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+</xsl:stylesheet>
+
diff --git a/tools/boostbook/xsl/testing/Jamfile.xsl b/tools/boostbook/xsl/testing/Jamfile.xsl
new file mode 100644
index 0000000000..f8648e42f9
--- /dev/null
+++ b/tools/boostbook/xsl/testing/Jamfile.xsl
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:include href="http://docbook.sourceforge.net/release/xsl/current/html/chunker.xsl"/>
+ <xsl:include href="http://docbook.sourceforge.net/release/xsl/current/common/common.xsl"/>
+
+ <!-- The root of the Boost directory -->
+ <xsl:param name="boost.root"/>
+
+ <!-- The number of columns in a source file line -->
+ <xsl:param name="boost.source.columns" select="78"/>
+
+ <xsl:output method="text"/>
+ <xsl:template match="/">
+ <xsl:if test="$boost.root">
+ <!-- Output testsuite Jamfiles -->
+ <xsl:apply-templates select="//testsuite" mode="Jamfile"/>
+
+ <!-- Output any source files that are written in XML -->
+ <xsl:apply-templates select="//source" mode="testsuite.generate"/>
+ </xsl:if>
+
+ <xsl:if test="not($boost.root)">
+ <xsl:message>
+ Please set the XSL stylesheet parameter "boost.root" to the top-level
+ Boost directory (i.e., BOOST_ROOT)
+ </xsl:message>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="testsuite" mode="Jamfile">
+ <xsl:variable name="subproject"
+ select="concat('libs/',ancestor::library/attribute::dirname,'/test')"/>
+ <xsl:variable name="filename"
+ select="concat($boost.root,'/libs/',ancestor::library/attribute::dirname,
+ '/test/Jamfile')"/>
+ <xsl:call-template name="write.text.chunk">
+ <xsl:with-param name="filename" select="$filename"/>
+ <xsl:with-param name="content">
+ <xsl:call-template name="source.print.header">
+ <xsl:with-param name="prefix" select="'#'"/>
+ </xsl:call-template>
+
+# Testing Jamfile autogenerated from XML source
+subproject <xsl:value-of select="$subproject"/> ;
+
+# bring in rules for testing
+SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
+include testing.jam ;
+
+# Make tests run by default.
+DEPENDS all : test ;
+
+{
+ # look in BOOST_ROOT for sources first, just in this Jamfile
+ local SEARCH_SOURCE = $(BOOST_ROOT) $(SEARCH_SOURCE) ;
+
+ test-suite <xsl:value-of select="ancestor::library/attribute::dirname"/>
+ : <xsl:apply-templates mode="Jamfile"/> ;
+}
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="compile-test|link-test|run-test|compile-fail-test|link-fail-test|run-fail-test"
+ mode="Jamfile">
+ <xsl:variable name="fullname"
+ select="concat(substring-before(local-name(.), '-test'), ' libs/',
+ ancestor::library/attribute::dirname, '/test/',
+ @filename)"/>
+ <xsl:text>[ </xsl:text>
+ <xsl:value-of select="$fullname"/>
+ <xsl:apply-templates select="lib" mode="Jamfile"/>
+ <xsl:text> : </xsl:text>
+ <!-- ... -->
+ <xsl:text> : </xsl:text>
+ <!-- ... -->
+ <xsl:text> : </xsl:text>
+ <xsl:apply-templates select="requirement" mode="Jamfile"/>
+ <!-- ... -->
+ <xsl:text> : </xsl:text>
+ <xsl:if test="@name">
+ <xsl:value-of select="@name"/>
+ </xsl:if>
+ <xsl:text> ]</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="lib" mode="Jamfile">
+ <xsl:text> &lt;lib&gt;</xsl:text><xsl:value-of select="text()"/>
+ </xsl:template>
+
+ <xsl:template match="requirement" mode="Jamfile">
+ <xsl:if test="count(preceding-sibling::requirement) &gt; 0">
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ <xsl:value-of select="concat('&lt;', @name, '&gt;')"/>
+ <xsl:value-of select="."/>
+ </xsl:template>
+
+ <xsl:template match="source" mode="testsuite.generate">
+ <xsl:variable name="filename"
+ select="concat($boost.root,'/libs/',ancestor::library/attribute::dirname,
+ '/test/',../@filename)"/>
+
+ <xsl:variable name="prefix" select="'//'"/>
+
+ <xsl:call-template name="write.text.chunk">
+ <xsl:with-param name="filename" select="$filename"/>
+ <xsl:with-param name="content">
+ <xsl:call-template name="source.print.header">
+ <xsl:with-param name="prefix" select="'//'"/>
+ </xsl:call-template>
+ <!-- Source code -->
+ <xsl:apply-templates mode="testsuite.generate"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="snippet" mode="testsuite.generate">
+ <xsl:variable name="snippet-name" select="@name"/>
+ <xsl:value-of select="//programlisting[@name=$snippet-name]"/>
+ </xsl:template>
+
+ <!-- Prints a header to a source file containing the library name,
+ copyright information, license information, and a link to the Boost
+ web site. The text is output using the "prefix" parameter at the
+ beginning of each line (it should denote a single-line comment) and
+ will only print up to boost.source.columns characters per line
+ (including the prefix). -->
+ <xsl:template name="source.print.header">
+ <xsl:param name="prefix"/>
+
+ <!-- Library name -->
+ <xsl:value-of select="concat($prefix, ' ',
+ ancestor::library/attribute::name,
+ ' library')"/>
+ <xsl:text>&#10;</xsl:text>
+
+ <!-- Copyrights -->
+ <xsl:apply-templates select="ancestor::library/libraryinfo/copyright"
+ mode="testsuite.generate">
+ <xsl:with-param name="prefix" select="$prefix"/>
+ </xsl:apply-templates>
+
+ <!-- Legal notice -->
+ <xsl:apply-templates select="ancestor::library/libraryinfo/legalnotice"
+ mode="testsuite.generate">
+ <xsl:with-param name="prefix" select="$prefix"/>
+ </xsl:apply-templates>
+
+ <xsl:text>&#10;&#10;</xsl:text>
+
+ <!-- For more information... -->
+ <xsl:value-of
+ select="concat($prefix,
+ ' For more information, see http://www.boost.org/')"/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="copyright" mode="testsuite.generate">
+ <xsl:param name="prefix"/>
+
+ <xsl:text>&#10;</xsl:text>
+
+ <xsl:value-of select="concat($prefix, ' Copyright (C) ')"/>
+ <xsl:call-template name="copyright.years">
+ <xsl:with-param name="years" select="year"/>
+ <xsl:with-param name="print.ranges" select="1"/>
+ <xsl:with-param name="single.year.ranges" select="1"/>
+ </xsl:call-template>
+
+ <xsl:text> </xsl:text>
+
+ <xsl:apply-templates select="holder" mode="titlepage.mode"/>
+ </xsl:template>
+
+ <xsl:template match="legalnotice" mode="testsuite.generate">
+ <xsl:param name="prefix"/>
+
+ <xsl:variable name="text" select="normalize-space(.)"/>
+
+ <xsl:text>&#10;&#10;</xsl:text>
+ <xsl:value-of select="concat($prefix, ' ')"/>
+
+ <xsl:call-template name="source.print.legalnotice">
+ <xsl:with-param name="prefix" select="$prefix"/>
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="column" select="string-length($prefix) + 1"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template name="source.print.legalnotice">
+ <xsl:param name="prefix"/>
+ <xsl:param name="text"/>
+ <xsl:param name="column"/>
+
+ <xsl:if test="contains($text, ' ') or string-length($text) &gt; 0">
+ <xsl:variable name="word">
+ <xsl:choose>
+ <xsl:when test="contains($text, ' ')">
+ <xsl:value-of select="substring-before($text, ' ')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="rest" select="substring-after($text, ' ')"/>
+
+ <xsl:choose>
+ <xsl:when
+ test="$column + string-length($word) &gt; $boost.source.columns">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:value-of select="concat($prefix, ' ')"/>
+ <xsl:call-template name="source.print.legalnotice">
+ <xsl:with-param name="prefix" select="$prefix"/>
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="column" select="string-length($prefix) + 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($word, ' ')"/>
+ <xsl:call-template name="source.print.legalnotice">
+ <xsl:with-param name="prefix" select="$prefix"/>
+ <xsl:with-param name="text" select="$rest"/>
+ <xsl:with-param name="column"
+ select="$column + string-length($word) + 1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="*" mode="testsuite.generate"/>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/testing/testsuite.xsl b/tools/boostbook/xsl/testing/testsuite.xsl
new file mode 100644
index 0000000000..b12eef6672
--- /dev/null
+++ b/tools/boostbook/xsl/testing/testsuite.xsl
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:template match="testsuite">
+ <section>
+ <xsl:choose>
+ <xsl:when test="@id">
+ <xsl:attribute name="id">
+ <xsl:value-of select="@id"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="../@id">
+ <xsl:attribute name="id">
+ <xsl:value-of select="concat(../@id, '.tests')"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+
+ <title>Testsuite</title>
+
+ <xsl:if test="compile-test|link-test|run-test">
+ <section>
+ <xsl:if test="@id">
+ <xsl:attribute name="id">
+ <xsl:value-of select="@id"/>
+ <xsl:text>.acceptance</xsl:text>
+ </xsl:attribute>
+ </xsl:if>
+
+ <title>Acceptance tests</title>
+ <informaltable>
+ <tgroup cols="3">
+ <colspec colnum="2" colwidth="1in"/>
+ <thead>
+ <row>
+ <entry>Test</entry>
+ <entry>Type</entry>
+ <entry>Description</entry>
+ <entry>If failing...</entry>
+ </row>
+ </thead>
+ <tbody>
+ <xsl:apply-templates select="compile-test|link-test|run-test"/>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </section>
+ </xsl:if>
+
+ <xsl:if test="compile-fail-test|link-fail-test|run-fail-test">
+ <section>
+ <xsl:if test="@id">
+ <xsl:attribute name="id">
+ <xsl:value-of select="@id"/>
+ <xsl:text>.negative</xsl:text>
+ </xsl:attribute>
+ </xsl:if>
+ <title>Negative tests</title>
+ <informaltable>
+ <tgroup cols="3">
+ <colspec colnum="2" colwidth="1in"/>
+ <thead>
+ <row>
+ <entry>Test</entry>
+ <entry>Type</entry>
+ <entry>Description</entry>
+ <entry>If failing...</entry>
+ </row>
+ </thead>
+ <tbody>
+ <xsl:apply-templates
+ select="compile-fail-test|link-fail-test|run-fail-test"/>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </section>
+ </xsl:if>
+ </section>
+ </xsl:template>
+
+ <xsl:template match="compile-test|link-test|run-test|
+ compile-fail-test|link-fail-test|run-fail-test">
+ <row>
+ <entry>
+ <simpara>
+ <ulink>
+ <xsl:attribute name="url">
+ <xsl:value-of
+ select="concat('../../libs/',
+ ancestor::library/attribute::dirname, '/test/',
+ @filename)"/>
+ </xsl:attribute>
+ <xsl:value-of select="@filename"/>
+ </ulink>
+ </simpara>
+ </entry>
+ <entry>
+ <simpara>
+ <xsl:value-of select="substring-before(local-name(.), '-test')"/>
+ </simpara>
+ </entry>
+ <entry><xsl:apply-templates select="purpose/*"/></entry>
+ <entry><xsl:apply-templates select="if-fails/*"/></entry>
+ </row>
+ </xsl:template>
+
+ <xsl:template match="snippet">
+ <xsl:variable name="snippet-name" select="@name"/>
+ <xsl:apply-templates select="//programlisting[@name=$snippet-name]"/>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/type.xsl b/tools/boostbook/xsl/type.xsl
new file mode 100644
index 0000000000..affb6aaff6
--- /dev/null
+++ b/tools/boostbook/xsl/type.xsl
@@ -0,0 +1,1693 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+ Copyright (c) 2007 Frank Mori Hess <fmhess@users.sourceforge.net>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+ <xsl:include href="global.xsl"/>
+ <xsl:strip-space elements="inherit purpose"/>
+
+ <!-- When true, the stylesheet will emit compact definitions of
+ enumerations when the enumeration does not have any detailed
+ description. A compact definition renders the enum definition along
+ with a comment for the purpose of the enum (if it exists) directly
+ within the synopsis. A non-compact definition will create a
+ separate refentry element for the enum. -->
+ <xsl:param name="boost.compact.enum">1</xsl:param>
+
+ <!-- When true, the stylesheet will emit compact definitions of
+ typedefs when the typedef does not have any detailed
+ description. -->
+ <xsl:param name="boost.compact.typedef">1</xsl:param>
+
+ <xsl:template match="class|struct|union" mode="generate.id">
+ <xsl:call-template name="fully-qualified-id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="class-specialization|struct-specialization|union-specialization" mode="generate.id">
+ <xsl:call-template name="fully-qualified-id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="typedef" mode="generate.id">
+ <xsl:call-template name="fully-qualified-id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="enum" mode="generate.id">
+ <xsl:call-template name="fully-qualified-id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="enumvalue" mode="generate.id">
+ <xsl:call-template name="fully-qualified-id">
+ <xsl:with-param name="node" select="parent::enum"/>
+ </xsl:call-template>
+ <xsl:text>.</xsl:text>
+ <xsl:value-of select="@name"/>
+ </xsl:template>
+
+ <!-- Display the full name of the current node, e.g., "Class
+ template function". -->
+ <xsl:template name="type.display.name">
+ <xsl:choose>
+ <xsl:when test="contains(local-name(.), 'class')">
+ <xsl:text>Class </xsl:text>
+ </xsl:when>
+ <xsl:when test="contains(local-name(.), 'struct')">
+ <xsl:text>Struct </xsl:text>
+ </xsl:when>
+ <xsl:when test="contains(local-name(.), 'union')">
+ <xsl:text>Union </xsl:text>
+ </xsl:when>
+ <xsl:when test="local-name(.)='enum'">
+ <xsl:text>Type </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>
+Unknown type element "<xsl:value-of select="local-name(.)"/>" in type.display.name
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="template and count(template/*) &gt; 0">
+ <xsl:text>template </xsl:text>
+ </xsl:if>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text">
+ <xsl:value-of select="@name"/>
+ <xsl:apply-templates select="specialization"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- Determine the class key for the given node -->
+ <xsl:template name="type.class.key">
+ <xsl:param name="node" select="."/>
+ <xsl:choose>
+ <xsl:when test="contains(local-name($node), '-specialization')">
+ <xsl:value-of select="substring-before(local-name($node), '-')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="local-name($node)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Emit class synopsis -->
+ <xsl:template match="class|class-specialization|
+ struct|struct-specialization|
+ union|union-specialization" mode="synopsis">
+ <xsl:param name="indentation"/>
+
+ <!-- The keyword used to declare this class type, e.g., class,
+ struct, or union. -->
+ <xsl:variable name="class-key">
+ <xsl:call-template name="type.class.key"/>
+ </xsl:variable>
+
+ <!-- Spacing -->
+ <xsl:if test="not (local-name(preceding-sibling::*[position()=1])=local-name(.)) and (position() &gt; 1)">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+
+ <xsl:text>&#10;</xsl:text>
+
+ <!-- Calculate how long this declaration would be if we put it all
+ on one line -->
+ <xsl:variable name="full-decl-string">
+ <xsl:apply-templates select="template" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="wrap" select="false()"/>
+ </xsl:apply-templates>
+ <xsl:value-of select="$class-key"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:apply-templates select="specialization"/>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="';'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="(string-length($full-decl-string) +
+ string-length($indentation)) &lt; $max-columns">
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:apply-templates select="template" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:apply-templates>
+
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="$class-key"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <xsl:value-of select="@name"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:apply-templates select="specialization"/>
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="';'"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <!-- Template header -->
+ <xsl:if test="template">
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:apply-templates select="template" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:apply-templates>
+ <xsl:text>&#10;</xsl:text>
+
+ <!-- Indent class templates' names in the synopsis -->
+ <xsl:text> </xsl:text>
+ </xsl:if>
+
+ <!-- Class name -->
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="$class-key"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="string(@name)"/>
+ </xsl:call-template>
+ <xsl:apply-templates select="specialization"/>
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="';'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <!-- Free functions associated with the class -->
+ <xsl:apply-templates select="free-function-group" mode="header-synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="class" select="@name"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <!-- Emit a typedef synopsis -->
+ <xsl:template name="type.typedef.display.aligned">
+ <xsl:param name="compact"/>
+ <xsl:param name="indentation"/>
+ <xsl:param name="is-reference"/>
+ <xsl:param name="max-type-length"/>
+ <xsl:param name="max-name-length"/>
+
+ <!-- What type of link the typedef name should have. This shall
+ be one of 'anchor' (the typedef output will be the target of
+ links), 'link' (the typedef output will link to a definition), or
+ 'none' (the typedef output will not be either a link or a link
+ target) -->
+ <xsl:param name="link-type">
+ <xsl:choose>
+ <xsl:when test="$is-reference">
+ <xsl:text>anchor</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>link</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:param>
+
+ <!-- The id we should link to or anchor as -->
+ <xsl:param name="link-to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:param>
+
+ <!-- The id we should link to or anchor as -->
+ <xsl:param name="typedef-name">
+ <xsl:value-of select="@name"/>
+ </xsl:param>
+
+ <!-- Padding for the typedef types -->
+ <xsl:variable name="type-padding">
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$max-type-length"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <!-- Padding for the typedef names -->
+ <xsl:variable name="name-padding">
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$max-name-length"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text>&#10;</xsl:text>
+ <xsl:choose>
+ <!-- Create a vertical ellipsis -->
+ <xsl:when test="@name = '...'">
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation + 3"/>
+ </xsl:call-template>
+ <xsl:text>.&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation + 3"/>
+ </xsl:call-template>
+ <xsl:text>.&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation + 3"/>
+ </xsl:call-template>
+ <xsl:text>.</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="'typedef'"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+
+ <!-- Length of the type -->
+ <xsl:variable name="type-length">
+ <xsl:choose>
+ <xsl:when test="@type">
+ <xsl:message>
+ <xsl:text>Warning: `type' attribute of `typedef' element is deprecated. Use 'type' element instead.</xsl:text>
+ </xsl:message>
+ <xsl:call-template name="print.warning.context"/>
+ <xsl:value-of select="string-length(@type)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string-length(type)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Emit the type -->
+ <xsl:choose>
+ <xsl:when test="@type">
+ <xsl:value-of select="@type"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="type/*|type/text()"
+ mode="highlight"/>
+ <!--
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text">
+ <xsl:apply-templates select="type/*|type/text()"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ -->
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:choose>
+ <xsl:when test="$max-type-length &gt; 0">
+ <xsl:value-of select="substring($type-padding, 1,
+ $max-type-length - $type-length)"/>
+ <xsl:text> </xsl:text>
+ <xsl:variable name="truncated-typedef-name" select="substring(@name,
+ 1, $max-name-length)"/>
+ <xsl:call-template name="link-or-anchor">
+ <xsl:with-param name="to" select="$link-to"/>
+ <xsl:with-param name="text" select="$truncated-typedef-name"/>
+ <xsl:with-param name="link-type" select="$link-type"/>
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="substring(concat(';', $name-padding),
+ 1, $max-name-length - string-length($truncated-typedef-name))"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="link-or-anchor">
+ <xsl:with-param name="to" select="$link-to"/>
+ <xsl:with-param name="text" select="$typedef-name"/>
+ <xsl:with-param name="link-type" select="$link-type"/>
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="';'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="$compact and purpose">
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:apply-templates select="purpose" mode="comment"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="typedef" mode="synopsis">
+ <xsl:param name="indentation"/>
+ <xsl:param name="max-type-length" select="0"/>
+ <xsl:param name="max-name-length" select="0"/>
+ <xsl:param name="allow-anchor" select="true()"/>
+
+ <!-- True if we should compact this typedef -->
+ <xsl:variable name="compact"
+ select="not (para|description) and ($boost.compact.typedef='1')"/>
+
+ <xsl:choose>
+ <xsl:when test="$compact">
+ <!-- Spacing -->
+ <xsl:if test="not (local-name(preceding-sibling::*[position()=1])=local-name(.)) and (position() &gt; 1)">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+
+ <xsl:call-template name="type.typedef.display.aligned">
+ <xsl:with-param name="compact" select="$compact"/>
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="is-reference" select="$allow-anchor"/>
+ <xsl:with-param name="max-type-length" select="$max-type-length"/>
+ <xsl:with-param name="max-name-length" select="$max-name-length"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="type.typedef.display.aligned">
+ <xsl:with-param name="compact" select="$compact"/>
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="is-reference" select="false()"/>
+ <xsl:with-param name="max-type-length" select="$max-type-length"/>
+ <xsl:with-param name="max-name-length" select="$max-name-length"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Emit a typedef reference entry -->
+ <xsl:template match="typedef" mode="namespace-reference">
+ <!-- True if this typedef was compacted -->
+ <xsl:variable name="compact"
+ select="not (para|description) and ($boost.compact.typedef='1')"/>
+
+ <xsl:if test="not ($compact)">
+ <xsl:call-template name="reference-documentation">
+ <xsl:with-param name="refname" select="@name"/>
+ <xsl:with-param name="purpose" select="purpose/*|purpose/text()"/>
+ <xsl:with-param name="anchor">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ <xsl:with-param name="name">
+ <xsl:text>Type definition </xsl:text>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="synopsis">
+ <xsl:call-template name="header-link"/>
+ <xsl:call-template name="type.typedef.display.aligned">
+ <xsl:with-param name="compact" select="false()"/>
+ <xsl:with-param name="indentation" select="0"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ <xsl:with-param name="link-type" select="'none'"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <xsl:apply-templates select="description"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="typedef" mode="reference">
+ <!-- True if this typedef was compacted -->
+ <xsl:variable name="compact"
+ select="not (para|description) and ($boost.compact.typedef='1')"/>
+
+ <xsl:if test="not ($compact)">
+ <listitem>
+ <para>
+ <xsl:call-template name="type.typedef.display.aligned">
+ <xsl:with-param name="compact" select="false()"/>
+ <xsl:with-param name="indentation" select="0"/>
+ <xsl:with-param name="is-reference" select="true()"/>
+ <xsl:with-param name="link-type" select="'anchor'"/>
+ </xsl:call-template>
+ </para>
+ <xsl:apply-templates select="description"/>
+ </listitem>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Emit a list of static constants -->
+ <xsl:template match="static-constant" mode="synopsis">
+ <xsl:param name="indentation"/>
+ <xsl:text>&#10;</xsl:text>
+
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="'static const '"/>
+ </xsl:call-template>
+
+ <xsl:apply-templates select="type" mode="highlight"/>
+
+ <xsl:if test="not(@name = '')">
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:if>
+
+ <xsl:text> = </xsl:text>
+
+ <xsl:call-template name="source-highlight">
+ <xsl:with-param name="text">
+ <xsl:apply-templates select="default/*|default/text()"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="';'"/>
+ </xsl:call-template>
+
+ <xsl:if test="purpose">
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:apply-templates select="purpose" mode="comment"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Format base classes on a single line -->
+ <xsl:template name="print.base.classes.single">
+ <xsl:apply-templates select="inherit"/>
+ </xsl:template>
+
+ <xsl:template name="print.base.classes.multi">
+ <xsl:param name="indentation"/>
+
+ <xsl:variable name="n" select="count(inherit)"/>
+ <xsl:for-each select="inherit">
+ <!-- Indentation -->
+ <xsl:if test="position() &gt; 1">
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:if>
+
+ <!-- Output the access specifier -->
+ <xsl:variable name="access">
+ <xsl:choose>
+ <xsl:when test="@access">
+ <xsl:value-of select="@access"/>
+ </xsl:when>
+ <xsl:when test="parent::class|parent::class-specialization">
+ <xsl:text>private</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>public</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="@access"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+
+ <!-- Output the type -->
+ <xsl:choose>
+ <xsl:when test="type">
+ <xsl:apply-templates select="type/*|type/text()" mode="annotation">
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>
+ <xsl:text>Warning: missing 'type' element inside 'inherit'</xsl:text>
+ </xsl:message>
+ <xsl:call-template name="print.warning.context"/>
+ <xsl:apply-templates mode="annotation"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="@pack=1"><xsl:text>...</xsl:text></xsl:if>
+
+ <!-- Output a comma if not at the end -->
+ <xsl:if test="position() &lt; $n">
+ <xsl:text>,</xsl:text>
+ </xsl:if>
+
+ <!-- Output a comment if we have one -->
+ <xsl:if test="purpose">
+ <xsl:choose>
+ <xsl:when test="position() &lt; $n">
+ <xsl:text> </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text> </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:apply-templates select="purpose"
+ mode="comment"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+
+ <xsl:if test="position() &lt; $n">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="print.base.classes">
+ <xsl:param name="indentation" select="0"/>
+ <xsl:param name="base-indentation" select="0"/>
+
+ <xsl:variable name="single-line-candidate" select="not(inherit/purpose)"/>
+ <xsl:variable name="single-line">
+ <xsl:if test="$single-line-candidate">
+ <xsl:call-template name="print.base.classes.single"/>
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="$single-line-candidate and
+ (string-length($single-line) + $indentation + 3
+ &lt; $max-columns)">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="' : '"/>
+ </xsl:call-template>
+ <xsl:call-template name="print.base.classes.single"/>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="' {'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$single-line-candidate and
+ (string-length($single-line) + $base-indentation + 2
+ &lt; $max-columns)">
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="' :&#10;'"/>
+ </xsl:call-template>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$base-indentation + 2"/>
+ </xsl:call-template>
+ <xsl:call-template name="print.base.classes.single"/>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$base-indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="'{'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="' : '"/>
+ </xsl:call-template>
+ <xsl:call-template name="print.base.classes.multi">
+ <xsl:with-param name="indentation" select="$indentation + 3"/>
+ </xsl:call-template>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$base-indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'{'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Emit a list of base classes without comments and on a single line -->
+ <xsl:template match="inherit">
+ <xsl:choose>
+ <xsl:when test="position()=1">
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>, </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="@access"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:apply-templates mode="annotation">
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:apply-templates>
+ <xsl:if test="@pack=1"><xsl:text>...</xsl:text></xsl:if>
+ </xsl:template>
+
+ <!-- Find the maximum length of the types in typedefs -->
+ <xsl:template name="find-max-type-length">
+ <xsl:param name="typedefs" select="typedef"/>
+ <xsl:param name="max-length" select="0"/>
+ <xsl:param name="want-name" select="false()"/>
+
+ <xsl:choose>
+ <xsl:when test="$typedefs">
+ <xsl:variable name="typedef" select="$typedefs[position()=1]"/>
+ <xsl:variable name="rest" select="$typedefs[position()!=1]"/>
+
+ <!-- Find the length of the type -->
+ <xsl:variable name="length">
+ <xsl:choose>
+ <xsl:when test="$typedef/@name != '...'">
+ <xsl:choose>
+ <xsl:when test="$want-name">
+ <xsl:value-of select="string-length($typedef/@name) + 1"/>
+ </xsl:when>
+ <xsl:when test="$typedef/@type">
+ <xsl:value-of select="string-length($typedef/@type)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string-length($typedef/type)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ 0
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Pass on the larger length -->
+ <xsl:choose>
+ <xsl:when test="$length &gt; $max-length">
+ <xsl:call-template name="find-max-type-length">
+ <xsl:with-param name="typedefs" select="$rest"/>
+ <xsl:with-param name="max-length" select="$length"/>
+ <xsl:with-param name="want-name" select="$want-name"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="find-max-type-length">
+ <xsl:with-param name="typedefs" select="$rest"/>
+ <xsl:with-param name="max-length" select="$max-length"/>
+ <xsl:with-param name="want-name" select="$want-name"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$max-length"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="constructor" mode="synopsis">
+ <xsl:param name="indentation"/>
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="context" select="../@name"/>
+ <xsl:with-param name="is-reference" select="false()"/>
+ <xsl:with-param name="constructor-for">
+ <xsl:call-template name="object-name"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="copy-assignment" mode="synopsis">
+ <xsl:param name="indentation"/>
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="context" select="../@name"/>
+ <xsl:with-param name="is-reference" select="false()"/>
+ <xsl:with-param name="copy-assign-for">
+ <xsl:call-template name="object-name"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="destructor" mode="synopsis">
+ <xsl:param name="indentation"/>
+ <xsl:call-template name="function">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="context" select="../@name"/>
+ <xsl:with-param name="is-reference" select="false()"/>
+ <xsl:with-param name="destructor-for">
+ <xsl:call-template name="object-name"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template name="class-members-synopsis">
+ <xsl:param name="indentation" select="0"/>
+ <!-- Used to suppress anchors in nested synopsis, so we don't get multiple anchors -->
+ <xsl:param name="allow-synopsis-anchors" select="false()"/>
+
+ <!-- Typedefs -->
+ <xsl:if test="typedef">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <!-- True if there are any non-compacted typedefs -->
+ <xsl:variable name="have-typedef-references"
+ select="typedef and ((typedef/para|typedef/description) or ($boost.compact.typedef='0'))"/>
+ <xsl:choose>
+ <xsl:when test="$have-typedef-references">
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ <xsl:text>types</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="'types'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>types</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+
+ <xsl:variable name="max-type-length">
+ <xsl:call-template name="find-max-type-length"/>
+ </xsl:variable>
+ <xsl:variable name="max-name-length">
+ <xsl:call-template name="find-max-type-length">
+ <xsl:with-param name="want-name" select="true()"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:apply-templates select="typedef" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ <xsl:with-param name="max-type-length"
+ select="$max-type-length"/>
+ <xsl:with-param name="max-name-length"
+ select="$max-name-length"/>
+ <xsl:with-param name="allow-anchor" select="$allow-synopsis-anchors"/>
+ </xsl:apply-templates>
+ </xsl:if>
+
+ <!-- Static constants -->
+ <xsl:if test="static-constant">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:if test="typedef">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text" select="'// static constants'"/>
+ </xsl:call-template>
+ <xsl:apply-templates select="static-constant" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:apply-templates>
+ </xsl:if>
+
+ <!-- Nested classes/structs/unions -->
+ <xsl:if test="class|class-specialization|struct|struct-specialization|union|union-specialization">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:if test="typedef|static-constant">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text" select="'// member classes/structs/unions'"/>
+ </xsl:call-template>
+ <xsl:apply-templates select="class|class-specialization|
+ struct|struct-specialization|
+ union|union-specialization"
+ mode="reference">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:apply-templates>
+ </xsl:if>
+
+ <!-- Enums -->
+ <xsl:apply-templates select="enum" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:apply-templates>
+
+ <!-- Construct/Copy/Destruct -->
+ <xsl:call-template name="construct-copy-destruct-synopsis">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:call-template>
+
+ <!-- Member functions -->
+ <xsl:apply-templates
+ select="method-group|method|overloaded-method"
+ mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:apply-templates>
+
+ <!-- Data members -->
+ <xsl:if test="data-member">
+ <xsl:text>&#10;&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:choose>
+ <xsl:when test="data-member/description">
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ <xsl:text>public-data-members</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="'public data members'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>public data members</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:apply-templates select="data-member" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation + 2"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="print-access-specification">
+ <xsl:param name="indentation" select="0"/>
+ <xsl:param name="specification" select="'public'"/>
+
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="$specification"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="':'"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="access" mode="synopsis">
+ <xsl:param name="indentation" select="0"/>
+ <xsl:param name="allow-synopsis-anchors" select="false()"/>
+
+ <xsl:call-template name="print-access-specification">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="specification" select="@name"/>
+ </xsl:call-template>
+ <xsl:call-template name="class-members-synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="allow-synopsis-anchors" select="$allow-synopsis-anchors"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template name="class-type-synopsis">
+ <xsl:param name="indentation" select="0"/>
+ <xsl:param name="allow-synopsis-anchors" select="false()"/>
+
+ <!-- The keyword used to declare this class type, e.g., class,
+ struct, or union. -->
+ <xsl:variable name="class-key">
+ <xsl:call-template name="type.class.key"/>
+ </xsl:variable>
+
+ <xsl:if test="ancestor::class|ancestor::class-specialization|
+ ancestor::struct|ancestor::struct-specialization|
+ ancestor::union|ancestor::union-specialization">
+ <xsl:text>&#10;</xsl:text>
+
+ <!-- If this nested class has a "purpose" element, use it as a
+ comment. -->
+ <xsl:if test="purpose">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:variable name="spaces">
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:copy-of select="$spaces"/>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:apply-templates select="purpose" mode="comment">
+ <xsl:with-param name="wrap" select="true()"/>
+ <xsl:with-param name="prefix" select="concat($spaces, '// ')"/>
+ </xsl:apply-templates>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+ </xsl:if>
+
+ <!-- Template header -->
+ <xsl:if test="template">
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:apply-templates select="template" mode="reference">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ <xsl:text>&#10;</xsl:text>
+
+ <!-- Class name -->
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="$class-key"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+
+ <!-- Make the class name a link to the class reference page (useful for nested classes) -->
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <xsl:value-of select="@name"/>
+ </xsl:with-param>
+ </xsl:call-template>
+
+ <xsl:apply-templates select="specialization"/>
+
+ <xsl:choose>
+ <xsl:when test="inherit">
+ <!-- Base class list (with opening brace) -->
+ <xsl:call-template name="print.base.classes">
+ <xsl:with-param name="indentation"
+ select="string-length($class-key) + string-length(@name)
+ + $indentation + 1"/>
+ <xsl:with-param name="base-indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Opening brace -->
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="' {'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <!-- Default public designator for members not inside explicit <access> elements -->
+ <xsl:if test="contains(local-name(.), 'class')">
+ <xsl:if test="count(static-constant|typedef|enum|
+ copy-assignment|constructor|destructor|method-group|
+ method|overloaded-method|data-member|
+ class|class-specialization|
+ struct|struct-specialization|
+ union|union-specialization) &gt; 0">
+ <xsl:call-template name="print-access-specification">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+
+ <xsl:call-template name="class-members-synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="allow-synopsis-anchors" select="$allow-synopsis-anchors"/>
+ </xsl:call-template>
+
+ <xsl:apply-templates select="access" mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="allow-synopsis-anchors" select="$allow-synopsis-anchors"/>
+ </xsl:apply-templates>
+
+ <!-- Closing brace -->
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="'};'"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- Emit nested class reference documentation -->
+ <xsl:template match="class|class-specialization|
+ struct|struct-specialization|
+ union|union-specialization" mode="reference">
+ <xsl:param name="indentation"/>
+
+ <xsl:call-template name="class-type-synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- Document template parameters -->
+ <xsl:template name="class-templates-reference">
+ <xsl:if test="(template/template-type-parameter/purpose|
+ template/template-nontype-parameter/purpose)
+ and not($template.param.brief)">
+ <refsect2>
+ <title>Template Parameters</title>
+ <orderedlist>
+ <xsl:for-each select="template/template-type-parameter|
+ template/template-nontype-parameter">
+ <listitem>
+ <para>
+ <xsl:variable name="link-to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:variable>
+
+ <xsl:call-template name="preformatted">
+ <xsl:with-param name="text">
+ <xsl:call-template name="template.parameter">
+ <xsl:with-param name="parameter" select="."/>
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </para>
+ <xsl:if test="purpose">
+ <para>
+ <xsl:apply-templates select="purpose/*"/>
+ </para>
+ </xsl:if>
+ </listitem>
+ </xsl:for-each>
+ </orderedlist>
+ </refsect2>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="member-typedefs-reference">
+ <!-- True if there are any non-compacted typedefs -->
+ <xsl:variable name="have-typedef-references"
+ select="typedef and ((typedef/para|typedef/description) or ($boost.compact.typedef='0'))"/>
+ <xsl:if test="$have-typedef-references">
+ <xsl:call-template name="member-documentation">
+ <xsl:with-param name="name">
+ <xsl:call-template name="anchor">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ <xsl:text>types</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="''"/>
+ </xsl:call-template>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text">
+ <xsl:call-template name="object-name"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="access-name"/>
+ <xsl:text> types</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <orderedlist>
+ <xsl:apply-templates select="typedef" mode="reference"/>
+ </orderedlist>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="data-member-reference">
+ <xsl:if test="data-member/description">
+ <xsl:call-template name="member-documentation">
+ <xsl:with-param name="name">
+ <xsl:call-template name="anchor">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ <xsl:text>public-data-members</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="''"/>
+ </xsl:call-template>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text">
+ <xsl:call-template name="object-name"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="access-name"/>
+ <xsl:text> public data members</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <orderedlist>
+ <xsl:apply-templates select="data-member" mode="reference"/>
+ </orderedlist>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="class-members-reference">
+
+ <xsl:call-template name="member-typedefs-reference"/>
+
+ <xsl:call-template name="construct-copy-destruct-reference"/>
+
+ <xsl:apply-templates
+ select="method-group|method|overloaded-method"
+ mode="reference"/>
+
+ <xsl:call-template name="data-member-reference"/>
+
+ <!-- Emit reference docs for nested classes -->
+ <xsl:apply-templates
+ select="class|class-specialization|
+ struct|struct-specialization|
+ union|union-specialization"
+ mode="namespace-reference"/>
+
+ <!-- Emit reference docs for nested enums -->
+ <xsl:apply-templates
+ select="enum"
+ mode="namespace-reference"/>
+ </xsl:template>
+
+ <xsl:template match="access" mode="namespace-reference">
+ <xsl:call-template name="class-members-reference"/>
+ </xsl:template>
+
+ <!-- Emit namespace-level class reference documentation -->
+ <xsl:template match="class|class-specialization|
+ struct|struct-specialization|
+ union|union-specialization" mode="namespace-reference">
+ <xsl:param name="indentation" select="0"/>
+
+ <xsl:call-template name="separator"/>
+ <xsl:call-template name="reference-documentation">
+ <xsl:with-param name="refname">
+ <xsl:call-template name="fully-qualified-name">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="purpose" select="purpose/*|purpose/text()"/>
+ <xsl:with-param name="anchor">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="name">
+ <xsl:call-template name="type.display.name"/>
+ </xsl:with-param>
+ <xsl:with-param name="synopsis">
+ <xsl:call-template name="header-link"/>
+ <xsl:call-template name="class-type-synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="allow-synopsis-anchors" select="true()"/>
+ </xsl:call-template>
+ <!-- Associated free functions -->
+ <xsl:apply-templates select="free-function-group"
+ mode="synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="class" select="@name"/>
+ </xsl:apply-templates>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <!-- Paragraphs go into the top of the "Description" section. -->
+ <xsl:if test="para">
+ <xsl:message>
+ <xsl:text>Warning: Use of 'para' elements in 'class' element is deprecated.&#10;Wrap them in a 'description' element.</xsl:text>
+ </xsl:message>
+ <xsl:call-template name="print.warning.context"/>
+ <xsl:apply-templates select="para" mode="annotation"/>
+ </xsl:if>
+ <xsl:apply-templates select="description"/>
+ <xsl:call-template name="class-templates-reference"/>
+ <xsl:call-template name="class-members-reference"/>
+ <xsl:apply-templates select="access" mode="namespace-reference"/>
+
+ <xsl:apply-templates select="free-function-group" mode="reference">
+ <xsl:with-param name="class" select="@name"/>
+ </xsl:apply-templates>
+
+ <!-- Specializations of this class -->
+ <!-- TBD: fix this. We should key off the class name and match
+ fully-qualified names -->
+ <xsl:variable name="name" select="@name"/>
+ <xsl:if test="local-name(.)='class' and
+ ../class-specialization[@name=$name]">
+ <refsect2>
+ <title>Specializations</title>
+ <itemizedlist>
+ <xsl:apply-templates
+ select="../class-specialization[@name=$name]"
+ mode="specialization-list"/>
+ </itemizedlist>
+ </refsect2>
+ </xsl:if>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- Output a link to a specialization -->
+ <xsl:template match="class-specialization|
+ struct-specialization|
+ union-specialization" mode="specialization-list">
+ <listitem>
+ <para>
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text">
+ <xsl:call-template name="type.display.name"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </para>
+ </listitem>
+ </xsl:template>
+
+ <!-- Data member synopsis -->
+ <xsl:template match="data-member" mode="synopsis">
+ <xsl:param name="indentation"/>
+
+ <xsl:choose>
+ <xsl:when test="ancestor::class|ancestor::class-specialization|
+ ancestor::struct|ancestor::struct-specialization|
+ ancestor::union|ancestor::union-specialization">
+
+ <!-- Spacing -->
+ <xsl:if
+ test="not(local-name(preceding-sibling::*[position()=1])=local-name(.)) and (position() &gt; 1)">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+
+ <!-- Indent -->
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+
+ <xsl:if test="@specifiers">
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="@specifiers"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ </xsl:if>
+
+ <xsl:apply-templates select="type" mode="highlight"/>
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <xsl:when test="description">
+ <xsl:variable name="link-to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:variable>
+ <xsl:call-template name="link-or-anchor">
+ <xsl:with-param name="to" select="$link-to"/>
+ <xsl:with-param name="text" select="@name"/>
+ <xsl:with-param name="link-type" select="'link'"/>
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="highlight-identifier">
+ <xsl:with-param name="identifier" select="@name"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="';'"/>
+ </xsl:call-template>
+
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="global-synopsis">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <!-- If there is a <purpose>, then add it as an
+ inline comment immediately following the data
+ member definition in the synopsis -->
+ <xsl:if test="purpose">
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:apply-templates select="purpose/*|purpose/text()"
+ mode="purpose"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Data member reference -->
+ <xsl:template match="data-member" mode="reference">
+ <xsl:choose>
+ <xsl:when test="ancestor::class|ancestor::class-specialization|
+ ancestor::struct|ancestor::struct-specialization|
+ ancestor::union|ancestor::union-specialization">
+ <xsl:if test="description">
+ <listitem>
+ <para>
+ <xsl:variable name="link-to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:variable>
+
+ <xsl:call-template name="preformatted">
+ <xsl:with-param name="text">
+ <xsl:if test="@specifiers">
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="@specifiers"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ </xsl:if>
+
+ <xsl:apply-templates select="type" mode="highlight"/>
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="link-or-anchor">
+ <xsl:with-param name="to" select="$link-to"/>
+ <xsl:with-param name="text" select="@name"/>
+ <xsl:with-param name="link-type" select="'anchor'"/>
+ <xsl:with-param name="highlight" select="true()"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="';'"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </para>
+ <xsl:apply-templates select="description"/>
+ </listitem>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="global-reference"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Enumeration synopsis -->
+ <xsl:template match="enum" mode="synopsis">
+ <xsl:param name="indentation"/>
+
+ <!-- Spacing -->
+ <xsl:if
+ test="(not (local-name(preceding-sibling::*[position()=1])=local-name(.))
+ and (position() &gt; 1)) or
+ not (para or description or not ($boost.compact.enum=1))">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+
+ <!-- Indent -->
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+
+ <xsl:choose>
+ <!-- When there is a detailed description, we only put the
+ declaration in the synopsis and will put detailed documentation
+ in either a <refentry/> or in class documentation. -->
+ <xsl:when test="para or description or not ($boost.compact.enum=1)">
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="'enum'"/>
+ </xsl:call-template>
+
+ <xsl:text> </xsl:text>
+
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="string(@name)"/>
+ <xsl:with-param name="higlhight" select="false()"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- When there is no detailed description, we put the enum
+ definition within the synopsis. The purpose of the enum (if
+ available) is formatted as a comment prior to the
+ definition. This way, we do not create a separate block of text
+ for what is generally a very small amount of information. -->
+ <xsl:otherwise>
+ <xsl:if test="purpose">
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text">
+ <xsl:text>// </xsl:text>
+ <xsl:apply-templates select="purpose" mode="comment"/>
+ </xsl:with-param>
+ </xsl:call-template>
+
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:if>
+
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="'enum'"/>
+ </xsl:call-template>
+
+ <xsl:text> </xsl:text>
+
+ <xsl:call-template name="anchor">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="@name"/>
+ <xsl:with-param name="higlhight" select="false()"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="' { '"/>
+ </xsl:call-template>
+ <xsl:call-template name="type.enum.list.compact">
+ <xsl:with-param name="indentation"
+ select="$indentation + string-length(@name) + 8"/>
+ <xsl:with-param name="compact" select="true()"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="' }'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="';'"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- Enumeration reference at namespace level -->
+ <xsl:template match="enum" mode="namespace-reference">
+ <xsl:if test="para or description or not ($boost.compact.enum=1)">
+ <xsl:call-template name="reference-documentation">
+ <xsl:with-param name="name">
+ <xsl:call-template name="type.display.name"/>
+ </xsl:with-param>
+ <xsl:with-param name="refname">
+ <xsl:call-template name="fully-qualified-name">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="purpose" select="purpose/*|purpose/text()"/>
+ <xsl:with-param name="anchor">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="synopsis">
+ <xsl:call-template name="header-link"/>
+ <xsl:call-template name="type.enum.display"/>
+ </xsl:with-param>
+
+ <xsl:with-param name="text">
+ <!-- Paragraphs go into the top of the "Description" section. -->
+ <xsl:if test="para">
+ <xsl:message>
+ <xsl:text>Warning: Use of 'para' elements in 'enum' element is deprecated.&#10;Wrap them in a 'description' element.</xsl:text>
+ </xsl:message>
+ <xsl:call-template name="print.warning.context"/>
+ <xsl:apply-templates select="para" mode="annotation"/>
+ </xsl:if>
+ <xsl:apply-templates select="description"/>
+ <xsl:if test="enumvalue/purpose | enumvalue/description">
+ <variablelist spacing="compact">
+ <xsl:apply-templates select="enumvalue" mode="reference"/>
+ </variablelist>
+ </xsl:if>
+ </xsl:with-param>
+
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Output an enumeration along with its values -->
+ <xsl:template name="type.enum.display">
+ <!-- Spacing -->
+ <xsl:if test="position() &gt; 1">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+
+ <xsl:text>&#10;</xsl:text>
+
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="'enum'"/>
+ </xsl:call-template>
+
+ <!-- Header -->
+ <xsl:variable name="header" select="concat(' ', @name, ' { ')"/>
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="$header"/>
+ </xsl:call-template>
+
+ <!-- Print the enumeration values -->
+ <xsl:call-template name="type.enum.list.compact">
+ <xsl:with-param name="indentation" select="4 + string-length($header)"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="highlight-text">
+ <xsl:with-param name="text" select="' };'"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- List enumeration values in a compact form e.g.,
+ enum Name { value1 = foo, value2 = bar, ... };
+ This routine prints only the enumeration values; the caller is
+ responsible for printing everything outside the braces
+ (inclusive). -->
+ <xsl:template name="type.enum.list.compact">
+ <xsl:param name="indentation"/>
+ <xsl:param name="compact" select="false()"/>
+
+ <!-- Internal: The column we are on -->
+ <xsl:param name="column" select="$indentation"/>
+
+ <!-- Internal: The index of the current enumvalue
+ we're processing -->
+ <xsl:param name="pos" select="1"/>
+
+ <!-- Internal: a prefix that we need to print prior to printing
+ this value. -->
+ <xsl:param name="prefix" select="''"/>
+
+ <xsl:if test="not($pos &gt; count(enumvalue))">
+ <xsl:variable name="value" select="enumvalue[position()=$pos]"/>
+
+ <!-- Compute the string to be printed for this value -->
+ <xsl:variable name="result">
+ <xsl:value-of select="$prefix"/>
+ <xsl:value-of select="$value/attribute::name"/>
+
+ <xsl:if test="$value/default">
+ <xsl:text> = </xsl:text>
+ <xsl:value-of select="$value/default/*|$value/default/text()"/>
+ </xsl:if>
+ </xsl:variable>
+
+ <!-- The column we will end on, assuming that this value fits on
+ this line -->
+ <xsl:variable name="end" select="$column + string-length($result)"/>
+
+ <!-- The column we will actually end on -->
+ <xsl:variable name="end2">
+ <xsl:choose>
+ <!-- If the enumeration value fits on this line, put it there -->
+ <xsl:when test="$end &lt; $max-columns">
+ <xsl:value-of select="$end"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$indentation
+ + string-length($result)
+ - string-length($prefix)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:value-of select="$prefix"/>
+
+ <!-- If the enumeration value doesn't fit on this line,
+ put it on a new line -->
+ <xsl:if test="not($end &lt; $max-columns)">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ </xsl:call-template>
+ </xsl:if>
+
+ <!-- If the enumeration value has a description, link it
+ to its description. -->
+ <xsl:choose>
+ <xsl:when test="($value/purpose or $value/description) and not($compact)">
+ <xsl:call-template name="internal-link">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id">
+ <xsl:with-param name="node" select="$value"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="$value/attribute::name"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value/attribute::name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <!-- If the enumeration value has a default,
+ print it. -->
+ <xsl:if test="$value/default">
+ <xsl:text> = </xsl:text>
+ <xsl:apply-templates
+ select="$value/default/*|$value/default/text()"/>
+ </xsl:if>
+
+ <!-- Recursively generate the rest of the enumeration list -->
+ <xsl:call-template name="type.enum.list.compact">
+ <xsl:with-param name="indentation" select="$indentation"/>
+ <xsl:with-param name="compact" select="$compact"/>
+ <xsl:with-param name="column" select="$end2"/>
+ <xsl:with-param name="pos" select="$pos + 1"/>
+ <xsl:with-param name="prefix" select="', '"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Enumeration reference at namespace level -->
+ <xsl:template match="enumvalue" mode="reference">
+ <xsl:if test="purpose or description">
+ <varlistentry>
+ <term>
+ <xsl:call-template name="monospaced">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ <!-- Note: the anchor must come after the text here, and not
+ before it; otherwise, FOP goes into an infinite loop. -->
+ <xsl:call-template name="anchor">
+ <xsl:with-param name="to">
+ <xsl:call-template name="generate.id"/>
+ </xsl:with-param>
+ <xsl:with-param name="text" select="''"/>
+ </xsl:call-template>
+ </term>
+ <listitem>
+ <xsl:apply-templates select="purpose|description" mode="comment"/>
+ </listitem>
+ </varlistentry>
+ </xsl:if>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/utility.xsl b/tools/boostbook/xsl/utility.xsl
new file mode 100644
index 0000000000..75ae1cafd2
--- /dev/null
+++ b/tools/boostbook/xsl/utility.xsl
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <!-- Indent the current line-->
+ <xsl:template name="indent">
+ <xsl:param name="indentation"/>
+ <xsl:if test="$indentation > 0">
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="indent">
+ <xsl:with-param name="indentation" select="$indentation - 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- get name of first ancestor-or-self which is a class, struct or union -->
+ <xsl:template name="object-name">
+ <xsl:variable name="ancestors" select="ancestor-or-self::class |
+ ancestor-or-self::class-specialization |
+ ancestor-or-self::struct |
+ ancestor-or-self::struct-specialization |
+ ancestor-or-self::union |
+ ancestor-or-self::union-specialization"/>
+ <xsl:value-of select="$ancestors[last()]/@name"/>
+ </xsl:template>
+
+ <!-- get name of access specification that we are inside -->
+ <xsl:template name="access-name">
+ <xsl:variable name="ancestors" select="ancestor-or-self::access |
+ ancestor-or-self::class |
+ ancestor-or-self::class-specialization |
+ ancestor-or-self::struct |
+ ancestor-or-self::struct-specialization |
+ ancestor-or-self::union |
+ ancestor-or-self::union-specialization"/>
+ <xsl:choose>
+ <xsl:when test="name($ancestors[last()])='access'">
+ <xsl:value-of select="$ancestors[last()]/@name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ public
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/xhtml.xsl b/tools/boostbook/xsl/xhtml.xsl
new file mode 100644
index 0000000000..484bb677df
--- /dev/null
+++ b/tools/boostbook/xsl/xhtml.xsl
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision"
+ version="1.0">
+
+ <!-- Import the HTML chunking stylesheet -->
+ <xsl:import
+ href="http://docbook.sourceforge.net/release/xsl/current/xhtml/chunk.xsl"/>
+ <xsl:import
+ href="http://docbook.sourceforge.net/release/xsl/current/xhtml/math.xsl"/>
+
+ <!-- Bring in the fast chunking overrides. There's nothing
+ that we need to override, so include instead of importing it. -->
+ <xsl:include
+ href="http://docbook.sourceforge.net/release/xsl/current/xhtml/chunkfast.xsl"/>
+
+ <!-- We have to make sure that our templates override all
+ docbook templates. Therefore, we include our own templates
+ instead of importing them. In order for this to work,
+ the stylesheets included here cannot also include each other -->
+ <xsl:include href="chunk-common.xsl"/>
+ <xsl:include href="docbook-layout.xsl"/>
+ <xsl:include href="navbar.xsl"/>
+ <xsl:include href="admon.xsl"/>
+ <xsl:include href="xref.xsl"/>
+ <xsl:include href="relative-href.xsl"/>
+ <xsl:include href="callout.xsl"/>
+ <xsl:include href="html-base.xsl"/>
+
+</xsl:stylesheet>
diff --git a/tools/boostbook/xsl/xref.xsl b/tools/boostbook/xsl/xref.xsl
new file mode 100644
index 0000000000..c6d85953d9
--- /dev/null
+++ b/tools/boostbook/xsl/xref.xsl
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<!--
+ Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:suwl="http://nwalsh.com/xslt/ext/com.nwalsh.saxon.UnwrapLinks"
+ exclude-result-prefixes="suwl"
+ version="1.0">
+
+<!-- Import the HTML chunking stylesheet -->
+<xsl:import
+ href="http://docbook.sourceforge.net/release/xsl/current/html/xref.xsl"/>
+
+
+<xsl:template name="adjust-url">
+ <xsl:param name="target"/>
+ <xsl:param name="context" select="."/>
+
+ <xsl:choose>
+ <xsl:when test="contains($target, ':')">
+ <xsl:value-of select="$target"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="href.target.relative">
+ <xsl:with-param name="target" select="$target"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+
+</xsl:template>
+
+
+<xsl:template match="ulink" name="ulink">
+ <xsl:variable name="link">
+ <a>
+ <xsl:if test="@id">
+ <xsl:attribute name="name">
+ <xsl:value-of select="@id"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="href">
+ <xsl:call-template name="adjust-url">
+ <xsl:with-param name="target" select="@url"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="$ulink.target != ''">
+ <xsl:attribute name="target">
+ <xsl:value-of select="$ulink.target"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="count(child::node())=0">
+ <xsl:value-of select="@url"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </a>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('suwl:unwrapLinks')">
+ <xsl:copy-of select="suwl:unwrapLinks($link)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="$link"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+</xsl:stylesheet>
diff --git a/tools/build/boost.css b/tools/build/boost.css
new file mode 100644
index 0000000000..d0a30762dd
--- /dev/null
+++ b/tools/build/boost.css
@@ -0,0 +1,65 @@
+/*
+Copyright 2002 David Abrahams.
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+ */
+H1
+{
+ FONT-SIZE: 200%
+ COLOR: #00007f
+}
+H2
+{
+ FONT-SIZE: 150%;
+}
+H3
+{
+ FONT-SIZE: 125%;
+}
+H4
+{
+ FONT-SIZE: 108%;
+}
+BODY
+{
+ FONT-SIZE: 100%;
+ BACKGROUND-COLOR: #ffffff
+}
+PRE
+{
+ MARGIN-LEFT: 2pc;
+ FONT-SIZE: 80%;
+ BACKGROUND-COLOR: #dfffff
+}
+CODE
+{
+ FONT-SIZE: 95%;
+ white-space: pre
+}
+.index
+{
+ TEXT-ALIGN: left
+}
+.page-index
+{
+ TEXT-ALIGN: left
+}
+.definition
+{
+ TEXT-ALIGN: left
+}
+.footnote
+{
+ FONT-SIZE: 66%;
+ VERTICAL-ALIGN: super;
+ TEXT-DECORATION: none
+}
+.function-semantics
+{
+ CLEAR: left
+}
+.metafunction-semantics
+{
+ CLEAR: left
+}
diff --git a/tools/build/index.html b/tools/build/index.html
new file mode 100644
index 0000000000..12f22e4132
--- /dev/null
+++ b/tools/build/index.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+ Copyright 2003 Rene Rivera.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta http-equiv="refresh" content="0; URL=v2/index.html" />
+
+ <title></title>
+</head>
+
+<body>
+ Automatic redirection failed, please go to <a href=
+ "v2/index.html">v2/index.html</a>.
+</body>
+</html>
diff --git a/tools/build/v2/Jamroot.jam b/tools/build/v2/Jamroot.jam
new file mode 100644
index 0000000000..11334864c2
--- /dev/null
+++ b/tools/build/v2/Jamroot.jam
@@ -0,0 +1,47 @@
+
+path-constant SELF : . ;
+
+import path ;
+import package ;
+import os ;
+
+local ext = "" ;
+if [ os.on-windows ]
+{
+ ext = ".exe" ;
+}
+
+
+package.install boost-build-engine boost-build
+ : # properties
+ : # binaries
+ b2$(ext) bjam$(ext)
+ ;
+
+local e1 = [ path.glob-tree $(SELF)/example : * : . .svn ] ;
+local e2 ;
+for e in $(e1)
+{
+ e = [ path.native $(e) ] ;
+ if [ CHECK_IF_FILE $(e) ]
+ {
+ e2 += $(e) ;
+ }
+}
+
+package.install-data boost-build-core
+ : # Which subdir of $prefix/share
+ boost-build
+ : # What to install
+ $(SELF)/boost-build.jam
+ $(SELF)/build-system.jam
+ [ path.glob-tree $(SELF)/build : *.jam *.py ]
+ [ path.glob-tree $(SELF)/kernel : *.jam *.py ]
+ [ path.glob-tree $(SELF)/util : *.jam *.py ]
+ [ path.glob-tree $(SELF)/tools : *.jam *.py ]
+ $(e2)
+ : # What is the root of the directory
+ <install-source-root>.
+ ;
+
+alias install : boost-build-engine boost-build-core ; \ No newline at end of file
diff --git a/tools/build/v2/boost-build.jam b/tools/build/v2/boost-build.jam
new file mode 100644
index 0000000000..73db0497be
--- /dev/null
+++ b/tools/build/v2/boost-build.jam
@@ -0,0 +1,8 @@
+# Copyright 2001, 2002 Dave Abrahams
+# Copyright 2002 Rene Rivera
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+boost-build kernel ;
diff --git a/tools/build/v2/boost.css b/tools/build/v2/boost.css
new file mode 100644
index 0000000000..8401b29c33
--- /dev/null
+++ b/tools/build/v2/boost.css
@@ -0,0 +1,63 @@
+/* Copyright 2002 Dave Abrahams */
+/* Distributed under the Boost Software License, Version 1.0. */
+/* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) */
+
+H1
+{
+ FONT-SIZE: 200%
+ COLOR: #00007f
+}
+H2
+{
+ FONT-SIZE: 150%;
+}
+H3
+{
+ FONT-SIZE: 125%;
+}
+H4
+{
+ FONT-SIZE: 108%;
+}
+BODY
+{
+ FONT-SIZE: 100%;
+ BACKGROUND-COLOR: #ffffff
+}
+PRE
+{
+ MARGIN-LEFT: 2pc;
+ FONT-SIZE: 80%;
+ BACKGROUND-COLOR: #dfffff
+}
+CODE
+{
+ FONT-SIZE: 95%;
+ white-space: pre
+}
+.index
+{
+ TEXT-ALIGN: left
+}
+.page-index
+{
+ TEXT-ALIGN: left
+}
+.definition
+{
+ TEXT-ALIGN: left
+}
+.footnote
+{
+ FONT-SIZE: 66%;
+ VERTICAL-ALIGN: super;
+ TEXT-DECORATION: none
+}
+.function-semantics
+{
+ CLEAR: left
+}
+.metafunction-semantics
+{
+ CLEAR: left
+}
diff --git a/tools/build/v2/boost_build.png b/tools/build/v2/boost_build.png
new file mode 100644
index 0000000000..3a9e64df2a
--- /dev/null
+++ b/tools/build/v2/boost_build.png
Binary files differ
diff --git a/tools/build/v2/boost_build.svg b/tools/build/v2/boost_build.svg
new file mode 100644
index 0000000000..ba4ccc77b5
--- /dev/null
+++ b/tools/build/v2/boost_build.svg
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg5675"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="boost_build.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs5677">
+ <linearGradient
+ id="linearGradient7594">
+ <stop
+ style="stop-color:#ff0000;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop7596" />
+ <stop
+ style="stop-color:#d6611e;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop7598" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient7594"
+ id="linearGradient3895"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(43.41842,0,0,0.471599,-2940.9332,-1070.4566)"
+ x1="69.430504"
+ y1="2520.6421"
+ x2="81.027824"
+ y2="2520.6421" />
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective5683" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.35"
+ inkscape:cx="375"
+ inkscape:cy="520"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="640"
+ inkscape:window-height="667"
+ inkscape:window-x="1032"
+ inkscape:window-y="308" />
+ <metadata
+ id="metadata5680">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <text
+ inkscape:export-ydpi="72"
+ inkscape:export-xdpi="72"
+ inkscape:export-filename="/tmp/boost_build_logo2.png"
+ font-size="101.123"
+ id="text3879"
+ style="font-size:78.68063354px;font-style:normal;font-variant:normal;font-weight:200;font-stretch:normal;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#4a6484;font-family:Denmark"
+ sodipodi:linespacing="100%"
+ x="114.2328"
+ y="103.41737">boost.build</text>
+ <rect
+ inkscape:export-ydpi="72.000000"
+ inkscape:export-xdpi="72.000000"
+ inkscape:export-filename="/tmp/boost_build_logo2.png"
+ y="96.838783"
+ x="-111.20226"
+ height="3.9837062"
+ width="12.670265"
+ id="rect3881"
+ style="fill:#090909;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.51475425pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ transform="matrix(-0.9999989,-1.4738959e-3,-8.0436748e-4,0.9999997,0,0)"
+ rx="0.98714525"
+ ry="0.98714548" />
+ <rect
+ inkscape:export-ydpi="72.000000"
+ inkscape:export-xdpi="72.000000"
+ inkscape:export-filename="/tmp/boost_build_logo2.png"
+ y="64.848404"
+ x="-111.1769"
+ height="3.9837253"
+ width="12.670281"
+ id="rect3883"
+ style="fill:#090909;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.51475577pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ transform="matrix(-0.9999989,-1.4738959e-3,-8.0436268e-4,0.9999997,0,0)"
+ rx="0.9871462"
+ ry="0.98715025" />
+ <rect
+ inkscape:export-ydpi="72.000000"
+ inkscape:export-xdpi="72.000000"
+ inkscape:export-filename="/tmp/boost_build_logo2.png"
+ y="96.915825"
+ x="-592.73004"
+ height="3.9841042"
+ width="50.977173"
+ id="rect3885"
+ style="fill:#090909;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.0325552pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ transform="matrix(-0.9999999,-3.6633946e-4,-3.2359694e-3,0.9999948,0,0)"
+ rx="0.98712909"
+ ry="0.98716646" />
+ <rect
+ inkscape:export-ydpi="72.000000"
+ inkscape:export-xdpi="72.000000"
+ inkscape:export-filename="/tmp/boost_build_logo2.png"
+ y="64.725166"
+ x="-568.02655"
+ height="3.9839954"
+ width="27.076828"
+ id="rect3887"
+ style="fill:#090909;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75251908pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ transform="matrix(-0.9999998,-6.89702e-4,-1.7187672e-3,0.9999985,0,0)"
+ rx="0.9871875"
+ ry="0.98721254" />
+ <path
+ inkscape:export-ydpi="72"
+ inkscape:export-xdpi="72"
+ inkscape:export-filename="/tmp/boost_build_logo2.png"
+ style="fill:#090909;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:4.44999981;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block"
+ d="M 567.03942,67.12677 L 590.59895,97.79227"
+ id="path3889"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:export-ydpi="72"
+ inkscape:export-xdpi="72"
+ inkscape:export-filename="/tmp/boost_build_logo2.png"
+ style="fill:#090909;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.95000005;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block"
+ d="M 566.93498,67.12677 L 542.24692,97.31967"
+ id="path3891"
+ sodipodi:nodetypes="cc" />
+ <rect
+ inkscape:export-ydpi="72"
+ inkscape:export-xdpi="72"
+ inkscape:export-filename="/tmp/boost_build_logo2.png"
+ y="116.76698"
+ x="98.71344"
+ height="7.0450115"
+ width="494.58636"
+ id="rect3893"
+ style="fill:url(#linearGradient3895);fill-opacity:1;fill-rule:nonzero;stroke:#b2b2b2;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block" />
+ </g>
+</svg>
diff --git a/tools/build/v2/bootstrap.bat b/tools/build/v2/bootstrap.bat
new file mode 100644
index 0000000000..190c9283de
--- /dev/null
+++ b/tools/build/v2/bootstrap.bat
@@ -0,0 +1,49 @@
+@ECHO OFF
+
+REM Copyright (C) 2009 Vladimir Prus
+REM
+REM Distributed under the Boost Software License, Version 1.0.
+REM (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+ECHO Bootstrapping the build engine
+if exist ".\engine\bin.ntx86\bjam.exe" del engine\bin.ntx86\bjam.exe
+if exist ".\engine\bin.ntx86_64\bjam.exe" del engine\bin.ntx86_64\bjam.exe
+cd engine
+
+call .\build.bat %* > ..\..\bootstrap.log
+@ECHO OFF
+cd ..
+
+if exist ".\engine\bin.ntx86\b2.exe" (
+ copy .\engine\bin.ntx86\b2.exe . > nul
+ copy .\engine\bin.ntx86\bjam.exe . > nul
+ goto :bjam_built)
+
+if exist ".\engine\bin.ntx86_64\b2.exe" (
+ copy .\engine\bin.ntx86_64\b2.exe . > nul
+ copy .\engine\bin.ntx86_64\bjam.exe . > nul
+ goto :bjam_built)
+
+goto :bjam_failure
+
+:bjam_built
+
+ECHO.
+ECHO Bootstrapping is done. To build, run:
+ECHO.
+ECHO .\b2 --prefix=DIR install
+ECHO.
+
+goto :end
+
+:bjam_failure
+
+ECHO.
+ECHO Failed to bootstrap the build engine
+ECHO Please consult bootstrap.log for furter diagnostics.
+ECHO.
+
+
+goto :end
+
+:end
diff --git a/tools/build/v2/bootstrap.jam b/tools/build/v2/bootstrap.jam
new file mode 100644
index 0000000000..af3e8bf506
--- /dev/null
+++ b/tools/build/v2/bootstrap.jam
@@ -0,0 +1,18 @@
+# Copyright (c) 2003 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# This file handles initial phase of Boost.Build loading.
+# Boost.Jam has already figured out where Boost.Build is
+# and loads this file, which is responsible for initialization
+# of basic facilities such a module system and loading the
+# main Boost.Build module, build-system.jam.
+#
+# Exact operation of this module is not interesting, it makes
+# sense to look at build-system.jam right away.
+
+# Load the kernel/bootstrap.jam, which does all the work.
+.bootstrap-file = $(.bootstrap-file:D)/kernel/bootstrap.jam ;
+include $(.bootstrap-file) ; \ No newline at end of file
diff --git a/tools/build/v2/bootstrap.sh b/tools/build/v2/bootstrap.sh
new file mode 100755
index 0000000000..5083551736
--- /dev/null
+++ b/tools/build/v2/bootstrap.sh
@@ -0,0 +1,120 @@
+#!/bin/sh
+# Copyright (C) 2005, 2006 Douglas Gregor.
+# Copyright (C) 2006 The Trustees of Indiana University
+# Copyright (C) 2010 Bryce Lelbach
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# boostinspect:notab - Tabs are required for the Makefile.
+
+BJAM=""
+TOOLSET=""
+BJAM_CONFIG=""
+
+for option
+do
+ case $option in
+
+ -help | --help | -h)
+ want_help=yes ;;
+
+ -with-toolset=* | --with-toolset=* )
+ TOOLSET=`expr "x$option" : "x-*with-toolset=\(.*\)"`
+ ;;
+
+ -*)
+ { echo "error: unrecognized option: $option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ esac
+done
+
+if test "x$want_help" = xyes; then
+ cat <<EOF
+\`./bootstrap.sh' creates minimal Boost.Build, which can install itself.
+
+Usage: $0 [OPTION]...
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --with-bjam=BJAM use existing Boost.Jam executable (bjam)
+ [automatically built]
+ --with-toolset=TOOLSET use specific Boost.Build toolset
+ [automatically detected]
+EOF
+fi
+test -n "$want_help" && exit 0
+
+# TBD: Determine where the script is located
+my_dir="."
+
+# Determine the toolset, if not already decided
+if test "x$TOOLSET" = x; then
+ guessed_toolset=`$my_dir/engine/build.sh --guess-toolset`
+ case $guessed_toolset in
+ acc | darwin | gcc | como | mipspro | pathscale | pgi | qcc | vacpp )
+ TOOLSET=$guessed_toolset
+ ;;
+
+ intel-* )
+ TOOLSET=intel
+ ;;
+
+ mingw )
+ TOOLSET=gcc
+ ;;
+
+ clang* )
+ TOOLSET=clang
+ ;;
+
+ sun* )
+ TOOLSET=sun
+ ;;
+
+ * )
+ # Not supported by Boost.Build
+ ;;
+ esac
+fi
+
+case $TOOLSET in
+ clang*)
+ TOOLSET=clang
+ ;;
+esac
+
+
+rm -f config.log
+
+# Build bjam
+if test "x$BJAM" = x; then
+ echo -n "Bootstrapping the build engine with toolset $TOOLSET... "
+ pwd=`pwd`
+ (cd "$my_dir/engine" && ./build.sh "$TOOLSET") > bootstrap.log 2>&1
+ if [ $? -ne 0 ]; then
+ echo
+ echo "Failed to bootstrap the build engine"
+ echo "Consult 'bootstrap.log' for more details"
+ exit 1
+ fi
+ cd "$pwd"
+ arch=`cd $my_dir/engine && ./bootstrap/jam0 -d0 -f build.jam --toolset=$TOOLSET --toolset-root= --show-locate-target && cd ..`
+ BJAM="$my_dir/engine/$arch/b2"
+ echo "engine/$arch/bjam"
+ cp "$BJAM" .
+ cp "$my_dir/engine/$arch/bjam" .
+fi
+
+cat << EOF
+
+Bootstrapping is done. To build and install, run:
+
+ ./b2 install --prefix=<DIR>
+
+EOF
diff --git a/tools/build/v2/build-system.jam b/tools/build/v2/build-system.jam
new file mode 100644
index 0000000000..9f9c884cc6
--- /dev/null
+++ b/tools/build/v2/build-system.jam
@@ -0,0 +1,1008 @@
+# Copyright 2003, 2005, 2007 Dave Abrahams
+# Copyright 2006, 2007 Rene Rivera
+# Copyright 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This file is part of Boost Build version 2. You can think of it as forming the
+# main() routine. It is invoked by the bootstrapping code in bootstrap.jam.
+
+import build-request ;
+import builtin ;
+import "class" : new ;
+import errors ;
+import feature ;
+import make ;
+import modules ;
+import os ;
+import path ;
+import project ;
+import property-set ;
+import regex ;
+import sequence ;
+import targets ;
+import toolset ;
+import utility ;
+import version ;
+import virtual-target ;
+import generators ;
+import configure ;
+
+################################################################################
+#
+# Module global data.
+#
+################################################################################
+
+# Shortcut used in this module for accessing used command-line parameters.
+.argv = [ modules.peek : ARGV ] ;
+
+# Flag indicating we should display additional debugging information related to
+# locating and loading Boost Build configuration files.
+.debug-config = [ MATCH ^(--debug-configuration)$ : $(.argv) ] ;
+
+# Legacy option doing too many things, some of which are not even documented.
+# Should be phased out.
+# * Disables loading site and user configuration files.
+# * Disables auto-configuration for toolsets specified explicitly on the
+# command-line.
+# * Causes --toolset command-line options to be ignored.
+# * Prevents the default toolset from being used even if no toolset has been
+# configured at all.
+.legacy-ignore-config = [ MATCH ^(--ignore-config)$ : $(.argv) ] ;
+
+# The cleaning is tricky. Say, if user says 'bjam --clean foo' where 'foo' is a
+# directory, then we want to clean targets which are in 'foo' as well as those
+# in any children Jamfiles under foo but not in any unrelated Jamfiles. To
+# achieve this we collect a list of projects under which cleaning is allowed.
+.project-targets = ;
+
+# Virtual targets obtained when building main targets references on the command
+# line. When running 'bjam --clean main_target' we want to clean only files
+# belonging to that main target so we need to record which targets are produced
+# for it.
+.results-of-main-targets = ;
+
+# Was an XML dump requested?
+.out-xml = [ MATCH ^--out-xml=(.*)$ : $(.argv) ] ;
+
+# Default toolset & version to be used in case no other toolset has been used
+# explicitly by either the loaded configuration files, the loaded project build
+# scripts or an explicit toolset request on the command line. If not specified,
+# an arbitrary default will be used based on the current host OS. This value,
+# while not strictly necessary, has been added to allow testing Boost-Build's
+# default toolset usage functionality.
+.default-toolset = ;
+.default-toolset-version = ;
+
+
+################################################################################
+#
+# Public rules.
+#
+################################################################################
+
+# Returns the property set with the free features from the currently processed
+# build request.
+#
+rule command-line-free-features ( )
+{
+ return $(.command-line-free-features) ;
+}
+
+
+# Returns the location of the build system. The primary use case is building
+# Boost where it is sometimes needed to get the location of other components
+# (e.g. BoostBook files) and it is convenient to use locations relative to the
+# Boost Build path.
+#
+rule location ( )
+{
+ local r = [ modules.binding build-system ] ;
+ return $(r:P) ;
+}
+
+
+# Sets the default toolset & version to be used in case no other toolset has
+# been used explicitly by either the loaded configuration files, the loaded
+# project build scripts or an explicit toolset request on the command line. For
+# more detailed information see the comment related to used global variables.
+#
+rule set-default-toolset ( toolset : version ? )
+{
+ .default-toolset = $(toolset) ;
+ .default-toolset-version = $(version) ;
+}
+
+rule set-pre-build-hook ( function )
+{
+ .pre-build-hook = $(function) ;
+}
+
+rule set-post-build-hook ( function )
+{
+ .post-build-hook = $(function) ;
+}
+
+################################################################################
+#
+# Local rules.
+#
+################################################################################
+
+# Returns actual Jam targets to be used for executing a clean request.
+#
+local rule actual-clean-targets ( )
+{
+ # Construct a list of projects explicitly detected as targets on this build
+ # system run. These are the projects under which cleaning is allowed.
+ for local t in $(targets)
+ {
+ if [ class.is-a $(t) : project-target ]
+ {
+ .project-targets += [ $(t).project-module ] ;
+ }
+ }
+
+ # Construct a list of targets explicitly detected on this build system run
+ # as a result of building main targets.
+ local targets-to-clean ;
+ for local t in $(.results-of-main-targets)
+ {
+ # Do not include roots or sources.
+ targets-to-clean += [ virtual-target.traverse $(t) ] ;
+ }
+ targets-to-clean = [ sequence.unique $(targets-to-clean) ] ;
+
+ local to-clean ;
+ for local t in [ virtual-target.all-targets ]
+ {
+ local p = [ $(t).project ] ;
+
+ # Remove only derived targets.
+ if [ $(t).action ]
+ {
+ if $(t) in $(targets-to-clean) ||
+ [ should-clean-project [ $(p).project-module ] ] = true
+ {
+ to-clean += $(t) ;
+ }
+ }
+ }
+
+ local to-clean-actual ;
+ for local t in $(to-clean)
+ {
+ to-clean-actual += [ $(t).actualize ] ;
+ }
+ return $(to-clean-actual) ;
+}
+
+
+# Given a target id, try to find and return the corresponding target. This is
+# only invoked when there is no Jamfile in ".". This code somewhat duplicates
+# code in project-target.find but we can not reuse that code without a
+# project-targets instance.
+#
+local rule find-target ( target-id )
+{
+ local split = [ MATCH (.*)//(.*) : $(target-id) ] ;
+
+ local pm ;
+ if $(split)
+ {
+ pm = [ project.find $(split[1]) : "." ] ;
+ }
+ else
+ {
+ pm = [ project.find $(target-id) : "." ] ;
+ }
+
+ local result ;
+ if $(pm)
+ {
+ result = [ project.target $(pm) ] ;
+ }
+
+ if $(split)
+ {
+ result = [ $(result).find $(split[2]) ] ;
+ }
+
+ return $(result) ;
+}
+
+
+# Initializes a new configuration module.
+#
+local rule initialize-config-module ( module-name : location ? )
+{
+ project.initialize $(module-name) : $(location) ;
+ if USER_MODULE in [ RULENAMES ]
+ {
+ USER_MODULE $(module-name) ;
+ }
+}
+
+
+# Helper rule used to load configuration files. Loads the first configuration
+# file with the given 'filename' at 'path' into module with name 'module-name'.
+# Not finding the requested file may or may not be treated as an error depending
+# on the must-find parameter. Returns a normalized path to the loaded
+# configuration file or nothing if no file was loaded.
+#
+local rule load-config ( module-name : filename : path + : must-find ? )
+{
+ if $(.debug-config)
+ {
+ ECHO "notice: Searching" "$(path)" "for" "$(module-name)"
+ "configuration file" "$(filename)" "." ;
+ }
+ local where = [ GLOB $(path) : $(filename) ] ;
+ if $(where)
+ {
+ where = [ NORMALIZE_PATH $(where[1]) ] ;
+ if $(.debug-config)
+ {
+ ECHO "notice: Loading" "$(module-name)" "configuration file"
+ "$(filename)" "from" $(where) "." ;
+ }
+
+ # Set source location so that path-constant in config files
+ # with relative paths work. This is of most importance
+ # for project-config.jam, but may be used in other
+ # config files as well.
+ local attributes = [ project.attributes $(module-name) ] ;
+ $(attributes).set source-location : $(where:D) : exact ;
+ modules.load $(module-name) : $(filename) : $(path) ;
+ project.load-used-projects $(module-name) ;
+ }
+ else
+ {
+ if $(must-find)
+ {
+ errors.user-error "Configuration file" "$(filename)" "not found in"
+ "$(path)" "." ;
+ }
+ if $(.debug-config)
+ {
+ ECHO "notice:" "Configuration file" "$(filename)" "not found in"
+ "$(path)" "." ;
+ }
+ }
+ return $(where) ;
+}
+
+
+# Loads all the configuration files used by Boost Build in the following order:
+#
+# -- test-config --
+# Loaded only if specified on the command-line using the --test-config
+# command-line parameter. It is ok for this file not to exist even if specified.
+# If this configuration file is loaded, regular site and user configuration
+# files will not be. If a relative path is specified, file is searched for in
+# the current folder.
+#
+# -- site-config --
+# Always named site-config.jam. Will only be found if located on the system
+# root path (Windows), /etc (non-Windows), user's home folder or the Boost Build
+# path, in that order. Not loaded in case the test-config configuration file is
+# loaded or either the --ignore-site-config or the --ignore-config command-line
+# option is specified.
+#
+# -- user-config --
+# Named user-config.jam by default or may be named explicitly using the
+# --user-config command-line option or the BOOST_BUILD_USER_CONFIG environment
+# variable. If named explicitly the file is looked for from the current working
+# directory and if the default one is used then it is searched for in the
+# user's home directory and the Boost Build path, in that order. Not loaded in
+# case either the test-config configuration file is loaded, --ignore-config
+# command-line option is specified or an empty file name is explicitly
+# specified. If the file name has been given explicitly then the file must
+# exist.
+#
+# Test configurations have been added primarily for use by Boost Build's
+# internal unit testing system but may be used freely in other places as well.
+#
+local rule load-configuration-files
+{
+ # Flag indicating that site configuration should not be loaded.
+ local ignore-site-config =
+ [ MATCH ^(--ignore-site-config)$ : $(.argv) ] ;
+
+ if $(.legacy-ignore-config) && $(.debug-config)
+ {
+ ECHO "notice: Regular site and user configuration files will be ignored" ;
+ ECHO "notice: due to the --ignore-config command-line option." ;
+ }
+
+ initialize-config-module test-config ;
+ local test-config = [ MATCH ^--test-config=(.*)$ : $(.argv) ] ;
+ local uq = [ MATCH \"(.*)\" : $(test-config) ] ;
+ if $(uq)
+ {
+ test-config = $(uq) ;
+ }
+ if $(test-config)
+ {
+ local where =
+ [ load-config test-config : $(test-config:BS) : $(test-config:D) ] ;
+ if $(where)
+ {
+ if $(.debug-config) && ! $(.legacy-ignore-config)
+ {
+ ECHO "notice: Regular site and user configuration files will" ;
+ ECHO "notice: be ignored due to the test configuration being"
+ "loaded." ;
+ }
+ }
+ else
+ {
+ test-config = ;
+ }
+ }
+
+ local user-path = [ os.home-directories ] [ os.environ BOOST_BUILD_PATH ] ;
+ local site-path = /etc $(user-path) ;
+ if [ os.name ] in NT CYGWIN
+ {
+ site-path = [ modules.peek : SystemRoot ] $(user-path) ;
+ }
+
+ if $(ignore-site-config) && !$(.legacy-ignore-config)
+ {
+ ECHO "notice: Site configuration files will be ignored due to the" ;
+ ECHO "notice: --ignore-site-config command-line option." ;
+ }
+
+ initialize-config-module site-config ;
+ if ! $(test-config) && ! $(ignore-site-config) && ! $(.legacy-ignore-config)
+ {
+ load-config site-config : site-config.jam : $(site-path) ;
+ }
+
+ initialize-config-module user-config ;
+ if ! $(test-config) && ! $(.legacy-ignore-config)
+ {
+ local user-config = [ MATCH ^--user-config=(.*)$ : $(.argv) ] ;
+ user-config = $(user-config[-1]) ;
+ user-config ?= [ os.environ BOOST_BUILD_USER_CONFIG ] ;
+ # Special handling for the case when the OS does not strip the quotes
+ # around the file name, as is the case when using Cygwin bash.
+ user-config = [ utility.unquote $(user-config) ] ;
+ local explicitly-requested = $(user-config) ;
+ user-config ?= user-config.jam ;
+
+ if $(user-config)
+ {
+ if $(explicitly-requested)
+ {
+ # Treat explicitly entered user paths as native OS path
+ # references and, if non-absolute, root them at the current
+ # working directory.
+ user-config = [ path.make $(user-config) ] ;
+ user-config = [ path.root $(user-config) [ path.pwd ] ] ;
+ user-config = [ path.native $(user-config) ] ;
+
+ if $(.debug-config)
+ {
+ ECHO "notice: Loading explicitly specified user"
+ "configuration file:" ;
+ ECHO " $(user-config)" ;
+ }
+
+ load-config user-config : $(user-config:BS) : $(user-config:D)
+ : must-exist ;
+ }
+ else
+ {
+ load-config user-config : $(user-config) : $(user-path) ;
+ }
+ }
+ else if $(.debug-config)
+ {
+ ECHO "notice: User configuration file loading explicitly disabled." ;
+ }
+ }
+
+ # We look for project-config.jam from "." upward.
+ # I am not sure this is 100% right decision, we might as well check for
+ # it only alonside the Jamroot file. However:
+ #
+ # - We need to load project-root.jam before Jamroot
+ # - We probably would need to load project-root.jam even if there's no
+ # Jamroot - e.g. to implement automake-style out-of-tree builds.
+ local file = [ path.glob "." : project-config.jam ] ;
+ if ! $(file)
+ {
+ file = [ path.glob-in-parents "." : project-config.jam ] ;
+ }
+ if $(file)
+ {
+ initialize-config-module project-config : $(file:D) ;
+ load-config project-config : project-config.jam : $(file:D) ;
+ }
+}
+
+
+# Autoconfigure toolsets based on any instances of --toolset=xx,yy,...zz or
+# toolset=xx,yy,...zz in the command line. May return additional properties to
+# be processed as if they had been specified by the user.
+#
+local rule process-explicit-toolset-requests
+{
+ local extra-properties ;
+
+ local option-toolsets = [ regex.split-list [ MATCH ^--toolset=(.*)$ : $(.argv) ] : "," ] ;
+ local feature-toolsets = [ regex.split-list [ MATCH ^toolset=(.*)$ : $(.argv) ] : "," ] ;
+
+ for local t in $(option-toolsets) $(feature-toolsets)
+ {
+ # Parse toolset-version/properties.
+ local (t-v,t,v) = [ MATCH (([^-/]+)-?([^/]+)?)/?.* : $(t) ] ;
+ local toolset-version = $((t-v,t,v)[1]) ;
+ local toolset = $((t-v,t,v)[2]) ;
+ local version = $((t-v,t,v)[3]) ;
+
+ if $(.debug-config)
+ {
+ ECHO notice: [cmdline-cfg] Detected command-line request for
+ $(toolset-version): "toolset=" $(toolset) "version="
+ $(version) ;
+ }
+
+ # If the toolset is not known, configure it now.
+ local known ;
+ if $(toolset) in [ feature.values <toolset> ]
+ {
+ known = true ;
+ }
+ if $(known) && $(version) && ! [ feature.is-subvalue toolset
+ : $(toolset) : version : $(version) ]
+ {
+ known = ;
+ }
+ # TODO: we should do 'using $(toolset)' in case no version has been
+ # specified and there are no versions defined for the given toolset to
+ # allow the toolset to configure its default version. For this we need
+ # to know how to detect whether a given toolset has any versions
+ # defined. An alternative would be to do this whenever version is not
+ # specified but that would require that toolsets correctly handle the
+ # case when their default version is configured multiple times which
+ # should be checked for all existing toolsets first.
+
+ if ! $(known)
+ {
+ if $(.debug-config)
+ {
+ ECHO "notice: [cmdline-cfg] toolset $(toolset-version) not"
+ "previously configured; attempting to auto-configure now" ;
+ }
+ toolset.using $(toolset) : $(version) ;
+ }
+ else
+ {
+ if $(.debug-config)
+ {
+ ECHO notice: [cmdline-cfg] toolset $(toolset-version) already
+ configured ;
+ }
+ }
+
+ # Make sure we get an appropriate property into the build request in
+ # case toolset has been specified using the "--toolset=..." command-line
+ # option form.
+ if ! $(t) in $(.argv) && ! $(t) in $(feature-toolsets)
+ {
+ if $(.debug-config)
+ {
+ ECHO notice: [cmdline-cfg] adding toolset=$(t) to the build
+ request. ;
+ }
+ extra-properties += toolset=$(t) ;
+ }
+ }
+
+ return $(extra-properties) ;
+}
+
+
+# Returns 'true' if the given 'project' is equal to or is a (possibly indirect)
+# child to any of the projects requested to be cleaned in this build system run.
+# Returns 'false' otherwise. Expects the .project-targets list to have already
+# been constructed.
+#
+local rule should-clean-project ( project )
+{
+ if ! $(.should-clean-project.$(project))
+ {
+ local r = false ;
+ if $(project) in $(.project-targets)
+ {
+ r = true ;
+ }
+ else
+ {
+ local parent = [ project.attribute $(project) parent-module ] ;
+ if $(parent) && $(parent) != user-config
+ {
+ r = [ should-clean-project $(parent) ] ;
+ }
+ }
+ .should-clean-project.$(project) = $(r) ;
+ }
+
+ return $(.should-clean-project.$(project)) ;
+}
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+{
+ if --version in $(.argv)
+ {
+ version.print ;
+ EXIT ;
+ }
+
+ version.verify-engine-version ;
+
+ load-configuration-files ;
+
+ local extra-properties ;
+ # Note that this causes --toolset options to be ignored if --ignore-config
+ # is specified.
+ if ! $(.legacy-ignore-config)
+ {
+ extra-properties = [ process-explicit-toolset-requests ] ;
+ }
+
+
+ # We always load project in "." so that 'use-project' directives have any
+ # chance of being seen. Otherwise, we would not be able to refer to
+ # subprojects using target ids.
+ local current-project ;
+ if [ project.find "." : "." ]
+ {
+ current-project = [ project.target [ project.load "." ] ] ;
+ }
+
+
+ # In case there are no toolsets currently defined makes the build run using
+ # the default toolset.
+ if ! $(.legacy-ignore-config) && ! [ feature.values <toolset> ]
+ {
+ local default-toolset = $(.default-toolset) ;
+ local default-toolset-version = ;
+ if $(default-toolset)
+ {
+ default-toolset-version = $(.default-toolset-version) ;
+ }
+ else
+ {
+ default-toolset = gcc ;
+ if [ os.name ] = NT
+ {
+ default-toolset = msvc ;
+ }
+ else if [ os.name ] = MACOSX
+ {
+ default-toolset = darwin ;
+ }
+ }
+
+ ECHO "warning: No toolsets are configured." ;
+ ECHO "warning: Configuring default toolset" \"$(default-toolset)\". ;
+ ECHO "warning: If the default is wrong, your build may not work correctly." ;
+ ECHO "warning: Use the \"toolset=xxxxx\" option to override our guess." ;
+ ECHO "warning: For more configuration options, please consult" ;
+ ECHO "warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" ;
+
+ toolset.using $(default-toolset) : $(default-toolset-version) ;
+ }
+
+
+ # Parse command line for targets and properties. Note that this requires
+ # that all project files already be loaded.
+ local build-request = [ build-request.from-command-line $(.argv)
+ $(extra-properties) ] ;
+ local target-ids = [ $(build-request).get-at 1 ] ;
+ local properties = [ $(build-request).get-at 2 ] ;
+
+
+ # Expand properties specified on the command line into multiple property
+ # sets consisting of all legal property combinations. Each expanded property
+ # set will be used for a single build run. E.g. if multiple toolsets are
+ # specified then requested targets will be built with each of them.
+ if $(properties)
+ {
+ expanded = [ build-request.expand-no-defaults $(properties) ] ;
+ local xexpanded ;
+ for local e in $(expanded)
+ {
+ xexpanded += [ property-set.create [ feature.split $(e) ] ] ;
+ }
+ expanded = $(xexpanded) ;
+ }
+ else
+ {
+ expanded = [ property-set.empty ] ;
+ }
+
+
+ # Check that we actually found something to build.
+ if ! $(current-project) && ! $(target-ids)
+ {
+ errors.user-error "error: no Jamfile in current directory found, and no"
+ "target references specified." ;
+ EXIT ;
+ }
+
+
+ # Flags indicating that this build system run has been started in order to
+ # clean existing instead of create new targets. Note that these are not the
+ # final flag values as they may get changed later on due to some special
+ # targets being specified on the command line.
+ local clean ; if "--clean" in $(.argv) { clean = true ; }
+ local cleanall ; if "--clean-all" in $(.argv) { cleanall = true ; }
+
+
+ # List of explicitly requested files to build. Any target references read
+ # from the command line parameter not recognized as one of the targets
+ # defined in the loaded Jamfiles will be interpreted as an explicitly
+ # requested file to build. If any such files are explicitly requested then
+ # only those files and the targets they depend on will be built and they
+ # will be searched for among targets that would have been built had there
+ # been no explicitly requested files.
+ local explicitly-requested-files
+
+
+ # List of Boost Build meta-targets, virtual-targets and actual Jam targets
+ # constructed in this build system run.
+ local targets ;
+ local virtual-targets ;
+ local actual-targets ;
+
+
+ # Process each target specified on the command-line and convert it into
+ # internal Boost Build target objects. Detect special clean target. If no
+ # main Boost Build targets were explictly requested use the current project
+ # as the target.
+ for local id in $(target-ids)
+ {
+ if $(id) = clean
+ {
+ clean = true ;
+ }
+ else
+ {
+ local t ;
+ if $(current-project)
+ {
+ t = [ $(current-project).find $(id) : no-error ] ;
+ }
+ else
+ {
+ t = [ find-target $(id) ] ;
+ }
+
+ if ! $(t)
+ {
+ ECHO "notice: could not find main target" $(id) ;
+ ECHO "notice: assuming it is a name of file to create." ;
+ explicitly-requested-files += $(id) ;
+ }
+ else
+ {
+ targets += $(t) ;
+ }
+ }
+ }
+ if ! $(targets)
+ {
+ targets += [ project.target [ project.module-name "." ] ] ;
+ }
+
+ if [ option.get dump-generators : : true ]
+ {
+ generators.dump ;
+ }
+
+ # We wish to put config.log in the build directory corresponding
+ # to Jamroot, so that the location does not differ depending on
+ # directory where we do build. The amount of indirection necessary
+ # here is scary.
+ local first-project = [ $(targets[0]).project ] ;
+ local first-project-root-location = [ $(first-project).get project-root ] ;
+ local first-project-root-module = [ project.load $(first-project-root-location) ] ;
+ local first-project-root = [ project.target $(first-project-root-module) ] ;
+ local first-build-build-dir = [ $(first-project-root).build-dir ] ;
+ configure.set-log-file $(first-build-build-dir)/config.log ;
+
+ # Now that we have a set of targets to build and a set of property sets to
+ # build the targets with, we can start the main build process by using each
+ # property set to generate virtual targets from all of our listed targets
+ # and any of their dependants.
+ for local p in $(expanded)
+ {
+ .command-line-free-features = [ property-set.create [ $(p).free ] ] ;
+ for local t in $(targets)
+ {
+ local g = [ $(t).generate $(p) ] ;
+ if ! [ class.is-a $(t) : project-target ]
+ {
+ .results-of-main-targets += $(g[2-]) ;
+ }
+ virtual-targets += $(g[2-]) ;
+ }
+ }
+
+
+ # Convert collected virtual targets into actual raw Jam targets.
+ for t in $(virtual-targets)
+ {
+ actual-targets += [ $(t).actualize ] ;
+ }
+
+
+ # If XML data output has been requested prepare additional rules and targets
+ # so we can hook into Jam to collect build data while its building and have
+ # it trigger the final XML report generation after all the planned targets
+ # have been built.
+ if $(.out-xml)
+ {
+ # Get a qualified virtual target name.
+ rule full-target-name ( target )
+ {
+ local name = [ $(target).name ] ;
+ local project = [ $(target).project ] ;
+ local project-path = [ $(project).get location ] ;
+ return $(project-path)//$(name) ;
+ }
+
+ # Generate an XML file containing build statistics for each constituent.
+ #
+ rule out-xml ( xml-file : constituents * )
+ {
+ # Prepare valid XML header and footer with some basic info.
+ local nl = "
+" ;
+ local os = [ modules.peek : OS OSPLAT JAMUNAME ] "" ;
+ local timestamp = [ modules.peek : JAMDATE ] ;
+ local cwd = [ PWD ] ;
+ local command = $(.argv) ;
+ local bb-version = [ version.boost-build ] ;
+ .header on $(xml-file) =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "$(nl)<build format=\"1.0\" version=\"$(bb-version)\">"
+ "$(nl) <os name=\"$(os[1])\" platform=\"$(os[2])\"><![CDATA[$(os[3-]:J= )]]></os>"
+ "$(nl) <timestamp><![CDATA[$(timestamp)]]></timestamp>"
+ "$(nl) <directory><![CDATA[$(cwd)]]></directory>"
+ "$(nl) <command><![CDATA[\"$(command:J=\" \")\"]]></command>"
+ ;
+ .footer on $(xml-file) =
+ "$(nl)</build>" ;
+
+ # Generate the target dependency graph.
+ .contents on $(xml-file) +=
+ "$(nl) <targets>" ;
+ for local t in [ virtual-target.all-targets ]
+ {
+ local action = [ $(t).action ] ;
+ if $(action)
+ # If a target has no action, it has no dependencies.
+ {
+ local name = [ full-target-name $(t) ] ;
+ local sources = [ $(action).sources ] ;
+ local dependencies ;
+ for local s in $(sources)
+ {
+ dependencies += [ full-target-name $(s) ] ;
+ }
+
+ local path = [ $(t).path ] ;
+ local jam-target = [ $(t).actual-name ] ;
+
+ .contents on $(xml-file) +=
+ "$(nl) <target>"
+ "$(nl) <name><![CDATA[$(name)]]></name>"
+ "$(nl) <dependencies>"
+ "$(nl) <dependency><![CDATA[$(dependencies)]]></dependency>"
+ "$(nl) </dependencies>"
+ "$(nl) <path><![CDATA[$(path)]]></path>"
+ "$(nl) <jam-target><![CDATA[$(jam-target)]]></jam-target>"
+ "$(nl) </target>"
+ ;
+ }
+ }
+ .contents on $(xml-file) +=
+ "$(nl) </targets>" ;
+
+ # Build $(xml-file) after $(constituents). Do so even if a
+ # constituent action fails and regenerate the xml on every bjam run.
+ INCLUDES $(xml-file) : $(constituents) ;
+ ALWAYS $(xml-file) ;
+ __ACTION_RULE__ on $(xml-file) = build-system.out-xml.generate-action ;
+ out-xml.generate $(xml-file) ;
+ }
+
+ # The actual build actions are here; if we did this work in the actions
+ # clause we would have to form a valid command line containing the
+ # result of @(...) below (the name of the XML file).
+ #
+ rule out-xml.generate-action ( args * : xml-file
+ : command status start end user system : output ? )
+ {
+ local contents =
+ [ on $(xml-file) return $(.header) $(.contents) $(.footer) ] ;
+ local f = @($(xml-file):E=$(contents)) ;
+ }
+
+ # Nothing to do here; the *real* actions happen in
+ # out-xml.generate-action.
+ actions quietly out-xml.generate { }
+
+ # Define the out-xml file target, which depends on all the targets so
+ # that it runs the collection after the targets have run.
+ out-xml $(.out-xml) : $(actual-targets) ;
+
+ # Set up a global __ACTION_RULE__ that records all the available
+ # statistics about each actual target in a variable "on" the --out-xml
+ # target.
+ #
+ rule out-xml.collect ( xml-file : target : command status start end user
+ system : output ? )
+ {
+ local nl = "
+" ;
+ # Open the action with some basic info.
+ .contents on $(xml-file) +=
+ "$(nl) <action status=\"$(status)\" start=\"$(start)\" end=\"$(end)\" user=\"$(user)\" system=\"$(system)\">" ;
+
+ # If we have an action object we can print out more detailed info.
+ local action = [ on $(target) return $(.action) ] ;
+ if $(action)
+ {
+ local action-name = [ $(action).action-name ] ;
+ local action-sources = [ $(action).sources ] ;
+ local action-props = [ $(action).properties ] ;
+
+ # The qualified name of the action which we created the target.
+ .contents on $(xml-file) +=
+ "$(nl) <name><![CDATA[$(action-name)]]></name>" ;
+
+ # The sources that made up the target.
+ .contents on $(xml-file) +=
+ "$(nl) <sources>" ;
+ for local source in $(action-sources)
+ {
+ local source-actual = [ $(source).actual-name ] ;
+ .contents on $(xml-file) +=
+ "$(nl) <source><![CDATA[$(source-actual)]]></source>" ;
+ }
+ .contents on $(xml-file) +=
+ "$(nl) </sources>" ;
+
+ # The properties that define the conditions under which the
+ # target was built.
+ .contents on $(xml-file) +=
+ "$(nl) <properties>" ;
+ for local prop in [ $(action-props).raw ]
+ {
+ local prop-name = [ MATCH ^<(.*)>$ : $(prop:G) ] ;
+ .contents on $(xml-file) +=
+ "$(nl) <property name=\"$(prop-name)\"><![CDATA[$(prop:G=)]]></property>" ;
+ }
+ .contents on $(xml-file) +=
+ "$(nl) </properties>" ;
+ }
+
+ local locate = [ on $(target) return $(LOCATE) ] ;
+ locate ?= "" ;
+ .contents on $(xml-file) +=
+ "$(nl) <jam-target><![CDATA[$(target)]]></jam-target>"
+ "$(nl) <path><![CDATA[$(target:G=:R=$(locate))]]></path>"
+ "$(nl) <command><![CDATA[$(command)]]></command>"
+ "$(nl) <output><![CDATA[$(output)]]></output>" ;
+ .contents on $(xml-file) +=
+ "$(nl) </action>" ;
+ }
+
+ # When no __ACTION_RULE__ is set "on" a target, the search falls back to
+ # the global module.
+ module
+ {
+ __ACTION_RULE__ = build-system.out-xml.collect
+ [ modules.peek build-system : .out-xml ] ;
+ }
+
+ IMPORT
+ build-system :
+ out-xml.collect
+ out-xml.generate-action
+ : :
+ build-system.out-xml.collect
+ build-system.out-xml.generate-action
+ ;
+ }
+
+ local j = [ option.get jobs ] ;
+ if $(j)
+ {
+ modules.poke : PARALLELISM : $(j) ;
+ }
+
+ local k = [ option.get keep-going : true : true ] ;
+ if $(k) in "on" "yes" "true"
+ {
+ modules.poke : KEEP_GOING : 1 ;
+ }
+ else if $(k) in "off" "no" "false"
+ {
+ modules.poke : KEEP_GOING : 0 ;
+ }
+ else
+ {
+ ECHO "error: Invalid value for the --keep-going option" ;
+ EXIT ;
+ }
+
+ # The 'all' pseudo target is not strictly needed expect in the case when we
+ # use it below but people often assume they always have this target
+ # available and do not declare it themselves before use which may cause
+ # build failures with an error message about not being able to build the
+ # 'all' target.
+ NOTFILE all ;
+
+ # And now that all the actual raw Jam targets and all the dependencies
+ # between them have been prepared all that is left is to tell Jam to update
+ # those targets.
+ if $(explicitly-requested-files)
+ {
+ # Note that this case can not be joined with the regular one when only
+ # exact Boost Build targets are requested as here we do not build those
+ # requested targets but only use them to construct the dependency tree
+ # needed to build the explicitly requested files.
+ UPDATE $(explicitly-requested-files:G=e) $(.out-xml) ;
+ }
+ else if $(cleanall)
+ {
+ UPDATE clean-all ;
+ }
+ else if $(clean)
+ {
+ common.Clean clean : [ actual-clean-targets ] ;
+ UPDATE clean ;
+ }
+ else
+ {
+ configure.print-configure-checks-summary ;
+
+ if $(.pre-build-hook)
+ {
+ $(.pre-build-hook) ;
+ }
+
+ DEPENDS all : $(actual-targets) ;
+ if UPDATE_NOW in [ RULENAMES ]
+ {
+ local ok = [ UPDATE_NOW all $(.out-xml) ] ;
+ if $(.post-build-hook)
+ {
+ $(.post-build-hook) $(ok) ;
+ }
+ # Prevent automatic update of the 'all' target, now that
+ # we have explicitly updated what we wanted.
+ UPDATE ;
+ }
+ else
+ {
+ UPDATE all $(.out-xml) ;
+ }
+ }
+}
diff --git a/tools/build/v2/build/__init__.py b/tools/build/v2/build/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/build/__init__.py
diff --git a/tools/build/v2/build/ac.jam b/tools/build/v2/build/ac.jam
new file mode 100644
index 0000000000..6768f358c2
--- /dev/null
+++ b/tools/build/v2/build/ac.jam
@@ -0,0 +1,198 @@
+# Copyright (c) 2010 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import property-set ;
+import path ;
+import modules ;
+import "class" ;
+import errors ;
+import configure ;
+
+rule find-include-path ( variable : properties : header
+ : provided-path ? )
+{
+ # FIXME: document which properties affect this function by
+ # default.
+ local target-os = [ $(properties).get <target-os> ] ;
+ properties = [ property-set.create <target-os>$(toolset) ] ;
+ if $($(variable)-$(properties))
+ {
+ return $($(variable)-$(properties)) ;
+ }
+ else
+ {
+ provided-path ?= [ modules.peek : $(variable) ] ;
+ includes = $(provided-path) ;
+ includes += [ $(properties).get <include> ] ;
+ if [ $(properties).get <target-os> ] != windows
+ {
+ # FIXME: use sysroot
+ includes += /usr/include ;
+ }
+
+ local result ;
+ while ! $(result) && $(includes)
+ {
+ local f = [ path.root $(header) $(includes[1]) ] ;
+ ECHO "Checking " $(f) ;
+ if [ path.exists $(f) ]
+ {
+ result = $(includes[1]) ;
+ }
+ else if $(provided-path)
+ {
+ errors.user-error "Could not find header" $(header)
+ : "in the user-specified directory" $(provided-path) ;
+ }
+ includes = $(includes[2-]) ;
+ }
+ $(variable)-$(properties) = $(result) ;
+ return $(result) ;
+ }
+}
+
+rule find-library ( variable : properties : names + : provided-path ? )
+{
+ local target-os = [ $(properties).get <target-os> ] ;
+ properties = [ property-set.create <target-os>$(toolset) ] ;
+ if $($(variable)-$(properties))
+ {
+ return $($(variable)-$(properties)) ;
+ }
+ else
+ {
+ provided-path ?= [ modules.peek : $(variable) ] ;
+ paths = $(provided-path) ;
+ paths += [ $(properties).get <library-path> ] ;
+ if [ $(properties).get <target-os> ] != windows
+ {
+ paths += /usr/lib /usr/lib32 /usr/lib64 ;
+ }
+
+ local result ;
+ while ! $(result) && $(paths)
+ {
+ while ! $(result) && $(names)
+ {
+ local f ;
+ if $(target-os) = windows
+ {
+ f = $(paths[1])/$(names[1]).lib ;
+ if [ path.exists $(f) ]
+ {
+ result = $(f) ;
+ }
+ }
+ else
+ {
+ # FIXME: check for .a as well, depending on
+ # the 'link' feature.
+ f = $(paths[1])/lib$(names[1]).so ;
+ ECHO "CHECKING $(f) " ;
+ if [ path.exists $(f) ]
+ {
+ result = $(f) ;
+ }
+ }
+ if ! $(result) && $(provided-path)
+ {
+ errors.user-error "Could not find either of: " $(names)
+ : "in the user-specified directory" $(provided-path) ;
+
+ }
+ names = $(names[2-]) ;
+ }
+ paths = $(paths[2-]) ;
+ }
+ $(variable)-$(properties) = $(result) ;
+ return $(result) ;
+ }
+}
+
+class ac-library : basic-target
+{
+ import errors ;
+ import indirect ;
+ import virtual-target ;
+ import ac ;
+ import configure ;
+
+ rule __init__ ( name : project : * : * )
+ {
+ basic-target.__init__ $(name) : $(project) : $(sources)
+ : $(requirements) ;
+
+ reconfigure $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule set-header ( header )
+ {
+ self.header = $(header) ;
+ }
+
+ rule set-default-names ( names + )
+ {
+ self.default-names = $(names) ;
+ }
+
+ rule reconfigure ( * : * )
+ {
+ ECHO "XXX" $(1) ;
+ if ! $(1)
+ {
+ # This is 'using xxx ;'. Nothing to configure, really.
+ }
+ else
+ {
+ for i in 1 2 3 4 5 6 7 8 9
+ {
+ # FIXME: this naming is inconsistent with XXX_INCLUDE/XXX_LIBRARY
+ if ! ( $($(i)[1]) in root include-path library-path library-name condition )
+ {
+ errors.user-error "Invalid named parameter" $($(i)[1]) ;
+ }
+ local name = $($(i)[1]) ;
+ local value = $($(i)[2-]) ;
+ if $($(name)) && $($(name)) != $(value)
+ {
+ errors.user-error "Attempt to change value of '$(name)'" ;
+ }
+ $(name) = $(value) ;
+ }
+
+ include-path ?= $(root)/include ;
+ library-path ?= $(root)/lib ;
+ }
+ }
+
+ rule construct ( name : sources * : property-set )
+ {
+ # FIXME: log results.
+ local libnames = $(library-name) ;
+ if ! $(libnames) && ! $(include-path) && ! $(library-path)
+ {
+ libnames = [ modules.peek : $(name:U)_NAME ] ;
+ # Backward compatibility only.
+ libnames ?= [ modules.peek : $(name:U)_BINARY ] ;
+ }
+ libnames ?= $(self.default-names) ;
+
+ local includes = [
+ ac.find-include-path $(name:U)_INCLUDE : $(property-set) : $(self.header) : $(include-path) ] ;
+ local library = [ ac.find-library $(name:U)_LIBRARY : $(property-set) : $(libnames) : $(library-path) ] ;
+ if $(includes) && $(library)
+ {
+ library = [ virtual-target.from-file $(library) : . : $(self.project) ] ;
+ configure.log-library-search-result $(name) : "found" ;
+ return [ property-set.create <include>$(includes) <source>$(library) ] ;
+ }
+ else
+ {
+ configure.log-library-search-result $(name) : "no found" ;
+ }
+ }
+}
+
diff --git a/tools/build/v2/build/alias.jam b/tools/build/v2/build/alias.jam
new file mode 100644
index 0000000000..48019cb988
--- /dev/null
+++ b/tools/build/v2/build/alias.jam
@@ -0,0 +1,73 @@
+# Copyright 2003, 2004, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This module defines the 'alias' rule and the associated target class.
+#
+# Alias is just a main target which returns its source targets without any
+# processing. For example:
+#
+# alias bin : hello test_hello ;
+# alias lib : helpers xml_parser ;
+#
+# Another important use of 'alias' is to conveniently group source files:
+#
+# alias platform-src : win.cpp : <os>NT ;
+# alias platform-src : linux.cpp : <os>LINUX ;
+# exe main : main.cpp platform-src ;
+#
+# Lastly, it is possible to create a local alias for some target, with different
+# properties:
+#
+# alias big_lib : : @/external_project/big_lib/<link>static ;
+#
+
+import "class" : new ;
+import project ;
+import property-set ;
+import targets ;
+
+
+class alias-target-class : basic-target
+{
+ rule __init__ ( name : project : sources * : requirements *
+ : default-build * : usage-requirements * )
+ {
+ basic-target.__init__ $(name) : $(project) : $(sources) :
+ $(requirements) : $(default-build) : $(usage-requirements) ;
+ }
+
+ rule construct ( name : source-targets * : property-set )
+ {
+ return [ property-set.empty ] $(source-targets) ;
+ }
+
+ rule compute-usage-requirements ( subvariant )
+ {
+ local base = [ basic-target.compute-usage-requirements $(subvariant) ] ;
+ return [ $(base).add [ $(subvariant).sources-usage-requirements ] ] ;
+ }
+}
+
+
+# Declares the 'alias' target. It will process its sources virtual-targets by
+# returning them unaltered as its own constructed virtual-targets.
+#
+rule alias ( name : sources * : requirements * : default-build * :
+ usage-requirements * )
+{
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new alias-target-class $(name) : $(project)
+ : [ targets.main-target-sources $(sources) : $(name) : no-renaming ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project)
+ ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) :
+ $(project) ]
+ ] ;
+}
+
+
+IMPORT $(__name__) : alias : : alias ;
diff --git a/tools/build/v2/build/alias.py b/tools/build/v2/build/alias.py
new file mode 100755
index 0000000000..575e53609d
--- /dev/null
+++ b/tools/build/v2/build/alias.py
@@ -0,0 +1,63 @@
+# Copyright 2003, 2004, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Status: ported (danielw)
+# Base revision: 56043
+
+# This module defines the 'alias' rule and associated class.
+#
+# Alias is just a main target which returns its source targets without any
+# processing. For example::
+#
+# alias bin : hello test_hello ;
+# alias lib : helpers xml_parser ;
+#
+# Another important use of 'alias' is to conveniently group source files::
+#
+# alias platform-src : win.cpp : <os>NT ;
+# alias platform-src : linux.cpp : <os>LINUX ;
+# exe main : main.cpp platform-src ;
+#
+# Lastly, it's possible to create local alias for some target, with different
+# properties::
+#
+# alias big_lib : : @/external_project/big_lib/<link>static ;
+#
+
+import targets
+import property_set
+from b2.manager import get_manager
+
+from b2.util import metatarget
+
+class AliasTarget(targets.BasicTarget):
+
+ def __init__(self, *args):
+ targets.BasicTarget.__init__(self, *args)
+
+ def construct(self, name, source_targets, properties):
+ return [property_set.empty(), source_targets]
+
+ def compute_usage_requirements(self, subvariant):
+ base = targets.BasicTarget.compute_usage_requirements(self, subvariant)
+ # Add source's usage requirement. If we don't do this, "alias" does not
+ # look like 100% alias.
+ return base.add(subvariant.sources_usage_requirements())
+
+@metatarget
+def alias(name, sources=[], requirements=[], default_build=[], usage_requirements=[]):
+
+ project = get_manager().projects().current()
+ targets = get_manager().targets()
+
+ targets.main_target_alternative(AliasTarget(
+ name, project,
+ targets.main_target_sources(sources, name, no_renaming=True),
+ targets.main_target_requirements(requirements or [], project),
+ targets.main_target_default_build(default_build, project),
+ targets.main_target_usage_requirements(usage_requirements or [], project)))
+
+# Declares the 'alias' target. It will build sources, and return them unaltered.
+get_manager().projects().add_rule("alias", alias)
+
diff --git a/tools/build/v2/build/build-request.jam b/tools/build/v2/build/build-request.jam
new file mode 100644
index 0000000000..8a1f7b0ebe
--- /dev/null
+++ b/tools/build/v2/build/build-request.jam
@@ -0,0 +1,322 @@
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import "class" : new ;
+import sequence ;
+import set ;
+import regex ;
+import feature ;
+import property ;
+import container ;
+import string ;
+
+
+# Transform property-set by applying f to each component property.
+#
+local rule apply-to-property-set ( f property-set )
+{
+ local properties = [ feature.split $(property-set) ] ;
+ return [ string.join [ $(f) $(properties) ] : / ] ;
+}
+
+
+# Expand the given build request by combining all property-sets which do not
+# specify conflicting non-free features. Expects all the project files to
+# already be loaded.
+#
+rule expand-no-defaults ( property-sets * )
+{
+ # First make all features and subfeatures explicit.
+ local expanded-property-sets = [ sequence.transform apply-to-property-set
+ feature.expand-subfeatures : $(property-sets) ] ;
+
+ # Now combine all of the expanded property-sets
+ local product = [ x-product $(expanded-property-sets) : $(feature-space) ] ;
+
+ return $(product) ;
+}
+
+
+# Implementation of x-product, below. Expects all the project files to already
+# be loaded.
+#
+local rule x-product-aux ( property-sets + )
+{
+ local result ;
+ local p = [ feature.split $(property-sets[1]) ] ;
+ local f = [ set.difference $(p:G) : [ feature.free-features ] ] ;
+ local seen ;
+ # No conflict with things used at a higher level?
+ if ! [ set.intersection $(f) : $(x-product-used) ]
+ {
+ local x-product-seen ;
+ {
+ # Do not mix in any conflicting features.
+ local x-product-used = $(x-product-used) $(f) ;
+
+ if $(property-sets[2])
+ {
+ local rest = [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ;
+ result = $(property-sets[1])/$(rest) ;
+ }
+
+ result ?= $(property-sets[1]) ;
+ }
+
+ # If we did not encounter a conflicting feature lower down, do not
+ # recurse again.
+ if ! [ set.intersection $(f) : $(x-product-seen) ]
+ {
+ property-sets = ;
+ }
+
+ seen = $(x-product-seen) ;
+ }
+
+ if $(property-sets[2])
+ {
+ result += [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ;
+ }
+
+ # Note that we have seen these features so that higher levels will recurse
+ # again without them set.
+ x-product-seen += $(f) $(seen) ;
+ return $(result) ;
+}
+
+
+# Return the cross-product of all elements of property-sets, less any that would
+# contain conflicting values for single-valued features. Expects all the project
+# files to already be loaded.
+#
+local rule x-product ( property-sets * )
+{
+ if $(property-sets).non-empty
+ {
+ # Prepare some "scoped globals" that can be used by the implementation
+ # function, x-product-aux.
+ local x-product-seen x-product-used ;
+ return [ x-product-aux $(property-sets) : $(feature-space) ] ;
+ }
+ # Otherwise return empty.
+}
+
+
+# Returns true if either 'v' or the part of 'v' before the first '-' symbol is
+# an implicit value. Expects all the project files to already be loaded.
+#
+local rule looks-like-implicit-value ( v )
+{
+ if [ feature.is-implicit-value $(v) ]
+ {
+ return true ;
+ }
+ else
+ {
+ local split = [ regex.split $(v) - ] ;
+ if [ feature.is-implicit-value $(split[1]) ]
+ {
+ return true ;
+ }
+ }
+}
+
+
+# Takes the command line tokens (such as taken from the ARGV rule) and
+# constructs a build request from them. Returns a vector of two vectors (where
+# "vector" means container.jam's "vector"). First is the set of targets
+# specified in the command line, and second is the set of requested build
+# properties. Expects all the project files to already be loaded.
+#
+rule from-command-line ( command-line * )
+{
+ local targets ;
+ local properties ;
+
+ command-line = $(command-line[2-]) ;
+ local skip-next = ;
+ for local e in $(command-line)
+ {
+ if $(skip-next)
+ {
+ skip-next = ;
+ }
+ else if ! [ MATCH "^(-).*" : $(e) ]
+ {
+ # Build request spec either has "=" in it or completely consists of
+ # implicit feature values.
+ local fs = feature-space ;
+ if [ MATCH "(.*=.*)" : $(e) ]
+ || [ looks-like-implicit-value $(e:D=) : $(feature-space) ]
+ {
+ properties += [ convert-command-line-element $(e) :
+ $(feature-space) ] ;
+ }
+ else
+ {
+ targets += $(e) ;
+ }
+ }
+ else if [ MATCH "^(-[-ldjfsto])$" : $(e) ]
+ {
+ skip-next = true ;
+ }
+ }
+ return [ new vector
+ [ new vector $(targets) ]
+ [ new vector $(properties) ] ] ;
+}
+
+
+# Converts one element of command line build request specification into internal
+# form. Expects all the project files to already be loaded.
+#
+local rule convert-command-line-element ( e )
+{
+ local result ;
+ local parts = [ regex.split $(e) "/" ] ;
+ while $(parts)
+ {
+ local p = $(parts[1]) ;
+ local m = [ MATCH "([^=]*)=(.*)" : $(p) ] ;
+ local lresult ;
+ local feature ;
+ local values ;
+ if $(m)
+ {
+ feature = $(m[1]) ;
+ values = [ regex.split $(m[2]) "," ] ;
+ lresult = <$(feature)>$(values) ;
+ }
+ else
+ {
+ lresult = [ regex.split $(p) "," ] ;
+ }
+
+ if $(feature) && free in [ feature.attributes $(feature) ]
+ {
+ # If we have free feature, then the value is everything
+ # until the end of the command line token. Slashes in
+ # the following string are not taked to mean separation
+ # of properties. Commas are also not interpreted specially.
+ values = $(values:J=,) ;
+ values = $(values) $(parts[2-]) ;
+ values = $(values:J=/) ;
+ lresult = <$(feature)>$(values) ;
+ parts = ;
+ }
+
+ if ! [ MATCH (.*-.*) : $(p) ]
+ {
+ # property.validate cannot handle subfeatures, so we avoid the check
+ # here.
+ for local p in $(lresult)
+ {
+ property.validate $(p) : $(feature-space) ;
+ }
+ }
+
+ if ! $(result)
+ {
+ result = $(lresult) ;
+ }
+ else
+ {
+ result = $(result)/$(lresult) ;
+ }
+
+ parts = $(parts[2-]) ;
+ }
+
+ return $(result) ;
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+ import feature ;
+
+ feature.prepare-test build-request-test-temp ;
+
+ import build-request ;
+ import build-request : expand-no-defaults : build-request.expand-no-defaults ;
+ import errors : try catch ;
+ import feature : feature subfeature ;
+
+ feature toolset : gcc msvc borland : implicit ;
+ subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4
+ 3.0 3.0.1 3.0.2 : optional ;
+
+ feature variant : debug release : implicit composite ;
+ feature inlining : on off ;
+ feature "include" : : free ;
+
+ feature stdlib : native stlport : implicit ;
+
+ feature runtime-link : dynamic static : symmetric ;
+
+ # Empty build requests should expand to empty.
+ assert.result
+ : build-request.expand-no-defaults ;
+
+ assert.result
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug
+ <toolset>msvc/<stdlib>stlport/<variant>debug
+ <toolset>msvc/<variant>debug
+ : build-request.expand-no-defaults gcc-3.0.1/stlport msvc/stlport msvc debug ;
+
+ assert.result
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug
+ <toolset>msvc/<variant>debug
+ <variant>debug/<toolset>msvc/<stdlib>stlport
+ : build-request.expand-no-defaults gcc-3.0.1/stlport msvc debug msvc/stlport ;
+
+ assert.result
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug/<inlining>off
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>release/<inlining>off
+ : build-request.expand-no-defaults gcc-3.0.1/stlport debug release <inlining>off ;
+
+ assert.result
+ <include>a/b/c/<toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug/<include>x/y/z
+ <include>a/b/c/<toolset>msvc/<stdlib>stlport/<variant>debug/<include>x/y/z
+ <include>a/b/c/<toolset>msvc/<variant>debug/<include>x/y/z
+ : build-request.expand-no-defaults <include>a/b/c gcc-3.0.1/stlport msvc/stlport msvc debug <include>x/y/z ;
+
+ local r ;
+
+ r = [ build-request.from-command-line bjam debug runtime-link=dynamic ] ;
+ assert.equal [ $(r).get-at 1 ] : ;
+ assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ;
+
+ try ;
+ {
+ build-request.from-command-line bjam gcc/debug runtime-link=dynamic/static ;
+ }
+ catch \"static\" is not a value of an implicit feature ;
+
+ r = [ build-request.from-command-line bjam -d2 --debug debug target runtime-link=dynamic ] ;
+ assert.equal [ $(r).get-at 1 ] : target ;
+ assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ;
+
+ r = [ build-request.from-command-line bjam debug runtime-link=dynamic,static ] ;
+ assert.equal [ $(r).get-at 1 ] : ;
+ assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic <runtime-link>static ;
+
+ r = [ build-request.from-command-line bjam debug gcc/runtime-link=dynamic,static ] ;
+ assert.equal [ $(r).get-at 1 ] : ;
+ assert.equal [ $(r).get-at 2 ] : debug gcc/<runtime-link>dynamic
+ gcc/<runtime-link>static ;
+
+ r = [ build-request.from-command-line bjam msvc gcc,borland/runtime-link=static ] ;
+ assert.equal [ $(r).get-at 1 ] : ;
+ assert.equal [ $(r).get-at 2 ] : msvc gcc/<runtime-link>static
+ borland/<runtime-link>static ;
+
+ r = [ build-request.from-command-line bjam gcc-3.0 ] ;
+ assert.equal [ $(r).get-at 1 ] : ;
+ assert.equal [ $(r).get-at 2 ] : gcc-3.0 ;
+
+ feature.finish-test build-request-test-temp ;
+}
diff --git a/tools/build/v2/build/build_request.py b/tools/build/v2/build/build_request.py
new file mode 100644
index 0000000000..cc9f2400a9
--- /dev/null
+++ b/tools/build/v2/build/build_request.py
@@ -0,0 +1,216 @@
+# Status: being ported by Vladimir Prus
+# TODO: need to re-compare with mainline of .jam
+# Base revision: 40480
+#
+# (C) Copyright David Abrahams 2002. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+import b2.build.feature
+feature = b2.build.feature
+
+from b2.util.utility import *
+import b2.build.property_set as property_set
+
+def expand_no_defaults (property_sets):
+ """ Expand the given build request by combining all property_sets which don't
+ specify conflicting non-free features.
+ """
+ # First make all features and subfeatures explicit
+ expanded_property_sets = [ps.expand_subfeatures() for ps in property_sets]
+
+ # Now combine all of the expanded property_sets
+ product = __x_product (expanded_property_sets)
+
+ return [property_set.create(p) for p in product]
+
+
+def __x_product (property_sets):
+ """ Return the cross-product of all elements of property_sets, less any
+ that would contain conflicting values for single-valued features.
+ """
+ x_product_seen = set()
+ return __x_product_aux (property_sets, x_product_seen)[0]
+
+def __x_product_aux (property_sets, seen_features):
+ """Returns non-conflicting combinations of property sets.
+
+ property_sets is a list of PropertySet instances. seen_features is a set of Property
+ instances.
+
+ Returns a tuple of:
+ - list of lists of Property instances, such that within each list, no two Property instance
+ have the same feature, and no Property is for feature in seen_features.
+ - set of features we saw in property_sets
+ """
+ if not property_sets:
+ return ([], set())
+
+ properties = property_sets[0].all()
+
+ these_features = set()
+ for p in property_sets[0].non_free():
+ these_features.add(p.feature())
+
+ # Note: the algorithm as implemented here, as in original Jam code, appears to
+ # detect conflicts based on features, not properties. For example, if command
+ # line build request say:
+ #
+ # <a>1/<b>1 c<1>/<b>1
+ #
+ # It will decide that those two property sets conflict, because they both specify
+ # a value for 'b' and will not try building "<a>1 <c1> <b1>", but rather two
+ # different property sets. This is a topic for future fixing, maybe.
+ if these_features & seen_features:
+
+ (inner_result, inner_seen) = __x_product_aux(property_sets[1:], seen_features)
+ return (inner_result, inner_seen | these_features)
+
+ else:
+
+ result = []
+ (inner_result, inner_seen) = __x_product_aux(property_sets[1:], seen_features | these_features)
+ if inner_result:
+ for inner in inner_result:
+ result.append(properties + inner)
+ else:
+ result.append(properties)
+
+ if inner_seen & these_features:
+ # Some of elements in property_sets[1:] conflict with elements of property_sets[0],
+ # Try again, this time omitting elements of property_sets[0]
+ (inner_result2, inner_seen2) = __x_product_aux(property_sets[1:], seen_features)
+ result.extend(inner_result2)
+
+ return (result, inner_seen | these_features)
+
+
+
+def looks_like_implicit_value(v):
+ """Returns true if 'v' is either implicit value, or
+ the part before the first '-' symbol is implicit value."""
+ if feature.is_implicit_value(v):
+ return 1
+ else:
+ split = v.split("-")
+ if feature.is_implicit_value(split[0]):
+ return 1
+
+ return 0
+
+def from_command_line(command_line):
+ """Takes the command line tokens (such as taken from ARGV rule)
+ and constructs build request from it. Returns a list of two
+ lists. First is the set of targets specified in the command line,
+ and second is the set of requested build properties."""
+
+ targets = []
+ properties = []
+
+ for e in command_line:
+ if e[0] != "-":
+ # Build request spec either has "=" in it, or completely
+ # consists of implicit feature values.
+ if e.find("=") != -1 or looks_like_implicit_value(e.split("/")[0]):
+ properties += convert_command_line_element(e)
+ else:
+ targets.append(e)
+
+ return [targets, properties]
+
+# Converts one element of command line build request specification into
+# internal form.
+def convert_command_line_element(e):
+
+ result = None
+ parts = e.split("/")
+ for p in parts:
+ m = p.split("=")
+ if len(m) > 1:
+ feature = m[0]
+ values = m[1].split(",")
+ lresult = [("<%s>%s" % (feature, v)) for v in values]
+ else:
+ lresult = p.split(",")
+
+ if p.find('-') == -1:
+ # FIXME: first port property.validate
+ # property.validate cannot handle subfeatures,
+ # so we avoid the check here.
+ #for p in lresult:
+ # property.validate(p)
+ pass
+
+ if not result:
+ result = lresult
+ else:
+ result = [e1 + "/" + e2 for e1 in result for e2 in lresult]
+
+ return [property_set.create(b2.build.feature.split(r)) for r in result]
+
+###
+### rule __test__ ( )
+### {
+### import assert feature ;
+###
+### feature.prepare-test build-request-test-temp ;
+###
+### import build-request ;
+### import build-request : expand_no_defaults : build-request.expand_no_defaults ;
+### import errors : try catch ;
+### import feature : feature subfeature ;
+###
+### feature toolset : gcc msvc borland : implicit ;
+### subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4
+### 3.0 3.0.1 3.0.2 : optional ;
+###
+### feature variant : debug release : implicit composite ;
+### feature inlining : on off ;
+### feature "include" : : free ;
+###
+### feature stdlib : native stlport : implicit ;
+###
+### feature runtime-link : dynamic static : symmetric ;
+###
+###
+### local r ;
+###
+### r = [ build-request.from-command-line bjam debug runtime-link=dynamic ] ;
+### assert.equal [ $(r).get-at 1 ] : ;
+### assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ;
+###
+### try ;
+### {
+###
+### build-request.from-command-line bjam gcc/debug runtime-link=dynamic/static ;
+### }
+### catch \"static\" is not a value of an implicit feature ;
+###
+###
+### r = [ build-request.from-command-line bjam -d2 --debug debug target runtime-link=dynamic ] ;
+### assert.equal [ $(r).get-at 1 ] : target ;
+### assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ;
+###
+### r = [ build-request.from-command-line bjam debug runtime-link=dynamic,static ] ;
+### assert.equal [ $(r).get-at 1 ] : ;
+### assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic <runtime-link>static ;
+###
+### r = [ build-request.from-command-line bjam debug gcc/runtime-link=dynamic,static ] ;
+### assert.equal [ $(r).get-at 1 ] : ;
+### assert.equal [ $(r).get-at 2 ] : debug gcc/<runtime-link>dynamic
+### gcc/<runtime-link>static ;
+###
+### r = [ build-request.from-command-line bjam msvc gcc,borland/runtime-link=static ] ;
+### assert.equal [ $(r).get-at 1 ] : ;
+### assert.equal [ $(r).get-at 2 ] : msvc gcc/<runtime-link>static
+### borland/<runtime-link>static ;
+###
+### r = [ build-request.from-command-line bjam gcc-3.0 ] ;
+### assert.equal [ $(r).get-at 1 ] : ;
+### assert.equal [ $(r).get-at 2 ] : gcc-3.0 ;
+###
+### feature.finish-test build-request-test-temp ;
+### }
+###
+###
diff --git a/tools/build/v2/build/configure.jam b/tools/build/v2/build/configure.jam
new file mode 100644
index 0000000000..14c1328aff
--- /dev/null
+++ b/tools/build/v2/build/configure.jam
@@ -0,0 +1,237 @@
+# Copyright (c) 2010 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# This module defines function to help with two main tasks:
+#
+# - Discovering build-time configuration for the purposes of adjusting
+# build process.
+# - Reporting what is built, and how it is configured.
+
+import targets ;
+import errors ;
+import targets ;
+import sequence ;
+import property ;
+import property-set ;
+import "class" : new ;
+import common ;
+import path ;
+
+rule log-summary ( )
+{
+
+}
+
+.width = 30 ;
+
+rule set-width ( width )
+{
+ .width = $(width) ;
+}
+
+# Declare that the components specified by the parameter exist.
+rule register-components ( components * )
+{
+ .components += $(components) ;
+}
+
+# Declare that the components specified by the parameters will
+# be build.
+rule components-building ( components * )
+{
+ .built-components += $(components) ;
+}
+
+# Report something about component configuration that the
+# user should better know.
+rule log-component-configuration ( component : message )
+{
+ # FIXME: implement per-property-set logs
+ .component-logs.$(component) += $(message) ;
+}
+
+
+
+rule log-check-result ( result )
+{
+ if ! $(.announced-checks)
+ {
+ ECHO "Performing configuration checks\n" ;
+ .announced-checks = 1 ;
+ }
+
+ ECHO $(result) ;
+ #.check-results += $(result) ;
+}
+
+rule log-library-search-result ( library : result )
+{
+ local x = [ PAD " - $(library) : $(result)" : $(.width) ] ;
+ log-check-result "$(x)" ;
+}
+
+rule print-component-configuration ( )
+{
+ local c = [ sequence.unique $(.components) ] ;
+
+ ECHO "\nComponent configuration:\n" ;
+ for c in $(.components)
+ {
+ local s ;
+ if $(c) in $(.built-components)
+ {
+ s = "building" ;
+ }
+ else
+ {
+ s = "not building" ;
+ }
+ ECHO [ PAD " - $(c)" : $(.width) ] ": $(s)" ;
+ for local m in $(.component-logs.$(c))
+ {
+ ECHO " -" $(m) ;
+ }
+ }
+ ECHO ;
+}
+
+rule print-configure-checks-summary ( )
+{
+ # FIXME: the problem with that approach is tha
+ # the user sees checks summary when all checks are
+ # done, and has no progress reporting while the
+ # checks are being executed.
+ if $(.check-results)
+ {
+ ECHO "Configuration checks summary\n" ;
+
+ for local r in $(.check-results)
+ {
+ ECHO $(r) ;
+ }
+ ECHO ;
+ }
+}
+
+# Attempt to build a metatarget named by 'metatarget-reference'
+# in context of 'project' with properties 'ps'.
+# Returns non-empty value if build is OK.
+rule builds-raw ( metatarget-reference : project : ps : what : retry ? )
+{
+ local result ;
+
+ if ! $(retry) && ! $(.$(what)-tested.$(ps))
+ {
+ .$(what)-tested.$(ps) = true ;
+
+ local targets = [ targets.generate-from-reference
+ $(metatarget-reference) : $(project) : $(ps) ] ;
+
+ local jam-targets ;
+ for local t in $(targets[2-])
+ {
+ jam-targets += [ $(t).actualize ] ;
+ }
+
+ if ! UPDATE_NOW in [ RULENAMES ]
+ {
+ # Cannot determine. Assume existance.
+ }
+ else
+ {
+ local x = [ PAD " - $(what)" : $(.width) ] ;
+ if [ UPDATE_NOW $(jam-targets) :
+ $(.log-fd) : ignore-minus-n : ignore-minus-q ]
+ {
+ .$(what)-supported.$(ps) = yes ;
+ result = true ;
+ log-check-result "$(x) : yes" ;
+ }
+ else
+ {
+ log-check-result "$(x) : no" ;
+ }
+ }
+ return $(result) ;
+ }
+ else
+ {
+ return $(.$(what)-supported.$(ps)) ;
+ }
+}
+
+rule builds ( metatarget-reference : properties * : what ? : retry ? )
+{
+ what ?= "$(metatarget-reference) builds" ;
+
+ # FIXME: this should not be hardcoded. Other checks might
+ # want to consider different set of features as relevant.
+ local toolset = [ property.select <toolset> : $(properties) ] ;
+ local toolset-version-property = "<toolset-$(toolset:G=):version>" ;
+ local relevant = [ property.select <target-os> <toolset> $(toolset-version-property)
+ <address-model> <architecture>
+ : $(properties) ] ;
+ local ps = [ property-set.create $(relevant) ] ;
+ local t = [ targets.current ] ;
+ local p = [ $(t).project ] ;
+
+ return [ builds-raw $(metatarget-reference) : $(p) : $(ps) : $(what) : $(retry) ] ;
+}
+
+
+# Called by Boost.Build startup code to specify name of a file
+# that will receive results of configure checks. This
+# should never be called by users.
+rule set-log-file ( log-file )
+{
+ path.makedirs [ path.parent $(log-file) ] ;
+
+ .log-fd = [ FILE_OPEN $(log-file) : "w" ] ;
+}
+
+# Frontend rules
+
+class check-target-builds-worker
+{
+ import configure ;
+ import property-set ;
+ import targets ;
+ import property ;
+
+ rule __init__ ( target message ? : true-properties * : false-properties * )
+ {
+ self.target = $(target) ;
+ self.message = $(message) ;
+ self.true-properties = $(true-properties) ;
+ self.false-properties = $(false-properties) ;
+ }
+
+ rule check ( properties * )
+ {
+ local choosen ;
+ if [ configure.builds $(self.target) : $(properties) : $(self.message) ]
+ {
+ choosen = $(self.true-properties) ;
+ }
+ else
+ {
+ choosen = $(self.false-properties) ;
+ }
+ return [ property.evaluate-conditionals-in-context $(choosen) : $(properties) ] ;
+ }
+}
+
+
+rule check-target-builds ( target message ? : true-properties * : false-properties * )
+{
+ local instance = [ new check-target-builds-worker $(target) $(message) : $(true-properties)
+ : $(false-properties) ] ;
+ return <conditional>@$(instance).check ;
+}
+
+IMPORT $(__name__) : check-target-builds : : check-target-builds ;
+
+
diff --git a/tools/build/v2/build/configure.py b/tools/build/v2/build/configure.py
new file mode 100644
index 0000000000..0426832c40
--- /dev/null
+++ b/tools/build/v2/build/configure.py
@@ -0,0 +1,164 @@
+# Status: ported.
+# Base revison: 64488
+#
+# Copyright (c) 2010 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# This module defines function to help with two main tasks:
+#
+# - Discovering build-time configuration for the purposes of adjusting
+# build process.
+# - Reporting what is built, and how it is configured.
+
+import b2.build.property as property
+import b2.build.property_set as property_set
+
+import b2.build.targets
+
+from b2.manager import get_manager
+from b2.util.sequence import unique
+from b2.util import bjam_signature, value_to_jam
+
+import bjam
+import os
+
+__width = 30
+
+def set_width(width):
+ global __width
+ __width = 30
+
+__components = []
+__built_components = []
+__component_logs = {}
+__announced_checks = False
+
+__log_file = None
+__log_fd = -1
+
+def register_components(components):
+ """Declare that the components specified by the parameter exist."""
+ __components.extend(components)
+
+def components_building(components):
+ """Declare that the components specified by the parameters will be build."""
+ __built_components.extend(components)
+
+def log_component_configuration(component, message):
+ """Report something about component configuration that the user should better know."""
+ __component_logs.setdefault(component, []).append(message)
+
+def log_check_result(result):
+ global __announced_checks
+ if not __announced_checks:
+ print "Performing configuration checks"
+ __announced_checks = True
+
+ print result
+
+def log_library_search_result(library, result):
+ log_check_result((" - %(library)s : %(result)s" % locals()).rjust(width))
+
+
+def print_component_configuration():
+
+ print "\nComponent configuration:"
+ for c in __components:
+ if c in __built_components:
+ s = "building"
+ else:
+ s = "not building"
+ message = " - %s)" % c
+ message = message.rjust(__width)
+ message += " : " + s
+ for m in __component_logs.get(c, []):
+ print " -" + m
+ print ""
+
+__builds_cache = {}
+
+def builds(metatarget_reference, project, ps, what):
+ # Attempt to build a metatarget named by 'metatarget-reference'
+ # in context of 'project' with properties 'ps'.
+ # Returns non-empty value if build is OK.
+
+ result = []
+
+ existing = __builds_cache.get((what, ps), None)
+ if existing is None:
+
+ result = False
+ __builds_cache[(what, ps)] = False
+
+ targets = b2.build.targets.generate_from_reference(
+ metatarget_reference, project, ps).targets()
+ jam_targets = []
+ for t in targets:
+ jam_targets.append(t.actualize())
+
+ x = (" - %s" % what).rjust(__width)
+ if bjam.call("UPDATE_NOW", jam_targets, str(__log_fd), "ignore-minus-n"):
+ __builds_cache[(what, ps)] = True
+ result = True
+ log_check_result("%s: yes" % x)
+ else:
+ log_check_result("%s: no" % x)
+
+ return result
+ else:
+ return existing
+
+def set_log_file(log_file_name):
+ # Called by Boost.Build startup code to specify name of a file
+ # that will receive results of configure checks. This
+ # should never be called by users.
+ global __log_file, __log_fd
+ dirname = os.path.dirname(log_file_name)
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+ # Make sure to keep the file around, so that it's not
+ # garbage-collected and closed
+ __log_file = open(log_file_name, "w")
+ __log_fd = __log_file.fileno()
+
+# Frontend rules
+
+class CheckTargetBuildsWorker:
+
+ def __init__(self, target, true_properties, false_properties):
+ self.target = target
+ self.true_properties = property.create_from_strings(true_properties, True)
+ self.false_properties = property.create_from_strings(false_properties, True)
+
+ def check(self, ps):
+
+ # FIXME: this should not be hardcoded. Other checks might
+ # want to consider different set of features as relevant.
+ toolset = ps.get('toolset')[0]
+ toolset_version_property = "<toolset-" + toolset + ":version>" ;
+ relevant = ps.get_properties('target-os') + \
+ ps.get_properties("toolset") + \
+ ps.get_properties(toolset_version_property) + \
+ ps.get_properties("address-model") + \
+ ps.get_properties("architecture")
+ rps = property_set.create(relevant)
+ t = get_manager().targets().current()
+ p = t.project()
+ if builds(self.target, p, rps, "%s builds" % self.target):
+ choosen = self.true_properties
+ else:
+ choosen = self.false_properties
+ return property.evaluate_conditionals_in_context(choosen, ps)
+
+@bjam_signature((["target"], ["true_properties", "*"], ["false_properties", "*"]))
+def check_target_builds(target, true_properties, false_properties):
+ worker = CheckTargetBuildsWorker(target, true_properties, false_properties)
+ value = value_to_jam(worker.check)
+ return "<conditional>" + value
+
+get_manager().projects().add_rule("check-target-builds", check_target_builds)
+
+
diff --git a/tools/build/v2/build/engine.py b/tools/build/v2/build/engine.py
new file mode 100644
index 0000000000..be9736e06c
--- /dev/null
+++ b/tools/build/v2/build/engine.py
@@ -0,0 +1,172 @@
+# Copyright Pedro Ferreira 2005.
+# Copyright Vladimir Prus 2007.
+# Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+bjam_interface = __import__('bjam')
+
+import operator
+import re
+
+import b2.build.property_set as property_set
+import b2.util
+
+class BjamAction:
+ """Class representing bjam action defined from Python."""
+
+ def __init__(self, action_name, function):
+ self.action_name = action_name
+ self.function = function
+
+ def __call__(self, targets, sources, property_set):
+ if self.function:
+ self.function(targets, sources, property_set)
+
+ # Bjam actions defined from Python have only the command
+ # to execute, and no associated jam procedural code. So
+ # passing 'property_set' to it is not necessary.
+ bjam_interface.call("set-update-action", self.action_name,
+ targets, sources, [])
+
+class BjamNativeAction:
+ """Class representing bjam action defined by Jam code.
+
+ We still allow to associate a Python callable that will
+ be called when this action is installed on any target.
+ """
+
+ def __init__(self, action_name, function):
+ self.action_name = action_name
+ self.function = function
+
+ def __call__(self, targets, sources, property_set):
+ if self.function:
+ self.function(targets, sources, property_set)
+
+ p = []
+ if property_set:
+ p = property_set.raw()
+
+ b2.util.set_jam_action(self.action_name, targets, sources, p)
+
+action_modifiers = {"updated": 0x01,
+ "together": 0x02,
+ "ignore": 0x04,
+ "quietly": 0x08,
+ "piecemeal": 0x10,
+ "existing": 0x20}
+
+class Engine:
+ """ The abstract interface to a build engine.
+
+ For now, the naming of targets, and special handling of some
+ target variables like SEARCH and LOCATE make this class coupled
+ to bjam engine.
+ """
+ def __init__ (self):
+ self.actions = {}
+
+ def add_dependency (self, targets, sources):
+ """Adds a dependency from 'targets' to 'sources'
+
+ Both 'targets' and 'sources' can be either list
+ of target names, or a single target name.
+ """
+ if isinstance (targets, str):
+ targets = [targets]
+ if isinstance (sources, str):
+ sources = [sources]
+
+ for target in targets:
+ for source in sources:
+ self.do_add_dependency (target, source)
+
+ def set_target_variable (self, targets, variable, value, append=0):
+ """ Sets a target variable.
+
+ The 'variable' will be available to bjam when it decides
+ where to generate targets, and will also be available to
+ updating rule for that 'taret'.
+ """
+ if isinstance (targets, str):
+ targets = [targets]
+
+ for target in targets:
+ self.do_set_target_variable (target, variable, value, append)
+
+ def set_update_action (self, action_name, targets, sources, properties=property_set.empty()):
+ """ Binds a target to the corresponding update action.
+ If target needs to be updated, the action registered
+ with action_name will be used.
+ The 'action_name' must be previously registered by
+ either 'register_action' or 'register_bjam_action'
+ method.
+ """
+ assert(isinstance(properties, property_set.PropertySet))
+ if isinstance (targets, str):
+ targets = [targets]
+ self.do_set_update_action (action_name, targets, sources, properties)
+
+ def register_action (self, action_name, command, bound_list = [], flags = [],
+ function = None):
+ """Creates a new build engine action.
+
+ Creates on bjam side an action named 'action_name', with
+ 'command' as the command to be executed, 'bound_variables'
+ naming the list of variables bound when the command is executed
+ and specified flag.
+ If 'function' is not None, it should be a callable taking three
+ parameters:
+ - targets
+ - sources
+ - instance of the property_set class
+ This function will be called by set_update_action, and can
+ set additional target variables.
+ """
+ if self.actions.has_key(action_name):
+ raise "Bjam action %s is already defined" % action_name
+
+ assert(isinstance(flags, list))
+
+ bjam_flags = reduce(operator.or_,
+ (action_modifiers[flag] for flag in flags), 0)
+
+ bjam_interface.define_action(action_name, command, bound_list, bjam_flags)
+
+ self.actions[action_name] = BjamAction(action_name, function)
+
+ def register_bjam_action (self, action_name, function=None):
+ """Informs self that 'action_name' is declared in bjam.
+
+ From this point, 'action_name' is a valid argument to the
+ set_update_action method. The action_name should be callable
+ in the global module of bjam.
+ """
+
+ # We allow duplicate calls to this rule for the same
+ # action name. This way, jamfile rules that take action names
+ # can just register them without specially checking if
+ # action is already registered.
+ if not self.actions.has_key(action_name):
+ self.actions[action_name] = BjamNativeAction(action_name, function)
+
+ # Overridables
+
+
+ def do_set_update_action (self, action_name, targets, sources, property_set):
+ action = self.actions.get(action_name)
+ if not action:
+ raise Exception("No action %s was registered" % action_name)
+ action(targets, sources, property_set)
+
+ def do_set_target_variable (self, target, variable, value, append):
+ if append:
+ bjam_interface.call("set-target-variable", target, variable, value, "true")
+ else:
+ bjam_interface.call("set-target-variable", target, variable, value)
+
+ def do_add_dependency (self, target, source):
+ bjam_interface.call("DEPENDS", target, source)
+
+
diff --git a/tools/build/v2/build/errors.py b/tools/build/v2/build/errors.py
new file mode 100644
index 0000000000..d9dceefe08
--- /dev/null
+++ b/tools/build/v2/build/errors.py
@@ -0,0 +1,127 @@
+# Status: being written afresh by Vladimir Prus
+
+# Copyright 2007 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This file is supposed to implement error reporting for Boost.Build.
+# Experience with jam version has shown that printing full backtrace
+# on each error is buffling. Further, for errors printed after parsing --
+# during target building, the stacktrace does not even mention what
+# target is being built.
+
+# This module implements explicit contexts -- where other code can
+# communicate which projects/targets are being built, and error
+# messages will show those contexts. For programming errors,
+# Python assertions are to be used.
+
+import bjam
+import traceback
+import sys
+
+def format(message, prefix=""):
+ parts = str(message).split("\n")
+ return "\n".join(prefix+p for p in parts)
+
+
+class Context:
+
+ def __init__(self, message, nested=None):
+ self.message_ = message
+ self.nested_ = nested
+
+ def report(self, indent=""):
+ print indent + " -", self.message_
+ if self.nested_:
+ print indent + " declared at:"
+ for n in self.nested_:
+ n.report(indent + " ")
+
+class JamfileContext:
+
+ def __init__(self):
+ raw = bjam.backtrace()
+ self.raw_ = raw
+
+ def report(self, indent=""):
+ for r in self.raw_:
+ print indent + " - %s:%s" % (r[0], r[1])
+
+class ExceptionWithUserContext(Exception):
+
+ def __init__(self, message, context,
+ original_exception=None, original_tb=None, stack=None):
+ Exception.__init__(self, message)
+ self.context_ = context
+ self.original_exception_ = original_exception
+ self.original_tb_ = original_tb
+ self.stack_ = stack
+
+ def report(self):
+ print "error:", self.args[0]
+ if self.original_exception_:
+ print format(str(self.original_exception_), " ")
+ print
+ print " error context (most recent first):"
+ for c in self.context_[::-1]:
+ c.report()
+ print
+ if "--stacktrace" in bjam.variable("ARGV"):
+ if self.original_tb_:
+ traceback.print_tb(self.original_tb_)
+ elif self.stack_:
+ for l in traceback.format_list(self.stack_):
+ print l,
+ else:
+ print " use the '--stacktrace' option to get Python stacktrace"
+ print
+
+def user_error_checkpoint(callable):
+ def wrapper(self, *args):
+ errors = self.manager().errors()
+ try:
+ return callable(self, *args)
+ except ExceptionWithUserContext, e:
+ raise
+ except Exception, e:
+ errors.handle_stray_exception(e)
+ finally:
+ errors.pop_user_context()
+
+ return wrapper
+
+class Errors:
+
+ def __init__(self):
+ self.contexts_ = []
+ self._count = 0
+
+ def count(self):
+ return self._count
+
+ def push_user_context(self, message, nested=None):
+ self.contexts_.append(Context(message, nested))
+
+ def pop_user_context(self):
+ del self.contexts_[-1]
+
+ def push_jamfile_context(self):
+ self.contexts_.append(JamfileContext())
+
+ def pop_jamfile_context(self):
+ del self.contexts_[-1]
+
+ def capture_user_context(self):
+ return self.contexts_[:]
+
+ def handle_stray_exception(self, e):
+ raise ExceptionWithUserContext("unexpected exception", self.contexts_[:],
+ e, sys.exc_info()[2])
+ def __call__(self, message):
+ self._count = self._count + 1
+ raise ExceptionWithUserContext(message, self.contexts_[:],
+ stack=traceback.extract_stack())
+
+
+
+
diff --git a/tools/build/v2/build/feature.jam b/tools/build/v2/build/feature.jam
new file mode 100644
index 0000000000..6f54adefbc
--- /dev/null
+++ b/tools/build/v2/build/feature.jam
@@ -0,0 +1,1335 @@
+# Copyright 2001, 2002, 2003 Dave Abrahams
+# Copyright 2002, 2006 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import assert : * ;
+import "class" : * ;
+import errors : lol->list ;
+import indirect ;
+import modules ;
+import regex ;
+import sequence ;
+import set ;
+import utility ;
+
+
+local rule setup ( )
+{
+ .all-attributes =
+ implicit
+ composite
+ optional
+ symmetric
+ free
+ incidental
+ path
+ dependency
+ propagated
+ link-incompatible
+ subfeature
+ order-sensitive
+ ;
+
+ .all-features = ;
+ .all-subfeatures = ;
+ .all-top-features = ; # non-subfeatures
+ .all-implicit-values = ;
+}
+setup ;
+
+
+# Prepare a fresh space to test in by moving all global variable settings into
+# the given temporary module and erasing them here.
+#
+rule prepare-test ( temp-module )
+{
+ DELETE_MODULE $(temp-module) ;
+
+ # Transfer globals to temp-module.
+ for local v in [ VARNAMES feature ]
+ {
+ if [ MATCH (\\.) : $(v) ]
+ {
+ modules.poke $(temp-module) : $(v) : $($(v)) ;
+ $(v) = ;
+ }
+ }
+ setup ;
+}
+
+
+# Clear out all global variables and recover all variables from the given
+# temporary module.
+#
+rule finish-test ( temp-module )
+{
+ # Clear globals.
+ for local v in [ VARNAMES feature ]
+ {
+ if [ MATCH (\\.) : $(v) ]
+ {
+ $(v) = ;
+ }
+ }
+
+ for local v in [ VARNAMES $(temp-module) ]
+ {
+ $(v) = [ modules.peek $(temp-module) : $(v) ] ;
+ }
+ DELETE_MODULE $(temp-module) ;
+}
+
+
+# Transform features by bracketing any elements which are not already bracketed
+# by "<>".
+#
+local rule grist ( features * )
+{
+ local empty = "" ;
+ return $(empty:G=$(features)) ;
+}
+
+
+# Declare a new feature with the given name, values, and attributes.
+#
+rule feature (
+ name # Feature name.
+ : values * # Allowable values - may be extended later using feature.extend.
+ : attributes * # Feature attributes (e.g. implicit, free, propagated...).
+)
+{
+ name = [ grist $(name) ] ;
+
+ local error ;
+
+ # Check for any unknown attributes.
+ if ! ( $(attributes) in $(.all-attributes) )
+ {
+ error = unknown attributes:
+ [ set.difference $(attributes) : $(.all-attributes) ] ;
+ }
+ else if $(name) in $(.all-features)
+ {
+ error = feature already defined: ;
+ }
+ else if implicit in $(attributes) && free in $(attributes)
+ {
+ error = free features cannot also be implicit ;
+ }
+ else if free in $(attributes) && propagated in $(attributes)
+ {
+ error = free features cannot be propagated ;
+ }
+ else
+ {
+ local m = [ MATCH (.*=.*) : $(values) ] ;
+ if $(m[1])
+ {
+ error = "feature value may not contain '='" ;
+ }
+ }
+
+ if $(error)
+ {
+ errors.error $(error)
+ : "in" feature declaration:
+ : feature [ lol->list $(1) : $(2) : $(3) ] ;
+ }
+
+ $(name).values ?= ;
+ $(name).attributes = $(attributes) ;
+ $(name).subfeatures ?= ;
+ $(attributes).features += $(name) ;
+
+ .all-features += $(name) ;
+ if subfeature in $(attributes)
+ {
+ .all-subfeatures += $(name) ;
+ }
+ else
+ {
+ .all-top-features += $(name) ;
+ }
+ extend $(name) : $(values) ;
+}
+
+
+# Sets the default value of the given feature, overriding any previous default.
+#
+rule set-default ( feature : value )
+{
+ local f = [ grist $(feature) ] ;
+ local a = $($(f).attributes) ;
+ local bad-attribute = ;
+ if free in $(a)
+ {
+ bad-attribute = free ;
+ }
+ else if optional in $(a)
+ {
+ bad-attribute = optional ;
+ }
+ if $(bad-attribute)
+ {
+ errors.error "$(bad-attribute) property $(f) cannot have a default." ;
+ }
+ if ! $(value) in $($(f).values)
+ {
+ errors.error "The specified default value, '$(value)' is invalid"
+ : "allowed values are: " $($(f).values) ;
+ }
+ $(f).default = $(value) ;
+}
+
+
+# Returns the default property values for the given features.
+#
+rule defaults ( features * )
+{
+ local result ;
+ for local f in $(features)
+ {
+ local gf = $(:E=:G=$(f)) ;
+ local a = $($(gf).attributes) ;
+ if ( free in $(a) ) || ( optional in $(a) )
+ {
+ }
+ else
+ {
+ result += $(gf)$($(gf).default) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Returns true iff all 'names' elements are valid features.
+#
+rule valid ( names + )
+{
+ if $(names) in $(.all-features)
+ {
+ return true ;
+ }
+}
+
+
+# Returns the attibutes of the given feature.
+#
+rule attributes ( feature )
+{
+ return $($(:E=:G=$(feature)).attributes) ;
+}
+
+
+# Returns the values of the given feature.
+#
+rule values ( feature )
+{
+ return $($(:E=:G=$(feature)).values) ;
+}
+
+
+# Returns true iff 'value-string' is a value-string of an implicit feature.
+#
+rule is-implicit-value ( value-string )
+{
+ local v = [ regex.split $(value-string) - ] ;
+ local failed ;
+ if ! $(v[1]) in $(.all-implicit-values)
+ {
+ failed = true ;
+ }
+ else
+ {
+ local feature = $($(v[1]).implicit-feature) ;
+ for local subvalue in $(v[2-])
+ {
+ if ! [ find-implied-subfeature $(feature) $(subvalue) : $(v[1]) ]
+ {
+ failed = true ;
+ }
+ }
+ }
+
+ if ! $(failed)
+ {
+ return true ;
+ }
+}
+
+
+# Returns the implicit feature associated with the given implicit value.
+#
+rule implied-feature ( implicit-value )
+{
+ local components = [ regex.split $(implicit-value) "-" ] ;
+
+ local feature = $($(components[1]).implicit-feature) ;
+ if ! $(feature)
+ {
+ errors.error \"$(implicit-value)\" is not a value of an implicit feature ;
+ feature = "" ; # Keep testing happy; it expects a result.
+ }
+ return $(feature) ;
+}
+
+
+local rule find-implied-subfeature ( feature subvalue : value-string ? )
+{
+ # Feature should be of the form <feature-name>.
+ if $(feature) != $(feature:G)
+ {
+ errors.error invalid feature $(feature) ;
+ }
+
+ return $($(feature)$(value-string:E="")<>$(subvalue).subfeature) ;
+}
+
+
+# Given a feature and a value of one of its subfeatures, find the name of the
+# subfeature. If value-string is supplied, looks for implied subfeatures that
+# are specific to that value of feature
+#
+rule implied-subfeature (
+ feature # The main feature name.
+ subvalue # The value of one of its subfeatures.
+ : value-string ? # The value of the main feature.
+)
+{
+ local subfeature = [ find-implied-subfeature $(feature) $(subvalue)
+ : $(value-string) ] ;
+ if ! $(subfeature)
+ {
+ value-string ?= "" ;
+ errors.error \"$(subvalue)\" is not a known subfeature value of
+ $(feature)$(value-string) ;
+ }
+ return $(subfeature) ;
+}
+
+
+# Generate an error if the feature is unknown.
+#
+local rule validate-feature ( feature )
+{
+ if ! $(feature) in $(.all-features)
+ {
+ errors.error unknown feature \"$(feature)\" ;
+ }
+}
+
+
+# Given a feature and its value or just a value corresponding to an implicit
+# feature, returns a property set consisting of all component subfeatures and
+# their values. For example all the following calls:
+#
+# expand-subfeatures-aux <toolset>gcc-2.95.2-linux-x86
+# expand-subfeatures-aux gcc-2.95.2-linux-x86
+#
+# return:
+#
+# <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
+#
+local rule expand-subfeatures-aux (
+ feature ? # Feature name or empty if value corresponds to an
+ # implicit property.
+ : value # Feature value.
+ : dont-validate ? # If set, no value string validation will be done.
+)
+{
+ if $(feature)
+ {
+ feature = $(feature) ;
+ }
+
+ if ! $(feature)
+ {
+ feature = [ implied-feature $(value) ] ;
+ }
+ else
+ {
+ validate-feature $(feature) ;
+ }
+ if ! $(dont-validate)
+ {
+ validate-value-string $(feature) $(value) ;
+ }
+
+ local components = [ regex.split $(value) "-" ] ;
+
+ # Get the top-level feature's value.
+ local value = $(components[1]:G=) ;
+
+ local result = $(components[1]:G=$(feature)) ;
+
+ local subvalues = $(components[2-]) ;
+ while $(subvalues)
+ {
+ local subvalue = $(subvalues[1]) ; # Pop the head off of subvalues.
+ subvalues = $(subvalues[2-]) ;
+
+ local subfeature = [ find-implied-subfeature $(feature) $(subvalue) :
+ $(value) ] ;
+
+ # If no subfeature was found reconstitute the value string and use that.
+ if ! $(subfeature)
+ {
+ result = $(components:J=-) ;
+ result = $(result:G=$(feature)) ;
+ subvalues = ; # Stop looping.
+ }
+ else
+ {
+ local f = [ MATCH ^<(.*)>$ : $(feature) ] ;
+ result += $(subvalue:G=$(f)-$(subfeature)) ;
+ }
+ }
+
+ return $(result) ;
+}
+
+
+# Make all elements of properties corresponding to implicit features explicit,
+# and express all subfeature values as separate properties in their own right.
+# For example, all of the following properties
+#
+# gcc-2.95.2-linux-x86
+# <toolset>gcc-2.95.2-linux-x86
+#
+# might expand to
+#
+# <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
+#
+rule expand-subfeatures (
+ properties * # Property set with elements of the form
+ # <feature>value-string or just value-string in the case
+ # of implicit features.
+ : dont-validate ?
+)
+{
+ local result ;
+ for local p in $(properties)
+ {
+ # Don't expand subfeatures in subfeatures
+ if ! [ MATCH "(:)" : $(p:G) ]
+ {
+ result += [ expand-subfeatures-aux $(p:G) : $(p:G=) : $(dont-validate) ] ;
+ }
+ else
+ {
+ result += $(p) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Helper for extend, below. Handles the feature case.
+#
+local rule extend-feature ( feature : values * )
+{
+ feature = [ grist $(feature) ] ;
+ validate-feature $(feature) ;
+ if implicit in $($(feature).attributes)
+ {
+ for local v in $(values)
+ {
+ if $($(v).implicit-feature)
+ {
+ errors.error $(v) is already associated with the \"$($(v).implicit-feature)\" feature ;
+ }
+ $(v).implicit-feature = $(feature) ;
+ }
+
+ .all-implicit-values += $(values) ;
+ }
+ if ! $($(feature).values)
+ {
+ # This is the first value specified for this feature so make it be the
+ # default.
+ $(feature).default = $(values[1]) ;
+ }
+ $(feature).values += $(values) ;
+}
+
+
+# Checks that value-string is a valid value-string for the given feature.
+#
+rule validate-value-string ( feature value-string )
+{
+ if ! (
+ free in $($(feature).attributes)
+ || ( $(value-string) in $(feature).values )
+ )
+ {
+ local values = $(value-string) ;
+
+ if $($(feature).subfeatures)
+ {
+ if ! ( $(value-string) in $($(feature).values) )
+ && ! ( $(value-string) in $($(feature).subfeatures) )
+ {
+ values = [ regex.split $(value-string) - ] ;
+ }
+ }
+
+ if ! ( $(values[1]) in $($(feature).values) ) &&
+
+ # An empty value is allowed for optional features.
+ ( $(values[1]) || ! ( optional in $($(feature).attributes) ) )
+ {
+ errors.error \"$(values[1])\" is not a known value of feature $(feature)
+ : legal values: \"$($(feature).values)\" ;
+ }
+
+ for local v in $(values[2-])
+ {
+ # This will validate any subfeature values in value-string.
+ implied-subfeature $(feature) $(v) : $(values[1]) ;
+ }
+ }
+}
+
+
+# A helper that computes:
+# * name(s) of module-local variable(s) used to record the correspondence
+# between subvalue(s) and a subfeature
+# * value of that variable when such a subfeature/subvalue has been defined and
+# returns a list consisting of the latter followed by the former.
+#
+local rule subvalue-var (
+ feature # Main feature name.
+ value-string ? # If supplied, specifies a specific value of the main
+ # feature for which the subfeature values are valid.
+ : subfeature # Subfeature name.
+ : subvalues * # Subfeature values.
+)
+{
+ feature = [ grist $(feature) ] ;
+ validate-feature $(feature) ;
+ if $(value-string)
+ {
+ validate-value-string $(feature) $(value-string) ;
+ }
+
+ local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
+
+ return $(subfeature-name)
+ $(feature)$(value-string:E="")<>$(subvalues).subfeature ;
+}
+
+
+# Extends the given subfeature with the subvalues. If the optional value-string
+# is provided, the subvalues are only valid for the given value of the feature.
+# Thus, you could say that <target-platform>mingw is specific to
+# <toolset>gcc-2.95.2 as follows:
+#
+# extend-subfeature toolset gcc-2.95.2 : target-platform : mingw ;
+#
+rule extend-subfeature (
+ feature # The feature whose subfeature is being extended.
+
+ value-string ? # If supplied, specifies a specific value of the main
+ # feature for which the new subfeature values are valid.
+
+ : subfeature # Subfeature name.
+ : subvalues * # Additional subfeature values.
+)
+{
+ local subfeature-vars = [ subvalue-var $(feature) $(value-string)
+ : $(subfeature) : $(subvalues) ] ;
+
+ local f = [ utility.ungrist [ grist $(feature) ] ] ;
+ extend $(f)-$(subfeature-vars[1]) : $(subvalues) ;
+
+ # Provide a way to get from the given feature or property and subfeature
+ # value to the subfeature name.
+ $(subfeature-vars[2-]) = $(subfeature-vars[1]) ;
+}
+
+
+# Returns true iff the subvalues are valid for the feature. When the optional
+# value-string is provided, returns true iff the subvalues are valid for the
+# given value of the feature.
+#
+rule is-subvalue ( feature : value-string ? : subfeature : subvalue )
+{
+ local subfeature-vars = [ subvalue-var $(feature) $(value-string)
+ : $(subfeature) : $(subvalue) ] ;
+
+ if $($(subfeature-vars[2])) = $(subfeature-vars[1])
+ {
+ return true ;
+ }
+}
+
+
+# Can be called three ways:
+#
+# 1. extend feature : values *
+# 2. extend <feature> subfeature : values *
+# 3. extend <feature>value-string subfeature : values *
+#
+# * Form 1 adds the given values to the given feature.
+# * Forms 2 and 3 add subfeature values to the given feature.
+# * Form 3 adds the subfeature values as specific to the given property
+# value-string.
+#
+rule extend ( feature-or-property subfeature ? : values * )
+{
+ local feature ; # If a property was specified this is its feature.
+ local value-string ; # E.g., the gcc-2.95-2 part of <toolset>gcc-2.95.2.
+
+ # If a property was specified.
+ if $(feature-or-property:G) && $(feature-or-property:G=)
+ {
+ # Extract the feature and value-string, if any.
+ feature = $(feature-or-property:G) ;
+ value-string = $(feature-or-property:G=) ;
+ }
+ else
+ {
+ feature = [ grist $(feature-or-property) ] ;
+ }
+
+ # Dispatch to the appropriate handler.
+ if $(subfeature)
+ {
+ extend-subfeature $(feature) $(value-string) : $(subfeature)
+ : $(values) ;
+ }
+ else
+ {
+ # If no subfeature was specified, we do not expect to see a
+ # value-string.
+ if $(value-string)
+ {
+ errors.error can only specify a property as the first argument when
+ extending a subfeature
+ : usage:
+ : " extend" feature ":" values...
+ : " | extend" <feature>value-string subfeature ":" values...
+ ;
+ }
+
+ extend-feature $(feature) : $(values) ;
+ }
+}
+
+
+local rule get-subfeature-name ( subfeature value-string ? )
+{
+ local prefix = $(value-string): ;
+ return $(prefix:E="")$(subfeature) ;
+}
+
+
+# Declares a subfeature.
+#
+rule subfeature (
+ feature # Root feature that is not a subfeature.
+ value-string ? # A value-string specifying which feature or subfeature
+ # values this subfeature is specific to, if any.
+ : subfeature # The name of the subfeature being declared.
+ : subvalues * # The allowed values of this subfeature.
+ : attributes * # The attributes of the subfeature.
+)
+{
+ feature = [ grist $(feature) ] ;
+ validate-feature $(feature) ;
+
+ # Add grist to the subfeature name if a value-string was supplied.
+ local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
+
+ if $(subfeature-name) in $($(feature).subfeatures)
+ {
+ errors.error \"$(subfeature)\" already declared as a subfeature of \"$(feature)\"
+ "specific to "$(value-string) ;
+ }
+ $(feature).subfeatures += $(subfeature-name) ;
+
+ # First declare the subfeature as a feature in its own right.
+ local f = [ utility.ungrist $(feature) ] ;
+ feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) subfeature ;
+
+ # Now make sure the subfeature values are known.
+ extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ;
+}
+
+
+# Set components of the given composite property.
+#
+rule compose ( composite-property : component-properties * )
+{
+ local feature = $(composite-property:G) ;
+ if ! ( composite in [ attributes $(feature) ] )
+ {
+ errors.error "$(feature)" is not a composite feature ;
+ }
+
+ $(composite-property).components ?= ;
+ if $($(composite-property).components)
+ {
+ errors.error components of "$(composite-property)" already set:
+ $($(composite-property).components) ;
+ }
+
+ if $(composite-property) in $(component-properties)
+ {
+ errors.error composite property "$(composite-property)" cannot have itself as a component ;
+ }
+ $(composite-property).components = $(component-properties) ;
+}
+
+
+local rule expand-composite ( property )
+{
+ return $(property)
+ [ sequence.transform expand-composite : $($(property).components) ] ;
+}
+
+
+# Return all values of the given feature specified by the given property set.
+#
+rule get-values ( feature : properties * )
+{
+ local result ;
+
+ feature = $(:E=:G=$(feature)) ; # Add <> if necessary.
+ for local p in $(properties)
+ {
+ if $(p:G) = $(feature)
+ {
+ # Use MATCH instead of :G= to get the value, in order to preserve
+ # the value intact instead of having bjam treat it as a decomposable
+ # path.
+ result += [ MATCH ">(.*)" : $(p) ] ;
+ }
+ }
+ return $(result) ;
+}
+
+
+rule free-features ( )
+{
+ return $(free.features) ;
+}
+
+
+# Expand all composite properties in the set so that all components are
+# explicitly expressed.
+#
+rule expand-composites ( properties * )
+{
+ local explicit-features = $(properties:G) ;
+ local result ;
+
+ # Now expand composite features.
+ for local p in $(properties)
+ {
+ local expanded = [ expand-composite $(p) ] ;
+
+ for local x in $(expanded)
+ {
+ if ! $(x) in $(result)
+ {
+ local f = $(x:G) ;
+
+ if $(f) in $(free.features)
+ {
+ result += $(x) ;
+ }
+ else if ! $(x) in $(properties) # x is the result of expansion
+ {
+ if ! $(f) in $(explicit-features) # not explicitly-specified
+ {
+ if $(f) in $(result:G)
+ {
+ errors.error expansions of composite features result
+ in conflicting values for $(f)
+ : values: [ get-values $(f) : $(result) ] $(x:G=)
+ : one contributing composite property was $(p) ;
+ }
+ else
+ {
+ result += $(x) ;
+ }
+ }
+ }
+ else if $(f) in $(result:G)
+ {
+ errors.error explicitly-specified values of non-free feature
+ $(f) conflict :
+ "existing values:" [ get-values $(f) : $(properties) ] :
+ "value from expanding " $(p) ":" $(x:G=) ;
+ }
+ else
+ {
+ result += $(x) ;
+ }
+ }
+ }
+ }
+ return $(result) ;
+}
+
+
+# Return true iff f is an ordinary subfeature of the parent-property's feature,
+# or if f is a subfeature of the parent-property's feature specific to the
+# parent-property's value.
+#
+local rule is-subfeature-of ( parent-property f )
+{
+ if subfeature in $($(f).attributes)
+ {
+ local specific-subfeature = [ MATCH <(.*):(.*)> : $(f) ] ;
+ if $(specific-subfeature)
+ {
+ # The feature has the form <topfeature-topvalue:subfeature>, e.g.
+ # <toolset-msvc:version>.
+ local feature-value = [ split-top-feature $(specific-subfeature[1])
+ ] ;
+ if <$(feature-value[1])>$(feature-value[2]) = $(parent-property)
+ {
+ return true ;
+ }
+ }
+ else
+ {
+ # The feature has the form <topfeature-subfeature>, e.g.
+ # <toolset-version>
+ local top-sub = [ split-top-feature [ utility.ungrist $(f) ] ] ;
+ if $(top-sub[2]) && <$(top-sub[1])> = $(parent-property:G)
+ {
+ return true ;
+ }
+ }
+ }
+}
+
+
+# As for is-subfeature-of but for subproperties.
+#
+local rule is-subproperty-of ( parent-property p )
+{
+ return [ is-subfeature-of $(parent-property) $(p:G) ] ;
+}
+
+
+# Given a property, return the subset of features consisting of all ordinary
+# subfeatures of the property's feature, and all specific subfeatures of the
+# property's feature which are conditional on the property's value.
+#
+local rule select-subfeatures ( parent-property : features * )
+{
+ return [ sequence.filter is-subfeature-of $(parent-property) : $(features) ] ;
+}
+
+
+# As for select-subfeatures but for subproperties.
+#
+local rule select-subproperties ( parent-property : properties * )
+{
+ return [ sequence.filter is-subproperty-of $(parent-property) : $(properties) ] ;
+}
+
+
+# Given a property set which may consist of composite and implicit properties
+# and combined subfeature values, returns an expanded, normalized property set
+# with all implicit features expressed explicitly, all subfeature values
+# individually expressed, and all components of composite properties expanded.
+# Non-free features directly expressed in the input properties cause any values
+# of those features due to composite feature expansion to be dropped. If two
+# values of a given non-free feature are directly expressed in the input, an
+# error is issued.
+#
+rule expand ( properties * )
+{
+ local expanded = [ expand-subfeatures $(properties) ] ;
+ return [ expand-composites $(expanded) ] ;
+}
+
+
+# Helper rule for minimize. Returns true iff property's feature is present in
+# the contents of the variable named by feature-set-var.
+#
+local rule in-features ( feature-set-var property )
+{
+ if $(property:G) in $($(feature-set-var))
+ {
+ return true ;
+ }
+}
+
+
+# Helper rule for minimize. Returns the list with the same properties, but with
+# all subfeatures moved to the end of the list.
+#
+local rule move-subfeatures-to-the-end ( properties * )
+{
+ local x1 ;
+ local x2 ;
+ for local p in $(properties)
+ {
+ if subfeature in $($(p:G).attributes)
+ {
+ x2 += $(p) ;
+ }
+ else
+ {
+ x1 += $(p) ;
+ }
+ }
+ return $(x1) $(x2) ;
+}
+
+
+# Given an expanded property set, eliminate all redundancy: properties that are
+# elements of other (composite) properties in the set will be eliminated.
+# Non-symmetric properties equal to default values will be eliminated unless
+# they override a value from some composite property. Implicit properties will
+# be expressed without feature grist, and sub-property values will be expressed
+# as elements joined to the corresponding main property.
+#
+rule minimize ( properties * )
+{
+ # Precondition checking
+ local implicits = [ set.intersection $(p:G=) : $(p:G) ] ;
+ if $(implicits)
+ {
+ errors.error minimize requires an expanded property set, but
+ \"$(implicits[1])\" appears to be the value of an un-expanded
+ implicit feature ;
+ }
+
+ # Remove properties implied by composite features.
+ local components = $($(properties).components) ;
+ local x = [ set.difference $(properties) : $(components) ] ;
+
+ # Handle subfeatures and implicit features.
+ x = [ move-subfeatures-to-the-end $(x) ] ;
+ local result ;
+ while $(x)
+ {
+ local p fullp = $(x[1]) ;
+ local f = $(p:G) ;
+ local v = $(p:G=) ;
+
+ # Eliminate features in implicit properties.
+ if implicit in [ attributes $(f) ]
+ {
+ p = $(v) ;
+ }
+
+ # Locate all subproperties of $(x[1]) in the property set.
+ local subproperties = [ select-subproperties $(fullp) : $(x) ] ;
+ if $(subproperties)
+ {
+ # Reconstitute the joined property name.
+ local sorted = [ sequence.insertion-sort $(subproperties) ] ;
+ result += $(p)-$(sorted:G="":J=-) ;
+
+ x = [ set.difference $(x[2-]) : $(subproperties) ] ;
+ }
+ else
+ {
+ # Eliminate properties whose value is equal to feature's default,
+ # which are not symmetric and which do not contradict values implied
+ # by composite properties.
+
+ # Since all component properties of composites in the set have been
+ # eliminated, any remaining property whose feature is the same as a
+ # component of a composite in the set must have a non-redundant
+ # value.
+ if $(fullp) != [ defaults $(f) ]
+ || symmetric in [ attributes $(f) ]
+ || $(fullp:G) in $(components:G)
+ {
+ result += $(p) ;
+ }
+
+ x = $(x[2-]) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Combine all subproperties into their parent properties
+#
+# Requires: for every subproperty, there is a parent property. All features are
+# explicitly expressed.
+#
+# This rule probably should not be needed, but build-request.expand-no-defaults
+# is being abused for unintended purposes and it needs help.
+#
+rule compress-subproperties ( properties * )
+{
+ local all-subs ;
+ local matched-subs ;
+ local result ;
+
+ for local p in $(properties)
+ {
+ if ! $(p:G)
+ {
+ # Expecting fully-gristed properties.
+ assert.variable-not-empty p:G ;
+ }
+
+ if ! subfeature in $($(p:G).attributes)
+ {
+ local subs = [ sequence.insertion-sort
+ [ sequence.filter is-subproperty-of $(p) : $(properties) ] ] ;
+
+ matched-subs += $(subs) ;
+
+ local subvalues = -$(subs:G=:J=-) ;
+ subvalues ?= "" ;
+ result += $(p)$(subvalues) ;
+ }
+ else
+ {
+ all-subs += $(p) ;
+ }
+ }
+ assert.result true : set.equal $(all-subs) : $(matched-subs) ;
+ return $(result) ;
+}
+
+
+# Given an ungristed string, finds the longest prefix which is a top-level
+# feature name followed by a dash, and return a pair consisting of the parts
+# before and after that dash. More interesting than a simple split because
+# feature names may contain dashes.
+#
+local rule split-top-feature ( feature-plus )
+{
+ local e = [ regex.split $(feature-plus) - ] ;
+ local f = $(e[1]) ;
+ local v ;
+ while $(e)
+ {
+ if <$(f)> in $(.all-top-features)
+ {
+ v = $(f) $(e[2-]:J=-) ;
+ }
+ e = $(e[2-]) ;
+ f = $(f)-$(e[1]) ;
+ }
+ return $(v) ;
+}
+
+
+# Given a set of properties, add default values for features not represented in
+# the set.
+#
+# Note: if there's an ordinary feature F1 and a composite feature F2 which
+# includes some value for F1 and both feature have default values then the
+# default value of F1 will be added (as opposed to the value in F2). This might
+# not be the right idea, e.g. consider:
+#
+# feature variant : debug ... ;
+# <variant>debug : .... <runtime-debugging>on
+# feature <runtime-debugging> : off on ;
+#
+# Here, when adding default for an empty property set, we'll get
+#
+# <variant>debug <runtime_debugging>off
+#
+# and that's kind of strange.
+#
+rule add-defaults ( properties * )
+{
+ for local v in $(properties:G=)
+ {
+ if $(v) in $(properties)
+ {
+ errors.error add-defaults requires explicitly specified features,
+ but \"$(v)\" appears to be the value of an un-expanded implicit
+ feature ;
+ }
+ }
+ # We don't add default for elements with ":" inside. This catches:
+ # 1. Conditional properties --- we don't want <variant>debug:<define>DEBUG
+ # to be takes as specified value for <variant>
+ # 2. Free properties with ":" in values. We don't care, since free
+ # properties don't have defaults.
+ local xproperties = [ MATCH "^([^:]+)$" : $(properties) ] ;
+ local missing-top = [ set.difference $(.all-top-features) : $(xproperties:G) ] ;
+ local more = [ defaults $(missing-top) ] ;
+ properties += $(more) ;
+ xproperties += $(more) ;
+
+ # Add defaults for subfeatures of features which are present.
+ for local p in $(xproperties)
+ {
+ local s = $($(p:G).subfeatures) ;
+ local f = [ utility.ungrist $(p:G) ] ;
+ local missing-subs = [ set.difference <$(f)-$(s)> : $(properties:G) ] ;
+ properties += [ defaults [ select-subfeatures $(p) : $(missing-subs) ] ] ;
+ }
+
+ return $(properties) ;
+}
+
+
+# Given a property-set of the form
+# v1/v2/...vN-1/<fN>vN/<fN+1>vN+1/...<fM>vM
+#
+# Returns
+# v1 v2 ... vN-1 <fN>vN <fN+1>vN+1 ... <fM>vM
+#
+# Note that vN...vM may contain slashes. This needs to be resilient to the
+# substitution of backslashes for slashes, since Jam, unbidden, sometimes swaps
+# slash direction on NT.
+#
+rule split ( property-set )
+{
+ local pieces = [ regex.split $(property-set) [\\/] ] ;
+ local result ;
+
+ for local x in $(pieces)
+ {
+ if ( ! $(x:G) ) && $(result[-1]:G)
+ {
+ result = $(result[1--2]) $(result[-1])/$(x) ;
+ }
+ else
+ {
+ result += $(x) ;
+ }
+ }
+
+ return $(result) ;
+}
+
+
+# Tests of module feature.
+#
+rule __test__ ( )
+{
+ # Use a fresh copy of the feature module.
+ prepare-test feature-test-temp ;
+
+ import assert ;
+ import errors : try catch ;
+
+ # These are local rules and so must be explicitly reimported into the
+ # testing module.
+ import feature : extend-feature validate-feature select-subfeatures ;
+
+ feature toolset : gcc : implicit ;
+ feature define : : free ;
+ feature runtime-link : dynamic static : symmetric ;
+ feature optimization : on off ;
+ feature variant : debug release profile : implicit composite symmetric ;
+ feature stdlib : native stlport ;
+ feature magic : : free ;
+
+ compose <variant>debug : <define>_DEBUG <optimization>off ;
+ compose <variant>release : <define>NDEBUG <optimization>on ;
+
+ assert.result dynamic static : values <runtime-link> ;
+ assert.result dynamic static : values runtime-link ;
+
+ try ;
+ {
+ compose <variant>profile : <variant>profile ;
+ }
+ catch composite property <variant>profile cannot have itself as a component ;
+
+ extend-feature toolset : msvc metrowerks ;
+ subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 3.0 3.0.1 3.0.2 ;
+
+ assert.true is-subvalue toolset : gcc : version : 2.95.3 ;
+ assert.false is-subvalue toolset : gcc : version : 1.1 ;
+
+ assert.false is-subvalue toolset : msvc : version : 2.95.3 ;
+ assert.false is-subvalue toolset : : version : yabba ;
+
+ feature yabba ;
+ subfeature yabba : version : dabba ;
+ assert.true is-subvalue yabba : : version : dabba ;
+
+ subfeature toolset gcc : platform : linux cygwin : optional ;
+
+ assert.result <toolset-gcc:version>
+ : select-subfeatures <toolset>gcc
+ : <toolset-gcc:version>
+ <toolset-msvc:version>
+ <toolset-version>
+ <stdlib> ;
+
+ subfeature stdlib : version : 3 4 : optional ;
+
+ assert.result <stdlib-version>
+ : select-subfeatures <stdlib>native
+ : <toolset-gcc:version>
+ <toolset-msvc:version>
+ <toolset-version>
+ <stdlib-version> ;
+
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
+ : expand-subfeatures <toolset>gcc-3.0.1 ;
+
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1 <toolset-gcc:platform>linux
+ : expand-subfeatures <toolset>gcc-3.0.1-linux ;
+
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
+ : expand <toolset>gcc <toolset-gcc:version>3.0.1 ;
+
+ assert.result <define>foo=x-y
+ : expand-subfeatures <define>foo=x-y ;
+
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
+ : expand-subfeatures gcc-3.0.1 ;
+
+ assert.result a c e
+ : get-values <x> : <x>a <y>b <x>c <y>d <x>e ;
+
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
+ <variant>debug <define>_DEBUG <optimization>on
+ : expand gcc-3.0.1 debug <optimization>on ;
+
+ assert.result <variant>debug <define>_DEBUG <optimization>on
+ : expand debug <optimization>on ;
+
+ assert.result <optimization>on <variant>debug <define>_DEBUG
+ : expand <optimization>on debug ;
+
+ assert.result <runtime-link>dynamic <optimization>on
+ : defaults <runtime-link> <define> <optimization> ;
+
+ # Make sure defaults is resilient to missing grist.
+ assert.result <runtime-link>dynamic <optimization>on
+ : defaults runtime-link define optimization ;
+
+ feature dummy : dummy1 dummy2 ;
+ subfeature dummy : subdummy : x y z : optional ;
+
+ feature fu : fu1 fu2 : optional ;
+ subfeature fu : subfu : x y z : optional ;
+ subfeature fu : subfu2 : q r s ;
+
+ assert.result optional : attributes <fu> ;
+ assert.result optional : attributes fu ;
+
+ assert.result <runtime-link>static <define>foobar <optimization>on
+ <toolset>gcc:<define>FOO <toolset>gcc <variant>debug <stdlib>native
+ <dummy>dummy1 <toolset-gcc:version>2.95.2
+ : add-defaults <runtime-link>static <define>foobar <optimization>on
+ <toolset>gcc:<define>FOO ;
+
+ assert.result <runtime-link>static <define>foobar <optimization>on
+ <toolset>gcc:<define>FOO <fu>fu1 <toolset>gcc <variant>debug
+ <stdlib>native <dummy>dummy1 <fu-subfu2>q <toolset-gcc:version>2.95.2
+ : add-defaults <runtime-link>static <define>foobar <optimization>on
+ <toolset>gcc:<define>FOO <fu>fu1 ;
+
+ set-default <runtime-link> : static ;
+ assert.result <runtime-link>static : defaults <runtime-link> ;
+
+ assert.result gcc-3.0.1 debug <optimization>on
+ : minimize [ expand gcc-3.0.1 debug <optimization>on <stdlib>native ] ;
+
+ assert.result gcc-3.0.1 debug <runtime-link>dynamic
+ : minimize
+ [ expand gcc-3.0.1 debug <optimization>off <runtime-link>dynamic ] ;
+
+ assert.result gcc-3.0.1 debug
+ : minimize [ expand gcc-3.0.1 debug <optimization>off ] ;
+
+ assert.result debug <optimization>on
+ : minimize [ expand debug <optimization>on ] ;
+
+ assert.result gcc-3.0
+ : minimize <toolset>gcc <toolset-gcc:version>3.0 ;
+
+ assert.result gcc-3.0
+ : minimize <toolset-gcc:version>3.0 <toolset>gcc ;
+
+ assert.result <x>y/z <a>b/c <d>e/f
+ : split <x>y/z/<a>b/c/<d>e/f ;
+
+ assert.result <x>y/z <a>b/c <d>e/f
+ : split <x>y\\z\\<a>b\\c\\<d>e\\f ;
+
+ assert.result a b c <d>e/f/g <h>i/j/k
+ : split a/b/c/<d>e/f/g/<h>i/j/k ;
+
+ assert.result a b c <d>e/f/g <h>i/j/k
+ : split a\\b\\c\\<d>e\\f\\g\\<h>i\\j\\k ;
+
+ # Test error checking.
+
+ try ;
+ {
+ expand release <optimization>off <optimization>on ;
+ }
+ catch explicitly-specified values of non-free feature <optimization> conflict ;
+
+ try ;
+ {
+ validate-feature <foobar> ;
+ }
+ catch unknown feature ;
+
+ validate-value-string <toolset> gcc ;
+ validate-value-string <toolset> gcc-3.0.1 ;
+
+ try ;
+ {
+ validate-value-string <toolset> digital_mars ;
+ }
+ catch \"digital_mars\" is not a known value of <toolset> ;
+
+ try ;
+ {
+ feature foobar : : baz ;
+ }
+ catch unknown attributes: baz ;
+
+ feature feature1 ;
+ try ;
+ {
+ feature feature1 ;
+ }
+ catch feature already defined: ;
+
+ try ;
+ {
+ feature feature2 : : free implicit ;
+ }
+ catch free features cannot also be implicit ;
+
+ try ;
+ {
+ feature feature3 : : free propagated ;
+ }
+ catch free features cannot be propagated ;
+
+ try ;
+ {
+ implied-feature lackluster ;
+ }
+ catch \"lackluster\" is not a value of an implicit feature ;
+
+ try ;
+ {
+ implied-subfeature <toolset> 3.0.1 ;
+ }
+ catch \"3.0.1\" is not a known subfeature value of <toolset> ;
+
+ try ;
+ {
+ implied-subfeature <toolset> not-a-version : gcc ;
+ }
+ catch \"not-a-version\" is not a known subfeature value of <toolset>gcc ;
+
+ # Leave a clean copy of the features module behind.
+ finish-test feature-test-temp ;
+}
diff --git a/tools/build/v2/build/feature.py b/tools/build/v2/build/feature.py
new file mode 100644
index 0000000000..315a18e944
--- /dev/null
+++ b/tools/build/v2/build/feature.py
@@ -0,0 +1,905 @@
+# Status: ported, except for unit tests.
+# Base revision: 64488
+#
+# Copyright 2001, 2002, 2003 Dave Abrahams
+# Copyright 2002, 2006 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import re
+
+from b2.util import utility, bjam_signature
+import b2.util.set
+from b2.util.utility import add_grist, get_grist, ungrist, replace_grist, to_seq
+from b2.exceptions import *
+
+__re_split_subfeatures = re.compile ('<(.*):(.*)>')
+__re_no_hyphen = re.compile ('^([^:]+)$')
+__re_slash_or_backslash = re.compile (r'[\\/]')
+
+class Feature(object):
+
+ # Map from string attribute names to integers bit flags.
+ # This will be initialized after declaration of the class.
+ _attribute_name_to_integer = {}
+
+ def __init__(self, name, values, attributes):
+ self._name = name
+ self._values = values
+ self._default = None
+ self._attributes = 0
+ for a in attributes:
+ self._attributes = self._attributes | Feature._attribute_name_to_integer[a]
+ self._attributes_string_list = attributes
+ self._subfeatures = []
+ self._parent = None
+
+ def name(self):
+ return self._name
+
+ def values(self):
+ return self._values
+
+ def add_values(self, values):
+ self._values.extend(values)
+
+ def attributes(self):
+ return self._attributes
+
+ def set_default(self, value):
+ self._default = value
+
+ def default(self):
+ return self._default
+
+ # FIXME: remove when we fully move to using classes for features/properties
+ def attributes_string_list(self):
+ return self._attributes_string_list
+
+ def subfeatures(self):
+ return self._subfeatures
+
+ def add_subfeature(self, name):
+ self._subfeatures.append(name)
+
+ def parent(self):
+ """For subfeatures, return pair of (parent_feature, value).
+
+ Value may be None if this subfeature is not specific to any
+ value of the parent feature.
+ """
+ return self._parent
+
+ def set_parent(self, feature, value):
+ self._parent = (feature, value)
+
+ def __str__(self):
+ return self._name
+
+
+def reset ():
+ """ Clear the module state. This is mainly for testing purposes.
+ """
+ global __all_attributes, __all_features, __implicit_features, __composite_properties
+ global __features_with_attributes, __subfeature_from_value, __all_top_features, __free_features
+ global __all_subfeatures
+
+ # The list with all attribute names.
+ __all_attributes = [ 'implicit',
+ 'composite',
+ 'optional',
+ 'symmetric',
+ 'free',
+ 'incidental',
+ 'path',
+ 'dependency',
+ 'propagated',
+ 'link-incompatible',
+ 'subfeature',
+ 'order-sensitive'
+ ]
+ i = 1
+ for a in __all_attributes:
+ setattr(Feature, a.upper(), i)
+ Feature._attribute_name_to_integer[a] = i
+ def probe(self, flag=i):
+ return getattr(self, "_attributes") & flag
+ setattr(Feature, a.replace("-", "_"), probe)
+ i = i << 1
+
+ # A map containing all features. The key is the feature name.
+ # The value is an instance of Feature class.
+ __all_features = {}
+
+ # All non-subfeatures.
+ __all_top_features = []
+
+ # Maps valus to the corresponding implicit feature
+ __implicit_features = {}
+
+ # A map containing all composite properties. The key is a Property instance,
+ # and the value is a list of Property instances
+ __composite_properties = {}
+
+ __features_with_attributes = {}
+ for attribute in __all_attributes:
+ __features_with_attributes [attribute] = []
+
+ # Maps a value to the corresponding subfeature name.
+ __subfeature_from_value = {}
+
+ # All free features
+ __free_features = []
+
+ __all_subfeatures = []
+
+reset ()
+
+def enumerate ():
+ """ Returns an iterator to the features map.
+ """
+ return __all_features.iteritems ()
+
+def get(name):
+ """Return the Feature instance for the specified name.
+
+ Throws if no feature by such name exists
+ """
+ return __all_features[name]
+
+# FIXME: prepare-test/finish-test?
+
+@bjam_signature((["name"], ["values", "*"], ["attributes", "*"]))
+def feature (name, values, attributes = []):
+ """ Declares a new feature with the given name, values, and attributes.
+ name: the feature name
+ values: a sequence of the allowable values - may be extended later with feature.extend
+ attributes: a sequence of the feature's attributes (e.g. implicit, free, propagated, ...)
+ """
+ __validate_feature_attributes (name, attributes)
+
+ feature = Feature(name, [], attributes)
+ __all_features[name] = feature
+ # Temporary measure while we have not fully moved from 'gristed strings'
+ __all_features["<" + name + ">"] = feature
+
+ for attribute in attributes:
+ __features_with_attributes [attribute].append (name)
+
+ name = add_grist(name)
+
+ if 'subfeature' in attributes:
+ __all_subfeatures.append(name)
+ else:
+ __all_top_features.append(feature)
+
+ extend (name, values)
+
+ # FIXME: why his is needed.
+ if 'free' in attributes:
+ __free_features.append (name)
+
+ return feature
+
+@bjam_signature((["feature"], ["value"]))
+def set_default (feature, value):
+ """ Sets the default value of the given feature, overriding any previous default.
+ feature: the name of the feature
+ value: the default value to assign
+ """
+ f = __all_features[feature]
+ attributes = f.attributes()
+ bad_attribute = None
+
+ if attributes & Feature.FREE:
+ bad_attribute = "free"
+ elif attributes & Feature.OPTIONAL:
+ bad_attribute = "optional"
+
+ if bad_attribute:
+ raise InvalidValue ("%s property %s cannot have a default" % (bad_attribute, feature.name()))
+
+ if not value in f.values():
+ raise InvalidValue ("The specified default value, '%s' is invalid.\n" % value + "allowed values are: %s" % values)
+
+ f.set_default(value)
+
+def defaults(features):
+ """ Returns the default property values for the given features.
+ """
+ # FIXME: should merge feature and property modules.
+ import property
+
+ result = []
+ for f in features:
+ if not f.free() and not f.optional() and f.default():
+ result.append(property.Property(f, f.default()))
+
+ return result
+
+def valid (names):
+ """ Returns true iff all elements of names are valid features.
+ """
+ def valid_one (name): return __all_features.has_key (name)
+
+ if isinstance (names, str):
+ return valid_one (names)
+ else:
+ return [ valid_one (name) for name in names ]
+
+def attributes (feature):
+ """ Returns the attributes of the given feature.
+ """
+ return __all_features[feature].attributes_string_list()
+
+def values (feature):
+ """ Return the values of the given feature.
+ """
+ validate_feature (feature)
+ return __all_features[feature].values()
+
+def is_implicit_value (value_string):
+ """ Returns true iff 'value_string' is a value_string
+ of an implicit feature.
+ """
+
+ if __implicit_features.has_key(value_string):
+ return __implicit_features[value_string]
+
+ v = value_string.split('-')
+
+ if not __implicit_features.has_key(v[0]):
+ return False
+
+ feature = __implicit_features[v[0]]
+
+ for subvalue in (v[1:]):
+ if not __find_implied_subfeature(feature, subvalue, v[0]):
+ return False
+
+ return True
+
+def implied_feature (implicit_value):
+ """ Returns the implicit feature associated with the given implicit value.
+ """
+ components = implicit_value.split('-')
+
+ if not __implicit_features.has_key(components[0]):
+ raise InvalidValue ("'%s' is not a value of an implicit feature" % implicit_value)
+
+ return __implicit_features[components[0]]
+
+def __find_implied_subfeature (feature, subvalue, value_string):
+
+ #if value_string == None: value_string = ''
+
+ if not __subfeature_from_value.has_key(feature) \
+ or not __subfeature_from_value[feature].has_key(value_string) \
+ or not __subfeature_from_value[feature][value_string].has_key (subvalue):
+ return None
+
+ return __subfeature_from_value[feature][value_string][subvalue]
+
+# Given a feature and a value of one of its subfeatures, find the name
+# of the subfeature. If value-string is supplied, looks for implied
+# subfeatures that are specific to that value of feature
+# feature # The main feature name
+# subvalue # The value of one of its subfeatures
+# value-string # The value of the main feature
+
+def implied_subfeature (feature, subvalue, value_string):
+ result = __find_implied_subfeature (feature, subvalue, value_string)
+ if not result:
+ raise InvalidValue ("'%s' is not a known subfeature value of '%s%s'" % (subvalue, feature, value_string))
+
+ return result
+
+def validate_feature (name):
+ """ Checks if all name is a valid feature. Otherwise, raises an exception.
+ """
+ if not __all_features.has_key(name):
+ raise InvalidFeature ("'%s' is not a valid feature name" % name)
+ else:
+ return __all_features[name]
+
+def valid (names):
+ """ Returns true iff all elements of names are valid features.
+ """
+ def valid_one (name): return __all_features.has_key (name)
+
+ if isinstance (names, str):
+ return valid_one (names)
+ else:
+ return [ valid_one (name) for name in names ]
+
+# Uses Property
+def __expand_subfeatures_aux (property, dont_validate = False):
+ """ Helper for expand_subfeatures.
+ Given a feature and value, or just a value corresponding to an
+ implicit feature, returns a property set consisting of all component
+ subfeatures and their values. For example:
+
+ expand_subfeatures <toolset>gcc-2.95.2-linux-x86
+ -> <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
+ equivalent to:
+ expand_subfeatures gcc-2.95.2-linux-x86
+
+ feature: The name of the feature, or empty if value corresponds to an implicit property
+ value: The value of the feature.
+ dont_validate: If True, no validation of value string will be done.
+ """
+ f = property.feature()
+ v = property.value()
+ if not dont_validate:
+ validate_value_string(f, v)
+
+ components = v.split ("-")
+
+ v = components[0]
+
+ import property
+
+ result = [property.Property(f, components[0])]
+
+ subvalues = components[1:]
+
+ while len(subvalues) > 0:
+ subvalue = subvalues [0] # pop the head off of subvalues
+ subvalues = subvalues [1:]
+
+ subfeature = __find_implied_subfeature (f, subvalue, v)
+
+ # If no subfeature was found, reconstitute the value string and use that
+ if not subfeature:
+ return [property.Property(f, '-'.join(components))]
+
+ result.append(property.Property(subfeature, subvalue))
+
+ return result
+
+def expand_subfeatures(properties, dont_validate = False):
+ """
+ Make all elements of properties corresponding to implicit features
+ explicit, and express all subfeature values as separate properties
+ in their own right. For example, the property
+
+ gcc-2.95.2-linux-x86
+
+ might expand to
+
+ <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
+
+ properties: A sequence with elements of the form
+ <feature>value-string or just value-string in the
+ case of implicit features.
+ : dont_validate: If True, no validation of value string will be done.
+ """
+ result = []
+ for p in properties:
+ # Don't expand subfeatures in subfeatures
+ if p.feature().subfeature():
+ result.append (p)
+ else:
+ result.extend(__expand_subfeatures_aux (p, dont_validate))
+
+ return result
+
+
+
+# rule extend was defined as below:
+ # Can be called three ways:
+ #
+ # 1. extend feature : values *
+ # 2. extend <feature> subfeature : values *
+ # 3. extend <feature>value-string subfeature : values *
+ #
+ # * Form 1 adds the given values to the given feature
+ # * Forms 2 and 3 add subfeature values to the given feature
+ # * Form 3 adds the subfeature values as specific to the given
+ # property value-string.
+ #
+ #rule extend ( feature-or-property subfeature ? : values * )
+#
+# Now, the specific rule must be called, depending on the desired operation:
+# extend_feature
+# extend_subfeature
+
+def extend (name, values):
+ """ Adds the given values to the given feature.
+ """
+ name = add_grist (name)
+ __validate_feature (name)
+ feature = __all_features [name]
+
+ if feature.implicit():
+ for v in values:
+ if __implicit_features.has_key(v):
+ raise BaseException ("'%s' is already associated with the feature '%s'" % (v, __implicit_features [v]))
+
+ __implicit_features[v] = feature
+
+ if len (feature.values()) == 0 and len (values) > 0:
+ # This is the first value specified for this feature,
+ # take it as default value
+ feature.set_default(values[0])
+
+ feature.add_values(values)
+
+def validate_value_string (f, value_string):
+ """ Checks that value-string is a valid value-string for the given feature.
+ """
+ if f.free() or value_string in f.values():
+ return
+
+ values = [value_string]
+
+ if f.subfeatures():
+ if not value_string in f.values() and \
+ not value_string in f.subfeatures():
+ values = value_string.split('-')
+
+ # An empty value is allowed for optional features
+ if not values[0] in f.values() and \
+ (values[0] or not f.optional()):
+ raise InvalidValue ("'%s' is not a known value of feature '%s'\nlegal values: '%s'" % (values [0], feature, f.values()))
+
+ for v in values [1:]:
+ # this will validate any subfeature values in value-string
+ implied_subfeature(f, v, values[0])
+
+
+""" Extends the given subfeature with the subvalues. If the optional
+ value-string is provided, the subvalues are only valid for the given
+ value of the feature. Thus, you could say that
+ <target-platform>mingw is specifc to <toolset>gcc-2.95.2 as follows:
+
+ extend-subfeature toolset gcc-2.95.2 : target-platform : mingw ;
+
+ feature: The feature whose subfeature is being extended.
+
+ value-string: If supplied, specifies a specific value of the
+ main feature for which the new subfeature values
+ are valid.
+
+ subfeature: The name of the subfeature.
+
+ subvalues: The additional values of the subfeature being defined.
+"""
+def extend_subfeature (feature_name, value_string, subfeature_name, subvalues):
+
+ feature = validate_feature(feature_name)
+
+ if value_string:
+ validate_value_string(feature, value_string)
+
+ subfeature_name = feature_name + '-' + __get_subfeature_name (subfeature_name, value_string)
+
+ extend(subfeature_name, subvalues) ;
+ subfeature = __all_features[subfeature_name]
+
+ if value_string == None: value_string = ''
+
+ if not __subfeature_from_value.has_key(feature):
+ __subfeature_from_value [feature] = {}
+
+ if not __subfeature_from_value[feature].has_key(value_string):
+ __subfeature_from_value [feature][value_string] = {}
+
+ for subvalue in subvalues:
+ __subfeature_from_value [feature][value_string][subvalue] = subfeature
+
+@bjam_signature((["feature_name", "value_string", "?"], ["subfeature"],
+ ["subvalues", "*"], ["attributes", "*"]))
+def subfeature (feature_name, value_string, subfeature, subvalues, attributes = []):
+ """ Declares a subfeature.
+ feature_name: Root feature that is not a subfeature.
+ value_string: An optional value-string specifying which feature or
+ subfeature values this subfeature is specific to,
+ if any.
+ subfeature: The name of the subfeature being declared.
+ subvalues: The allowed values of this subfeature.
+ attributes: The attributes of the subfeature.
+ """
+ parent_feature = validate_feature (feature_name)
+
+ # Add grist to the subfeature name if a value-string was supplied
+ subfeature_name = __get_subfeature_name (subfeature, value_string)
+
+ if subfeature_name in __all_features[feature_name].subfeatures():
+ message = "'%s' already declared as a subfeature of '%s'" % (subfeature, feature_name)
+ message += " specific to '%s'" % value_string
+ raise BaseException (message)
+
+ # First declare the subfeature as a feature in its own right
+ f = feature (feature_name + '-' + subfeature_name, subvalues, attributes + ['subfeature'])
+ f.set_parent(parent_feature, value_string)
+
+ parent_feature.add_subfeature(f)
+
+ # Now make sure the subfeature values are known.
+ extend_subfeature (feature_name, value_string, subfeature, subvalues)
+
+
+@bjam_signature((["composite_property_s"], ["component_properties_s", "*"]))
+def compose (composite_property_s, component_properties_s):
+ """ Sets the components of the given composite property.
+
+ All paremeters are <feature>value strings
+ """
+ import property
+
+ component_properties_s = to_seq (component_properties_s)
+ composite_property = property.create_from_string(composite_property_s)
+ f = composite_property.feature()
+
+ if len(component_properties_s) > 0 and isinstance(component_properties_s[0], property.Property):
+ component_properties = component_properties_s
+ else:
+ component_properties = [property.create_from_string(p) for p in component_properties_s]
+
+ if not f.composite():
+ raise BaseException ("'%s' is not a composite feature" % f)
+
+ if __composite_properties.has_key(property):
+ raise BaseException ('components of "%s" already set: %s' % (composite_property, str (__composite_properties[composite_property])))
+
+ if composite_property in component_properties:
+ raise BaseException ('composite property "%s" cannot have itself as a component' % composite_property)
+
+ __composite_properties[composite_property] = component_properties
+
+
+def expand_composite(property):
+ result = [ property ]
+ if __composite_properties.has_key(property):
+ for p in __composite_properties[property]:
+ result.extend(expand_composite(p))
+ return result
+
+
+def get_values (feature, properties):
+ """ Returns all values of the given feature specified by the given property set.
+ """
+ result = []
+ for p in properties:
+ if get_grist (p) == feature:
+ result.append (replace_grist (p, ''))
+
+ return result
+
+def free_features ():
+ """ Returns all free features.
+ """
+ return __free_features
+
+def expand_composites (properties):
+ """ Expand all composite properties in the set so that all components
+ are explicitly expressed.
+ """
+ explicit_features = set(p.feature() for p in properties)
+
+ result = []
+
+ # now expand composite features
+ for p in properties:
+ expanded = expand_composite(p)
+
+ for x in expanded:
+ if not x in result:
+ f = x.feature()
+
+ if f.free():
+ result.append (x)
+ elif not x in properties: # x is the result of expansion
+ if not f in explicit_features: # not explicitly-specified
+ if any(r.feature() == f for r in result):
+ raise FeatureConflict(
+ "expansions of composite features result in "
+ "conflicting values for '%s'\nvalues: '%s'\none contributing composite property was '%s'" %
+ (f.name(), [r.value() for r in result if r.feature() == f] + [x.value()], p))
+ else:
+ result.append (x)
+ elif any(r.feature() == f for r in result):
+ raise FeatureConflict ("explicitly-specified values of non-free feature '%s' conflict\n"
+ "existing values: '%s'\nvalue from expanding '%s': '%s'" % (f,
+ [r.value() for r in result if r.feature() == f], p, x.value()))
+ else:
+ result.append (x)
+
+ return result
+
+# Uses Property
+def is_subfeature_of (parent_property, f):
+ """ Return true iff f is an ordinary subfeature of the parent_property's
+ feature, or if f is a subfeature of the parent_property's feature
+ specific to the parent_property's value.
+ """
+ if not f.subfeature():
+ return False
+
+ p = f.parent()
+ if not p:
+ return False
+
+ parent_feature = p[0]
+ parent_value = p[1]
+
+ if parent_feature != parent_property.feature():
+ return False
+
+ if parent_value and parent_value != parent_property.value():
+ return False
+
+ return True
+
+def __is_subproperty_of (parent_property, p):
+ """ As is_subfeature_of, for subproperties.
+ """
+ return is_subfeature_of (parent_property, p.feature())
+
+
+# Returns true iff the subvalue is valid for the feature. When the
+# optional value-string is provided, returns true iff the subvalues
+# are valid for the given value of the feature.
+def is_subvalue(feature, value_string, subfeature, subvalue):
+
+ if not value_string:
+ value_string = ''
+
+ if not __subfeature_from_value.has_key(feature):
+ return False
+
+ if not __subfeature_from_value[feature].has_key(value_string):
+ return False
+
+ if not __subfeature_from_value[feature][value_string].has_key(subvalue):
+ return False
+
+ if __subfeature_from_value[feature][value_string][subvalue]\
+ != subfeature:
+ return False
+
+ return True
+
+def implied_subfeature (feature, subvalue, value_string):
+ result = __find_implied_subfeature (feature, subvalue, value_string)
+ if not result:
+ raise InvalidValue ("'%s' is not a known subfeature value of '%s%s'" % (subvalue, feature, value_string))
+
+ return result
+
+
+# Uses Property
+def expand (properties):
+ """ Given a property set which may consist of composite and implicit
+ properties and combined subfeature values, returns an expanded,
+ normalized property set with all implicit features expressed
+ explicitly, all subfeature values individually expressed, and all
+ components of composite properties expanded. Non-free features
+ directly expressed in the input properties cause any values of
+ those features due to composite feature expansion to be dropped. If
+ two values of a given non-free feature are directly expressed in the
+ input, an error is issued.
+ """
+ expanded = expand_subfeatures(properties)
+ return expand_composites (expanded)
+
+# Accepts list of Property objects
+def add_defaults (properties):
+ """ Given a set of properties, add default values for features not
+ represented in the set.
+ Note: if there's there's ordinary feature F1 and composite feature
+ F2, which includes some value for F1, and both feature have default values,
+ then the default value of F1 will be added, not the value in F2. This might
+ not be right idea: consider
+
+ feature variant : debug ... ;
+ <variant>debug : .... <runtime-debugging>on
+ feature <runtime-debugging> : off on ;
+
+ Here, when adding default for an empty property set, we'll get
+
+ <variant>debug <runtime_debugging>off
+
+ and that's kind of strange.
+ """
+ result = [x for x in properties]
+
+ handled_features = set()
+ for p in properties:
+ # We don't add default for conditional properties. We don't want
+ # <variant>debug:<define>DEBUG to be takes as specified value for <variant>
+ if not p.condition():
+ handled_features.add(p.feature())
+
+ missing_top = [f for f in __all_top_features if not f in handled_features]
+ more = defaults(missing_top)
+ result.extend(more)
+ for p in more:
+ handled_features.add(p.feature())
+
+ # Add defaults for subfeatures of features which are present
+ for p in result[:]:
+ s = p.feature().subfeatures()
+ more = defaults([s for s in p.feature().subfeatures() if not s in handled_features])
+ for p in more:
+ handled_features.add(p.feature())
+ result.extend(more)
+
+ return result
+
+def minimize (properties):
+ """ Given an expanded property set, eliminate all redundancy: properties
+ which are elements of other (composite) properties in the set will
+ be eliminated. Non-symmetric properties equal to default values will be
+ eliminated, unless the override a value from some composite property.
+ Implicit properties will be expressed without feature
+ grist, and sub-property values will be expressed as elements joined
+ to the corresponding main property.
+ """
+
+ # remove properties implied by composite features
+ components = []
+ for property in properties:
+ if __composite_properties.has_key (property):
+ components.extend(__composite_properties[property])
+ properties = b2.util.set.difference (properties, components)
+
+ # handle subfeatures and implicit features
+
+ # move subfeatures to the end of the list
+ properties = [p for p in properties if not p.feature().subfeature()] +\
+ [p for p in properties if p.feature().subfeature()]
+
+ result = []
+ while properties:
+ p = properties[0]
+ f = p.feature()
+
+ # locate all subproperties of $(x[1]) in the property set
+ subproperties = __select_subproperties (p, properties)
+
+ if subproperties:
+ # reconstitute the joined property name
+ subproperties.sort ()
+ joined = b2.build.property.Property(p.feature(), p.value() + '-' + '-'.join ([sp.value() for sp in subproperties]))
+ result.append(joined)
+
+ properties = b2.util.set.difference(properties[1:], subproperties)
+
+ else:
+ # eliminate properties whose value is equal to feature's
+ # default and which are not symmetric and which do not
+ # contradict values implied by composite properties.
+
+ # since all component properties of composites in the set
+ # have been eliminated, any remaining property whose
+ # feature is the same as a component of a composite in the
+ # set must have a non-redundant value.
+ if p.value() != f.default() or f.symmetric():
+ result.append (p)
+ #\
+ #or get_grist (fullp) in get_grist (components):
+ # FIXME: restore above
+
+
+ properties = properties[1:]
+
+ return result
+
+
+def split (properties):
+ """ Given a property-set of the form
+ v1/v2/...vN-1/<fN>vN/<fN+1>vN+1/...<fM>vM
+
+ Returns
+ v1 v2 ... vN-1 <fN>vN <fN+1>vN+1 ... <fM>vM
+
+ Note that vN...vM may contain slashes. This is resilient to the
+ substitution of backslashes for slashes, since Jam, unbidden,
+ sometimes swaps slash direction on NT.
+ """
+
+ def split_one (properties):
+ pieces = re.split (__re_slash_or_backslash, properties)
+ result = []
+
+ for x in pieces:
+ if not get_grist (x) and len (result) > 0 and get_grist (result [-1]):
+ result = result [0:-1] + [ result [-1] + '/' + x ]
+ else:
+ result.append (x)
+
+ return result
+
+ if isinstance (properties, str):
+ return split_one (properties)
+
+ result = []
+ for p in properties:
+ result += split_one (p)
+ return result
+
+
+def compress_subproperties (properties):
+ """ Combine all subproperties into their parent properties
+
+ Requires: for every subproperty, there is a parent property. All
+ features are explicitly expressed.
+
+ This rule probably shouldn't be needed, but
+ build-request.expand-no-defaults is being abused for unintended
+ purposes and it needs help
+ """
+ result = []
+ matched_subs = set()
+ all_subs = set()
+ for p in properties:
+ f = p.feature()
+
+ if not f.subfeature():
+ subs = __select_subproperties (p, properties)
+ if subs:
+
+ matched_subs.update(subs)
+
+ subvalues = '-'.join (sub.value() for sub in subs)
+ result.append(b2.build.property.Property(
+ p.feature(), p.value() + '-' + subvalues,
+ p.condition()))
+ else:
+ result.append(p)
+
+ else:
+ all_subs.add(p)
+
+ # TODO: this variables are used just for debugging. What's the overhead?
+ assert all_subs == matched_subs
+
+ return result
+
+######################################################################################
+# Private methods
+
+def __select_subproperties (parent_property, properties):
+ return [ x for x in properties if __is_subproperty_of (parent_property, x) ]
+
+def __get_subfeature_name (subfeature, value_string):
+ if value_string == None:
+ prefix = ''
+ else:
+ prefix = value_string + ':'
+
+ return prefix + subfeature
+
+
+def __validate_feature_attributes (name, attributes):
+ for attribute in attributes:
+ if not attribute in __all_attributes:
+ raise InvalidAttribute ("unknown attributes: '%s' in feature declaration: '%s'" % (str (b2.util.set.difference (attributes, __all_attributes)), name))
+
+ if name in __all_features:
+ raise AlreadyDefined ("feature '%s' already defined" % name)
+ elif 'implicit' in attributes and 'free' in attributes:
+ raise InvalidAttribute ("free features cannot also be implicit (in declaration of feature '%s')" % name)
+ elif 'free' in attributes and 'propagated' in attributes:
+ raise InvalidAttribute ("free features cannot also be propagated (in declaration of feature '%s')" % name)
+
+
+def __validate_feature (feature):
+ """ Generates an error if the feature is unknown.
+ """
+ if not __all_features.has_key (feature):
+ raise BaseException ('unknown feature "%s"' % feature)
+
+
+def __select_subfeatures (parent_property, features):
+ """ Given a property, return the subset of features consisting of all
+ ordinary subfeatures of the property's feature, and all specific
+ subfeatures of the property's feature which are conditional on the
+ property's value.
+ """
+ return [f for f in features if is_subfeature_of (parent_property, f)]
+
+# FIXME: copy over tests.
diff --git a/tools/build/v2/build/generators.jam b/tools/build/v2/build/generators.jam
new file mode 100644
index 0000000000..1515525f2d
--- /dev/null
+++ b/tools/build/v2/build/generators.jam
@@ -0,0 +1,1408 @@
+# Copyright Vladimir Prus 2002.
+# Copyright Rene Rivera 2006.
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Manages 'generators' --- objects which can do transformation between different
+# target types and contain algorithm for finding transformation from sources to
+# targets.
+#
+# The main entry point to this module is generators.construct rule. It is given
+# a list of source targets, desired target type and a set of properties. It
+# starts by selecting 'viable generators', which have any chances of producing
+# the desired target type with the required properties. Generators are ranked
+# and a set of the most specific ones is selected.
+#
+# The most specific generators have their 'run' methods called, with the
+# properties and list of sources. Each one selects a target which can be
+# directly consumed, and tries to convert the remaining ones to the types it can
+# consume. This is done by recursively calling 'construct' with all consumable
+# types.
+#
+# If the generator has collected all the targets it needs, it creates targets
+# corresponding to result, and returns it. When all generators have been run,
+# results of one of them are selected and returned as a result.
+#
+# It is quite possible for 'construct' to return more targets that it was asked
+# for. For example, if it were asked to generate a target of type EXE, but the
+# only found generator produces both EXE and TDS (file with debug) information.
+# The extra target will be returned.
+#
+# Likewise, when generator tries to convert sources to consumable types, it can
+# get more targets that it was asked for. The question is what to do with extra
+# targets. Boost.Build attempts to convert them to requested types, and attempts
+# that as early as possible. Specifically, this is done after invoking each
+# generator. TODO: An example is needed to document the rationale for trying
+# extra target conversion at that point.
+#
+# In order for the system to be able to use a specific generator instance 'when
+# needed', the instance needs to be registered with the system using
+# generators.register() or one of its related rules. Unregistered generators may
+# only be run explicitly and will not be considered by Boost.Build when when
+# converting between given target types.
+
+import "class" : new ;
+import errors ;
+import property-set ;
+import sequence ;
+import set ;
+import type ;
+import utility ;
+import virtual-target ;
+
+
+if "--debug-generators" in [ modules.peek : ARGV ]
+{
+ .debug = true ;
+}
+
+
+# Updated cached viable source target type information as needed after a new
+# target type gets defined. This is needed because if a target type is a viable
+# source target type for some generator then all of the target type's derived
+# target types should automatically be considered as viable source target types
+# for the same generator as well. Does nothing if a non-derived target type is
+# passed to it.
+#
+rule update-cached-information-with-a-new-type ( type )
+{
+ local base-type = [ type.base $(type) ] ;
+ if $(base-type)
+ {
+ for local g in $(.vstg-cached-generators)
+ {
+ if $(base-type) in $(.vstg.$(g))
+ {
+ .vstg.$(g) += $(type) ;
+ }
+ }
+
+ for local t in $(.vst-cached-types)
+ {
+ if $(base-type) in $(.vst.$(t))
+ {
+ .vst.$(t) += $(type) ;
+ }
+ }
+ }
+}
+
+
+# Clears cached viable source target type information except for target types
+# and generators with all source types listed as viable. Should be called when
+# something invalidates those cached values by possibly causing some new source
+# types to become viable.
+#
+local rule invalidate-extendable-viable-source-target-type-cache ( )
+{
+ local generators-with-cached-source-types = $(.vstg-cached-generators) ;
+ .vstg-cached-generators = ;
+ for local g in $(generators-with-cached-source-types)
+ {
+ if $(.vstg.$(g)) = *
+ {
+ .vstg-cached-generators += $(g) ;
+ }
+ else
+ {
+ .vstg.$(g) = ;
+ }
+ }
+
+ local types-with-cached-source-types = $(.vst-cached-types) ;
+ .vst-cached-types = ;
+ for local t in $(types-with-cached-source-types)
+ {
+ if $(.vst.$(t)) = *
+ {
+ .vst-cached-types += $(t) ;
+ }
+ else
+ {
+ .vst.$(t) = ;
+ }
+ }
+}
+
+
+# Outputs a debug message if generators debugging is on. Each element of
+# 'message' is checked to see if it is a class instance. If so, instead of the
+# value, the result of 'str' call is output.
+#
+local rule generators.dout ( message * )
+{
+ if $(.debug)
+ {
+ ECHO [ sequence.transform utility.str : $(message) ] ;
+ }
+}
+
+
+local rule indent ( )
+{
+ return $(.indent:J="") ;
+}
+
+
+local rule increase-indent ( )
+{
+ .indent += " " ;
+}
+
+
+local rule decrease-indent ( )
+{
+ .indent = $(.indent[2-]) ;
+}
+
+
+# Models a generator.
+#
+class generator
+{
+ import generators : indent increase-indent decrease-indent generators.dout ;
+ import set ;
+ import utility ;
+ import feature ;
+ import errors ;
+ import sequence ;
+ import type ;
+ import virtual-target ;
+ import "class" : new ;
+ import property ;
+ import path ;
+
+ EXPORT class@generator : indent increase-indent decrease-indent
+ generators.dout ;
+
+ rule __init__ (
+ id # Identifies the generator - should be name
+ # of the rule which sets up the build
+ # actions.
+
+ composing ? # Whether generator processes each source
+ # target in turn, converting it to required
+ # types. Ordinary generators pass all
+ # sources together to the recursive
+ # generators.construct-types call.
+
+ : source-types * # Types that this generator can handle. If
+ # empty, the generator can consume anything.
+
+ : target-types-and-names + # Types the generator will create and,
+ # optionally, names for created targets.
+ # Each element should have the form
+ # type["(" name-pattern ")"], for example,
+ # obj(%_x). Generated target name will be
+ # found by replacing % with the name of
+ # source, provided an explicit name was not
+ # specified.
+
+ : requirements *
+ )
+ {
+ self.id = $(id) ;
+ self.rule-name = $(id) ;
+ self.composing = $(composing) ;
+ self.source-types = $(source-types) ;
+ self.target-types-and-names = $(target-types-and-names) ;
+ self.requirements = $(requirements) ;
+
+ for local e in $(target-types-and-names)
+ {
+ # Create three parallel lists: one with the list of target types,
+ # and two other with prefixes and postfixes to be added to target
+ # name. We use parallel lists for prefix and postfix (as opposed to
+ # mapping), because given target type might occur several times, for
+ # example "H H(%_symbols)".
+ local m = [ MATCH ([^\\(]*)(\\((.*)%(.*)\\))? : $(e) ] ;
+ self.target-types += $(m[1]) ;
+ self.name-prefix += $(m[3]:E="") ;
+ self.name-postfix += $(m[4]:E="") ;
+ }
+
+ # Note that 'transform' here, is the same as 'for_each'.
+ sequence.transform type.validate : $(self.source-types) ;
+ sequence.transform type.validate : $(self.target-types) ;
+ }
+
+ ################# End of constructor #################
+
+ rule id ( )
+ {
+ return $(self.id) ;
+ }
+
+ # Returns the list of target type the generator accepts.
+ #
+ rule source-types ( )
+ {
+ return $(self.source-types) ;
+ }
+
+ # Returns the list of target types that this generator produces. It is
+ # assumed to be always the same -- i.e. it can not change depending on some
+ # provided list of sources.
+ #
+ rule target-types ( )
+ {
+ return $(self.target-types) ;
+ }
+
+ # Returns the required properties for this generator. Properties in returned
+ # set must be present in build properties if this generator is to be used.
+ # If result has grist-only element, that build properties must include some
+ # value of that feature.
+ #
+ # XXX: remove this method?
+ #
+ rule requirements ( )
+ {
+ return $(self.requirements) ;
+ }
+
+ rule set-rule-name ( rule-name )
+ {
+ self.rule-name = $(rule-name) ;
+ }
+
+ rule rule-name ( )
+ {
+ return $(self.rule-name) ;
+ }
+
+ # Returns a true value if the generator can be run with the specified
+ # properties.
+ #
+ rule match-rank ( property-set-to-match )
+ {
+ # See if generator requirements are satisfied by 'properties'. Treat a
+ # feature name in requirements (i.e. grist-only element), as matching
+ # any value of the feature.
+ local all-requirements = [ requirements ] ;
+
+ local property-requirements feature-requirements ;
+ for local r in $(all-requirements)
+ {
+ if $(r:G=)
+ {
+ property-requirements += $(r) ;
+ }
+ else
+ {
+ feature-requirements += $(r) ;
+ }
+ }
+
+ local properties-to-match = [ $(property-set-to-match).raw ] ;
+ if $(property-requirements) in $(properties-to-match) &&
+ $(feature-requirements) in $(properties-to-match:G)
+ {
+ return true ;
+ }
+ else
+ {
+ return ;
+ }
+ }
+
+ # Returns another generator which differs from $(self) in
+ # - id
+ # - value to <toolset> feature in properties
+ #
+ rule clone ( new-id : new-toolset-properties + )
+ {
+ local g = [ new $(__class__) $(new-id) $(self.composing) :
+ $(self.source-types) : $(self.target-types-and-names) :
+ # Note: this does not remove any subfeatures of <toolset> which
+ # might cause problems.
+ [ property.change $(self.requirements) : <toolset> ]
+ $(new-toolset-properties) ] ;
+ return $(g) ;
+ }
+
+ # Creates another generator that is the same as $(self), except that if
+ # 'base' is in target types of $(self), 'type' will in target types of the
+ # new generator.
+ #
+ rule clone-and-change-target-type ( base : type )
+ {
+ local target-types ;
+ for local t in $(self.target-types-and-names)
+ {
+ local m = [ MATCH ([^\\(]*)(\\(.*\\))? : $(t) ] ;
+ if $(m) = $(base)
+ {
+ target-types += $(type)$(m[2]:E="") ;
+ }
+ else
+ {
+ target-types += $(t) ;
+ }
+ }
+
+ local g = [ new $(__class__) $(self.id) $(self.composing) :
+ $(self.source-types) : $(target-types) : $(self.requirements) ] ;
+ if $(self.rule-name)
+ {
+ $(g).set-rule-name $(self.rule-name) ;
+ }
+ return $(g) ;
+ }
+
+ # Tries to invoke this generator on the given sources. Returns a list of
+ # generated targets (instances of 'virtual-target') and optionally a set of
+ # properties to be added to the usage-requirements for all the generated
+ # targets. Returning nothing from run indicates that the generator was
+ # unable to create the target.
+ #
+ rule run
+ (
+ project # Project for which the targets are generated.
+ name ? # Used when determining the 'name' attribute for all
+ # generated targets. See the 'generated-targets' method.
+ : property-set # Desired properties for generated targets.
+ : sources + # Source targets.
+ )
+ {
+ generators.dout [ indent ] " ** generator" $(self.id) ;
+ generators.dout [ indent ] " composing:" $(self.composing) ;
+
+ if ! $(self.composing) && $(sources[2]) && $(self.source-types[2])
+ {
+ errors.error "Unsupported source/source-type combination" ;
+ }
+
+ # We do not run composing generators if no name is specified. The reason
+ # is that composing generator combines several targets, which can have
+ # different names, and it cannot decide which name to give for produced
+ # target. Therefore, the name must be passed.
+ #
+ # This in effect, means that composing generators are runnable only at
+ # the top-level of a transformation graph, or if their name is passed
+ # explicitly. Thus, we dissallow composing generators in the middle. For
+ # example, the transformation CPP -> OBJ -> STATIC_LIB -> RSP -> EXE
+ # will not be allowed as the OBJ -> STATIC_LIB generator is composing.
+ if ! $(self.composing) || $(name)
+ {
+ run-really $(project) $(name) : $(property-set) : $(sources) ;
+ }
+ }
+
+ rule run-really ( project name ? : property-set : sources + )
+ {
+ # Targets that this generator will consume directly.
+ local consumed = ;
+ # Targets that can not be consumed and will be returned as-is.
+ local bypassed = ;
+
+ if $(self.composing)
+ {
+ convert-multiple-sources-to-consumable-types $(project)
+ : $(property-set) : $(sources) : consumed bypassed ;
+ }
+ else
+ {
+ convert-to-consumable-types $(project) $(name) : $(property-set)
+ : $(sources) : : consumed bypassed ;
+ }
+
+ local result ;
+ if $(consumed)
+ {
+ result = [ construct-result $(consumed) : $(project) $(name) :
+ $(property-set) ] ;
+ }
+
+ if $(result)
+ {
+ generators.dout [ indent ] " SUCCESS: " $(result) ;
+ }
+ else
+ {
+ generators.dout [ indent ] " FAILURE" ;
+ }
+ generators.dout ;
+ return $(result) ;
+ }
+
+ # Constructs the dependency graph to be returned by this generator.
+ #
+ rule construct-result
+ (
+ consumed + # Already prepared list of consumable targets.
+ # Composing generators may receive multiple sources
+ # all of which will have types matching those in
+ # $(self.source-types). Non-composing generators with
+ # multiple $(self.source-types) will receive exactly
+ # len $(self.source-types) sources with types matching
+ # those in $(self.source-types). And non-composing
+ # generators with only a single source type may
+ # receive multiple sources with all of them of the
+ # type listed in $(self.source-types).
+ : project name ?
+ : property-set # Properties to be used for all actions created here.
+ )
+ {
+ local result ;
+ # If this is 1->1 transformation, apply it to all consumed targets in
+ # order.
+ if ! $(self.source-types[2]) && ! $(self.composing)
+ {
+ for local r in $(consumed)
+ {
+ result += [ generated-targets $(r) : $(property-set) :
+ $(project) $(name) ] ;
+ }
+ }
+ else if $(consumed)
+ {
+ result += [ generated-targets $(consumed) : $(property-set) :
+ $(project) $(name) ] ;
+ }
+ return $(result) ;
+ }
+
+ # Determine target name from fullname (maybe including path components)
+ # Place optional prefix and postfix around basename
+ #
+ rule determine-target-name ( fullname : prefix ? : postfix ? )
+ {
+ # See if we need to add directory to the target name.
+ local dir = $(fullname:D) ;
+ local name = $(fullname:B) ;
+
+ name = $(prefix:E=)$(name) ;
+ name = $(name)$(postfix:E=) ;
+
+ if $(dir) &&
+ # Never append '..' to target path.
+ ! [ MATCH .*(\\.\\.).* : $(dir) ]
+ &&
+ ! [ path.is-rooted $(dir) ]
+ {
+ # Relative path is always relative to the source
+ # directory. Retain it, so that users can have files
+ # with the same in two different subdirectories.
+ name = $(dir)/$(name) ;
+ }
+ return $(name) ;
+ }
+
+ # Determine the name of the produced target from the names of the sources.
+ #
+ rule determine-output-name ( sources + )
+ {
+ # The simple case if when a name of source has single dot. Then, we take
+ # the part before dot. Several dots can be caused by:
+ # - using source file like a.host.cpp, or
+ # - a type whose suffix has a dot. Say, we can type 'host_cpp' with
+ # extension 'host.cpp'.
+ # In the first case, we want to take the part up to the last dot. In the
+ # second case -- not sure, but for now take the part up to the last dot
+ # too.
+ name = [ utility.basename [ $(sources[1]).name ] ] ;
+
+ for local s in $(sources[2])
+ {
+ local n2 = [ utility.basename [ $(s).name ] ] ;
+ if $(n2) != $(name)
+ {
+ errors.error "$(self.id): source targets have different names: cannot determine target name" ;
+ }
+ }
+ name = [ determine-target-name [ $(sources[1]).name ] ] ;
+ return $(name) ;
+ }
+
+ # Constructs targets that are created after consuming 'sources'. The result
+ # will be the list of virtual-target, which has the same length as the
+ # 'target-types' attribute and with corresponding types.
+ #
+ # When 'name' is empty, all source targets must have the same 'name'
+ # attribute value, which will be used instead of the 'name' argument.
+ #
+ # The 'name' attribute value for each generated target will be equal to
+ # the 'name' parameter if there is no name pattern for this type. Otherwise,
+ # the '%' symbol in the name pattern will be replaced with the 'name'
+ # parameter to obtain the 'name' attribute.
+ #
+ # For example, if targets types are T1 and T2 (with name pattern "%_x"),
+ # suffixes for T1 and T2 are .t1 and .t2, and source is foo.z, then created
+ # files would be "foo.t1" and "foo_x.t2". The 'name' attribute actually
+ # determines the basename of a file.
+ #
+ # Note that this pattern mechanism has nothing to do with implicit patterns
+ # in make. It is a way to produce a target whose name is different than the
+ # name of its source.
+ #
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ if ! $(name)
+ {
+ name = [ determine-output-name $(sources) ] ;
+ }
+
+ # Assign an action for each target.
+ local action = [ action-class ] ;
+ local a = [ class.new $(action) $(sources) : $(self.rule-name) :
+ $(property-set) ] ;
+
+ # Create generated target for each target type.
+ local targets ;
+ local pre = $(self.name-prefix) ;
+ local post = $(self.name-postfix) ;
+ for local t in $(self.target-types)
+ {
+ local generated-name = $(pre[1])$(name:BS)$(post[1]) ;
+ generated-name = $(generated-name:R=$(name:D)) ;
+ pre = $(pre[2-]) ;
+ post = $(post[2-]) ;
+
+ targets += [ class.new file-target $(generated-name) : $(t) :
+ $(project) : $(a) ] ;
+ }
+
+ return [ sequence.transform virtual-target.register : $(targets) ] ;
+ }
+
+ # Attempts to convert 'sources' to targets of types that this generator can
+ # handle. The intention is to produce the set of targets that can be used
+ # when the generator is run.
+ #
+ rule convert-to-consumable-types
+ (
+ project name ?
+ : property-set
+ : sources +
+ : only-one ? # Convert 'source' to only one of the source types. If
+ # there is more that one possibility, report an error.
+ : consumed-var # Name of the variable which receives all targets which
+ # can be consumed.
+ bypassed-var # Name of the variable which receives all targets which
+ # can not be consumed.
+ )
+ {
+ # We are likely to be passed 'consumed' and 'bypassed' var names. Use
+ # '_' to avoid name conflicts.
+ local _consumed ;
+ local _bypassed ;
+ local missing-types ;
+
+ if $(sources[2])
+ {
+ # Do not know how to handle several sources yet. Just try to pass
+ # the request to other generator.
+ missing-types = $(self.source-types) ;
+ }
+ else
+ {
+ consume-directly $(sources) : _consumed : missing-types ;
+ }
+
+ # No need to search for transformation if some source type has consumed
+ # source and no more source types are needed.
+ if $(only-one) && $(_consumed)
+ {
+ missing-types = ;
+ }
+
+ # TODO: we should check that only one source type if create of
+ # 'only-one' is true.
+ # TODO: consider if consumed/bypassed separation should be done by
+ # 'construct-types'.
+
+ if $(missing-types)
+ {
+ local transformed = [ generators.construct-types $(project) $(name)
+ : $(missing-types) : $(property-set) : $(sources) ] ;
+
+ # Add targets of right type to 'consumed'. Add others to 'bypassed'.
+ # The 'generators.construct' rule has done its best to convert
+ # everything to the required type. There is no need to rerun it on
+ # targets of different types.
+
+ # NOTE: ignoring usage requirements.
+ for local t in $(transformed[2-])
+ {
+ if [ $(t).type ] in $(missing-types)
+ {
+ _consumed += $(t) ;
+ }
+ else
+ {
+ _bypassed += $(t) ;
+ }
+ }
+ }
+
+ _consumed = [ sequence.unique $(_consumed) ] ;
+ _bypassed = [ sequence.unique $(_bypassed) ] ;
+
+ # Remove elements of '_bypassed' that are in '_consumed'.
+
+ # Suppose the target type of current generator, X is produced from X_1
+ # and X_2, which are produced from Y by one generator. When creating X_1
+ # from Y, X_2 will be added to 'bypassed'. Likewise, when creating X_2
+ # from Y, X_1 will be added to 'bypassed', but they are also in
+ # 'consumed'. We have to remove them from bypassed, so that generators
+ # up the call stack do not try to convert them.
+
+ # In this particular case, X_1 instance in 'consumed' and X_1 instance
+ # in 'bypassed' will be the same: because they have the same source and
+ # action name, and 'virtual-target.register' will not allow two
+ # different instances. Therefore, it is OK to use 'set.difference'.
+
+ _bypassed = [ set.difference $(_bypassed) : $(_consumed) ] ;
+
+ $(consumed-var) += $(_consumed) ;
+ $(bypassed-var) += $(_bypassed) ;
+ }
+
+ # Converts several files to consumable types. Called for composing
+ # generators only.
+ #
+ rule convert-multiple-sources-to-consumable-types ( project : property-set :
+ sources * : consumed-var bypassed-var )
+ {
+ # We process each source one-by-one, trying to convert it to a usable
+ # type.
+ for local source in $(sources)
+ {
+ local _c ;
+ local _b ;
+ # TODO: need to check for failure on each source.
+ convert-to-consumable-types $(project) : $(property-set) : $(source)
+ : true : _c _b ;
+ if ! $(_c)
+ {
+ generators.dout [ indent ] " failed to convert " $(source) ;
+ }
+ $(consumed-var) += $(_c) ;
+ $(bypassed-var) += $(_b) ;
+ }
+ }
+
+ rule consume-directly ( source : consumed-var : missing-types-var )
+ {
+ local real-source-type = [ $(source).type ] ;
+
+ # If there are no source types, we can consume anything.
+ local source-types = $(self.source-types) ;
+ source-types ?= $(real-source-type) ;
+
+ for local st in $(source-types)
+ {
+ # The 'source' if of the right type already.
+ if $(real-source-type) = $(st) || [ type.is-derived
+ $(real-source-type) $(st) ]
+ {
+ $(consumed-var) += $(source) ;
+ }
+ else
+ {
+ $(missing-types-var) += $(st) ;
+ }
+ }
+ }
+
+ # Returns the class to be used to actions. Default implementation returns
+ # "action".
+ #
+ rule action-class ( )
+ {
+ return "action" ;
+ }
+}
+
+
+# Registers a new generator instance 'g'.
+#
+rule register ( g )
+{
+ .all-generators += $(g) ;
+
+ # A generator can produce several targets of the same type. We want unique
+ # occurrence of that generator in .generators.$(t) in that case, otherwise,
+ # it will be tried twice and we will get a false ambiguity.
+ for local t in [ sequence.unique [ $(g).target-types ] ]
+ {
+ .generators.$(t) += $(g) ;
+ }
+
+ # Update the set of generators for toolset.
+
+ # TODO: should we check that generator with this id is not already
+ # registered. For example, the fop.jam module intentionally declared two
+ # generators with the same id, so such check will break it.
+ local id = [ $(g).id ] ;
+
+ # Some generators have multiple periods in their name, so a simple $(id:S=)
+ # will not generate the right toolset name. E.g. if id = gcc.compile.c++,
+ # then .generators-for-toolset.$(id:S=) will append to
+ # .generators-for-toolset.gcc.compile, which is a separate value from
+ # .generators-for-toolset.gcc. Correcting this makes generator inheritance
+ # work properly. See also inherit-generators in the toolset module.
+ local base = $(id) ;
+ while $(base:S)
+ {
+ base = $(base:B) ;
+ }
+ .generators-for-toolset.$(base) += $(g) ;
+
+
+ # After adding a new generator that can construct new target types, we need
+ # to clear the related cached viable source target type information for
+ # constructing a specific target type or using a specific generator. Cached
+ # viable source target type lists affected by this are those containing any
+ # of the target types constructed by the new generator or any of their base
+ # target types.
+ #
+ # A more advanced alternative to clearing that cached viable source target
+ # type information would be to expand it with additional source types or
+ # even better - mark it as needing to be expanded on next use.
+ #
+ # Also see the http://thread.gmane.org/gmane.comp.lib.boost.build/19077
+ # mailing list thread for an even more advanced idea of how we could convert
+ # Boost Build's Jamfile processing, target selection and generator selection
+ # into separate steps which would prevent these caches from ever being
+ # invalidated.
+ #
+ # For now we just clear all the cached viable source target type information
+ # that does not simply state 'all types' and may implement a more detailed
+ # algorithm later on if it becomes needed.
+
+ invalidate-extendable-viable-source-target-type-cache ;
+}
+
+
+# Creates a new non-composing 'generator' class instance and registers it.
+# Returns the created instance. Rationale: the instance is returned so that it
+# is possible to first register a generator and then call its 'run' method,
+# bypassing the whole generator selection process.
+#
+rule register-standard ( id : source-types * : target-types + : requirements * )
+{
+ local g = [ new generator $(id) : $(source-types) : $(target-types) :
+ $(requirements) ] ;
+ register $(g) ;
+ return $(g) ;
+}
+
+
+# Creates a new composing 'generator' class instance and registers it.
+#
+rule register-composing ( id : source-types * : target-types + : requirements *
+ )
+{
+ local g = [ new generator $(id) true : $(source-types) : $(target-types) :
+ $(requirements) ] ;
+ register $(g) ;
+ return $(g) ;
+}
+
+
+# Returns all generators belonging to the given 'toolset', i.e. whose ids are
+# '$(toolset).<something>'.
+#
+rule generators-for-toolset ( toolset )
+{
+ return $(.generators-for-toolset.$(toolset)) ;
+}
+
+
+# Make generator 'overrider-id' be preferred to 'overridee-id'. If, when
+# searching for generators that could produce a target of a certain type, both
+# those generators are among viable generators, the overridden generator is
+# immediately discarded.
+#
+# The overridden generators are discarded immediately after computing the list
+# of viable generators but before running any of them.
+#
+rule override ( overrider-id : overridee-id )
+{
+ .override.$(overrider-id) += $(overridee-id) ;
+}
+
+
+# Returns a list of source type which can possibly be converted to 'target-type'
+# by some chain of generator invocation.
+#
+# More formally, takes all generators for 'target-type' and returns a union of
+# source types for those generators and result of calling itself recursively on
+# source types.
+#
+# Returns '*' in case any type should be considered a viable source type for the
+# given type.
+#
+local rule viable-source-types-real ( target-type )
+{
+ local result ;
+
+ # 't0' is the initial list of target types we need to process to get a list
+ # of their viable source target types. New target types will not be added to
+ # this list.
+ local t0 = [ type.all-bases $(target-type) ] ;
+
+ # 't' is the list of target types which have not yet been processed to get a
+ # list of their viable source target types. This list will get expanded as
+ # we locate more target types to process.
+ local t = $(t0) ;
+
+ while $(t)
+ {
+ # Find all generators for the current type. Unlike
+ # 'find-viable-generators' we do not care about the property-set.
+ local generators = $(.generators.$(t[1])) ;
+ t = $(t[2-]) ;
+
+ while $(generators)
+ {
+ local g = $(generators[1]) ;
+ generators = $(generators[2-]) ;
+
+ if ! [ $(g).source-types ]
+ {
+ # Empty source types -- everything can be accepted.
+ result = * ;
+ # This will terminate this loop.
+ generators = ;
+ # This will terminate the outer loop.
+ t = ;
+ }
+
+ for local source-type in [ $(g).source-types ]
+ {
+ if ! $(source-type) in $(result)
+ {
+ # If a generator accepts a 'source-type' it will also
+ # happily accept any type derived from it.
+ for local n in [ type.all-derived $(source-type) ]
+ {
+ if ! $(n) in $(result)
+ {
+ # Here there is no point in adding target types to
+ # the list of types to process in case they are or
+ # have already been on that list. We optimize this
+ # check by realizing that we only need to avoid the
+ # original target type's base types. Other target
+ # types that are or have been on the list of target
+ # types to process have been added to the 'result'
+ # list as well and have thus already been eliminated
+ # by the previous if.
+ if ! $(n) in $(t0)
+ {
+ t += $(n) ;
+ }
+ result += $(n) ;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return $(result) ;
+}
+
+
+# Helper rule, caches the result of 'viable-source-types-real'.
+#
+rule viable-source-types ( target-type )
+{
+ local key = .vst.$(target-type) ;
+ if ! $($(key))
+ {
+ .vst-cached-types += $(target-type) ;
+ local v = [ viable-source-types-real $(target-type) ] ;
+ if ! $(v)
+ {
+ v = none ;
+ }
+ $(key) = $(v) ;
+ }
+
+ if $($(key)) != none
+ {
+ return $($(key)) ;
+ }
+}
+
+
+# Returns the list of source types, which, when passed to 'run' method of
+# 'generator', has some change of being eventually used (probably after
+# conversion by other generators).
+#
+# Returns '*' in case any type should be considered a viable source type for the
+# given generator.
+#
+rule viable-source-types-for-generator-real ( generator )
+{
+ local source-types = [ $(generator).source-types ] ;
+ if ! $(source-types)
+ {
+ # If generator does not specify any source types, it might be a special
+ # generator like builtin.lib-generator which just relays to other
+ # generators. Return '*' to indicate that any source type is possibly
+ # OK, since we do not know for sure.
+ return * ;
+ }
+ else
+ {
+ local result ;
+ while $(source-types)
+ {
+ local s = $(source-types[1]) ;
+ source-types = $(source-types[2-]) ;
+ local viable-sources = [ generators.viable-source-types $(s) ] ;
+ if $(viable-sources) = *
+ {
+ result = * ;
+ source-types = ; # Terminate the loop.
+ }
+ else
+ {
+ result += [ type.all-derived $(s) ] $(viable-sources) ;
+ }
+ }
+ return [ sequence.unique $(result) ] ;
+ }
+}
+
+
+# Helper rule, caches the result of 'viable-source-types-for-generator'.
+#
+local rule viable-source-types-for-generator ( generator )
+{
+ local key = .vstg.$(generator) ;
+ if ! $($(key))
+ {
+ .vstg-cached-generators += $(generator) ;
+ local v = [ viable-source-types-for-generator-real $(generator) ] ;
+ if ! $(v)
+ {
+ v = none ;
+ }
+ $(key) = $(v) ;
+ }
+
+ if $($(key)) != none
+ {
+ return $($(key)) ;
+ }
+}
+
+
+# Returns usage requirements + list of created targets.
+#
+local rule try-one-generator-really ( project name ? : generator : target-type
+ : property-set : sources * )
+{
+ local targets =
+ [ $(generator).run $(project) $(name) : $(property-set) : $(sources) ] ;
+
+ local usage-requirements ;
+ local success ;
+
+ generators.dout [ indent ] returned $(targets) ;
+
+ if $(targets)
+ {
+ success = true ;
+
+ if [ class.is-a $(targets[1]) : property-set ]
+ {
+ usage-requirements = $(targets[1]) ;
+ targets = $(targets[2-]) ;
+ }
+ else
+ {
+ usage-requirements = [ property-set.empty ] ;
+ }
+ }
+
+ generators.dout [ indent ] " generator" [ $(generator).id ] " spawned " ;
+ generators.dout [ indent ] " " $(targets) ;
+ if $(usage-requirements)
+ {
+ generators.dout [ indent ] " with usage requirements:" $(x) ;
+ }
+
+ if $(success)
+ {
+ return $(usage-requirements) $(targets) ;
+ }
+}
+
+
+# Checks if generator invocation can be pruned, because it is guaranteed to
+# fail. If so, quickly returns an empty list. Otherwise, calls
+# try-one-generator-really.
+#
+local rule try-one-generator ( project name ? : generator : target-type
+ : property-set : sources * )
+{
+ local source-types ;
+ for local s in $(sources)
+ {
+ source-types += [ $(s).type ] ;
+ }
+ local viable-source-types = [ viable-source-types-for-generator $(generator)
+ ] ;
+
+ if $(source-types) && $(viable-source-types) != * &&
+ ! [ set.intersection $(source-types) : $(viable-source-types) ]
+ {
+ local id = [ $(generator).id ] ;
+ generators.dout [ indent ] " ** generator '$(id)' pruned" ;
+ #generators.dout [ indent ] "source-types" '$(source-types)' ;
+ #generators.dout [ indent ] "viable-source-types" '$(viable-source-types)' ;
+ }
+ else
+ {
+ return [ try-one-generator-really $(project) $(name) : $(generator) :
+ $(target-type) : $(property-set) : $(sources) ] ;
+ }
+}
+
+
+rule construct-types ( project name ? : target-types + : property-set
+ : sources + )
+{
+ local result ;
+ local matched-types ;
+ local usage-requirements = [ property-set.empty ] ;
+ for local t in $(target-types)
+ {
+ local r = [ construct $(project) $(name) : $(t) : $(property-set) :
+ $(sources) ] ;
+ if $(r)
+ {
+ usage-requirements = [ $(usage-requirements).add $(r[1]) ] ;
+ result += $(r[2-]) ;
+ matched-types += $(t) ;
+ }
+ }
+ # TODO: have to introduce parameter controlling if several types can be
+ # matched and add appropriate checks.
+
+ # TODO: need to review the documentation for 'construct' to see if it should
+ # return $(source) even if nothing can be done with it. Currents docs seem
+ # to imply that, contrary to the behaviour.
+ if $(result)
+ {
+ return $(usage-requirements) $(result) ;
+ }
+ else
+ {
+ return $(usage-requirements) $(sources) ;
+ }
+}
+
+
+# Ensures all 'targets' have their type. If this is not so, exists with error.
+#
+local rule ensure-type ( targets * )
+{
+ for local t in $(targets)
+ {
+ if ! [ $(t).type ]
+ {
+ errors.error "target" [ $(t).str ] "has no type" ;
+ }
+ }
+}
+
+
+# Returns generators which can be used to construct target of specified type
+# with specified properties. Uses the following algorithm:
+# - iterates over requested target-type and all its bases (in the order returned
+# by type.all-bases).
+# - for each type find all generators that generate that type and whose
+# requirements are satisfied by properties.
+# - if the set of generators is not empty, returns that set.
+#
+# Note: this algorithm explicitly ignores generators for base classes if there
+# is at least one generator for the requested target-type.
+#
+local rule find-viable-generators-aux ( target-type : property-set )
+{
+ # Select generators that can create the required target type.
+ local viable-generators = ;
+ local generator-rank = ;
+
+ import type ;
+ local t = [ type.all-bases $(target-type) ] ;
+
+ generators.dout [ indent ] find-viable-generators target-type= $(target-type)
+ property-set= [ $(property-set).as-path ] ;
+
+ # Get the list of generators for the requested type. If no generator is
+ # registered, try base type, and so on.
+ local generators ;
+ while $(t[1])
+ {
+ generators.dout [ indent ] "trying type" $(t[1]) ;
+ if $(.generators.$(t[1]))
+ {
+ generators.dout [ indent ] "there are generators for this type" ;
+ generators = $(.generators.$(t[1])) ;
+
+ if $(t[1]) != $(target-type)
+ {
+ # We are here because there were no generators found for
+ # target-type but there are some generators for its base type.
+ # We will try to use them, but they will produce targets of
+ # base type, not of 'target-type'. So, we clone the generators
+ # and modify the list of target types.
+ local generators2 ;
+ for local g in $(generators)
+ {
+ # generators.register adds a generator to the list of
+ # generators for toolsets, which is a bit strange, but
+ # should work. That list is only used when inheriting a
+ # toolset, which should have been done before running
+ # generators.
+ generators2 += [ $(g).clone-and-change-target-type $(t[1]) :
+ $(target-type) ] ;
+ generators.register $(generators2[-1]) ;
+ }
+ generators = $(generators2) ;
+ }
+ t = ;
+ }
+ t = $(t[2-]) ;
+ }
+
+ for local g in $(generators)
+ {
+ generators.dout [ indent ] "trying generator" [ $(g).id ] "(" [ $(g).source-types ] -> [ $(g).target-types ] ")" ;
+
+ local m = [ $(g).match-rank $(property-set) ] ;
+ if $(m)
+ {
+ generators.dout [ indent ] " is viable" ;
+ viable-generators += $(g) ;
+ }
+ }
+
+ return $(viable-generators) ;
+}
+
+
+rule find-viable-generators ( target-type : property-set )
+{
+ local key = $(target-type).$(property-set) ;
+ local l = $(.fv.$(key)) ;
+ if ! $(l)
+ {
+ l = [ find-viable-generators-aux $(target-type) : $(property-set) ] ;
+ if ! $(l)
+ {
+ l = none ;
+ }
+ .fv.$(key) = $(l) ;
+ }
+
+ if $(l) = none
+ {
+ l = ;
+ }
+
+ local viable-generators ;
+ for local g in $(l)
+ {
+ # Avoid trying the same generator twice on different levels.
+ if ! $(g) in $(.active-generators)
+ {
+ viable-generators += $(g) ;
+ }
+ else
+ {
+ generators.dout [ indent ] " generator " [ $(g).id ] "is active, discaring" ;
+ }
+ }
+
+ # Generators which override 'all'.
+ local all-overrides ;
+ # Generators which are overriden.
+ local overriden-ids ;
+ for local g in $(viable-generators)
+ {
+ local id = [ $(g).id ] ;
+ local this-overrides = $(.override.$(id)) ;
+ overriden-ids += $(this-overrides) ;
+ if all in $(this-overrides)
+ {
+ all-overrides += $(g) ;
+ }
+ }
+ if $(all-overrides)
+ {
+ viable-generators = $(all-overrides) ;
+ }
+ local result ;
+ for local g in $(viable-generators)
+ {
+ if ! [ $(g).id ] in $(overriden-ids)
+ {
+ result += $(g) ;
+ }
+ }
+
+ return $(result) ;
+}
+
+
+.construct-stack = ;
+
+
+# Attempts to construct a target by finding viable generators, running them and
+# selecting the dependency graph.
+#
+local rule construct-really ( project name ? : target-type : property-set :
+ sources * )
+{
+ viable-generators = [ find-viable-generators $(target-type) :
+ $(property-set) ] ;
+
+ generators.dout [ indent ] "*** " [ sequence.length $(viable-generators) ]
+ " viable generators" ;
+
+ local result ;
+ local generators-that-succeeded ;
+ for local g in $(viable-generators)
+ {
+ # This variable will be restored on exit from this scope.
+ local .active-generators = $(g) $(.active-generators) ;
+
+ local r = [ try-one-generator $(project) $(name) : $(g) : $(target-type)
+ : $(property-set) : $(sources) ] ;
+
+ if $(r)
+ {
+ generators-that-succeeded += $(g) ;
+ if $(result)
+ {
+ ECHO "Error: ambiguity found when searching for best transformation" ;
+ ECHO "Trying to produce type '$(target-type)' from: " ;
+ for local s in $(sources)
+ {
+ ECHO " - " [ $(s).str ] ;
+ }
+ ECHO "Generators that succeeded:" ;
+ for local g in $(generators-that-succeeded)
+ {
+ ECHO " - " [ $(g).id ] ;
+ }
+ ECHO "First generator produced: " ;
+ for local t in $(result[2-])
+ {
+ ECHO " - " [ $(t).str ] ;
+ }
+ ECHO "Second generator produced: " ;
+ for local t in $(r[2-])
+ {
+ ECHO " - " [ $(t).str ] ;
+ }
+ EXIT ;
+ }
+ else
+ {
+ result = $(r) ;
+ }
+ }
+ }
+
+ return $(result) ;
+}
+
+
+# Attempts to create a target of 'target-type' with 'properties' from 'sources'.
+# The 'sources' are treated as a collection of *possible* ingridients, i.e.
+# there is no obligation to consume them all.
+#
+# Returns a list of targets. When this invocation is first instance of
+# 'construct' in stack, returns only targets of requested 'target-type',
+# otherwise, returns also unused sources and additionally generated targets.
+#
+# If 'top-level' is set, does not suppress generators that are already
+# used in the stack. This may be useful in cases where a generator
+# has to build a metatargets -- for example a target corresponding to
+# built tool.
+#
+rule construct ( project name ? : target-type : property-set * : sources * : top-level ? )
+{
+ local saved-stack ;
+ if $(top-level)
+ {
+ saved-active = $(.active-generators) ;
+ .active-generators = ;
+ }
+
+ if (.construct-stack)
+ {
+ ensure-type $(sources) ;
+ }
+
+ .construct-stack += 1 ;
+
+ increase-indent ;
+
+ if $(.debug)
+ {
+ generators.dout [ indent ] "*** construct" $(target-type) ;
+
+ for local s in $(sources)
+ {
+ generators.dout [ indent ] " from" $(s) ;
+ }
+ generators.dout [ indent ] " properties:" [ $(property-set).raw ] ;
+ }
+
+ local result = [ construct-really $(project) $(name) : $(target-type) :
+ $(property-set) : $(sources) ] ;
+
+ decrease-indent ;
+
+ .construct-stack = $(.construct-stack[2-]) ;
+
+ if $(top-level)
+ {
+ .active-generators = $(saved-active) ;
+ }
+
+ return $(result) ;
+}
+
+# Given 'result', obtained from some generator or generators.construct, adds
+# 'raw-properties' as usage requirements to it. If result already contains usage
+# requirements -- that is the first element of result of an instance of the
+# property-set class, the existing usage requirements and 'raw-properties' are
+# combined.
+#
+rule add-usage-requirements ( result * : raw-properties * )
+{
+ if $(result)
+ {
+ if [ class.is-a $(result[1]) : property-set ]
+ {
+ return [ $(result[1]).add-raw $(raw-properties) ] $(result[2-]) ;
+ }
+ else
+ {
+ return [ property-set.create $(raw-properties) ] $(result) ;
+ }
+ }
+}
+
+rule dump ( )
+{
+ for local g in $(.all-generators)
+ {
+ ECHO [ $(g).id ] ":" [ $(g).source-types ] -> [ $(g).target-types ] ;
+ }
+}
+
diff --git a/tools/build/v2/build/generators.py b/tools/build/v2/build/generators.py
new file mode 100644
index 0000000000..2c59f7ca14
--- /dev/null
+++ b/tools/build/v2/build/generators.py
@@ -0,0 +1,1089 @@
+# Status: being ported by Vladimir Prus
+# Base revision: 48649
+# TODO: replace the logging with dout
+
+# Copyright Vladimir Prus 2002.
+# Copyright Rene Rivera 2006.
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Manages 'generators' --- objects which can do transformation between different
+# target types and contain algorithm for finding transformation from sources
+# to targets.
+#
+# The main entry point to this module is generators.construct rule. It is given
+# a list of source targets, desired target type and a set of properties.
+# It starts by selecting 'viable generators', which have any chances of producing
+# the desired target type with the required properties. Generators are ranked and
+# a set of most specific ones is selected.
+#
+# The most specific generators have their 'run' methods called, with the properties
+# and list of sources. Each one selects target which can be directly consumed, and
+# tries to convert the remaining ones to the types it can consume. This is done
+# by recursively calling 'construct' with all consumable types.
+#
+# If the generator has collected all the targets it needs, it creates targets
+# corresponding to result, and returns it. When all generators have been run,
+# results of one of them are selected and returned as result.
+#
+# It's quite possible that 'construct' returns more targets that it was asked for.
+# For example, it was asked to target type EXE, but the only found generators produces
+# both EXE and TDS (file with debug) information. The extra target will be returned.
+#
+# Likewise, when generator tries to convert sources to consumable types, it can get
+# more targets that it was asked for. The question is what to do with extra targets.
+# Boost.Build attempts to convert them to requested types, and attempts as early as
+# possible. Specifically, this is done after invoking each generator. (Later I'll
+# document the rationale for trying extra target conversion at that point).
+#
+# That early conversion is not always desirable. Suppose a generator got a source of
+# type Y and must consume one target of type X_1 and one target of type X_2.
+# When converting Y to X_1 extra target of type Y_2 is created. We should not try to
+# convert it to type X_1, because if we do so, the generator will get two targets
+# of type X_1, and will be at loss as to which one to use. Because of that, the
+# 'construct' rule has a parameter, telling if multiple targets can be returned. If
+# the parameter is false, conversion of extra targets is not performed.
+
+
+import re
+import cStringIO
+import os.path
+
+from virtual_target import Subvariant
+import virtual_target, type, property_set, property
+from b2.util.logger import *
+from b2.util.utility import *
+from b2.util import set
+from b2.util.sequence import unique
+import b2.util.sequence as sequence
+from b2.manager import get_manager
+import b2.build.type
+
+def reset ():
+ """ Clear the module state. This is mainly for testing purposes.
+ """
+ global __generators, __type_to_generators, __generators_for_toolset, __construct_stack
+ global __overrides, __active_generators
+ global __viable_generators_cache, __viable_source_types_cache
+ global __vstg_cached_generators, __vst_cached_types
+
+ __generators = {}
+ __type_to_generators = {}
+ __generators_for_toolset = {}
+ __overrides = {}
+
+ # TODO: can these be global?
+ __construct_stack = []
+ __viable_generators_cache = {}
+ __viable_source_types_cache = {}
+ __active_generators = []
+
+ __vstg_cached_generators = []
+ __vst_cached_types = []
+
+reset ()
+
+_re_separate_types_prefix_and_postfix = re.compile ('([^\\(]*)(\\((.*)%(.*)\\))?')
+_re_match_type = re.compile('([^\\(]*)(\\(.*\\))?')
+
+
+__debug = None
+__indent = ""
+
+def debug():
+ global __debug
+ if __debug is None:
+ __debug = "--debug-generators" in bjam.variable("ARGV")
+ return __debug
+
+def increase_indent():
+ global __indent
+ __indent += " "
+
+def decrease_indent():
+ global __indent
+ __indent = __indent[0:-4]
+
+
+# Updated cached viable source target type information as needed after a new
+# derived target type gets added. This is needed because if a target type is a
+# viable source target type for some generator then all of the target type's
+# derived target types are automatically viable as source target types for the
+# same generator. Does nothing if a non-derived target type is passed to it.
+#
+def update_cached_information_with_a_new_type(type):
+
+ base_type = b2.build.type.base(type)
+
+ if base_type:
+ for g in __vstg_cached_generators:
+ if base_type in __viable_source_types_cache.get(g, []):
+ __viable_source_types_cache[g].append(type)
+
+ for t in __vst_cached_types:
+ if base_type in __viable_source_types_cache.get(t, []):
+ __viable_source_types_cache[t].append(type)
+
+# Clears cached viable source target type information except for target types
+# and generators with all source types listed as viable. Should be called when
+# something invalidates those cached values by possibly causing some new source
+# types to become viable.
+#
+def invalidate_extendable_viable_source_target_type_cache():
+
+ global __vstg_cached_generators
+ generators_with_cached_source_types = __vstg_cached_generators
+ __vstg_cached_generators = []
+
+ for g in generators_with_cached_source_types:
+ if __viable_source_types_cache.has_key(g):
+ if __viable_source_types_cache[g] == ["*"]:
+ __vstg_cached_generators.append(g)
+ else:
+ del __viable_source_types_cache[g]
+
+ global __vst_cached_types
+ types_with_cached_sources_types = __vst_cached_types
+ __vst_cached_types = []
+ for t in types_with_cached_sources_types:
+ if __viable_source_types_cache.has_key(t):
+ if __viable_source_types_cache[t] == ["*"]:
+ __vst_cached_types.append(t)
+ else:
+ del __viable_source_types_cache[t]
+
+def dout(message):
+ if debug():
+ print __indent + message
+
+class Generator:
+ """ Creates a generator.
+ manager: the build manager.
+ id: identifies the generator
+
+ rule: the rule which sets up build actions.
+
+ composing: whether generator processes each source target in
+ turn, converting it to required types.
+ Ordinary generators pass all sources together to
+ recusrive generators.construct_types call.
+
+ source_types (optional): types that this generator can handle
+
+ target_types_and_names: types the generator will create and, optionally, names for
+ created targets. Each element should have the form
+ type["(" name-pattern ")"]
+ for example, obj(%_x). Name of generated target will be found
+ by replacing % with the name of source, provided explicit name
+ was not specified.
+
+ requirements (optional)
+
+ NOTE: all subclasses must have a similar signature for clone to work!
+ """
+ def __init__ (self, id, composing, source_types, target_types_and_names, requirements = []):
+ assert(not isinstance(source_types, str))
+ assert(not isinstance(target_types_and_names, str))
+ self.id_ = id
+ self.composing_ = composing
+ self.source_types_ = source_types
+ self.target_types_and_names_ = target_types_and_names
+ self.requirements_ = requirements
+
+ self.target_types_ = []
+ self.name_prefix_ = []
+ self.name_postfix_ = []
+
+ for e in target_types_and_names:
+ # Create three parallel lists: one with the list of target types,
+ # and two other with prefixes and postfixes to be added to target
+ # name. We use parallel lists for prefix and postfix (as opposed
+ # to mapping), because given target type might occur several times,
+ # for example "H H(%_symbols)".
+ m = _re_separate_types_prefix_and_postfix.match (e)
+
+ if not m:
+ raise BaseException ("Invalid type and name '%s' in declaration of type '%s'" % (e, id))
+
+ target_type = m.group (1)
+ if not target_type: target_type = ''
+ prefix = m.group (3)
+ if not prefix: prefix = ''
+ postfix = m.group (4)
+ if not postfix: postfix = ''
+
+ self.target_types_.append (target_type)
+ self.name_prefix_.append (prefix)
+ self.name_postfix_.append (postfix)
+
+ for x in self.source_types_:
+ type.validate (x)
+
+ for x in self.target_types_:
+ type.validate (x)
+
+ def clone (self, new_id, new_toolset_properties):
+ """ Returns another generator which differers from $(self) in
+ - id
+ - value to <toolset> feature in properties
+ """
+ return self.__class__ (new_id,
+ self.composing_,
+ self.source_types_,
+ self.target_types_and_names_,
+ # Note: this does not remove any subfeatures of <toolset>
+ # which might cause problems
+ property.change (self.requirements_, '<toolset>') + new_toolset_properties)
+
+ def clone_and_change_target_type(self, base, type):
+ """Creates another generator that is the same as $(self), except that
+ if 'base' is in target types of $(self), 'type' will in target types
+ of the new generator."""
+ target_types = []
+ for t in self.target_types_and_names_:
+ m = _re_match_type.match(t)
+ assert m
+
+ if m.group(1) == base:
+ if m.group(2):
+ target_types.append(type + m.group(2))
+ else:
+ target_types.append(type)
+ else:
+ target_types.append(t)
+
+ return self.__class__(self.id_, self.composing_,
+ self.source_types_,
+ target_types,
+ self.requirements_)
+
+
+ def id(self):
+ return self.id_
+
+ def source_types (self):
+ """ Returns the list of target type the generator accepts.
+ """
+ return self.source_types_
+
+ def target_types (self):
+ """ Returns the list of target types that this generator produces.
+ It is assumed to be always the same -- i.e. it cannot change depending
+ list of sources.
+ """
+ return self.target_types_
+
+ def requirements (self):
+ """ Returns the required properties for this generator. Properties
+ in returned set must be present in build properties if this
+ generator is to be used. If result has grist-only element,
+ that build properties must include some value of that feature.
+ """
+ return self.requirements_
+
+ def match_rank (self, ps):
+ """ Returns true if the generator can be run with the specified
+ properties.
+ """
+ # See if generator's requirements are satisfied by
+ # 'properties'. Treat a feature name in requirements
+ # (i.e. grist-only element), as matching any value of the
+ # feature.
+ all_requirements = self.requirements ()
+
+ property_requirements = []
+ feature_requirements = []
+ # This uses strings because genenator requirements allow
+ # the '<feature>' syntax without value and regular validation
+ # is not happy about that.
+ for r in all_requirements:
+ if get_value (r):
+ property_requirements.append (r)
+
+ else:
+ feature_requirements.append (r)
+
+ return all(ps.get(get_grist(s)) == [get_value(s)] for s in property_requirements) \
+ and all(ps.get(get_grist(s)) for s in feature_requirements)
+
+ def run (self, project, name, prop_set, sources):
+ """ Tries to invoke this generator on the given sources. Returns a
+ list of generated targets (instances of 'virtual-target').
+
+ project: Project for which the targets are generated.
+
+ name: Determines the name of 'name' attribute for
+ all generated targets. See 'generated_targets' method.
+
+ prop_set: Desired properties for generated targets.
+
+ sources: Source targets.
+ """
+
+ if project.manager ().logger ().on ():
+ project.manager ().logger ().log (__name__, " generator '%s'" % self.id_)
+ project.manager ().logger ().log (__name__, " composing: '%s'" % self.composing_)
+
+ if not self.composing_ and len (sources) > 1 and len (self.source_types_) > 1:
+ raise BaseException ("Unsupported source/source_type combination")
+
+ # We don't run composing generators if no name is specified. The reason
+ # is that composing generator combines several targets, which can have
+ # different names, and it cannot decide which name to give for produced
+ # target. Therefore, the name must be passed.
+ #
+ # This in effect, means that composing generators are runnable only
+ # at top-level of transofrmation graph, or if name is passed explicitly.
+ # Thus, we dissallow composing generators in the middle. For example, the
+ # transofrmation CPP -> OBJ -> STATIC_LIB -> RSP -> EXE won't be allowed
+ # (the OBJ -> STATIC_LIB generator is composing)
+ if not self.composing_ or name:
+ return self.run_really (project, name, prop_set, sources)
+ else:
+ return []
+
+ def run_really (self, project, name, prop_set, sources):
+
+ # consumed: Targets that this generator will consume directly.
+ # bypassed: Targets that can't be consumed and will be returned as-is.
+
+ if self.composing_:
+ (consumed, bypassed) = self.convert_multiple_sources_to_consumable_types (project, prop_set, sources)
+ else:
+ (consumed, bypassed) = self.convert_to_consumable_types (project, name, prop_set, sources)
+
+ result = []
+ if consumed:
+ result = self.construct_result (consumed, project, name, prop_set)
+ result.extend (bypassed)
+
+ if result:
+ if project.manager ().logger ().on ():
+ project.manager ().logger ().log (__name__, " SUCCESS: ", result)
+
+ else:
+ project.manager ().logger ().log (__name__, " FAILURE")
+
+ return result
+
+ def construct_result (self, consumed, project, name, prop_set):
+ """ Constructs the dependency graph that will be returned by this
+ generator.
+ consumed: Already prepared list of consumable targets
+ If generator requires several source files will contain
+ exactly len $(self.source_types_) targets with matching types
+ Otherwise, might contain several targets with the type of
+ self.source_types_ [0]
+ project:
+ name:
+ prop_set: Properties to be used for all actions create here
+ """
+ result = []
+ # If this is 1->1 transformation, apply it to all consumed targets in order.
+ if len (self.source_types_) < 2 and not self.composing_:
+
+ for r in consumed:
+ result.extend (self.generated_targets ([r], prop_set, project, name))
+
+ else:
+
+ if consumed:
+ result.extend (self.generated_targets (consumed, prop_set, project, name))
+
+ return result
+
+ def determine_target_name(self, fullname):
+ # Determine target name from fullname (maybe including path components)
+ # Place optional prefix and postfix around basename
+
+ dir = os.path.dirname(fullname)
+ name = os.path.basename(fullname)
+
+ if dir and not ".." in dir and not os.path.isabs(dir):
+ # Relative path is always relative to the source
+ # directory. Retain it, so that users can have files
+ # with the same in two different subdirectories.
+ name = dir + "/" + name
+
+ return name
+
+ def determine_output_name(self, sources):
+ """Determine the name of the produced target from the
+ names of the sources."""
+
+ # The simple case if when a name
+ # of source has single dot. Then, we take the part before
+ # dot. Several dots can be caused by:
+ # - Using source file like a.host.cpp
+ # - A type which suffix has a dot. Say, we can
+ # type 'host_cpp' with extension 'host.cpp'.
+ # In the first case, we want to take the part till the last
+ # dot. In the second case -- no sure, but for now take
+ # the part till the last dot too.
+ name = os.path.splitext(sources[0].name())[0]
+
+ for s in sources[1:]:
+ n2 = os.path.splitext(s.name())
+ if n2 != name:
+ get_manager().errors()(
+ "%s: source targets have different names: cannot determine target name"
+ % (self.id_))
+
+ # Names of sources might include directory. We should strip it.
+ return self.determine_target_name(sources[0].name())
+
+
+ def generated_targets (self, sources, prop_set, project, name):
+ """ Constructs targets that are created after consuming 'sources'.
+ The result will be the list of virtual-target, which the same length
+ as 'target_types' attribute and with corresponding types.
+
+ When 'name' is empty, all source targets must have the same value of
+ the 'name' attribute, which will be used instead of the 'name' argument.
+
+ The value of 'name' attribute for each generated target will be equal to
+ the 'name' parameter if there's no name pattern for this type. Otherwise,
+ the '%' symbol in the name pattern will be replaced with the 'name' parameter
+ to obtain the 'name' attribute.
+
+ For example, if targets types are T1 and T2(with name pattern "%_x"), suffixes
+ for T1 and T2 are .t1 and t2, and source if foo.z, then created files would
+ be "foo.t1" and "foo_x.t2". The 'name' attribute actually determined the
+ basename of a file.
+
+ Note that this pattern mechanism has nothing to do with implicit patterns
+ in make. It's a way to produce target which name is different for name of
+ source.
+ """
+ if not name:
+ name = self.determine_output_name(sources)
+
+ # Assign an action for each target
+ action = self.action_class()
+ a = action(project.manager(), sources, self.id_, prop_set)
+
+ # Create generated target for each target type.
+ targets = []
+ pre = self.name_prefix_
+ post = self.name_postfix_
+ for t in self.target_types_:
+ basename = os.path.basename(name)
+ idx = basename.find(".")
+ if idx != -1:
+ basename = basename[:idx]
+ generated_name = pre[0] + basename + post[0]
+ generated_name = os.path.join(os.path.dirname(name), generated_name)
+ pre = pre[1:]
+ post = post[1:]
+
+ targets.append(virtual_target.FileTarget(generated_name, t, project, a))
+
+ return [ project.manager().virtual_targets().register(t) for t in targets ]
+
+ def convert_to_consumable_types (self, project, name, prop_set, sources, only_one=False):
+ """ Attempts to convert 'source' to the types that this generator can
+ handle. The intention is to produce the set of targets can should be
+ used when generator is run.
+ only_one: convert 'source' to only one of source types
+ if there's more that one possibility, report an
+ error.
+
+ Returns a pair:
+ consumed: all targets that can be consumed.
+ bypassed: all targets that cannot be consumed.
+ """
+ consumed = []
+ bypassed = []
+ missing_types = []
+
+ if len (sources) > 1:
+ # Don't know how to handle several sources yet. Just try
+ # to pass the request to other generator
+ missing_types = self.source_types_
+
+ else:
+ (c, m) = self.consume_directly (sources [0])
+ consumed += c
+ missing_types += m
+
+ # No need to search for transformation if
+ # some source type has consumed source and
+ # no more source types are needed.
+ if only_one and consumed:
+ missing_types = []
+
+ #TODO: we should check that only one source type
+ #if create of 'only_one' is true.
+ # TODO: consider if consuned/bypassed separation should
+ # be done by 'construct_types'.
+
+ if missing_types:
+ transformed = construct_types (project, name, missing_types, prop_set, sources)
+
+ # Add targets of right type to 'consumed'. Add others to
+ # 'bypassed'. The 'generators.construct' rule has done
+ # its best to convert everything to the required type.
+ # There's no need to rerun it on targets of different types.
+
+ # NOTE: ignoring usage requirements
+ for t in transformed[1]:
+ if t.type() in missing_types:
+ consumed.append(t)
+
+ else:
+ bypassed.append(t)
+
+ consumed = unique(consumed)
+ bypassed = unique(bypassed)
+
+ # remove elements of 'bypassed' that are in 'consumed'
+
+ # Suppose the target type of current generator, X is produced from
+ # X_1 and X_2, which are produced from Y by one generator.
+ # When creating X_1 from Y, X_2 will be added to 'bypassed'
+ # Likewise, when creating X_2 from Y, X_1 will be added to 'bypassed'
+ # But they are also in 'consumed'. We have to remove them from
+ # bypassed, so that generators up the call stack don't try to convert
+ # them.
+
+ # In this particular case, X_1 instance in 'consumed' and X_1 instance
+ # in 'bypassed' will be the same: because they have the same source and
+ # action name, and 'virtual-target.register' won't allow two different
+ # instances. Therefore, it's OK to use 'set.difference'.
+
+ bypassed = set.difference(bypassed, consumed)
+
+ return (consumed, bypassed)
+
+
+ def convert_multiple_sources_to_consumable_types (self, project, prop_set, sources):
+ """ Converts several files to consumable types.
+ """
+ consumed = []
+ bypassed = []
+
+ # We process each source one-by-one, trying to convert it to
+ # a usable type.
+ for s in sources:
+ # TODO: need to check for failure on each source.
+ (c, b) = self.convert_to_consumable_types (project, None, prop_set, [s], True)
+ if not c:
+ project.manager ().logger ().log (__name__, " failed to convert ", s)
+
+ consumed.extend (c)
+ bypassed.extend (b)
+
+ return (consumed, bypassed)
+
+ def consume_directly (self, source):
+ real_source_type = source.type ()
+
+ # If there are no source types, we can consume anything
+ source_types = self.source_types()
+ if not source_types:
+ source_types = [real_source_type]
+
+ consumed = []
+ missing_types = []
+ for st in source_types:
+ # The 'source' if of right type already)
+ if real_source_type == st or type.is_derived (real_source_type, st):
+ consumed.append (source)
+
+ else:
+ missing_types.append (st)
+
+ return (consumed, missing_types)
+
+ def action_class (self):
+ """ Returns the class to be used to actions. Default implementation
+ returns "action".
+ """
+ return virtual_target.Action
+
+
+def find (id):
+ """ Finds the generator with id. Returns None if not found.
+ """
+ return __generators.get (id, None)
+
+def register (g):
+ """ Registers new generator instance 'g'.
+ """
+ id = g.id()
+
+ __generators [id] = g
+
+ # A generator can produce several targets of the
+ # same type. We want unique occurence of that generator
+ # in .generators.$(t) in that case, otherwise, it will
+ # be tried twice and we'll get false ambiguity.
+ for t in sequence.unique(g.target_types()):
+ __type_to_generators.setdefault(t, []).append(g)
+
+ # Update the set of generators for toolset
+
+ # TODO: should we check that generator with this id
+ # is not already registered. For example, the fop.jam
+ # module intentionally declared two generators with the
+ # same id, so such check will break it.
+
+ # Some generators have multiple periods in their name, so the
+ # normal $(id:S=) won't generate the right toolset name.
+ # e.g. if id = gcc.compile.c++, then
+ # .generators-for-toolset.$(id:S=) will append to
+ # .generators-for-toolset.gcc.compile, which is a separate
+ # value from .generators-for-toolset.gcc. Correcting this
+ # makes generator inheritance work properly.
+ # See also inherit-generators in module toolset
+ base = id.split ('.', 100) [0]
+
+ __generators_for_toolset.setdefault(base, []).append(g)
+
+ # After adding a new generator that can construct new target types, we need
+ # to clear the related cached viable source target type information for
+ # constructing a specific target type or using a specific generator. Cached
+ # viable source target type lists affected by this are those containing any
+ # of the target types constructed by the new generator or any of their base
+ # target types.
+ #
+ # A more advanced alternative to clearing that cached viable source target
+ # type information would be to expand it with additional source types or
+ # even better - mark it as needing to be expanded on next use.
+ #
+ # For now we just clear all the cached viable source target type information
+ # that does not simply state 'all types' and may implement a more detailed
+ # algorithm later on if it becomes needed.
+
+ invalidate_extendable_viable_source_target_type_cache()
+
+
+def register_standard (id, source_types, target_types, requirements = []):
+ """ Creates new instance of the 'generator' class and registers it.
+ Returns the creates instance.
+ Rationale: the instance is returned so that it's possible to first register
+ a generator and then call 'run' method on that generator, bypassing all
+ generator selection.
+ """
+ g = Generator (id, False, source_types, target_types, requirements)
+ register (g)
+ return g
+
+def register_composing (id, source_types, target_types, requirements = []):
+ g = Generator (id, True, source_types, target_types, requirements)
+ register (g)
+ return g
+
+def generators_for_toolset (toolset):
+ """ Returns all generators which belong to 'toolset'.
+ """
+ return __generators_for_toolset.get(toolset, [])
+
+def override (overrider_id, overridee_id):
+ """Make generator 'overrider-id' be preferred to
+ 'overridee-id'. If, when searching for generators
+ that could produce a target of certain type,
+ both those generators are amoung viable generators,
+ the overridden generator is immediately discarded.
+
+ The overridden generators are discarded immediately
+ after computing the list of viable generators, before
+ running any of them."""
+
+ __overrides.get(overrider_id, []).append(overridee_id)
+
+def __viable_source_types_real (target_type):
+ """ Returns a list of source type which can possibly be converted
+ to 'target_type' by some chain of generator invocation.
+
+ More formally, takes all generators for 'target_type' and
+ returns union of source types for those generators and result
+ of calling itself recusrively on source types.
+ """
+ generators = []
+
+ # 't0' is the initial list of target types we need to process to get a list
+ # of their viable source target types. New target types will not be added to
+ # this list.
+ t0 = type.all_bases (target_type)
+
+
+ # 't' is the list of target types which have not yet been processed to get a
+ # list of their viable source target types. This list will get expanded as
+ # we locate more target types to process.
+ t = t0
+
+ result = []
+ while t:
+ # Find all generators for current type.
+ # Unlike 'find_viable_generators' we don't care about prop_set.
+ generators = __type_to_generators.get (t [0], [])
+ t = t[1:]
+
+ for g in generators:
+ if not g.source_types():
+ # Empty source types -- everything can be accepted
+ result = "*"
+ # This will terminate outer loop.
+ t = None
+ break
+
+ for source_type in g.source_types ():
+ if not source_type in result:
+ # If generator accepts 'source_type' it
+ # will happily accept any type derived from it
+ all = type.all_derived (source_type)
+ for n in all:
+ if not n in result:
+
+ # Here there is no point in adding target types to
+ # the list of types to process in case they are or
+ # have already been on that list. We optimize this
+ # check by realizing that we only need to avoid the
+ # original target type's base types. Other target
+ # types that are or have been on the list of target
+ # types to process have been added to the 'result'
+ # list as well and have thus already been eliminated
+ # by the previous if.
+ if not n in t0:
+ t.append (n)
+ result.append (n)
+
+ return result
+
+
+def viable_source_types (target_type):
+ """ Helper rule, caches the result of '__viable_source_types_real'.
+ """
+ if not __viable_source_types_cache.has_key(target_type):
+ __vst_cached_types.append(target_type)
+ __viable_source_types_cache [target_type] = __viable_source_types_real (target_type)
+ return __viable_source_types_cache [target_type]
+
+def viable_source_types_for_generator_real (generator):
+ """ Returns the list of source types, which, when passed to 'run'
+ method of 'generator', has some change of being eventually used
+ (probably after conversion by other generators)
+ """
+ source_types = generator.source_types ()
+
+ if not source_types:
+ # If generator does not specify any source types,
+ # it might be special generator like builtin.lib-generator
+ # which just relays to other generators. Return '*' to
+ # indicate that any source type is possibly OK, since we don't
+ # know for sure.
+ return ['*']
+
+ else:
+ result = []
+ for s in source_types:
+ viable_sources = viable_source_types(s)
+ if viable_sources == "*":
+ result = ["*"]
+ break
+ else:
+ result.extend(type.all_derived(s) + viable_sources)
+ return unique(result)
+
+def viable_source_types_for_generator (generator):
+ """ Caches the result of 'viable_source_types_for_generator'.
+ """
+ if not __viable_source_types_cache.has_key(generator):
+ __vstg_cached_generators.append(generator)
+ __viable_source_types_cache[generator] = viable_source_types_for_generator_real (generator)
+
+ return __viable_source_types_cache[generator]
+
+def try_one_generator_really (project, name, generator, target_type, properties, sources):
+ """ Returns usage requirements + list of created targets.
+ """
+ targets = generator.run (project, name, properties, sources)
+
+ usage_requirements = []
+ success = False
+
+ dout("returned " + str(targets))
+
+ if targets:
+ success = True;
+
+ if isinstance (targets[0], property_set.PropertySet):
+ usage_requirements = targets [0]
+ targets = targets [1]
+
+ else:
+ usage_requirements = property_set.empty ()
+
+ dout( " generator" + generator.id() + " spawned ")
+ # generators.dout [ indent ] " " $(targets) ;
+# if $(usage-requirements)
+# {
+# generators.dout [ indent ] " with usage requirements:" $(x) ;
+# }
+
+ if success:
+ return (usage_requirements, targets)
+ else:
+ return None
+
+def try_one_generator (project, name, generator, target_type, properties, sources):
+ """ Checks if generator invocation can be pruned, because it's guaranteed
+ to fail. If so, quickly returns empty list. Otherwise, calls
+ try_one_generator_really.
+ """
+ source_types = []
+
+ for s in sources:
+ source_types.append (s.type ())
+
+ viable_source_types = viable_source_types_for_generator (generator)
+
+ if source_types and viable_source_types != ['*'] and\
+ not set.intersection (source_types, viable_source_types):
+ if project.manager ().logger ().on ():
+ id = generator.id ()
+ project.manager ().logger ().log (__name__, "generator '%s' pruned" % id)
+ project.manager ().logger ().log (__name__, "source_types" '%s' % source_types)
+ project.manager ().logger ().log (__name__, "viable_source_types '%s'" % viable_source_types)
+
+ return []
+
+ else:
+ return try_one_generator_really (project, name, generator, target_type, properties, sources)
+
+
+def construct_types (project, name, target_types, prop_set, sources):
+
+ result = []
+ usage_requirements = property_set.empty()
+
+ for t in target_types:
+ r = construct (project, name, t, prop_set, sources)
+
+ if r:
+ (ur, targets) = r
+ usage_requirements = usage_requirements.add(ur)
+ result.extend(targets)
+
+ # TODO: have to introduce parameter controlling if
+ # several types can be matched and add appropriate
+ # checks
+
+ # TODO: need to review the documentation for
+ # 'construct' to see if it should return $(source) even
+ # if nothing can be done with it. Currents docs seem to
+ # imply that, contrary to the behaviour.
+ if result:
+ return (usage_requirements, result)
+
+ else:
+ return (usage_requirements, sources)
+
+def __ensure_type (targets):
+ """ Ensures all 'targets' have types. If this is not so, exists with
+ error.
+ """
+ for t in targets:
+ if not t.type ():
+ get_manager().errors()("target '%s' has no type" % str (t))
+
+def find_viable_generators_aux (target_type, prop_set):
+ """ Returns generators which can be used to construct target of specified type
+ with specified properties. Uses the following algorithm:
+ - iterates over requested target_type and all it's bases (in the order returned bt
+ type.all-bases.
+ - for each type find all generators that generate that type and which requirements
+ are satisfied by properties.
+ - if the set of generators is not empty, returns that set.
+
+ Note: this algorithm explicitly ignores generators for base classes if there's
+ at least one generator for requested target_type.
+ """
+ # Select generators that can create the required target type.
+ viable_generators = []
+ initial_generators = []
+
+ import type
+
+ # Try all-type generators first. Assume they have
+ # quite specific requirements.
+ all_bases = type.all_bases(target_type)
+
+ for t in all_bases:
+
+ initial_generators = __type_to_generators.get(t, [])
+
+ if initial_generators:
+ dout("there are generators for this type")
+ if t != target_type:
+ # We're here, when no generators for target-type are found,
+ # but there are some generators for a base type.
+ # We'll try to use them, but they will produce targets of
+ # base type, not of 'target-type'. So, we clone the generators
+ # and modify the list of target types.
+ generators2 = []
+ for g in initial_generators[:]:
+ # generators.register adds generator to the list of generators
+ # for toolsets, which is a bit strange, but should work.
+ # That list is only used when inheriting toolset, which
+ # should have being done before generators are run.
+ ng = g.clone_and_change_target_type(t, target_type)
+ generators2.append(ng)
+ register(ng)
+
+ initial_generators = generators2
+ break
+
+ for g in initial_generators:
+ dout("trying generator " + g.id()
+ + "(" + str(g.source_types()) + "->" + str(g.target_types()) + ")")
+
+ m = g.match_rank(prop_set)
+ if m:
+ dout(" is viable")
+ viable_generators.append(g)
+
+ return viable_generators
+
+def find_viable_generators (target_type, prop_set):
+ key = target_type + '.' + str (prop_set)
+
+ l = __viable_generators_cache.get (key, None)
+ if not l:
+ l = []
+
+ if not l:
+ l = find_viable_generators_aux (target_type, prop_set)
+
+ __viable_generators_cache [key] = l
+
+ viable_generators = []
+ for g in l:
+ # Avoid trying the same generator twice on different levels.
+ # TODO: is this really used?
+ if not g in __active_generators:
+ viable_generators.append (g)
+ else:
+ dout(" generator %s is active, discarding" % g.id())
+
+ # Generators which override 'all'.
+ all_overrides = []
+
+ # Generators which are overriden
+ overriden_ids = []
+
+ for g in viable_generators:
+ id = g.id ()
+
+ this_overrides = __overrides.get (id, [])
+
+ if this_overrides:
+ overriden_ids.extend (this_overrides)
+ if 'all' in this_overrides:
+ all_overrides.append (g)
+
+ if all_overrides:
+ viable_generators = all_overrides
+
+ result = []
+ for g in viable_generators:
+ if not g.id () in overriden_ids:
+ result.append (g)
+
+
+ return result
+
+def __construct_really (project, name, target_type, prop_set, sources):
+ """ Attempts to construct target by finding viable generators, running them
+ and selecting the dependency graph.
+ """
+ viable_generators = find_viable_generators (target_type, prop_set)
+
+ result = []
+
+ project.manager ().logger ().log (__name__, "*** %d viable generators" % len (viable_generators))
+
+ generators_that_succeeded = []
+
+ for g in viable_generators:
+ __active_generators.append(g)
+ r = try_one_generator (project, name, g, target_type, prop_set, sources)
+ del __active_generators[-1]
+
+ if r:
+ generators_that_succeeded.append(g)
+ if result:
+ output = cStringIO.StringIO()
+ print >>output, "ambiguity found when searching for best transformation"
+ print >>output, "Trying to produce type '%s' from: " % (target_type)
+ for s in sources:
+ print >>output, " - " + s.str()
+ print >>output, "Generators that succeeded:"
+ for g in generators_that_succeeded:
+ print >>output, " - " + g.id()
+ print >>output, "First generator produced: "
+ for t in result[1:]:
+ print >>output, " - " + str(t)
+ print >>output, "Second generator produced:"
+ for t in r[1:]:
+ print >>output, " - " + str(t)
+ get_manager().errors()(output.getvalue())
+ else:
+ result = r;
+
+ return result;
+
+
+def construct (project, name, target_type, prop_set, sources, top_level=False):
+ """ Attempts to create target of 'target-type' with 'properties'
+ from 'sources'. The 'sources' are treated as a collection of
+ *possible* ingridients -- i.e. it is not required to consume
+ them all. If 'multiple' is true, the rule is allowed to return
+ several targets of 'target-type'.
+
+ Returns a list of target. When this invocation is first instance of
+ 'construct' in stack, returns only targets of requested 'target-type',
+ otherwise, returns also unused sources and additionally generated
+ targets.
+
+ If 'top-level' is set, does not suppress generators that are already
+ used in the stack. This may be useful in cases where a generator
+ has to build a metatarget -- for example a target corresponding to
+ built tool.
+ """
+
+ global __active_generators
+ if top_level:
+ saved_active = __active_generators
+ __active_generators = []
+
+ global __construct_stack
+ if not __construct_stack:
+ __ensure_type (sources)
+
+ __construct_stack.append (1)
+
+ if project.manager().logger().on():
+ increase_indent ()
+
+ dout( "*** construct " + target_type)
+
+ for s in sources:
+ dout(" from " + str(s))
+
+ project.manager().logger().log (__name__, " properties: ", prop_set.raw ())
+
+ result = __construct_really(project, name, target_type, prop_set, sources)
+
+ project.manager().logger().decrease_indent()
+
+ __construct_stack = __construct_stack [1:]
+
+ if top_level:
+ __active_generators = saved_active
+
+ return result
+
diff --git a/tools/build/v2/build/modifiers.jam b/tools/build/v2/build/modifiers.jam
new file mode 100644
index 0000000000..6b00934333
--- /dev/null
+++ b/tools/build/v2/build/modifiers.jam
@@ -0,0 +1,232 @@
+# Copyright 2003 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Modifiers are generalized generators that mutate targets in specific ways.
+# This structure allows for grouping a variety of functionality in an
+# orthogonal way to the functionality in toolsets, and without specifying
+# more target variations. In turn the modifiers can be used as building
+# blocks to implement simple requests, like the <version> feature.
+
+import modules ;
+import feature ;
+import errors ;
+import type ;
+import "class" : new ;
+import generators ;
+import property ;
+import virtual-target ;
+import numbers ;
+import sequence ;
+import symlink ;
+import property-set ;
+
+# Base generator for creating targets that are modifications of existing
+# targets.
+#
+class modifier : generator
+{
+ rule __init__ (
+ id
+ composing ?
+ : source-types *
+ : target-types-and-names +
+ : requirements *
+ )
+ {
+ generator.__init__ $(id) $(composing)
+ : $(source-types)
+ : $(target-types-and-names)
+ : $(requirements) ;
+
+ self.targets-in-progress = ;
+ }
+
+ # Wraps the generation of the target to call before and after rules to
+ # affect the real target.
+ #
+ rule run ( project name ? : property-set : sources + )
+ {
+ local result ;
+ local current-target = $(project)^$(name) ;
+ if ! $(current-target) in $(self.targets-in-progress)
+ {
+ # Before modifications...
+ local project_ =
+ [ modify-project-before
+ $(project) $(name) : $(property-set) : $(sources) ] ;
+ local name_ =
+ [ modify-name-before
+ $(project) $(name) : $(property-set) : $(sources) ] ;
+ local property-set_ =
+ [ modify-properties-before
+ $(project) $(name) : $(property-set) : $(sources) ] ;
+ local sources_ =
+ [ modify-sources-before
+ $(project) $(name) : $(property-set) : $(sources) ] ;
+ project = $(project_) ;
+ name = $(name_) ;
+ property-set = $(property-set_) ;
+ sources = $(sources_) ;
+
+ # Generate the real target...
+ local target-type-p =
+ [ property.select <main-target-type> : [ $(property-set).raw ] ] ;
+ self.targets-in-progress += $(current-target) ;
+ result =
+ [ generators.construct $(project) $(name)
+ : $(target-type-p:G=)
+ : $(property-set)
+ : $(sources) ] ;
+ self.targets-in-progress = $(self.targets-in-progress[1--2]) ;
+
+ # After modifications...
+ result =
+ [ modify-target-after $(result)
+ : $(project) $(name)
+ : $(property-set)
+ : $(sources) ] ;
+ }
+ return $(result) ;
+ }
+
+ rule modify-project-before ( project name ? : property-set : sources + )
+ {
+ return $(project) ;
+ }
+
+ rule modify-name-before ( project name ? : property-set : sources + )
+ {
+ return $(name) ;
+ }
+
+ rule modify-properties-before ( project name ? : property-set : sources + )
+ {
+ return $(property-set) ;
+ }
+
+ rule modify-sources-before ( project name ? : property-set : sources + )
+ {
+ return $(sources) ;
+ }
+
+ rule modify-target-after ( target : project name ? : property-set : sources + )
+ {
+ return $(target) ;
+ }
+
+ # Utility, clones a file-target with optional changes to the name, type and
+ # project of the target.
+ # NOTE: This functionality should be moved, and generalized, to
+ # virtual-targets.
+ #
+ rule clone-file-target ( target : new-name ? : new-type ? : new-project ? )
+ {
+ # Need a MUTCH better way to clone a target...
+ new-name ?= [ $(target).name ] ;
+ new-type ?= [ $(target).type ] ;
+ new-project ?= [ $(target).project ] ;
+ local result = [ new file-target $(new-name) : $(new-type) : $(new-project) ] ;
+
+ if [ $(target).dependencies ] { $(result).depends [ $(target).dependencies ] ; }
+ $(result).root [ $(target).root ] ;
+ $(result).set-usage-requirements [ $(target).usage-requirements ] ;
+
+ local action = [ $(target).action ] ;
+ local action-class = [ modules.peek $(action) : __class__ ] ;
+
+ local ps = [ $(action).properties ] ;
+ local cloned-action = [ new $(action-class) $(result) :
+ [ $(action).sources ] : [ $(action).action-name ] : $(ps) ] ;
+ $(result).action $(cloned-action) ;
+
+ return $(result) ;
+ }
+}
+
+
+# A modifier that changes the name of a target, after it's generated, given a
+# regular expression to split the name, and a set of token to insert between the
+# split tokens of the name. This also exposes the target for other uses with a
+# symlink to the original name (optionally).
+#
+class name-modifier : modifier
+{
+ rule __init__ ( )
+ {
+ # Apply ourselves to EXE targets, for now.
+ modifier.__init__ name.modifier : : EXE LIB : <name-modify>yes ;
+ }
+
+ # Modifies the name, by cloning the target with the new name.
+ #
+ rule modify-target-after ( target : project name ? : property-set : sources + )
+ {
+ local result = $(target) ;
+
+ local name-mod-p = [ property.select <name-modifier> : [ $(property-set).raw ] ] ;
+ if $(name-mod-p)
+ {
+ local new-name = [ modify-name [ $(target).name ] : $(name-mod-p:G=) ] ;
+ if $(new-name) != [ $(target).name ]
+ {
+ result = [ clone-file-target $(target) : $(new-name) ] ;
+ }
+ local expose-original-as-symlink = [ MATCH "<symlink>(.*)" : $(name-mod-p) ] ;
+ if $(expose-original-as-symlink)
+ {
+ local symlink-t = [ new symlink-targets $(project) : $(name) : [ $(result).name ] ] ;
+ result = [ $(symlink-t).construct $(result)
+ : [ property-set.create [ $(property-set).raw ] <symlink-location>build-relative ] ] ;
+ }
+ }
+
+ return $(result) ;
+ }
+
+ # Do the transformation of the name.
+ #
+ rule modify-name ( name : modifier-spec + )
+ {
+ local match = [ MATCH "<match>(.*)" : $(modifier-spec) ] ;
+ local name-parts = [ MATCH $(match) : $(name) ] ;
+ local insertions = [ sequence.insertion-sort [ MATCH "(<[0123456789]+>.*)" : $(modifier-spec) ] ] ;
+ local new-name-parts ;
+ local insert-position = 1 ;
+ while $(insertions)
+ {
+ local insertion = [ MATCH "<$(insert-position)>(.*)" : $(insertions[1]) ] ;
+ if $(insertion)
+ {
+ new-name-parts += $(insertion) ;
+ insertions = $(insertions[2-]) ;
+ }
+ new-name-parts += $(name-parts[1]) ;
+ name-parts = $(name-parts[2-]) ;
+ insert-position = [ numbers.increment $(insert-position) ] ;
+ }
+ new-name-parts += $(name-parts) ;
+ return [ sequence.join $(new-name-parts) ] ;
+ }
+
+ rule optional-properties ( )
+ {
+ return <name-modify>yes ;
+ }
+}
+feature.feature name-modifier : : free ;
+feature.feature name-modify : no yes : incidental optional ;
+generators.register [ new name-modifier ] ;
+
+# Translates <version> property to a set of modification properties
+# that are applied by the name-modifier, and symlink-modifier.
+#
+rule version-to-modifier ( property : properties * )
+{
+ return
+ <name-modify>yes
+ <name-modifier><match>"^([^.]*)(.*)" <name-modifier><2>.$(property:G=)
+ <name-modifier><symlink>yes
+ ;
+}
+feature.action <version> : version-to-modifier ;
diff --git a/tools/build/v2/build/project.ann.py b/tools/build/v2/build/project.ann.py
new file mode 100644
index 0000000000..349f549550
--- /dev/null
+++ b/tools/build/v2/build/project.ann.py
@@ -0,0 +1,996 @@
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 1) # Status: being ported by Vladimir Prus
+ddc17f01 (vladimir_prus 2007-10-26 14:57:56 +0000 2) # Base revision: 40480
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 3)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 4) # Copyright 2002, 2003 Dave Abrahams
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 5) # Copyright 2002, 2005, 2006 Rene Rivera
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 6) # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 7) # Distributed under the Boost Software License, Version 1.0.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 8) # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 9)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 10) # Implements project representation and loading.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 11) # Each project is represented by
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 12) # - a module where all the Jamfile content live.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 13) # - an instance of 'project-attributes' class.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 14) # (given module name, can be obtained by 'attributes' rule)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 15) # - an instance of 'project-target' class (from targets.jam)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 16) # (given a module name, can be obtained by 'target' rule)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 17) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 18) # Typically, projects are created as result of loading Jamfile, which is
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 19) # do by rules 'load' and 'initialize', below. First, module for Jamfile
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 20) # is loaded and new project-attributes instance is created. Some rules
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 21) # necessary for project are added to the module (see 'project-rules' module)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 22) # at the bottom of this file.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 23) # Default project attributes are set (inheriting attributes of parent project, if
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 24) # it exists). After that, Jamfile is read. It can declare its own attributes,
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 25) # via 'project' rule, which will be combined with already set attributes.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 26) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 27) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 28) # The 'project' rule can also declare project id, which will be associated with
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 29) # the project module.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 30) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 31) # There can also be 'standalone' projects. They are created by calling 'initialize'
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 32) # on arbitrary module, and not specifying location. After the call, the module can
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 33) # call 'project' rule, declare main target and behave as regular projects. However,
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 34) # since it's not associated with any location, it's better declare only prebuilt
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 35) # targets.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 36) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 37) # The list of all loaded Jamfile is stored in variable .project-locations. It's possible
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 38) # to obtain module name for a location using 'module-name' rule. The standalone projects
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 39) # are not recorded, the only way to use them is by project id.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 40)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 41) import b2.util.path
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 42) from b2.build import property_set, property
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 43) from b2.build.errors import ExceptionWithUserContext
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 44) import b2.build.targets
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 45)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 46) import bjam
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 47)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 48) import re
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 49) import sys
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 50) import os
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 51) import string
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 52) import imp
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 53) import traceback
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 54)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 55) class ProjectRegistry:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 56)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 57) def __init__(self, manager, global_build_dir):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 58) self.manager = manager
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 59) self.global_build_dir = None
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 60) self.project_rules_ = ProjectRules(self)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 61)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 62) # The target corresponding to the project being loaded now
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 63) self.current_project = None
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 64)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 65) # The set of names of loaded project modules
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 66) self.jamfile_modules = {}
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 67)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 68) # Mapping from location to module name
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 69) self.location2module = {}
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 70)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 71) # Mapping from project id to project module
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 72) self.id2module = {}
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 73)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 74) # Map from Jamfile directory to parent Jamfile/Jamroot
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 75) # location.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 76) self.dir2parent_jamfile = {}
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 77)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 78) # Map from directory to the name of Jamfile in
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 79) # that directory (or None).
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 80) self.dir2jamfile = {}
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 81)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 82) # Map from project module to attributes object.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 83) self.module2attributes = {}
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 84)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 85) # Map from project module to target for the project
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 86) self.module2target = {}
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 87)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 88) # Map from names to Python modules, for modules loaded
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 89) # via 'using' and 'import' rules in Jamfiles.
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 90) self.loaded_tool_modules_ = {}
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 91)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 92) # Map from project target to the list of
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 93) # (id,location) pairs corresponding to all 'use-project'
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 94) # invocations.
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 95) # TODO: should not have a global map, keep this
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 96) # in ProjectTarget.
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 97) self.used_projects = {}
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 98)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 99) self.saved_current_project = []
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 100)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 101) self.JAMROOT = self.manager.getenv("JAMROOT");
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 102)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 103) # Note the use of character groups, as opposed to listing
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 104) # 'Jamroot' and 'jamroot'. With the latter, we'd get duplicate
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 105) # matches on windows and would have to eliminate duplicates.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 106) if not self.JAMROOT:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 107) self.JAMROOT = ["project-root.jam", "[Jj]amroot", "[Jj]amroot.jam"]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 108)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 109) # Default patterns to search for the Jamfiles to use for build
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 110) # declarations.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 111) self.JAMFILE = self.manager.getenv("JAMFILE")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 112)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 113) if not self.JAMFILE:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 114) self.JAMFILE = ["[Bb]uild.jam", "[Jj]amfile.v2", "[Jj]amfile",
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 115) "[Jj]amfile.jam"]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 116)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 117)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 118) def load (self, jamfile_location):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 119) """Loads jamfile at the given location. After loading, project global
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 120) file and jamfile needed by the loaded one will be loaded recursively.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 121) If the jamfile at that location is loaded already, does nothing.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 122) Returns the project module for the Jamfile."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 123)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 124) absolute = os.path.join(os.getcwd(), jamfile_location)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 125) absolute = os.path.normpath(absolute)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 126) jamfile_location = b2.util.path.relpath(os.getcwd(), absolute)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 127)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 128) if "--debug-loading" in self.manager.argv():
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 129) print "Loading Jamfile at '%s'" % jamfile_location
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 130)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 131)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 132) mname = self.module_name(jamfile_location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 133) # If Jamfile is already loaded, don't try again.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 134) if not mname in self.jamfile_modules:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 135)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 136) self.load_jamfile(jamfile_location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 137)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 138) # We want to make sure that child project are loaded only
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 139) # after parent projects. In particular, because parent projects
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 140) # define attributes whch are inherited by children, and we don't
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 141) # want children to be loaded before parents has defined everything.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 142) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 143) # While "build-project" and "use-project" can potentially refer
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 144) # to child projects from parent projects, we don't immediately
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 145) # load child projects when seing those attributes. Instead,
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 146) # we record the minimal information that will be used only later.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 147)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 148) self.load_used_projects(mname)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 149)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 150) return mname
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 151)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 152) def load_used_projects(self, module_name):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 153) # local used = [ modules.peek $(module-name) : .used-projects ] ;
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 154) used = self.used_projects[module_name]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 155)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 156) location = self.attribute(module_name, "location")
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 157) for u in used:
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 158) id = u[0]
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 159) where = u[1]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 160)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 161) self.use(id, os.path.join(location, where))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 162)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 163) def load_parent(self, location):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 164) """Loads parent of Jamfile at 'location'.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 165) Issues an error if nothing is found."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 166)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 167) found = b2.util.path.glob_in_parents(
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 168) location, self.JAMROOT + self.JAMFILE)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 169)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 170) if not found:
+1674e2d9 (jhunold 2008-08-08 19:52:05 +0000 171) print "error: Could not find parent for project at '%s'" % location
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 172) print "error: Did not find Jamfile or project-root.jam in any parent directory."
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 173) sys.exit(1)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 174)
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 175) return self.load(os.path.dirname(found[0]))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 176)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 177) def act_as_jamfile(self, module, location):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 178) """Makes the specified 'module' act as if it were a regularly loaded Jamfile
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 179) at 'location'. If Jamfile is already located for that location, it's an
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 180) error."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 181)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 182) if self.module_name(location) in self.jamfile_modules:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 183) self.manager.errors()(
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 184) "Jamfile was already loaded for '%s'" % location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 185)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 186) # Set up non-default mapping from location to module.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 187) self.location2module[location] = module
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 188)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 189) # Add the location to the list of project locations
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 190) # so that we don't try to load Jamfile in future
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 191) self.jamfile_modules.append(location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 192)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 193) self.initialize(module, location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 194)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 195) def find(self, name, current_location):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 196) """Given 'name' which can be project-id or plain directory name,
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 197) return project module corresponding to that id or directory.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 198) Returns nothing of project is not found."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 199)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 200) project_module = None
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 201)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 202) # Try interpreting name as project id.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 203) if name[0] == '/':
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 204) project_module = self.id2module.get(name)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 205)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 206) if not project_module:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 207) location = os.path.join(current_location, name)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 208) # If no project is registered for the given location, try to
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 209) # load it. First see if we have Jamfile. If not we might have project
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 210) # root, willing to act as Jamfile. In that case, project-root
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 211) # must be placed in the directory referred by id.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 212)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 213) project_module = self.module_name(location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 214) if not project_module in self.jamfile_modules and \
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 215) b2.util.path.glob([location], self.JAMROOT + self.JAMFILE):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 216) project_module = self.load(location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 217)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 218) return project_module
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 219)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 220) def module_name(self, jamfile_location):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 221) """Returns the name of module corresponding to 'jamfile-location'.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 222) If no module corresponds to location yet, associates default
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 223) module name with that location."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 224) module = self.location2module.get(jamfile_location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 225) if not module:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 226) # Root the path, so that locations are always umbiguious.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 227) # Without this, we can't decide if '../../exe/program1' and '.'
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 228) # are the same paths, or not.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 229) jamfile_location = os.path.realpath(
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 230) os.path.join(os.getcwd(), jamfile_location))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 231) module = "Jamfile<%s>" % jamfile_location
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 232) self.location2module[jamfile_location] = module
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 233) return module
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 234)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 235) def find_jamfile (self, dir, parent_root=0, no_errors=0):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 236) """Find the Jamfile at the given location. This returns the
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 237) exact names of all the Jamfiles in the given directory. The optional
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 238) parent-root argument causes this to search not the given directory
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 239) but the ones above it up to the directory given in it."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 240)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 241) # Glob for all the possible Jamfiles according to the match pattern.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 242) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 243) jamfile_glob = None
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 244) if parent_root:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 245) parent = self.dir2parent_jamfile.get(dir)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 246) if not parent:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 247) parent = b2.util.path.glob_in_parents(dir,
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 248) self.JAMFILE)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 249) self.dir2parent_jamfile[dir] = parent
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 250) jamfile_glob = parent
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 251) else:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 252) jamfile = self.dir2jamfile.get(dir)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 253) if not jamfile:
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 254) jamfile = b2.util.path.glob([dir], self.JAMFILE)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 255) self.dir2jamfile[dir] = jamfile
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 256) jamfile_glob = jamfile
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 257)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 258) if len(jamfile_glob):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 259) # Multiple Jamfiles found in the same place. Warn about this.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 260) # And ensure we use only one of them.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 261) # As a temporary convenience measure, if there's Jamfile.v2 amount
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 262) # found files, suppress the warning and use it.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 263) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 264) pattern = "(.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam)"
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 265) v2_jamfiles = [x for x in jamfile_glob if re.match(pattern, x)]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 266) if len(v2_jamfiles) == 1:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 267) jamfile_glob = v2_jamfiles
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 268) else:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 269) print """warning: Found multiple Jamfiles at '%s'!
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 270) Loading the first one: '%s'.""" % (dir, jamfile_glob[0])
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 271)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 272) # Could not find it, error.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 273) if not no_errors and not jamfile_glob:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 274) self.manager.errors()(
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 275) """Unable to load Jamfile.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 276) Could not find a Jamfile in directory '%s'
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 277) Attempted to find it with pattern '%s'.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 278) Please consult the documentation at 'http://boost.org/b2.'."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 279) % (dir, string.join(self.JAMFILE)))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 280)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 281) return jamfile_glob[0]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 282)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 283) def load_jamfile(self, dir):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 284) """Load a Jamfile at the given directory. Returns nothing.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 285) Will attempt to load the file as indicated by the JAMFILE patterns.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 286) Effect of calling this rule twice with the same 'dir' is underfined."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 287)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 288) # See if the Jamfile is where it should be.
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 289) jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 290) if not jamfile_to_load:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 291) jamfile_to_load = self.find_jamfile(dir)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 292) else:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 293) jamfile_to_load = jamfile_to_load[0]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 294)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 295) # The module of the jamfile.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 296) dir = os.path.realpath(os.path.dirname(jamfile_to_load))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 297)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 298) jamfile_module = self.module_name (dir)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 299)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 300) # Initialize the jamfile module before loading.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 301) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 302) self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 303)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 304) saved_project = self.current_project
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 305)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 306) self.used_projects[jamfile_module] = []
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 307)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 308) # Now load the Jamfile in it's own context.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 309) # Initialization might have load parent Jamfiles, which might have
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 310) # loaded the current Jamfile with use-project. Do a final check to make
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 311) # sure it's not loaded already.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 312) if not jamfile_module in self.jamfile_modules:
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 313) self.jamfile_modules[jamfile_module] = True
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 314)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 315) # FIXME:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 316) # mark-as-user $(jamfile-module) ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 317)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 318) bjam.call("load", jamfile_module, jamfile_to_load)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 319) basename = os.path.basename(jamfile_to_load)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 320)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 321) # Now do some checks
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 322) if self.current_project != saved_project:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 323) self.manager.errors()(
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 324) """The value of the .current-project variable
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 325) has magically changed after loading a Jamfile.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 326) This means some of the targets might be defined a the wrong project.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 327) after loading %s
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 328) expected value %s
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 329) actual value %s""" % (jamfile_module, saved_project, self.current_project))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 330)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 331) if self.global_build_dir:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 332) id = self.attribute(jamfile_module, "id")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 333) project_root = self.attribute(jamfile_module, "project-root")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 334) location = self.attribute(jamfile_module, "location")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 335)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 336) if location and project_root == dir:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 337) # This is Jamroot
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 338) if not id:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 339) # FIXME: go via errors module, so that contexts are
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 340) # shown?
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 341) print "warning: the --build-dir option was specified"
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 342) print "warning: but Jamroot at '%s'" % dir
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 343) print "warning: specified no project id"
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 344) print "warning: the --build-dir option will be ignored"
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 345)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 346)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 347) def load_standalone(self, jamfile_module, file):
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 348) """Loads 'file' as standalone project that has no location
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 349) associated with it. This is mostly useful for user-config.jam,
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 350) which should be able to define targets, but although it has
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 351) some location in filesystem, we don't want any build to
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 352) happen in user's HOME, for example.
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 353)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 354) The caller is required to never call this method twice on
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 355) the same file.
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 356) """
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 357)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 358) self.initialize(jamfile_module)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 359) self.used_projects[jamfile_module] = []
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 360) bjam.call("load", jamfile_module, file)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 361) self.load_used_projects(jamfile_module)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 362)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 363) def is_jamroot(self, basename):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 364) match = [ pat for pat in self.JAMROOT if re.match(pat, basename)]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 365) if match:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 366) return 1
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 367) else:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 368) return 0
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 369)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 370) def initialize(self, module_name, location=None, basename=None):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 371) """Initialize the module for a project.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 372)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 373) module-name is the name of the project module.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 374) location is the location (directory) of the project to initialize.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 375) If not specified, stanalone project will be initialized
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 376) """
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 377)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 378) if "--debug-loading" in self.manager.argv():
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 379) print "Initializing project '%s'" % module_name
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 380)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 381) # TODO: need to consider if standalone projects can do anything but defining
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 382) # prebuilt targets. If so, we need to give more sensible "location", so that
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 383) # source paths are correct.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 384) if not location:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 385) location = ""
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 386) else:
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 387) location = b2.util.path.relpath(os.getcwd(), location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 388)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 389) attributes = ProjectAttributes(self.manager, location, module_name)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 390) self.module2attributes[module_name] = attributes
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 391)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 392) if location:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 393) attributes.set("source-location", location, exact=1)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 394) else:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 395) attributes.set("source-location", "", exact=1)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 396)
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 397) attributes.set("requirements", property_set.empty(), exact=True)
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 398) attributes.set("usage-requirements", property_set.empty(), exact=True)
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 399) attributes.set("default-build", [], exact=True)
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 400) attributes.set("projects-to-build", [], exact=True)
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 401) attributes.set("project-root", None, exact=True)
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 402) attributes.set("build-dir", None, exact=True)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 403)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 404) self.project_rules_.init_project(module_name)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 405)
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 406) jamroot = False
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 407)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 408) parent_module = None;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 409) if module_name == "site-config":
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 410) # No parent
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 411) pass
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 412) elif module_name == "user-config":
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 413) parent_module = "site-config"
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 414) elif location and not self.is_jamroot(basename):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 415) # We search for parent/project-root only if jamfile was specified
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 416) # --- i.e
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 417) # if the project is not standalone.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 418) parent_module = self.load_parent(location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 419) else:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 420) # It's either jamroot, or standalone project.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 421) # If it's jamroot, inherit from user-config.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 422) if location:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 423) parent_module = "user-config" ;
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 424) jamroot = True ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 425)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 426) if parent_module:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 427) self.inherit_attributes(module_name, parent_module)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 428) attributes.set("parent-module", parent_module, exact=1)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 429)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 430) if jamroot:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 431) attributes.set("project-root", location, exact=1)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 432)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 433) parent = None
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 434) if parent_module:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 435) parent = self.target(parent_module)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 436)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 437) if not self.module2target.has_key(module_name):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 438) target = b2.build.targets.ProjectTarget(self.manager,
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 439) module_name, module_name, parent,
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 440) self.attribute(module_name,"requirements"),
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 441) # FIXME: why we need to pass this? It's not
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 442) # passed in jam code.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 443) self.attribute(module_name, "default-build"))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 444) self.module2target[module_name] = target
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 445)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 446) self.current_project = self.target(module_name)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 447)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 448) def inherit_attributes(self, project_module, parent_module):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 449) """Make 'project-module' inherit attributes of project
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 450) root and parent module."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 451)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 452) attributes = self.module2attributes[project_module]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 453) pattributes = self.module2attributes[parent_module]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 454)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 455) # Parent module might be locationless user-config.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 456) # FIXME:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 457) #if [ modules.binding $(parent-module) ]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 458) #{
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 459) # $(attributes).set parent : [ path.parent
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 460) # [ path.make [ modules.binding $(parent-module) ] ] ] ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 461) # }
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 462)
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 463) attributes.set("project-root", pattributes.get("project-root"), exact=True)
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 464) attributes.set("default-build", pattributes.get("default-build"), exact=True)
+49c03622 (jhunold 2008-07-23 09:57:41 +0000 465) attributes.set("requirements", pattributes.get("requirements"), exact=True)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 466) attributes.set("usage-requirements",
+cde6f09a (vladimir_prus 2007-10-19 23:12:33 +0000 467) pattributes.get("usage-requirements"), exact=1)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 468)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 469) parent_build_dir = pattributes.get("build-dir")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 470)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 471) if parent_build_dir:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 472) # Have to compute relative path from parent dir to our dir
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 473) # Convert both paths to absolute, since we cannot
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 474) # find relative path from ".." to "."
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 475)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 476) location = attributes.get("location")
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 477) parent_location = pattributes.get("location")
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 478)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 479) our_dir = os.path.join(os.getcwd(), location)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 480) parent_dir = os.path.join(os.getcwd(), parent_location)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 481)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 482) build_dir = os.path.join(parent_build_dir,
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 483) b2.util.path.relpath(parent_dir,
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 484) our_dir))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 485)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 486) def register_id(self, id, module):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 487) """Associate the given id with the given project module."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 488) self.id2module[id] = module
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 489)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 490) def current(self):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 491) """Returns the project which is currently being loaded."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 492) return self.current_project
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 493)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 494) def push_current(self, project):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 495) """Temporary changes the current project to 'project'. Should
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 496) be followed by 'pop-current'."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 497) self.saved_current_project.append(self.current_project)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 498) self.current_project = project
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 499)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 500) def pop_current(self):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 501) self.current_project = self.saved_current_project[-1]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 502) del self.saved_current_project[-1]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 503)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 504) def attributes(self, project):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 505) """Returns the project-attribute instance for the
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 506) specified jamfile module."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 507) return self.module2attributes[project]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 508)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 509) def attribute(self, project, attribute):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 510) """Returns the value of the specified attribute in the
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 511) specified jamfile module."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 512) return self.module2attributes[project].get(attribute)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 513)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 514) def target(self, project_module):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 515) """Returns the project target corresponding to the 'project-module'."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 516) if not self.module2target[project_module]:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 517) self.module2target[project_module] = \
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 518) ProjectTarget(project_module, project_module,
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 519) self.attribute(project_module, "requirements"))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 520)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 521) return self.module2target[project_module]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 522)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 523) def use(self, id, location):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 524) # Use/load a project.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 525) saved_project = self.current_project
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 526) project_module = self.load(location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 527) declared_id = self.attribute(project_module, "id")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 528)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 529) if not declared_id or declared_id != id:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 530) # The project at 'location' either have no id or
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 531) # that id is not equal to the 'id' parameter.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 532) if self.id2module[id] and self.id2module[id] != project_module:
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 533) self.manager.errors()(
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 534) """Attempt to redeclare already existing project id '%s'""" % id)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 535) self.id2module[id] = project_module
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 536)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 537) self.current_module = saved_project
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 538)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 539) def add_rule(self, name, callable):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 540) """Makes rule 'name' available to all subsequently loaded Jamfiles.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 541)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 542) Calling that rule wil relay to 'callable'."""
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 543) self.project_rules_.add_rule(name, callable)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 544)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 545) def project_rules(self):
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 546) return self.project_rules_
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 547)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 548) def glob_internal(self, project, wildcards, excludes, rule_name):
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 549) location = project.get("source-location")
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 550)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 551) result = []
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 552) callable = b2.util.path.__dict__[rule_name]
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 553)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 554) paths = callable(location, wildcards, excludes)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 555) has_dir = 0
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 556) for w in wildcards:
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 557) if os.path.dirname(w):
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 558) has_dir = 1
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 559) break
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 560)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 561) if has_dir or rule_name != "glob":
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 562) # The paths we've found are relative to current directory,
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 563) # but the names specified in sources list are assumed to
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 564) # be relative to source directory of the corresponding
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 565) # prject. So, just make the name absolute.
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 566) result = [os.path.join(os.getcwd(), p) for p in paths]
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 567) else:
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 568) # There were not directory in wildcard, so the files are all
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 569) # in the source directory of the project. Just drop the
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 570) # directory, instead of making paths absolute.
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 571) result = [os.path.basename(p) for p in paths]
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 572)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 573) return result
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 574)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 575) def load_module(self, name, extra_path=None):
+53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 576) """Classic Boost.Build 'modules' are in fact global variables.
+53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 577) Therefore, try to find an already loaded Python module called 'name' in sys.modules.
+53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 578) If the module ist not loaded, find it Boost.Build search
+53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 579) path and load it. The new module is not entered in sys.modules.
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 580) The motivation here is to have disjoint namespace of modules
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 581) loaded via 'import/using' in Jamfile, and ordinary Python
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 582) modules. We don't want 'using foo' in Jamfile to load ordinary
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 583) Python module 'foo' which is going to not work. And we
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 584) also don't want 'import foo' in regular Python module to
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 585) accidentally grab module named foo that is internal to
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 586) Boost.Build and intended to provide interface to Jamfiles."""
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 587)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 588) existing = self.loaded_tool_modules_.get(name)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 589) if existing:
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 590) return existing
+53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 591)
+53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 592) modules = sys.modules
+53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 593) for class_name in modules:
+53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 594) if name in class_name:
+53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 595) module = modules[class_name]
+53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 596) self.loaded_tool_modules_[name] = module
+53b0faa2 (jhunold 2008-08-10 18:25:50 +0000 597) return module
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 598)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 599) path = extra_path
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 600) if not path:
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 601) path = []
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 602) path.extend(self.manager.b2.path())
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 603) location = None
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 604) for p in path:
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 605) l = os.path.join(p, name + ".py")
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 606) if os.path.exists(l):
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 607) location = l
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 608) break
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 609)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 610) if not location:
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 611) self.manager.errors()("Cannot find module '%s'" % name)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 612)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 613) mname = "__build_build_temporary__"
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 614) file = open(location)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 615) try:
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 616) # TODO: this means we'll never make use of .pyc module,
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 617) # which might be a problem, or not.
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 618) module = imp.load_module(mname, file, os.path.basename(location),
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 619) (".py", "r", imp.PY_SOURCE))
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 620) del sys.modules[mname]
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 621) self.loaded_tool_modules_[name] = module
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 622) return module
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 623) finally:
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 624) file.close()
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 625)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 626)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 627)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 628) # FIXME:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 629) # Defines a Boost.Build extension project. Such extensions usually
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 630) # contain library targets and features that can be used by many people.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 631) # Even though extensions are really projects, they can be initialize as
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 632) # a module would be with the "using" (project.project-rules.using)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 633) # mechanism.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 634) #rule extension ( id : options * : * )
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 635) #{
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 636) # # The caller is a standalone module for the extension.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 637) # local mod = [ CALLER_MODULE ] ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 638) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 639) # # We need to do the rest within the extension module.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 640) # module $(mod)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 641) # {
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 642) # import path ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 643) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 644) # # Find the root project.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 645) # local root-project = [ project.current ] ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 646) # root-project = [ $(root-project).project-module ] ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 647) # while
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 648) # [ project.attribute $(root-project) parent-module ] &&
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 649) # [ project.attribute $(root-project) parent-module ] != user-config
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 650) # {
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 651) # root-project = [ project.attribute $(root-project) parent-module ] ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 652) # }
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 653) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 654) # # Create the project data, and bring in the project rules
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 655) # # into the module.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 656) # project.initialize $(__name__) :
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 657) # [ path.join [ project.attribute $(root-project) location ] ext $(1:L) ] ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 658) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 659) # # Create the project itself, i.e. the attributes.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 660) # # All extensions are created in the "/ext" project space.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 661) # project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 662) # local attributes = [ project.attributes $(__name__) ] ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 663) #
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 664) # # Inherit from the root project of whomever is defining us.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 665) # project.inherit-attributes $(__name__) : $(root-project) ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 666) # $(attributes).set parent-module : $(root-project) : exact ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 667) # }
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 668) #}
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 669)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 670)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 671) class ProjectAttributes:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 672) """Class keeping all the attributes of a project.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 673)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 674) The standard attributes are 'id', "location", "project-root", "parent"
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 675) "requirements", "default-build", "source-location" and "projects-to-build".
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 676) """
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 677)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 678) def __init__(self, manager, location, project_module):
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 679) self.manager = manager
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 680) self.location = location
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 681) self.project_module = project_module
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 682) self.attributes = {}
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 683) self.usage_requirements = None
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 684)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 685) def set(self, attribute, specification, exact):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 686) """Set the named attribute from the specification given by the user.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 687) The value actually set may be different."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 688)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 689) if exact:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 690) self.__dict__[attribute] = specification
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 691)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 692) elif attribute == "requirements":
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 693) self.requirements = property_set.refine_from_user_input(
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 694) self.requirements, specification,
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 695) self.project_module, self.location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 696)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 697) elif attribute == "usage-requirements":
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 698) unconditional = []
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 699) for p in specification:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 700) split = property.split_conditional(p)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 701) if split:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 702) unconditional.append(split[1])
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 703) else:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 704) unconditional.append(p)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 705)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 706) non_free = property.remove("free", unconditional)
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 707) if non_free:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 708) pass
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 709) # FIXME:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 710) #errors.error "usage-requirements" $(specification) "have non-free properties" $(non-free) ;
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 711)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 712) t = property.translate_paths(specification, self.location)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 713)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 714) existing = self.__dict__.get("usage-requirements")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 715) if existing:
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 716) new = property_set.create(existing.raw() + t)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 717) else:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 718) new = property_set.create(t)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 719) self.__dict__["usage-requirements"] = new
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 720)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 721)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 722) elif attribute == "default-build":
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 723) self.__dict__["default-build"] = property_set.create(specification)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 724)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 725) elif attribute == "source-location":
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 726) source_location = []
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 727) for path in specification:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 728) source_location += os.path.join(self.location, path)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 729) self.__dict__["source-location"] = source_location
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 730)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 731) elif attribute == "build-dir":
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 732) self.__dict__["build-dir"] = os.path.join(self.location, specification)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 733)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 734) elif not attribute in ["id", "default-build", "location",
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 735) "source-location", "parent",
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 736) "projects-to-build", "project-root"]:
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 737) self.manager.errors()(
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 738) """Invalid project attribute '%s' specified
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 739) for project at '%s'""" % (attribute, self.location))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 740) else:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 741) self.__dict__[attribute] = specification
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 742)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 743) def get(self, attribute):
+cde6f09a (vladimir_prus 2007-10-19 23:12:33 +0000 744) return self.__dict__[attribute]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 745)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 746) def dump(self):
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 747) """Prints the project attributes."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 748) id = self.get("id")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 749) if not id:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 750) id = "(none)"
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 751) else:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 752) id = id[0]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 753)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 754) parent = self.get("parent")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 755) if not parent:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 756) parent = "(none)"
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 757) else:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 758) parent = parent[0]
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 759)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 760) print "'%s'" % id
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 761) print "Parent project:%s", parent
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 762) print "Requirements:%s", self.get("requirements")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 763) print "Default build:%s", string.join(self.get("debuild-build"))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 764) print "Source location:%s", string.join(self.get("source-location"))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 765) print "Projects to build:%s", string.join(self.get("projects-to-build").sort());
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 766)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 767) class ProjectRules:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 768) """Class keeping all rules that are made available to Jamfile."""
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 769)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 770) def __init__(self, registry):
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 771) self.registry = registry
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 772) self.manager_ = registry.manager
+38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 773) self.rules = {}
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 774) self.local_names = [x for x in self.__class__.__dict__
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 775) if x not in ["__init__", "init_project", "add_rule",
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 776) "error_reporting_wrapper", "add_rule_for_type"]]
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 777) self.all_names_ = [x for x in self.local_names]
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 778)
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 779) def add_rule_for_type(self, type):
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 780) rule_name = type.lower();
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 781)
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 782) def xpto (name, sources, requirements = [], default_build = None, usage_requirements = []):
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 783) return self.manager_.targets().create_typed_target(
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 784) type, self.registry.current(), name[0], sources,
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 785) requirements, default_build, usage_requirements)
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 786)
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 787) self.add_rule(type.lower(), xpto)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 788)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 789) def add_rule(self, name, callable):
+38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 790) self.rules[name] = callable
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 791) self.all_names_.append(name)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 792)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 793) def all_names(self):
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 794) return self.all_names_
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 795)
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 796) def call_and_report_errors(self, callable, *args):
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 797) result = None
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 798) try:
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 799) self.manager_.errors().push_jamfile_context()
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 800) result = callable(*args)
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 801) except ExceptionWithUserContext, e:
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 802) e.report()
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 803) except Exception, e:
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 804) try:
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 805) self.manager_.errors().handle_stray_exception (e)
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 806) except ExceptionWithUserContext, e:
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 807) e.report()
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 808) finally:
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 809) self.manager_.errors().pop_jamfile_context()
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 810)
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 811) return result
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 812)
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 813) def make_wrapper(self, callable):
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 814) """Given a free-standing function 'callable', return a new
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 815) callable that will call 'callable' and report all exceptins,
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 816) using 'call_and_report_errors'."""
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 817) def wrapper(*args):
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 818) self.call_and_report_errors(callable, *args)
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 819) return wrapper
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 820)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 821) def init_project(self, project_module):
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 822)
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 823) for n in self.local_names:
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 824) # Using 'getattr' here gives us a bound method,
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 825) # while using self.__dict__[r] would give unbound one.
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 826) v = getattr(self, n)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 827) if callable(v):
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 828) if n == "import_":
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 829) n = "import"
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 830) else:
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 831) n = string.replace(n, "_", "-")
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 832)
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 833) bjam.import_rule(project_module, n,
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 834) self.make_wrapper(v))
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 835)
+38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 836) for n in self.rules:
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 837) bjam.import_rule(project_module, n,
+0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 838) self.make_wrapper(self.rules[n]))
+38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 839)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 840) def project(self, *args):
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 841)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 842) jamfile_module = self.registry.current().project_module()
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 843) attributes = self.registry.attributes(jamfile_module)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 844)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 845) id = None
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 846) if args and args[0]:
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 847) id = args[0][0]
+092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 848) args = args[1:]
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 849)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 850) if id:
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 851) if id[0] != '/':
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 852) id = '/' + id
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 853) self.registry.register_id (id, jamfile_module)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 854)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 855) explicit_build_dir = None
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 856) for a in args:
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 857) if a:
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 858) attributes.set(a[0], a[1:], exact=0)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 859) if a[0] == "build-dir":
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 860) explicit_build_dir = a[1]
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 861)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 862) # If '--build-dir' is specified, change the build dir for the project.
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 863) if self.registry.global_build_dir:
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 864)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 865) location = attributes.get("location")
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 866) # Project with empty location is 'standalone' project, like
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 867) # user-config, or qt. It has no build dir.
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 868) # If we try to set build dir for user-config, we'll then
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 869) # try to inherit it, with either weird, or wrong consequences.
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 870) if location and location == attributes.get("project-root"):
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 871) # This is Jamroot.
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 872) if id:
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 873) if explicit_build_dir and os.path.isabs(explicit_build_dir):
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 874) self.register.manager.errors()(
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 875) """Absolute directory specified via 'build-dir' project attribute
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 876) Don't know how to combine that with the --build-dir option.""")
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 877)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 878) rid = id
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 879) if rid[0] == '/':
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 880) rid = rid[1:]
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 881)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 882) p = os.path.join(self.registry.global_build_dir,
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 883) rid, explicit_build_dir)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 884) attributes.set("build-dir", p, exact=1)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 885) elif explicit_build_dir:
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 886) self.registry.manager.errors()(
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 887) """When --build-dir is specified, the 'build-project'
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 888) attribute is allowed only for top-level 'project' invocations""")
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 889)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 890) def constant(self, name, value):
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 891) """Declare and set a project global constant.
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 892) Project global constants are normal variables but should
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 893) not be changed. They are applied to every child Jamfile."""
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 894) m = "Jamfile</home/ghost/Work/Boost/boost-svn/tools/build/v2_python/python/tests/bjam/make>"
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 895) self.registry.current().add_constant(name[0], value)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 896)
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 897) def path_constant(self, name, value):
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 898) """Declare and set a project global constant, whose value is a path. The
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 899) path is adjusted to be relative to the invocation directory. The given
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 900) value path is taken to be either absolute, or relative to this project
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 901) root."""
+0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 902) self.registry.current().add_constant(name[0], value, path=1)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 903)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 904) def use_project(self, id, where):
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 905) # See comment in 'load' for explanation why we record the
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 906) # parameters as opposed to loading the project now.
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 907) m = self.registry.current().project_module();
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 908) self.registry.used_projects[m].append((id, where))
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 909)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 910) def build_project(self, dir):
+1674e2d9 (jhunold 2008-08-08 19:52:05 +0000 911) assert(isinstance(dir, list))
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 912) jamfile_module = self.registry.current().project_module()
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 913) attributes = self.registry.attributes(jamfile_module)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 914) now = attributes.get("projects-to-build")
+1674e2d9 (jhunold 2008-08-08 19:52:05 +0000 915) attributes.set("projects-to-build", now + dir, exact=True)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 916)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 917) def explicit(self, target_names):
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 918) t = self.registry.current()
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 919) for n in target_names:
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 920) t.mark_target_as_explicit(n)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 921)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 922) def glob(self, wildcards, excludes=None):
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 923) return self.registry.glob_internal(self.registry.current(),
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 924) wildcards, excludes, "glob")
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 925)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 926) def glob_tree(self, wildcards, excludes=None):
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 927) bad = 0
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 928) for p in wildcards:
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 929) if os.path.dirname(p):
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 930) bad = 1
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 931)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 932) if excludes:
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 933) for p in excludes:
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 934) if os.path.dirname(p):
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 935) bad = 1
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 936)
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 937) if bad:
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 938) self.registry.manager().errors()(
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 939) "The patterns to 'glob-tree' may not include directory")
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 940) return self.registry.glob_internal(self.registry.current(),
+2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 941) wildcards, excludes, "glob_tree")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 942)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 943)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 944) def using(self, toolset, *args):
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 945) # The module referred by 'using' can be placed in
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 946) # the same directory as Jamfile, and the user
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 947) # will expect the module to be found even though
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 948) # the directory is not in BOOST_BUILD_PATH.
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 949) # So temporary change the search path.
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 950) jamfile_module = self.registry.current().project_module()
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 951) attributes = self.registry.attributes(jamfile_module)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 952) location = attributes.get("location")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 953)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 954) m = self.registry.load_module(toolset[0], [location])
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 955) if not m.__dict__.has_key("init"):
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 956) self.registry.manager.errors()(
+7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 957) "Tool module '%s' does not define the 'init' method" % toolset[0])
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 958) m.init(*args)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 959)
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 960)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 961) def import_(self, name, names_to_import=None, local_names=None):
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 962)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 963) name = name[0]
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 964) jamfile_module = self.registry.current().project_module()
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 965) attributes = self.registry.attributes(jamfile_module)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 966) location = attributes.get("location")
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 967)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 968) m = self.registry.load_module(name, [location])
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 969)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 970) for f in m.__dict__:
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 971) v = m.__dict__[f]
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 972) if callable(v):
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 973) bjam.import_rule(jamfile_module, name + "." + f, v)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 974)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 975) if names_to_import:
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 976) if not local_names:
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 977) local_names = names_to_import
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 978)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 979) if len(names_to_import) != len(local_names):
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 980) self.registry.manager.errors()(
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 981) """The number of names to import and local names do not match.""")
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 982)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 983) for n, l in zip(names_to_import, local_names):
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 984) bjam.import_rule(jamfile_module, l, m.__dict__[n])
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 985)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 986) def conditional(self, condition, requirements):
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 987) """Calculates conditional requirements for multiple requirements
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 988) at once. This is a shorthand to be reduce duplication and to
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 989) keep an inline declarative syntax. For example:
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 990)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 991) lib x : x.cpp : [ conditional <toolset>gcc <variant>debug :
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 992) <define>DEBUG_EXCEPTION <define>DEBUG_TRACE ] ;
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 993) """
+f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 994)
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 995) c = string.join(condition, ",")
+f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 996) return [c + ":" + r for r in requirements]
diff --git a/tools/build/v2/build/project.jam b/tools/build/v2/build/project.jam
new file mode 100644
index 0000000000..c9967613bc
--- /dev/null
+++ b/tools/build/v2/build/project.jam
@@ -0,0 +1,1110 @@
+# Copyright 2002, 2003 Dave Abrahams
+# Copyright 2002, 2005, 2006 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Implements project representation and loading. Each project is represented by:
+# - a module where all the Jamfile content live.
+# - an instance of 'project-attributes' class.
+# (given a module name, can be obtained using the 'attributes' rule)
+# - an instance of 'project-target' class (from targets.jam)
+# (given a module name, can be obtained using the 'target' rule)
+#
+# Typically, projects are created as result of loading a Jamfile, which is done
+# by rules 'load' and 'initialize', below. First, module for Jamfile is loaded
+# and new project-attributes instance is created. Some rules necessary for
+# project are added to the module (see 'project-rules' module) at the bottom of
+# this file. Default project attributes are set (inheriting attributes of parent
+# project, if it exists). After that the Jamfile is read. It can declare its own
+# attributes using the 'project' rule which will be combined with any already
+# set attributes.
+#
+# The 'project' rule can also declare a project id which will be associated with
+# the project module.
+#
+# There can also be 'standalone' projects. They are created by calling
+# 'initialize' on an arbitrary module and not specifying their location. After
+# the call, the module can call the 'project' rule, declare main targets and
+# behave as a regular project except that, since it is not associated with any
+# location, it should not declare targets that are not prebuilt.
+#
+# The list of all loaded Jamfile is stored in the .project-locations variable.
+# It is possible to obtain a module name for a location using the 'module-name'
+# rule. Standalone projects are not recorded and can only be referenced using
+# their project id.
+
+import "class" : new ;
+import errors ;
+import modules ;
+import path ;
+import print ;
+import property-set ;
+import sequence ;
+
+
+# Loads the Jamfile at the given location. After loading, project global file
+# and Jamfiles needed by the requested one will be loaded recursively. If the
+# Jamfile at that location is loaded already, does nothing. Returns the project
+# module for the Jamfile.
+#
+rule load ( jamfile-location )
+{
+ if --debug-loading in [ modules.peek : ARGV ]
+ {
+ ECHO "Loading Jamfile at" '$(jamfile-location)' ;
+ }
+
+ local module-name = [ module-name $(jamfile-location) ] ;
+ # If Jamfile is already loaded, don't try again.
+ if ! $(module-name) in $(.jamfile-modules)
+ {
+ load-jamfile $(jamfile-location) : $(module-name) ;
+
+ # We want to make sure that child project are loaded only after parent
+ # projects. In particular, because parent projects define attributes
+ # which are inherited by children, and we don't want children to be
+ # loaded before parent has defined everything.
+ #
+ # While "build-project" and "use-project" can potentially refer to child
+ # projects from parent projects, we don't immediately load child
+ # projects when seeing those attributes. Instead, we record the minimal
+ # information to be used only later.
+ load-used-projects $(module-name) ;
+ }
+ return $(module-name) ;
+}
+
+
+rule load-used-projects ( module-name )
+{
+ local used = [ modules.peek $(module-name) : .used-projects ] ;
+ local location = [ attribute $(module-name) location ] ;
+ import project ;
+ while $(used)
+ {
+ local id = $(used[1]) ;
+ local where = $(used[2]) ;
+
+ project.use $(id) : [ path.root [ path.make $(where) ] $(location) ] ;
+ used = $(used[3-]) ;
+ }
+}
+
+
+# Note the use of character groups, as opposed to listing 'Jamroot' and
+# 'jamroot'. With the latter, we would get duplicate matches on Windows and
+# would have to eliminate duplicates.
+JAMROOT ?= [ modules.peek : JAMROOT ] ;
+JAMROOT ?= project-root.jam [Jj]amroot [Jj]amroot.jam ;
+
+
+# Loads parent of Jamfile at 'location'. Issues an error if nothing is found.
+#
+rule load-parent ( location )
+{
+ local found = [ path.glob-in-parents $(location) : $(JAMROOT) $(JAMFILE) ] ;
+
+ if ! $(found)
+ {
+ ECHO error: Could not find parent for project at '$(location)' ;
+ EXIT error: Did not find Jamfile.jam or Jamroot.jam in any parent
+ directory. ;
+ }
+
+ return [ load $(found[1]:D) ] ;
+}
+
+
+# Makes the specified 'module' act as if it were a regularly loaded Jamfile at
+# 'location'. Reports an error if a Jamfile has already been loaded for that
+# location.
+#
+rule act-as-jamfile ( module : location )
+{
+ if [ module-name $(location) ] in $(.jamfile-modules)
+ {
+ errors.error "Jamfile was already loaded for '$(location)'" ;
+ }
+ # Set up non-default mapping from location to module.
+ .module.$(location) = $(module) ;
+
+ # Add the location to the list of project locations so that we don't try to
+ # reload the same Jamfile in the future.
+ .jamfile-modules += [ module-name $(location) ] ;
+
+ initialize $(module) : $(location) ;
+}
+
+
+# Returns the project module corresponding to the given project-id or plain
+# directory name. Returns nothing if such a project can not be found.
+#
+rule find ( name : current-location )
+{
+ local project-module ;
+
+ # Try interpreting name as project id.
+ if [ path.is-rooted $(name) ]
+ {
+ project-module = $($(name).jamfile-module) ;
+ }
+
+ if ! $(project-module)
+ {
+ local location = [ path.root [ path.make $(name) ] $(current-location) ]
+ ;
+
+ # If no project is registered for the given location, try to load it.
+ # First see if we have a Jamfile. If not, then see if we might have a
+ # project root willing to act as a Jamfile. In that case, project root
+ # must be placed in the directory referred by id.
+
+ project-module = [ module-name $(location) ] ;
+ if ! $(project-module) in $(.jamfile-modules)
+ {
+ if [ path.glob $(location) : $(JAMROOT) $(JAMFILE) ]
+ {
+ project-module = [ load $(location) ] ;
+ }
+ else
+ {
+ project-module = ;
+ }
+ }
+ }
+
+ return $(project-module) ;
+}
+
+
+# Returns the name of the module corresponding to 'jamfile-location'. If no
+# module corresponds to that location yet, associates the default module name
+# with that location.
+#
+rule module-name ( jamfile-location )
+{
+ if ! $(.module.$(jamfile-location))
+ {
+ # Root the path, so that locations are always unambiguous. Without this,
+ # we can't decide if '../../exe/program1' and '.' are the same paths.
+ jamfile-location = [ path.root $(jamfile-location) [ path.pwd ] ] ;
+ .module.$(jamfile-location) = Jamfile<$(jamfile-location)> ;
+ }
+ return $(.module.$(jamfile-location)) ;
+}
+
+
+# Default patterns to search for the Jamfiles to use for build declarations.
+#
+JAMFILE = [ modules.peek : JAMFILE ] ;
+JAMFILE ?= [Bb]uild.jam [Jj]amfile.v2 [Jj]amfile [Jj]amfile.jam ;
+
+
+# Find the Jamfile at the given location. This returns the exact names of all
+# the Jamfiles in the given directory. The optional parent-root argument causes
+# this to search not the given directory but the ones above it up to the
+# directory given in it.
+#
+rule find-jamfile (
+ dir # The directory(s) to look for a Jamfile.
+ parent-root ? # Optional flag indicating to search for the parent Jamfile.
+ : no-errors ?
+ )
+{
+ # Glob for all the possible Jamfiles according to the match pattern.
+ #
+ local jamfile-glob = ;
+ if $(parent-root)
+ {
+ if ! $(.parent-jamfile.$(dir))
+ {
+ .parent-jamfile.$(dir) = [ path.glob-in-parents $(dir) : $(JAMFILE)
+ ] ;
+ }
+ jamfile-glob = $(.parent-jamfile.$(dir)) ;
+ }
+ else
+ {
+ if ! $(.jamfile.$(dir))
+ {
+ .jamfile.$(dir) = [ path.glob $(dir) : $(JAMFILE) ] ;
+ }
+ jamfile-glob = $(.jamfile.$(dir)) ;
+
+ }
+
+ local jamfile-to-load = $(jamfile-glob) ;
+ # Multiple Jamfiles found in the same place. Warn about this and ensure we
+ # use only one of them. As a temporary convenience measure, if there is
+ # Jamfile.v2 among found files, suppress the warning and use it.
+ #
+ if $(jamfile-to-load[2-])
+ {
+ local v2-jamfiles = [ MATCH (.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam) : $(jamfile-to-load) ] ;
+
+ if $(v2-jamfiles) && ! $(v2-jamfiles[2])
+ {
+ jamfile-to-load = $(v2-jamfiles) ;
+ }
+ else
+ {
+ local jamfile = [ path.basename $(jamfile-to-load[1]) ] ;
+ ECHO "warning: Found multiple Jamfiles at '"$(dir)"'!"
+ "Loading the first one: '$(jamfile)'." ;
+ }
+
+ jamfile-to-load = $(jamfile-to-load[1]) ;
+ }
+
+ # Could not find it, error.
+ #
+ if ! $(no-errors) && ! $(jamfile-to-load)
+ {
+ errors.error Unable to load Jamfile.
+ : Could not find a Jamfile in directory '$(dir)'.
+ : Attempted to find it with pattern '"$(JAMFILE:J=" ")"'.
+ : Please consult the documentation at 'http://www.boost.org'. ;
+ }
+
+ return $(jamfile-to-load) ;
+}
+
+
+# Load a Jamfile at the given directory. Returns nothing. Will attempt to load
+# the file as indicated by the JAMFILE patterns. Effect of calling this rule
+# twice with the same 'dir' is undefined.
+#
+local rule load-jamfile (
+ dir # The directory of the project Jamfile.
+ : jamfile-module
+ )
+{
+ # See if the Jamfile is where it should be.
+ #
+ local jamfile-to-load = [ path.glob $(dir) : $(JAMROOT) ] ;
+ if ! $(jamfile-to-load)
+ {
+ jamfile-to-load = [ find-jamfile $(dir) ] ;
+ }
+
+ if $(jamfile-to-load[2])
+ {
+ errors.error "Multiple Jamfiles found at '$(dir)'"
+ : "Filenames are: " $(jamfile-to-load:D=) ;
+ }
+
+ # Now load the Jamfile in it's own context.
+ # The call to 'initialize' may load parent Jamfile, which might have
+ # 'use-project' statement that causes a second attempt to load the
+ # same project we're loading now. Checking inside .jamfile-modules
+ # prevents that second attempt from messing up.
+ if ! $(jamfile-module) in $(.jamfile-modules)
+ {
+ .jamfile-modules += $(jamfile-module) ;
+
+ # Initialize the Jamfile module before loading.
+ #
+ initialize $(jamfile-module) : [ path.parent $(jamfile-to-load) ]
+ : $(jamfile-to-load:BS) ;
+
+ local saved-project = $(.current-project) ;
+
+ mark-as-user $(jamfile-module) ;
+ modules.load $(jamfile-module) : [ path.native $(jamfile-to-load) ] : . ;
+ if [ MATCH ($(JAMROOT)) : $(jamfile-to-load:BS) ]
+ {
+ jamfile = [ find-jamfile $(dir) : no-errors ] ;
+ if $(jamfile)
+ {
+ load-aux $(jamfile-module) : [ path.native $(jamfile) ] ;
+ }
+ }
+
+ # Now do some checks.
+ if $(.current-project) != $(saved-project)
+ {
+ errors.error "The value of the .current-project variable has magically"
+ : "changed after loading a Jamfile. This means some of the targets"
+ : "might be defined in the wrong project."
+ : "after loading" $(jamfile-module)
+ : "expected value" $(saved-project)
+ : "actual value" $(.current-project) ;
+ }
+
+ if $(.global-build-dir)
+ {
+ local id = [ attribute $(jamfile-module) id ] ;
+ local project-root = [ attribute $(jamfile-module) project-root ] ;
+ local location = [ attribute $(jamfile-module) location ] ;
+
+ if $(location) && $(project-root) = $(dir)
+ {
+ # This is Jamroot.
+ if ! $(id)
+ {
+ ECHO "warning: the --build-dir option was specified" ;
+ ECHO "warning: but Jamroot at '$(dir)'" ;
+ ECHO "warning: specified no project id" ;
+ ECHO "warning: the --build-dir option will be ignored" ;
+ }
+ }
+ }
+ }
+}
+
+
+rule mark-as-user ( module-name )
+{
+ if USER_MODULE in [ RULENAMES ]
+ {
+ USER_MODULE $(module-name) ;
+ }
+}
+
+
+rule load-aux ( module-name : file )
+{
+ mark-as-user $(module-name) ;
+
+ module $(module-name)
+ {
+ include $(2) ;
+ local rules = [ RULENAMES $(1) ] ;
+ IMPORT $(1) : $(rules) : $(1) : $(1).$(rules) ;
+ }
+}
+
+
+.global-build-dir = [ MATCH --build-dir=(.*) : [ modules.peek : ARGV ] ] ;
+if $(.global-build-dir)
+{
+ # If the option is specified several times, take the last value.
+ .global-build-dir = [ path.make $(.global-build-dir[-1]) ] ;
+}
+
+
+# Initialize the module for a project.
+#
+rule initialize (
+ module-name # The name of the project module.
+ : location ? # The location (directory) of the project to initialize. If
+ # not specified, a standalone project will be initialized.
+ : basename ?
+ )
+{
+ if --debug-loading in [ modules.peek : ARGV ]
+ {
+ ECHO "Initializing project '$(module-name)'" ;
+ }
+
+ # TODO: need to consider if standalone projects can do anything but define
+ # prebuilt targets. If so, we need to give it a more sensible "location", so
+ # that source paths are correct.
+ location ?= "" ;
+ # Create the module for the Jamfile first.
+ module $(module-name)
+ {
+ }
+ $(module-name).attributes = [ new project-attributes $(location)
+ $(module-name) ] ;
+ local attributes = $($(module-name).attributes) ;
+
+ if $(location)
+ {
+ $(attributes).set source-location : [ path.make $(location) ] : exact ;
+ }
+ else if ! $(module-name) in test-config site-config user-config project-config
+ {
+ # This is a standalone project with known location. Set source location
+ # so that it can declare targets. This is intended so that you can put
+ # a .jam file in your sources and use it via 'using'. Standard modules
+ # (in 'tools' subdir) may not assume source dir is set.
+ local s = [ modules.binding $(module-name) ] ;
+ if ! $(s)
+ {
+ errors.error "Could not determine project location $(module-name)" ;
+ }
+ $(attributes).set source-location : $(s:D) : exact ;
+ }
+
+ $(attributes).set requirements : [ property-set.empty ] : exact ;
+ $(attributes).set usage-requirements : [ property-set.empty ] : exact ;
+
+ # Import rules common to all project modules from project-rules module,
+ # defined at the end of this file.
+ local rules = [ RULENAMES project-rules ] ;
+ IMPORT project-rules : $(rules) : $(module-name) : $(rules) ;
+
+ local jamroot ;
+
+ local parent-module ;
+ if $(module-name) = test-config
+ {
+ # No parent.
+ }
+ else if $(module-name) = site-config
+ {
+ parent-module = test-config ;
+ }
+ else if $(module-name) = user-config
+ {
+ parent-module = site-config ;
+ }
+ else if $(module-name) = project-config
+ {
+ parent-module = user-config ;
+ }
+ else
+ {
+ # We search for parent/project-root only if Jamfile was specified, i.e.
+ # if the project is not standalone.
+ if $(location) && ! [ MATCH ($(JAMROOT)) : $(basename) ]
+ {
+ parent-module = [ load-parent $(location) ] ;
+ }
+ else
+ {
+ # It's either jamroot or standalone project. If it's jamroot,
+ # inherit from user-config.
+ if $(location)
+ {
+ # If project-config module exist, inherit from it.
+ if $(project-config.attributes)
+ {
+ parent-module = project-config ;
+ }
+ else
+ {
+ parent-module = user-config ;
+ }
+ jamroot = true ;
+ }
+ }
+ }
+
+ if $(parent-module)
+ {
+ inherit-attributes $(module-name) : $(parent-module) ;
+ $(attributes).set parent-module : $(parent-module) : exact ;
+ }
+
+ if $(jamroot)
+ {
+ $(attributes).set project-root : $(location) : exact ;
+ }
+
+ local parent ;
+ if $(parent-module)
+ {
+ parent = [ target $(parent-module) ] ;
+ }
+
+ if ! $(.target.$(module-name))
+ {
+ .target.$(module-name) = [ new project-target $(module-name)
+ : $(module-name) $(parent)
+ : [ attribute $(module-name) requirements ] ] ;
+
+ if --debug-loading in [ modules.peek : ARGV ]
+ {
+ ECHO "Assigned project target" $(.target.$(module-name))
+ "to '$(module-name)'" ;
+ }
+ }
+
+ .current-project = [ target $(module-name) ] ;
+}
+
+
+# Make 'project-module' inherit attributes of project root and parent module.
+#
+rule inherit-attributes ( project-module : parent-module )
+{
+ local attributes = $($(project-module).attributes) ;
+ local pattributes = [ attributes $(parent-module) ] ;
+ # Parent module might be locationless configuration module.
+ if [ modules.binding $(parent-module) ]
+ {
+ $(attributes).set parent : [ path.parent
+ [ path.make [ modules.binding $(parent-module) ] ] ] ;
+ }
+ local v = [ $(pattributes).get project-root ] ;
+ $(attributes).set project-root : $(v) : exact ;
+ $(attributes).set default-build
+ : [ $(pattributes).get default-build ] ;
+ $(attributes).set requirements
+ : [ $(pattributes).get requirements ] : exact ;
+ $(attributes).set usage-requirements
+ : [ $(pattributes).get usage-requirements ] : exact ;
+
+ local parent-build-dir = [ $(pattributes).get build-dir ] ;
+ if $(parent-build-dir)
+ {
+ # Have to compute relative path from parent dir to our dir. Convert both
+ # paths to absolute, since we cannot find relative path from ".." to
+ # ".".
+
+ local location = [ attribute $(project-module) location ] ;
+ local parent-location = [ attribute $(parent-module) location ] ;
+
+ local pwd = [ path.pwd ] ;
+ local parent-dir = [ path.root $(parent-location) $(pwd) ] ;
+ local our-dir = [ path.root $(location) $(pwd) ] ;
+ $(attributes).set build-dir : [ path.join $(parent-build-dir)
+ [ path.relative $(our-dir) $(parent-dir) ] ] : exact ;
+ }
+}
+
+
+# Associate the given id with the given project module.
+#
+rule register-id ( id : module )
+{
+ $(id).jamfile-module = $(module) ;
+}
+
+
+# Class keeping all the attributes of a project.
+#
+# The standard attributes are "id", "location", "project-root", "parent"
+# "requirements", "default-build", "source-location" and "projects-to-build".
+#
+class project-attributes
+{
+ import property ;
+ import property-set ;
+ import errors ;
+ import path ;
+ import print ;
+ import sequence ;
+ import project ;
+
+ rule __init__ ( location project-module )
+ {
+ self.location = $(location) ;
+ self.project-module = $(project-module) ;
+ }
+
+ # Set the named attribute from the specification given by the user. The
+ # value actually set may be different.
+ #
+ rule set ( attribute : specification *
+ : exact ? # Sets value from 'specification' without any processing.
+ )
+ {
+ if $(exact)
+ {
+ self.$(attribute) = $(specification) ;
+ }
+ else if $(attribute) = "requirements"
+ {
+ local result = [ property-set.refine-from-user-input
+ $(self.requirements) : $(specification)
+ : $(self.project-module) : $(self.location) ] ;
+
+ if $(result[1]) = "@error"
+ {
+ errors.error Requirements for project at '$(self.location)'
+ conflict with parent's. : Explanation: $(result[2-]) ;
+ }
+ else
+ {
+ self.requirements = $(result) ;
+ }
+ }
+ else if $(attribute) = "usage-requirements"
+ {
+ local unconditional ;
+ for local p in $(specification)
+ {
+ local split = [ property.split-conditional $(p) ] ;
+ split ?= nothing $(p) ;
+ unconditional += $(split[2]) ;
+ }
+
+ local non-free = [ property.remove free : $(unconditional) ] ;
+ if $(non-free)
+ {
+ errors.error usage-requirements $(specification) have non-free
+ properties $(non-free) ;
+ }
+ local t = [ property.translate-paths $(specification)
+ : $(self.location) ] ;
+ if $(self.usage-requirements)
+ {
+ self.usage-requirements = [ property-set.create
+ [ $(self.usage-requirements).raw ] $(t) ] ;
+ }
+ else
+ {
+ self.usage-requirements = [ property-set.create $(t) ] ;
+ }
+ }
+ else if $(attribute) = "default-build"
+ {
+ self.default-build = [ property.make $(specification) ] ;
+ }
+ else if $(attribute) = "source-location"
+ {
+ self.source-location = ;
+ for local src-path in $(specification)
+ {
+ self.source-location += [ path.root [ path.make $(src-path) ]
+ $(self.location) ] ;
+ }
+ }
+ else if $(attribute) = "build-dir"
+ {
+ self.build-dir = [ path.root
+ [ path.make $(specification) ] $(self.location) ] ;
+ }
+ else if $(attribute) = "id"
+ {
+ id = [ path.root $(specification) / ] ;
+ project.register-id $(id) : $(self.project-module) ;
+ self.id = $(id) ;
+ }
+ else if ! $(attribute) in "default-build" "location" "parent"
+ "projects-to-build" "project-root" "source-location"
+ {
+ errors.error Invalid project attribute '$(attribute)' specified for
+ project at '$(self.location)' ;
+ }
+ else
+ {
+ self.$(attribute) = $(specification) ;
+ }
+ }
+
+ # Returns the value of the given attribute.
+ #
+ rule get ( attribute )
+ {
+ return $(self.$(attribute)) ;
+ }
+
+ # Prints the project attributes.
+ #
+ rule print ( )
+ {
+ local id = $(self.id) ; id ?= (none) ;
+ local parent = $(self.parent) ; parent ?= (none) ;
+ print.section "'"$(id)"'" ;
+ print.list-start ;
+ print.list-item "Parent project:" $(parent) ;
+ print.list-item "Requirements:" [ $(self.requirements).raw ] ;
+ print.list-item "Default build:" $(self.default-build) ;
+ print.list-item "Source location:" $(self.source-location) ;
+ print.list-item "Projects to build:"
+ [ sequence.insertion-sort $(self.projects-to-build) ] ;
+ print.list-end ;
+ }
+}
+
+
+# Returns the project which is currently being loaded.
+#
+rule current ( )
+{
+ return $(.current-project) ;
+}
+
+
+# Temporarily changes the current project to 'project'. Should be followed by
+# 'pop-current'.
+#
+rule push-current ( project )
+{
+ .saved-current-project += $(.current-project) ;
+ .current-project = $(project) ;
+}
+
+
+rule pop-current ( )
+{
+ .current-project = $(.saved-current-project[-1]) ;
+ .saved-current-project = $(.saved-current-project[1--2]) ;
+}
+
+
+# Returns the project-attribute instance for the specified Jamfile module.
+#
+rule attributes ( project )
+{
+ return $($(project).attributes) ;
+}
+
+
+# Returns the value of the specified attribute in the specified Jamfile module.
+#
+rule attribute ( project attribute )
+{
+ return [ $($(project).attributes).get $(attribute) ] ;
+}
+
+
+# Returns the project target corresponding to the 'project-module'.
+#
+rule target ( project-module )
+{
+ if ! $(.target.$(project-module))
+ {
+ .target.$(project-module) = [ new project-target $(project-module)
+ : $(project-module)
+ : [ attribute $(project-module) requirements ] ] ;
+ }
+ return $(.target.$(project-module)) ;
+}
+
+
+# Use/load a project.
+#
+rule use ( id : location )
+{
+ local saved-project = $(.current-project) ;
+ local project-module = [ project.load $(location) ] ;
+ local declared-id = [ project.attribute $(project-module) id ] ;
+
+ if ! $(declared-id) || $(declared-id) != $(id)
+ {
+ # The project at 'location' either has no id or that id is not equal to
+ # the 'id' parameter.
+ if $($(id).jamfile-module) && ( $($(id).jamfile-module) !=
+ $(project-module) )
+ {
+ errors.user-error Attempt to redeclare already existing project id
+ '$(id)'
+ location '$(location)' ;
+ }
+ $(id).jamfile-module = $(project-module) ;
+ }
+ .current-project = $(saved-project) ;
+}
+
+
+# Defines a Boost.Build extension project. Such extensions usually contain
+# library targets and features that can be used by many people. Even though
+# extensions are really projects, they can be initialized as a module would be
+# with the "using" (project.project-rules.using) mechanism.
+#
+rule extension ( id : options * : * )
+{
+ # The caller is a standalone module for the extension.
+ local mod = [ CALLER_MODULE ] ;
+
+ # We need to do the rest within the extension module.
+ module $(mod)
+ {
+ import path ;
+
+ # Find the root project.
+ local root-project = [ project.current ] ;
+ root-project = [ $(root-project).project-module ] ;
+ while
+ [ project.attribute $(root-project) parent-module ] &&
+ [ project.attribute $(root-project) parent-module ] != user-config
+ {
+ root-project = [ project.attribute $(root-project) parent-module ] ;
+ }
+
+ # Create the project data, and bring in the project rules into the
+ # module.
+ project.initialize $(__name__) : [ path.join [ project.attribute
+ $(root-project) location ] ext $(1:L) ] ;
+
+ # Create the project itself, i.e. the attributes. All extensions are
+ # created in the "/ext" project space.
+ project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) :
+ $(9) ;
+ local attributes = [ project.attributes $(__name__) ] ;
+
+ # Inherit from the root project of whomever is defining us.
+ project.inherit-attributes $(__name__) : $(root-project) ;
+ $(attributes).set parent-module : $(root-project) : exact ;
+ }
+}
+
+
+rule glob-internal ( project : wildcards + : excludes * : rule-name )
+{
+ local location = [ $(project).get source-location ] ;
+
+ local result ;
+ local paths = [ path.$(rule-name) $(location) :
+ [ sequence.transform path.make : $(wildcards) ] :
+ [ sequence.transform path.make : $(excludes) ] ] ;
+ if $(wildcards:D) || $(rule-name) != glob
+ {
+ # The paths we have found are relative to the current directory, but the
+ # names specified in the sources list are assumed to be relative to the
+ # source directory of the corresponding project. So, just make the names
+ # absolute.
+ for local p in $(paths)
+ {
+ # If the path is below source location, use relative path.
+ # Otherwise, use full path just to avoid any ambiguities.
+ local rel = [ path.relative $(p) $(location) : no-error ] ;
+ if $(rel) = not-a-child
+ {
+ result += [ path.root $(p) [ path.pwd ] ] ;
+ }
+ else
+ {
+ result += $(rel) ;
+ }
+ }
+ }
+ else
+ {
+ # There were no wildcards in the directory path, so the files are all in
+ # the source directory of the project. Just drop the directory, instead
+ # of making paths absolute.
+ result = $(paths:D="") ;
+ }
+
+ return $(result) ;
+}
+
+
+# This module defines rules common to all projects.
+#
+module project-rules
+{
+ rule using ( toolset-module : * )
+ {
+ import toolset ;
+ import modules ;
+ import project ;
+
+ # Temporarily change the search path so the module referred to by
+ # 'using' can be placed in the same directory as Jamfile. User will
+ # expect the module to be found even though the directory is not in
+ # BOOST_BUILD_PATH.
+ local x = [ modules.peek : BOOST_BUILD_PATH ] ;
+ local caller = [ CALLER_MODULE ] ;
+ local caller-location = [ modules.binding $(caller) ] ;
+ modules.poke : BOOST_BUILD_PATH : $(caller-location:D) $(x) ;
+ toolset.using $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ modules.poke : BOOST_BUILD_PATH : $(x) ;
+
+ # The above might have clobbered .current-project. Restore the correct
+ # value.
+ modules.poke project : .current-project
+ : [ project.target $(caller) ] ;
+ }
+
+ import modules ;
+
+ rule import ( * : * : * )
+ {
+ modules.import project ;
+
+ local caller = [ CALLER_MODULE ] ;
+ local saved = [ modules.peek project : .current-project ] ;
+ module $(caller)
+ {
+ modules.import $(1) : $(2) : $(3) ;
+ }
+ modules.poke project : .current-project : $(saved) ;
+ }
+
+ rule project ( id ? : options * : * )
+ {
+ import errors ;
+ import path ;
+ import project ;
+
+ local caller = [ CALLER_MODULE ] ;
+ local attributes = [ project.attributes $(caller) ] ;
+ if $(id)
+ {
+ $(attributes).set id : $(id) ;
+ }
+
+ local explicit-build-dir ;
+
+ for n in 2 3 4 5 6 7 8 9
+ {
+ local option = $($(n)) ;
+ if $(option)
+ {
+ $(attributes).set $(option[1]) : $(option[2-]) ;
+ }
+ if $(option[1]) = "build-dir"
+ {
+ explicit-build-dir = [ path.make $(option[2-]) ] ;
+ }
+ }
+
+ # If '--build-dir' is specified, change the build dir for the project.
+ local global-build-dir =
+ [ modules.peek project : .global-build-dir ] ;
+
+ if $(global-build-dir)
+ {
+ local location = [ $(attributes).get location ] ;
+ # Project with an empty location is a 'standalone' project such as
+ # user-config or qt. It has no build dir. If we try to set build dir
+ # for user-config, we shall then try to inherit it, with either
+ # weird or wrong consequences.
+ if $(location) && $(location) = [ $(attributes).get project-root ]
+ {
+ # Re-read the project id, since it might have been changed in
+ # the project's attributes.
+ id = [ $(attributes).get id ] ;
+ # This is Jamroot.
+ if $(id)
+ {
+ if $(explicit-build-dir) &&
+ [ path.is-rooted $(explicit-build-dir) ]
+ {
+ errors.user-error Absolute directory specified via
+ 'build-dir' project attribute : Do not know how to
+ combine that with the --build-dir option. ;
+ }
+ # Strip the leading slash from id.
+ local rid = [ MATCH /(.*) : $(id) ] ;
+ local p = [ path.join
+ $(global-build-dir) $(rid) $(explicit-build-dir) ] ;
+
+ $(attributes).set build-dir : $(p) : exact ;
+ }
+ }
+ else
+ {
+ # Not Jamroot.
+ if $(explicit-build-dir)
+ {
+ errors.user-error When --build-dir is specified, the
+ 'build-dir' project : attribute is allowed only for
+ top-level 'project' invocations ;
+ }
+ }
+ }
+ }
+
+ # Declare and set a project global constant. Project global constants are
+ # normal variables but should not be changed. They are applied to every
+ # child Jamfile.
+ #
+ rule constant (
+ name # Variable name of the constant.
+ : value + # Value of the constant.
+ )
+ {
+ import project ;
+ local caller = [ CALLER_MODULE ] ;
+ local p = [ project.target $(caller) ] ;
+ $(p).add-constant $(name) : $(value) ;
+ }
+
+ # Declare and set a project global constant, whose value is a path. The path
+ # is adjusted to be relative to the invocation directory. The given value
+ # path is taken to be either absolute, or relative to this project root.
+ #
+ rule path-constant (
+ name # Variable name of the constant.
+ : value + # Value of the constant.
+ )
+ {
+ import project ;
+ local caller = [ CALLER_MODULE ] ;
+ local p = [ project.target $(caller) ] ;
+ $(p).add-constant $(name) : $(value) : path ;
+ }
+
+ rule use-project ( id : where )
+ {
+ import modules ;
+ # See comment in 'load' for explanation.
+ local caller = [ CALLER_MODULE ] ;
+ modules.poke $(caller) : .used-projects :
+ [ modules.peek $(caller) : .used-projects ]
+ $(id) $(where) ;
+ }
+
+ rule build-project ( dir )
+ {
+ import project ;
+ local caller = [ CALLER_MODULE ] ;
+ local attributes = [ project.attributes $(caller) ] ;
+
+ local now = [ $(attributes).get projects-to-build ] ;
+ $(attributes).set projects-to-build : $(now) $(dir) ;
+ }
+
+ rule explicit ( target-names * )
+ {
+ import project ;
+ # If 'explicit' is used in a helper rule defined in Jamroot and
+ # inherited by children, then most of the time we want 'explicit' to
+ # operate on the Jamfile where the helper rule is invoked.
+ local t = [ project.current ] ;
+ for local n in $(target-names)
+ {
+ $(t).mark-target-as-explicit $(n) ;
+ }
+ }
+
+ rule always ( target-names * )
+ {
+ import project ;
+ local t = [ project.current ] ;
+ for local n in $(target-names)
+ {
+ $(t).mark-target-as-always $(n) ;
+ }
+ }
+
+ rule glob ( wildcards + : excludes * )
+ {
+ import project ;
+ return [ project.glob-internal [ project.current ] : $(wildcards) :
+ $(excludes) : glob ] ;
+ }
+
+ rule glob-tree ( wildcards + : excludes * )
+ {
+ import project ;
+
+ if $(wildcards:D) || $(excludes:D)
+ {
+ errors.user-error The patterns to 'glob-tree' may not include
+ directory ;
+ }
+ return [ project.glob-internal [ project.current ] : $(wildcards) :
+ $(excludes) : glob-tree ] ;
+ }
+
+ # Calculates conditional requirements for multiple requirements at once.
+ # This is a shorthand to reduce duplication and to keep an inline
+ # declarative syntax. For example:
+ #
+ # lib x : x.cpp : [ conditional <toolset>gcc <variant>debug :
+ # <define>DEBUG_EXCEPTION <define>DEBUG_TRACE ] ;
+ #
+ rule conditional ( condition + : requirements * )
+ {
+ local condition = $(condition:J=,) ;
+ if [ MATCH (:) : $(condition) ]
+ {
+ return $(condition)$(requirements) ;
+ }
+ else
+ {
+ return $(condition):$(requirements) ;
+ }
+ }
+
+ rule option ( name : value )
+ {
+ if $(__name__) != site-config && $(__name__) != user-config && $(__name__) != project-config
+ {
+ import errors ;
+ errors.error "The 'option' rule may be used only in site-config or user-config" ;
+ }
+ import option ;
+ option.set $(name) : $(value) ;
+ }
+}
diff --git a/tools/build/v2/build/project.py b/tools/build/v2/build/project.py
new file mode 100644
index 0000000000..1e1e16faed
--- /dev/null
+++ b/tools/build/v2/build/project.py
@@ -0,0 +1,1120 @@
+# Status: ported.
+# Base revision: 64488
+
+# Copyright 2002, 2003 Dave Abrahams
+# Copyright 2002, 2005, 2006 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Implements project representation and loading.
+# Each project is represented by
+# - a module where all the Jamfile content live.
+# - an instance of 'project-attributes' class.
+# (given module name, can be obtained by 'attributes' rule)
+# - an instance of 'project-target' class (from targets.jam)
+# (given a module name, can be obtained by 'target' rule)
+#
+# Typically, projects are created as result of loading Jamfile, which is
+# do by rules 'load' and 'initialize', below. First, module for Jamfile
+# is loaded and new project-attributes instance is created. Some rules
+# necessary for project are added to the module (see 'project-rules' module)
+# at the bottom of this file.
+# Default project attributes are set (inheriting attributes of parent project, if
+# it exists). After that, Jamfile is read. It can declare its own attributes,
+# via 'project' rule, which will be combined with already set attributes.
+#
+#
+# The 'project' rule can also declare project id, which will be associated with
+# the project module.
+#
+# There can also be 'standalone' projects. They are created by calling 'initialize'
+# on arbitrary module, and not specifying location. After the call, the module can
+# call 'project' rule, declare main target and behave as regular projects. However,
+# since it's not associated with any location, it's better declare only prebuilt
+# targets.
+#
+# The list of all loaded Jamfile is stored in variable .project-locations. It's possible
+# to obtain module name for a location using 'module-name' rule. The standalone projects
+# are not recorded, the only way to use them is by project id.
+
+import b2.util.path
+from b2.build import property_set, property
+from b2.build.errors import ExceptionWithUserContext
+import b2.build.targets
+
+import bjam
+
+import re
+import sys
+import os
+import string
+import imp
+import traceback
+import b2.util.option as option
+
+from b2.util import record_jam_to_value_mapping, qualify_jam_action
+
+class ProjectRegistry:
+
+ def __init__(self, manager, global_build_dir):
+ self.manager = manager
+ self.global_build_dir = global_build_dir
+ self.project_rules_ = ProjectRules(self)
+
+ # The target corresponding to the project being loaded now
+ self.current_project = None
+
+ # The set of names of loaded project modules
+ self.jamfile_modules = {}
+
+ # Mapping from location to module name
+ self.location2module = {}
+
+ # Mapping from project id to project module
+ self.id2module = {}
+
+ # Map from Jamfile directory to parent Jamfile/Jamroot
+ # location.
+ self.dir2parent_jamfile = {}
+
+ # Map from directory to the name of Jamfile in
+ # that directory (or None).
+ self.dir2jamfile = {}
+
+ # Map from project module to attributes object.
+ self.module2attributes = {}
+
+ # Map from project module to target for the project
+ self.module2target = {}
+
+ # Map from names to Python modules, for modules loaded
+ # via 'using' and 'import' rules in Jamfiles.
+ self.loaded_tool_modules_ = {}
+
+ self.loaded_tool_module_path_ = {}
+
+ # Map from project target to the list of
+ # (id,location) pairs corresponding to all 'use-project'
+ # invocations.
+ # TODO: should not have a global map, keep this
+ # in ProjectTarget.
+ self.used_projects = {}
+
+ self.saved_current_project = []
+
+ self.JAMROOT = self.manager.getenv("JAMROOT");
+
+ # Note the use of character groups, as opposed to listing
+ # 'Jamroot' and 'jamroot'. With the latter, we'd get duplicate
+ # matches on windows and would have to eliminate duplicates.
+ if not self.JAMROOT:
+ self.JAMROOT = ["project-root.jam", "[Jj]amroot", "[Jj]amroot.jam"]
+
+ # Default patterns to search for the Jamfiles to use for build
+ # declarations.
+ self.JAMFILE = self.manager.getenv("JAMFILE")
+
+ if not self.JAMFILE:
+ self.JAMFILE = ["[Bb]uild.jam", "[Jj]amfile.v2", "[Jj]amfile",
+ "[Jj]amfile.jam"]
+
+
+ def load (self, jamfile_location):
+ """Loads jamfile at the given location. After loading, project global
+ file and jamfile needed by the loaded one will be loaded recursively.
+ If the jamfile at that location is loaded already, does nothing.
+ Returns the project module for the Jamfile."""
+
+ absolute = os.path.join(os.getcwd(), jamfile_location)
+ absolute = os.path.normpath(absolute)
+ jamfile_location = b2.util.path.relpath(os.getcwd(), absolute)
+
+ if "--debug-loading" in self.manager.argv():
+ print "Loading Jamfile at '%s'" % jamfile_location
+
+
+ mname = self.module_name(jamfile_location)
+ # If Jamfile is already loaded, don't try again.
+ if not mname in self.jamfile_modules:
+
+ self.load_jamfile(jamfile_location, mname)
+
+ # We want to make sure that child project are loaded only
+ # after parent projects. In particular, because parent projects
+ # define attributes whch are inherited by children, and we don't
+ # want children to be loaded before parents has defined everything.
+ #
+ # While "build-project" and "use-project" can potentially refer
+ # to child projects from parent projects, we don't immediately
+ # load child projects when seing those attributes. Instead,
+ # we record the minimal information that will be used only later.
+
+ self.load_used_projects(mname)
+
+ return mname
+
+ def load_used_projects(self, module_name):
+ # local used = [ modules.peek $(module-name) : .used-projects ] ;
+ used = self.used_projects[module_name]
+
+ location = self.attribute(module_name, "location")
+ for u in used:
+ id = u[0]
+ where = u[1]
+
+ self.use(id, os.path.join(location, where))
+
+ def load_parent(self, location):
+ """Loads parent of Jamfile at 'location'.
+ Issues an error if nothing is found."""
+
+ found = b2.util.path.glob_in_parents(
+ location, self.JAMROOT + self.JAMFILE)
+
+ if not found:
+ print "error: Could not find parent for project at '%s'" % location
+ print "error: Did not find Jamfile or project-root.jam in any parent directory."
+ sys.exit(1)
+
+ return self.load(os.path.dirname(found[0]))
+
+ def act_as_jamfile(self, module, location):
+ """Makes the specified 'module' act as if it were a regularly loaded Jamfile
+ at 'location'. If Jamfile is already located for that location, it's an
+ error."""
+
+ if self.module_name(location) in self.jamfile_modules:
+ self.manager.errors()(
+ "Jamfile was already loaded for '%s'" % location)
+
+ # Set up non-default mapping from location to module.
+ self.location2module[location] = module
+
+ # Add the location to the list of project locations
+ # so that we don't try to load Jamfile in future
+ self.jamfile_modules.append(location)
+
+ self.initialize(module, location)
+
+ def find(self, name, current_location):
+ """Given 'name' which can be project-id or plain directory name,
+ return project module corresponding to that id or directory.
+ Returns nothing of project is not found."""
+
+ project_module = None
+
+ # Try interpreting name as project id.
+ if name[0] == '/':
+ project_module = self.id2module.get(name)
+
+ if not project_module:
+ location = os.path.join(current_location, name)
+ # If no project is registered for the given location, try to
+ # load it. First see if we have Jamfile. If not we might have project
+ # root, willing to act as Jamfile. In that case, project-root
+ # must be placed in the directory referred by id.
+
+ project_module = self.module_name(location)
+ if not project_module in self.jamfile_modules:
+ if b2.util.path.glob([location], self.JAMROOT + self.JAMFILE):
+ project_module = self.load(location)
+ else:
+ project_module = None
+
+ return project_module
+
+ def module_name(self, jamfile_location):
+ """Returns the name of module corresponding to 'jamfile-location'.
+ If no module corresponds to location yet, associates default
+ module name with that location."""
+ module = self.location2module.get(jamfile_location)
+ if not module:
+ # Root the path, so that locations are always umbiguious.
+ # Without this, we can't decide if '../../exe/program1' and '.'
+ # are the same paths, or not.
+ jamfile_location = os.path.realpath(
+ os.path.join(os.getcwd(), jamfile_location))
+ module = "Jamfile<%s>" % jamfile_location
+ self.location2module[jamfile_location] = module
+ return module
+
+ def find_jamfile (self, dir, parent_root=0, no_errors=0):
+ """Find the Jamfile at the given location. This returns the
+ exact names of all the Jamfiles in the given directory. The optional
+ parent-root argument causes this to search not the given directory
+ but the ones above it up to the directory given in it."""
+
+ # Glob for all the possible Jamfiles according to the match pattern.
+ #
+ jamfile_glob = None
+ if parent_root:
+ parent = self.dir2parent_jamfile.get(dir)
+ if not parent:
+ parent = b2.util.path.glob_in_parents(dir,
+ self.JAMFILE)
+ self.dir2parent_jamfile[dir] = parent
+ jamfile_glob = parent
+ else:
+ jamfile = self.dir2jamfile.get(dir)
+ if not jamfile:
+ jamfile = b2.util.path.glob([dir], self.JAMFILE)
+ self.dir2jamfile[dir] = jamfile
+ jamfile_glob = jamfile
+
+ if len(jamfile_glob) > 1:
+ # Multiple Jamfiles found in the same place. Warn about this.
+ # And ensure we use only one of them.
+ # As a temporary convenience measure, if there's Jamfile.v2 amount
+ # found files, suppress the warning and use it.
+ #
+ pattern = "(.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam)"
+ v2_jamfiles = [x for x in jamfile_glob if re.match(pattern, x)]
+ if len(v2_jamfiles) == 1:
+ jamfile_glob = v2_jamfiles
+ else:
+ print """warning: Found multiple Jamfiles at '%s'!""" % (dir)
+ for j in jamfile_glob:
+ print " -", j
+ print "Loading the first one"
+
+ # Could not find it, error.
+ if not no_errors and not jamfile_glob:
+ self.manager.errors()(
+ """Unable to load Jamfile.
+Could not find a Jamfile in directory '%s'
+Attempted to find it with pattern '%s'.
+Please consult the documentation at 'http://boost.org/boost-build2'."""
+ % (dir, string.join(self.JAMFILE)))
+
+ if jamfile_glob:
+ return jamfile_glob[0]
+
+ def load_jamfile(self, dir, jamfile_module):
+ """Load a Jamfile at the given directory. Returns nothing.
+ Will attempt to load the file as indicated by the JAMFILE patterns.
+ Effect of calling this rule twice with the same 'dir' is underfined."""
+
+ # See if the Jamfile is where it should be.
+ is_jamroot = False
+ jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT)
+ if not jamfile_to_load:
+ jamfile_to_load = self.find_jamfile(dir)
+ else:
+ if len(jamfile_to_load) > 1:
+ get_manager().errors()("Multiple Jamfiles found at '%s'\n" +\
+ "Filenames are: %s"
+ % (dir, [os.path.basename(j) for j in jamfile_to_load]))
+
+ is_jamroot = True
+ jamfile_to_load = jamfile_to_load[0]
+
+ dir = os.path.dirname(jamfile_to_load)
+ if not dir:
+ dir = "."
+
+ self.used_projects[jamfile_module] = []
+
+ # Now load the Jamfile in it's own context.
+ # The call to 'initialize' may load parent Jamfile, which might have
+ # 'use-project' statement that causes a second attempt to load the
+ # same project we're loading now. Checking inside .jamfile-modules
+ # prevents that second attempt from messing up.
+ if not jamfile_module in self.jamfile_modules:
+ self.jamfile_modules[jamfile_module] = True
+
+ # Initialize the jamfile module before loading.
+ #
+ self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load))
+
+ saved_project = self.current_project
+
+ bjam.call("load", jamfile_module, jamfile_to_load)
+ basename = os.path.basename(jamfile_to_load)
+
+ if is_jamroot:
+ jamfile = self.find_jamfile(dir, no_errors=True)
+ if jamfile:
+ bjam.call("load", jamfile_module, jamfile)
+
+ # Now do some checks
+ if self.current_project != saved_project:
+ self.manager.errors()(
+"""The value of the .current-project variable
+has magically changed after loading a Jamfile.
+This means some of the targets might be defined a the wrong project.
+after loading %s
+expected value %s
+actual value %s""" % (jamfile_module, saved_project, self.current_project))
+
+ if self.global_build_dir:
+ id = self.attributeDefault(jamfile_module, "id", None)
+ project_root = self.attribute(jamfile_module, "project-root")
+ location = self.attribute(jamfile_module, "location")
+
+ if location and project_root == dir:
+ # This is Jamroot
+ if not id:
+ # FIXME: go via errors module, so that contexts are
+ # shown?
+ print "warning: the --build-dir option was specified"
+ print "warning: but Jamroot at '%s'" % dir
+ print "warning: specified no project id"
+ print "warning: the --build-dir option will be ignored"
+
+
+ def load_standalone(self, jamfile_module, file):
+ """Loads 'file' as standalone project that has no location
+ associated with it. This is mostly useful for user-config.jam,
+ which should be able to define targets, but although it has
+ some location in filesystem, we don't want any build to
+ happen in user's HOME, for example.
+
+ The caller is required to never call this method twice on
+ the same file.
+ """
+
+ self.used_projects[jamfile_module] = []
+ bjam.call("load", jamfile_module, file)
+ self.load_used_projects(jamfile_module)
+
+ def is_jamroot(self, basename):
+ match = [ pat for pat in self.JAMROOT if re.match(pat, basename)]
+ if match:
+ return 1
+ else:
+ return 0
+
+ def initialize(self, module_name, location=None, basename=None):
+ """Initialize the module for a project.
+
+ module-name is the name of the project module.
+ location is the location (directory) of the project to initialize.
+ If not specified, stanalone project will be initialized
+ """
+
+ if "--debug-loading" in self.manager.argv():
+ print "Initializing project '%s'" % module_name
+
+ # TODO: need to consider if standalone projects can do anything but defining
+ # prebuilt targets. If so, we need to give more sensible "location", so that
+ # source paths are correct.
+ if not location:
+ location = ""
+
+ attributes = ProjectAttributes(self.manager, location, module_name)
+ self.module2attributes[module_name] = attributes
+
+ python_standalone = False
+ if location:
+ attributes.set("source-location", [location], exact=1)
+ elif not module_name in ["test-config", "site-config", "user-config", "project-config"]:
+ # This is a standalone project with known location. Set source location
+ # so that it can declare targets. This is intended so that you can put
+ # a .jam file in your sources and use it via 'using'. Standard modules
+ # (in 'tools' subdir) may not assume source dir is set.
+ module = sys.modules[module_name]
+ attributes.set("source-location", self.loaded_tool_module_path_[module_name], exact=1)
+ python_standalone = True
+
+ attributes.set("requirements", property_set.empty(), exact=True)
+ attributes.set("usage-requirements", property_set.empty(), exact=True)
+ attributes.set("default-build", property_set.empty(), exact=True)
+ attributes.set("projects-to-build", [], exact=True)
+ attributes.set("project-root", None, exact=True)
+ attributes.set("build-dir", None, exact=True)
+
+ self.project_rules_.init_project(module_name, python_standalone)
+
+ jamroot = False
+
+ parent_module = None;
+ if module_name == "test-config":
+ # No parent
+ pass
+ elif module_name == "site-config":
+ parent_module = "test-config"
+ elif module_name == "user-config":
+ parent_module = "site-config"
+ elif module_name == "project-config":
+ parent_module = "user-config"
+ elif location and not self.is_jamroot(basename):
+ # We search for parent/project-root only if jamfile was specified
+ # --- i.e
+ # if the project is not standalone.
+ parent_module = self.load_parent(location)
+ else:
+ # It's either jamroot, or standalone project.
+ # If it's jamroot, inherit from user-config.
+ if location:
+ # If project-config module exist, inherit from it.
+ if self.module2attributes.has_key("project-config"):
+ parent_module = "project-config"
+ else:
+ parent_module = "user-config" ;
+
+ jamroot = True ;
+
+ if parent_module:
+ self.inherit_attributes(module_name, parent_module)
+ attributes.set("parent-module", parent_module, exact=1)
+
+ if jamroot:
+ attributes.set("project-root", location, exact=1)
+
+ parent = None
+ if parent_module:
+ parent = self.target(parent_module)
+
+ if not self.module2target.has_key(module_name):
+ target = b2.build.targets.ProjectTarget(self.manager,
+ module_name, module_name, parent,
+ self.attribute(module_name,"requirements"),
+ # FIXME: why we need to pass this? It's not
+ # passed in jam code.
+ self.attribute(module_name, "default-build"))
+ self.module2target[module_name] = target
+
+ self.current_project = self.target(module_name)
+
+ def inherit_attributes(self, project_module, parent_module):
+ """Make 'project-module' inherit attributes of project
+ root and parent module."""
+
+ attributes = self.module2attributes[project_module]
+ pattributes = self.module2attributes[parent_module]
+
+ # Parent module might be locationless user-config.
+ # FIXME:
+ #if [ modules.binding $(parent-module) ]
+ #{
+ # $(attributes).set parent : [ path.parent
+ # [ path.make [ modules.binding $(parent-module) ] ] ] ;
+ # }
+
+ attributes.set("project-root", pattributes.get("project-root"), exact=True)
+ attributes.set("default-build", pattributes.get("default-build"), exact=True)
+ attributes.set("requirements", pattributes.get("requirements"), exact=True)
+ attributes.set("usage-requirements",
+ pattributes.get("usage-requirements"), exact=1)
+
+ parent_build_dir = pattributes.get("build-dir")
+
+ if parent_build_dir:
+ # Have to compute relative path from parent dir to our dir
+ # Convert both paths to absolute, since we cannot
+ # find relative path from ".." to "."
+
+ location = attributes.get("location")
+ parent_location = pattributes.get("location")
+
+ our_dir = os.path.join(os.getcwd(), location)
+ parent_dir = os.path.join(os.getcwd(), parent_location)
+
+ build_dir = os.path.join(parent_build_dir,
+ os.path.relpath(our_dir, parent_dir))
+ attributes.set("build-dir", build_dir, exact=True)
+
+ def register_id(self, id, module):
+ """Associate the given id with the given project module."""
+ self.id2module[id] = module
+
+ def current(self):
+ """Returns the project which is currently being loaded."""
+ return self.current_project
+
+ def set_current(self, c):
+ self.current_project = c
+
+ def push_current(self, project):
+ """Temporary changes the current project to 'project'. Should
+ be followed by 'pop-current'."""
+ self.saved_current_project.append(self.current_project)
+ self.current_project = project
+
+ def pop_current(self):
+ self.current_project = self.saved_current_project[-1]
+ del self.saved_current_project[-1]
+
+ def attributes(self, project):
+ """Returns the project-attribute instance for the
+ specified jamfile module."""
+ return self.module2attributes[project]
+
+ def attribute(self, project, attribute):
+ """Returns the value of the specified attribute in the
+ specified jamfile module."""
+ return self.module2attributes[project].get(attribute)
+ try:
+ return self.module2attributes[project].get(attribute)
+ except:
+ raise BaseException("No attribute '%s' for project" % (attribute, project))
+
+ def attributeDefault(self, project, attribute, default):
+ """Returns the value of the specified attribute in the
+ specified jamfile module."""
+ return self.module2attributes[project].getDefault(attribute, default)
+
+ def target(self, project_module):
+ """Returns the project target corresponding to the 'project-module'."""
+ if not self.module2target.has_key(project_module):
+ self.module2target[project_module] = \
+ b2.build.targets.ProjectTarget(project_module, project_module,
+ self.attribute(project_module, "requirements"))
+
+ return self.module2target[project_module]
+
+ def use(self, id, location):
+ # Use/load a project.
+ saved_project = self.current_project
+ project_module = self.load(location)
+ declared_id = self.attributeDefault(project_module, "id", "")
+
+ if not declared_id or declared_id != id:
+ # The project at 'location' either have no id or
+ # that id is not equal to the 'id' parameter.
+ if self.id2module.has_key(id) and self.id2module[id] != project_module:
+ self.manager.errors()(
+"""Attempt to redeclare already existing project id '%s' at location '%s'""" % (id, location))
+ self.id2module[id] = project_module
+
+ self.current_module = saved_project
+
+ def add_rule(self, name, callable):
+ """Makes rule 'name' available to all subsequently loaded Jamfiles.
+
+ Calling that rule wil relay to 'callable'."""
+ self.project_rules_.add_rule(name, callable)
+
+ def project_rules(self):
+ return self.project_rules_
+
+ def glob_internal(self, project, wildcards, excludes, rule_name):
+ location = project.get("source-location")[0]
+
+ result = []
+ callable = b2.util.path.__dict__[rule_name]
+
+ paths = callable([location], wildcards, excludes)
+ has_dir = 0
+ for w in wildcards:
+ if os.path.dirname(w):
+ has_dir = 1
+ break
+
+ if has_dir or rule_name != "glob":
+ result = []
+ # The paths we've found are relative to current directory,
+ # but the names specified in sources list are assumed to
+ # be relative to source directory of the corresponding
+ # prject. Either translate them or make absolute.
+
+ for p in paths:
+ rel = os.path.relpath(p, location)
+ # If the path is below source location, use relative path.
+ if not ".." in rel:
+ result.append(rel)
+ else:
+ # Otherwise, use full path just to avoid any ambiguities.
+ result.append(os.path.abspath(p))
+
+ else:
+ # There were not directory in wildcard, so the files are all
+ # in the source directory of the project. Just drop the
+ # directory, instead of making paths absolute.
+ result = [os.path.basename(p) for p in paths]
+
+ return result
+
+ def load_module(self, name, extra_path=None):
+ """Load a Python module that should be useable from Jamfiles.
+
+ There are generally two types of modules Jamfiles might want to
+ use:
+ - Core Boost.Build. Those are imported using plain names, e.g.
+ 'toolset', so this function checks if we have module named
+ b2.package.module already.
+ - Python modules in the same directory as Jamfile. We don't
+ want to even temporary add Jamfile's directory to sys.path,
+ since then we might get naming conflicts between standard
+ Python modules and those.
+ """
+
+ # See if we loaded module of this name already
+ existing = self.loaded_tool_modules_.get(name)
+ if existing:
+ return existing
+
+ # See if we have a module b2.whatever.<name>, where <name>
+ # is what is passed to this function
+ modules = sys.modules
+ for class_name in modules:
+ parts = class_name.split('.')
+ if name is class_name or parts[0] == "b2" \
+ and parts[-1] == name.replace("-", "_"):
+ module = modules[class_name]
+ self.loaded_tool_modules_[name] = module
+ return module
+
+ # Lookup a module in BOOST_BUILD_PATH
+ path = extra_path
+ if not path:
+ path = []
+ path.extend(self.manager.boost_build_path())
+ location = None
+ for p in path:
+ l = os.path.join(p, name + ".py")
+ if os.path.exists(l):
+ location = l
+ break
+
+ if not location:
+ self.manager.errors()("Cannot find module '%s'" % name)
+
+ mname = name + "__for_jamfile"
+ file = open(location)
+ try:
+ # TODO: this means we'll never make use of .pyc module,
+ # which might be a problem, or not.
+ self.loaded_tool_module_path_[mname] = location
+ module = imp.load_module(mname, file, os.path.basename(location),
+ (".py", "r", imp.PY_SOURCE))
+ self.loaded_tool_modules_[name] = module
+ return module
+ finally:
+ file.close()
+
+
+
+# FIXME:
+# Defines a Boost.Build extension project. Such extensions usually
+# contain library targets and features that can be used by many people.
+# Even though extensions are really projects, they can be initialize as
+# a module would be with the "using" (project.project-rules.using)
+# mechanism.
+#rule extension ( id : options * : * )
+#{
+# # The caller is a standalone module for the extension.
+# local mod = [ CALLER_MODULE ] ;
+#
+# # We need to do the rest within the extension module.
+# module $(mod)
+# {
+# import path ;
+#
+# # Find the root project.
+# local root-project = [ project.current ] ;
+# root-project = [ $(root-project).project-module ] ;
+# while
+# [ project.attribute $(root-project) parent-module ] &&
+# [ project.attribute $(root-project) parent-module ] != user-config
+# {
+# root-project = [ project.attribute $(root-project) parent-module ] ;
+# }
+#
+# # Create the project data, and bring in the project rules
+# # into the module.
+# project.initialize $(__name__) :
+# [ path.join [ project.attribute $(root-project) location ] ext $(1:L) ] ;
+#
+# # Create the project itself, i.e. the attributes.
+# # All extensions are created in the "/ext" project space.
+# project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+# local attributes = [ project.attributes $(__name__) ] ;
+#
+# # Inherit from the root project of whomever is defining us.
+# project.inherit-attributes $(__name__) : $(root-project) ;
+# $(attributes).set parent-module : $(root-project) : exact ;
+# }
+#}
+
+
+class ProjectAttributes:
+ """Class keeping all the attributes of a project.
+
+ The standard attributes are 'id', "location", "project-root", "parent"
+ "requirements", "default-build", "source-location" and "projects-to-build".
+ """
+
+ def __init__(self, manager, location, project_module):
+ self.manager = manager
+ self.location = location
+ self.project_module = project_module
+ self.attributes = {}
+ self.usage_requirements = None
+
+ def set(self, attribute, specification, exact=False):
+ """Set the named attribute from the specification given by the user.
+ The value actually set may be different."""
+
+ if exact:
+ self.__dict__[attribute] = specification
+
+ elif attribute == "requirements":
+ self.requirements = property_set.refine_from_user_input(
+ self.requirements, specification,
+ self.project_module, self.location)
+
+ elif attribute == "usage-requirements":
+ unconditional = []
+ for p in specification:
+ split = property.split_conditional(p)
+ if split:
+ unconditional.append(split[1])
+ else:
+ unconditional.append(p)
+
+ non_free = property.remove("free", unconditional)
+ if non_free:
+ get_manager().errors()("usage-requirements %s have non-free properties %s" \
+ % (specification, non_free))
+
+ t = property.translate_paths(
+ property.create_from_strings(specification, allow_condition=True),
+ self.location)
+
+ existing = self.__dict__.get("usage-requirements")
+ if existing:
+ new = property_set.create(existing.all() + t)
+ else:
+ new = property_set.create(t)
+ self.__dict__["usage-requirements"] = new
+
+
+ elif attribute == "default-build":
+ self.__dict__["default-build"] = property_set.create(specification)
+
+ elif attribute == "source-location":
+ source_location = []
+ for path in specification:
+ source_location.append(os.path.join(self.location, path))
+ self.__dict__["source-location"] = source_location
+
+ elif attribute == "build-dir":
+ self.__dict__["build-dir"] = os.path.join(self.location, specification[0])
+
+ elif attribute == "id":
+ id = specification[0]
+ if id[0] != '/':
+ id = "/" + id
+ self.manager.projects().register_id(id, self.project_module)
+ self.__dict__["id"] = id
+
+ elif not attribute in ["default-build", "location",
+ "source-location", "parent",
+ "projects-to-build", "project-root"]:
+ self.manager.errors()(
+"""Invalid project attribute '%s' specified
+for project at '%s'""" % (attribute, self.location))
+ else:
+ self.__dict__[attribute] = specification
+
+ def get(self, attribute):
+ return self.__dict__[attribute]
+
+ def getDefault(self, attribute, default):
+ return self.__dict__.get(attribute, default)
+
+ def dump(self):
+ """Prints the project attributes."""
+ id = self.get("id")
+ if not id:
+ id = "(none)"
+ else:
+ id = id[0]
+
+ parent = self.get("parent")
+ if not parent:
+ parent = "(none)"
+ else:
+ parent = parent[0]
+
+ print "'%s'" % id
+ print "Parent project:%s", parent
+ print "Requirements:%s", self.get("requirements")
+ print "Default build:%s", string.join(self.get("debuild-build"))
+ print "Source location:%s", string.join(self.get("source-location"))
+ print "Projects to build:%s", string.join(self.get("projects-to-build").sort());
+
+class ProjectRules:
+ """Class keeping all rules that are made available to Jamfile."""
+
+ def __init__(self, registry):
+ self.registry = registry
+ self.manager_ = registry.manager
+ self.rules = {}
+ self.local_names = [x for x in self.__class__.__dict__
+ if x not in ["__init__", "init_project", "add_rule",
+ "error_reporting_wrapper", "add_rule_for_type", "reverse"]]
+ self.all_names_ = [x for x in self.local_names]
+
+ def _import_rule(self, bjam_module, name, callable):
+ if hasattr(callable, "bjam_signature"):
+ bjam.import_rule(bjam_module, name, self.make_wrapper(callable), callable.bjam_signature)
+ else:
+ bjam.import_rule(bjam_module, name, self.make_wrapper(callable))
+
+
+ def add_rule_for_type(self, type):
+ rule_name = type.lower().replace("_", "-")
+
+ def xpto (name, sources = [], requirements = [], default_build = [], usage_requirements = []):
+ return self.manager_.targets().create_typed_target(
+ type, self.registry.current(), name[0], sources,
+ requirements, default_build, usage_requirements)
+
+ self.add_rule(rule_name, xpto)
+
+ def add_rule(self, name, callable):
+ self.rules[name] = callable
+ self.all_names_.append(name)
+
+ # Add new rule at global bjam scope. This might not be ideal,
+ # added because if a jamroot does 'import foo' where foo calls
+ # add_rule, we need to import new rule to jamroot scope, and
+ # I'm lazy to do this now.
+ self._import_rule("", name, callable)
+
+ def all_names(self):
+ return self.all_names_
+
+ def call_and_report_errors(self, callable, *args, **kw):
+ result = None
+ try:
+ self.manager_.errors().push_jamfile_context()
+ result = callable(*args, **kw)
+ except ExceptionWithUserContext, e:
+ e.report()
+ except Exception, e:
+ try:
+ self.manager_.errors().handle_stray_exception (e)
+ except ExceptionWithUserContext, e:
+ e.report()
+ finally:
+ self.manager_.errors().pop_jamfile_context()
+
+ return result
+
+ def make_wrapper(self, callable):
+ """Given a free-standing function 'callable', return a new
+ callable that will call 'callable' and report all exceptins,
+ using 'call_and_report_errors'."""
+ def wrapper(*args, **kw):
+ return self.call_and_report_errors(callable, *args, **kw)
+ return wrapper
+
+ def init_project(self, project_module, python_standalone=False):
+
+ if python_standalone:
+ m = sys.modules[project_module]
+
+ for n in self.local_names:
+ if n != "import_":
+ setattr(m, n, getattr(self, n))
+
+ for n in self.rules:
+ setattr(m, n, self.rules[n])
+
+ return
+
+ for n in self.local_names:
+ # Using 'getattr' here gives us a bound method,
+ # while using self.__dict__[r] would give unbound one.
+ v = getattr(self, n)
+ if callable(v):
+ if n == "import_":
+ n = "import"
+ else:
+ n = string.replace(n, "_", "-")
+
+ self._import_rule(project_module, n, v)
+
+ for n in self.rules:
+ self._import_rule(project_module, n, self.rules[n])
+
+ def project(self, *args):
+
+ jamfile_module = self.registry.current().project_module()
+ attributes = self.registry.attributes(jamfile_module)
+
+ id = None
+ if args and args[0]:
+ id = args[0][0]
+ args = args[1:]
+
+ if id:
+ attributes.set('id', [id])
+
+ explicit_build_dir = None
+ for a in args:
+ if a:
+ attributes.set(a[0], a[1:], exact=0)
+ if a[0] == "build-dir":
+ explicit_build_dir = a[1]
+
+ # If '--build-dir' is specified, change the build dir for the project.
+ if self.registry.global_build_dir:
+
+ location = attributes.get("location")
+ # Project with empty location is 'standalone' project, like
+ # user-config, or qt. It has no build dir.
+ # If we try to set build dir for user-config, we'll then
+ # try to inherit it, with either weird, or wrong consequences.
+ if location and location == attributes.get("project-root"):
+ # Re-read the project id, since it might have been changed in
+ # the project's attributes.
+ id = attributes.get('id')
+
+ # This is Jamroot.
+ if id:
+ if explicit_build_dir and os.path.isabs(explicit_build_dir):
+ self.registry.manager.errors()(
+"""Absolute directory specified via 'build-dir' project attribute
+Don't know how to combine that with the --build-dir option.""")
+
+ rid = id
+ if rid[0] == '/':
+ rid = rid[1:]
+
+ p = os.path.join(self.registry.global_build_dir, rid)
+ if explicit_build_dir:
+ p = os.path.join(p, explicit_build_dir)
+ attributes.set("build-dir", p, exact=1)
+ elif explicit_build_dir:
+ self.registry.manager.errors()(
+"""When --build-dir is specified, the 'build-dir'
+attribute is allowed only for top-level 'project' invocations""")
+
+ def constant(self, name, value):
+ """Declare and set a project global constant.
+ Project global constants are normal variables but should
+ not be changed. They are applied to every child Jamfile."""
+ m = "Jamfile</home/ghost/Work/Boost/boost-svn/tools/build/v2_python/python/tests/bjam/make>"
+ self.registry.current().add_constant(name[0], value)
+
+ def path_constant(self, name, value):
+ """Declare and set a project global constant, whose value is a path. The
+ path is adjusted to be relative to the invocation directory. The given
+ value path is taken to be either absolute, or relative to this project
+ root."""
+ if len(value) > 1:
+ self.registry.manager.error()("path constant should have one element")
+ self.registry.current().add_constant(name[0], value[0], path=1)
+
+ def use_project(self, id, where):
+ # See comment in 'load' for explanation why we record the
+ # parameters as opposed to loading the project now.
+ m = self.registry.current().project_module();
+ self.registry.used_projects[m].append((id[0], where[0]))
+
+ def build_project(self, dir):
+ assert(isinstance(dir, list))
+ jamfile_module = self.registry.current().project_module()
+ attributes = self.registry.attributes(jamfile_module)
+ now = attributes.get("projects-to-build")
+ attributes.set("projects-to-build", now + dir, exact=True)
+
+ def explicit(self, target_names):
+ self.registry.current().mark_targets_as_explicit(target_names)
+
+ def always(self, target_names):
+ self.registry.current().mark_targets_as_alays(target_names)
+
+ def glob(self, wildcards, excludes=None):
+ return self.registry.glob_internal(self.registry.current(),
+ wildcards, excludes, "glob")
+
+ def glob_tree(self, wildcards, excludes=None):
+ bad = 0
+ for p in wildcards:
+ if os.path.dirname(p):
+ bad = 1
+
+ if excludes:
+ for p in excludes:
+ if os.path.dirname(p):
+ bad = 1
+
+ if bad:
+ self.registry.manager.errors()(
+"The patterns to 'glob-tree' may not include directory")
+ return self.registry.glob_internal(self.registry.current(),
+ wildcards, excludes, "glob_tree")
+
+
+ def using(self, toolset, *args):
+ # The module referred by 'using' can be placed in
+ # the same directory as Jamfile, and the user
+ # will expect the module to be found even though
+ # the directory is not in BOOST_BUILD_PATH.
+ # So temporary change the search path.
+ current = self.registry.current()
+ location = current.get('location')
+
+ m = self.registry.load_module(toolset[0], [location])
+ if not m.__dict__.has_key("init"):
+ self.registry.manager.errors()(
+ "Tool module '%s' does not define the 'init' method" % toolset[0])
+ m.init(*args)
+
+ # The above might have clobbered .current-project. Restore the correct
+ # value.
+ self.registry.set_current(current)
+
+ def import_(self, name, names_to_import=None, local_names=None):
+
+ name = name[0]
+ py_name = name
+ if py_name == "os":
+ py_name = "os_j"
+ jamfile_module = self.registry.current().project_module()
+ attributes = self.registry.attributes(jamfile_module)
+ location = attributes.get("location")
+
+ saved = self.registry.current()
+
+ m = self.registry.load_module(py_name, [location])
+
+ for f in m.__dict__:
+ v = m.__dict__[f]
+ f = f.replace("_", "-")
+ if callable(v):
+ qn = name + "." + f
+ self._import_rule(jamfile_module, qn, v)
+ record_jam_to_value_mapping(qualify_jam_action(qn, jamfile_module), v)
+
+
+ if names_to_import:
+ if not local_names:
+ local_names = names_to_import
+
+ if len(names_to_import) != len(local_names):
+ self.registry.manager.errors()(
+"""The number of names to import and local names do not match.""")
+
+ for n, l in zip(names_to_import, local_names):
+ self._import_rule(jamfile_module, l, m.__dict__[n])
+
+ self.registry.set_current(saved)
+
+ def conditional(self, condition, requirements):
+ """Calculates conditional requirements for multiple requirements
+ at once. This is a shorthand to be reduce duplication and to
+ keep an inline declarative syntax. For example:
+
+ lib x : x.cpp : [ conditional <toolset>gcc <variant>debug :
+ <define>DEBUG_EXCEPTION <define>DEBUG_TRACE ] ;
+ """
+
+ c = string.join(condition, ",")
+ if c.find(":") != -1:
+ return [c + r for r in requirements]
+ else:
+ return [c + ":" + r for r in requirements]
+
+ def option(self, name, value):
+ name = name[0]
+ if not name in ["site-config", "user-config", "project-config"]:
+ get_manager().errors()("The 'option' rule may be used only in site-config or user-config")
+
+ option.set(name, value[0])
diff --git a/tools/build/v2/build/property-set.jam b/tools/build/v2/build/property-set.jam
new file mode 100644
index 0000000000..70fd90cde5
--- /dev/null
+++ b/tools/build/v2/build/property-set.jam
@@ -0,0 +1,481 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import "class" : new ;
+import feature ;
+import path ;
+import project ;
+import property ;
+import sequence ;
+import set ;
+import option ;
+
+# Class for storing a set of properties.
+#
+# There is 1<->1 correspondence between identity and value. No two instances
+# of the class are equal. To maintain this property, the 'property-set.create'
+# rule should be used to create new instances. Instances are immutable.
+#
+# Each property is classified with regard to its effect on build results.
+# Incidental properties have no effect on build results, from Boost.Build's
+# point of view. Others are either free, or non-free and we refer to non-free
+# ones as 'base'. Each property belongs to exactly one of those categories.
+#
+# It is possible to get a list of properties belonging to each category as
+# well as a list of properties with a specific attribute.
+#
+# Several operations, like and refine and as-path are provided. They all use
+# caching whenever possible.
+#
+class property-set
+{
+ import errors ;
+ import feature ;
+ import path ;
+ import property ;
+ import property-set ;
+ import set ;
+
+ rule __init__ ( raw-properties * )
+ {
+ self.raw = $(raw-properties) ;
+
+ for local p in $(raw-properties)
+ {
+ if ! $(p:G)
+ {
+ errors.error "Invalid property: '$(p)'" ;
+ }
+
+ local att = [ feature.attributes $(p:G) ] ;
+ # A feature can be both incidental and free, in which case we add it
+ # to incidental.
+ if incidental in $(att)
+ {
+ self.incidental += $(p) ;
+ }
+ else if free in $(att)
+ {
+ self.free += $(p) ;
+ }
+ else
+ {
+ self.base += $(p) ;
+ }
+
+ if dependency in $(att)
+ {
+ self.dependency += $(p) ;
+ }
+ else
+ {
+ self.non-dependency += $(p) ;
+ }
+
+ if [ MATCH (:) : $(p:G=) ]
+ {
+ self.conditional += $(p) ;
+ }
+ else
+ {
+ self.non-conditional += $(p) ;
+ }
+
+ if propagated in $(att)
+ {
+ self.propagated += $(p) ;
+ }
+ if link-incompatible in $(att)
+ {
+ self.link-incompatible += $(p) ;
+ }
+ }
+ }
+
+ # Returns Jam list of stored properties.
+ #
+ rule raw ( )
+ {
+ return $(self.raw) ;
+ }
+
+ rule str ( )
+ {
+ return "[" $(self.raw) "]" ;
+ }
+
+ # Returns properties that are neither incidental nor free.
+ #
+ rule base ( )
+ {
+ return $(self.base) ;
+ }
+
+ # Returns free properties which are not incidental.
+ #
+ rule free ( )
+ {
+ return $(self.free) ;
+ }
+
+ # Returns dependency properties.
+ #
+ rule dependency ( )
+ {
+ return $(self.dependency) ;
+ }
+
+ rule non-dependency ( )
+ {
+ return $(self.non-dependency) ;
+ }
+
+ rule conditional ( )
+ {
+ return $(self.conditional) ;
+ }
+
+ rule non-conditional ( )
+ {
+ return $(self.non-conditional) ;
+ }
+
+ # Returns incidental properties.
+ #
+ rule incidental ( )
+ {
+ return $(self.incidental) ;
+ }
+
+ rule refine ( ps )
+ {
+ if ! $(self.refined.$(ps))
+ {
+ local r = [ property.refine $(self.raw) : [ $(ps).raw ] ] ;
+ if $(r[1]) != "@error"
+ {
+ self.refined.$(ps) = [ property-set.create $(r) ] ;
+ }
+ else
+ {
+ self.refined.$(ps) = $(r) ;
+ }
+ }
+ return $(self.refined.$(ps)) ;
+ }
+
+ rule expand ( )
+ {
+ if ! $(self.expanded)
+ {
+ self.expanded = [ property-set.create [ feature.expand $(self.raw) ] ] ;
+ }
+ return $(self.expanded) ;
+ }
+
+ rule expand-composites ( )
+ {
+ if ! $(self.composites)
+ {
+ self.composites = [ property-set.create
+ [ feature.expand-composites $(self.raw) ] ] ;
+ }
+ return $(self.composites) ;
+ }
+
+ rule evaluate-conditionals ( context ? )
+ {
+ context ?= $(__name__) ;
+ if ! $(self.evaluated.$(context))
+ {
+ self.evaluated.$(context) = [ property-set.create
+ [ property.evaluate-conditionals-in-context $(self.raw) : [ $(context).raw ] ] ] ;
+ }
+ return $(self.evaluated.$(context)) ;
+ }
+
+ rule propagated ( )
+ {
+ if ! $(self.propagated-ps)
+ {
+ self.propagated-ps = [ property-set.create $(self.propagated) ] ;
+ }
+ return $(self.propagated-ps) ;
+ }
+
+ rule link-incompatible ( )
+ {
+ if ! $(self.link-incompatible-ps)
+ {
+ self.link-incompatible-ps =
+ [ property-set.create $(self.link-incompatible) ] ;
+ }
+ return $(self.link-incompatible-ps) ;
+ }
+
+ rule run-actions ( )
+ {
+ if ! $(self.run)
+ {
+ self.run = [ property-set.create [ feature.run-actions $(self.raw) ] ] ;
+ }
+ return $(self.run) ;
+ }
+
+ rule add-defaults ( )
+ {
+ if ! $(self.defaults)
+ {
+ self.defaults = [ property-set.create
+ [ feature.add-defaults $(self.raw) ] ] ;
+ }
+ return $(self.defaults) ;
+ }
+
+ rule as-path ( )
+ {
+ if ! $(self.as-path)
+ {
+ self.as-path = [ property.as-path $(self.base) ] ;
+ }
+ return $(self.as-path) ;
+ }
+
+ # Computes the path to be used for a target with the given properties.
+ # Returns a list of
+ # - the computed path
+ # - if the path is relative to the build directory, a value of 'true'.
+ #
+ rule target-path ( )
+ {
+ if ! $(self.target-path)
+ {
+ # The <location> feature can be used to explicitly change the
+ # location of generated targets.
+ local l = [ get <location> ] ;
+ if $(l)
+ {
+ self.target-path = $(l) ;
+ }
+ else
+ {
+ local p = [ as-path ] ;
+ p = [ property-set.hash-maybe $(p) ] ;
+
+ # A real ugly hack. Boost regression test system requires
+ # specific target paths, and it seems that changing it to handle
+ # other directory layout is really hard. For that reason, we
+ # teach V2 to do the things regression system requires. The
+ # value of '<location-prefix>' is prepended to the path.
+ local prefix = [ get <location-prefix> ] ;
+ if $(prefix)
+ {
+ self.target-path = [ path.join $(prefix) $(p) ] ;
+ }
+ else
+ {
+ self.target-path = $(p) ;
+ }
+ if ! $(self.target-path)
+ {
+ self.target-path = . ;
+ }
+ # The path is relative to build dir.
+ self.target-path += true ;
+ }
+ }
+ return $(self.target-path) ;
+ }
+
+ rule add ( ps )
+ {
+ if ! $(self.added.$(ps))
+ {
+ self.added.$(ps) = [ property-set.create $(self.raw) [ $(ps).raw ] ] ;
+ }
+ return $(self.added.$(ps)) ;
+ }
+
+ rule add-raw ( properties * )
+ {
+ return [ add [ property-set.create $(properties) ] ] ;
+ }
+
+ rule link-incompatible-with ( ps )
+ {
+ if ! $(.li.$(ps))
+ {
+ local li1 = [ $(__name__).link-incompatible ] ;
+ local li2 = [ $(ps).link-incompatible ] ;
+ if [ set.equal $(li1) : $(li2) ]
+ {
+ .li.$(ps) = false ;
+ }
+ else
+ {
+ .li.$(ps) = true ;
+ }
+ }
+ if $(.li.$(ps)) = true
+ {
+ return true ;
+ }
+ else
+ {
+ return ;
+ }
+ }
+
+ # Returns all values of 'feature'.
+ #
+ rule get ( feature )
+ {
+ if ! $(self.map-built)
+ {
+ # For each feature, create a member var and assign all values to it.
+ # Since all regular member vars start with 'self', there will be no
+ # conflicts between names.
+ self.map-built = true ;
+ for local v in $(self.raw)
+ {
+ $(v:G) += $(v:G=) ;
+ }
+ }
+ return $($(feature)) ;
+ }
+}
+
+
+# Creates a new 'property-set' instance for the given raw properties or returns
+# an already existing ones.
+#
+rule create ( raw-properties * )
+{
+ raw-properties = [ sequence.unique
+ [ sequence.insertion-sort $(raw-properties) ] ] ;
+
+ local key = $(raw-properties:J=-:E=) ;
+
+ if ! $(.ps.$(key))
+ {
+ .ps.$(key) = [ new property-set $(raw-properties) ] ;
+ }
+ return $(.ps.$(key)) ;
+}
+NATIVE_RULE property-set : create ;
+
+
+# Creates a new 'property-set' instance after checking that all properties are
+# valid and converting incidental properties into gristed form.
+#
+rule create-with-validation ( raw-properties * )
+{
+ property.validate $(raw-properties) ;
+ return [ create [ property.make $(raw-properties) ] ] ;
+}
+
+
+# Creates a property-set from the input given by the user, in the context of
+# 'jamfile-module' at 'location'.
+#
+rule create-from-user-input ( raw-properties * : jamfile-module location )
+{
+ local specification = [ property.translate-paths $(raw-properties)
+ : $(location) ] ;
+ specification = [ property.translate-indirect $(specification)
+ : $(jamfile-module) ] ;
+ local project-id = [ project.attribute $(jamfile-module) id ] ;
+ project-id ?= [ path.root $(location) [ path.pwd ] ] ;
+ specification = [ property.translate-dependencies
+ $(specification) : $(project-id) : $(location) ] ;
+ specification =
+ [ property.expand-subfeatures-in-conditions $(specification) ] ;
+ specification = [ property.make $(specification) ] ;
+ return [ property-set.create $(specification) ] ;
+}
+
+
+# Refines requirements with requirements provided by the user. Specially handles
+# "-<property>value" syntax in specification to remove given requirements.
+# - parent-requirements -- property-set object with requirements to refine.
+# - specification -- string list of requirements provided by the user.
+# - project-module -- module to which context indirect features will be
+# bound.
+# - location -- path to which path features are relative.
+#
+rule refine-from-user-input ( parent-requirements : specification * :
+ project-module : location )
+{
+ if ! $(specification)
+ {
+ return $(parent-requirements) ;
+ }
+ else
+ {
+ local add-requirements ;
+ local remove-requirements ;
+
+ for local r in $(specification)
+ {
+ local m = [ MATCH "^-(.*)" : $(r) ] ;
+ if $(m)
+ {
+ remove-requirements += $(m) ;
+ }
+ else
+ {
+ add-requirements += $(r) ;
+ }
+ }
+
+ if $(remove-requirements)
+ {
+ # Need to create a property set, so that path features and indirect
+ # features are translated just like they are in project
+ # requirements.
+ local ps = [ property-set.create-from-user-input
+ $(remove-requirements) : $(project-module) $(location) ] ;
+
+ parent-requirements = [ property-set.create
+ [ set.difference [ $(parent-requirements).raw ]
+ : [ $(ps).raw ] ] ] ;
+ specification = $(add-requirements) ;
+ }
+
+ local requirements = [ property-set.create-from-user-input
+ $(specification) : $(project-module) $(location) ] ;
+
+ return [ $(parent-requirements).refine $(requirements) ] ;
+ }
+}
+
+
+# Returns a property-set with an empty set of properties.
+#
+rule empty ( )
+{
+ if ! $(.empty)
+ {
+ .empty = [ create ] ;
+ }
+ return $(.empty) ;
+}
+
+if [ option.get hash : : yes ] = yes
+{
+ rule hash-maybe ( path ? )
+ {
+ path ?= "" ;
+ return [ MD5 $(path) ] ;
+ }
+}
+else
+{
+ rule hash-maybe ( path ? )
+ {
+ return $(path) ;
+ }
+}
+
diff --git a/tools/build/v2/build/property.jam b/tools/build/v2/build/property.jam
new file mode 100644
index 0000000000..a2ad5226b9
--- /dev/null
+++ b/tools/build/v2/build/property.jam
@@ -0,0 +1,788 @@
+# Copyright 2001, 2002, 2003 Dave Abrahams
+# Copyright 2006 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import errors ;
+import feature ;
+import indirect ;
+import path ;
+import regex ;
+import string ;
+import sequence ;
+import set ;
+import utility ;
+
+
+# Refines 'properties' by overriding any non-free and non-conditional properties
+# for which a different value is specified in 'requirements'. Returns the
+# resulting list of properties.
+#
+rule refine ( properties * : requirements * )
+{
+ local result ;
+ local error ;
+
+ # All the 'requirements' elements should be present in the result. Record
+ # them so that we can handle 'properties'.
+ for local r in $(requirements)
+ {
+ # Do not consider conditional requirements.
+ if ! [ MATCH (:) : $(r:G=) ]
+ {
+ # Note: cannot use a local variable here, so use an ugly name.
+ __require__$(r:G) = $(r:G=) ;
+ }
+ }
+
+ for local p in $(properties)
+ {
+ if [ MATCH (:) : $(p:G=) ]
+ {
+ # Do not modify conditional properties.
+ result += $(p) ;
+ }
+ else if free in [ feature.attributes $(p:G) ]
+ {
+ # Do not modify free properties.
+ result += $(p) ;
+ }
+ else
+ {
+ local required-value = $(__require__$(p:G)) ;
+ if $(required-value)
+ {
+ if $(p:G=) != $(required-value)
+ {
+ result += $(p:G)$(required-value) ;
+ }
+ else
+ {
+ result += $(p) ;
+ }
+ }
+ else
+ {
+ result += $(p) ;
+ }
+ }
+ }
+
+ # Unset our ugly map.
+ for local r in $(requirements)
+ {
+ __require__$(r:G) = ;
+ }
+
+ if $(error)
+ {
+ return $(error) ;
+ }
+ else
+ {
+ return [ sequence.unique $(result) $(requirements) ] ;
+ }
+}
+
+
+# Removes all conditional properties whose conditions are not met. For those
+# with met conditions, removes the condition. Properties in conditions are
+# looked up in 'context'.
+#
+rule evaluate-conditionals-in-context ( properties * : context * )
+{
+ local base ;
+ local conditionals ;
+ for local p in $(properties)
+ {
+ if [ MATCH (:<) : $(p) ]
+ {
+ conditionals += $(p) ;
+ }
+ else
+ {
+ base += $(p) ;
+ }
+ }
+
+ local result = $(base) ;
+ for local p in $(conditionals)
+ {
+ # Separate condition and property.
+ local s = [ MATCH (.*):(<.*) : $(p) ] ;
+ # Split condition into individual properties.
+ local condition = [ regex.split $(s[1]) "," ] ;
+ # Evaluate condition.
+ if ! [ MATCH (!).* : $(condition:G=) ]
+ {
+ # Only positive checks
+ if $(condition) in $(context)
+ {
+ result += $(s[2]) ;
+ }
+ }
+ else
+ {
+ # Have negative checks
+ local fail ;
+ while $(condition)
+ {
+ local c = $(condition[1]) ;
+ local m = [ MATCH !(.*) : $(c) ] ;
+ if $(m)
+ {
+ local p = $(m:G=$(c:G)) ;
+ if $(p) in $(context)
+ {
+ fail = true ;
+ c = ;
+ }
+ }
+ else
+ {
+ if ! $(c) in $(context)
+ {
+ fail = true ;
+ c = ;
+ }
+ }
+ condition = $(condition[2-]) ;
+ }
+ if ! $(fail)
+ {
+ result += $(s[2]) ;
+ }
+ }
+ }
+ return $(result) ;
+}
+
+
+rule expand-subfeatures-in-conditions ( properties * )
+{
+ local result ;
+ for local p in $(properties)
+ {
+ local s = [ MATCH (.*):(<.*) : $(p) ] ;
+ if ! $(s)
+ {
+ result += $(p) ;
+ }
+ else
+ {
+ local condition = $(s[1]) ;
+ local value = $(s[2]) ;
+ # Condition might include several elements.
+ condition = [ regex.split $(condition) "," ] ;
+ local e ;
+ for local c in $(condition)
+ {
+ # It is common for a condition to include a toolset or
+ # subfeatures that have not been defined. In that case we want
+ # the condition to simply 'never be satisfied' and validation
+ # would only produce a spurious error so we prevent it by
+ # passing 'true' as the second parameter.
+ e += [ feature.expand-subfeatures $(c) : true ] ;
+ }
+ if $(e) = $(condition)
+ {
+ # (todo)
+ # This is just an optimization and possibly a premature one at
+ # that.
+ # (todo) (12.07.2008.) (Jurko)
+ result += $(p) ;
+ }
+ else
+ {
+ result += $(e:J=,):$(value) ;
+ }
+ }
+ }
+ return $(result) ;
+}
+
+
+# Helper for as-path, below. Orders properties with the implicit ones first, and
+# within the two sections in alphabetical order of feature name.
+#
+local rule path-order ( x y )
+{
+ if $(y:G) && ! $(x:G)
+ {
+ return true ;
+ }
+ else if $(x:G) && ! $(y:G)
+ {
+ return ;
+ }
+ else
+ {
+ if ! $(x:G)
+ {
+ x = [ feature.expand-subfeatures $(x) ] ;
+ y = [ feature.expand-subfeatures $(y) ] ;
+ }
+
+ if $(x[1]) < $(y[1])
+ {
+ return true ;
+ }
+ }
+}
+
+
+local rule abbreviate-dashed ( string )
+{
+ local r ;
+ for local part in [ regex.split $(string) - ]
+ {
+ r += [ string.abbreviate $(part) ] ;
+ }
+ return $(r:J=-) ;
+}
+
+
+local rule identity ( string )
+{
+ return $(string) ;
+}
+
+
+if --abbreviate-paths in [ modules.peek : ARGV ]
+{
+ .abbrev = abbreviate-dashed ;
+}
+else
+{
+ .abbrev = identity ;
+}
+
+
+# Returns a path representing the given expanded property set.
+#
+rule as-path ( properties * )
+{
+ local entry = .result.$(properties:J=-) ;
+
+ if ! $($(entry))
+ {
+ # Trim redundancy.
+ properties = [ feature.minimize $(properties) ] ;
+
+ # Sort according to path-order.
+ properties = [ sequence.insertion-sort $(properties) : path-order ] ;
+
+ local components ;
+ for local p in $(properties)
+ {
+ if $(p:G)
+ {
+ local f = [ utility.ungrist $(p:G) ] ;
+ p = $(f)-$(p:G=) ;
+ }
+ components += [ $(.abbrev) $(p) ] ;
+ }
+
+ $(entry) = $(components:J=/) ;
+ }
+
+ return $($(entry)) ;
+}
+
+
+# Exit with error if property is not valid.
+#
+local rule validate1 ( property )
+{
+ local msg ;
+ if $(property:G)
+ {
+ local feature = $(property:G) ;
+ local value = $(property:G=) ;
+
+ if ! [ feature.valid $(feature) ]
+ {
+ # Ungrist for better error messages.
+ feature = [ utility.ungrist $(property:G) ] ;
+ msg = "unknown feature '$(feature)'" ;
+ }
+ else if $(value) && ! free in [ feature.attributes $(feature) ]
+ {
+ feature.validate-value-string $(feature) $(value) ;
+ }
+ else if ! ( $(value) || ( optional in [ feature.attributes $(feature) ] ) )
+ {
+ # Ungrist for better error messages.
+ feature = [ utility.ungrist $(property:G) ] ;
+ msg = "No value specified for feature '$(feature)'" ;
+ }
+ }
+ else
+ {
+ local feature = [ feature.implied-feature $(property) ] ;
+ feature.validate-value-string $(feature) $(property) ;
+ }
+ if $(msg)
+ {
+ errors.error "Invalid property "'$(property:J=" ")'": "$(msg:J=" "). ;
+ }
+}
+
+
+rule validate ( properties * )
+{
+ for local p in $(properties)
+ {
+ validate1 $(p) ;
+ }
+}
+
+
+rule validate-property-sets ( property-sets * )
+{
+ for local s in $(property-sets)
+ {
+ validate [ feature.split $(s) ] ;
+ }
+}
+
+
+# Expands any implicit property values in the given property 'specification' so
+# they explicitly state their feature.
+#
+rule make ( specification * )
+{
+ local result ;
+ for local e in $(specification)
+ {
+ if $(e:G)
+ {
+ result += $(e) ;
+ }
+ else if [ feature.is-implicit-value $(e) ]
+ {
+ local feature = [ feature.implied-feature $(e) ] ;
+ result += $(feature)$(e) ;
+ }
+ else
+ {
+ errors.error "'$(e)' is not a valid property specification" ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Returns a property set containing all the elements in 'properties' that do not
+# have their attributes listed in 'attributes'.
+#
+rule remove ( attributes + : properties * )
+{
+ local result ;
+ for local e in $(properties)
+ {
+ if ! [ set.intersection $(attributes) : [ feature.attributes $(e:G) ] ]
+ {
+ result += $(e) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Returns a property set containing all the elements in 'properties' that have
+# their attributes listed in 'attributes'.
+#
+rule take ( attributes + : properties * )
+{
+ local result ;
+ for local e in $(properties)
+ {
+ if [ set.intersection $(attributes) : [ feature.attributes $(e:G) ] ]
+ {
+ result += $(e) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Selects properties corresponding to any of the given features.
+#
+rule select ( features * : properties * )
+{
+ local result ;
+
+ # Add any missing angle brackets.
+ local empty = "" ;
+ features = $(empty:G=$(features)) ;
+
+ for local p in $(properties)
+ {
+ if $(p:G) in $(features)
+ {
+ result += $(p) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Returns a modified version of properties with all values of the given feature
+# replaced by the given value. If 'value' is empty the feature will be removed.
+#
+rule change ( properties * : feature value ? )
+{
+ local result ;
+ for local p in $(properties)
+ {
+ if $(p:G) = $(feature)
+ {
+ result += $(value:G=$(feature)) ;
+ }
+ else
+ {
+ result += $(p) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# If 'property' is a conditional property, returns the condition and the
+# property. E.g. <variant>debug,<toolset>gcc:<inlining>full will become
+# <variant>debug,<toolset>gcc <inlining>full. Otherwise, returns an empty
+# string.
+#
+rule split-conditional ( property )
+{
+ local m = [ MATCH "(.+):<(.+)" : $(property) ] ;
+ if $(m)
+ {
+ return $(m[1]) <$(m[2]) ;
+ }
+}
+
+
+# Interpret all path properties in 'properties' as relative to 'path'. The
+# property values are assumed to be in system-specific form, and will be
+# translated into normalized form.
+#
+rule translate-paths ( properties * : path )
+{
+ local result ;
+ for local p in $(properties)
+ {
+ local split = [ split-conditional $(p) ] ;
+ local condition = "" ;
+ if $(split)
+ {
+ condition = $(split[1]): ;
+ p = $(split[2]) ;
+ }
+
+ if path in [ feature.attributes $(p:G) ]
+ {
+ local values = [ regex.split $(p:TG=) "&&" ] ;
+ local t ;
+ for local v in $(values)
+ {
+ t += [ path.root [ path.make $(v) ] $(path) ] ;
+ }
+ t = $(t:J="&&") ;
+ result += $(condition)$(t:TG=$(p:G)) ;
+ }
+ else
+ {
+ result += $(condition)$(p) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Assumes that all feature values that start with '@' are names of rules, used
+# in 'context-module'. Such rules can be either local to the module or global.
+# Converts such values into 'indirect-rule' format (see indirect.jam), so they
+# can be called from other modules. Does nothing for such values that are
+# already in the 'indirect-rule' format.
+#
+rule translate-indirect ( specification * : context-module )
+{
+ local result ;
+ for local p in $(specification)
+ {
+ local m = [ MATCH ^@(.+) : $(p:G=) ] ;
+ if $(m)
+ {
+ local v ;
+ if [ MATCH "^([^%]*)%([^%]+)$" : $(m) ]
+ {
+ # Rule is already in the 'indirect-rule' format.
+ v = $(m) ;
+ }
+ else
+ {
+ if ! [ MATCH ".*([.]).*" : $(m) ]
+ {
+ # This is an unqualified rule name. The user might want to
+ # set flags on this rule name and toolset.flag
+ # auto-qualifies it. Need to do the same here so flag
+ # setting works. We can arrange for toolset.flag to *not*
+ # auto-qualify the argument but then two rules defined in
+ # two Jamfiles would conflict.
+ m = $(context-module).$(m) ;
+ }
+ v = [ indirect.make $(m) : $(context-module) ] ;
+ }
+
+ v = @$(v) ;
+ result += $(v:G=$(p:G)) ;
+ }
+ else
+ {
+ result += $(p) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Binds all dependency properties in a list relative to the given project.
+# Targets with absolute paths will be left unchanged and targets which have a
+# project specified will have the path to the project interpreted relative to
+# the specified location.
+#
+rule translate-dependencies ( specification * : project-id : location )
+{
+ local result ;
+ for local p in $(specification)
+ {
+ local split = [ split-conditional $(p) ] ;
+ local condition = "" ;
+ if $(split)
+ {
+ condition = $(split[1]): ;
+ p = $(split[2]) ;
+ }
+ if dependency in [ feature.attributes $(p:G) ]
+ {
+ local split-target = [ regex.match (.*)//(.*) : $(p:G=) ] ;
+ if $(split-target)
+ {
+ local rooted = [ path.root [ path.make $(split-target[1]) ]
+ [ path.root $(location) [ path.pwd ] ] ] ;
+ result += $(condition)$(p:G)$(rooted)//$(split-target[2]) ;
+ }
+ else if [ path.is-rooted $(p:G=) ]
+ {
+ result += $(condition)$(p) ;
+ }
+ else
+ {
+ result += $(condition)$(p:G)$(project-id)//$(p:G=) ;
+ }
+ }
+ else
+ {
+ result += $(condition)$(p) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Class maintaining a property set -> string mapping.
+#
+class property-map
+{
+ import errors ;
+ import numbers ;
+ import sequence ;
+
+ rule __init__ ( )
+ {
+ self.next-flag = 1 ;
+ }
+
+ # Associate 'value' with 'properties'.
+ #
+ rule insert ( properties + : value )
+ {
+ self.all-flags += $(self.next-flag) ;
+ self.properties.$(self.next-flag) = $(properties) ;
+ self.value.$(self.next-flag) = $(value) ;
+
+ self.next-flag = [ numbers.increment $(self.next-flag) ] ;
+ }
+
+ # Returns the value associated with 'properties' or any subset of it. If
+ # more than one subset has a value assigned to it, returns the value for the
+ # longest subset, if it is unique.
+ #
+ rule find ( properties + )
+ {
+ return [ find-replace $(properties) ] ;
+ }
+
+ # Returns the value associated with 'properties'. If 'value' parameter is
+ # given, replaces the found value.
+ #
+ rule find-replace ( properties + : value ? )
+ {
+ # First find all matches.
+ local matches ;
+ local match-ranks ;
+ for local i in $(self.all-flags)
+ {
+ if $(self.properties.$(i)) in $(properties)
+ {
+ matches += $(i) ;
+ match-ranks += [ sequence.length $(self.properties.$(i)) ] ;
+ }
+ }
+ local best = [ sequence.select-highest-ranked $(matches)
+ : $(match-ranks) ] ;
+ if $(best[2])
+ {
+ errors.error "Ambiguous key $(properties:J= :E=)" ;
+ }
+ local original = $(self.value.$(best)) ;
+ if $(value)
+ {
+ self.value.$(best) = $(value) ;
+ }
+ return $(original) ;
+ }
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+ import "class" : new ;
+ import errors : try catch ;
+ import feature ;
+
+ # Local rules must be explicitly re-imported.
+ import property : path-order abbreviate-dashed ;
+
+ feature.prepare-test property-test-temp ;
+
+ feature.feature toolset : gcc : implicit symmetric ;
+ feature.subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 3.0 3.0.1
+ 3.0.2 : optional ;
+ feature.feature define : : free ;
+ feature.feature runtime-link : dynamic static : symmetric link-incompatible ;
+ feature.feature optimization : on off ;
+ feature.feature variant : debug release : implicit composite symmetric ;
+ feature.feature rtti : on off : link-incompatible ;
+
+ feature.compose <variant>debug : <define>_DEBUG <optimization>off ;
+ feature.compose <variant>release : <define>NDEBUG <optimization>on ;
+
+ validate <toolset>gcc <toolset>gcc-3.0.1 : $(test-space) ;
+
+ assert.true path-order $(test-space) debug <define>foo ;
+ assert.false path-order $(test-space) <define>foo debug ;
+ assert.true path-order $(test-space) gcc debug ;
+ assert.false path-order $(test-space) debug gcc ;
+ assert.true path-order $(test-space) <optimization>on <rtti>on ;
+ assert.false path-order $(test-space) <rtti>on <optimization>on ;
+
+ assert.result-set-equal <toolset>gcc <rtti>off <define>FOO
+ : refine <toolset>gcc <rtti>off
+ : <define>FOO
+ : $(test-space) ;
+
+ assert.result-set-equal <toolset>gcc <optimization>on
+ : refine <toolset>gcc <optimization>off
+ : <optimization>on
+ : $(test-space) ;
+
+ assert.result-set-equal <toolset>gcc <rtti>off
+ : refine <toolset>gcc : <rtti>off : $(test-space) ;
+
+ assert.result-set-equal <toolset>gcc <rtti>off <rtti>off:<define>FOO
+ : refine <toolset>gcc : <rtti>off <rtti>off:<define>FOO
+ : $(test-space) ;
+
+ assert.result-set-equal <toolset>gcc:<define>foo <toolset>gcc:<define>bar
+ : refine <toolset>gcc:<define>foo : <toolset>gcc:<define>bar
+ : $(test-space) ;
+
+ assert.result <define>MY_RELEASE
+ : evaluate-conditionals-in-context
+ <variant>release,<rtti>off:<define>MY_RELEASE
+ : <toolset>gcc <variant>release <rtti>off ;
+
+ assert.result debug
+ : as-path <optimization>off <variant>debug
+ : $(test-space) ;
+
+ assert.result gcc/debug/rtti-off
+ : as-path <toolset>gcc <optimization>off <rtti>off <variant>debug
+ : $(test-space) ;
+
+ assert.result optmz-off : abbreviate-dashed optimization-off ;
+ assert.result rntm-lnk-sttc : abbreviate-dashed runtime-link-static ;
+
+ try ;
+ validate <feature>value : $(test-space) ;
+ catch "Invalid property '<feature>value': unknown feature 'feature'." ;
+
+ try ;
+ validate <rtti>default : $(test-space) ;
+ catch \"default\" is not a known value of feature <rtti> ;
+
+ validate <define>WHATEVER : $(test-space) ;
+
+ try ;
+ validate <rtti> : $(test-space) ;
+ catch "Invalid property '<rtti>': No value specified for feature 'rtti'." ;
+
+ try ;
+ validate value : $(test-space) ;
+ catch "value" is not a value of an implicit feature ;
+
+ assert.result-set-equal <rtti>on
+ : remove free implicit : <toolset>gcc <define>foo <rtti>on : $(test-space) ;
+
+ assert.result-set-equal <include>a
+ : select include : <include>a <toolset>gcc ;
+
+ assert.result-set-equal <include>a
+ : select include bar : <include>a <toolset>gcc ;
+
+ assert.result-set-equal <include>a <toolset>gcc
+ : select include <bar> <toolset> : <include>a <toolset>gcc ;
+
+ assert.result-set-equal <toolset>kylix <include>a
+ : change <toolset>gcc <include>a : <toolset> kylix ;
+
+ pm = [ new property-map ] ;
+ $(pm).insert <toolset>gcc : o ;
+ $(pm).insert <toolset>gcc <os>NT : obj ;
+ $(pm).insert <toolset>gcc <os>CYGWIN : obj ;
+
+ assert.equal o : [ $(pm).find <toolset>gcc ] ;
+
+ assert.equal obj : [ $(pm).find <toolset>gcc <os>NT ] ;
+
+ try ;
+ $(pm).find <toolset>gcc <os>NT <os>CYGWIN ;
+ catch "Ambiguous key <toolset>gcc <os>NT <os>CYGWIN" ;
+
+ # Test ordinary properties.
+ assert.result : split-conditional <toolset>gcc ;
+
+ # Test properties with ":".
+ assert.result : split-conditional <define>FOO=A::B ;
+
+ # Test conditional feature.
+ assert.result-set-equal <toolset>gcc,<toolset-gcc:version>3.0 <define>FOO
+ : split-conditional <toolset>gcc,<toolset-gcc:version>3.0:<define>FOO ;
+
+ feature.finish-test property-test-temp ;
+}
diff --git a/tools/build/v2/build/property.py b/tools/build/v2/build/property.py
new file mode 100644
index 0000000000..c4b13dbcba
--- /dev/null
+++ b/tools/build/v2/build/property.py
@@ -0,0 +1,593 @@
+# Status: ported, except for tests and --abbreviate-paths.
+# Base revision: 64070
+#
+# Copyright 2001, 2002, 2003 Dave Abrahams
+# Copyright 2006 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import re
+from b2.util.utility import *
+from b2.build import feature
+from b2.util import sequence, qualify_jam_action
+import b2.util.set
+from b2.manager import get_manager
+
+__re_two_ampersands = re.compile ('&&')
+__re_comma = re.compile (',')
+__re_split_condition = re.compile ('(.*):(<.*)')
+__re_split_conditional = re.compile (r'(.+):<(.+)')
+__re_colon = re.compile (':')
+__re_has_condition = re.compile (r':<')
+__re_separate_condition_and_property = re.compile (r'(.*):(<.*)')
+
+class Property(object):
+
+ __slots__ = ('_feature', '_value', '_condition')
+
+ def __init__(self, f, value, condition = []):
+ if type(f) == type(""):
+ f = feature.get(f)
+ # At present, single property has a single value.
+ assert type(value) != type([])
+ assert(f.free() or value.find(':') == -1)
+ self._feature = f
+ self._value = value
+ self._condition = condition
+
+ def feature(self):
+ return self._feature
+
+ def value(self):
+ return self._value
+
+ def condition(self):
+ return self._condition
+
+ def to_raw(self):
+ result = "<" + self._feature.name() + ">" + str(self._value)
+ if self._condition:
+ result = ",".join(str(p) for p in self._condition) + ':' + result
+ return result
+
+ def __str__(self):
+ return self.to_raw()
+
+ def __hash__(self):
+ # FIXME: consider if this class should be value-is-identity one
+ return hash((self._feature, self._value, tuple(self._condition)))
+
+ def __cmp__(self, other):
+ return cmp((self._feature, self._value, self._condition),
+ (other._feature, other._value, other._condition))
+
+
+def create_from_string(s, allow_condition=False):
+
+ condition = []
+ import types
+ if not isinstance(s, types.StringType):
+ print type(s)
+ if __re_has_condition.search(s):
+
+ if not allow_condition:
+ raise BaseException("Conditional property is not allowed in this context")
+
+ m = __re_separate_condition_and_property.match(s)
+ condition = m.group(1)
+ s = m.group(2)
+
+ # FIXME: break dependency cycle
+ from b2.manager import get_manager
+
+ feature_name = get_grist(s)
+ if not feature_name:
+ if feature.is_implicit_value(s):
+ f = feature.implied_feature(s)
+ value = s
+ else:
+ raise get_manager().errors()("Invalid property '%s' -- unknown feature" % s)
+ else:
+ f = feature.get(feature_name)
+
+ value = get_value(s)
+ if not value:
+ get_manager().errors()("Invalid property '%s' -- no value specified" % s)
+
+
+ if condition:
+ condition = [create_from_string(x) for x in condition.split(',')]
+
+ return Property(f, value, condition)
+
+def create_from_strings(string_list, allow_condition=False):
+
+ return [create_from_string(s, allow_condition) for s in string_list]
+
+def reset ():
+ """ Clear the module state. This is mainly for testing purposes.
+ """
+ global __results
+
+ # A cache of results from as_path
+ __results = {}
+
+reset ()
+
+
+def path_order (x, y):
+ """ Helper for as_path, below. Orders properties with the implicit ones
+ first, and within the two sections in alphabetical order of feature
+ name.
+ """
+ if x == y:
+ return 0
+
+ xg = get_grist (x)
+ yg = get_grist (y)
+
+ if yg and not xg:
+ return -1
+
+ elif xg and not yg:
+ return 1
+
+ else:
+ if not xg:
+ x = feature.expand_subfeatures([x])
+ y = feature.expand_subfeatures([y])
+
+ if x < y:
+ return -1
+ elif x > y:
+ return 1
+ else:
+ return 0
+
+def identify(string):
+ return string
+
+# Uses Property
+def refine (properties, requirements):
+ """ Refines 'properties' by overriding any non-free properties
+ for which a different value is specified in 'requirements'.
+ Conditional requirements are just added without modification.
+ Returns the resulting list of properties.
+ """
+ # The result has no duplicates, so we store it in a set
+ result = set()
+
+ # Records all requirements.
+ required = {}
+
+ # All the elements of requirements should be present in the result
+ # Record them so that we can handle 'properties'.
+ for r in requirements:
+ # Don't consider conditional requirements.
+ if not r.condition():
+ required[r.feature()] = r
+
+ for p in properties:
+ # Skip conditional properties
+ if p.condition():
+ result.add(p)
+ # No processing for free properties
+ elif p.feature().free():
+ result.add(p)
+ else:
+ if required.has_key(p.feature()):
+ result.add(required[p.feature()])
+ else:
+ result.add(p)
+
+ return sequence.unique(list(result) + requirements)
+
+def translate_paths (properties, path):
+ """ Interpret all path properties in 'properties' as relative to 'path'
+ The property values are assumed to be in system-specific form, and
+ will be translated into normalized form.
+ """
+ result = []
+
+ for p in properties:
+
+ if p.feature().path():
+ values = __re_two_ampersands.split(p.value())
+
+ new_value = "&&".join(os.path.join(path, v) for v in values)
+
+ if new_value != p.value():
+ result.append(Property(p.feature(), new_value, p.condition()))
+ else:
+ result.append(p)
+
+ else:
+ result.append (p)
+
+ return result
+
+def translate_indirect(properties, context_module):
+ """Assumes that all feature values that start with '@' are
+ names of rules, used in 'context-module'. Such rules can be
+ either local to the module or global. Qualified local rules
+ with the name of the module."""
+ result = []
+ for p in properties:
+ if p.value()[0] == '@':
+ q = qualify_jam_action(p.value()[1:], context_module)
+ get_manager().engine().register_bjam_action(q)
+ result.append(Property(p.feature(), '@' + q, p.condition()))
+ else:
+ result.append(p)
+
+ return result
+
+def validate (properties):
+ """ Exit with error if any of the properties is not valid.
+ properties may be a single property or a sequence of properties.
+ """
+
+ if isinstance (properties, str):
+ __validate1 (properties)
+ else:
+ for p in properties:
+ __validate1 (p)
+
+def expand_subfeatures_in_conditions (properties):
+
+ result = []
+ for p in properties:
+
+ if not p.condition():
+ result.append(p)
+ else:
+ expanded = []
+ for c in p.condition():
+
+ if c.feature().name().startswith("toolset") or c.feature().name() == "os":
+ # It common that condition includes a toolset which
+ # was never defined, or mentiones subfeatures which
+ # were never defined. In that case, validation will
+ # only produce an spirious error, so don't validate.
+ expanded.extend(feature.expand_subfeatures ([c], True))
+ else:
+ expanded.extend(feature.expand_subfeatures([c]))
+
+ result.append(Property(p.feature(), p.value(), expanded))
+
+ return result
+
+# FIXME: this should go
+def split_conditional (property):
+ """ If 'property' is conditional property, returns
+ condition and the property, e.g
+ <variant>debug,<toolset>gcc:<inlining>full will become
+ <variant>debug,<toolset>gcc <inlining>full.
+ Otherwise, returns empty string.
+ """
+ m = __re_split_conditional.match (property)
+
+ if m:
+ return (m.group (1), '<' + m.group (2))
+
+ return None
+
+
+def select (features, properties):
+ """ Selects properties which correspond to any of the given features.
+ """
+ result = []
+
+ # add any missing angle brackets
+ features = add_grist (features)
+
+ return [p for p in properties if get_grist(p) in features]
+
+def validate_property_sets (sets):
+ for s in sets:
+ validate(s.all())
+
+def evaluate_conditionals_in_context (properties, context):
+ """ Removes all conditional properties which conditions are not met
+ For those with met conditions, removes the condition. Properies
+ in conditions are looked up in 'context'
+ """
+ base = []
+ conditional = []
+
+ for p in properties:
+ if p.condition():
+ conditional.append (p)
+ else:
+ base.append (p)
+
+ result = base[:]
+ for p in conditional:
+
+ # Evaluate condition
+ # FIXME: probably inefficient
+ if all(x in context for x in p.condition()):
+ result.append(Property(p.feature(), p.value()))
+
+ return result
+
+
+def change (properties, feature, value = None):
+ """ Returns a modified version of properties with all values of the
+ given feature replaced by the given value.
+ If 'value' is None the feature will be removed.
+ """
+ result = []
+
+ feature = add_grist (feature)
+
+ for p in properties:
+ if get_grist (p) == feature:
+ if value:
+ result.append (replace_grist (value, feature))
+
+ else:
+ result.append (p)
+
+ return result
+
+
+################################################################
+# Private functions
+
+def __validate1 (property):
+ """ Exit with error if property is not valid.
+ """
+ msg = None
+
+ if not property.feature().free():
+ feature.validate_value_string (property.feature(), property.value())
+
+
+###################################################################
+# Still to port.
+# Original lines are prefixed with "# "
+#
+#
+# import utility : ungrist ;
+# import sequence : unique ;
+# import errors : error ;
+# import feature ;
+# import regex ;
+# import sequence ;
+# import set ;
+# import path ;
+# import assert ;
+#
+#
+
+
+# rule validate-property-sets ( property-sets * )
+# {
+# for local s in $(property-sets)
+# {
+# validate [ feature.split $(s) ] ;
+# }
+# }
+#
+
+def remove(attributes, properties):
+ """Returns a property sets which include all the elements
+ in 'properties' that do not have attributes listed in 'attributes'."""
+
+ result = []
+ for e in properties:
+ attributes_new = feature.attributes(get_grist(e))
+ has_common_features = 0
+ for a in attributes_new:
+ if a in attributes:
+ has_common_features = 1
+ break
+
+ if not has_common_features:
+ result += e
+
+ return result
+
+
+def take(attributes, properties):
+ """Returns a property set which include all
+ properties in 'properties' that have any of 'attributes'."""
+ result = []
+ for e in properties:
+ if b2.util.set.intersection(attributes, feature.attributes(get_grist(e))):
+ result.append(e)
+ return result
+
+def translate_dependencies(properties, project_id, location):
+
+ result = []
+ for p in properties:
+
+ if not p.feature().dependency():
+ result.append(p)
+ else:
+ v = p.value()
+ m = re.match("(.*)//(.*)", v)
+ if m:
+ rooted = m.group(1)
+ if rooted[0] == '/':
+ # Either project id or absolute Linux path, do nothing.
+ pass
+ else:
+ rooted = os.path.join(os.getcwd(), location, rooted)
+
+ result.append(Property(p.feature(), rooted + "//" + m.group(2), p.condition()))
+
+ elif os.path.isabs(v):
+ result.append(p)
+ else:
+ result.append(Property(p.feature(), project_id + "//" + v, p.condition()))
+
+ return result
+
+
+class PropertyMap:
+ """ Class which maintains a property set -> string mapping.
+ """
+ def __init__ (self):
+ self.__properties = []
+ self.__values = []
+
+ def insert (self, properties, value):
+ """ Associate value with properties.
+ """
+ self.__properties.append(properties)
+ self.__values.append(value)
+
+ def find (self, properties):
+ """ Return the value associated with properties
+ or any subset of it. If more than one
+ subset has value assigned to it, return the
+ value for the longest subset, if it's unique.
+ """
+ return self.find_replace (properties)
+
+ def find_replace(self, properties, value=None):
+ matches = []
+ match_ranks = []
+
+ for i in range(0, len(self.__properties)):
+ p = self.__properties[i]
+
+ if b2.util.set.contains (p, properties):
+ matches.append (i)
+ match_ranks.append(len(p))
+
+ best = sequence.select_highest_ranked (matches, match_ranks)
+
+ if not best:
+ return None
+
+ if len (best) > 1:
+ raise NoBestMatchingAlternative ()
+
+ best = best [0]
+
+ original = self.__values[best]
+
+ if value:
+ self.__values[best] = value
+
+ return original
+
+# local rule __test__ ( )
+# {
+# import errors : try catch ;
+# import feature ;
+# import feature : feature subfeature compose ;
+#
+# # local rules must be explicitly re-imported
+# import property : path-order ;
+#
+# feature.prepare-test property-test-temp ;
+#
+# feature toolset : gcc : implicit symmetric ;
+# subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4
+# 3.0 3.0.1 3.0.2 : optional ;
+# feature define : : free ;
+# feature runtime-link : dynamic static : symmetric link-incompatible ;
+# feature optimization : on off ;
+# feature variant : debug release : implicit composite symmetric ;
+# feature rtti : on off : link-incompatible ;
+#
+# compose <variant>debug : <define>_DEBUG <optimization>off ;
+# compose <variant>release : <define>NDEBUG <optimization>on ;
+#
+# import assert ;
+# import "class" : new ;
+#
+# validate <toolset>gcc <toolset>gcc-3.0.1 : $(test-space) ;
+#
+# assert.result <toolset>gcc <rtti>off <define>FOO
+# : refine <toolset>gcc <rtti>off
+# : <define>FOO
+# : $(test-space)
+# ;
+#
+# assert.result <toolset>gcc <optimization>on
+# : refine <toolset>gcc <optimization>off
+# : <optimization>on
+# : $(test-space)
+# ;
+#
+# assert.result <toolset>gcc <rtti>off
+# : refine <toolset>gcc : <rtti>off : $(test-space)
+# ;
+#
+# assert.result <toolset>gcc <rtti>off <rtti>off:<define>FOO
+# : refine <toolset>gcc : <rtti>off <rtti>off:<define>FOO
+# : $(test-space)
+# ;
+#
+# assert.result <toolset>gcc:<define>foo <toolset>gcc:<define>bar
+# : refine <toolset>gcc:<define>foo : <toolset>gcc:<define>bar
+# : $(test-space)
+# ;
+#
+# assert.result <define>MY_RELEASE
+# : evaluate-conditionals-in-context
+# <variant>release,<rtti>off:<define>MY_RELEASE
+# : <toolset>gcc <variant>release <rtti>off
+#
+# ;
+#
+# try ;
+# validate <feature>value : $(test-space) ;
+# catch "Invalid property '<feature>value': unknown feature 'feature'." ;
+#
+# try ;
+# validate <rtti>default : $(test-space) ;
+# catch \"default\" is not a known value of feature <rtti> ;
+#
+# validate <define>WHATEVER : $(test-space) ;
+#
+# try ;
+# validate <rtti> : $(test-space) ;
+# catch "Invalid property '<rtti>': No value specified for feature 'rtti'." ;
+#
+# try ;
+# validate value : $(test-space) ;
+# catch "value" is not a value of an implicit feature ;
+#
+#
+# assert.result <rtti>on
+# : remove free implicit : <toolset>gcc <define>foo <rtti>on : $(test-space) ;
+#
+# assert.result <include>a
+# : select include : <include>a <toolset>gcc ;
+#
+# assert.result <include>a
+# : select include bar : <include>a <toolset>gcc ;
+#
+# assert.result <include>a <toolset>gcc
+# : select include <bar> <toolset> : <include>a <toolset>gcc ;
+#
+# assert.result <toolset>kylix <include>a
+# : change <toolset>gcc <include>a : <toolset> kylix ;
+#
+# # Test ordinary properties
+# assert.result
+# : split-conditional <toolset>gcc
+# ;
+#
+# # Test properties with ":"
+# assert.result
+# : split-conditional <define>FOO=A::B
+# ;
+#
+# # Test conditional feature
+# assert.result <toolset>gcc,<toolset-gcc:version>3.0 <define>FOO
+# : split-conditional <toolset>gcc,<toolset-gcc:version>3.0:<define>FOO
+# ;
+#
+# feature.finish-test property-test-temp ;
+# }
+#
+
diff --git a/tools/build/v2/build/property_set.py b/tools/build/v2/build/property_set.py
new file mode 100644
index 0000000000..f12eb90c14
--- /dev/null
+++ b/tools/build/v2/build/property_set.py
@@ -0,0 +1,449 @@
+# Status: ported.
+# Base revision: 40480
+
+# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+from b2.util.utility import *
+import property, feature, string
+import b2.build.feature
+from b2.exceptions import *
+from b2.util.sequence import unique
+from b2.util.set import difference
+from b2.util import cached
+
+from b2.manager import get_manager
+
+
+def reset ():
+ """ Clear the module state. This is mainly for testing purposes.
+ """
+ global __cache
+
+ # A cache of property sets
+ # TODO: use a map of weak refs?
+ __cache = {}
+
+reset ()
+
+
+def create (raw_properties = []):
+ """ Creates a new 'PropertySet' instance for the given raw properties,
+ or returns an already existing one.
+ """
+ # FIXME: propagate to callers.
+ if len(raw_properties) > 0 and isinstance(raw_properties[0], property.Property):
+ x = raw_properties
+ else:
+ x = [property.create_from_string(ps) for ps in raw_properties]
+ x.sort()
+ x = unique (x)
+
+ # FIXME: can we do better, e.g. by directly computing
+ # has value of the list?
+ key = tuple(x)
+
+ if not __cache.has_key (key):
+ __cache [key] = PropertySet(x)
+
+ return __cache [key]
+
+def create_with_validation (raw_properties):
+ """ Creates new 'PropertySet' instances after checking
+ that all properties are valid and converting incidental
+ properties into gristed form.
+ """
+ properties = [property.create_from_string(s) for s in raw_properties]
+ property.validate(properties)
+
+ return create(properties)
+
+def empty ():
+ """ Returns PropertySet with empty set of properties.
+ """
+ return create ()
+
+def create_from_user_input(raw_properties, jamfile_module, location):
+ """Creates a property-set from the input given by the user, in the
+ context of 'jamfile-module' at 'location'"""
+
+ properties = property.create_from_strings(raw_properties, True)
+ properties = property.translate_paths(properties, location)
+ properties = property.translate_indirect(properties, jamfile_module)
+
+ project_id = get_manager().projects().attributeDefault(jamfile_module, 'id', None)
+ if not project_id:
+ project_id = os.path.abspath(location)
+ properties = property.translate_dependencies(properties, project_id, location)
+ properties = property.expand_subfeatures_in_conditions(properties)
+ return create(properties)
+
+
+def refine_from_user_input(parent_requirements, specification, jamfile_module,
+ location):
+ """Refines requirements with requirements provided by the user.
+ Specially handles "-<property>value" syntax in specification
+ to remove given requirements.
+ - parent-requirements -- property-set object with requirements
+ to refine
+ - specification -- string list of requirements provided by the use
+ - project-module -- the module to which context indirect features
+ will be bound.
+ - location -- the path to which path features are relative."""
+
+
+ if not specification:
+ return parent_requirements
+
+
+ add_requirements = []
+ remove_requirements = []
+
+ for r in specification:
+ if r[0] == '-':
+ remove_requirements.append(r[1:])
+ else:
+ add_requirements.append(r)
+
+ if remove_requirements:
+ # Need to create property set, so that path features
+ # and indirect features are translated just like they
+ # are in project requirements.
+ ps = create_from_user_input(remove_requirements,
+ jamfile_module, location)
+
+ parent_requirements = create(difference(parent_requirements.all(),
+ ps.all()))
+ specification = add_requirements
+
+ requirements = create_from_user_input(specification,
+ jamfile_module, location)
+
+ return parent_requirements.refine(requirements)
+
+class PropertySet:
+ """ Class for storing a set of properties.
+ - there's 1<->1 correspondence between identity and value. No
+ two instances of the class are equal. To maintain this property,
+ the 'PropertySet.create' rule should be used to create new instances.
+ Instances are immutable.
+
+ - each property is classified with regard to it's effect on build
+ results. Incidental properties have no effect on build results, from
+ Boost.Build point of view. Others are either free, or non-free, which we
+ call 'base'. Each property belong to exactly one of those categories and
+ it's possible to get list of properties in each category.
+
+ In addition, it's possible to get list of properties with specific
+ attribute.
+
+ - several operations, like and refine and as_path are provided. They all use
+ caching whenever possible.
+ """
+ def __init__ (self, properties = []):
+
+
+ raw_properties = []
+ for p in properties:
+ raw_properties.append(p.to_raw())
+
+ self.all_ = properties
+ self.all_raw_ = raw_properties
+ self.all_set_ = set(properties)
+
+ self.incidental_ = []
+ self.free_ = []
+ self.base_ = []
+ self.dependency_ = []
+ self.non_dependency_ = []
+ self.conditional_ = []
+ self.non_conditional_ = []
+ self.propagated_ = []
+ self.link_incompatible = []
+
+ # A cache of refined properties.
+ self.refined_ = {}
+
+ # A cache of property sets created by adding properties to this one.
+ self.added_ = {}
+
+ # Cache for the default properties.
+ self.defaults_ = None
+
+ # Cache for the expanded properties.
+ self.expanded_ = None
+
+ # Cache for the expanded composite properties
+ self.composites_ = None
+
+ # Cache for property set with expanded subfeatures
+ self.subfeatures_ = None
+
+ # Cache for the property set containing propagated properties.
+ self.propagated_ps_ = None
+
+ # A map of features to its values.
+ self.feature_map_ = None
+
+ # A tuple (target path, is relative to build directory)
+ self.target_path_ = None
+
+ self.as_path_ = None
+
+ # A cache for already evaluated sets.
+ self.evaluated_ = {}
+
+ for p in raw_properties:
+ if not get_grist (p):
+ raise BaseException ("Invalid property: '%s'" % p)
+
+ att = feature.attributes (get_grist (p))
+
+ if 'propagated' in att:
+ self.propagated_.append (p)
+
+ if 'link_incompatible' in att:
+ self.link_incompatible.append (p)
+
+ for p in properties:
+
+ # A feature can be both incidental and free,
+ # in which case we add it to incidental.
+ if p.feature().incidental():
+ self.incidental_.append(p)
+ elif p.feature().free():
+ self.free_.append(p)
+ else:
+ self.base_.append(p)
+
+ if p.condition():
+ self.conditional_.append(p)
+ else:
+ self.non_conditional_.append(p)
+
+ if p.feature().dependency():
+ self.dependency_.append (p)
+ else:
+ self.non_dependency_.append (p)
+
+
+ def all(self):
+ return self.all_
+
+ def raw (self):
+ """ Returns the list of stored properties.
+ """
+ return self.all_raw_
+
+ def __str__(self):
+ return ' '.join(str(p) for p in self.all_)
+
+ def base (self):
+ """ Returns properties that are neither incidental nor free.
+ """
+ return self.base_
+
+ def free (self):
+ """ Returns free properties which are not dependency properties.
+ """
+ return self.free_
+
+ def non_free(self):
+ return self.base_ + self.incidental_
+
+ def dependency (self):
+ """ Returns dependency properties.
+ """
+ return self.dependency_
+
+ def non_dependency (self):
+ """ Returns properties that are not dependencies.
+ """
+ return self.non_dependency_
+
+ def conditional (self):
+ """ Returns conditional properties.
+ """
+ return self.conditional_
+
+ def non_conditional (self):
+ """ Returns properties that are not conditional.
+ """
+ return self.non_conditional_
+
+ def incidental (self):
+ """ Returns incidental properties.
+ """
+ return self.incidental_
+
+ def refine (self, requirements):
+ """ Refines this set's properties using the requirements passed as an argument.
+ """
+ assert isinstance(requirements, PropertySet)
+ if not self.refined_.has_key (requirements):
+ r = property.refine(self.all_, requirements.all_)
+
+ self.refined_[requirements] = create(r)
+
+ return self.refined_[requirements]
+
+ def expand (self):
+ if not self.expanded_:
+ expanded = feature.expand(self.all_)
+ self.expanded_ = create(expanded)
+ return self.expanded_
+
+ def expand_subfeatures(self):
+ if not self.subfeatures_:
+ self.subfeatures_ = create(feature.expand_subfeatures(self.all_))
+ return self.subfeatures_
+
+ def evaluate_conditionals(self, context=None):
+ if not context:
+ context = self
+
+ if not self.evaluated_.has_key(context):
+ # FIXME: figure why the call messes up first parameter
+ self.evaluated_[context] = create(
+ property.evaluate_conditionals_in_context(self.all(), context))
+
+ return self.evaluated_[context]
+
+ def propagated (self):
+ if not self.propagated_ps_:
+ self.propagated_ps_ = create (self.propagated_)
+ return self.propagated_ps_
+
+ def add_defaults (self):
+ # FIXME: this caching is invalidated when new features
+ # are declare inside non-root Jamfiles.
+ if not self.defaults_:
+ expanded = feature.add_defaults(self.all_)
+ self.defaults_ = create(expanded)
+ return self.defaults_
+
+ def as_path (self):
+ if not self.as_path_:
+
+ def path_order (p1, p2):
+
+ i1 = p1.feature().implicit()
+ i2 = p2.feature().implicit()
+
+ if i1 != i2:
+ return i2 - i1
+ else:
+ return cmp(p1.feature().name(), p2.feature().name())
+
+ # trim redundancy
+ properties = feature.minimize(self.base_)
+
+ # sort according to path_order
+ properties.sort (path_order)
+
+ components = []
+ for p in properties:
+ if p.feature().implicit():
+ components.append(p.value())
+ else:
+ components.append(p.feature().name() + "-" + p.value())
+
+ self.as_path_ = '/'.join (components)
+
+ return self.as_path_
+
+ def target_path (self):
+ """ Computes the target path that should be used for
+ target with these properties.
+ Returns a tuple of
+ - the computed path
+ - if the path is relative to build directory, a value of
+ 'true'.
+ """
+ if not self.target_path_:
+ # The <location> feature can be used to explicitly
+ # change the location of generated targets
+ l = self.get ('<location>')
+ if l:
+ computed = l[0]
+ is_relative = False
+
+ else:
+ p = self.as_path ()
+
+ # Really, an ugly hack. Boost regression test system requires
+ # specific target paths, and it seems that changing it to handle
+ # other directory layout is really hard. For that reason,
+ # we teach V2 to do the things regression system requires.
+ # The value o '<location-prefix>' is predended to the path.
+ prefix = self.get ('<location-prefix>')
+
+ if prefix:
+ if len (prefix) > 1:
+ raise AlreadyDefined ("Two <location-prefix> properties specified: '%s'" % prefix)
+
+ computed = os.path.join(prefix[0], p)
+
+ else:
+ computed = p
+
+ if not computed:
+ computed = "."
+
+ is_relative = True
+
+ self.target_path_ = (computed, is_relative)
+
+ return self.target_path_
+
+ def add (self, ps):
+ """ Creates a new property set containing the properties in this one,
+ plus the ones of the property set passed as argument.
+ """
+ if not self.added_.has_key(ps):
+ self.added_[ps] = create(self.all_ + ps.all())
+ return self.added_[ps]
+
+ def add_raw (self, properties):
+ """ Creates a new property set containing the properties in this one,
+ plus the ones passed as argument.
+ """
+ return self.add (create (properties))
+
+
+ def get (self, feature):
+ """ Returns all values of 'feature'.
+ """
+ if type(feature) == type([]):
+ feature = feature[0]
+ if not isinstance(feature, b2.build.feature.Feature):
+ feature = b2.build.feature.get(feature)
+
+ if not self.feature_map_:
+ self.feature_map_ = {}
+
+ for v in self.all_:
+ if not self.feature_map_.has_key(v.feature()):
+ self.feature_map_[v.feature()] = []
+ self.feature_map_[v.feature()].append(v.value())
+
+ return self.feature_map_.get(feature, [])
+
+ @cached
+ def get_properties(self, feature):
+ """Returns all contained properties associated with 'feature'"""
+
+ if not isinstance(feature, b2.build.feature.Feature):
+ feature = b2.build.feature.get(feature)
+
+ result = []
+ for p in self.all_:
+ if p.feature() == feature:
+ result.append(p)
+ return result
+
+ def __contains__(self, item):
+ return item in self.all_set_
+
diff --git a/tools/build/v2/build/readme.txt b/tools/build/v2/build/readme.txt
new file mode 100644
index 0000000000..c3dddd8d78
--- /dev/null
+++ b/tools/build/v2/build/readme.txt
@@ -0,0 +1,13 @@
+Copyright 2001, 2002 Dave Abrahams
+Copyright 2002 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+Development code for new build system. To run unit tests for jam code, execute:
+
+ bjam --debug --build-system=test
+
+Comprehensive tests require Python. See ../test/readme.txt
+
+
+
diff --git a/tools/build/v2/build/scanner.jam b/tools/build/v2/build/scanner.jam
new file mode 100644
index 0000000000..d6042ea2c7
--- /dev/null
+++ b/tools/build/v2/build/scanner.jam
@@ -0,0 +1,153 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Implements scanners: objects that compute implicit dependencies for
+# files, such as includes in C++.
+#
+# Scanner has a regular expression used to find dependencies, some
+# data needed to interpret those dependencies (for example, include
+# paths), and a code which actually established needed relationship
+# between actual jam targets.
+#
+# Scanner objects are created by actions, when they try to actualize
+# virtual targets, passed to 'virtual-target.actualize' method and are
+# then associated with actual targets. It is possible to use
+# several scanners for a virtual-target. For example, a single source
+# might be used by to compile actions, with different include paths.
+# In this case, two different actual targets will be created, each
+# having scanner of its own.
+#
+# Typically, scanners are created from target type and action's
+# properties, using the rule 'get' in this module. Directly creating
+# scanners is not recommended, because it might create many equvivalent
+# but different instances, and lead in unneeded duplication of
+# actual targets. However, actions can also create scanners in a special
+# way, instead of relying on just target type.
+
+import "class" : new ;
+import property virtual-target property-set ;
+import errors : error ;
+
+# Base scanner class.
+class scanner
+{
+ rule __init__ ( )
+ {
+ }
+
+ # Returns a pattern to use for scanning
+ rule pattern ( )
+ {
+ error "method must be overriden" ;
+ }
+
+ # Establish necessary relationship between targets,
+ # given actual target beeing scanned, and a list of
+ # pattern matches in that file.
+ rule process ( target : matches * )
+ {
+ error "method must be overriden" ;
+ }
+}
+
+# Registers a new generator class, specifying a set of
+# properties relevant to this scanner. Ctor for that class
+# should have one parameter: list of properties.
+rule register ( scanner-class : relevant-properties * )
+{
+ .registered += $(scanner-class) ;
+ .relevant-properties.$(scanner-class) = $(relevant-properties) ;
+}
+
+# Common scanner class, which can be used when there's only one
+# kind of includes (unlike C, where "" and <> includes have different
+# search paths).
+class common-scanner : scanner
+{
+ import scanner ;
+ rule __init__ ( includes * )
+ {
+ scanner.__init__ ;
+ self.includes = $(includes) ;
+ }
+
+ rule process ( target : matches * : binding )
+ {
+ local target_path = [ NORMALIZE_PATH $(binding:D) ] ;
+
+ NOCARE $(matches) ;
+ INCLUDES $(target) : $(matches) ;
+ SEARCH on $(matches) = $(target_path) $(self.includes:G=) ;
+ ISFILE $(matches) ;
+
+ scanner.propagate $(__name__) : $(matches) : $(target) ;
+ }
+}
+
+
+# Returns an instance of previously registered scanner,
+# with the specified properties.
+rule get ( scanner-class : property-set )
+{
+ if ! $(scanner-class) in $(.registered)
+ {
+ error "attempt to get unregisted scanner" ;
+ }
+
+ local r = $(.rv-cache.$(property-set)) ;
+ if ! $(r)
+ {
+ r = [ property-set.create
+ [ property.select $(.relevant-properties.$(scanner-class)) :
+ [ $(property-set).raw ] ] ] ;
+ .rv-cache.$(property-set) = $(r) ;
+ }
+
+ if ! $(scanner.$(scanner-class).$(r:J=-))
+ {
+ scanner.$(scanner-class).$(r:J=-) = [ new $(scanner-class) [ $(r).raw ] ] ;
+ }
+ return $(scanner.$(scanner-class).$(r:J=-)) ;
+}
+
+
+# Installs the specified scanner on actual target 'target'.
+rule install ( scanner : target
+ vtarget # virtual target from which 'target' was actualized
+)
+{
+ HDRSCAN on $(target) = [ $(scanner).pattern ] ;
+ SCANNER on $(target) = $(scanner) ;
+ HDRRULE on $(target) = scanner.hdrrule ;
+
+ # scanner reflects difference in properties affecting
+ # binding of 'target', which will be known when processing
+ # includes for it, will give information on how to
+ # interpret quoted includes.
+ HDRGRIST on $(target) = $(scanner) ;
+}
+
+# Propagate scanner setting from 'including-target' to 'targets'.
+rule propagate ( scanner : targets * : including-target )
+{
+ HDRSCAN on $(targets) = [ on $(including-target) return $(HDRSCAN) ] ;
+ SCANNER on $(targets) = $(scanner) ;
+ HDRRULE on $(targets) = scanner.hdrrule ;
+ HDRGRIST on $(targets) = [ on $(including-target) return $(HDRGRIST) ] ;
+}
+
+
+rule hdrrule ( target : matches * : binding )
+{
+ local scanner = [ on $(target) return $(SCANNER) ] ;
+ $(scanner).process $(target) : $(matches) : $(binding) ;
+}
+# hdrrule must be available at global scope so that it can be invoked
+# by header scanning
+IMPORT scanner : hdrrule : : scanner.hdrrule ;
+
+
+
+
diff --git a/tools/build/v2/build/scanner.py b/tools/build/v2/build/scanner.py
new file mode 100644
index 0000000000..19f1431d47
--- /dev/null
+++ b/tools/build/v2/build/scanner.py
@@ -0,0 +1,158 @@
+# Status: ported.
+# Base revision: 45462
+#
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Implements scanners: objects that compute implicit dependencies for
+# files, such as includes in C++.
+#
+# Scanner has a regular expression used to find dependencies, some
+# data needed to interpret those dependencies (for example, include
+# paths), and a code which actually established needed relationship
+# between actual jam targets.
+#
+# Scanner objects are created by actions, when they try to actualize
+# virtual targets, passed to 'virtual-target.actualize' method and are
+# then associated with actual targets. It is possible to use
+# several scanners for a virtual-target. For example, a single source
+# might be used by to compile actions, with different include paths.
+# In this case, two different actual targets will be created, each
+# having scanner of its own.
+#
+# Typically, scanners are created from target type and action's
+# properties, using the rule 'get' in this module. Directly creating
+# scanners is not recommended, because it might create many equvivalent
+# but different instances, and lead in unneeded duplication of
+# actual targets. However, actions can also create scanners in a special
+# way, instead of relying on just target type.
+
+import property
+import bjam
+import os
+from b2.exceptions import *
+from b2.manager import get_manager
+
+def reset ():
+ """ Clear the module state. This is mainly for testing purposes.
+ """
+ global __scanners, __rv_cache, __scanner_cache
+
+ # Maps registered scanner classes to relevant properties
+ __scanners = {}
+
+ # A cache of scanners.
+ # The key is: class_name.properties_tag, where properties_tag is the concatenation
+ # of all relevant properties, separated by '-'
+ __scanner_cache = {}
+
+reset ()
+
+
+def register(scanner_class, relevant_properties):
+ """ Registers a new generator class, specifying a set of
+ properties relevant to this scanner. Ctor for that class
+ should have one parameter: list of properties.
+ """
+ __scanners[str(scanner_class)] = relevant_properties
+
+def registered(scanner_class):
+ """ Returns true iff a scanner of that class is registered
+ """
+ return __scanners.has_key(str(scanner_class))
+
+def get(scanner_class, properties):
+ """ Returns an instance of previously registered scanner
+ with the specified properties.
+ """
+ scanner_name = str(scanner_class)
+
+ if not registered(scanner_name):
+ raise BaseException ("attempt to get unregisted scanner: %s" % scanner_name)
+
+ relevant_properties = __scanners[scanner_name]
+ r = property.select(relevant_properties, properties)
+
+ scanner_id = scanner_name + '.' + '-'.join(r)
+
+ if not __scanner_cache.has_key(scanner_name):
+ __scanner_cache[scanner_name] = scanner_class(r)
+
+ return __scanner_cache[scanner_name]
+
+class Scanner:
+ """ Base scanner class.
+ """
+ def __init__ (self):
+ pass
+
+ def pattern (self):
+ """ Returns a pattern to use for scanning.
+ """
+ raise BaseException ("method must be overriden")
+
+ def process (self, target, matches):
+ """ Establish necessary relationship between targets,
+ given actual target beeing scanned, and a list of
+ pattern matches in that file.
+ """
+ raise BaseException ("method must be overriden")
+
+
+# Common scanner class, which can be used when there's only one
+# kind of includes (unlike C, where "" and <> includes have different
+# search paths).
+class CommonScanner(Scanner):
+
+ def __init__ (self, includes):
+ Scanner.__init__(self)
+ self.includes = includes
+
+ def process(self, target, matches, binding):
+
+ target_path = os.path.normpath(os.path.dirname(binding[0]))
+ bjam.call("mark-included", target, matches)
+
+ get_manager().engine().set_target_variable(matches, "SEARCH",
+ [target_path] + self.includes)
+ get_manager().scanners().propagate(self, matches)
+
+class ScannerRegistry:
+
+ def __init__ (self, manager):
+ self.manager_ = manager
+ self.count_ = 0
+ self.exported_scanners_ = {}
+
+ def install (self, scanner, target, vtarget):
+ """ Installs the specified scanner on actual target 'target'.
+ vtarget: virtual target from which 'target' was actualized.
+ """
+ engine = self.manager_.engine()
+ engine.set_target_variable(target, "HDRSCAN", scanner.pattern())
+ if not self.exported_scanners_.has_key(scanner):
+ exported_name = "scanner_" + str(self.count_)
+ self.count_ = self.count_ + 1
+ self.exported_scanners_[scanner] = exported_name
+ bjam.import_rule("", exported_name, scanner.process)
+ else:
+ exported_name = self.exported_scanners_[scanner]
+
+ engine.set_target_variable(target, "HDRRULE", exported_name)
+
+ # scanner reflects difference in properties affecting
+ # binding of 'target', which will be known when processing
+ # includes for it, will give information on how to
+ # interpret quoted includes.
+ engine.set_target_variable(target, "HDRGRIST", str(id(scanner)))
+ pass
+
+ def propagate(self, scanner, targets):
+ engine = self.manager_.engine()
+ engine.set_target_variable(targets, "HDRSCAN", scanner.pattern())
+ engine.set_target_variable(targets, "HDRRULE",
+ self.exported_scanners_[scanner])
+ engine.set_target_variable(targets, "HDRGRIST", str(id(scanner)))
+
diff --git a/tools/build/v2/build/targets.jam b/tools/build/v2/build/targets.jam
new file mode 100644
index 0000000000..a70532ce73
--- /dev/null
+++ b/tools/build/v2/build/targets.jam
@@ -0,0 +1,1659 @@
+# Copyright Vladimir Prus 2002.
+# Copyright Rene Rivera 2006.
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Supports 'abstract' targets, which are targets explicitly defined in a
+# Jamfile.
+#
+# Abstract targets are represented by classes derived from 'abstract-target'
+# class. The first abstract target is 'project-target', which is created for
+# each Jamfile, and can be obtained by the 'target' rule in the Jamfile's module
+# (see project.jam).
+#
+# Project targets keep a list of 'main-target' instances. A main target is what
+# the user explicitly defines in a Jamfile. It is possible to have several
+# definitions for a main target, for example to have different lists of sources
+# for different platforms. So, main targets keep a list of alternatives.
+#
+# Each alternative is an instance of 'abstract-target'. When a main target
+# subvariant is defined by some rule, that rule will decide what class to use,
+# create an instance of that class and add it to the list of alternatives for
+# the main target.
+#
+# Rules supplied by the build system will use only targets derived from
+# 'basic-target' class, which will provide some default behaviour. There will be
+# different classes derived from it such as 'make-target', created by the 'make'
+# rule, and 'typed-target', created by rules such as 'exe' and 'lib'.
+
+#
+# +------------------------+
+# |abstract-target |
+# +========================+
+# |name |
+# |project |
+# | |
+# |generate(properties) = 0|
+# +-----------+------------+
+# |
+# ^
+# / \
+# +-+-+
+# |
+# |
+# +------------------------+------+------------------------------+
+# | | |
+# | | |
+# +----------+-----------+ +------+------+ +------+-------+
+# | project-target | | main-target | | basic-target |
+# +======================+ 1 * +=============+ alternatives +==============+
+# | generate(properties) |o-----------+ generate |<>------------->| generate |
+# | main-target | +-------------+ | construct = 0|
+# +----------------------+ +--------------+
+# |
+# ^
+# / \
+# +-+-+
+# |
+# |
+# ...--+----------------+------------------+----------------+---+
+# | | | |
+# | | | |
+# ... ---+-----+ +------+-------+ +------+------+ +--------+-----+
+# | | typed-target | | make-target | | stage-target |
+# . +==============+ +=============+ +==============+
+# . | construct | | construct | | construct |
+# +--------------+ +-------------+ +--------------+
+
+import assert ;
+import "class" : new ;
+import errors ;
+import feature ;
+import indirect ;
+import path ;
+import property ;
+import property-set ;
+import sequence ;
+import set ;
+import toolset ;
+import build-request ;
+
+
+# Base class for all abstract targets.
+#
+class abstract-target
+{
+ import project ;
+ import assert ;
+ import "class" ;
+ import errors ;
+
+ rule __init__ ( name # Name of the target in Jamfile.
+ : project-target # The project target to which this one belongs.
+ )
+ {
+ # Note: it might seem that we don't need either name or project at all.
+ # However, there are places where we really need it. One example is
+ # error messages which should name problematic targets. Another is
+ # setting correct paths for sources and generated files.
+
+ self.name = $(name) ;
+ self.project = $(project-target) ;
+ self.location = [ errors.nearest-user-location ] ;
+ }
+
+ # Returns the name of this target.
+ rule name ( )
+ {
+ return $(self.name) ;
+ }
+
+ # Returns the project for this target.
+ rule project ( )
+ {
+ return $(self.project) ;
+ }
+
+ # Return the location where the target was declared.
+ rule location ( )
+ {
+ return $(self.location) ;
+ }
+
+ # Returns a user-readable name for this target.
+ rule full-name ( )
+ {
+ local location = [ $(self.project).get location ] ;
+ return $(location)/$(self.name) ;
+ }
+
+ # Generates virtual targets for this abstract target using the specified
+ # properties, unless a different value of some feature is required by the
+ # target.
+ # On success, returns:
+ # - a property-set with the usage requirements to be applied to dependants
+ # - a list of produced virtual targets, which may be empty.
+ # If 'property-set' is empty, performs the default build of this target, in
+ # a way specific to the derived class.
+ #
+ rule generate ( property-set )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+
+ rule rename ( new-name )
+ {
+ self.name = $(new-name) ;
+ }
+}
+
+
+if --debug-building in [ modules.peek : ARGV ]
+{
+ modules.poke : .debug-building : true ;
+}
+
+
+rule indent ( )
+{
+ return $(.indent:J="") ;
+}
+
+
+rule increase-indent ( )
+{
+ .indent += " " ;
+}
+
+
+rule decrease-indent ( )
+{
+ .indent = $(.indent[2-]) ;
+}
+
+
+# Project target class (derived from 'abstract-target').
+#
+# This class has the following responsibilities:
+# - Maintaining a list of main targets in this project and building them.
+#
+# Main targets are constructed in two stages:
+# - When Jamfile is read, a number of calls to 'add-alternative' is made. At
+# that time, alternatives can also be renamed to account for inline targets.
+# - The first time 'main-target' or 'has-main-target' rule is called, all
+# alternatives are enumerated and main targets are created.
+#
+class project-target : abstract-target
+{
+ import project ;
+ import targets ;
+ import path ;
+ import print ;
+ import property-set ;
+ import set ;
+ import sequence ;
+ import "class" : new ;
+ import errors ;
+
+ rule __init__ ( name : project-module parent-project ?
+ : requirements * : default-build * )
+ {
+ abstract-target.__init__ $(name) : $(__name__) ;
+
+ self.project-module = $(project-module) ;
+ self.location = [ project.attribute $(project-module) location ] ;
+ self.requirements = $(requirements) ;
+ self.default-build = $(default-build) ;
+
+ if $(parent-project)
+ {
+ inherit $(parent-project) ;
+ }
+ }
+
+ # This is needed only by the 'make' rule. Need to find the way to make
+ # 'make' work without this method.
+ #
+ rule project-module ( )
+ {
+ return $(self.project-module) ;
+ }
+
+ rule get ( attribute )
+ {
+ return [ project.attribute $(self.project-module) $(attribute) ] ;
+ }
+
+ rule build-dir ( )
+ {
+ if ! $(self.build-dir)
+ {
+ self.build-dir = [ get build-dir ] ;
+ if ! $(self.build-dir)
+ {
+ self.build-dir = [ path.join [ $(self.project).get location ]
+ bin ] ;
+ }
+ }
+ return $(self.build-dir) ;
+ }
+
+ # Generates all possible targets contained in this project.
+ #
+ rule generate ( property-set * )
+ {
+ if [ modules.peek : .debug-building ]
+ {
+ ECHO [ targets.indent ] "building project" [ name ] " ('$(__name__)') with" [ $(property-set).raw ] ;
+ targets.increase-indent ;
+ }
+
+ local usage-requirements = [ property-set.empty ] ;
+ local targets ;
+
+ for local t in [ targets-to-build ]
+ {
+ local g = [ $(t).generate $(property-set) ] ;
+ usage-requirements = [ $(usage-requirements).add $(g[1]) ] ;
+ targets += $(g[2-]) ;
+ }
+ targets.decrease-indent ;
+ return $(usage-requirements) [ sequence.unique $(targets) ] ;
+ }
+
+ # Computes and returns a list of abstract-target instances which must be
+ # built when this project is built.
+ #
+ rule targets-to-build ( )
+ {
+ local result ;
+
+ if ! $(self.built-main-targets)
+ {
+ build-main-targets ;
+ }
+
+ # Collect all main targets here, except for "explicit" ones.
+ for local t in $(self.main-targets)
+ {
+ if ! [ $(t).name ] in $(self.explicit-targets)
+ {
+ result += $(t) ;
+ }
+ }
+
+ # Collect all projects referenced via "projects-to-build" attribute.
+ local self-location = [ get location ] ;
+ for local pn in [ get projects-to-build ]
+ {
+ result += [ find $(pn)/ ] ;
+ }
+
+ return $(result) ;
+ }
+
+ # Add 'target' to the list of targets in this project that should be build
+ # only by explicit request
+ #
+ rule mark-target-as-explicit ( target-name * )
+ {
+ # Record the name of the target, not instance, since this rule is called
+ # before main target instances are created.
+ self.explicit-targets += $(target-name) ;
+ }
+
+ rule mark-target-as-always ( target-name * )
+ {
+ # Record the name of the target, not instance, since this rule is called
+ # before main target instances are created.
+ self.always-targets += $(target-name) ;
+ }
+
+ # Add new target alternative
+ #
+ rule add-alternative ( target-instance )
+ {
+ if $(self.built-main-targets)
+ {
+ errors.error add-alternative called when main targets are already
+ created. : in project [ full-name ] ;
+ }
+ self.alternatives += $(target-instance) ;
+ }
+
+ # Returns a 'main-target' class instance corresponding to 'name'.
+ #
+ rule main-target ( name )
+ {
+ if ! $(self.built-main-targets)
+ {
+ build-main-targets ;
+ }
+ return $(self.main-target.$(name)) ;
+ }
+
+ # Returns whether a main target with the specified name exists.
+ #
+ rule has-main-target ( name )
+ {
+ if ! $(self.built-main-targets)
+ {
+ build-main-targets ;
+ }
+
+ if $(self.main-target.$(name))
+ {
+ return true ;
+ }
+ }
+
+ # Worker function for the find rule not implementing any caching and simply
+ # returning nothing in case the target can not be found.
+ #
+ rule find-really ( id )
+ {
+ local result ;
+ local current-location = [ get location ] ;
+
+ local split = [ MATCH (.*)//(.*) : $(id) ] ;
+ local project-part = $(split[1]) ;
+ local target-part = $(split[2]) ;
+
+ local extra-error-message ;
+ if $(project-part)
+ {
+ # There is an explicitly specified project part in id. Looks up the
+ # project and passes the request to it.
+ local pm = [ project.find $(project-part) : $(current-location) ] ;
+ if $(pm)
+ {
+ project-target = [ project.target $(pm) ] ;
+ result = [ $(project-target).find $(target-part) : no-error ] ;
+ }
+ else
+ {
+ # TODO: This extra error message will not get displayed most
+ # likely due to some buggy refactoring. Refactor the code so the
+ # message gets diplayed again.
+ extra-error-message = error: could not find project
+ '$(project-part)' ;
+ }
+ }
+ else
+ {
+ # Interpret target-name as name of main target. Need to do this
+ # before checking for file. Consider the following scenario with a
+ # toolset not modifying its executable's names, e.g. gcc on
+ # Unix-like platforms:
+ #
+ # exe test : test.cpp ;
+ # install s : test : <location>. ;
+ #
+ # After the first build we would have a target named 'test' in the
+ # Jamfile and a file named 'test' on the disk. We need the target to
+ # override the file.
+ result = [ main-target $(id) ] ;
+
+ # Interpret id as an existing file reference.
+ if ! $(result)
+ {
+ result = [ new file-reference [ path.make $(id) ] :
+ $(self.project) ] ;
+ if ! [ $(result).exists ]
+ {
+ result = ;
+ }
+ }
+
+ # Interpret id as project-id.
+ if ! $(result)
+ {
+ local project-module = [ project.find $(id) :
+ $(current-location) ] ;
+ if $(project-module)
+ {
+ result = [ project.target $(project-module) ] ;
+ }
+ }
+ }
+
+ return $(result) ;
+ }
+
+ # Find and return the target with the specified id, treated relative to
+ # self. Id may specify either a target or a file name with the target taking
+ # priority. May report an error or return nothing if the target is not found
+ # depending on the 'no-error' parameter.
+ #
+ rule find ( id : no-error ? )
+ {
+ local v = $(.id.$(id)) ;
+ if ! $(v)
+ {
+ v = [ find-really $(id) ] ;
+ if ! $(v)
+ {
+ v = none ;
+ }
+ .id.$(id) = $(v) ;
+ }
+
+ if $(v) != none
+ {
+ return $(v) ;
+ }
+ else
+ {
+ if ! $(no-error)
+ {
+ local current-location = [ get location ] ;
+ ECHO "error: Unable to find file or target named" ;
+ ECHO "error: '$(id)'" ;
+ ECHO "error: referred from project at" ;
+ ECHO "error: '$(current-location)'" ;
+ ECHO $(extra-error-message) ;
+ EXIT ;
+ }
+ }
+ }
+
+ rule build-main-targets ( )
+ {
+ self.built-main-targets = true ;
+ for local a in $(self.alternatives)
+ {
+ local name = [ $(a).name ] ;
+ local target = $(self.main-target.$(name)) ;
+ if ! $(target)
+ {
+ local t = [ new main-target $(name) : $(self.project) ] ;
+ self.main-target.$(name) = $(t) ;
+ self.main-targets += $(t) ;
+ target = $(self.main-target.$(name)) ;
+ }
+
+ if $(name) in $(self.always-targets)
+ {
+ $(a).always ;
+ }
+
+ $(target).add-alternative $(a) ;
+ }
+ }
+
+ # Accessor, add a constant.
+ #
+ rule add-constant (
+ name # Variable name of the constant.
+ : value + # Value of the constant.
+ : type ? # Optional type of value.
+ )
+ {
+ switch $(type)
+ {
+ case path :
+ local r ;
+ for local v in $(value)
+ {
+ local l = $(self.location) ;
+ if ! $(l)
+ {
+ # Project corresponding to config files do not have
+ # 'location' attribute, but do have source location.
+ # It might be more reasonable to make every project have
+ # a location and use some other approach to prevent buildable
+ # targets in config files, but that's for later.
+ l = [ get source-location ] ;
+ }
+ v = [ path.root [ path.make $(v) ] $(l) ] ;
+ # Now make the value absolute path.
+ v = [ path.root $(v) [ path.pwd ] ] ;
+ # Constants should be in platform-native form.
+ v = [ path.native $(v) ] ;
+ r += $(v) ;
+ }
+ value = $(r) ;
+ }
+ if ! $(name) in $(self.constants)
+ {
+ self.constants += $(name) ;
+ }
+ self.constant.$(name) = $(value) ;
+ # Inject the constant in the scope of the Jamroot module.
+ modules.poke $(self.project-module) : $(name) : $(value) ;
+ }
+
+ rule inherit ( parent )
+ {
+ for local c in [ modules.peek $(parent) : self.constants ]
+ {
+ # No need to pass the type. Path constants were converted to
+ # absolute paths already by parent.
+ add-constant $(c)
+ : [ modules.peek $(parent) : self.constant.$(c) ] ;
+ }
+
+ # Import rules from parent.
+ local this-module = [ project-module ] ;
+ local parent-module = [ $(parent).project-module ] ;
+ # Do not import rules coming from 'project-rules' as they must be
+ # imported localized.
+ local user-rules = [ set.difference
+ [ RULENAMES $(parent-module) ] :
+ [ RULENAMES project-rules ] ] ;
+ IMPORT $(parent-module) : $(user-rules) : $(this-module) : $(user-rules) ;
+ EXPORT $(this-module) : $(user-rules) ;
+ }
+}
+
+
+# Helper rules to detect cycles in main target references.
+#
+local rule start-building ( main-target-instance )
+{
+ if $(main-target-instance) in $(.targets-being-built)
+ {
+ local names ;
+ for local t in $(.targets-being-built) $(main-target-instance)
+ {
+ names += [ $(t).full-name ] ;
+ }
+
+ errors.error "Recursion in main target references"
+ : "the following target are being built currently:"
+ : $(names) ;
+ }
+ .targets-being-built += $(main-target-instance) ;
+}
+
+
+local rule end-building ( main-target-instance )
+{
+ .targets-being-built = $(.targets-being-built[1--2]) ;
+}
+
+
+# A named top-level target in Jamfile.
+#
+class main-target : abstract-target
+{
+ import assert ;
+ import errors ;
+ import feature ;
+ import print ;
+ import property-set ;
+ import sequence ;
+ import targets : start-building end-building ;
+
+ rule __init__ ( name : project )
+ {
+ abstract-target.__init__ $(name) : $(project) ;
+ }
+
+ # Add a new alternative for this target
+ rule add-alternative ( target )
+ {
+ local d = [ $(target).default-build ] ;
+ if $(self.alternatives) && ( $(self.default-build) != $(d) )
+ {
+ errors.error "default build must be identical in all alternatives"
+ : "main target is" [ full-name ]
+ : "with" [ $(d).raw ]
+ : "differing from previous default build" [ $(self.default-build).raw ] ;
+ }
+ else
+ {
+ self.default-build = $(d) ;
+ }
+ self.alternatives += $(target) ;
+ }
+
+ # Returns the best viable alternative for this property-set. See the
+ # documentation for selection rules.
+ #
+ local rule select-alternatives ( property-set debug ? )
+ {
+ # When selecting alternatives we have to consider defaults, for example:
+ # lib l : l.cpp : <variant>debug ;
+ # lib l : l_opt.cpp : <variant>release ;
+ # won't work unless we add default value <variant>debug.
+ property-set = [ $(p).add-defaults ] ;
+
+ # The algorithm: we keep the current best viable alternative. When we've
+ # got a new best viable alternative, we compare it with the current one.
+
+ local best ;
+ local best-properties ;
+
+ if $(self.alternatives[2-])
+ {
+ local bad ;
+ local worklist = $(self.alternatives) ;
+ while $(worklist) && ! $(bad)
+ {
+ local v = $(worklist[1]) ;
+ local properties = [ $(v).match $(property-set) $(debug) ] ;
+
+ if $(properties) != no-match
+ {
+ if ! $(best)
+ {
+ best = $(v) ;
+ best-properties = $(properties) ;
+ }
+ else
+ {
+ if $(properties) = $(best-properties)
+ {
+ bad = true ;
+ }
+ else if $(properties) in $(best-properties)
+ {
+ # Do nothing, this alternative is worse
+ }
+ else if $(best-properties) in $(properties)
+ {
+ best = $(v) ;
+ best-properties = $(properties) ;
+ }
+ else
+ {
+ bad = true ;
+ }
+ }
+ }
+ worklist = $(worklist[2-]) ;
+ }
+ if ! $(bad)
+ {
+ return $(best) ;
+ }
+ }
+ else
+ {
+ return $(self.alternatives) ;
+ }
+ }
+
+ rule apply-default-build ( property-set )
+ {
+ return [ targets.apply-default-build $(property-set)
+ : $(self.default-build) ] ;
+ }
+
+ # Select an alternative for this main target, by finding all alternatives
+ # which requirements are satisfied by 'properties' and picking the one with
+ # the longest requirements set. Returns the result of calling 'generate' on
+ # that alternative.
+ #
+ rule generate ( property-set )
+ {
+ start-building $(__name__) ;
+
+ # We want composite properties in build request act as if all the
+ # properties it expands too are explicitly specified.
+ property-set = [ $(property-set).expand ] ;
+
+ local all-property-sets = [ apply-default-build $(property-set) ] ;
+ local usage-requirements = [ property-set.empty ] ;
+ local result ;
+ for local p in $(all-property-sets)
+ {
+ local r = [ generate-really $(p) ] ;
+ if $(r)
+ {
+ usage-requirements = [ $(usage-requirements).add $(r[1]) ] ;
+ result += $(r[2-]) ;
+ }
+ }
+ end-building $(__name__) ;
+ return $(usage-requirements) [ sequence.unique $(result) ] ;
+ }
+
+ # Generates the main target with the given property set and returns a list
+ # which first element is property-set object containing usage-requirements
+ # of generated target and with generated virtual target in other elements.
+ # It is possible that no targets are generated.
+ #
+ local rule generate-really ( property-set )
+ {
+ local best-alternatives = [ select-alternatives $(property-set) ] ;
+ if ! $(best-alternatives)
+ {
+ ECHO "error: No best alternative for" [ full-name ] ;
+ select-alternatives $(property-set) debug ;
+ return [ property-set.empty ] ;
+ }
+ else
+ {
+ # Now return virtual targets for the only alternative.
+ return [ $(best-alternatives).generate $(property-set) ] ;
+ }
+ }
+
+ rule rename ( new-name )
+ {
+ abstract-target.rename $(new-name) ;
+ for local a in $(self.alternatives)
+ {
+ $(a).rename $(new-name) ;
+ }
+ }
+}
+
+
+# Abstract target refering to a source file. This is an artificial entity
+# allowing sources to a target to be represented using a list of abstract target
+# instances.
+#
+class file-reference : abstract-target
+{
+ import virtual-target ;
+ import property-set ;
+ import path ;
+
+ rule __init__ ( file : project )
+ {
+ abstract-target.__init__ $(file) : $(project) ;
+ }
+
+ rule generate ( properties )
+ {
+ return [ property-set.empty ] [ virtual-target.from-file $(self.name) :
+ [ location ] : $(self.project) ] ;
+ }
+
+ # Returns true if the referred file really exists.
+ rule exists ( )
+ {
+ location ;
+ return $(self.file-path) ;
+ }
+
+ # Returns the location of target. Needed by 'testing.jam'.
+ rule location ( )
+ {
+ if ! $(self.file-location)
+ {
+ local source-location = [ $(self.project).get source-location ] ;
+ for local src-dir in $(source-location)
+ {
+ if ! $(self.file-location)
+ {
+ local location = [ path.root $(self.name) $(src-dir) ] ;
+ if [ CHECK_IF_FILE [ path.native $(location) ] ]
+ {
+ self.file-location = $(src-dir) ;
+ self.file-path = $(location) ;
+ }
+ }
+ }
+ }
+ return $(self.file-location) ;
+ }
+}
+
+
+# Given a target-reference, made in context of 'project', returns the
+# abstract-target instance that is referred to, as well as properties explicitly
+# specified for this reference.
+#
+rule resolve-reference ( target-reference : project )
+{
+ # Separate target name from properties override.
+ local split = [ MATCH "^([^<]*)(/(<.*))?$" : $(target-reference) ] ;
+ local id = $(split[1]) ;
+ local sproperties = ;
+ if $(split[3])
+ {
+ sproperties = [ property.make [ feature.split $(split[3]) ] ] ;
+ sproperties = [ feature.expand-composites $(sproperties) ] ;
+ }
+
+ # Find the target.
+ local target = [ $(project).find $(id) ] ;
+
+ return $(target) [ property-set.create $(sproperties) ] ;
+}
+
+
+# Attempts to generate the target given by target reference, which can refer
+# both to a main target or to a file. Returns a list consisting of
+# - usage requirements
+# - generated virtual targets, if any
+#
+rule generate-from-reference (
+ target-reference # Target reference.
+ : project # Project where the reference is made.
+ : property-set # Properties of the main target that makes the reference.
+)
+{
+ local r = [ resolve-reference $(target-reference) : $(project) ] ;
+ local target = $(r[1]) ;
+ local sproperties = $(r[2]) ;
+
+ # Take properties which should be propagated and refine them with
+ # source-specific requirements.
+ local propagated = [ $(property-set).propagated ] ;
+ local rproperties = [ $(propagated).refine $(sproperties) ] ;
+ if $(rproperties[1]) = "@error"
+ {
+ errors.error
+ "When building" [ full-name ] " with properties " $(properties) :
+ "Invalid properties specified for " $(source) ":"
+ $(rproperties[2-]) ;
+ }
+ return [ $(target).generate $(rproperties) ] ;
+}
+
+rule apply-default-build ( property-set : default-build )
+{
+ # 1. First, see what properties from default-build are already present
+ # in property-set.
+
+ local raw = [ $(property-set).raw ] ;
+ local specified-features = $(raw:G) ;
+
+ local defaults-to-apply ;
+ for local d in [ $(default-build).raw ]
+ {
+ if ! $(d:G) in $(specified-features)
+ {
+ defaults-to-apply += $(d) ;
+ }
+ }
+
+ # 2. If there are any defaults to be applied, form a new build request.
+ # Pass it through to 'expand-no-defaults' since default-build might
+ # contain "release debug" resulting in two property-sets.
+ local result ;
+ if $(defaults-to-apply)
+ {
+ properties = [
+ build-request.expand-no-defaults
+
+ # We have to compress subproperties here to prevent property
+ # lists like:
+ #
+ # <toolset>msvc <toolset-msvc:version>7.1 <threading>multi
+ #
+ # from being expanded into:
+ #
+ # <toolset-msvc:version>7.1/<threading>multi
+ # <toolset>msvc/<toolset-msvc:version>7.1/<threading>multi
+ #
+ # due to a cross-product property combination. That may be an
+ # indication that build-request.expand-no-defaults is the wrong
+ # rule to use here.
+ [ feature.compress-subproperties $(raw) ]
+ $(defaults-to-apply)
+ ] ;
+
+ if $(properties)
+ {
+ for local p in $(properties)
+ {
+ result += [ property-set.create
+ [ feature.expand [ feature.split $(p) ] ] ] ;
+ }
+ }
+ else
+ {
+ result = [ property-set.empty ] ;
+ }
+ }
+ else
+ {
+ result = $(property-set) ;
+ }
+ return $(result) ;
+}
+
+
+# Given a build request and requirements, return properties common to dependency
+# build request and target requirements.
+#
+# TODO: Document exactly what 'common properties' are, whether they should
+# include default property values, whether they should contain any conditional
+# properties or should those be already processed, etc. See whether there are
+# any differences between use cases with empty and non-empty build-request as
+# well as with requirements containing and those not containing any non-free
+# features.
+#
+rule common-properties ( build-request requirements )
+{
+ # For optimization, we add free requirements directly, without using a
+ # complex algorithm. This gives the complex algorithm a better chance of
+ # caching results.
+ local free = [ $(requirements).free ] ;
+ local non-free = [ property-set.create [ $(requirements).base ]
+ [ $(requirements).incidental ] ] ;
+
+ local key = .rp.$(build-request)-$(non-free) ;
+ if ! $($(key))
+ {
+ $(key) = [ common-properties2 $(build-request) $(non-free) ] ;
+ }
+ result = [ $($(key)).add-raw $(free) ] ;
+}
+
+
+# Given a 'context' -- a set of already present properties, and 'requirements',
+# decide which extra properties should be applied to 'context'. For conditional
+# requirements, this means evaluating the condition. For indirect conditional
+# requirements, this means calling a rule. Ordinary requirements are always
+# applied.
+#
+# Handles the situation where evaluating one conditional requirement affects
+# conditions of another conditional requirements, such as:
+# <toolset>gcc:<variant>release <variant>release:<define>RELEASE
+#
+# If 'what' is 'refined' returns context refined with new requirements. If
+# 'what' is 'added' returns just the requirements to be applied.
+#
+rule evaluate-requirements ( requirements : context : what )
+{
+ # Apply non-conditional requirements. It is possible that further
+ # conditional requirement change a value set by non-conditional
+ # requirements. For example:
+ #
+ # exe a : a.cpp : <threading>single <toolset>foo:<threading>multi ;
+ #
+ # I am not sure if this should be an error, or not, especially given that
+ #
+ # <threading>single
+ #
+ # might come from project's requirements.
+
+ local unconditional = [ feature.expand [ $(requirements).non-conditional ] ] ;
+
+ local raw = [ $(context).raw ] ;
+ raw = [ property.refine $(raw) : $(unconditional) ] ;
+
+ # We have collected properties that surely must be present in common
+ # properties. We now try to figure out what other properties should be added
+ # in order to satisfy rules (4)-(6) from the docs.
+
+ local conditionals = [ $(requirements).conditional ] ;
+ # The 'count' variable has one element for each conditional feature and for
+ # each occurrence of '<indirect-conditional>' feature. It is used as a loop
+ # counter: for each iteration of the loop before we remove one element and
+ # the property set should stabilize before we are done. It is assumed that
+ # #conditionals iterations should be enough for properties to propagate
+ # along conditions in any direction.
+ local count = $(conditionals)
+ [ $(requirements).get <conditional> ]
+ and-once-more ;
+
+ local added-requirements ;
+
+ local current = $(raw) ;
+
+ # It is assumed that ordinary conditional requirements can not add
+ # <conditional> properties (a.k.a. indirect conditional properties), and
+ # that rules referred to by <conditional> properties can not add new
+ # <conditional> properties. So the list of indirect conditionals does not
+ # change.
+ local indirect = [ $(requirements).get <conditional> ] ;
+ indirect = [ MATCH ^@(.*) : $(indirect) ] ;
+
+ local ok ;
+ while $(count)
+ {
+ # Evaluate conditionals in context of current properties.
+ local e = [ property.evaluate-conditionals-in-context $(conditionals)
+ : $(current) ] ;
+
+ # Evaluate indirect conditionals.
+ for local i in $(indirect)
+ {
+ e += [ indirect.call $(i) $(current) ] ;
+ }
+
+ if $(e) = $(added-requirements)
+ {
+ # If we got the same result, we have found the final properties.
+ count = ;
+ ok = true ;
+ }
+ else
+ {
+ # Oops, conditional evaluation results have changed. Also 'current'
+ # contains leftovers from a previous evaluation. Recompute 'current'
+ # using initial properties and conditional requirements.
+ added-requirements = $(e) ;
+ current = [ property.refine $(raw) : [ feature.expand $(e) ] ] ;
+ }
+ count = $(count[2-]) ;
+ }
+ if ! $(ok)
+ {
+ errors.error "Can not evaluate conditional properties " $(conditionals) ;
+ }
+
+ if $(what) = added
+ {
+ return [ property-set.create $(unconditional) $(added-requirements) ] ;
+ }
+ else if $(what) = refined
+ {
+ return [ property-set.create $(current) ] ;
+ }
+ else
+ {
+ errors.error "Invalid value of the 'what' parameter." ;
+ }
+}
+
+
+rule common-properties2 ( build-request requirements )
+{
+ # This guarantees that default properties are present in the result, unless
+ # they are overriden by some requirement. FIXME: There is possibility that
+ # we have added <foo>bar, which is composite and expands to <foo2>bar2, but
+ # default value of <foo2> is not bar2, in which case it is not clear what to
+ # do.
+ #
+ build-request = [ $(build-request).add-defaults ] ;
+ # Features added by 'add-default' can be composite and expand to features
+ # without default values -- so they are not added yet. It could be clearer/
+ # /faster to expand only newly added properties but that is not critical.
+ build-request = [ $(build-request).expand ] ;
+
+ return [ evaluate-requirements $(requirements) : $(build-request) :
+ refined ] ;
+}
+
+rule push-target ( target )
+{
+ .targets = $(target) $(.targets) ;
+}
+
+rule pop-target ( )
+{
+ .targets = $(.targets[2-]) ;
+}
+
+# Return the metatarget that is currently being generated.
+rule current ( )
+{
+ return $(.targets[1]) ;
+}
+
+
+# Implements the most standard way of constructing main target alternative from
+# sources. Allows sources to be either file or other main target and handles
+# generation of those dependency targets.
+#
+class basic-target : abstract-target
+{
+ import build-request ;
+ import build-system ;
+ import "class" : new ;
+ import errors ;
+ import feature ;
+ import property ;
+ import property-set ;
+ import sequence ;
+ import set ;
+ import targets ;
+ import virtual-target ;
+
+ rule __init__ ( name : project : sources * : requirements *
+ : default-build * : usage-requirements * )
+ {
+ abstract-target.__init__ $(name) : $(project) ;
+
+ self.sources = $(sources) ;
+ if ! $(requirements) {
+ requirements = [ property-set.empty ] ;
+ }
+ self.requirements = $(requirements) ;
+ if ! $(default-build)
+ {
+ default-build = [ property-set.empty ] ;
+ }
+ self.default-build = $(default-build) ;
+ if ! $(usage-requirements)
+ {
+ usage-requirements = [ property-set.empty ] ;
+ }
+ self.usage-requirements = $(usage-requirements) ;
+
+ if $(sources:G)
+ {
+ errors.user-error properties found in the 'sources' parameter for
+ [ full-name ] ;
+ }
+ }
+
+ rule always ( )
+ {
+ self.always = 1 ;
+ }
+
+ # Returns the list of abstract-targets which are used as sources. The extra
+ # properties specified for sources are not represented. The only user for
+ # this rule at the moment is the "--dump-tests" feature of the test system.
+ #
+ rule sources ( )
+ {
+ if ! $(self.source-targets)
+ {
+ for local s in $(self.sources)
+ {
+ self.source-targets +=
+ [ targets.resolve-reference $(s) : $(self.project) ] ;
+ }
+ }
+ return $(self.source-targets) ;
+ }
+
+ rule requirements ( )
+ {
+ return $(self.requirements) ;
+ }
+
+ rule default-build ( )
+ {
+ return $(self.default-build) ;
+ }
+
+ # Returns the alternative condition for this alternative, if the condition
+ # is satisfied by 'property-set'.
+ #
+ rule match ( property-set debug ? )
+ {
+ # The condition is composed of all base non-conditional properties. It
+ # is not clear if we should expand 'self.requirements' or not. For one
+ # thing, it would be nice to be able to put
+ # <toolset>msvc-6.0
+ # in requirements. On the other hand, if we have <variant>release as a
+ # condition it does not make sense to require <optimization>full to be
+ # in the build request just to select this variant.
+ local bcondition = [ $(self.requirements).base ] ;
+ local ccondition = [ $(self.requirements).conditional ] ;
+ local condition = [ set.difference $(bcondition) : $(ccondition) ] ;
+ if $(debug)
+ {
+ ECHO " next alternative: required properties:" $(condition:E=(empty)) ;
+ }
+
+ if $(condition) in [ $(property-set).raw ]
+ {
+ if $(debug)
+ {
+ ECHO " matched" ;
+ }
+ return $(condition) ;
+ }
+ else
+ {
+ if $(debug)
+ {
+ ECHO " not matched" ;
+ }
+ return no-match ;
+ }
+ }
+
+ # Takes a target reference, which might be either target id or a dependency
+ # property, and generates that target using 'property-set' as build request.
+ #
+ # The results are added to the variable called 'result-var'. Usage
+ # requirements are added to the variable called 'usage-requirements-var'.
+ #
+ rule generate-dependencies ( dependencies * : property-set
+ : result-var usage-requirements-var )
+ {
+ for local dependency in $(dependencies)
+ {
+ local grist = $(dependency:G) ;
+ local id = $(dependency:G=) ;
+
+ local result = [ targets.generate-from-reference $(id) :
+ $(self.project) : $(property-set) ] ;
+
+ $(result-var) += $(result[2-]:G=$(grist)) ;
+ $(usage-requirements-var) += [ $(result[1]).raw ] ;
+ }
+ }
+
+ # Determines final build properties, generates sources, and calls
+ # 'construct'. This method should not be overridden.
+ #
+ rule generate ( property-set )
+ {
+ if [ modules.peek : .debug-building ]
+ {
+ ECHO ;
+ local fn = [ full-name ] ;
+ ECHO [ targets.indent ] "Building target '$(fn)'" ;
+ targets.increase-indent ;
+ ECHO [ targets.indent ] "Build request: " $(property-set) [ $(property-set).raw ] ;
+ local cf = [ build-system.command-line-free-features ] ;
+ ECHO [ targets.indent ] "Command line free features: " [ $(cf).raw ] ;
+ ECHO [ targets.indent ] "Target requirements: " [ $(self.requirements).raw ] ;
+ }
+ targets.push-target $(__name__) ;
+
+ if ! $(self.generated.$(property-set))
+ {
+ # Apply free features from the command line. If user said
+ # define=FOO
+ # he most likely wants this define to be set for all compiles.
+ property-set = [ $(property-set).refine
+ [ build-system.command-line-free-features ] ] ;
+ local rproperties = [ targets.common-properties $(property-set)
+ $(self.requirements) ] ;
+
+ if [ modules.peek : .debug-building ]
+ {
+ ECHO ;
+ ECHO [ targets.indent ] "Common properties: " [ $(rproperties).raw ] ;
+ }
+
+ if ( $(rproperties[1]) != "@error" ) && ( [ $(rproperties).get
+ <build> ] != no )
+ {
+ local source-targets ;
+ local properties = [ $(rproperties).non-dependency ] ;
+ local usage-requirements ;
+
+ generate-dependencies [ $(rproperties).dependency ] :
+ $(rproperties) : properties usage-requirements ;
+
+ generate-dependencies $(self.sources) : $(rproperties) :
+ source-targets usage-requirements ;
+
+ if [ modules.peek : .debug-building ]
+ {
+ ECHO ;
+ ECHO [ targets.indent ] "Usage requirements for"
+ $(self.name)": " $(usage-requirements) ;
+ }
+
+ rproperties = [ property-set.create $(properties)
+ $(usage-requirements) ] ;
+ usage-requirements = [ property-set.create $(usage-requirements) ] ;
+
+ if [ modules.peek : .debug-building ]
+ {
+ ECHO [ targets.indent ] "Build properties: "
+ [ $(rproperties).raw ] ;
+ }
+
+ local extra = [ $(rproperties).get <source> ] ;
+ source-targets += $(extra:G=) ;
+ # We might get duplicate sources, for example if we link to two
+ # libraries having the same <library> usage requirement.
+ # Use stable sort, since for some targets the order is
+ # important. E.g. RUN_PY target need python source to come
+ # first.
+ source-targets = [ sequence.unique $(source-targets) : stable ] ;
+
+ local result = [ construct $(self.name) : $(source-targets) :
+ $(rproperties) ] ;
+
+ if $(result)
+ {
+ local gur = $(result[1]) ;
+ result = $(result[2-]) ;
+
+ if $(self.always)
+ {
+ for local t in $(result)
+ {
+ $(t).always ;
+ }
+ }
+
+ local s = [ create-subvariant $(result)
+ : [ virtual-target.recent-targets ]
+ : $(property-set) : $(source-targets)
+ : $(rproperties) : $(usage-requirements) ] ;
+ virtual-target.clear-recent-targets ;
+
+ local ur = [ compute-usage-requirements $(s) ] ;
+ ur = [ $(ur).add $(gur) ] ;
+ $(s).set-usage-requirements $(ur) ;
+ if [ modules.peek : .debug-building ]
+ {
+ ECHO [ targets.indent ] "Usage requirements from"
+ $(self.name)": " [ $(ur).raw ] ;
+ }
+
+ self.generated.$(property-set) = $(ur) $(result) ;
+ }
+ }
+ else
+ {
+ if $(rproperties[1]) = "@error"
+ {
+ ECHO [ targets.indent ] "Skipping build of:" [ full-name ]
+ "cannot compute common properties" ;
+ }
+ else if [ $(rproperties).get <build> ] = no
+ {
+ # If we just see <build>no, we cannot produce any reasonable
+ # diagnostics. The code that adds this property is expected
+ # to explain why a target is not built, for example using
+ # the configure.log-component-configuration function.
+ }
+ else
+ {
+ ECHO [ targets.indent ] "Skipping build of: " [ full-name ]
+ " unknown reason" ;
+ }
+
+ # We are here either because there has been an error computing
+ # properties or there is <build>no in properties. In the latter
+ # case we do not want any diagnostic. In the former case, we
+ # need diagnostics. FIXME
+
+ # If this target fails to build, add <build>no to properties to
+ # cause any parent target to fail to build. Except that it
+ # - does not work now, since we check for <build>no only in
+ # common properties, but not in properties that came from
+ # dependencies
+ # - it is not clear if that is a good idea anyway. The alias
+ # target, for example, should not fail to build if a
+ # dependency fails.
+ self.generated.$(property-set) = [ property-set.create <build>no ] ;
+ }
+ }
+ else
+ {
+ if [ modules.peek : .debug-building ]
+ {
+ ECHO [ targets.indent ] "Already built" ;
+ local ur = $(self.generated.$(property-set)) ;
+ ur = $(ur[0]) ;
+ targets.increase-indent ;
+ ECHO [ targets.indent ] "Usage requirements from"
+ $(self.name)": " [ $(ur).raw ] ;
+ targets.decrease-indent ;
+ }
+ }
+
+ targets.pop-target ;
+ targets.decrease-indent ;
+ return $(self.generated.$(property-set)) ;
+ }
+
+ # Given the set of generated targets, and refined build properties,
+ # determines and sets appropriate usage requirements on those targets.
+ #
+ rule compute-usage-requirements ( subvariant )
+ {
+ local rproperties = [ $(subvariant).build-properties ] ;
+ xusage-requirements = [ targets.evaluate-requirements
+ $(self.usage-requirements) : $(rproperties) : added ] ;
+
+ # We generate all dependency properties and add them, as well as their
+ # usage requirements, to the result.
+ local extra ;
+ generate-dependencies [ $(xusage-requirements).dependency ] :
+ $(rproperties) : extra extra ;
+
+ local result = [ property-set.create
+ [ $(xusage-requirements).non-dependency ] $(extra) ] ;
+
+ # Propagate usage requirements we got from sources, except for the
+ # <pch-header> and <pch-file> features.
+ #
+ # That feature specifies which pch file to use, and should apply only to
+ # direct dependents. Consider:
+ #
+ # pch pch1 : ...
+ # lib lib1 : ..... pch1 ;
+ # pch pch2 :
+ # lib lib2 : pch2 lib1 ;
+ #
+ # Here, lib2 should not get <pch-header> property from pch1.
+ #
+ # Essentially, when those two features are in usage requirements, they
+ # are propagated only to direct dependents. We might need a more general
+ # mechanism, but for now, only those two features are special.
+ #
+ # TODO - Actually there are more possible candidates like for instance
+ # when listing static library X as a source for another static library.
+ # Then static library X will be added as a <source> property to the
+ # second library's usage requirements but those requirements should last
+ # only up to the first executable or shared library that actually links
+ # to it.
+ local raw = [ $(subvariant).sources-usage-requirements ] ;
+ raw = [ $(raw).raw ] ;
+ raw = [ property.change $(raw) : <pch-header> ] ;
+ raw = [ property.change $(raw) : <pch-file> ] ;
+ return [ $(result).add [ property-set.create $(raw) ] ] ;
+ }
+
+ # Creates new subvariant instances for 'targets'.
+ # 'root-targets' - virtual targets to be returned to dependants
+ # 'all-targets' - virtual targets created while building this main target
+ # 'build-request' - property-set instance with requested build properties
+ #
+ local rule create-subvariant ( root-targets * : all-targets * :
+ build-request : sources * : rproperties : usage-requirements )
+ {
+ for local e in $(root-targets)
+ {
+ $(e).root true ;
+ }
+
+ # Process all virtual targets that will be created if this main target
+ # is created.
+ local s = [ new subvariant $(__name__) : $(build-request) : $(sources) :
+ $(rproperties) : $(usage-requirements) : $(all-targets) ] ;
+ for local v in $(all-targets)
+ {
+ if ! [ $(v).creating-subvariant ]
+ {
+ $(v).creating-subvariant $(s) ;
+ }
+ }
+ return $(s) ;
+ }
+
+ # Constructs virtual targets for this abstract target and the dependency
+ # graph. Returns a usage-requirements property-set and a list of virtual
+ # targets. Should be overriden in derived classes.
+ #
+ rule construct ( name : source-targets * : properties * )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+}
+
+
+class typed-target : basic-target
+{
+ import generators ;
+
+ rule __init__ ( name : project : type : sources * : requirements * :
+ default-build * : usage-requirements * )
+ {
+ basic-target.__init__ $(name) : $(project) : $(sources) :
+ $(requirements) : $(default-build) : $(usage-requirements) ;
+
+ self.type = $(type) ;
+ }
+
+ rule type ( )
+ {
+ return $(self.type) ;
+ }
+
+ rule construct ( name : source-targets * : property-set )
+ {
+ local r = [ generators.construct $(self.project) $(name:S=) : $(self.type)
+ : [ property-set.create [ $(property-set).raw ]
+ <main-target-type>$(self.type) ]
+ : $(source-targets) : true ] ;
+ if ! $(r)
+ {
+ ECHO "warn: Unable to construct" [ full-name ] ;
+
+ # Are there any top-level generators for this type/property set.
+ if ! [ generators.find-viable-generators $(self.type)
+ : $(property-set) ]
+ {
+ ECHO "error: no generators were found for type '$(self.type)'" ;
+ ECHO "error: and the requested properties" ;
+ ECHO "error: make sure you've configured the needed tools" ;
+ ECHO "See http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" ;
+ ECHO "To debug this problem, try the --debug-generators option." ;
+ EXIT ;
+ }
+ }
+ return $(r) ;
+ }
+}
+
+
+# Return the list of sources to use, if main target rule is invoked with
+# 'sources'. If there are any objects in 'sources', they are treated as main
+# target instances, and the name of such targets are adjusted to be
+# '<name_of_this_target>__<name_of_source_target>'. Such renaming is disabled if
+# a non-empty value is passed as the 'no-renaming' parameter.
+#
+rule main-target-sources ( sources * : main-target-name : no-renaming ? )
+{
+ local result ;
+ for local t in $(sources)
+ {
+ if [ class.is-instance $(t) ]
+ {
+ local name = [ $(t).name ] ;
+ if ! $(no-renaming)
+ {
+ name = $(main-target-name)__$(name) ;
+ $(t).rename $(name) ;
+ }
+ # Inline targets are not built by default.
+ local p = [ $(t).project ] ;
+ $(p).mark-target-as-explicit $(name) ;
+ result += $(name) ;
+ }
+ else
+ {
+ result += $(t) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Returns the requirements to use when declaring a main target, obtained by
+# translating all specified property paths and refining project requirements
+# with the ones specified for the target.
+#
+rule main-target-requirements (
+ specification * # Properties explicitly specified for the main target.
+ : project # Project where the main target is to be declared.
+)
+{
+ specification += [ toolset.requirements ] ;
+
+ local requirements = [ property-set.refine-from-user-input
+ [ $(project).get requirements ] : $(specification) :
+ [ $(project).project-module ] : [ $(project).get location ] ] ;
+ if $(requirements[1]) = "@error"
+ {
+ errors.error "Conflicting requirements for target:" $(requirements) ;
+ }
+ return $(requirements) ;
+}
+
+
+# Returns the usage requirements to use when declaring a main target, which are
+# obtained by translating all specified property paths and adding project's
+# usage requirements.
+#
+rule main-target-usage-requirements (
+ specification * # Use-properties explicitly specified for a main target.
+ : project # Project where the main target is to be declared.
+)
+{
+ local project-usage-requirements = [ $(project).get usage-requirements ] ;
+
+ # We do not use 'refine-from-user-input' because:
+ # - I am not sure if removing parent's usage requirements makes sense
+ # - refining usage requirements is not needed, since usage requirements are
+ # always free.
+ local usage-requirements = [ property-set.create-from-user-input
+ $(specification)
+ : [ $(project).project-module ] [ $(project).get location ] ] ;
+
+ return [ $(project-usage-requirements).add $(usage-requirements) ] ;
+}
+
+
+# Return the default build value to use when declaring a main target, which is
+# obtained by using the specified value if not empty and parent's default build
+# attribute otherwise.
+#
+rule main-target-default-build (
+ specification * # Default build explicitly specified for a main target.
+ : project # Project where the main target is to be declared.
+)
+{
+ local result ;
+ if $(specification)
+ {
+ result = $(specification) ;
+ }
+ else
+ {
+ result = [ $(project).get default-build ] ;
+ }
+ return [ property-set.create-with-validation $(result) ] ;
+}
+
+
+# Registers the specified target as a main target alternative and returns it.
+#
+rule main-target-alternative ( target )
+{
+ local ptarget = [ $(target).project ] ;
+ $(ptarget).add-alternative $(target) ;
+ return $(target) ;
+}
+
+# Creates a new metargets with the specified properties, using 'klass' as
+# the class. The 'name', 'sources',
+# 'requirements', 'default-build' and 'usage-requirements' are assumed to be in
+# the form specified by the user in Jamfile corresponding to 'project'.
+#
+rule create-metatarget ( klass : project : name : sources * : requirements * :
+ default-build * : usage-requirements * )
+{
+ return [
+ targets.main-target-alternative
+ [ new $(klass) $(name) : $(project)
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
+ ] ] ;
+}
+
+# Creates a typed-target with the specified properties. The 'name', 'sources',
+# 'requirements', 'default-build' and 'usage-requirements' are assumed to be in
+# the form specified by the user in Jamfile corresponding to 'project'.
+#
+rule create-typed-target ( type : project : name : sources * : requirements * :
+ default-build * : usage-requirements * )
+{
+ return [
+ targets.main-target-alternative
+ [ new typed-target $(name) : $(project) : $(type)
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
+ ] ] ;
+}
diff --git a/tools/build/v2/build/targets.py b/tools/build/v2/build/targets.py
new file mode 100644
index 0000000000..a35612cea0
--- /dev/null
+++ b/tools/build/v2/build/targets.py
@@ -0,0 +1,1401 @@
+# Status: ported.
+# Base revision: 64488
+
+# Copyright Vladimir Prus 2002-2007.
+# Copyright Rene Rivera 2006.
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Supports 'abstract' targets, which are targets explicitly defined in Jamfile.
+#
+# Abstract targets are represented by classes derived from 'AbstractTarget' class.
+# The first abstract target is 'project_target', which is created for each
+# Jamfile, and can be obtained by the 'target' rule in the Jamfile's module.
+# (see project.jam).
+#
+# Project targets keep a list of 'MainTarget' instances.
+# A main target is what the user explicitly defines in a Jamfile. It is
+# possible to have several definitions for a main target, for example to have
+# different lists of sources for different platforms. So, main targets
+# keep a list of alternatives.
+#
+# Each alternative is an instance of 'AbstractTarget'. When a main target
+# subvariant is defined by some rule, that rule will decide what class to
+# use, create an instance of that class and add it to the list of alternatives
+# for the main target.
+#
+# Rules supplied by the build system will use only targets derived
+# from 'BasicTarget' class, which will provide some default behaviour.
+# There will be two classes derived from it, 'make-target', created by the
+# 'make' rule, and 'TypedTarget', created by rules such as 'exe' and 'dll'.
+
+#
+# +------------------------+
+# |AbstractTarget |
+# +========================+
+# |name |
+# |project |
+# | |
+# |generate(properties) = 0|
+# +-----------+------------+
+# |
+# ^
+# / \
+# +-+-+
+# |
+# |
+# +------------------------+------+------------------------------+
+# | | |
+# | | |
+# +----------+-----------+ +------+------+ +------+-------+
+# | project_target | | MainTarget | | BasicTarget |
+# +======================+ 1 * +=============+ alternatives +==============+
+# | generate(properties) |o-----------+ generate |<>------------->| generate |
+# | main-target | +-------------+ | construct = 0|
+# +----------------------+ +--------------+
+# |
+# ^
+# / \
+# +-+-+
+# |
+# |
+# ...--+----------------+------------------+----------------+---+
+# | | | |
+# | | | |
+# ... ---+-----+ +------+-------+ +------+------+ +--------+-----+
+# | | TypedTarget | | make-target | | stage-target |
+# . +==============+ +=============+ +==============+
+# . | construct | | construct | | construct |
+# +--------------+ +-------------+ +--------------+
+
+import re
+import os.path
+import sys
+
+from b2.manager import get_manager
+
+from b2.util.utility import *
+import property, project, virtual_target, property_set, feature, generators, toolset
+from virtual_target import Subvariant
+from b2.exceptions import *
+from b2.util.sequence import unique
+from b2.util import path, bjam_signature
+from b2.build.errors import user_error_checkpoint
+
+import b2.build.build_request as build_request
+
+import b2.util.set
+_re_separate_target_from_properties = re.compile (r'^([^<]*)(/(<.*))?$')
+
+class TargetRegistry:
+
+ def __init__ (self):
+ # All targets that are currently being built.
+ # Only the key is id (target), the value is the actual object.
+ self.targets_being_built_ = {}
+
+ # Current indent for debugging messages
+ self.indent_ = ""
+
+ self.debug_building_ = "--debug-building" in bjam.variable("ARGV")
+
+ self.targets_ = []
+
+ def main_target_alternative (self, target):
+ """ Registers the specified target as a main target alternatives.
+ Returns 'target'.
+ """
+ target.project ().add_alternative (target)
+ return target
+
+ def main_target_sources (self, sources, main_target_name, no_renaming=0):
+ """Return the list of sources to use, if main target rule is invoked
+ with 'sources'. If there are any objects in 'sources', they are treated
+ as main target instances, and the name of such targets are adjusted to
+ be '<name_of_this_target>__<name_of_source_target>'. Such renaming
+ is disabled is non-empty value is passed for 'no-renaming' parameter."""
+ result = []
+
+ for t in sources:
+
+ t = b2.util.jam_to_value_maybe(t)
+
+ if isinstance (t, AbstractTarget):
+ name = t.name ()
+
+ if not no_renaming:
+ name = main_target_name + '__' + name
+ t.rename (name)
+
+ # Inline targets are not built by default.
+ p = t.project()
+ p.mark_targets_as_explicit([name])
+ result.append(name)
+
+ else:
+ result.append (t)
+
+ return result
+
+
+ def main_target_requirements(self, specification, project):
+ """Returns the requirement to use when declaring a main target,
+ which are obtained by
+ - translating all specified property paths, and
+ - refining project requirements with the one specified for the target
+
+ 'specification' are the properties xplicitly specified for a
+ main target
+ 'project' is the project where the main taret is to be declared."""
+
+ specification.extend(toolset.requirements())
+
+ requirements = property_set.refine_from_user_input(
+ project.get("requirements"), specification,
+ project.project_module(), project.get("location"))
+
+ return requirements
+
+ def main_target_usage_requirements (self, specification, project):
+ """ Returns the use requirement to use when declaraing a main target,
+ which are obtained by
+ - translating all specified property paths, and
+ - adding project's usage requirements
+ specification: Use-properties explicitly specified for a main target
+ project: Project where the main target is to be declared
+ """
+ project_usage_requirements = project.get ('usage-requirements')
+
+ # We don't use 'refine-from-user-input' because I'm not sure if:
+ # - removing of parent's usage requirements makes sense
+ # - refining of usage requirements is not needed, since usage requirements
+ # are always free.
+ usage_requirements = property_set.create_from_user_input(
+ specification, project.project_module(), project.get("location"))
+
+ return project_usage_requirements.add (usage_requirements)
+
+ def main_target_default_build (self, specification, project):
+ """ Return the default build value to use when declaring a main target,
+ which is obtained by using specified value if not empty and parent's
+ default build attribute otherwise.
+ specification: Default build explicitly specified for a main target
+ project: Project where the main target is to be declared
+ """
+ if specification:
+ return property_set.create_with_validation(specification)
+ else:
+ return project.get ('default-build')
+
+ def start_building (self, main_target_instance):
+ """ Helper rules to detect cycles in main target references.
+ """
+ if self.targets_being_built_.has_key(id(main_target_instance)):
+ names = []
+ for t in self.targets_being_built_.values() + [main_target_instance]:
+ names.append (t.full_name())
+
+ get_manager().errors()("Recursion in main target references\n")
+
+ self.targets_being_built_[id(main_target_instance)] = main_target_instance
+
+ def end_building (self, main_target_instance):
+ assert (self.targets_being_built_.has_key (id (main_target_instance)))
+ del self.targets_being_built_ [id (main_target_instance)]
+
+ def create_typed_target (self, type, project, name, sources, requirements, default_build, usage_requirements):
+ """ Creates a TypedTarget with the specified properties.
+ The 'name', 'sources', 'requirements', 'default_build' and
+ 'usage_requirements' are assumed to be in the form specified
+ by the user in Jamfile corresponding to 'project'.
+ """
+ return self.main_target_alternative (TypedTarget (name, project, type,
+ self.main_target_sources (sources, name),
+ self.main_target_requirements (requirements, project),
+ self.main_target_default_build (default_build, project),
+ self.main_target_usage_requirements (usage_requirements, project)))
+
+ def increase_indent(self):
+ self.indent_ += " "
+
+ def decrease_indent(self):
+ self.indent_ = self.indent_[0:-4]
+
+ def logging(self):
+ return self.debug_building_
+
+ def log(self, message):
+ if self.debug_building_:
+ print self.indent_ + message
+
+ def push_target(self, target):
+ self.targets_.append(target)
+
+ def pop_target(self):
+ self.targets_ = self.targets_[:-1]
+
+ def current(self):
+ return self.targets_[0]
+
+
+class GenerateResult:
+
+ def __init__ (self, ur=None, targets=None):
+ if not targets:
+ targets = []
+
+ self.__usage_requirements = ur
+ self.__targets = targets
+ assert all(isinstance(t, virtual_target.VirtualTarget) for t in targets)
+
+ if not self.__usage_requirements:
+ self.__usage_requirements = property_set.empty ()
+
+ def usage_requirements (self):
+ return self.__usage_requirements
+
+ def targets (self):
+ return self.__targets
+
+ def extend (self, other):
+ assert (isinstance (other, GenerateResult))
+
+ self.__usage_requirements = self.__usage_requirements.add (other.usage_requirements ())
+ self.__targets.extend (other.targets ())
+
+class AbstractTarget:
+ """ Base class for all abstract targets.
+ """
+ def __init__ (self, name, project, manager = None):
+ """ manager: the Manager object
+ name: name of the target
+ project: the project target to which this one belongs
+ manager:the manager object. If none, uses project.manager ()
+ """
+ assert (isinstance (project, ProjectTarget))
+ # Note: it might seem that we don't need either name or project at all.
+ # However, there are places where we really need it. One example is error
+ # messages which should name problematic targets. Another is setting correct
+ # paths for sources and generated files.
+
+ # Why allow manager to be specified? Because otherwise project target could not derive
+ # from this class.
+ if manager:
+ self.manager_ = manager
+ else:
+ self.manager_ = project.manager ()
+
+ self.name_ = name
+ self.project_ = project
+
+ def manager (self):
+ return self.manager_
+
+ def name (self):
+ """ Returns the name of this target.
+ """
+ return self.name_
+
+ def project (self):
+ """ Returns the project for this target.
+ """
+ return self.project_
+
+ def location (self):
+ """ Return the location where the target was declared.
+ """
+ return self.location_
+
+ def full_name (self):
+ """ Returns a user-readable name for this target.
+ """
+ location = self.project ().get ('location')
+ return location + '/' + self.name_
+
+ def generate (self, property_set):
+ """ Takes a property set. Generates virtual targets for this abstract
+ target, using the specified properties, unless a different value of some
+ feature is required by the target.
+ On success, returns a GenerateResult instance with:
+ - a property_set with the usage requirements to be
+ applied to dependents
+ - a list of produced virtual targets, which may be
+ empty.
+ If 'property_set' is empty, performs default build of this
+ target, in a way specific to derived class.
+ """
+ raise BaseException ("method should be defined in derived classes")
+
+ def rename (self, new_name):
+ self.name_ = new_name
+
+class ProjectTarget (AbstractTarget):
+ """ Project target class (derived from 'AbstractTarget')
+
+ This class these responsibilities:
+ - maintaining a list of main target in this project and
+ building it
+
+ Main targets are constructed in two stages:
+ - When Jamfile is read, a number of calls to 'add_alternative' is made.
+ At that time, alternatives can also be renamed to account for inline
+ targets.
+ - The first time 'main-target' or 'has-main-target' rule is called,
+ all alternatives are enumerated an main targets are created.
+ """
+ def __init__ (self, manager, name, project_module, parent_project, requirements, default_build):
+ AbstractTarget.__init__ (self, name, self, manager)
+
+ self.project_module_ = project_module
+ self.location_ = manager.projects().attribute (project_module, 'location')
+ self.requirements_ = requirements
+ self.default_build_ = default_build
+
+ self.build_dir_ = None
+
+ # A cache of IDs
+ self.ids_cache_ = {}
+
+ # True is main targets have already been built.
+ self.built_main_targets_ = False
+
+ # A list of the registered alternatives for this project.
+ self.alternatives_ = []
+
+ # A map from main target name to the target corresponding
+ # to it.
+ self.main_target_ = {}
+
+ # Targets marked as explicit.
+ self.explicit_targets_ = set()
+
+ # Targets marked as always
+ self.always_targets_ = set()
+
+ # The constants defined for this project.
+ self.constants_ = {}
+
+ # Whether targets for all main target are already created.
+ self.built_main_targets_ = 0
+
+ if parent_project:
+ self.inherit (parent_project)
+
+
+ # TODO: This is needed only by the 'make' rule. Need to find the
+ # way to make 'make' work without this method.
+ def project_module (self):
+ return self.project_module_
+
+ def get (self, attribute):
+ return self.manager().projects().attribute(
+ self.project_module_, attribute)
+
+ def build_dir (self):
+ if not self.build_dir_:
+ self.build_dir_ = self.get ('build-dir')
+ if not self.build_dir_:
+ self.build_dir_ = os.path.join(self.project_.get ('location'), 'bin')
+
+ return self.build_dir_
+
+ def generate (self, ps):
+ """ Generates all possible targets contained in this project.
+ """
+ self.manager_.targets().log(
+ "Building project '%s' with '%s'" % (self.name (), str(ps)))
+ self.manager_.targets().increase_indent ()
+
+ result = GenerateResult ()
+
+ for t in self.targets_to_build ():
+ g = t.generate (ps)
+ result.extend (g)
+
+ self.manager_.targets().decrease_indent ()
+ return result
+
+ def targets_to_build (self):
+ """ Computes and returns a list of AbstractTarget instances which
+ must be built when this project is built.
+ """
+ result = []
+
+ if not self.built_main_targets_:
+ self.build_main_targets ()
+
+ # Collect all main targets here, except for "explicit" ones.
+ for n, t in self.main_target_.iteritems ():
+ if not t.name () in self.explicit_targets_:
+ result.append (t)
+
+ # Collect all projects referenced via "projects-to-build" attribute.
+ self_location = self.get ('location')
+ for pn in self.get ('projects-to-build'):
+ result.append (self.find(pn + "/"))
+
+ return result
+
+ def mark_targets_as_explicit (self, target_names):
+ """Add 'target' to the list of targets in this project
+ that should be build only by explicit request."""
+
+ # Record the name of the target, not instance, since this
+ # rule is called before main target instaces are created.
+ self.explicit_targets_.update(target_names)
+
+ def mark_targets_as_always(self, target_names):
+ self.always_targets_.update(target_names)
+
+ def add_alternative (self, target_instance):
+ """ Add new target alternative.
+ """
+ if self.built_main_targets_:
+ raise IllegalOperation ("add-alternative called when main targets are already created for project '%s'" % self.full_name ())
+
+ self.alternatives_.append (target_instance)
+
+ def main_target (self, name):
+ if not self.built_main_targets_:
+ self.build_main_targets()
+
+ return self.main_target_[name]
+
+ def has_main_target (self, name):
+ """Tells if a main target with the specified name exists."""
+ if not self.built_main_targets_:
+ self.build_main_targets()
+
+ return self.main_target_.has_key(name)
+
+ def create_main_target (self, name):
+ """ Returns a 'MainTarget' class instance corresponding to the 'name'.
+ """
+ if not self.built_main_targets_:
+ self.build_main_targets ()
+
+ return self.main_targets_.get (name, None)
+
+
+ def find_really(self, id):
+ """ Find and return the target with the specified id, treated
+ relative to self.
+ """
+ result = None
+ current_location = self.get ('location')
+
+ __re_split_project_target = re.compile (r'(.*)//(.*)')
+ split = __re_split_project_target.match (id)
+
+ project_part = None
+ target_part = None
+
+ if split:
+ project_part = split.group (1)
+ target_part = split.group (2)
+
+ project_registry = self.project_.manager ().projects ()
+
+ extra_error_message = ''
+ if project_part:
+ # There's explicit project part in id. Looks up the
+ # project and pass the request to it.
+ pm = project_registry.find (project_part, current_location)
+
+ if pm:
+ project_target = project_registry.target (pm)
+ result = project_target.find (target_part, no_error=1)
+
+ else:
+ extra_error_message = "error: could not find project '$(project_part)'"
+
+ else:
+ # Interpret target-name as name of main target
+ # Need to do this before checking for file. Consider this:
+ #
+ # exe test : test.cpp ;
+ # install s : test : <location>. ;
+ #
+ # After first build we'll have target 'test' in Jamfile and file
+ # 'test' on the disk. We need target to override the file.
+
+ result = None
+ if self.has_main_target(id):
+ result = self.main_target(id)
+
+ if not result:
+ result = FileReference (self.manager_, id, self.project_)
+ if not result.exists ():
+ # File actually does not exist.
+ # Reset 'target' so that an error is issued.
+ result = None
+
+
+ if not result:
+ # Interpret id as project-id
+ project_module = project_registry.find (id, current_location)
+ if project_module:
+ result = project_registry.target (project_module)
+
+ return result
+
+ def find (self, id, no_error = False):
+ v = self.ids_cache_.get (id, None)
+
+ if not v:
+ v = self.find_really (id)
+ self.ids_cache_ [id] = v
+
+ if v or no_error:
+ return v
+
+ raise BaseException ("Unable to find file or target named '%s'\nreferred from project at '%s'" % (id, self.get ('location')))
+
+
+ def build_main_targets (self):
+ self.built_main_targets_ = True
+
+ for a in self.alternatives_:
+ name = a.name ()
+ if not self.main_target_.has_key (name):
+ t = MainTarget (name, self.project_)
+ self.main_target_ [name] = t
+
+ if name in self.always_targets_:
+ a.always()
+
+ self.main_target_ [name].add_alternative (a)
+
+ def add_constant(self, name, value, path=0):
+ """Adds a new constant for this project.
+
+ The constant will be available for use in Jamfile
+ module for this project. If 'path' is true,
+ the constant will be interpreted relatively
+ to the location of project.
+ """
+
+ if path:
+ l = self.location_
+ if not l:
+ # Project corresponding to config files do not have
+ # 'location' attribute, but do have source location.
+ # It might be more reasonable to make every project have
+ # a location and use some other approach to prevent buildable
+ # targets in config files, but that's for later.
+ l = get('source-location')
+
+ value = os.path.join(l, value)
+ # Now make the value absolute path
+ value = os.path.join(os.getcwd(), value)
+
+ self.constants_[name] = value
+ bjam.call("set-variable", self.project_module(), name, value)
+
+ def inherit(self, parent_project):
+ for c in parent_project.constants_:
+ # No need to pass the type. Path constants were converted to
+ # absolute paths already by parent.
+ self.add_constant(c, parent_project.constants_[c])
+
+ # Import rules from parent
+ this_module = self.project_module()
+ parent_module = parent_project.project_module()
+
+ rules = bjam.call("RULENAMES", parent_module)
+ if not rules:
+ rules = []
+ user_rules = [x for x in rules
+ if x not in self.manager().projects().project_rules().all_names()]
+ if user_rules:
+ bjam.call("import-rules-from-parent", parent_module, this_module, user_rules)
+
+class MainTarget (AbstractTarget):
+ """ A named top-level target in Jamfile.
+ """
+ def __init__ (self, name, project):
+ AbstractTarget.__init__ (self, name, project)
+ self.alternatives_ = []
+ self.default_build_ = property_set.empty ()
+
+ def add_alternative (self, target):
+ """ Add a new alternative for this target.
+ """
+ d = target.default_build ()
+
+ if self.alternatives_ and self.default_build_ != d:
+ get_manager().errors()("default build must be identical in all alternatives\n"
+ "main target is '%s'\n"
+ "with '%s'\n"
+ "differing from previous default build: '%s'" % (self.full_name (), d.raw (), self.default_build_.raw ()))
+
+ else:
+ self.default_build_ = d
+
+ self.alternatives_.append (target)
+
+ def __select_alternatives (self, property_set, debug):
+ """ Returns the best viable alternative for this property_set
+ See the documentation for selection rules.
+ # TODO: shouldn't this be 'alternative' (singular)?
+ """
+ # When selecting alternatives we have to consider defaults,
+ # for example:
+ # lib l : l.cpp : <variant>debug ;
+ # lib l : l_opt.cpp : <variant>release ;
+ # won't work unless we add default value <variant>debug.
+ property_set = property_set.add_defaults ()
+
+ # The algorithm: we keep the current best viable alternative.
+ # When we've got new best viable alternative, we compare it
+ # with the current one.
+ best = None
+ best_properties = None
+
+ if len (self.alternatives_) == 0:
+ return None
+
+ if len (self.alternatives_) == 1:
+ return self.alternatives_ [0]
+
+ if debug:
+ print "Property set for selection:", property_set
+
+ for v in self.alternatives_:
+ properties = v.match (property_set, debug)
+
+ if properties is not None:
+ if not best:
+ best = v
+ best_properties = properties
+
+ else:
+ if b2.util.set.equal (properties, best_properties):
+ return None
+
+ elif b2.util.set.contains (properties, best_properties):
+ # Do nothing, this alternative is worse
+ pass
+
+ elif b2.util.set.contains (best_properties, properties):
+ best = v
+ best_properties = properties
+
+ else:
+ return None
+
+ return best
+
+ def apply_default_build (self, property_set):
+ return apply_default_build(property_set, self.default_build_)
+
+ def generate (self, ps):
+ """ Select an alternative for this main target, by finding all alternatives
+ which requirements are satisfied by 'properties' and picking the one with
+ longest requirements set.
+ Returns the result of calling 'generate' on that alternative.
+ """
+ self.manager_.targets ().start_building (self)
+
+ # We want composite properties in build request act as if
+ # all the properties it expands too are explicitly specified.
+ ps = ps.expand ()
+
+ all_property_sets = self.apply_default_build (ps)
+
+ result = GenerateResult ()
+
+ for p in all_property_sets:
+ result.extend (self.__generate_really (p))
+
+ self.manager_.targets ().end_building (self)
+
+ return result
+
+ def __generate_really (self, prop_set):
+ """ Generates the main target with the given property set
+ and returns a list which first element is property_set object
+ containing usage_requirements of generated target and with
+ generated virtual target in other elements. It's possible
+ that no targets are generated.
+ """
+ best_alternative = self.__select_alternatives (prop_set, debug=0)
+
+ if not best_alternative:
+ # FIXME: revive.
+ # self.__select_alternatives(prop_set, debug=1)
+ self.manager_.errors()(
+ "No best alternative for '%s'.\n"
+ % (self.full_name(),))
+
+ result = best_alternative.generate (prop_set)
+
+ # Now return virtual targets for the only alternative
+ return result
+
+ def rename(self, new_name):
+ AbstractTarget.rename(self, new_name)
+ for a in self.alternatives_:
+ a.rename(new_name)
+
+class FileReference (AbstractTarget):
+ """ Abstract target which refers to a source file.
+ This is artificial creature; it's usefull so that sources to
+ a target can be represented as list of abstract target instances.
+ """
+ def __init__ (self, manager, file, project):
+ AbstractTarget.__init__ (self, file, project)
+ self.file_location_ = None
+
+ def generate (self, properties):
+ return GenerateResult (None, [
+ self.manager_.virtual_targets ().from_file (
+ self.name_, self.location(), self.project_) ])
+
+ def exists (self):
+ """ Returns true if the referred file really exists.
+ """
+ if self.location ():
+ return True
+ else:
+ return False
+
+ def location (self):
+ # Returns the location of target. Needed by 'testing.jam'
+ if not self.file_location_:
+ source_location = self.project_.get('source-location')
+
+ for src_dir in source_location:
+ location = os.path.join(src_dir, self.name())
+ if os.path.isfile(location):
+ self.file_location_ = src_dir
+ self.file_path = location
+ break
+
+ return self.file_location_
+
+def resolve_reference(target_reference, project):
+ """ Given a target_reference, made in context of 'project',
+ returns the AbstractTarget instance that is referred to, as well
+ as properties explicitly specified for this reference.
+ """
+ # Separate target name from properties override
+ split = _re_separate_target_from_properties.match (target_reference)
+ if not split:
+ raise BaseException ("Invalid reference: '%s'" % target_reference)
+
+ id = split.group (1)
+
+ sproperties = []
+
+ if split.group (3):
+ sproperties = property.create_from_strings(feature.split(split.group(3)))
+ sproperties = feature.expand_composites(sproperties)
+
+ # Find the target
+ target = project.find (id)
+
+ return (target, property_set.create(sproperties))
+
+def generate_from_reference(target_reference, project, property_set):
+ """ Attempts to generate the target given by target reference, which
+ can refer both to a main target or to a file.
+ Returns a list consisting of
+ - usage requirements
+ - generated virtual targets, if any
+ target_reference: Target reference
+ project: Project where the reference is made
+ property_set: Properties of the main target that makes the reference
+ """
+ target, sproperties = resolve_reference(target_reference, project)
+
+ # Take properties which should be propagated and refine them
+ # with source-specific requirements.
+ propagated = property_set.propagated()
+ rproperties = propagated.refine(sproperties)
+
+ return target.generate(rproperties)
+
+
+
+class BasicTarget (AbstractTarget):
+ """ Implements the most standard way of constructing main target
+ alternative from sources. Allows sources to be either file or
+ other main target and handles generation of those dependency
+ targets.
+ """
+ def __init__ (self, name, project, sources, requirements = None, default_build = None, usage_requirements = None):
+ AbstractTarget.__init__ (self, name, project)
+
+ for s in sources:
+ if get_grist (s):
+ raise InvalidSource ("property '%s' found in the 'sources' parameter for '%s'" % (s, name))
+
+ self.sources_ = sources
+
+ if not requirements: requirements = property_set.empty ()
+ self.requirements_ = requirements
+
+ if not default_build: default_build = property_set.empty ()
+ self.default_build_ = default_build
+
+ if not usage_requirements: usage_requirements = property_set.empty ()
+ self.usage_requirements_ = usage_requirements
+
+ # A cache for resolved references
+ self.source_targets_ = None
+
+ # A cache for generated targets
+ self.generated_ = {}
+
+ # A cache for build requests
+ self.request_cache = {}
+
+ # Result of 'capture_user_context' has everything. For example, if this
+ # target is declare as result of loading Jamfile which was loaded when
+ # building target B which was requested from A, then we'll have A, B and
+ # Jamroot location in context. We only care about Jamroot location, most
+ # of the times.
+ self.user_context_ = self.manager_.errors().capture_user_context()[-1:]
+
+ self.always_ = False
+
+ def always(self):
+ self.always_ = True
+
+ def sources (self):
+ """ Returns the list of AbstractTargets which are used as sources.
+ The extra properties specified for sources are not represented.
+ The only used of this rule at the moment is the '--dump-tests'
+ feature of the test system.
+ """
+ if self.source_targets_ == None:
+ self.source_targets_ = []
+ for s in self.sources_:
+ self.source_targets_.append(resolve_reference(s, self.project_)[0])
+
+ return self.source_targets_
+
+ def requirements (self):
+ return self.requirements_
+
+ def default_build (self):
+ return self.default_build_
+
+ def common_properties (self, build_request, requirements):
+ """ Given build request and requirements, return properties
+ common to dependency build request and target build
+ properties.
+ """
+ # For optimization, we add free unconditional requirements directly,
+ # without using complex algorithsm.
+ # This gives the complex algorithm better chance of caching results.
+ # The exact effect of this "optimization" is no longer clear
+ free_unconditional = []
+ other = []
+ for p in requirements.all():
+ if p.feature().free() and not p.condition() and p.feature().name() != 'conditional':
+ free_unconditional.append(p)
+ else:
+ other.append(p)
+ other = property_set.create(other)
+
+ key = (build_request, other)
+ if not self.request_cache.has_key(key):
+ self.request_cache[key] = self.__common_properties2 (build_request, other)
+
+ return self.request_cache[key].add_raw(free_unconditional)
+
+ # Given 'context' -- a set of already present properties, and 'requirements',
+ # decide which extra properties should be applied to 'context'.
+ # For conditional requirements, this means evaluating condition. For
+ # indirect conditional requirements, this means calling a rule. Ordinary
+ # requirements are always applied.
+ #
+ # Handles situation where evaluating one conditional requirements affects
+ # condition of another conditional requirements, for example:
+ #
+ # <toolset>gcc:<variant>release <variant>release:<define>RELEASE
+ #
+ # If 'what' is 'refined' returns context refined with new requirements.
+ # If 'what' is 'added' returns just the requirements that must be applied.
+ def evaluate_requirements(self, requirements, context, what):
+ # Apply non-conditional requirements.
+ # It's possible that that further conditional requirement change
+ # a value set by non-conditional requirements. For example:
+ #
+ # exe a : a.cpp : <threading>single <toolset>foo:<threading>multi ;
+ #
+ # I'm not sure if this should be an error, or not, especially given that
+ #
+ # <threading>single
+ #
+ # might come from project's requirements.
+ unconditional = feature.expand(requirements.non_conditional())
+
+ context = context.refine(property_set.create(unconditional))
+
+ # We've collected properties that surely must be present in common
+ # properties. We now try to figure out what other properties
+ # should be added in order to satisfy rules (4)-(6) from the docs.
+
+ conditionals = property_set.create(requirements.conditional())
+
+ # It's supposed that #conditionals iterations
+ # should be enough for properties to propagate along conditions in any
+ # direction.
+ max_iterations = len(conditionals.all()) +\
+ len(requirements.get("<conditional>")) + 1
+
+ added_requirements = []
+ current = context
+
+ # It's assumed that ordinary conditional requirements can't add
+ # <indirect-conditional> properties, and that rules referred
+ # by <indirect-conditional> properties can't add new
+ # <indirect-conditional> properties. So the list of indirect conditionals
+ # does not change.
+ indirect = requirements.get("<conditional>")
+
+ ok = 0
+ for i in range(0, max_iterations):
+
+ e = conditionals.evaluate_conditionals(current).all()[:]
+
+ # Evaluate indirect conditionals.
+ for i in indirect:
+ i = b2.util.jam_to_value_maybe(i)
+ if callable(i):
+ # This is Python callable, yeah.
+ e.extend(i(current))
+ else:
+ # Name of bjam function. Because bjam is unable to handle
+ # list of Property, pass list of strings.
+ br = b2.util.call_jam_function(i[1:], [str(p) for p in current.all()])
+ if br:
+ e.extend(property.create_from_strings(br))
+
+ if e == added_requirements:
+ # If we got the same result, we've found final properties.
+ ok = 1
+ break
+ else:
+ # Oops, results of evaluation of conditionals has changed.
+ # Also 'current' contains leftover from previous evaluation.
+ # Recompute 'current' using initial properties and conditional
+ # requirements.
+ added_requirements = e
+ current = context.refine(property_set.create(feature.expand(e)))
+
+ if not ok:
+ self.manager().errors()("Can't evaluate conditional properties "
+ + str(conditionals))
+
+
+ if what == "added":
+ return property_set.create(unconditional + added_requirements)
+ elif what == "refined":
+ return current
+ else:
+ self.manager().errors("Invalid value of the 'what' parameter")
+
+ def __common_properties2(self, build_request, requirements):
+ # This guarantees that default properties are present
+ # in result, unless they are overrided by some requirement.
+ # TODO: There is possibility that we've added <foo>bar, which is composite
+ # and expands to <foo2>bar2, but default value of <foo2> is not bar2,
+ # in which case it's not clear what to do.
+ #
+ build_request = build_request.add_defaults()
+ # Featured added by 'add-default' can be composite and expand
+ # to features without default values -- so they are not added yet.
+ # It could be clearer/faster to expand only newly added properties
+ # but that's not critical.
+ build_request = build_request.expand()
+
+ return self.evaluate_requirements(requirements, build_request,
+ "refined")
+
+ def match (self, property_set, debug):
+ """ Returns the alternative condition for this alternative, if
+ the condition is satisfied by 'property_set'.
+ """
+ # The condition is composed of all base non-conditional properties.
+ # It's not clear if we should expand 'self.requirements_' or not.
+ # For one thing, it would be nice to be able to put
+ # <toolset>msvc-6.0
+ # in requirements.
+ # On the other hand, if we have <variant>release in condition it
+ # does not make sense to require <optimization>full to be in
+ # build request just to select this variant.
+ bcondition = self.requirements_.base ()
+ ccondition = self.requirements_.conditional ()
+ condition = b2.util.set.difference (bcondition, ccondition)
+
+ if debug:
+ print " next alternative: required properties:", [str(p) for p in condition]
+
+ if b2.util.set.contains (condition, property_set.all()):
+
+ if debug:
+ print " matched"
+
+ return condition
+
+ else:
+ return None
+
+
+ def generate_dependency_targets (self, target_ids, property_set):
+ targets = []
+ usage_requirements = []
+ for id in target_ids:
+
+ result = generate_from_reference(id, self.project_, property_set)
+ targets += result.targets()
+ usage_requirements += result.usage_requirements().all()
+
+ return (targets, usage_requirements)
+
+ def generate_dependency_properties(self, properties, ps):
+ """ Takes a target reference, which might be either target id
+ or a dependency property, and generates that target using
+ 'property_set' as build request.
+
+ Returns a tuple (result, usage_requirements).
+ """
+ result_properties = []
+ usage_requirements = []
+ for p in properties:
+
+ result = generate_from_reference(p.value(), self.project_, ps)
+
+ for t in result.targets():
+ result_properties.append(property.Property(p.feature(), t))
+
+ usage_requirements += result.usage_requirements().all()
+
+ return (result_properties, usage_requirements)
+
+
+
+
+ @user_error_checkpoint
+ def generate (self, ps):
+ """ Determines final build properties, generates sources,
+ and calls 'construct'. This method should not be
+ overridden.
+ """
+ self.manager_.errors().push_user_context(
+ "Generating target " + self.full_name(), self.user_context_)
+
+ if self.manager().targets().logging():
+ self.manager().targets().log(
+ "Building target '%s'" % self.name_)
+ self.manager().targets().increase_indent ()
+ self.manager().targets().log(
+ "Build request: '%s'" % str (ps.raw ()))
+ cf = self.manager().command_line_free_features()
+ self.manager().targets().log(
+ "Command line free features: '%s'" % str (cf.raw ()))
+ self.manager().targets().log(
+ "Target requirements: %s'" % str (self.requirements().raw ()))
+
+ self.manager().targets().push_target(self)
+
+ if not self.generated_.has_key(ps):
+
+ # Apply free features form the command line. If user
+ # said
+ # define=FOO
+ # he most likely want this define to be set for all compiles.
+ ps = ps.refine(self.manager().command_line_free_features())
+ rproperties = self.common_properties (ps, self.requirements_)
+
+ self.manager().targets().log(
+ "Common properties are '%s'" % str (rproperties))
+
+ if rproperties.get("<build>") != ["no"]:
+
+ result = GenerateResult ()
+
+ properties = rproperties.non_dependency ()
+
+ (p, u) = self.generate_dependency_properties (rproperties.dependency (), rproperties)
+ properties += p
+ assert all(isinstance(p, property.Property) for p in properties)
+ usage_requirements = u
+
+ (source_targets, u) = self.generate_dependency_targets (self.sources_, rproperties)
+ usage_requirements += u
+
+ self.manager_.targets().log(
+ "Usage requirements for '%s' are '%s'" % (self.name_, usage_requirements))
+
+ # FIXME:
+
+ rproperties = property_set.create(properties + usage_requirements)
+ usage_requirements = property_set.create (usage_requirements)
+
+ self.manager_.targets().log(
+ "Build properties: '%s'" % str(rproperties))
+
+ source_targets += rproperties.get('<source>')
+
+ # We might get duplicate sources, for example if
+ # we link to two library which have the same <library> in
+ # usage requirements.
+ # Use stable sort, since for some targets the order is
+ # important. E.g. RUN_PY target need python source to come
+ # first.
+ source_targets = unique(source_targets, stable=True)
+
+ # FIXME: figure why this call messes up source_targets in-place
+ result = self.construct (self.name_, source_targets[:], rproperties)
+
+ if result:
+ assert len(result) == 2
+ gur = result [0]
+ result = result [1]
+
+ if self.always_:
+ for t in result:
+ t.always()
+
+ s = self.create_subvariant (
+ result,
+ self.manager().virtual_targets().recent_targets(), ps,
+ source_targets, rproperties, usage_requirements)
+ self.manager().virtual_targets().clear_recent_targets()
+
+ ur = self.compute_usage_requirements (s)
+ ur = ur.add (gur)
+ s.set_usage_requirements (ur)
+
+ self.manager_.targets().log (
+ "Usage requirements from '%s' are '%s'" %
+ (self.name(), str(rproperties)))
+
+ self.generated_[ps] = GenerateResult (ur, result)
+ else:
+ self.generated_[ps] = GenerateResult (property_set.empty(), [])
+ else:
+ # If we just see <build>no, we cannot produce any reasonable
+ # diagnostics. The code that adds this property is expected
+ # to explain why a target is not built, for example using
+ # the configure.log-component-configuration function.
+
+ # If this target fails to build, add <build>no to properties
+ # to cause any parent target to fail to build. Except that it
+ # - does not work now, since we check for <build>no only in
+ # common properties, but not in properties that came from
+ # dependencies
+ # - it's not clear if that's a good idea anyway. The alias
+ # target, for example, should not fail to build if a dependency
+ # fails.
+ self.generated_[ps] = GenerateResult(
+ property_set.create(["<build>no"]), [])
+ else:
+ self.manager().targets().log ("Already built")
+
+ self.manager().targets().pop_target()
+ self.manager().targets().decrease_indent()
+
+ return self.generated_[ps]
+
+ def compute_usage_requirements (self, subvariant):
+ """ Given the set of generated targets, and refined build
+ properties, determines and sets appripriate usage requirements
+ on those targets.
+ """
+ rproperties = subvariant.build_properties ()
+ xusage_requirements =self.evaluate_requirements(
+ self.usage_requirements_, rproperties, "added")
+
+ # We generate all dependency properties and add them,
+ # as well as their usage requirements, to result.
+ (r1, r2) = self.generate_dependency_properties(xusage_requirements.dependency (), rproperties)
+ extra = r1 + r2
+
+ result = property_set.create (xusage_requirements.non_dependency () + extra)
+
+ # Propagate usage requirements we've got from sources, except
+ # for the <pch-header> and <pch-file> features.
+ #
+ # That feature specifies which pch file to use, and should apply
+ # only to direct dependents. Consider:
+ #
+ # pch pch1 : ...
+ # lib lib1 : ..... pch1 ;
+ # pch pch2 :
+ # lib lib2 : pch2 lib1 ;
+ #
+ # Here, lib2 should not get <pch-header> property from pch1.
+ #
+ # Essentially, when those two features are in usage requirements,
+ # they are propagated only to direct dependents. We might need
+ # a more general mechanism, but for now, only those two
+ # features are special.
+ raw = subvariant.sources_usage_requirements().raw()
+ raw = property.change(raw, "<pch-header>", None);
+ raw = property.change(raw, "<pch-file>", None);
+ result = result.add(property_set.create(raw))
+
+ return result
+
+ def create_subvariant (self, root_targets, all_targets,
+ build_request, sources,
+ rproperties, usage_requirements):
+ """Creates a new subvariant-dg instances for 'targets'
+ - 'root-targets' the virtual targets will be returned to dependents
+ - 'all-targets' all virtual
+ targets created while building this main target
+ - 'build-request' is property-set instance with
+ requested build properties"""
+
+ for e in root_targets:
+ e.root (True)
+
+ s = Subvariant (self, build_request, sources,
+ rproperties, usage_requirements, all_targets)
+
+ for v in all_targets:
+ if not v.creating_subvariant():
+ v.creating_subvariant(s)
+
+ return s
+
+ def construct (self, name, source_targets, properties):
+ """ Constructs the virtual targets for this abstract targets and
+ the dependecy graph. Returns a tuple consisting of the properties and the list of virtual targets.
+ Should be overrided in derived classes.
+ """
+ raise BaseException ("method should be defined in derived classes")
+
+
+class TypedTarget (BasicTarget):
+ import generators
+
+ def __init__ (self, name, project, type, sources, requirements, default_build, usage_requirements):
+ BasicTarget.__init__ (self, name, project, sources, requirements, default_build, usage_requirements)
+ self.type_ = type
+
+ def __jam_repr__(self):
+ return b2.util.value_to_jam(self)
+
+ def type (self):
+ return self.type_
+
+ def construct (self, name, source_targets, prop_set):
+
+ r = generators.construct (self.project_, name, self.type_,
+ prop_set.add_raw(['<main-target-type>' + self.type_]),
+ source_targets, True)
+
+ if not r:
+ print "warning: Unable to construct '%s'" % self.full_name ()
+
+ # Are there any top-level generators for this type/property set.
+ if not generators.find_viable_generators (self.type_, prop_set):
+ print "error: no generators were found for type '" + self.type_ + "'"
+ print "error: and the requested properties"
+ print "error: make sure you've configured the needed tools"
+ print "See http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html"
+
+ print "To debug this problem, try the --debug-generators option."
+ sys.exit(1)
+
+ return r
+
+def apply_default_build(property_set, default_build):
+ # 1. First, see what properties from default_build
+ # are already present in property_set.
+
+ specified_features = set(p.feature() for p in property_set.all())
+
+ defaults_to_apply = []
+ for d in default_build.all():
+ if not d.feature() in specified_features:
+ defaults_to_apply.append(d)
+
+ # 2. If there's any defaults to be applied, form the new
+ # build request. Pass it throw 'expand-no-defaults', since
+ # default_build might contain "release debug", which will
+ # result in two property_sets.
+ result = []
+ if defaults_to_apply:
+
+ # We have to compress subproperties here to prevent
+ # property lists like:
+ #
+ # <toolset>msvc <toolset-msvc:version>7.1 <threading>multi
+ #
+ # from being expanded into:
+ #
+ # <toolset-msvc:version>7.1/<threading>multi
+ # <toolset>msvc/<toolset-msvc:version>7.1/<threading>multi
+ #
+ # due to cross-product property combination. That may
+ # be an indication that
+ # build_request.expand-no-defaults is the wrong rule
+ # to use here.
+ compressed = feature.compress_subproperties(property_set.all())
+
+ result = build_request.expand_no_defaults(
+ b2.build.property_set.create([p]) for p in (compressed + defaults_to_apply))
+
+ else:
+ result.append (property_set)
+
+ return result
+
+
+def create_typed_metatarget(name, type, sources, requirements, default_build, usage_requirements):
+
+ from b2.manager import get_manager
+ t = get_manager().targets()
+
+ project = get_manager().projects().current()
+
+ return t.main_target_alternative(
+ TypedTarget(name, project, type,
+ t.main_target_sources(sources, name),
+ t.main_target_requirements(requirements, project),
+ t.main_target_default_build(default_build, project),
+ t.main_target_usage_requirements(usage_requirements, project)))
+
+
+def create_metatarget(klass, name, sources, requirements=[], default_build=[], usage_requirements=[]):
+ from b2.manager import get_manager
+ t = get_manager().targets()
+
+ project = get_manager().projects().current()
+
+ return t.main_target_alternative(
+ klass(name, project,
+ t.main_target_sources(sources, name),
+ t.main_target_requirements(requirements, project),
+ t.main_target_default_build(default_build, project),
+ t.main_target_usage_requirements(usage_requirements, project)))
+
+def metatarget_function_for_class(class_):
+
+ @bjam_signature((["name"], ["sources", "*"], ["requirements", "*"],
+ ["default_build", "*"], ["usage_requirements", "*"]))
+ def create_metatarget(name, sources, requirements = [], default_build = None, usage_requirements = []):
+
+ from b2.manager import get_manager
+ t = get_manager().targets()
+
+ project = get_manager().projects().current()
+
+ return t.main_target_alternative(
+ class_(name, project,
+ t.main_target_sources(sources, name),
+ t.main_target_requirements(requirements, project),
+ t.main_target_default_build(default_build, project),
+ t.main_target_usage_requirements(usage_requirements, project)))
+
+ return create_metatarget
diff --git a/tools/build/v2/build/toolset.jam b/tools/build/v2/build/toolset.jam
new file mode 100644
index 0000000000..f2036d999c
--- /dev/null
+++ b/tools/build/v2/build/toolset.jam
@@ -0,0 +1,502 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2005 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Support for toolset definition.
+
+import errors ;
+import feature ;
+import generators ;
+import numbers ;
+import path ;
+import property ;
+import regex ;
+import sequence ;
+import set ;
+
+
+.flag-no = 1 ;
+
+.ignore-requirements = ;
+
+# This is used only for testing, to make sure we do not get random extra
+# elements in paths.
+if --ignore-toolset-requirements in [ modules.peek : ARGV ]
+{
+ .ignore-requirements = 1 ;
+}
+
+
+# Initializes an additional toolset-like module. First load the 'toolset-module'
+# and then calls its 'init' rule with trailing arguments.
+#
+rule using ( toolset-module : * )
+{
+ import $(toolset-module) ;
+ $(toolset-module).init $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+}
+
+
+# Expands subfeatures in each property sets, e.g. '<toolset>gcc-3.2' will be
+# converted to '<toolset>gcc/<toolset-version>3.2'.
+#
+local rule normalize-condition ( property-sets * )
+{
+ local result ;
+ for local p in $(property-sets)
+ {
+ local split = [ feature.split $(p) ] ;
+ local expanded = [ feature.expand-subfeatures [ feature.split $(p) ] ] ;
+ result += $(expanded:J=/) ;
+ }
+ return $(result) ;
+}
+
+
+# Specifies if the 'flags' rule should check that the invoking module is the
+# same as the module we are setting the flag for. 'v' can be either 'checked' or
+# 'unchecked'. Subsequent call to 'pop-checking-for-flags-module' will restore
+# the setting that was in effect before calling this rule.
+#
+rule push-checking-for-flags-module ( v )
+{
+ .flags-module-checking = $(v) $(.flags-module-checking) ;
+}
+
+rule pop-checking-for-flags-module ( )
+{
+ .flags-module-checking = $(.flags-module-checking[2-]) ;
+}
+
+
+# Specifies the flags (variables) that must be set on targets under certain
+# conditions, described by arguments.
+#
+rule flags (
+ rule-or-module # If contains a dot, should be a rule name. The flags will
+ # be applied when that rule is used to set up build
+ # actions.
+ #
+ # If does not contain dot, should be a module name. The
+ # flag will be applied for all rules in that module. If
+ # module for rule is different from the calling module, an
+ # error is issued.
+
+ variable-name # Variable that should be set on target.
+ condition * : # A condition when this flag should be applied. Should be a
+ # set of property sets. If one of those property sets is
+ # contained in the build properties, the flag will be used.
+ # Implied values are not allowed: "<toolset>gcc" should be
+ # used, not just "gcc". Subfeatures, like in
+ # "<toolset>gcc-3.2" are allowed. If left empty, the flag
+ # will be used unconditionally.
+ #
+ # Propery sets may use value-less properties ('<a>' vs.
+ # '<a>value') to match absent properties. This allows to
+ # separately match:
+ #
+ # <architecture>/<address-model>64
+ # <architecture>ia64/<address-model>
+ #
+ # Where both features are optional. Without this syntax
+ # we would be forced to define "default" values.
+
+ values * : # The value to add to variable. If <feature> is specified,
+ # then the value of 'feature' will be added.
+ unchecked ? # If value 'unchecked' is passed, will not test that flags
+ # are set for the calling module.
+ : hack-hack ? # For
+ # flags rule OPTIONS <cxx-abi> : -model ansi
+ # Treat <cxx-abi> as condition
+ # FIXME: ugly hack.
+)
+{
+ local caller = [ CALLER_MODULE ] ;
+ if ! [ MATCH ".*([.]).*" : $(rule-or-module) ]
+ && [ MATCH "(Jamfile<.*)" : $(caller) ]
+ {
+ # Unqualified rule name, used inside Jamfile. Most likely used with
+ # 'make' or 'notfile' rules. This prevents setting flags on the entire
+ # Jamfile module (this will be considered as rule), but who cares?
+ # Probably, 'flags' rule should be split into 'flags' and
+ # 'flags-on-module'.
+ rule-or-module = $(caller).$(rule-or-module) ;
+ }
+ else
+ {
+ local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ;
+ if $(unchecked) != unchecked
+ && $(.flags-module-checking[1]) != unchecked
+ && $(module_) != $(caller)
+ {
+ errors.error "Module $(caller) attempted to set flags for module $(module_)" ;
+ }
+ }
+
+ if $(condition) && ! $(condition:G=) && ! $(hack-hack)
+ {
+ # We have condition in the form '<feature>', that is, without value.
+ # That is an older syntax:
+ # flags gcc.link RPATH <dll-path> ;
+ # for compatibility, convert it to
+ # flags gcc.link RPATH : <dll-path> ;
+ values = $(condition) ;
+ condition = ;
+ }
+
+ if $(condition)
+ {
+ property.validate-property-sets $(condition) ;
+ condition = [ normalize-condition $(condition) ] ;
+ }
+
+ add-flag $(rule-or-module) : $(variable-name) : $(condition) : $(values) ;
+}
+
+
+# Adds a new flag setting with the specified values. Does no checking.
+#
+local rule add-flag ( rule-or-module : variable-name : condition * : values * )
+{
+ .$(rule-or-module).flags += $(.flag-no) ;
+
+ # Store all flags for a module.
+ local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ;
+ .module-flags.$(module_) += $(.flag-no) ;
+ # Store flag-no -> rule-or-module mapping.
+ .rule-or-module.$(.flag-no) = $(rule-or-module) ;
+
+ .$(rule-or-module).variable.$(.flag-no) += $(variable-name) ;
+ .$(rule-or-module).values.$(.flag-no) += $(values) ;
+ .$(rule-or-module).condition.$(.flag-no) += $(condition) ;
+
+ .flag-no = [ numbers.increment $(.flag-no) ] ;
+}
+
+
+# Returns the first element of 'property-sets' which is a subset of
+# 'properties' or an empty list if no such element exists.
+#
+rule find-property-subset ( property-sets * : properties * )
+{
+ # Cut property values off.
+ local prop-keys = $(properties:G) ;
+
+ local result ;
+ for local s in $(property-sets)
+ {
+ if ! $(result)
+ {
+ # Handle value-less properties like '<architecture>' (compare with
+ # '<architecture>x86').
+
+ local set = [ feature.split $(s) ] ;
+
+ # Find the set of features that
+ # - have no property specified in required property set
+ # - are omitted in the build property set.
+ local default-props ;
+ for local i in $(set)
+ {
+ # If $(i) is a value-less property it should match default value
+ # of an optional property. See the first line in the example
+ # below:
+ #
+ # property set properties result
+ # <a> <b>foo <b>foo match
+ # <a> <b>foo <a>foo <b>foo no match
+ # <a>foo <b>foo <b>foo no match
+ # <a>foo <b>foo <a>foo <b>foo match
+ if ! ( $(i:G=) || ( $(i:G) in $(prop-keys) ) )
+ {
+ default-props += $(i) ;
+ }
+ }
+
+ if $(set) in $(properties) $(default-props)
+ {
+ result = $(s) ;
+ }
+ }
+ }
+ return $(result) ;
+}
+
+
+# Returns a value to be added to some flag for some target based on the flag's
+# value definition and the given target's property set.
+#
+rule handle-flag-value ( value * : properties * )
+{
+ local result ;
+ if $(value:G)
+ {
+ local matches = [ property.select $(value) : $(properties) ] ;
+ for local p in $(matches)
+ {
+ local att = [ feature.attributes $(p:G) ] ;
+ if dependency in $(att)
+ {
+ # The value of a dependency feature is a target and needs to be
+ # actualized.
+ result += [ $(p:G=).actualize ] ;
+ }
+ else if path in $(att) || free in $(att)
+ {
+ local values ;
+ # Treat features with && in the value specially -- each
+ # &&-separated element is considered a separate value. This is
+ # needed to handle searched libraries or include paths, which
+ # may need to be in a specific order.
+ if ! [ MATCH (&&) : $(p:G=) ]
+ {
+ values = $(p:G=) ;
+ }
+ else
+ {
+ values = [ regex.split $(p:G=) "&&" ] ;
+ }
+ if path in $(att)
+ {
+ result += [ sequence.transform path.native : $(values) ] ;
+ }
+ else
+ {
+ result += $(values) ;
+ }
+ }
+ else
+ {
+ result += $(p:G=) ;
+ }
+ }
+ }
+ else
+ {
+ result += $(value) ;
+ }
+ return $(result) ;
+}
+
+
+# Given a rule name and a property set, returns a list of interleaved variables
+# names and values which must be set on targets for that rule/property-set
+# combination.
+#
+rule set-target-variables-aux ( rule-or-module : property-set )
+{
+ local result ;
+ properties = [ $(property-set).raw ] ;
+ for local f in $(.$(rule-or-module).flags)
+ {
+ local variable = $(.$(rule-or-module).variable.$(f)) ;
+ local condition = $(.$(rule-or-module).condition.$(f)) ;
+ local values = $(.$(rule-or-module).values.$(f)) ;
+
+ if ! $(condition) ||
+ [ find-property-subset $(condition) : $(properties) ]
+ {
+ local processed ;
+ for local v in $(values)
+ {
+ # The value might be <feature-name> so needs special treatment.
+ processed += [ handle-flag-value $(v) : $(properties) ] ;
+ }
+ for local r in $(processed)
+ {
+ result += $(variable) $(r) ;
+ }
+ }
+ }
+
+ # Strip away last dot separated part and recurse.
+ local next = [ MATCH ^(.+)\\.([^\\.])* : $(rule-or-module) ] ;
+ if $(next)
+ {
+ result += [ set-target-variables-aux $(next[1]) : $(property-set) ] ;
+ }
+ return $(result) ;
+}
+
+
+rule set-target-variables ( rule-or-module targets + : property-set )
+{
+ properties = [ $(property-set).raw ] ;
+ local key = $(rule-or-module).$(property-set) ;
+ local settings = $(.stv.$(key)) ;
+ if ! $(settings)
+ {
+ settings = [ set-target-variables-aux $(rule-or-module) :
+ $(property-set) ] ;
+
+ if ! $(settings)
+ {
+ settings = none ;
+ }
+ .stv.$(key) = $(settings) ;
+ }
+
+ if $(settings) != none
+ {
+ local var-name = ;
+ for local name-or-value in $(settings)
+ {
+ if $(var-name)
+ {
+ $(var-name) on $(targets) += $(name-or-value) ;
+ var-name = ;
+ }
+ else
+ {
+ var-name = $(name-or-value) ;
+ }
+ }
+ }
+}
+
+
+# Make toolset 'toolset', defined in a module of the same name, inherit from
+# 'base'.
+# 1. The 'init' rule from 'base' is imported into 'toolset' with full name.
+# Another 'init' is called, which forwards to the base one.
+# 2. All generators from 'base' are cloned. The ids are adjusted and <toolset>
+# property in requires is adjusted too.
+# 3. All flags are inherited.
+# 4. All rules are imported.
+#
+rule inherit ( toolset : base )
+{
+ import $(base) ;
+ inherit-generators $(toolset) : $(base) ;
+ inherit-flags $(toolset) : $(base) ;
+ inherit-rules $(toolset) : $(base) ;
+}
+
+
+rule inherit-generators ( toolset properties * : base : generators-to-ignore * )
+{
+ properties ?= <toolset>$(toolset) ;
+ local base-generators = [ generators.generators-for-toolset $(base) ] ;
+ for local g in $(base-generators)
+ {
+ local id = [ $(g).id ] ;
+
+ if ! $(id) in $(generators-to-ignore)
+ {
+ # Some generator names have multiple periods in their name, so
+ # $(id:B=$(toolset)) does not generate the right new-id name. E.g.
+ # if id = gcc.compile.c++ then $(id:B=darwin) = darwin.c++, which is
+ # not what we want. Manually parse the base and suffix. If there is
+ # a better way to do this, I would love to see it. See also the
+ # register() rule in the generators module.
+ local base = $(id) ;
+ local suffix = "" ;
+ while $(base:S)
+ {
+ suffix = $(base:S)$(suffix) ;
+ base = $(base:B) ;
+ }
+ local new-id = $(toolset)$(suffix) ;
+
+ generators.register [ $(g).clone $(new-id) : $(properties) ] ;
+ }
+ }
+}
+
+
+# Brings all flag definitions from the 'base' toolset into the 'toolset'
+# toolset. Flag definitions whose conditions make use of properties in
+# 'prohibited-properties' are ignored. Do not confuse property and feature, for
+# example <debug-symbols>on and <debug-symbols>off, so blocking one of them does
+# not block the other one.
+#
+# The flag conditions are not altered at all, so if a condition includes a name,
+# or version of a base toolset, it will not ever match the inheriting toolset.
+# When such flag settings must be inherited, define a rule in base toolset
+# module and call it as needed.
+#
+rule inherit-flags ( toolset : base : prohibited-properties * : prohibited-vars * )
+{
+ for local f in $(.module-flags.$(base))
+ {
+ local rule-or-module = $(.rule-or-module.$(f)) ;
+ if ( [ set.difference
+ $(.$(rule-or-module).condition.$(f)) :
+ $(prohibited-properties) ]
+ || ! $(.$(rule-or-module).condition.$(f))
+ ) && ( ! $(.$(rule-or-module).variable.$(f)) in $(prohibited-vars) )
+ {
+ local rule_ = [ MATCH "[^.]*\.(.*)" : $(rule-or-module) ] ;
+ local new-rule-or-module ;
+ if $(rule_)
+ {
+ new-rule-or-module = $(toolset).$(rule_) ;
+ }
+ else
+ {
+ new-rule-or-module = $(toolset) ;
+ }
+
+ add-flag
+ $(new-rule-or-module)
+ : $(.$(rule-or-module).variable.$(f))
+ : $(.$(rule-or-module).condition.$(f))
+ : $(.$(rule-or-module).values.$(f)) ;
+ }
+ }
+}
+
+
+rule inherit-rules ( toolset : base : localize ? )
+{
+ # It appears that "action" creates a local rule.
+ local base-generators = [ generators.generators-for-toolset $(base) ] ;
+ local rules ;
+ for local g in $(base-generators)
+ {
+ rules += [ MATCH "[^.]*\.(.*)" : [ $(g).rule-name ] ] ;
+ }
+ rules = [ sequence.unique $(rules) ] ;
+ IMPORT $(base) : $(rules) : $(toolset) : $(rules) : $(localize) ;
+ IMPORT $(toolset) : $(rules) : : $(toolset).$(rules) ;
+}
+
+
+# Return the list of global 'toolset requirements'. Those requirements will be
+# automatically added to the requirements of any main target.
+#
+rule requirements ( )
+{
+ return $(.requirements) ;
+}
+
+
+# Adds elements to the list of global 'toolset requirements'. The requirements
+# will be automatically added to the requirements for all main targets, as if
+# they were specified literally. For best results, all requirements added should
+# be conditional or indirect conditional.
+#
+rule add-requirements ( requirements * )
+{
+ if ! $(.ignore-requirements)
+ {
+ .requirements += $(requirements) ;
+ }
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+ local p = <b>0 <c>1 <d>2 <e>3 <f>4 ;
+ assert.result <c>1/<d>2/<e>3 : find-property-subset <c>1/<d>2/<e>3 <a>0/<b>0/<c>1 <d>2/<e>5 <a>9 : $(p) ;
+ assert.result : find-property-subset <a>0/<b>0/<c>9/<d>9/<e>5 <a>9 : $(p) ;
+
+ local p-set = <a>/<b> <a>0/<b> <a>/<b>1 <a>0/<b>1 ;
+ assert.result <a>/<b> : find-property-subset $(p-set) : ;
+ assert.result <a>0/<b> : find-property-subset $(p-set) : <a>0 <c>2 ;
+ assert.result <a>/<b>1 : find-property-subset $(p-set) : <b>1 <c>2 ;
+ assert.result <a>0/<b>1 : find-property-subset $(p-set) : <a>0 <b>1 ;
+}
diff --git a/tools/build/v2/build/toolset.py b/tools/build/v2/build/toolset.py
new file mode 100644
index 0000000000..b426798784
--- /dev/null
+++ b/tools/build/v2/build/toolset.py
@@ -0,0 +1,398 @@
+# Status: being ported by Vladimir Prus
+# Base revision: 40958
+#
+# Copyright 2003 Dave Abrahams
+# Copyright 2005 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+""" Support for toolset definition.
+"""
+
+import feature, property, generators, property_set
+import b2.util.set
+from b2.util import cached, qualify_jam_action
+from b2.util.utility import *
+from b2.util import bjam_signature
+from b2.manager import get_manager
+
+__re_split_last_segment = re.compile (r'^(.+)\.([^\.])*')
+__re_two_ampersands = re.compile ('(&&)')
+__re_first_segment = re.compile ('([^.]*).*')
+__re_first_group = re.compile (r'[^.]*\.(.*)')
+
+# Flag is a mechanism to set a value
+# A single toolset flag. Specifies that when certain
+# properties are in build property set, certain values
+# should be appended to some variable.
+#
+# A flag applies to a specific action in specific module.
+# The list of all flags for a module is stored, and each
+# flag further contains the name of the rule it applies
+# for,
+class Flag:
+
+ def __init__(self, variable_name, values, condition, rule = None):
+ self.variable_name = variable_name
+ self.values = values
+ self.condition = condition
+ self.rule = rule
+
+ def __str__(self):
+ return("Flag(" + str(self.variable_name) + ", " + str(self.values) +\
+ ", " + str(self.condition) + ", " + str(self.rule) + ")")
+
+def reset ():
+ """ Clear the module state. This is mainly for testing purposes.
+ """
+ global __module_flags, __flags, __stv
+
+ # Mapping from module name to a list of all flags that apply
+ # to either that module directly, or to any rule in that module.
+ # Each element of the list is Flag instance.
+ # So, for module named xxx this might contain flags for 'xxx',
+ # for 'xxx.compile', for 'xxx.compile.c++', etc.
+ __module_flags = {}
+
+ # Mapping from specific rule or module name to a list of Flag instances
+ # that apply to that name.
+ # Say, it might contain flags for 'xxx.compile.c++'. If there are
+ # entries for module name 'xxx', they are flags for 'xxx' itself,
+ # not including any rules in that module.
+ __flags = {}
+
+ # A cache for varaible settings. The key is generated from the rule name and the properties.
+ __stv = {}
+
+reset ()
+
+# FIXME: --ignore-toolset-requirements
+# FIXME: using
+
+# FIXME push-checking-for-flags-module ....
+# FIXME: investigate existing uses of 'hack-hack' parameter
+# in jam code.
+
+@bjam_signature((["rule_or_module", "variable_name", "condition", "*"],
+ ["values", "*"]))
+def flags(rule_or_module, variable_name, condition, values = []):
+ """ Specifies the flags (variables) that must be set on targets under certain
+ conditions, described by arguments.
+ rule_or_module: If contains dot, should be a rule name.
+ The flags will be applied when that rule is
+ used to set up build actions.
+
+ If does not contain dot, should be a module name.
+ The flags will be applied for all rules in that
+ module.
+ If module for rule is different from the calling
+ module, an error is issued.
+
+ variable_name: Variable that should be set on target
+
+ condition A condition when this flag should be applied.
+ Should be set of property sets. If one of
+ those property sets is contained in build
+ properties, the flag will be used.
+ Implied values are not allowed:
+ "<toolset>gcc" should be used, not just
+ "gcc". Subfeatures, like in "<toolset>gcc-3.2"
+ are allowed. If left empty, the flag will
+ always used.
+
+ Propery sets may use value-less properties
+ ('<a>' vs. '<a>value') to match absent
+ properties. This allows to separately match
+
+ <architecture>/<address-model>64
+ <architecture>ia64/<address-model>
+
+ Where both features are optional. Without this
+ syntax we'd be forced to define "default" value.
+
+ values: The value to add to variable. If <feature>
+ is specified, then the value of 'feature'
+ will be added.
+ """
+ caller = bjam.caller()[:-1]
+ if not '.' in rule_or_module and caller.startswith("Jamfile"):
+ # Unqualified rule name, used inside Jamfile. Most likely used with
+ # 'make' or 'notfile' rules. This prevents setting flags on the entire
+ # Jamfile module (this will be considered as rule), but who cares?
+ # Probably, 'flags' rule should be split into 'flags' and
+ # 'flags-on-module'.
+ rule_or_module = qualify_jam_action(rule_or_module, caller)
+ else:
+ # FIXME: revive checking that we don't set flags for a different
+ # module unintentionally
+ pass
+
+ if condition and not replace_grist (condition, ''):
+ # We have condition in the form '<feature>', that is, without
+ # value. That's a previous syntax:
+ #
+ # flags gcc.link RPATH <dll-path> ;
+ # for compatibility, convert it to
+ # flags gcc.link RPATH : <dll-path> ;
+ values = [ condition ]
+ condition = None
+
+ if condition:
+ transformed = []
+ for c in condition:
+ # FIXME: 'split' might be a too raw tool here.
+ pl = [property.create_from_string(s) for s in c.split('/')]
+ pl = feature.expand_subfeatures(pl);
+ transformed.append(property_set.create(pl))
+ condition = transformed
+
+ property.validate_property_sets(condition)
+
+ __add_flag (rule_or_module, variable_name, condition, values)
+
+def set_target_variables (manager, rule_or_module, targets, ps):
+ """
+ """
+ settings = __set_target_variables_aux(manager, rule_or_module, ps)
+
+ if settings:
+ for s in settings:
+ for target in targets:
+ manager.engine ().set_target_variable (target, s [0], s[1], True)
+
+def find_satisfied_condition(conditions, ps):
+ """Returns the first element of 'property-sets' which is a subset of
+ 'properties', or an empty list if no such element exists."""
+
+ features = set(p.feature() for p in ps.all())
+
+ for condition in conditions:
+
+ found_all = True
+ for i in condition.all():
+
+ found = False
+ if i.value():
+ found = i.value() in ps.get(i.feature())
+ else:
+ # Handle value-less properties like '<architecture>' (compare with
+ # '<architecture>x86').
+ # If $(i) is a value-less property it should match default
+ # value of an optional property. See the first line in the
+ # example below:
+ #
+ # property set properties result
+ # <a> <b>foo <b>foo match
+ # <a> <b>foo <a>foo <b>foo no match
+ # <a>foo <b>foo <b>foo no match
+ # <a>foo <b>foo <a>foo <b>foo match
+ found = not i.feature() in features
+
+ found_all = found_all and found
+
+ if found_all:
+ return condition
+
+ return None
+
+
+def register (toolset):
+ """ Registers a new toolset.
+ """
+ feature.extend('toolset', [toolset])
+
+def inherit_generators (toolset, properties, base, generators_to_ignore = []):
+ if not properties:
+ properties = [replace_grist (toolset, '<toolset>')]
+
+ base_generators = generators.generators_for_toolset(base)
+
+ for g in base_generators:
+ id = g.id()
+
+ if not id in generators_to_ignore:
+ # Some generator names have multiple periods in their name, so
+ # $(id:B=$(toolset)) doesn't generate the right new_id name.
+ # e.g. if id = gcc.compile.c++, $(id:B=darwin) = darwin.c++,
+ # which is not what we want. Manually parse the base and suffix
+ # (if there's a better way to do this, I'd love to see it.)
+ # See also register in module generators.
+ (base, suffix) = split_action_id(id)
+
+ new_id = toolset + '.' + suffix
+
+ generators.register(g.clone(new_id, properties))
+
+def inherit_flags(toolset, base, prohibited_properties = []):
+ """Brings all flag definitions from the 'base' toolset into the 'toolset'
+ toolset. Flag definitions whose conditions make use of properties in
+ 'prohibited-properties' are ignored. Don't confuse property and feature, for
+ example <debug-symbols>on and <debug-symbols>off, so blocking one of them does
+ not block the other one.
+
+ The flag conditions are not altered at all, so if a condition includes a name,
+ or version of a base toolset, it won't ever match the inheriting toolset. When
+ such flag settings must be inherited, define a rule in base toolset module and
+ call it as needed."""
+ for f in __module_flags.get(base, []):
+
+ if not f.condition or b2.util.set.difference(f.condition, prohibited_properties):
+ match = __re_first_group.match(f.rule)
+ rule_ = None
+ if match:
+ rule_ = match.group(1)
+
+ new_rule_or_module = ''
+
+ if rule_:
+ new_rule_or_module = toolset + '.' + rule_
+ else:
+ new_rule_or_module = toolset
+
+ __add_flag (new_rule_or_module, f.variable_name, f.condition, f.values)
+
+def inherit_rules (toolset, base):
+ pass
+ # FIXME: do something about this.
+# base_generators = generators.generators_for_toolset (base)
+
+# import action
+
+# ids = []
+# for g in base_generators:
+# (old_toolset, id) = split_action_id (g.id ())
+# ids.append (id) ;
+
+# new_actions = []
+
+# engine = get_manager().engine()
+ # FIXME: do this!
+# for action in engine.action.values():
+# pass
+# (old_toolset, id) = split_action_id(action.action_name)
+#
+# if old_toolset == base:
+# new_actions.append ((id, value [0], value [1]))
+#
+# for a in new_actions:
+# action.register (toolset + '.' + a [0], a [1], a [2])
+
+ # TODO: how to deal with this?
+# IMPORT $(base) : $(rules) : $(toolset) : $(rules) : localized ;
+# # Import the rules to the global scope
+# IMPORT $(toolset) : $(rules) : : $(toolset).$(rules) ;
+# }
+#
+
+######################################################################################
+# Private functions
+
+@cached
+def __set_target_variables_aux (manager, rule_or_module, ps):
+ """ Given a rule name and a property set, returns a list of tuples of
+ variables names and values, which must be set on targets for that
+ rule/properties combination.
+ """
+ result = []
+
+ for f in __flags.get(rule_or_module, []):
+
+ if not f.condition or find_satisfied_condition (f.condition, ps):
+ processed = []
+ for v in f.values:
+ # The value might be <feature-name> so needs special
+ # treatment.
+ processed += __handle_flag_value (manager, v, ps)
+
+ for r in processed:
+ result.append ((f.variable_name, r))
+
+ # strip away last dot separated part and recurse.
+ next = __re_split_last_segment.match(rule_or_module)
+
+ if next:
+ result.extend(__set_target_variables_aux(
+ manager, next.group(1), ps))
+
+ return result
+
+def __handle_flag_value (manager, value, ps):
+ result = []
+
+ if get_grist (value):
+ f = feature.get(value)
+ values = ps.get(f)
+
+ for value in values:
+
+ if f.dependency():
+ # the value of a dependency feature is a target
+ # and must be actualized
+ result.append(value.actualize())
+
+ elif f.path() or f.free():
+
+ # Treat features with && in the value
+ # specially -- each &&-separated element is considered
+ # separate value. This is needed to handle searched
+ # libraries, which must be in specific order.
+ if not __re_two_ampersands.search(value):
+ result.append(value)
+
+ else:
+ result.extend(value.split ('&&'))
+ else:
+ result.append (ungristed)
+ else:
+ result.append (value)
+
+ return result
+
+def __add_flag (rule_or_module, variable_name, condition, values):
+ """ Adds a new flag setting with the specified values.
+ Does no checking.
+ """
+ f = Flag(variable_name, values, condition, rule_or_module)
+
+ # Grab the name of the module
+ m = __re_first_segment.match (rule_or_module)
+ assert m
+ module = m.group(1)
+
+ __module_flags.setdefault(m, []).append(f)
+ __flags.setdefault(rule_or_module, []).append(f)
+
+__requirements = []
+
+def requirements():
+ """Return the list of global 'toolset requirements'.
+ Those requirements will be automatically added to the requirements of any main target."""
+ return __requirements
+
+def add_requirements(requirements):
+ """Adds elements to the list of global 'toolset requirements'. The requirements
+ will be automatically added to the requirements for all main targets, as if
+ they were specified literally. For best results, all requirements added should
+ be conditional or indirect conditional."""
+
+ #if ! $(.ignore-requirements)
+ #{
+ print "XXXX", requirements
+ __requirements.extend(requirements)
+ #}
+
+# Make toolset 'toolset', defined in a module of the same name,
+# inherit from 'base'
+# 1. The 'init' rule from 'base' is imported into 'toolset' with full
+# name. Another 'init' is called, which forwards to the base one.
+# 2. All generators from 'base' are cloned. The ids are adjusted and
+# <toolset> property in requires is adjusted too
+# 3. All flags are inherited
+# 4. All rules are imported.
+def inherit(toolset, base):
+ get_manager().projects().load_module(base, []);
+
+ inherit_generators(toolset, [], base)
+ inherit_flags(toolset, base)
+ inherit_rules(toolset, base)
diff --git a/tools/build/v2/build/type.jam b/tools/build/v2/build/type.jam
new file mode 100644
index 0000000000..1a7a578234
--- /dev/null
+++ b/tools/build/v2/build/type.jam
@@ -0,0 +1,425 @@
+# Copyright 2002, 2003 Dave Abrahams
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Deals with target type declaration and defines target class which supports
+# typed targets.
+
+import "class" : new ;
+import errors ;
+import feature ;
+import generators : * ;
+import project ;
+import property ;
+import scanner ;
+import os ;
+
+# The following import would create a circular dependency:
+# project -> project-root -> builtin -> type -> targets -> project
+# import targets ;
+
+# The feature is optional so it would never get added implicitly. It is used
+# only for internal purposes and in all cases we want to use it explicitly.
+feature.feature target-type : : composite optional ;
+
+feature.feature main-target-type : : optional incidental ;
+feature.feature base-target-type : : composite optional free ;
+
+
+# Registers a target type, possible derived from a 'base-type'. Providing a list
+# of 'suffixes' here is a shortcut for separately calling the register-suffixes
+# rule with the given suffixes and the set-generated-target-suffix rule with the
+# first given suffix.
+#
+rule register ( type : suffixes * : base-type ? )
+{
+ # Type names cannot contain hyphens, because when used as feature-values
+ # they would be interpreted as composite features which need to be
+ # decomposed.
+ switch $(type)
+ {
+ case *-* : errors.error "type name \"$(type)\" contains a hyphen" ;
+ }
+
+ if $(type) in $(.types)
+ {
+ errors.error "Type $(type) is already registered." ;
+ }
+ else
+ {
+ .types += $(type) ;
+ .base.$(type) = $(base-type) ;
+ .derived.$(base-type) += $(type) ;
+
+ if $(suffixes)-is-not-empty
+ {
+ # Specify mapping from suffixes to type.
+ register-suffixes $(suffixes) : $(type) ;
+ # By default generated targets of 'type' will use the first of
+ #'suffixes'. This may be overriden.
+ set-generated-target-suffix $(type) : : $(suffixes[1]) ;
+ }
+
+ feature.extend target-type : $(type) ;
+ feature.extend main-target-type : $(type) ;
+ feature.extend base-target-type : $(type) ;
+
+ feature.compose <target-type>$(type) : $(base-type:G=<base-target-type>) ;
+ feature.compose <base-target-type>$(type) : <base-target-type>$(base-type) ;
+
+ # We used to declare the main target rule only when a 'main' parameter
+ # has been specified. However, it is hard to decide that a type will
+ # *never* need a main target rule and so from time to time we needed to
+ # make yet another type 'main'. So now a main target rule is defined for
+ # each type.
+ main-rule-name = [ type-to-rule-name $(type) ] ;
+ .main-target-type.$(main-rule-name) = $(type) ;
+ IMPORT $(__name__) : main-target-rule : : $(main-rule-name) ;
+
+ # Adding a new derived type affects generator selection so we need to
+ # make the generator selection module update any of its cached
+ # information related to a new derived type being defined.
+ generators.update-cached-information-with-a-new-type $(type) ;
+ }
+}
+
+
+# Given a type, returns the name of the main target rule which creates targets
+# of that type.
+#
+rule type-to-rule-name ( type )
+{
+ # Lowercase everything. Convert underscores to dashes.
+ import regex ;
+ local n = [ regex.split $(type:L) "_" ] ;
+ return $(n:J=-) ;
+}
+
+
+# Given a main target rule name, returns the type for which it creates targets.
+#
+rule type-from-rule-name ( rule-name )
+{
+ return $(.main-target-type.$(rule-name)) ;
+}
+
+
+# Specifies that files with suffix from 'suffixes' be recognized as targets of
+# type 'type'. Issues an error if a different type is already specified for any
+# of the suffixes.
+#
+rule register-suffixes ( suffixes + : type )
+{
+ for local s in $(suffixes)
+ {
+ if ! $(.type.$(s))
+ {
+ .type.$(s) = $(type) ;
+ }
+ else if $(.type.$(s)) != $(type)
+ {
+ errors.error Attempting to specify multiple types for suffix
+ \"$(s)\" : "Old type $(.type.$(s)), New type $(type)" ;
+ }
+ }
+}
+
+
+# Returns true iff type has been registered.
+#
+rule registered ( type )
+{
+ if $(type) in $(.types)
+ {
+ return true ;
+ }
+}
+
+
+# Issues an error if 'type' is unknown.
+#
+rule validate ( type )
+{
+ if ! [ registered $(type) ]
+ {
+ errors.error "Unknown target type $(type)" ;
+ }
+}
+
+
+# Sets a scanner class that will be used for this 'type'.
+#
+rule set-scanner ( type : scanner )
+{
+ validate $(type) ;
+ .scanner.$(type) = $(scanner) ;
+}
+
+
+# Returns a scanner instance appropriate to 'type' and 'properties'.
+#
+rule get-scanner ( type : property-set )
+{
+ if $(.scanner.$(type))
+ {
+ return [ scanner.get $(.scanner.$(type)) : $(property-set) ] ;
+ }
+}
+
+
+# Returns a base type for the given type or nothing in case the given type is
+# not derived.
+#
+rule base ( type )
+{
+ return $(.base.$(type)) ;
+}
+
+
+# Returns the given type and all of its base types in order of their distance
+# from type.
+#
+rule all-bases ( type )
+{
+ local result = $(type) ;
+ while $(type)
+ {
+ type = [ base $(type) ] ;
+ result += $(type) ;
+ }
+ return $(result) ;
+}
+
+
+# Returns the given type and all of its derived types in order of their distance
+# from type.
+#
+rule all-derived ( type )
+{
+ local result = $(type) ;
+ for local d in $(.derived.$(type))
+ {
+ result += [ all-derived $(d) ] ;
+ }
+ return $(result) ;
+}
+
+
+# Returns true if 'type' is equal to 'base' or has 'base' as its direct or
+# indirect base.
+#
+rule is-derived ( type base )
+{
+ if $(base) in [ all-bases $(type) ]
+ {
+ return true ;
+ }
+}
+
+# Returns true if 'type' is either derived from or is equal to 'base'.
+#
+# TODO: It might be that is-derived and is-subtype were meant to be different
+# rules - one returning true for type = base and one not, but as currently
+# implemented they are actually the same. Clean this up.
+#
+rule is-subtype ( type base )
+{
+ return [ is-derived $(type) $(base) ] ;
+}
+
+
+# Store suffixes for generated targets.
+.suffixes = [ new property-map ] ;
+
+# Store prefixes for generated targets (e.g. "lib" for library).
+.prefixes = [ new property-map ] ;
+
+
+# Sets a file suffix to be used when generating a target of 'type' with the
+# specified properties. Can be called with no properties if no suffix has
+# already been specified for the 'type'. The 'suffix' parameter can be an empty
+# string ("") to indicate that no suffix should be used.
+#
+# Note that this does not cause files with 'suffix' to be automatically
+# recognized as being of 'type'. Two different types can use the same suffix for
+# their generated files but only one type can be auto-detected for a file with
+# that suffix. User should explicitly specify which one using the
+# register-suffixes rule.
+#
+rule set-generated-target-suffix ( type : properties * : suffix )
+{
+ set-generated-target-ps suffix : $(type) : $(properties) : $(suffix) ;
+}
+
+
+# Change the suffix previously registered for this type/properties combination.
+# If suffix is not yet specified, sets it.
+#
+rule change-generated-target-suffix ( type : properties * : suffix )
+{
+ change-generated-target-ps suffix : $(type) : $(properties) : $(suffix) ;
+}
+
+
+# Returns the suffix used when generating a file of 'type' with the given
+# properties.
+#
+rule generated-target-suffix ( type : property-set )
+{
+ return [ generated-target-ps suffix : $(type) : $(property-set) ] ;
+}
+
+
+# Sets a target prefix that should be used when generating targets of 'type'
+# with the specified properties. Can be called with empty properties if no
+# prefix for 'type' has been specified yet.
+#
+# The 'prefix' parameter can be empty string ("") to indicate that no prefix
+# should be used.
+#
+# Usage example: library names use the "lib" prefix on unix.
+#
+rule set-generated-target-prefix ( type : properties * : prefix )
+{
+ set-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ;
+}
+
+
+# Change the prefix previously registered for this type/properties combination.
+# If prefix is not yet specified, sets it.
+#
+rule change-generated-target-prefix ( type : properties * : prefix )
+{
+ change-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ;
+}
+
+
+rule generated-target-prefix ( type : property-set )
+{
+ return [ generated-target-ps prefix : $(type) : $(property-set) ] ;
+}
+
+
+# Common rules for prefix/suffix provisioning follow.
+
+local rule set-generated-target-ps ( ps : type : properties * : psval )
+{
+ properties = <target-type>$(type) $(properties) ;
+ $(.$(ps)es).insert $(properties) : $(psval) ;
+}
+
+
+local rule change-generated-target-ps ( ps : type : properties * : psval )
+{
+ properties = <target-type>$(type) $(properties) ;
+ local prev = [ $(.$(ps)es).find-replace $(properties) : $(psval) ] ;
+ if ! $(prev)
+ {
+ set-generated-target-ps $(ps) : $(type) : $(properties) : $(psval) ;
+ }
+}
+
+
+# Returns either prefix or suffix (as indicated by 'ps') that should be used
+# when generating a target of 'type' with the specified properties. Parameter
+# 'ps' can be either "prefix" or "suffix". If no prefix/suffix is specified for
+# 'type', returns prefix/suffix for base type, if any.
+#
+local rule generated-target-ps-real ( ps : type : properties * )
+{
+ local result ;
+ local found ;
+ while $(type) && ! $(found)
+ {
+ result = [ $(.$(ps)es).find <target-type>$(type) $(properties) ] ;
+ # If the prefix/suffix is explicitly set to an empty string, we consider
+ # prefix/suffix to be found. If we were not to compare with "", there
+ # would be no way to specify an empty prefix/suffix.
+ if $(result)-is-not-empty
+ {
+ found = true ;
+ }
+ type = $(.base.$(type)) ;
+ }
+ if $(result) = ""
+ {
+ result = ;
+ }
+ return $(result) ;
+}
+
+
+local rule generated-target-ps ( ps : type : property-set )
+{
+ local key = .$(ps).$(type).$(property-set) ;
+ local v = $($(key)) ;
+ if ! $(v)
+ {
+ v = [ generated-target-ps-real $(ps) : $(type) : [ $(property-set).raw ]
+ ] ;
+ if ! $(v)
+ {
+ v = none ;
+ }
+ $(key) = $(v) ;
+ }
+
+ if $(v) != none
+ {
+ return $(v) ;
+ }
+}
+
+
+# Returns file type given its name. If there are several dots in filename, tries
+# each suffix. E.g. for name of "file.so.1.2" suffixes "2", "1", and "so" will
+# be tried.
+#
+rule type ( filename )
+{
+ if [ os.name ] in NT CYGWIN
+ {
+ filename = $(filename:L) ;
+ }
+ local type ;
+ while ! $(type) && $(filename:S)
+ {
+ local suffix = $(filename:S) ;
+ type = $(.type$(suffix)) ;
+ filename = $(filename:S=) ;
+ }
+ return $(type) ;
+}
+
+
+# Rule used to construct all main targets. Note that this rule gets imported
+# into the global namespace under different alias names and the exact target
+# type to construct is selected based on the alias used to actually invoke this
+# rule.
+#
+rule main-target-rule ( name : sources * : requirements * : default-build * :
+ usage-requirements * )
+{
+ # First discover the required target type based on the exact alias used to
+ # invoke this rule.
+ local bt = [ BACKTRACE 1 ] ;
+ local rulename = $(bt[4]) ;
+ local target-type = [ type-from-rule-name $(rulename) ] ;
+
+ # This is a circular module dependency and so must be imported here.
+ import targets ;
+
+ return [ targets.create-typed-target $(target-type) : [ project.current ] :
+ $(name) : $(sources) : $(requirements) : $(default-build) :
+ $(usage-requirements) ] ;
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+
+ # TODO: Add tests for all the is-derived, is-base & related type relation
+ # checking rules.
+}
diff --git a/tools/build/v2/build/type.py b/tools/build/v2/build/type.py
new file mode 100644
index 0000000000..ddb7ba09d2
--- /dev/null
+++ b/tools/build/v2/build/type.py
@@ -0,0 +1,313 @@
+# Status: ported.
+# Base revision: 45462.
+
+# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+
+
+import re
+import os
+import os.path
+from b2.util.utility import replace_grist, os_name
+from b2.exceptions import *
+from b2.build import feature, property, scanner
+from b2.util import bjam_signature
+
+
+__re_hyphen = re.compile ('-')
+
+def __register_features ():
+ """ Register features need by this module.
+ """
+ # The feature is optional so that it is never implicitly added.
+ # It's used only for internal purposes, and in all cases we
+ # want to explicitly use it.
+ feature.feature ('target-type', [], ['composite', 'optional'])
+ feature.feature ('main-target-type', [], ['optional', 'incidental'])
+ feature.feature ('base-target-type', [], ['composite', 'optional', 'free'])
+
+def reset ():
+ """ Clear the module state. This is mainly for testing purposes.
+ Note that this must be called _after_ resetting the module 'feature'.
+ """
+ global __prefixes_suffixes, __suffixes_to_types, __types, __rule_names_to_types, __target_suffixes_cache
+
+ __register_features ()
+
+ # Stores suffixes for generated targets.
+ __prefixes_suffixes = [property.PropertyMap(), property.PropertyMap()]
+
+ # Maps suffixes to types
+ __suffixes_to_types = {}
+
+ # A map with all the registered types, indexed by the type name
+ # Each entry is a dictionary with following values:
+ # 'base': the name of base type or None if type has no base
+ # 'derived': a list of names of type which derive from this one
+ # 'scanner': the scanner class registered for this type, if any
+ __types = {}
+
+ # Caches suffixes for targets with certain properties.
+ __target_suffixes_cache = {}
+
+reset ()
+
+@bjam_signature((["type"], ["suffixes", "*"], ["base_type", "?"]))
+def register (type, suffixes = [], base_type = None):
+ """ Registers a target type, possibly derived from a 'base-type'.
+ If 'suffixes' are provided, they list all the suffixes that mean a file is of 'type'.
+ Also, the first element gives the suffix to be used when constructing and object of
+ 'type'.
+ type: a string
+ suffixes: None or a sequence of strings
+ base_type: None or a string
+ """
+ # Type names cannot contain hyphens, because when used as
+ # feature-values they will be interpreted as composite features
+ # which need to be decomposed.
+ if __re_hyphen.search (type):
+ raise BaseException ('type name "%s" contains a hyphen' % type)
+
+ if __types.has_key (type):
+ raise BaseException ('Type "%s" is already registered.' % type)
+
+ entry = {}
+ entry ['base'] = base_type
+ entry ['derived'] = []
+ entry ['scanner'] = None
+ __types [type] = entry
+
+ if base_type:
+ __types [base_type]['derived'].append (type)
+
+ if len (suffixes) > 0:
+ # Generated targets of 'type' will use the first of 'suffixes'
+ # (this may be overriden)
+ set_generated_target_suffix (type, [], suffixes [0])
+
+ # Specify mapping from suffixes to type
+ register_suffixes (suffixes, type)
+
+ feature.extend('target-type', [type])
+ feature.extend('main-target-type', [type])
+ feature.extend('base-target-type', [type])
+
+ if base_type:
+ feature.compose ('<target-type>' + type, replace_grist (base_type, '<base-target-type>'))
+ feature.compose ('<base-target-type>' + type, '<base-target-type>' + base_type)
+
+ import b2.build.generators as generators
+ # Adding a new derived type affects generator selection so we need to
+ # make the generator selection module update any of its cached
+ # information related to a new derived type being defined.
+ generators.update_cached_information_with_a_new_type(type)
+
+ # FIXME: resolving recursive dependency.
+ from b2.manager import get_manager
+ get_manager().projects().project_rules().add_rule_for_type(type)
+
+# FIXME: quick hack.
+def type_from_rule_name(rule_name):
+ return rule_name.upper().replace("-", "_")
+
+
+def register_suffixes (suffixes, type):
+ """ Specifies that targets with suffix from 'suffixes' have the type 'type'.
+ If a different type is already specified for any of syffixes, issues an error.
+ """
+ for s in suffixes:
+ if __suffixes_to_types.has_key (s):
+ old_type = __suffixes_to_types [s]
+ if old_type != type:
+ raise BaseException ('Attempting to specify type for suffix "%s"\nOld type: "%s", New type "%s"' % (s, old_type, type))
+ else:
+ __suffixes_to_types [s] = type
+
+def registered (type):
+ """ Returns true iff type has been registered.
+ """
+ return __types.has_key (type)
+
+def validate (type):
+ """ Issues an error if 'type' is unknown.
+ """
+ if not registered (type):
+ raise BaseException ("Unknown target type '%s'" % type)
+
+def set_scanner (type, scanner):
+ """ Sets a scanner class that will be used for this 'type'.
+ """
+ validate (type)
+ __types [type]['scanner'] = scanner
+
+def get_scanner (type, prop_set):
+ """ Returns a scanner instance appropriate to 'type' and 'property_set'.
+ """
+ if registered (type):
+ scanner_type = __types [type]['scanner']
+ if scanner_type:
+ return scanner.get (scanner_type, prop_set.raw ())
+ pass
+
+ return None
+
+def base(type):
+ """Returns a base type for the given type or nothing in case the given type is
+ not derived."""
+
+ return __types[type]['base']
+
+def all_bases (type):
+ """ Returns type and all of its bases, in the order of their distance from type.
+ """
+ result = []
+ while type:
+ result.append (type)
+ type = __types [type]['base']
+
+ return result
+
+def all_derived (type):
+ """ Returns type and all classes that derive from it, in the order of their distance from type.
+ """
+ result = [type]
+ for d in __types [type]['derived']:
+ result.extend (all_derived (d))
+
+ return result
+
+def is_derived (type, base):
+ """ Returns true if 'type' is 'base' or has 'base' as its direct or indirect base.
+ """
+ # TODO: this isn't very efficient, especially for bases close to type
+ if base in all_bases (type):
+ return True
+ else:
+ return False
+
+def is_subtype (type, base):
+ """ Same as is_derived. Should be removed.
+ """
+ # TODO: remove this method
+ return is_derived (type, base)
+
+@bjam_signature((["type"], ["properties", "*"], ["suffix"]))
+def set_generated_target_suffix (type, properties, suffix):
+ """ Sets a target suffix that should be used when generating target
+ of 'type' with the specified properties. Can be called with
+ empty properties if no suffix for 'type' was specified yet.
+ This does not automatically specify that files 'suffix' have
+ 'type' --- two different types can use the same suffix for
+ generating, but only one type should be auto-detected for
+ a file with that suffix. User should explicitly specify which
+ one.
+
+ The 'suffix' parameter can be empty string ("") to indicate that
+ no suffix should be used.
+ """
+ set_generated_target_ps(1, type, properties, suffix)
+
+
+
+def change_generated_target_suffix (type, properties, suffix):
+ """ Change the suffix previously registered for this type/properties
+ combination. If suffix is not yet specified, sets it.
+ """
+ change_generated_target_ps(1, type, properties, suffix)
+
+def generated_target_suffix(type, properties):
+ return generated_target_ps(1, type, properties)
+
+# Sets a target prefix that should be used when generating targets of 'type'
+# with the specified properties. Can be called with empty properties if no
+# prefix for 'type' has been specified yet.
+#
+# The 'prefix' parameter can be empty string ("") to indicate that no prefix
+# should be used.
+#
+# Usage example: library names use the "lib" prefix on unix.
+@bjam_signature((["type"], ["properties", "*"], ["suffix"]))
+def set_generated_target_prefix(type, properties, prefix):
+ set_generated_target_ps(0, type, properties, prefix)
+
+# Change the prefix previously registered for this type/properties combination.
+# If prefix is not yet specified, sets it.
+def change_generated_target_prefix(type, properties, prefix):
+ change_generated_target_ps(0, type, properties, prefix)
+
+def generated_target_prefix(type, properties):
+ return generated_target_ps(0, type, properties)
+
+def set_generated_target_ps(is_suffix, type, properties, val):
+ properties.append ('<target-type>' + type)
+ __prefixes_suffixes[is_suffix].insert (properties, val)
+
+def change_generated_target_ps(is_suffix, type, properties, val):
+ properties.append ('<target-type>' + type)
+ prev = __prefixes_suffixes[is_suffix].find_replace(properties, val)
+ if not prev:
+ set_generated_target_ps(is_suffix, type, properties, val)
+
+# Returns either prefix or suffix (as indicated by 'is_suffix') that should be used
+# when generating a target of 'type' with the specified properties.
+# If no prefix/suffix is specified for 'type', returns prefix/suffix for
+# base type, if any.
+def generated_target_ps_real(is_suffix, type, properties):
+
+ result = ''
+ found = False
+ while type and not found:
+ result = __prefixes_suffixes[is_suffix].find (['<target-type>' + type] + properties)
+
+ # Note that if the string is empty (""), but not null, we consider
+ # suffix found. Setting prefix or suffix to empty string is fine.
+ if result is not None:
+ found = True
+
+ type = __types [type]['base']
+
+ if not result:
+ result = ''
+ return result
+
+def generated_target_ps(is_suffix, type, prop_set):
+ """ Returns suffix that should be used when generating target of 'type',
+ with the specified properties. If not suffix were specified for
+ 'type', returns suffix for base type, if any.
+ """
+ key = (is_suffix, type, prop_set)
+ v = __target_suffixes_cache.get(key, None)
+
+ if not v:
+ v = generated_target_ps_real(is_suffix, type, prop_set.raw())
+ __target_suffixes_cache [key] = v
+
+ return v
+
+def type(filename):
+ """ Returns file type given it's name. If there are several dots in filename,
+ tries each suffix. E.g. for name of "file.so.1.2" suffixes "2", "1", and
+ "so" will be tried.
+ """
+ while 1:
+ filename, suffix = os.path.splitext (filename)
+ if not suffix: return None
+ suffix = suffix[1:]
+
+ if __suffixes_to_types.has_key(suffix):
+ return __suffixes_to_types[suffix]
+
+# NOTE: moved from tools/types/register
+def register_type (type, suffixes, base_type = None, os = []):
+ """ Register the given type on the specified OSes, or on remaining OSes
+ if os is not specified. This rule is injected into each of the type
+ modules for the sake of convenience.
+ """
+ if registered (type):
+ return
+
+ if not os or os_name () in os:
+ register (type, suffixes, base_type)
diff --git a/tools/build/v2/build/version.jam b/tools/build/v2/build/version.jam
new file mode 100644
index 0000000000..7626ddda8d
--- /dev/null
+++ b/tools/build/v2/build/version.jam
@@ -0,0 +1,161 @@
+# Copyright 2002, 2003, 2004, 2006 Vladimir Prus
+# Copyright 2008 Jurko Gospodnetic
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import errors ;
+import numbers ;
+
+major = "2011" ;
+minor = "04" ;
+
+rule boost-build ( )
+{
+ return "$(major).$(minor)-svn" ;
+}
+
+rule print ( )
+{
+ if [ verify-engine-version ]
+ {
+ ECHO "Boost.Build" [ boost-build ] ;
+ }
+}
+
+rule verify-engine-version ( )
+{
+ local v = [ modules.peek : JAM_VERSION ] ;
+
+ if $(v[1]) != $(major) || $(v[2]) != $(minor)
+ {
+ local argv = [ modules.peek : ARGV ] ;
+ local e = $(argv[1]) ;
+ local l = [ modules.binding version ] ;
+ l = $(l:D) ;
+ l = $(l:D) ;
+ ECHO "warning: mismatched versions of Boost.Build engine and core" ;
+ ECHO "warning: Boost.Build engine ($(e)) is $(v:J=.)" ;
+ ECHO "warning: Boost.Build core (at $(l)) is" [ boost-build ] ;
+ }
+ else
+ {
+ return true ;
+ }
+}
+
+
+
+# Utility rule for testing whether all elements in a sequence are equal to 0.
+#
+local rule is-all-zeroes ( sequence * )
+{
+ local result = "true" ;
+ for local e in $(sequence)
+ {
+ if $(e) != "0"
+ {
+ result = "" ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Returns "true" if the first version is less than the second one.
+#
+rule version-less ( lhs + : rhs + )
+{
+ numbers.check $(lhs) ;
+ numbers.check $(rhs) ;
+
+ local done ;
+ local result ;
+
+ while ! $(done) && $(lhs) && $(rhs)
+ {
+ if [ numbers.less $(lhs[1]) $(rhs[1]) ]
+ {
+ done = "true" ;
+ result = "true" ;
+ }
+ else if [ numbers.less $(rhs[1]) $(lhs[1]) ]
+ {
+ done = "true" ;
+ }
+ else
+ {
+ lhs = $(lhs[2-]) ;
+ rhs = $(rhs[2-]) ;
+ }
+ }
+ if ( ! $(done) && ! $(lhs) && ! [ is-all-zeroes $(rhs) ] )
+ {
+ result = "true" ;
+ }
+
+ return $(result) ;
+}
+
+
+# Returns "true" if the current JAM version version is at least the given
+# version.
+#
+rule check-jam-version ( version + )
+{
+ local version-tag = $(version:J=.) ;
+ if ! $(version-tag)
+ {
+ errors.error Invalid version specifier: : $(version:E="(undefined)") ;
+ }
+
+ if ! $(.jam-version-check.$(version-tag))-is-not-empty
+ {
+ local jam-version = [ modules.peek : JAM_VERSION ] ;
+ if ! $(jam-version)
+ {
+ errors.error "Unable to deduce Boost Jam version. Your Boost Jam"
+ "installation is most likely terribly outdated." ;
+ }
+ .jam-version-check.$(version-tag) = "true" ;
+ if [ version-less [ modules.peek : JAM_VERSION ] : $(version) ]
+ {
+ .jam-version-check.$(version-tag) = "" ;
+ }
+ }
+ return $(.jam-version-check.$(version-tag)) ;
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+
+ local jam-version = [ modules.peek : JAM_VERSION ] ;
+ local future-version = $(jam-version) ;
+ future-version += "1" ;
+
+ assert.true check-jam-version $(jam-version) ;
+ assert.false check-jam-version $(future-version) ;
+
+ assert.true version-less 0 : 1 ;
+ assert.false version-less 0 : 0 ;
+ assert.true version-less 1 : 2 ;
+ assert.false version-less 1 : 1 ;
+ assert.false version-less 2 : 1 ;
+ assert.true version-less 3 1 20 : 3 4 10 ;
+ assert.false version-less 3 1 10 : 3 1 10 ;
+ assert.false version-less 3 4 10 : 3 1 20 ;
+ assert.true version-less 3 1 20 5 1 : 3 4 10 ;
+ assert.false version-less 3 1 10 5 1 : 3 1 10 ;
+ assert.false version-less 3 4 10 5 1 : 3 1 20 ;
+ assert.true version-less 3 1 20 : 3 4 10 5 1 ;
+ assert.true version-less 3 1 10 : 3 1 10 5 1 ;
+ assert.false version-less 3 4 10 : 3 1 20 5 1 ;
+ assert.false version-less 3 1 10 : 3 1 10 0 0 ;
+ assert.false version-less 3 1 10 0 0 : 3 1 10 ;
+ assert.false version-less 3 1 10 0 : 3 1 10 0 0 ;
+ assert.false version-less 3 1 10 0 : 03 1 10 0 0 ;
+ assert.false version-less 03 1 10 0 : 3 1 10 0 0 ;
+
+ # TODO: Add tests for invalid input data being sent to version-less.
+}
diff --git a/tools/build/v2/build/virtual-target.jam b/tools/build/v2/build/virtual-target.jam
new file mode 100644
index 0000000000..2e8446bcc8
--- /dev/null
+++ b/tools/build/v2/build/virtual-target.jam
@@ -0,0 +1,1317 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2005, 2006 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Implements virtual targets, which correspond to actual files created during a
+# build, but are not yet targets in Jam sense. They are needed, for example,
+# when searching for possible transformation sequences, when it is not yet known
+# whether a particular target should be created at all.
+
+import "class" : new ;
+import errors ;
+import path ;
+import sequence ;
+import set ;
+import type ;
+import utility ;
+
+
+# +--------------------------+
+# | virtual-target |
+# +==========================+
+# | actualize |
+# +--------------------------+
+# | actualize-action() = 0 |
+# | actualize-location() = 0 |
+# +----------------+---------+
+# |
+# ^
+# / \
+# +-+-+
+# |
+# +---------------------+ +-------+--------------+
+# | action | | abstract-file-target |
+# +=====================| * +======================+
+# | action-name | +--+ action |
+# | properties | | +----------------------+
+# +---------------------+--+ | actualize-action() |
+# | actualize() |0..1 +-----------+----------+
+# | path() | |
+# | adjust-properties() | sources |
+# | actualize-sources() | targets |
+# +------+--------------+ ^
+# | / \
+# ^ +-+-+
+# / \ |
+# +-+-+ +-------------+-------------+
+# | | |
+# | +------+---------------+ +--------+-------------+
+# | | file-target | | searched-lib-target |
+# | +======================+ +======================+
+# | | actualize-location() | | actualize-location() |
+# | +----------------------+ +----------------------+
+# |
+# +-+------------------------------+
+# | |
+# +----+----------------+ +---------+-----------+
+# | compile-action | | link-action |
+# +=====================+ +=====================+
+# | adjust-properties() | | adjust-properties() |
+# +---------------------+ | actualize-sources() |
+# +---------------------+
+#
+# The 'compile-action' and 'link-action' classes are not defined here but in
+# builtin.jam modules. They are shown in the diagram to give the big picture.
+
+
+# Models a potential target. It can be converted into a Jam target and used in
+# building, if needed. However, it can be also dropped, which allows us to
+# search for different transformations and select only one.
+#
+class virtual-target
+{
+ import scanner ;
+ import sequence ;
+ import utility ;
+ import virtual-target ;
+
+ rule __init__ (
+ name # Target/project name.
+ : project # Project to which this target belongs.
+ )
+ {
+ self.name = $(name) ;
+ self.project = $(project) ;
+ self.dependencies = ;
+ }
+
+ # Name of this target.
+ #
+ rule name ( )
+ {
+ return $(self.name) ;
+ }
+
+ # Project of this target.
+ #
+ rule project ( )
+ {
+ return $(self.project) ;
+ }
+
+ # Adds additional 'virtual-target' instances this one depends on.
+ #
+ rule depends ( d + )
+ {
+ self.dependencies = [ sequence.merge $(self.dependencies) :
+ [ sequence.insertion-sort $(d) ] ] ;
+ }
+
+ rule dependencies ( )
+ {
+ return $(self.dependencies) ;
+ }
+
+ rule always ( )
+ {
+ .always = 1 ;
+ }
+
+ # Generates all the actual targets and sets up build actions for this
+ # target.
+ #
+ # If 'scanner' is specified, creates an additional target with the same
+ # location as the actual target, which will depend on the actual target and
+ # be associated with a 'scanner'. That additional target is returned. See
+ # the docs (#dependency_scanning) for rationale. Target must correspond to a
+ # file if 'scanner' is specified.
+ #
+ # If scanner is not specified then the actual target is returned.
+ #
+ rule actualize ( scanner ? )
+ {
+ local actual-name = [ actualize-no-scanner ] ;
+
+ if $(.always)
+ {
+ ALWAYS $(actual-name) ;
+ }
+
+ if ! $(scanner)
+ {
+ return $(actual-name) ;
+ }
+ else
+ {
+ # Add the scanner instance to the grist for name.
+ local g = [ sequence.join
+ [ utility.ungrist $(actual-name:G) ] $(scanner) : - ] ;
+ local name = $(actual-name:G=$(g)) ;
+
+ if ! $(self.made.$(name))
+ {
+ self.made.$(name) = true ;
+
+ DEPENDS $(name) : $(actual-name) ;
+
+ actualize-location $(name) ;
+
+ scanner.install $(scanner) : $(name) $(__name__) ;
+ }
+ return $(name) ;
+ }
+ }
+
+# private: (overridables)
+
+ # Sets up build actions for 'target'. Should call appropriate rules and set
+ # target variables.
+ #
+ rule actualize-action ( target )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+
+ # Sets up variables on 'target' which specify its location.
+ #
+ rule actualize-location ( target )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+
+ # If the target is a generated one, returns the path where it will be
+ # generated. Otherwise, returns an empty list.
+ #
+ rule path ( )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+
+ # Returns the actual target name to be used in case when no scanner is
+ # involved.
+ #
+ rule actual-name ( )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+
+# implementation
+ rule actualize-no-scanner ( )
+ {
+ # In fact, we just need to merge virtual-target with
+ # abstract-file-target as the latter is the only class derived from the
+ # former. But that has been left for later.
+
+ errors.error "method should be defined in derived classes" ;
+ }
+}
+
+
+# Target corresponding to a file. The exact mapping for file is not yet
+# specified in this class. (TODO: Actually, the class name could be better...)
+#
+# May be a source file (when no action is specified) or a derived file
+# (otherwise).
+#
+# The target's grist is a concatenation of its project's location, action
+# properties (for derived targets) and, optionally, value identifying the main
+# target.
+#
+class abstract-file-target : virtual-target
+{
+ import project ;
+ import regex ;
+ import sequence ;
+ import path ;
+ import type ;
+ import property-set ;
+ import indirect ;
+
+ rule __init__ (
+ name # Target's name.
+ exact ? # If non-empty, the name is exactly the name created file
+ # should have. Otherwise, the '__init__' method will add a
+ # suffix obtained from 'type' by calling
+ # 'type.generated-target-suffix'.
+ : type ? # Target's type.
+ : project
+ : action ?
+ )
+ {
+ virtual-target.__init__ $(name) : $(project) ;
+
+ self.type = $(type) ;
+ self.action = $(action) ;
+ if $(action)
+ {
+ $(action).add-targets $(__name__) ;
+
+ if $(self.type) && ! $(exact)
+ {
+ _adjust-name $(name) ;
+ }
+ }
+ }
+
+ rule type ( )
+ {
+ return $(self.type) ;
+ }
+
+ # Sets the path. When generating target name, it will override any path
+ # computation from properties.
+ #
+ rule set-path ( path )
+ {
+ self.path = [ path.native $(path) ] ;
+ }
+
+ # Returns the currently set action.
+ #
+ rule action ( )
+ {
+ return $(self.action) ;
+ }
+
+ # Sets/gets the 'root' flag. Target is root if it directly corresponds to
+ # some variant of a main target.
+ #
+ rule root ( set ? )
+ {
+ if $(set)
+ {
+ self.root = true ;
+ }
+ return $(self.root) ;
+ }
+
+ # Gets or sets the subvariant which created this target. Subvariant is set
+ # when target is brought into existance and is never changed after that. In
+ # particular, if a target is shared by a subvariant, only the first is
+ # stored.
+ #
+ rule creating-subvariant ( s ? # If specified, specifies the value to set,
+ # which should be a 'subvariant' class
+ # instance.
+ )
+ {
+ if $(s) && ! $(self.creating-subvariant)
+ {
+ self.creating-subvariant = $(s) ;
+ }
+ return $(self.creating-subvariant) ;
+ }
+
+ rule actualize-action ( target )
+ {
+ if $(self.action)
+ {
+ $(self.action).actualize ;
+ }
+ }
+
+ # Return a human-readable representation of this target. If this target has
+ # an action, that is:
+ #
+ # { <action-name>-<self.name>.<self.type> <action-sources>... }
+ #
+ # otherwise, it is:
+ #
+ # { <self.name>.<self.type> }
+ #
+ rule str ( )
+ {
+ local action = [ action ] ;
+ local name-dot-type = [ sequence.join $(self.name) "." $(self.type) ] ;
+
+ if $(action)
+ {
+ local sources = [ $(action).sources ] ;
+ local action-name = [ $(action).action-name ] ;
+
+ local ss ;
+ for local s in $(sources)
+ {
+ ss += [ $(s).str ] ;
+ }
+
+ return "{" $(action-name)-$(name-dot-type) $(ss) "}" ;
+ }
+ else
+ {
+ return "{" $(name-dot-type) "}" ;
+ }
+ }
+
+ rule less ( a )
+ {
+ if [ str ] < [ $(a).str ]
+ {
+ return true ;
+ }
+ }
+
+ rule equal ( a )
+ {
+ if [ str ] = [ $(a).str ]
+ {
+ return true ;
+ }
+ }
+
+# private:
+ rule actual-name ( )
+ {
+ if ! $(self.actual-name)
+ {
+ local grist = [ grist ] ;
+ local basename = [ path.native $(self.name) ] ;
+ self.actual-name = <$(grist)>$(basename) ;
+ }
+ return $(self.actual-name) ;
+ }
+
+ # Helper to 'actual-name', above. Computes a unique prefix used to
+ # distinguish this target from other targets with the same name creating
+ # different files.
+ #
+ rule grist ( )
+ {
+ # Depending on target, there may be different approaches to generating
+ # unique prefixes. We generate prefixes in the form:
+ # <one letter approach code> <the actual prefix>
+ local path = [ path ] ;
+ if $(path)
+ {
+ # The target will be generated to a known path. Just use the path
+ # for identification, since path is as unique as it can get.
+ return p$(path) ;
+ }
+ else
+ {
+ # File is either source, which will be searched for, or is not a
+ # file at all. Use the location of project for distinguishing.
+ local project-location = [ $(self.project).get location ] ;
+ local location-grist = [ sequence.join [ regex.split
+ $(project-location) "/" ] : "!" ] ;
+
+ if $(self.action)
+ {
+ local ps = [ $(self.action).properties ] ;
+ local property-grist = [ $(ps).as-path ] ;
+ # 'property-grist' can be empty when 'ps' is an empty property
+ # set.
+ if $(property-grist)
+ {
+ location-grist = $(location-grist)/$(property-grist) ;
+ }
+ }
+
+ return l$(location-grist) ;
+ }
+ }
+
+ # Given the target name specified in constructor, returns the name which
+ # should be really used, by looking at the <tag> properties. Tag properties
+ # need to be specified as <tag>@rule-name. This makes Boost Build call the
+ # specified rule with the target name, type and properties to get the new
+ # name. If no <tag> property is specified or the rule specified by <tag>
+ # returns nothing, returns the result of calling
+ # virtual-target.add-prefix-and-suffix.
+ #
+ rule _adjust-name ( specified-name )
+ {
+ local ps ;
+ if $(self.action)
+ {
+ ps = [ $(self.action).properties ] ;
+ }
+ else
+ {
+ ps = [ property-set.empty ] ;
+ }
+
+ # We add ourselves to the properties so that any tag rule can get more
+ # direct information about the target than just that available through
+ # the properties. This is useful in implementing name changes based on
+ # the sources of the target. For example to make unique names of object
+ # files based on the source file. --grafik
+ ps = [ property-set.create [ $(ps).raw ] <target>$(__name__) ] ;
+
+ local tag = [ $(ps).get <tag> ] ;
+
+ if $(tag)
+ {
+ local rule-name = [ MATCH ^@(.*) : $(tag) ] ;
+ if $(rule-name)
+ {
+ if $(tag[2])
+ {
+ errors.error "<tag>@rulename is present but is not the only"
+ "<tag> feature" ;
+ }
+
+ self.name = [ indirect.call $(rule-name) $(specified-name)
+ : $(self.type) : $(ps) ] ;
+ }
+ else
+ {
+ errors.error
+ "The value of the <tag> feature must be '@rule-name'" ;
+ }
+ }
+
+ # If there is no tag or the tag rule returned nothing.
+ if ! $(tag) || ! $(self.name)
+ {
+ self.name = [ virtual-target.add-prefix-and-suffix $(specified-name)
+ : $(self.type) : $(ps) ] ;
+ }
+ }
+
+ rule actualize-no-scanner ( )
+ {
+ local name = [ actual-name ] ;
+
+ # Do anything only on the first invocation.
+ if ! $(self.made.$(name))
+ {
+ self.made.$(name) = true ;
+
+ if $(self.action)
+ {
+ # For non-derived target, we do not care if there are several
+ # virtual targets that refer to the same name. One case when
+ # this is unavoidable is when the file name is main.cpp and two
+ # targets have types CPP (for compiling) and MOCCABLE_CPP (for
+ # conversion to H via Qt tools).
+ virtual-target.register-actual-name $(name) : $(__name__) ;
+ }
+
+ for local i in $(self.dependencies)
+ {
+ DEPENDS $(name) : [ $(i).actualize ] ;
+ }
+
+ actualize-location $(name) ;
+ actualize-action $(name) ;
+ }
+ return $(name) ;
+ }
+}
+
+
+# Appends the suffix appropriate to 'type/property-set' combination to the
+# specified name and returns the result.
+#
+rule add-prefix-and-suffix ( specified-name : type ? : property-set )
+{
+ local suffix = [ type.generated-target-suffix $(type) : $(property-set) ] ;
+
+ # Handle suffixes for which no leading dot is desired. Those are specified
+ # by enclosing them in <...>. Needed by python so it can create "_d.so"
+ # extensions, for example.
+ if $(suffix:G)
+ {
+ suffix = [ utility.ungrist $(suffix) ] ;
+ }
+ else
+ {
+ suffix = .$(suffix) ;
+ }
+
+ local prefix = [ type.generated-target-prefix $(type) : $(property-set) ] ;
+
+ if [ MATCH ^($(prefix)) : $(specified-name) ]
+ {
+ prefix = ;
+ }
+ return $(prefix:E="")$(specified-name)$(suffix:E="") ;
+}
+
+
+# File targets with explicitly known location.
+#
+# The file path is determined as
+# * Value passed to the 'set-path' method, if any.
+# * For derived files, project's build dir, joined with components that
+# describe action properties. If free properties are not equal to the
+# project's reference properties an element with the name of the main
+# target is added.
+# * For source files, project's source dir.
+#
+# The file suffix is determined as:
+# * The value passed to the 'suffix' method, if any.
+# * The suffix corresponding to the target's type.
+#
+class file-target : abstract-file-target
+{
+ import "class" : new ;
+ import common ;
+ import errors ;
+
+ rule __init__ (
+ name exact ?
+ : type ? # Optional type for this target.
+ : project
+ : action ?
+ : path ?
+ )
+ {
+ abstract-file-target.__init__ $(name) $(exact) : $(type) : $(project) :
+ $(action) ;
+
+ self.path = $(path) ;
+ }
+
+ rule clone-with-different-type ( new-type )
+ {
+ return [ new file-target $(self.name) exact : $(new-type) :
+ $(self.project) : $(self.action) : $(self.path) ] ;
+ }
+
+ rule actualize-location ( target )
+ {
+ if $(self.action)
+ {
+ # This is a derived file.
+ local path = [ path ] ;
+ LOCATE on $(target) = $(path) ;
+
+ # Make sure the path exists.
+ DEPENDS $(target) : $(path) ;
+ common.MkDir $(path) ;
+
+ # It is possible that the target name includes a directory too, for
+ # example when installing headers. Create that directory.
+ if $(target:D)
+ {
+ local d = $(target:D) ;
+ d = $(d:R=$(path)) ;
+ DEPENDS $(target) : $(d) ;
+ common.MkDir $(d) ;
+ }
+
+ # For a real file target, we create a fake target depending on the
+ # real target. This allows us to run
+ #
+ # bjam hello.o
+ #
+ # without trying to guess the name of the real target. Note that the
+ # target has no directory name and uses a special <e> grist.
+ #
+ # First, that means that "bjam hello.o" will build all known hello.o
+ # targets. Second, the <e> grist makes sure this target will not be
+ # confused with other targets, for example, if we have subdir 'test'
+ # with target 'test' in it that includes a 'test.o' file, then the
+ # target for directory will be just 'test' the target for test.o
+ # will be <ptest/bin/gcc/debug>test.o and the target we create below
+ # will be <e>test.o
+ DEPENDS $(target:G=e) : $(target) ;
+ # Allow bjam <path-to-file>/<file> to work. This will not catch all
+ # possible ways to refer to the path (relative/absolute, extra ".",
+ # various "..", but should help in obvious cases.
+ DEPENDS $(target:G=e:R=$(path)) : $(target) ;
+ }
+ else
+ {
+ SEARCH on $(target) = [ path.native $(self.path) ] ;
+ }
+ }
+
+ # Returns the directory for this target.
+ #
+ rule path ( )
+ {
+ if ! $(self.path)
+ {
+ if $(self.action)
+ {
+ local p = [ $(self.action).properties ] ;
+ local path,relative-to-build-dir = [ $(p).target-path ] ;
+ local path = $(path,relative-to-build-dir[1]) ;
+ local relative-to-build-dir = $(path,relative-to-build-dir[2]) ;
+
+ if $(relative-to-build-dir)
+ {
+ path = [ path.join [ $(self.project).build-dir ] $(path) ] ;
+ }
+
+ self.path = [ path.native $(path) ] ;
+ }
+ }
+ return $(self.path) ;
+ }
+}
+
+
+class notfile-target : abstract-file-target
+{
+ rule __init__ ( name : project : action ? )
+ {
+ abstract-file-target.__init__ $(name) : : $(project) : $(action) ;
+ }
+
+ # Returns nothing to indicate that the target's path is not known.
+ #
+ rule path ( )
+ {
+ return ;
+ }
+
+ rule actualize-location ( target )
+ {
+ NOTFILE $(target) ;
+ ALWAYS $(target) ;
+ # TEMPORARY $(target) ;
+ NOUPDATE $(target) ;
+ }
+}
+
+
+# Class representing an action. Both 'targets' and 'sources' should list
+# instances of 'virtual-target'. Action name should name a rule with this
+# prototype:
+# rule action-name ( targets + : sources * : properties * )
+# Targets and sources are passed as actual Jam targets. The rule may not
+# establish additional dependency relationships.
+#
+class action
+{
+ import "class" ;
+ import errors ;
+ import type ;
+ import toolset ;
+ import property-set ;
+ import indirect ;
+ import path ;
+ import set : difference ;
+
+ rule __init__ ( sources * : action-name + : property-set ? )
+ {
+ self.sources = $(sources) ;
+
+ self.action-name = [ indirect.make-qualified $(action-name) ] ;
+
+ if ! $(property-set)
+ {
+ property-set = [ property-set.empty ] ;
+ }
+
+ if ! [ class.is-instance $(property-set) ]
+ {
+ errors.error "Property set instance required" ;
+ }
+
+ self.properties = $(property-set) ;
+ }
+
+ rule add-targets ( targets * )
+ {
+ self.targets += $(targets) ;
+ }
+
+ rule replace-targets ( old-targets * : new-targets * )
+ {
+ self.targets = [ set.difference $(self.targets) : $(old-targets) ] ;
+ self.targets += $(new-targets) ;
+ }
+
+ rule targets ( )
+ {
+ return $(self.targets) ;
+ }
+
+ rule sources ( )
+ {
+ return $(self.sources) ;
+ }
+
+ rule action-name ( )
+ {
+ return $(self.action-name) ;
+ }
+
+ rule properties ( )
+ {
+ return $(self.properties) ;
+ }
+
+ # Generates actual build instructions.
+ #
+ rule actualize ( )
+ {
+ if ! $(self.actualized)
+ {
+ self.actualized = true ;
+
+ local ps = [ properties ] ;
+ local properties = [ adjust-properties $(ps) ] ;
+
+ local actual-targets ;
+ for local i in [ targets ]
+ {
+ actual-targets += [ $(i).actualize ] ;
+ }
+
+ actualize-sources [ sources ] : $(properties) ;
+
+ DEPENDS $(actual-targets) : $(self.actual-sources)
+ $(self.dependency-only-sources) ;
+
+ # This works around a bug with -j and actions that
+ # produce multiple target, where:
+ # - dependency on the first output is found, and
+ # the action is started
+ # - dependency on the second output is found, and
+ # bjam noticed that command is already running
+ # - instead of waiting for the command, dependents
+ # of the second targets are immediately updated.
+ if $(actual-targets[2])
+ {
+ INCLUDES $(actual-targets) : $(actual-targets) ;
+ }
+
+ # Action name can include additional argument to rule, which should
+ # not be passed to 'set-target-variables'
+ toolset.set-target-variables
+ [ indirect.get-rule $(self.action-name[1]) ] $(actual-targets)
+ : $(properties) ;
+
+ # Reflect ourselves in a variable for the target. This allows
+ # looking up additional info for the action given the raw target.
+ # For example to debug or output action information from action
+ # rules.
+ .action on $(actual-targets) = $(__name__) ;
+
+ indirect.call $(self.action-name) $(actual-targets)
+ : $(self.actual-sources) : [ $(properties).raw ] ;
+
+ # Since we set up the creating action here, we set up the action for
+ # cleaning up as well.
+ common.Clean clean-all : $(actual-targets) ;
+ }
+ }
+
+ # Helper for 'actualize-sources'. For each passed source, actualizes it with
+ # the appropriate scanner. Returns the actualized virtual targets.
+ #
+ rule actualize-source-type ( sources * : property-set )
+ {
+ local result = ;
+ for local i in $(sources)
+ {
+ local scanner ;
+ if [ $(i).type ]
+ {
+ scanner = [ type.get-scanner [ $(i).type ] : $(property-set) ] ;
+ }
+ result += [ $(i).actualize $(scanner) ] ;
+ }
+ return $(result) ;
+ }
+
+ # Creates actual Jam targets for sources. Initializes the following member
+ # variables:
+ # 'self.actual-sources' -- sources passed to the updating action.
+ # 'self.dependency-only-sources' -- sources marked as dependencies, but
+ # are not used otherwise.
+ #
+ # New values will be *appended* to the variables. They may be non-empty if
+ # caller wants it.
+ #
+ rule actualize-sources ( sources * : property-set )
+ {
+ local dependencies = [ $(self.properties).get <dependency> ] ;
+
+ self.dependency-only-sources +=
+ [ actualize-source-type $(dependencies) : $(property-set) ] ;
+ self.actual-sources +=
+ [ actualize-source-type $(sources) : $(property-set) ] ;
+
+ # This is used to help bjam find dependencies in generated headers and
+ # other main targets, e.g. in:
+ #
+ # make a.h : ....... ;
+ # exe hello : hello.cpp : <implicit-dependency>a.h ;
+ #
+ # For bjam to find the dependency the generated target must be
+ # actualized (i.e. have its Jam target constructed). In the above case,
+ # if we are building just hello ("bjam hello"), 'a.h' will not be
+ # actualized unless we do it here.
+ local implicit = [ $(self.properties).get <implicit-dependency> ] ;
+ for local i in $(implicit)
+ {
+ $(i:G=).actualize ;
+ }
+ }
+
+ # Determines real properties when trying to build with 'properties'. This is
+ # the last chance to fix properties, for example to adjust includes to get
+ # generated headers correctly. Default implementation simply returns its
+ # argument.
+ #
+ rule adjust-properties ( property-set )
+ {
+ return $(property-set) ;
+ }
+}
+
+
+# Action class which does nothing --- it produces the targets with specific
+# properties out of nowhere. It is needed to distinguish virtual targets with
+# different properties that are known to exist and have no actions which create
+# them.
+#
+class null-action : action
+{
+ rule __init__ ( property-set ? )
+ {
+ action.__init__ : .no-action : $(property-set) ;
+ }
+
+ rule actualize ( )
+ {
+ if ! $(self.actualized)
+ {
+ self.actualized = true ;
+ for local i in [ targets ]
+ {
+ $(i).actualize ;
+ }
+ }
+ }
+}
+
+
+# Class which acts exactly like 'action', except that its sources are not
+# scanned for dependencies.
+#
+class non-scanning-action : action
+{
+ rule __init__ ( sources * : action-name + : property-set ? )
+ {
+ action.__init__ $(sources) : $(action-name) : $(property-set) ;
+ }
+
+ rule actualize-source-type ( sources * : property-set )
+ {
+ local result ;
+ for local i in $(sources)
+ {
+ result += [ $(i).actualize ] ;
+ }
+ return $(result) ;
+ }
+}
+
+
+# Creates a virtual target with an appropriate name and type from 'file'. If a
+# target with that name in that project already exists, returns that already
+# created target.
+#
+# FIXME: a more correct way would be to compute the path to the file, based on
+# name and source location for the project, and use that path to determine if
+# the target has already been created. This logic should be shared with how we
+# usually find targets identified by a specific target id. It should also be
+# updated to work correctly when the file is specified using both relative and
+# absolute paths.
+#
+# TODO: passing a project with all virtual targets is starting to be annoying.
+#
+rule from-file ( file : file-loc : project )
+{
+ import type ; # Had to do this here to break a circular dependency.
+
+ # Check whether we already created a target corresponding to this file.
+ local path = [ path.root [ path.root $(file) $(file-loc) ] [ path.pwd ] ] ;
+
+ if $(.files.$(path))
+ {
+ return $(.files.$(path)) ;
+ }
+ else
+ {
+ local name = [ path.make $(file) ] ;
+ local type = [ type.type $(file) ] ;
+ local result ;
+
+ result = [ new file-target $(file) : $(type) : $(project) : :
+ $(file-loc) ] ;
+
+ .files.$(path) = $(result) ;
+ return $(result) ;
+ }
+}
+
+
+# Registers a new virtual target. Checks if there is already a registered target
+# with the same name, type, project and subvariant properties as well as the
+# same sources and equal action. If such target is found it is returned and a
+# new 'target' is not registered. Otherwise, 'target' is registered and
+# returned.
+#
+rule register ( target )
+{
+ local signature = [ sequence.join
+ [ $(target).path ] [ $(target).name ] : - ] ;
+
+ local result ;
+ for local t in $(.cache.$(signature))
+ {
+ local a1 = [ $(t).action ] ;
+ local a2 = [ $(target).action ] ;
+
+ if ! $(result)
+ {
+ if ! $(a1) && ! $(a2)
+ {
+ result = $(t) ;
+ }
+ else
+ {
+ if $(a1) && $(a2) &&
+ ( [ $(a1).action-name ] = [ $(a2).action-name ] ) &&
+ ( [ $(a1).sources ] = [ $(a2).sources ] )
+ {
+ local ps1 = [ $(a1).properties ] ;
+ local ps2 = [ $(a2).properties ] ;
+ local p1 = [ $(ps1).base ] [ $(ps1).free ] [ set.difference
+ [ $(ps1).dependency ] : [ $(ps1).incidental ] ] ;
+ local p2 = [ $(ps2).base ] [ $(ps2).free ] [ set.difference
+ [ $(ps2).dependency ] : [ $(ps2).incidental ] ] ;
+ if $(p1) = $(p2)
+ {
+ result = $(t) ;
+ }
+ }
+ }
+ }
+ }
+
+ if ! $(result)
+ {
+ .cache.$(signature) += $(target) ;
+ result = $(target) ;
+ }
+
+ .recent-targets += $(result) ;
+ .all-targets += $(result) ;
+
+ return $(result) ;
+}
+
+
+# Each target returned by 'register' is added to the .recent-targets list,
+# returned by this function. This allows us to find all virtual targets created
+# when building a specific main target, even those constructed only as
+# intermediate targets.
+#
+rule recent-targets ( )
+{
+ return $(.recent-targets) ;
+}
+
+
+rule clear-recent-targets ( )
+{
+ .recent-targets = ;
+}
+
+
+# Returns all virtual targets ever created.
+#
+rule all-targets ( )
+{
+ return $(.all-targets) ;
+}
+
+
+# Returns all targets from 'targets' with types equal to 'type' or derived from
+# it.
+#
+rule select-by-type ( type : targets * )
+{
+ local result ;
+ for local t in $(targets)
+ {
+ if [ type.is-subtype [ $(t).type ] $(type) ]
+ {
+ result += $(t) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+rule register-actual-name ( actual-name : virtual-target )
+{
+ if $(.actual.$(actual-name))
+ {
+ local cs1 = [ $(.actual.$(actual-name)).creating-subvariant ] ;
+ local cs2 = [ $(virtual-target).creating-subvariant ] ;
+ local cmt1 = [ $(cs1).main-target ] ;
+ local cmt2 = [ $(cs2).main-target ] ;
+
+ local action1 = [ $(.actual.$(actual-name)).action ] ;
+ local action2 = [ $(virtual-target).action ] ;
+ local properties-added ;
+ local properties-removed ;
+ if $(action1) && $(action2)
+ {
+ local p1 = [ $(action1).properties ] ;
+ p1 = [ $(p1).raw ] ;
+ local p2 = [ $(action2).properties ] ;
+ p2 = [ $(p2).raw ] ;
+ properties-removed = [ set.difference $(p1) : $(p2) ] ;
+ properties-removed ?= "none" ;
+ properties-added = [ set.difference $(p2) : $(p1) ] ;
+ properties-added ?= "none" ;
+ }
+ errors.error "Duplicate name of actual target:" $(actual-name)
+ : "previous virtual target" [ $(.actual.$(actual-name)).str ]
+ : "created from" [ $(cmt1).full-name ]
+ : "another virtual target" [ $(virtual-target).str ]
+ : "created from" [ $(cmt2).full-name ]
+ : "added properties:" $(properties-added)
+ : "removed properties:" $(properties-removed) ;
+ }
+ else
+ {
+ .actual.$(actual-name) = $(virtual-target) ;
+ }
+}
+
+
+# Traverses the dependency graph of 'target' and return all targets that will be
+# created before this one is created. If the root of some dependency graph is
+# found during traversal, it is either included or not, depending on the
+# 'include-roots' value. In either case traversal stops at root targets, i.e.
+# root target sources are not traversed.
+#
+rule traverse ( target : include-roots ? : include-sources ? )
+{
+ local result ;
+ if [ $(target).action ]
+ {
+ local action = [ $(target).action ] ;
+ # This includes the 'target' as well.
+ result += [ $(action).targets ] ;
+
+ for local t in [ $(action).sources ]
+ {
+ if ! [ $(t).root ]
+ {
+ result += [ traverse $(t) : $(include-roots) : $(include-sources) ] ;
+ }
+ else if $(include-roots)
+ {
+ result += $(t) ;
+ }
+ }
+ }
+ else if $(include-sources)
+ {
+ result = $(target) ;
+ }
+ return $(result) ;
+}
+
+
+# Takes an 'action' instance and creates a new instance of it and all targets
+# produced by the action. The rule-name and properties are set to
+# 'new-rule-name' and 'new-properties', if those are specified. Returns the
+# cloned action.
+#
+rule clone-action ( action : new-project : new-action-name ? : new-properties ? )
+{
+ if ! $(new-action-name)
+ {
+ new-action-name = [ $(action).action-name ] ;
+ }
+ if ! $(new-properties)
+ {
+ new-properties = [ $(action).properties ] ;
+ }
+
+ local action-class = [ modules.peek $(action) : __class__ ] ;
+ local cloned-action = [ class.new $(action-class)
+ [ $(action).sources ] : $(new-action-name) : $(new-properties) ] ;
+
+ local cloned-targets ;
+ for local target in [ $(action).targets ]
+ {
+ local n = [ $(target).name ] ;
+ # Do not modify produced target names.
+ local cloned-target = [ class.new file-target $(n) exact :
+ [ $(target).type ] : $(new-project) : $(cloned-action) ] ;
+ local d = [ $(target).dependencies ] ;
+ if $(d)
+ {
+ $(cloned-target).depends $(d) ;
+ }
+ $(cloned-target).root [ $(target).root ] ;
+ $(cloned-target).creating-subvariant [ $(target).creating-subvariant ] ;
+
+ cloned-targets += $(cloned-target) ;
+ }
+
+ return $(cloned-action) ;
+}
+
+
+class subvariant
+{
+ import sequence ;
+ import type ;
+
+ rule __init__ ( main-target # The instance of main-target class.
+ : property-set # Properties requested for this target.
+ : sources *
+ : build-properties # Actually used properties.
+ : sources-usage-requirements # Properties propagated from sources.
+ : created-targets * ) # Top-level created targets.
+ {
+ self.main-target = $(main-target) ;
+ self.properties = $(property-set) ;
+ self.sources = $(sources) ;
+ self.build-properties = $(build-properties) ;
+ self.sources-usage-requirements = $(sources-usage-requirements) ;
+ self.created-targets = $(created-targets) ;
+
+ # Pre-compose a list of other dependency graphs this one depends on.
+ local deps = [ $(build-properties).get <implicit-dependency> ] ;
+ for local d in $(deps)
+ {
+ self.other-dg += [ $(d:G=).creating-subvariant ] ;
+ }
+
+ self.other-dg = [ sequence.unique $(self.other-dg) ] ;
+ }
+
+ rule main-target ( )
+ {
+ return $(self.main-target) ;
+ }
+
+ rule created-targets ( )
+ {
+ return $(self.created-targets) ;
+ }
+
+ rule requested-properties ( )
+ {
+ return $(self.properties) ;
+ }
+
+ rule build-properties ( )
+ {
+ return $(self.build-properties) ;
+ }
+
+ rule sources-usage-requirements ( )
+ {
+ return $(self.sources-usage-requirements) ;
+ }
+
+ rule set-usage-requirements ( usage-requirements )
+ {
+ self.usage-requirements = $(usage-requirements) ;
+ }
+
+ rule usage-requirements ( )
+ {
+ return $(self.usage-requirements) ;
+ }
+
+ # Returns all targets referenced by this subvariant, either directly or
+ # indirectly, and either as sources, or as dependency properties. Targets
+ # referred to using the dependency property are returned as properties, not
+ # targets.
+ #
+ rule all-referenced-targets ( theset )
+ {
+ # Find directly referenced targets.
+ local deps = [ $(self.build-properties).dependency ] ;
+ local all-targets = $(self.sources) $(deps) ;
+
+ # Find other subvariants.
+ local r ;
+ for local t in $(all-targets)
+ {
+ if ! [ $(theset).contains $(t) ]
+ {
+ $(theset).add $(t) ;
+ r += [ $(t:G=).creating-subvariant ] ;
+ }
+ }
+ r = [ sequence.unique $(r) ] ;
+ for local s in $(r)
+ {
+ if $(s) != $(__name__)
+ {
+ $(s).all-referenced-targets $(theset) ;
+ }
+ }
+ }
+
+ # Returns the properties specifying implicit include paths to generated
+ # headers. This traverses all targets in this subvariant and subvariants
+ # referred by <implcit-dependecy> properties. For all targets of type
+ # 'target-type' (or for all targets, if 'target-type' is not specified), the
+ # result will contain <$(feature)>path-to-that-target.
+ #
+ rule implicit-includes ( feature : target-type ? )
+ {
+ local key = ii$(feature)-$(target-type:E="") ;
+ if ! $($(key))-is-not-empty
+ {
+ local target-paths = [ all-target-directories $(target-type) ] ;
+ target-paths = [ sequence.unique $(target-paths) ] ;
+ local result = $(target-paths:G=$(feature)) ;
+ if ! $(result)
+ {
+ result = "" ;
+ }
+ $(key) = $(result) ;
+ }
+ if $($(key)) = ""
+ {
+ return ;
+ }
+ else
+ {
+ return $($(key)) ;
+ }
+ }
+
+ rule all-target-directories ( target-type ? )
+ {
+ if ! $(self.target-directories)
+ {
+ compute-target-directories $(target-type) ;
+ }
+ return $(self.target-directories) ;
+ }
+
+ rule compute-target-directories ( target-type ? )
+ {
+ local result ;
+ for local t in $(self.created-targets)
+ {
+ # Skip targets of the wrong type.
+ if ! $(target-type) ||
+ [ type.is-derived [ $(t).type ] $(target-type) ]
+ {
+ result = [ sequence.merge $(result) : [ $(t).path ] ] ;
+ }
+ }
+ for local d in $(self.other-dg)
+ {
+ result += [ $(d).all-target-directories $(target-type) ] ;
+ }
+ self.target-directories = $(result) ;
+ }
+}
diff --git a/tools/build/v2/build/virtual_target.py b/tools/build/v2/build/virtual_target.py
new file mode 100644
index 0000000000..51dff0374b
--- /dev/null
+++ b/tools/build/v2/build/virtual_target.py
@@ -0,0 +1,1118 @@
+# Status: ported.
+# Base revision: 64488.
+#
+# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+# Implements virtual targets, which correspond to actual files created during
+# build, but are not yet targets in Jam sense. They are needed, for example,
+# when searching for possible transormation sequences, when it's not known
+# if particular target should be created at all.
+#
+#
+# +--------------------------+
+# | VirtualTarget |
+# +==========================+
+# | actualize |
+# +--------------------------+
+# | actualize_action() = 0 |
+# | actualize_location() = 0 |
+# +----------------+---------+
+# |
+# ^
+# / \
+# +-+-+
+# |
+# +---------------------+ +-------+--------------+
+# | Action | | AbstractFileTarget |
+# +=====================| * +======================+
+# | action_name | +--+ action |
+# | properties | | +----------------------+
+# +---------------------+--+ | actualize_action() |
+# | actualize() |0..1 +-----------+----------+
+# | path() | |
+# | adjust_properties() | sources |
+# | actualize_sources() | targets |
+# +------+--------------+ ^
+# | / \
+# ^ +-+-+
+# / \ |
+# +-+-+ +-------------+-------------+
+# | | |
+# | +------+---------------+ +--------+-------------+
+# | | FileTarget | | SearchedLibTarget |
+# | +======================+ +======================+
+# | | actualize-location() | | actualize-location() |
+# | +----------------------+ +----------------------+
+# |
+# +-+------------------------------+
+# | |
+# +----+----------------+ +---------+-----------+
+# | CompileAction | | LinkAction |
+# +=====================+ +=====================+
+# | adjust_properties() | | adjust_properties() |
+# +---------------------+ | actualize_sources() |
+# +---------------------+
+#
+# The 'CompileAction' and 'LinkAction' classes are defined not here,
+# but in builtin.jam modules. They are shown in the diagram to give
+# the big picture.
+
+import bjam
+
+import re
+import os.path
+import string
+import types
+
+from b2.util import path, utility, set
+from b2.util.utility import add_grist, get_grist, ungrist, replace_grist, get_value
+from b2.util.sequence import unique
+from b2.tools import common
+from b2.exceptions import *
+import b2.build.type
+import b2.build.property_set as property_set
+
+import b2.build.property as property
+
+from b2.manager import get_manager
+from b2.util import bjam_signature
+
+__re_starts_with_at = re.compile ('^@(.*)')
+
+class VirtualTargetRegistry:
+ def __init__ (self, manager):
+ self.manager_ = manager
+
+ # A cache for FileTargets
+ self.files_ = {}
+
+ # A cache for targets.
+ self.cache_ = {}
+
+ # A map of actual names to virtual targets.
+ # Used to make sure we don't associate same
+ # actual target to two virtual targets.
+ self.actual_ = {}
+
+ self.recent_targets_ = []
+
+ # All targets ever registed
+ self.all_targets_ = []
+
+ self.next_id_ = 0
+
+ def register (self, target):
+ """ Registers a new virtual target. Checks if there's already registered target, with the same
+ name, type, project and subvariant properties, and also with the same sources
+ and equal action. If such target is found it is retured and 'target' is not registered.
+ Otherwise, 'target' is registered and returned.
+ """
+ if target.path():
+ signature = target.path() + "-" + target.name()
+ else:
+ signature = "-" + target.name()
+
+ result = None
+ if not self.cache_.has_key (signature):
+ self.cache_ [signature] = []
+
+ for t in self.cache_ [signature]:
+ a1 = t.action ()
+ a2 = target.action ()
+
+ # TODO: why are we checking for not result?
+ if not result:
+ if not a1 and not a2:
+ result = t
+ else:
+ if a1 and a2 and a1.action_name () == a2.action_name () and a1.sources () == a2.sources ():
+ ps1 = a1.properties ()
+ ps2 = a2.properties ()
+ p1 = ps1.base () + ps1.free () +\
+ b2.util.set.difference(ps1.dependency(), ps1.incidental())
+ p2 = ps2.base () + ps2.free () +\
+ b2.util.set.difference(ps2.dependency(), ps2.incidental())
+ if p1 == p2:
+ result = t
+
+ if not result:
+ self.cache_ [signature].append (target)
+ result = target
+
+ # TODO: Don't append if we found pre-existing target?
+ self.recent_targets_.append(result)
+ self.all_targets_.append(result)
+
+ return result
+
+ def from_file (self, file, file_location, project):
+ """ Creates a virtual target with appropriate name and type from 'file'.
+ If a target with that name in that project was already created, returns that already
+ created target.
+ TODO: more correct way would be to compute path to the file, based on name and source location
+ for the project, and use that path to determine if the target was already created.
+ TODO: passing project with all virtual targets starts to be annoying.
+ """
+ # Check if we've created a target corresponding to this file.
+ path = os.path.join(os.getcwd(), file_location, file)
+ path = os.path.normpath(path)
+
+ if self.files_.has_key (path):
+ return self.files_ [path]
+
+ file_type = b2.build.type.type (file)
+
+ result = FileTarget (file, file_type, project,
+ None, file_location)
+ self.files_ [path] = result
+
+ return result
+
+ def recent_targets(self):
+ """Each target returned by 'register' is added to a list of
+ 'recent-target', returned by this function. So, this allows
+ us to find all targets created when building a given main
+ target, even if the target."""
+
+ return self.recent_targets_
+
+ def clear_recent_targets(self):
+ self.recent_targets_ = []
+
+ def all_targets(self):
+ # Returns all virtual targets ever created
+ return self.all_targets_
+
+ # Returns all targets from 'targets' with types
+ # equal to 'type' or derived from it.
+ def select_by_type(self, type, targets):
+ return [t for t in targets if b2.build.type.is_sybtype(t.type(), type)]
+
+ def register_actual_name (self, actual_name, virtual_target):
+ if self.actual_.has_key (actual_name):
+ cs1 = self.actual_ [actual_name].creating_subvariant ()
+ cs2 = virtual_target.creating_subvariant ()
+ cmt1 = cs1.main_target ()
+ cmt2 = cs2.main_target ()
+
+ action1 = self.actual_ [actual_name].action ()
+ action2 = virtual_target.action ()
+
+ properties_added = []
+ properties_removed = []
+ if action1 and action2:
+ p1 = action1.properties ()
+ p1 = p1.raw ()
+ p2 = action2.properties ()
+ p2 = p2.raw ()
+
+ properties_removed = set.difference (p1, p2)
+ if not properties_removed: properties_removed = "none"
+
+ properties_added = set.difference (p2, p1)
+ if not properties_added: properties_added = "none"
+
+ # FIXME: Revive printing of real location.
+ get_manager().errors()(
+ "Duplicate name of actual target: '%s'\n"
+ "previous virtual target '%s'\n"
+ "created from '%s'\n"
+ "another virtual target '%s'\n"
+ "created from '%s'\n"
+ "added properties: '%s'\n"
+ "removed properties: '%s'\n"
+ % (actual_name,
+ self.actual_ [actual_name], "loc", #cmt1.location (),
+ virtual_target,
+ "loc", #cmt2.location (),
+ properties_added, properties_removed))
+
+ else:
+ self.actual_ [actual_name] = virtual_target
+
+
+ def add_suffix (self, specified_name, file_type, prop_set):
+ """ Appends the suffix appropriate to 'type/property_set' combination
+ to the specified name and returns the result.
+ """
+ suffix = b2.build.type.generated_target_suffix (file_type, prop_set)
+
+ if suffix:
+ return specified_name + '.' + suffix
+
+ else:
+ return specified_name
+
+class VirtualTarget:
+ """ Potential target. It can be converted into jam target and used in
+ building, if needed. However, it can be also dropped, which allows
+ to search for different transformation and select only one.
+ name: name of this target.
+ project: project to which this target belongs.
+ """
+ def __init__ (self, name, project):
+ self.name_ = name
+ self.project_ = project
+ self.dependencies_ = []
+ self.always_ = False
+
+ # Caches if dapendencies for scanners have already been set.
+ self.made_ = {}
+
+ def manager(self):
+ return self.project_.manager()
+
+ def virtual_targets(self):
+ return self.manager().virtual_targets()
+
+ def name (self):
+ """ Name of this target.
+ """
+ return self.name_
+
+ def project (self):
+ """ Project of this target.
+ """
+ return self.project_
+
+ def depends (self, d):
+ """ Adds additional instances of 'VirtualTarget' that this
+ one depends on.
+ """
+ self.dependencies_ = unique (self.dependencies_ + d).sort ()
+
+ def dependencies (self):
+ return self.dependencies_
+
+ def always(self):
+ self.always_ = True
+
+ def actualize (self, scanner = None):
+ """ Generates all the actual targets and sets up build actions for
+ this target.
+
+ If 'scanner' is specified, creates an additional target
+ with the same location as actual target, which will depend on the
+ actual target and be associated with 'scanner'. That additional
+ target is returned. See the docs (#dependency_scanning) for rationale.
+ Target must correspond to a file if 'scanner' is specified.
+
+ If scanner is not specified, then actual target is returned.
+ """
+ actual_name = self.actualize_no_scanner ()
+
+ if self.always_:
+ bjam.call("ALWAYS", actual_name)
+
+ if not scanner:
+ return actual_name
+
+ else:
+ # Add the scanner instance to the grist for name.
+ g = '-'.join ([ungrist(get_grist(actual_name)), str(id(scanner))])
+
+ name = replace_grist (actual_name, '<' + g + '>')
+
+ if not self.made_.has_key (name):
+ self.made_ [name] = True
+
+ self.project_.manager ().engine ().add_dependency (name, actual_name)
+
+ self.actualize_location (name)
+
+ self.project_.manager ().scanners ().install (scanner, name, str (self))
+
+ return name
+
+# private: (overridables)
+
+ def actualize_action (self, target):
+ """ Sets up build actions for 'target'. Should call appropriate rules
+ and set target variables.
+ """
+ raise BaseException ("method should be defined in derived classes")
+
+ def actualize_location (self, target):
+ """ Sets up variables on 'target' which specify its location.
+ """
+ raise BaseException ("method should be defined in derived classes")
+
+ def path (self):
+ """ If the target is generated one, returns the path where it will be
+ generated. Otherwise, returns empty list.
+ """
+ raise BaseException ("method should be defined in derived classes")
+
+ def actual_name (self):
+ """ Return that actual target name that should be used
+ (for the case where no scanner is involved)
+ """
+ raise BaseException ("method should be defined in derived classes")
+
+
+class AbstractFileTarget (VirtualTarget):
+ """ Target which correspond to a file. The exact mapping for file
+ is not yet specified in this class. (TODO: Actually, the class name
+ could be better...)
+
+ May be a source file (when no action is specified), or
+ derived file (otherwise).
+
+ The target's grist is concatenation of project's location,
+ properties of action (for derived files), and, optionally,
+ value identifying the main target.
+
+ exact: If non-empty, the name is exactly the name
+ created file should have. Otherwise, the '__init__'
+ method will add suffix obtained from 'type' by
+ calling 'type.generated-target-suffix'.
+
+ type: optional type of this target.
+ """
+ def __init__ (self, name, type, project, action = None, exact=False):
+ VirtualTarget.__init__ (self, name, project)
+
+ self.type_ = type
+
+ self.action_ = action
+ self.exact_ = exact
+
+ if action:
+ action.add_targets ([self])
+
+ if self.type and not exact:
+ self.__adjust_name (name)
+
+
+ self.actual_name_ = None
+ self.path_ = None
+ self.intermediate_ = False
+ self.creating_subvariant_ = None
+
+ # True if this is a root target.
+ self.root_ = False
+
+ def type (self):
+ return self.type_
+
+ def set_path (self, path):
+ """ Sets the path. When generating target name, it will override any path
+ computation from properties.
+ """
+ self.path_ = path
+
+ def action (self):
+ """ Returns the action.
+ """
+ return self.action_
+
+ def root (self, set = None):
+ """ Sets/gets the 'root' flag. Target is root is it directly correspods to some
+ variant of a main target.
+ """
+ if set:
+ self.root_ = True
+ return self.root_
+
+ def creating_subvariant (self, s = None):
+ """ Gets or sets the subvariant which created this target. Subvariant
+ is set when target is brought into existance, and is never changed
+ after that. In particual, if target is shared by subvariant, only
+ the first is stored.
+ s: If specified, specified the value to set,
+ which should be instance of 'subvariant' class.
+ """
+ if s and not self.creating_subvariant ():
+ if self.creating_subvariant ():
+ raise BaseException ("Attempt to change 'dg'")
+
+ else:
+ self.creating_subvariant_ = s
+
+ return self.creating_subvariant_
+
+ def actualize_action (self, target):
+ if self.action_:
+ self.action_.actualize ()
+
+ # Return a human-readable representation of this target
+ #
+ # If this target has an action, that's:
+ #
+ # { <action-name>-<self.name>.<self.type> <action-sources>... }
+ #
+ # otherwise, it's:
+ #
+ # { <self.name>.<self.type> }
+ #
+ def str(self):
+ a = self.action()
+
+ name_dot_type = self.name_ + "." + self.type_
+
+ if a:
+ action_name = a.action_name()
+ ss = [ s.str() for s in a.sources()]
+
+ return "{ %s-%s %s}" % (action_name, name_dot_type, str(ss))
+ else:
+ return "{ " + name_dot_type + " }"
+
+# private:
+
+ def actual_name (self):
+ if not self.actual_name_:
+ self.actual_name_ = '<' + self.grist() + '>' + self.name_
+
+ return self.actual_name_
+
+ def grist (self):
+ """Helper to 'actual_name', above. Compute unique prefix used to distinguish
+ this target from other targets with the same name which create different
+ file.
+ """
+ # Depending on target, there may be different approaches to generating
+ # unique prefixes. We'll generate prefixes in the form
+ # <one letter approach code> <the actual prefix>
+ path = self.path ()
+
+ if path:
+ # The target will be generated to a known path. Just use the path
+ # for identification, since path is as unique as it can get.
+ return 'p' + path
+
+ else:
+ # File is either source, which will be searched for, or is not a file at
+ # all. Use the location of project for distinguishing.
+ project_location = self.project_.get ('location')
+ path_components = b2.util.path.split(project_location)
+ location_grist = '!'.join (path_components)
+
+ if self.action_:
+ ps = self.action_.properties ()
+ property_grist = ps.as_path ()
+ # 'property_grist' can be empty when 'ps' is an empty
+ # property set.
+ if property_grist:
+ location_grist = location_grist + '/' + property_grist
+
+ return 'l' + location_grist
+
+ def __adjust_name(self, specified_name):
+ """Given the target name specified in constructor, returns the
+ name which should be really used, by looking at the <tag> properties.
+ The tag properties come in two flavour:
+ - <tag>value,
+ - <tag>@rule-name
+ In the first case, value is just added to name
+ In the second case, the specified rule is called with specified name,
+ target type and properties and should return the new name.
+ If not <tag> property is specified, or the rule specified by
+ <tag> returns nothing, returns the result of calling
+ virtual-target.add-suffix"""
+
+ if self.action_:
+ ps = self.action_.properties()
+ else:
+ ps = property_set.empty()
+
+ # FIXME: I'm not sure how this is used, need to check with
+ # Rene to figure out how to implement
+ #~ We add ourselves to the properties so that any tag rule can get
+ #~ more direct information about the target than just that available
+ #~ through the properties. This is useful in implementing
+ #~ name changes based on the sources of the target. For example to
+ #~ make unique names of object files based on the source file.
+ #~ --grafik
+ #ps = property_set.create(ps.raw() + ["<target>%s" % "XXXX"])
+ #ps = [ property-set.create [ $(ps).raw ] <target>$(__name__) ] ;
+
+ tag = ps.get("<tag>")
+
+ if tag:
+
+ if len(tag) > 1:
+ get_manager().errors()(
+ """<tag>@rulename is present but is not the only <tag> feature""")
+
+ tag = tag[0]
+ if callable(tag):
+ self.name_ = tag(specified_name, self.type_, ps)
+ else:
+ if not tag[0] == '@':
+ self.manager_.errors()("""The value of the <tag> feature must be '@rule-nane'""")
+
+ exported_ps = b2.util.value_to_jam(ps, methods=True)
+ self.name_ = b2.util.call_jam_function(
+ tag[1:], specified_name, self.type_, exported_ps)
+ if self.name_:
+ self.name_ = self.name_[0]
+
+ # If there's no tag or the tag rule returned nothing.
+ if not tag or not self.name_:
+ self.name_ = add_prefix_and_suffix(specified_name, self.type_, ps)
+
+ def actualize_no_scanner(self):
+ name = self.actual_name()
+
+ # Do anything only on the first invocation
+ if not self.made_:
+ self.made_[name] = True
+
+ if self.action_:
+ # For non-derived target, we don't care if there
+ # are several virtual targets that refer to the same name.
+ # One case when this is unavoidable is when file name is
+ # main.cpp and two targets have types CPP (for compiling)
+ # and MOCCABLE_CPP (for convertion to H via Qt tools).
+ self.virtual_targets().register_actual_name(name, self)
+
+ for i in self.dependencies_:
+ self.manager_.engine().add_dependency(name, i.actualize())
+
+ self.actualize_location(name)
+ self.actualize_action(name)
+
+ return name
+
+@bjam_signature((["specified_name"], ["type"], ["property_set"]))
+def add_prefix_and_suffix(specified_name, type, property_set):
+ """Appends the suffix appropriate to 'type/property-set' combination
+ to the specified name and returns the result."""
+
+ property_set = b2.util.jam_to_value_maybe(property_set)
+
+ suffix = ""
+ if type:
+ suffix = b2.build.type.generated_target_suffix(type, property_set)
+
+ # Handle suffixes for which no leading dot is desired. Those are
+ # specified by enclosing them in <...>. Needed by python so it
+ # can create "_d.so" extensions, for example.
+ if get_grist(suffix):
+ suffix = ungrist(suffix)
+ elif suffix:
+ suffix = "." + suffix
+
+ prefix = ""
+ if type:
+ prefix = b2.build.type.generated_target_prefix(type, property_set)
+
+ if specified_name.startswith(prefix):
+ prefix = ""
+
+ if not prefix:
+ prefix = ""
+ if not suffix:
+ suffix = ""
+ return prefix + specified_name + suffix
+
+
+class FileTarget (AbstractFileTarget):
+ """ File target with explicitly known location.
+
+ The file path is determined as
+ - value passed to the 'set_path' method, if any
+ - for derived files, project's build dir, joined with components
+ that describe action's properties. If the free properties
+ are not equal to the project's reference properties
+ an element with name of main target is added.
+ - for source files, project's source dir
+
+ The file suffix is
+ - the value passed to the 'suffix' method, if any, or
+ - the suffix which correspond to the target's type.
+ """
+ def __init__ (self, name, type, project, action = None, path=None, exact=False):
+ AbstractFileTarget.__init__ (self, name, type, project, action, exact)
+
+ self.path_ = path
+
+ def __str__(self):
+ if self.type_:
+ return self.name_ + "." + self.type_
+ else:
+ return self.name_
+
+ def clone_with_different_type(self, new_type):
+ return FileTarget(self.name_, new_type, self.project_,
+ self.action_, self.path_, exact=True)
+
+ def actualize_location (self, target):
+ engine = self.project_.manager_.engine ()
+
+ if self.action_:
+ # This is a derived file.
+ path = self.path ()
+ engine.set_target_variable (target, 'LOCATE', path)
+
+ # Make sure the path exists.
+ engine.add_dependency (target, path)
+ common.mkdir(engine, path)
+
+ # It's possible that the target name includes a directory
+ # too, for example when installing headers. Create that
+ # directory.
+ d = os.path.dirname(get_value(target))
+ if d:
+ d = os.path.join(path, d)
+ engine.add_dependency(target, d)
+ common.mkdir(engine, d)
+
+ # For real file target, we create a fake target that
+ # depends on the real target. This allows to run
+ #
+ # bjam hello.o
+ #
+ # without trying to guess the name of the real target.
+ # Note the that target has no directory name, and a special
+ # grist <e>.
+ #
+ # First, that means that "bjam hello.o" will build all
+ # known hello.o targets.
+ # Second, the <e> grist makes sure this target won't be confused
+ # with other targets, for example, if we have subdir 'test'
+ # with target 'test' in it that includes 'test.o' file,
+ # then the target for directory will be just 'test' the target
+ # for test.o will be <ptest/bin/gcc/debug>test.o and the target
+ # we create below will be <e>test.o
+ engine.add_dependency("<e>%s" % get_value(target), target)
+
+ # Allow bjam <path-to-file>/<file> to work. This won't catch all
+ # possible ways to refer to the path (relative/absolute, extra ".",
+ # various "..", but should help in obvious cases.
+ engine.add_dependency("<e>%s" % (os.path.join(path, get_value(target))), target)
+
+ else:
+ # This is a source file.
+ engine.set_target_variable (target, 'SEARCH', self.project_.get ('source-location'))
+
+
+ def path (self):
+ """ Returns the directory for this target.
+ """
+ if not self.path_:
+ if self.action_:
+ p = self.action_.properties ()
+ (target_path, relative_to_build_dir) = p.target_path ()
+
+ if relative_to_build_dir:
+ # Indicates that the path is relative to
+ # build dir.
+ target_path = os.path.join (self.project_.build_dir (), target_path)
+
+ # Store the computed path, so that it's not recomputed
+ # any more
+ self.path_ = target_path
+
+ return self.path_
+
+
+class NotFileTarget(AbstractFileTarget):
+
+ def __init__(self, name, project, action):
+ AbstractFileTarget.__init__(self, name, None, project, action)
+
+ def path(self):
+ """Returns nothing, to indicate that target path is not known."""
+ return None
+
+ def actualize_location(self, target):
+ bjam.call("NOTFILE", target)
+ bjam.call("ALWAYS", target)
+ bjam.call("NOUPDATE", target)
+
+
+class Action:
+ """ Class which represents an action.
+ Both 'targets' and 'sources' should list instances of 'VirtualTarget'.
+ Action name should name a rule with this prototype
+ rule action_name ( targets + : sources * : properties * )
+ Targets and sources are passed as actual jam targets. The rule may
+ not establish dependency relationship, but should do everything else.
+ """
+ def __init__ (self, manager, sources, action_name, prop_set):
+ assert(isinstance(prop_set, property_set.PropertySet))
+ assert type(sources) == types.ListType
+ self.sources_ = sources
+ self.action_name_ = action_name
+ if not prop_set:
+ prop_set = property_set.empty()
+ self.properties_ = prop_set
+ if not all(isinstance(v, VirtualTarget) for v in prop_set.get('implicit-dependency')):
+ import pdb
+ pdb.set_trace()
+
+ self.manager_ = manager
+ self.engine_ = self.manager_.engine ()
+ self.targets_ = []
+
+ # Indicates whether this has been actualized or not.
+ self.actualized_ = False
+
+ self.dependency_only_sources_ = []
+ self.actual_sources_ = []
+
+
+ def add_targets (self, targets):
+ self.targets_ += targets
+
+
+ def replace_targets (old_targets, new_targets):
+ self.targets_ = [t for t in targets if not t in old_targets] + new_targets
+
+ def targets (self):
+ return self.targets_
+
+ def sources (self):
+ return self.sources_
+
+ def action_name (self):
+ return self.action_name_
+
+ def properties (self):
+ return self.properties_
+
+ def actualize (self):
+ """ Generates actual build instructions.
+ """
+ if self.actualized_:
+ return
+
+ self.actualized_ = True
+
+ ps = self.properties ()
+ properties = self.adjust_properties (ps)
+
+
+ actual_targets = []
+
+ for i in self.targets ():
+ actual_targets.append (i.actualize ())
+
+ self.actualize_sources (self.sources (), properties)
+
+ self.engine_.add_dependency (actual_targets, self.actual_sources_ + self.dependency_only_sources_)
+
+ # This works around a bug with -j and actions that
+ # produce multiple target, where:
+ # - dependency on the first output is found, and
+ # the action is started
+ # - dependency on the second output is found, and
+ # bjam noticed that command is already running
+ # - instead of waiting for the command, dependents
+ # of the second targets are immediately updated.
+ if len(actual_targets) > 1:
+ bjam.call("INCLUDES", actual_targets, actual_targets)
+
+ # FIXME: check the comment below. Was self.action_name_ [1]
+ # Action name can include additional argument to rule, which should not
+ # be passed to 'set-target-variables'
+ # FIXME: breaking circular dependency
+ import toolset
+ toolset.set_target_variables (self.manager_, self.action_name_, actual_targets, properties)
+
+ engine = self.manager_.engine ()
+
+ # FIXME: this is supposed to help --out-xml option, but we don't
+ # implement that now, and anyway, we should handle it in Python,
+ # not but putting variables on bjam-level targets.
+ bjam.call("set-target-variable", actual_targets, ".action", repr(self))
+
+ self.manager_.engine ().set_update_action (self.action_name_, actual_targets, self.actual_sources_,
+ properties)
+
+ # Since we set up creating action here, we also set up
+ # action for cleaning up
+ self.manager_.engine ().set_update_action ('common.Clean', 'clean-all',
+ actual_targets)
+
+ return actual_targets
+
+ def actualize_source_type (self, sources, prop_set):
+ """ Helper for 'actualize_sources'.
+ For each passed source, actualizes it with the appropriate scanner.
+ Returns the actualized virtual targets.
+ """
+ result = []
+ for i in sources:
+ scanner = None
+
+# FIXME: what's this?
+# if isinstance (i, str):
+# i = self.manager_.get_object (i)
+
+ if i.type ():
+ scanner = b2.build.type.get_scanner (i.type (), prop_set)
+
+ r = i.actualize (scanner)
+ result.append (r)
+
+ return result
+
+ def actualize_sources (self, sources, prop_set):
+ """ Creates actual jam targets for sources. Initializes two member
+ variables:
+ 'self.actual_sources_' -- sources which are passed to updating action
+ 'self.dependency_only_sources_' -- sources which are made dependencies, but
+ are not used otherwise.
+
+ New values will be *appended* to the variables. They may be non-empty,
+ if caller wants it.
+ """
+ dependencies = self.properties_.get ('<dependency>')
+
+ self.dependency_only_sources_ += self.actualize_source_type (dependencies, prop_set)
+ self.actual_sources_ += self.actualize_source_type (sources, prop_set)
+
+ # This is used to help bjam find dependencies in generated headers
+ # in other main targets.
+ # Say:
+ #
+ # make a.h : ....... ;
+ # exe hello : hello.cpp : <implicit-dependency>a.h ;
+ #
+ # However, for bjam to find the dependency the generated target must
+ # be actualized (i.e. have the jam target). In the above case,
+ # if we're building just hello ("bjam hello"), 'a.h' won't be
+ # actualized unless we do it here.
+ implicit = self.properties_.get("<implicit-dependency>")
+
+ for i in implicit:
+ i.actualize()
+
+ def adjust_properties (self, prop_set):
+ """ Determines real properties when trying building with 'properties'.
+ This is last chance to fix properties, for example to adjust includes
+ to get generated headers correctly. Default implementation returns
+ its argument.
+ """
+ return prop_set
+
+
+class NullAction (Action):
+ """ Action class which does nothing --- it produces the targets with
+ specific properties out of nowhere. It's needed to distinguish virtual
+ targets with different properties that are known to exist, and have no
+ actions which create them.
+ """
+ def __init__ (self, manager, prop_set):
+ Action.__init__ (self, manager, [], None, prop_set)
+
+ def actualize (self):
+ if not self.actualized_:
+ self.actualized_ = True
+
+ for i in self.targets ():
+ i.actualize ()
+
+class NonScanningAction(Action):
+ """Class which acts exactly like 'action', except that the sources
+ are not scanned for dependencies."""
+
+ def __init__(self, sources, action_name, property_set):
+ #FIXME: should the manager parameter of Action.__init__
+ #be removed? -- Steven Watanabe
+ Action.__init__(self, b2.manager.get_manager(), sources, action_name, property_set)
+
+ def actualize_source_type(self, sources, property_set):
+
+ result = []
+ for s in sources:
+ result.append(s.actualize())
+ return result
+
+def traverse (target, include_roots = False, include_sources = False):
+ """ Traverses the dependency graph of 'target' and return all targets that will
+ be created before this one is created. If root of some dependency graph is
+ found during traversal, it's either included or not, dependencing of the
+ value of 'include_roots'. In either case, sources of root are not traversed.
+ """
+ result = []
+
+ if target.action ():
+ action = target.action ()
+
+ # This includes 'target' as well
+ result += action.targets ()
+
+ for t in action.sources ():
+
+ # FIXME:
+ # TODO: see comment in Manager.register_object ()
+ #if not isinstance (t, VirtualTarget):
+ # t = target.project_.manager_.get_object (t)
+
+ if not t.root ():
+ result += traverse (t, include_roots, include_sources)
+
+ elif include_roots:
+ result.append (t)
+
+ elif include_sources:
+ result.append (target)
+
+ return result
+
+def clone_action (action, new_project, new_action_name, new_properties):
+ """Takes an 'action' instances and creates new instance of it
+ and all produced target. The rule-name and properties are set
+ to 'new-rule-name' and 'new-properties', if those are specified.
+ Returns the cloned action."""
+
+ if not new_action_name:
+ new_action_name = action.action_name()
+
+ if not new_properties:
+ new_properties = action.properties()
+
+ cloned_action = action.__class__(action.manager_, action.sources(), new_action_name,
+ new_properties)
+
+ cloned_targets = []
+ for target in action.targets():
+
+ n = target.name()
+ # Don't modify the name of the produced targets. Strip the directory f
+ cloned_target = FileTarget(n, target.type(), new_project,
+ cloned_action, exact=True)
+
+ d = target.dependencies()
+ if d:
+ cloned_target.depends(d)
+ cloned_target.root(target.root())
+ cloned_target.creating_subvariant(target.creating_subvariant())
+
+ cloned_targets.append(cloned_target)
+
+ return cloned_action
+
+class Subvariant:
+
+ def __init__ (self, main_target, prop_set, sources, build_properties, sources_usage_requirements, created_targets):
+ """
+ main_target: The instance of MainTarget class
+ prop_set: Properties requested for this target
+ sources:
+ build_properties: Actually used properties
+ sources_usage_requirements: Properties propagated from sources
+ created_targets: Top-level created targets
+ """
+ self.main_target_ = main_target
+ self.properties_ = prop_set
+ self.sources_ = sources
+ self.build_properties_ = build_properties
+ self.sources_usage_requirements_ = sources_usage_requirements
+ self.created_targets_ = created_targets
+
+ self.usage_requirements_ = None
+
+ # Pre-compose the list of other dependency graphs, on which this one
+ # depends
+ deps = build_properties.get('<implicit-dependency>')
+
+ self.other_dg_ = []
+ for d in deps:
+ self.other_dg_.append(d.creating_subvariant ())
+
+ self.other_dg_ = unique (self.other_dg_)
+
+ self.implicit_includes_cache_ = {}
+ self.target_directories_ = None
+
+ def main_target (self):
+ return self.main_target_
+
+ def created_targets (self):
+ return self.created_targets_
+
+ def requested_properties (self):
+ return self.properties_
+
+ def build_properties (self):
+ return self.build_properties_
+
+ def sources_usage_requirements (self):
+ return self.sources_usage_requirements_
+
+ def set_usage_requirements (self, usage_requirements):
+ self.usage_requirements_ = usage_requirements
+
+ def usage_requirements (self):
+ return self.usage_requirements_
+
+ def all_referenced_targets(self, result):
+ """Returns all targets referenced by this subvariant,
+ either directly or indirectly, and either as sources,
+ or as dependency properties. Targets referred with
+ dependency property are returned a properties, not targets."""
+
+ # Find directly referenced targets.
+ deps = self.build_properties().dependency()
+ all_targets = self.sources_ + deps
+
+ # Find other subvariants.
+ r = []
+ for e in all_targets:
+ if not e in result:
+ result.add(e)
+ if isinstance(e, property.Property):
+ t = e.value()
+ else:
+ t = e
+
+ # FIXME: how can this be?
+ cs = t.creating_subvariant()
+ if cs:
+ r.append(cs)
+ r = unique(r)
+ for s in r:
+ if s != self:
+ s.all_referenced_targets(result)
+
+
+ def implicit_includes (self, feature, target_type):
+ """ Returns the properties which specify implicit include paths to
+ generated headers. This traverses all targets in this subvariant,
+ and subvariants referred by <implcit-dependecy>properties.
+ For all targets which are of type 'target-type' (or for all targets,
+ if 'target_type' is not specified), the result will contain
+ <$(feature)>path-to-that-target.
+ """
+
+ if not target_type:
+ key = feature
+ else:
+ key = feature + "-" + target_type
+
+
+ result = self.implicit_includes_cache_.get(key)
+ if not result:
+ target_paths = self.all_target_directories(target_type)
+ target_paths = unique(target_paths)
+ result = ["<%s>%s" % (feature, p) for p in target_paths]
+ self.implicit_includes_cache_[key] = result
+
+ return result
+
+ def all_target_directories(self, target_type = None):
+ # TODO: does not appear to use target_type in deciding
+ # if we've computed this already.
+ if not self.target_directories_:
+ self.target_directories_ = self.compute_target_directories(target_type)
+ return self.target_directories_
+
+ def compute_target_directories(self, target_type=None):
+ result = []
+ for t in self.created_targets():
+ if not target_type or b2.build.type.is_derived(t.type(), target_type):
+ result.append(t.path())
+
+ for d in self.other_dg_:
+ result.extend(d.all_target_directories(target_type))
+
+ result = unique(result)
+ return result
diff --git a/tools/build/v2/build_system.py b/tools/build/v2/build_system.py
new file mode 100644
index 0000000000..55d8b806ca
--- /dev/null
+++ b/tools/build/v2/build_system.py
@@ -0,0 +1,872 @@
+# Status: mostly ported. Missing is --out-xml support, 'configure' integration
+# and some FIXME.
+# Base revision: 64351
+
+# Copyright 2003, 2005 Dave Abrahams
+# Copyright 2006 Rene Rivera
+# Copyright 2003, 2004, 2005, 2006, 2007 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+
+from b2.build.engine import Engine
+from b2.manager import Manager
+from b2.util.path import glob
+from b2.build import feature, property_set
+import b2.build.virtual_target
+from b2.build.targets import ProjectTarget
+from b2.util.sequence import unique
+import b2.build.build_request
+from b2.build.errors import ExceptionWithUserContext
+import b2.tools.common
+
+import b2.build.project as project
+import b2.build.virtual_target as virtual_target
+import b2.build.build_request as build_request
+
+import b2.util.regex
+
+from b2.manager import get_manager
+from b2.util import cached
+from b2.util import option
+
+
+import bjam
+
+import os
+import sys
+import re
+
+################################################################################
+#
+# Module global data.
+#
+################################################################################
+
+# Flag indicating we should display additional debugging information related to
+# locating and loading Boost Build configuration files.
+debug_config = False
+
+# Legacy option doing too many things, some of which are not even documented.
+# Should be phased out.
+# * Disables loading site and user configuration files.
+# * Disables auto-configuration for toolsets specified explicitly on the
+# command-line.
+# * Causes --toolset command-line options to be ignored.
+# * Prevents the default toolset from being used even if no toolset has been
+# configured at all.
+legacy_ignore_config = False
+
+# The cleaning is tricky. Say, if user says 'bjam --clean foo' where 'foo' is a
+# directory, then we want to clean targets which are in 'foo' as well as those
+# in any children Jamfiles under foo but not in any unrelated Jamfiles. To
+# achieve this we collect a list of projects under which cleaning is allowed.
+project_targets = []
+
+# Virtual targets obtained when building main targets references on the command
+# line. When running 'bjam --clean main_target' we want to clean only files
+# belonging to that main target so we need to record which targets are produced
+# for it.
+results_of_main_targets = []
+
+# Was an XML dump requested?
+out_xml = False
+
+# Default toolset & version to be used in case no other toolset has been used
+# explicitly by either the loaded configuration files, the loaded project build
+# scripts or an explicit toolset request on the command line. If not specified,
+# an arbitrary default will be used based on the current host OS. This value,
+# while not strictly necessary, has been added to allow testing Boost-Build's
+# default toolset usage functionality.
+default_toolset = None
+default_toolset_version = None
+
+################################################################################
+#
+# Public rules.
+#
+################################################################################
+
+# Returns the property set with the free features from the currently processed
+# build request.
+#
+def command_line_free_features():
+ return command_line_free_features
+
+# Sets the default toolset & version to be used in case no other toolset has
+# been used explicitly by either the loaded configuration files, the loaded
+# project build scripts or an explicit toolset request on the command line. For
+# more detailed information see the comment related to used global variables.
+#
+def set_default_toolset(toolset, version=None):
+ default_toolset = toolset
+ default_toolset_version = version
+
+
+pre_build_hook = []
+
+def add_pre_build_hook(callable):
+ pre_build_hook.append(callable)
+
+post_build_hook = None
+
+def set_post_build_hook(callable):
+ post_build_hook = callable
+
+################################################################################
+#
+# Local rules.
+#
+################################################################################
+
+# Returns actual Jam targets to be used for executing a clean request.
+#
+def actual_clean_targets(targets):
+
+ # Construct a list of projects explicitly detected as targets on this build
+ # system run. These are the projects under which cleaning is allowed.
+ for t in targets:
+ if isinstance(t, b2.build.targets.ProjectTarget):
+ project_targets.append(t.project_module())
+
+ # Construct a list of targets explicitly detected on this build system run
+ # as a result of building main targets.
+ targets_to_clean = set()
+ for t in results_of_main_targets:
+ # Do not include roots or sources.
+ targets_to_clean.update(virtual_target.traverse(t))
+
+ to_clean = []
+ for t in get_manager().virtual_targets().all_targets():
+
+ # Remove only derived targets.
+ if t.action():
+ p = t.project()
+ if t in targets_to_clean or should_clean_project(p.project_module()):
+ to_clean.append(t)
+
+ return [t.actualize() for t in to_clean]
+
+_target_id_split = re.compile("(.*)//(.*)")
+
+# Given a target id, try to find and return the corresponding target. This is
+# only invoked when there is no Jamfile in ".". This code somewhat duplicates
+# code in project-target.find but we can not reuse that code without a
+# project-targets instance.
+#
+def find_target(target_id):
+
+ projects = get_manager().projects()
+ m = _target_id_split.match(target_id)
+ if m:
+ pm = projects.find(m.group(1), ".")
+ else:
+ pm = projects.find(target_id, ".")
+
+ if pm:
+ result = projects.target(pm)
+
+ if m:
+ result = result.find(m.group(2))
+
+ return result
+
+def initialize_config_module(module_name, location=None):
+
+ get_manager().projects().initialize(module_name, location)
+
+# Helper rule used to load configuration files. Loads the first configuration
+# file with the given 'filename' at 'path' into module with name 'module-name'.
+# Not finding the requested file may or may not be treated as an error depending
+# on the must-find parameter. Returns a normalized path to the loaded
+# configuration file or nothing if no file was loaded.
+#
+def load_config(module_name, filename, paths, must_find=False):
+
+ if debug_config:
+ print "notice: Searching '%s' for '%s' configuration file '%s." \
+ % (paths, module_name, filename)
+
+ where = None
+ for path in paths:
+ t = os.path.join(path, filename)
+ if os.path.exists(t):
+ where = t
+ break
+
+ if where:
+ where = os.path.realpath(where)
+
+ if debug_config:
+ print "notice: Loading '%s' configuration file '%s' from '%s'." \
+ % (module_name, filename, where)
+
+ # Set source location so that path-constant in config files
+ # with relative paths work. This is of most importance
+ # for project-config.jam, but may be used in other
+ # config files as well.
+ attributes = get_manager().projects().attributes(module_name) ;
+ attributes.set('source-location', os.path.dirname(where), True)
+ get_manager().projects().load_standalone(module_name, where)
+
+ else:
+ msg = "Configuration file '%s' not found in '%s'." % (filename, path)
+ if must_find:
+ get_manager().errors()(msg)
+
+ elif debug_config:
+ print msg
+
+ return where
+
+# Loads all the configuration files used by Boost Build in the following order:
+#
+# -- test-config --
+# Loaded only if specified on the command-line using the --test-config
+# command-line parameter. It is ok for this file not to exist even if specified.
+# If this configuration file is loaded, regular site and user configuration
+# files will not be. If a relative path is specified, file is searched for in
+# the current folder.
+#
+# -- site-config --
+# Always named site-config.jam. Will only be found if located on the system
+# root path (Windows), /etc (non-Windows), user's home folder or the Boost Build
+# path, in that order. Not loaded in case the test-config configuration file is
+# loaded or either the --ignore-site-config or the --ignore-config command-line
+# option is specified.
+#
+# -- user-config --
+# Named user-config.jam by default or may be named explicitly using the
+# --user-config command-line option or the BOOST_BUILD_USER_CONFIG environment
+# variable. If named explicitly the file is looked for from the current working
+# directory and if the default one is used then it is searched for in the
+# user's home directory and the Boost Build path, in that order. Not loaded in
+# case either the test-config configuration file is loaded, --ignore-config
+# command-line option is specified or an empty file name is explicitly
+# specified. If the file name has been given explicitly then the file must
+# exist.
+#
+# Test configurations have been added primarily for use by Boost Build's
+# internal unit testing system but may be used freely in other places as well.
+#
+def load_configuration_files():
+
+ # Flag indicating that site configuration should not be loaded.
+ ignore_site_config = "--ignore-site-config" in sys.argv
+
+ if legacy_ignore_config and debug_config:
+ print "notice: Regular site and user configuration files will be ignored"
+ print "notice: due to the --ignore-config command-line option."
+
+ initialize_config_module("test-config")
+ test_config = None
+ for a in sys.argv:
+ m = re.match("--test-config=(.*)$", a)
+ if m:
+ test_config = b2.util.unquote(m.group(1))
+ break
+
+ if test_config:
+ where = load_config("test-config", os.path.basename(test_config), [os.path.dirname(test_config)])
+ if where:
+ if debug_config and not legacy_ignore_config:
+ print "notice: Regular site and user configuration files will"
+ print "notice: be ignored due to the test configuration being loaded."
+
+ user_path = [os.path.expanduser("~")] + bjam.variable("BOOST_BUILD_PATH")
+ site_path = ["/etc"] + user_path
+ if os.name in ["nt"]:
+ site_path = [os.getenv("SystemRoot")] + user_path
+
+ if ignore_site_config and not legacy_ignore_config:
+ print "notice: Site configuration files will be ignored due to the"
+ print "notice: --ignore-site-config command-line option."
+
+ initialize_config_module("site-config")
+ if not test_config and not ignore_site_config and not legacy_ignore_config:
+ load_config('site-config', 'site-config.jam', site_path)
+
+ initialize_config_module('user-config')
+ if not test_config and not legacy_ignore_config:
+
+ user_config = None
+ for a in sys.argv:
+ m = re.match("--user-config=(.*)$", a)
+ if m:
+ user_config = m.group(1)
+ break
+
+ if not user_config:
+ user_config = os.getenv("BOOST_BUILD_USER_CONFIG")
+
+ # Special handling for the case when the OS does not strip the quotes
+ # around the file name, as is the case when using Cygwin bash.
+ user_config = b2.util.unquote(user_config)
+ explicitly_requested = user_config
+ if not user_config:
+ user_config = "user-config.jam"
+
+ if explicitly_requested:
+
+ user_config = os.path.abspath(user_config)
+
+ if debug_config:
+ print "notice: Loading explicitly specified user configuration file:"
+ print " " + user_config
+
+ load_config('user-config', os.path.basename(user_config), [os.path.dirname(user_config)], True)
+ else:
+ load_config('user-config', os.path.basename(user_config), user_path)
+
+ elif debug_config:
+ print "notice: User configuration file loading explicitly disabled." ;
+
+ # We look for project-config.jam from "." upward.
+ # I am not sure this is 100% right decision, we might as well check for
+ # it only alonside the Jamroot file. However:
+ #
+ # - We need to load project-root.jam before Jamroot
+ # - We probably would need to load project-root.jam even if there's no
+ # Jamroot - e.g. to implement automake-style out-of-tree builds.
+ if os.path.exists("project-config.jam"):
+ file = ["project-config.jam"]
+ else:
+ file = b2.util.path.glob_in_parents(".", ["project-config.jam"])
+
+ if file:
+ initialize_config_module('project-config', os.path.dirname(file[0]))
+ load_config('project-config', "project-config.jam", [os.path.dirname(file[0])], True)
+
+
+# Autoconfigure toolsets based on any instances of --toolset=xx,yy,...zz or
+# toolset=xx,yy,...zz in the command line. May return additional properties to
+# be processed as if they had been specified by the user.
+#
+def process_explicit_toolset_requests():
+
+ extra_properties = []
+
+ option_toolsets = [e for option in b2.util.regex.transform(sys.argv, "^--toolset=(.*)$")
+ for e in option.split(',')]
+ feature_toolsets = [e for option in b2.util.regex.transform(sys.argv, "^toolset=(.*)$")
+ for e in option.split(',')]
+
+ for t in option_toolsets + feature_toolsets:
+
+ # Parse toolset-version/properties.
+ (toolset_version, toolset, version) = re.match("(([^-/]+)-?([^/]+)?)/?.*", t).groups()
+
+ if debug_config:
+ print "notice: [cmdline-cfg] Detected command-line request for '%s': toolset= %s version=%s" \
+ % (toolset_version, toolset, version)
+
+ # If the toolset is not known, configure it now.
+ known = False
+ if toolset in feature.values("toolset"):
+ known = True
+
+ if known and version and not feature.is_subvalue("toolset", toolset, "version", version):
+ known = False
+ # TODO: we should do 'using $(toolset)' in case no version has been
+ # specified and there are no versions defined for the given toolset to
+ # allow the toolset to configure its default version. For this we need
+ # to know how to detect whether a given toolset has any versions
+ # defined. An alternative would be to do this whenever version is not
+ # specified but that would require that toolsets correctly handle the
+ # case when their default version is configured multiple times which
+ # should be checked for all existing toolsets first.
+
+ if not known:
+
+ if debug_config:
+ print "notice: [cmdline-cfg] toolset '%s' not previously configured; attempting to auto-configure now" % toolset_version
+ toolset.using(toolset, version)
+
+ else:
+
+ if debug_config:
+
+ print "notice: [cmdline-cfg] toolset '%s' already configured" % toolset_version
+
+ # Make sure we get an appropriate property into the build request in
+ # case toolset has been specified using the "--toolset=..." command-line
+ # option form.
+ if not t in sys.argv and not t in feature_toolsets:
+
+ if debug_config:
+ print "notice: [cmdline-cfg] adding toolset=%s) to the build request." % t ;
+ extra_properties += "toolset=%s" % t
+
+ return extra_properties
+
+
+
+# Returns 'true' if the given 'project' is equal to or is a (possibly indirect)
+# child to any of the projects requested to be cleaned in this build system run.
+# Returns 'false' otherwise. Expects the .project-targets list to have already
+# been constructed.
+#
+@cached
+def should_clean_project(project):
+
+ if project in project_targets:
+ return True
+ else:
+
+ parent = get_manager().projects().attribute(project, "parent-module")
+ if parent and parent != "user-config":
+ return should_clean_project(parent)
+ else:
+ return False
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+def main():
+
+ sys.argv = bjam.variable("ARGV")
+
+ # FIXME: document this option.
+ if "--profiling" in sys.argv:
+ import cProfile
+ r = cProfile.runctx('main_real()', globals(), locals(), "stones.prof")
+
+ import pstats
+ stats = pstats.Stats("stones.prof")
+ stats.strip_dirs()
+ stats.sort_stats('time', 'calls')
+ stats.print_callers(20)
+ return r
+ else:
+ try:
+ return main_real()
+ except ExceptionWithUserContext, e:
+ e.report()
+
+def main_real():
+
+ global debug_config, legacy_ignore_config, out_xml
+
+ debug_config = "--debug-configuration" in sys.argv
+ legacy_ignore_config = "--ignore_config" in sys.argv
+ out_xml = any(re.match("^--out-xml=(.*)$", a) for a in sys.argv)
+
+ engine = Engine()
+
+ global_build_dir = option.get("build-dir")
+ manager = Manager(engine, global_build_dir)
+
+ import b2.build.configure as configure
+
+ if "--version" in sys.argv:
+
+ version.report()
+ return
+
+ # This module defines types and generator and what not,
+ # and depends on manager's existence
+ import b2.tools.builtin
+
+ b2.tools.common.init(manager)
+
+ load_configuration_files()
+
+ extra_properties = []
+ # Note that this causes --toolset options to be ignored if --ignore-config
+ # is specified.
+ if not legacy_ignore_config:
+ extra_properties = process_explicit_toolset_requests()
+
+ # We always load project in "." so that 'use-project' directives have any
+ # chance of being seen. Otherwise, we would not be able to refer to
+ # subprojects using target ids.
+ current_project = None
+ projects = get_manager().projects()
+ if projects.find(".", "."):
+ current_project = projects.target(projects.load("."))
+
+ # In case there are no toolsets currently defined makes the build run using
+ # the default toolset.
+ if not legacy_ignore_config and not feature.values("toolset"):
+
+ dt = default_toolset
+ dtv = None
+ if default_toolset:
+ dtv = default_toolset_version
+ else:
+ dt = "gcc"
+ if os.name == 'nt':
+ dt = "msvc"
+ # FIXME:
+ #else if [ os.name ] = MACOSX
+ #{
+ # default-toolset = darwin ;
+ #}
+
+ print "warning: No toolsets are configured."
+ print "warning: Configuring default toolset '%s'." % dt
+ print "warning: If the default is wrong, your build may not work correctly."
+ print "warning: Use the \"toolset=xxxxx\" option to override our guess."
+ print "warning: For more configuration options, please consult"
+ print "warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html"
+
+ toolset.using(dt, dtv)
+
+ # Parse command line for targets and properties. Note that this requires
+ # that all project files already be loaded.
+ (target_ids, properties) = build_request.from_command_line(sys.argv[1:] + extra_properties)
+
+ # Expand properties specified on the command line into multiple property
+ # sets consisting of all legal property combinations. Each expanded property
+ # set will be used for a single build run. E.g. if multiple toolsets are
+ # specified then requested targets will be built with each of them.
+ if properties:
+ expanded = build_request.expand_no_defaults(properties)
+ else:
+ expanded = [property_set.empty()]
+
+ # Check that we actually found something to build.
+ if not current_project and not target_ids:
+ get_manager().errors()("no Jamfile in current directory found, and no target references specified.")
+ # FIXME:
+ # EXIT
+
+ # Flags indicating that this build system run has been started in order to
+ # clean existing instead of create new targets. Note that these are not the
+ # final flag values as they may get changed later on due to some special
+ # targets being specified on the command line.
+ clean = "--clean" in sys.argv
+ cleanall = "--clean-all" in sys.argv
+
+ # List of explicitly requested files to build. Any target references read
+ # from the command line parameter not recognized as one of the targets
+ # defined in the loaded Jamfiles will be interpreted as an explicitly
+ # requested file to build. If any such files are explicitly requested then
+ # only those files and the targets they depend on will be built and they
+ # will be searched for among targets that would have been built had there
+ # been no explicitly requested files.
+ explicitly_requested_files = []
+
+ # List of Boost Build meta-targets, virtual-targets and actual Jam targets
+ # constructed in this build system run.
+ targets = []
+ virtual_targets = []
+ actual_targets = []
+
+ explicitly_requested_files = []
+
+ # Process each target specified on the command-line and convert it into
+ # internal Boost Build target objects. Detect special clean target. If no
+ # main Boost Build targets were explictly requested use the current project
+ # as the target.
+ for id in target_ids:
+ if id == "clean":
+ clean = 1
+ else:
+ t = None
+ if current_project:
+ t = current_project.find(id, no_error=1)
+ else:
+ t = find_target(id)
+
+ if not t:
+ print "notice: could not find main target '%s'" % id
+ print "notice: assuming it's a name of file to create " ;
+ explicitly_requested_files.append(id)
+ else:
+ targets.append(t)
+
+ if not targets:
+ targets = [projects.target(projects.module_name("."))]
+
+ # FIXME: put this BACK.
+
+ ## if [ option.get dump-generators : : true ]
+ ## {
+ ## generators.dump ;
+ ## }
+
+
+ # We wish to put config.log in the build directory corresponding
+ # to Jamroot, so that the location does not differ depending on
+ # directory where we do build. The amount of indirection necessary
+ # here is scary.
+ first_project = targets[0].project()
+ first_project_root_location = first_project.get('project-root')
+ first_project_root_module = manager.projects().load(first_project_root_location)
+ first_project_root = manager.projects().target(first_project_root_module)
+ first_build_build_dir = first_project_root.build_dir()
+ configure.set_log_file(os.path.join(first_build_build_dir, "config.log"))
+
+ virtual_targets = []
+
+ global results_of_main_targets
+
+ # Now that we have a set of targets to build and a set of property sets to
+ # build the targets with, we can start the main build process by using each
+ # property set to generate virtual targets from all of our listed targets
+ # and any of their dependants.
+ for p in expanded:
+ manager.set_command_line_free_features(property_set.create(p.free()))
+
+ for t in targets:
+ try:
+ g = t.generate(p)
+ if not isinstance(t, ProjectTarget):
+ results_of_main_targets.extend(g.targets())
+ virtual_targets.extend(g.targets())
+ except ExceptionWithUserContext, e:
+ e.report()
+ except Exception:
+ raise
+
+ # Convert collected virtual targets into actual raw Jam targets.
+ for t in virtual_targets:
+ actual_targets.append(t.actualize())
+
+
+ # FIXME: restore
+## # If XML data output has been requested prepare additional rules and targets
+## # so we can hook into Jam to collect build data while its building and have
+## # it trigger the final XML report generation after all the planned targets
+## # have been built.
+## if $(.out-xml)
+## {
+## # Get a qualified virtual target name.
+## rule full-target-name ( target )
+## {
+## local name = [ $(target).name ] ;
+## local project = [ $(target).project ] ;
+## local project-path = [ $(project).get location ] ;
+## return $(project-path)//$(name) ;
+## }
+
+## # Generate an XML file containing build statistics for each constituent.
+## #
+## rule out-xml ( xml-file : constituents * )
+## {
+## # Prepare valid XML header and footer with some basic info.
+## local nl = "
+## " ;
+## local jam = [ version.jam ] ;
+## local os = [ modules.peek : OS OSPLAT JAMUNAME ] "" ;
+## local timestamp = [ modules.peek : JAMDATE ] ;
+## local cwd = [ PWD ] ;
+## local command = $(.sys.argv) ;
+## local bb-version = [ version.boost-build ] ;
+## .header on $(xml-file) =
+## "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+## "$(nl)<build format=\"1.0\" version=\"$(bb-version)\">"
+## "$(nl) <jam version=\"$(jam:J=.)\" />"
+## "$(nl) <os name=\"$(os[1])\" platform=\"$(os[2])\"><![CDATA[$(os[3-]:J= )]]></os>"
+## "$(nl) <timestamp><![CDATA[$(timestamp)]]></timestamp>"
+## "$(nl) <directory><![CDATA[$(cwd)]]></directory>"
+## "$(nl) <command><![CDATA[\"$(command:J=\" \")\"]]></command>"
+## ;
+## .footer on $(xml-file) =
+## "$(nl)</build>" ;
+
+## # Generate the target dependency graph.
+## .contents on $(xml-file) +=
+## "$(nl) <targets>" ;
+## for local t in [ virtual-target.all-targets ]
+## {
+## local action = [ $(t).action ] ;
+## if $(action)
+## # If a target has no action, it has no dependencies.
+## {
+## local name = [ full-target-name $(t) ] ;
+## local sources = [ $(action).sources ] ;
+## local dependencies ;
+## for local s in $(sources)
+## {
+## dependencies += [ full-target-name $(s) ] ;
+## }
+
+## local path = [ $(t).path ] ;
+## local jam-target = [ $(t).actual-name ] ;
+
+## .contents on $(xml-file) +=
+## "$(nl) <target>"
+## "$(nl) <name><![CDATA[$(name)]]></name>"
+## "$(nl) <dependencies>"
+## "$(nl) <dependency><![CDATA[$(dependencies)]]></dependency>"
+## "$(nl) </dependencies>"
+## "$(nl) <path><![CDATA[$(path)]]></path>"
+## "$(nl) <jam-target><![CDATA[$(jam-target)]]></jam-target>"
+## "$(nl) </target>"
+## ;
+## }
+## }
+## .contents on $(xml-file) +=
+## "$(nl) </targets>" ;
+
+## # Build $(xml-file) after $(constituents). Do so even if a
+## # constituent action fails and regenerate the xml on every bjam run.
+## INCLUDES $(xml-file) : $(constituents) ;
+## ALWAYS $(xml-file) ;
+## __ACTION_RULE__ on $(xml-file) = build-system.out-xml.generate-action ;
+## out-xml.generate $(xml-file) ;
+## }
+
+## # The actual build actions are here; if we did this work in the actions
+## # clause we would have to form a valid command line containing the
+## # result of @(...) below (the name of the XML file).
+## #
+## rule out-xml.generate-action ( args * : xml-file
+## : command status start end user system : output ? )
+## {
+## local contents =
+## [ on $(xml-file) return $(.header) $(.contents) $(.footer) ] ;
+## local f = @($(xml-file):E=$(contents)) ;
+## }
+
+## # Nothing to do here; the *real* actions happen in
+## # out-xml.generate-action.
+## actions quietly out-xml.generate { }
+
+## # Define the out-xml file target, which depends on all the targets so
+## # that it runs the collection after the targets have run.
+## out-xml $(.out-xml) : $(actual-targets) ;
+
+## # Set up a global __ACTION_RULE__ that records all the available
+## # statistics about each actual target in a variable "on" the --out-xml
+## # target.
+## #
+## rule out-xml.collect ( xml-file : target : command status start end user
+## system : output ? )
+## {
+## local nl = "
+## " ;
+## # Open the action with some basic info.
+## .contents on $(xml-file) +=
+## "$(nl) <action status=\"$(status)\" start=\"$(start)\" end=\"$(end)\" user=\"$(user)\" system=\"$(system)\">" ;
+
+## # If we have an action object we can print out more detailed info.
+## local action = [ on $(target) return $(.action) ] ;
+## if $(action)
+## {
+## local action-name = [ $(action).action-name ] ;
+## local action-sources = [ $(action).sources ] ;
+## local action-props = [ $(action).properties ] ;
+
+## # The qualified name of the action which we created the target.
+## .contents on $(xml-file) +=
+## "$(nl) <name><![CDATA[$(action-name)]]></name>" ;
+
+## # The sources that made up the target.
+## .contents on $(xml-file) +=
+## "$(nl) <sources>" ;
+## for local source in $(action-sources)
+## {
+## local source-actual = [ $(source).actual-name ] ;
+## .contents on $(xml-file) +=
+## "$(nl) <source><![CDATA[$(source-actual)]]></source>" ;
+## }
+## .contents on $(xml-file) +=
+## "$(nl) </sources>" ;
+
+## # The properties that define the conditions under which the
+## # target was built.
+## .contents on $(xml-file) +=
+## "$(nl) <properties>" ;
+## for local prop in [ $(action-props).raw ]
+## {
+## local prop-name = [ MATCH ^<(.*)>$ : $(prop:G) ] ;
+## .contents on $(xml-file) +=
+## "$(nl) <property name=\"$(prop-name)\"><![CDATA[$(prop:G=)]]></property>" ;
+## }
+## .contents on $(xml-file) +=
+## "$(nl) </properties>" ;
+## }
+
+## local locate = [ on $(target) return $(LOCATE) ] ;
+## locate ?= "" ;
+## .contents on $(xml-file) +=
+## "$(nl) <jam-target><![CDATA[$(target)]]></jam-target>"
+## "$(nl) <path><![CDATA[$(target:G=:R=$(locate))]]></path>"
+## "$(nl) <command><![CDATA[$(command)]]></command>"
+## "$(nl) <output><![CDATA[$(output)]]></output>" ;
+## .contents on $(xml-file) +=
+## "$(nl) </action>" ;
+## }
+
+## # When no __ACTION_RULE__ is set "on" a target, the search falls back to
+## # the global module.
+## module
+## {
+## __ACTION_RULE__ = build-system.out-xml.collect
+## [ modules.peek build-system : .out-xml ] ;
+## }
+
+## IMPORT
+## build-system :
+## out-xml.collect
+## out-xml.generate-action
+## : :
+## build-system.out-xml.collect
+## build-system.out-xml.generate-action
+## ;
+## }
+
+ j = option.get("jobs")
+ if j:
+ bjam.call("set-variable", PARALLELISM, j)
+
+ k = option.get("keep-going", "true", "true")
+ if k in ["on", "yes", "true"]:
+ bjam.call("set-variable", "KEEP_GOING", "1")
+ elif k in ["off", "no", "false"]:
+ bjam.call("set-variable", "KEEP_GOING", "0")
+ else:
+ print "error: Invalid value for the --keep-going option"
+ sys.exit()
+
+ # The 'all' pseudo target is not strictly needed expect in the case when we
+ # use it below but people often assume they always have this target
+ # available and do not declare it themselves before use which may cause
+ # build failures with an error message about not being able to build the
+ # 'all' target.
+ bjam.call("NOTFILE", "all")
+
+ # And now that all the actual raw Jam targets and all the dependencies
+ # between them have been prepared all that is left is to tell Jam to update
+ # those targets.
+ if explicitly_requested_files:
+ # Note that this case can not be joined with the regular one when only
+ # exact Boost Build targets are requested as here we do not build those
+ # requested targets but only use them to construct the dependency tree
+ # needed to build the explicitly requested files.
+ # FIXME: add $(.out-xml)
+ bjam.call("UPDATE", ["<e>%s" % x for x in explicitly_requested_files])
+ elif cleanall:
+ bjam.call("UPDATE", "clean-all")
+ elif clean:
+ manager.engine().set_update_action("common.Clean", "clean",
+ actual_clean_targets(targets))
+ bjam.call("UPDATE", "clean")
+ else:
+ # FIXME:
+ #configure.print-configure-checks-summary ;
+
+ if pre_build_hook:
+ for h in pre_build_hook:
+ h()
+
+ bjam.call("DEPENDS", "all", actual_targets)
+ ok = bjam.call("UPDATE_NOW", "all") # FIXME: add out-xml
+ if post_build_hook:
+ post_build_hook(ok)
+ # Prevent automatic update of the 'all' target, now that
+ # we have explicitly updated what we wanted.
+ bjam.call("UPDATE")
+
+ if manager.errors().count() == 0:
+ return ["ok"]
+ else:
+ return []
diff --git a/tools/build/v2/changes.txt b/tools/build/v2/changes.txt
new file mode 100644
index 0000000000..7ac8ffa2ff
--- /dev/null
+++ b/tools/build/v2/changes.txt
@@ -0,0 +1,317 @@
+Copyright 2004-2007 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+Milestone 13 (in development)
+
+Changes in this release:
+
+The following bugs were fixed:
+
+ - gcc suport did not work on HP-UX systems
+
+Milestone 12 (Oct 1, 2007)
+
+Changes in this release:
+
+ - The Pathscale, PGI and mipspro compilers are now supported.
+ - Support for autoconfiguration of toolset based on command-line
+ toolset=xxxx request, and for default toolset
+ configuration as a fallback.
+ - Support for precompiled headers for gcc toolset,
+ and improvements for msvc.
+ - Mechanism for removing inherited requirements.
+ - The 'make' rule support specifying usage-requirements.
+ - New 'project.extension' rule for declaring standalone
+ projects.
+ - New 'conditional' convenience rule.
+ - New 'glob-tree' rule.
+ - The 'glob' rule accepts patterns to exclude.
+ - Inline targets are now marked explicit automatically.
+ - Toolsets can now implicitly add requirements to
+ all targets.
+ - New 'generate' rule.
+ - The executables produced by the 'run' rule are automatically
+ removed after run.
+ - The gcc toolset uses the version obtained by running
+ the compiler, if no explicit one is provided.
+ - The sun toolset now supports the 'address-model' feature,
+ and uses -KPIC for shared libraries.
+ - Free features on command line affect all targets, not
+ just 'directly requested' ones.
+
+
+Documentation changes:
+
+ - Installation instructions for Linux distributors.
+ - Configuration options for all supported C++ compilers
+ are now documented.
+
+The following bugs were fixed:
+
+ - The 'cflags' and 'linkflags' now work on Darwin.o
+ - The intel toolset now works on Windows.
+ - Fix library search options for CodeWarriour toolset.
+ - The <install-source-root> could cause duplicate
+ mkdir commands.
+ - Numerious fixes in Boost autolink support
+ - Numerious fixes in Boost.Python support.
+ - Indirect properties not evaluated in usage requirements.
+ - Generator that returns a property set but not target is
+ considered successful.
+ - On Darwin, when several compiler versions
+ are configured, -fcoalesce-templates is applied only to
+ versions that need it.
+
+
+Milestone 11 (Jule 20, 2006)
+
+Changes in this release:
+
+ - New C++ compilers: IBM xlf, HP aCC, HP CXX, Intel fortran compiler.
+ - New tools: Qt4 support, MS message compiler and IDL compiler.
+ - New main targets: 'notfile' and 'cast'.
+
+ - Core changes:
+
+ - Only one file required at top level of a project, named Jamroot.
+ - Jamfiles can now contain project-specific help messages.
+ - "Indirect conditional requirements" introduced
+ (http://tinyurl.com/mn3jp)
+ - Strip suffix in main target names when computing names of generated
+ files (URL)
+ - The 'source-location' project attribute can contain
+ several directories.
+ - Usage requirements are propagated not only direct dependents,
+ but to indirect dependents.
+
+ - Command line option changes (see http://tinyurl.com/zbycz)
+ - New option --build-dir
+ - The --clean option cleans only target below the current directory,
+ not globally.
+ - New --clean-all option was added.
+ - New option --debug-building
+ - Running "bjam some_directory" works even if there's no Jamfile
+ in the current directory.
+
+ - Toolset improvements:
+ - Assembling support with gcc, borland and msvc.
+ - Support amd64/ia64 cross-compiling with msvc.
+ - Improved, registry-based autodetection for msvc.
+ - Serialize execution of gcc.link actions
+ - Precompiled headers supported on MSVC
+ (Need documentation)
+
+ - New features <warnings> and <warnings-as-errors>
+ - The 'glob' rule accepts wildcards in directory names.
+ - The 'stage' rule was renamed to 'install'
+ (the old name still available for compatibility)
+ - The <tag> feature can accept user-defined function as value
+ (URL)
+ - The 'install' rule can install a directory hierarchy preserving relative
+ paths.
+ - The 'install' rule no longer allows to change library
+ name during install.
+ - The Jamfile referred via 'use-project' may declare project id different
+ from the one in 'use-project'.
+ - The 'using' rule now searches the directory of containing Jamfile.
+
+
+The following bugs were fixed:
+
+ - The <library> feature was ignored for static linking
+ - Fix #include scanning for C files.
+ - Child projects were sometimes loaded before parent projects.
+ - Fix project references with absolute paths on Windows.
+ - The <dependency> feature was ignored for 'install' targets.
+ - A generator having the same type in sources and targets was causing hang.
+ - Use 'icpc' command for Intel, fixing errors with 8.1 and higher.
+ - Generation of PS files with the FOP tool really produces .PS files.
+ - No dependency scanning was done for C files.
+ - The 'constant' and 'path-constant' rules did not accept multi-element
+ value.
+ - Don't pass -fcoalesce-templates to gcc on OSX 10.4
+ - Fix static lib suffix on OSX.
+ - Fix rpath setting on Intel/Linux.
+ - The 'install' rule don't unnecessary scans #includes in installed
+ headers.
+
+
+Developer visible changes:
+
+ - Ability to customize type's prefix depending on build properties.
+ - Generator's 'run' method can return usage-requirements.
+ - Main target rule is automatically declared for each new target type.
+ - 'Link incompatible' feature attribute was removed
+ - Generators no longer bypass unhandled sources, they just ignore them.
+ - If there are several applicable generators, immediately report ambiguity.
+ Provide a way to explicitly resolve conflicts between generators.
+ - The 'flags' rule can match absense of feature.
+ - Great improvement in response files handling
+ - The 'toolset.flags' rules allows value-less feature to signify
+ absense of this feature (fix hack-hack).
+ - Automatically declare main target rule for each declared target type.
+ - When inheriting types, inherit generators for the base type, as opposed
+ to using various hacks to invoke base generators when needed.
+ - Improve diagnostic for "duplicate actual target" and generator ambiguity.
+
+
+Milestone 10 (October 29, 2004)
+
+Changes in this release:
+
+ Many toolsets were added: Intel, Metrowerks, Comeau, aCC, vacpp.
+ Documentation was converted to BoostBook and improved.
+ Performance was improved.
+
+ - Toolsets initialization syntax is much more uniform. Compiler and linker
+ flags can now be specified.
+ - The algorithm for computing build properties was improved. Conditional
+ requirements can be chained, and a number of bugs were fixed.
+ - Specific order of properties can be specified.
+ - The main target rules can be called from everywhere, not necessary from
+ Jamfile.
+ - Check for "unused sources" removed.
+ - The <library> feature affects only linking now.
+ - The <file> feature now works only for libraries.
+ - Simpler syntax for "searched" libraries was added.
+ - New <dependency> feature.
+
+
+ Unix:
+ The right order of static libraries on Unix is automatically
+ computed.
+ The <hardcode-dll-paths> feature is the default.
+ gcc:
+ The -fPIC option is passed when creating shared libraries.
+ Problems with distcc were solved.
+ Sun:
+ It's now possible to use the sun linker (as opposed to gnu), and
+ to compile C files.
+ Darwin:
+ Shared libraries are now supported.
+ MSVC: Before resource files compilation, the setup script is invoked.
+ Options deprecated in 8.0 are not longer used.
+
+
+The following bugs were fixed:
+
+ - The <unit-test> rule did not handle the <library> property (!!!!!!)
+ - Don't add "bin" to the build directory explicitly specified by the user.
+ - Allow <include-type> to select staged targets,
+ even with <traverse-dependencies>off.
+ - Includes for the form '# include <whatever>" did not work.
+ - (Qt) Add paths to all dependent libs to uic command
+ line, which helps if the UI files uses plugins.
+ - Using <toolset-msvc:version>xxx in requirements was broken.
+ - Error message printed when target can be found is much more clear.
+ - Inline targets in sources of 'stage' did not work.
+ - Don't produce 'independent target' warnings on Windows
+ - (gcc) The <link-runtime>static did not work.
+ - (gcc) Suppress warnings from the 'ar' tool on some systems.
+ - (gcc) Don't try to set soname on NT.
+
+Developer visible changes:
+
+ - Generator priorities are gone, explicit overrides are used.
+ - 'Active' features were removed
+ - Support for VMS paths was added.
+
+Thanks to Christopher Currie, Pedro Ferreira, Philipp Frauenfelder,
+Andre Hentz, Jurgen Hunold, Toon Knapen, Johan Nilsson, Alexey Pakhunov,
+Brock Peabody, Michael Stevens and Zbynek Winkler who contributed
+code to this release.
+
+
+Milestone 9.1 (Nov 6, 2003)
+
+The following bugs were fixed:
+
+ - The 'unit-test' rule used to ignore <library> properties.
+ - The gcc toolset used to ignore <threading> property.
+
+Milestone 9 (Nov 6, 2003)
+
+Changes in this release
+
+ - Putting library in sources of other library now works even for static
+ linking, which makes expressing library->library dependency much
+ simpler.
+ - Performance was considerably improved.
+ - Regression testing framework now works on windows.
+ - The "alias" rule can have usage requirements and passes on usage
+ requirements of sources.
+ - The "stage" rule can traverse dependencies.
+ - Support for "def files" was implemented.
+ - Targets paths are now shorter.
+ - Darwin toolset was improved.
+
+The following bugs were fixed:
+
+ - It was not possible to specify empty suffix for a target type derived
+ from other type.
+ - The stage rules used to generate incorrect suffix in some cases.
+ - It was possible to load Jamfile twice.
+ - The 'use-project' rule was broken when referring to a child project.
+ - Use of composite properties in requirements did not work.
+
+Developer visible changes:
+
+ - New CALC builtin, which considerable improves performance.
+ - Source layout was reorganized.
+ - Handling of response file was simplified.
+
+Thanks to Pedro Ferreira, Kirill Lapshin, Andre Hentz, Paul Lin,
+Jurgen Hunold, Christopher Currie, and Brock Peabody, who contributed to
+this release.
+
+Milestone 8 (Oct 15, 2003)
+
+Changes in this release:
+
+ - A regression testing framework was implemented.
+ - New <implicit-dependency> feature was added for better handling
+ of dependencies to generated headers.
+ - The link-compatibility checks not longer cause projects to be skipped,
+ and issue warning, not error, for main targets.
+ - Algorithm for selecting main target alternative was improved.
+ - The <dependency> feature was renamed to <use>.
+ - Project root constants were made available in project root itself.
+
+The following bugs were fixed:
+
+ - failure to recognize shared libraries with version as such
+ - the 'path-constant' rule was mishandling absolute paths on Windows.
+
+
+Milestone 7 (Sep 11, 2003)
+
+Changes in this release:
+
+ - Performance was improved.
+ - Support for Sun and Darwin toolsets was added.
+ - <tag> feature, which changes the name of target depending of build
+ variant, was implemented.
+ - Old-style targets-ids are no longer supported.
+ - New 'glob' rule allows to easily perform wildcard matching in Jamfile.
+ - Improve bison/flex support to understand C++.
+
+The following bugs were fixed:
+
+ - bogus error on use of project default-build attribute with several
+ main target alternatives.
+ - broken toolset inheritance
+ - hard error after skipping a target due to incompatible requirements
+ - incorrect behaviour of a generator when producing several targets of
+ the same type
+ - errors on use of the 'project-root' rule in Jamfile context
+ - inability to require specific compiler version for a main target.
+ - incorrect behaviour of "bjam msvc" when msvc is configured with explicit
+ version.
+
+Thanks to Christopher Currie, Pedro Ferreira and Michael Stevens, who
+contributed to this release.
+
+
+
+
diff --git a/tools/build/v2/contrib/boost.jam b/tools/build/v2/contrib/boost.jam
new file mode 100644
index 0000000000..388ac4d157
--- /dev/null
+++ b/tools/build/v2/contrib/boost.jam
@@ -0,0 +1,321 @@
+# $Id: boost.jam 63913 2010-07-12 07:37:43Z vladimir_prus $
+# Copyright 2008 Roland Schwarz
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Boost library support module.
+#
+# This module allows to use the boost library from boost-build projects.
+# The location of a boost source tree or the path to a pre-built
+# version of the library can be configured from either site-config.jam
+# or user-config.jam. If no location is configured the module looks for
+# a BOOST_ROOT environment variable, which should point to a boost source
+# tree. As a last resort it tries to use pre-built libraries from the standard
+# search path of the compiler.
+#
+# If the location to a source tree is known, the module can be configured
+# from the *-config.jam files:
+#
+# using boost : 1.35 : <root>/path-to-boost-root ;
+#
+# If the location to a pre-built version is known:
+#
+# using boost : 1.34
+# : <include>/usr/local/include/boost_1_34
+# <library>/usr/local/lib
+# ;
+#
+# It is legal to configure more than one boost library version in the config
+# files. The version identifier is used to disambiguate between them.
+# The first configured version becomes the default.
+#
+# To use a boost library you need to put a 'use' statement into your
+# Jamfile:
+#
+# import boost ;
+#
+# boost.use-project 1.35 ;
+#
+# If you don't care about a specific version you just can omit the version
+# part, in which case the default is picked up:
+#
+# boost.use-project ;
+#
+# The library can be referenced with the project identifier '/boost'. To
+# reference the program_options you would specify:
+#
+# exe myexe : mysrc.cpp : <library>/boost//program_options ;
+#
+# Note that the requirements are automatically transformed into suitable
+# tags to find the correct pre-built library.
+#
+
+import modules ;
+import errors ;
+import project ;
+import string ;
+import toolset ;
+import property-set ;
+import regex ;
+import common ;
+import option ;
+import numbers ;
+
+.boost.auto_config = [ property-set.create <layout>system ] ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+# Configuration of the boost library to use.
+#
+# This can either be a boost source tree or
+# pre-built libraries. The 'version' parameter must be a valid boost
+# version number, e.g. 1.35, if specifying a pre-built version with
+# versioned layout. It may be a symbolic name, e.g. 'trunk' if specifying
+# a source tree. The options are specified as named parameters (like
+# properties). The following paramters are available:
+#
+# <root>/path-to-boost-root: Specify a source tree.
+#
+# <include>/path-to-include: The include directory to search.
+#
+# <library>/path-to-library: The library directory to search.
+#
+# <layout>system or <layout>versioned.
+#
+# <build-id>my_build_id: The custom build id to use.
+#
+rule init
+(
+ version # Version identifier.
+ : options * # Set the option properties.
+)
+{
+ if $(.boost.$(version)) {
+ errors.user-error
+ "Boost " $(version) "already configured." ;
+ }
+ else {
+ if $(.debug-configuration) {
+ if ! $(.boost_default) {
+ echo notice: configuring default boost library $(version) ;
+ }
+ echo notice: configuring boost library $(version) ;
+ }
+ .boost_default ?= $(version) ; # the first configured is default
+ .boost.$(version) = [ property-set.create $(options) ] ;
+ }
+}
+
+# Use a certain version of the library.
+#
+# The use-project rule causes the module to define a boost project of
+# searchable pre-built boost libraries, or references a source tree
+# of the boost library. If the 'version' parameter is omitted either
+# the configured default (first in config files) is used or an auto
+# configuration will be attempted.
+#
+rule use-project
+(
+ version ? # The version of the library to use.
+)
+{
+ project.push-current [ project.current ] ;
+ version ?= $(.boost_default) ;
+ version ?= auto_config ;
+
+ if $(.initialized) {
+ if $(.initialized) != $(version) {
+ errors.user-error
+ "Attempt to use" $(__name__) "with different parameters" ;
+ }
+ }
+ else {
+ if $(.boost.$(version)) {
+ local opt = $(.boost.$(version)) ;
+ local root = [ $(opt).get <root> ] ;
+ local inc = [ $(opt).get <include> ] ;
+ local lib = [ $(opt).get <library> ] ;
+
+ if $(.debug-configuration) {
+ echo notice: using boost library $(version) [ $(opt).raw ] ;
+ }
+
+ .layout = [ $(opt).get <layout> ] ;
+ .layout ?= versioned ;
+ .build_id = [ $(opt).get <build-id> ] ;
+ .version_tag = [ regex.replace $(version) "[*\\/:.\"\' ]" "_" ] ;
+ .initialized = $(version) ;
+
+ if ( $(root) && $(inc) )
+ || ( $(root) && $(lib) )
+ || ( $(lib) && ! $(inc) )
+ || ( ! $(lib) && $(inc) ) {
+ errors.user-error
+ "Ambiguous parameters,"
+ "use either <root> or <inlude> with <library>." ;
+ }
+ else if ! $(root) && ! $(inc) {
+ root = [ modules.peek : BOOST_ROOT ] ;
+ }
+
+ local prj = [ project.current ] ;
+ local mod = [ $(prj).project-module ] ;
+
+ if $(root) {
+ modules.call-in $(mod) : use-project boost : $(root) ;
+ }
+ else {
+ project.initialize $(__name__) ;
+ # It is possible to overide the setup of the searched
+ # libraries per version. The (unlikely) tag 0.0.1 is
+ # meant as an example template only.
+ switch $(version) {
+ case 0.0.1 : boost_0_0_1 $(inc) $(lib) ;
+ case * : boost_std $(inc) $(lib) ;
+ }
+ }
+ }
+ else {
+ errors.user-error
+ "Reference to unconfigured boost version." ;
+ }
+ }
+ project.pop-current ;
+}
+
+rule boost_std ( inc ? lib ? )
+{
+# The default definitions for pre-built libraries.
+
+ project boost
+ : usage-requirements <include>$(inc) <define>BOOST_ALL_NO_LIB
+ : requirements <tag>@tag_std <search>$(lib)
+ ;
+
+ alias headers ;
+ lib date_time : : : :
+ <link>shared:<define>BOOST_DATE_TIME_DYN_LINK ;
+ lib filesystem : : : :
+ <link>shared:<define>BOOST_FILE_SYSTEM_DYN_LINK ;
+ lib graph : : : :
+ <link>shared:<define>BOOST_GRAPH_DYN_LINK ;
+ lib graph_parallel : : : :
+ <link>shared:<define>BOOST_GRAPH_DYN_LINK ;
+ lib iostreams : : : :
+ <link>shared:<define>BOOST_IOSTREAMS_DYN_LINK ;
+ lib math_tr1 : : : :
+ <link>shared:<define>BOOST_MATH_TR1_DYN_LINK ;
+ lib math_tr1f : : : :
+ <link>shared:<define>BOOST_MATH_TR1_DYN_LINK ;
+ lib math_tr1l : : : :
+ <link>shared:<define>BOOST_MATH_TR1_DYN_LINK ;
+ lib math_c99 : : : :
+ <link>shared:<define>BOOST_MATH_TR1_DYN_LINK ;
+ lib math_c99f : : : :
+ <link>shared:<define>BOOST_MATH_TR1_DYN_LINK ;
+ lib math_c99l : : : :
+ <link>shared:<define>BOOST_MATH_TR1_DYN_LINK ;
+ lib mpi : : : :
+ <link>shared:<define>BOOST_MPI_DYN_LINK ;
+ lib program_options : : : :
+ <link>shared:<define>BOOST_PROGRAM_OPTIONS_DYN_LINK ;
+ lib python : : : :
+ <link>shared:<define>BOOST_PYTHON_DYN_LINK ;
+ lib random : : : :
+ <link>shared:<define>BOOST_RANDOM_DYN_LINK ;
+ lib regex : : : :
+ <link>shared:<define>BOOST_REGEX_DYN_LINK ;
+ lib serialization : : : :
+ <link>shared:<define>BOOST_SERIALIZATION_DYN_LINK ;
+ lib wserialization : : : :
+ <link>shared:<define>BOOST_SERIALIZATION_DYN_LINK ;
+ lib signals : : : :
+ <link>shared:<define>BOOST_SIGNALS_DYN_LINK ;
+ lib system : : : :
+ <link>shared:<define>BOOST_SYSTEM_DYN_LINK ;
+ lib unit_test_framework : : : :
+ <link>shared:<define>BOOST_TEST_DYN_LINK ;
+ lib prg_exec_monitor : : : :
+ <link>shared:<define>BOOST_TEST_DYN_LINK ;
+ lib test_exec_monitor : : : :
+ <link>shared:<define>BOOST_TEST_DYN_LINK ;
+ lib thread : : : :
+ <link>shared:<define>BOOST_THREAD_DYN_DLL ;
+ lib wave : : : :
+ <link>shared:<define>BOOST_WAVE_DYN_LINK ;
+}
+
+rule boost_0_0_1 ( inc ? lib ? )
+{
+ echo "You are trying to use an example placeholder for boost libs." ;
+ # Copy this template to another place (in the file boost.jam)
+ # and define a project and libraries modelled after the
+ # boost_std rule. Please note that it is also possible to have
+ # a per version taging rule in case they are different between
+ # versions.
+}
+
+rule tag_std ( name : type ? : property-set )
+{
+ name = boost_$(name) ;
+ if ( [ $(property-set).get <link> ] in static ) &&
+ ( [ $(property-set).get <target-os> ] in windows )
+ {
+ name = lib$(name) ;
+ }
+
+ local result ;
+ if $(.layout) = system
+ {
+ local version = [ MATCH ^([0-9]+)_([0-9]+) : $(.version_tag) ] ;
+ if $(version[1]) = "1" && [ numbers.less $(version[2]) 39 ]
+ {
+ result = [ tag_tagged $(name) : $(type) : $(property-set) ] ;
+ }
+ else
+ {
+ result = [ tag_system $(name) : $(type) : $(property-set) ] ;
+ }
+ }
+ else if $(.layout) = tagged
+ {
+ result = [ tag_tagged $(name) : $(type) : $(property-set) ] ;
+ }
+ else if $(.layout) = versioned
+ {
+ result = [ tag_versioned $(name) : $(type) : $(property-set) ] ;
+ }
+ else
+ {
+ errors.error "Missing layout" ;
+ }
+
+ return $(result) ;
+}
+
+rule tag_system ( name : type ? : property-set )
+{
+ return [ common.format-name
+ <base>
+ -$(.build_id)
+ : $(name) : $(type) : $(property-set) ] ;
+}
+
+rule tag_tagged ( name : type ? : property-set )
+{
+ return [ common.format-name
+ <base> <threading> <runtime>
+ -$(.build_id)
+ : $(name) : $(type) : $(property-set) ] ;
+}
+
+rule tag_versioned ( name : type ? : property-set )
+{
+ return [ common.format-name
+ <base> <toolset> <threading> <runtime> -$(.version_tag)
+ -$(.build_id)
+ : $(name) : $(type) : $(property-set) ] ;
+}
diff --git a/tools/build/v2/contrib/tntnet.jam b/tools/build/v2/contrib/tntnet.jam
new file mode 100644
index 0000000000..0bd0ae5590
--- /dev/null
+++ b/tools/build/v2/contrib/tntnet.jam
@@ -0,0 +1,208 @@
+# Copyright 2008 Eduardo Gurgel
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+# Support for creating components for the Tntnet web application
+# server (http://tntnet.org)
+#
+# Example:
+#
+# using tntnet : /usr ;
+# lib index : index.png index.js index.css index.ecpp otherclass.cpp
+# /tntnnet//tntnet /tntnet//cxxtools ;
+#
+#
+
+import modules ;
+import feature ;
+import errors ;
+import "class" : new ;
+import generators ;
+import project ;
+import toolset : flags ;
+import os ;
+import virtual-target ;
+import scanner ;
+import type ;
+
+type.register ECPP : ecpp ;
+type.register JPEG : jpeg ;
+type.register JPG : jpg ;
+type.register PNG : png ;
+type.register JS : js ;
+type.register CSS : css ;
+type.register GIF : gif ;
+
+project.initialize $(__name__) ;
+project tntnet ;
+
+# Save the project so that we tolerate 'import + using' combo.
+.project = [ project.current ] ;
+# Initialized the Tntnet support module. The 'prefix' parameter
+# tells where Tntnet is installed.
+rule init ( prefix : full_bin ? : full_inc ? : full_lib ? )
+{
+ project.push-current $(.project) ;
+
+ # pre-build paths to detect reinitializations changes
+ local inc_prefix lib_prefix bin_prefix ;
+ if $(full_inc)
+ {
+ inc_prefix = $(full_inc) ;
+ }
+ else
+ {
+ inc_prefix = $(prefix)/include ;
+ }
+ if $(full_lib)
+ {
+ lib_prefix = $(full_lib) ;
+ }
+ else
+ {
+ lib_prefix = $(prefix)/lib ;
+ }
+ if $(full_bin)
+ {
+ bin_prefix = $(full_bin) ;
+ }
+ else
+ {
+ bin_prefix = $(prefix)/bin ;
+ }
+
+ if $(.initialized)
+ {
+ if $(prefix) != $(.prefix)
+ {
+ errors.error
+ "Attempt the reinitialize Tntnet with different installation prefix" ;
+ }
+ if $(inc_prefix) != $(.incprefix)
+ {
+ errors.error
+ "Attempt the reinitialize Tntnet with different include path" ;
+ }
+ if $(lib_prefix) != $(.libprefix)
+ {
+ errors.error
+ "Attempt the reinitialize Tntnet with different library path" ;
+ }
+ if $(bin_prefix) != $(.binprefix)
+ {
+ errors.error
+ "Attempt the reinitialize Tntnet with different bin path" ;
+ }
+ }
+ else
+ {
+ .initialized = true ;
+ .prefix = $(prefix) ;
+
+ # Setup prefixes for include, binaries and libs.
+ .incprefix = $(.prefix)/include ;
+ .libprefix = $(.prefix)/lib ;
+ .binprefix = $(.prefix)/bin ;
+
+ # Generates cpp files from ecpp files using "ecppc" tool
+ generators.register-standard tntnet.ecpp : ECPP : CPP ;
+ # Generates cpp files from jpeg files using "ecppc" tool
+ generators.register-standard tntnet.jpeg : JPEG : CPP ;
+ # Generates cpp files from jpg files using "ecppc" tool
+ generators.register-standard tntnet.jpg : JPG : CPP ;
+ # Generates cpp files from png files using "ecppc" tool
+ generators.register-standard tntnet.png : PNG : CPP ;
+ # Generates cpp files from js files using "ecppc" tool
+ generators.register-standard tntnet.js : JS : CPP ;
+ # Generates cpp files from gif files using "ecppc" tool
+ generators.register-standard tntnet.gif : GIF : CPP ;
+ # Generates cpp files from css files using "ecppc" tool
+ generators.register-standard tntnet.css : CSS : CPP ;
+ # Scanner for ecpp includes
+ type.set-scanner ECPP : ecpp-scanner ;
+
+
+ local usage-requirements =
+ <include>$(.incprefix)
+ <library-path>$(.libprefix)
+ <dll-path>$(.libprefix)
+ <threading>multi
+ <allow>tntnet ;
+ lib cxxtools : $(main)
+ :
+ :
+ :
+ <include>$(.incprefix)/cxxtools
+ $(usage-requiriments)
+ ;
+ lib tntnet : $(main)
+ :
+ :
+ :
+ <include>$(.incprefix)/tntnet
+ $(usage-requiriments)
+ ;
+
+ }
+ project.pop-current ;
+
+}
+
+rule directory
+{
+ return $(.prefix) ;
+}
+
+rule initialized ( )
+{
+ return $(.initialized) ;
+}
+
+# Get <include> from current toolset.
+flags tntnet.ecpp INCLUDES <include> ;
+
+actions ecpp
+{
+ $(.binprefix)/ecppc -I " $(INCLUDES) " -o $(<) $(>)
+}
+
+actions jpeg
+{
+ $(.binprefix)/ecppc -b -m image/jpeg -o $(<) $(>)
+}
+
+actions jpg
+{
+ $(.binprefix)/ecppc -b -m image/jpeg -o $(<) $(>)
+}
+
+actions js
+{
+ $(.binprefix)/ecppc -b -m application/x-javascript -o $(<) $(>)
+}
+
+actions png
+{
+ $(.binprefix)/ecppc -b -m image/png -o $(<) $(>)
+}
+actions gif
+{
+ $(.binprefix)/ecppc -b -m image/gif -o $(<) $(>)
+}
+actions css
+{
+ $(.binprefix)/ecppc -b -m text/css -o $(<) $(>)
+}
+
+class ecpp-scanner : common-scanner
+{
+ rule pattern ( )
+ {
+ return "<%include.*>(.*)</%include>" ;
+ }
+}
+
+scanner.register ecpp-scanner : include ;
diff --git a/tools/build/v2/contrib/wxFormBuilder.jam b/tools/build/v2/contrib/wxFormBuilder.jam
new file mode 100644
index 0000000000..c9ee2de729
--- /dev/null
+++ b/tools/build/v2/contrib/wxFormBuilder.jam
@@ -0,0 +1,195 @@
+################################################################################
+#
+# Copyright (c) 2007-2008 Dario Senic, Jurko Gospodnetic.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+################################################################################
+
+################################################################################
+#
+# Boost Build wxFormBuilder generator tool module.
+#
+# wxFormBuilder is a GUI designer tool for the wxWidgets library. It can then
+# generate C++ sources modeling the designed GUI using the wxWidgets library
+# APIs.
+#
+# This module defines a wxFormBuilder project file type and rules needed to
+# generate C++ source files from those projects. With it you can simply list
+# wxFormBuilder projects as sources for some target and Boost Build will
+# automatically convert them to C++ sources and process from there.
+#
+# The wxFormBuilder executable location may be provided as a parameter when
+# configuring this toolset. Otherwise the default wxFormBuilder.exe executable
+# name is used located in the folder pointed to by the WXFORMBUILDER environment
+# variable.
+#
+# Current limitations:
+#
+# * Works only on Windows.
+# * Works only when run via Boost Jam using the native Windows cmd.exe command
+# interpreter, i.e. the default native Windows Boost Jam build.
+# * Used wxFormBuilder projects need to have their output file names defined
+# consistently with target names assumed by this build script. This means
+# that their target names must use the prefix 'wxFormBuilderGenerated_' and
+# have no output folder defined where the base name is equal to the .fpb
+# project file's name.
+#
+################################################################################
+
+################################################################################
+#
+# Implementation note:
+#
+# Avoiding the limitation on the generated target file names can be done but
+# would require depending on external tools to copy the wxFormBuilder project to
+# a temp location and then modify it in-place to set its target file names. On
+# the other hand wxFormBuilder is expected to add command-line options for
+# choosing the target file names from the command line which will allow us to
+# remove this limitation in a much cleaner way.
+# (23.08.2008.) (Jurko)
+#
+################################################################################
+
+import generators ;
+import os ;
+import path ;
+import toolset ;
+import type ;
+
+
+################################################################################
+#
+# wxFormBuilder.generate()
+# ------------------------
+#
+# Action for processing WX_FORM_BUILDER_PROJECT types.
+#
+################################################################################
+#
+# Implementation notes:
+#
+# wxFormBuilder generated CPP and H files need to be moved to the location
+# where the Boost Build target system expects them so that the generated CPP
+# file can be included into the compile process and that the clean rule
+# succesfully deletes both CPP and H files. We expect wxFormBuilder to generate
+# files in the same location where the provided WX_FORM_BUILDER_PROJECT file is
+# located.
+# (15.05.2007.) (Dario)
+#
+################################################################################
+
+actions generate
+{
+ start "" /wait "$(EXECUTABLE)" /g "$(2)"
+ move "$(1[1]:BSR=$(2:P))" "$(1[1]:P)"
+ move "$(1[2]:BSR=$(2:P))" "$(1[2]:P)"
+}
+
+
+################################################################################
+#
+# wxFormBuilder.init()
+# --------------------
+#
+# Main toolset initialization rule called via the toolset.using rule.
+#
+################################################################################
+
+rule init ( executable ? )
+{
+ if $(.initialized)
+ {
+ if $(.debug-configuration)
+ {
+ ECHO notice: [wxFormBuilder-cfg] Repeated initialization request
+ (executable \"$(executable:E="")\") detected and ignored. ;
+ }
+ }
+ else
+ {
+ local environmentVariable = WXFORMBUILDER ;
+
+ if $(.debug-configuration)
+ {
+ ECHO notice: [wxFormBuilder-cfg] Configuring wxFormBuilder... ;
+ }
+
+ # Deduce the path to the used wxFormBuilder executable.
+ if ! $(executable)
+ {
+ executable = "wxFormBuilder.exe" ;
+ local executable-path = [ os.environ $(environmentVariable) ] ;
+ if $(executable-path)-is-not-empty
+ {
+ executable = [ path.root $(executable) $(executable-path) ] ;
+ }
+ else if $(.debug-configuration)
+ {
+ ECHO notice: [wxFormBuilder-cfg] No wxFormBuilder path
+ configured either explicitly or using the
+ $(environmentVariable) environment variable. ;
+ ECHO notice: [wxFormBuilder-cfg] To avoid complications please
+ update your configuration to includes a correct path to the
+ wxFormBuilder executable. ;
+ ECHO notice: [wxFormBuilder-cfg] wxFormBuilder executable will
+ be searched for on the system path. ;
+ }
+ }
+ if $(.debug-configuration)
+ {
+ ECHO notice: [wxFormBuilder-cfg] Will use wxFormBuilder executable
+ \"$(executable)\". ;
+ }
+
+ # Now we are sure we have everything we need to initialize this toolset.
+ .initialized = true ;
+
+ # Store the path to the used wxFormBuilder executable.
+ .executable = $(executable) ;
+
+ # Type registration.
+ type.register WX_FORM_BUILDER_PROJECT : fbp ;
+
+ # Parameters to be forwarded to the action rule.
+ toolset.flags wxFormBuilder.generate EXECUTABLE : $(.executable) ;
+
+ # Generator definition and registration.
+ generators.register-standard wxFormBuilder.generate :
+ WX_FORM_BUILDER_PROJECT : CPP(wxFormBuilderGenerated_%)
+ H(wxFormBuilderGenerated_%) ;
+ }
+}
+
+
+################################################################################
+#
+# wxFormBuilder.is-initialized()
+# ------------------------------
+#
+# Returns whether this toolset has been initialized.
+#
+################################################################################
+
+rule is-initialized ( )
+{
+ return $(.initialized) ;
+}
+
+
+################################################################################
+#
+# Startup code executed when loading this module.
+#
+################################################################################
+
+# Global variables for this module.
+.executable = ;
+.initialized = ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
diff --git a/tools/build/v2/debian/boost-build.docs b/tools/build/v2/debian/boost-build.docs
new file mode 100644
index 0000000000..70af14954e
--- /dev/null
+++ b/tools/build/v2/debian/boost-build.docs
@@ -0,0 +1,4 @@
+boost_build_v2.html
+index_v2.html
+boost.png
+doc \ No newline at end of file
diff --git a/tools/build/v2/debian/boost-build.examples b/tools/build/v2/debian/boost-build.examples
new file mode 100644
index 0000000000..e5a7b8d3bf
--- /dev/null
+++ b/tools/build/v2/debian/boost-build.examples
@@ -0,0 +1 @@
+example/* \ No newline at end of file
diff --git a/tools/build/v2/debian/changelog b/tools/build/v2/debian/changelog
new file mode 100644
index 0000000000..bfc1f139c4
--- /dev/null
+++ b/tools/build/v2/debian/changelog
@@ -0,0 +1,6 @@
+boost-build (2.0.m10-1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- Vladimir Prus <ghost@cs.msu.su> Wed, 14 Aug 2002 14:08:00 +0400
+
diff --git a/tools/build/v2/debian/conffiles b/tools/build/v2/debian/conffiles
new file mode 100644
index 0000000000..291d688edd
--- /dev/null
+++ b/tools/build/v2/debian/conffiles
@@ -0,0 +1 @@
+/etc/site-config.jam
diff --git a/tools/build/v2/debian/control b/tools/build/v2/debian/control
new file mode 100644
index 0000000000..7d1733e783
--- /dev/null
+++ b/tools/build/v2/debian/control
@@ -0,0 +1,13 @@
+Source: boost-build
+Section: devel
+Priority: optional
+Maintainer: Vladimir Prus <ghost@cs.msu.su>
+Build-Depends: debhelper (>> 3.0.0), docbook-to-man, bison
+Standards-Version: 3.5.2
+
+Package: boost-build
+Architecture: all
+Depends: ${shlibs:Depends}, bjam (>> 3.1.9-1)
+Description: Build system
+ Boost.Build is a build system with a simple and high-level language.
+ It supports build variants, and several different compilers and tools.
diff --git a/tools/build/v2/debian/copyright b/tools/build/v2/debian/copyright
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/debian/copyright
diff --git a/tools/build/v2/debian/excludes b/tools/build/v2/debian/excludes
new file mode 100644
index 0000000000..59882930dd
--- /dev/null
+++ b/tools/build/v2/debian/excludes
@@ -0,0 +1,14 @@
+boost.css
+boost_build_v2.html
+index_v2.html
+boost.png
+generators_prototype.py
+hacking.txt
+release_procedure.txt
+site-config.jam
+roll.sh
+debian
+doc
+example
+test
+CVS \ No newline at end of file
diff --git a/tools/build/v2/debian/rules b/tools/build/v2/debian/rules
new file mode 100755
index 0000000000..96ccc418b6
--- /dev/null
+++ b/tools/build/v2/debian/rules
@@ -0,0 +1,56 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# This file is public domain software, originally written by Joey Hess.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+build:
+clean:
+binary-arch:
+
+binary-indep:
+ dh_testdir
+ dh_testroot
+
+ dh_clean -k
+ dh_installdirs usr/share/boost-build etc
+
+ # Add here commands to install the package into debian/<packagename>
+ (tar --exclude-from debian/excludes -cpf - * ) | (cd `pwd`/debian/tmp/usr/share/boost-build && tar xpf - )
+ chmod a-x -R `pwd`/debian/tmp/usr/share/boost-build
+
+ dh_installchangelogs
+ dh_installdocs -XCVS
+ mv `pwd`/debian/tmp/usr/share/doc/boost-build/index_v2.html `pwd`/debian/tmp/usr/share/doc/boost-build/index.html
+
+ (tar --exclude make --exclude CVS -cpf - example/* ) | ( cd `pwd`/debian/tmp/usr/share/doc/boost-build && tar xpf - )
+
+ sed 's/# using gcc ;/using gcc ;/' user-config.jam > `pwd`/debian/tmp/etc/site-config.jam
+
+# dh_install
+# dh_installmenu
+# dh_installdebconf
+# dh_installlogrotate
+# dh_installemacsen
+# dh_installcatalogs
+# dh_installpam
+# dh_installmime
+# dh_installinit
+# dh_installcron
+# dh_installinfo
+# dh_undocumented
+ dh_installman
+ dh_link
+ dh_compress
+ dh_fixperms
+# dh_perl
+# dh_python
+# dh_makeshlibs
+ dh_installdeb
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
diff --git a/tools/build/v2/doc/bjam.qbk b/tools/build/v2/doc/bjam.qbk
new file mode 100644
index 0000000000..95207332dc
--- /dev/null
+++ b/tools/build/v2/doc/bjam.qbk
@@ -0,0 +1,1696 @@
+[article Boost.Jam
+ [quickbook 1.3]
+ [version: 3.1.19]
+ [authors [Rivera, Rene], [Abrahams, David], [Prus, Vladimir]]
+ [copyright 2003 2004 2005 2006 2007 Rene Rivera, David Abrahams, Vladimir Prus]
+ [category tool-build]
+ [id jam]
+ [dirname jam]
+ [purpose
+ Jam is a make(1) replacement that makes building simple things simple
+ and building complicated things manageable.
+ ]
+ [license
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ [@http://www.boost.org/LICENSE_1_0.txt])
+ ]
+]
+
+[/ QuickBook Document version 1.3 ]
+
+[/ Shortcuts ]
+
+[def :version: 3.1.19]
+
+[/ Images ]
+
+[def :NOTE: [$images/note.png]]
+[def :ALERT: [$images/caution.png]]
+[def :DETAIL: [$images/note.png]]
+[def :TIP: [$images/tip.png]]
+
+[/ Links ]
+
+[def :Boost: [@http://www.boost.org Boost]]
+[def :Perforce_Jam: [@http://www.perforce.com/jam/jam.html Perforce Jam]]
+
+[/ Templates ]
+
+[template literal[text]'''<literallayout><literal>'''[text]'''</literal></literallayout>''']
+[template list[items]'''<itemizedlist>'''[items]'''</itemizedlist>''']
+[template orderedlist[items]'''<orderedlist>'''[items]'''</orderedlist>''']
+[template li[text]'''<listitem>'''[text]'''</listitem>''']
+[template lines[items]'''<simplelist type='vert' columns='1'>'''[items]'''</simplelist>''']
+[template line[text]'''<member>'''[text]'''</member>''']
+
+[section:building Building BJam]
+
+Installing =BJam= after building it is simply a matter of copying the
+generated executables someplace in your =PATH=. For building the executables
+there are a set of =build= bootstrap scripts to accomodate particular
+environments. The scripts take one optional argument, the name of the toolset
+to build with. When the toolset is not given an attempt is made to detect an
+available toolset and use that. The build scripts accept these arguments:
+
+[pre
+/build/ \[/toolset/\]
+]
+
+Running the scripts without arguments will give you the best chance of success. On Windows platforms from a command console do:
+
+[pre
+cd /jam source location/
+.\\build.bat
+]
+
+On Unix type platforms do:
+
+[pre
+cd /jam source location/
+sh ./build.sh
+]
+
+For the Boost.Jam source included with the Boost distribution the /jam source location/ is =BOOST_ROOT/tools/jam/src=.
+
+If the scripts fail to detect an appropriate toolset to build with your particular toolset may not be auto-detectable. In that case, you can specify the toolset as the first argument, this assumes that the toolset is readily available in the =PATH=.
+
+[note
+The toolset used to build Boost.Jam is independent of the toolsets used for Boost.Build. Only one version of Boost.Jam is needed to use Boost.Build.
+]
+
+The supported toolsets, and whether they are auto-detected, are:
+
+[table Supported Toolsets
+
+[[Script] [Platform] [Toolset] [Detection and Notes]]
+
+[ [=build.bat=] [Windows NT, 2000, and XP]
+ [[lines
+ [line [@http://www.codegear.com/downloads/free/cppbuilder =borland=]]
+ [line [@http://www.borland.com/ Borland] C++Builder (BCC 5.5)]
+ ]]
+ [[list
+ [li Common install location: "=C:\Borland\BCC55="]
+ [li =BCC32.EXE= in =PATH=]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://www.comeaucomputing.com/ =como=]]
+ [line Comeau Computing C/C++]
+ ]]
+ []
+]
+
+[ [] []
+ [[lines
+ [line [@http://gcc.gnu.org/ =gcc=]]
+ [line GNU GCC]
+ ]]
+ []
+]
+
+[ [] []
+ [[lines
+ [line [@http://gcc.gnu.org/ =gcc-nocygwin=]]
+ [line GNU GCC]
+ ]]
+ []
+]
+
+[ [] []
+ [[lines
+ [line [@http://www.intel.com/software/products/compilers/c60 =intel-win32=]]
+ [line Intel C++ Compiler for Windows]
+ ]]
+ [[list
+ [li =ICL.EXE= in =PATH=]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://www.metrowerks.com/ =metrowerks=]]
+ [line MetroWerks CodeWarrior C/C++ 7.x, 8.x, 9.x]
+ ]]
+ [[list
+ [li =CWFolder= variable configured]
+ [li =MWCC.EXE= in =PATH=]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://www.mingw.org/ =mingw=]]
+ [line GNU [@http://gcc.gnu.org/ GCC] as the [@http://www.mingw.org/ MinGW] configuration]
+ ]]
+ [[list
+ [li Common install location: "=C:\MinGW="]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://msdn.microsoft.com/visualc/ =msvc=]]
+ [line Microsoft Visual C++ 6.x]
+ ]]
+ [[list
+ [li =VCVARS32.BAT= already configured]
+ [li =%MSVCDir%= is present in environment]
+ [li Common install locations: "=%ProgramFiles%\Microsoft Visual Studio=", "=%ProgramFiles%\Microsoft Visual C++="]
+ [li =CL.EXE= in =PATH=]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://msdn.microsoft.com/visualc/ =vc7=]]
+ [line Microsoft Visual C++ 7.x]
+ ]]
+ [[list
+ [li =VCVARS32.BAT= or =VSVARS32.BAT= already configured]
+ [li =%VS71COMNTOOLS%= is present in environment]
+ [li =%VCINSTALLDIR%= is present in environment]
+ [li Common install locations: "=%ProgramFiles%\Microsoft Visual Studio .NET=", "=%ProgramFiles%\Microsoft Visual Studio .NET 2003="]
+ [li =CL.EXE= in =PATH=]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://msdn.microsoft.com/visualc/ =vc8= and =vc9=]]
+ [line Microsoft Visual C++ 8.x and 9.x]
+ ]]
+ [Detection:
+ [list
+ [li =VCVARSALL.BAT= already configured]
+ [li =%VS90COMNTOOLS%= is present in environment]
+ [li Common install location: "=%ProgramFiles%\Microsoft Visual Studio 9="]
+ [li =%VS80COMNTOOLS%= is present in environment]
+ [li Common install location: "=%ProgramFiles%\Microsoft Visual Studio 8="]
+ [li =CL.EXE= in =PATH=]
+ ]
+
+ Notes:
+ [list
+ [li If =VCVARSALL.BAT= is called to set up the toolset, it is passed all the extra arguments, see below for what those arguments are. This can be used to build, for example, a Win64 specific version of =bjam=. Consult the VisualStudio documentation for what the possible argument values to the =VCVARSALL.BAT= are.]
+ ]
+ ]
+]
+
+[ [=build.sh=] [Unix, Linux, Cygwin, etc.]
+ [[lines
+ [line [@http://www.hp.com/go/c++ =acc=]]
+ [line HP-UX aCC]
+ ]]
+ [[list
+ [li =aCC= in =PATH=]
+ [li =uname= is "HP-UX"]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://www.comeaucomputing.com/ =como=]]
+ [line Comeau Computing C/C++]
+ ]]
+ [[list
+ [li como in =PATH=]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://gcc.gnu.org/ =gcc=]]
+ [line GNU GCC]
+ ]]
+ [[list
+ [li gcc in =PATH=]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://www.intel.com/software/products/compilers/c60l/ =intel-linux=]]
+ [line Intel C++ for Linux]
+ ]]
+ [[list
+ [li =icc= in =PATH=]
+ [li Common install locations: "=/opt/intel/cc/9.0=", "=/opt/intel_cc_80=", "=/opt/intel/compiler70=", "=/opt/intel/compiler60=", "=/opt/intel/compiler50="]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line =kcc=]
+ [line Intel KAI C++]
+ ]]
+ [[list
+ [li =KCC= in =PATH=]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://www.codegear.com/downloads/free/cppbuilder =kylix=]]
+ [line [@http://www.borland.com/ Borland] C++Builder]
+ ]]
+ [[list
+ [li bc++ in PATH]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://www.sgi.com/developers/devtools/languages/mipspro.html =mipspro=]]
+ [line SGI MIPSpro C]
+ ]]
+ [[list
+ [li =uname= is "=IRIX=" or "=IRIX64="]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line =sunpro=]
+ [line Sun Workshop 6 C++]
+ ]]
+ [[list
+ [li Standard install location: "=/opt/SUNWspro="]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line =qcc=]
+ [line [@http://www.qnx.com/ QNX Neutrino]]
+ ]]
+ [[list
+ [li =uname= is "=QNX=" and =qcc= in =PATH=]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://www.tru64unix.compaq.com/cplus/ =true64cxx=]]
+ [line Compaq C++ Compiler for True64 UNIX]
+ ]]
+ [[list
+ [li =uname= is "=OSF1="]
+ ]]
+]
+
+[ [] []
+ [[lines
+ [line [@http://www.ibm.com/software/awdtools/vacpp/ =vacpp=]]
+ [line IBM VisualAge C++]
+ ]]
+ [[list
+ [li =xlc= in =PATH=]
+ ]]
+]
+
+[ [] [MacOS X]
+ [[lines
+ [line [@http://developer.apple.com/tools/compilers.html =darwin=]]
+ [line Apple MacOS X GCC]
+ ]]
+ [[list
+ [li =uname= is "=Darwin="]
+ ]]
+]
+
+[ [] [Windows NT, 2000, and XP]
+ [[lines
+ [line [@http://www.mingw.org/ =mingw=]]
+ [line GNU [@http://gcc.gnu.org/ GCC] as the [@http://www.mingw.org/ MinGW] configuration with the MSYS shell]
+ ]]
+ [[list
+ [li Common install location: "=/mingw="]
+ ]]
+]
+
+]
+
+The built executables are placed in a subdirectory specific to your platform. For example, in Linux running on an Intel x86 compatible chip, the executables are placed in: "=bin.linuxx86=". The =bjam[.exe]= executable can be used to invoke Boost.Build.
+
+The build scripts support additional invocation arguments for use by developers of Boost.Jam and for additional setup of the toolset. The extra arguments come after the toolset:
+
+* Arguments not in the form of an option, before option arguments, are used for extra setup to toolset configuration scripts.
+* Arguments of the form "=--option=", which are passed to the =build.jam= build script.
+* Arguments not in the form of an option, after the options, which are targets for the =build.jam= script.
+
+[pre
+/build/ \[/toolset/\] \[/setup/\*\] \[--/option/+ /target/\*\]
+]
+
+The arguments immediately after the toolset are passed directly to the setup script of the toolset, if available and if it needs to be invoked. This allows one to configure the toolset ass needed to do non-default builds of =bjam=. For example to build a Win64 version with =vc8=. See the toolset descriptiona above for when particular toolsets support this.
+
+The arguments starting with the "=--option=" forms are passed to the =build.jam= script and are used to further customize what gets built. Options and targets supported by the =build.jam= script:
+
+[variablelist
+ [[[literal ---]]
+ [Empty option when one wants to only specify a target.]]
+ [[[literal --release]]
+ [The default, builds the optimized executable.]]
+ [[[literal --debug]]
+ [Builds debugging versions of the executable. When built they are placed in their own directory "=bin./platform/.debug=".]]
+ [[[literal --grammar]]
+ [Normally the Jam language grammar parsing files are not regenerated. This forces building of the grammar, although it may not force the regeneration of the grammar parser. If the parser is out of date it will be regenerated and subsequently built.]]
+ [[[literal --with-python=/path/]]
+ [Enables Python integration, given a path to the Python libraries.]]
+ [[[literal --gc]]
+ [Enables use of the Boehm Garbage Collector. The build will look for the Boehm-GC source in a "boehm_gc" subdirectory from the =bjam= sources.]]
+ [[[literal --duma]]
+ [Enables use of the DUMA (Detect Uintended Memory Access) debugging memory allocator. The build expects to find the DUMA source files in a "duma" subdirectory from the =bjam= sources.]]
+ [[[literal --toolset-root=/path/]]
+ [Indicates where the toolset used to build is located. This option is passed in by the bootstrap (=build.bat= or =build.sh=) script.]]
+ [[[literal --show-locate-target]]
+ [For information, prints out where it will put the built executable.]]
+ [[[literal --noassert]]
+ [Disable debug assertions, even if building the debug version of the executable.]]
+ [[[literal dist]]
+ [Generate packages (compressed archives) as appropriate for distribution in the platform, if possible.]]
+ [[[literal clean]]
+ [Remove all the built executables and objects.]]
+]
+
+[endsect]
+
+[section:language Language]
+
+=BJam= has an interpreted, procedural language. Statements in =bjam= are rule (procedure) definitions, rule invocations, flow-of-control structures, variable assignments, and sundry language support.
+
+[section:lexical Lexical Features]
+
+=BJam= treats its input files as whitespace-separated tokens, with two exceptions: double quotes (") can enclose whitespace to embed it into a token, and everything between the matching curly braces ({}) in the definition of a rule action is treated as a single string. A backslash (\\) can escape a double quote, or any single whitespace character.
+
+=BJam= requires whitespace (blanks, tabs, or newlines) to surround all tokens, including the colon (:) and semicolon (;) tokens.
+
+=BJam= keywords (an mentioned in this document) are reserved and generally
+must be quoted with double quotes (") to be used as arbitrary tokens, such as
+variable or target names.
+
+Comments start with the [^#] character and extend until the end of line.
+
+[endsect]
+
+[section:target Targets]
+
+The essential =bjam= data entity is a target. Build targets are files to be updated. Source targets are the files used in updating built targets. Built targets and source targets are collectively referred to as file targets, and frequently built targets are source targets for other built targets. Pseudotargets are symbols which represent dependencies on other targets, but which are not themselves associated with any real file.
+
+A file target's identifier is generally the file's name, which can be absolutely rooted, relative to the directory of =bjam='s invocation, or simply local (no directory). Most often it is the last case, and the actual file path is bound using the =$(SEARCH)= and =$(LOCATE)= special variables. See [link jam.language.variables.builtins.search SEARCH and LOCATE Variables] below. A local filename is optionally qualified with grist, a string value used to assure uniqueness. A file target with an identifier of the form /file(member)/ is a library member (usually an =ar=(1) archive on Unix).
+
+[section Binding Detection]
+
+Whenever a target is bound to a location in the filesystem, Boost Jam will look for a variable called =BINDRULE= (first "on" the target being bound, then in the global module). If non-empty, =$(BINDRULE[1])= names a rule which is called with the name of the target and the path it is being bound to. The signature of the rule named by =$(BINDRULE[1])= should match the following:
+
+[pre
+rule /bind-rule/ ( /target/ : /path/ )
+]
+
+This facility is useful for correct header file scanning, since many compilers will search for `#include` files first in the directory containing the file doing the `#include` directive. =$(BINDRULE)= can be used to make a record of that directory.
+
+[endsect]
+
+[endsect]
+
+[section:rules Rules]
+
+The basic =bjam= language entity is called a rule. A rule is defined in two parts: the procedure and the actions. The procedure is a body of jam statements to be run when the rule is invoked; the actions are the OS shell commands to execute when updating the built targets of the rule.
+
+Rules can return values, which can be expanded into a list with "[ /rule/ /args/ ... ]". A rule's value is the value of its last statement, though only the following statements have values: 'if' (value of the leg chosen), 'switch' (value of the case chosen), set (value of the resulting variable), and 'return' (value of its arguments). Note that 'return' doesn't actually cause a return, i.e., is a no-op unless it is the last statement of the last block executed within rule body.
+
+The =bjam= statements for defining and invoking rules are as follows:
+
+Define a rule's procedure, replacing any previous definition.
+
+[pre
+rule /rulename/ { /statements/ }
+]
+
+Define a rule's updating actions, replacing any previous definition.
+
+[pre
+actions \[ /modifiers/ \] /rulename/ { /commands/ }
+]
+
+Invoke a rule.
+
+[pre
+/rulename/ /field1/ : /field2/ : /.../ : /fieldN/ ;
+]
+
+Invoke a rule under the influence of target's specific variables..
+
+[pre
+on /target/ /rulename/ /field1/ : /field2/ : /.../ : /fieldN/ ;
+]
+
+Used as an argument, expands to the return value of the rule invoked.
+
+[pre
+\[ /rulename/ /field1/ : /field2/ : /.../ : /fieldN/ \]
+\[ on /target/ /rulename/ /field1/ : /field2/ : /.../ : /fieldN/ \]
+]
+
+A rule is invoked with values in /field1/ through /fieldN/. They may be referenced in the procedure's statements as [^$(1)] through [^$(['N])] (9 max), and the first two only may be referenced in the action's /commands/ as [^$(1)] and [^$(2)]. [^$(<)] and [^$(>)] are synonymous with [^$(1)] and [^$(2)].
+
+Rules fall into two categories: updating rules (with actions), and pure procedure rules (without actions). Updating rules treat arguments [^$(1)] and [^$(2)] as built targets and sources, respectively, while pure procedure rules can take arbitrary arguments.
+
+When an updating rule is invoked, its updating actions are added to those associated with its built targets ([^$(1)]) before the rule's procedure is run. Later, to build the targets in the updating phase, /commands/ are passed to the OS command shell, with [^$(1)] and [^$(2)] replaced by bound versions of the target names. See Binding above.
+
+Rule invocation may be indirected through a variable:
+
+[pre
+$(/var/) /field1/ : /field2/ : /.../ : /fieldN/ ;
+
+on /target/ $(/var/) /field1/ : /field2/ : /.../ : /fieldN/ ;
+
+\[ $(/var/) /field1/ : /field2/ : /.../ : /fieldN/ \]
+\[ on /target/ $(/var/) /field1/ : /field2/ : /.../ : /fieldN/ \]
+]
+
+The variable's value names the rule (or rules) to be invoked. A rule is
+invoked for each element in the list of [^$(/var/)]'s values. The fields
+[^/field1/ : /field2/ : /.../] are passed as arguments for each
+invokation. For the [ ... ] forms, the return value is the concatenation of
+the return values for all of the invocations.
+
+[section Action Modifiers]
+
+The following action modifiers are understood:
+
+[variablelist
+
+[[[^actions bind /vars/]]
+ [[^$(/vars/)] will be replaced with bound values.]]
+
+[[[^actions existing]]
+ [[^$(>)] includes only source targets currently existing.]]
+
+[[[^actions ignore]]
+ [The return status of the commands is ignored.]]
+
+[[[^actions piecemeal]]
+ [commands are repeatedly invoked with a subset of [^$(>)] small enough to fit in the command buffer on this OS.]]
+
+[[[^actions quietly]]
+ [The action is not echoed to the standard output.]]
+
+[[[^actions together]]
+ [The [^$(>)] from multiple invocations of the same action on the same built target are glommed together.]]
+
+[[[^actions updated]]
+ [[^$(>)] includes only source targets themselves marked for updating.]]
+
+]
+
+[endsect]
+
+[section Argument lists]
+
+You can describe the arguments accepted by a rule, and refer to them by name within the rule. For example, the following prints "I'm sorry, Dave" to the console:
+
+[pre
+rule report ( pronoun index ? : state : names + )
+{
+ local he.suffix she.suffix it.suffix = s ;
+ local I.suffix = m ;
+ local they.suffix you.suffix = re ;
+ ECHO $(pronoun)'$($(pronoun).suffix) $(state), $(names\[$(index)\]) ;
+}
+report I 2 : sorry : Joe Dave Pete ;
+]
+
+Each name in a list of formal arguments (separated by "=:=" in the rule declaration) is bound to a single element of the corresponding actual argument unless followed by one of these modifiers:
+
+[table
+[[Symbol] [Semantics of preceding symbol]]
+[[=?=] [optional]]
+[[=*=] [Bind to zero or more unbound elements of the actual argument. When =*= appears where an argument name is expected, any number of additional arguments are accepted. This feature can be used to implement "varargs" rules.]]
+[[=+=] [Bind to one or more unbound elements of the actual argument.]]
+]
+
+The actual and formal arguments are checked for inconsistencies, which cause Jam to exit with an error code:
+
+[pre
+### argument error
+# rule report ( pronoun index ? : state : names + )
+# called with: ( I 2 foo : sorry : Joe Dave Pete )
+# extra argument foo
+### argument error
+# rule report ( pronoun index ? : state : names + )
+# called with: ( I 2 : sorry )
+# missing argument names
+]
+
+If you omit the list of formal arguments, all checking is bypassed as in "classic" Jam. Argument lists drastically improve the reliability and readability of your rules, however, and are *strongly recommended* for any new Jam code you write.
+
+[endsect]
+
+[section:builtins Built-in Rules]
+
+=BJam= has a growing set of built-in rules, all of which are pure procedure rules without updating actions. They are in three groups: the first builds the dependency graph; the second modifies it; and the third are just utility rules.
+
+[section Dependency Building]
+
+[section =DEPENDS= ]
+
+[pre
+rule DEPENDS ( /targets1/ * : /targets2/ * )
+]
+
+Builds a direct dependency: makes each of /targets1/ depend on each of /targets2/. Generally, /targets1/ will be rebuilt if /targets2/ are themselves rebuilt or are newer than /targets1/.
+
+[endsect]
+
+[section =INCLUDES= ]
+
+[pre
+rule INCLUDES ( /targets1/ * : /targets2/ * )
+]
+
+Builds a sibling dependency: makes any target that depends on any of /targets1/ also depend on each of /targets2/. This reflects the dependencies that arise when one source file includes another: the object built from the source file depends both on the original and included source file, but the two sources files don't depend on each other. For example:
+
+[pre
+DEPENDS foo.o : foo.c ;
+INCLUDES foo.c : foo.h ;
+]
+
+"=foo.o=" depends on "=foo.c=" and "=foo.h=" in this example.
+
+[endsect]
+
+[endsect]
+
+[section Modifying Binding]
+
+The six rules =ALWAYS=, =LEAVES=, =NOCARE=, =NOTFILE=, =NOUPDATE=, and =TEMPORARY= modify the dependency graph so that =bjam= treats the targets differently during its target binding phase. See Binding above. Normally, =bjam= updates a target if it is missing, if its filesystem modification time is older than any of its dependencies (recursively), or if any of its dependencies are being updated. This basic behavior can be changed by invoking the following rules:
+
+[section =ALWAYS= ]
+
+[pre
+rule ALWAYS ( /targets/ * )
+]
+
+Causes /targets/ to be rebuilt regardless of whether they are up-to-date (they must still be in the dependency graph). This is used for the clean and uninstall targets, as they have no dependencies and would otherwise appear never to need building. It is best applied to targets that are also =NOTFILE= targets, but it can also be used to force a real file to be updated as well.
+
+[endsect]
+
+[section =LEAVES= ]
+
+[pre
+rule LEAVES ( /targets/ * )
+]
+
+Makes each of /targets/ depend only on its leaf sources, and not on any intermediate targets. This makes it immune to its dependencies being updated, as the "leaf" dependencies are those without their own dependencies and without updating actions. This allows a target to be updated only if original source files change.
+
+[endsect]
+
+[section =NOCARE= ]
+
+[pre
+rule NOCARE ( /targets/ * )
+]
+
+Causes =bjam= to ignore /targets/ that neither can be found nor have updating actions to build them. Normally for such targets =bjam= issues a warning and then skips other targets that depend on these missing targets. The =HdrRule= in =Jambase= uses =NOCARE= on the header file names found during header file scanning, to let =bjam= know that the included files may not exist. For example, if an `#include` is within an `#ifdef`, the included file may not actually be around.
+
+[warning For targets with build actions: if their build actions exit with a nonzero return code, dependent targets will still be built.]
+
+[endsect]
+
+[section =NOTFILE= ]
+
+[pre
+rule NOTFILE ( /targets/ * )
+]
+
+Marks /targets/ as pseudotargets and not real files. No timestamp is checked, and so the actions on such a target are only executed if the target's dependencies are updated, or if the target is also marked with =ALWAYS=. The default =bjam= target "=all=" is a pseudotarget. In =Jambase=, =NOTFILE= is used to define several addition convenient pseudotargets.
+
+[endsect]
+
+[section =NOUPDATE= ]
+
+[pre
+rule NOUPDATE ( /targets/ * )
+]
+
+Causes the timestamps on /targets/ to be ignored. This has two effects: first, once the target has been created it will never be updated; second, manually updating target will not cause other targets to be updated. In =Jambase=, for example, this rule is applied to directories by the =MkDir= rule, because =MkDir= only cares that the target directory exists, not when it has last been updated.
+
+[endsect]
+
+[section =TEMPORARY= ]
+
+[pre
+rule TEMPORARY ( /targets/ * )
+]
+
+Marks /targets/ as temporary, allowing them to be removed after other targets that depend upon them have been updated. If a =TEMPORARY= target is missing, =bjam= uses the timestamp of the target's parent. =Jambase= uses =TEMPORARY= to mark object files that are archived in a library after they are built, so that they can be deleted after they are archived.
+
+[endsect]
+
+[section =FAIL_EXPECTED= ]
+
+[pre
+rule FAIL_EXPECTED ( /targets/ * )
+]
+
+For handling targets whose build actions are expected to fail (e.g. when testing
+that assertions or compile-time type checking work properly), Boost Jam supplies
+the =FAIL_EXPECTED= rule in the same style as =NOCARE=, et. al. During target
+updating, the return code of the build actions for arguments to =FAIL_EXPECTED=
+is inverted: if it fails, building of dependent targets continues as though it
+succeeded. If it succeeds, dependent targets are skipped.
+
+[endsect]
+
+[section =RMOLD= ]
+
+[pre
+rule RMOLD ( /targets/ * )
+]
+
+=BJam= removes any target files that may exist on disk when the rule used to build those targets fails. However, targets whose dependencies fail to build are not removed by default. The =RMOLD= rule causes its arguments to be removed if any of their dependencies fail to build.
+
+[endsect]
+
+[section =ISFILE= ]
+
+[pre
+rule ISFILE ( /targets/ * )
+]
+
+=ISFILE= marks targets as required to be files. This changes the way =bjam= searches for the target such that it ignores mathes for file system items that are not file, like directories. This makes it possible to avoid `#include "exception"` matching if one happens to have a directory named exception in the header search path.
+
+[warning This is currently not fully implemented.]
+
+[endsect]
+
+[endsect]
+
+[section Utility]
+
+The two rules =ECHO= and =EXIT= are utility rules, used only in =bjam='s parsing phase.
+
+[section =ECHO= ]
+
+[pre
+rule ECHO ( /args/ * )
+]
+
+Blurts out the message /args/ to stdout.
+
+[endsect]
+
+[section =EXIT= ]
+
+[pre
+rule EXIT ( /message/ * : /result-value/ ? )
+]
+
+Blurts out the /message/ to stdout and then exits with a failure status if no /result-value/ is given, otherwise it exits with the given /result-value/.
+
+"=Echo=", "=echo=", "=Exit=", and "=exit=" are accepted as aliases for =ECHO= and =EXIT=, since it is hard to tell that these are built-in rules and not part of the language, like "=include=".
+
+[endsect]
+
+[section =GLOB= ]
+
+The =GLOB= rule does filename globbing.
+
+[pre
+rule GLOB ( /directories/ * : /patterns/ * : /downcase-opt/ ? )
+]
+
+Using the same wildcards as for the patterns in the switch statement. It is invoked by being used as an argument to a rule invocation inside of "=[ ]=". For example: "[^FILES = \[ GLOB dir1 dir2 : *.c *.h \]]" sets =FILES= to the list of C source and header files in =dir1= and =dir2=. The resulting filenames are the full pathnames, including the directory, but the pattern is applied only to the file name without the directory.
+
+If /downcase-opt/ is supplied, filenames are converted to all-lowercase before matching against the pattern; you can use this to do case-insensitive matching using lowercase patterns. The paths returned will still have mixed case if the OS supplies them. On Windows NT and Cygwin, filenames are always downcased before matching.
+
+[endsect]
+
+[section =MATCH= ]
+
+The =MATCH= rule does pattern matching.
+
+[pre
+rule MATCH ( /regexps/ + : /list/ * )
+]
+
+Matches the =egrep=(1) style regular expressions /regexps/ against the strings in /list/. The result is the concatenation of matching =()= subexpressions for each string in /list/, and for each regular expression in /regexps/. Only useful within the "=[ ]=" construct, to change the result into a list.
+
+[endsect]
+
+[section =BACKTRACE= ]
+
+[pre
+rule BACKTRACE ( )
+]
+
+Returns a list of quadruples: /filename/ /line/ /module/ /rulename/..., describing each shallower level of the call stack. This rule can be used to generate useful diagnostic messages from Jam rules.
+
+[endsect]
+
+[section =UPDATE= ]
+
+[pre
+rule UPDATE ( /targets/ * )
+]
+
+Classic jam treats any non-option element of command line as a name of target to be updated. This prevented more sophisticated handling of command line. This is now enabled again but with additional changes to the =UPDATE= rule to allow for the flexibility of changing the list of targets to update. The UPDATE rule has two effects:
+
+# It clears the list of targets to update, and
+# Causes the specified targets to be updated.
+
+If no target was specified with the =UPDATE= rule, no targets will be updated. To support changing of the update list in more useful ways, the rule also returns the targets previously in the update list. This makes it possible to add targets as such:
+
+[pre
+local previous-updates = \[ UPDATE \] ;
+UPDATE $(previous-updates) a-new-target ;
+]
+
+[endsect]
+
+[section =W32_GETREG= ]
+
+[pre
+rule W32_GETREG ( /path/ : /data/ ? )
+]
+
+Defined only for win32 platform. It reads the registry of Windows. '/path/' is the location of the information, and '/data/' is the name of the value which we want to get. If '/data/' is omitted, the default value of '/path/' will be returned. The '/path/' value must conform to MS key path format and must be prefixed with one of the predefined root keys. As usual,
+
+* '=HKLM=' is equivalent to '=HKEY_LOCAL_MACHINE='.
+* '=HKCU=' is equivalent to '=HKEY_CURRENT_USER='.
+* '=HKCR=' is equivalent to '=HKEY_CLASSES_ROOT='.
+
+Other predefined root keys are not supported.
+
+Currently supported data types : '=REG_DWORD=', '=REG_SZ=', '=REG_EXPAND_SZ=', '=REG_MULTI_SZ='. The data with '=REG_DWORD=' type will be turned into a string, '=REG_MULTI_SZ=' into a list of strings, and for those with '=REG_EXPAND_SZ=' type environment variables in it will be replaced with their defined values. The data with '=REG_SZ=' type and other unsupported types will be put into a string without modification. If it can't receive the value of the data, it just return an empty list. For example,
+
+[pre
+local PSDK-location =
+ \[ W32_GETREG HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\Microsoft\\\\MicrosoftSDK\\\\Directories : "Install Dir" \] ;
+]
+
+[endsect]
+
+[section =W32_GETREGNAMES= ]
+
+[pre
+rule W32_GETREGNAMES ( /path/ : /result-type/ )
+]
+
+Defined only for win32 platform. It reads the registry of Windows. '/path/' is the location of the information, and '/result-type/' is either '=subkeys=' or '=values='. For more information on '/path/' format and constraints, please see =W32_GETREG=.
+
+Depending on '/result-type/', the rule returns one of the following:
+
+[variablelist
+ [[=subkeys=] [Names of all direct subkeys of '/path/'.]]
+ [[=values=] [Names of values contained in registry key given by '/path/'. The "default" value of the key appears in the returned list only if its value has been set in the registry.]]
+]
+
+If '/result-type/' is not recognized, or requested data cannot be retrieved, the rule returns an empty list.
+Example:
+
+[pre
+local key = "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\App Paths" ;
+local subkeys = \[ W32_GETREGNAMES "$(key)" : subkeys \] ;
+for local subkey in $(subkeys)
+{
+ local values = \[ W32_GETREGNAMES "$(key)\\\\$(subkey)" : values \] ;
+ for local value in $(values)
+ {
+ local data = \[ W32_GETREG "$(key)\\\\$(subkey)" : "$(value)" \] ;
+ ECHO "Registry path: " $(key)\\\\$(subkey) ":" $(value) "=" $(data) ;
+ }
+}
+]
+
+[endsect]
+
+[section =SHELL= ]
+
+[pre
+rule SHELL ( /command/ : * )
+]
+
+=SHELL= executes /command/, and then returns the standard output of /command/. =SHELL= only works on platforms with a =popen()= function in the C library. On platforms without a working =popen()= function, =SHELL= is implemented as a no-op. =SHELL= works on Unix, MacOS X, and most Windows compilers. =SHELL= is a no-op on Metrowerks compilers under Windows. There is a variable set of allowed options as additional arguments:
+
+[variablelist
+ [[=exit-status=] [In addition to the output the result status of the executed command is returned as a second element of the result.]]
+ [[=no-output=] [Don't capture the output of the command. Instead an empty ("") string value is returned in place of the output.]]
+]
+
+Because the Perforce/Jambase defines a =SHELL= rule which hides the
+builtin rule, =COMMAND= can be used as an alias for =SHELL= in such a case.
+
+[endsect]
+
+[section =MD5= ]
+
+[pre
+rule MD5 ( /string/ )
+]
+
+=MD5= computes the MD5 hash of the string passed as paramater and returns it.
+
+[endsect]
+
+[section =SPLIT_BY_CHARACTERS= ]
+
+[pre
+rule SPLIT_BY_CHARACTERS ( /string/ : /delimiters/ )
+]
+
+=SPLIT_BY_CHARACTERS= splits the specified /string/ on any delimiter character
+present in /delimiters/ and returns the resulting list.
+
+[endsect]
+
+[section =PRECIOUS= ]
+
+[pre
+rule PRECIOUS ( /targets/ * )
+]
+
+The =PRECIOUS= rule specifies that each of the targets passed as the arguments
+should not be removed even if the command updating that target fails.
+
+[endsect]
+
+[section =PAD= ]
+
+[pre
+rule PAD ( /string/ : /width/ )
+]
+
+If /string/ is shorter than /width/ characters, pads it with whitespace
+characters on the right, and returns the result. Otherwise, returns
+/string/ unmodified.
+
+[endsect]
+
+[section =FILE_OPEN= ]
+
+[pre
+rule FILE_OPEN ( /filename/ : /mode/ )
+]
+
+The =FILE_OPEN= rule opens the specified file and returns a file
+descriptor. The /mode/ parameter can be either "w" or "r". Note
+that at present, only the =UPDATE_NOW= rule can use the resulting
+file descriptor number.
+
+[endsect]
+
+[section =UPDATE_NOW= ]
+
+[pre
+rule UPDATE_NOW ( /targets/ * : /log/ ? : /ignore-minus-n/ ? )
+]
+
+The =UPDATE_NOW= caused the specified targets to be updated immediately.
+If update was successfull, non-empty string is returned. The /log/ parameter,
+if present, specifies a descriptor of a file where all output from building
+is redirected. If the /ignore-minus-n/ parameter is specified, the targets
+are updated even if the =-n= parameter is specified on the command line.
+
+[endsect]
+
+[endsect]
+
+[endsect]
+
+[endsect]
+
+[section Flow-of-Control]
+
+=BJam= has several simple flow-of-control statements:
+
+[pre
+for /var/ in /list/ { /statements/ }
+]
+
+Executes /statements/ for each element in /list/, setting the variable /var/ to the element value.
+
+[pre
+if /cond/ { /statements/ }
+\[ else { /statements/ } \]
+]
+
+Does the obvious; the =else= clause is optional. /cond/ is built of:
+
+[variablelist
+
+[[[^['a]]]
+ [true if any ['a] element is a non-zero-length string]]
+
+[[[^['a] = ['b]]]
+ [list ['a] matches list ['b] string-for-string]]
+
+[[[^['a] != ['b]]]
+ [list ['a] does not match list ['b]]]
+
+[[[^['a] < ['b]]]
+ [['a\[i\]] string is less than ['b\[i\]] string, where ['i] is first mismatched element in lists ['a] and ['b]]]
+
+[[[^['a] <= ['b]]]
+ [every ['a] string is less than or equal to its ['b] counterpart]]
+
+[[[^['a] > ['b]]]
+ [['a\[i\]] string is greater than ['b\[i\]] string, where ['i] is first mismatched element]]
+
+[[[^['a] >= ['b]]]
+ [every ['a] string is greater than or equal to its ['b] counterpart]]
+
+[[[^['a] in ['b]]]
+ [true if all elements of ['a] can be found in ['b], or if ['a] has no elements]]
+
+[[[^! ['cond]]]
+ [condition not true]]
+
+[[[^['cond] && ['cond]]]
+ [conjunction]]
+
+[[[^['cond] || ['cond]]]
+ [disjunction]]
+
+[[[^( ['cond] )]]
+ [precedence grouping]]
+
+]
+
+[pre
+include /file/ ;
+]
+
+Causes =bjam= to read the named /file/. The /file/ is bound like a regular target (see Binding above) but unlike a regular target the include /file/ cannot be built.
+
+The include /file/ is inserted into the input stream during the parsing phase. The primary input file and all the included file(s) are treated as a single file; that is, jam infers no scope boundaries from included files.
+
+[pre
+local /vars/ \[ = /values/ \] ;
+]
+
+Creates new /vars/ inside to the enclosing ={}= block, obscuring any previous values they might have. The previous values for vars are restored when the current block ends. Any rule called or file included will see the local and not the previous value (this is sometimes called Dynamic Scoping). The local statement may appear anywhere, even outside of a block (in which case the previous value is restored when the input ends). The /vars/ are initialized to /values/ if present, or left uninitialized otherwise.
+
+[pre
+return /values/ ;
+]
+
+Within a rule body, the return statement sets the return value for an invocation of the rule. It does *not* cause the rule to return; a rule's value is actually the value of the last statement executed, so a return should be the last statement executed before the rule "naturally" returns.
+
+[pre
+switch /value/
+{
+ case /pattern1/ : /statements/ ;
+ case /pattern2/ : /statements/ ;
+ ...
+}
+]
+
+The switch statement executes zero or one of the enclosed /statements/, depending on which, if any, is the first case whose /pattern/ matches /value/. The /pattern/ values are not variable-expanded. The pattern values may include the following wildcards:
+
+[variablelist
+
+[[[^?]]
+ [match any single character]]
+
+[[[^*]]
+ [match zero or more characters]]
+
+[[[^\[/chars/\]]]
+ [match any single character in /chars/]]
+
+[[[^\[\^/chars/\]]]
+ [match any single character not in /chars/]]
+
+[[[^\\/x/]]
+ [match /x/ (escapes the other wildcards)]]
+
+]
+
+[pre
+while /cond/ { /statements/ }
+]
+
+Repeatedly execute /statements/ while /cond/ remains true upon entry. (See the description of /cond/ expression syntax under if, above).
+
+[endsect]
+
+[section Variables]
+
+=BJam= variables are lists of zero or more elements, with each element being a string value. An undefined variable is indistinguishable from a variable with an empty list, however, a defined variable may have one more elements which are null strings. All variables are referenced as [^$(/variable/)].
+
+Variables are either global or target-specific. In the latter case, the variable takes on the given value only during the updating of the specific target.
+
+A variable is defined with:
+
+[pre
+/variable/ = /elements/ ;
+/variable/ += /elements/ ;
+/variable/ on /targets/ = /elements/ ;
+/variable/ on /targets/ += /elements/ ;
+/variable/ default = /elements/ ;
+/variable/ ?= /elements/ ;
+]
+
+The first two forms set /variable/ globally. The third and forth forms set a target-specific variable. The [^\=] operator replaces any previous elements of /variable/ with /elements/; the [^+=] operation adds /elements/ to /variable/'s list of elements. The final two forms are synonymous: they set /variable/ globally, but only if it was previously unset.
+
+Variables referenced in updating commands will be replaced with their values; target-specific values take precedence over global values. Variables passed as arguments (=$(1)= and =$(2)=) to actions are replaced with their bound values; the "=bind=" modifier can be used on actions to cause other variables to be replaced with bound values. See Action Modifiers above.
+
+=BJam= variables are not re-exported to the environment of the shell that executes the updating actions, but the updating actions can reference =bjam= variables with [^$(/variable/)].
+
+[section:expansion Variable Expansion]
+
+During parsing, =bjam= performs variable expansion on each token that is not a keyword or rule name. Such tokens with embedded variable references are replaced with zero or more tokens. Variable references are of the form [^$(/v/)] or [^$(/vm/)], where ['v] is the variable name, and ['m] are optional modifiers.
+
+Variable expansion in a rule's actions is similar to variable expansion in statements, except that the action string is tokenized at whitespace regardless of quoting.
+
+The result of a token after variable expansion is the /product/ of the components of the token, where each component is a literal substring or a list substituting a variable reference. For example:
+
+[pre
+$(X) -> a b c
+t$(X) -> ta tb tc
+$(X)z -> az bz cz
+$(X)-$(X) -> a-a a-b a-c b-a b-b b-c c-a c-b c-c
+]
+
+The variable name and modifiers can themselves contain a variable reference, and this partakes of the product as well:
+
+[pre
+$(X) -> a b c
+$(Y) -> 1 2
+$(Z) -> X Y
+$($(Z)) -> a b c 1 2
+]
+
+Because of this product expansion, if any variable reference in a token is undefined, the result of the expansion is an empty list. If any variable element is a null string, the result propagates the non-null elements:
+
+[pre
+$(X) -> a ""
+$(Y) -> "" 1
+$(Z) ->
+-$(X)$(Y)- -> -a- -a1- -- -1-
+-$(X)$(Z)- ->
+]
+
+A variable element's string value can be parsed into grist and filename-related components. Modifiers to a variable are used to select elements, select components, and replace components. The modifiers are:
+
+[variablelist
+
+[[[^\[['n]\]]] [Select element number ['n] (starting at 1). If the variable
+ contains fewer than ['n] elements, the result is a zero-element list. ['n]
+ can be negative in which case the element number ['n] from the last leftward
+ is returned.]]
+
+[[[^\[['n]-['m]\]]]
+ [Select elements number ['n] through ['m]. ['n] and ['m] can be negative in which case they refer to elements counting from the last leftward.]]
+
+[[[^\[['n]-\]]]
+ [Select elements number ['n] through the last. ['n] can be negative in which case it refers to the element counting from the last leftward.]]
+
+[[[^:B]]
+ [Select filename base.]]
+
+[[[^:S]]
+ [Select (last) filename suffix.]]
+
+[[[^:M]]
+ [Select archive member name.]]
+
+[[[^:D]]
+ [Select directory path.]]
+
+[[[^:P]]
+ [Select parent directory.]]
+
+[[[^:G]]
+ [Select grist.]]
+
+[[[^:U]]
+ [Replace lowercase characters with uppercase.]]
+
+[[[^:L]]
+ [Replace uppercase characters with lowercase.]]
+
+[[[^:T]]
+ [Converts all back-slashes ("\\") to forward slashes ("/"). For example
+``
+ x = "C:\\Program Files\\Borland" ; ECHO $(x:T) ;
+``
+prints [^"C:/Program Files/Borland"]
+]]
+
+[[[^:W]]
+ [When invoking Windows-based tools from [@http://www.cygwin.com/ Cygwin]
+ it can be important to pass them true windows-style paths. The =:W=
+ modifier, *under Cygwin only*, turns a cygwin path into a Win32 path using
+ the [@http://www.cygwin.com/cygwin-api/func-cygwin-conv-to-win32-path.html
+ =cygwin_conv_to_win32_path=] function. On other platforms, the string is
+ unchanged. For example
+``
+ x = "/cygdrive/c/Program Files/Borland" ; ECHO $(x:W) ;
+``
+prints [^"C:\\Program Files\\Borland"] on Cygwin
+]]
+
+[[[^:['chars]]]
+ [Select the components listed in ['chars].]]
+
+[[[^:G=['grist]]]
+ [Replace grist with ['grist].]]
+
+[[[^:D=['path]]]
+ [Replace directory with ['path].]]
+
+[[[^:B=['base]]]
+ [Replace the base part of file name with ['base].]]
+
+[[[^:S=['suf]]]
+ [Replace the suffix of file name with ['suf].]]
+
+[[[^:M=['mem]]]
+ [Replace the archive member name with ['mem].]]
+
+[[[^:R=['root]]]
+ [Prepend ['root] to the whole file name, if not already rooted.]]
+
+[[[^:E=['value]]]
+ [Assign ['value] to the variable if it is unset.]]
+
+[[[^:J=['joinval]]]
+ [Concatentate list elements into single element, separated by ['joinval]'.]]
+
+]
+
+On VMS, [^$(var:P)] is the parent directory of [^$(var:D)].
+
+[endsect]
+
+[section Local For Loop Variables]
+
+Boost Jam allows you to declare a local for loop control variable right in the loop:
+
+[pre
+x = 1 2 3 ;
+y = 4 5 6 ;
+for *local* y in $(x)
+{
+ ECHO $(y) ; # prints "1", "2", or "3"
+}
+ECHO $(y) ; # prints "4 5 6"
+]
+
+[endsect]
+
+[section:atfile Generated File Expansion]
+
+During expansion of expressions =bjam= also looks for subexpressions of the form
+=@(filename:E=filecontents)= and replaces the expression with =filename= after
+creating the given file with the contents set to =filecontents=. This is useful
+for creating compiler response files, and other "internal" files. The expansion
+works both during parsing and action execution. Hence it is possible to create
+files during any of the three build phases.
+
+[endsect]
+
+[section:builtins Built-in Variables]
+
+This section discusses variables that have special meaning to =bjam=. All of
+these must be defined or used in the global module -- using those variables
+inside a named module will not have the desired effect.
+See [link jam.language.modules Modules].
+
+[section:search SEARCH and LOCATE]
+
+These two variables control the binding of file target names to locations in
+the file system. Generally, =$(SEARCH)= is used to find existing sources
+while =$(LOCATE)= is used to fix the location for built targets.
+
+Rooted (absolute path) file targets are bound as is. Unrooted file target names are also normally bound as is, and thus relative to the current directory, but the settings of =$(LOCATE)= and =$(SEARCH)= alter this:
+
+* If =$(LOCATE)= is set then the target is bound relative to the first directory in =$(LOCATE)=. Only the first element is used for binding.
+* If =$(SEARCH)= is set then the target is bound to the first directory in =$(SEARCH)= where the target file already exists.
+* If the =$(SEARCH)= search fails, the target is bound relative to the current directory anyhow.
+
+Both =$(SEARCH)= and =$(LOCATE)= should be set target-specific and not globally. If they were set globally, =bjam= would use the same paths for all file binding, which is not likely to produce sane results. When writing your own rules, especially ones not built upon those in Jambase, you may need to set =$(SEARCH)= or =$(LOCATE)= directly. Almost all of the rules defined in Jambase set =$(SEARCH)= and =$(LOCATE)= to sensible values for sources they are looking for and targets they create, respectively.
+
+[endsect]
+
+[section:hdrscan HDRSCAN and HDRRULE]
+
+These two variables control header file scanning. =$(HDRSCAN)= is an
+=egrep(1)= pattern, with ()'s surrounding the file name, used to find file
+inclusion statements in source files. =Jambase= uses =$(HDRPATTERN)= as the
+pattern for =$(HDRSCAN)=. =$(HDRRULE)= is the name of a rule to invoke with
+the results of the scan: the scanned file is the target, the found files are
+the sources. This is the only place where =bjam= invokes a rule through a
+variable setting.
+
+Both =$(HDRSCAN)= and =$(HDRRULE)= must be set for header file scanning to take place, and they should be set target-specific and not globally. If they were set globally, all files, including executables and libraries, would be scanned for header file include statements.
+
+The scanning for header file inclusions is not exact, but it is at least dynamic, so there is no need to run something like =makedepend(GNU)= to create a static dependency file. The scanning mechanism errs on the side of inclusion (i.e., it is more likely to return filenames that are not actually used by the compiler than to miss include files) because it can't tell if `#include` lines are inside `#ifdefs` or other conditional logic. In =Jambase=, =HdrRule= applies the =NOCARE= rule to each header file found during scanning so that if the file isn't present yet doesn't cause the compilation to fail, =bjam= won't care.
+
+Also, scanning for regular expressions only works where the included file name is literally in the source file. It can't handle languages that allow including files using variable names (as the =Jam= language itself does).
+
+[endsect]
+
+[section Semaphores]
+
+It is sometimes desirable to disallow parallel execution of some actions. For example:
+
+* Old versions of yacc use files with fixed names. So, running two yacc actions is dangerous.
+* One might want to perform parallel compiling, but not do parallel linking, because linking is i/o bound and only gets slower.
+
+Craig McPeeters has extended Perforce Jam to solve such problems, and that extension was integrated in Boost.Jam.
+
+Any target can be assigned a /semaphore/, by setting a variable called =SEMAPHORE= on that target. The value of the variable is the semaphore name. It must be different from names of any declared target, but is arbitrary otherwise.
+
+The semantic of semaphores is that in a group of targets which have the same semaphore, only one can be updated at the moment, regardless of "=-j=" option.
+
+[endsect]
+
+[section Platform Identifier]
+
+A number of Jam built-in variables can be used to identify runtime platform:
+
+[variablelist
+[[=OS=] [OS identifier string]]
+[[=OSPLAT=] [Underlying architecture, when applicable]]
+[[=MAC=] [true on MAC platform]]
+[[=NT=] [true on NT platform]]
+[[=OS2=] [true on OS2 platform]]
+[[=UNIX=] [true on Unix platforms]]
+[[=VMS=] [true on VMS platform]]
+]
+
+[endsect]
+
+[section Jam Version]
+
+[variablelist
+[[=JAMDATE=] [Time and date at =bjam= start-up as an ISO-8601 UTC value.]]
+[[=JAMUNAME=] [Ouput of uname(1) command (Unix only)]]
+[[=JAMVERSION=] [=bjam= version, currently ":version:"]]
+[[=JAM_VERSION=] [A predefined global variable with two elements indicates the version number of Boost Jam. Boost Jam versions start at "=03=" "=00=". Earlier versions of =Jam= do not automatically define =JAM_VERSION=.]]
+]
+
+[endsect]
+
+[section JAMSHELL]
+
+When =bjam= executes a rule's action block, it forks and execs a shell, passing the action block as an argument to the shell. The invocation of the shell can be controlled by =$(JAMSHELL)=. The default on Unix is, for example:
+
+[pre
+JAMSHELL = /bin/sh -c % ;
+]
+
+The =%= is replaced with the text of the action block.
+
+=BJam= does not directly support building in parallel across multiple hosts, since that is heavily dependent on the local environment. To build in parallel across multiple hosts, you need to write your own shell that provides access to the multiple hosts. You then reset =$(JAMSHELL)= to reference it.
+
+Just as =bjam= expands a =%= to be the text of the rule's action block, it expands a =!= to be the multi-process slot number. The slot number varies between 1 and the number of concurrent jobs permitted by the =-j= flag given on the command line. Armed with this, it is possible to write a multiple host shell. For example:
+
+[pre
+#!/bin/sh
+
+# This sample JAMSHELL uses the SunOS on(1) command to execute a
+# command string with an identical environment on another host.
+
+# Set JAMSHELL = jamshell ! %
+#
+# where jamshell is the name of this shell file.
+#
+# This version handles up to -j6; after that they get executed
+# locally.
+
+case $1 in
+1|4) on winken sh -c "$2";;
+2|5) on blinken sh -c "$2";;
+3|6) on nod sh -c "$2";;
+*) eval "$2";;
+esac
+]
+
+[endsect]
+
+[section:actionrule =__TIMING_RULE__= and =__ACTION_RULE__=]
+
+The =__TIMING_RULE__= and =__ACTION_RULE__= can be set to the name of a rule
+for =bjam= to call *after* an action completes for a target. They both give
+diagnostic information about the action that completed. For =__TIMING_RULE__=
+the rule is called as:
+
+ rule timing-rule ( args * : target : start end user system )
+
+And =__ACTION_RULE__= is called as:
+
+ rule action-rule ( args * : target : command status start end user system : output ? )
+
+The arguments for both are:
+
+[variablelist
+ [[[^args]]
+ [Any values following the rule name in the =__TIMING_RULE__= or =__ACTION_RULE__=
+ are passed along here.]]
+ [[[^target]]
+ [The =bjam= target that was built.]]
+ [[[^command]]
+ [The text of the executed command in the action body.]]
+ [[[^status]]
+ [The integer result of the executed command.]]
+ [[[^start]]
+ [The starting timestamp of the executed command as a ISO-8601 UTC value.]]
+ [[[^end]]
+ [The completion timestamp of the executed command as a ISO-8601 UTC value.]]
+ [[[^user]]
+ [The number of user CPU seconds the executed command spent as a floating
+ point value.]]
+ [[[^system]]
+ [The number of system CPU seconds the executed command spent as a floating
+ point value.]]
+ [[[^output]]
+ [The output of the command as a single string. The content of the output
+ reflects the use of the =-pX= option.]]
+]
+
+[note
+ If both variables are set for a target both are called, first =__TIMING_RULE__=
+ then =__ACTION_RULE__=. ]
+
+[endsect]
+
+[endsect]
+
+[endsect]
+
+[section Modules]
+
+Boost Jam introduces support for modules, which provide some rudimentary namespace protection for rules and variables. A new keyword, "=module=" was also introduced. The features described in this section are primitives, meaning that they are meant to provide the operations needed to write Jam rules which provide a more elegant module interface.
+
+[section Declaration]
+
+[pre
+module /expression/ { ... }
+]
+
+Code within the [^{ ... }] executes within the module named by evaluating expression. Rule definitions can be found in the module's own namespace, and in the namespace of the global module as /module-name/./rule-name/, so within a module, other rules in that module may always be invoked without qualification:
+
+[pre
+*module my_module*
+*{*
+ rule salute ( x ) { ECHO $(x), world ; }
+ rule greet ( ) { salute hello ; }
+ greet ;
+*}*
+*my_module.salute* goodbye ;
+]
+
+When an invoked rule is not found in the current module's namespace, it is looked up in the namespace of the global module, so qualified calls work across modules:
+
+[pre
+module your_module
+{
+ rule bedtime ( ) { *my_module.salute* goodnight ; }
+}
+]
+
+[endsect]
+
+[section Variable Scope]
+
+Each module has its own set of dynamically nested variable scopes. When execution passes from module A to module B, all the variable bindings from A become unavailable, and are replaced by the bindings that belong to B. This applies equally to local and global variables:
+
+[pre
+module A
+{
+ x = 1 ;
+ rule f ( )
+ {
+ local y = 999 ; # becomes visible again when B.f calls A.g
+ B.f ;
+ }
+ rule g ( )
+ {
+ ECHO $(y) ; # prints "999"
+ }
+}
+module B
+{
+ y = 2 ;
+ rule f ( )
+ {
+ ECHO $(y) ; # always prints "2"
+ A.g ;
+ }
+}
+]
+
+The only way to access another module's variables is by entering that module:
+
+[pre
+rule peek ( module-name ? : variables + )
+{
+ module $(module-name)
+ {
+ return $($(>)) ;
+ }
+}
+]
+
+Note that because existing variable bindings change whenever a new module scope is entered, argument bindings become unavailable. That explains the use of "=$(>)=" in the peek rule above.
+
+[endsect]
+
+[section Local Rules]
+
+[pre
+local rule /rulename/...
+]
+
+The rule is declared locally to the current module. It is not entered in the global module with qualification, and its name will not appear in the result of:
+
+[pre
+\[ RULENAMES /module-name/ \]
+]
+
+[endsect]
+
+[section The =RULENAMES= Rule]
+
+[pre
+rule RULENAMES ( /module/ ? )
+]
+
+Returns a list of the names of all non-local rules in the given module. If /module/ is omitted, the names of all non-local rules in the global module are returned.
+
+[endsect]
+
+[section The =VARNAMES= Rule]
+
+[pre
+rule VARNAMES ( /module/ ? )
+]
+
+Returns a list of the names of all variable bindings in the given module. If /module/ is omitted, the names of all variable bindings in the global module are returned.
+
+[note This includes any local variables in rules from the call stack which have not returned at the time of the =VARNAMES= invocation.]
+
+[endsect]
+
+[section The =IMPORT= Rule]
+
+=IMPORT= allows rule name aliasing across modules:
+
+[pre
+rule IMPORT ( /source_module/ ? : /source_rules/ *
+ : /target_module/ ? : /target_rules/ * )
+]
+
+The =IMPORT= rule copies rules from the /source_module/ into the /target_module/ as local rules. If either /source_module/ or /target_module/ is not supplied, it refers to the global module. /source_rules/ specifies which rules from the /source_module/ to import; /target_rules/ specifies the names to give those rules in /target_module/. If /source_rules/ contains a name which doesn't correspond to a rule in /source_module/, or if it contains a different number of items than /target_rules/, an error is issued. For example,
+
+[pre
+# import m1.rule1 into m2 as local rule m1-rule1.
+IMPORT m1 : rule1 : m2 : m1-rule1 ;
+# import all non-local rules from m1 into m2
+IMPORT m1 : \[ RULENAMES m1 \] : m2 : \[ RULENAMES m1 \] ;
+]
+
+[endsect]
+
+[section The =EXPORT= Rule]
+
+=EXPORT= allows rule name aliasing across modules:
+
+[pre
+rule EXPORT ( /module/ ? : /rules/ * )
+]
+
+The =EXPORT= rule marks /rules/ from the =source_module= as non-local (and thus exportable). If an element of /rules/ does not name a rule in /module/, an error is issued. For example,
+
+[pre
+module X {
+ local rule r { ECHO X.r ; }
+}
+IMPORT X : r : : r ; # error - r is local in X
+EXPORT X : r ;
+IMPORT X : r : : r ; # OK.
+]
+
+[endsect]
+
+[section The =CALLER_MODULE= Rule]
+
+[pre
+rule CALLER_MODULE ( /levels/ ? )
+]
+
+=CALLER_MODULE= returns the name of the module scope enclosing the call to its caller (if levels is supplied, it is interpreted as an integer number of additional levels of call stack to traverse to locate the module). If the scope belongs to the global module, or if no such module exists, returns the empty list. For example, the following prints "{Y} {X}":
+
+[pre
+module X {
+ rule get-caller { return \[ CALLER_MODULE \] ; }
+ rule get-caller's-caller { return \[ CALLER_MODULE 1 \] ; }
+ rule call-Y { return Y.call-X2 ; }
+}
+module Y {
+ rule call-X { return X.get-caller ; }
+ rule call-X2 { return X.get-caller's-caller ; }
+}
+callers = \[ X.get-caller \] \[ Y.call-X \] \[ X.call-Y \] ;
+ECHO {$(callers)} ;
+]
+
+[endsect]
+
+[section The =DELETE_MODULE= Rule]
+
+[pre
+rule DELETE_MODULE ( /module/ ? )
+]
+
+=DELETE_MODULE= removes all of the variable bindings and otherwise-unreferenced rules from the given module (or the global module, if no module is supplied), and returns their memory to the system.
+
+[note Though it won't affect rules that are currently executing until they complete, =DELETE_MODULE= should be used with extreme care because it will wipe out any others and all variable (including locals in that module) immediately. Because of the way dynamic binding works, variables which are shadowed by locals will not be destroyed, so the results can be really unpredictable.]
+
+[endsect]
+
+[endsect]
+
+[endsect]
+
+[section Miscellaneous]
+
+[section Diagnostics]
+
+In addition to generic error messages, =bjam= may emit one of the following:
+
+[pre warning: unknown rule X]
+
+A rule was invoked that has not been defined with an "=actions=" or "=rule=" statement.
+
+[pre using N temp target(s)]
+
+Targets marked as being temporary (but nonetheless present) have been found.
+
+[pre updating N target(s)]
+
+Targets are out-of-date and will be updated.
+
+[pre can't find N target(s)]
+
+Source files can't be found and there are no actions to create them.
+
+[pre can't make N target(s)]
+
+Due to sources not being found, other targets cannot be made.
+
+[pre warning: X depends on itself]
+
+A target depends on itself either directly or through its sources.
+
+[pre don't know how to make X]
+
+A target is not present and no actions have been defined to create it.
+
+[pre X skipped for lack of Y]
+
+A source failed to build, and thus a target cannot be built.
+
+[pre warning: using independent target X]
+
+A target that is not a dependency of any other target is being referenced with =$(<)= or =$(>)=.
+
+[pre X removed]
+
+=BJam= removed a partially built target after being interrupted.
+
+[endsect]
+
+[section Bugs, Limitations]
+
+For parallel building to be successful, the dependencies among files must be properly spelled out, as targets tend to get built in a quickest-first ordering. Also, beware of un-parallelizable commands that drop fixed-named files into the current directory, like =yacc(1)= does.
+
+A poorly set =$(JAMSHELL)= is likely to result in silent failure.
+
+[endsect]
+
+[section Fundamentals]
+
+This section is derived from the official Jam documentation and from experience using it and reading the Jambase rules. We repeat the information here mostly because it is essential to understanding and using Jam, but is not consolidated in a single place. Some of it is missing from the official documentation altogether. We hope it will be useful to anyone wishing to become familiar with Jam and the Boost build system.
+
+* Jam "=rules=" are actually simple procedural entities. Think of them as functions. Arguments are separated by colons.
+
+* A Jam *target* is an abstract entity identified by an arbitrary string. The build-in =DEPENDS= rule creates a link in the dependency graph between the named targets.
+
+* Note that the original Jam documentation for the built-in =INCLUDES= rule is incorrect: [^INCLUDES ['targets1] : ['targets2]] causes everything that depends on a member of /targets1/ to depend on all members of /targets2/. It does this in an odd way, by tacking /targets2/ onto a special tail section in the dependency list of everything in /targets1/. It seems to be OK to create circular dependencies this way; in fact, it appears to be the "right thing to do" when a single build action produces both /targets1/ and /targets2/.
+
+* When a rule is invoked, if there are =actions= declared with the same name as the rule, the actions are added to the updating actions for the target identified by the rule's first argument. It is actually possible to invoke an undeclared rule if corresponding actions are declared: the rule is treated as empty.
+
+* Targets (other than =NOTFILE= targets) are associated with paths in the file system through a process called binding. Binding is a process of searching for a file with the same name as the target (sans grist), based on the settings of the target-specific =SEARCH= and =LOCATE= variables.
+
+* In addition to local and global variables, jam allows you to set a variable =on= a target. Target-specific variable values can usually not be read, and take effect only in the following contexts:
+
+ * In updating actions, variable values are first looked up =on= the target named by the first argument (the target being updated). Because Jam builds its entire dependency tree before executing actions, Jam rules make target-specific variable settings as a way of supplying parameters to the corresponding actions.
+ * Binding is controlled /entirely/ by the target-specific setting of the =SEARCH= and =LOCATE= variables, as described here.
+ * In the special rule used for header file scanning, variable values are first looked up =on= the target named by the rule's first argument (the source file being scanned).
+
+* The "bound value" of a variable is the path associated with the target named by the variable. In build actions, the first two arguments are automatically replaced with their bound values. Target-specific variables can be selectively replaced by their bound values using the =bind= action modifier.
+
+* Note that the term "binding" as used in the Jam documentation indicates a phase of processing that includes three sub-phases: /binding/ (yes!), update determination, and header file scanning. The repetition of the term "binding" can lead to some confusion. In particular, the Modifying Binding section in the Jam documentation should probably be titled "Modifying Update Determination".
+
+* "Grist" is just a string prefix of the form </characters/>. It is used in Jam to create unique target names based on simpler names. For example, the file name "=test.exe=" may be used by targets in separate subprojects, or for the debug and release variants of the "same" abstract target. Each distinct target bound to a file called "test.exe" has its own unique grist prefix. The Boost build system also takes full advantage of Jam's ability to divide strings on grist boundaries, sometimes concatenating multiple gristed elements at the beginning of a string. Grist is used instead of identifying targets with absolute paths for two reasons:
+
+ # The location of targets cannot always be derived solely from what the user puts in a Jamfile, but sometimes depends also on the binding process. Some mechanism to distinctly identify targets with the same name is still needed.
+ # Grist allows us to use a uniform abstract identifier for each built target, regardless of target file location (as allowed by setting ALL_LOCATE_TARGET).
+
+* When grist is extracted from a name with $(var:G), the result includes the leading and trailing angle brackets. When grist is added to a name with $(var:G=expr), existing grist is first stripped. Then, if expr is non-empty, leading <s and trailing >s are added if necessary to form an expression of the form <expr2>; <expr2> is then prepended.
+
+* When Jam is invoked it imports all environment variable settings into corresponding Jam variables, followed by all command-line (-s...) variable settings. Variables whose name ends in PATH, Path, or path are split into string lists on OS-specific path-list separator boundaries (e.g. ":" for UNIX and ";" for Windows). All other variables are split on space (" ") boundaries. Boost Jam modifies that behavior by allowing variables to be quoted.
+
+* A variable whose value is an empty list or which consists entirely of empty
+ strings has a negative logical value. Thus, for example, code like the
+ following allows a sensible non-empty default which can easily be overridden
+ by the user:
+ ``
+MESSAGE ?\= starting jam... ;
+if $(MESSAGE) { ECHO The message is: $(MESSAGE) ; }
+``
+ If the user wants a specific message, he invokes jam with [^"-sMESSAGE\=message text"]. If he wants no message, he invokes jam with [^-sMESSAGE\=] and nothing at all is printed.
+
+* The parsing of command line options in Jam can be rather unintuitive, with regards to how other Unix programs accept options. There are two variants accepted as valid for an option:
+
+ # =-xvalue=, and
+ # =-x value=.
+
+[endsect]
+
+[endsect]
+
+
+[section History]
+[include history.qbk]
+[endsect]
diff --git a/tools/build/v2/doc/development_plan.html b/tools/build/v2/doc/development_plan.html
new file mode 100644
index 0000000000..598c23dae7
--- /dev/null
+++ b/tools/build/v2/doc/development_plan.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<!-- Copyright 2004 Aleksey Gurtovoy -->
+<!-- Copyright 2003, 2004 Vladimir Prus -->
+<!-- Distributed under the Boost Software License, Version 1.0. -->
+<!-- (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) -->
+
+<html>
+ <head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st April 2002), see www.w3.org">
+ <meta name="generator" content="Microsoft FrontPage 5.0">
+ <meta http-equiv="Content-Type" content=
+ "text/html; charset=windows-1252">
+ <!-- tidy options: &dash;&dash;tidy-mark false -i -wrap 78 !-->
+
+ <title>Boost Build System V2</title>
+ </head>
+
+ <body bgcolor="#FFFFFF" text="#000000">
+ <img src="../../../../boost.png" alt="boost.png (6897 bytes)" align="center"
+ width="277" height="86"> <!-- sf logo -->
+
+
+ <h1>Boost Build Development Plan</h1>
+
+ <ul>
+ <li>
+ <b>Milestone 2</b> (October 25, 2002)
+
+ <p>Boost buildable with gcc and also usable as part of another
+ project.</p>
+ </li>
+
+ <li>
+ <b>Milestone 3</b> (May 21, 2003)
+
+ <p>Two gcc versions and two other compilers are supported. Some other
+ tools (e.g. lex and BoostBook) are implemented.</p>
+ </li>
+
+ <li>
+ <b>Milestone 4</b> (June 18, 2003)
+
+ <p>More tools implemented.</p>
+ </li>
+
+ <li>
+ <b>Milestone 5</b> (Jule 2, 2003)
+
+ <p>Improvements and bugfixes with dependency scanning. Support for
+ i18n tools. Testing framework for Boost.</p>
+ </li>
+
+ <li>
+ <b>Milestone 6</b> (Jule 22, 2003)
+
+ <p>Bugfixes.</p>
+ </li>
+
+ <li>
+ <b>Milestone 7</b> (Aug 1, 2003)
+
+ <p>Optimizations.</p>
+ </li>
+
+ <li>
+ <b>Milestone 8</b> (Oct 15, 2003)
+
+ <p>Implementation of regression testing framework was
+ implemented. Handling of dependencies to generated headers was
+ optimized. Algorithms for link-compatibility checking and selecting
+ main target alternatives were improved.</p>
+ </li>
+
+ <li>
+ <b>Milestone 9.1</b> (Nov 06, 2003)
+
+ <p>Performance was considerably improved. The syntax for linking a
+ library into a library was simplified. The 'stage' rule can traverse
+ dependencies of the targets it installs. Regression testing support
+ now works on Windows. Some toolsets were improved. Bugs in project
+ loading and suffix determination were fixed.
+ </li>
+
+ <li>
+ <b>Milestone 10</b> (TBD)
+
+ <p>Remaining features for <a href="http://boost.org">C++ Boost</a>:
+ improved installation, Python support. Uniform toolset initialization
+ scheme. Many bugfixes</p>
+ </li>
+
+
+ <li>
+ <b>Alpha</b> (TBD)
+
+ <p>Optimization. Using buildable tools: consider using bison, which
+ is itself built with Boost.Build.</p>
+ </li>
+
+ <li>
+ <b>Beta</b> (TBD)
+
+ <p>Feature-complete milestone.</p>
+ </li>
+
+ <li>
+ <b>2.0 Release</b> (TBD)
+
+ <p>Bugfixes</p>
+ </li>
+ </ul>
+ <hr>
+
+ <p>&copy; Copyright Vladimir Prus 2002-2003. Permission to copy, use,
+ modify, sell and distribute this document is granted provided this
+ copyright notice appears in all copies. This document is provided "as is"
+ without express or implied warranty, and with no claim as to its
+ suitability for any purpose.</p>
+
+ <p>Revised
+ <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
+ -->23 Aug, 2004
+ <!--webbot bot="Timestamp" endspan i-checksum="13972"
+ -->
+ </p>
+ </body>
+</html>
+
diff --git a/tools/build/v2/doc/history.qbk b/tools/build/v2/doc/history.qbk
new file mode 100644
index 0000000000..f5a89b0c16
--- /dev/null
+++ b/tools/build/v2/doc/history.qbk
@@ -0,0 +1,377 @@
+[variablelist
+
+[[3.1.18] [
+
+After years of bjam developments.. This is going to be the last unbundled release of the
+3.1.x series. From this point forward bjam will only be bundled as part of the larger
+Boost Build system. And hence will likely change name at some point. As a side effect
+of this move people will get more frequent release of bjam (or whatever it ends up being
+called).
+
+[list
+ [li New built-ins, MD5, SPLIT_BY_CHARACTERS, PRECIOUS, PAD, FILE_OPEN, and UPDATE_NOW.
+ -- ['Vladimir P.]
+ ]
+ [li Ensure all file descriptors are closed when executing actions complete on *nix.
+ -- ['Noel B.]
+ ]
+ [li Fix warnings, patch from Mateusz Loskot.
+ -- ['Vladimir P.]
+ ]
+ [li Add KEEP_GOING var to programatically override the '-q' option.
+ -- ['Vladimir P.]
+ ]
+ [li Add more parameters, up to 19 from 9, to rule invocations. Patch from
+ Jonathan Biggar.
+ -- ['Vladimir P.]
+ ]
+ [li Print failed command output even if the normally quite '-d0' option.
+ -- ['Vladimir P.]
+ ]
+ [li Build of bjam with vc10, aka Visual Studio 2010.
+ -- ['Vladimir P.]
+ ]
+ [li More macros for detection of OSPLAT, patch from John W. Bito.
+ -- ['Vladimir P.]
+ ]
+ [li Add PARALLELISM var to programatically override the '-j' option.
+ -- ['Vladimir P.]
+ ]
+ [li Tweak doc building to allow for PDF generation of docs.
+ -- ['John M.]
+ ]
+]
+
+]]
+
+[[3.1.17] [
+
+A year in the making this release has many stability improvements and various performance
+improvements. And because of the efforts of Jurko the code is considerably more readable!
+
+[list
+ [li Reflect the results of calling bjam from Python.
+ -- ['Rene R.]
+ ]
+ [li For building on Windows: Rework how arguments are parsed and tested to fix handling
+ of quoted arguments, options arguments, and arguments with "=".
+ -- ['Rene R.]
+ ]
+ [li Try to work around at least one compiler bug with GCC and variable aliasing that
+ causes crashes with hashing file cache entries.
+ -- ['Rene R.]
+ ]
+ [li Add -Wc,-fno-strict-aliasing for QCC/QNX to avoid the same aliasing crashes as in
+ the general GCC 4.x series (thanks to Niklas Angare for the fix).
+ -- ['Rene R.]
+ ]
+ [li On Windows let the child bjam commands inherit stdin, as some commands assume
+ it's available.
+ -- ['Rene R.]
+ ]
+ [li On Windows don't limit bjam output to ASCII as some tools output characters in
+ extended character sets.
+ -- ['Rene R.]
+ ]
+ [li Isolate running of bjam tests to individual bjam instances to prevent possible
+ spillover errors from one test affecting another test. Separate the bjam used to run
+ the tests vs. the bjam being tested. And add automatic re-building of the bjam being
+ tested.
+ -- ['Rene R.]
+ ]
+ [li Fix some possible overrun issues revealed by Fortify build. Thanks to Steven Robbins
+ for pointing out the issues.
+ -- ['Rene R.]
+ ]
+ [li Handle \\n and \\r escape sequences.
+ -- ['Vladimir P.]
+ ]
+ [li Minor edits to remove -Wall warnings.
+ -- ['Rene R.]
+ ]
+ [li Dynamically adjust pwd buffer query size to allow for when PATH_MAX is default
+ defined instead of being provided by the system C library.
+ -- ['Rene R.]
+ ]
+ [li Minor perf improvement for bjam by replacing hash function with faster version. Only
+ 1% diff for Boost tree.
+ -- ['Rene R.]
+ ]
+ [li Updated Boost Jam's error location reporting when parsing Jamfiles. Now it reports
+ the correct error location information when encountering an unexpected EOF. It now
+ also reports where an invalid lexical token being read started instead of finished
+ which makes it much easier to find errors like unclosed quotes or curly braces.
+ -- ['Jurko G.]
+ ]
+ [li Removed the -xarch=generic architecture from build.jam
+ as this option is unknown so the Sun compilers on Linux.
+ -- ['Noel B.]
+ ]
+ [li Fixed a bug with T_FATE_ISTMP getting reported as T_FATE_ISTMP & T_FATE_NEEDTMP at
+ the same time due to a missing break in a switch statement.
+ -- ['Jurko G.]
+ ]
+ [li Fixed a Boost Jam bug causing it to sometimes trigger actions depending on targets
+ that have not been built yet.
+ -- ['Jurko G.]
+ ]
+ [li Added missing documentation for Boost Jam's :T variable expansion modifier which
+ converts all back-slashes ('\\') to forward slashed ('/').
+ -- ['Jurko G.]
+ ]
+ [li Added Boost Jam support for executing command lines longer than 2047 characters (up
+ to 8191) characters when running on Windows XP or later OS version.
+ -- ['Jurko G.]
+ ]
+ [li Fixed a Boost Jam bug on Windows causing its SHELL command not to work correctly with
+ some commands containing quotes.
+ -- ['Jurko G.]
+ ]
+ [li Corrected a potential memory leak in Boost Jam's builtin_shell() function that would
+ appear should Boost Jam ever start to release its allocated string objects.
+ -- ['Jurko G.]
+ ]
+ [li Made all Boost Jam's ECHO commands automatically flush the standard output to make
+ that output more promptly displayed to the user.
+ -- ['Jurko G.]
+ ]
+ [li Made Boost Jam tests quote their bjam executable name when calling it allowing those
+ executables to contain spaces in their name and/or path.
+ -- ['Jurko G.]
+ ]
+ [li Change execunix.c to always use fork() instead of
+ vfork() on the Mac. This works around known issues
+ with bjam on PPC under Tiger and a problem reported
+ by Rene with bjam on x86 under Leopard.
+ -- ['Noel B.]
+ ]
+ [li Corrected a bug in Boost Jam's base Jambase script causing it to trim the error
+ message displayed when its boost-build rule gets called multiple times.
+ -- ['Jurko G.]
+ ]
+ [li When importing from Python into an module with empty string as name,
+ import into root module.
+ -- ['Vladimir P.]
+ ]
+ [li Patch for the NORMALIZE_PATH builtin Boost Jam rule as well as an appropriate update
+ for the path.jam Boost Build module where that rule was being used to implement path
+ join and related operations.
+ -- ['Jurko G.]
+ ]
+ [li Fixed a bug causing Boost Jam not to handle target file names specified as both short
+ and long file names correctly.
+ -- ['Jurko G.]
+ ]
+ [li Relaxed test, ignoring case of drive letter.
+ -- ['Roland S.]
+ ]
+ [li Implemented a patch contributed by Igor Nazarenko reimplementing the list_sort()
+ function to use a C qsort() function instead of a hand-crafted merge-sort algorithm.
+ Makes some list sortings (e.g. 1,2,1,2,1,2,1,2, \.\.\.) extremely faster, in turn
+ significantly speeding up some project builds.
+ -- ['Jurko G.]
+ ]
+ [li Fixed a bug with bjam not handling the '\' root Windows path correctly without its
+ drive letter being specified.
+ -- ['Jurko G.]
+ ]
+ [li Solved the problem with child process returning the value 259 (Windows constant
+ STILL_ACTIVE) causing bjam never to detect that it exited and therefore keep running
+ in an endless loop.
+ -- ['Jurko G.]
+ ]
+ [li Solved the problem with bjam going into an active wait state, hogging up processor
+ resources, when waiting for one of its child processes to terminate while not all of
+ its available child process slots are being used.
+ -- ['Jurko G.]
+ ]
+ [li Solved a race condition between bjam's output reading/child process termination
+ detection and the child process's output generation/termination which could have
+ caused bjam not to collect the terminated process's final output.
+ -- ['Jurko G.]
+ ]
+ [li Change from vfork to fork for executing actions on Darwin to improve stability.
+ -- ['Noel B.]
+ ]
+ [li Code reformatting and cleanups.
+ -- ['Jurko G.]
+ ]
+ [li Implement ISFILE built-in.
+ -- ['Vladimir P.]
+ ]
+]
+
+]]
+
+[[3.1.16] [
+
+This is mostly a bug fix release.
+
+[list
+ [li Work around some Windows CMD.EXE programs that will fail executing a totally
+ empty batch file.
+ -- ['Rene R.]
+ ]
+ [li Add support for detection and building with =vc9=.
+ -- ['John P.]
+ ]
+ [li Plug memory leak when closing out actions. Thanks to Martin Kortmann for finding this.
+ -- ['Rene R.]
+ ]
+ [li Various improvements to =__TIMING_RULE__= and =__ACTION_RULE__= target variable
+ hooks.
+ -- ['Rene R.]
+ ]
+ [li Change [^JAMDATE] to use common ISO date format.
+ -- ['Rene R.]
+ ]
+ [li Add test for result status values of simple actions, i.e. empty actions.
+ -- ['Rene R.]
+ ]
+ [li Fix buffer overrun bug in expanding [^@()] subexpressions.
+ -- ['Rene R.]
+ ]
+ [li Check empty string invariants, instead of assuming all strings are allocated.
+ And reset strings when they are freed.
+ -- ['Rene R.]
+ ]
+ [li Add [^OSPLAT=PARISC] for HP-UX PA-RISC.
+ -- ['Boris G.]
+ ]
+ [li Make quietly actions really quiet by not printing the command output. The
+ output for the quietly actions is still available through =__ACTION_RULE__=.
+ -- ['Rene R.]
+ ]
+ [li Switch intel-win32 to use static multi thread runtime since the single
+ thread static runtime is no longer available.
+ -- ['Rene R.]
+ ]
+ [li When setting =OSPLAT=, check =__ia64= macro.
+ -- ['Boris G.]
+ ]
+ [li Get the unix timing working correctly.
+ -- ['Noel B.]
+ ]
+ [li Add =-fno-strict-aliasing= to compilation with gcc. Which works around
+ GCC-4.2 crash problems.
+ -- ['Boris G.]
+ ]
+ [li Increased support for Python integration.
+ -- ['Vladimir P.], ['Daniel W.]
+ ]
+ [li Allow specifying options with quotes, i.e. [^--with-python=xyz], to work
+ around the CMD shell using [^=] as an argument separator.
+ -- ['Rene R.]
+ ]
+ [li Add values of variables specified with -s to .EVNRION
+ module, so that we can override environment on
+ command line.
+ -- ['Vladimir P.]
+ ]
+ [li Make NORMALIZE_PATH convert \\ to /.
+ -- ['Vladimir P.]
+ ]
+]
+
+]]
+
+[[3.1.15] [
+
+This release sees a variety of fixes for long standing Perforce/Jam problems. Most of
+them relating to running actions in parallel with the -jN option. The end result of the
+changes is that running parallel actions is now reliably possible in Unix and Windows
+environments. Many thanks to Noel for joining the effort, to implement and fix the Unix
+side of stuff.
+
+[list
+ [li Add support for building bjam with pgi and pathscale toolsets.
+ -- ['Noel B.]
+ ]
+ [li Implement running action commands through pipes (-p option) to fix jumbled
+ output when using parallel execution with -j option. This is implemented
+ for Unix variants, and Windows (Win32/NT).
+ -- ['Rene R.], ['Noel B.]
+ ]
+ [li Add "sun" as alias to Sun Workshop compiler tools.
+ -- ['Rene R.]
+ ]
+ [li Set MAXLINE in jam.h to 23k bytes for AIX. The piecemeal archive action
+ was broken with the default MAXLINE of 102400. Because the AIX shell uses
+ some of the 24k default buffer size for its own use, I reduced it to 23k.
+ -- ['Noel B.]
+ ]
+ [li Make use of output dir options of msvc to not polute src dir with compiled files.
+ -- ['Rene R.]
+ ]
+ [li A small fix, so -d+2 will always show the "real" commands being executed
+ instead of casually the name of a temporary batch file.
+ -- ['Roland S.]
+ ]
+ [li Add test to check 'bjam -n'.
+ -- ['Rene R.]
+ ]
+ [li Add test to check 'bjam -d2'.
+ -- ['Rene R.]
+ ]
+ [li Bring back missing output of -n option. The -o option continues to be
+ broken as it has been for a long time now because of the @ file feature.
+ -- ['Rene R.]
+ ]
+ [li Update GC support to work with Boehm GC 7.0.
+ -- ['Rene R.]
+ ]
+ [li Revert the BOOST_BUILD_PATH change, since the directory passed to
+ boost-build should be first in searched paths, else project local
+ build system will not be picked correctly. The order had been changed to
+ allow searching of alternate user-config.jam files from boost build. This
+ better should be done with --user-config= switch or similar.
+ -- ['Roland S.]
+ ]
+ [li Initial support for defining action body from Python.
+ -- ['Vladimir P.]
+ ]
+ [li Implement @() expansion during parse phase.
+ -- ['Rene R.]
+ ]
+ [li Define OSPLAT var unconditionally, and more generically, when possible.
+ -- ['Rene R.]
+ ]
+ [li Fix undeclared INT_MAX on some platforms, i.e. Linux.
+ -- ['Rene R.]
+ ]
+ [li Modified execunix.c to add support for terminating
+ processes that consume too much cpu or that hang and
+ fail to consume cpu at all. This in support of the
+ bjam -lx option.
+ -- ['Noel B.]
+ ]
+ [li Add internal dependencies for multi-file generating actions to indicate
+ that the targets all only appear when the first target appears. This fixes
+ the long standing problem Perforce/Jam has with multi-file actions and
+ parallel execution (-jN).
+ -- ['Rene R.]
+ ]
+ [li Add test of -l limit option now that it's implemented on windows and unix.
+ -- ['Rene R.]
+ ]
+ [li Add test for no-op @() expansion.
+ -- ['Rene R.]
+ ]
+ [li Handle invalid formats of @() as doing a straight substitution instead of
+ erroring out.
+ -- ['Rene R.]
+ ]
+ [li Various fixes to compile on SGI/Irix.
+ -- ['Noel B.]
+ ]
+ [li Add output for when actions timeout with -lN option.
+ -- ['Rene R.], ['Noel B.]
+ ]
+ [li Add needed include (according to XOPEN) for definition of WIFEXITED and WEXITSTATUS.
+ -- ['Markus S.]
+ ]
+]
+
+]]
+
+]
diff --git a/tools/build/v2/doc/jamfile.jam b/tools/build/v2/doc/jamfile.jam
new file mode 100644
index 0000000000..9bfbd06411
--- /dev/null
+++ b/tools/build/v2/doc/jamfile.jam
@@ -0,0 +1,26 @@
+# Copyright 2004,2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import quickbook
+ ;
+
+project tools/build/v2/doc
+ ;
+
+boostbook userman : src/standalone.xml
+ : <xsl:param>toc.section.depth=1
+ <xsl:param>doc.standalone=true
+ <xsl:param>nav.layout=none
+ <implicit-dependency>jam_docs
+ <dependency>jam_docs
+ <xsl:param>boost.root=../../../../..
+ <xsl:param>boost.defaults=Boost
+ ;
+
+xml jam_docs : bjam.qbk ;
+
+if ! $(BOOST_ROOT)
+{
+ BOOST_ROOT = [ modules.peek : BOOST_ROOT ] ;
+}
diff --git a/tools/build/v2/doc/src/architecture.xml b/tools/build/v2/doc/src/architecture.xml
new file mode 100644
index 0000000000..2ee0edce41
--- /dev/null
+++ b/tools/build/v2/doc/src/architecture.xml
@@ -0,0 +1,636 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE appendix PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <appendix id="bbv2.arch">
+ <title>Boost.Build v2 architecture</title>
+
+ <sidebar>
+ <para>This document is work-in progress. Don't expect much from it
+ yet.</para>
+ </sidebar>
+
+ <section id="bbv2.arch.overview">
+ <title>Overview</title>
+
+ <para>The Boost.Build code is structured in four different components:
+ "kernel", "util", "build" and "tools". The first two are relatively
+ uninteresting, so we'll focus on the remaining pair. The "build" component
+ provides classes necessary to declare targets, determine which properties
+ should be used for their building, and for creating the dependency
+ graph. The "tools" component provides user-visible functionality. It
+ mostly allows to declare specific kind of main targets, and declare
+ avaiable tools, which are then used when creating the dependency graph.
+ </para>
+
+ </section>
+
+ <section id="bbv2.arch.build">
+ <title>The build layer</title>
+
+ <para>The build layer has just four main parts -- metatargets (abstract targets),
+ virtual targets, generators and properties.
+ <itemizedlist>
+ <listitem><para>Metatargets (see the "targets.jam" module) represent
+ all the user-defined entities which can be built. The "meta" prefix
+ signify that they don't really corrspond to files -- depending of
+ build request, they can produce different set of
+ files. Metatargets are created when Jamfiles are loaded. Each
+ metagarget has a <code>generate</code> method which is given a
+ property set and produces virtual targets for the passed properties.
+ </para></listitem>
+ <listitem><para>Virtual targets (see the "virtual-targets.jam"
+ module) correspond to the atomic things which can be updated --
+ most typically files.
+ </para></listitem>
+ <listitem><para>Properties are just (name, value) pairs, specified
+ by the user and describing how the targets should be
+ built. Properties are stored using the <code>property-set</code> class.
+ </para></listitem>
+ <listitem><para>Generators are the objects which encapsulate tools
+ -- they can take a list of source virtual targets and produce new
+ virtual targets from them.
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>The build process includes those steps:
+ <orderedlist>
+ <listitem><para>Top-level code calls the <code>generate</code>
+ method of a metatarget with some properties. </para></listitem>
+
+
+ <listitem><para>The metatarget combines the requested properties
+ with requirements and passes the result, together with the list
+ of sources, to the <code>generators.construct</code>
+ function</para></listitem>
+
+
+ <listitem><para>A generator appropriate for the build properties is
+ selected and its <code>run</code> method is
+ called. The method returns a list of virtual targets
+ </para></listitem>
+
+ <listitem><para>The targets are returned to the top level code. They
+ are converted into bjam targets (via
+ <code>virtual-target.actualize</code>) and passed to bjam for building.
+ </para></listitem>
+ </orderedlist>
+ </para>
+
+ <section id="bbv2.arch.metatargets">
+ <title>Metatargets</title>
+
+ <para>There are several classes derived from "abstract-target". The
+ "main-target" class represents top-level main target, the "project-target"
+ acts like container for all main targets, and "basic-target" class is a
+ base class for all further target types.
+ </para>
+
+ <para>Since each main target can have several alternatives, all top-level
+ target objects are just containers, referring to "real" main target
+ classes. The type is that container is "main-target". For example, given:
+<programlisting>
+alias a ;
+lib a : a.cpp : &lt;toolset&gt;gcc ;
+</programlisting>
+ we would have one-top level instance of "main-target-class", which will
+ contain one instance of "alias-target-class" and one instance of
+ "lib-target-class". The "generate" method of "main-target" decides
+ which of the alternative should be used, and call "generate" on the
+ corresponding instance.
+ </para>
+
+ <para>Each alternative is a instance of a class derived from
+ "basic-target". The "basic-target.generate" does several things that are
+ always should be done:
+ <itemizedlist>
+ <listitem>
+ <para>Determines what properties should be used for building the
+ target. This includes looking at requested properties, requirements,
+ and usage requirements of all sources.</para>
+ </listitem>
+ <listitem>
+ <para>Builds all sources</para>
+ </listitem>
+ <listitem>
+ <para>Computes the usage requirements which should be passes back.</para>
+ </listitem>
+ </itemizedlist>
+ For the real work of constructing virtual target, a new method
+ "construct" is called.
+ </para>
+
+ <para>The "construct" method can be implemented in any way by classes
+ derived from "basic-target", but one specific derived class plays the
+ central role -- "typed-target". That class holds the desired type of file
+ to be produces, and calls the generators modules to do the job.
+ </para>
+
+ <para>This means that a specific metatarget subclass may avoid using
+ generators at all. However, this is deprecated and we're trying to
+ eliminate all such subsclasses at the moment.
+ </para>
+
+ <para>Note that the <filename>build/targets.jam</filename> file contains
+ an UML diagram which might help.</para>
+
+ </section>
+
+ <section id="bbv2.arch.virtual">
+ <title>Virtual targets</title>
+
+ <para>Virtual targets correspond to the atomic things which can be
+ updated. Each virtual target can be assigned an updating action --
+ instance of the <code>action</code> class. The action class, in
+ turn, contains a list of source targets, properties, and a name of
+ bjam action block which should be executed.
+ </para>
+
+ <para>We try hard to never create equal instances of the
+ <code>virtual-target</code> class. Each code which creates virtual
+ targets passes them though the <code>virtual-target.register</code>
+ function, which detects if a target with the same name, sources, and
+ properties was created. In that case, existing target is returned.
+ </para>
+
+ <para>When all virtual targets are produced, they are
+ "actualized". This means that the real file names are computed, and
+ the commands that should be run are generated. This is done by the
+ <code>virtual-target.actualize</code> method and the
+ <code>action.actualize</code> methods. The first is conceptually
+ simple, while the second need additional explanation. The commands
+ in bjam are generated in two-stage process. First, a rule with the
+ appropriate name (for example
+ "gcc.compile") is called and is given the names of targets. The rule
+ sets some variables, like "OPTIONS". After that, the command string
+ is taken, and variable are substitutes, so use of OPTIONS inside the
+ command string become the real compile options.
+ </para>
+
+ <para>Boost.Build added a third stage to simplify things. It's now
+ possible to automatically convert properties to appropriate assignments to
+ variables. For example, &lt;debug-symbols&gt;on would add "-g" to the
+ OPTIONS variable, without requiring to manually add this logic to
+ gcc.compile. This functionality is part of the "toolset" module.
+ </para>
+
+ <para>Note that the <filename>build/virtual-targets.jam</filename> file
+ contains an UML diagram which might help.</para>
+ </section>
+
+ <section id="bbv2.arch.properties">
+ <para>Above, we noted that metatargets are built with a set of
+ properties. That set is represented with the
+ <code>property-set</code> class. An important point is that handling
+ of property sets can get very expensive. For that reason, we make
+ sure that for each set of (name, value) pairs only one
+ <code>property-set</code> instance is created. The
+ <code>property-set</code> uses extensive caching for all operation,
+ so most work is avoided. The <code>property-set.create</code> is the
+ factory function which should be used to create instances of the
+ <code>property-set</code> class.
+ </para>
+ </section>
+
+
+ </section>
+
+ <section id="bbv2.arch.tools">
+ <title>The tools layer</title>
+
+ <para>Write me!</para>
+
+ </section>
+
+ <section id="bbv2.arch.targets">
+ <title>Targets</title>
+
+ <para>NOTE: THIS SECTION IS NOT EXPECTED TO BE READ!
+ There are two user-visible kinds of targets in Boost.Build.
+ First are "abstract" &#x2014; they correspond to things declared
+ by user, for example, projects and executable files. The primary
+ thing about abstract target is that it's possible to request them
+ to be build with a particular values of some properties. Each
+ combination of properties may possible yield different set of
+ real file, so abstract target do not have a direct correspondence
+ with files.</para>
+
+ <para>File targets, on the contary, are associated with concrete
+ files. Dependency graphs for abstract targets with specific
+ properties are constructed from file targets. User has no was to
+ create file targets, however it can specify rules that detect
+ file type for sources, and also rules for transforming between
+ file targets of different types. That information is used in
+ constructing dependency graph, as desribed in the "next section".
+ [ link? ] <emphasis role="bold">Note:</emphasis>File targets are not
+ the same as targets in Jam sense; the latter are created from
+ file targets at the latest possible moment. <emphasis role="bold">Note:</emphasis>"File
+ target" is a proposed name for what we call virtual targets. It
+ it more understandable by users, but has one problem: virtual
+ targets can potentially be "phony", and not correspond to any
+ file.</para>
+
+ <section id="bbv2.arch.depends">
+ <title>Dependency scanning</title>
+
+ <para>Dependency scanning is the process of finding implicit
+ dependencies, like "#include" statements in C++. The requirements
+ for right dependency scanning mechanism are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Support for different scanning algorithms. C++ and XML have
+ quite different syntax for includes and rules for looking up
+ included files.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Ability to scan the same file several times. For example,
+ single C++ file can be compiled with different include
+ paths.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Proper detection of dependencies on generated files.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Proper detection of dependencies from generated file.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <section>
+ <title>Support for different scanning algorithms</title>
+
+ <para>Different scanning algorithm are encapsulated by objects
+ called "scanners". Please see the documentation for "scanner"
+ module for more details.</para>
+
+ </section>
+
+ <section>
+ <title>Ability to scan the same file several times</title>
+
+ <para>As said above, it's possible to compile a C++ file twice, with
+ different include paths. Therefore, include dependencies for
+ those compilations can be different. The problem is that bjam
+ does not allow several scans of the same target.</para>
+
+ <para>The solution in Boost.Build is straigtforward. When a virtual
+ target is converted to bjam target (via
+ <literal>virtual-target.actualize</literal> method), we specify the scanner
+ object to be used. The actualize method will create different
+ bjam targets for different scanners.</para>
+
+ <para>All targets with specific scanner are made dependent on target
+ without scanner, which target is always created. This is done in
+ case the target is updated. The updating action will be
+ associated with target without scanner, but if sources for that
+ action are touched, all targets &#x2014; with scanner and without
+ should be considered outdated.</para>
+
+ <para>For example, assume that "a.cpp" is compiled by two compilers
+ with different include path. It's also copied into some install
+ location. In turn, it's produced from "a.verbatim". The
+ dependency graph will look like:</para>
+
+<programlisting>
+a.o (&lt;toolset&gt;gcc) &lt;--(compile)-- a.cpp (scanner1) ----+
+a.o (&lt;toolset&gt;msvc) &lt;--(compile)-- a.cpp (scanner2) ----|
+a.cpp (installed copy) &lt;--(copy) ----------------------- a.cpp (no scanner)
+ ^
+ |
+ a.verbose --------------------------------+
+</programlisting>
+
+ </section>
+ <section>
+ <title>Proper detection of dependencies on generated files.</title>
+
+ <para>This requirement breaks down to the following ones.</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ If when compiling "a.cpp" there's include of "a.h", the
+ "dir" directory is in include path, and a target called "a.h"
+ will be generated to "dir", then bjam should discover the
+ include, and create "a.h" before compiling "a.cpp".
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Since almost always Boost.Build generates targets to a
+ "bin" directory, it should be supported as well. I.e. in the
+ scanario above, Jamfile in "dir" might create a main target,
+ which generates "a.h". The file will be generated to "dir/bin"
+ directory, but we still have to recognize the dependency.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>The first requirement means that when determining what "a.h"
+ means, when found in "a.cpp", we have to iterate over all
+ directories in include paths, checking for each one:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ If there's file "a.h" in that directory, or
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there's a target called "a.h", which will be generated
+ to that directory.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>Classic Jam has built-in facilities for point (1) above, but
+ that's not enough. It's hard to implement the right semantic
+ without builtin support. For example, we could try to check if
+ there's targer called "a.h" somewhere in dependency graph, and
+ add a dependency to it. The problem is that without search in
+ include path, the semantic may be incorrect. For example, one can
+ have an action which generated some "dummy" header, for system
+ which don't have the native one. Naturally, we don't want to
+ depend on that generated header on platforms where native one is
+ included.</para>
+
+ <para>There are two design choices for builtin support. Suppose we
+ have files a.cpp and b.cpp, and each one includes header.h,
+ generated by some action. Dependency graph created by classic jam
+ would look like:</para>
+
+<programlisting>
+a.cpp -----&gt; &lt;scanner1&gt;header.h [search path: d1, d2, d3]
+
+
+ &lt;d2&gt;header.h --------&gt; header.y
+ [generated in d2]
+
+b.cpp -----&gt; &lt;scanner2&gt;header.h [ search path: d1, d2, d4]
+</programlisting>
+
+ <para>
+In this case, Jam thinks all header.h target are not
+realated. The right dependency graph might be:
+
+<programlisting>
+a.cpp ----
+ \
+ \
+ &gt;----&gt; &lt;d2&gt;header.h --------&gt; header.y
+ / [generated in d2]
+ /
+b.cpp ----
+</programlisting>
+
+or
+
+<programlisting>
+a.cpp -----&gt; &lt;scanner1&gt;header.h [search path: d1, d2, d3]
+ |
+ (includes)
+ V
+ &lt;d2&gt;header.h --------&gt; header.y
+ [generated in d2]
+ ^
+ (includes)
+ |
+b.cpp -----&gt; &lt;scanner2&gt;header.h [ search path: d1, d2, d4]
+</programlisting>
+ </para>
+
+ <para>
+The first alternative was used for some time. The problem
+however is: what include paths should be used when scanning
+header.h? The second alternative was suggested by Matt Armstrong.
+It has similiar effect: add targets which depend on
+&lt;scanner1&gt;header.h will also depend on &lt;d2&gt;header.h.
+But now we have two different target with two different scanners,
+and those targets can be scanned independently. The problem of
+first alternative is avoided, so the second alternative is
+implemented now.
+ </para>
+
+ <para>The second sub-requirements is that targets generated to "bin"
+ directory are handled as well. Boost.Build implements
+ semi-automatic approach. When compiling C++ files the process
+ is:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ The main target to which compiled file belongs is found.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ All other main targets that the found one depends on are
+ found. Those include main target which are used as sources, or
+ present as values of "dependency" features.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ All directories where files belonging to those main target
+ will be generated are added to the include path.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>After this is done, dependencies are found by the approach
+ explained previously.</para>
+
+ <para>Note that if a target uses generated headers from other main
+ target, that main target should be explicitly specified as
+ dependency property. It would be better to lift this requirement,
+ but it seems not very problematic in practice.</para>
+
+ <para>For target types other than C++, adding of include paths must
+ be implemented anew.</para>
+
+ </section>
+ <section>
+ <title>Proper detection of dependencies from generated files</title>
+
+ <para>Suppose file "a.cpp" includes "a.h" and both are generated by
+ some action. Note that classic jam has two stages. In first stage
+ dependency graph graph is build and actions which should be run
+ are determined. In second stage the actions are executed.
+ Initially, neither file exists, so the include is not found. As
+ the result, jam might attempt to compile a.cpp before creating
+ a.h, and compilation will fail.</para>
+
+ <para>The solution in Boost.Jam is to perform additional dependency
+ scans after targets are updated. This break separation between
+ build stages in jam &#x2014; which some people consider a good
+ thing &#x2014; but I'm not aware of any better solution.</para>
+
+ <para>In order to understand the rest of this section, you better
+ read some details about jam dependency scanning, available
+ <ulink url=
+ "http://public.perforce.com:8080/@md=d&amp;cd=//public/jam/src/&amp;ra=s&amp;c=kVu@//2614?ac=10">
+ at this link</ulink>.</para>
+
+ <para>Whenever a target is updated, Boost.Jam rescans it for
+ includes. Consider this graph, created before any actions are
+ run.</para>
+
+<programlisting>
+A -------&gt; C ----&gt; C.pro
+ /
+B --/ C-includes ---&gt; D
+</programlisting>
+
+ <para>
+Both A and B have dependency on C and C-includes (the latter
+dependency is not shown). Say during building we've tried to create
+A, then tried to create C and successfully created C.
+ </para>
+
+ <para>In that case, the set of includes in C might well have
+ changed. We do not bother to detect precisely which includes were
+ added or removed. Instead we create another internal node
+ C-includes-2. Then we determine what actions should be run to
+ update the target. In fact this mean that we perform logic of
+ first stage while already executing stage.</para>
+
+ <para>After actions for C-includes-2 are determined, we add
+ C-includes-2 to the list of A's dependents, and stage 2 proceeds
+ as usual. Unfortunately, we can't do the same with target B,
+ since when it's not visited, C target does not know B depends on
+ it. So, we add a flag to C which tells and it was rescanned. When
+ visiting B target, the flag is notices and C-includes-2 will be
+ added to the list of B's dependencies.</para>
+
+ <para>Note also that internal nodes are sometimes updated too.
+ Consider this dependency graph:</para>
+
+<programlisting>
+a.o ---&gt; a.cpp
+ a.cpp-includes --&gt; a.h (scanned)
+ a.h-includes ------&gt; a.h (generated)
+ |
+ |
+ a.pro &lt;-------------------------------------------+
+</programlisting>
+
+ <para>Here, out handling of generated headers come into play. Say
+ that a.h exists but is out of date with respect to "a.pro", then
+ "a.h (generated)" and "a.h-includes" will be marking for
+ updating, but "a.h (scanned)" won't be marked. We have to rescan
+ "a.h" file after it's created, but since "a.h (generated)" has no
+ scanner associated with it, it's only possible to rescan "a.h"
+ after "a.h-includes" target was updated.</para>
+
+ <para>Tbe above consideration lead to decision that we'll rescan a
+ target whenever it's updated, no matter if this target is
+ internal or not.</para>
+
+ <warning>
+ <para>
+ The remainder of this document is not indended to be read at
+ all. This will be rearranged in future.
+ </para>
+ </warning>
+
+ <section>
+ <title>File targets</title>
+
+ <para>
+ As described above, file targets corresponds
+ to files that Boost.Build manages. User's may be concerned about
+ file targets in three ways: when declaring file target types,
+ when declaring transformations between types, and when
+ determining where file target will be placed. File targets can
+ also be connected with actions, that determine how the target is
+ created. Both file targets and actions are implemented in the
+ <literal>virtual-target</literal> module.
+ </para>
+
+ <section>
+ <title>Types</title>
+
+ <para>A file target can be given a file, which determines
+ what transformations can be applied to the file. The
+ <literal>type.register</literal> rule declares new types. File type can
+ also be assigned a scanner, which is used to find implicit
+ dependencies. See "dependency scanning" [ link? ] below.</para>
+ </section>
+ </section>
+
+ <section>
+ <title>Target paths</title>
+
+ <para>To distinguish targets build with different properties, they
+ are put in different directories. Rules for determining target
+ paths are given below:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ All targets are placed under directory corresponding to the
+ project where they are defined.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Each non free, non incidental property cause an additional
+ element to be added to the target path. That element has the
+ form <literal>&lt;feature-name&gt;-&lt;feature-value&gt;</literal> for
+ ordinary features and <literal>&lt;feature-value&gt;</literal> for
+ implicit ones. [Note about composite features].
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If the set of free, non incidental properties is different
+ from the set of free, non incidental properties for the project
+ in which the main target that uses the target is defined, a
+ part of the form <literal>main_target-&lt;name&gt;</literal> is added to
+ the target path. <emphasis role="bold">Note:</emphasis>It would be nice to completely
+ track free features also, but this appears to be complex and
+ not extremely needed.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>For example, we might have these paths:</para>
+
+<programlisting>
+debug/optimization-off
+debug/main-target-a
+</programlisting>
+
+ </section>
+ </section>
+ </section>
+ </section>
+ </appendix>
+
+<!--
+ Local Variables:
+ mode: xml
+ sgml-indent-data: t
+ sgml-parent-document: ("userman.xml" "chapter")
+ sgml-set-face: t
+ End:
+-->
diff --git a/tools/build/v2/doc/src/catalog.xml b/tools/build/v2/doc/src/catalog.xml
new file mode 100644
index 0000000000..26e16145d3
--- /dev/null
+++ b/tools/build/v2/doc/src/catalog.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalog
+ PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
+ "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <rewriteURI uriStartString="http://www.boost.org/tools/boostbook/dtd/" rewritePrefix="file:///home/ccurrie/src/boost/tools/boostbook/dtd//"/>
+ <rewriteURI uriStartString="http://docbook.sourceforge.net/release/xsl/current/" rewritePrefix="file:///shared/ccurrie/share/sgml/docbook/docbook-xsl-1.64.1/"/>
+ <rewriteURI uriStartString="http://www.oasis-open.org/docbook/xml/4.2/" rewritePrefix="file:///shared/ccurrie/share/sgml/docbook/docbook-dtd-4.2/"/>
+</catalog>
diff --git a/tools/build/v2/doc/src/extending.xml b/tools/build/v2/doc/src/extending.xml
new file mode 100644
index 0000000000..3d0fda569d
--- /dev/null
+++ b/tools/build/v2/doc/src/extending.xml
@@ -0,0 +1,1207 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE appendix PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <chapter id="bbv2.extender">
+ <title>Extender Manual</title>
+
+ <section id="bbv2.extender.intro">
+ <title>Introduction</title>
+
+ <para>
+ This section explains how to extend Boost.Build to accomodate your
+ local requirements&mdash;primarily to add support for non-standard
+ tools you have. Before we start, be sure you have read and understoon
+ the concept of metatarget, <xref linkend="bbv2.overview.concepts"/>,
+ which is critical to understanding the remaining material.
+ </para>
+
+ <para>
+ The current version of Boost.Build has three levels of targets, listed
+ below.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>metatarget</term>
+ <listitem>
+ <para>
+ Object that is created from declarations in Jamfiles. May
+ be called with a set of properties to produce concrete
+ targets.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>concrete target</term>
+ <listitem>
+ <para>
+ Object that corresponds to a file or an action.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>jam target</term>
+ <listitem>
+ <para>
+ Low-level concrete target that is specific to Boost.Jam build
+ engine. Essentially a string&mdash;most often a name of file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+ In most cases, you will only have to deal with concrete targets and
+ the process that creates concrete targets from
+ metatargets. Extending metatarget level is rarely required. The jam
+ targets are typically only used inside the command line patterns.
+ </para>
+
+ <warning>
+ <para>All of the Boost.Jam target-related builtin functions, like
+ <code>DEPENDS</code> or <code>ALWAYS</code> operate on jam
+ targets. Applying them to metatargets or concrete targets has no
+ effect.</para>
+ </warning>
+
+ <section id="bbv2.extender.overview.metatargets">
+ <title>Metatargets</title>
+
+ <para>Metatarget is an object that records information specified
+ in Jamfile, such as metatarget kind, name, sources and properties,
+ and can be called with specific properties to generate concrete
+ targets. At the code level it is represented by an instance of
+ class derived from <classname>abstract-target</classname>.
+ <footnote><para>This name is historic, and will be eventuall changed to
+ <code>metatarget</code></para></footnote>
+ </para>
+
+ <para>The <methodname>generate</methodname> method takes the build properties
+ (as an instance of the <classname>property-set</classname> class) and returns
+ a list containing:</para>
+ <itemizedlist>
+ <listitem><para>As front element&mdash;Usage-requirements from this invocation
+ (an instance of <classname>property-set</classname>)</para></listitem>
+ <listitem><para>As subsequent elements&mdash;created concrete targets (
+ instances of the <classname>virtual-target</classname> class.)</para></listitem>
+ </itemizedlist>
+
+ <para>It's possible to lookup a metataget by target-id using the
+ <code>targets.resolve-reference</code> function, and the
+ <code>targets.generate-from-reference</code> function can both
+ lookup and generate a metatarget.</para>
+
+ <para>The <classname>abstract-target</classname> class has three immediate
+ derived classes:</para>
+ <itemizedlist>
+
+ <listitem><para><classname>project-target</classname> that
+ corresponds to a project and is not intended for further
+ subclassing. The <methodname>generate</methodname> method of this
+ class builds all targets in the project that are not marked as
+ explicit.</para></listitem>
+
+ <listitem><para><classname>main-target</classname> corresponds to a target in a project
+ and contains one or more target alternatives. This class also should not be
+ subclassed. The <methodname>generate</methodname> method of this class selects
+ an alternative to build, and calls the <methodname>generate</methodname> method of that
+ alternative.</para></listitem>
+
+ <listitem><para><classname>basic-target</classname> corresponds to a
+ specific target alternative. This is base class, with a number of
+ derived classes. The <methodname>generate</methodname> method
+ processes the target requirements and requested build properties to
+ determine final properties for the target, builds all sources, and
+ finally calls the abstract <classname>construct</classname> method with the list
+ of source virtual targets, and the final properties.
+ </para></listitem>
+
+ </itemizedlist>
+
+ <para>The instances of the <classname>project-target</classname> and
+ <classname>main-target</classname> classes are created
+ implicitly&mdash;when loading a new Jamfiles, or when a new target
+ alternative with as-yet unknown name is created. The instances of the
+ classes derived from <classname>basic-target</classname> are typically
+ created when Jamfile calls a <firstterm>metatarget rule</firstterm>,
+ such as such as <code>exe</code>.
+ </para>
+
+ <para>It it permissible to create a custom class derived from
+ <classname>basic-target</classname> and create new metatarget rule
+ that creates instance of such target. However, in the majority
+ of cases, a specific subclass of <classname>basic-target</classname>&mdash;
+ <classname>typed-target</classname> is used. That class is associated
+ with a <firstterm>type</firstterm> and relays to <firstterm>generators</firstterm>
+ to construct concrete targets of that type. This process will be explained below.
+ When a new type is declared, a new metatarget rule is automatically defined.
+ That rule creates new instance of type-target, associated with that type.
+ </para>
+
+ </section>
+
+ <section id="bbv2.extender.overview.targets">
+ <title>Concrete targets</title>
+
+ <para>Concrete targets are represented by instance of classes derived
+ from <classname>virtual-target</classname>. The most commonly used
+ subclass is <classname>file-target</classname>. A file target is associated
+ with an action that creates it&mdash; an instance of the <classname>action</classname>
+ class. The action, in turn, hold a list of source targets. It also holds the
+ <classname>property-set</classname> instance with the build properties that
+ should be used for the action.</para>
+
+ <para>Here's an example of creating a target from another target, <code>source</code></para>
+<programlisting>
+local a = [ new action $(source) : common.copy : $(property-set) ] ;
+local t = [ new file-target $(name) : CPP : $(project) : $(a) ] ;
+</programlisting>
+ <para>The first line creates an instance of the <classname>action></classname> class.
+ The first parameter is the list of sources. The second parameter is the name
+ a jam-level <link linkend="bbv2.overview.jam_language.actions">action</link>.
+ The third parameter is the property-set applying to this action. The second line
+ creates a target. We specifie a name, a type and a project. We also pass the
+ action object created earlier. If the action creates several targets, we can repeat
+ the second line several times.</para>
+
+ <para>In some cases, code that creates concrete targets may be invoked more than
+ once with the same properties. Returning to different instance of <classname>file-target</classname>
+ that correspond to the same file clearly will result in problems. Therefore, whenever
+ returning targets you should pass them via the <code>virtual-target.register</code>
+ function, that will replace targets with previously created identical ones, as
+ necessary.<footnote><para>This create-then-register pattern is caused by limitations
+ of the Boost.Jam language. Python port is likely to never create duplicate targets.</para></footnote>
+ Here are a couple of examples:
+<programlisting>
+return [ virtual-target.register $(t) ] ;
+return [ sequence.transform virtual-target.register : $(targets) ] ;
+</programlisting>
+ </para>
+
+ </section>
+
+ <section id="bbv2.extender.overview.generators">
+ <title>Generators</title>
+
+ <para>In theory, every kind of metatarget in Boost.Build (like <code>exe</code>,
+ <code>lib</code> or <code>obj</code>) could be implemented
+ by writing a new metatarget class that, independently of the other code, figures
+ what files to produce and what commands to use. However, that would be rather inflexible.
+ For example, adding support for a new compiler would require editing several metatargets.
+ </para>
+
+ <para>In practice, most files have specific types, and most tools
+ consume and produce files of specific type. To take advantage of this
+ fact, Boost.Build defines concept of target type and
+ <indexterm><primary>generators</primary></indexterm>
+ <firstterm>generators</firstterm>, and has special metatarget class
+ <classname>typed-target</classname>. Target type is merely an
+ identifier. It is associated with a set of file extensions that
+ correspond to that type. Generator is an abstraction of a tool. It advertises
+ the types it produces and, if called with a set of input target, tries to construct
+ output targets of the advertised types. Finally, <classname>typed-target</classname>
+ is associated with specific target type, and relays the generator (or generators)
+ for that type.
+ </para>
+
+ <para>A generator is an instance of a class derived from <classname>generator</classname>.
+ The <classname>generator</classname> class itself is suitable for common cases.
+ You can define derived classes for custom scenarios.</para>
+
+ <!--
+ <para>Given a set of generators, the fundamental operation is to
+ construct a target of a given type, with given properties, from a
+ set of targets. That operation is performed by rule
+ <literal>generators.construct</literal> and the used algorithm is described
+ below.</para>
+
+ <section>
+ <title>Selecting and ranking viable generators</title>
+
+ <para>Each generator, in addition to target types that it can
+ produce, have attribute that affects its applicability in
+ particular sitiation. Those attributes are:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Required properties, which are properties absolutely
+ necessary for the generator to work. For example, generator
+ encapsulating the gcc compiler would have &lt;toolset&gt;gcc as
+ required property.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Optional properties, which increase the generators
+ suitability for a particual build.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ Generator's required and optional properties may not include
+ either free or incidental properties. (Allowing this would
+ greatly complicate caching targets).
+ </para>
+
+ <para>When trying to construct a target, the first step is to select
+ all possible generators for the requested target type, which
+ required properties are a subset of requested properties.
+ Generators that were already selected up the call stack are
+ excluded. In addition, if any composing generators were selected
+ up the call stack, all other composing generators are ignored
+ (TODO: define composing generators). The found generators
+ are assigned a rank, which is the number of optional properties
+ present in requested properties. Finally, generators with highest
+ rank are selected for futher processing.</para>
+
+ </section>
+ <section>
+ <title>Running generators</title>
+
+ <para>When generators are selected, each is run to produce a list of
+ created targets. This list might include targets that are not of
+ requested types, because generators create the same targets as
+ some tool, and tool's behaviour is fixed. (Note: should specify
+ that in some cases we actually want extra targets). If generator
+ fails, it returns an empty list. Generator is free to call
+ 'construct' again, to convert sources to the types it can handle.
+ It also can pass modified properties to 'construct'. However, a
+ generator is not allowed to modify any propagated properties,
+ otherwise when actually consuming properties we might discover
+ that the set of propagated properties is different from what was
+ used for building sources.</para>
+
+ <para>For all targets that are not of requested types, we try to
+ convert them to requested type, using a second call to
+ <literal>construct</literal>. This is done in order to support
+ transformation sequences where single source file expands to
+ several later. See <ulink url=
+ "http://groups.yahoo.com/group/jamboost/message/1667">this
+ message</ulink> for details.</para>
+
+ </section>
+
+ -->
+
+ <!-- FIXME: review the below content. Maybe, some of it is
+ still useful.
+ <section>
+ <title>Property adjustment</title>
+
+ <para>Because target location is determined by the build system, it
+ is sometimes necessary to adjust properties, in order to not
+ break actions. For example, if there's an action that generates
+ a header, say "a_parser.h", and a source file "a.cpp" which
+ includes that file, we must make everything work as if a_parser.h
+ is generated in the same directory where it would be generated
+ without any subvariants.</para>
+
+ <para>Correct property adjustment can be done only after all targets
+ are created, so the approach taken is:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>
+ When dependency graph is constructed, each action can be
+ assigned a rule for property adjustment.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ When virtual target is actualized, that rule is run and
+ return the final set of properties. At this stage it can use
+ information of all created virtual targets.
+ </para>
+ </listitem>
+ </orderedlist>
+
+ <para>In case of quoted includes, no adjustment can give 100% correct
+ results. If target dirs are not changed by build system, quoted
+ includes are searched in "." and then in include path, while angle
+ includes are searched only in include path. When target dirs are
+ changed, we'd want to make quoted includes to be search in "." then in
+ additional dirs and then in the include path and make angle includes
+ be searched in include path, probably with additional paths added at
+ some position. Unless, include path already has "." as the first
+ element, this is not possible. So, either generated headers should not
+ be included with quotes, or first element of include path should be
+ ".", which essentially erases the difference between quoted and angle
+ includes. <emphasis role="bold">Note:</emphasis> the only way to get
+ "." as include path into compiler command line is via verbatim
+ compiler option. In all other case, Boost.Build will convert "." into
+ directory where it occurs.</para>
+
+ </section>
+
+ -->
+
+ </section>
+
+ </section>
+
+ <section id="bbv2.extender.example">
+ <title>Example: 1-to-1 generator</title>
+
+ <para>Say you're writing an application that generates C++ code. If
+ you ever did this, you know that it's not nice. Embedding large
+ portions of C++ code in string literals is very awkward. A much
+ better solution is:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Write the template of the code to be generated, leaving
+ placeholders at the points that will change
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Access the template in your application and replace
+ placeholders with appropriate text.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>Write the result.</simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>It's quite easy to achieve. You write special verbatim files that are
+ just C++, except that the very first line of the file contains the name of a
+ variable that should be generated. A simple tool is created that takes a
+ verbatim file and creates a cpp file with a single <code>char*</code> variable
+ whose name is taken from the first line of the verbatim file and whose value
+ is the file's properly quoted content.</para>
+
+ <para>Let's see what Boost.Build can do.</para>
+
+ <para>First off, Boost.Build has no idea about "verbatim files". So, you must
+ register a new target type. The following code does it:</para>
+
+<programlisting>
+import type ;
+type.register VERBATIM : verbatim ;
+</programlisting>
+
+ <para>The first parameter to <functionname>type.register</functionname> gives
+ the name of the declared type. By convention, it's uppercase. The second
+ parameter is the suffix for files of this type. So, if Boost.Build sees
+ <filename>code.verbatim</filename> in a list of sources, it knows that it's of
+ type <code>VERBATIM</code>.</para>
+
+ <para>Next, you tell Boost.Build that the verbatim files can be
+ transformed into C++ files in one build step. A
+ <firstterm>generator</firstterm> is a template for a build step that
+ transforms targets of one type (or set of types) into another. Our
+ generator will be called <code>verbatim.inline-file</code>; it
+ transforms <code>VERBATIM</code> files into <code>CPP</code> files:
+
+<programlisting>
+import generators ;
+generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
+</programlisting>
+ </para>
+
+ <para>Lastly, you have to inform Boost.Build about the shell
+ commands used to make that transformation. That's done with an
+ <code>actions</code> declaration.
+
+<programlisting>
+actions inline-file
+{
+ "./inline-file.py" $(&lt;) $(&gt;)
+}
+</programlisting>
+
+<!-- You need to explain all the parameters to an "actions" and
+ describe the accompanying rule declaration: the user has no clue
+ what $(<) and $(>) are, and doesn't know about the third
+ parameter that gets passed to the rule. -->
+
+<!-- We use verbatim.inline-file in one place and just inline-file in
+ another. Is this confusing for user?
+ -->
+</para>
+
+ <para>
+ Now, we're ready to tie it all together. Put all the code above in file
+ <filename>verbatim.jam</filename>, add <code>import verbatim ;</code> to
+ <filename>Jamroot.jam</filename>, and it's possible to write the following
+ in your Jamfile:
+ </para>
+
+<programlisting>
+exe codegen : codegen.cpp class_template.verbatim usage.verbatim ;
+</programlisting>
+
+ <para>
+ The listed verbatim files will be automatically converted into C++ source
+ files, compiled and then linked to the codegen executable.
+ </para>
+
+ <para>
+ In subsequent sections, we will extend this example, and review all the
+ mechanisms in detail. The complete code is available in the
+ <filename>example/customization</filename> directory.
+ </para>
+ </section>
+
+ <section id="bbv2.extending.targets">
+ <title>Target types</title>
+ <para>The first thing we did in the <link
+ linkend="bbv2.extender.intro">intruduction</link> was declaring a
+ new target type:
+<programlisting>
+import type ;
+type.register VERBATIM : verbatim ;
+</programlisting>
+ The type is the most important property of a target. Boost.Build can
+ automatically generate necessary build actions only because you
+ specify the desired type (using the different main target rules), and
+ because Boost.Build can guess the type of sources from their
+ extensions.
+ </para>
+
+ <para>The first two parameters for the <code>type.register</code> rule
+ are the name of new type and the list of extensions associated with
+ it. A file with an extension from the list will have the given target
+ type. In the case where a target of the declared type is generated
+ from other sources, the first specified extension will be used.
+ </para>
+
+ <para>Sometimes you want to change the suffix used for generated targets
+ depending on build properties, such as toolset. For example, some compiler
+ uses extension <literal>elf</literal> for executable files. You can use the
+ <code>type.set-generated-target-suffix</code> rule:
+<programlisting>
+type.set-generated-target-suffix EXE : &lt;toolset&gt;elf : elf ;
+</programlisting>
+ </para>
+
+ <para>A new target type can be inherited from an existing one.
+<programlisting>
+type.register PLUGIN : : SHARED_LIB ;
+</programlisting>
+ The above code defines a new type derived from
+ <code>SHARED_LIB</code>. Initially, the new type inherits all the
+ properties of the base type - in particular generators and suffix.
+ Typically, you'll change the new type in some way. For example, using
+ <code>type.set-generated-target-suffix</code> you can set the suffix for
+ the new type. Or you can write special a generator for the new type. For
+ example, it can generate additional metainformation for the plugin.
+ In either way, the <code>PLUGIN</code> type can be used whenever
+ <code>SHARED_LIB</code> can. For example, you can directly link plugins
+ to an application.
+ </para>
+
+ <para>A type can be defined as "main", in which case Boost.Build will
+ automatically declare a main target rule for building targets of that
+ type. More details can be found <link
+ linkend="bbv2.extending.rules.main-type">later</link>.
+ </para>
+
+ <section id="bbv2.extending.scanners">
+ <title>Scanners</title>
+ <para>
+ Sometimes, a file can refer to other files via some include system. To
+ make Boost.Build track dependencies between included files, you need
+ to provide a scanner. The primary limitation is that only one scanner
+ can be assigned to a target type.
+ </para>
+
+ <para>First, we need to declare a new class for the scanner:
+<programlisting>
+class verbatim-scanner : common-scanner
+{
+ rule pattern ( )
+ {
+ return "//###include[ ]*\"([^\"]*)\"" ;
+ }
+}
+</programlisting>
+ All the complex logic is in the <code>common-scanner</code>
+ class, and you only need to override the method that returns
+ the regular expression to be used for scanning. The
+ parentheses in the regular expression indicate which part
+ of the string is the name of the included file. Only the
+ first parenthesized group in the regular expression will be
+ recognized; if you can't express everything you want that
+ way, you can return multiple regular expressions, each of
+ which contains a parenthesized group to be matched.
+ </para>
+
+ <para>After that, we need to register our scanner class:
+<programlisting>
+scanner.register verbatim-scanner : include ;
+</programlisting>
+ The value of the second parameter, in this case
+ <code>include</code>, specifies the properties that contain the list
+ of paths that should be searched for the included files.
+ </para>
+
+ <para>Finally, we assign the new scanner to the <code>VERBATIM</code>
+ target type:
+<programlisting>
+type.set-scanner VERBATIM : verbatim-scanner ;
+</programlisting>
+ That's enough for scanning include dependencies.
+ </para>
+
+ </section>
+
+ </section>
+
+ <section id="bbv2.extending.tools">
+ <title>Tools and generators</title>
+ <para>
+ This section will describe how Boost.Build can be extended to support
+ new tools.
+ </para>
+
+ <para>For each additional tool, a Boost.Build object called generator
+ must be created. That object has specific types of targets that it
+ accepts and produces. Using that information, Boost.Build is able
+ to automatically invoke the generator. For example, if you declare a
+ generator that takes a target of the type <literal>D</literal> and
+ produces a target of the type <literal>OBJ</literal>, when placing a
+ file with extention <literal>.d</literal> in a list of sources will
+ cause Boost.Build to invoke your generator, and then to link the
+ resulting object file into an application. (Of course, this requires
+ that you specify that the <literal>.d</literal> extension corresponds
+ to the <literal>D</literal> type.)
+ </para>
+
+ <para>Each generator should be an instance of a class derived from the
+ <code>generator</code> class. In the simplest case, you don't need to
+ create a derived class, but simply create an instance of the
+ <code>generator</code> class. Let's review the example we've seen in the
+ <link linkend="bbv2.extender.intro">introduction</link>.
+ <!-- Is the following supposed to be verbatim.jam? Tell the
+ user so. You also need to describe the meanings of $(<)
+ and $(>); this is the first time they're encountered. -->
+<programlisting>
+import generators ;
+generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
+actions inline-file
+{
+ "./inline-file.py" $(&lt;) $(&gt;)
+}
+</programlisting>
+ </para>
+
+ <para>We declare a standard generator, specifying its id, the source type
+ and the target type. When invoked, the generator will create a target
+ of type <literal>CPP</literal> with a source target of
+ type <literal>VERBATIM</literal> as the only source. But what command
+ will be used to actually generate the file? In bjam, actions are
+ specified using named "actions" blocks and the name of the action
+ block should be specified when creating targets. By convention,
+ generators use the same name of the action block as their own id. So,
+ in above example, the "inline-file" actions block will be used to
+ convert the source into the target.
+ </para>
+
+ <para>
+ There are two primary kinds of generators: standard and composing,
+ which are registered with the
+ <code>generators.register-standard</code> and the
+ <code>generators.register-composing</code> rules, respectively. For
+ example:
+<programlisting>
+generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
+generators.register-composing mex.mex : CPP LIB : MEX ;
+</programlisting>
+ The first (standard) generator takes a <emphasis>single</emphasis>
+ source of type <code>VERBATIM</code> and produces a result. The second
+ (composing) generator takes any number of sources, which can have either
+ the <code>CPP</code> or the <code>LIB</code> type. Composing generators
+ are typically used for generating top-level target type. For example,
+ the first generator invoked when building an <code>exe</code> target is
+ a composing generator corresponding to the proper linker.
+ </para>
+
+ <para>You should also know about two specific functions for registering
+ generators: <code>generators.register-c-compiler</code> and
+ <code>generators.register-linker</code>. The first sets up header
+ dependecy scanning for C files, and the seconds handles various
+ complexities like searched libraries. For that reason, you should always
+ use those functions when adding support for compilers and linkers.
+ </para>
+
+ <para>(Need a note about UNIX)</para>
+ <!-- What kind of note? Either write the note or don't, but remove this dross. -->
+ <bridgehead>Custom generator classes</bridgehead>
+
+ <para>The standard generators allows you to specify source and target
+ types, an action, and a set of flags. If you need anything more complex,
+ <!-- What sort of flags? Command-line flags? What does the system do with them? -->
+ you need to create a new generator class with your own logic. Then,
+ you have to create an instance of that class and register it. Here's
+ an example how you can create your own generator class:
+<programlisting>
+class custom-generator : generator
+{
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+<!-- What is the point of this __init__ function?? -->
+}
+
+generators.register
+ [ new custom-generator verbatim.inline-file : VERBATIM : CPP ] ;
+</programlisting>
+ This generator will work exactly like the
+ <code>verbatim.inline-file</code> generator we've defined above, but
+ it's possible to customize the behaviour by overriding methods of the
+ <code>generator</code> class.
+ </para>
+
+ <para>There are two methods of interest. The <code>run</code> method is
+ responsible for the overall process - it takes a number of source targets,
+ converts them to the right types, and creates the result. The
+ <code>generated-targets</code> method is called when all sources are
+ converted to the right types to actually create the result.
+ </para>
+
+ <para>The <code>generated-targets</code> method can be overridden when you
+ want to add additional properties to the generated targets or use
+ additional sources. For a real-life example, suppose you have a program
+ analysis tool that should be given a name of executable and the list of
+ all sources. Naturally, you don't want to list all source files
+ manually. Here's how the <code>generated-targets</code> method can find
+ the list of sources automatically:
+<programlisting>
+class itrace-generator : generator {
+....
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ local leaves ;
+ local temp = [ virtual-target.traverse $(sources[1]) : : include-sources ] ;<!-- You must explain include-sources! -->
+ for local t in $(temp)
+ {
+ if ! [ $(t).action<!-- In what namespace is this evaluated? --> ]
+ {
+ leaves += $(t) ;
+ }
+ }
+ return [ generator.generated-targets $(sources) $(leafs)
+ : $(property-set) : $(project) $(name) ] ;
+ }
+}
+generators.register [ new itrace-generator nm.itrace : EXE : ITRACE ] ;
+</programlisting>
+ The <code>generated-targets</code> method will be called with a single
+ source target of type <literal>EXE</literal>. The call to
+ <code>virtual-target.traverse</code> will return all targets the
+ executable depends on, and we further find files that are not
+ produced from anything. <!-- What does "not produced from anything" mean? -->
+ The found targets are added to the sources.
+ </para>
+
+ <para>The <code>run</code> method can be overriden to completely
+ customize the way the generator works. In particular, the conversion of
+ sources to the desired types can be completely customized. Here's
+ another real example. Tests for the Boost Python library usually
+ consist of two parts: a Python program and a C++ file. The C++ file is
+ compiled to Python extension that is loaded by the Python
+ program. But in the likely case that both files have the same name,
+ the created Python extension must be renamed. Otherwise, the Python
+ program will import itself, not the extension. Here's how it can be
+ done:
+<programlisting>
+rule run ( project name ? : property-set : sources * )
+{
+ local python ;
+ for local s in $(sources)
+ {
+ if [ $(s).type ] = PY
+ {
+ python = $(s) ;
+ }
+ }
+ <!-- This is horrible code. Use a filter function, or at _least_ consolidate the two loops! -->
+ local libs ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] LIB ]
+ {
+ libs += $(s) ;
+ }
+ }
+
+ local new-sources ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] CPP ]
+ {
+ local name = [ $(s).name ] ; # get the target's basename
+ if $(name) = [ $(python).name ]
+ {
+ name = $(name)_ext ; # rename the target
+ }
+ new-sources += [ generators.construct $(project) $(name) :
+ PYTHON_EXTENSION : $(property-set) : $(s) $(libs) ] ;
+ }
+ }
+
+ result = [ construct-result $(python) $(new-sources) : $(project) $(name)
+ : $(property-set) ] ;
+}
+</programlisting>
+ <!-- Why are we doing this with a generator??? It seems
+ insane. We could just use a nice front-end rule that
+ calls some normal target-creation rules. No? -->
+
+ First, we separate all source into python files, libraries and C++
+ sources. For each C++ source we create a separate Python extension by
+ calling <code>generators.construct</code> and passing the C++ source
+ and the libraries. At this point, we also change the extension's name,
+ if necessary.
+ </para>
+
+
+ </section>
+
+ <section id="bbv2.extending.features">
+ <title>Features</title>
+ <para>
+ Often, we need to control the options passed the invoked tools. This
+ is done with features. Consider an example:
+<programlisting>
+# Declare a new free feature
+import feature : feature ;
+feature verbatim-options : : free ;
+
+# Cause the value of the 'verbatim-options' feature to be
+# available as 'OPTIONS' variable inside verbatim.inline-file
+import toolset : flags ;
+flags verbatim.inline-file OPTIONS &lt;verbatim-options&gt; ;<!-- You must tell the reader what the syntax of the flags rule is -->
+
+# Use the "OPTIONS" variable
+actions inline-file
+{
+ "./inline-file.py" $(OPTIONS) $(&lt;) $(&gt;)
+}
+</programlisting>
+ We first define a new feature. Then, the <code>flags</code> invocation
+ says that whenever verbatin.inline-file action is run, the value of
+ the <code>verbatim-options</code> feature will be added to the
+ <code>OPTIONS</code> variable, and can be used inside the action body.
+ You'd need to consult online help (--help) to find all the features of
+ the <code>toolset.flags</code> rule.
+ <!-- It's been a while since I wrote these notes, so I don't
+ remember what I meant. But right here, I wrote "bad" and
+ circled it. Maybe you can figure out what I meant. ;-)
+ -->
+ </para>
+
+ <para>
+ Although you can define any set of features and interpret their values
+ in any way, Boost.Build suggests the following coding standard for
+ designing features.
+ </para>
+
+ <para>Most features should have a fixed set of values that is portable
+ (tool neutral) across the class of tools they are designed to work
+ with. The user does not have to adjust the values for a exact tool. For
+ example, <code>&lt;optimization&gt;speed</code> has the same meaning for
+ all C++ compilers and the user does not have to worry about the exact
+ options passed to the compiler's command line.
+ </para>
+
+ <para>
+ Besides such portable features there are special 'raw' features that
+ allow the user to pass any value to the command line parameters for a
+ particular tool, if so desired. For example, the
+ <code>&lt;cxxflags&gt;</code> feature allows you to pass any command line
+ options to a C++ compiler. The <code>&lt;include&gt;</code> feature
+ allows you to pass any string preceded by <code>-I</code> and the interpretation
+ is tool-specific. <!-- It's really tool-specific? That surprises me --> (See <xref
+ linkend="bbv2.faq.external"/> for an example of very smart usage of that
+ feature). Of course one should always strive to use portable
+ features, but these are still be provided as a backdoor just to make
+ sure Boost.Build does not take away any control from the user.
+ </para>
+
+ <para>
+ Using portable features is a good idea because:
+ <itemizedlist>
+ <listitem>
+ <para>When a portable feature is given a fixed set of
+ values, you can build your project with two different
+ settings of the feature and Boost.Build will automatically
+ use two different directories for generated files.
+ Boost.Build does not try to separate targets built with
+ different raw options.
+ <!-- It's a computer program. It doesn't "care" about options -->
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>Unlike with “raw†features, you don't need to use
+ specific command-line flags in your Jamfile, and it will be
+ more likely to work with other tools.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead>Steps for adding a feauture</bridgehead>
+ <!-- This section is redundant with the previous one -->
+ <para>Adding a feature requires three steps:
+
+ <orderedlist>
+ <listitem><para>Declaring a feature. For that, the "feature.feature"
+ rule is used. You have to decide on the set of <link
+ linkend="bbv2.reference.features.attributes">feature
+ attributes</link>:
+
+ <itemizedlist>
+ <listitem><para>if you want a feature value set for one target
+ to automaticaly propagate to its dependant targets then make it
+ “propagatedâ€. <!-- Examples needed. --></para></listitem>
+
+ <listitem><para>if a feature does not have a fixed list of
+ values, it must be “free.†For example, the <code>include
+ </code> feature is a free feature.</para></listitem>
+
+ <listitem><para>if a feature is used to refer to a path relative
+ to the Jamfile, it must be a “path†feature. Such features will
+ also get their values automatically converted to Boost Build's
+ internal path representation. For example, <code>include</code>
+ is a path feature.</para></listitem>
+
+ <listitem><para>if feature is used to refer to some target, it
+ must be a “dependency†feature. <!-- for example? --></para>
+
+ <!-- Any other feature attributes? -->
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+
+ <listitem><para>Representing the feature value in a
+ target-specific variable. Build actions are command
+ templates modified by Boost.Jam variable expansions. The
+ <code>toolset.flags</code> rule sets a target-specific
+ variable to the value of a feature.</para></listitem>
+
+ <listitem><para>Using the variable. The variable set in step 2 can
+ be used in a build action to form command parameters or
+ files.</para></listitem>
+
+ </orderedlist>
+ </para>
+
+ <bridgehead>Another example</bridgehead>
+
+ <para>Here's another example.
+ Let's see how we can make a feature that refers to a target. For example,
+ when linking dynamic libraries on Windows, one sometimes needs to
+ specify a "DEF file", telling what functions should be exported. It
+ would be nice to use this file like this:
+<programlisting>
+ lib a : a.cpp : &lt;def-file&gt;a.def ;
+</programlisting>
+<!-- Why would that be nice? It seems to me that having a.def in the sources is the obvious and much nicer thing to do:
+
+ lib a : a.cpp a.def ;
+-->
+ Actually, this feature is already supported, but anyway...
+ <!-- Something about saying that is very off-putting. I'm
+ sorry that I can't put my finger on it -->
+ </para>
+
+ <orderedlist>
+ <listitem>
+ <para>Since the feature refers to a target, it must be "dependency".
+<programlisting>
+feature def-file : : free dependency ;
+</programlisting>
+ </para></listitem>
+
+ <listitem><para>One of the toolsets that cares about
+ <!-- The toolset doesn't "care." What do your really mean? -->
+ DEF files is msvc. The following line should be added to it.
+ <!-- Are you saying the msvc toolset is broken (or that it
+ doesn't use DEF files) as-shipped and the reader needs to
+ fix it? -->
+
+<programlisting>
+flags msvc.link DEF_FILE &lt;def-file&gt; ;
+</programlisting>
+ <!-- And that line does... what? -->
+ </para></listitem>
+
+ <listitem><para>Since the DEF_FILE variable is not used by the
+msvc.link action,
+<!-- It's not? You just told us that MSVC "cares" about DEF files. I
+ presume that means that it uses them in some appropriate way? -->
+we need to modify it to be:
+
+<programlisting>
+actions link bind DEF_FILE
+{
+ $(.LD) .... /DEF:$(DEF_FILE) ....
+}
+</programlisting>
+ </para>
+
+
+ <para> Note the <code>bind DEF_FILE</code> part. It tells
+ bjam to translate the internal target name in
+ <varname>DEF_FILE</varname> to a corresponding filename in
+ the <code>link</code> action. Without it the expansion of
+ <code>$(DEF_FILE)</code> would be a strange symbol that is
+ not likely to make sense for the linker.
+ </para>
+
+ <!-- I have a note here that says: "none of this works for
+ targets in general, only source files." I'm not sure
+ what I meant by that; maybe you can figure it out. -->
+ <para>
+ We are almost done, but we should stop for a small workaround. Add the following
+ code to msvc.jam
+
+<programlisting>
+rule link
+{
+ DEPENDS $(&lt;) : [ on $(&lt;) return $(DEF_FILE) ] ;
+}
+</programlisting>
+<!-- You *must* explain the part in [...] above. It's completely opaque to the casual reader -->
+
+ This is needed to accomodate some bug in bjam, which hopefully
+ will be fixed one day.
+ <!-- This is *NOT* a bug!! Anyway, BBv2 shouild handle this automatically. Why doesn't it? -->
+</para></listitem>
+
+ </orderedlist>
+
+ <bridgehead>Variants and composite features.</bridgehead>
+
+ <para>Sometimes you want to create a shortcut for some set of
+ features. For example, <code>release</code> is a value of
+ <code>&lt;variant&gt;</code> and is a shortcut for a set of features.
+ </para>
+
+ <para>It is possible to define your own build variants. For example:
+<programlisting>
+variant crazy : &lt;optimization&gt;speed &lt;inlining&gt;off
+ &lt;debug-symbols&gt;on &lt;profiling&gt;on ;
+</programlisting>
+ will define a new variant with the specified set of properties. You
+ can also extend an existing variant:
+<programlisting>
+variant super_release : release : &lt;define&gt;USE_ASM ;
+</programlisting>
+ In this case, <code>super_release</code> will expand to all properties
+ specified by <code>release</code>, and the additional one you've specified.
+ </para>
+
+ <para>You are not restricted to using the <code>variant</code> feature
+ only.
+ <!-- What do you mean by that? How is defining a new feature related to what came before? -->
+ Here's example that defines a brand new feature:
+<programlisting>
+feature parallelism : mpi fake none : composite link-incompatible ;
+feature.compose &lt;parallelism&gt;mpi : &lt;library&gt;/mpi//mpi/&lt;parallelism&gt;none ;
+feature.compose &lt;parallelism&gt;fake : &lt;library&gt;/mpi//fake/&lt;parallelism&gt;none ;
+</programlisting>
+<!-- The use of the <library>/mpi//mpi/<parallelism>none construct
+ above is at best confusing and unexplained -->
+ This will allow you to specify the value of feature
+ <code>parallelism</code>, which will expand to link to the necessary
+ library.
+ </para>
+
+ </section>
+
+ <section id="bbv2.extending.rules">
+ <title>Main target rules</title>
+ <para>
+ A main target rule (e.g “<functionname>exe</functionname>â€
+ Or “<functionname>lib</functionname>â€) creates a top-level target. It's quite likely that you'll want to declare your own and
+ there are two ways to do that.
+ <!-- Why did "that" get changed to "this" above? -->
+ </para>
+
+ <para id="bbv2.extending.rules.main-type">The first way applies when
+<!-- This is not a "way of defining a main target rule." Rephrase this and the previous sentence. -->
+ your target rule should just produce a target of specific type. In that case, a
+ rule is already defined for you! When you define a new type, Boost.Build
+ automatically defines a corresponding rule. The name of the rule is
+ obtained from the name of the type, by downcasing all letters and
+ replacing underscores with dashes.
+ <!-- This strikes me as needless complexity, and confusing. Why
+ do we have the uppercase-underscore convention for target
+ types? If we just dropped that, the rule names could be
+ the same as the type names. -->
+ For example, if you create a module
+ <filename>obfuscate.jam</filename> containing:
+
+<programlisting>
+import type ;
+type.register OBFUSCATED_CPP : ocpp ;
+
+import generators ;
+generators.register-standard obfuscate.file : CPP : OBFUSCATED_CPP ;
+</programlisting>
+ and import that module, you'll be able to use the rule "obfuscated-cpp"
+ in Jamfiles, which will convert source to the OBFUSCATED_CPP type.
+ </para>
+
+ <para>
+ The second way is to write a wrapper rule that calls any of the existing
+ rules. For example, suppose you have only one library per directory and
+ want all cpp files in the directory to be compiled into that library. You
+ can achieve this effect using:
+<programlisting>
+lib codegen : [ glob *.cpp ] ;
+</programlisting>
+ If you want to make it even simpler, you could add the following
+ definition to the <filename>Jamroot.jam</filename> file:
+<programlisting>
+rule glib ( name : extra-sources * : requirements * )
+{
+ lib $(name) : [ glob *.cpp ] $(extra-sources) : $(requirements) ;
+}
+</programlisting>
+ allowing you to reduce the Jamfile to just
+<programlisting>
+glib codegen ;
+</programlisting>
+ </para>
+
+ <para>
+ Note that because you can associate a custom generator with a target type,
+ the logic of building can be rather complicated. For example, the
+ <code>boostbook</code> module declares a target type
+ <code>BOOSTBOOK_MAIN</code> and a custom generator for that type. You can
+ use that as example if your main target rule is non-trivial.
+ </para>
+ </section>
+
+ <section id="bbv2.extending.toolset_modules">
+
+ <title>Toolset modules</title>
+
+ <para>
+ If your extensions will be used only on one project, they can be placed in
+ a separate <filename>.jam</filename> file and imported by your
+ <filename>Jamroot.jam</filename>. If the extensions will be used on many
+ projects, users will thank you for a finishing touch.
+ </para>
+
+ <para>The <code>using</code> rule provides a standard mechanism
+ for loading and configuring extensions. To make it work, your module
+ <!-- "module" hasn't been defined yet. Furthermore you haven't
+ said anything about where that module file must be
+ placed. -->
+ should provide an <code>init</code> rule. The rule will be called
+ with the same parameters that were passed to the
+ <code>using</code> rule. The set of allowed parameters is
+ determined by you. For example, you can allow the user to specify
+ paths, tool versions, and other options.
+ <!-- But it's not entirely arbitrary. We have a standard
+ parameter order which you should describe here for
+ context. -->
+ </para>
+
+ <para>Here are some guidelines that help to make Boost.Build more
+ consistent:
+ <itemizedlist>
+ <listitem><para>The <code>init</code> rule should never fail. Even if
+ the user provided an incorrect path, you should emit a warning and go
+ on. Configuration may be shared between different machines, and
+ wrong values on one machine can be OK on another.
+ <!-- So why shouldn't init fail on machines where it's wrong?? -->
+ </para></listitem>
+
+ <listitem><para>Prefer specifying the command to be executed
+ to specifying the tool's installation path. First of all, this
+ gives more control: it's possible to specify
+<programlisting>
+/usr/bin/g++-snapshot
+time g++
+<!-- Is this meant to be a single command? If not, insert "or" -->
+</programlisting>
+ as the command. Second, while some tools have a logical
+ "installation root", it's better if the user doesn't have to remember whether
+ a specific tool requires a full command or a path.
+ <!-- But many tools are really collections: e.g. a
+ compiler, a linker, and others. The idea that the
+ "command to invoke" has any significance may be
+ completely bogus. Plus if you want to allow "time
+ /usr/bin/g++" the toolset may need to somehow parse
+ the command and find the path when it needs to invoke
+ some related executable. And in that case, will the
+ command be ignored? This scheme doesn't scale and
+ should be fixed. -->
+ </para></listitem>
+
+ <listitem><para>Check for multiple initialization. A user can try to
+ initialize the module several times. You need to check for this
+ and decide what to do. Typically, unless you support several
+ versions of a tool, duplicate initialization is a user error.
+ <!-- Why should that be typical? -->
+ If the
+ tool's version can be specified during initialization, make sure the
+ version is either always specified, or never specified (in which
+ case the tool is initialied only once). For example, if you allow:
+<programlisting>
+using yfc ;
+using yfc : 3.3 ;
+using yfc : 3.4 ;
+</programlisting>
+ Then it's not clear if the first initialization corresponds to
+ version 3.3 of the tool, version 3.4 of the tool, or some other
+ version. This can lead to building twice with the same version.
+ <!-- That would not be so terrible, and is much less harmful
+ than this restriction, IMO. It makes site-config
+ harder to maintain than necessary. -->
+ </para></listitem>
+
+ <listitem><para>If possible, <code>init</code> must be callable
+ with no parameters. In which case, it should try to autodetect all
+ the necessary information, for example, by looking for a tool in
+ <envar>PATH</envar> or in common installation locations. Often this
+ is possible and allows the user to simply write:
+<programlisting>
+using yfc ;
+</programlisting>
+ </para></listitem>
+
+ <listitem><para>Consider using facilities in the
+ <code>tools/common</code> module. You can take a look at how
+ <code>tools/gcc.jam</code> uses that module in the <code>init</code> rule.
+ </para></listitem>
+
+ </itemizedlist>
+ </para>
+
+
+
+
+ </section>
+
+ </chapter>
+
+<!--
+ Local Variables:
+ sgml-indent-data: t
+ sgml-parent-document: ("userman.xml" "chapter")
+ sgml-set-face: t
+ End:
+-->
diff --git a/tools/build/v2/doc/src/faq.xml b/tools/build/v2/doc/src/faq.xml
new file mode 100644
index 0000000000..551e22e25b
--- /dev/null
+++ b/tools/build/v2/doc/src/faq.xml
@@ -0,0 +1,458 @@
+<?xml version="1.0" standalone="yes"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+<chapter id="bbv2.faq">
+ <title>Frequently Asked Questions</title>
+
+ <section>
+ <title>
+ How do I get the current value of feature in Jamfile?
+ </title>
+
+ <para>
+ This is not possible, since Jamfile does not have "current" value of any
+ feature, be it toolset, build variant or anything else. For a single
+ invocation of <filename>bjam</filename>, any given main target can be
+ built with several property sets. For example, user can request two build
+ variants on the command line. Or one library is built as shared when used
+ from one application, and as static when used from another. Each Jamfile
+ is read only once so generally there is no single value of a feature you
+ can access in Jamfile.
+ </para>
+
+ <para>
+ A feature has a specific value only when building a target, and there are
+ two ways you can use that value:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Use conditional requirements or indirect conditional requirements. See
+ <xref linkend="bbv2.overview.targets.requirements.conditional"/>.
+ </simpara>
+ </listitem>
+ <listitem>
+ Define a custom generator and a custom main target type. The custom
+ generator can do arbitrary processing or properties. See the <xref
+ linkend="bbv2.extender">extender manual</xref>.
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>
+ I am getting a "Duplicate name of actual target" error. What does that
+ mean?
+ </title>
+
+ <para>
+ The most likely case is that you are trying to compile the same file
+ twice, with almost the same, but differing properties. For example:
+<programlisting>
+exe a : a.cpp : &lt;include&gt;/usr/local/include ;
+exe b : a.cpp ;
+</programlisting>
+ </para>
+
+ <para>
+ The above snippet requires two different compilations of
+ <code>a.cpp</code>, which differ only in their <literal>include</literal>
+ property. Since the <literal>include</literal> feature is declared as
+ <literal>free</literal> Boost.Build does not create a separate build
+ directory for each of its values and those two builds would both produce
+ object files generated in the same build directory. Ignoring this and
+ compiling the file only once would be dangerous as different includes
+ could potentially cause completely different code to be compiled.
+ </para>
+
+ <para>
+ To solve this issue, you need to decide if the file should be compiled
+ once or twice.
+ </para>
+
+ <orderedlist>
+ <listitem>
+ <para>
+ To compile the file only once, make sure that properties are the same
+ for both target requests:
+<programlisting>
+exe a : a.cpp : &lt;include&gt;/usr/local/include ;
+exe b : a.cpp : &lt;include&gt;/usr/local/include ;
+</programlisting>
+ or:
+<programlisting>
+alias a-with-include : a.cpp : &lt;include&gt;/usr/local/include ;
+exe a : a-with-include ;
+exe b : a-with-include ;
+</programlisting>
+ or if you want the <literal>includes</literal> property not to affect
+ how any other sources added for the built <code>a</code> and
+ <code>b</code> executables would be compiled:
+<programlisting>
+obj a-obj : a.cpp : &lt;include&gt;/usr/local/include ;
+exe a : a-obj ;
+exe b : a-obj ;
+</programlisting>
+ </para>
+ <para>
+ Note that in both of these cases the <literal>include</literal>
+ property will be applied only for building these object files and not
+ any other sources that might be added for targets <code>a</code> and
+ <code>b</code>.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ To compile the file twice, you can tell Boost.Build to compile it to
+ two separate object files like so:
+<programlisting>
+ obj a_obj : a.cpp : &lt;include&gt;/usr/local/include ;
+ obj b_obj : a.cpp ;
+ exe a : a_obj ;
+ exe b : b_obj ;
+</programlisting>
+ or you can make the object file targets local to the main target:
+<programlisting>
+ exe a : [ obj a_obj : a.cpp : &lt;include&gt;/usr/local/include ] ;
+ exe b : [ obj a_obj : a.cpp ] ;
+</programlisting>
+ which will cause Boost.Build to actually change the generated object
+ file names a bit for you and thus avoid any conflicts.
+ </para>
+ <para>
+ Note that in both of these cases the <literal>include</literal>
+ property will be applied only for building these object files and not
+ any other sources that might be added for targets <code>a</code> and
+ <code>b</code>.
+ </para>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ A good question is why Boost.Build can not use some of the above
+ approaches automatically. The problem is that such magic would only help
+ in half of the cases, while in the other half it would be silently doing
+ the wrong thing. It is simpler and safer to ask the user to clarify his
+ intention in such cases.
+ </para>
+ </section>
+
+ <section id="bbv2.faq.envar">
+ <title>
+ Accessing environment variables
+ </title>
+
+ <para>
+ Many users would like to use environment variables in Jamfiles, for
+ example, to control the location of external libraries. In many cases it
+ is better to declare those external libraries in the site-config.jam file,
+ as documented in the <link linkend="bbv2.recipies.site-config">recipes
+ section</link>. However, if the users already have the environment
+ variables set up, it may not be convenient for them to set up their
+ site-config.jam files as well and using the environment variables might be
+ reasonable.
+ </para>
+
+ <para>
+ Boost.Jam automatically imports all environment variables into its
+ built-in .ENVIRON module so user can read them from there directly or by
+ using the helper os.environ rule. For example:
+<programlisting>
+import os ;
+local unga-unga = [ os.environ UNGA_UNGA ] ;
+ECHO $(unga-unga) ;
+</programlisting>
+ or a bit more realistic:
+<programlisting>
+import os ;
+local SOME_LIBRARY_PATH = [ os.environ SOME_LIBRARY_PATH ] ;
+exe a : a.cpp : &lt;include&gt;$(SOME_LIBRARY_PATH) ;
+</programlisting>
+ </para>
+ </section>
+
+ <section>
+ <title>
+ How to control properties order?
+ </title>
+
+ <para>
+ For internal reasons, Boost.Build sorts all the properties alphabetically.
+ This means that if you write:
+<programlisting>
+exe a : a.cpp : &lt;include&gt;b &lt;include&gt;a ;
+</programlisting>
+ then the command line with first mention the <code>a</code> include
+ directory, and then <code>b</code>, even though they are specified in the
+ opposite order. In most cases, the user does not care. But sometimes the
+ order of includes, or other properties, is important. For such cases, a
+ special syntax is provided:
+<programlisting>
+exe a : a.cpp : &lt;include&gt;a&amp;&amp;b ;
+</programlisting>
+ </para>
+
+ <para>
+ The <code>&amp;&amp;</code> symbols separate property values and specify
+ that their order should be preserved. You are advised to use this feature
+ only when the order of properties really matters and not as a convenient
+ shortcut. Using it everywhere might negatively affect performance.
+ </para>
+ </section>
+
+ <section>
+ <title>
+ How to control the library linking order on Unix?
+ </title>
+
+ <para>
+ On Unix-like operating systems, the order in which static libraries are
+ specified when invoking the linker is important, because by default, the
+ linker uses one pass though the libraries list. Passing the libraries in
+ the incorrect order will lead to a link error. Further, this behaviour is
+ often used to make one library override symbols from another. So,
+ sometimes it is necessary to force specific library linking order.
+ </para>
+
+ <para>
+ Boost.Build tries to automatically compute the right order. The primary
+ rule is that if library <code>a</code> "uses" library <code>b</code>, then
+ library <code>a</code> will appear on the command line before library
+ <code>b</code>. Library <code>a</code> is considered to use <code>b</code>
+ if <code>b</code> is present either in the <code>a</code> library's
+ sources or its usage is listed in its requirements. To explicitly specify
+ the <literal>use</literal> relationship one can use the
+ <literal>&lt;use&gt;</literal> feature. For example, both of the following
+ lines will cause <code>a</code> to appear before <code>b</code> on the
+ command line:
+<programlisting>
+lib a : a.cpp b ;
+lib a : a.cpp : &lt;use&gt;b ;
+</programlisting>
+ </para>
+
+ <para>
+ The same approach works for searched libraries as well:
+<programlisting>
+lib z ;
+lib png : : &lt;use&gt;z ;
+exe viewer : viewer png z ;
+</programlisting>
+ </para>
+ </section>
+
+ <section id="bbv2.faq.external">
+ <title>
+ Can I get capture external program output using a Boost.Jam variable?
+ </title>
+
+ <para>
+ The <literal>SHELL</literal> builtin rule may be used for this purpose:
+<programlisting>
+local gtk_includes = [ SHELL "gtk-config --cflags" ] ;
+</programlisting>
+ </para>
+ </section>
+
+ <section>
+ <title>
+ How to get the project root (a.k.a. Jamroot) location?
+ </title>
+
+ <para>
+ You might want to use your project's root location in your Jamfiles. To
+ access it just declare a path constant in your Jamroot.jam file using:
+<programlisting>
+path-constant TOP : . ;
+</programlisting>
+ After that, the <code>TOP</code> variable can be used in every Jamfile.
+ </para>
+ </section>
+
+ <section>
+ <title>
+ How to change compilation flags for one file?
+ </title>
+
+ <para>
+ If one file must be compiled with special options, you need to explicitly
+ declare an <code>obj</code> target for that file and then use that target
+ in your <code>exe</code> or <code>lib</code> target:
+<programlisting>
+exe a : a.cpp b ;
+obj b : b.cpp : &lt;optimization&gt;off ;
+</programlisting>
+ Of course you can use other properties, for example to specify specific
+ C/C++ compiler options:
+<programlisting>
+exe a : a.cpp b ;
+obj b : b.cpp : &lt;cflags&gt;-g ;
+</programlisting>
+ You can also use <link linkend="bbv2.tutorial.conditions">conditional
+ properties</link> for finer control:
+<programlisting>
+exe a : a.cpp b ;
+obj b : b.cpp : &lt;variant&gt;release:&lt;optimization&gt;off ;
+</programlisting>
+ </para>
+ </section>
+
+ <section id="bbv2.faq.dll-path">
+ <title>
+ Why are the <literal>dll-path</literal> and <literal>hardcode-dll-paths
+ </literal> properties useful?
+ </title>
+ <note>
+ <para>
+ This entry is specific to Unix systems.
+ </para>
+ </note>
+ <para>
+ Before answering the questions, let us recall a few points about shared
+ libraries. Shared libraries can be used by several applications, or other
+ libraries, without physically including the library in the application
+ which can greatly decrease the total application size. It is also possible
+ to upgrade a shared library when the application is already installed.
+ </para>
+
+ <para>
+ However, in order for application depending on shared libraries to be
+ started the OS may need to find the shared library when the application is
+ started. The dynamic linker will search in a system-defined list of paths,
+ load the library and resolve the symbols. Which means that you should
+ either change the system-defined list, given by the <envar>LD_LIBRARY_PATH
+ </envar> environment variable, or install the libraries to a system
+ location. This can be inconvenient when developing, since the libraries
+ are not yet ready to be installed, and cluttering system paths may be
+ undesirable. Luckily, on Unix there is another way.
+ </para>
+
+ <para>
+ An executable can include a list of additional library paths, which will
+ be searched before system paths. This is excellent for development because
+ the build system knows the paths to all libraries and can include them in
+ the executables. That is done when the <literal>hardcode-dll-paths
+ </literal> feature has the <literal>true</literal> value, which is the
+ default. When the executables should be installed, the story is different.
+ </para>
+
+ <para>
+ Obviously, installed executable should not contain hardcoded paths to your
+ development tree. <!-- Make the following parenthised sentence a footer
+ note --> (The <literal>install</literal> rule explicitly disables the
+ <literal>hardcode-dll-paths</literal> feature for that reason.) However,
+ you can use the <literal>dll-path</literal> feature to add explicit paths
+ manually. For example:
+<programlisting>
+install installed : application : &lt;dll-path&gt;/usr/lib/snake
+ &lt;location&gt;/usr/bin ;
+</programlisting>
+ will allow the application to find libraries placed in the <filename>
+ /usr/lib/snake</filename> directory.
+ </para>
+
+ <para>
+ If you install libraries to a nonstandard location and add an explicit
+ path, you get more control over libraries which will be used. A library of
+ the same name in a system location will not be inadvertently used. If you
+ install libraries to a system location and do not add any paths, the
+ system administrator will have more control. Each library can be
+ individually upgraded, and all applications will use the new library.
+ </para>
+
+ <para>
+ Which approach is best depends on your situation. If the libraries are
+ relatively standalone and can be used by third party applications, they
+ should be installed in the system location. If you have lots of libraries
+ which can be used only by your application, it makes sense to install them
+ to a nonstandard directory and add an explicit path, like the example
+ above shows. Please also note that guidelines for different systems differ
+ in this respect. For example, the Debian GNU guidelines prohibit any
+ additional search paths while Solaris guidelines suggest that they should
+ always be used.
+ </para>
+ </section>
+
+ <section id="bbv2.recipies.site-config">
+ <title>Targets in site-config.jam</title>
+
+ <para>
+ It is desirable to declare standard libraries available on a given system.
+ Putting target declaration in a specific project's Jamfile is not really
+ good, since locations of the libraries can vary between different
+ development machines and then such declarations would need to be
+ duplicated in different projects. The solution is to declare the targets
+ in Boost.Build's <filename>site-config.jam</filename> configuration file:
+<programlisting>
+project site-config ;
+lib zlib : : &lt;name&gt;z ;
+</programlisting>
+ </para>
+
+ <para>
+ Recall that both <filename>site-config.jam</filename> and
+ <filename>user-config.jam</filename> are projects, and everything you can
+ do in a Jamfile you can do in those files as well. So, you declare a
+ project id and a target. Now, one can write:
+<programlisting>
+exe hello : hello.cpp /site-config//zlib ;
+</programlisting>
+ in any Jamfile.
+ </para>
+ </section>
+
+ <section id="bbv2.faq.header-only-libraries">
+ <title>Header-only libraries</title>
+
+ <para>
+ In modern C++, libraries often consist of just header files, without any
+ source files to compile. To use such libraries, you need to add proper
+ includes and possibly defines to your project. But with a large number of
+ external libraries it becomes problematic to remember which libraries are
+ header only, and which ones you have to link to. However, with Boost.Build
+ a header-only library can be declared as Boost.Build target and all
+ dependents can use such library without having to remeber whether it is a
+ header-only library or not.
+ </para>
+
+ <para>
+ Header-only libraries may be declared using the <code>alias</code> rule,
+ specifying their include path as a part of its usage requirements, for
+ example:
+<programlisting>
+alias my-lib
+ : # no sources
+ : # no build requirements
+ : # no default build
+ : &lt;include&gt;whatever ;
+</programlisting>
+ The includes specified in usage requirements of <code>my-lib</code> are
+ automatically added to all of its dependants' build properties. The
+ dependants need not care if <code>my-lib</code> is a header-only or not,
+ and it is possible to later make <code>my-lib</code> into a regular
+ compiled library without having to that its dependants' declarations.
+ </para>
+
+ <para>
+ If you already have proper usage requirements declared for a project where
+ a header-only library is defined, you do not need to duplicate them for
+ the <code>alias</code> target:
+<programlisting>
+project my : usage-requirements &lt;include&gt;whatever ;
+alias mylib ;
+</programlisting>
+ </para>
+ </section>
+</chapter>
+
+<!--
+ Local Variables:
+ mode: nxml
+ sgml-indent-data: t
+ sgml-parent-document: ("userman.xml" "chapter")
+ sgml-set-face: t
+ End:
+-->
diff --git a/tools/build/v2/doc/src/fragments.xml b/tools/build/v2/doc/src/fragments.xml
new file mode 100644
index 0000000000..78438a0c10
--- /dev/null
+++ b/tools/build/v2/doc/src/fragments.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+<chapter>
+ <section id="root_option">
+ <varlistentry>
+ <term><literal>root</literal></term>
+
+ <!-- At present, this option is only used to set LD_LIBRARY_PATH when
+ running tests, and matters only if compiler's lib directory is not in
+ LD_LIBRARY_PATH. -->
+
+ <listitem><para>Specifies root directory of the compiler installation.
+ This option is necessary only if it is not possible to detect this
+ information from the compiler command&#x2014;for example if the specified
+ compiler command is a user script.</para></listitem>
+ </varlistentry>
+ </section>
+
+ <section id="common_options">
+
+ <!-- This most likely needs splitting into common_options,
+ common_cxx_options & common_fortran_options or something similar. We also
+ need to document the fortran specific fflags option. Possibly related Boost
+ Build code should be updated as well so that fortran options may not be
+ specified for non-fortran toolsets and C/C++ options may not be specified
+ for non-C/C++ ones. -->
+
+ <varlistentry>
+ <term><literal>cflags</literal></term>
+
+ <listitem><para>Specifies additional compiler flags that will be used when
+ compiling C sources.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>cxxflags</literal></term>
+
+ <listitem><para>Specifies additional compiler flags that will be used when
+ compiling C++ sources.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>compileflags</literal></term>
+
+ <listitem><para>Specifies additional compiler flags that will be used when
+ compiling both C and C++ sources.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>linkflags</literal></term>
+
+ <listitem><para>Specifies additional command line options that will be
+ passed to the linker.</para>
+ </listitem>
+ </varlistentry>
+ </section>
+</chapter>
diff --git a/tools/build/v2/doc/src/howto.xml b/tools/build/v2/doc/src/howto.xml
new file mode 100644
index 0000000000..bd128a3214
--- /dev/null
+++ b/tools/build/v2/doc/src/howto.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <chapter id="bbv2.howto">
+ <title>How to use this document</title>
+
+ <para>
+ If you've just found out about Boost.Build V2 and want to know
+ if it will work for you, start with <xref linkend=
+ "bbv2.tutorial" />. You can continue with <xref
+ linkend="bbv2.overview" />. When you're ready to try Boost.Build
+ in practice, go to <xref linkend="bbv2.installation"/>.
+ </para>
+
+ <para>
+ If you are about to use Boost.Build on your project, or already
+ using it and have a problem, look at <xref linkend=
+ "bbv2.overview"/>.
+ </para>
+
+ <para>
+ If you're trying to build a project which uses Boost.Build,
+ see <xref linkend="bbv2.installation"/> and then read about
+ <xref linkend="bbv2.overview.invocation"/>.
+ </para>
+
+ <para>
+ If you have questions, please post them to our mailing list (<ulink
+ url="http://boost.org/more/mailing_lists.htm#jamboost"/>). The mailing list is
+ also mirrowed to newsgroup <ulink url="news://news.gmane.org/gmane.comp.lib.boost.build"/>.
+ </para>
+
+ </chapter>
diff --git a/tools/build/v2/doc/src/install.xml b/tools/build/v2/doc/src/install.xml
new file mode 100644
index 0000000000..afae46aa15
--- /dev/null
+++ b/tools/build/v2/doc/src/install.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <chapter id="bbv2.installation">
+ <title>Installation</title>
+
+ <para>
+ To install Boost.Build from an official release or a nightly build, as
+ available on the <ulink url="http://boost.org/boost-build2">official web site</ulink>,
+ follow these steps:
+ </para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Unpack the release. On the command line, go to the root of the
+ unpacked tree.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Run either <command>.\bootstrap.bat</command> (on Windows), or
+ <command>./bootstrap.sh</command> (on other operating systems).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Run
+ <screen>./bjam install --prefix=<replaceable>PREFIX</replaceable></screen>
+ where <replaceable>PREFIX</replaceable> is a directory where you
+ want Boost.Build to be installed.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Optionally, add <filename><replaceable>PREFIX</replaceable>/bin</filename>
+ to your <envar>PATH</envar> environment variable.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>If you are not using Boost.Build package, but rather the version
+ bundled with the Boost C++ Libraries, the above commands should be run
+ in the <filename>tools/build/v2</filename> directory.</para>
+
+ <para>
+ Now that Boost.Build is installed, you can try some of examples. Copy
+ <filename><replaceable>PREFIX</replaceable>/share/boost-build/examples/hello</filename>
+ to a different directory, then change to that directory and run:
+<screen><filename><replaceable>PREFIX</replaceable>/bin/bjam</filename></screen>
+ A simple executable should be built.
+ </para>
+
+ <!--
+ <simpara>
+ Configure Boost.Build to recognize the build resources (such
+ as compilers and libraries) you have installed on your
+ system. Open the
+ <filename>user-config.jam</filename> file in the Boost.Build
+ root directory and follow the instructions there to describe
+ your toolsets and libraries, and, if necessary, where they
+ are located.
+ </simpara>
+ </listitem>
+ -->
+
+ <!-- This part should not go into intoduction docs, but we need to
+ place it somewhere.
+
+ <para>It is slighly better way is to copy
+ <filename>new/user-config.jam</filename> into one of the locations
+ where it can be found (given in <link linkend=
+ "bbv2.reference.init.config">this table</link>). This prevent you
+ from accidentally overwriting your config when updating.</para>
+
+ -->
+
+ <!--
+ <bridgehead>Information for distributors</bridgehead>
+
+ <para>
+ If you're planning to package Boost.Build for a Linux distribution,
+ please follow these guidelines:
+
+ <itemizedlist>
+ <listitem><para>Create a separate package for Boost.Jam.</para></listitem>
+
+ <listitem>
+ <para>Create another package for Boost.Build, and make
+ this package install all Boost.Build files to
+ <filename>/usr/share/boost-build</filename> directory. After
+ install, that directory should contain everything you see in
+ Boost.Build release package, except for
+ <filename>jam_src</filename> directory. If you're using Boost CVS
+ to obtain Boost.Build, as opposed to release package, take
+ everything from the <filename>tools/build/v2</filename> directory.
+ For a check, make sure that
+ <filename>/usr/share/boost-build/boost-build.jam</filename> is installed.
+ </para>
+
+ <para>Placing Boost.Build into <filename>/usr/share/boost-build</filename>
+ will make sure that <command>bjam</command> will find Boost.Build
+ without any additional setup.</para>
+ </listitem>
+
+ <listitem><para>Provide a
+ <filename>/etc/site-config.jam</filename> configuration file that will
+ contain:
+<programlisting>
+using gcc ;
+</programlisting>
+ You might want to add dependency from Boost.Build package to gcc,
+ to make sure that users can always build Boost.Build examples.
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>If those guidelines are met, users will be able to invoke
+ <command>bjam</command> without any explicit configuration.
+ </para>
+
+
+ -->
+
+
+ </chapter>
+
+<!--
+ Local Variables:
+ mode: nxml
+ sgml-indent-data:t
+ sgml-parent-document:("userman.xml" "chapter")
+ sgml-set-face: t
+ sgml-omittag:nil
+ sgml-shorttag:nil
+ sgml-namecase-general:t
+ sgml-general-insert-case:lower
+ sgml-minimize-attributes:nil
+ sgml-always-quote-attributes:t
+ sgml-indent-step:2
+ sgml-exposed-tags:nil
+ sgml-local-catalogs:nil
+ sgml-local-ecat-files:nil
+ End:
+-->
+
diff --git a/tools/build/v2/doc/src/overview.xml b/tools/build/v2/doc/src/overview.xml
new file mode 100644
index 0000000000..048898867e
--- /dev/null
+++ b/tools/build/v2/doc/src/overview.xml
@@ -0,0 +1,1682 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <chapter id="bbv2.overview">
+ <title>Overview</title>
+
+ <para>
+ This section will provide the information necessary to create your own
+ projects using Boost.Build. The information provided here is relatively
+ high-level, and <xref linkend="bbv2.reference"/> as well as the on-line
+ help system must be used to obtain low-level documentation (see <xref
+ linkend="bbv2.reference.init.options.help"/>).
+ </para>
+
+ <para>
+ Boost.Build actually consists of two parts - Boost.Jam, a build engine
+ with its own interpreted language, and Boost.Build itself, implemented in
+ Boost.Jam's language. The chain of events when you type
+ <command>bjam</command> on the command line is as follows:
+ <orderedlist>
+ <listitem>
+ <para>
+ Boost.Jam tries to find Boost.Build and loads the top-level module.
+ The exact process is described in <xref linkend=
+ "bbv2.reference.init"/>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The top-level module loads user-defined configuration files,
+ <filename>user-config.jam</filename> and <filename>site-config.jam
+ </filename>, which define available toolsets.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The Jamfile in the current directory is read. That in turn might
+ cause reading of further Jamfiles. As a result, a tree of projects
+ is created, with targets inside projects.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Finally, using the build request specified on the command line,
+ Boost.Build decides which targets should be built and how. That
+ information is passed back to Boost.Jam, which takes care of
+ actually running the scheduled build action commands.
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+
+ <para>
+ So, to be able to successfully use Boost.Build, you need to know only four
+ things:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <link linkend="bbv2.overview.configuration">How to configure
+ Boost.Build</link>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <link linkend="bbv2.overview.targets">How to declare targets in
+ Jamfiles</link>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <link linkend="bbv2.overview.build_process">How the build process
+ works</link>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Some Basics about the Boost.Jam language. See <xref linkend=
+ "bbv2.overview.jam_language"/>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <section id="bbv2.overview.concepts">
+ <title>Concepts</title>
+
+ <para>Boost.Build has a few unique concepts that are introduced in this section. The best
+ way to explain the concepts is by comparison with more classical build tools.</para>
+
+ <para>
+ When using any flavour of make, you directly specify <firstterm>targets</firstterm>
+ and commands that are used to create them from other target. The below example
+ creates <filename>a.o</filename> from <filename>a.c</filename> using a hardcoded
+ compiler invocation command.
+<programlisting>
+a.o: a.c
+ g++ -o a.o -g a.c
+</programlisting>
+ This is rather low-level description mechanism and it's hard to adjust commands, options,
+ and sets of created targets depending on the used compiler and operating system.
+ </para>
+
+ <para>
+ To improve portability, most modern build system provide a set of higher-level
+ functions that can be used in build description files. Consider this example:
+<programlisting>
+add_program ("a", "a.c")
+</programlisting>
+ This is a function call that creates targets necessary to create executable file
+ from source file <filename>a.c</filename>. Depending on configured properties,
+ different commands line may be used. However, <code>add_program</code> is higher-level,
+ but rather thin level. All targets are created immediately when build description
+ is parsed, which makes it impossible to perform multi-variant builds. Often, change
+ in any build property requires complete reconfiguration of the build tree.
+ </para>
+
+ <para>
+ In order to support true multivariant builds, Boost.Build introduces the concept of
+ <indexterm> <primary>metatarget</primary> <secondary>definition</secondary></indexterm>
+ <indexterm> <primary>main target</primary> <see>metataget</see> </indexterm>
+ <firstterm>metatarget</firstterm>&mdash;object that is created when build description
+ is parsed and can be later called with specific build properties to generate
+ actual targets.
+ </para>
+
+ <para>
+ Consider an example:
+<programlisting>
+exe a : a.cpp ;
+</programlisting>
+ When this declaration is parsed, Boost.Build creates a metatarget, but does not
+ yet decides what files must be created, or what commands must be used. After
+ all build files are parsed, Boost.Build considers properties requested on the
+ command line. Supposed you have invoked Boost.Build with:
+<screen>
+bjam toolset=gcc toolset=msvc
+</screen>
+ In that case, the metatarget will be called twice, once with <code>toolset=gcc</code>
+ and once with <code>toolset=msvc</code>. Both invocations will produce concrete
+ targets, that will have different extensions and use different command lines.
+ </para>
+
+ <para>
+ Another key concept is
+ <indexterm><primary>property</primary><secondary>definition</secondary></indexterm>
+ <firstterm>build property</firstterm>. Build property is a variable
+ that affects the build process. It can be specified on the command line, and is
+ passed when calling a metatarget. While all build tools have a similar mechanism,
+ Boost.Build differs by requiring that all build properties are declared in advance,
+ and providing a large set of properties with portable semantics.
+ </para>
+
+ <para>
+ The final concept is <indexterm><primary>property</primary><secondary>propagation</secondary></indexterm>
+ <firstterm>property propagation</firstterm>. Boost.Build does not require that every
+ metatarget is called with the same properties. Instead, the
+ "top-level" metatargets are called with the properties specified on the command line.
+ Each metatarget can elect to augment or override some properties (in particular,
+ using the requirements mechanism, see <xref linkend="bbv2.overview.targets.requirements"/>).
+ Then, the dependency metatargets are called with modified properties and produce
+ concrete targets that are then used in build process. Of course, dependency metatargets
+ maybe in turn modify build properties and have dependencies of their own.
+ </para>
+
+ <para>For more in-depth treatment of the requirements and concepts, you may refer
+ to <ulink url="http://syrcose.ispras.ru/2009/files/04_paper.pdf">SYRCoSE 2009 Boost.Build article</ulink>.
+ </para>
+
+ </section>
+
+ <section id="bbv2.overview.jam_language">
+ <title>Boost.Jam Language</title>
+
+ <para>
+ This section will describe the basics of the Boost.Jam language&#x2014;
+ just enough for writing Jamfiles. For more information, please see the
+ <link linkend="bbv2.jam">Boost.Jam</link> documentation.
+ </para>
+
+ <para>
+ <link linkend="bbv2.jam">Boost.Jam</link> has an interpreted, procedural
+ language. On the lowest level, a <link linkend="bbv2.jam">Boost.Jam
+ </link> program consists of variables and <indexterm><primary>rule
+ </primary></indexterm> <firstterm>rules</firstterm> (Jam term for
+ function). They are grouped into modules&#x2014;there is one global
+ module and a number of named modules. Besides that, a <link linkend=
+ "bbv2.jam">Boost.Jam</link> program contains classes and class
+ instances.
+ </para>
+
+ <para>
+ Syntantically, a <link linkend="bbv2.jam">Boost.Jam</link> program
+ consists of two kind of elements&#x2014;keywords (which have a special
+ meaning to <link linkend="bbv2.jam">Boost.Jam</link>) and literals.
+ Consider this code:
+<programlisting>
+a = b ;
+</programlisting>
+ which assigns the value <literal>b</literal> to the variable <literal>a
+ </literal>. Here, <literal>=</literal> and <literal>;</literal> are
+ keywords, while <literal>a</literal> and <literal>b</literal> are
+ literals.
+ <warning>
+ <para>
+ All syntax elements, even keywords, must be separated by spaces. For
+ example, omitting the space character before <literal>;</literal>
+ will lead to a syntax error.
+ </para>
+ </warning>
+ If you want to use a literal value that is the same as some keyword, the
+ value can be quoted:
+<programlisting>
+a = "=" ;
+</programlisting>
+ </para>
+
+ <para>
+ All variables in <link linkend="bbv2.jam">Boost.Jam</link> have the same
+ type&#x2014;list of strings. To define a variable one assigns a value to
+ it, like in the previous example. An undefined variable is the same as a
+ variable with an empty value. Variables can be accessed using the
+ <code>$(<replaceable>variable</replaceable>)</code> syntax. For example:
+<programlisting>
+a = $(b) $(c) ;
+</programlisting>
+ </para>
+
+ <para>
+ Rules are defined by specifying the rule name, the parameter names, and
+ the allowed value list size for each parameter.
+<programlisting>
+rule <replaceable>example</replaceable>
+ (
+ <replaceable>parameter1</replaceable> :
+ <replaceable>parameter2 ?</replaceable> :
+ <replaceable>parameter3 +</replaceable> :
+ <replaceable>parameter4 *</replaceable>
+ )
+ {
+ # rule body
+ }
+ </programlisting>
+ When this rule is called, the list passed as the first argument must
+ have exactly one value. The list passed as the second argument can
+ either have one value of be empty. The two remaining arguments can be
+ arbitrarily long, but the third argument may not be empty.
+ </para>
+
+ <para>
+ The overview of <link linkend="bbv2.jam">Boost.Jam</link> language
+ statements is given below:
+<programlisting>
+helper 1 : 2 : 3 ;
+x = [ helper 1 : 2 : 3 ] ;
+</programlisting>
+ This code calls the named rule with the specified arguments. When the
+ result of the call must be used inside some expression, you need to add
+ brackets around the call, like shown on the second line.
+<programlisting>
+if cond { statements } [ else { statements } ]
+</programlisting>
+ This is a regular if-statement. The condition is composed of:
+ <itemizedlist>
+ <listitem>
+ <para>
+ Literals (true if at least one string is not empty)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Comparisons: <code>a <replaceable>operator</replaceable> b</code>
+ where <replaceable>operator</replaceable> is one of
+ <code>=</code>, <code>!=</code>, <code>&lt;</code>,
+ <code>&gt;</code>, <code>&lt;=</code> or <code>&gt;=</code>. The
+ comparison is done pairwise between each string in the left and
+ the right arguments.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Logical operations: <code>! a</code>, <code>a &amp;&amp; b</code>,
+ <code>a || b</code>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Grouping: <code>( cond )</code>
+ </para>
+ </listitem>
+ </itemizedlist>
+<programlisting>
+for var in list { statements }
+</programlisting>
+ Executes statements for each element in list, setting the variable
+ <varname>var</varname> to the element value.
+<programlisting>
+while cond { statements }
+</programlisting>
+ Repeatedly execute statements while cond remains true upon entry.
+<programlisting>
+return values ;
+</programlisting>
+ This statement should be used only inside a rule and assigns
+ <code>values</code> to the return value of the rule.
+ <warning>
+ <para>
+ The <code>return</code> statement does not exit the rule. For
+ example:
+<programlisting>
+rule test ( )
+{
+ if 1 = 1
+ {
+ return "reasonable" ;
+ }
+ return "strange" ;
+}
+</programlisting>
+ will return <literal>strange</literal>, not
+ <literal>reasonable</literal>.
+ </para>
+ </warning>
+<programlisting>
+import <replaceable>module</replaceable> ;
+import <replaceable>module</replaceable> : <replaceable>rule</replaceable> ;
+</programlisting>
+ The first form imports the specified bjam module. All rules from that
+ module are made available using the qualified name: <code><replaceable>
+ module</replaceable>.<replaceable>rule</replaceable></code>. The second
+ form imports the specified rules only, and they can be called using
+ unqualified names.
+ </para>
+
+ <para id="bbv2.overview.jam_language.actions">
+ Sometimes, you'd need to specify the actual command lines to be used
+ when creating targets. In jam language, you use named actions to do
+ this. For example:
+<programlisting>
+actions create-file-from-another
+{
+ create-file-from-another $(&lt;) $(&gt;)
+}
+</programlisting>
+ This specifies a named action called <literal>
+ create-file-from-another</literal>. The text inside braces is the
+ command to invoke. The <literal>$(&lt;)</literal> variable will be
+ expanded to a list of generated files, and the <literal>$(&gt;)
+ </literal> variable will be expanded to a list of source files.
+ </para>
+
+ <para>
+ To flexibly adjust the command line, you can define a rule with the same
+ name as the action and taking three parameters -- targets, sources and
+ properties. For example:
+<programlisting>
+rule create-file-from-another ( targets * : sources * : properties * )
+{
+ if &lt;variant&gt;debug in $(properties)
+ {
+ OPTIONS on $(targets) = --debug ;
+ }
+}
+actions create-file-from-another
+{
+ create-file-from-another $(OPTIONS) $(&lt;) $(&gt;)
+}
+</programlisting>
+ In this example, the rule checks if certain build property is specified.
+ If so, it sets variable <varname>OPIONS</varname> that is then used
+ inside the action. Note that the variables set "on a target" will be
+ visible only inside actions building that target, not globally. Were
+ they set globally, using variable named <varname>OPTIONS</varname> in
+ two unrelated actions would be impossible.
+ </para>
+
+ <para>
+ More details can be found in Jam reference, <xref
+ linkend="jam.language.rules"/>.
+ </para>
+ </section>
+
+ <section id="bbv2.overview.configuration">
+ <title>Configuration</title>
+
+ <para>
+ On startup, Boost.Build searches and reads two configuration files:
+ <filename>site-config.jam</filename> and <filename>user-config.jam</filename>.
+ The first one is usually installed and maintained by system administrator, and
+ the second is for user to modify. You can edit the one in the top-level
+ directory of Boost.Build installation or create a copy in your home
+ directory and edit the copy. The following table explains where both files
+ are searched.
+ </para>
+
+ <table id="bbv2.reference.init.config">
+ <title>Search paths for configuration files</title>
+
+ <tgroup cols="3">
+ <thead>
+
+ <row>
+ <entry></entry>
+
+ <entry>site-config.jam</entry>
+
+ <entry>user-config.jam</entry>
+ </row>
+
+ </thead>
+ <tbody>
+
+ <row>
+ <entry>Linux</entry>
+
+ <entry>
+ <simpara><code>/etc</code></simpara>
+ <simpara><code>$HOME</code></simpara>
+ <simpara><code>$BOOST_BUILD_PATH</code></simpara>
+ </entry>
+
+ <entry>
+ <simpara><code>$HOME</code></simpara>
+ <simpara><code>$BOOST_BUILD_PATH</code></simpara>
+ </entry>
+ </row>
+
+ <row>
+ <entry>Windows</entry>
+
+ <entry>
+ <simpara><code>%SystemRoot%</code></simpara>
+ <simpara><code>%HOMEDRIVE%%HOMEPATH%</code></simpara>
+ <simpara><code>%HOME%</code></simpara>
+ <simpara><code>%BOOST_BUILD_PATH%</code></simpara>
+ </entry>
+
+ <entry>
+ <simpara><code>%HOMEDRIVE%%HOMEPATH%</code></simpara>
+ <simpara><code>%HOME%</code></simpara>
+ <simpara><code>%BOOST_BUILD_PATH%</code></simpara>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <tip>
+ <para>
+ You can use the <command>--debug-configuration</command> option to
+ find which configuration files are actually loaded.
+ </para>
+ </tip>
+
+ <para>
+ Usually, <filename>user-config.jam</filename> just defines available compilers
+ and other tools (see <xref linkend="bbv2.recipies.site-config"/> for more advanced
+ usage). A tool is configured using the following syntax:
+ </para>
+
+<programlisting>
+using <replaceable>tool-name</replaceable> : ... ;
+</programlisting>
+<para>
+ The <functionname>using</functionname> rule is given a name of tool, and
+ will make that tool available to Boost.Build. For example,
+<programlisting>
+using gcc ;
+</programlisting> will make the <ulink url="http://gcc.gnu.org">GCC</ulink> compiler available.
+ </para>
+
+ <para>
+ All the supported tools are documented in <xref linkend="bbv2.reference.tools"/>,
+ including the specific options they take. Some general notes that apply to most
+ C++ compilers are below.
+ </para>
+
+ <para>
+ For all the C++ compiler toolsets Boost.Build supports
+ out-of-the-box, the list of parameters to
+ <functionname>using</functionname> is the same: <parameter
+ class="function">toolset-name</parameter>, <parameter
+ class="function">version</parameter>, <parameter
+ class="function">invocation-command</parameter>, and <parameter
+ class="function">options</parameter>.
+ </para>
+
+ <para>If you have a single compiler, and the compiler executable
+ <itemizedlist>
+ <listitem><para>has its &#x201C;usual name&#x201D; and is in the
+ <envar>PATH</envar>, or</para></listitem>
+ <listitem><para>was installed in a standard &#x201C;installation
+ directory&#x201D;, or</para></listitem>
+ <listitem><para>can be found using a global system like the Windows
+ registry.</para></listitem>
+ </itemizedlist>
+ it can be configured by simply:</para>
+<programlisting>
+using <replaceable>tool-name</replaceable> ;
+</programlisting>
+ <!-- TODO: mention auto-configuration? -->
+
+ <para>If the compiler is installed in a custom directory, you should provide the
+ command that invokes the compiler, for example:</para>
+<programlisting>
+using gcc : : g++-3.2 ;
+using msvc : : "Z:/Programs/Microsoft Visual Studio/vc98/bin/cl" ;
+</programlisting>
+ <para>
+ Some Boost.Build toolsets will use that path to take additional actions
+ required before invoking the compiler, such as calling vendor-supplied
+ scripts to set up its required environment variables. When compiler
+ executables for C and C++ are different, path to the C++ compiler
+ executable must be specified. The command can
+ be any command allowed by the operating system. For example:
+<programlisting>
+using msvc : : echo Compiling &#x26;&#x26; foo/bar/baz/cl ;
+</programlisting>
+ will work.
+ </para>
+
+ <para>
+ To configure several versions of a toolset, simply invoke the
+ <functionname>using</functionname> rule multiple times:
+<programlisting>
+using gcc : 3.3 ;
+using gcc : 3.4 : g++-3.4 ;
+using gcc : 3.2 : g++-3.2 ;
+</programlisting>
+ Note that in the first call to <functionname>using</functionname>, the
+ compiler found in the <envar>PATH</envar> will be used, and there is no
+ need to explicitly specify the command.
+ </para>
+
+<!-- TODO: This is not actually relevant for gcc now, and we need to rethink this
+ <para>As shown above, both the <parameter
+ class="function">version</parameter> and <parameter
+ class="function">invocation-command</parameter> parameters are
+ optional, but there's an important restriction: if you configure
+ the same toolset more than once, you must pass the <parameter
+ class="function">version</parameter>
+ parameter every time. For example, the following is not allowed:
+<programlisting>
+using gcc ;
+using gcc : 3.4 : g++-3.4 ;
+</programlisting>
+ because the first <functionname>using</functionname> call does
+ not specify a <parameter class="function">version</parameter>.
+ </para> -->
+
+ <para>
+ Many of toolsets have an <parameter class="function">options</parameter>
+ parameter to fine-tune the configuration. All of
+ Boost.Build's standard compiler toolsets accept four options
+ <varname>cflags</varname>, <varname>cxxflags</varname>,
+ <varname>compileflags</varname> and <varname>linkflags</varname> as <parameter
+ class="function">options</parameter> specifying flags that will be
+ always passed to the corresponding tools. Values of the
+ <varname>cflags</varname> feature are passed directly to the C
+ compiler, values of the <varname>cxxflags</varname> feature are
+ passed directly to the C++ compiler, and values of the
+ <varname>compileflags</varname> feature are passed to both. For
+ example, to configure a <command>gcc</command> toolset so that it
+ always generates 64-bit code you could write:
+<programlisting>
+ using gcc : 3.4 : : &lt;compileflags&gt;-m64 &lt;linkflags&gt;-m64 ;
+</programlisting>
+ </para>
+
+ <warning>
+ <para>
+ Although the syntax used to specify toolset options is very similar
+ to syntax used to specify requirements in Jamfiles, the toolset options
+ are not the same as features. Don't try to specify a feature value
+ in toolset initialization.
+ </para>
+ </warning>
+
+ </section>
+
+ <section id="bbv2.overview.invocation">
+ <title>Invocation</title>
+
+ <para>To invoke Boost.Build, type <command>bjam</command> on the command line. Three kinds
+ of command-line tokens are accepted, in any order:</para>
+ <variablelist>
+ <varlistentry>
+ <term>options</term>
+
+ <listitem><para>Options start with either dash, or two dashes. The standard options
+ are listed below, and each project may add additional options</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>properties</term>
+
+ <listitem><para>Properties specify details of what you want to build (e.g. debug
+ or release variant). Syntactically, all command line tokens with equal sign in them
+ are considered to specify properties. In the simplest form, property looks like
+ <command><replaceable>feature</replaceable>=<replaceable>value</replaceable></command>
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>target</term>
+
+ <listitem><para>All tokens that are neither options nor properties specify
+ what targets to build. The available targets entirely depend on the project
+ you are building.</para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <section id="bbv2.overview.invocation.examples">
+ <title>Examples</title>
+
+ <para>To build all targets defined in Jamfile in the current directory with default properties, run:
+<screen>
+bjam
+</screen>
+ </para>
+
+ <para>To build specific targets, specify them on the command line:
+<screen>
+bjam lib1 subproject//lib2
+</screen>
+ </para>
+
+ <para>To request a certain value for some property, add <literal>
+ <replaceable>property</replaceable>=<replaceable>value</replaceable></literal> to the command line:
+<screen>
+bjam toolset=gcc variant=debug optimization=space
+</screen>
+ </para>
+ </section>
+
+ <section id="bbv2.overview.invocation.options">
+ <title>Options</title>
+
+ <para>Boost.Build recognizes the following command line options.</para>
+
+ <variablelist>
+
+ <varlistentry id="bbv2.reference.init.options.help">
+ <term><option>--help</option></term>
+ <listitem>
+ <para>Invokes the online help system. This prints general
+ information on how to use the help system with additional
+ --help* options.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--clean</option></term>
+ <listitem>
+ <para>Cleans all targets in the current directory and
+ in any subprojects. Note that unlike the <literal>clean</literal>
+ target in make, you can use <literal>--clean</literal>
+ together with target names to clean specific targets.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--clean-all</option></term>
+ <listitem>
+ <para>Cleans all targets,
+ no matter where they are defined. In particular, it will clean targets
+ in parent Jamfiles, and targets defined under other project roots.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--build-dir</option></term>
+ <listitem>
+ <para>Changes build directories for all project roots being built. When
+ this option is specified, all Jamroot files should declare project name.
+ The build directory for the project root will be computed by concatanating
+ the value of the <option>--build-dir</option> option, the project name
+ specified in Jamroot, and the build dir specified in Jamroot
+ (or <literal>bin</literal>, if none is specified).
+ </para>
+
+ <para>The option is primarily useful when building from read-only
+ media, when you can't modify Jamroot.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--version</option></term>
+ <listitem>
+ <para>Prints information on Boost.Build and Boost.Jam
+ versions.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-a</option></term>
+ <listitem>
+ <para>Causes all files to be rebuilt.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-n</option></term>
+ <listitem>
+ <para>Do no execute the commands, only print them.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-q</option></term>
+ <listitem>
+ <para>Stop at first error, as opposed to continuing to build targets
+ that don't depend on the failed ones.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-j <replaceable>N</replaceable></option></term>
+ <listitem>
+ <para>Run up to <replaceable>N</replaceable> commands in parallel.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--debug-configuration</option></term>
+ <listitem>
+ <para>Produces debug information about loading of Boost.Build
+ and toolset files.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--debug-building</option></term>
+ <listitem>
+ <para>Prints what targets are being built and with what properties.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--debug-generators</option></term>
+ <listitem>
+ <para>Produces debug output from generator search process.
+ Useful for debugging custom generators.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--ignore-config</option></term>
+ <listitem>
+ <para>Do not load <literal>site-config.jam</literal> and
+ <literal>user-config.jam</literal> configuration files.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-d0</option></term>
+ <listitem>
+ <para>Supress all informational messages.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-d <replaceable>N</replaceable></option></term>
+ <listitem>
+ <para>Enable cummulative debugging levels from 1 to n. Values are:
+ <orderedlist>
+ <listitem>Show the actions taken for building targets, as they are executed (the default).</listitem>
+ <listitem>Show "quiet" actions and display all action text, as they are executed.</listitem>
+ <listitem>Show dependency analysis, and target/source timestamps/paths.</listitem>
+ <listitem>Show arguments and timming of shell invocations.</listitem>
+ <listitem>Show rule invocations and variable expansions.</listitem>
+ <listitem>Show directory/header file/archive scans, and attempts at binding to targets.</listitem>
+ <listitem>Show variable settings.</listitem>
+ <listitem>Show variable fetches, variable expansions, and evaluation of '"if"' expressions.</listitem>
+ <listitem>Show variable manipulation, scanner tokens, and memory usage.</listitem>
+ <listitem>Show profile information for rules, both timing and memory.</listitem>
+ <listitem>Show parsing progress of Jamfiles.</listitem>
+ <listitem>Show graph of target dependencies.</listitem>
+ <listitem>Show change target status (fate).</listitem>
+ </orderedlist>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-d +<replaceable>N</replaceable></option></term>
+ <listitem>
+ <para>Enable debugging level <replaceable>N</replaceable>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-o <replaceable>file</replaceable></option></term>
+ <listitem>
+ <para>Write the updating actions to the specified file instead of running them.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-s <replaceable>var</replaceable>=<replaceable>value</replaceable></option></term>
+ <listitem>
+ <para>Set the variable <replaceable>var</replaceable> to
+ <replaceable>value</replaceable> in the global scope of the jam
+ language interpreter, overriding variables imported from the
+ environment.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ <section id="bbv2.overview.invocation.properties">
+ <title>Properties</title>
+
+ <para>In the simplest case, the build is performed with a single set of properties,
+ that you specify on the command line with elements in the form
+ <command><replaceable>feature</replaceable>=<replaceable>value</replaceable></command>.
+ The complete list of features can be found in <xref linkend="bbv2.overview.builtins.features"/>.
+ The most common features are summarized below.</para>
+
+ <table>
+ <tgroup cols="3">
+ <thead>
+
+ <row>
+ <entry>Feature</entry>
+
+ <entry>Allowed values</entry>
+
+ <entry>Notes</entry>
+ </row>
+
+ </thead>
+ <tbody>
+
+ <row>
+ <entry>variant</entry>
+
+ <entry>debug,release</entry>
+
+ <entry></entry>
+ </row>
+
+ <row>
+ <entry>link</entry>
+
+ <entry>shared,static</entry>
+
+ <entry>Determines if Boost.Build creates shared or static libraries</entry>
+ </row>
+
+ <row>
+ <entry>threading</entry>
+
+ <entry>single,multi</entry>
+
+ <entry>Cause the produced binaries to be thread-safe. This requires proper support in the source code itself.</entry>
+ </row>
+
+ <row>
+ <entry>address-model</entry>
+
+ <entry>32,64</entry>
+
+ <entry>Explicitly request either 32-bit or 64-bit code generation. This typically
+ requires that your compiler is appropriately configured. Please refer to
+ <xref linkend="bbv2.reference.tools.compilers"/> and your compiler documentation
+ in case of problems.</entry>
+ </row>
+
+ <row>
+ <entry>toolset</entry>
+
+ <entry>(Depends on configuration)</entry>
+
+ <entry>The C++ compiler to use. See <xref linkend="bbv2.reference.tools.compilers"/> for a detailed list.</entry>
+ </row>
+
+ <row>
+ <entry>include</entry>
+
+ <entry>(Arbitrary string)</entry>
+
+ <entry>Additional include paths for C and C++ compilers.</entry>
+ </row>
+
+ <row>
+ <entry>define</entry>
+
+ <entry>(Arbitrary string)</entry>
+
+ <entry>Additional macro definitions for C and C++ compilers. The string should be either
+ <code>SYMBOL</code> or <code>SYMBOL=VALUE</code></entry>
+ </row>
+
+ <row>
+ <entry>cxxflags</entry>
+
+ <entry>(Arbitrary string)</entry>
+
+ <entry>Custom options to pass to the C++ compiler.</entry>
+ </row>
+
+ <row>
+ <entry>cflags</entry>
+
+ <entry>(Arbitrary string)</entry>
+
+ <entry>Custom options to pass to the C compiler.</entry>
+ </row>
+
+ <row>
+ <entry>linkflags</entry>
+
+ <entry>(Arbitrary string)</entry>
+
+ <entry>Custom options to pass to the C++ linker.</entry>
+ </row>
+
+ <row>
+ <entry>runtime-link</entry>
+
+ <entry>shared,static</entry>
+
+ <entry>Determines if shared or static version of C and C++ runtimes should be used.</entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </table>
+
+ If you have more than one version of a given C++ toolset (e.g. configured in
+ <filename>user-config.jam</filename>, or autodetected, as happens with msvc), you can
+ request the specific version by passing
+ <code><replaceable>toolset</replaceable>-<replaceable>version</replaceable></code> as
+ the value of the <code>toolset</code> feature, for example <code>toolset=msvc-8.0</code>.
+
+
+ <para>
+ If a feature has a fixed set of values it can be specified more than
+ once on the command line. <!-- define 'base' and link to it -->
+ In which case, everything will be built several times --
+ once for each specified value of a feature. For example, if you use
+ </para>
+<screen>
+bjam link=static link=shared threading=single threading=multi
+</screen>
+ <para>
+ Then a total of 4 builds will be performed. For convenience,
+ instead of specifying all requested values of a feature in separate command line elements,
+ you can separate the values with commands, for example:
+ </para>
+<screen>
+bjam link=static,shared threading=single,multi
+</screen>
+ <para>
+ The comma has special meaning only if the feature has a fixed set of values, so
+ </para>
+<screen>
+bjam include=static,shared
+</screen>
+ <para>is not treated specially.</para>
+
+ </section>
+
+ <section id="bbv2.overview.invocation.targets">
+ <title>Targets</title>
+
+ <para>All command line elements that are neither options nor properties are the names of the
+ targets to build. See <xref linkend="bbv2.reference.ids"/>. If no target is specified,
+ the project in the current directory is built.</para>
+ </section>
+
+ </section>
+
+ <section id="bbv2.overview.targets">
+ <title>Declaring Targets</title>
+
+ <para id="bbv2.overview.targets.main">
+ A <firstterm>Main target</firstterm> is a user-defined named
+ entity that can be built, for example an executable file.
+ Declaring a main target is usually done using one of the main
+ target rules described in <xref linkend=
+ "bbv2.reference.rules"/>. The user can also declare
+ custom main target rules as shown in <xref
+ linkend="bbv2.extending.rules"/>.
+ </para>
+
+ <indexterm><primary>main target</primary><secondary>declaration
+ syntax</secondary></indexterm>
+ <para>Most main target rules in Boost.Build have the same common
+ signature:</para>
+
+ <!-- I think we maybe ought to be talking about a common
+ _signature_ here, having already explained Boost.Jam function
+ signatures at the beginning of this chapter. Then we could show
+ ( main-target-name : sources * : requirements * : default-build * : usage-requirements * )
+ instead. More precise.
+
+ Also, I suggest replacing "default-build" by "default-properties" everywhere.
+ -->
+
+<indexterm><primary>common signature</primary></indexterm>
+<anchor id="bbv2.main-target-rule-syntax"/>
+<programlisting>
+rule <replaceable>rule-name</replaceable> (
+ main-target-name :
+ sources + :
+ requirements * :
+ default-build * :
+ usage-requirements * )
+</programlisting>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ <parameter>main-target-name</parameter> is the name used
+ to request the target on command line and to use it from
+ other main targets. A main target name may contain
+ alphanumeric characters, dashes
+ (&#x2018;<code>-</code>&#x2019;), and underscores
+ (&#x2018;<code>_</code>&#x2019;).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <parameter>sources</parameter> is the list of source files and other main
+ targets that must be combined.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <parameter>requirements</parameter> is the list of properties that must always
+ be present when this main target is built.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <parameter>default-build</parameter> is the list of properties that will be used
+ unless some other value of the same feature is already
+ specified, e.g. on the command line or by propagation from a dependent target.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <parameter>usage-requirements</parameter> is the list of properties that will be
+ propagated to all main targets that use this one, i.e. to all its
+ dependents.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Some main target rules have a different list of parameters as explicitly
+ stated in their documentation.
+ </para>
+
+ <para>The actual requirements for a target are obtained by refining
+ requirements of the project where a target is declared with the
+ explicitly specified requirements. The same is true for
+ usage-requirements. More details can be found in
+ <xref linkend="bbv2.reference.variants.proprefine"/>
+ </para>
+
+ <section>
+ <title>Name</title>
+
+ <!-- perphaps we should use 'name-target-name' to closer
+ bind this description to the rule's signature. Here, and for
+ other parameters. -->
+ <para>The name of main target has two purposes. First, it's used to refer to this target from
+ other targets and from command line. Second, it's used to compute the names of the generated files.
+ Typically, filenames are obtained from main target name by appending system-dependent suffixes and
+ prefixes.
+ </para>
+
+ <para>The name of a main target can contain alphanumeric characters,
+ dashes, undescores and dots. The entire
+ name is significant when resolving references from other targets. For determining filenames, only the
+ part before the first dot is taken. For example:</para>
+<programlisting>
+obj test.release : test.cpp : &lt;variant&gt;release ;
+obj test.debug : test.cpp : &lt;variant&gt;debug ;
+</programlisting>
+ <para>will generate two files named <filename>test.obj</filename> (in two different directories), not
+ two files named <filename>test.release.obj</filename> and <filename>test.debug.obj</filename>.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Sources</title>
+
+ <para>The list of sources specifies what should be processed to
+ get the resulting targets. Most of the time, it's just a list of
+ files. Sometimes, you'll want to automatically construct the
+ list of source files rather than having to spell it out
+ manually, in which case you can use the
+ <functionname>glob</functionname> rule. Here are two examples:</para>
+<programlisting>
+exe a : a.cpp ; # a.cpp is the only source file
+exe b : [ glob *.cpp ] ; # all .cpp files in this directory are sources
+</programlisting>
+ <para>
+ Unless you specify a file with an absolute path, the name is
+ considered relative to the source directory&#x200A;&#x2014;&#x200A;which is typically
+ the directory where the Jamfile is located, but can be changed as
+ described in <xref linkend=
+ "bbv2.overview.projects.attributes.projectrule"/>.
+ </para>
+
+ <para>
+ <!-- use "project-id" here? -->
+ The list of sources can also refer to other main targets. Targets in
+ the same project can be referred to by name, while targets in other
+ projects must be qualified with a directory or a symbolic project
+ name. The directory/project name is separated from the target name by
+ a double forward slash. There is no special syntax to distinguish the
+ directory name from the project name&#x2014;the part before the double
+ slash is first looked up as project name, and then as directory name.
+ For example:
+ </para>
+<programlisting>
+lib helper : helper.cpp ;
+exe a : a.cpp helper ;
+# Since all project ids start with slash, ".." is a directory name.
+exe b : b.cpp ..//utils ;
+exe c : c.cpp /boost/program_options//program_options ;
+</programlisting>
+ <para>
+ The first exe uses the library defined in the same project. The second
+ one uses some target (most likely a library) defined by a Jamfile one
+ level higher. Finally, the third target uses a <ulink url=
+ "http://boost.org">C++ Boost</ulink> library, referring to it using
+ its absolute symbolic name. More information about target references
+ can be found in <xref linkend="bbv2.tutorial.libs"/> and <xref
+ linkend="bbv2.reference.ids"/>.
+ </para>
+ </section>
+
+ <section id="bbv2.overview.targets.requirements">
+ <title>Requirements</title>
+ <indexterm><primary>requirements</primary></indexterm>
+ <para>Requirements are the properties that should always be present when
+ building a target. Typically, they are includes and defines:
+<programlisting>
+exe hello : hello.cpp : &lt;include&gt;/opt/boost &lt;define&gt;MY_DEBUG ;
+</programlisting>
+ There is a number of other features, listed in
+ <xref linkend="bbv2.overview.builtins.features"/>. For example if
+ a library can only be built statically, or a file can't be compiled
+ with optimization due to a compiler bug, one can use
+<programlisting>
+lib util : util.cpp : &lt;link&gt;static ;
+obj main : main.cpp : &lt;optimization&gt;off ;
+</programlisting>
+ </para>
+
+ <para id="bbv2.overview.targets.requirements.conditional">Sometimes, particular relationships need to be maintained
+ among a target's build properties. This can be achieved with
+ <firstterm>conditional
+ requirements</firstterm>. For example, you might want to set
+ specific <code>#defines</code> when a library is built as shared,
+ or when a target's <code>release</code> variant is built in
+ release mode.
+<programlisting>
+lib network : network.cpp
+ : <emphasis role="bold">&lt;link&gt;shared:&lt;define&gt;NEWORK_LIB_SHARED</emphasis>
+ &lt;variant&gt;release:&lt;define&gt;EXTRA_FAST
+ ;
+</programlisting>
+
+ In the example above, whenever <filename>network</filename> is
+ built with <code>&lt;link&gt;shared</code>,
+ <code>&lt;define&gt;NEWORK_LIB_SHARED</code> will be in its
+ properties, too.
+ </para>
+
+ <para>You can use several properties in the condition, for example:
+<programlisting>
+lib network : network.cpp
+ : &lt;toolset&gt;gcc,&lt;optimization&gt;speed:&lt;define&gt;USE_INLINE_ASSEMBLER
+ ;
+</programlisting>
+ </para>
+
+ <para id="bbv2.overview.targets.requirements.indirect">
+ A more powerful variant of conditional requirements
+ is <firstterm>indirect conditional requirements</firstterm>.
+ You can provide a rule that will be called with the current build properties and can compute additional properties
+ to be added. For example:
+<programlisting>
+lib network : network.cpp
+ : &lt;conditional&gt;@my-rule
+ ;
+rule my-rule ( properties * )
+{
+ local result ;
+ if &lt;toolset&gt;gcc &lt;optimization&gt;speed in $(properties)
+ {
+ result += &lt;define&gt;USE_INLINE_ASSEMBLER ;
+ }
+ return $(result) ;
+}
+</programlisting>
+ This example is equivalent to the previous one, but for complex cases, indirect conditional
+ requirements can be easier to write and understand.
+ </para>
+
+ <para>Requirements explicitly specified for a target are usually
+ combined with the requirements specified for the containing project. You
+ can cause a target to completely ignore specific project's requirement
+ using the syntax by adding a minus sign before a property, for example:
+<programlisting>
+exe main : main.cpp : <emphasis role="bold">-&lt;define&gt;UNNECESSARY_DEFINE</emphasis> ;
+</programlisting>
+ This syntax is the only way to ignore free properties from a parent,
+ such as defines. It can be also useful for ordinary properties. Consider
+ this example:
+<programlisting>
+project test : requirements &lt;threading&gt;multi ;
+exe test1 : test1.cpp ;
+exe test2 : test2.cpp : &lt;threading&gt;single ;
+exe test3 : test3.cpp : -&lt;threading&gt;multi ;
+</programlisting>
+ Here, <code>test1</code> inherits project requirements and will always
+ be built in multi-threaded mode. The <code>test2</code> target
+ <emphasis>overrides</emphasis> project's requirements and will
+ always be built in single-threaded mode. In contrast, the
+ <code>test3</code> target <emphasis>removes</emphasis> a property
+ from project requirements and will be built either in single-threaded or
+ multi-threaded mode depending on which variant is requested by the
+ user.</para>
+
+ <para>Note that the removal of requirements is completely textual:
+ you need to specify exactly the same property to remove it.</para>
+
+ </section>
+
+ <section>
+ <title>Default Build</title>
+
+ <para>The <varname>default-build</varname> parameter
+ is a set of properties to be used if the build request does
+ not otherwise specify a value for features in the set. For example:
+<programlisting>
+exe hello : hello.cpp : : &lt;threading&gt;multi ;
+</programlisting>
+ would build a multi-threaded target unless the user
+ explicitly requests a single-threaded version. The difference between
+ requirements and default-build is that requirements cannot be
+ overridden in any way.
+ </para>
+ </section>
+
+ <section>
+ <title>Additional Information</title>
+
+ <para>
+ The ways a target is built can be so different that
+ describing them using conditional requirements would be
+ hard. For example, imagine that a library actually uses
+ different source files depending on the toolset used to build
+ it. We can express this situation using <firstterm>target
+ alternatives</firstterm>:
+<programlisting>
+lib demangler : dummy_demangler.cpp ; # alternative 1
+lib demangler : demangler_gcc.cpp : &lt;toolset&gt;gcc ; # alternative 2
+lib demangler : demangler_msvc.cpp : &lt;toolset&gt;msvc ; # alternative 3
+</programlisting>
+ In the example above, when built with <literal>gcc</literal>
+ or <literal>msvc</literal>, <filename>demangler</filename>
+ will use a source file specific to the toolset. Otherwise, it
+ will use a generic source file,
+ <filename>dummy_demangler.cpp</filename>.
+ </para>
+
+ <para>It is possible to declare a target inline, i.e. the "sources"
+ parameter may include calls to other main rules. For example:</para>
+
+<programlisting>
+exe hello : hello.cpp
+ [ obj helpers : helpers.cpp : &lt;optimization&gt;off ] ;</programlisting>
+
+ <para>
+ Will cause "helpers.cpp" to be always compiled without
+ optimization. When referring to an inline main target, its declared
+ name must be prefixed by its parent target's name and two dots. In
+ the example above, to build only helpers, one should run
+ <code>bjam hello..helpers</code>.
+ </para>
+
+ <para>When no target is requested on the command line, all targets in the
+ current project will be built. If a target should be built only by
+ explicit request, this can be expressed by the
+ <functionname>explicit</functionname> rule:
+ <programlisting>
+explicit install_programs ;</programlisting>
+ </para>
+
+ </section>
+ </section>
+
+ <section id="bbv2.overview.projects">
+ <title>Projects</title>
+
+ <para>As mentioned before, targets are grouped into projects,
+ and each Jamfile is a separate project. Projects are useful
+ because they allow us to group related targets together, define
+ properties common to all those targets, and assign a symbolic
+ name to the project that can be used in referring to its
+ targets.
+ </para>
+
+ <para>Projects are named using the
+ <functionname>project</functionname> rule, which has the
+ following syntax:
+<programlisting>
+project <replaceable>id</replaceable> : <replaceable>attributes</replaceable> ;
+</programlisting>
+ Here, <replaceable>attributes</replaceable> is a sequence of
+ rule arguments, each of which begins with an attribute-name
+ and is followed by any number of build properties. The list
+ of attribute names along with its handling is also shown in
+ the table below. For example, it is possible to write:
+<programlisting>
+project tennis
+ : requirements &lt;threading&gt;multi
+ : default-build release
+ ;
+</programlisting>
+ </para>
+
+ <para>The possible attributes are listed below.</para>
+
+ <para><emphasis>Project id</emphasis> is a short way to denote a project, as
+ opposed to the Jamfile's pathname. It is a hierarchical path,
+ unrelated to filesystem, such as "boost/thread". <link linkend=
+ "bbv2.reference.ids">Target references</link> make use of project ids to
+ specify a target.</para>
+ <!--
+ This is actually spelled "project-id," isn't it? You
+ have to fix all of these and use a code font. Also below
+ in the table.
+ -->
+
+ <para><emphasis>Source location</emphasis> specifies the directory where sources
+ for the project are located.</para>
+
+ <para><emphasis>Project requirements</emphasis> are requirements that apply to
+ all the targets in the projects as well as all subprojects.</para>
+
+ <para><emphasis>Default build</emphasis> is the build request that should be
+ used when no build request is specified explicitly.</para>
+ <!--
+ This contradicts your earlier description of default
+ build and I believe it is incorrect. Specifying a build
+ request does not neccessarily render default build
+ ineffective, because it may cover different features.
+ This description is repeated too many times in the
+ documentation; you almost *had* to get it wrong once.
+ -->
+
+ <para id="bbv2.overview.projects.attributes.projectrule">
+ The default values for those attributes are
+ given in the table below.
+
+ <table>
+ <title/>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+
+ <entry>Name</entry>
+
+ <entry>Default value</entry>
+
+ <entry>Handling by the <functionname>project</functionname>
+ rule</entry>
+
+ </row>
+ </thead>
+
+ <tbody>
+
+ <row>
+ <entry>Project id</entry>
+
+ <entry>none</entry>
+
+ <entry>none</entry>
+
+ <entry>Assigned from the first parameter of the 'project' rule.
+ It is assumed to denote absolute project id.</entry>
+ </row>
+
+ <row>
+ <entry>Source location</entry>
+
+ <entry><literal>source-location</literal></entry>
+
+ <entry>The location of jamfile for the project</entry>
+
+ <entry>Sets to the passed value</entry>
+ </row>
+
+ <row>
+ <entry>Requirements</entry>
+
+ <entry><literal>requirements</literal></entry>
+
+ <entry>The parent's requirements</entry>
+
+ <entry>The parent's requirements are refined with the passed
+ requirement and the result is used as the project
+ requirements.</entry>
+ </row>
+
+ <row>
+ <entry>Default build</entry>
+
+ <entry><literal>default-build</literal></entry>
+
+ <entry>none</entry>
+
+ <entry>Sets to the passed value</entry>
+ </row>
+
+ <row>
+ <entry>Build directory</entry>
+
+ <entry><literal>build-dir</literal></entry>
+
+ <entry>Empty if the parent has no build directory set.
+ Otherwise, the parent's build directory with the
+ relative path from parent to the current project
+ appended to it.
+ </entry>
+
+ <entry>Sets to the passed value, interpreted as relative to the
+ project's location.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
+
+ <para>Besides defining projects and main targets, Jamfiles
+ often invoke various utility rules. For the full list of rules
+ that can be directly used in Jamfile see
+ <xref linkend="bbv2.reference.rules"/>.
+ </para>
+
+ <para>Each subproject inherits attributes, constants and rules
+ from its parent project, which is defined by the nearest
+ Jamfile in an ancestor directory above
+ the subproject. The top-level project is declared in a file
+ called <filename>Jamroot</filename> rather than
+ <filename>Jamfile</filename>. When loading a project,
+ Boost.Build looks for either <filename>Jamroot</filename> or
+ <code>Jamfile</code>. They are handled identically, except
+ that if the file is called <filename>Jamroot</filename>, the
+ search for a parent project is not performed.
+ </para>
+
+ <para>Even when building in a subproject directory, parent
+ project files are always loaded before those of their
+ subprojects, so that every definition made in a parent project
+ is always available to its children. The loading order of any
+ other projects is unspecified. Even if one project refers to
+ another via the <code>use-project</code> or a target reference,
+ no specific order should be assumed.
+ </para>
+
+ <note>
+ <para>Giving the root project the special name
+ &#x201C;<filename>Jamroot</filename>&#x201D; ensures that
+ Boost.Build won't misinterpret a directory above it as the
+ project root just because the directory contains a Jamfile.
+ <!-- The logic of the previous reasoning didn't hang together -->
+ </para>
+ </note>
+
+ <!-- All this redundancy with the tutorial is bad. The tutorial
+ should just be made into the introductory sections of this
+ document, which should be called the "User Guide." It's
+ perfectly appropriate to start a user guide with that kind
+ of material. -->
+ </section>
+
+ <section id="bbv2.overview.build_process">
+ <title>The Build Process</title>
+
+ <para>When you've described your targets, you want Boost.Build to run the
+ right tools and create the needed targets.
+ <!-- That sentence is awkward and doesn't add much. -->
+ This section will describe
+ two things: how you specify what to build, and how the main targets are
+ actually constructed.
+ </para>
+
+ <para>The most important thing to note is that in Boost.Build, unlike
+ other build tools, the targets you declare do not correspond to specific
+ files. What you declare in a Jamfile is more like a “metatarget.â€
+ <!-- Do we need a new word? We already have “main target.†If
+ you're going to introduce “metatarget†you should at least
+ tie it together with the main target concept. It's too
+ strange to have been saying “main target†all along and now
+ suddenly start saying “what you declare in a jamfile†-->
+ Depending on the properties you specify on the command line,
+ each metatarget will produce a set of real targets corresponding
+ to the requested properties. It is quite possible that the same
+ metatarget is built several times with different properties,
+ producing different files.
+ </para>
+ <tip>
+ <para>
+ This means that for Boost.Build, you cannot directly obtain a build
+ variant from a Jamfile. There could be several variants requested by the
+ user, and each target can be built with different properties.
+ </para>
+ </tip>
+
+ <section id="bbv2.overview.build_request">
+ <title>Build Request</title>
+
+ <para>
+ The command line specifies which targets to build and with which
+ properties. For example:
+<programlisting>
+bjam app1 lib1//lib1 toolset=gcc variant=debug optimization=full
+</programlisting>
+ would build two targets, "app1" and "lib1//lib1" with the specified
+ properties. You can refer to any targets, using
+ <link linkend="bbv2.reference.ids">target id</link> and specify arbitrary
+ properties. Some of the properties are very common, and for them the name
+ of the property can be omitted. For example, the above can be written as:
+<programlisting>
+bjam app1 lib1//lib1 gcc debug optimization=full
+</programlisting>
+ The complete syntax, which has some additional shortcuts, is
+ described in <xref linkend="bbv2.overview.invocation"/>.
+ </para>
+ </section>
+
+ <section><title>Building a main target</title>
+
+ <para>When you request, directly or indirectly, a build of a main target
+ with specific requirements, the following steps are done. Some brief
+ explanation is provided, and more details are given in <xref
+ linkend="bbv2.reference.buildprocess"/>.
+ <orderedlist>
+
+ <listitem><para>Applying default build. If the default-build
+ property of a target specifies a value of a feature that is not
+ present in the build request, that value is added.</para>
+ <!--
+ Added to what? Don't say “the build request!†The
+ request is what was requested; if its meaning changes
+ the reader will be confused.
+ -->
+ </listitem>
+
+ <listitem><para>Selecting the main target alternative to use. For
+ each alternative we look how many properties are present both in
+ alternative's requirements, and in build request. The
+ alternative with large number of matching properties is selected.
+ </para></listitem>
+
+ <listitem><para>Determining "common" properties.
+ <!-- It would be nice to have a better name for this. But
+ even more importantly, unless you say something about
+ the reason for choosing whatever term you use, the
+ reader is going to wonder what it means. -->
+ The build request
+ is <link linkend="bbv2.reference.variants.proprefine">refined</link>
+ with target's requirements.
+ <!-- It's good that you have the links here and below,
+ but I'm concerned that it doesn't communicate well
+ in print and there's not enough information for the
+ print reader. Maybe we need separate XSL for PDF
+ printing that generates a readable footnote. -->
+ The conditional properties in
+ requirements are handled as well. Finally, default values of
+ features are added.
+ </para></listitem>
+
+ <listitem><para>Building targets referred by the sources list and
+ dependency properties. The list of sources and the properties
+ can refer to other target using <link
+ linkend="bbv2.reference.ids">target references</link>. For each
+ reference, we take all <link
+ linkend="bbv2.reference.features.attributes.propagated">propagated</link>
+ properties, refine them by explicit properties specified in the
+ target reference, and pass the resulting properties as build
+ request to the other target.
+ </para></listitem>
+
+ <listitem><para>Adding the usage requirements produced when building
+ dependencies to the "common" properties. When dependencies are
+ built in the previous step, they return
+ <!-- don't assume reader has a mental model for BB internals! -->
+ both the set of created
+ "real" targets, and usage requirements. The usage requirements
+ are added to the common properties and the resulting property
+ set will be used for building the current target.
+ </para></listitem>
+
+ <listitem><para>Building the target using generators. To convert the
+ sources to the desired type, Boost.Build uses "generators" ---
+ objects that correspond to tools like compilers and linkers. Each
+ generator declares what type of targets it can produce and what
+ type of sources it requires. Using this information, Boost.Build
+ determines which generators must be run to produce a specific
+ target from specific sources. When generators are run, they return
+ the "real" targets.
+ </para></listitem>
+
+ <listitem><para>Computing the usage requirements to be returned. The
+ conditional properties in usage requirements are expanded
+ <!-- what does "expanded" mean? -->
+ and the result is returned.</para></listitem>
+ </orderedlist>
+ </para>
+ </section>
+
+ <section><title>Building a Project</title>
+
+ <para>Often, a user builds a complete project, not just one main
+ target. In fact, invoking <command>bjam</command> without
+ arguments
+ <!-- do you know the difference between parameters and
+ arguments? I only learned this year -->
+ builds the project defined in the current
+ directory.</para>
+
+ <para>When a project is built, the build request is passed without
+ modification to all main targets in that project.
+ <!-- What does it mean to pass a build request to a target?
+ -->
+ It's is possible to
+ prevent implicit building of a target in a project with the
+ <code>explicit</code> rule:
+<programlisting>
+explicit hello_test ;
+</programlisting>
+ would cause the <code>hello_test</code> target to be built only if
+ explicitly requested by the user or by some other target.
+ </para>
+
+ <para>The Jamfile for a project can include a number of
+ <code>build-project</code> rule calls that specify additional projects to
+ be built.
+ </para>
+
+ </section>
+
+ </section>
+
+ </chapter>
+
+<!--
+ Local Variables:
+ mode: nxml
+ sgml-indent-data: t
+ sgml-parent-document: ("userman.xml" "chapter")
+ sgml-set-face: t
+ End:
+-->
diff --git a/tools/build/v2/doc/src/recipes.xml b/tools/build/v2/doc/src/recipes.xml
new file mode 100644
index 0000000000..7230aabdf7
--- /dev/null
+++ b/tools/build/v2/doc/src/recipes.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE appendix PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <!-- The file is empty. It's not clear if it will be needed in
+ future or FAQ completely supercedes it. -->
+
+ <appendix id="bbv2.recipies">
+ <title>Boost Build System V2 recipes</title>
+
+ </appendix>
diff --git a/tools/build/v2/doc/src/reference.xml b/tools/build/v2/doc/src/reference.xml
new file mode 100644
index 0000000000..80775aaceb
--- /dev/null
+++ b/tools/build/v2/doc/src/reference.xml
@@ -0,0 +1,2325 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"
+[
+<!ENTITY toolset_ops "<optional><replaceable>version</replaceable></optional> : <optional><replaceable>c++-compile-command</replaceable></optional> : <optional><replaceable>compiler options</replaceable></optional>">
+<!ENTITY option_list_intro "<para>The following options can be provided, using <literal>&lt;<replaceable>option-name</replaceable>&gt;<replaceable>option-value</replaceable></literal> syntax:</para>">
+<!ENTITY using_repeation "<para>This statement may be repeated several times, if you want to configure several versions of the compiler.</para>">
+]>
+
+<chapter id="bbv2.reference"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Reference</title>
+
+ <section id="bbv2.reference.general">
+ <title>General information</title>
+
+ <section id="bbv2.reference.init">
+ <title>Initialization</title>
+
+ <para>bjam's first job upon startup is to load the Jam code that
+ implements the build system. To do this, it searches for a file
+ called <filename>boost-build.jam</filename>, first in the invocation directory, then
+ in its parent and so forth up to the filesystem root, and finally
+ in the directories specified by the environment variable
+ BOOST_BUILD_PATH. When found, the file is interpreted, and should
+ specify the build system location by calling the boost-build
+ rule:</para>
+
+<programlisting>
+rule boost-build ( location ? )
+</programlisting>
+
+ <para>
+ If location is a relative path, it is treated as relative to
+ the directory of <filename>boost-build.jam</filename>. The directory specified by
+ that location and the directories in BOOST_BUILD_PATH are then searched for
+ a file called <filename>bootstrap.jam</filename>, which is expected to
+ bootstrap the build system. This arrangement allows the build
+ system to work without any command-line or environment variable
+ settings. For example, if the build system files were located in a
+ directory "build-system/" at your project root, you might place a
+ <filename>boost-build.jam</filename> at the project root containing:
+
+<programlisting>
+boost-build build-system ;
+</programlisting>
+
+ In this case, running bjam anywhere in the project tree will
+ automatically find the build system.</para>
+
+ <para>The default <filename>bootstrap.jam</filename>, after loading some standard
+ definitions, loads two <filename>site-config.jam</filename> and <filename>user-config.jam</filename>.</para>
+
+ </section>
+
+ </section>
+
+ <section id="bbv2.reference.rules">
+ <title>Builtin rules</title>
+
+ <para>This section contains the list of all rules that
+ can be used in Jamfile&#x2014;both rules that define new
+ targets and auxiliary rules.</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>exe</literal></term>
+
+ <listitem><para>Creates an executable file. See
+ <xref linkend="bbv2.tasks.programs"/>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>lib</literal></term>
+
+ <listitem><para>Creates an library file. See
+ <xref linkend="bbv2.tasks.libraries"/>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>install</literal></term>
+
+ <listitem><para>Installs built targets and other files. See
+ <xref linkend="bbv2.tasks.installing"/>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>alias</literal></term>
+
+ <listitem><para>Creates an alias for other targets. See
+ <xref linkend="bbv2.tasks.alias"/>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>unit-test</literal></term>
+
+ <listitem><para>Creates an executable that will be automatically run. See
+ <xref linkend="bbv2.builtins.testing"/>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>compile</literal></term>
+ <term><literal>compile-fail</literal></term>
+ <term><literal>link</literal></term>
+ <term><literal>link-fail</literal></term>
+ <term><literal>run</literal></term>
+ <term><literal>run-fail</literal></term>
+
+ <listitem><para>Specialized rules for testing. See
+ <xref linkend="bbv2.builtins.testing"/>.</para></listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term><literal>obj</literal></term>
+
+ <listitem><para>Creates an object file. Useful when a single source
+ file must be compiled with special properties.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>preprocessed</literal></term>
+ <indexterm><primary>preprocessed</primary></indexterm>
+
+ <listitem><para>Creates an preprocessed source file. The arguments follow the
+ <link linkend="bbv2.main-target-rule-syntax">common syntax</link>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>glob</literal></term>
+
+ <listitem><para>The <code>glob</code> rule takes a list shell pattern
+ and returns the list of files in the project's source directory that
+ match the pattern. For example:
+ <programlisting>
+lib tools : [ glob *.cpp ] ;
+ </programlisting>
+ It is possible to also pass a second argument&#x2014;the list of
+ exclude patterns. The result will then include the list of
+ files patching any of include patterns, and not matching any
+ of the exclude patterns. For example:
+ <programlisting>
+lib tools : [ glob *.cpp : file_to_exclude.cpp bad*.cpp ] ;
+ </programlisting>
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry id="bbv2.reference.glob-tree">
+ <indexterm><primary>glob-tree</primary></indexterm>
+ <term><literal>glob-tree</literal></term>
+
+ <listitem><para>The <code>glob-tree</code> is similar to the
+ <code>glob</code> except that it operates recursively from
+ the directory of the containing Jamfile. For example:
+ <programlisting>
+ECHO [ glob-tree *.cpp : .svn ] ;
+ </programlisting>
+ will print the names of all C++ files in your project. The
+ <literal>.svn</literal> exclude pattern prevents the
+ <code>glob-tree</code> rule from entering administrative
+ directories of the Subversion version control system.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>project</literal></term>
+
+ <listitem><para>Declares project id and attributes, including
+ project requirements. See <xref linkend="bbv2.overview.projects"/>.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>use-project</literal></term>
+
+ <listitem><para>Assigns a symbolic project ID to a project at
+ a given path. This rule must be better documented!
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>explicit</literal></term>
+
+ <listitem><para>The <literal>explicit</literal> rule takes a single
+ parameter&#x2014;a list of target names. The named targets will
+ be marked explicit, and will be built only if they are explicitly
+ requested on the command line, or if their dependents are built.
+ Compare this to ordinary targets, that are built implicitly when
+ their containing project is built.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>always</literal></term>
+ <indexterm><primary>always building a metatarget</primary></indexterm>
+
+ <listitem><para>The <literal>always</literal> funciton takes a single
+ parameter&#x2014;a list of metatarget names. The top-level targets produced
+ by the named metatargets will be always considered out of date. Consider this example:
+ </para>
+<programlisting>
+exe hello : hello.cpp ;
+exe bye : bye.cpp ;
+always hello ;
+</programlisting>
+ <para>If a build of <filename>hello</filename> is requested, then the binary will
+ always be relinked. The object files will not be recompiled, though. Note that if
+ a build of <filename>hello</filename> is not requested, for example you specify just
+ <filename>bye</filename> on the command line, <filename>hello</filename> will not
+ be relinked.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>constant</literal></term>
+
+ <listitem><para>Sets project-wide constant. Takes two
+ parameters: variable name and a value and makes the specified
+ variable name accessible in this Jamfile and any child Jamfiles.
+ For example:
+ <programlisting>
+constant VERSION : 1.34.0 ;
+ </programlisting>
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>path-constant</literal></term>
+
+ <listitem><para>Same as <literal>constant</literal> except that
+ the value is treated as path relative to Jamfile location. For example,
+ if <command>bjam</command> is invoked in the current directory,
+ and Jamfile in <filename>helper</filename> subdirectory has:
+ <programlisting>
+path-constant DATA : data/a.txt ;
+ </programlisting>
+ then the variable <varname>DATA</varname> will be set to
+ <literal>helper/data/a.txt</literal>, and if <command>bjam</command>
+ is invoked from the <filename>helper</filename> directory, then
+ the variable <varname>DATA</varname> will be set to
+ <literal>data/a.txt</literal>.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>build-project</literal></term>
+
+ <listitem><para>Cause some other project to be built. This rule
+ takes a single parameter&#x2014;a directory name relative to
+ the containing Jamfile. When the containing Jamfile is built,
+ the project located at that directory will be built as well.
+ At the moment, the parameter to this rule should be a directory
+ name. Project ID or general target references are not allowed.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>test-suite</literal></term>
+
+ <listitem><para>This rule is deprecated and equivalent to
+ <code>alias</code>.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </section>
+
+ <section id="bbv2.overview.builtins.features">
+ <title>Builtin features</title>
+
+ <para>This section documents the features that are built-in into
+ Boost.Build. For features with a fixed set of values, that set is
+ provided, with the default value listed first.</para>
+
+ <indexterm><primary>features</primary><secondary>builtin</secondary></indexterm>
+
+ <variablelist>
+ <varlistentry><term><literal>variant</literal></term>
+ <indexterm><primary>variant</primary></indexterm>
+
+ <listitem>
+ <para>
+ A feature combining several low-level features, making it easy to
+ request common build configurations.
+ </para>
+
+ <para>
+ <emphasis role="bold">Allowed values:</emphasis>
+ <literal>debug</literal>, <literal>release</literal>,
+ <literal>profile</literal>.
+ </para>
+
+ <para>
+ The value <literal>debug</literal> expands to
+ </para>
+
+<programlisting>
+&lt;optimization&gt;off &lt;debug-symbols&gt;on &lt;inlining&gt;off &lt;runtime-debugging&gt;on
+</programlisting>
+
+ <para>
+ The value <literal>release</literal> expands to
+ </para>
+
+<programlisting>
+&lt;optimization&gt;speed &lt;debug-symbols&gt;off &lt;inlining&gt;full &lt;runtime-debugging&gt;off
+</programlisting>
+
+ <para>
+ The value <literal>profile</literal> expands to the same as
+ <literal>release</literal>, plus:
+ </para>
+
+<programlisting>
+&lt;profiling&gt;on &lt;debug-symbols&gt;on
+</programlisting>
+
+ <para>
+ Users can define their own build variants using the
+ <code>variant</code> rule from the <code>common</code> module.
+ </para>
+
+ <para>
+ <emphasis role="bold">Note:</emphasis> Runtime debugging is on in
+ debug builds to suit the expectations of people used to various
+ IDEs.
+ <!-- Define "runtime debugging". Why will those people expect it to
+ be on in debug builds? -->
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry id="bbv2.overview.builtins.features.link">
+ <term><literal>link</literal></term>
+ <indexterm><primary>link</primary></indexterm>
+
+ <listitem>
+
+ <para><emphasis role="bold">Allowed values:</emphasis> <literal>shared</literal>,
+ <literal>static</literal></para>
+
+ <simpara>
+ A feature controling how libraries are built.
+ </simpara>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry id="bbv2.overview.builtins.features.runtime-link">
+ <indexterm><primary>runtime linking</primary></indexterm>
+ <term><literal>runtime-link</literal></term>
+
+ <listitem>
+ <para><emphasis role="bold">Allowed values:</emphasis> <literal>shared</literal>,
+ <literal>static</literal></para>
+
+ <simpara>
+ Controls if a static or shared C/C++ runtime should be used. There
+ are some restrictions how this feature can be used, for example
+ on some compilers an application using static runtime should
+ not use shared libraries at all, and on some compilers,
+ mixing static and shared runtime requires extreme care. Check
+ your compiler documentation for more details.
+ </simpara>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>threading</literal></term>
+ <indexterm><primary>threading</primary></indexterm>
+
+ <listitem>
+
+ <para><emphasis role="bold">Allowed values:</emphasis> <literal>single</literal>,
+ <literal>multi</literal></para>
+
+ <simpara>
+ Controls if the project should be built in multi-threaded mode. This feature does not
+ necessary change code generation in the compiler, but it causes the compiler to link
+ to additional or different runtime libraries, and define additional preprocessor
+ symbols (for example, <code>_MT</code> on Windows and <code>_REENTRANT</code> on Linux).
+ How those symbols affect the compiled code depends on the code itself.
+ </simpara>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>source</literal></term>
+ <indexterm><primary>source</primary></indexterm>
+
+ <listitem>
+ <simpara>
+ The <code>&lt;source&gt;X</code> feature has the same effect on
+ building a target as putting X in the list of sources. It is useful
+ when you want to add the same source to all targets in the project
+ (you can put &lt;source&gt; in requirements) or to conditionally
+ include a source (using conditional requirements, see <xref linkend=
+ "bbv2.tutorial.conditions"/>). See also the <code>&lt;library&gt;
+ </code> feature.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>library</literal></term>
+ <indexterm><primary>library</primary></indexterm>
+
+ <listitem>
+ <simpara>
+ This feature is almost equivalent to the <code>&lt;source&gt;</code>
+ feature, except that it takes effect only for linking. When you want
+ to link all targets in a Jamfile to certain library, the
+ <code>&lt;library&gt;</code> feature is preferred over
+ <code>&lt;source&gt;X</code> -- the latter will add the library to
+ all targets, even those that have nothing to do with libraries.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><anchor id="bbv2.builtin.features.dependency"/>
+ <literal>dependency</literal></term>
+ <indexterm><primary>dependency</primary></indexterm>
+
+ <listitem>
+ <simpara>
+ Introduces a dependency on the target named by the value of this
+ feature (so it will be brought up-to-date whenever the target being
+ declared is). The dependency is not used in any other way.
+
+ <!--
+ ====================================================================
+ An example and a motivation is needed here. Below is some commented
+ out content that used to be here but did not make any sense and
+ seems to have been left unfinished in some previous revision. Should
+ be fixed and this whole feature should be retested and fixed as
+ needed.
+ ====================================================================
+ For example, in application with plugins, the plugins are not used
+ when linking the application, application might have a dependency on
+ its plugins, even though
+
+ and
+ adds its usage requirements to the build properties
+ of the target being declared.
+
+ The primary use case is when you want
+ the usage requirements (such as <code>#include</code> paths) of some
+ library to be applied, but do not want to link to it.
+
+ It is hard to picture why anyone would want to do that. Please flesh
+ out this motivation.
+ ====================================================================
+ -->
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry><term><anchor id="bbv2.builtin.features.use"/>
+ <literal>use</literal></term>
+ <indexterm><primary>use</primary></indexterm>
+
+ <listitem>
+ <simpara>
+ Introduces a dependency on the target named by the value of this
+ feature (so it will be brought up-to-date whenever the target being
+ declared is), and adds its usage requirements to the build
+ properties
+ <!-- Do you really mean "to the requirements?" -->
+ of the target being declared. The dependency is not used in any
+ other way. The primary use case is when you want the usage
+ requirements (such as <code>#include</code> paths) of some library
+ to be applied, but do not want to link to it.
+ <!-- It is hard to picture why anyone would want to do that. Please
+ flesh out this motivation. -->
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><anchor id="bbv2.reference.features.dll-path"/>
+ <literal>dll-path</literal></term>
+ <indexterm><primary>dll-path</primary></indexterm>
+
+ <listitem>
+ <simpara>
+ Specify an additional directory where the system should
+ look for shared libraries when the executable or shared
+ library is run. This feature only affects Unix
+ compilers. Plase see <xref linkend="bbv2.faq.dll-path"/>
+ in <xref linkend="bbv2.faq"/> for details.
+ </simpara>
+ </listitem></varlistentry>
+
+ <varlistentry>
+ <term><literal>hardcode-dll-paths</literal></term>
+ <indexterm><primary>hardcode-dll-paths</primary></indexterm>
+
+ <listitem>
+ <simpara>
+ Controls automatic generation of dll-path properties.
+ </simpara>
+
+ <para><emphasis role="bold">Allowed values:</emphasis>
+ <literal>true</literal>, <literal>false</literal>. This property is
+ specific to Unix systems. If an executable is built with
+ <code>&lt;hardcode-dll-paths&gt;true</code>, the generated binary
+ will contain the list of all the paths to the used shared libraries.
+ As the result, the executable can be run without changing system
+ paths to shared libraries or installing the libraries to system
+ paths. This <!-- you need an antecedent. This _what_? --> is very
+ convenient during development. Plase see the <link linkend=
+ "bbv2.faq.dll-path">FAQ entry</link> for details. Note that on Mac
+ OSX, the paths are unconditionally hardcoded by the linker, and it
+ is not possible to disable that behaviour.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>cflags</literal></term>
+ <term><literal>cxxflags</literal></term>
+ <term><literal>linkflags</literal></term>
+
+ <listitem>
+ <simpara>
+ The value of those features is passed without modification to the
+ corresponding tools. For <code>cflags</code> that is both the C and
+ C++ compilers, for <code>cxxflags</code> that is the C++ compiler
+ and for <code>linkflags</code> that is the linker. The features are
+ handy when you are trying to do something special that cannot be
+ achieved by a higher-level feature in Boost.Build.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>include</literal></term>
+ <indexterm><primary>include</primary></indexterm>
+
+ <listitem>
+ <simpara>
+ Specifies an additional include path that is to be passed to C and
+ C++ compilers.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>define</literal></term>
+ <indexterm><primary>define</primary></indexterm>
+
+ <listitem>
+ <simpara>
+ Specifies an preprocessor symbol that should be defined on the command
+ line. You may either specify just the symbol, which will be defined
+ without any value, or both the symbol and the value, separated by
+ equal sign.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry><term><literal>warnings</literal></term>
+ <listitem>
+ <simpara>
+ The <code>&lt;warnings&gt;</code> feature controls the warning level
+ of compilers. It has the following values:
+ <itemizedlist>
+ <listitem><para><code>off</code> - disables all warnings.</para></listitem>
+ <listitem><para><code>on</code> - enables default warning level for the tool.</para></listitem>
+ <listitem><para><code>all</code> - enables all warnings.</para></listitem>
+ </itemizedlist>
+ Default value is <code>all</code>.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><literal>warnings-as-errors</literal></term>
+ <listitem>
+ <simpara>
+ The <code>&lt;warnings-as-errors&gt;</code> makes it possible to
+ treat warnings as errors and abort compilation on a warning. The
+ value <code>on</code> enables this behaviour. The default value is
+ <code>off</code>.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><literal>build</literal></term>
+
+ <listitem>
+ <para><emphasis role="bold">Allowed values:</emphasis> <literal>no</literal></para>
+
+ <para>
+ The <code>build</code> feature is used to conditionally disable
+ build of a target. If <code>&lt;build&gt;no</code> is in properties
+ when building a target, build of that target is skipped. Combined
+ with conditional requirements this allows you to skip building some
+ target in configurations where the build is known to fail.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><literal>tag</literal></term>
+
+ <listitem><para>The <literal>tag</literal> feature is used to customize
+ the name of the generated files. The value should have the form:
+<programlisting>@<replaceable>rulename</replaceable></programlisting> where
+ <replaceable>rulename</replaceable> should be a name of a rule with the
+ following signature:
+<programlisting>rule tag ( name : type ? : property-set )</programlisting>
+ The rule will be called for each target with the default name computed
+ by Boost.Build, the type of the target, and property set. The rule can
+ either return a string that must be used as the name of the target, or
+ an empty string, in which case the default name will be used.
+ </para>
+
+ <para>Most typical use of the <literal>tag</literal> feature is to
+ encode build properties, or library version in library target names. You
+ should take care to return non-empty string from the tag rule only for
+ types you care about &#x2014; otherwise, you might end up modifying
+ names of object files, generated header file and other targets for which
+ changing names does not make sense.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><literal>debug-symbols</literal></term>
+
+ <listitem>
+ <para><emphasis role="bold">Allowed values:</emphasis> <literal>on</literal>, <literal>off</literal>.</para>
+
+ <para>The <literal>debug-symbols</literal> feature specifies if
+ produced object files, executables and libraries should include
+ debug information.
+ Typically, the value of this feature is implicitly set by the
+ <literal>variant</literal> feature, but it can be explicitly
+ specified by the user. The most common usage is to build
+ release variant with debugging information.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><literal>target-os</literal></term>
+ <listitem>
+
+ <anchor id="bbv2.reference.features.target-os"/>
+
+ <para>
+ The operating system for which the code is to be generated. The
+ compiler you used should be the compiler for that operating
+ system. This option causes Boost.Build to use naming conventions
+ suitable for that operating system, and adjust build process
+ accordingly. For example, with gcc, it controls if import
+ libraries are produced for shared libraries or not.
+ </para>
+
+ <para>The complete list of possible values for this feature is:
+ aix, bsd, cygwin, darwin, freebsd, hpux, iphone, linux, netbsd,
+ openbsd, osf, qnx, qnxnto, sgi, solaris, unix, unixware, windows.
+ </para>
+
+ <para>See <xref linkend="bbv2.tasks.crosscompile"/> for details of
+ crosscompilation</para>
+
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry><term><literal>architecture</literal></term>
+ <listitem>
+
+ <para>The <literal>architecture</literal> features specifies
+ the general processor familty to generate code for.</para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><literal>instruction-set</literal></term>
+ <indexterm><primary>instruction-set</primary></indexterm>
+ <listitem>
+ <para>
+ <emphasis role="bold">Allowed values:</emphasis> depend on the used
+ toolset.
+ </para>
+
+ <para>The <literal>instruction-set</literal> specifies for which
+ specific instruction set the code should be generated. The
+ code in general might not run on processors with older/different
+ instruction sets.</para>
+
+ <para>While Boost.Build allows a large set of possible values
+ for this features, whether a given value works depends on which
+ compiler you use. Please see
+ <xref linkend="bbv2.reference.tools.compilers"/> for details.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><literal>address-model</literal></term>
+ <indexterm><primary>64-bit compilation</primary></indexterm>
+ <listitem>
+ <para><emphasis role="bold">Allowed values:</emphasis> <literal>32</literal>, <literal>64</literal>.</para>
+
+ <para>The <literal>address-model</literal> specifies if 32-bit or
+ 64-bit code should be generated by the compiler. Whether this feature
+ works depends on the used compiler, its version, how the compiler is
+ configured, and the values of the <literal>architecture</literal>
+ <literal>instruction-set</literal>
+ features. Please see <xref linkend="bbv2.reference.tools.compilers"/>
+ for details.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><literal>c++-template-depth</literal></term>
+ <listitem>
+ <para>
+ <emphasis role="bold">Allowed values:</emphasis> Any positive
+ integer.
+ </para>
+
+ <para>
+ This feature allows configuring a C++ compiler with the maximal
+ template instantiation depth parameter. Specific toolsets may or may
+ not provide support for this feature depending on whether their
+ compilers provide a corresponding command-line option.
+ </para>
+
+ <para>
+ <emphasis role="bold">Note:</emphasis> Due to some internal details
+ in the current Boost Build implementation it is not possible to have
+ features whose valid values are all positive integer. As a
+ workaround a large set of allowed values has been defined for this
+ feature and, if a different one is needed, user can easily add it by
+ calling the feature.extend rule.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><literal>embed-manifest</literal></term>
+ <listitem>
+
+ <indexterm><primary>manifest file</primary><secondary>embedding</secondary></indexterm>
+ <indexterm><primary>embed-manifest</primary></indexterm>
+
+ <para>
+ <emphasis role="bold">Allowed values:</emphasis> on, off.
+ </para>
+
+ <para>This feature is specific to the msvc toolset (see
+ <xref linkend="bbv2.reference.tools.compiler.msvc"/>),
+ and controls whether the manifest files should be embedded inside
+ executables and shared libraries, or placed alongside them. This
+ feature corresponds to the IDE option found in the project settings dialog,
+ under <menuchoice><guimenu>Configuration Properties</guimenu>
+ <guisubmenu>Manifest Tool</guisubmenu>
+ <guisubmenu>Input and Output</guisubmenu>
+ <guimenuitem>Embed manifest</guimenuitem> </menuchoice>.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+
+ </variablelist>
+ </section>
+
+ <section id="bbv2.reference.tools">
+ <title>Builtin tools</title>
+
+ <para>Boost.Build comes with support for a large number of C++ compilers,
+ and other tools. This section documents how to use those tools.</para>
+
+ <para>Before using any tool, you must declare your intention, and possibly
+ specify additional information about the tool's configuration. This is
+ done by calling the <code>using</code> rule, typically in your
+ <filename>user-config.jam</filename>, for example:</para>
+<programlisting>
+using gcc ;
+</programlisting>
+ <para>additional parameters can be passed just like for other rules, for example:</para>
+<programlisting>
+using gcc : 4.0 : g++-4.0 ;
+</programlisting>
+
+
+
+ <para>The options that can be passed to each tool are documented in the
+ subsequent sections.</para>
+
+ <section id="bbv2.reference.tools.compilers">
+
+ <title>C++ Compilers</title>
+
+ <para>This section lists all Boost.Build modules that support C++
+ compilers and documents how each one can be initialized. The name
+ of support module for compiler is also the value for
+ the <code>toolset</code> feature that can be used to explicitly
+ request that compiler. </para>
+
+ <section id="bbv2.reference.tools.compiler.gcc">
+
+ <title>GNU C++</title>
+
+ <para>The <code>gcc</code> module supports the
+ <ulink url="http://gcc.gnu.org">GNU C++ compiler</ulink>
+ on Linux, a number of Unix-like system including SunOS and on Windows
+ (either <ulink url="http://www.cygwin.com">Cygwin</ulink> or
+ <ulink url="http://www.mingw.org">MinGW</ulink>). On Mac OSX, it is recommended
+ to use system gcc, see <xref linkend="bbv2.reference.tools.compiler.darwin"/>.
+ </para>
+
+ <para>The <code>gcc</code> module is initialized using the following
+ syntax:</para>
+ <programlisting>
+using gcc : &toolset_ops; ;</programlisting>
+
+ &using_repeation;
+
+ <!-- FIXME: mention everywhere what is the semantic
+ of version is -->
+
+ <para>
+ If the version is not explicitly specified, it will be
+ automatically detected by running the compiler with the <code>-v</code>
+ option. If the command is not specified, the <command>g++</command>
+ binary will be searched in <envar>PATH</envar>.</para>
+
+ &option_list_intro;
+ <variablelist>
+
+ <xi:include href="fragments.xml" xpointer="xpointer(id('common_options')/*)"
+ parse="xml"/>
+
+ <xi:include href="fragments.xml" xpointer="xpointer(id('root_option')/*)"
+ parse="xml"/>
+
+ <varlistentry>
+ <term><literal>rc</literal></term>
+
+ <listitem>
+ <para>Specifies the resource compiler command
+ that will be used with the version of gcc that is being
+ configured. This setting makes sense only for Windows and only
+ if you plan to use resource files. By
+ default <command>windres</command> will be used.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>rc-type</literal></term>
+
+ <listitem>
+ <para>Specifies the type of resource compiler. The value can
+ be either <code>windres</code> for msvc resource compiler,
+ or <code>rc</code> for borland's resource compiler.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <indexterm><primary>64-bit compilation</primary>
+ <secondary>gcc</secondary></indexterm>
+
+ In order to compile 64-bit applications, you have to specify
+ <code>address-model=64</code>, and the <code>instruction-set</code>
+ feature should refer to a 64 bit processor. Currently, those
+ include <literal>nocona</literal>, <literal>opteron</literal>,
+ <literal>athlon64</literal> and <literal>athlon-fx</literal>.
+
+ </section>
+
+ <section id="bbv2.reference.tools.compiler.darwin">
+
+ <title>Apple Darwin gcc</title>
+
+ <para>The <code>darwin</code> module supports the version of gcc that is
+ modified and provided by Apple. The configuration is essentially identical
+ to that of the gcc module.
+ </para>
+
+ <para>
+ <indexterm><primary>fat binaries</primary></indexterm>
+ The darwin toolset can generate so called "fat"
+ binaries&#x2014;binaries that can run support more than one
+ architecture, or address mode. To build a binary that can run both
+ on Intel and PowerPC processors, specify
+ <code>architecture=combined</code>. To build a binary that can run
+ both in 32-bit and 64-bit modes, specify
+ <code>address-model=32_64</code>. If you specify both of those
+ properties, a "4-way" fat binary will be generated.
+ </para>
+
+ </section>
+
+ <section id="bbv2.reference.tools.compiler.msvc">
+
+ <title>Microsoft Visual C++</title>
+
+ <para>The <code>msvc</code> module supports the
+ <ulink url="http://msdn.microsoft.com/visualc/">Microsoft Visual
+ C++</ulink> command-line tools on Microsoft Windows. The supported
+ products and versions of command line tools are listed below:</para>
+ <itemizedlist>
+ <listitem><para>Visual Studio 2010&#x2014;10.0</para></listitem>
+ <listitem><para>Visual Studio 2008&#x2014;9.0</para></listitem>
+ <listitem><para>Visual Studio 2005&#x2014;8.0</para></listitem>
+ <listitem><para>Visual Studio .NET 2003&#x2014;7.1</para></listitem>
+ <listitem><para>Visual Studio .NET&#x2014;7.0</para></listitem>
+ <listitem><para>Visual Studio 6.0, Service Pack 5&#x2014;6.5</para></listitem>
+ </itemizedlist>
+
+ <para>The <code>msvc</code> module is initialized using the following
+ syntax:</para>
+ <programlisting>
+using msvc : &toolset_ops; ;
+ </programlisting>
+ &using_repeation;
+ <para>If the version is not explicitly specified, the most recent
+ version found in the registry will be used instead. If the special
+ value <code>all</code> is passed as the version, all versions found in
+ the registry will be configured. If a version is specified, but the
+ command is not, the compiler binary will be searched in standard
+ installation paths for that version, followed by <envar>PATH</envar>.
+ </para>
+
+ <para>The compiler command should be specified using forward slashes,
+ and quoted.</para>
+
+ &option_list_intro;
+ <variablelist>
+
+ <xi:include href="fragments.xml" xpointer="xpointer(id('common_options')/*)"
+ parse="xml"/>
+
+ <varlistentry>
+ <term><literal>assembler</literal></term>
+
+ <listitem><para>The command that compiles assembler sources. If
+ not specified, <command>ml</command> will be used. The command
+ will be invoked after the setup script was executed and adjusted
+ the <envar>PATH</envar> variable.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>compiler</literal></term>
+
+ <listitem><para>The command that compiles C and C++ sources. If
+ not specified, <command>cl</command> will be used. The command
+ will be invoked after the setup script was executed and adjusted
+ the <envar>PATH</envar> variable.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>compiler-filter</literal></term>
+
+ <listitem><para>Command through which to pipe the output of
+ running the compiler. For example to pass the output to STLfilt.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>idl-compiler</literal></term>
+
+ <listitem><para>The command that compiles Microsoft COM interface
+ definition files. If not specified, <command>midl</command> will
+ be used. The command will be invoked after the setup script was
+ executed and adjusted the <envar>PATH</envar> variable.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>linker</literal></term>
+
+ <listitem><para>The command that links executables and dynamic
+ libraries. If not specified, <command>link</command> will be used.
+ The command will be invoked after the setup script was executed
+ and adjusted the <envar>PATH</envar> variable.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>mc-compiler</literal></term>
+
+ <listitem><para>The command that compiles Microsoft message
+ catalog files. If not specified, <command>mc</command> will be
+ used. The command will be invoked after the setup script was
+ executed and adjusted the <envar>PATH</envar> variable.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>resource-compiler</literal></term>
+
+ <listitem><para>The command that compiles resource files. If not
+ specified, <command>rc</command> will be used. The command will be
+ invoked after the setup script was executed and adjusted the
+ <envar>PATH</envar> variable.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>setup</literal></term>
+
+ <listitem><para>The filename of the global environment setup
+ script to run before invoking any of the tools defined in this
+ toolset. Will not be used in case a target platform specific
+ script has been explicitly specified for the current target
+ platform. Used setup script will be passed the target platform
+ identifier (x86, x86_amd64, x86_ia64, amd64 or ia64) as a
+ arameter. If not specified a default script is chosen based on the
+ used compiler binary, e.g. <command>vcvars32.bat</command> or
+ <command>vsvars32.bat</command>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>setup-amd64</literal></term>
+ <term><literal>setup-i386</literal></term>
+ <term><literal>setup-ia64</literal></term>
+
+ <listitem><para>The filename of the target platform specific
+ environment setup script to run before invoking any of the tools
+ defined in this toolset. If not specified the global environment
+ setup script is used.</para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <section id="v2.reference.tools.compiler.msvc.64">
+ <title>64-bit support</title>
+
+ <indexterm><primary>64-bit compilation</primary>
+ <secondary>Microsoft Visual Studio</secondary></indexterm>
+
+ <para>Starting with version 8.0, Microsoft Visual Studio can
+ generate binaries for 64-bit processor, both 64-bit flavours of x86
+ (codenamed AMD64/EM64T), and Itanium (codenamed IA64). In addition,
+ compilers that are itself run in 64-bit mode, for better
+ performance, are provided. The complete list of compiler
+ configurations are as follows (we abbreviate AMD64/EM64T to just
+ AMD64):</para>
+
+ <itemizedlist>
+ <listitem><para>32-bit x86 host, 32-bit x86 target</para>
+ </listitem>
+ <listitem><para>32-bit x86 host, 64-bit AMD64 target</para>
+ </listitem>
+ <listitem><para>32-bit x86 host, 64-bit IA64 target</para>
+ </listitem>
+ <listitem><para>64-bit AMD64 host, 64-bit AMD64 target</para>
+ </listitem>
+ <listitem><para>64-bit IA64 host, 64-bit IA64 target</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The 32-bit host compilers can be always used, even on 64-bit
+ Windows. On the contrary, 64-bit host compilers require both 64-bit
+ host processor and 64-bit Windows, but can be faster. By default,
+ only 32-bit host, 32-bit target compiler is installed, and
+ additional compilers need to be installed explicitly.
+ </para>
+
+ <para>To use 64-bit compilation you should:</para>
+ <orderedlist>
+ <listitem><para>Configure you compiler as usual. If you provide a
+ path to the compiler explicitly, provide the path to the 32-bit
+ compiler. If you try to specify the path to any of 64-bit
+ compilers, configuration will not work.</para></listitem>
+
+ <listitem><para>When compiling, use <code>address-model=64</code>,
+ to generate AMD64 code.</para></listitem>
+
+ <listitem><para>To generate IA64 code, use
+ <code>architecture=ia64</code></para></listitem>
+ </orderedlist>
+
+ <para>The (AMD64 host, AMD64 target) compiler will be used
+ automatically when you are generating AMD64 code and are running
+ 64-bit Windows on AMD64. The (IA64 host, IA64 target) compiler will
+ never be used, since nobody has an IA64 machine to test.</para>
+
+ <para>It is believed that AMD64 and EM64T targets are essentially
+ compatible. The compiler options <code>/favor:AMD64</code> and
+ <code>/favor:EM64T</code>, which are accepted only by AMD64
+ targeting compilers, cause the generated code to be tuned to a
+ specific flavor of 64-bit x86. Boost.Build will make use of those
+ options depending on the value of the<code>instruction-set</code>
+ feature.</para>
+ </section>
+ </section>
+
+ <section id="bbv2.reference.tools.compiler.intel">
+
+ <title>Intel C++</title>
+
+ <para>The <code>intel-linux</code> and <code>intel-win</code> modules
+ support the Intel C++ command-line compiler&#x2014;the <ulink url=
+ "http://www.intel.com/software/products/compilers/clin/index.htm">Linux</ulink>
+ and <ulink url=
+ "http://www.intel.com/cd/software/products/asmo-na/eng/compilers/284527.htm">
+ Windows</ulink> versions respectively.</para>
+
+ <para>The module is initialized using the following syntax:</para>
+ <programlisting>
+using intel-linux : &toolset_ops; ;</programlisting>
+ <para>or</para>
+ <programlisting>
+using intel-win : &toolset_ops; ;</programlisting>
+ <para>respectively.</para>
+
+ &using_repeation;
+
+ <para>
+ If compiler command is not specified, then Boost.Build will
+ look in <envar>PATH</envar> for an executable <command>icpc</command>
+ (on Linux), or <command>icc.exe</command> (on Windows).
+ </para>
+
+ &option_list_intro;
+ <variablelist>
+
+ <xi:include href="fragments.xml" xpointer="xpointer(id('common_options')/*)"
+ parse="xml"/>
+
+ </variablelist>
+
+ <para>The Linux version supports the following additional options:</para>
+ <variablelist>
+
+ <xi:include href="fragments.xml" xpointer="xpointer(id('root_option')/*)"
+ parse="xml"/>
+
+ </variablelist>
+
+ <!-- the compatibility option appears to be messed up -->
+
+ </section>
+
+ <section id="bbv2.reference.tools.compiler.acc">
+
+ <title>HP aC++ compiler</title>
+
+ <para>The <code>acc</code> module supports the
+<ulink url="http://h21007.www2.hp.com/dspp/tech/tech_TechSoftwareDetailPage_IDX/1,1703,1740,00.html">HP aC++ compiler</ulink>
+ for the HP-UX operating system.</para>
+
+ <para>The module is initialized using the following
+ syntax:</para>
+ <programlisting>
+using acc : &toolset_ops; ;</programlisting>
+
+ &using_repeation;
+
+
+ <para>
+ If the command is not specified, the <command>aCC</command>
+ binary will be searched in <envar>PATH</envar>.</para>
+
+ &option_list_intro;
+ <variablelist>
+ <xi:include href="fragments.xml" xpointer="xpointer(id('common_options')/*)"
+ parse="xml"/>
+ </variablelist>
+
+ </section>
+
+ <section id="bbv2.reference.tools.compiler.borland">
+
+ <title>Borland C++ Compiler</title>
+
+ <para>The <code>borland</code> module supports the command line
+ C++ compiler included in
+ <ulink url="http://www.borland.com/us/products/cbuilder/index.html">C++ Builder 2006</ulink>
+ product and earlier version of it, running on Microsoft Windows.</para>
+
+ <para>The supported products are listed below. The version reported
+ by the command lines tools is also listed for reference.:</para>
+ <itemizedlist>
+ <listitem><para>C++ Builder 2006&#x2014;5.8.2</para></listitem>
+ <listitem><para>CBuilderX&#x2014;5.6.5, 5.6.4 (depending on release)</para></listitem>
+ <listitem><para>CBuilder6&#x2014;5.6.4</para></listitem>
+ <listitem><para>Free command line tools&#x2014;5.5.1</para></listitem>
+ </itemizedlist>
+
+ <para>The module is initialized using the following syntax:</para>
+ <programlisting>
+using borland : &toolset_ops; ;</programlisting>
+
+ &using_repeation;
+
+ <para>If the command is not specified, Boost.Build will search for
+ a binary named <command>bcc32</command> in <envar>PATH</envar>.</para>
+
+ &option_list_intro;
+ <variablelist>
+ <xi:include href="fragments.xml" xpointer="xpointer(id('common_options')/*)"
+ parse="xml"/>
+ </variablelist>
+
+ </section>
+
+ <section id="bbv2.reference.tools.compiler.como">
+
+ <title>Comeau C/C++ Compiler</title>
+
+ <para>The <code>como-linux</code> and the <code>como-win</code>
+ modules supports the
+ <ulink url="http://www.comeaucomputing.com/">Comeau C/C++ Compiler</ulink>
+ on Linux and Windows respectively.</para>
+
+ <para>The module is initialized using the following syntax:</para>
+ <programlisting>
+using como-linux : &toolset_ops; ;</programlisting>
+
+ &using_repeation;
+
+ <para>If the command is not specified, Boost.Build will search for
+ a binary named <command>como</command> in
+ <envar>PATH</envar>.</para>
+
+ &option_list_intro;
+ <variablelist>
+ <xi:include href="fragments.xml" xpointer="xpointer(id('common_options')/*)"
+ parse="xml"/>
+ </variablelist>
+
+ <para>Before using the Windows version of the compiler, you need to
+ setup necessary environment variables per compiler's documentation. In
+ particular, the <envar>COMO_XXX_INCLUDE</envar> variable should be
+ set, where <envar>XXX</envar> corresponds to the used backend C
+ compiler.</para>
+ </section>
+
+ <section id="bbv2.reference.tools.compiler.cw">
+
+ <title>Code Warrior</title>
+
+ <para>The <code>cw</code> module support CodeWarrior compiler,
+ originally produced by Metrowerks and presently developed by
+ Freescale. Boost.Build supports only the versions of the compiler that
+ target x86 processors. All such versions were released by Metrowerks
+ before aquisition and are not sold any longer. The last version known
+ to work is 9.4.</para>
+
+ <para>The module is initialized using the following syntax:</para>
+ <programlisting>
+using cw : &toolset_ops; ;</programlisting>
+
+ &using_repeation;
+
+ <para>If the command is not specified, Boost.Build will search for a
+ binary named <command>mwcc</command> in default installation paths and
+ in <envar>PATH</envar>.</para>
+
+ &option_list_intro;
+ <variablelist>
+
+ <xi:include href="fragments.xml" xpointer="xpointer(id('common_options')/*)"
+ parse="xml"/>
+
+ <xi:include href="fragments.xml" xpointer="xpointer(id('root_option')/*)"
+ parse="xml"/>
+
+ <varlistentry>
+ <term><literal>setup</literal></term>
+
+ <listitem><para>The command that sets up environment variables
+ prior to invoking the compiler. If not specified,
+ <command>cwenv.bat</command> alongside the compiler binary
+ will be used.</para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term><literal>compiler</literal></term>
+
+ <listitem><para>The command that compiles C and C++ sources.
+ If not specified, <command>mwcc</command> will be used. The
+ command will be invoked after the setup script was
+ executed and adjusted the <envar>PATH</envar> variable.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>linker</literal></term>
+
+ <listitem><para>The command that links executables and dynamic
+ libraries.
+ If not specified, <command>mwld</command> will be used. The
+ command will be invoked after the setup script was
+ executed and adjusted the <envar>PATH</envar> variable.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </section>
+
+ <section id="bbv2.reference.tools.compiler.dmc">
+
+ <title>Digital Mars C/C++ Compiler</title>
+
+ <para>The <code>dmc</code> module supports the
+ <ulink url="http://www.digitalmars.com/">Digital Mars C++ compiler.</ulink>
+ </para>
+
+ <para>The module is initialized using the following syntax:</para>
+ <programlisting>
+using dmc : &toolset_ops; ;</programlisting>
+
+ &using_repeation;
+
+ <para>If the command is not specified, Boost.Build will search for
+ a binary named <command>dmc</command> in
+ <envar>PATH</envar>.</para>
+
+ &option_list_intro;
+ <variablelist>
+ <xi:include href="fragments.xml" xpointer="xpointer(id('common_options')/*)"
+ parse="xml"/>
+ </variablelist>
+
+ </section>
+
+ <section id="bbv2.reference.tools.compiler.hp_cxx">
+
+ <title>HP C++ Compiler for Tru64 Unix</title>
+
+ <para>The <code>hp_cxx</code> modules supports the
+ <ulink url="http://h30097.www3.hp.com/cplus/?jumpid=reg_R1002_USEN">
+ HP C++ Compiler</ulink> for Tru64 Unix.</para>
+
+ <para>The module is initialized using the following syntax:</para>
+ <programlisting>
+using hp_cxx : &toolset_ops; ;</programlisting>
+
+ &using_repeation;
+
+ <para>If the command is not specified, Boost.Build will search for
+ a binary named <command>hp_cxx</command> in <envar>PATH</envar>.</para>
+
+ &option_list_intro;
+ <variablelist>
+ <xi:include href="fragments.xml" xpointer="xpointer(id('common_options')/*)"
+ parse="xml"/>
+ </variablelist>
+
+ </section>
+
+ <section id="bbv2.reference.tools.compiler.sun">
+
+ <title>Sun Studio</title>
+
+ <para>The <code>sun</code> module supports the
+ <ulink url="http://developers.sun.com/sunstudio/index.jsp">
+ Sun Studio</ulink> C++ compilers for the Solaris OS.</para>
+
+ <para>The module is initialized using the following syntax:</para>
+ <programlisting>
+using sun : &toolset_ops; ;</programlisting>
+
+ &using_repeation;
+
+ <para>If the command is not specified, Boost.Build will search for
+ a binary named <command>CC</command>
+ in <filename>/opt/SUNWspro/bin</filename> and in
+ <envar>PATH</envar>.</para>
+
+ <para>When using this compiler on complex C++ code, such as the
+ <ulink url="http://boost.org">Boost C++ library</ulink>, it is
+ recommended to specify the following options when intializing the
+ <code>sun</code> module:
+ <screen>
+-library=stlport4 -features=tmplife -features=tmplrefstatic
+ </screen> See the <ulink url="http://blogs.sun.com/sga/entry/command_line_options">
+ Sun C++ Frontend Tales</ulink> for details.</para>
+
+ &option_list_intro;
+ <variablelist>
+ <xi:include href="fragments.xml" xpointer="xpointer(id('common_options')/*)"
+ parse="xml"/>
+ </variablelist>
+
+ <indexterm><primary>64-bit compilation</primary>
+ <secondary>Sun Studio</secondary></indexterm>
+ Starting with Sun Studio 12, you can create 64-bit applications
+ by using the <code>address-model=64</code> property.
+
+ </section>
+
+ <section id="bbv2.reference.tools.compiler.vacpp">
+
+ <title>IBM Visual Age</title>
+ <para>The <code>vacpp</code> module supports the
+ <ulink url="http://www.ibm.com/software/ad/vacpp">IBM Visual
+ Age</ulink> C++ Compiler, for the AIX operating system. Versions
+ 7.1 and 8.0 are known to work.</para>
+
+ <para>The module is initialized using the following
+ syntax:</para>
+ <programlisting>
+using vacpp ;</programlisting>
+
+ <para>The module does not accept any initialization options. The
+ compiler should be installed in the <filename>/usr/vacpp/bin</filename>
+ directory.</para>
+
+ <para>Later versions of Visual Age are known as XL C/C++. They
+ were not tested with the the <code>vacpp</code> module.</para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Third-party libraries</title>
+
+ <para>Boost.Build provides special support for some
+ third-party C++ libraries, documented below.</para>
+
+ <section id="bbv2.reference.tools.libraries.stlport">
+ <title>STLport library</title>
+ <indexterm><primary>STLport</primary></indexterm>
+
+ <para>The <ulink url="http://stlport.org">STLport</ulink> library
+ is an alternative implementation of C++ runtime library. Boost.Build
+ supports using that library on Windows platfrom. Linux is
+ hampered by different naming of libraries in each STLport
+ version and is not officially supported.</para>
+
+ <para>Before using STLport, you need to configure it in
+ <filename>user-config.jam</filename> using the following syntax:
+ </para>
+ <programlisting>
+using stlport : <optional><replaceable>version</replaceable></optional> : <replaceable>header-path</replaceable> : <optional><replaceable>library-path</replaceable></optional> ;
+</programlisting>
+ <para>
+ Where <replaceable>version</replaceable> is the version of
+ STLport, for example <literal>5.1.4</literal>,
+ <replaceable>headers</replaceable> is the location where
+ STLport headers can be found, and <replaceable>libraries</replaceable>
+ is the location where STLport libraries can be found.
+ The version should always be provided, and the library path should
+ be provided if you're using STLport's implementation of
+ iostreams. Note that STLport 5.* always uses its own iostream
+ implementation, so the library path is required.
+ </para>
+
+ <para>When STLport is configured, you can build with STLport by
+ requesting <literal>stdlib=stlport</literal> on the command line.
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Documentation tools</title>
+
+ <para>Boost.Build support for the Boost documentation tools is
+ documented below.
+ </para>
+
+ <section id="bbv2.reference.tools.doc.xsltproc">
+ <title>xsltproc</title>
+ <indexterm><primary>xsltproc</primary></indexterm>
+
+ <para>To use xsltproc, you first need to configure it using the following syntax:</para>
+ <programlisting>
+using xsltproc : <optional><replaceable>xsltproc</replaceable></optional> ;
+</programlisting>
+ <para>
+ Where <replaceable>xsltproc</replaceable> is the xsltproc executable.
+ If <replaceable>xsltproc</replaceable> is not specified, and the
+ variable XSLTPROC is set, the value of XSLTPROC will be used.
+ Otherwise, xsltproc will be searched for in PATH.
+ </para>
+
+
+ &option_list_intro;
+ <variablelist>
+
+ <varlistentry>
+ <indexterm><primary>xsl:param</primary></indexterm>
+ <term><literal>xsl:param</literal></term>
+ <listitem>
+ <para>Values should have the form
+ <replaceable>name</replaceable>=<replaceable>value</replaceable></para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <indexterm><primary>xsl:path</primary></indexterm>
+ <term><literal>xsl:path</literal></term>
+ <listitem>
+ <para>Sets an additional search path for xi:include elements.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <indexterm><primary>catalog</primary></indexterm>
+ <term><literal>catalog</literal></term>
+ <listitem>
+ <para>A catalog file used to rewrite remote URL's to a local copy.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>The xsltproc module provides the following rules. Note that
+ these operate on jam targets and are intended to be used by another
+ toolset, such as boostbook, rather than directly by users.
+ </para>
+ <variablelist>
+
+ <varlistentry>
+ <indexterm><primary>xslt</primary></indexterm>
+ <term><literal>xslt</literal></term>
+ <listitem>
+ <programlisting>
+rule xslt ( target : source stylesheet : properties * )
+</programlisting>
+ <para>Runs xsltproc to create a single output file.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <indexterm><primary>xslt-dir</primary></indexterm>
+ <term><literal>xslt-dir</literal></term>
+ <listitem>
+ <programlisting>
+rule xslt-dir ( target : source stylesheet : properties * : dirname )
+</programlisting>
+ <para>Runs xsltproc to create multiple outputs in a directory.
+ <literal>dirname</literal> is unused, but exists for
+ historical reasons. The output directory is determined from the
+ target.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </section>
+
+ <section id="bbv2.reference.tools.doc.boostbook">
+ <title>boostbook</title>
+ <indexterm><primary>boostbook</primary><secondary>module</secondary></indexterm>
+
+ <para>To use boostbook, you first need to configure it using the following syntax:</para>
+ <programlisting>
+using boostbook : <optional><replaceable>docbook-xsl-dir</replaceable></optional> : <optional><replaceable>docbook-dtd-dir</replaceable></optional> : <optional><replaceable>boostbook-dir</replaceable></optional> ;
+</programlisting>
+ <para>
+ <replaceable>docbook-xsl-dir</replaceable> is the DocBook XSL stylesheet
+ directory. If not provided, we use DOCBOOK_XSL_DIR from the environment
+ (if available) or look in standard locations. Otherwise, we let the
+ XML processor load the stylesheets remotely.
+ </para>
+
+ <para>
+ <replaceable>docbook-dtd-dir</replaceable> is the DocBook DTD directory.
+ If not provided, we use DOCBOOK_DTD_DIR From the environment (if
+ available) or look in standard locations. Otherwise, we let the XML
+ processor load the DTD remotely.
+ </para>
+
+ <para>
+ <replaceable>boostbook-dir</replaceable> is the BoostBook directory
+ with the DTD and XSL subdirs.
+ </para>
+
+ <para>The boostbook module depends on xsltproc. For pdf or ps output,
+ it also depends on fop.
+ </para>
+
+ &option_list_intro;
+ <variablelist>
+
+ <varlistentry>
+ <indexterm><primary>format</primary></indexterm>
+ <indexterm><primary>html</primary></indexterm>
+ <indexterm><primary>xhtml</primary></indexterm>
+ <indexterm><primary>htmlhelp</primary></indexterm>
+ <indexterm><primary>onehtml</primary></indexterm>
+ <indexterm><primary>man</primary></indexterm>
+ <indexterm><primary>pdf</primary></indexterm>
+ <indexterm><primary>ps</primary></indexterm>
+ <indexterm><primary>docbook</primary></indexterm>
+ <indexterm><primary>fo</primary></indexterm>
+ <indexterm><primary>tests</primary></indexterm>
+ <term><literal>format</literal></term>
+ <listitem>
+ <para>
+ <emphasis role="bold">Allowed values:</emphasis>
+ <literal>html</literal>, <literal>xhtml</literal>,
+ <literal>htmlhelp</literal>, <literal>onehtml</literal>,
+ <literal>man</literal>, <literal>pdf</literal>,
+ <literal>ps</literal>, <literal>docbook</literal>,
+ <literal>fo</literal>, <literal>tests</literal>.
+ </para>
+
+
+ <para>The <literal>format</literal> feature determines the type
+ of output produced by the boostbook rule.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>The boostbook module defines a rule for creating a target
+ following the common syntax.</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <indexterm><primary>boostbook</primary><secondary>rule</secondary></indexterm>
+ <term><literal>boostbook</literal></term>
+ <listitem>
+ <programlisting>
+rule boostbook ( target-name : sources * : requirements * : default-build * )
+</programlisting>
+ <para>Creates a boostbook target.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </section>
+
+ <section id="bbv2.reference.tools.doc.doxygen">
+ <title>doxygen</title>
+ <indexterm><primary>doxygen</primary></indexterm>
+
+ <para>To use doxygen, you first need to configure it using the following syntax:</para>
+ <programlisting>
+using doxygen : <optional><replaceable>name</replaceable></optional> ;
+</programlisting>
+ <para>
+ <replaceable>name</replaceable> is the doxygen command.
+ If it is not specified, it will be found in the PATH.
+ </para>
+
+ <para>The doxygen module depends on the boostbook module when
+ generating BoostBook XML.
+ </para>
+
+ &option_list_intro;
+ <variablelist>
+
+ <varlistentry>
+ <indexterm><primary>doxygen:param</primary></indexterm>
+ <term><literal>doxygen:param</literal></term>
+ <listitem>
+ <para>All the values of <literal>doxygen:param</literal>
+ are added to the doxyfile.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <indexterm><primary>prefix</primary></indexterm>
+ <term><literal>prefix</literal></term>
+ <listitem>
+ <para>Specifies the common prefix of all headers
+ when generating BoostBook XML. Everything before
+ this will be stripped off.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <indexterm><primary>reftitle</primary></indexterm>
+ <term><literal>reftitle</literal></term>
+ <listitem>
+ <para>Specifies the title of the library-reference section,
+ when generating BoostBook XML.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <indexterm><primary>doxygen:xml-imagedir</primary></indexterm>
+ <term><literal>doxygen:xml-imagedir</literal></term>
+ <listitem>
+ <para>When generating BoostBook XML, specifies the
+ directory in which to place the images generated
+ from LaTex formulae.</para>
+ <warning><para>The path is interpreted relative to the
+ current working directory, not relative to the Jamfile.
+ This is necessary to match the behavior of BoostBook.
+ </para></warning>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>The doxygen module defines a rule for creating a target
+ following the common syntax.</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <indexterm><primary>doxygen</primary><secondary>rule</secondary></indexterm>
+ <term><literal>doxygen</literal></term>
+ <listitem>
+ <programlisting>
+rule doxygen ( target : sources * : requirements * : default-build * : usage-requirements * )
+</programlisting>
+ <para>Creates a doxygen target. If the target name
+ ends with .html, then this will generate an html
+ directory. Otherwise it will generate BoostBook XML.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </section>
+
+ <section id="bbv2.reference.tools.doc.quickbook">
+ <title>quickbook</title>
+ <indexterm><primary>quickbook</primary></indexterm>
+
+ <para>The quickbook module provides a generator to convert from
+ Quickbook to BoostBook XML.</para>
+
+ <para>To use quickbook, you first need to configure it using the following syntax:</para>
+ <programlisting>
+using quickbook : <optional><replaceable>command</replaceable></optional> ;
+</programlisting>
+ <para>
+ <replaceable>command</replaceable> is the quickbook executable.
+ If it is not specified, Boost.Build will compile it from source.
+ If it is unable to find the source it will search for a quickbook
+ executable in PATH.
+ </para>
+
+ </section>
+
+ <section id="bbv2.reference.tools.doc.fop">
+ <title>fop</title>
+ <indexterm><primary>fop</primary></indexterm>
+
+ <para>The fop module provides generators to convert from
+ XSL formatting objects to Postscript and PDF.</para>
+
+ <para>To use fop, you first need to configure it using the following syntax:</para>
+ <programlisting>
+using fop : <optional><replaceable>fop-command</replaceable></optional> : <optional><replaceable>java-home</replaceable></optional> : <optional><replaceable>java</replaceable></optional> ;
+</programlisting>
+ <para>
+ <replaceable>fop-command</replaceable> is the command to run fop.
+ If it is not specified, Boost.Build will search for it in PATH and
+ FOP_HOME.
+ </para>
+ <para>
+ Either <replaceable>java-home</replaceable> or
+ <replaceable>java</replaceable>
+ can be used to specify where to find java.
+ </para>
+
+ </section>
+
+ </section>
+
+ </section>
+
+ <section id="bbv2.reference.buildprocess">
+ <title>Build process</title>
+
+ <para>The general overview of the build process was given in the
+ <link linkend="bbv2.overview.build_process">user documentation</link>.
+ This section provides additional details, and some specific rules.
+ </para>
+
+ <para>To recap, building a target with specific properties includes the
+ following steps:
+ <orderedlist>
+
+ <listitem><para>applying default build,</para></listitem>
+
+ <listitem><para>selecting the main target alternative to use,
+ </para></listitem>
+
+ <listitem><para>determining "common" properties,</para></listitem>
+
+ <listitem><para>building targets referred by the sources list and
+ dependency properties,</para></listitem>
+
+ <listitem><para>adding the usage requirements produces when building
+ dependencies to the "common" properties,</para></listitem>
+
+ <listitem><para>building the target using generators,</para></listitem>
+
+ <listitem><para>computing the usage requirements to be returned.</para></listitem>
+
+ </orderedlist>
+ </para>
+
+ <section id="bbv2.reference.buildprocess.alternatives">
+ <title>Alternative selection</title>
+
+ <para>When there are several alternatives, one of them must be
+ selected. The process is as follows:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ For each alternative <emphasis>condition</emphasis> is defined as
+ the set of base properties in requirements. [Note: it might be
+ better to specify the condition explicitly, as in conditional
+ requirements].
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ An alternative is viable only if all properties in condition
+ are present in build request.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there's one viable alternative, it's choosen. Otherwise,
+ an attempt is made to find one best alternative. An alternative
+ a is better than another alternative b, iff the set of properties
+ in b's condition is a strict subset of the set of properities of
+ 'a's condition. If there's one viable alternative, which is
+ better than all others, it's selected. Otherwise, an error is
+ reported.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ </section>
+
+ <section id="bbv2.reference.buildprocess.common">
+ <title>Determining common properties</title>
+
+ <para>The "common" properties is a somewhat artificial term. Those are
+ the intermediate property set from which both the build request for
+ dependencies and properties for building the target are derived.
+ </para>
+
+ <para>Since default build and alternatives are already handled, we have
+ only two inputs: build requests and requirements. Here are the rules
+ about common properties.
+ </para>
+
+ <orderedlist>
+ <listitem><para>Non-free feature can have only one
+ value</para></listitem>
+
+ <listitem><para>A non-conditional property in requirement in always
+ present in common properties.</para></listitem>
+
+ <listitem><para>A property in build request is present in
+ common properties, unless (2) tells otherwise.</para></listitem>
+
+ <listitem><para>If either build request, or requirements (non-conditional
+ or conditional) include an expandable property (either composite,
+ or property with specified subfeature value), the behaviour is
+ equivalent to explicitly adding all expanded properties to build
+ request or requirements.</para></listitem>
+
+ <listitem><para>If requirements include a conditional property, and
+ condiiton of this property is true in context of common
+ properties, then the conditional property should be in common
+ properties as well.</para></listitem>
+
+ <listitem><para>If no value for a feature is given by other rules
+ here, it has default value in common properties.</para></listitem>
+ </orderedlist>
+
+ <para>Those rules are declarative, they don't specify how to compute the
+ common properties. However, they provide enough information for the
+ user. The important point is the handling of conditional
+ requirements. The condition can be satisfied either by property in
+ build request, by non-conditional requirements, or even by another
+ conditional property. For example, the following example works as
+ expected:
+<programlisting>
+exe a : a.cpp
+ : &lt;toolset&gt;gcc:&lt;variant&gt;release
+ &lt;variant&gt;release:&lt;define&gt;FOO ;
+</programlisting>
+ </para>
+
+ </section>
+
+ </section>
+
+
+
+ <section id="bbv2.reference.definitions">
+
+ <title>Definitions</title>
+
+ <section id="bbv2.reference.features">
+ <title>Features and properties</title>
+
+ <para>A <emphasis>feature</emphasis> is a normalized (toolset-independent)
+ aspect of a build configuration, such as whether inlining is
+ enabled. Feature names may not contain the '<literal>&gt;</literal>'
+ character.</para>
+
+ <!--
+ And what about dash?
+ -->
+
+ <para>Each feature in a build configuration has one or more
+ associated <emphasis>value</emphasis>s. Feature values for non-free features
+ may not contain the '<literal>&lt;</literal>', '<literal>:</literal>', or
+ '<literal>=</literal>' characters. Feature values for free features may not
+ contain the '<literal>&lt;</literal>' character.</para>
+
+ <para>A <emphasis>property</emphasis> is a (feature,value) pair, expressed as
+ &lt;feature&gt;value.</para>
+
+ <para>A <emphasis>subfeature</emphasis> is a feature that only exists in the
+ presence of its parent feature, and whose identity can be derived
+ (in the context of its parent) from its value. A subfeature's
+ parent can never be another subfeature. Thus, features and their
+ subfeatures form a two-level hierarchy.</para>
+
+ <para>A <emphasis>value-string</emphasis> for a feature <emphasis role="bold">F</emphasis> is a string of
+ the form
+ <literal>value-subvalue1-subvalue2</literal>...<literal>-subvalueN</literal>, where
+ <literal>value</literal> is a legal value for <emphasis role="bold">F</emphasis> and
+ <literal>subvalue1</literal>...<literal>subvalueN</literal> are legal values of some
+ of <emphasis role="bold">F</emphasis>'s subfeatures. For example, the properties
+ <literal>&lt;toolset&gt;gcc &lt;toolset-version&gt;3.0.1</literal> can be
+ expressed more conscisely using a value-string, as
+ <literal>&lt;toolset&gt;gcc-3.0.1</literal>.</para>
+
+ <para>A <emphasis>property set</emphasis> is a set of properties (i.e. a
+ collection without duplicates), for instance:
+ <literal>&lt;toolset&gt;gcc &lt;runtime-link&gt;static</literal>.</para>
+
+ <para>A <emphasis>property path</emphasis> is a property set whose elements have
+ been joined into a single string separated by slashes. A property
+ path representation of the previous example would be
+ <literal>&lt;toolset&gt;gcc/&lt;runtime-link&gt;static</literal>.</para>
+
+ <para>A <emphasis>build specification</emphasis> is a property set that fully
+ describes the set of features used to build a target.</para>
+
+ <section id="bbv2.reference.features.validity">
+ <title>Property Validity</title>
+
+ <para>
+ For <link linkend=
+ "bbv2.reference.features.attributes.free">free</link>
+ features, all values are valid. For all other features,
+ the valid values are explicitly specified, and the build
+ system will report an error for the use of an invalid
+ feature-value. Subproperty validity may be restricted so
+ that certain values are valid only in the presence of
+ certain other subproperties. For example, it is possible
+ to specify that the <code>&lt;gcc-target&gt;mingw</code>
+ property is only valid in the presence of
+ <code>&lt;gcc-version&gt;2.95.2</code>.
+ </para>
+
+ </section>
+ <section id="bbv2.reference.features.attributes">
+ <title>Feature Attributes</title>
+
+ <para>Each feature has a collection of zero or more of the following
+ attributes. Feature attributes are low-level descriptions of how the
+ build system should interpret a feature's values when they appear in
+ a build request. We also refer to the attributes of properties, so
+ that an <emphasis>incidental</emphasis> property, for example, is
+ one whose feature has the <emphasis>incidental</emphasis>
+ attribute.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>incidental</emphasis></para>
+
+ <para>Incidental features are assumed not to affect build
+ products at all. As a consequence, the build system may use
+ the same file for targets whose build specification differs
+ only in incidental features. A feature that controls a
+ compiler's warning level is one example of a likely
+ incidental feature.</para>
+
+ <para>Non-incidental features are assumed to affect build
+ products, so the files for targets whose build specification
+ differs in non-incidental features are placed in different
+ directories as described in "target paths" below. [ where? ]
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <anchor id="bbv2.reference.features.attributes.propagated"/>
+ <emphasis>propagated</emphasis>
+ </para>
+
+ <para>Features of this kind are
+ propagated to dependencies. That is, if a <link linkend=
+ "bbv2.overview.targets.main">main target</link> is built using a
+ propagated
+ property, the build systems attempts to use the same property
+ when building any of its dependencies as part of that main
+ target. For instance, when an optimized exectuable is
+ requested, one usually wants it to be linked with optimized
+ libraries. Thus, the <literal>&lt;optimization&gt;</literal> feature is
+ propagated.</para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <anchor id="bbv2.reference.features.attributes.free"/>
+ <emphasis>free</emphasis>
+ </para>
+
+ <para>Most features have a finite set of allowed values, and can
+ only take on a single value from that set in a given build
+ specification. Free features, on the other hand, can have
+ several values at a time and each value can be an arbitrary
+ string. For example, it is possible to have several
+ preprocessor symbols defined simultaneously:</para>
+
+<programlisting>
+&lt;define&gt;NDEBUG=1 &lt;define&gt;HAS_CONFIG_H=1
+</programlisting>
+
+ </listitem>
+
+ <listitem>
+ <para><emphasis>optional</emphasis></para>
+
+ <para>An optional feature is a feature that is not required to
+ appear in a build specification. Every non-optional non-free
+ feature has a default value that is used when a value for
+ the feature is not otherwise specified, either in a target's
+ requirements or in the user's build request. [A feature's
+ default value is given by the first value listed in the
+ feature's declaration. -- move this elsewhere - dwa]</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>symmetric</emphasis></para>
+
+ <para>A symmetric feature's default value is not automatically
+ included in <link linkend=
+ "bbv2.reference.variants">build variants</link>. Normally
+ a feature only generates a subvariant directory when its
+ value differs from the value specified by the build variant,
+ leading to an assymmetric subvariant directory structure for
+ certain values of the feature. A symmetric feature, when
+ relevant to the toolset, always generates a corresponding
+ subvariant directory.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>path</emphasis></para>
+
+ <para>The value of a path feature specifies a path. The path is
+ treated as relative to the directory of Jamfile where path
+ feature is used and is translated appropriately by the build
+ system when the build is invoked from a different
+ directory</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>implicit</emphasis></para>
+
+ <para>Values of implicit features alone identify the feature.
+ For example, a user is not required to write
+ "&lt;toolset&gt;gcc", but can simply write "gcc". Implicit
+ feature names also don't appear in variant paths, although
+ the values do. Thus: bin/gcc/... as opposed to
+ bin/toolset-gcc/.... There should typically be only a few
+ such features, to avoid possible name clashes.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>composite</emphasis></para>
+
+ <para>Composite features actually correspond to groups of
+ properties. For example, a build variant is a composite
+ feature. When generating targets from a set of build
+ properties, composite features are recursively expanded and
+ <emphasis>added</emphasis> to the build property set, so rules can find
+ them if necessary. Non-composite non-free features override
+ components of composite features in a build property set.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>dependency</emphasis></para>
+
+ <para>The value of a dependency feature is a target reference.
+ When used for building of a main target, the value of
+ dependency feature is treated as additional dependency.</para>
+
+ <para>For example, dependency features allow to state that
+ library A depends on library B. As the result, whenever an
+ application will link to A, it will also link to B.
+ Specifying B as dependency of A is different from adding B to
+ the sources of A. <!-- Need to clarify this. --></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Features that are neither free nor incidental are called
+ <emphasis>base</emphasis> features.</para>
+
+
+ </section>
+ <section id="bbv2.reference.features.declaration">
+ <title>Feature Declaration</title>
+
+ <para>The low-level feature declaration interface is the
+ <literal>feature</literal> rule from the
+ <literal>feature</literal> module:
+
+<programlisting>
+rule feature ( name : allowed-values * : attributes * )
+</programlisting>
+
+ A feature's allowed-values may be extended with the
+ <code>feature.extend</code> rule.
+ </para>
+
+ </section>
+ </section>
+
+ <section id="bbv2.reference.variants">
+ <title>Build Variants</title>
+
+ <para>
+ A build variant, or (simply variant) is a special kind of composite
+ feature that automatically incorporates the default values of
+ features that . Typically you'll want at least two separate
+ variants: one for debugging, and one for your release code. [
+ Volodya says: "Yea, we'd need to mention that it's a composite
+ feature and describe how they are declared, in pacticular that
+ default values of non-optional features are incorporated into
+ build variant automagically. Also, do we wan't some variant
+ inheritance/extension/templates. I don't remember how it works in
+ V1, so can't document this for V2.". Will clean up soon -DWA ]
+ </para>
+
+ </section>
+
+ <section id="bbv2.reference.variants.proprefine">
+ <title>Property refinement</title>
+
+ <para>When a target with certain properties is requested, and that
+ target requires some set of properties, it is needed to find the
+ set of properties to use for building. This process is called
+ <emphasis>property refinement</emphasis> and is performed by these rules</para>
+
+ <orderedlist>
+
+ <listitem>
+ <simpara>
+ Each property in the required set is added to the original
+ property set
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If the original property set includes property with a different
+ value of non free feature, that property is removed.
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </section>
+
+ <section id="bbv2.reference.variants.propcond">
+ <title>Conditional properties</title>
+
+ <para>Sometime it's desirable to apply certain requirements only for
+ a specific combination of other properties. For example, one of
+ compilers that you use issues a pointless warning that you want to
+ suppress by passing a command line option to it. You would not
+ want to pass that option to other compilers. Conditional
+ properties allow you to do just that. Their syntax is:</para>
+
+ <programlisting>
+ property ( "," property ) * ":" property
+ </programlisting>
+
+ <para>
+ For example, the problem above would be solved by:
+
+<programlisting>
+exe hello : hello.cpp : &lt;toolset&gt;yfc:&lt;cxxflags&gt;-disable-pointless-warning ;
+</programlisting>
+ </para>
+
+ <para>The syntax also allows several properties in the condition, for
+ example:
+<programlisting>
+exe hello : hello.cpp : &lt;os&gt;NT,&lt;toolset&gt;gcc:&lt;link&gt;static ;
+</programlisting>
+ </para>
+
+ </section>
+
+ <section id="bbv2.reference.ids">
+ <title>Target identifiers and references</title>
+
+ <para><emphasis>Target identifier</emphasis> is used to denote a
+ target. The syntax is:</para>
+
+<programlisting>
+target-id -&gt; (project-id | target-name | file-name )
+ | (project-id | directory-name) "//" target-name
+project-id -&gt; path
+target-name -&gt; path
+file-name -&gt; path
+directory-name -&gt; path
+</programlisting>
+
+ <para>
+ This grammar allows some elements to be recognized as either
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ project id (at this point, all project ids start with slash).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ name of target declared in current Jamfile (note that target
+ names may include slash).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ a regular file, denoted by absolute name or name relative to
+ project's sources location.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ To determine the real meaning a check is made if project-id
+ by the specified name exists, and then if main target of that
+ name exists. For example, valid target ids might be:
+
+<screen>
+a -- target in current project
+lib/b.cpp -- regular file
+/boost/thread -- project "/boost/thread"
+/home/ghost/build/lr_library//parser -- target in specific project
+</screen>
+
+ </para>
+
+ <para><emphasis role="bold">Rationale:</emphasis>Target is separated from project by special
+ separator (not just slash), because:</para>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ It emphasises that projects and targets are different things.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ It allows to have main target names with slashes.
+
+ <!-- The motivation for which is:
+
+ So, to summarize:
+
+ 1. The project that extract tarfile may extract all possible kinds
+ of targets, and it's reasonable to use them directly from other
+ project.
+
+ 2. The rule for unpacking tar is inplemented in terms of
+ "patch-file", for maintainability, and therefore, must use main
+ target name that contains slashes?
+
+ 3. Using sub-Jamfile in "foo" to declare extracted file "foo/b" is
+ not an option, because you should not change existing tree
+
+ That makes good rationale for why main target must contain names.
+ -->
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para id="bbv2.reference.targets.references">
+ <emphasis>Target reference</emphasis> is used to
+ specify a source target, and may additionally specify desired
+ properties for that target. It has this syntax:</para>
+
+<programlisting>
+target-reference -&gt; target-id [ "/" requested-properties ]
+requested-properties -&gt; property-path
+</programlisting>
+
+ <para>
+ For example,
+
+ <programlisting>
+ exe compiler : compiler.cpp libs/cmdline/&lt;optimization&gt;space ;
+ </programlisting>
+
+ would cause the version of <literal>cmdline</literal> library,
+ optimized for space, to be linked in even if the
+ <literal>compiler</literal> executable is build with optimization for
+ speed.
+ </para>
+ </section>
+
+ </section>
+
+</chapter>
+
+<!--
+ Local Variables:
+ mode: nxml
+ sgml-indent-data: t
+ sgml-parent-document: ("userman.xml" "chapter")
+ sgml-set-face: t
+ End:
+-->
diff --git a/tools/build/v2/doc/src/standalone.xml b/tools/build/v2/doc/src/standalone.xml
new file mode 100644
index 0000000000..eea5e101da
--- /dev/null
+++ b/tools/build/v2/doc/src/standalone.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude"
+ id="bbv2" last-revision="$Date: 2011-01-25 13:06:12 -0500 (Tue, 25 Jan 2011) $">
+ <bookinfo>
+ <copyright>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <holder>Vladimir Prus</holder>
+ </copyright>
+
+ <legalnotice>
+ <para>Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
+ <ulink
+ url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
+ </para>
+ </legalnotice>
+ </bookinfo>
+
+ <title>Boost.Build V2 User Manual</title>
+
+ <!-- Chapters -->
+ <xi:include href="howto.xml"/>
+ <xi:include href="install.xml"/>
+ <xi:include href="tutorial.xml"/>
+ <xi:include href="overview.xml"/>
+ <xi:include href="tasks.xml"/>
+ <xi:include href="reference.xml"/>
+ <xi:include href="extending.xml"/>
+ <xi:include href="faq.xml"/>
+
+ <!-- Appendicies -->
+<!-- <xi:include href="architecture.xml"/> -->
+ <appendix id="bbv2.jam">
+ <title>Boost.Jam Documentation</title>
+ <xi:include href="jam_docs.xml" parse="xml"
+ xpointer="xpointer(id('jam.building')|id('jam.building')/following-sibling::*)"/>
+ </appendix>
+
+ <index/>
+
+</book>
diff --git a/tools/build/v2/doc/src/tasks.xml b/tools/build/v2/doc/src/tasks.xml
new file mode 100644
index 0000000000..2b3e68bd16
--- /dev/null
+++ b/tools/build/v2/doc/src/tasks.xml
@@ -0,0 +1,774 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+<!-- Copyright 2006 Vladimir Prus -->
+<!-- Distributed under the Boost Software License, Version 1.0. -->
+<!-- (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) -->
+
+<chapter id="bbv2.tasks">
+ <title>Common tasks</title>
+
+ <para>
+ This section describes main targets types that Boost.Build supports
+ out-of-the-box. Unless otherwise noted, all mentioned main target rules have
+ the common signature, described in <xref linkend="bbv2.overview.targets"/>.
+ </para>
+
+ <section id="bbv2.tasks.programs">
+ <title>Programs</title>
+
+ <indexterm><primary>exe</primary></indexterm>
+ <para>
+ Programs are created using the <code>exe</code> rule, which follows the
+ <link linkend="bbv2.main-target-rule-syntax">common syntax</link>. For
+ example:
+<programlisting>
+exe hello : hello.cpp some_library.lib /some_project//library
+ : &lt;threading&gt;multi
+ ;
+</programlisting>
+ This will create an executable file from the sources -- in this case, one
+ C++ file, one library file present in the same directory, and another
+ library that is created by Boost.Build. Generally, sources can include C
+ and C++ files, object files and libraries. Boost.Build will automatically
+ try to convert targets of other types.
+ </para>
+
+ <tip>
+ <para>
+ On Windows, if an application uses shared libraries, and both the
+ application and the libraries are built using Boost.Build, it is not
+ possible to immediately run the application, because the <literal>PATH
+ </literal> environment variable should include the path to the
+ libraries. It means you have to either add the paths manually, or have
+ the build place the application and the libraries into the same
+ directory. See <xref linkend="bbv2.tasks.installing"/>.
+ </para>
+ <!-- We should be emphasizing the use of the built-in testing rules
+ rather than continually discussing these quirks of running programs
+ with shared libraries. -->
+ </tip>
+ </section>
+
+ <section id="bbv2.tasks.libraries">
+ <title>Libraries</title>
+
+ <para>
+ Library targets are created using the <code>lib</code> rule, which
+ follows the <link linkend="bbv2.main-target-rule-syntax">common syntax
+ </link>. For example:
+<programlisting>
+lib helpers : helpers.cpp ;
+</programlisting>
+ This will define a library target named <code>helpers</code> built from
+ the <code>helpers.cpp</code> source file.
+ </para>
+ <para>
+ Depending on the given &lt;link&gt; feature value the library will be
+ either static or shared.
+ </para>
+ <para>
+ Library targets may be used to represent:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <code>Built libraries</code> that get built from specified sources,
+ as is the one in the example above. <!-- add link -->
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>Prebuilt libraries</code> which already exist on the system
+ and are just supposed to be used by the build system. Such
+ libraries may be searched for by the tools using them (typically
+ linkers referencing the library using the <option>-l</option>
+ option) or their path may be known in advance by the build system.
+ <!-- We need examples for this. -->
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ The syntax for these case is given below:
+<programlisting>
+lib z : : &lt;name&gt;z &lt;search&gt;/home/ghost ;
+lib compress : : &lt;file&gt;/opt/libs/compress.a ;
+</programlisting>
+ The <code>name</code> property specifies the name that should be passed to
+ the <option>-l</option> option, and the <code>file</code> property
+ specifies the file location. The <varname>search</varname> feature
+ specifies paths in which to search for the library. That feature can be
+ specified several times or it can be omitted, in which case only the
+ default compiler paths will be searched.
+ </para>
+
+ <para>
+ The difference between using the <varname>file</varname> feature as
+ opposed to the <varname>name</varname> feature together with the <varname>
+ search</varname> feature is that <varname>file</varname> is more precise.
+ A specific file will be used as opposed to the <varname>search</varname>
+ feature only adding a library path, or the <varname>name</varname> feature
+ giving only the basic name of the library. The search rules are specific
+ to the linker used. For example, given these definition:
+<programlisting>
+lib a : : &lt;variant&gt;release &lt;file&gt;/pool/release/a.so ;
+lib a : : &lt;variant&gt;debug &lt;file&gt;/pool/debug/a.so ;
+lib b : : &lt;variant&gt;release &lt;file&gt;/pool/release/b.so ;
+lib b : : &lt;variant&gt;debug &lt;file&gt;/pool/debug/b.so ;
+</programlisting>
+ It is possible to use a release version of <code>a</code> and debug
+ version of <code>b</code>. Had we used the <varname>name</varname> and
+ <varname>search</varname> features, the linker would have always picked
+ either the release or the debug versions.
+ <!-- explain -->
+ </para>
+
+ <para>
+ For convenience, the following syntax is allowed:
+<programlisting>
+lib z ;
+lib gui db aux ;
+</programlisting>
+ which has exactly the same effect as:
+<programlisting>
+lib z : : &lt;name&gt;z ;
+lib gui : : &lt;name&gt;gui ;
+lib db : : &lt;name&gt;db ;
+lib aux : : &lt;name&gt;aux ;
+</programlisting>
+ </para>
+
+ <para>
+ When a library references another library you should put that other
+ library in its list of sources. This will do the right thing in all cases.
+ <!--Add a link to the notes below. --> For portability, you should specify
+ library dependencies even for searched and prebuilt libraries, othewise,
+ static linking on Unix will not work. For example:
+<programlisting>
+lib z ;
+lib png : z : &lt;name&gt;png ;
+</programlisting>
+ </para>
+
+ <note>
+ <para>
+ When a library has a shared library defined as its source, or a static
+ library has another static library defined as its source then any target
+ linking to the first library with automatically link to its source
+ library as well.
+ </para>
+ <para>
+ On the other hand, when a shared library has a static library defined as
+ its source then the first library will be built so that it completely
+ includes the second one.
+ </para>
+ <para>
+ If you do not want shared libraries to include all libraries specified
+ in its sources (especially statically linked ones), you would need to
+ use the following:
+<programlisting>
+lib b : a.cpp ;
+lib a : a.cpp : &lt;use&gt;b : : &lt;library&gt;b ;
+</programlisting>
+ This specifies that library <code>a</code> uses library <code>b</code>,
+ and causes all executables that link to <code>a</code> also link to
+ <code>b</code>. In this case, even for shared linking, the
+ <code>a</code> library will not even refer to <code>b</code>.
+ </para>
+ </note>
+
+ <para>
+ One Boost.Build feature that is often very useful for defining library
+ targets are usage requirements. <!-- Rephrase that. But then, it is much
+ too late for an introduction of usage requirements - you have already
+ discussed them many times. Also, add references to the sections describing
+ requirements and usage-requirements here. --> For example, imagine that
+ you want you build a <code>helpers</code> library and its interface is
+ described in its <code>helpers.hpp</code> header file located in the same
+ directory as the <code>helpers.cpp</code> source file. Then you could add
+ the following to the Jamfile located in that same directory:
+<programlisting>
+lib helpers : helpers.cpp : : : &lt;include&gt;. ;
+</programlisting>
+ which would automatically add the directory where the target has been
+ defined (and where the library's header file is located) to the compiler's
+ include path for all targets using the <code>helpers</code> library. This
+ feature greatly simplifies Jamfiles.
+ </para>
+ </section>
+
+ <section id="bbv2.tasks.alias">
+ <title>Alias</title>
+
+ <para>
+ The <functionname>alias</functionname> rule gives an alternative name to a
+ group of targets. For example, to give the name <filename>core</filename>
+ to a group of three other targets with the following code:
+<programlisting>
+alias core : im reader writer ;
+</programlisting>
+ Using <filename>core</filename> on the command line, or in the source list
+ of any other target is the same as explicitly using <filename>im
+ </filename>, <filename>reader</filename>, and <filename>writer</filename>.
+ </para>
+
+ <para>
+ Another use of the <code>alias</code> rule is to change build properties.
+ For example, if you want to use link statically to the Boost Threads
+ library, you can write the following:
+<programlisting>
+alias threads : /boost/thread//boost_thread : &lt;link&gt;static ;
+</programlisting>
+ and use only the <code>threads</code> alias in your Jamfiles.
+ </para>
+
+ <para>
+ You can also specify usage requirements for the <code>alias</code> target.
+ If you write the following:
+<programlisting>
+alias header_only_library : : : : &lt;include&gt;/usr/include/header_only_library ;
+</programlisting>
+ then using <code>header_only_library</code> in sources will only add an
+ include path. Also note that when an alias has sources, their usage
+ requirements are propagated as well. For example:
+<programlisting>
+lib library1 : library1.cpp : : : &lt;include&gt;/library/include1 ;
+lib library2 : library2.cpp : : : &lt;include&gt;/library/include2 ;
+alias static_libraries : library1 library2 : &lt;link&gt;static ;
+exe main : main.cpp static_libraries ;
+</programlisting>
+ will compile <filename>main.cpp</filename> with additional includes
+ required for using the specified static libraries.
+ </para>
+ </section>
+
+ <section id="bbv2.tasks.installing">
+ <title>Installing</title>
+
+ <para>
+ This section describes various ways to install built target and arbitrary
+ files.
+ </para>
+
+ <bridgehead>Basic install</bridgehead>
+
+ <para>
+ For installing a built target you should use the <code>install</code>
+ rule, which follows the <link linkend="bbv2.main-target-rule-syntax">
+ common syntax</link>. For example:
+<programlisting>
+install dist : hello helpers ;
+</programlisting>
+ will cause the targets <code>hello</code> and <code>helpers</code> to be
+ moved to the <filename>dist</filename> directory, relative to the
+ Jamfile's directory. The directory can be changed using the
+ <code>location</code> property:
+<programlisting>
+install dist : hello helpers : &lt;location&gt;/usr/bin ;
+</programlisting>
+ While you can achieve the same effect by changing the target name to
+ <filename>/usr/bin</filename>, using the <code>location</code> property is
+ better as it allows you to use a mnemonic target name.
+ </para>
+
+ <para>
+ The <code>location</code> property is especially handy when the location
+ is not fixed, but depends on the build variant or environment variables:
+<programlisting>
+install dist : hello helpers :
+ &lt;variant&gt;release:&lt;location&gt;dist/release
+ &lt;variant&gt;debug:&lt;location&gt;dist/debug ;
+install dist2 : hello helpers : &lt;location&gt;$(DIST) ;
+</programlisting>
+ See also <link linkend="bbv2.reference.variants.propcond">conditional
+ properties</link> and <link linkend="bbv2.faq.envar">environment
+ variables</link>
+ </para>
+
+ <bridgehead>Installing with all dependencies</bridgehead>
+
+ <para>
+ Specifying the names of all libraries to install can be boring. The
+ <code>install</code> allows you to specify only the top-level executable
+ targets to install, and automatically install all dependencies:
+<programlisting>
+install dist : hello
+ : &lt;install-dependencies&gt;on &lt;install-type&gt;EXE
+ &lt;install-type&gt;LIB
+ ;
+</programlisting>
+ will find all targets that <code>hello</code> depends on, and install all
+ of those which are either executables or libraries. More specifically, for
+ each target, other targets that were specified as sources or as dependency
+ properties, will be recursively found. One exception is that targets
+ referred with the <link linkend="bbv2.builtin.features.use">
+ <code>use</code></link> feature are not considered, as that feature is
+ typically used to refer to header-only libraries. If the set of target
+ types is specified, only targets of that type will be installed,
+ otherwise, all found target will be installed.
+ </para>
+
+ <bridgehead>Preserving Directory Hierarchy</bridgehead>
+
+ <indexterm><primary>install-source-root</primary></indexterm>
+
+ <para>
+ By default, the <code>install</code> rule will strip paths from its
+ sources. So, if sources include <filename>a/b/c.hpp</filename>, the
+ <filename>a/b</filename> part will be ignored. To make the
+ <code>install</code> rule preserve the directory hierarchy you need to
+ use the <literal>&lt;install-source-root&gt;</literal> feature to specify
+ the root of the hierarchy you are installing. Relative paths from that
+ root will be preserved. For example, if you write:
+<programlisting>
+install headers
+ : a/b/c.h
+ : &lt;location&gt;/tmp &lt;install-source-root&gt;a
+ ;
+</programlisting>
+ the a file named <filename>/tmp/b/c.h</filename> will be created.
+ </para>
+
+ <para>
+ The <link linkend="bbv2.reference.glob-tree">glob-tree</link> rule can be
+ used to find all files below a given directory, making it easy to install
+ an entire directory tree.
+ </para>
+
+ <bridgehead>Installing into Several Directories</bridgehead>
+
+ <para>
+ The <link linkend="bbv2.tasks.alias"><code>alias</code></link> rule can be
+ used when targets need to be installed into several directories:
+<programlisting>
+alias install : install-bin install-lib ;
+install install-bin : applications : /usr/bin ;
+install install-lib : helper : /usr/lib ;
+</programlisting>
+ </para>
+
+ <para>
+ Because the <code>install</code> rule just copies targets, most free
+ features <footnote><para>see the definition of "free" in <xref
+ linkend="bbv2.reference.features.attributes"/>.</para></footnote> have no
+ effect when used in requirements of the <code>install</code> rule. The
+ only two that matter are <link linkend="bbv2.builtin.features.dependency">
+ <varname>dependency</varname></link> and, on Unix, <link
+ linkend="bbv2.reference.features.dll-path"><varname>dll-path</varname>
+ </link>.
+ </para>
+
+ <note>
+ <para>
+ (Unix specific) On Unix, executables built using Boost.Build typically
+ contain the list of paths to all used shared libraries. For installing,
+ this is not desired, so Boost.Build relinks the executable with an empty
+ list of paths. You can also specify additional paths for installed
+ executables using the <varname>dll-path</varname> feature.
+ </para>
+ </note>
+ </section>
+
+ <section id="bbv2.builtins.testing">
+ <title>Testing</title>
+
+ <para>
+ Boost.Build has convenient support for running unit tests. The simplest
+ way is the <code>unit-test</code> rule, which follows the <link
+ linkend="bbv2.main-target-rule-syntax">common syntax</link>. For example:
+<programlisting>
+unit-test helpers_test : helpers_test.cpp helpers ;
+</programlisting>
+ </para>
+
+ <para>
+ The <functionname>unit-test</functionname> rule behaves like the
+ <functionname>exe</functionname> rule, but after the executable is created
+ it is also run. If the executable returns an error code, the build system
+ will also return an error and will try running the executable on the next
+ invocation until it runs successfully. This behaviour ensures that you can
+ not miss a unit test failure.
+ </para>
+
+ <para>
+ By default, the executable is run directly. Sometimes, it is desirable to
+ run the executable using some helper command. You should use the <literal>
+ testing.launcher</literal> property to specify the name of the helper
+ command. For example, if you write:
+<programlisting>
+unit-test helpers_test
+ : helpers_test.cpp helpers
+ : <emphasis role="bold">&lt;testing.launcher&gt;valgrind</emphasis>
+ ;
+</programlisting>
+ The command used to run the executable will be:
+<screen>
+<emphasis role="bold">valgrind</emphasis> bin/$toolset/debug/helpers_test
+</screen>
+ </para>
+
+ <para>
+ There are few specialized testing rules, listed below:
+<programlisting>
+rule compile ( sources : requirements * : target-name ? )
+rule compile-fail ( sources : requirements * : target-name ? )
+rule link ( sources + : requirements * : target-name ? )
+rule link-fail ( sources + : requirements * : target-name ? )
+</programlisting>
+ They are given a list of sources and requirements. If the target name is
+ not provided, the name of the first source file is used instead. The
+ <literal>compile*</literal> tests try to compile the passed source. The
+ <literal>link*</literal> rules try to compile and link an application from
+ all the passed sources. The <literal>compile</literal> and <literal>link
+ </literal> rules expect that compilation/linking succeeds. The <literal>
+ compile-fail</literal> and <literal>link-fail</literal> rules expect that
+ the compilation/linking fails.
+ </para>
+
+ <para>
+ There are two specialized rules for running applications, which are more
+ powerful than the <code>unit-test</code> rule. The <code>run</code> rule
+ has the following signature:
+<programlisting>
+rule run ( sources + : args * : input-files * : requirements * : target-name ?
+ : default-build * )
+</programlisting>
+ The rule builds application from the provided sources and runs it, passing
+ <varname>args</varname> and <varname>input-files</varname> as command-line
+ arguments. The <varname>args</varname> parameter is passed verbatim and
+ the values of the <varname>input-files</varname> parameter are treated as
+ paths relative to containing Jamfile, and are adjusted if <command>bjam
+ </command> is invoked from a different directory. The
+ <code>run-fail</code> rule is identical to the <code>run</code> rule,
+ except that it expects that the run fails.
+ </para>
+
+ <para>
+ All rules described in this section, if executed successfully, create a
+ special manifest file to indicate that the test passed. For the
+ <code>unit-test</code> rule the files is named <filename><replaceable>
+ target-name</replaceable>.passed</filename> and for the other rules it is
+ called <filename><replaceable>target-name</replaceable>.test</filename>.
+ The <code>run*</code> rules also capture all output from the program, and
+ store it in a file named <filename><replaceable>
+ target-name</replaceable>.output</filename>.
+ </para>
+
+ <para>
+ <indexterm><primary>preserve-test-targets</primary></indexterm>
+ If the <literal>preserve-test-targets</literal> feature has the value
+ <literal>off</literal>, then <code>run</code> and the <code>run-fail</code>
+ rules will remove the executable after running it. This somewhat decreases
+ disk space requirements for continuous testing environments. The default
+ value of <literal>preserve-test-targets</literal> feature is <literal>on</literal>.
+ </para>
+
+ <para>
+ It is possible to print the list of all test targets (except for
+ <code>unit-test</code>) declared in your project, by passing the <literal>
+ --dump-tests</literal> command-line option. The output will consist of
+ lines of the form:
+<screen>
+boost-test(<replaceable>test-type</replaceable>) <replaceable>path</replaceable> : <replaceable>sources</replaceable>
+</screen>
+ </para>
+
+ <para>
+ It is possible to process the list of tests, the output of bjam during
+ command run, and the presense/absense of the <filename>*.test</filename>
+ files created when test passes into human-readable status table of tests.
+ Such processing utilities are not included in Boost.Build.
+ </para>
+ </section>
+
+ <section id="bbv2.builtins.raw">
+ <title>Custom commands</title>
+
+ <para>
+ When you use most of main target rules, Boost.Build automatically figures
+ what commands to run and it what order. As soon as you want to use new
+ file types or support new tools, one approach is to extend Boost.Build to
+ smoothly support them, as documented in <xref linkend="bbv2.extender"/>.
+ However, if there is only a single place where the new tool is used, it
+ might be easier to just explicitly specify the commands to run.
+ </para>
+
+ <para>
+ <!-- This paragraph requires links to where the terms 'virtual target' &
+ 'target' are defined. -->
+ Three main target rules can be used for that. The <functionname>make
+ </functionname> rule allows you to construct a single file from any number
+ of source file, by running a command you specify. The <functionname>
+ notfile</functionname> rule allows you to run an arbitrary command,
+ without creating any files. And finaly, the <functionname>generate
+ </functionname> rule allows you to describe transformation using
+ Boost.Build's virtual targets. This is higher-level than file names that
+ the <functionname>make</functionname> rule operates with and allows you to
+ create more than one target, create differently named targets depending on
+ properties or use more than one tool.
+ </para>
+
+ <para>
+ The <functionname>make</functionname> rule is used when you want to create
+ one file from a number of sources using some specific command. The
+ <functionname>notfile</functionname> is used to unconditionally run a
+ command.
+ </para>
+
+ <!-- We need to specify somewhere that the user can get rules like make,
+ notfile & generate defined in his Jamfiles by importing an appropriate
+ Boost.Build module. Also, each of those rules should get a separate
+ documentation page explicitly listing which module needs to be imported for
+ them to become accessible. -->
+
+ <para>
+ Suppose you want to create file <filename>file.out</filename> from file
+ <filename>file.in</filename> by running command <command>
+ in2out</command>. Here is how you would do this in Boost.Build:
+<programlisting>
+make file.out : file.in : @in2out ;
+actions in2out
+{
+ in2out $(&lt;) $(&gt;)
+}
+</programlisting>
+ If you run <command>bjam</command> and <filename>file.out</filename> does
+ not exist, Boost.Build will run the <command>in2out</command> command to
+ create that file. For more details on specifying actions, see <xref
+ linkend="bbv2.overview.jam_language.actions"/>.
+ </para>
+
+ <para>
+ It could be that you just want to run some command unconditionally, and
+ that command does not create any specific files. For that you can use the
+ <functionname>notfile</functionname> rule. For example:
+<programlisting>
+notfile echo_something : @echo ;
+actions echo
+{
+ echo "something"
+}
+</programlisting>
+ The only difference from the <functionname>make</functionname> rule is
+ that the name of the target is not considered a name of a file, so
+ Boost.Build will unconditionally run the action.
+ </para>
+
+ <para>
+ <!-- This paragraph requires links to where terms like 'virtual target',
+ 'target', 'project-target' & 'property-set' are defined. -->
+ The <functionname>generate</functionname> rule is used when you want to
+ express transformations using Boost.Build's virtual targets, as opposed to
+ just filenames. The <functionname>generate</functionname> rule has the
+ standard main target rule signature, but you are required to specify the
+ <literal>generating-rule</literal> property. The value of the property
+ should be in the form <literal>
+ @<replaceable>rule-name</replaceable></literal>, the named rule should
+ have the following signature:
+<programlisting>
+rule generating-rule ( project name : property-set : sources * )
+</programlisting>
+ and will be called with an instance of the <code>project-target</code>
+ class, the name of the main target, an instance of the
+ <code>property-set</code> class containing build properties, and the list
+ of instances of the <code>virtual-target</code> class corresponding to
+ sources. The rule must return a list of <code>virtual-target</code>
+ instances. The interface of the <code>virtual-target</code> class can be
+ learned by looking at the <filename>build/virtual-target.jam</filename>
+ file. The <filename>generate</filename> example contained in the
+ Boost.Build distribution illustrates how the <literal>generate</literal>
+ rule can be used.
+ </para>
+ </section>
+
+ <section id="bbv2.reference.precompiled_headers">
+ <title>Precompiled Headers</title>
+
+ <para>
+ Precompiled headers is a mechanism to speed up compilation by creating a
+ partially processed version of some header files, and then using that
+ version during compilations rather then repeatedly parsing the original
+ headers. Boost.Build supports precompiled headers with gcc and msvc
+ toolsets.
+ </para>
+
+ <para>
+ To use precompiled headers, follow the following steps:
+ </para>
+
+ <orderedlist>
+ <listitem>
+ <para>
+ Create a header that includes headers used by your project that you
+ want precompiled. It is better to include only headers that are
+ sufficiently stable &#x2014; like headers from the compiler and
+ external libraries. Please wrap the header in <code>#ifdef
+ BOOST_BUILD_PCH_ENABLED</code>, so that the potentially expensive
+ inclusion of headers is not done when PCH is not enabled. Include the
+ new header at the top of your source files.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Declare a new Boost.Build target for the precompiled header and add
+ that precompiled header to the sources of the target whose compilation
+ you want to speed up:
+<programlisting>
+cpp-pch pch : pch.hpp ;
+exe main : main.cpp pch ;
+</programlisting>
+ You can use the <functionname>c-pch</functionname> rule if you want to
+ use the precompiled header in C programs.
+ </para></listitem>
+ </orderedlist>
+
+ <para>
+ The <filename>pch</filename> example in Boost.Build distribution can be
+ used as reference.
+ </para>
+
+ <para>
+ Please note the following:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ The inclusion of the precompiled header must be the first thing in a
+ source file, before any code or preprocessor directives.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ The build properties used to compile the source files and the
+ precompiled header must be the same. Consider using project
+ requirements to assure this.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Precompiled headers must be used purely as a way to improve
+ compilation time, not to save the number of <code>#include</code>
+ statements. If a source file needs to include some header, explicitly
+ include it in the source file, even if the same header is included
+ from the precompiled header. This makes sure that your project will
+ build even if precompiled headers are not supported.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ On the gcc compiler, the name of the header being precompiled must be
+ equal to the name of the <code>cpp-pch</code> target. This is a gcc
+ requirement.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Prior to version 4.2, the gcc compiler did not allow anonymous
+ namespaces in precompiled headers, which limits their utility. See the
+ <ulink url="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29085"> bug
+ report</ulink> for details.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="bbv2.reference.generated_headers">
+ <title>Generated headers</title>
+
+ <para>
+ Usually, Boost.Build handles implicit dependendies completely
+ automatically. For example, for C++ files, all <literal>#include</literal>
+ statements are found and handled. The only aspect where user help might be
+ needed is implicit dependency on generated files.
+ </para>
+
+ <para>
+ By default, Boost.Build handles such dependencies within one main target.
+ For example, assume that main target "app" has two sources, "app.cpp" and
+ "parser.y". The latter source is converted into "parser.c" and "parser.h".
+ Then, if "app.cpp" includes "parser.h", Boost.Build will detect this
+ dependency. Moreover, since "parser.h" will be generated into a build
+ directory, the path to that directory will automatically added to include
+ path.
+ </para>
+
+ <para>
+ Making this mechanism work across main target boundaries is possible, but
+ imposes certain overhead. For that reason, if there is implicit dependency
+ on files from other main targets, the <literal>&lt;implicit-dependency&gt;
+ </literal> [ link ] feature must be used, for example:
+<programlisting>
+lib parser : parser.y ;
+exe app : app.cpp : &lt;implicit-dependency&gt;parser ;
+</programlisting>
+ The above example tells the build system that when scanning all sources of
+ "app" for implicit-dependencies, it should consider targets from "parser"
+ as potential dependencies.
+ </para>
+ </section>
+
+ <section id="bbv2.tasks.crosscompile">
+ <title>Cross-compilation</title>
+
+ <indexterm><primary>cross compilation</primary></indexterm>
+
+ <para>Boost.Build supports cross compilation with the gcc and msvc
+ toolsets.</para>
+
+ <para>
+ When using gcc, you first need to specify your cross compiler
+ in <filename>user-config.jam</filename> (see <xref linkend="bbv2.overview.configuration"/>),
+ for example:</para>
+<programlisting>
+using gcc : arm : arm-none-linux-gnueabi-g++ ;
+</programlisting>
+ <para>
+ After that, if the host and target os are the same, for example Linux, you can
+ just request that this compiler version to be used:
+ </para>
+<screen>
+bjam toolset=gcc-arm
+</screen>
+
+ <para>
+ If you want to target different operating system from the host, you need
+ to additionally specify the value for the <code>target-os</code> feature, for
+ example:
+ </para>
+<screen>
+# On windows box
+bjam toolset=gcc-arm <emphasis role="bold">target-os=linux</emphasis>
+# On Linux box
+bjam toolset=gcc-mingw <emphasis role="bold">target-os=windows</emphasis>
+</screen>
+ <para>
+ For the complete list of allowed opeating system names, please see the documentation for
+ <link linkend="bbv2.reference.features.target-os">target-os feature</link>.
+ </para>
+
+ <para>
+ When using the msvc compiler, it's only possible to cross-compiler to a 64-bit system
+ on a 32-bit host. Please see <xref linkend="v2.reference.tools.compiler.msvc.64"/> for
+ details.
+ </para>
+
+ </section>
+
+</chapter>
+
+<!--
+ Local Variables:
+ mode: nxml
+ sgml-indent-data: t
+ sgml-parent-document: ("userman.xml" "chapter")
+ sgml-set-face: t
+ End:
+-->
diff --git a/tools/build/v2/doc/src/tutorial.xml b/tools/build/v2/doc/src/tutorial.xml
new file mode 100644
index 0000000000..3763471dfe
--- /dev/null
+++ b/tools/build/v2/doc/src/tutorial.xml
@@ -0,0 +1,681 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+<?psgml nofill screen programlisting literallayout?>
+
+<chapter id="bbv2.tutorial">
+ <title>Tutorial</title>
+
+<!-- You can't launch into this stuff without describing how to configure -->
+<!-- Boost.Build... unless of course you think it's likely to work with -->
+<!-- no configuration. But even if you do you have to tell people how to -->
+<!-- configure their installation in case it doesn't work. -->
+<!--
+ VP: need also mention the examples which correspond to specific
+ sections.
+-->
+
+ <para>
+ This section will guide you though the most basic features of Boost.Build
+ V2. We will start with the &#x201C;Hello, world&#x201D; example, learn how
+ to use libraries, and finish with testing and installing features.
+ </para>
+
+ <section id="bbv2.tutorial.hello">
+ <title>Hello, world</title>
+
+ <para>
+ The simplest project that Boost.Build can construct is stored in
+ <filename>example/hello/</filename> directory. The project is described by
+ a file called <filename>Jamroot</filename> that contains:
+
+<programlisting>
+exe hello : hello.cpp ;
+</programlisting>
+
+ Even with this simple setup, you can do some interesting things. First of
+ all, just invoking <command>bjam</command> will build the <filename>hello
+ </filename> executable by compiling and linking <filename>hello.cpp
+ </filename>. By default, debug variant is built. Now, to build the release
+ variant of <filename>hello</filename>, invoke
+
+<screen>
+bjam release
+</screen>
+
+ Note that debug and release variants are created in different directories,
+ so you can switch between variants or even build multiple variants at
+ once, without any unnecessary recompilation. Let us extend the example by
+ adding another line to our project's <filename>Jamroot</filename>:
+
+<programlisting>
+exe hello2 : hello.cpp ;
+</programlisting>
+
+ Now let us build both the debug and release variants of our project again:
+
+<screen>
+bjam debug release
+</screen>
+
+ Note that two variants of <filename>hello2</filename> are linked. Since we
+ have already built both variants of <filename>hello</filename>, hello.cpp
+ will not be recompiled; instead the existing object files will just be
+ linked into the corresponding variants of <filename>hello2</filename>. Now
+ let us remove all the built products:
+
+<screen>
+bjam --clean debug release
+</screen>
+
+ It is also possible to build or clean specific targets. The following two
+ commands, respectively, build or clean only the debug version of
+ <filename>hello2</filename>.
+
+<screen>
+bjam hello2
+bjam --clean hello2
+</screen>
+ </para>
+ </section>
+
+ <section id="bbv2.tutorial.properties">
+ <title>Properties</title>
+
+ <para>
+ To portably represent aspects of target configuration such as
+ debug and release variants, or single- and multi-threaded
+ builds, Boost.Build uses <firstterm>features</firstterm> with
+ associated <firstterm>values</firstterm>. For
+ example, the <code>debug-symbols</code> feature can have a value of <code>on</code> or
+ <code>off</code>. A <firstterm>property</firstterm> is just a (feature,
+ value) pair. When a user initiates a build, Boost.Build
+ automatically translates the requested properties into appropriate
+ command-line flags for invoking toolset components like compilers
+ and linkers.
+ </para>
+
+ <para>
+ There are many built-in features that can be combined to
+ produce arbitrary build configurations. The following command
+ builds the project's <code>release</code> variant with inlining
+ disabled and debug symbols enabled:
+<screen>
+bjam release inlining=off debug-symbols=on
+</screen>
+ </para>
+
+ <para>
+ Properties on the command-line are specified with the syntax:
+
+<screen>
+<replaceable>feature-name</replaceable>=<replaceable>feature-value</replaceable>
+</screen>
+ </para>
+
+ <para>
+ The <option>release</option> and <option>debug</option> that we have seen
+ in <command>bjam</command> invocations are just a shorthand way to specify
+ values of the <varname>variant</varname> feature. For example, the
+ command above could also have been written this way:
+
+ <screen>
+bjam variant=release inlining=off debug-symbols=on
+ </screen>
+ </para>
+
+ <para>
+ <varname>variant</varname> is so commonly-used that it has been given
+ special status as an <firstterm>implicit</firstterm> feature&#x2014;
+ Boost.Build will deduce the its identity just from the name of one of its
+ values.
+ </para>
+
+ <para>
+ A complete description of features can be found in <xref linkend="bbv2.reference.features"/>.
+ </para>
+
+ <section id="bbv2.tutorial.properties.requirements">
+ <title>Build Requests and Target Requirements</title>
+
+ <para>
+ The set of properties specified on the command line constitute
+ a <firstterm>build request</firstterm>&#x2014;a description of
+ the desired properties for building the requested targets (or,
+ if no targets were explicitly requested, the project in the
+ current directory). The <emphasis>actual</emphasis>
+ properties used for building targets are typically a
+ combination of the build request and properties derived from
+ the project's <filename>Jamroot</filename> (and its other
+ Jamfiles, as described in <xref
+ linkend="bbv2.tutorial.hierarchy"/>). For example, the
+ locations of <code>#include</code>d header files are normally
+ not specified on the command-line, but described in
+ Jamfiles as <firstterm>target
+ requirements</firstterm> and automatically combined with the
+ build request for those targets. Multithread-enabled
+ compilation is another example of a typical target
+ requirement. The Jamfile fragment below
+ illustrates how these requirements might be specified.
+ </para>
+
+<programlisting>
+exe hello
+ : hello.cpp
+ : &lt;include&gt;boost &lt;threading&gt;multi
+ ;
+</programlisting>
+
+ <para>
+ When <filename>hello</filename> is built, the two requirements specified
+ above will always be present. If the build request given on the
+ <command>bjam</command> command-line explictly contradicts a target's
+ requirements, the target requirements usually override (or, in the case
+ of &#x201C;free&rdquo;&#x201D; features like
+ <varname>&lt;include&gt;</varname>,
+ <footnote>
+ <para>
+ See <xref linkend="bbv2.reference.features.attributes"/>
+ </para>
+ </footnote>
+ augments) the build request.
+ </para>
+
+ <tip>
+ <para>
+ The value of the <varname>&lt;include&gt;</varname> feature is
+ relative to the location of <filename>Jamroot</filename> where it is
+ used.
+ </para>
+ </tip>
+ </section>
+
+ <section id="bbv2.tutorial.properties.project_attributes">
+ <title>Project Attributes</title>
+
+ <para>
+ If we want the same requirements for our other target, <filename>hello2
+ </filename>, we could simply duplicate them. However, as projects grow,
+ that approach leads to a great deal of repeated boilerplate in Jamfiles.
+
+ Fortunately, there's a better way. Each project can specify a set of
+ <firstterm>attributes</firstterm>, including requirements:
+
+<programlisting>
+project
+ : requirements &lt;include&gt;/home/ghost/Work/boost &lt;threading&gt;multi
+ ;
+
+exe hello : hello.cpp ;
+exe hello2 : hello.cpp ;</programlisting>
+
+ The effect would be as if we specified the same requirement for both
+ <filename>hello</filename> and <filename>hello2</filename>.
+ </para>
+ </section>
+ </section>
+
+ <section id="bbv2.tutorial.hierarchy">
+ <title>Project Hierarchies</title>
+
+ <para>
+ So far we have only considered examples with one project &#x2014;a. with
+ one user-written Boost.Jam file, <filename>Jamroot</filename>). A typical
+ large codebase would be composed of many projects organized into a tree.
+ The top of the tree is called the <firstterm>project root</firstterm>.
+ Every subproject is defined by a file called <filename>Jamfile</filename>
+ in a descendant directory of the project root. The parent project of a
+ subproject is defined by the nearest <filename>Jamfile</filename> or
+ <filename>Jamroot</filename> file in an ancestor directory. For example,
+ in the following directory layout:
+
+<screen>
+top/
+ |
+ +-- Jamroot
+ |
+ +-- app/
+ | |
+ | +-- Jamfile
+ | `-- app.cpp
+ |
+ `-- util/
+ |
+ +-- foo/
+ . |
+ . +-- Jamfile
+ . `-- bar.cpp
+</screen>
+
+ the project root is <filename>top/</filename>. The projects in
+ <filename>top/app/</filename> and <filename>top/util/foo/</filename> are
+ immediate children of the root project.
+
+ <note>
+ <para>
+ When we refer to a &#x201C;Jamfile,&#x201D; set in normal
+ type, we mean a file called either
+ <filename>Jamfile</filename> or
+ <filename>Jamroot</filename>. When we need to be more
+ specific, the filename will be set as
+ &#x201C;<filename>Jamfile</filename>&#x201D; or
+ &#x201C;<filename>Jamroot</filename>.&#x201D;
+ </para>
+ </note>
+ </para>
+
+ <para>
+ Projects inherit all attributes (such as requirements)
+ from their parents. Inherited requirements are combined with
+ any requirements specified by the subproject.
+ For example, if <filename>top/Jamroot</filename> has
+
+<programlisting>
+&lt;include&gt;/home/ghost/local
+</programlisting>
+
+ in its requirements, then all of its subprojects will have it
+ in their requirements, too. Of course, any project can add
+ include paths to those specified by its parents. <footnote>
+ <para>Many
+ features will be overridden,
+ rather than added-to, in subprojects. See <xref
+ linkend="bbv2.reference.features.attributes"/> for more
+ information</para>
+ </footnote>
+ More details can be found in
+ <xref linkend= "bbv2.overview.projects"/>.
+ </para>
+
+ <para>
+ Invoking <command>bjam</command> without explicitly specifying
+ any targets on the command line builds the project rooted in the
+ current directory. Building a project does not automatically
+ cause its subprojects to be built unless the parent project's
+ Jamfile explicitly requests it. In our example,
+ <filename>top/Jamroot</filename> might contain:
+
+<programlisting>
+build-project app ;
+</programlisting>
+
+ which would cause the project in <filename>top/app/</filename>
+ to be built whenever the project in <filename>top/</filename> is
+ built. However, targets in <filename>top/util/foo/</filename>
+ will be built only if they are needed by targets in
+ <filename>top/</filename> or <filename>top/app/</filename>.
+ </para>
+ </section>
+
+ <section id="bbv2.tutorial.libs">
+ <title>Dependent Targets</title>
+
+ <para>
+ When a building a target <filename>X</filename> depends on first
+ building another target <filename>Y</filename> (such as a
+ library that must be linked with <firstterm>X</firstterm>),
+ <filename>Y</filename> is called a
+ <firstterm>dependency</firstterm> of <filename>X</filename> and
+ <filename>X</filename> is termed a
+ <firstterm>dependent</firstterm> of <filename>Y</filename>.
+ </para>
+
+ <para>To get a feeling of target dependencies, let's continue the
+ above example and see how <filename>top/app/Jamfile</filename> can
+ use libraries from <filename>top/util/foo</filename>. If
+ <filename>top/util/foo/Jamfile</filename> contains
+
+<programlisting>
+lib bar : bar.cpp ;
+</programlisting>
+
+ then to use this library in <filename>top/app/Jamfile</filename>, we can
+ write:
+
+<programlisting>
+exe app : app.cpp ../util/foo//bar ;
+</programlisting>
+
+ While <code>app.cpp</code> refers to a regular source file,
+ <code>../util/foo//bar</code> is a reference to another target:
+ a library <filename>bar</filename> declared in the Jamfile at
+ <filename>../util/foo</filename>.
+ </para>
+
+ <tip>
+ <para>Some other build system have special syntax for listing dependent
+ libraries, for example <varname>LIBS</varname> variable. In Boost.Build,
+ you just add the library to the list of sources.
+ </para>
+ </tip>
+
+ <para>Suppose we build <filename>app</filename> with:
+ <screen>
+bjam app optimization=full define=USE_ASM
+ </screen>
+ Which properties will be used to build <code>foo</code>? The answer is
+ that some features are
+ <firstterm>propagated</firstterm>&#x2014;Boost.Build attempts to use
+ dependencies with the same value of propagated features. The
+ <varname>&lt;optimization&gt;</varname> feature is propagated, so both
+ <filename>app</filename> and <filename>foo</filename> will be compiled
+ with full optimization. But <varname>&lt;define&gt;</varname> is not
+ propagated: its value will be added as-is to the compiler flags for
+ <filename>a.cpp</filename>, but won't affect <filename>foo</filename>.
+ </para>
+
+
+ <para>
+ Let's improve this project further. The library probably has some headers
+ that must be used when compiling <filename>app.cpp</filename>. We could
+ manually add the necessary <code>#include</code> paths to <filename>app
+ </filename>'s requirements as values of the <varname>&lt;include&gt;
+ </varname> feature, but then this work will be repeated for all programs
+ that use <filename>foo</filename>. A better solution is to modify
+ <filename>util/foo/Jamfile</filename> in this way:
+
+ <programlisting>
+project
+ : usage-requirements &lt;include&gt;.
+ ;
+
+lib foo : foo.cpp ;</programlisting>
+
+ Usage requirements are applied not to the target being declared but to its
+ dependants. In this case, <literal>&lt;include&gt;.</literal> will be
+ applied to all targets that directly depend on <filename>foo</filename>.
+ </para>
+
+ <para>
+ Another improvement is using symbolic identifiers to refer to the library,
+ as opposed to <filename>Jamfile</filename> location. In a large project, a
+ library can be used by many targets, and if they all use <filename>Jamfile
+ </filename> location, a change in directory organization entails much
+ work. The solution is to use project ids&#x2014;symbolic names not tied to
+ directory layout. First, we need to assign a project id by adding this
+ code to <filename>Jamroot</filename>:
+ </para>
+
+ <programlisting>
+use-project /library-example/foo : util/foo ;</programlisting>
+
+ <para>
+ Second, we modify <filename>app/Jamfile</filename> to use the project id:
+ <programlisting>
+exe app : app.cpp /library-example/foo//bar ;</programlisting>
+
+ The <filename>/library-example/foo//bar</filename> syntax is used to refer
+ to the target <filename>bar</filename> in the project with id <filename>
+ /library-example/foo</filename>. We've achieved our goal&#x2014;if the
+ library is moved to a different directory, only <filename>Jamroot
+ </filename> must be modified. Note that project ids are global&#x2014;two
+ Jamfiles are not allowed to assign the same project id to different
+ directories.
+ </para>
+
+ <tip>
+ <para>If you want all applications in some project to link to a certain
+ library, you can avoid having to specify it directly the sources of
+ every target by using the <varname>&lt;library&gt;</varname> property.
+ For example, if <filename>/boost/filesystem//fs</filename> should be
+ linked to all applications in your project, you can add
+ <code>&lt;library&gt;/boost/filesystem//fs</code> to the project's
+ requirements, like this:
+ </para>
+
+ <programlisting>
+project
+ : requirements &lt;library&gt;/boost/filesystem//fs
+ ;</programlisting>
+ </tip>
+ </section>
+
+ <section id="bbv2.tutorial.linkage">
+ <title>Static and shared libaries</title>
+
+ <para>
+ Libraries can be either <emphasis>static</emphasis>, which means they are
+ included in executable files that use them, or <emphasis>shared</emphasis>
+ (a.k.a. <emphasis>dynamic</emphasis>), which are only referred to from
+ executables, and must be available at run time. Boost.Build can create and
+ use both kinds.
+ </para>
+
+ <para>
+ The kind of library produced from a <code>lib</code> target is determined
+ by the value of the <varname>link</varname> feature. Default value is
+ <literal>shared</literal>, and to build a static library, the value should
+ be <literal>static</literal>. You can request a static build either on the
+ command line:
+ <programlisting>bjam link=static</programlisting>
+ or in the library's requirements:
+ <programlisting>lib l : l.cpp : &lt;link&gt;static ;</programlisting>
+ </para>
+
+ <para>
+ We can also use the <varname>&lt;link&gt;</varname> property to express
+ linking requirements on a per-target basis. For example, if a particular
+ executable can be correctly built only with the static version of a
+ library, we can qualify the executable's <link
+ linkend="bbv2.reference.targets.references">target reference</link> to the
+ library as follows:
+
+<!-- There has been no earlier indication that target references can contain
+ properties. You can't assume that the reader will recognize that strange
+ incantation as a target reference, or that she'll know what it means. You
+ also can't assume that hyperlinks will help the reader, because she may be
+ working from a printout, as I was.
+ VP: to be addressed when this section is moved. See comment below.
+-->
+
+ <programlisting>
+exe important : main.cpp helpers/&lt;link&gt;static ;</programlisting>
+
+ No matter what arguments are specified on the <command>bjam</command>
+ command line, <filename>important</filename> will only be linked with the
+ static version of <filename>helpers</filename>.
+ </para>
+
+ <para>
+ Specifying properties in target references is especially useful if you use
+ a library defined in some other project (one you can't change) but you
+ still want static (or dynamic) linking to that library in all cases. If
+ that library is used by many targets, you <emphasis>could</emphasis> use
+ target references everywhere:
+
+ <programlisting>
+exe e1 : e1.cpp /other_project//bar/&lt;link&gt;static ;
+exe e10 : e10.cpp /other_project//bar/&lt;link&gt;static ;</programlisting>
+
+ but that's far from being convenient. A better approach is to introduce a
+ level of indirection. Create a local <type>alias</type> target that refers
+ to the static (or dynamic) version of <filename>foo</filename>:
+
+ <programlisting>
+alias foo : /other_project//bar/&lt;link&gt;static ;
+exe e1 : e1.cpp foo ;
+exe e10 : e10.cpp foo ;</programlisting>
+
+ The <link linkend="bbv2.tasks.alias"><functionname>alias</functionname>
+ </link> rule is specifically used to rename a reference to a target and
+ possibly change the properties.
+
+ <!-- You should introduce the alias rule in an earlier section, before
+ describing how it applies to this specific use-case, and the
+ foregoing sentence should go there.
+ VP: we've agreed that this section should be moved further in the
+ docs, since it's more like advanced reading. When I move it, I'll
+ make sure 'alias' is already mentioned.
+ -->
+ </para>
+
+ <tip>
+ <para>
+ When one library uses another, you put the second library in the source
+ list of the first. For example:
+ <programlisting>
+lib utils : utils.cpp /boost/filesystem//fs ;
+lib core : core.cpp utils ;
+exe app : app.cpp core ;</programlisting>
+ This works no matter what kind of linking is used. When <filename>core
+ </filename> is built as a shared library, it is linked directly into
+ <filename>utils</filename>. Static libraries can't link to other
+ libraries, so when <filename>core</filename> is built as a static
+ library, its dependency on <filename>utils</filename> is passed along to
+ <filename>core</filename>'s dependents, causing <filename>app</filename>
+ to be linked with both <filename>core</filename> and <filename>utils
+ </filename>.
+ </para>
+ </tip>
+
+ <note>
+ <para>
+ (Note for non-UNIX system). Typically, shared libraries must be
+ installed to a directory in the dynamic linker's search path. Otherwise,
+ applications that use shared libraries can't be started. On Windows, the
+ dynamic linker's search path is given by the <envar>PATH</envar>
+ environment variable. This restriction is lifted when you use
+ Boost.Build testing facilities&#x2014;the <envar>PATH</envar> variable
+ will be automatically adjusted before running the executable.
+ <!-- Need ref here to 'testing facilities' -->
+ </para>
+ </note>
+ </section>
+
+ <section id="bbv2.tutorial.conditions">
+ <title>Conditions and alternatives</title>
+
+ <para>
+ Sometimes, particular relationships need to be maintained among a target's
+ build properties. For example, you might want to set specific <code>
+ #define</code> when a library is built as shared, or when a target's
+ <code>release</code> variant is built. This can be achieved using
+ <firstterm>conditional requirements</firstterm>.
+
+ <programlisting>
+lib network : network.cpp
+ : <emphasis role="bold">&lt;link&gt;shared:&lt;define&gt;NEWORK_LIB_SHARED</emphasis>
+ &lt;variant&gt;release:&lt;define&gt;EXTRA_FAST
+ ;</programlisting>
+
+ In the example above, whenever <filename>network</filename> is built with
+ <code>&lt;link&gt;shared</code>, <code>&lt;define&gt;NEWORK_LIB_SHARED
+ </code> will be in its properties, too. Also, whenever its release variant
+ is built, <code>&lt;define&gt;EXTRA_FAST</code> will appear in its
+ properties.
+ </para>
+
+ <para>
+ Sometimes the ways a target is built are so different that describing them
+ using conditional requirements would be hard. For example, imagine that a
+ library actually uses different source files depending on the toolset used
+ to build it. We can express this situation using <firstterm>target
+ alternatives</firstterm>:
+ <programlisting>
+lib demangler : dummy_demangler.cpp ; # alternative 1
+lib demangler : demangler_gcc.cpp : &lt;toolset&gt;gcc ; # alternative 2
+lib demangler : demangler_msvc.cpp : &lt;toolset&gt;msvc ; # alternative 3</programlisting>
+ When building <filename>demangler</filename>, Boost.Build will compare
+ requirements for each alternative with build properties to find the best
+ match. For example, when building with <code>&lt;toolset&gt;gcc</code>
+ alternative 2, will be selected, and when building with
+ <code>&lt;toolset&gt;msvc</code> alternative 3 will be selected. In all
+ other cases, the most generic alternative 1 will be built.
+ </para>
+ </section>
+
+ <section id="bbv2.tutorial.prebuilt">
+ <title>Prebuilt targets</title>
+
+ <para>
+ To link to libraries whose build instructions aren't given in a Jamfile,
+ you need to create <code>lib</code> targets with an appropriate
+ <varname>file</varname> property. Target alternatives can be used to
+ associate multiple library files with a single conceptual target. For
+ example:
+ <programlisting>
+# util/lib2/Jamfile
+lib lib2
+ :
+ : &lt;file&gt;lib2_release.a &lt;variant&gt;release
+ ;
+
+lib lib2
+ :
+ : &lt;file&gt;lib2_debug.a &lt;variant&gt;debug
+ ;</programlisting>
+
+ This example defines two alternatives for <filename>lib2</filename>, and
+ for each one names a prebuilt file. Naturally, there are no sources.
+ Instead, the <varname>&lt;file&gt;</varname> feature is used to specify
+ the file name.
+ </para>
+
+ <para>
+ Once a prebuilt target has been declared, it can be used just like any
+ other target:
+
+ <programlisting>
+exe app : app.cpp ../util/lib2//lib2 ;</programlisting>
+
+ As with any target, the alternative selected depends on the properties
+ propagated from <filename>lib2</filename>'s dependants. If we build the
+ release and debug versions of <filename>app</filename> will be linked
+ with <filename>lib2_release.a</filename> and <filename>lib2_debug.a
+ </filename>, respectively.
+ </para>
+
+ <para>
+ System libraries&#x2014;those that are automatically found by the toolset
+ by searching through some set of predetermined paths&#x2014;should be
+ declared almost like regular ones:
+
+ <programlisting>
+lib pythonlib : : &lt;name&gt;python22 ;</programlisting>
+
+ We again don't specify any sources, but give a <varname>name</varname>
+ that should be passed to the compiler. If the gcc toolset were used to
+ link an executable target to <filename>pythonlib</filename>,
+ <option>-lpython22</option> would appear in the command line (other
+ compilers may use different options).
+ </para>
+
+ <para>
+ We can also specify where the toolset should look for the library:
+
+ <programlisting>
+lib pythonlib : : &lt;name&gt;python22 &lt;search&gt;/opt/lib ;</programlisting>
+
+ And, of course, target alternatives can be used in the usual way:
+
+ <programlisting>
+lib pythonlib : : &lt;name&gt;python22 &lt;variant&gt;release ;
+lib pythonlib : : &lt;name&gt;python22_d &lt;variant&gt;debug ;</programlisting>
+ </para>
+
+ <para>
+ A more advanced use of prebuilt targets is described in <xref linkend=
+ "bbv2.recipies.site-config"/>.
+ </para>
+ </section>
+</chapter>
+
+<!--
+ Local Variables:
+ mode: nxml
+ sgml-indent-data:t
+ sgml-parent-document:("userman.xml" "chapter")
+ sgml-set-face: t
+ sgml-omittag:nil
+ sgml-shorttag:nil
+ sgml-namecase-general:t
+ sgml-general-insert-case:lower
+ sgml-minimize-attributes:nil
+ sgml-always-quote-attributes:t
+ sgml-indent-step:2
+ sgml-exposed-tags:nil
+ sgml-local-catalogs:nil
+ sgml-local-ecat-files:nil
+ End:
+-->
diff --git a/tools/build/v2/doc/src/userman.xml b/tools/build/v2/doc/src/userman.xml
new file mode 100644
index 0000000000..c8f6b685f4
--- /dev/null
+++ b/tools/build/v2/doc/src/userman.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE part PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+<part xmlns:xi="http://www.w3.org/2001/XInclude"
+ id="bbv2" last-revision="$Date: 2011-01-25 13:06:12 -0500 (Tue, 25 Jan 2011) $">
+ <partinfo>
+ <copyright>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <holder>Vladimir Prus</holder>
+ </copyright>
+
+ <legalnotice>
+ <para>Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
+ <ulink
+ url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
+ </para>
+ </legalnotice>
+ </partinfo>
+
+ <title>Boost.Build V2 User Manual</title>
+
+ <!-- Chapters -->
+ <xi:include href="howto.xml"/>
+ <xi:include href="install.xml"/>
+ <xi:include href="tutorial.xml"/>
+ <xi:include href="overview.xml"/>
+ <xi:include href="tasks.xml"/>
+ <xi:include href="reference.xml"/>
+ <xi:include href="extending.xml"/>
+ <xi:include href="faq.xml"/>
+
+ <!-- Appendicies -->
+<!-- <xi:include href="architecture.xml"/> -->
+
+</part>
diff --git a/tools/build/v2/doc/tools.html b/tools/build/v2/doc/tools.html
new file mode 100644
index 0000000000..8b4929d290
--- /dev/null
+++ b/tools/build/v2/doc/tools.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<!-- Copyright 2004 Aleksey Gurtovoy -->
+<!-- Copyright 2003, 2004 Vladimir Prus -->
+<!-- Distributed under the Boost Software License, Version 1.0. -->
+<!-- (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) -->
+
+<html>
+ <head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st April 2002), see www.w3.org">
+ <meta name="generator" content="Microsoft FrontPage 5.0">
+ <meta http-equiv="Content-Type" content=
+ "text/html; charset=windows-1252">
+ <!-- tidy options: &dash;&dash;tidy-mark false -i -wrap 78 !-->
+
+ <title>Boost Build System V2 &mdash; supported tools</title>
+ </head>
+
+ <body bgcolor="#FFFFFF" text="#000000">
+ <img src="../../../../boost.png" alt="boost.png (6897 bytes)" align="center"
+ width="277" height="86"> <a href="http://sourceforge.net"><img src=
+ "http://sourceforge.net/sflogo.php?group_id=7586&amp;type=1" width="88"
+ height="31" border="0" alt="SourceForge.net Logo" align="right"></a>
+
+ <h1>Boost Build System V2 &mdash; supported tools</h1>
+
+ <h2>Compilers</h2>
+
+ <p>The following compilers are supported:</p>
+
+ <ul>
+ <li>GNU gcc (various versions), on Linux, NT, Cygwin and Darwin.</li>
+
+ <li>Microsoft VC++ compiler (various version), on NT and Cygwin.</li>
+
+ <li>Borland's compiler, on NT and Cygwin.</li>
+
+ <li>Metrowerks Code Warrior, on NT.</li>
+
+ <li>Intel C++ Compiler, on Linux and NT.</li>
+
+ <li>Sun's C++ Compiler.</li>
+
+ </ul>
+
+ <h2>Libraries</h2>
+
+ <p>Some important libraries have special support in Boost.Build:</p>
+
+ <ul>
+ <li><a href="http://stlport.sourceforge.net">STLport</a> &mdash; on gcc and
+ msvc.</li>
+
+ <li><a href="http://www.trolltech.com/products/qt/index.html">QT</a>,
+ including the <tt>moc</tt> and <tt>uic</tt> tools &mdash; on gcc and msvc.</li>
+ </ul>
+
+ <h2>Other tools</h2>
+
+ <ul>
+ <li>Parser/lexer generators <tt>bison</tt> and <tt>lex</tt>.</li>
+
+ <li>XSLT processor <a href=
+ "http://xmlsoft.org/XSLT/">xsltproc</a>.</li>
+
+ <li>The Apache <a href="http://xml.apache.org/fop/index.html">FOP</a>
+ tool.</li>
+
+ <li>BoostBook documentation format.</li>
+
+ <li>GNU <a href=
+ "http://www.gnu.org/software/gettext/gettext.html">gettext</a>
+ internationalization tools.</li>
+ </ul>
+ <hr>
+
+ <p>&copy; Copyright Vladimir Prus 2003. Permission to copy, use, modify,
+ sell and distribute this document is granted provided this copyright
+ notice appears in all copies. This document is provided "as is" without
+ express or implied warranty, and with no claim as to its suitability for
+ any purpose.</p>
+
+ <p>Revised
+ <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
+ -->Jule 3, 2003
+ <!--webbot bot="Timestamp" endspan i-checksum="13972"
+ -->
+ </p>
+ </body>
+</html>
+
diff --git a/tools/build/v2/engine/Jambase b/tools/build/v2/engine/Jambase
new file mode 100644
index 0000000000..94f8fbde5c
--- /dev/null
+++ b/tools/build/v2/engine/Jambase
@@ -0,0 +1,2473 @@
+#
+# /+\
+# +\ Copyright 1993, 2000 Christopher Seiwald.
+# \+/
+#
+# This file is part of Jam - see jam.c for Copyright information.
+#
+
+# This file is ALSO:
+# Copyright 2001-2004 David Abrahams.
+# Copyright 2002-2004 Rene Rivera.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+if $(NT)
+{
+ SLASH ?= \\ ;
+}
+SLASH ?= / ;
+
+
+# Glob for patterns in the directories starting from the given start directory,
+# up to and including the root of the file-system. We stop globbing as soon as
+# we find at least one match.
+#
+rule find-to-root ( dir : patterns + )
+{
+ local globs = [ GLOB $(dir) : $(patterns) ] ;
+ while ! $(globs) && $(dir:P) != $(dir)
+ {
+ dir = $(dir:P) ;
+ globs = [ GLOB $(dir) : $(patterns) ] ;
+ }
+ return $(globs) ;
+}
+
+
+# This global will hold the location of the user's boost-build.jam file.
+.boost-build-file = ;
+
+# This global will hold the location of the build system bootstrap file.
+.bootstrap-file = ;
+
+# Remember the value of $(BOOST_BUILD_PATH) supplied to us by the user.
+BOOST_BUILD_PATH.user-value = $(BOOST_BUILD_PATH) ;
+
+# On Unix only, when BOOST_BUILD_PATH is not supplied by the user, set it to a
+# sensible default value. This allows Boost.Build to work without any
+# environment variables, which is good in itself and also required by the Debian
+# Policy.
+if ! $(BOOST_BUILD_PATH) && $(UNIX)
+{
+ BOOST_BUILD_PATH = /usr/share/boost-build ;
+}
+
+
+rule _poke ( module-name ? : variables + : value * )
+{
+ module $(<)
+ {
+ $(>) = $(3) ;
+ }
+}
+
+
+# This rule can be invoked from an optional user's boost-build.jam file to both
+# indicate where to find the build system files, and to load them. The path
+# indicated is relative to the location of the boost-build.jam file.
+#
+rule boost-build ( dir ? )
+{
+ if $(.bootstrap-file)
+ {
+ ECHO "Error: Illegal attempt to re-bootstrap the build system by invoking" ;
+ ECHO ;
+ ECHO " 'boost-build" $(dir) ";'" ;
+ ECHO ;
+ EXIT "Please consult the documentation at 'http://www.boost.org'." ;
+ }
+
+ # Add the given directory to the path so we can find the build system. If
+ # dir is empty, has no effect.
+ BOOST_BUILD_PATH = $(dir:R=$(.boost-build-file:D)) $(BOOST_BUILD_PATH) ;
+
+ # We might have just modified the *global* value of BOOST_BUILD_PATH. The
+ # code that loads the rest of Boost.Build, in particular the site-config.jam
+ # and user-config.jam configuration files uses os.environ, so we need to
+ # update the value there.
+ _poke .ENVIRON : BOOST_BUILD_PATH : $(BOOST_BUILD_PATH) ;
+
+ # Try to find the build system bootstrap file 'bootstrap.jam'.
+ local bootstrap-file = [ GLOB $(BOOST_BUILD_PATH) : bootstrap.jam ] ;
+ .bootstrap-file = $(bootstrap-file[1]) ;
+
+ # There is no bootstrap.jam we can find, exit with an error.
+ if ! $(.bootstrap-file)
+ {
+ ECHO "Unable to load Boost.Build: could not find build system." ;
+ ECHO --------------------------------------------------------- ;
+ ECHO "$(.boost-build-file) attempted to load the build system by invoking" ;
+ ECHO ;
+ ECHO " 'boost-build" $(dir) ";'" ;
+ ECHO ;
+ ECHO "but we were unable to find \"bootstrap.jam\" in the specified directory" ;
+ ECHO "or in BOOST_BUILD_PATH (searching "$(BOOST_BUILD_PATH:J=", ")")." ;
+ ECHO ;
+ EXIT "Please consult the documentation at 'http://www.boost.org'." ;
+ }
+
+ if [ MATCH .*(--debug-configuration).* : $(ARGV) ]
+ {
+ ECHO "notice: loading Boost.Build from"
+ [ NORMALIZE_PATH $(.bootstrap-file:D) ] ;
+ }
+
+ # Load the build system, now that we know where to start from.
+ include $(.bootstrap-file) ;
+}
+
+
+if [ MATCH .*(b2).* : $(ARGV[1]:BL) ]
+ || [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]
+ || $(BOOST_ROOT) # A temporary measure so Jam works with Boost.Build v1.
+{
+ # We attempt to load "boost-build.jam" by searching from the current
+ # invocation directory up to the root of the file-system.
+ #
+ # boost-build.jam is expected to invoke the "boost-build" rule to load the
+ # Boost.Build files.
+
+ local search-path = $(BOOST_BUILD_PATH) $(BOOST_ROOT) ;
+ local self = [ SELF_PATH ] ;
+ local boost-build-relative = ../../share/boost-build ;
+ local self-based-path = [ NORMALIZE_PATH $(boost-build-relative:R=$(self)) ] ;
+
+ local boost-build-files =
+ [ find-to-root [ PWD ] : boost-build.jam ]
+ [ GLOB $(self-based-path) : boost-build.jam ]
+ # Another temporary measure so Jam works with Boost.Build v1.
+ [ GLOB $(search-path) : boost-build.jam ] ;
+
+ .boost-build-file = $(boost-build-files[1]) ;
+
+ # There is no boost-build.jam we can find, exit with an error, and
+ # information.
+ if ! $(.boost-build-file)
+ {
+ ECHO "Unable to load Boost.Build: could not find \"boost-build.jam\"" ;
+ ECHO --------------------------------------------------------------- ;
+
+ if ! [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]
+ {
+ ECHO "BOOST_ROOT must be set, either in the environment, or " ;
+ ECHO "on the command-line with -sBOOST_ROOT=..., to the root" ;
+ ECHO "of the boost installation." ;
+ ECHO ;
+ }
+
+ ECHO "Attempted search from" [ PWD ] "up to the root" ;
+ ECHO "at" $(self-based-path) ;
+ ECHO "and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: "$(search-path:J=", ")"." ;
+ EXIT "Please consult the documentation at 'http://www.boost.org'." ;
+ }
+
+ if [ MATCH .*(--debug-configuration).* : $(ARGV) ]
+ {
+ ECHO "notice: found boost-build.jam at"
+ [ NORMALIZE_PATH $(.boost-build-file) ] ;
+ }
+
+ # Now load the boost-build.jam to get the build system loaded. This
+ # incidentaly loads the users jamfile and attempts to build targets.
+ #
+ # We also set it up so we can tell whether we are loading the new V2 system
+ # or the the old V1 system.
+ include $(.boost-build-file) ;
+
+ # Check that, at minimum, the bootstrap file was found.
+ if ! $(.bootstrap-file)
+ {
+ ECHO "Unable to load Boost.Build" ;
+ ECHO -------------------------- ;
+ ECHO "\"$(.boost-build-file)\" was found by searching from" [ PWD ] "up to the root" ;
+ ECHO "and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: "$(search-path:J=", ")"." ;
+ ECHO ;
+ ECHO "However, it failed to call the \"boost-build\" rule to indicate" ;
+ ECHO "the location of the build system." ;
+ ECHO ;
+ EXIT "Please consult the documentation at 'http://www.boost.org'." ;
+ }
+}
+else
+{
+
+#
+# JAMBASE - jam 2.3 ruleset providing make(1)-like functionality
+#
+# Supports UNIX, NT, and VMS.
+#
+# 12/27/93 (seiwald) - purturb library sources with SOURCE_GRIST
+# 04/18/94 (seiwald) - use '?=' when setting OS specific vars
+# 04/21/94 (seiwald) - do RmTemps together
+# 05/05/94 (seiwald) - all supported C compilers support -o: relegate
+# RELOCATE as an option; set Ranlib to "" to disable it
+# 06/01/94 (seiwald) - new 'actions existing' to do existing sources
+# 08/25/94 (seiwald) - new ObjectCcFlags rule to append to per-target CCFLAGS
+# 08/29/94 (seiwald) - new ObjectHdrs rule to append to per-target HDRS
+# 09/19/94 (seiwald) - LinkLibraries and Undefs now append
+# - Rule names downshifted.
+# 10/06/94 (seiwald) - Dumb yyacc stuff moved into Jamfile.
+# 10/14/94 (seiwald) - (Crude) support for .s, .C, .cc, .cpp, and .f files.
+# 01/08/95 (seiwald) - Shell now handled with awk, not sed
+# 01/09/95 (seiwald) - Install* now take dest directory as target
+# 01/10/95 (seiwald) - All entries sorted.
+# 01/10/95 (seiwald) - NT support moved in, with LauraW's help.
+# 01/10/95 (seiwald) - VMS support moved in.
+# 02/06/95 (seiwald) - ObjectC++Flags and SubDirC++Flags added.
+# 02/07/95 (seiwald) - Iron out when HDRSEARCH uses "" or SEARCH_SOURCE.
+# 02/08/95 (seiwald) - SubDir works on VMS.
+# 02/14/95 (seiwald) - MkDir and entourage.
+# 04/30/95 (seiwald) - Use install -c flag so that it copies, not moves.
+# 07/10/95 (taylor) - Support for Microsoft C++.
+# 11/21/96 (peterk) - Support for BeOS
+# 07/19/99 (sickel) - Support for Mac OS X Server (and maybe client)
+# 02/18/00 (belmonte)- Support for Cygwin.
+
+# Special targets defined in this file:
+#
+# all - parent of first, shell, files, lib, exe
+# first - first dependency of 'all', for potential initialization
+# shell - parent of all Shell targets
+# files - parent of all File targets
+# lib - parent of all Library targets
+# exe - parent of all Main targets
+# dirs - parent of all MkDir targets
+# clean - removes all Shell, File, Library, and Main targets
+# uninstall - removes all Install targets
+#
+
+# Rules defined by this file:
+#
+# as obj.o : source.s ; .s -> .o
+# Bulk dir : files ; populate directory with many files
+# Cc obj.o : source.c ; .c -> .o
+# C++ obj.o : source.cc ; .cc -> .o
+# Clean clean : sources ; remove sources with 'jam clean'
+# File dest : source ; copy file
+# Fortran obj.o : source.f ; .f -> .o
+# GenFile source.c : program args ; make custom file
+# Hardlink target : source ; make link from source to target
+# HdrRule source : headers ; handle #includes
+# InstallInto dir : sources ; install any files
+# InstallBin dir : sources ; install binaries
+# InstallLib dir : sources ; install files
+# InstallFile dir : sources ; install files
+# InstallMan dir : sources ; install man pages
+# InstallShell dir : sources ; install shell scripts
+# Lex source.c : source.l ; .l -> .c
+# Library lib : source ; archive library from compiled sources
+# LibraryFromObjects lib : objects ; archive library from objects
+# LinkLibraries images : libraries ; bag libraries onto Mains
+# Main image : source ; link executable from compiled sources
+# MainFromObjects image : objects ; link executable from objects
+# MkDir dir ; make a directory, if not there
+# Object object : source ; compile object from source
+# ObjectCcFlags source : flags ; add compiler flags for object
+# ObjectC++Flags source : flags ; add compiler flags for object
+# ObjectHdrs source : dirs ; add include directories for object
+# Objects sources ; compile sources
+# RmTemps target : sources ; remove temp sources after target made
+# Setuid images ; mark executables Setuid
+# SubDir TOP d1 d2 ... ; start a subdirectory Jamfile
+# SubDirCcFlags flags ; add compiler flags until next SubDir
+# SubDirC++Flags flags ; add compiler flags until next SubDir
+# SubDirHdrs dirs ; add include dirs until next SubDir
+# SubInclude TOP d1 d2 ... ; include a subdirectory Jamfile
+# Shell exe : source ; make a shell executable
+# Undefines images : symbols ; save undef's for linking
+# UserObject object : source ; handle unknown suffixes for Object
+# Yacc source.c : source.y ; .y -> .c
+#
+# Utility rules that have no side effects (not supported):
+#
+# FAppendSuffix f1 f2 ... : $(SUF) ; return $(<) with suffixes
+# FConcat value ... ; return contatenated values
+# FDirName d1 d2 ... ; return path from root to dir
+# FGrist d1 d2 ... ; return d1!d2!...
+# FGristFiles value ; return $(value:G=$(SOURCE_GRIST))
+# FGristSourceFiles value ; return $(value:G=$(SOURCE_GRIST))
+# FRelPath d1 : d2 ; return rel path from d1 to d2
+# FSubDir d1 d2 ... ; return path to root
+#
+
+
+# Brief review of the jam language:
+#
+# Statements:
+# rule RULE - statements to process a rule
+# actions RULE - system commands to carry out target update
+#
+# Modifiers on actions:
+# together - multiple instances of same rule on target get executed
+# once with their sources ($(>)) concatenated
+# updated - refers to updated sources ($(>)) only
+# ignore - ignore return status of command
+# quietly - don't trace its execution unless verbose
+# piecemeal - iterate command each time with a small subset of $(>)
+# existing - refers to currently existing sources ($(>)) only
+# bind vars - subject to binding before expanding in actions
+#
+# Special rules:
+# ALWAYS - always build a target
+# DEPENDS - builds the dependency graph
+# ECHO - blurt out targets on stdout
+# EXIT - blurt out targets and exit
+# INCLUDES - marks sources as headers for target (a codependency)
+# NOCARE - don't panic if the target can't be built
+# NOUPDATE - create the target if needed but never update it
+# NOTFILE - ignore the timestamp of the target (it's not a file)
+# TEMPORARY - target need not be present if sources haven't changed
+#
+# Special variables set by jam:
+# $(<) - targets of a rule (to the left of the :)
+# $(>) - sources of a rule (to the right of the :)
+# $(xxx) - true on xxx (UNIX, VMS, NT, OS2, MAC)
+# $(OS) - name of OS - varies wildly
+# $(JAMVERSION) - version number (2.3)
+#
+# Special variables used by jam:
+# SEARCH - where to find something (used during binding and actions)
+# LOCATE - where to plop something not found with SEARCH
+# HDRRULE - rule to call to handle include files
+# HDRSCAN - egrep regex to extract include files
+#
+# Special targets:
+# all - default if none given on command line
+#
+
+# Initialize variables
+#
+
+#
+# OS specific variable settings
+#
+if $(NT)
+{
+ # the list of supported toolsets on Windows NT and Windows 95/98
+ #
+ local SUPPORTED_TOOLSETS = "BORLANDC" "VC7" "VISUALC" "VISUALC16" "INTELC" "WATCOM"
+ "MINGW" "LCC" ;
+
+ # this variable holds the current toolset
+ #
+ TOOLSET = "" ;
+
+ # if the JAM_TOOLSET environment variable is defined, check that it is
+ # one of our supported values
+ #
+ if $(JAM_TOOLSET)
+ {
+ local t ;
+
+ for t in $(SUPPORTED_TOOLSETS)
+ {
+ $(t) = $($(t):J=" ") ; # reconstitute paths with spaces in them
+ if $(t) = $(JAM_TOOLSET) { TOOLSET = $(t) ; }
+ }
+
+ if ! $(TOOLSET)
+ {
+ ECHO "The JAM_TOOLSET environment variable is defined but its value" ;
+ ECHO "is invalid, please use one of the following:" ;
+ ECHO ;
+
+ for t in $(SUPPORTED_TOOLSETS) { ECHO " " $(t) ; }
+ EXIT ;
+ }
+ }
+
+ # if TOOLSET is empty, we'll try to detect the toolset from other
+ # environment variables to remain backwards compatible with Jam 2.3
+ #
+ if ! $(TOOLSET)
+ {
+ if $(BCCROOT)
+ {
+ TOOLSET = BORLANDC ;
+ BORLANDC = $(BCCROOT:J=" ") ;
+ }
+ else if $(MSVC)
+ {
+ TOOLSET = VISUALC16 ;
+ VISUALC16 = $(MSVC:J=" ") ;
+ }
+ else if $(MSVCNT)
+ {
+ TOOLSET = VISUALC ;
+ VISUALC = $(MSVCNT:J=" ") ;
+ }
+ else if $(MSVCDir)
+ {
+ TOOLSET = VISUALC ;
+ VISUALC = $(MSVCDir:J=" ") ;
+ }
+ else if $(MINGW)
+ {
+ TOOLSET = MINGW ;
+ }
+ else
+ {
+ ECHO "Jam cannot be run because, either:" ;
+ ECHO " a. You didn't set BOOST_ROOT to indicate the root of your" ;
+ ECHO " Boost installation." ;
+ ECHO " b. You are trying to use stock Jam but didn't indicate which" ;
+ ECHO " compilation toolset to use. To do so, follow these simple" ;
+ ECHO " instructions:" ;
+ ECHO ;
+ ECHO " - define one of the following environment variable, with the" ;
+ ECHO " appropriate value according to this list:" ;
+ ECHO ;
+ ECHO " Variable Toolset Description" ;
+ ECHO ;
+ ECHO " BORLANDC Borland C++ BC++ install path" ;
+ ECHO " VISUALC Microsoft Visual C++ VC++ install path" ;
+ ECHO " VISUALC16 Microsoft Visual C++ 16 bit VC++ 16 bit install" ;
+ ECHO " INTELC Intel C/C++ IC++ install path" ;
+ ECHO " WATCOM Watcom C/C++ Watcom install path" ;
+ ECHO " MINGW MinGW (gcc) MinGW install path" ;
+ ECHO " LCC Win32-LCC LCC-Win32 install path" ;
+ ECHO ;
+ ECHO " - define the JAM_TOOLSET environment variable with the *name*" ;
+ ECHO " of the toolset variable you want to use." ;
+ ECHO ;
+ ECHO " e.g.: set VISUALC=C:\\Visual6" ;
+ ECHO " set JAM_TOOLSET=VISUALC" ;
+ EXIT ;
+ }
+ }
+
+ CP ?= copy ;
+ RM ?= del /f/q ;
+ SLASH ?= \\ ;
+ SUFLIB ?= .lib ;
+ SUFOBJ ?= .obj ;
+ SUFEXE ?= .exe ;
+
+ if $(TOOLSET) = BORLANDC
+ {
+ ECHO "Compiler is Borland C++" ;
+
+ AR ?= tlib /C /P64 ;
+ CC ?= bcc32 ;
+ CCFLAGS ?= -q -y -d -v -w-par -w-ccc -w-rch -w-pro -w-aus ;
+ C++ ?= bcc32 ;
+ C++FLAGS ?= -q -y -d -v -w-par -w-ccc -w-rch -w-pro -w-aus -P ;
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= $(CCFLAGS) ;
+ STDLIBPATH ?= $(BORLANDC)\\lib ;
+ STDHDRS ?= $(BORLANDC)\\include ;
+ NOARSCAN ?= true ;
+ }
+ else if $(TOOLSET) = VISUALC16
+ {
+ ECHO "Compiler is Microsoft Visual C++ 16 bit" ;
+
+ AR ?= lib /nologo ;
+ CC ?= cl /nologo ;
+ CCFLAGS ?= /D \"WIN\" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= $(CCFLAGS) ;
+ LINKLIBS ?=
+ \"$(VISUALC16)\\lib\\mlibce.lib\"
+ \"$(VISUALC16)\\lib\\oldnames.lib\"
+ ;
+ LINKLIBS ?= ;
+ NOARSCAN ?= true ;
+ OPTIM ?= "" ;
+ STDHDRS ?= $(VISUALC16)\\include ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = VISUALC
+ {
+ ECHO "Compiler is Microsoft Visual C++" ;
+
+ AR ?= lib ;
+ AS ?= masm386 ;
+ CC ?= cl /nologo ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= link /nologo ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= \"$(VISUALC)\\lib\\advapi32.lib\"
+ # $(VISUALC)\\lib\\libc.lib
+ # $(VISUALC)\\lib\\oldnames.lib
+ \"$(VISUALC)\\lib\\gdi32.lib\"
+ \"$(VISUALC)\\lib\\user32.lib\"
+ \"$(VISUALC)\\lib\\kernel32.lib\" ;
+ OPTIM ?= "" ;
+ STDHDRS ?= $(VISUALC)\\include ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = VC7
+ {
+ ECHO "Compiler is Microsoft Visual C++ .NET" ;
+
+ AR ?= lib ;
+ AS ?= masm386 ;
+ CC ?= cl /nologo ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= link /nologo ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= \"$(VISUALC)\\PlatformSDK\\lib\\advapi32.lib\"
+ # $(VISUALC)\\lib\\libc.lib
+ # $(VISUALC)\\lib\\oldnames.lib
+ \"$(VISUALC)\\PlatformSDK\\lib\\gdi32.lib\"
+ \"$(VISUALC)\\PlatformSDK\\lib\\user32.lib\"
+ \"$(VISUALC)\\PlatformSDK\\lib\\kernel32.lib\" ;
+ OPTIM ?= "" ;
+ STDHDRS ?= \"$(VISUALC)\\include\"
+ \"$(VISUALC)\\PlatformSDK\\include\" ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = INTELC
+ {
+ ECHO "Compiler is Intel C/C++" ;
+
+ if ! $(VISUALC)
+ {
+ ECHO "As a special exception, when using the Intel C++ compiler, you need" ;
+ ECHO "to define the VISUALC environment variable to indicate the location" ;
+ ECHO "of your Visual C++ installation. Aborting.." ;
+ EXIT ;
+ }
+
+ AR ?= lib ;
+ AS ?= masm386 ;
+ CC ?= icl /nologo ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= link /nologo ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= $(VISUALC)\\lib\\advapi32.lib
+ # $(VISUALC)\\lib\\libc.lib
+ # $(VISUALC)\\lib\\oldnames.lib
+ $(VISUALC)\\lib\\kernel32.lib
+ ;
+ OPTIM ?= "" ;
+ STDHDRS ?= $(INTELC)\include $(VISUALC)\\include ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = WATCOM
+ {
+ ECHO "Compiler is Watcom C/C++" ;
+
+ AR ?= wlib ;
+ CC ?= wcc386 ;
+ CCFLAGS ?= /zq /DWIN32 /I$(WATCOM)\\h ; # zq=quiet
+ C++ ?= wpp386 ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ CP ?= copy ;
+ DOT ?= . ;
+ DOTDOT ?= .. ;
+ LINK ?= wcl386 ;
+ LINKFLAGS ?= /zq ; # zq=quiet
+ LINKLIBS ?= ;
+ MV ?= move ;
+ NOARSCAN ?= true ;
+ OPTIM ?= ;
+ RM ?= del /f ;
+ SLASH ?= \\ ;
+ STDHDRS ?= $(WATCOM)\\h $(WATCOM)\\h\\nt ;
+ SUFEXE ?= .exe ;
+ SUFLIB ?= .lib ;
+ SUFOBJ ?= .obj ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = MINGW
+ {
+ ECHO "Compiler is GCC with Mingw" ;
+
+ AR ?= ar -ru ;
+ CC ?= gcc ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= "" ;
+ OPTIM ?= ;
+ SUFOBJ = .o ;
+ SUFLIB = .a ;
+ SLASH = / ;
+# NOARSCAN ?= true ;
+ }
+ else if $(TOOLSET) = LCC
+ {
+ ECHO "Compiler is Win32-LCC" ;
+
+ AR ?= lcclib ;
+ CC ?= lcc ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= lcclnk ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= "" ;
+ OPTIM ?= ;
+ NOARSCAN = true ;
+ }
+ else
+ {
+#
+# XXX: We need better comments here !!
+#
+ EXIT On NT, set BCCROOT, MSVCNT, MINGW or MSVC to the root of the
+ Borland or Microsoft directories. ;
+ }
+
+}
+else if $(OS2)
+{
+ # the list of supported toolsets on Windows NT and Windows 95/98
+ #
+ local SUPPORTED_TOOLSETS = "EMX" "WATCOM" ;
+
+ # this variable holds the current toolset
+ #
+ TOOLSET = "" ;
+
+ # if the JAM_TOOLSET environment variable is defined, check that it is
+ # one of our supported values
+ #
+ if $(JAM_TOOLSET)
+ {
+ local t ;
+
+ for t in $(SUPPORTED_TOOLSETS)
+ {
+ $(t) = $($(t):J=" ") ; # reconstitute paths with spaces in them
+ if $(t) = $(JAM_TOOLSET) { TOOLSET = $(t) ; }
+ }
+
+ if ! $(TOOLSET)
+ {
+ ECHO "The JAM_TOOLSET environment variable is defined but its value" ;
+ ECHO "is invalid, please use one of the following:" ;
+ ECHO ;
+
+ for t in $(SUPPORTED_TOOLSETS) { ECHO " " $(t) ; }
+ EXIT ;
+ }
+ }
+
+ # if TOOLSET is empty, we'll try to detect the toolset from other
+ # environment variables to remain backwards compatible with Jam 2.3
+ #
+ if ! $(TOOLSET)
+ {
+ if $(watcom)
+ {
+ WATCOM = $(watcom:J=" ") ;
+ TOOLSET = WATCOM ;
+ }
+ else
+ {
+ ECHO "Jam cannot be run because you didn't indicate which compilation toolset" ;
+ ECHO "to use. To do so, follow these simple instructions:" ;
+ ECHO ;
+ ECHO " - define one of the following environment variable, with the" ;
+ ECHO " appropriate value according to this list:" ;
+ ECHO ;
+ ECHO " Variable Toolset Description" ;
+ ECHO ;
+ ECHO " WATCOM Watcom C/C++ Watcom install path" ;
+ ECHO " EMX EMX (gcc) EMX install path" ;
+ ECHO " VISUALAGE IBM Visual Age C/C++ VisualAge install path" ;
+ ECHO ;
+ ECHO " - define the JAM_TOOLSET environment variable with the *name*" ;
+ ECHO " of the toolset variable you want to use." ;
+ ECHO ;
+ ECHO " e.g.: set WATCOM=C:\WATCOM" ;
+ ECHO " set JAM_TOOLSET=WATCOM" ;
+ ECHO ;
+ EXIT ;
+ }
+ }
+
+ RM = del /f ;
+ CP = copy ;
+ MV ?= move ;
+ DOT ?= . ;
+ DOTDOT ?= .. ;
+ SUFLIB ?= .lib ;
+ SUFOBJ ?= .obj ;
+ SUFEXE ?= .exe ;
+
+ if $(TOOLSET) = WATCOM
+ {
+ AR ?= wlib ;
+ BINDIR ?= \\os2\\apps ;
+ CC ?= wcc386 ;
+ CCFLAGS ?= /zq /DOS2 /I$(WATCOM)\\h ; # zq=quiet
+ C++ ?= wpp386 ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= wcl386 ;
+ LINKFLAGS ?= /zq ; # zq=quiet
+ LINKLIBS ?= ;
+ NOARSCAN ?= true ;
+ OPTIM ?= ;
+ SLASH ?= \\ ;
+ STDHDRS ?= $(WATCOM)\\h ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = EMX
+ {
+ ECHO "Compiler is GCC-EMX" ;
+ AR ?= ar -ru ;
+ CC ?= gcc ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= "" ;
+ OPTIM ?= ;
+ SUFOBJ = .o ;
+ SUFLIB = .a ;
+ UNDEFFLAG ?= "-U" ;
+ SLASH = / ;
+# NOARSCAN ?= true ;
+ }
+ else
+ {
+ # should never happen
+ EXIT "Sorry, but the $(JAM_TOOLSET) toolset isn't supported for now" ;
+ }
+}
+else if $(VMS)
+{
+ C++ ?= cxx ;
+ C++FLAGS ?= ;
+ CC ?= cc ;
+ CCFLAGS ?= ;
+ CHMOD ?= set file/prot= ;
+ CP ?= copy/replace ;
+ CRELIB ?= true ;
+ DOT ?= [] ;
+ DOTDOT ?= [-] ;
+ EXEMODE ?= (w:e) ;
+ FILEMODE ?= (w:r) ;
+ HDRS ?= ;
+ LINK ?= link ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= ;
+ MKDIR ?= create/dir ;
+ MV ?= rename ;
+ OPTIM ?= "" ;
+ RM ?= delete ;
+ RUNVMS ?= mcr ;
+ SHELLMODE ?= (w:er) ;
+ SLASH ?= . ;
+ STDHDRS ?= decc$library_include ;
+ SUFEXE ?= .exe ;
+ SUFLIB ?= .olb ;
+ SUFOBJ ?= .obj ;
+
+ switch $(OS)
+ {
+ case OPENVMS : CCFLAGS ?= /stand=vaxc ;
+ case VMS : LINKLIBS ?= sys$library:vaxcrtl.olb/lib ;
+ }
+}
+else if $(MAC)
+{
+ local OPT ;
+
+ CW ?= "{CW}" ;
+
+ MACHDRS ?=
+ "$(UMACHDRS):Universal:Interfaces:CIncludes"
+ "$(CW):MSL:MSL_C:MSL_Common:Include"
+ "$(CW):MSL:MSL_C:MSL_MacOS:Include" ;
+
+ MACLIBS ?=
+ "$(CW):MacOS Support:Universal:Libraries:StubLibraries:Interfacelib"
+ "$(CW):MacOS Support:Universal:Libraries:StubLibraries:Mathlib" ;
+
+ MPWLIBS ?=
+ "$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib"
+ "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW.Lib" ;
+
+ MPWNLLIBS ?=
+ "$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib"
+ "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW(NL).Lib" ;
+
+ SIOUXHDRS ?= ;
+
+ SIOUXLIBS ?=
+ "$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL RuntimePPC.lib"
+ "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL SIOUX.PPC.Lib"
+ "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC.Lib" ;
+
+ C++ ?= mwcppc ;
+ C++FLAGS ?= -w off -nomapcr ;
+ CC ?= mwcppc ;
+ CCFLAGS ?= -w off -nomapcr ;
+ CP ?= duplicate -y ;
+ DOT ?= ":" ;
+ DOTDOT ?= "::" ;
+ HDRS ?= $(MACHDRS) $(MPWHDRS) ;
+ LINK ?= mwlinkppc ;
+ LINKFLAGS ?= -mpwtool -warn ;
+ LINKLIBS ?= $(MACLIBS) $(MPWLIBS) ;
+ MKDIR ?= newfolder ;
+ MV ?= rename -y ;
+ NOARSCAN ?= true ;
+ OPTIM ?= ;
+ RM ?= delete -y ;
+ SLASH ?= ":" ;
+ STDHDRS ?= ;
+ SUFLIB ?= .lib ;
+ SUFOBJ ?= .o ;
+}
+else if $(OS) = BEOS && $(METROWERKS)
+{
+ AR ?= mwld -xml -o ;
+ BINDIR ?= /boot/apps ;
+ CC ?= mwcc ;
+ CCFLAGS ?= -nosyspath ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= -nosyspath ;
+ FORTRAN ?= "" ;
+ LIBDIR ?= /boot/develop/libraries ;
+ LINK ?= mwld ;
+ LINKFLAGS ?= "" ;
+ MANDIR ?= /boot/documentation/"Shell Tools"/HTML ;
+ NOARSCAN ?= true ;
+ STDHDRS ?= /boot/develop/headers/posix ;
+}
+else if $(OS) = BEOS
+{
+ BINDIR ?= /boot/apps ;
+ CC ?= gcc ;
+ C++ ?= $(CC) ;
+ FORTRAN ?= "" ;
+ LIBDIR ?= /boot/develop/libraries ;
+ LINK ?= gcc ;
+ LINKLIBS ?= -lnet ;
+ NOARSCAN ?= true ;
+ STDHDRS ?= /boot/develop/headers/posix ;
+}
+else if $(UNIX)
+{
+ switch $(OS)
+ {
+ case AIX :
+ LINKLIBS ?= -lbsd ;
+
+ case AMIGA :
+ CC ?= gcc ;
+ YACC ?= "bison -y" ;
+
+ case CYGWIN :
+ CC ?= gcc ;
+ CCFLAGS += -D__cygwin__ ;
+ LEX ?= flex ;
+ RANLIB ?= "" ;
+ SUFEXE ?= .exe ;
+ YACC ?= "bison -y" ;
+
+ case DGUX :
+ RANLIB ?= "" ;
+ RELOCATE ?= true ;
+
+ case HPUX :
+ YACC = ;
+ CFLAGS += -Ae ;
+ CCFLAGS += -Ae ;
+ RANLIB ?= "" ;
+
+ case INTERIX :
+ CC ?= gcc ;
+ RANLIB ?= "" ;
+
+ case IRIX :
+ RANLIB ?= "" ;
+
+ case MPEIX :
+ CC ?= gcc ;
+ C++ ?= gcc ;
+ CCFLAGS += -D_POSIX_SOURCE ;
+ HDRS += /usr/include ;
+ RANLIB ?= "" ;
+ NOARSCAN ?= true ;
+ NOARUPDATE ?= true ;
+
+ case MVS :
+ RANLIB ?= "" ;
+
+ case NEXT :
+ AR ?= libtool -o ;
+ RANLIB ?= "" ;
+
+ case MACOSX :
+ AR ?= libtool -o ;
+ C++ ?= c++ ;
+ MANDIR ?= /usr/local/share/man ;
+ RANLIB ?= "" ;
+
+ case NCR :
+ RANLIB ?= "" ;
+
+ case PTX :
+ RANLIB ?= "" ;
+
+ case QNX :
+ AR ?= wlib ;
+ CC ?= cc ;
+ CCFLAGS ?= -Q ; # quiet
+ C++ ?= $(CC) ;
+ C++FLAGS ?= -Q ; # quiet
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= -Q ; # quiet
+ NOARSCAN ?= true ;
+ RANLIB ?= "" ;
+
+ case SCO :
+ RANLIB ?= "" ;
+ RELOCATE ?= true ;
+
+ case SINIX :
+ RANLIB ?= "" ;
+
+ case SOLARIS :
+ RANLIB ?= "" ;
+ AR ?= "/usr/ccs/bin/ar ru" ;
+
+ case UNICOS :
+ NOARSCAN ?= true ;
+ OPTIM ?= -O0 ;
+
+ case UNIXWARE :
+ RANLIB ?= "" ;
+ RELOCATE ?= true ;
+ }
+
+ # UNIX defaults
+
+ CCFLAGS ?= ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ CHMOD ?= chmod ;
+ CHGRP ?= chgrp ;
+ CHOWN ?= chown ;
+ LEX ?= lex ;
+ LINKFLAGS ?= $(CCFLAGS) ;
+ LINKLIBS ?= ;
+ OPTIM ?= -O ;
+ RANLIB ?= ranlib ;
+ YACC ?= yacc ;
+ YACCFILES ?= y.tab ;
+ YACCFLAGS ?= -d ;
+}
+
+#
+# General defaults; a lot like UNIX
+#
+
+ AR ?= ar ru ;
+ AS ?= as ;
+ ASFLAGS ?= ;
+ AWK ?= awk ;
+ BINDIR ?= /usr/local/bin ;
+ C++ ?= cc ;
+ C++FLAGS ?= ;
+ CC ?= cc ;
+ CCFLAGS ?= ;
+ CP ?= cp -f ;
+ CRELIB ?= ;
+ DOT ?= . ;
+ DOTDOT ?= .. ;
+ EXEMODE ?= 711 ;
+ FILEMODE ?= 644 ;
+ FORTRAN ?= f77 ;
+ FORTRANFLAGS ?= ;
+ HDRS ?= ;
+ INSTALLGRIST ?= installed ;
+ JAMFILE ?= Jamfile ;
+ JAMRULES ?= Jamrules ;
+ LEX ?= ;
+ LIBDIR ?= /usr/local/lib ;
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= ;
+ LINKLIBS ?= ;
+ LN ?= ln ;
+ MANDIR ?= /usr/local/man ;
+ MKDIR ?= mkdir ;
+ MV ?= mv -f ;
+ OPTIM ?= ;
+ RCP ?= rcp ;
+ RM ?= rm -f ;
+ RSH ?= rsh ;
+ SED ?= sed ;
+ SHELLHEADER ?= "#!/bin/sh" ;
+ SHELLMODE ?= 755 ;
+ SLASH ?= / ;
+ STDHDRS ?= /usr/include ;
+ SUFEXE ?= "" ;
+ SUFLIB ?= .a ;
+ SUFOBJ ?= .o ;
+ UNDEFFLAG ?= "-u _" ;
+ YACC ?= ;
+ YACCFILES ?= ;
+ YACCFLAGS ?= ;
+
+ HDRPATTERN =
+ "^[ ]*#[ ]*include[ ]*[<\"]([^\">]*)[\">].*$" ;
+
+ OSFULL = $(OS)$(OSVER)$(OSPLAT) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ;
+
+
+#
+# Base dependencies - first for "bootstrap" kinds of rules
+#
+
+DEPENDS all : shell files lib exe obj ;
+DEPENDS all shell files lib exe obj : first ;
+NOTFILE all first shell files lib exe obj dirs clean uninstall ;
+ALWAYS clean uninstall ;
+
+#
+# Rules
+#
+
+rule As
+{
+ DEPENDS $(<) : $(>) ;
+ ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
+}
+
+rule Bulk
+{
+ local i ;
+
+ for i in $(>)
+ {
+ File $(i:D=$(<)) : $(i) ;
+ }
+}
+
+rule Cc
+{
+ local _h ;
+
+ DEPENDS $(<) : $(>) ;
+
+ # Just to clarify here: this sets the per-target CCFLAGS to
+ # be the current value of (global) CCFLAGS and SUBDIRCCFLAGS.
+
+ CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) ;
+
+ # If the compiler's -o flag doesn't work, relocate the .o
+
+ if $(RELOCATE)
+ {
+ CcMv $(<) : $(>) ;
+ }
+
+ _h = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;
+
+ if $(VMS) && $(_h)
+ {
+ SLASHINC on $(<) = "/inc=(" $(_h[1]) ,$(_h[2-]) ")" ;
+ }
+ else if $(MAC) && $(_h)
+ {
+ local _i _j ;
+ _j = $(_h[1]) ;
+ for _i in $(_h[2-])
+ {
+ _j = $(_j),$(_i) ;
+ }
+ MACINC on $(<) = \"$(_j)\" ;
+ }
+}
+
+rule C++
+{
+ local _h ;
+
+ DEPENDS $(<) : $(>) ;
+ C++FLAGS on $(<) += $(C++FLAGS) $(SUBDIRC++FLAGS) ;
+
+ if $(RELOCATE)
+ {
+ CcMv $(<) : $(>) ;
+ }
+
+ _h = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;
+
+ if $(VMS) && $(_h)
+ {
+ SLASHINC on $(<) = "/inc=(" $(_h[1]) ,$(_h[2-]) ")" ;
+ }
+ else if $(MAC) && $(_h)
+ {
+ local _i _j ;
+ _j = $(_h[1]) ;
+ for _i in $(_h[2-])
+ {
+ _j = $(_j),$(_i) ;
+ }
+ MACINC on $(<) = \"$(_j)\" ;
+ }
+}
+
+rule Chmod
+{
+ if $(CHMOD) { Chmod1 $(<) ; }
+}
+
+rule File
+{
+ DEPENDS files : $(<) ;
+ DEPENDS $(<) : $(>) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+ MODE on $(<) = $(FILEMODE) ;
+ Chmod $(<) ;
+}
+
+rule Fortran
+{
+ DEPENDS $(<) : $(>) ;
+}
+
+rule GenFile
+{
+ local _t = [ FGristSourceFiles $(<) ] ;
+ local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;
+ Depends $(_t) : $(_s) $(>[2-]) ;
+ GenFile1 $(_t) : $(_s) $(>[2-]) ;
+ Clean clean : $(_t) ;
+}
+
+rule GenFile1
+{
+ MakeLocate $(<) : $(LOCATE_SOURCE) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+}
+
+rule HardLink
+{
+ DEPENDS files : $(<) ;
+ DEPENDS $(<) : $(>) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+}
+
+rule HdrMacroFile
+{
+ # HdrMacroFile file ;
+ #
+ # this rule is used to indicate that a given file contains definitions
+ # for filename macros (e.g. "#define MYFILE_H <myfile.h>") that can
+ # later be used in #include statements in the rest of the source
+ #
+ # theses files must be parsed before any make is tried..
+ #
+ HDRMACRO $(<) ;
+}
+
+rule HdrRule
+{
+ # HdrRule source : headers ;
+
+ # N.B. This rule is called during binding, potentially after
+ # the fate of many targets has been determined, and must be
+ # used with caution: don't add dependencies to unrelated
+ # targets, and don't set variables on $(<).
+
+ # Tell Jam that anything depending on $(<) also depends on $(>),
+ # set SEARCH so Jam can find the headers, but then say we don't
+ # care if we can't actually find the headers (they may have been
+ # within ifdefs),
+
+ local s ;
+
+ if $(HDRGRIST)
+ {
+ s = $(>:G=$(HDRGRIST)) ;
+ } else {
+ s = $(>) ;
+ }
+
+ INCLUDES $(<) : $(s) ;
+ SEARCH on $(s) = $(HDRSEARCH) ;
+ NOCARE $(s) ;
+
+ # Propagate on $(<) to $(>)
+
+ HDRSEARCH on $(s) = $(HDRSEARCH) ;
+ HDRSCAN on $(s) = $(HDRSCAN) ;
+ HDRRULE on $(s) = $(HDRRULE) ;
+ HDRGRIST on $(s) = $(HDRGRIST) ;
+}
+
+rule InstallInto
+{
+ # InstallInto dir : sources ;
+
+ local i t ;
+
+ t = $(>:G=$(INSTALLGRIST)) ;
+
+ # Arrange for jam install
+ # Arrange for jam uninstall
+ # sources are in SEARCH_SOURCE
+ # targets are in dir
+
+ Depends install : $(t) ;
+ Clean uninstall : $(t) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+ MakeLocate $(t) : $(<) ;
+
+ # For each source, make gristed target name
+ # and Install, Chmod, Chown, and Chgrp
+
+ for i in $(>)
+ {
+ local tt = $(i:G=$(INSTALLGRIST)) ;
+
+ Depends $(tt) : $(i) ;
+ Install $(tt) : $(i) ;
+ Chmod $(tt) ;
+
+ if $(OWNER) && $(CHOWN)
+ {
+ Chown $(tt) ;
+ OWNER on $(tt) = $(OWNER) ;
+ }
+
+ if $(GROUP) && $(CHGRP)
+ {
+ Chgrp $(tt) ;
+ GROUP on $(tt) = $(GROUP) ;
+ }
+ }
+}
+
+rule InstallBin
+{
+ local _t = [ FAppendSuffix $(>) : $(SUFEXE) ] ;
+
+ InstallInto $(<) : $(_t) ;
+ MODE on $(_t:G=installed) = $(EXEMODE) ;
+}
+
+rule InstallFile
+{
+ InstallInto $(<) : $(>) ;
+ MODE on $(>:G=installed) = $(FILEMODE) ;
+}
+
+rule InstallLib
+{
+ InstallInto $(<) : $(>) ;
+ MODE on $(>:G=installed) = $(FILEMODE) ;
+}
+
+rule InstallMan
+{
+ # Really this just strips the . from the suffix
+
+ local i s d ;
+
+ for i in $(>)
+ {
+ switch $(i:S)
+ {
+ case .1 : s = 1 ; case .2 : s = 2 ; case .3 : s = 3 ;
+ case .4 : s = 4 ; case .5 : s = 5 ; case .6 : s = 6 ;
+ case .7 : s = 7 ; case .8 : s = 8 ; case .l : s = l ;
+ case .n : s = n ; case .man : s = 1 ;
+ }
+
+ d = man$(s) ;
+
+ InstallInto $(d:R=$(<)) : $(i) ;
+ }
+
+ MODE on $(>:G=installed) = $(FILEMODE) ;
+}
+
+rule InstallShell
+{
+ InstallInto $(<) : $(>) ;
+ MODE on $(>:G=installed) = $(SHELLMODE) ;
+}
+
+rule Lex
+{
+ LexMv $(<) : $(>) ;
+ DEPENDS $(<) : $(>) ;
+ MakeLocate $(<) : $(LOCATE_SOURCE) ;
+ Clean clean : $(<) ;
+}
+
+rule Library
+{
+ LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
+ Objects $(>) ;
+}
+
+rule LibraryFromObjects
+{
+ local _i _l _s ;
+
+ # Add grist to file names
+
+ _s = [ FGristFiles $(>) ] ;
+ _l = $(<:S=$(SUFLIB)) ;
+
+ # library depends on its member objects
+
+ if $(KEEPOBJS)
+ {
+ DEPENDS obj : $(_s) ;
+ }
+ else
+ {
+ DEPENDS lib : $(_l) ;
+ }
+
+ # Set LOCATE for the library and its contents. The bound
+ # value shows up as $(NEEDLIBS) on the Link actions.
+ # For compatibility, we only do this if the library doesn't
+ # already have a path.
+
+ if ! $(_l:D)
+ {
+ MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ;
+ }
+
+ if $(NOARSCAN)
+ {
+ # If we can't scan the library to timestamp its contents,
+ # we have to just make the library depend directly on the
+ # on-disk object files.
+
+ DEPENDS $(_l) : $(_s) ;
+ }
+ else
+ {
+ # If we can scan the library, we make the library depend
+ # on its members and each member depend on the on-disk
+ # object file.
+
+ DEPENDS $(_l) : $(_l)($(_s:BS)) ;
+
+ for _i in $(_s)
+ {
+ DEPENDS $(_l)($(_i:BS)) : $(_i) ;
+ }
+ }
+
+ Clean clean : $(_l) ;
+
+ if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; }
+
+ Archive $(_l) : $(_s) ;
+
+ if $(RANLIB) { Ranlib $(_l) ; }
+
+ # If we can't scan the library, we have to leave the .o's around.
+
+ if ! ( $(NOARSCAN) || $(KEEPOBJS) ) { RmTemps $(_l) : $(_s) ; }
+}
+
+rule Link
+{
+ MODE on $(<) = $(EXEMODE) ;
+ Chmod $(<) ;
+}
+
+rule LinkLibraries
+{
+ # make library dependencies of target
+ # set NEEDLIBS variable used by 'actions Main'
+
+ local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
+
+ DEPENDS $(_t) : $(>:S=$(SUFLIB)) ;
+ NEEDLIBS on $(_t) += $(>:S=$(SUFLIB)) ;
+}
+
+rule Main
+{
+ MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
+ Objects $(>) ;
+}
+
+rule MainFromObjects
+{
+ local _s _t ;
+
+ # Add grist to file names
+ # Add suffix to exe
+
+ _s = [ FGristFiles $(>) ] ;
+ _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
+
+ if $(_t) != $(<)
+ {
+ DEPENDS $(<) : $(_t) ;
+ NOTFILE $(<) ;
+ }
+
+ # make compiled sources a dependency of target
+
+ DEPENDS exe : $(_t) ;
+ DEPENDS $(_t) : $(_s) ;
+ MakeLocate $(_t) : $(LOCATE_TARGET) ;
+
+ Clean clean : $(_t) ;
+
+ Link $(_t) : $(_s) ;
+}
+
+rule MakeLocate
+{
+ if $(>)
+ {
+ LOCATE on $(<) = $(>) ;
+ Depends $(<) : $(>[1]) ;
+ MkDir $(>[1]) ;
+ }
+}
+
+rule MkDir
+{
+ # If dir exists, don't update it
+ # Do this even for $(DOT).
+
+ NOUPDATE $(<) ;
+
+ if $(<) != $(DOT) && ! $($(<)-mkdir)
+ {
+ local s ;
+
+ # Cheesy gate to prevent multiple invocations on same dir
+ # MkDir1 has the actions
+ # Arrange for jam dirs
+
+ $(<)-mkdir = true ;
+ MkDir1 $(<) ;
+ Depends dirs : $(<) ;
+
+ # Recursively make parent directories.
+ # $(<:P) = $(<)'s parent, & we recurse until root
+
+ s = $(<:P) ;
+
+ if $(NT)
+ {
+ switch $(s)
+ {
+ case *: : s = ;
+ case *:\\ : s = ;
+ }
+ }
+
+ if $(s) && $(s) != $(<)
+ {
+ Depends $(<) : $(s) ;
+ MkDir $(s) ;
+ }
+ else if $(s)
+ {
+ NOTFILE $(s) ;
+ }
+
+ }
+}
+
+rule Object
+{
+ local h ;
+
+ # locate object and search for source, if wanted
+
+ Clean clean : $(<) ;
+
+ MakeLocate $(<) : $(LOCATE_TARGET) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+
+ # Save HDRS for -I$(HDRS) on compile.
+ # We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers
+ # in the .c file's directory, but generated .c files (from
+ # yacc, lex, etc) are located in $(LOCATE_TARGET), possibly
+ # different from $(SEARCH_SOURCE).
+
+ HDRS on $(<) = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;
+
+ # handle #includes for source: Jam scans for headers with
+ # the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE)
+ # with the scanned file as the target and the found headers
+ # as the sources. HDRSEARCH is the value of SEARCH used for
+ # the found header files. Finally, if jam must deal with
+ # header files of the same name in different directories,
+ # they can be distinguished with HDRGRIST.
+
+ # $(h) is where cc first looks for #include "foo.h" files.
+ # If the source file is in a distant directory, look there.
+ # Else, look in "" (the current directory).
+
+ if $(SEARCH_SOURCE)
+ {
+ h = $(SEARCH_SOURCE) ;
+ }
+ else
+ {
+ h = "" ;
+ }
+
+ HDRRULE on $(>) = HdrRule ;
+ HDRSCAN on $(>) = $(HDRPATTERN) ;
+ HDRSEARCH on $(>) = $(HDRS) $(SUBDIRHDRS) $(h) $(STDHDRS) ;
+ HDRGRIST on $(>) = $(HDRGRIST) ;
+
+ # if source is not .c, generate .c with specific rule
+
+ switch $(>:S)
+ {
+ case .asm : As $(<) : $(>) ;
+ case .c : Cc $(<) : $(>) ;
+ case .C : C++ $(<) : $(>) ;
+ case .cc : C++ $(<) : $(>) ;
+ case .cpp : C++ $(<) : $(>) ;
+ case .f : Fortran $(<) : $(>) ;
+ case .l : Cc $(<) : $(<:S=.c) ;
+ Lex $(<:S=.c) : $(>) ;
+ case .s : As $(<) : $(>) ;
+ case .y : Cc $(<) : $(<:S=.c) ;
+ Yacc $(<:S=.c) : $(>) ;
+ case * : UserObject $(<) : $(>) ;
+ }
+}
+
+
+rule ObjectCcFlags
+{
+ CCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
+}
+
+rule ObjectC++Flags
+{
+ C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
+}
+
+rule ObjectHdrs
+{
+ HDRS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
+}
+
+rule Objects
+{
+ local _i ;
+
+ for _i in [ FGristFiles $(<) ]
+ {
+ Object $(_i:S=$(SUFOBJ)) : $(_i) ;
+ DEPENDS obj : $(_i:S=$(SUFOBJ)) ;
+ }
+}
+
+rule RmTemps
+{
+ TEMPORARY $(>) ;
+}
+
+rule Setuid
+{
+ MODE on [ FAppendSuffix $(<) : $(SUFEXE) ] = 4711 ;
+}
+
+rule Shell
+{
+ DEPENDS shell : $(<) ;
+ DEPENDS $(<) : $(>) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+ MODE on $(<) = $(SHELLMODE) ;
+ Clean clean : $(<) ;
+ Chmod $(<) ;
+}
+
+rule SubDir
+{
+ local _r _s ;
+
+ #
+ # SubDir TOP d1 [ ... ]
+ #
+ # This introduces a Jamfile that is part of a project tree
+ # rooted at $(TOP). It (only once) includes the project-specific
+ # rules file $(TOP)/Jamrules and then sets search & locate stuff.
+ #
+ # If the variable $(TOPRULES) is set (where TOP is the first arg
+ # to SubDir), that file is included instead of $(TOP)/Jamrules.
+ #
+ # d1 ... are the directory elements that lead to this directory
+ # from $(TOP). We construct the system dependent path from these
+ # directory elements in order to set search & locate stuff.
+ #
+
+ if ! $($(<[1]))
+ {
+ if ! $(<[1])
+ {
+ EXIT SubDir syntax error ;
+ }
+
+ $(<[1]) = [ FSubDir $(<[2-]) ] ;
+ }
+
+ #
+ # If $(TOP)/Jamrules hasn't been included, do so.
+ #
+
+ if ! $($(<[1])-included)
+ {
+ # Gated entry.
+
+ $(<[1])-included = TRUE ;
+
+ # File is $(TOPRULES) or $(TOP)/Jamrules.
+
+ _r = $($(<[1])RULES) ;
+
+ if ! $(_r)
+ {
+ _r = $(JAMRULES:R=$($(<[1]))) ;
+ }
+
+ # Include it.
+
+ include $(_r) ;
+ }
+
+ # Get path to current directory from root using SubDir.
+ # Save dir tokens for other potential uses.
+
+ _s = [ FDirName $(<[2-]) ] ;
+ SUBDIR = $(_s:R=$($(<[1]))) ;
+ SUBDIR_TOKENS = $(<[2-]) ;
+
+ # Now set up SEARCH_SOURCE, LOCATE_TARGET, SOURCE_GRIST
+ # These can be reset if needed. For example, if the source
+ # directory should not hold object files, LOCATE_TARGET can
+ # subsequently be redefined.
+
+ SEARCH_SOURCE = $(SUBDIR) ;
+ LOCATE_SOURCE = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
+ LOCATE_TARGET = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
+ SOURCE_GRIST = [ FGrist $(<[2-]) ] ;
+
+ # Reset per-directory ccflags, hdrs
+
+ SUBDIRCCFLAGS = ;
+ SUBDIRC++FLAGS = ;
+ SUBDIRHDRS = ;
+}
+
+rule SubDirCcFlags
+{
+ SUBDIRCCFLAGS += $(<) ;
+}
+
+rule SubDirC++Flags
+{
+ SUBDIRC++FLAGS += $(<) ;
+}
+
+rule SubDirHdrs
+{
+ SUBDIRHDRS += $(<) ;
+}
+
+rule SubInclude
+{
+ local _s ;
+
+ # That's
+ # SubInclude TOP d1 [ d2 [ d3 [ d4 ] ] ]
+ #
+ # to include a subdirectory's Jamfile.
+
+ if ! $($(<[1]))
+ {
+ EXIT Top level of source tree has not been set with $(<[1]) ;
+ }
+
+ _s = [ FDirName $(<[2-]) ] ;
+
+ include $(JAMFILE:D=$(_s):R=$($(<[1]))) ;
+}
+
+rule Undefines
+{
+ UNDEFS on [ FAppendSuffix $(<) : $(SUFEXE) ] += $(UNDEFFLAG)$(>) ;
+}
+
+rule UserObject
+{
+ EXIT "Unknown suffix on" $(>) "- see UserObject rule in Jamfile(5)." ;
+}
+
+rule Yacc
+{
+ local _h ;
+
+ _h = $(<:BS=.h) ;
+
+ # Some places don't have a yacc.
+
+ MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ;
+
+ if $(YACC)
+ {
+ DEPENDS $(<) $(_h) : $(>) ;
+ Yacc1 $(<) $(_h) : $(>) ;
+ YaccMv $(<) $(_h) : $(>) ;
+ Clean clean : $(<) $(_h) ;
+ }
+
+ # Make sure someone includes $(_h) else it will be a deadly independent
+ # target.
+ INCLUDES $(<) : $(_h) ;
+}
+
+#
+# Utility rules; no side effects on these.
+#
+
+rule FGrist
+{
+ # Turn individual elements in $(<) into grist.
+
+ local _g _i ;
+
+ _g = $(<[1]) ;
+
+ for _i in $(<[2-])
+ {
+ _g = $(_g)!$(_i) ;
+ }
+
+ return $(_g) ;
+}
+
+rule FGristFiles
+{
+ if ! $(SOURCE_GRIST)
+ {
+ return $(<) ;
+ }
+ else
+ {
+ return $(<:G=$(SOURCE_GRIST)) ;
+ }
+}
+
+rule FGristSourceFiles
+{
+ # Produce source file name name with grist in it,
+ # if SOURCE_GRIST is set.
+
+ # Leave header files alone, because they have a global
+ # visibility.
+
+ if ! $(SOURCE_GRIST)
+ {
+ return $(<) ;
+ }
+ else
+ {
+ local _i _o ;
+
+ for _i in $(<)
+ {
+ switch $(_i)
+ {
+ case *.h : _o += $(_i) ;
+ case * : _o += $(_i:G=$(SOURCE_GRIST)) ;
+ }
+ }
+
+ return $(_o) ;
+ }
+}
+
+rule FConcat
+{
+ # Puts the variables together, removing spaces.
+
+ local _t _r ;
+
+ $(_r) = $(<[1]) ;
+
+ for _t in $(<[2-])
+ {
+ $(_r) = $(_r)$(_t) ;
+ }
+
+ return $(_r) ;
+}
+
+rule FSubDir
+{
+ local _i _d ;
+
+ # If $(>) is the path to the current directory, compute the
+ # path (using ../../ etc) back to that root directory.
+ # Sets result in $(<)
+
+ if ! $(<[1])
+ {
+ _d = $(DOT) ;
+ }
+ else
+ {
+ _d = $(DOTDOT) ;
+
+ for _i in $(<[2-])
+ {
+ _d = $(_d:R=$(DOTDOT)) ;
+ }
+ }
+
+ return $(_d) ;
+}
+
+rule FDirName
+{
+ local _s _i ;
+
+ # Turn individual elements in $(<) into a usable path.
+
+ if ! $(<)
+ {
+ _s = $(DOT) ;
+ }
+ else if $(VMS)
+ {
+ # This handles the following cases:
+ # a -> [.a]
+ # a b c -> [.a.b.c]
+ # x: -> x:
+ # x: a -> x:[a]
+ # x:[a] b -> x:[a.b]
+
+ switch $(<[1])
+ {
+ case *:* : _s = $(<[1]) ;
+ case \\[*\\] : _s = $(<[1]) ;
+ case * : _s = [.$(<[1])] ;
+ }
+
+ for _i in [.$(<[2-])]
+ {
+ _s = $(_i:R=$(_s)) ;
+ }
+ }
+ else if $(MAC)
+ {
+ _s = $(DOT) ;
+
+ for _i in $(<)
+ {
+ _s = $(_i:R=$(_s)) ;
+ }
+ }
+ else
+ {
+ _s = $(<[1]) ;
+
+ for _i in $(<[2-])
+ {
+ _s = $(_i:R=$(_s)) ;
+ }
+ }
+
+ return $(_s) ;
+}
+
+
+rule _makeCommon
+{
+ # strip common initial elements
+
+ if $($(<)[1]) && $($(<)[1]) = $($(>)[1])
+ {
+ $(<) = $($(<)[2-]) ;
+ $(>) = $($(>)[2-]) ;
+ _makeCommon $(<) : $(>) ;
+ }
+}
+
+
+rule FRelPath
+{
+ local _l _r ;
+
+ # first strip off common parts
+
+ _l = $(<) ;
+ _r = $(>) ;
+
+ _makeCommon _l : _r ;
+
+ # now make path to root and path down
+
+ _l = [ FSubDir $(_l) ] ;
+ _r = [ FDirName $(_r) ] ;
+
+ # Concatenate and save
+
+ # XXX This should be better
+
+ if $(_r) = $(DOT) {
+ return $(_l) ;
+ } else {
+ return $(_r:R=$(_l)) ;
+ }
+}
+
+rule FAppendSuffix
+{
+ # E.g., "FAppendSuffix yacc lex foo.bat : $(SUFEXE) ;"
+ # returns (yacc,lex,foo.bat) on Unix and
+ # (yacc.exe,lex.exe,foo.bat) on NT.
+
+ if $(>)
+ {
+ local _i _o ;
+
+ for _i in $(<)
+ {
+ if $(_i:S)
+ {
+ _o += $(_i) ;
+ }
+ else
+ {
+ _o += $(_i:S=$(>)) ;
+ }
+ }
+ return $(_o) ;
+ }
+ else
+ {
+ return $(<) ;
+ }
+}
+
+rule unmakeDir
+{
+ if $(>[1]:D) && $(>[1]:D) != $(>[1]) && $(>[1]:D) != \\\\
+ {
+ unmakeDir $(<) : $(>[1]:D) $(>[1]:BS) $(>[2-]) ;
+ }
+ else
+ {
+ $(<) = $(>) ;
+ }
+}
+
+
+rule FConvertToSlashes
+{
+ local _d, _s, _i ;
+
+ unmakeDir _d : $(<) ;
+
+ _s = $(_d[1]) ;
+ for _i in $(_d[2-])
+ {
+ _s = $(_s)/$(_i) ;
+ }
+ return $(_s) ;
+}
+
+
+#
+# Actions
+#
+
+#
+# First the defaults
+#
+
+actions updated together piecemeal Archive
+{
+ $(AR) $(<) $(>)
+}
+
+actions As
+{
+ $(AS) $(ASFLAGS) -I$(HDRS) -o $(<) $(>)
+}
+
+actions C++
+{
+ $(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)
+}
+
+actions Cc
+{
+ $(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)
+}
+
+actions Chgrp
+{
+ $(CHGRP) $(GROUP) $(<)
+}
+
+actions Chmod1
+{
+ $(CHMOD) $(MODE) $(<)
+}
+
+actions Chown
+{
+ $(CHOWN) $(OWNER) $(<)
+}
+
+actions piecemeal together existing Clean
+{
+ $(RM) $(>)
+}
+
+actions File
+{
+ $(CP) $(>) $(<)
+}
+
+actions GenFile1
+{
+ $(>[1]) $(<) $(>[2-])
+}
+
+actions Fortran
+{
+ $(FORTRAN) $(FORTRANFLAGS) -o $(<) $(>)
+}
+
+actions HardLink
+{
+ $(RM) $(<) && $(LN) $(>) $(<)
+}
+
+actions Install
+{
+ $(CP) $(>) $(<)
+}
+
+actions Lex
+{
+ $(LEX) $(>)
+}
+
+actions LexMv
+{
+ $(MV) lex.yy.c $(<)
+}
+
+actions Link bind NEEDLIBS
+{
+ $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+}
+
+actions MkDir1
+{
+ $(MKDIR) $(<)
+}
+
+actions together Ranlib
+{
+ $(RANLIB) $(<)
+}
+
+actions quietly updated piecemeal together RmTemps
+{
+ $(RM) $(>)
+}
+
+actions Shell
+{
+ $(AWK) '
+ NR == 1 { print "$(SHELLHEADER)" }
+ NR == 1 && /^[#:]/ { next }
+ /^##/ { next }
+ { print }
+ ' < $(>) > $(<)
+}
+
+actions Yacc1
+{
+ $(YACC) $(YACCFLAGS) $(>)
+}
+
+actions YaccMv
+{
+ $(MV) $(YACCFILES).c $(<[1])
+ $(MV) $(YACCFILES).h $(<[2])
+}
+
+#
+# RELOCATE - for compilers with broken -o flags
+#
+
+if $(RELOCATE)
+{
+ actions C++
+ {
+ $(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) $(>)
+ }
+
+ actions Cc
+ {
+ $(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) $(>)
+ }
+
+ actions ignore CcMv
+ {
+ [ $(<) != $(>:BS=$(SUFOBJ)) ] && $(MV) $(>:BS=$(SUFOBJ)) $(<)
+ }
+}
+
+#
+# NOARUPDATE - can't update an archive
+#
+
+if $(NOARUPDATE)
+{
+ actions Archive
+ {
+ $(AR) $(<) $(>)
+ }
+}
+
+#
+# NT specific actions
+#
+
+if $(NT)
+{
+ if $(TOOLSET) = VISUALC || $(TOOLSET) = VC7 || $(TOOLSET) = INTELC
+ {
+ actions updated together piecemeal Archive
+ {
+ if exist $(<) set _$(<:B)_=$(<)
+ $(AR) /out:$(<) %_$(<:B)_% $(>)
+ }
+
+ actions As
+ {
+ $(AS) /Ml /p /v /w2 $(>) $(<) ,nul,nul;
+ }
+
+ actions Cc
+ {
+ $(CC) /c $(CCFLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) /c $(C++FLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) /Tp$(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+ }
+ }
+ else if $(TOOLSET) = VISUALC16
+ {
+ actions updated together piecemeal Archive
+ {
+ $(AR) $(<) -+$(>)
+ }
+
+ actions Cc
+ {
+ $(CC) /c $(CCFLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) /c $(C++FLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /Tp$(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+ }
+ }
+ else if $(TOOLSET) = BORLANDC
+ {
+ actions updated together piecemeal Archive
+ {
+ $(AR) $(<) -+$(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) -e$(<) $(LINKFLAGS) $(UNDEFS) -L$(LINKLIBS) $(NEEDLIBS) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+
+ actions Cc
+ {
+ $(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+
+ }
+ else if $(TOOLSET) = MINGW
+ {
+ actions together piecemeal Archive
+ {
+ $(AR) $(<) $(>:T)
+ }
+
+ actions Cc
+ {
+ $(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+ }
+ else if $(TOOLSET) = WATCOM
+ {
+ actions together piecemeal Archive
+ {
+ $(AR) $(<) +-$(>)
+ }
+
+ actions Cc
+ {
+ $(CC) $(CCFLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) $(C++FLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+ }
+
+ actions Shell
+ {
+ $(CP) $(>) $(<)
+ }
+ }
+ else if $(TOOLSET) = LCC
+ {
+ actions together piecemeal Archive
+ {
+ $(AR) /out:$(<) $(>)
+ }
+
+ actions Cc
+ {
+ $(CC) $(CCFLAGS) $(OPTIM) -Fo$(<) -I$(HDRS) $(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+ }
+
+ actions Shell
+ {
+ $(CP) $(>) $(<)
+ }
+ }
+}
+
+#
+# OS2 specific actions
+#
+
+else if $(OS2)
+{
+ if $(TOOLSET) = WATCOM
+ {
+ actions together piecemeal Archive
+ {
+ $(AR) $(<) +-$(>)
+ }
+
+ actions Cc
+ {
+ $(CC) $(CCFLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) $(C++FLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+ }
+
+ actions Shell
+ {
+ $(CP) $(>) $(<)
+ }
+ }
+ else if $(TOOLSET) = EMX
+ {
+ actions together piecemeal Archive
+ {
+ $(AR) $(<) $(>:T)
+ }
+
+ actions Cc
+ {
+ $(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+ }
+}
+
+#
+# VMS specific actions
+#
+
+else if $(VMS)
+{
+ actions updated together piecemeal Archive
+ {
+ lib/replace $(<) $(>[1]) ,$(>[2-])
+ }
+
+ actions Cc
+ {
+ $(CC)/obj=$(<) $(CCFLAGS) $(OPTIM) $(SLASHINC) $(>)
+ }
+
+ actions C++
+ {
+ $(C++)/obj=$(<) $(C++FLAGS) $(OPTIM) $(SLASHINC) $(>)
+ }
+
+ actions piecemeal together existing Clean
+ {
+ $(RM) $(>[1]);* ,$(>[2-]);*
+ }
+
+ actions together quietly CreLib
+ {
+ if f$search("$(<)") .eqs. "" then lib/create $(<)
+ }
+
+ actions GenFile1
+ {
+ mcr $(>[1]) $(<) $(>[2-])
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK)/exe=$(<) $(LINKFLAGS) $(>[1]) ,$(>[2-]) ,$(NEEDLIBS)/lib ,$(LINKLIBS)
+ }
+
+ actions quietly updated piecemeal together RmTemps
+ {
+ $(RM) $(>[1]);* ,$(>[2-]);*
+ }
+
+ actions Shell
+ {
+ $(CP) $(>) $(<)
+ }
+}
+
+#
+# Mac specifc actions
+#
+
+else if $(MAC)
+{
+ actions together Archive
+ {
+ $(LINK) -library -o $(<) $(>)
+ }
+
+ actions Cc
+ {
+ set -e MWCincludes $(MACINC)
+ $(CC) -o $(<) $(CCFLAGS) $(OPTIM) $(>)
+ }
+
+ actions C++
+ {
+ set -e MWCincludes $(MACINC)
+ $(CC) -o $(<) $(C++FLAGS) $(OPTIM) $(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) -o $(<) $(LINKFLAGS) $(>) $(NEEDLIBS) "$(LINKLIBS)"
+ }
+}
+
+#
+# Backwards compatibility with jam 1, where rules were uppercased.
+#
+
+rule BULK { Bulk $(<) : $(>) ; }
+rule FILE { File $(<) : $(>) ; }
+rule HDRRULE { HdrRule $(<) : $(>) ; }
+rule INSTALL { Install $(<) : $(>) ; }
+rule LIBRARY { Library $(<) : $(>) ; }
+rule LIBS { LinkLibraries $(<) : $(>) ; }
+rule LINK { Link $(<) : $(>) ; }
+rule MAIN { Main $(<) : $(>) ; }
+rule SETUID { Setuid $(<) ; }
+rule SHELL { Shell $(<) : $(>) ; }
+rule UNDEFINES { Undefines $(<) : $(>) ; }
+
+# Old INSTALL* didn't take dest directory.
+
+rule INSTALLBIN { InstallBin $(BINDIR) : $(<) ; }
+rule INSTALLLIB { InstallLib $(LIBDIR) : $(<) ; }
+rule INSTALLMAN { InstallMan $(MANDIR) : $(<) ; }
+
+# Compatibility with jam 2.2.
+
+rule addDirName { $(<) += [ FDirName $(>) ] ; }
+rule makeDirName { $(<) = [ FDirName $(>) ] ; }
+rule makeGristedName { $(<) = [ FGristSourceFiles $(>) ] ; }
+rule makeRelPath { $(<[1]) = [ FRelPath $(<[2-]) : $(>) ] ; }
+rule makeSuffixed { $(<[1]) = [ FAppendSuffix $(>) : $(<[2]) ] ; }
+
+#
+# Now include the user's Jamfile.
+#
+
+{
+ if $(JAMFILE) { include $(JAMFILE) ; }
+}
+
+}
diff --git a/tools/build/v2/engine/boehm_gc/AmigaOS.c b/tools/build/v2/engine/boehm_gc/AmigaOS.c
new file mode 100644
index 0000000000..d171503940
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/AmigaOS.c
@@ -0,0 +1,623 @@
+
+
+/******************************************************************
+
+ AmigaOS-spesific routines for GC.
+ This file is normally included from os_dep.c
+
+******************************************************************/
+
+
+#if !defined(GC_AMIGA_DEF) && !defined(GC_AMIGA_SB) && !defined(GC_AMIGA_DS) && !defined(GC_AMIGA_AM)
+# include "gc_priv.h"
+# include <stdio.h>
+# include <signal.h>
+# define GC_AMIGA_DEF
+# define GC_AMIGA_SB
+# define GC_AMIGA_DS
+# define GC_AMIGA_AM
+#endif
+
+
+#ifdef GC_AMIGA_DEF
+
+# ifndef __GNUC__
+# include <exec/exec.h>
+# endif
+# include <proto/exec.h>
+# include <proto/dos.h>
+# include <dos/dosextens.h>
+# include <workbench/startup.h>
+
+#endif
+
+
+
+
+#ifdef GC_AMIGA_SB
+
+/******************************************************************
+ Find the base of the stack.
+******************************************************************/
+
+ptr_t GC_get_main_stack_base()
+{
+ struct Process *proc = (struct Process*)SysBase->ThisTask;
+
+ /* Reference: Amiga Guru Book Pages: 42,567,574 */
+ if (proc->pr_Task.tc_Node.ln_Type==NT_PROCESS
+ && proc->pr_CLI != NULL) {
+ /* first ULONG is StackSize */
+ /*longPtr = proc->pr_ReturnAddr;
+ size = longPtr[0];*/
+
+ return (char *)proc->pr_ReturnAddr + sizeof(ULONG);
+ } else {
+ return (char *)proc->pr_Task.tc_SPUpper;
+ }
+}
+
+#if 0 /* old version */
+ptr_t GC_get_stack_base()
+{
+ extern struct WBStartup *_WBenchMsg;
+ extern long __base;
+ extern long __stack;
+ struct Task *task;
+ struct Process *proc;
+ struct CommandLineInterface *cli;
+ long size;
+
+ if ((task = FindTask(0)) == 0) {
+ GC_err_puts("Cannot find own task structure\n");
+ ABORT("task missing");
+ }
+ proc = (struct Process *)task;
+ cli = BADDR(proc->pr_CLI);
+
+ if (_WBenchMsg != 0 || cli == 0) {
+ size = (char *)task->tc_SPUpper - (char *)task->tc_SPLower;
+ } else {
+ size = cli->cli_DefaultStack * 4;
+ }
+ return (ptr_t)(__base + GC_max(size, __stack));
+}
+#endif
+
+
+#endif
+
+
+#ifdef GC_AMIGA_DS
+/******************************************************************
+ Register data segments.
+******************************************************************/
+
+ void GC_register_data_segments()
+ {
+ struct Process *proc;
+ struct CommandLineInterface *cli;
+ BPTR myseglist;
+ ULONG *data;
+
+ int num;
+
+
+# ifdef __GNUC__
+ ULONG dataSegSize;
+ GC_bool found_segment = FALSE;
+ extern char __data_size[];
+
+ dataSegSize=__data_size+8;
+ /* Can`t find the Location of __data_size, because
+ it`s possible that is it, inside the segment. */
+
+# endif
+
+ proc= (struct Process*)SysBase->ThisTask;
+
+ /* Reference: Amiga Guru Book Pages: 538ff,565,573
+ and XOper.asm */
+ if (proc->pr_Task.tc_Node.ln_Type==NT_PROCESS) {
+ if (proc->pr_CLI == NULL) {
+ myseglist = proc->pr_SegList;
+ } else {
+ /* ProcLoaded 'Loaded as a command: '*/
+ cli = BADDR(proc->pr_CLI);
+ myseglist = cli->cli_Module;
+ }
+ } else {
+ ABORT("Not a Process.");
+ }
+
+ if (myseglist == NULL) {
+ ABORT("Arrrgh.. can't find segments, aborting");
+ }
+
+ /* xoper hunks Shell Process */
+
+ num=0;
+ for (data = (ULONG *)BADDR(myseglist); data != NULL;
+ data = (ULONG *)BADDR(data[0])) {
+ if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) ||
+ ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) {
+# ifdef __GNUC__
+ if (dataSegSize == data[-1]) {
+ found_segment = TRUE;
+ }
+# endif
+ GC_add_roots_inner((char *)&data[1],
+ ((char *)&data[1]) + data[-1], FALSE);
+ }
+ ++num;
+ } /* for */
+# ifdef __GNUC__
+ if (!found_segment) {
+ ABORT("Can`t find correct Segments.\nSolution: Use an newer version of ixemul.library");
+ }
+# endif
+ }
+
+#if 0 /* old version */
+ void GC_register_data_segments()
+ {
+ extern struct WBStartup *_WBenchMsg;
+ struct Process *proc;
+ struct CommandLineInterface *cli;
+ BPTR myseglist;
+ ULONG *data;
+
+ if ( _WBenchMsg != 0 ) {
+ if ((myseglist = _WBenchMsg->sm_Segment) == 0) {
+ GC_err_puts("No seglist from workbench\n");
+ return;
+ }
+ } else {
+ if ((proc = (struct Process *)FindTask(0)) == 0) {
+ GC_err_puts("Cannot find process structure\n");
+ return;
+ }
+ if ((cli = BADDR(proc->pr_CLI)) == 0) {
+ GC_err_puts("No CLI\n");
+ return;
+ }
+ if ((myseglist = cli->cli_Module) == 0) {
+ GC_err_puts("No seglist from CLI\n");
+ return;
+ }
+ }
+
+ for (data = (ULONG *)BADDR(myseglist); data != 0;
+ data = (ULONG *)BADDR(data[0])) {
+# ifdef AMIGA_SKIP_SEG
+ if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) ||
+ ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) {
+# else
+ {
+# endif /* AMIGA_SKIP_SEG */
+ GC_add_roots_inner((char *)&data[1],
+ ((char *)&data[1]) + data[-1], FALSE);
+ }
+ }
+ }
+#endif /* old version */
+
+
+#endif
+
+
+
+#ifdef GC_AMIGA_AM
+
+#ifndef GC_AMIGA_FASTALLOC
+
+void *GC_amiga_allocwrapper(size_t size,void *(*AllocFunction)(size_t size2)){
+ return (*AllocFunction)(size);
+}
+
+void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
+ =GC_amiga_allocwrapper;
+
+#else
+
+
+
+
+void *GC_amiga_allocwrapper_firsttime(size_t size,void *(*AllocFunction)(size_t size2));
+
+void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
+ =GC_amiga_allocwrapper_firsttime;
+
+
+/******************************************************************
+ Amiga-spesific routines to obtain memory, and force GC to give
+ back fast-mem whenever possible.
+ These hacks makes gc-programs go many times faster when
+ the amiga is low on memory, and are therefore strictly necesarry.
+
+ -Kjetil S. Matheussen, 2000.
+******************************************************************/
+
+
+
+/* List-header for all allocated memory. */
+
+struct GC_Amiga_AllocedMemoryHeader{
+ ULONG size;
+ struct GC_Amiga_AllocedMemoryHeader *next;
+};
+struct GC_Amiga_AllocedMemoryHeader *GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(int)~(NULL);
+
+
+
+/* Type of memory. Once in the execution of a program, this might change to MEMF_ANY|MEMF_CLEAR */
+
+ULONG GC_AMIGA_MEMF = MEMF_FAST | MEMF_CLEAR;
+
+
+/* Prevents GC_amiga_get_mem from allocating memory if this one is TRUE. */
+#ifndef GC_AMIGA_ONLYFAST
+BOOL GC_amiga_dontalloc=FALSE;
+#endif
+
+#ifdef GC_AMIGA_PRINTSTATS
+int succ=0,succ2=0;
+int nsucc=0,nsucc2=0;
+int nullretries=0;
+int numcollects=0;
+int chipa=0;
+int allochip=0;
+int allocfast=0;
+int cur0=0;
+int cur1=0;
+int cur10=0;
+int cur50=0;
+int cur150=0;
+int cur151=0;
+int ncur0=0;
+int ncur1=0;
+int ncur10=0;
+int ncur50=0;
+int ncur150=0;
+int ncur151=0;
+#endif
+
+/* Free everything at program-end. */
+
+void GC_amiga_free_all_mem(void){
+ struct GC_Amiga_AllocedMemoryHeader *gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(GC_AMIGAMEM));
+ struct GC_Amiga_AllocedMemoryHeader *temp;
+
+#ifdef GC_AMIGA_PRINTSTATS
+ printf("\n\n"
+ "%d bytes of chip-mem, and %d bytes of fast-mem where allocated from the OS.\n",
+ allochip,allocfast
+ );
+ printf(
+ "%d bytes of chip-mem were returned from the GC_AMIGA_FASTALLOC supported allocating functions.\n",
+ chipa
+ );
+ printf("\n");
+ printf("GC_gcollect was called %d times to avoid returning NULL or start allocating with the MEMF_ANY flag.\n",numcollects);
+ printf("%d of them was a success. (the others had to use allocation from the OS.)\n",nullretries);
+ printf("\n");
+ printf("Succeded forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",succ,succ2);
+ printf("Failed forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",nsucc,nsucc2);
+ printf("\n");
+ printf(
+ "Number of retries before succeding a chip->fast force:\n"
+ "0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
+ cur0,cur1,cur10,cur50,cur150,cur151
+ );
+ printf(
+ "Number of retries before giving up a chip->fast force:\n"
+ "0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
+ ncur0,ncur1,ncur10,ncur50,ncur150,ncur151
+ );
+#endif
+
+ while(gc_am!=NULL){
+ temp=gc_am->next;
+ FreeMem(gc_am,gc_am->size);
+ gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(temp));
+ }
+}
+
+#ifndef GC_AMIGA_ONLYFAST
+
+/* All memory with address lower than this one is chip-mem. */
+
+char *chipmax;
+
+
+/*
+ * Allways set to the last size of memory tried to be allocated.
+ * Needed to ensure allocation when the size is bigger than 100000.
+ *
+ */
+size_t latestsize;
+
+#endif
+
+
+/*
+ * The actual function that is called with the GET_MEM macro.
+ *
+ */
+
+void *GC_amiga_get_mem(size_t size){
+ struct GC_Amiga_AllocedMemoryHeader *gc_am;
+
+#ifndef GC_AMIGA_ONLYFAST
+ if(GC_amiga_dontalloc==TRUE){
+// printf("rejected, size: %d, latestsize: %d\n",size,latestsize);
+ return NULL;
+ }
+
+ // We really don't want to use chip-mem, but if we must, then as little as possible.
+ if(GC_AMIGA_MEMF==(MEMF_ANY|MEMF_CLEAR) && size>100000 && latestsize<50000) return NULL;
+#endif
+
+ gc_am=AllocMem((ULONG)(size + sizeof(struct GC_Amiga_AllocedMemoryHeader)),GC_AMIGA_MEMF);
+ if(gc_am==NULL) return NULL;
+
+ gc_am->next=GC_AMIGAMEM;
+ gc_am->size=size + sizeof(struct GC_Amiga_AllocedMemoryHeader);
+ GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(gc_am));
+
+// printf("Allocated %d (%d) bytes at address: %x. Latest: %d\n",size,tot,gc_am,latestsize);
+
+#ifdef GC_AMIGA_PRINTSTATS
+ if((char *)gc_am<chipmax){
+ allochip+=size;
+ }else{
+ allocfast+=size;
+ }
+#endif
+
+ return gc_am+1;
+
+}
+
+
+
+
+#ifndef GC_AMIGA_ONLYFAST
+
+/* Tries very hard to force GC to find fast-mem to return. Done recursively
+ * to hold the rejected memory-pointers reachable from the collector in an
+ * easy way.
+ *
+ */
+#ifdef GC_AMIGA_RETRY
+void *GC_amiga_rec_alloc(size_t size,void *(*AllocFunction)(size_t size2),const int rec){
+ void *ret;
+
+ ret=(*AllocFunction)(size);
+
+#ifdef GC_AMIGA_PRINTSTATS
+ if((char *)ret>chipmax || ret==NULL){
+ if(ret==NULL){
+ nsucc++;
+ nsucc2+=size;
+ if(rec==0) ncur0++;
+ if(rec==1) ncur1++;
+ if(rec>1 && rec<10) ncur10++;
+ if(rec>=10 && rec<50) ncur50++;
+ if(rec>=50 && rec<150) ncur150++;
+ if(rec>=150) ncur151++;
+ }else{
+ succ++;
+ succ2+=size;
+ if(rec==0) cur0++;
+ if(rec==1) cur1++;
+ if(rec>1 && rec<10) cur10++;
+ if(rec>=10 && rec<50) cur50++;
+ if(rec>=50 && rec<150) cur150++;
+ if(rec>=150) cur151++;
+ }
+ }
+#endif
+
+ if (((char *)ret)<=chipmax && ret!=NULL && (rec<(size>500000?9:size/5000))){
+ ret=GC_amiga_rec_alloc(size,AllocFunction,rec+1);
+// GC_free(ret2);
+ }
+
+ return ret;
+}
+#endif
+
+
+/* The allocating-functions defined inside the amiga-blocks in gc.h is called
+ * via these functions.
+ */
+
+
+void *GC_amiga_allocwrapper_any(size_t size,void *(*AllocFunction)(size_t size2)){
+ void *ret,*ret2;
+
+ GC_amiga_dontalloc=TRUE; // Pretty tough thing to do, but its indeed necesarry.
+ latestsize=size;
+
+ ret=(*AllocFunction)(size);
+
+ if(((char *)ret) <= chipmax){
+ if(ret==NULL){
+ //Give GC access to allocate memory.
+#ifdef GC_AMIGA_GC
+ if(!GC_dont_gc){
+ GC_gcollect();
+#ifdef GC_AMIGA_PRINTSTATS
+ numcollects++;
+#endif
+ ret=(*AllocFunction)(size);
+ }
+#endif
+ if(ret==NULL){
+ GC_amiga_dontalloc=FALSE;
+ ret=(*AllocFunction)(size);
+ if(ret==NULL){
+ WARN("Out of Memory! Returning NIL!\n", 0);
+ }
+ }
+#ifdef GC_AMIGA_PRINTSTATS
+ else{
+ nullretries++;
+ }
+ if(ret!=NULL && (char *)ret<=chipmax) chipa+=size;
+#endif
+ }
+#ifdef GC_AMIGA_RETRY
+ else{
+ /* We got chip-mem. Better try again and again and again etc., we might get fast-mem sooner or later... */
+ /* Using gctest to check the effectiviness of doing this, does seldom give a very good result. */
+ /* However, real programs doesn't normally rapidly allocate and deallocate. */
+// printf("trying to force... %d bytes... ",size);
+ if(
+ AllocFunction!=GC_malloc_uncollectable
+#ifdef ATOMIC_UNCOLLECTABLE
+ && AllocFunction!=GC_malloc_atomic_uncollectable
+#endif
+ ){
+ ret2=GC_amiga_rec_alloc(size,AllocFunction,0);
+ }else{
+ ret2=(*AllocFunction)(size);
+#ifdef GC_AMIGA_PRINTSTATS
+ if((char *)ret2<chipmax || ret2==NULL){
+ nsucc++;
+ nsucc2+=size;
+ ncur0++;
+ }else{
+ succ++;
+ succ2+=size;
+ cur0++;
+ }
+#endif
+ }
+ if(((char *)ret2)>chipmax){
+// printf("Succeeded.\n");
+ GC_free(ret);
+ ret=ret2;
+ }else{
+ GC_free(ret2);
+// printf("But did not succeed.\n");
+ }
+ }
+#endif
+ }
+
+ GC_amiga_dontalloc=FALSE;
+
+ return ret;
+}
+
+
+
+void (*GC_amiga_toany)(void)=NULL;
+
+void GC_amiga_set_toany(void (*func)(void)){
+ GC_amiga_toany=func;
+}
+
+#endif // !GC_AMIGA_ONLYFAST
+
+
+void *GC_amiga_allocwrapper_fast(size_t size,void *(*AllocFunction)(size_t size2)){
+ void *ret;
+
+ ret=(*AllocFunction)(size);
+
+ if(ret==NULL){
+ // Enable chip-mem allocation.
+// printf("ret==NULL\n");
+#ifdef GC_AMIGA_GC
+ if(!GC_dont_gc){
+ GC_gcollect();
+#ifdef GC_AMIGA_PRINTSTATS
+ numcollects++;
+#endif
+ ret=(*AllocFunction)(size);
+ }
+#endif
+ if(ret==NULL){
+#ifndef GC_AMIGA_ONLYFAST
+ GC_AMIGA_MEMF=MEMF_ANY | MEMF_CLEAR;
+ if(GC_amiga_toany!=NULL) (*GC_amiga_toany)();
+ GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_any;
+ return GC_amiga_allocwrapper_any(size,AllocFunction);
+#endif
+ }
+#ifdef GC_AMIGA_PRINTSTATS
+ else{
+ nullretries++;
+ }
+#endif
+ }
+
+ return ret;
+}
+
+void *GC_amiga_allocwrapper_firsttime(size_t size,void *(*AllocFunction)(size_t size2)){
+ atexit(&GC_amiga_free_all_mem);
+ chipmax=(char *)SysBase->MaxLocMem; // For people still having SysBase in chip-mem, this might speed up a bit.
+ GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_fast;
+ return GC_amiga_allocwrapper_fast(size,AllocFunction);
+}
+
+
+#endif //GC_AMIGA_FASTALLOC
+
+
+
+/*
+ * The wrapped realloc function.
+ *
+ */
+void *GC_amiga_realloc(void *old_object,size_t new_size_in_bytes){
+#ifndef GC_AMIGA_FASTALLOC
+ return GC_realloc(old_object,new_size_in_bytes);
+#else
+ void *ret;
+ latestsize=new_size_in_bytes;
+ ret=GC_realloc(old_object,new_size_in_bytes);
+ if(ret==NULL && GC_AMIGA_MEMF==(MEMF_FAST | MEMF_CLEAR)){
+ /* Out of fast-mem. */
+#ifdef GC_AMIGA_GC
+ if(!GC_dont_gc){
+ GC_gcollect();
+#ifdef GC_AMIGA_PRINTSTATS
+ numcollects++;
+#endif
+ ret=GC_realloc(old_object,new_size_in_bytes);
+ }
+#endif
+ if(ret==NULL){
+#ifndef GC_AMIGA_ONLYFAST
+ GC_AMIGA_MEMF=MEMF_ANY | MEMF_CLEAR;
+ if(GC_amiga_toany!=NULL) (*GC_amiga_toany)();
+ GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_any;
+ ret=GC_realloc(old_object,new_size_in_bytes);
+#endif
+ }
+#ifdef GC_AMIGA_PRINTSTATS
+ else{
+ nullretries++;
+ }
+#endif
+ }
+ if(ret==NULL){
+ WARN("Out of Memory! Returning NIL!\n", 0);
+ }
+#ifdef GC_AMIGA_PRINTSTATS
+ if(((char *)ret)<chipmax && ret!=NULL){
+ chipa+=new_size_in_bytes;
+ }
+#endif
+ return ret;
+#endif
+}
+
+#endif //GC_AMIGA_AM
+
+
diff --git a/tools/build/v2/engine/boehm_gc/BCC_MAKEFILE b/tools/build/v2/engine/boehm_gc/BCC_MAKEFILE
new file mode 100644
index 0000000000..b825ec4df7
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/BCC_MAKEFILE
@@ -0,0 +1,87 @@
+# Makefile for Borland C++ 5.5 on NT
+# If you have the Borland assembler, remove "-DUSE_GENERIC"
+#
+bc= c:\Borland\BCC55
+bcbin= $(bc)\bin
+bclib= $(bc)\lib
+bcinclude= $(bc)\include
+
+gcinclude1 = $(bc)\gc6.2\include
+gcinclude2 = $(bc)\gc6.2\cord
+
+cc= $(bcbin)\bcc32
+rc= $(bcbin)\brc32
+lib= $(bcbin)\tlib
+link= $(bcbin)\ilink32
+cflags= -O2 -R -v- -vi -H -H=gc.csm -I$(bcinclude);$(gcinclude1);$(gcinclude2) -L$(bclib) \
+ -w-pro -w-aus -w-par -w-ccc -w-rch -a4 -D__STDC__=0
+defines= -DALL_INTERIOR_POINTERS -DUSE_GENERIC -DNO_GETENV -DJAVA_FINALIZATION -DGC_OPERATOR_NEW_ARRAY
+
+.c.obj:
+ $(cc) @&&|
+ $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.c
+|
+
+.cpp.obj:
+ $(cc) @&&|
+ $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.cpp
+|
+
+.rc.res:
+ $(rc) -i$(bcinclude) -r -fo$* $*.rc
+
+XXXOBJS= XXXalloc.obj XXXreclaim.obj XXXallchblk.obj XXXmisc.obj \
+ XXXmach_dep.obj XXXos_dep.obj XXXmark_rts.obj XXXheaders.obj XXXmark.obj \
+ XXXobj_map.obj XXXblacklst.obj XXXfinalize.obj XXXnew_hblk.obj \
+ XXXdbg_mlc.obj XXXmalloc.obj XXXstubborn.obj XXXdyn_load.obj \
+ XXXtypd_mlc.obj XXXptr_chck.obj XXXgc_cpp.obj XXXmallocx.obj
+
+OBJS= $(XXXOBJS:XXX=)
+
+all: gctest.exe cord\de.exe test_cpp.exe
+
+$(OBJS) test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h MAKEFILE
+
+gc.lib: $(OBJS)
+ del gc.lib
+ $(lib) $* @&&|
+ $(XXXOBJS:XXX=+)
+|
+
+gctest.exe: tests\test.obj gc.lib
+ $(cc) @&&|
+ $(cflags) -W -e$* tests\test.obj gc.lib
+|
+
+cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h \
+ cord\de_cmds.h
+
+cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj \
+ cord\de_win.res gc.lib
+ $(cc) @&&|
+ $(cflags) -W -e$* cord\cordbscs.obj cord\cordxtra.obj \
+ cord\de.obj cord\de_win.obj gc.lib
+|
+ $(rc) cord\de_win.res cord\de.exe
+
+gc_cpp.obj: include\gc_cpp.h include\gc.h
+
+gc_cpp.cpp: gc_cpp.cc
+ copy gc_cpp.cc gc_cpp.cpp
+
+test_cpp.cpp: tests\test_cpp.cc
+ copy tests\test_cpp.cc test_cpp.cpp
+
+test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib
+ $(cc) @&&|
+ $(cflags) -W -e$* test_cpp.obj gc.lib
+|
+
+scratch:
+ -del *.obj *.res *.exe *.csm cord\*.obj cord\*.res cord\*.exe cord\*.csm
+
+clean:
+ del gc.lib
+ del *.obj
+ del tests\test.obj
+
diff --git a/tools/build/v2/engine/boehm_gc/ChangeLog b/tools/build/v2/engine/boehm_gc/ChangeLog
new file mode 100644
index 0000000000..96bf3171e9
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/ChangeLog
@@ -0,0 +1,363 @@
+2007-07-02 Hans Boehm <Hans.Boehm@hp.com>
+
+ * gc_config_macros.h: Also check for IA64 when setting
+ GC_HPUX_THREADS.
+ * mallocx.c: Change my_bytes_allocd to signed_word.
+ * include/pthread_redirects.h: Remove obsolete Solaris threads
+ (as opposed to pthreads) support.
+
+2007-07-02 Hans Boehm <Hans.Boehm@hp.com>
+
+ * mach_dep.c (GC_with_callee_saves_pushed): Don't use getcontext()
+ on ARM/Linux. Check getcontext() return value.
+
+2007-06-29 Hans Boehm <Hans.Boehm@hp.com>
+
+ * backgraph.c (per_object_func): Make argument types consistent.
+ (GC_traverse_back_graph): Mark GC_deepest_obj.
+
+2007-06-29 Hans Boehm <Hans.Boehm@hp.com>
+
+ * finalize.c (GC_finalize): Change dl_size and fo_size to size_t.
+ * os_dep.c (GC_win32_get_mem): Add GC_mem_top_down option.
+
+2007-06-28 Hans Boehm <Hans.Boehm@hp.com>
+
+ * doc/README.win32, doc/README, README.QUICK: Fix some of the worst
+ anachronisms.
+ * dyn_load.c: Partially support cygwin, but don't enable it yet.
+
+2007-06-28 Hans Boehm <Hans.Boehm@hp.com>
+
+ * Makefile.am: Use -no-undefined for libgc.
+ * Makefile.in: Regenerate.
+ * Makefile.direct: Document USE_PROC_FOR_LIBRARIES.
+ * dyn_load.c (GC_register_map_entries): Rename prot_buf to prot
+ consistently.
+ * misc.c: Fix some WARN calls. Move GC_is_initialized setting and
+ GC_thr_init() call.
+ * os_dep.c: Consistently use WARN where appropriate.
+ * thread_local_alloc.c: Revert change to GC_WIN32_THREADS test. Instead
+ remove inappropriate pthread.h include.
+ * doc/README.linux: Remove some anachronisms.
+
+2007-06-23 Hans Boehm <Hans.Boehm@hp.com>
+
+ * alloc.c: Also use GC_check_tls on non-Linux systems.
+ * mallocx.c (GC_reclaim_generic): Remove bogus declaration.
+ * include/private/gc_priv.h (GC_reclaim_generic): Declare correctly
+ with prototype.
+
+2007-06-19 Hans Boehm <Hans.Boehm@hp.com>
+
+ * alloc.c (GC_adj_bytes_allocd): Avoid (long) casts, fix comment.
+ (GC_print_heap_sects): Use size_t instead of unsigned long.
+ * thread_local_alloc.c (GC_lookup_thread): Define in the correct
+ context.
+ * win32_threads.c, include/gc_config_macros.h: The last of Romano
+ Paolo Tenca's patch. Move stdint.h include to gc_config_macros.h.
+ * include/gc_inline.h: Avoid gc_priv.h dependencies.
+ * tests/test.c (check_heap_stats): Replace unsigned long with size_t.
+
+2007-06-12 Hans Boehm <Hans.Boehm@hp.com>
+
+ * aclocal.m4: Regenerate to update date.
+
+2007-06-10 Hans Boehm <Hans.Boehm@hp.com>
+
+ * NT_X64_STATIC_THREADS_MAKEFILE: Replace obsolete -debugtype:cv.
+ * mark_rts.c (GC_push_roots): Fix kind type.
+
+2007-06-06 Hans Boehm <Hans.Boehm@hp.com>
+
+ * doc/README.win64: New file.
+ * doc/doc.am, Makefile.direct: Add README.win64.
+ * Makefile.in: Regenerate.
+
+2007-06-06 Hans Boehm <Hans.Boehm@hp.com>
+
+ * Makefile.am, Makefile.direct: Add NT_X64_STATIC_THREADS_MAKEFILE.
+ * Makefile.in: Regenerate.
+ * NT_X64_STATIC_THREADS_MAKEFILE: Fix warning flags.
+ * allochblk.c, alloc.c, blacklst.c, dbg_malc.c, dyn_load.c,
+ finalize.c, headers.c, mach_dep.c, malloc.c, mark.c, misc.c,
+ obj_map.c, os_dep.c, ptr_chck.c, reclaim.c, typd_mlc.c,
+ win32_threads.c, cord/de_win.c, include/gc_mark.h,
+ include/private/gc_hdrs.h, include/private/gc_pmark.h,
+ include/private/gc_priv.h, tests/test_cpp.cc:
+ Replace old style function declarations. Clean up integral types.
+ Remove register declarations. The change in malloc.c and the
+ "int descr" declaration in mark.c are the most likely to have
+ been real bugs outside of win64.
+ * msvc_dbg.c: Disable on win64.
+ * win32_threads.c: Add AMD64 support.
+ * include/gc.h: no backtrace on AMD64 for now.
+
+2007-06-06 Hans Boehm <Hans.Boehm@hp.com>
+
+ * msvc_dbg.c(GetModuleBase): Replace strcat with strcat_s.
+
+2007-06-06 Hans Boehm <Hans.Boehm@hp.com>
+
+ * include/gc.h: (GC_word, GC_signed_word): Fix win64 definitions.
+ Don't include windows.h in an extern "C" context.
+ * include/private/gcconfig.h: Fix win64/X86_64 configuration.
+ * tests/test.c: Eliminate more old style function definitions.
+ Cleanup pointer and integer casts for win64.
+ * tests/test_cpp.cc: Don't include gc_priv.h.
+ * NT_STATIC_THREADS_MAKEFILE: Restrict suffixes for VC++ 2005.
+ * NT_X64_STATIC_THREADS_MAKEFILE: New.
+
+2007-06-06 Hans Boehm <Hans.Boehm@hp.com> (Really mostly Romano Paolo Tenca)
+
+ * win32_threads.c: Separate out DEBUG_WIN32_PTHREADS_STACK. Ignore
+ FINISHED threads for suspension. (GC_pthread_join): Add
+ pthread_self() cast. (GC_pthread_start_inner): Execute cleanup
+ handler when popping it.
+ * include/private/gc_locks.h: Inline THREAD_EQUAL for
+ GC_WIN32_PTHREADS. Define USE_PTHREAD_LOCKS only if we have
+ pthreads.
+
+2007-05-23 Hans Boehm <Hans.Boehm@hp.com> (Really mostly Romano Paolo Tenca)
+
+ * gc_dlopen.c, thread_local_alloc.c, threadlibs.c, win32_threads.c,
+ tests/test.c: Accomodate GC_WIN32_PTHREADS.
+ * include/gc.h: Don't include windows.h for GC_WIN32_PTHREADS.
+ * include/gc_config_macros.h: Define both PTHREADS and
+ GC_WIN32_THREADS.
+ * include/private/gc_locks.h: Nonstandard definitions of
+ NUMERIC_THREAD_ID for GC_WIN32_PTHREADS.
+ * doc/README.win32, Makefile.direct: Include documentation
+ for GC_WIN32_PTHREADS.
+ * Makefile.direct: Remove some anachronisms in the documentation.
+
+2007-05-23 Hans Boehm <Hans.Boehm@hp.com>
+
+ * Makefile.am: Move includes to bottom. Add better library
+ dependencies. Increment library version. Remove "SUBDIRS += .".
+ * cord/cord.am, tests/tests.am: Add better library dependencies.
+ Remove now unnecessary dependencies.
+ * Makefile.in: Regenerate.
+ * include/gc.h (GC_begin_thread_ex, GC_endthreadex, GC_ExitThread):
+ Move to define on all Windows platforms. (_beginthread): define
+ to generate error if used.
+
+2007-05-22 Hans Boehm <Hans.Boehm@hp.com>
+
+ * include/private/gc_locks.h: Format to 80 columns.
+
+2007-05-22 Hans Boehm <Hans.Boehm@hp.com>
+
+ * malloc.c(GC_free): Ignore bad frees on MSWIN32 with REDIRECT_MALLOC.
+ * NT_MAKEFILE: msvc_dbg.h is in include/private. Don't use cvars
+ rc.
+ * misc.c (WIN32 GC_write): Define GC_need_to_lock in single-threaded
+ case.
+ * win32_threads.c: Test for __MINGW32__ in addition to _MINGW_VER.
+ (GC_CreateThread, GC_beginthreadex): Deallocate args even if we fail.
+ * include/gc.h: Add GC_reachable_here(). (GC_WinMain): Add GC_API.
+ (GC_beginthreadex, GC_endthreadex, GC_ExitThread): Declare.
+ * tests/test.c: Add GC_reachable_here() call.
+
+2007-05-21 Hans Boehm <Hans.Boehm@hp.com>
+
+ * alloc.c (GC_try_to_collect): Call GC_init if necessary.
+ * tests/thread_leak_test.c: Don't unconditionally define
+ GC_LINUX_THREADS.
+
+2007-05-21 Andreas Tobler <a.tobler@schweiz.org>
+
+ * Makefile.am: Remove extra_ldflags_libgc definition.
+ * Makefile.in: Regenerate.
+
+2007-05-17 Hans Boehm <Hans.Boehm@hp.com>
+
+ * include/private/gc_priv.h: Define AO_REQUIRE_CAS.
+
+2007-05-16 Hans Boehm <Hans.Boehm@hp.com>
+
+ * finalize.c (GC_unreachable_finalize_mark_proc): Don't return void
+ value.
+
+2007-05-15 Hans Boehm <Hans.Boehm@hp.com>
+
+ * configure.ac, version.h, doc/README: Change version to 7.0alpha10.
+ * configure: Regenerate.
+
+[7.0alpha9 release]
+
+2007-05-15 Hans Boehm <Hans.Boehm@hp.com>
+
+ * configure.ac, version.h, doc/README: Change version to 7.0alpha9.
+ * configure: Regenerate.
+
+2007-05-15 Hans Boehm <Hans.Boehm@hp.com>
+
+ * Makefile.am: Include NT_STSTIC_THREADS_MAKEFILE in dist.
+ * Makefile.in: Regenerate.
+ * include/private/gc_locks.h: GC_compare_and_exchange, GC_atomic_add:
+ remove. NUMERIC_THREAD_ID, THREAD_EQUAL: New. GC_lock_holder: now
+ unsigned long. I_DONT_HOLD_LOCK, I_HOLD_LOCK: Update.
+ * pthread_stop_world.c, pthread_support.c, win32_threads.c: Use
+ NUMERIC_THREAD_ID, THREAD_EQUAL.
+ * include/private/gcconfig.h: GENERIC_COMPARE_AND_SWAP: Remove.
+ * include/private/thread_local_alloc.h: Don't USE_COMPILER_TLS on
+ ARM.
+
+2007-05-11 Hans Boehm <Hans.Boehm@hp.com>
+
+ * dbg_mlc.c, include/gc.h, finalize.c: Merge Alexandre Oliva's
+ GC_debug_register_finalizer_unreachable() patch from gcc tree.
+ * thread_local_alloc.c (GC_malloc, GC_malloc_atomic): Add assertions
+ to check GC has been initialized.
+
+2007-05-10 Hans Boehm <Hans.Boehm@hp.com>
+
+ * include/gc_cpp.h: Documentation updates.
+ * include/gc_config_macros.h: Don't check for __ppc__ to set
+ DARWIN_THREADS.
+ * Makefile.am: Include configure_atomic_ops.sh in dist.
+ * Makefile.in: Regenerate.
+
+2007-05-08 Hans Boehm <Hans.Boehm@hp.com>
+
+ * Makefile.am: Dont distribute copied atomic_ops files. Include
+ libatomic_ops with "make dist".
+ * Makefile.in: Regenerate.
+ * configure: Regenerate.
+ * configure.ac: Enable THREAD_LOCAL_ALLOC for Cygwin with threads.
+ * win32_threads.c: Report error for Cygwin + GC_DLL.
+
+2007-05-08 Hans Boehm <Hans.Boehm@hp.com>
+
+ * Makefile.direct: Update THREAD_LOCAL_ALLOC documentation.
+ * cord/de_win.c: Rename and move AboutBox. Call GC_INIT. Remove
+ MakeProcInstance anachronism.
+ * doc/README.macros: Officially remove elif prohibition.
+ Remove documentation for defunct SRC_M3 support.
+ * include/gc.h: Remove more SRC_M3 references.
+ * include/private/gcconfig.h: Remove still more SRC_M3 references.
+ GC_SOLARIS_THREADS no longer needs to be checked separately.
+
+2007-05-08 Hans Boehm <Hans.Boehm@hp.com>
+
+ * thread_local_alloc.c, include/private/thread_local_alloc.h:
+ Spell __declspec correctly.
+ * NT_STATIC_THREADS_MAKEFILE: Enable thread-local allocation.
+
+2007-05-07 Hans Boehm <Hans.Boehm@hp.com>
+
+ * doc/README.win32: Adjust GC_win32_dll_threads rules again.
+
+2007-05-07 Hans Boehm <Hans.Boehm@hp.com>
+
+ * mark.c (GC_mark_some wrapper): Restructure for readability, handle
+ GC_started_thread_while_stopped.
+ * misc.c (Win32 GC_write): Lock GC_write_cs only if needed.
+ * win32_threads.c: (client_has_run): remove,
+ GC_started_thread_while_stopped, GC_attached_thread: add.
+ (GC_push_all_stacks): Add verbose output.
+ (DllMain): Avoid initializing collector or the like.
+ Never update both thread tables.
+ * doc/README.win32: Adjust GC_win32_dll_threads rules.
+
+2007-05-07 Hans Boehm <Hans.Boehm@hp.com>
+
+ * pthread_stop_world.c (GC_push_all_stacks): Print thread count with
+ GC_PRINT_VERBOSE_STATS.
+
+2007-05-01 Hans Boehm <Hans.Boehm@hp.com>
+ (and Manuel Serrano, Craig McDaniel)
+
+ * configure.ac: Comment out redundant
+ AC_DEFINE(NO_EXECUTE_PERMISSION).
+ * configure: Regenerate.
+ * sparc_mach_dep.S: Remove single quote in comment.
+ * include/private/gcconfig.h: Fix DATAEND for NONSTOP.
+ * win32_threads.c: Include stdint.h for Mingw. Add GC_API for DllMain.
+ (GC_use_DllMain): Fix assertion.
+
+2007-02-14 Andreas Tobler <a.tobler@schweiz.org>
+
+ * configure.ac: Introduce extra_ldflags_libgc. Use it for Darwin.
+ * configure: Regenerate.
+ * Makefile.am (libgc_la_LDFLAGS): Use extra_ldflags_libgc.
+ * Makefile.in: Regenerate.
+ * include/private/gcconfig.h: Enable MPROTECT_VDB for all Darwin
+ targets. Remove comments.
+ Prepare ppc64 support for Darwin.
+
+2007-01-29 Andreas Tobler <a.tobler@schweiz.org>
+
+ * darwin_stop_world.c: Clean up and reformat code.
+
+2007-01-28 Andreas Tobler <a.tobler@schweiz.org>
+
+ * darwin_stop_world.c (GC_push_all_stacks): Fix compiler warnings.
+ Make i unsigned.
+ (GC_stop_world): Likewise. Remove unused GC_thread p.
+ (GC_start_world): Likewise.
+
+ * os_dep.c: Define GC_darwin_register_mach_handler_thread extern.
+ Remove double SIG_HNDLR_PTR definition.
+ (GC_forward_exception): Fix compiler warnings, make i unsigned.
+ Initialize thread_state to NULL.
+ (catch_exception_raise): Fix compiler warnings, make i unsigned.
+
+2007-01-25 Petr Salinger and Hans Boehm <Hans.Boehm@hp.com>
+
+ * include/private/gc_priv.h (NEED_FIND_LIMIT, FREEBSD variant):
+ also define for X86_64.
+ * configure.ac: Move generic gnu (Hurd) case to below kfreebsd case.
+ * configure: Regenerate.
+ * README.changes: Point to ChangeLog.
+
+2007-01-25 Andreas Tobler <a.tobler@schweiz.org>
+
+ * darwin_stop_world.c: Move THREAD_FLD defines to ...
+ * include/private/gc_priv.h: ... here.
+ Fix THREAD_STATE definitions for ppc64.
+ * os_dep.c (catch_exception_raise): Use THREAD_FLD for exc_state member
+ access.
+
+2007-01-18 Andreas Tobler <a.tobler@schweiz.org>
+
+ * os_dep.c (if defined(MPROTECT_VDB) && defined(DARWIN)): Clean up and
+ reformat code.
+ Correct email reference.
+
+2007-01-11 Andreas Tobler <a.tobler@schweiz.org>
+
+ * configure.ac (i?86*-*-darwin*): Replaced HAS_I386_THREAD_STATE_* with
+ HAS_X86_THREAD_STATE32_*.
+ (x86_64-*-darwin*): Extended the above check for x86_64-*-darwin* with
+ HAS_X86_THREAD_STATE64_*.
+ Added value 1 in the above AC_DEFINE's. Important for the upcoming
+ Leopard.
+ * configure: Regenerated.
+ * include/private/gcconfig.h: Modified X86_64 define for Darwin.
+ Removed __x86_64__ check in POWERPC section. Added base definitions
+ for the X86_64 Darwin port.
+ * include/private/gc_priv.h: Added GC_MACH_HEADER and GC_MACH_SECTION
+ to distinguish between 32 and 64-bit applications. Added definitions
+ for X86_64 Darwin.
+ * darwin_stop_world.c: Added HAS_X86_THREAD_STATE64___RAX. And
+ replaced HAS_I386_THREAD_STATE___EAX with HAS_X86_THREAD_STATE32___EAX.
+ (GC_push_all_stacks): Added code for X86_64 Darwin. Even for the
+ !DARWIN_DONT_PARSE_STACK. Maybe obsolete.
+ * dyn_load.c (GC_dyld_name_for_hdr): Use GC_MACH_HEADER.
+ (GC_dyld_image_add): Use GC_MACH_HEADER and GC_MACH_SECTION.
+ Distinguish between getsectbynamefromheader_64 and
+ getsectbynamefromheader.
+ * os_dep.c (catch_exception_raise): Introduce exception definition for
+ X86_64 Darwin. Replaced old i386_EXCEPTION_STATE_* definition with
+ x86_EXCEPTION_STATE32_*. Add X86_64 for exc_state.faultvaddr.
+
+2007-01-09 Andreas Tobler <a.tobler@schweiz.org>
+
+ * libtool.m4: Update to version from libtool-1.5.22.
+ * ltmain.sh: Likewise.
+ * ChangeLog: Created.
+
+See doc/README.changes for earlier changes.
+
diff --git a/tools/build/v2/engine/boehm_gc/EMX_MAKEFILE b/tools/build/v2/engine/boehm_gc/EMX_MAKEFILE
new file mode 100644
index 0000000000..c7e5bb806e
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/EMX_MAKEFILE
@@ -0,0 +1,140 @@
+#
+# OS/2 specific Makefile for the EMX environment
+#
+# You need GNU Make 3.71, gcc 2.5.7, emx 0.8h and GNU fileutils 3.9
+# or similar tools. C++ interface and de.exe weren't tested.
+#
+# Rename this file "Makefile".
+#
+
+# Primary targets:
+# gc.a - builds basic library
+# c++ - adds C++ interface to library and include directory
+# cords - adds cords (heavyweight strings) to library and include directory
+# test - prints porting information, then builds basic version of gc.a, and runs
+# some tests of collector and cords. Does not add cords or c++ interface to gc.a
+# cord/de.exe - builds dumb editor based on cords.
+CC= gcc
+CXX=g++
+# Needed only for "make c++", which adds the c++ interface
+
+CFLAGS= -O -DALL_INTERIOR_POINTERS
+# Setjmp_test may yield overly optimistic results when compiled
+# without optimization.
+# -DCHECKSUMS reports on erroneously clear dirty bits, and unexpectedly
+# altered stubborn objects, at substantial performance cost.
+# -DFIND_LEAK causes the collector to assume that all inaccessible
+# objects should have been explicitly deallocated, and reports exceptions
+# -DSOLARIS_THREADS enables support for Solaris (thr_) threads.
+# (Clients should also define SOLARIS_THREADS and then include
+# gc.h before performing thr_ or GC_ operations.)
+# -DALL_INTERIOR_POINTERS allows all pointers to the interior
+# of objects to be recognized. (See gc_private.h for consequences.)
+# -DSMALL_CONFIG tries to tune the collector for small heap sizes,
+# usually causing it to use less space in such situations.
+# Incremental collection no longer works in this case.
+# -DDONT_ADD_BYTE_AT_END is meaningful only with
+# -DALL_INTERIOR_POINTERS. Normally -DALL_INTERIOR_POINTERS
+# causes all objects to be padded so that pointers just past the end of
+# an object can be recognized. This can be expensive. (The padding
+# is normally more than one byte due to alignment constraints.)
+# -DDONT_ADD_BYTE_AT_END disables the padding.
+
+AR= ar
+RANLIB= ar s
+
+# Redefining srcdir allows object code for the nonPCR version of the collector
+# to be generated in different directories
+srcdir = .
+VPATH = $(srcdir)
+
+OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dyn_load.o dbg_mlc.o malloc.o stubborn.o checksums.o typd_mlc.o ptr_chck.o mallocx.o
+
+CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o
+
+CORD_INCLUDE_FILES= $(srcdir)/gc.h $(srcdir)/cord/cord.h $(srcdir)/cord/ec.h \
+ $(srcdir)/cord/cord_pos.h
+
+# Libraries needed for curses applications. Only needed for de.
+CURSES= -lcurses -ltermlib
+
+# The following is irrelevant on most systems. But a few
+# versions of make otherwise fork the shell specified in
+# the SHELL environment variable.
+SHELL= bash
+
+SPECIALCFLAGS =
+# Alternative flags to the C compiler for mach_dep.c.
+# Mach_dep.c often doesn't like optimization, and it's
+# not time-critical anyway.
+
+all: gc.a gctest.exe
+
+$(OBJS) test.o: $(srcdir)/gc_priv.h $(srcdir)/gc_hdrs.h $(srcdir)/gc.h \
+ $(srcdir)/gcconfig.h $(srcdir)/gc_typed.h
+# The dependency on Makefile is needed. Changing
+# options affects the size of GC_arrays,
+# invalidating all .o files that rely on gc_priv.h
+
+mark.o typd_mlc.o finalize.o: $(srcdir)/include/gc_mark.h $(srcdir)/include/private/gc_pmark.h
+
+gc.a: $(OBJS)
+ $(AR) ru gc.a $(OBJS)
+ $(RANLIB) gc.a
+
+cords: $(CORD_OBJS) cord/cordtest.exe
+ $(AR) ru gc.a $(CORD_OBJS)
+ $(RANLIB) gc.a
+ cp $(srcdir)/cord/cord.h include/cord.h
+ cp $(srcdir)/cord/ec.h include/ec.h
+ cp $(srcdir)/cord/cord_pos.h include/cord_pos.h
+
+gc_cpp.o: $(srcdir)/gc_cpp.cc $(srcdir)/gc_cpp.h
+ $(CXX) -c -O $(srcdir)/gc_cpp.cc
+
+c++: gc_cpp.o $(srcdir)/gc_cpp.h
+ $(AR) ru gc.a gc_cpp.o
+ $(RANLIB) gc.a
+ cp $(srcdir)/gc_cpp.h include/gc_cpp.h
+
+mach_dep.o: $(srcdir)/mach_dep.c
+ $(CC) -o mach_dep.o -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+
+mark_rts.o: $(srcdir)/mark_rts.c
+ $(CC) -o mark_rts.o -c $(CFLAGS) $(srcdir)/mark_rts.c
+
+cord/cordbscs.o: $(srcdir)/cord/cordbscs.c $(CORD_INCLUDE_FILES)
+ $(CC) $(CFLAGS) -c $(srcdir)/cord/cordbscs.c -o cord/cordbscs.o
+
+cord/cordxtra.o: $(srcdir)/cord/cordxtra.c $(CORD_INCLUDE_FILES)
+ $(CC) $(CFLAGS) -c $(srcdir)/cord/cordxtra.c -o cord/cordxtra.o
+
+cord/cordprnt.o: $(srcdir)/cord/cordprnt.c $(CORD_INCLUDE_FILES)
+ $(CC) $(CFLAGS) -c $(srcdir)/cord/cordprnt.c -o cord/cordprnt.o
+
+cord/cordtest.exe: $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a
+ $(CC) $(CFLAGS) -o cord/cordtest.exe $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a
+
+cord/de.exe: $(srcdir)/cord/de.c $(srcdir)/cord/cordbscs.o $(srcdir)/cord/cordxtra.o gc.a
+ $(CC) $(CFLAGS) -o cord/de.exe $(srcdir)/cord/de.c $(srcdir)/cord/cordbscs.o $(srcdir)/cord/cordxtra.o gc.a $(CURSES)
+
+clean:
+ rm -f gc.a tests/test.o gctest.exe output-local output-diff $(OBJS) \
+ setjmp_test mon.out gmon.out a.out core \
+ $(CORD_OBJS) cord/cordtest.exe cord/de.exe
+ -rm -f *~
+
+gctest.exe: tests/test.o gc.a
+ $(CC) $(CFLAGS) -o gctest.exe tests/test.o gc.a
+
+# If an optimized setjmp_test generates a segmentation fault,
+# odds are your compiler is broken. Gctest may still work.
+# Try compiling setjmp_t.c unoptimized.
+setjmp_test.exe: $(srcdir)/setjmp_t.c $(srcdir)/gc.h
+ $(CC) $(CFLAGS) -o setjmp_test.exe $(srcdir)/setjmp_t.c
+
+test: setjmp_test.exe gctest.exe
+ ./setjmp_test
+ ./gctest
+ make cord/cordtest.exe
+ cord/cordtest
diff --git a/tools/build/v2/engine/boehm_gc/MacOS.c b/tools/build/v2/engine/boehm_gc/MacOS.c
new file mode 100644
index 0000000000..b56bea782b
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/MacOS.c
@@ -0,0 +1,156 @@
+/*
+ MacOS.c
+
+ Some routines for the Macintosh OS port of the Hans-J. Boehm, Alan J. Demers
+ garbage collector.
+
+ <Revision History>
+
+ 11/22/94 pcb StripAddress the temporary memory handle for 24-bit mode.
+ 11/30/94 pcb Tracking all memory usage so we can deallocate it all at once.
+ 02/10/96 pcb Added routine to perform a final collection when
+unloading shared library.
+
+ by Patrick C. Beard.
+ */
+/* Boehm, February 15, 1996 2:55 pm PST */
+
+#include <Resources.h>
+#include <Memory.h>
+#include <LowMem.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gc.h"
+#include "gc_priv.h"
+
+// use 'CODE' resource 0 to get exact location of the beginning of global space.
+
+typedef struct {
+ unsigned long aboveA5;
+ unsigned long belowA5;
+ unsigned long JTSize;
+ unsigned long JTOffset;
+} *CodeZeroPtr, **CodeZeroHandle;
+
+void* GC_MacGetDataStart()
+{
+ CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0);
+ if (code0) {
+ long belowA5Size = (**code0).belowA5;
+ ReleaseResource((Handle)code0);
+ return (LMGetCurrentA5() - belowA5Size);
+ }
+ fprintf(stderr, "Couldn't load the jump table.");
+ exit(-1);
+ return 0;
+}
+
+/* track the use of temporary memory so it can be freed all at once. */
+
+typedef struct TemporaryMemoryBlock TemporaryMemoryBlock, **TemporaryMemoryHandle;
+
+struct TemporaryMemoryBlock {
+ TemporaryMemoryHandle nextBlock;
+ char data[];
+};
+
+static TemporaryMemoryHandle theTemporaryMemory = NULL;
+static Boolean firstTime = true;
+
+void GC_MacFreeTemporaryMemory(void);
+
+Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory)
+{
+ static Boolean firstTime = true;
+ OSErr result;
+ TemporaryMemoryHandle tempMemBlock;
+ Ptr tempPtr = nil;
+
+ tempMemBlock = (TemporaryMemoryHandle)TempNewHandle(size + sizeof(TemporaryMemoryBlock), &result);
+ if (tempMemBlock && result == noErr) {
+ HLockHi((Handle)tempMemBlock);
+ tempPtr = (**tempMemBlock).data;
+ if (clearMemory) memset(tempPtr, 0, size);
+ tempPtr = StripAddress(tempPtr);
+
+ // keep track of the allocated blocks.
+ (**tempMemBlock).nextBlock = theTemporaryMemory;
+ theTemporaryMemory = tempMemBlock;
+ }
+
+# if !defined(SHARED_LIBRARY_BUILD)
+ // install an exit routine to clean up the memory used at the end.
+ if (firstTime) {
+ atexit(&GC_MacFreeTemporaryMemory);
+ firstTime = false;
+ }
+# endif
+
+ return tempPtr;
+}
+
+extern word GC_fo_entries;
+
+static void perform_final_collection()
+{
+ unsigned i;
+ word last_fo_entries = 0;
+
+ /* adjust the stack bottom, because CFM calls us from another stack
+ location. */
+ GC_stackbottom = (ptr_t)&i;
+
+ /* try to collect and finalize everything in sight */
+ for (i = 0; i < 2 || GC_fo_entries < last_fo_entries; i++) {
+ last_fo_entries = GC_fo_entries;
+ GC_gcollect();
+ }
+}
+
+
+void GC_MacFreeTemporaryMemory()
+{
+# if defined(SHARED_LIBRARY_BUILD)
+ /* if possible, collect all memory, and invoke all finalizers. */
+ perform_final_collection();
+# endif
+
+ if (theTemporaryMemory != NULL) {
+ long totalMemoryUsed = 0;
+ TemporaryMemoryHandle tempMemBlock = theTemporaryMemory;
+ while (tempMemBlock != NULL) {
+ TemporaryMemoryHandle nextBlock = (**tempMemBlock).nextBlock;
+ totalMemoryUsed += GetHandleSize((Handle)tempMemBlock);
+ DisposeHandle((Handle)tempMemBlock);
+ tempMemBlock = nextBlock;
+ }
+ theTemporaryMemory = NULL;
+
+# if !defined(SHARED_LIBRARY_BUILD)
+ if (GC_print_stats) {
+ fprintf(stdout, "[total memory used: %ld bytes.]\n",
+ totalMemoryUsed);
+ fprintf(stdout, "[total collections: %ld.]\n", GC_gc_no);
+ }
+# endif
+ }
+}
+
+#if __option(far_data)
+
+ void* GC_MacGetDataEnd()
+ {
+ CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0);
+ if (code0) {
+ long aboveA5Size = (**code0).aboveA5;
+ ReleaseResource((Handle)code0);
+ return (LMGetCurrentA5() + aboveA5Size);
+ }
+ fprintf(stderr, "Couldn't load the jump table.");
+ exit(-1);
+ return 0;
+ }
+
+#endif /* __option(far_data) */
diff --git a/tools/build/v2/engine/boehm_gc/MacProjects.sit.hqx b/tools/build/v2/engine/boehm_gc/MacProjects.sit.hqx
new file mode 100644
index 0000000000..99dff88b4c
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/MacProjects.sit.hqx
@@ -0,0 +1,886 @@
+(This file must be converted with BinHex 4.0)
+
+:$deKBe"bEfTPBh4c,R0TG!"6594%8dP8)3#3"&)e!!!"4UiT8dP8)3!(!!"50A*
+
+-BA8#ZJ#3!aB"#3d0#'GM,MBi5bkjBf038%-ZZ3#3%)Zi!*!8"@`!N!6rN!4069"
+
+568e$3`%!UbqAD+X`19S!!!Ba!!!,*J!!!F%!!!-PfTmj1`#3"PET)d31)LTH6H4
+
+#*AqG5b5HI*)QjY$IIb00%ReTJSi6rG$jG(bZ,"Rc,9Umf[IRj)6FZ-j`GfGR)#!
+
+m-#qLqB#cj'G%46qffB3q8AppLXKc+P&*il4FMJMq3N32r[U,(PlSNdrQm-J(4!p
+
+jK)NHmKJSHY!,&chS$4)pk%8mL3I)B0'$AU6S3'q)k%%[5[5J&ffa#68)0ZM&#T!
+
+!*fHC-2dFZ3i83[Vr[4Xh'+DNQrm'J)rrpqe%ST`,FeVi6b,*qHH")4eQc28NFMN
+
+ZT*m,L"Y%-`pdAk6RLHDaeVV0a,,@P(4UUK66rUM'8bf91llS("lTh81)MBQ+4*q
+
+rfHENEhD)Ke#3!09'M%bL[P1+G88fa$3e)5Gpf0kARpBf*6eIH*0`ZBHR%ii"PbN
+
++D&*)688M)Sm$Bm[cCdDjh2YIjmAc`(TVpi*Vka((A*&Yl@'LTSH1M*AMP#,2[A$
+
+(FHA@S"dL4dER#3b!EfBYem(C9P5iGH"a-bb-AL(F"bb-AL,F6)%a9pJUL,(hf%B
+
+TeQb["X5ib4DQXV!-fa6&mZf&3,(C&UDd-((SpeMBEIB`8Zc,BcZR3A5'X+jYj$'
+
+6)6HVV+R[!`#3!`X!(E@*MFQ%R4d"))`m[3JM[c)bBS54Tj'M(AP+MK&f%VD5SdG
+
+SANFB@3Rqc$Am83(+)`"G(D%A'9!bBQ6!b)b4Sq3SH8D1NDGNX$)bBi54!51--$*
+
+Kj0L!M"KKK"dC--,)-h+-6#KKC-$)-F)NamL!!Z06#X!!b&%bBUHp8RcN'%%6!b,
+
+i!!kV"`"DLHFaK*!!"Ym4K,,2i2X4c[,`c5!GIPf!ZcNi'8'VfJFpSfdpq+CY$8j
+
+-V'f-DZr2[36#1(ael5hmfT@1cSU66D5pqDSA89pdTP-`Z[jj6T&!PmZBFZjal"&
+
+5iG6#blE$+&kLh#QZ118&(0T1J(hZ,9)5MJ9ic*qPI!ac'RJ96QMZjSbkMq()Ui6
+
+B+f,,#'N1icbM4N"aaBr1`3Z9U'8RY'XAiVXFKp#&k2D5Be%VCdh4%,+2QS'b"Q2
+
+%0PNT4rE#%kTUFqYDM56bVjfe!p8MqmL)1VmjVkJY`U[*$&*L3AMSpB@LCQ*U&l%
+
+T+3890rL,V9klFN*4@f0UTf8Z&&afN!"4GC6G8p3fN9$4+4[-@DAeK%lej"@eAAL
+
+eU@&4[Tm28%mqqUkS(F+VDa#lB&'rlRAllRP&l460Qc,)MHR$jMh@$8Y4Xc'e`cd
+
+ZE2AUUiH+fK96feb$epq&'RAQeLG&lCDjmP+"Kr8k9#qp'eI8RPf[6R$dS+$UcqI
+
+ELYSV[*ETFL&j[@lr803qd9I2A#bi4Vei3*d[+@Urk*!!&abe0HTVm%44"i4A6JN
+
+c(2I!kjRl6a9e813DK"A6p(LjRZZGaGH+1L5SiBT[(6ekd2*ILMSXU(l)#m3QMDB
+
+V+QTG!r*NG#RQai#DNh4,l0&!Ie`dYi98Y1%1A$5hKP4,`d9cHdKP'LkD@q4hYC*
+
+%dfdLeCCNN@i9UIBNLh5l5(8N68qhM&4R`d9cfdKP'bkD@dHU+qe&XRfNZSqc10j
+
+#8Me*&ZNfNZT0hSYd+dP&ri-FGM6G6P,p5D,rPNT0`dQLk5+6'NLb5"HDe'$L)Pe
+
+X8N2bj-Z'$r$6-$NZjLGC)1lB-"jQSff@[ak%LJ[rI#%p2ddAGREN(@"V+,S6CI!
+
+I!!!0$3KRBbj38%-ZZ@0M8&"$,VN!N"#$BJ#3%4B!!!d'!*!%rj!%68e38Ne33d-
+
+"!+X[PfqV-$P*!!!'-3!!&UB!!!(&!!!&C80(jji!N!BMM#0%$L)UANhN3L9rV@9
+
+B`f#c2p$XpAVVCc-[`k20Y5bJ+CTHPScj`Z'!lmr*#EPaRH(ZcR!J!!rqMKG"q)#
+
+cj'G%46qffB3q8Aqp4R6FA83PM6`KUjaYD&IlZ@jDrY"pk[b&AZrdH*kFbb9PM*S
+
+`4Kh$c8Lf0bVe+Y`Q$amM6mc%*C1(jF&1bFSdGIlLpc*04b#X&D8[&6R%+-#6HhJ
+
+kX"#A+Bp6%6RGkB&kM%'jh$ZLmam[1Irq,r82rGM"5H4bh1ZB+b"Z%&-pD)5CL9(
+
+AP(4UUK6$!(lkH+UPFXFARF-MIHHMXf!5Nd%SZYRQj'pfL)G3N!$94X#(q25G8U`
+
+VXL'QU3Njk8[phV2@0Q92J#d6rA2N1["[!%c(M4X-8p,0IcYJf2lRBmD2c)*RQEF
+
+68m'9jqq*MjHTji&GqDp$kh501r9fqVPJe4iQDRS)L!)ELqiX08i#@40jpP1+F@p
+
+iC&))L)Qq4Bk-cK-i*h`cDlN1cMBUbZA3+beKhX*-&UD`X%ME%F91fHB3BaCC''Y
+
+KNba-C@(,"-40Yl"l,#c8`YCDf%#"XGD%F4m3'*i'k"iah[Ddam+k"Xd3eV@02'B
+
+bj'D90I9p!!!-q)[jAU2HhQ[NiCQC&f(Ne`JR!hlN1''4Sjc`)hcL5IK+f(@8(q&
+
+(1&Nj2XreTBI[M!0dGB4'MK01#CFF2c,JK"*1MNZ1(q&(11@5ii5EKimF*ja``Np
+
+#bA(#bBL6BpQ6jq5imT-m2mQ!dq2N'H&2RT2M%Nii'6$J,PF!#N#jGS3IS9Uba%G
+
+'A-)*8[#%!j-9'#r3@EpUPQ9+NL6$ldj*kVS6INIK@`*q'q$hGRJCPb,`pUJm(fQ
+
+3!#mGrdQqe$Nm22hkJ2cerNp"i3$m4Z62S5YA40V([V`MbHF@)QPT2IN@3@$ceHm
+
+I&dT3GqF9K,'&&8[6LKMTbQ6@-*%bJE#4RM,b'FA*'VC5`0BBdTa"@aNXM#)mU'"
+
+N@d@XSIKMMiMh#RbbLSjLT49GG9"F84)Q8QfN&![N1hK"A'V5F,,dJIF@+`iNJEb
+
+H-(5Nar84j!"*Q54MH+j&08dYQc,(ipT9I+aFqIQc-XP313&803UUPPD4*+UAIlj
+
+$U+jMAP1QUSfEYV2Qp4HKfZ#TYQTCT)hEaCbp+ZXH0"m5USfHDV1HbL4cCT@41rr
+
+5+d+eL4&+'hR90)iLRp$LYcm)e5McQN@UMR#&$kKqr%eHU-DBejbUCC-k+P4N5r%
+
+Iha+Uc5aj)kVfm*'ej*8Dali5ULfHDLah-l$Zfer1#G9@6l8TTf*r,RKTZ2#Q8'h
+
+MA2&i%MYq(0aCicHKfPlfDYLeJ3*FFEG3l@"HmfJbqFrdHU&IU+jRHE95BmQFkJF
+
+29)qp)93hX!aCGLfYP0!jSEU4HF9)-e8M9rADGfC4U(BbVVC66+8XR2Hj2RAmGk'
+
+kLDNk8`@p0[6F"hrG,e3h`kmm(BhDMQjBm@`ejDH1pG)YbUXYM'Y'5aD`-H(VPZ)
+
+,*i6A,Nqe)D1Y'5@UV@HM3VAE)a3$3MT+9jAGa)HI#%*E@9ie+jmf-PA9dY#66`Z
+
+[fkMA!l&$eZ3)bP996crcal6`ZRdT$9NG0S#+V([`rRZ&eae,A%dMGB2V4H%9YPL
+
+LfZ3B194,NC[ik!QKZSYlaE"deVc1$3[9(XVeFJIG0T,9**@'AVXJZ2Db$%'!,$a
+
+e+d2+8SES`Z&RD1(C`m,VlM*Aj)cP#M@ZlJI#Djp(U28`fl)VL9dKY+IXeFM!HRJ
+
+MVc0#YCpj6@!,M0VrHYh,CMQN!FBjl1ZVEPhjaCK)``"6,6JiU@@ekMjdmEEPI@M
+
+3DpXKj3pi+f`LFFpIUPrF058)N4X)f4ZQ*P5c1[&!pGhC4i@Ue2BCE"bRL&haLRk
+
+Thb#ZUK&ZK-Kc9k4Z-[QKhdaf&1KhN!#*#IdZ-XfJhdPQ)I6l#![SYjD'HXp$hdA
+
+f$1LhNlN-r4DbV8$I8iS[RSEqj#URqY@$9b3dJG1XG))%khUHJMX,Vh896Z%"I%B
+
+PFK1MejpP2[@,$LpbTe[Q%h#[hhai0BBHF+r-MrTeL9G6k!!IKHa1rmf2qMf,9c6
+
+d)%I[5Hq$1hVVq60(`H@-9fb&cfkb$BBDc1-Ck@@#jrVH%0cXH$@cIK[C#F&2Q9X
+
+[qpl(HTpEQ9F`KqVA3&iYS3Pl6#ARpIXMVpCP6[+ma`PkbJPkbJPkbJPkbJPkbJP
+
+kbJPkbJPkbJPk1MHKTlbJTlbJpqGlF2RNe4CD`1XDTfUZEYjDHE@[F0T$,KbK"Vc
+
+mA!9AAPiGS3Qjm[HQi+l-LraVj'p1i3&mcNKce1@eZ4pFX(PY@1(66rD18)Im"eF
+
+YAJ1K#AYcK92peXpVBfM#AZAIKi*r&r$U$"h)dkhp2[JI!kp0S3GjhdZZV))A!43
+
+jH4kk(TLQKF4pTXhHI!ITRb%hcX3KfeN#**1EI54a"'@Z8(9Dm%D@b"Y#qhm!N!-
+
+0!!PRBfaTBLda,VPM8&"$,VN!N"#ah3#3%!9X!!!I``#3"2q3"&"56dT,38K-!3#
+
+TY1))Uc!eD!!!@F-!N!B563#3"2$I!*!)22J1`2KbNQaPEr+hGEX``Jk!Vpa0&eT
+
+RDl*eSGZ&%EEAc@iGG+hAYBDRapHZd6ETQH'lV2AbpMVJ4lN,ck0G4lMb)fcKAQi
+
+*AeLhm1)VRfPGM,"Zi8pBG1%a3VYZi@m,@rM#2'iAfhjHacE,K"[bJGYB,ZcNP&#
+
+"$cqJ[fRG`SmXR'aMC-H6r-)AXTaNHE+Fj"HkN!"0"R[G!H4jITB&`!(!dKX"PZ#
+
+Z+PX+S(dCS&YGZI3,cN3L+P4H)V5R@D3p,54$JD"3'!j')mhRcl%mUJ)9e2PVUaF
+
+j[6lNX)ll!4,jajb6UrZK!hSTX[caD`$ZIHl,pdeVm&EaLeKG-YjQB6AKT)84pF,
+
+kB$+55%ID`b-4QF0T19ckfSl,d['15$X-4cTr0"2!dIR5%1j[S4JQa0,J4lT!pkc
+
+"EjcQ2ZmmNDF36,1DH)X!8($N3ihbR+mcX1GC!E!0fi)+ra)rCUL`#HU&V9)ke`6
+
+IhTB!b&RK%B!&4fA8Ecr8+8IBcr)4Z8L+$bmVaA0$-Lr)$3+SMf0Xkh!%1L(hiM$
+
+H56i!P'Q(V3ZXrmCRE,f[6f'0N!"Z$E6%fl(AqCL20Ka-#kRdjh`qA&CRACe[!5i
+
++PSiKjh)6PJM4H$#5%&U%HF#GqF0F$MM6fH)T68dFSQ!hQ*["e3hGME'TS#e`Fmq
+
+Sl`'0qRTZMfEcM@b8M`(hV,a,kqB4N8iZ[4Sh5b!9ddQpT9YP#5UK!NX`BDbr,"E
+
+!TME)X#08Bm,*$)fP2Ci@G1bTGUbETe@@q%4QL60h[2d5)BQGX-U5,*6)q)99'NX
+
+bP3a1pJZTH#BC&"!P%4'5XP`!Fm82LidDE@#h&eejC#m'cSQd"k1C&S(CD`*"Va"
+
+S%C+TmmkE6aJ*6S3kTd8)4GS&PNjQ"#DY1419T&!JQT+cV-0*5@'9$$5+K-58Y"%
+
+N8Ea'&)q3!*!!UeBZ'qd'!&14D",LQVJ'$qTI1DUU3$%0cAD!e9HMkl`KaGAASBj
+
+TJ#pMhSb5Rq0c+LJ3l3LJkD2dcrJM2Q%3Kh&mZL-JR(&m+L$L-)j29b,%B4br8)j
+
+X!Y$j4ZUh`)[eI!A!R(d!4AHG`LH[d[f@re6*b2mAI`)H5F0aI+2XYq2iC)+N`6M
+
+qC$b5"Z2ij,N%KHI*24K!$k@Plm*Hm'Rd8-bci0h@*rK6m%JDM[-[aZ1Nhq+IKNH
+
+UJA&mE-V&'KM(2a129!2Mq2,5(2qIrSHmNfTSR2rTH+3D'XHRfL81irM8FE,Ep4r
+
+eTUeM[5Ra8bilkJJ6f!)lF0e(0'p*Cke+2Nq9ccEjh#UIZq6c&[RmM(3ZV*!!cL0
+
+k&5l"Jp4$Ilc)-m$9BDMqeV0m$l6LhM(EAX9A,10lG,aR)2GNb6Sm29&b0@CfmMd
+
+&Mr!pHLh'hX&p"qiPVV#h)jIcaN(YAHVY!-im,lH&lp&Fc$pX!KD$+,qKqbMQh",
+
+@BjDAX[M-KFF0&bH!le%r'GC@E`LVXP9mKXdeG)3QcED[U18Vq4jY2c-fD8XFl$a
+
+Jb0pEdXPRCYXVR!e1c(f%qF`GKAUQcPT3T6E-YjCF2GYHhq#[aqa0'*p@XJl4r*8
+
+qM(Fa(e1(MAb2DUZDVTq-SD2mJ+kFAj*ldAQmX-KFQf"C5i,E1fA&P2jHj`!8*c4
+
+Cbq,eU+LUqmriLrQ-H$8"RJ(GXC,YKXYCKk(M!EcN!3MV-HG3b@DB@MEAd"P5,9[
+
+2CjDYplkH1ckr$1D5aNf'jH[,p0ehXaPCKe@(eI0#11SC',UQT)X9K3qD(G8hK#c
+
+C@GQUfADhU*AQPE#2X"A&i-9KaAUdDe$"bpQU)@mfJNfL,U61YQ4RBFiKFac+[hC
+
+Y@49Fi(Ye4UjKII9Fl[b`UM[(Ca+6ZhF[@mq`0Seer)R3*#Y$$IcK`pPc%EI6FKZ
+
+I`IV"'%bLZK'Mdl!5jqQ+3J!feU'k*f(FZf(EGY@@N!!CGAmMqd9@CrDD68d'jf(
+
+3TlQV6AYhAEJlGh4$epjV3bSqBiDXKA!BPjeTVUYp1pI,DPfESAK1"2eSD[B-elh
+
+H#"KCEIFl0K-Um0E-CFr[,$HC6Hhc`fDr-eb-HmN5*`iSE-8)!#TL+mfKpUV"jrc
+
+$X6fMXIlRYZ5'5$I94YXX-&C(`""L$Dkf)VmVe*%)GZr'mh(#3i3EqlYKNKblRf*
+
+'9fi`h"aV43`ejERI0DPfA"MDB``XX)HHa#bYS3h1c!hCcPlQ0+mDh0Yr`mEU8Hk
+
+YrAmUXCIMj8SFBkA%6iNVCjRI%C(IMj&E3@l3G[C&a#hGId-rBQbXrT)c0e6q'2p
+
+eC)89`[fJmPd62,qrh"5fBCA-$%rb1d1R5hbj`ddQ1G,60%Q1l'T#EqB1)110@)h
+
+%i!95M+ekEiM0HfqSHM1k9UQY&%V$jTQPB&VZFVm*4FmG"[Acbff$#qbZ,a3IKUr
+
+B"VZ2A1J-[B%elK$paa&k8Z63JaakNVNdL$c1fP%+A`QGIJ'bm6iH0ZklkX(0S"E
+
+8jP*3Mb,[3pbE@&fLD'2RS@ZY1`pG"kj1X1j#2R9*X*QX*TAMbYcVef*YX2)T6FA
+
+Q@D$Hf'AE5@VBGSP+2*elSqN#9T4Gc"`I)"SMr!P3K8hPL)Se--@E+!*#j8qBAdA
+
+F)f`H'*JMT!TSH@V*`'V2IZI1K@DpeEljYRXA2YJ9eU,IcfjLaVQJjXS%LTUELM'
+
+UNU1Q*M@HTVX(FV[-AA`QqadqFr3i9[JU81PlSB$r%d$A3iqhZfXV+KG!GjBeeU(
+
+[-cfI+9deX0(XqqDqeeCrEqGcqm6iUPf$i$#AQd`B@p0rSjJ6NR2d'hX'fX5-"MQ
+
+MU,pRS%(-F-NCDZeUk[$*BA*h$2XG9RaZHj-D6bq3!1YJC6AD61@QEFZ@lXi09,[
+
+#3r`40LMRE"V0'C!!FecYKJh1Q(D[`hN%90BLbX@@Y!c8C8j3QmY!ApD)[GhVGTJ
+
+**CcApF6MTA!ZjkemqUrh9AKG,PI[cVeVI+q#h6`$QIm$kKcXmZ"@c&ph+[pbaRf
+
++-2[6I1-)JqV1YQR9UpZ-&Cd9Uc'6i5P6JCdV6"8c-TKV%$1eQ*@af2(L22GJCe"
+
+VaTDFcfaEffcXh1Pef-$Pm$Vic)0VQmqbL$(+mRVQJpGcr8kVcZZakIJ-9F5"VJ2
+
+A)XVacTfpDfd&ZhSY"9l2XleH6rpD3Epa6E1D10FlQJjH!G34SPGS&qM3*fC3Pe2
+
+L`2L%lVY,CV!*T39qcpXH[fHHVQRU'%UAhk2&Qk`VKaD[,i2ZHk`cX2[6K&iQRrQ
+
+lbPXmS@QX)1Y!&RH`da"Y"8BfPYDc4GPC#3lV4AhlG+E(2&HTGaMM!VD)&65CaPL
+
+Dr4lQB&J09`k9kE(,mhf[0f[T[[2#[mfpH2-6*6k4bk,U5Z`kcd%Ia$UcfEZ2Z!G
+
+1&'%PEF2B1aKl$'0hBH`R',X1BjX`pP1-h6AD-aHa8TJD0Z"T@[KdIJ$5L*0!R+1
+
+)NmCi#mDEj(J5i`fS4KaV[49[Y[ASjjGJCfSIkdaR)f+)e-#cLpMMH4iTJQFE+B$
+
+RFiN4RXfXNFpBZGXAc[3QM,G2Yh*CMh@3!(q8lFE6#ID-P'YZ"AefKT9M99N2Re%
+
+Z5UJ[cKd0UjR$Y@%N5eQr[bVdDANH1X3[2[#XjcJ0%Se1!jKa'U#f[M%BE`p&`TC
+
+@-mfEF*1J""c`J'Sc4b0!`0Q1cH9X!e(3aCl!)H`k4qIhpfYS1)*',+EMMLJR'JM
+
+*XAVRp4,L3*6EFHJLENI+bThcfZ@BBX$BV8U1Sr-@+@iljX&F'M+D6*J-'5#(%1k
+
+[1&EhlT'("@L3!%(&RA-a6V0,2#9X9%3D8*&8fT'k`V(k5V),NCZX$kh*MY@GDYV
+
+4Y-8%c[bAlh!l-U6&69c*e@N4Mj-C)C2d+XbiMLZjUSJ3--Aq8HQ-$[R0RcMaPa8
+
+e&lLqlpUj[TGS[iMVqri'VZr9AUl[KhZi[J-YA0r"GUl[d&eFhq'YA0rr0h*pEml
+
+RqYlHa2Ap"212)[Ba!pGh2-6e$Gc+p3dqbr80[FMe`hbZAjA&I4IA2aN0'##DQ-I
+
+F0B%8$M1bX*!!6V&dUi!$KD&N2-DNDAZFBic&F2BrKF2r6-!j%"D+4)8c'q,aD,f
+
+3!-3j51B9SJP@RdlLA(j+(8X++A@L25E3BD9ki@,HV9l@i1F0$6KDbP$RC(bL'2*
+
+%ikP8)(QCZL15MXe30%"dDAVbI)DMURqBCV&i5b4dfDrbrk!LN!!@@#SGL#9B+*j
+
+N3JH#Y3HLV#@5r"fhhq@IS5Jp9LM&BLQF6+PSMTk2cbS%9c)KQ@5a90K#Sf4N5PN
+
+S5M[3da4hiQK)k+XiA(ND$YpSYSe-m)LIZ,6N5rL%!p$M"e)Z2G@JJJ8FXU,((EM
+
+pQ)@$C4*&(*ZN6`SqKSGP)q02Q+F@[iqA@RaFJFBHbCM4qfMF%h!%89`D('LN6e`
+
+k'KDkIh4i5)XM8r4*4)JcM9hKZ+)%Kcj2Rl4%aj+pAcSALTmN,qQmF&6[3Z`$k*0
+
+%H%M18RJEF-b22R&0qM&+6,@P[&-a!BIik*1U!BGKe64B611lY)`iBNHI9"S+Ab9
+
+l)JjKd5HT3V25,H+!P%`9Z`rkT%9kNCS1THY!pHQ6Q&%@$8)T99L%Sfhd5H*hI$J
+
+64C28Y,C`Djl#m$6b!XGfTmrR*X8$d@L`Y6QkdK+%4i(E8[b59GP&,"cqQPC3ih4
+
+MlA''N6k&X1iVfl4IfC%6%hNG3kaD8[4Nmd+LGcpXR+[Xb-XNFZZYEkLS`Q4G+Yd
+
+5L413!'S-T`$1NR'U9P55`+R)+U%aM8!K9-"b-+[Xk$GR5FTkh)hN*rJB5@-L'EP
+
+%j(6IK+GdbSlH-e9"XT!!TkM$335*3-%BFqd`miD+#P4)M`VKJ,5STAS-5DFJ,A9
+
+lRF6mdQ"V)#Q+K-c,[YUNl&M9XNEZ@PkXmY(k8'eCj+P3G[5T%69*)e+cY5@CqV"
+
+#$%SP0969B)9`fR3N*L#-jAfF#50kqURL8%pU-)M3+FmipZBILqkTH!E9YJip)aj
+
+%`mKhi"GMeDhkeqSZq1IU*VIi[,SeRcM3"dM$M['C$j!!BhcZ!m11mCN2&2k,$aK
+
+qi32[Hr5%Rh[d,hX-I&T(k6&F2UIBBc4(!m'9d93k(d+2NBr*-djj`D*SpBJAZ,f
+
+9j!86F'3iZ$+9LDAqShqJf[jh,cLPbr2V[SPKZ8BUA*j'UT'@jR"M,2UIAFerUC*
+
+hbU&Hqqk24KaUB492qKV`$C4!&+Z"V#$rQ"GJ24rmKPrCa6X4KAZ0c$d@5+lmTal
+
+hVejS(qNI[*91V#iSP&p#b,2@2paR1A6E52mJe6FBBMJ1dGJL*2+9p3qIhj!![Bp
+
+M('C8fB"h)XK)5,I&%TpfThIZ`BHa&(9Vm2+9kL#QA,kQIZdYiIaLYrARRVV2f2q
+
+YNG[k'UGr%8DeBN-EK0EmEAlarTd(p5,rIHIa&j&hIpETLXk#R@jbC@-b,9jkj$[
+
+SG20dc3jaep#MG,*Rm*9,kClGd#jFfLM2Qq@TmibVrRcNcU2@95h1CX5Efl"&%5r
+
+8mURGV@U5ZdHGS,k4EYRemG4[EPCrFjZ4PqYQYFV$Li`LB4cI%5Ak4CIabTc4cV5
+
+Z`5pfTSPdXM(B'Xb,d*RQlCVl-6rbfNK(iUpddhemB9))4J14@"k%hM42efh'efl
+
+%*i192U1qBE',qSa81Y2F(%qfjbIV-mbRlM2Dk!QiiGN-X@CeBXhQjHJG2R%#l)P
+
+%*m$r!"'46R)DGS+2k[XNTp(qiGGq@r81$FI)IYZ`[)lZM!cTba)YbQKh2VHq(T'
+
+iYATPahXMf583L9i#-b!5'SA3JP$LMk5FV"eL5P&e,)!2AM(fqq[&rAqqJEX3ZJ0
+
+4GUAcq1#I[$MlrpXrj3jb$ZiY+2BkkdRM@qKR3r"mcb,mia%m2lM89dZ[Vqh!-,f
+
+QqNbpVjjZ29qJCq04M`2d!b+N'UT5MqGLqX832%q[Aej$mA2Gr%)2D,J,T!VQVUK
+
+`%6jhAB9V+HAI4,rjJHFl+Pb,m4eQEZZ5@KrPp5aF@N9GqC2+ql1S&YkPdTmG6Gr
+
+!qEV`09U+&4c&223NLQNk-DpALZNdR1mDqVXNM'QAB`crlBKL%mp(M*G"*FCZ`&J
+
+DZ&cZG*Ki-f,J@mmLMhX`*R29E-FB[Qe,XDNr4DlPFZc[1GrDKlkqQYkKeBBaYUl
+
+YEqK(@E3aM+N[HKM14ThU%2X*Hb(-`McNHXhpB"3j2BDaPJB6I!Ne%&qEaD`r`V`
+
+YU-G"k"3ar)MaKKaEKl'$NQC6hd1-Lq4B$Q0G-XB+e-BRajCJ,+'*V3bd4NrqAp,
+
+B[bJT[kddmXG*R(e#AIa5)9RRT[cr!`!!$3!*Cf0XD@)Y-LkjBe"33bkj!*!3qL)
+
+!N"!0"J!!,h3!N!6rN!438Np+5d&)6!%!UE6L#+X`0A!!!#*k!*!'$d%!N!43[J#
+
+3#1j"$F$iCXbcEQ9ffFS2dS@*jbZl63NYVcACZY$0##1XPDZ$V[@ke[$dmVQ6K5h
+
+FYGEmE+(Rmc@246PGf0D9hF)@VNAi`VhS`KGM(GQA+lmmdfiI)f`c`Tq`63P23V[
+
+Y`VEH`KHqX)9f(@(E*!Zrf-)@IZi)AhKXi3[E,M3j*432"&!HrHaD@&$M#f(,qq3
+
+@XL1hN!$"3Rk6AcKCb%+1%di@J&@""TeG+a&(42abSQ*m9@@VL(4[%29TUPEGj%S
+
+NfN09'd1a&"q0T8,*F(-`0#85E)pZZ-eZrEB+Z[80G6A,A6ir2'5jYd$i*mlPdrI
+
+-@8-1XA6I6r6dUG[h&cAjUSAPI(dbhQEPDb0*+mqX6fN-*U1*9$3@'8GN$c0%(%0
+
+GelfTH&Fd4Q0)jLrR%MNc2aM&pcf8d``Y,Ak!B(cHb*GQH1E2Phb'JLQq0Yi5)P*
+
+IZ&DMccNrDX`mDiN1BLbSE&MC!)B+3p!!(FM4Z3"pmf##5,64Fd39&fA9Eck6N4(
+
+q-Kr+TK`qGQ`-&dGPAb51%'Q'J"dB3bK$iZYMHPIm%$'QJ`j8f2l6cq5j@TmTYD&
+
+8Dh0,2)CCjkGqG*&J+Y5CqU@IDmIQUUrh9q!`X*4GG$59b(1#DBYLrXT3Hc`B6B4
+
+D3NZ)Zr'(SNLFq4ETPX+0#01J@-c9Mci&E"ETe"lZK'B2D682F5pVpcl#6cM0`cF
+
+VIh2RdI%LA6N'$6l@jXi1I@kfp+LX3395@i-*Bq1p(FdBDS-m*N)0#&FB@QXXRJV
+
+TqHr&d$F[UDca!YiDjchaf-C3%T1`bTUFNM26%1V@@T1GbH#dKP"R2*d-KU#5L)D
+
+5FVQ)&NXr0"XEY)Prh,6j`NN!Fk+aB(Zk*F3lDTZ$[P"c5bMC1Arq8UD4i#5T15f
+
+KF$3@iP2*G)M2RB8&#LRFh0iTXfaMT'5S@aDD8))aK6DZ*"9[2BV(P+51c4hG,L+
+
+c53S*k44Xa8Acmd49U9R$Xk-p6,4P'e,Rh4bZH3"e6"(G$Pjab5Ikh&MNk*3JKBH
+
+am`[rd,p4KJ)IdrpGAkQ!SYrdArSB+K6p(4q-kaYR%DeiK@MHTTrT+airpFpf(!c
+
+C6D6hMrH[fSGq[SpSi@NLdj2ApC8!q05rrM0pH5A%p,FGr*AqP!RpYPrTjl,kIr)
+
+Mrc0p)kiXJcl9Cb(1%'6hP`BRQ0MP'EU4U`lF@CCrSLp0(%#3!"HAp98B52*lSGq
+
+&ZrfkrM3CD5@kEp'%2R+m!*ldPFM#f(9p0R-`C#rdT5&)cLr`#Kk#rMULrlIXZ[j
+
+d'6P$Y0N+!(Y!54rDdc&h'$"brDYqB3l4$[hhr$0$4PE$2eXNb2ieb2fErJLM)1T
+
+RZCa*(rQIH68r2Xk[*I+#iKreEj!!r52r-kc1XRmYjSpI3ai@B(RaKIqI,BSqG$#
+
+E'MkH69X[ckB'iJEe$Qi`RhhAFB-&cq&lKKZFKRc"-D9m50)#'Z6Fp%2+jFLffS0
+
+N5Tj%4@C5"GI&cC(ZFcD,h$e838lFZmM*m-eX'F$dP%A,,mqff[SF8$&N-KPiM91
+
+9NF2XSa0J@f1fH(J8"hGPCVYkTSRLJ,V55r6R486P'%J,"U5PdFrVi(p*UM20Z#1
+
+AjGIGE[0r"EdLeqdcjp[mNSplX,Y)hCYJ5aj0I@@G*jb-Gm65lHf-'iiR1d+aG!I
+
+M4Q-YACfKpTEfZ,40CpQLY-XkZ5B+lNFp6BS(cVppFXHLm)JE3biI%jRZ4TD29iR
+
+SY!R1P$QEBbjeBD*lqi'1GccMbIje'bEC1H@a56dI1a@*I@9pEqBF-qYcdaaAM`b
+
+5FjP9B(QLVT*e4Aa$'kXN*T*FX[j[jrbLXcJ8Me@X&Eh%AL-JTT!!Gd4B3#S&rjI
+
+6(0UBDSje*M'BT4+G-9BhC9*@-5jcH$[1@!XpJKl'$ZGDCHXmRb03ICB4reapCC!
+
+!(Mqj("6&rGSNfp+B@FQGKfZV'cfXb6ZLR8&V%2h"l5[mJ8hjJPR%eT0&kPUA"r-
+
+MPcHq*D-)FI[,GTp4[[$$5jiqJ&BGP+G#UkjaI6!H#dFM9NbNa28pDebXI1(,,(N
+
+ED'bUV!CChjPULFDCN!"U8NG00mXke@ZV@1Ge4VY$ke-3#PpeT"PAmJT`"+9)V,N
+
+pTl6IHLkVI,'RZ6PAIkpR2HXM[+GCRdK'0dVZpqGr6kpmXC'CT5KCd3'NL33K%LA
+
+eT(2pQ21Q5[3dR+GDX116UUkC9$)S5UXm2KGcINq`Y6NTP421bhiMS(ba5j&Vj+N
+
+6f#aTQ1JNeElPhNVPLj`GVbDV%DYQDdZbmeS[j5Xpee4GLelLG+PS4`JbeUXka[&
+
+k0V$H4$f6H2FMHFHjNP0bI"Sd(Fh4'2DERk5`R-%10TmaEFjrI`$I68b$mrG)kq6
+
+aHBBP*&LlQC0%8Xl9HQQfr9b!L@&XcMHPT*eJ*QI3,1Ibj`$iNqZ&q@YbPJ1Ha&!
+
+Tc3P+,rc(E-IjIaGE%9QEH@4l"'92bccba&FiN!#)&l6[jHikPAbI*GrYmVe9[[I
+
+)phhbr86Z2U8bGeIk!)'b%TGV)mAiNDCMGeGHc9GI%IUT&GqZ"BjUSA+ed+mA[-2
+
+LXC)(FAZaC"ZB'D&IrCc3Ep!"HarI&r!YF8GmAD,SLj2'YmVA4CaPLEK2k0IH*6a
+
+V*Vk$fS9GI4I"H5aL!-[(@%*ka9$HA3N5qMA()VUDA4&9YPT)mi[cZX*6&cM@eJP
+
+93VpZN!!h"R3P6RiqmI$[+mN)k3@15PH6#pcRH,qPD`T@&9NVUY3'[UeNf`)(%Um
+
+4l0h!LdSHK&T$P4pi$qrR04'Md+mkS'(0E3aI&)EejF*+mAAAd"56T5l"Ckd*lZ6
+
+dYG-("ec$9*M3CUehlN4&9Aer+0`PT+AR#H3GeRp3FMK[%pq9er8Y223JLKM!HEY
+
+N,mdU@jbA#DY@la65UhIkhK'(PTE4BPEM30kDR@@'[UIiiUc6TNIh["CTp`k2hPr
+
+5`jXLjbc1QSI$eZbmE28#KdHUPIB[)RkQV95-AKqV@,pZ+bUiLHmHp@@M''(eB8f
+
+f*6X2R,FYF5Vrc4ePeE6)rfDaf,5cCM&h@d69*`VTa,5qikYhmZK0Ble`+6c9aU-
+
+'$C(cf9ZKQl&q68LMIi$490Bh%PU%6PbL0f'aB1Hl9(X5aT1l$Kj@l3YE82GhXer
+
+JkbdqLcQ3!1Fk6iB8YmemmZL+iq,&A6dRGi493YT#@5[6iERXA%YphBr&!El1[CF
+
++&dD44l1b0lLIpNA*b0Ie[@mhS`,[c9hpkT&bXm8F@aUa0,JLKIL@V(3KLJm!)8*
+
+&l+8LDUmD1G8`KVdmJ3fHfLH1XVUTHZhcb&J6TE``hq4Z-c@i`ef*B0pah)HB(K3
+
+H'HbMU6,f$BBChH*)C%0(+c3dM1IjL9Re`SV`bmEQ#NIi'&Lk[$Dk84behl,DCHN
+
+H16RiF'r0K2I@`Gr,ZCIaFJ8(9XVm+EKbPreGN!$mr6@mUF84qbhVQ,I8i-1$d1L
+
+YqD*,(#erAVJEVY!Kh&Y92c(6UfI+c4%lZQ4ZC'U$+c`cjjFl(c$,5(pJUS`F$5#
+
+EZE0`h)YZC!jHBaAMZcmFjCGm1&U$M9+Ne&j+T4(,h&)bVh&lrSC-Tmk6jY8epT%
+
++KrZQ`[0dKhfNlm)+9rKGp,K6bKpRq*MNS4mHqT0LLL3I0lp35RH%Cbk#'pph)mE
+
+6[h0S,fP#'NXTD5D86d2hbhap`Y5EHAZ(lFME$j!!1d1fSr"6Rb5lf@C@BB2jcJl
+
+d"Pmq29"SQ8HDhKll%9B0qe'T%Lq*l`B@mDEXREcc)d9M9,K%USLj(+VSJHQqK)Q
+
+BUR$*mLCd,r",+)phKPA01S'YCFRQb(lRkmXX"TYMlpHHARDS*k*$hLm)m'`$`C@
+
+&''S*&!*9bDJjS-&YYQGB2'VT%G,Cl`MTLd2Sm'j5'3C),I`f)I@3!2%1,)HU+UJ
+
+[bkq[4qlc"L&GfMhFDr(rrZQrf[,p)kG15hMhd4&b@XV0CQ"E"aq41''CBqMY(fk
+
+6'%db`c6B2p`N-G`b3k2E`LC4PM$L%f0jKiiA$`FdZ,h'8JHGYGjZ,MFIA,hUZ$K
+
+Fiik-#KIi%CQcHi)c,(2FXEaGVJlG5DIV!UPX*XE&5&T'QM)AD5aPC#KEMpRZ(3F
+
+@d#@FcrhLGd[T9XjApG)IRkldZGhZJ5-RYrVI*)HP'-lr3A8KTMck#[J2AZG[`VV
+
+Jha3@r)a[((G3NfNVUYR5CUc-9'i"NmFYABR*P@C*M$5iH4*6"eEDLVfl+"l+"(8
+
+@M14#qZ$f$FE-%Cr66QkRcbQN$fhIF,09`KM,jee+2Zp$4fakRpHZ&p+X)mlfR0d
+
+"PD(-NB(YG[A4!D[DjheP`1FGh"ibp'lGS''H'jf"FrF4Q`L4&ES+2A+LQ%dj*8l
+
+JqAe2P46cqDAU"Zq2[3hH*IV!V%Q9RJD[$Y[IcD0hlLbM[MffBNarf[!E,'IqV1S
+
+aElL)9fHGF2%%2`0UDi(dPMEbbl2c%Kck4I2iE0i!RV[80kDaL&r1U`2Q5CH@"Lr
+
+[j0%0QdI,$*Mbr0mIb&Vl[VlL6mAA(hfaa#pj@9j6KDPc$R)3I@Chp&h`$&mbSC-
+
+1!RXIf22!RJ6fYm!H!,BEf0m"Hh*LCMEaT63VNSGE8@5Q-%`Tk#5JFa%k+H!Y`!-
+
+bRJ6HK'V%dHZYf,SBN!$R'c'C1LBRd`93$,0Ui1jQlR&I`LU#Zje9!2GEQ52F,Ia
+
+k)@hM(PmfejF`2MlEaQ@pYK(Kfraah#la*h*F5bXCXX8fMUr1HS@dXLKKFl&i-D,
+
+KRHjGikbVar'Y9la$l2RB6pmR,LdS'+0CVLaC,H`"dT@r%Z!F2cScr3P3LVMhU0$
+
+RDQ6lXmIBIJ6h2FZaT-(pd#Tr(GX$[`!BEfIS4+1rNEepHBe0*1LCXfaR!QFkYKh
+
+"[C!!E89`RpfiTTEKYhU%C9l5FSYb1eVZ[NShdqFHU(5[B[`[Xmd%lNp8ZZr%``V
+
+Z`-Sk2q2e,eY9c6DeamCH2MPq""hf),AJ0Z`'mAk4BHU,`2"fN@(D$$6B3eKJHLe
+
+ijh+BEJhfCmrNX"X@BR0iMP35pJI3b"!RLM2TKUm#`jj4mR%B@%X1Qrhh`&k8X3q
+
+"I82'4(M5h,f&[F[64H#l[1e2f"XKA3FdhPMh,0f#,XX(PR*-SARJ23cXC6*+rTj
+
+($GBeQHQ,U+Ad,JkXA`G[(hJpP*%d'S#PC1a"B'rNDPDX"RC'a[6!hT)eeX&I3XE
+
+f-%rDMYpUEQfrmLafmJQYmYTfr+%XjmL[Mpm65YCl'2rr!!d!#'GMG'9cG#kjZ@0
+
+38%-ZZ3#3%%0D!*!3(m-!!%+&!*!%rj!%8&*25NY"5%`"!+QdiJLV-$9B!!"5l3#
+
+3"K+K!*!%$I3!N!Me"!i!pCQCc1abX2*Ef-,&mj8EA@KjV4fRQfkf--,fZP@[Eld
+
+Z$dq2VmN'A5Bp-hbAY9lHAJFXfQdl+AG,Z2)ME*&GEJRrA-libQIDl@-,fic`*fc
+
+6K5HKhAEKE`YIq-)mEQiRK(pXXmb@iapGq-+kKCfFELT3q1c,IZ&ZXPf1@pl#b%)
+
+ffjdZC,)F@FK#&m,)B+r,!D4[CPq-FBbaqZ@-eH&@A,@%-I9,M(@V+THFE3i'I@,
+
+PFV%p`R[E)f,)lA5*'SmV)SBMaKm`"H(DkkSAQQdeb1%*lP8%I"Kcj(3rX&H6m0M
+
+IZTkaqjrj`UCT$PZ9X*!!V`m&fSamV5GNj#ReR!CAb"Z-H0XpDBqF`ePa(%eGaiT
+
+)S-2EcP+HcTr1B+bXmm9Kh'q$6Mf`X[$"KF4R$RhYV2*CXk3m49H%V`fdL)`T"cl
+
+J+-2j13Fpcq@-E8&E8'&IE%H%!Ne3,pZF#1HDf2Hf""Q,&l1('*Yr8%EphJ1GXSF
+
+r%JrNr)3rGBV*(aq@mf,a)FC8Kq$ER2+`6KCr)B9h0"r'+0,%0Xm[rQdqSqFB2cQ
+
+eBU69f4*S4krcbhc8LClZG$iIR'*cIAh0I"abUXM3iXkAEq$(ilQ,49r!j3f+,H)
+
+maNhp56c112ejNK@"P6JkPXIB&fjK8aKcR!drZX6iG+jqq&li[TdQiqM4U(!CR@&
+
+rGU+(,&FBA8QAdZJ+kKT@q*eSAPdm1Mm9!Sj'C"RE!a%aQhqm(IAaK-)B'-FE!ha
+
+jS(fj'%,(Uc#'FK,*f-@9@FC3113DEaI$J@M)*3)Pk"9$i'!+Qm`pccf[0,(*#J2
+
+h%ZcNS8*JE#k(6ij38,[0q$[cVaRB"FIjhRDA,pSLmUCDTmXQ1P[%8(M@V%X))mK
+
+*81HhL'j[ZmK(3P'46jb,ab@$h%jI@)iU6J@&a*8bd!J5%NZ'TC%NDKY",5%K9lA
+
+%%1kQ%f8Z9IE(4kQ5X*9Mq!UPK%dirih2+53-k[E(m!QELQ!-Rl#ccq$6B)6Z-I`
+
+FQ(52iC0Hd6f'2a&QlKPm`YDG`5GX%V)aI-*'%r+rq)3prJ`qB9260)C2f"21i"-
+
+feI!B2QRI@@I`#A[5'Ic*-1NH`dIV+GeMrFY8Q(52j8mG(mdXar#TGUKe(X1R`pq
+
+T1G'EYSlfTT4IFZ446jL-RfpLA2G!eYX*@kf3!1dTXPdLfkfbh5AE'fAlbB5G8j'
+
+`4rJkCZFXKT(SUhpj-0jKc0+KVIl1dd)2DmAG-GY8*93X&AUb"HYJr,'#0E!H,EJ
+
+1NCe#Mr)KS8HMKZmGh)rJ,V"iE"haZ#h!9,BPYJl''HE&0`Sp@9F+$qSClfFqB9h
+
+h3F6FlY%JbNC43[653pSVJdcS86hQ89H[mbKL98+8Rk[YF1I00PeH*e3+2HTqAYH
+
+N,LMMCc%HqGX+1SASE&1&f@&'l%0mMD%M4m1VBND`e)EiiS,VCTXD(2B'40m'rl5
+
+#08#c9pE!hmAAm#U26ZK4E&E48%VR2LJ-CTF+Lq-[Q!rPj"[UJRc-'14f6EKm3Rq
+
+[HC!!63aQaBb,eS*44IHY`T9#9"TN-1YJpRX&fl4AmahDMZpMp-1B4i1Br38Ef*5
+
+LZGT1Yf,T@L'kG+hYpILK5iVBA1+i5A[CfL*0plhmp&KCF6DUCir(CadF[VkJLmr
+
+hl$189GrN0XCQaUTQQmSPVV*HpY33GT)apN++X4le+M"i0Epbf"EcSZR0GUYL,E'
+
+CL0P[#,$5,pp39-AQe,`b2HjB@cfAZmLMk)i,dH$ilTe,er+S69fpF0LG9mb$!l[
+
+R31a#i(BDla#LU"ri@"l9MH5GKNUFPjh[CUb%le$F&p6Y@VGPQf+Mf`$HhiaG`0F
+
+EE!CpNpCmJ'NLh(AkA6XZh4NrZ+jVe`eZK4!eX*L4F(JZ0X03ArHcH#pICpR!*Pl
+
+XK4j0L8ffh'rc-KeIere1L4i-[$eMkE2E5r8'IIXP(S2Gl*Q)Zf#a'@X,Qq&K$)b
+
+8&-E"[@,S'A[+pp5)VrqCMI&KiNfa[Q3Qde9lQGE01baYqAD,Zb2SkYi*qa$K!H(
+
+QrQk@*rZq5ckG*6lNDIDh!N0&FHA[kK@2A1Tq5ZHFEh)rKLLeYSe0M3qAR,I8E&J
+
+jY+[rT[A9)lQhp[p4)R[CAjVd`eG)q5Ap59[1Ed$+lfq3!*Xb2P4bhK@8@k6rTRj
+
+JV+rq[$NqA2U`m"9NK3VKAUem9mqHIDj8lbP"PFc`j0R0lNQ*I,N$6AVCdp18*hY
+
+f0%'EZEh)H$fUN6,B3ica+pmIjZHp2ebp!DT9@&,)#Mf''B9-IjQPr#f@rm`"TRV
+
+fXT+Kq5E,f4-2X#q@$(82A'Tf[iND,j2dTmcpQ*4$$h,S#F8M6-VMR%F+f4IGNqB
+
+J'pZ22,VGhpLkJDP%PD'3!+P'N!"h!rF@[MkB[ljcr`h&frIIb#bGV(J(mUN2X4*
+
+pX9j4GNhmp4Y3'hcTK+D*KTP-YEkVC$Za8E*$BZ+*q*Y0FrMmf#+ql$LLcLXFCJU
+
+2[K5SU)%*YQ!q)e6KX1%9i!l`mjL@,h-VR'U"@M4@E)Vpm1i&"NfaDF-GpbrBfZ9
+
+43qpR0r'kZ8c&&BRN0640K&FKHr90+PMRPJr'GaLkK'MXKd,di#&8q%UQd23bTI"
+
+9"Y@$aT[+kbSUjl2Z'0pB$phR08+dF1AJHN20YhDrGZhcfjrC,IPAlKKLCBC5[4k
+
+q9Idh5c&Z18Dc[QH`6BT`b"(jr6f$$LR#)NHSe0H#a(a5Q2KG+Ee$aFHh0DPJl5(
+
+93@8ePZK,p9Z@,YNC(kbfH)D&!Aj)MVPY*'C3MV'dDpHCrHTGCHB"TLM1TeLdU%9
+
+-9@4Q+N-4da3eSVGlhF4QX!,1CRRd4iAX3Xj@qF4Il+k`@5b@hZfl9Y@m`Nb'kFM
+
+m(e%[4TI(rJ6aDdl'AmecRb,-rM4HPmkJZV0Y@[@eEEU+cSTV%FR$LPDJFf96T)J
+
+SBV95T"T4851Qcr(ieNkAfS!@ABKZ@GfXkpaZ+bYKPM*EQ4$GZVVj(+2NSbLEp4*
+
+QXhjcHh'fc9U5,85T)[CflEd"+)FkYrHZ,P(Zk$8UEGDRHfh@rY@LC[fUCKAPh&$
+
+@Y1rVM$T#D)9kIMCdBMTe139Pm1GfheX`RFmY90UY2l2DVI1bQkD-SR6CVHVV',Y
+
+QH0(D)YCpAr&dG(pClTG)CrkkmRDVHaU[M*8KLl[iXi"f16cV#a[iKE'C33leSVV
+
+cA&k$1%ZK,B8aKer)+j[dSeNDl&DqM%FeA$0FT%'A9r0mEmcBIIHPIa9riGZ2&Y4
+
+)Z5bXVN6AH6jd%(9@BZSH+"mmR)p+fJ,I1r!p$0mpm2dGI$I#GaYmI`rI25-pFcj
+
+Ib+CiY,#QH5B*Jb`#R#"`$J)R!Rm,r%fb2`5r!f`%81ZYQ*CVS1I,dCQD4M[6f8"
+
+d%aZ`,C3pl(R%#1`5BJ$fKC34E!2I+%5,Z6XAc,!&GAHH@mc&V-9$`JriRE!1mdm
+
+QBJfY6"1EAXca96'V%%d15UJ[MKrdU2JbblTde+I(r2fRV)GU*0F[GKFZ'6FZ&@C
+
+!@&e$S`1V*BfZ3,[Ekc'f'QM#1TGaI6mfFAd[dRd&lTYa2mhe[DcQqPkGarAYVFD
+
+pRq[EGj!!kh[Gb2@pdFVerHebVZqYjlLqJ6bZladIehI`(Ul[(a4Fhf(J[@rMqRk
+
+qJHZ,jh2ph!,FAqIkPGrNqY@YA,rQDG`$A2piD5R$)dE#I+49a0+%1a6`miQp3Qa
+
+bq2hBFJaMcC%A-H[Lh9kI1084#2JDa"!f3ALEk![b$C%30K$$+Rp)$+Z#lAk4M'@
+
+U"BZ%FY95Keh3%Y-m5!m&aNNZUbm3$MY$+e3GhSKrHRQY-ib9%UaRb2XM&r&Bb[Q
+
+$#1m2Y(MG+riPr[FUR"'4$dHFrL$[$S4iX30Jl8iIhq)0r5khhm926M)p@LJ6T9)
+
+i'P,4l,[)jI1kP[&L+-6l`aiMMHaaP!k@(kR(!$5jIF64)2HV9c"fkm2Bb8M[NA,
+
+5*ahe$KKB9T9'TSPBKI4**`H4UR2Kk*+M&9J[`FHC*Q&NUD#pVUA83F[45Jadk'0
+
+F3Yf1$dpTM65,Hfl&AGM3!#1U'a&eQabGKF82I&eA%c-D$%HjjT%"U4TMFAb*[&A
+
+h)@)HETXFRBf&$h`V0NVHj1U3!,`K#cY(qL511H*j`3MI14L%iN0H')LU%pY@kEb
+
+e@+I!ap@!&jDr$K6[395bNR+a,%&ISM6!LST@Uj*V5MUX3Y#A)"$4+kM@NKY`il$
+
+S30pF$R`T#q@S*(BHeKMSieHp#Flf)`,0AQTaDcb@&2)PHQQ)5fb5Xdb1cXF+!Vj
+
+N8DB2,Ic5f4Kjid'T!M!XRlE0,$48%8&NcjVeLhiPLG[pfVbedR#BF'qX0CFl+(-
+
+SP#2N$)DCki1*FLTMEYAMF%qMfLlECUkT+5IZR$kIUlACYmcS)YhC12(&iZ3YB9'
+
+@5Q5*+ZHdkID)X$BCAmp+hXKTKT6AHm#U3r4C*hSQB(BrU*ZE[*&EJ[hH"NF&f1H
+
+b`j%@Ei"`&+-i5TRYhSDUbbZ*lE"hTGJB!9#%@0JA5pj3Yh-5l&V,'fQFRq0a03C
+
+$hZ956TYb(mp1hP#k+8NN)bQBbZ-#L*FT4c0ATc*h9&5!)3dB`XSCTF08SdMC5D3
+
+Pj6BcCAk9Up8CNNK#jN9IDNVH8!QCSr)k39+0G(N`aFD&eSVN$99-XdNF%CZY,D(
+
+`"a@L69D5SkS@&F+T)ekr#"MM-CcF0*pfUMM`5Hd-*A450pjlk`mPT8VU"Y9h0R3
+
+Mi#,4b)#J'D-9V[Mh#PIqZX**-8jAH0BrUp"aT*4UR0)#8Sh6@T!!8Se6@T!!maX
+
+Yd(kN"FGd1[HIG2TA[3DH,8Mf'TBDXp4V02ZFVQ8q2,U3!#'KemM%T"XRp@#KVcU
+
+Y"q@f5Y+$A#aMZCD&Srj`4S3qiL3hckljPY445pa8@+b09#FYcCj'[bpc@BGcr'Q
+
+!%69iq@)m[C*8URU(RG4!'ib%'PfYVS`*8j,-6"h[aReIXbG[D8k5c,e@cYh[$#h
+
+lT)pilFFr65[(JLU"+N',p`QF2Y40KM[Pq2-plHN1e&CT4R@a((P61@0C"rU4'Q`
+
+blVmMh8FNDTaTr9MRD@`4JjR-qSM6-pGM1,T84T8160L3!*%BDI-(2jh'hIh8YR5
+
+r8BZ42Y@"2cR5GhfQ,m$+0,B(FZ(*qFCchdR[JG5Dl3[K98[0EFBhc6Jf!k'Hj$p
+
+R)(rUIIG)ebZT#lVHd,,'8%3DJQ5UfdlEP"@LKiU5A8P9!ff@U2hH-(@biF`FQ[(
+
+KV+6++NJeiI9JS(a#A@K@FPTGe,p@Pj4QR&)AdSc6kT,5M&2U3T15dqU5QT4mULl
+
+T5FPrl#eaeipXJ`L95k4YN!"fmDV'M(FlXp`hrMJpBDZc9%XlCB(Q0M6#dJJhdpT
+
+%2bZdFd30'KTT[d-6#2rA22prCQFCZHEjar[pNj2C69PYp)K@DM)V+8'fT!3C%RU
+
+0$!Sc%%F&0K8NII&jQb@NScQPp1@%DKc0DD4,rDbV-ccd@PV(lCAPY$H4%a*G2UI
+
+ARl'MdM)(c3+5MpDF8)f1Rr4*kNc)faB*9I4DMcVDlZfJPej1UXfAEck8RMde1"C
+
+Ci0@')p(QjN#S(A*Mr%a[J*8"E)T3G!%pL5YhHBl+"RVj4bhpa)5,Y@G#d)*M[FH
+
+rp@3IGap(N9*kF+TlbrUSQrlA5IIaD[aidXeYj&CVNMH83&CM+!&9RaC+%&Q"[`%
+
+!PM5C'9(,)ph(*fUTr9!YMqT9DV2iP&iGfErj4+r'r8D[mMkHFibb02iMPNjf1PA
+
+[d("$VLh(CI8d(p1LX&VN*cJbP(8k[pfF2kE#ZPqTX(51-%LC%ZXU[a22)[*i8[E
+
+rZJ[cIcUGL4G#pHMBk,e2kCF0VX,2PP#E5Iik[#T1$qmHrqXJc[6'Fa2`XLUETTM
+
+$*YV-$D3cYp12%m#qEb(qhJ$feL8eGE5PqJMF0!YqXU&'QZAY39+9b(8[r8`"-MX
+
+Ah$6![T!!ITF!pTb'bfV*EbNA&PMaKL[H#UA+i@kTX"!qGeH&C3R&EkCI&X"$k6d
+
+9PN9@f#m[VUY"R%+aB%N90%@4PhahPUZj([c3IkY-$A%eUr''+[Q8"m(LQS3[kcE
+
+1G+!PiF[1j8b6mBiYqG4I![EZK'rFji"Ab"55leDmdYV+9*,[$[MHa&2kj,XIH(K
+
+90KkIa-Ep'I$!Tj5(&h&2b4cN`,G2pSf$$kqZ5Vi*m(hh+pHLCV(B#pqMEAp*2`L
+
+K$S-ce482X[1!F4&mDd`jE#EL`-(e-DD6q,X(FCd12IXm1+#IdU#-2SFi1q)HB*d
+
+54KI`ANVie'C`8jVJFZTNa%85A%ip'ebqP1"bkZr$jj-acJ0'8-Di!,i@'@-Q-2E
+
+*q68KTiMXZ`ja[9RqCFj@hp%rG"RpQjINMlqNrpQ&-qA@"ki53rAP&2rr!!!0$3p
+
+YGbpRBh4PFh3Z0MK,,VN!N""453#3%#pd!!"+8`#3"2q3"%e08&*0680$!3#V,jH
+
+ZUc!jB!!!"M%!!"R%!!!"V3!!"E(*MaZS!*!'[VXM4!iL+Pj0j%)PIdhl9fbRBC!
+
+!DR1(JAFp3hUJ2KNcZ@(k&LeHlIYc*cMM1X2GRCf"!*`N(81C&iAQNTm4&Ifii1"
+
+EpGII4h6#PiP+'R-jb[e$&IeM12rA3hh-XBk+D2XK9#@U!P9e!@eRU22XRT!!%ar
+
+%6jaP3[FjFKhiIjQ@hidE$&25cAm$`-IrIXai*1U*jZd88q%pXX1%F$M`RNJbAQS
+
+ih%%N0J*@A""6p[pE#%1,cL9X%K8j[Z%i38$F)*'R%8!QpTQQT&06TCMf4amme9+
+
+jii[1iC(HE43E%aa#QlrCjZ4[GSL(8*!!e8D-E"#r6LR@&GN3aF6F'028K*cdTGk
+
+aT$fkUhhK6F,P(Tj11!CFTLJ+QQSXDINp,M$RL-+Cm9q6j"VK+Hr'rhrjXB16b1@
+
+iec&AC&Z,)bAP)A[QZNkT`brFF9bj0@L(b*(4H3)$i*YCbh9`YK90aj%$0a!Gm&!
+
+,de[B3!XlC'%$"-Eme,D0'(Z229-8DlB`9Q$FC!Y6@9L'KA%@PQm[")V0YM#PKBP
+
+$[mI#m!L#i#MfjAH50i4eE512Q3bj@@90I4m!N!--!'XcXfpJlh2Ij$4lRaZHF-P
+
+a`Tr-D)4&@%FjIAiV9hi5rZ3i@3NqRhV5`hI'm8m[3MNjENHi%AjN`!NMR"`rbB$
+
+bTrc)FA,m$%r*F51Fm*03FTa`FTa`-Q#%%hlN'4R`Pa`RA(+FF+mMamRa)mq2m$2
+
+#bB!#GjN8B'@Y6-+0iUpN*rl)-F)*2m)*8[#%!j-9H"9SN!!()1QkKK#+`Hm@K$S
+
+HJ&m,rN[#E`hmIJLEJ,q0bk)PQTCS@&q4J@q@4d"9U,FU)md-(0Yrf-'kLSC3Ech
+
+QTZ6PDfM!,6kXTJh48"8c3%-B$Af2ZR8CG9Ip2$-35k-p#&9[4Zd)$4`EE%%G46!
+
+,R0"9-23T99CN34j4,-#2%@HJ4P(6T'aDQa#N[iMDX5G2a3J5j8hqU`G8AI)J-HU
+
+[2pc+8DXTel3Q5K1DDDe`rC'MeMLS#5QV5"2QC-jFKV@(Y,XiDUf$'TI6Q941+fY
+
+NIrEXmabeMLSdTZC&6Ae8m48krm8h(,@HFXdUSU`BRMk!q[lRHBlD3,RQ4#QENT@
+
+#"cXRI2X+4ie6jif)dMfM+mkEUadrc9%E(G5'h+TKlGFqRHHS#3He,LFDrPe`h($
+
+QCBlDa(3e*P+'jG["RP9riDM0,PI9V"`8d09SikJYP'YH1C5kHVfHlZ'SDkKIpI4
+
+i+LIkaJ28)bpbe,88e9!N694cCG6ZNqFjkMUUN!"T6DE6ZT(h&AViKGmikRVU"NX
+
+TAdR(H9q1FY4@bY@D,XL9SfF2rY6286HiPp,*+'9G,aJIFG50p#Uce14Gj3Y'd81
+
+Ek"h5cFV&)blrQ+1f8B8b8UTJU&0#eN-9cVh+8GXGe*U-j!-kU)P6p4b9*UB'dj*
+
+PCDb-E#IIrF$K4qBkCkfIRK)eFi@ZrFEXr4ae-h@$T1I(e%`C&K,!AUi3T&L#1U`
+
+I'P&bCG3h(rRp#Fje+d8&50fBrKHeFp&j@4Q5M3GV$pea1eGSfk+(0$9pa80R1GF
+
+ZCkfce*a5FDbGI1mKMRSpifUSq482fFRj!BlD6Id+#UPkaDr(MfcMU0YGVSSeRLY
+
+8Z0V[F05H43q4)19lk0aM"lL(GMKViS"LkT1'T(MH+rPeTkZ3!*U"!([&H8FjkLl
+
++0@RS306mKfX[64ZJ+`31D"5@fGUaCaUiVRd8Y@!C+5NVP42Ef6h&a0E[S,D5e*Z
+
+k$e*4k[,4R"1qUq@S0cKV-k$Hk86c@fiEqT2V*rYSlLHcfePEppip1YM9Hl2Del9
+
+2!&`"@TQ,U#F1&[Z''jdelZ4b1(ZHmdimH"0(45eR)(&!*q9f)f6q6PCX0VTUBad
+
+IAd$pf!@`[ik1Br'KUlR)+fakrN"cHF(H36)2h%jb&H(+NrX0&jMF9VMIj$*$&L)
+
+T"p)0cLf`Yq1%"AXR6JQ`Yq'FKMf0GB,GdbRXPYLiZ+lq4#IBL8k`%jeJ*cV"6R5
+
+#RHJ%1p%*GU)6l%3Rf)P1h%qc#+[@Y15RS-eL8qhT&"fJcd&k4dVkK,dC'pb'AVi
+
+MRZjKXmB'HccD3(IrcJ8G(KYmfk)&p1R"5Hkrqa'fKQc`$Bdfm0&Ek'dF5*Cm&25
+
+6E"T+qQc(16M5i"iI4FpKHCCb3p#-XSR6I3[1YF$(e@dVrAm(hAhGA,f#1a4fVQ`
+
+D)a0bM1IcX19PNiJXd-QrQrjp$rTP0Nh4$ljDEE6C0*GdfSPEQNJ$[AaI"9dkQjE
+
+)"&rjZ5PSlpQXL6c)65I42'&jkHi((6HE659pGY(F%GhJrk#CBp-AQC!!QcfG`RF
+
+BE0C'2GbTm18(Qh@4"hI+cbI"'a-fkb-2I05,Qq*VI86`ZS90Dq6"IEUNPpZrZ6d
+
+IkmP@hp@`f9$5UmK,"LjZ2dGjKIdd'pTRSrf,Re6[[[HdcbYXX0R3aK[KcVI)#mr
+
+A-dm"R8jJFcLjAc2T0r!1Xr%Ph(NRKdhm"Y1PM9qd9#9(PFc#![X)[SNKr!e@jAm
+
+!N!-0$3pYGbpRBh4PFh3Z8&"$,VN!N"!4c!#3%%+&!*!)rj!%68e38Ne33d-"!+X
+
+[PkkV-$P&!!!'-3!!'Z!!!!'T!!!&bE5F%03!N!B"fL0%$L)UANhN3L9r6IYAE+G
+
+KN!"UFiH"Gce$HU!q'61jBIV#iB$[cjhJM1X-GhH'!`%ib6Q'-Lm+c58r)bVkFF(
+
+"YqU[[irS4$#9MENFjIkKL[iaR2rVS6lQ@%G&Y2d3UK*9JDUkJ,Bce(Pf6fJm&6R
+
+b2Z8HRJiXa'A+ir""h#2TreqK*11PKX-G4'@dI[MrP@fl(cXiL9b1Haec4BbeKmP
+
+aeJj"iNA$iL1d#Y1J+HR89#QQrG%86l98l[LLFhLNlhad)NaL2JK&0pZFr-d1m4!
+
++XYS)fcSm[diTeKAC%-A8h"M6e)5Fp+AHXD3p1ZNm1FY%rabj$[`E!$0bi`E$P26
+
+rG@!p"$aQr-JXH*CjLX,-Um9UPGj1-5VH)fY@`*(4VHaDSf,&r6CPrlq&--R1K6X
+
+*#r!9a`Q#"HZ@0$hdcLR&Z$Fm-LN%a%6I)NG'j`NF&EkCY9`(CaX9iFL4(fpK!IC
+
+B8#c-*P,XP1dG-@D4KE%@0XR#9"C'PcdhhF,ZXE"3#eYVB3-&a[CDHNU"FB-@YXI
+
+#PPJD!bcX5f0T(aH0)DaV'hR-C-M0+Q[Uq``!Da0l'f3fmMSr"jhCCQZ%N3NRNdf
+
+14LJRP"rPR[a@3Sqr%8D1NjAJmk5Hp2#G-Ic6Le"1MJm)Pachb(2###I(6c*J%8k
+
+j%8k1RiHRj,J46[K*+$P11$P11"P3`JNrmS`-q)!-Z'6!D6eKj2L4C`f-F$+J`(8
+
+Q"D$m9QE4e,T1r"&qK,q%%k6J#3FQ+c!qS%%HJ+LU#N)S",rE%'S`i2Fjq"D$ha,
+
+iI4qf+2P[K53BJQi)Q['&0I#IjBQL)Y4CP"42pjcUHm,'ZSf'8'HBF--Ck@qdLS0
+
+b3K-d'HXH'L*+S#ZS9C93Dp(hThY##E32SH*'Y!@KRP2p0@MV!TJ"6QM*DZUi,'%
+
+T+JeJ!r"$PM03TD!SBLUKM%E&Qd60d0-c)3Z*mVDqK3&9&I13!!6eTfr[iUM&P'Y
+
+#%F4446G@Z(l(88YXe)LB`Z+S2TE@Pf(0!mTp(,A84Uf3!",*H&STD'4qmZcc(,@
+
+-+M3XC`4&IJbl#Phql%Z1'UCF8eL3!,#@e`G3hrdd`e(,+GHd)+EL%XlQBDHLAlh
+
+-85ZSm`B%mB'K&HG0PBjFj+L90QTjHXf`jUXI6h28L)eDPKBdpblBE[Mm*BjDaA6
+
+94Z1DiGV"R*4rj+M9$PGCAcdSS+ZfQD2@8+iCI$4qqhSpdmj4DkPIeF4)2#fiaJ2
+
+8Bbpbe(889F1L)XMT!QVVKFXFYBiUT"YMLB5UC9b&(RhKCikkRVV"`)8VDEQKZf-
+
+V4kfRA)f*V,4kp-cqUedFGB0c+Hf-8Y$eQ[B"4pe)Vc*,6IQVI%eEm0!QHSG8IIA
+
+L@5lrN!#MEUCQhhrr8(p,Ec3@kie#4,V"pIbK)a`9-T!!GBlk-`E@KJ84,f%LG'i
+
+f[T!!!'KLUKNie$XiPM(N0&lQH[KU'dGYS"j+L['X*Sp(8hPGSl0R1'UMM9U5&&e
+
+!'c8b%qDSN!"L,3rTKL6Ki3+b'A[l2CZI0G[Y06`a,LMk#PhcpFQ(1'S6pDZSCSE
+
+PC!&fUR[r&Uj3-eASS(Td!+F,U1H1r2)8jpT#83&5e5EZS1kBGej+JZb9Kc82h(-
+
+h9kKehN1+R,MPS8ZFDjZpPPPABF@aCZbG`abeRA(9j-b+KmcBG!p(lD"q"B9NGG@
+
+[CimeFp5G$PGXM+5cUec0YcMUVRN2@9(2pG$Xii2F3jhf'KR%ZMUQL6M[[CaIGcX
+
++b8Q)f,HFGj+MGP'Z-8d&S[SrA2I32!5k3L5#cQ1CV4NkAXjer4pehS"JT*BMJmh
+
+eq+jHMVUAFXdD@Pa-LB8NHQRI3K)PI3p-0D6jHqhb!-,0lkJIrAq#kpTYIkZh1S$
+
+iJj!!%H0,"hSUqR8TjiTU6d$LH!3qd"l'QVp5(*Z0MQj%N5IR8$IK#2YVk#b4%AU
+
+KAhRjVG*[D*cA0T*HB1mJp`hf9R+*B@mR9a,f0R*MBGp1mJVX655"`0j)XK,X1mL
+
+pKlf"*+irG2*l,$B1E[#"6T2S$,#X@[56ejba+FlV&"bJcm2dMZ6dm6Xk0U4jAES
+
+MHGhp&Sp0DH#"lZkGmrT#0Q@"!rVX)TRXhr[K0j4X`S%(2RS$[3RXDKCpj(@KE-T
+
+cqZ`NL6E3i"kI4160319LE["D@$B9G'mQ#4Ai1,Ued1qGG(GeFr6blT!!hqqbU3a
+
+-b$&jRrZ0-TY)B)&1lYedll[ACE1T#Rl`e9TlcUBkTp0ZdVF%-H4Z[lGR8a1Bi#X
+
+h0hN["GM8"KlNTJYSfQ*jrHjlI6UE66PpZQMZ#'l`[pH@XGNEQ*!!Qr-kq@mqf+`
+
+,HVK6rLX60R@""hI+c5IHHaBfk`-2I,5(G,jrpK(H5aSfpB%(pqQkANlrj[4mV#G
+
+EHm2$CN01V`9H%R"aqMR+bhpj`iDqe%&p8bAIR!qTj%[4$kpFY(MK'lcmYcPXk&Z
+
+H1lcmlTi0lIT[mPVbJIFUL!elGjRM4BM8c8"+#$@"@kr%qK5GrJGH8d5JeDSp%6Z
+
+S`aY94TZmpLQ+$H(Nh"cl%r`RK-KrL#Vr!3#3!aq$!!!"!*!$!43!N!-8!*!$-Tr
+
+lRLe!rr#`!,K[$#eZd!6rm2rdd"lm`FAKdkSV8FY+$deKBe"bEfTPBh4c,R0TG!)
+
+!N!06594%8dP8)3#3"P0*9%46593K!*!BUc!jI3!!8M8!!!&'"1"2l'mDG@6JrHc
+
+K@5U#NI*HN@GK!Z"2kQ`FG&2UN!"S!!,L@5[48(adA`CdC!EJ6qj[8hJS!!EJEHl
+
+LEe5!)D$!FJC1ANl!*IrX51FI-#D`jL63G!*&0K!+1Li!&Ri!)VX-S"lbUKQJ(Z`
+
+3!+SDI!$!#3ZT8,aIE!!!Q$!'8!6"aG!!N!-3!#X!"3%B!J#3"`-!N!-"!*!$!43
+
+!N!-8!*!$-J$j(l!@#J#3!a`!-J!!8f9dC`#3!`S!!2rr!*!&q@G%'@B:
+
diff --git a/tools/build/v2/engine/boehm_gc/Mac_files/MacOS_Test_config.h b/tools/build/v2/engine/boehm_gc/Mac_files/MacOS_Test_config.h
new file mode 100644
index 0000000000..4e5d252778
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/Mac_files/MacOS_Test_config.h
@@ -0,0 +1,91 @@
+/*
+ MacOS_Test_config.h
+
+ Configuration flags for Macintosh development systems.
+
+ Test version.
+
+ <Revision History>
+
+ 11/16/95 pcb Updated compilation flags to reflect latest 4.6 Makefile.
+
+ by Patrick C. Beard.
+ */
+/* Boehm, November 17, 1995 12:05 pm PST */
+
+#ifdef __MWERKS__
+
+// for CodeWarrior Pro with Metrowerks Standard Library (MSL).
+// #define MSL_USE_PRECOMPILED_HEADERS 0
+#include <ansi_prefix.mac.h>
+#ifndef __STDC__
+#define __STDC__ 0
+#endif
+
+#endif
+
+// these are defined again in gc_priv.h.
+#undef TRUE
+#undef FALSE
+
+#define ALL_INTERIOR_POINTERS // follows interior pointers.
+//#define SILENT // want collection messages.
+//#define DONT_ADD_BYTE_AT_END // no padding.
+//#define SMALL_CONFIG // whether to a smaller heap.
+#define NO_SIGNALS // signals aren't real on the Macintosh.
+#define USE_TEMPORARY_MEMORY // use Macintosh temporary memory.
+
+// CFLAGS= -O -DNO_SIGNALS -DALL_INTERIOR_POINTERS -DSILENT
+//
+//LIBGC_CFLAGS= -O -DNO_SIGNALS -DSILENT \
+// -DREDIRECT_MALLOC=GC_malloc_uncollectable \
+// -DDONT_ADD_BYTE_AT_END -DALL_INTERIOR_POINTERS
+// Flags for building libgc.a -- the last two are required.
+//
+// Setjmp_test may yield overly optimistic results when compiled
+// without optimization.
+// -DSILENT disables statistics printing, and improves performance.
+// -DCHECKSUMS reports on erroneously clear dirty bits, and unexpectedly
+// altered stubborn objects, at substantial performance cost.
+// Use only for incremental collector debugging.
+// -DFIND_LEAK causes the collector to assume that all inaccessible
+// objects should have been explicitly deallocated, and reports exceptions.
+// Finalization and the test program are not usable in this mode.
+// -DSOLARIS_THREADS enables support for Solaris (thr_) threads.
+// (Clients should also define SOLARIS_THREADS and then include
+// gc.h before performing thr_ or GC_ operations.)
+// This is broken on nonSPARC machines.
+// -DALL_INTERIOR_POINTERS allows all pointers to the interior
+// of objects to be recognized. (See gc_priv.h for consequences.)
+// -DSMALL_CONFIG tries to tune the collector for small heap sizes,
+// usually causing it to use less space in such situations.
+// Incremental collection no longer works in this case.
+// -DLARGE_CONFIG tunes the collector for unusually large heaps.
+// Necessary for heaps larger than about 500 MB on most machines.
+// Recommended for heaps larger than about 64 MB.
+// -DDONT_ADD_BYTE_AT_END is meaningful only with
+// -DALL_INTERIOR_POINTERS. Normally -DALL_INTERIOR_POINTERS
+// causes all objects to be padded so that pointers just past the end of
+// an object can be recognized. This can be expensive. (The padding
+// is normally more than one byte due to alignment constraints.)
+// -DDONT_ADD_BYTE_AT_END disables the padding.
+// -DNO_SIGNALS does not disable signals during critical parts of
+// the GC process. This is no less correct than many malloc
+// implementations, and it sometimes has a significant performance
+// impact. However, it is dangerous for many not-quite-ANSI C
+// programs that call things like printf in asynchronous signal handlers.
+// -DGC_OPERATOR_NEW_ARRAY declares that the C++ compiler supports the
+// new syntax "operator new[]" for allocating and deleting arrays.
+// See gc_cpp.h for details. No effect on the C part of the collector.
+// This is defined implicitly in a few environments.
+// -DREDIRECT_MALLOC=X causes malloc, realloc, and free to be defined
+// as aliases for X, GC_realloc, and GC_free, respectively.
+// Calloc is redefined in terms of the new malloc. X should
+// be either GC_malloc or GC_malloc_uncollectable.
+// The former is occasionally useful for working around leaks in code
+// you don't want to (or can't) look at. It may not work for
+// existing code, but it often does. Neither works on all platforms,
+// since some ports use malloc or calloc to obtain system memory.
+// (Probably works for UNIX, and win32.)
+// -DNO_DEBUG removes GC_dump and the debugging routines it calls.
+// Reduces code size slightly at the expense of debuggability.
diff --git a/tools/build/v2/engine/boehm_gc/Mac_files/MacOS_config.h b/tools/build/v2/engine/boehm_gc/Mac_files/MacOS_config.h
new file mode 100644
index 0000000000..407bdf154a
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/Mac_files/MacOS_config.h
@@ -0,0 +1,89 @@
+/*
+ MacOS_config.h
+
+ Configuration flags for Macintosh development systems.
+
+ <Revision History>
+
+ 11/16/95 pcb Updated compilation flags to reflect latest 4.6 Makefile.
+
+ by Patrick C. Beard.
+ */
+/* Boehm, November 17, 1995 12:10 pm PST */
+
+#ifdef __MWERKS__
+
+// for CodeWarrior Pro with Metrowerks Standard Library (MSL).
+// #define MSL_USE_PRECOMPILED_HEADERS 0
+#include <ansi_prefix.mac.h>
+#ifndef __STDC__
+#define __STDC__ 0
+#endif
+
+#endif /* __MWERKS__ */
+
+// these are defined again in gc_priv.h.
+#undef TRUE
+#undef FALSE
+
+#define ALL_INTERIOR_POINTERS // follows interior pointers.
+#define SILENT // no collection messages.
+//#define DONT_ADD_BYTE_AT_END // no padding.
+//#define SMALL_CONFIG // whether to use a smaller heap.
+#define NO_SIGNALS // signals aren't real on the Macintosh.
+#define USE_TEMPORARY_MEMORY // use Macintosh temporary memory.
+
+// CFLAGS= -O -DNO_SIGNALS -DSILENT -DALL_INTERIOR_POINTERS
+//
+//LIBGC_CFLAGS= -O -DNO_SIGNALS -DSILENT \
+// -DREDIRECT_MALLOC=GC_malloc_uncollectable \
+// -DDONT_ADD_BYTE_AT_END -DALL_INTERIOR_POINTERS
+// Flags for building libgc.a -- the last two are required.
+//
+// Setjmp_test may yield overly optimistic results when compiled
+// without optimization.
+// -DSILENT disables statistics printing, and improves performance.
+// -DCHECKSUMS reports on erroneously clear dirty bits, and unexpectedly
+// altered stubborn objects, at substantial performance cost.
+// Use only for incremental collector debugging.
+// -DFIND_LEAK causes the collector to assume that all inaccessible
+// objects should have been explicitly deallocated, and reports exceptions.
+// Finalization and the test program are not usable in this mode.
+// -DSOLARIS_THREADS enables support for Solaris (thr_) threads.
+// (Clients should also define SOLARIS_THREADS and then include
+// gc.h before performing thr_ or GC_ operations.)
+// This is broken on nonSPARC machines.
+// -DALL_INTERIOR_POINTERS allows all pointers to the interior
+// of objects to be recognized. (See gc_priv.h for consequences.)
+// -DSMALL_CONFIG tries to tune the collector for small heap sizes,
+// usually causing it to use less space in such situations.
+// Incremental collection no longer works in this case.
+// -DLARGE_CONFIG tunes the collector for unusually large heaps.
+// Necessary for heaps larger than about 500 MB on most machines.
+// Recommended for heaps larger than about 64 MB.
+// -DDONT_ADD_BYTE_AT_END is meaningful only with
+// -DALL_INTERIOR_POINTERS. Normally -DALL_INTERIOR_POINTERS
+// causes all objects to be padded so that pointers just past the end of
+// an object can be recognized. This can be expensive. (The padding
+// is normally more than one byte due to alignment constraints.)
+// -DDONT_ADD_BYTE_AT_END disables the padding.
+// -DNO_SIGNALS does not disable signals during critical parts of
+// the GC process. This is no less correct than many malloc
+// implementations, and it sometimes has a significant performance
+// impact. However, it is dangerous for many not-quite-ANSI C
+// programs that call things like printf in asynchronous signal handlers.
+// -DGC_OPERATOR_NEW_ARRAY declares that the C++ compiler supports the
+// new syntax "operator new[]" for allocating and deleting arrays.
+// See gc_cpp.h for details. No effect on the C part of the collector.
+// This is defined implicitly in a few environments.
+// -DREDIRECT_MALLOC=X causes malloc, realloc, and free to be defined
+// as aliases for X, GC_realloc, and GC_free, respectively.
+// Calloc is redefined in terms of the new malloc. X should
+// be either GC_malloc or GC_malloc_uncollectable.
+// The former is occasionally useful for working around leaks in code
+// you don't want to (or can't) look at. It may not work for
+// existing code, but it often does. Neither works on all platforms,
+// since some ports use malloc or calloc to obtain system memory.
+// (Probably works for UNIX, and win32.)
+// -DNO_DEBUG removes GC_dump and the debugging routines it calls.
+// Reduces code size slightly at the expense of debuggability.
diff --git a/tools/build/v2/engine/boehm_gc/Mac_files/dataend.c b/tools/build/v2/engine/boehm_gc/Mac_files/dataend.c
new file mode 100644
index 0000000000..a3e3fe8446
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/Mac_files/dataend.c
@@ -0,0 +1,9 @@
+/*
+ dataend.c
+
+ A hack to get the extent of global data for the Macintosh.
+
+ by Patrick C. Beard.
+ */
+
+long __dataend;
diff --git a/tools/build/v2/engine/boehm_gc/Mac_files/datastart.c b/tools/build/v2/engine/boehm_gc/Mac_files/datastart.c
new file mode 100644
index 0000000000..a9e0dd5941
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/Mac_files/datastart.c
@@ -0,0 +1,9 @@
+/*
+ datastart.c
+
+ A hack to get the extent of global data for the Macintosh.
+
+ by Patrick C. Beard.
+ */
+
+long __datastart;
diff --git a/tools/build/v2/engine/boehm_gc/Makefile.DLLs b/tools/build/v2/engine/boehm_gc/Makefile.DLLs
new file mode 100644
index 0000000000..011f49d3bc
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/Makefile.DLLs
@@ -0,0 +1,107 @@
+#-----------------------------------------------------------------------------#
+
+# Makefile.DLLs, version 0.4.
+
+# Contributed by Fergus Henderson.
+
+# This Makefile contains rules for creating DLLs on Windows using gnu-win32.
+
+#-----------------------------------------------------------------------------#
+
+# This rule creates a `.def' file, which lists the symbols that are exported
+# from the DLL. We use `nm' to get a list of all the exported text (`T')
+# symbols and data symbols -- including uninitialized data (`B'),
+# initialized data (`D'), read-only data (`R'), and common blocks (`C').
+%.def: %.a
+ echo EXPORTS > $@
+ nm $< | grep '^........ [BCDRT] _' | sed 's/[^_]*_//' >> $@
+
+# We need to use macros to access global data:
+# the user of the DLL must refer to `foo' as `(*__imp_foo)'.
+# This rule creates a `_globals.h' file, which contains macros
+# for doing this.
+
+SYM_PREFIX = $(firstword $(SYM_PREFIX-$*) $*)
+DLL_MACRO = $(SYM_PREFIX)_USE_DLL
+IMP_MACRO = $(SYM_PREFIX)_IMP
+GLOBAL_MACRO = $(SYM_PREFIX)_GLOBAL
+
+%_globals.h: %.a
+ echo "/* automatically generated by Makefile.DLLs */" > $@
+ echo "#if defined(__GNUC__) && defined(_WIN32) \\" >> $@
+ echo " && defined($(DLL_MACRO))" >> $@
+ echo "# define $(IMP_MACRO)(name) __imp_##name" >> $@
+ echo "# define $(GLOBAL_MACRO)(name) (*$(IMP_MACRO)(name))" >> $@
+ echo "#else" >> $@
+ echo "# define $(GLOBAL_MACRO)(name) name" >> $@
+ echo "#endif" >> $@
+ echo "" >> $@
+ for sym in `nm $< | grep '^........ [BCDR] _' | sed 's/[^_]*_//'`; do \
+ echo "#define $$sym $(GLOBAL_MACRO)($$sym)" >> $@; \
+ done
+
+# This rule creates the export object file (`foo.exp') which contains the
+# jump table array; this export object file becomes part of the DLL.
+# This rule also creates the import library (`foo_dll.a') which contains small
+# stubs for all the functions exported by the DLL which jump to them via the
+# jump table. Executables that will use the DLL must be linked against this
+# stub library.
+%.exp %_dll.a : %.def
+ dlltool $(DLLTOOLFLAGS) $(DLLTOOLFLAGS-$*) \
+ --def $< \
+ --dllname $*.dll \
+ --output-exp $*.exp \
+ --output-lib $*_dll.a
+
+# The `sed' commands below are to convert DOS-style `C:\foo\bar'
+# pathnames into Unix-style `//c/foo/bar' pathnames.
+CYGWIN32_LIBS = $(shell echo \
+ -L`dirname \`gcc -print-file-name=libgcc.a | \
+ sed -e 's@^\\\\([A-Za-z]\\\\):@//\\\\1@g' -e 's@\\\\\\\\@/@g' \` ` \
+ -L`dirname \`gcc -print-file-name=libcygwin.a | \
+ sed -e 's@^\\\\([A-Za-z]\\\\):@//\\\\1@g' -e 's@\\\\\\\\@/@g' \` ` \
+ -L`dirname \`gcc -print-file-name=libkernel32.a | \
+ sed -e 's@^\\\\([A-Za-z]\\\\):@//\\\\1@g' -e 's@\\\\\\\\@/@g' \` ` \
+ -lgcc -lcygwin -lkernel32 -lgcc)
+
+RELOCATABLE=yes
+
+ifeq "$(strip $(RELOCATABLE))" "yes"
+
+# to create relocatable DLLs, we need to do two passes
+%.dll: %.exp %.a dll_fixup.o dll_init.o
+ $(LD) $(LDFLAGS) $(LDFLAGS-$*) --dll -o $*.base \
+ -e _dll_entry@12 dll_init.o \
+ dll_fixup.o $*.exp $*.a \
+ $(LDLIBS) $(LDLIBS-$*) \
+ $(CYGWIN32_LIBS)
+ $(LD) $(LDFLAGS) $(LDFLAGS-$*) --dll --base-file $*.base -o $@ \
+ -e _dll_entry@12 dll_init.o \
+ dll_fixup.o $*.exp $*.a \
+ $(LDLIBS) $(LDLIBS-$*) \
+ $(CYGWIN32_LIBS)
+ rm -f $*.base
+else
+
+%.dll: %.exp %.a dll_fixup.o dll_init.o
+ $(LD) $(LDFLAGS) $(LDFLAGS-$*) --dll -o $@ \
+ -e _dll_entry@12 dll_init.o \
+ dll_fixup.o $*.exp $*.a \
+ $(LDLIBS) $(LDLIBS-$*) \
+ $(CYGWIN32_LIBS)
+
+endif
+
+# This black magic piece of assembler needs to be linked in in order to
+# properly terminate the list of imported DLLs.
+dll_fixup.s:
+ echo '.section .idata$$3' > dll_fixup.s
+ echo '.long 0,0,0,0, 0,0,0,0' >> dll_fixup.s
+
+# This bit is necessary to provide an initialization function for the DLL.
+dll_init.c:
+ echo '__attribute__((stdcall))' > dll_init.c
+ echo 'int dll_entry(int handle, int reason, void *ptr)' >> dll_init.c
+ echo '{return 1; }' >> dll_init.c
+
+dont_throw_away: dll_fixup.o dll_init.o
diff --git a/tools/build/v2/engine/boehm_gc/Makefile.am b/tools/build/v2/engine/boehm_gc/Makefile.am
new file mode 100644
index 0000000000..e632864df2
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/Makefile.am
@@ -0,0 +1,206 @@
+# Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved.
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose, provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+#
+# Original author: Tom Tromey
+# Severely truncated by Hans-J. Boehm
+# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
+# Modified by: Petter Urkedal <petter.urkedal@nordita.dk> (2005-04)
+
+## Process this file with automake to produce Makefile.in.
+
+## FIXME: `make distcheck' in this directory will not currently work.
+## This is most likely to the explicit flags passed to submakes.
+
+# We currently use the source files directly from libatomic_ops, if we
+# use the internal version. This is done since libatomic_ops doesn't
+# use libtool, since it has no real use for it. But that seems to make
+# it hard to use either the resulting object files or libraries.
+# Thus there seems too be no real reason to recusively build in the
+# libatomic_ops directory.
+# if USE_INTERNAL_LIBATOMICS_OPS
+# SUBDIRS = @maybe_libatomic_ops@
+# else
+# SUBDIRS =
+# endif
+SUBDIRS =
+
+# Initialize variables so that we can declare files locally.
+EXTRA_DIST =
+lib_LTLIBRARIES =
+include_HEADERS =
+pkginclude_HEADERS =
+dist_noinst_HEADERS =
+check_PROGRAMS =
+TESTS =
+
+pkgconfigdir = $(libdir)/pkgconfig
+dist_pkgconfig_DATA = bdw-gc.pc
+
+# C Library
+# ---------
+
+lib_LTLIBRARIES += libgc.la
+libgc_la_SOURCES = \
+ allchblk.c alloc.c blacklst.c checksums.c dbg_mlc.c \
+ dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c \
+ malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.c \
+ obj_map.c os_dep.c pcr_interface.c ptr_chck.c real_malloc.c reclaim.c \
+ specific.c stubborn.c typd_mlc.c \
+ backgraph.c thread_local_alloc.c
+
+# C Library: Architecture Dependent
+# ---------------------------------
+
+if PTHREADS
+libgc_la_SOURCES += pthread_support.c pthread_stop_world.c
+endif
+
+if DARWIN_THREADS
+libgc_la_SOURCES += darwin_stop_world.c
+endif
+
+if WIN32_THREADS
+libgc_la_SOURCES += win32_threads.c
+endif
+
+if USE_INTERNAL_LIBATOMIC_OPS
+nodist_libgc_la_SOURCES = atomic_ops.c
+endif
+
+if NEED_ATOMIC_OPS_ASM
+nodist_libgc_la_SOURCES = atomic_ops_sysdeps.S
+endif
+
+# Include THREADDLLIBS here to ensure that the correct versions of
+# linuxthread semaphore functions get linked:
+libgc_la_LIBADD = @addobjs@ $(THREADDLLIBS) $(UNWINDLIBS)
+libgc_la_DEPENDENCIES = @addobjs@
+libgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info 1:3:0 -no-undefined
+
+EXTRA_libgc_la_SOURCES = alpha_mach_dep.S \
+ mips_sgi_mach_dep.s mips_ultrix_mach_dep.s \
+ rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \
+ sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
+
+
+# C++ Interface
+# -------------
+
+if CPLUSPLUS
+lib_LTLIBRARIES += libgccpp.la
+pkginclude_HEADERS += include/gc_cpp.h include/gc_allocator.h
+libgccpp_la_SOURCES = gc_cpp.cc
+libgccpp_la_LIBADD = $(top_builddir)/libgc.la
+libgccpp_la_LDFLAGS = -version-info 1:3:0 -no-undefined
+endif
+
+# FIXME: If Visual C++ users use Makefile.am, this should go into
+# pkginclude_HEADERS with proper AM_CONDITIONALization. Otherwise
+# delete this comment.
+EXTRA_DIST += gc_cpp.cpp
+
+
+# Misc
+# ----
+
+AM_CXXFLAGS = @GC_CFLAGS@
+AM_CFLAGS = @GC_CFLAGS@
+
+## FIXME: relies on internal code generated by automake.
+## FIXME: ./configure --enable-dependency-tracking should be used
+#all_objs = @addobjs@ $(libgc_la_OBJECTS)
+#$(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \
+#include/private/gc_hdrs.h include/gc.h include/gc_gcj.h \
+#include/gc_pthread_redirects.h include/gc_config_macros.h \
+#include/private/thread_local_alloc.h include/private_support.h \
+#include/private/pthread_stop_world.h \
+#include/gc_mark.h @addincludes@
+
+## FIXME: we shouldn't have to do this, but automake forces us to.
+## We use -Wp,-P to strip #line directives. Irix `as' chokes on
+## these.
+if COMPILER_XLC
+ ## XLC neither requires nor tolerates the unnecessary assembler goop
+ ASM_CPP_OPTIONS =
+else
+ ## We use -Wp,-P to strip #line directives. Irix `as' chokes on
+ ## these.
+ ASM_CPP_OPTIONS = -Wp,-P -x assembler-with-cpp
+endif
+.s.lo:
+ $(LTCOMPILE) $(ASM_CPP_OPTIONS) -c $<
+
+.S.lo:
+ $(LTCOMPILE) $(ASM_CPP_OPTIONS) -c $<
+
+## We need to add DEFS to assembler flags
+## :FIXME: what if assembler does not accept -D... ?
+## (use Autoconf to prepare ASDEFS ???)
+
+CCASFLAGS += $(DEFS)
+
+dist_noinst_SCRIPTS = callprocs configure.host
+ ## callprocs --- used by Makefile.{dj,direct}
+ ## configure.host --- used by Makefile.{am,dj,direct}
+
+# headers which are not installed
+# (see include/include.am for more)
+#
+dist_noinst_HEADERS += version.h
+
+# documentation which is not installed
+#
+EXTRA_DIST += README.QUICK
+
+# other makefiles
+# :GOTCHA: deliberately we do not include 'Makefile'
+EXTRA_DIST += BCC_MAKEFILE NT_MAKEFILE NT_THREADS_MAKEFILE \
+ OS2_MAKEFILE PCR-Makefile digimars.mak EMX_MAKEFILE \
+ Makefile.direct Makefile.dj Makefile.DLLs SMakefile.amiga \
+ WCC_MAKEFILE configure_atomic_ops.sh \
+ NT_STATIC_THREADS_MAKEFILE NT_X64_STATIC_THREADS_MAKEFILE
+
+# files used by makefiles other than Makefile.am
+#
+EXTRA_DIST += add_gc_prefix.c gcname.c if_mach.c if_not_there.c \
+ hpux_test_and_clear.s gc.mak MacOS.c \
+ MacProjects.sit.hqx mach_dep.c setjmp_t.c \
+ threadlibs.c AmigaOS.c \
+ Mac_files/datastart.c Mac_files/dataend.c \
+ Mac_files/MacOS_config.h Mac_files/MacOS_Test_config.h \
+ include/private/msvc_dbg.h msvc_dbg.c
+
+# The libatomic_ops library. This is not ideal, since we pick up junk from
+# there. The hard-coded version number should also go.
+EXTRA_DIST += libatomic_ops-1.2
+
+# this is an auxiliary shell file used by Makefile and Makefile.direct
+#
+CONFIG_STATUS_DEPENDENCIES = $(srcdir)/configure.host
+
+# :FIXME: why do we distribute this one???
+#
+EXTRA_DIST += libtool.m4
+
+#
+# :GOTCHA: GNU make rule for making .s out of .S is flawed,
+# it will not remove dest if building fails
+.S.s:
+ if $(CPP) $< >$@ ; then :; else rm -f $@; fi
+
+include include/include.am
+include cord/cord.am
+include tests/tests.am
+include doc/doc.am
+# Putting these at the top causes cord to be built first, and not find libgc.a
+# on HP/UX. There may be a better fix.
+
+
diff --git a/tools/build/v2/engine/boehm_gc/Makefile.direct b/tools/build/v2/engine/boehm_gc/Makefile.direct
new file mode 100644
index 0000000000..40195a5625
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/Makefile.direct
@@ -0,0 +1,737 @@
+# This is the original manually generated Makefile. It may still be used
+# to build the collector.
+#
+# Primary targets:
+# gc.a - builds basic library
+# c++ - adds C++ interface to library
+# cords - adds cords (heavyweight strings) to library
+# test - prints porting information, then builds basic version of gc.a,
+# and runs some tests of collector and cords. Does not add cords or
+# c++ interface to gc.a
+# cord/de - builds dumb editor based on cords.
+ABI_FLAG=
+# ABI_FLAG should be the cc flag that specifies the ABI. On most
+# platforms this will be the empty string. Possible values:
+# +DD64 for 64-bit executable on HP/UX.
+# -n32, -n64, -o32 for SGI/MIPS ABIs.
+
+AS_ABI_FLAG=$(ABI_FLAG)
+# ABI flag for assembler. On HP/UX this is +A64 for 64 bit
+# executables.
+
+CC=cc $(ABI_FLAG)
+CXX=g++ $(ABI_FLAG)
+AS=as $(AS_ABI_FLAG)
+# The above doesn't work with gas, which doesn't run cpp.
+# Define AS as `gcc -c -x assembler-with-cpp' instead.
+
+# Redefining srcdir allows object code for the nonPCR version of the collector
+# to be generated in different directories.
+srcdir= .
+VPATH= $(srcdir)
+
+# Atomic_ops installation directory. If this doesn't exist, we create
+# it from the included libatomic_ops distribution.
+AO_VERSION=1.2
+AO_SRC_DIR=$(srcdir)/libatomic_ops-$(AO_VERSION)
+AO_INSTALL_DIR=$(srcdir)/libatomic_ops-install
+
+CFLAGS= -O -I$(srcdir)/include -I$(AO_INSTALL_DIR)/include -DATOMIC_UNCOLLECTABLE -DNO_EXECUTE_PERMISSION -DALL_INTERIOR_POINTERS
+
+# To build the parallel collector on Linux, add to the above:
+# -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC
+# To build the thread-capable preload library that intercepts
+# malloc, add -DGC_USE_DLOPEN_WRAP -DREDIRECT_MALLOC=GC_malloc -fpic
+# To build the parallel collector in a static library on HP/UX,
+# add to the above:
+# -DGC_HPUX_THREADS -DTHREAD_LOCAL_ALLOC -D_POSIX_C_SOURCE=199506L -mt
+# FIXME: PARALLEL_MARK currently broken on HP/UX.
+# To build the thread-safe collector on Tru64, add to the above:
+# -pthread -DGC_OSF1_THREADS
+
+# HOSTCC and HOSTCFLAGS are used to build executables that will be run as
+# part of the build process, i.e. on the build machine. These will usually
+# be the same as CC and CFLAGS, except in a cross-compilation environment.
+# Note that HOSTCFLAGS should include any -D flags that affect thread support.
+HOSTCC=$(CC)
+HOSTCFLAGS=$(CFLAGS)
+
+# For dynamic library builds, it may be necessary to add flags to generate
+# PIC code, e.g. -fPIC on Linux.
+
+# Setjmp_test may yield overly optimistic results when compiled
+# without optimization.
+
+# These define arguments influence the collector configuration:
+# -DFIND_LEAK causes GC_find_leak to be initially set.
+# This causes the collector to assume that all inaccessible
+# objects should have been explicitly deallocated, and reports exceptions.
+# Finalization and the test program are not usable in this mode.
+#
+# IMPORTANT: Any of the _THREADS options must normally also be defined in
+# the client before including gc.h. This redefines thread primitives to
+# invoke the GC_ versions instead. Alternatively, linker-based symbol
+# interception can be used on a few platforms.
+# -DGC_THREADS should set the appropriate one of the below macros,
+# except -DGC_WIN32_PTHREADS, which must be set explicitly.
+# -DGC_SOLARIS_PTHREADS enables support for Solaris pthreads.
+# (Clients should also define GC_SOLARIS_THREADS and then include
+# gc.h before performing thr_ or dl* or GC_ operations.)
+# Must also define -D_REENTRANT.
+# -DGC_IRIX_THREADS enables support for Irix pthreads. See README.irix.
+# -DGC_HPUX_THREADS enables support for HP/UX 11 pthreads.
+# Also requires -D_REENTRANT or -D_POSIX_C_SOURCE=199506L. See README.hp.
+# -DGC_LINUX_THREADS enables support for Xavier Leroy's Linux threads
+# or NPTL threads. See README.linux. -D_REENTRANT may also be required.
+# -DGC_OSF1_THREADS enables support for Tru64 pthreads.
+# -DGC_FREEBSD_THREADS enables support for FreeBSD pthreads.
+# Appeared to run into some underlying thread problems.
+# -DGC_DARWIN_THREADS enables support for Mac OS X pthreads.
+# -DGC_AIX_THREADS enables support for IBM AIX threads.
+# -DGC_DGUX386_THREADS enables support for DB/UX on I386 threads.
+# See README.DGUX386. (Probably has not been tested recently.)
+# -DGC_WIN32_THREADS enables support for win32 threads. That makes sense
+# for this Makefile only under Cygwin.
+# -DGC_WIN32_PTHREADS enables support for Ming32 pthreads. This cannot be
+# enabled automatically by GC_THREADS, which would assume Win32 native
+# threads.
+# -DPTW32_STATIC_LIB causes the static version of the Mingw pthreads library
+# to be used. Requires -DGC_WIN32_PTHREADS.
+#
+# -DALL_INTERIOR_POINTERS allows all pointers to the interior
+# of objects to be recognized. (See gc_priv.h for consequences.)
+# Alternatively, GC_all_interior_pointers can be set at process
+# initialization time.
+# -DSMALL_CONFIG tries to tune the collector for small heap sizes,
+# usually causing it to use less space in such situations.
+# Incremental collection no longer works in this case.
+# -DLARGE_CONFIG tunes the collector for unusually large heaps.
+# Necessary for heaps larger than about 500 MB on most machines.
+# Recommended for heaps larger than about 64 MB.
+# -DDONT_ADD_BYTE_AT_END is meaningful only with -DALL_INTERIOR_POINTERS or
+# GC_all_interior_pointers = 1. Normally -DALL_INTERIOR_POINTERS
+# causes all objects to be padded so that pointers just past the end of
+# an object can be recognized. This can be expensive. (The padding
+# is normally more than one byte due to alignment constraints.)
+# -DDONT_ADD_BYTE_AT_END disables the padding.
+# -DNO_EXECUTE_PERMISSION may cause some or all of the heap to not
+# have execute permission, i.e. it may be impossible to execute
+# code from the heap. Currently this only affects the incremental
+# collector on UNIX machines. It may greatly improve its performance,
+# since this may avoid some expensive cache synchronization.
+# -DGC_NO_OPERATOR_NEW_ARRAY declares that the C++ compiler does not support
+# the new syntax "operator new[]" for allocating and deleting arrays.
+# See gc_cpp.h for details. No effect on the C part of the collector.
+# This is defined implicitly in a few environments. Must also be defined
+# by clients that use gc_cpp.h.
+# -DREDIRECT_MALLOC=X causes malloc to be defined as alias for X.
+# Unless the following macros are defined, realloc is also redirected
+# to GC_realloc, and free is redirected to GC_free.
+# Calloc and strdup are redefined in terms of the new malloc. X should
+# be either GC_malloc or GC_malloc_uncollectable, or
+# GC_debug_malloc_replacement. (The latter invokes GC_debug_malloc
+# with dummy source location information, but still results in
+# properly remembered call stacks on Linux/X86 and Solaris/SPARC.
+# It requires that the following two macros also be used.)
+# The former is occasionally useful for working around leaks in code
+# you don't want to (or can't) look at. It may not work for
+# existing code, but it often does. Neither works on all platforms,
+# since some ports use malloc or calloc to obtain system memory.
+# (Probably works for UNIX, and win32.) If you build with DBG_HDRS_ALL,
+# you should only use GC_debug_malloc_replacement as a malloc
+# replacement.
+# -DREDIRECT_REALLOC=X causes GC_realloc to be redirected to X.
+# The canonical use is -DREDIRECT_REALLOC=GC_debug_realloc_replacement,
+# together with -DREDIRECT_MALLOC=GC_debug_malloc_replacement to
+# generate leak reports with call stacks for both malloc and realloc.
+# This also requires the following:
+# -DREDIRECT_FREE=X causes free to be redirected to X. The
+# canonical use is -DREDIRECT_FREE=GC_debug_free.
+# -DIGNORE_FREE turns calls to free into a noop. Only useful with
+# -DREDIRECT_MALLOC.
+# -DNO_DEBUGGING removes GC_dump and the debugging routines it calls.
+# Reduces code size slightly at the expense of debuggability.
+# -DJAVA_FINALIZATION makes it somewhat safer to finalize objects out of
+# order by specifying a nonstandard finalization mark procedure (see
+# finalize.c). Objects reachable from finalizable objects will be marked
+# in a separate postpass, and hence their memory won't be reclaimed.
+# Not recommended unless you are implementing a language that specifies
+# these semantics. Since 5.0, determines only the initial value
+# of GC_java_finalization variable.
+# -DFINALIZE_ON_DEMAND causes finalizers to be run only in response
+# to explicit GC_invoke_finalizers() calls.
+# In 5.0 this became runtime adjustable, and this only determines the
+# initial value of GC_finalize_on_demand.
+# -DATOMIC_UNCOLLECTABLE includes code for GC_malloc_atomic_uncollectable.
+# This is useful if either the vendor malloc implementation is poor,
+# or if REDIRECT_MALLOC is used.
+# -DMARK_BIT_PER_GRANULE requests that a mark bit (or often byte)
+# be allocated for each allocation granule, as opposed to each object.
+# This often improves speed, possibly at some cost in space and/or
+# cache footprint. Normally it is best to let this decision be
+# made automatically depending on platform.
+# -DMARK_BIT_PER_OBJ requests that a mark bit be allocated for each
+# object instead of allocation granule. The opposiet of
+# MARK_BIT_PER_GRANULE.
+# -DHBLKSIZE=ddd, where ddd is a power of 2 between 512 and 16384, explicitly
+# sets the heap block size. Each heap block is devoted to a single size and
+# kind of object. For the incremental collector it makes sense to match
+# the most likely page size. Otherwise large values result in more
+# fragmentation, but generally better performance for large heaps.
+# -DUSE_MMAP use MMAP instead of sbrk to get new memory.
+# Works for Solaris and Irix.
+# -DUSE_MUNMAP causes memory to be returned to the OS under the right
+# circumstances. This currently disables VM-based incremental collection.
+# This is currently experimental, and works only under some Unix,
+# Linux and Windows versions.
+# -DMMAP_STACKS (for Solaris threads) Use mmap from /dev/zero rather than
+# GC_scratch_alloc() to get stack memory.
+# -DPRINT_BLACK_LIST Whenever a black list entry is added, i.e. whenever
+# the garbage collector detects a value that looks almost, but not quite,
+# like a pointer, print both the address containing the value, and the
+# value of the near-bogus-pointer. Can be used to identifiy regions of
+# memory that are likely to contribute misidentified pointers.
+# -DKEEP_BACK_PTRS Add code to save back pointers in debugging headers
+# for objects allocated with the debugging allocator. If all objects
+# through GC_MALLOC with GC_DEBUG defined, this allows the client
+# to determine how particular or randomly chosen objects are reachable
+# for debugging/profiling purposes. The gc_backptr.h interface is
+# implemented only if this is defined.
+# -DGC_ASSERTIONS Enable some internal GC assertion checking. Currently
+# this facility is only used in a few places. It is intended primarily
+# for debugging of the garbage collector itself, but could also
+# -DDBG_HDRS_ALL Make sure that all objects have debug headers. Increases
+# the reliability (from 99.9999% to 100% mod. bugs) of some of the debugging
+# code (especially KEEP_BACK_PTRS). Makes -DSHORT_DBG_HDRS possible.
+# Assumes that all client allocation is done through debugging
+# allocators.
+# -DSHORT_DBG_HDRS Assume that all objects have debug headers. Shorten
+# the headers to minimize object size, at the expense of checking for
+# writes past the end of an object. This is intended for environments
+# in which most client code is written in a "safe" language, such as
+# Scheme or Java. Assumes that all client allocation is done using
+# the GC_debug_ functions, or through the macros that expand to these,
+# or by redirecting malloc to GC_debug_malloc_replacement.
+# (Also eliminates the field for the requested object size.)
+# occasionally be useful for debugging of client code. Slows down the
+# collector somewhat, but not drastically.
+# -DSAVE_CALL_COUNT=<n> Set the number of call frames saved with objects
+# allocated through the debugging interface. Affects the amount of
+# information generated in leak reports. Only matters on platforms
+# on which we can quickly generate call stacks, currently Linux/(X86 & SPARC)
+# and Solaris/SPARC and platforms that provide execinfo.h.
+# Default is zero. On X86, client
+# code should NOT be compiled with -fomit-frame-pointer.
+# -DSAVE_CALL_NARGS=<n> Set the number of functions arguments to be
+# saved with each call frame. Default is zero. Ignored if we
+# don't know how to retrieve arguments on the platform.
+# -DCHECKSUMS reports on erroneously clear dirty bits, and unexpectedly
+# altered stubborn objects, at substantial performance cost.
+# Use only for debugging of the incremental collector.
+# -DGC_GCJ_SUPPORT includes support for gcj (and possibly other systems
+# that include a pointer to a type descriptor in each allocated object).
+# Building this way requires an ANSI C compiler.
+# -DUSE_I686_PREFETCH causes the collector to issue Pentium III style
+# prefetch instructions. No effect except on X86 Linux platforms.
+# Assumes a very recent gcc-compatible compiler and assembler.
+# (Gas prefetcht0 support was added around May 1999.)
+# Empirically the code appears to still run correctly on Pentium II
+# processors, though with no performance benefit. May not run on other
+# X86 processors? In some cases this improves performance by
+# 15% or so.
+# -DUSE_3DNOW_PREFETCH causes the collector to issue AMD 3DNow style
+# prefetch instructions. Same restrictions as USE_I686_PREFETCH.
+# Minimally tested. Didn't appear to be an obvious win on a K6-2/500.
+# -DUSE_PPC_PREFETCH causes the collector to issue PowerPC style
+# prefetch instructions. No effect except on PowerPC OS X platforms.
+# Performance impact untested.
+# -DGC_USE_LD_WRAP in combination with the old flags listed in README.linux
+# causes the collector some system and pthread calls in a more transparent
+# fashion than the usual macro-based approach. Requires GNU ld, and
+# currently probably works only with Linux.
+# -DGC_USE_DLOPEN_WRAP causes the collector to redefine malloc and intercepted
+# pthread routines with their real names, and causes it to use dlopen
+# and dlsym to refer to the original versions. This makes it possible to
+# build an LD_PRELOADable malloc replacement library.
+# -DTHREAD_LOCAL_ALLOC defines GC_malloc(), GC_malloc_atomic()
+# and GC_gcj_malloc() to use a per-thread set of free-lists.
+# These then allocate in a way that usually does not involve
+# acquisition of a global lock. Currently supported only on platforms
+# such as Linux that use pthread_support.c. Recommended for multiprocessors.
+# Requires explicit GC_INIT() call, unless REDIRECT_MALLOC is
+# defined and GC_malloc is used first.
+# -DUSE_COMPILER_TLS causes thread local allocation to use compiler-supported
+# "__thread" thread-local variables. This is the default in HP/UX. It
+# may help performance on recent Linux installations. (It failed for
+# me on RedHat 8, but appears to work on RedHat 9.)
+# -DPARALLEL_MARK allows the marker to run in multiple threads. Recommended
+# for multiprocessors. Currently requires Linux on X86 or IA64, though
+# support for other Posix platforms should be fairly easy to add,
+# if the thread implementation is otherwise supported.
+# -DNO_GETENV prevents the collector from looking at environment variables.
+# These may otherwise alter its configuration, or turn off GC altogether.
+# I don't know of a reason to disable this, except possibly if the
+# resulting process runs as a privileged user?
+# -DUSE_GLOBAL_ALLOC. Win32 only. Use GlobalAlloc instead of
+# VirtualAlloc to allocate the heap. May be needed to work around
+# a Windows NT/2000 issue. Incompatible with USE_MUNMAP.
+# See README.win32 for details.
+# -DMAKE_BACK_GRAPH. Enable GC_PRINT_BACK_HEIGHT environment variable.
+# See README.environment for details. Experimental. Limited platform
+# support. Implies DBG_HDRS_ALL. All allocation should be done using
+# the debug interface.
+# -DSTUBBORN_ALLOC allows allocation of "hard to change" objects, and thus
+# makes incremental collection easier. Was enabled by default until 6.0.
+# Rarely used, to my knowledge.
+# -DHANDLE_FORK attempts to make GC_malloc() work in a child process fork()ed
+# from a multithreaded parent. Currently only supported by pthread_support.c.
+# (Similar code should work on Solaris or Irix, but it hasn't been tried.)
+# -DTEST_WITH_SYSTEM_MALLOC causes gctest to allocate (and leak) large chunks
+# of memory with the standard system malloc. This will cause the root
+# set and collected heap to grow significantly if malloced memory is
+# somehow getting traced by the collector. This has no impact on the
+# generated library; it only affects the test.
+# -DNO_INCREMENTAL cases the gctest program to not invoke the incremental
+# collector. This has no impact on the generated library, only on the
+# test program. (This is often useful for debugging failures unrelated
+# to incremental GC.)
+# -DPOINTER_MASK=0x... causes candidate pointers to be ANDed with the
+# given mask before being considered. If either this or the following
+# macro is defined, it will be assumed that all pointers stored in
+# the heap need to be processed this way. Stack and register pointers
+# will be considered both with and without processing.
+# These macros are normally needed only to support systems that use
+# high-order pointer tags. EXPERIMENTAL.
+# -DPOINTER_SHIFT=n causes the collector to left shift candidate pointers
+# by the indicated amount before trying to interpret them. Applied
+# after POINTER_MASK. EXPERIMENTAL. See also the preceding macro.
+# -DENABLE_TRACE enables the GC_TRACE=addr environment setting to do its
+# job. By default this is not supported in order to keep the marker as fast
+# as possible.
+# -DDARWIN_DONT_PARSE_STACK Causes the Darwin port to discover thread
+# stack bounds in the same way as other pthread ports, without trying to
+# walk the frames onthe stack. This is recommended only as a fallback
+# for applications that don't support proper stack unwinding.
+# -DUSE_PROC_FOR_LIBRARIES Causes the Linux collector to treat writable
+# memory mappings (as reported by /proc) as roots, if it doesn't have
+# otherinformation about them. It no longer traverses dynamic loader
+# data structures to find dynamic library static data. This may be
+# required for applications that store pointers in mmapped segments without
+# informaing the collector. But it typically performs poorly, especially
+# since it will scan inactive but cached NPTL thread stacks completely.
+#
+
+CXXFLAGS= $(CFLAGS)
+AR= ar
+RANLIB= ranlib
+
+
+OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o \
+ headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o \
+ malloc.o stubborn.o checksums.o pthread_support.o pthread_stop_world.o \
+ darwin_stop_world.o typd_mlc.o ptr_chck.o mallocx.o gcj_mlc.o specific.o \
+ gc_dlopen.o backgraph.o win32_threads.o thread_local_alloc.o
+
+CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c \
+ headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c \
+ new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c \
+ checksums.c pthread_support.c pthread_stop_world.c darwin_stop_world.c \
+ typd_mlc.c ptr_chck.c mallocx.c gcj_mlc.c specific.c gc_dlopen.c \
+ backgraph.c win32_threads.c thread_local_alloc.c
+
+CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c include/cord.h include/ec.h include/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC
+
+CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o
+
+SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.S \
+ sparc_mach_dep.S include/gc.h include/gc_typed.h include/gc_tiny_fl.h \
+ include/private/gc_hdrs.h include/private/gc_priv.h \
+ include/private/gcconfig.h include/private/gc_pmark.h \
+ include/gc_inline.h include/gc_mark.h \
+ threadlibs.c if_mach.c if_not_there.c gc_cpp.cc include/gc_cpp.h \
+ gcname.c include/weakpointer.h include/private/gc_locks.h \
+ mips_ultrix_mach_dep.s \
+ include/new_gc_alloc.h include/gc_allocator.h \
+ include/javaxfc.h sparc_sunos4_mach_dep.s sparc_netbsd_mach_dep.s \
+ include/gc_backptr.h \
+ hpux_test_and_clear.s include/gc_gcj.h \
+ include/private/dbg_mlc.h \
+ include/private/specific.h \
+ include/leak_detector.h include/gc_amiga_redirects.h \
+ include/gc_pthread_redirects.h ia64_save_regs_in_stack.s \
+ include/gc_config_macros.h include/private/pthread_support.h \
+ include/private/pthread_stop_world.h include/private/darwin_semaphore.h \
+ include/private/darwin_stop_world.h include/private/thread_local_alloc.h \
+ $(CORD_SRCS)
+
+DOC_FILES= README.QUICK doc/README.Mac doc/README.MacOSX doc/README.OS2 \
+ doc/README.amiga doc/README.cords doc/debugging.html \
+ doc/porting.html doc/overview.html \
+ doc/README.dj doc/README.hp doc/README.linux doc/README.rs6000 \
+ doc/README.sgi doc/README.solaris2 doc/README.uts \
+ doc/README.win32 doc/barrett_diagram doc/README \
+ doc/README.contributors doc/README.changes doc/gc.man \
+ doc/README.environment doc/tree.html doc/gcdescr.html \
+ doc/README.autoconf doc/README.macros doc/README.ews4800 \
+ doc/README.DGUX386 doc/README.arm.cross doc/leak.html \
+ doc/scale.html doc/gcinterface.html doc/README.darwin \
+ doc/simple_example.html doc/README.win64
+
+TESTS= tests/test.c tests/test_cpp.cc tests/trace_test.c \
+ tests/leak_test.c tests/thread_leak_test.c tests/middle.c
+
+GNU_BUILD_FILES= configure.ac Makefile.am configure acinclude.m4 \
+ libtool.m4 install-sh configure.host Makefile.in \
+ aclocal.m4 config.sub config.guess \
+ include/include.am doc/doc.am \
+ ltmain.sh mkinstalldirs depcomp missing \
+ cord/cord.am tests/tests.am autogen.sh \
+ bdw-gc.pc.in compile
+
+OTHER_MAKEFILES= OS2_MAKEFILE NT_MAKEFILE NT_THREADS_MAKEFILE gc.mak \
+ BCC_MAKEFILE EMX_MAKEFILE WCC_MAKEFILE Makefile.dj \
+ PCR-Makefile SMakefile.amiga Makefile.DLLs \
+ digimars.mak Makefile.direct NT_STATIC_THREADS_MAKEFILE \
+ NT_X64_STATIC_THREADS_MAKEFILE configure_atomic_ops.sh
+# Makefile and Makefile.direct are copies of each other.
+
+OTHER_FILES= Makefile setjmp_t.c callprocs \
+ MacProjects.sit.hqx MacOS.c \
+ Mac_files/datastart.c Mac_files/dataend.c \
+ Mac_files/MacOS_config.h Mac_files/MacOS_Test_config.h \
+ add_gc_prefix.c gc_cpp.cpp \
+ version.h AmigaOS.c mscvc_dbg.c include/private/msvc_dbg.h \
+ $(TESTS) $(GNU_BUILD_FILES) $(OTHER_MAKEFILES)
+
+CORD_INCLUDE_FILES= $(srcdir)/include/gc.h $(srcdir)/include/cord.h \
+ $(srcdir)/include/ec.h $(srcdir)/include/private/cord_pos.h
+
+UTILS= if_mach if_not_there threadlibs
+
+# Libraries needed for curses applications. Only needed for de.
+CURSES= -lcurses -ltermlib
+
+# The following is irrelevant on most systems. But a few
+# versions of make otherwise fork the shell specified in
+# the SHELL environment variable.
+SHELL= /bin/sh
+
+SPECIALCFLAGS = -I$(srcdir)/include -I$(AO_INSTALL_DIR)/include
+# Alternative flags to the C compiler for mach_dep.c.
+# Mach_dep.c often doesn't like optimization, and it's
+# not time-critical anyway.
+# Set SPECIALCFLAGS to -q nodirect_code on Encore.
+
+all: gc.a gctest
+
+# if AO_INSTALL_DIR doesn't exist, we assume that it is pointing to
+# the default location, and we need to build
+$(AO_INSTALL_DIR):
+ CC=$(CC) $(srcdir)/configure_atomic_ops.sh
+ cd $(AO_SRC_DIR); make CC=$(CC) install
+
+LEAKFLAGS=$(CFLAGS) -DFIND_LEAK
+
+BSD-pkg-all: bsd-libgc.a bsd-libleak.a
+
+bsd-libgc.a:
+ $(MAKE) CFLAGS="$(CFLAGS)" clean c++-t
+ mv gc.a bsd-libgc.a
+
+bsd-libleak.a:
+ $(MAKE) -f Makefile.direct CFLAGS="$(LEAKFLAGS)" clean c++-nt
+ mv gc.a bsd-libleak.a
+
+BSD-pkg-install: BSD-pkg-all
+ ${CP} bsd-libgc.a libgc.a
+ ${INSTALL_DATA} libgc.a ${PREFIX}/lib
+ ${INSTALL_DATA} gc.h gc_cpp.h ${PREFIX}/include
+ ${INSTALL_MAN} doc/gc.man ${PREFIX}/man/man3/gc.3
+
+pcr: PCR-Makefile include/private/gc_private.h include/private/gc_hdrs.h \
+include/private/gc_locks.h include/gc.h include/private/gcconfig.h \
+mach_dep.o $(SRCS)
+ $(MAKE) -f PCR-Makefile depend
+ $(MAKE) -f PCR-Makefile
+
+$(OBJS) tests/test.o dyn_load.o dyn_load_sunos53.o: \
+ $(srcdir)/include/private/gc_priv.h \
+ $(srcdir)/include/private/gc_hdrs.h $(srcdir)/include/private/gc_locks.h \
+ $(srcdir)/include/gc.h $(srcdir)/include/gc_pthread_redirects.h \
+ $(srcdir)/include/private/gcconfig.h $(srcdir)/include/gc_typed.h \
+ $(srcdir)/include/gc_config_macros.h Makefile $(AO_INSTALL_DIR)
+# The dependency on Makefile is needed. Changing
+# options affects the size of GC_arrays,
+# invalidating all .o files that rely on gc_priv.h
+
+mark.o typd_mlc.o finalize.o ptr_chck.o: $(srcdir)/include/gc_mark.h \
+ $(srcdir)/include/private/gc_pmark.h
+
+specific.o pthread_support.o thread_local_alloc.o win32_threads.o: \
+ $(srcdir)/include/private/specific.h $(srcdir)/include/gc_inline.h \
+ $(srcdir)/include/private/thread_local_alloc.h
+
+dbg_mlc.o gcj_mlc.o: $(srcdir)/include/private/dbg_mlc.h
+
+tests/test.o: tests $(srcdir)/tests/test.c
+ $(CC) $(CFLAGS) -c $(srcdir)/tests/test.c
+ mv test.o tests/test.o
+
+tests:
+ mkdir tests
+
+base_lib gc.a: $(OBJS) dyn_load.o $(UTILS)
+ echo > base_lib
+ rm -f dont_ar_1
+ cp $(AO_INSTALL_DIR)/lib/libatomic_ops.a gc.a
+ ./if_mach SPARC SOLARIS touch dont_ar_1
+ ./if_mach SPARC SOLARIS $(AR) rus gc.a $(OBJS) dyn_load.o
+ ./if_mach M68K AMIGA touch dont_ar_1
+ ./if_mach M68K AMIGA $(AR) -vrus gc.a $(OBJS) dyn_load.o
+ ./if_not_there dont_ar_1 $(AR) ru gc.a $(OBJS) dyn_load.o
+ ./if_not_there dont_ar_1 $(RANLIB) gc.a || cat /dev/null
+# ignore ranlib failure; that usually means it doesn't exist, and isn't needed
+
+cords: $(CORD_OBJS) cord/cordtest $(UTILS)
+ rm -f dont_ar_3
+ ./if_mach SPARC SOLARIS touch dont_ar_3
+ ./if_mach SPARC SOLARIS $(AR) rus gc.a $(CORD_OBJS)
+ ./if_mach M68K AMIGA touch dont_ar_3
+ ./if_mach M68K AMIGA $(AR) -vrus gc.a $(CORD_OBJS)
+ ./if_not_there dont_ar_3 $(AR) ru gc.a $(CORD_OBJS)
+ ./if_not_there dont_ar_3 $(RANLIB) gc.a || cat /dev/null
+
+gc_cpp.o: $(srcdir)/gc_cpp.cc $(srcdir)/include/gc_cpp.h $(srcdir)/include/gc.h Makefile
+ $(CXX) -c $(CXXFLAGS) $(srcdir)/gc_cpp.cc
+
+test_cpp: $(srcdir)/tests/test_cpp.cc $(srcdir)/include/gc_cpp.h gc_cpp.o $(srcdir)/include/gc.h \
+base_lib $(UTILS)
+ rm -f test_cpp
+ ./if_mach HP_PA HPUX $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/tests/test_cpp.cc gc_cpp.o gc.a -ldld `./threadlibs`
+ ./if_not_there test_cpp $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/tests/test_cpp.cc gc_cpp.o gc.a `./threadlibs`
+
+c++-t: c++
+ ./test_cpp 1
+
+c++-nt: c++
+ @echo "Use ./test_cpp 1 to test the leak library"
+
+c++: gc_cpp.o $(srcdir)/include/gc_cpp.h test_cpp
+ rm -f dont_ar_4
+ ./if_mach SPARC SOLARIS touch dont_ar_4
+ ./if_mach SPARC SOLARIS $(AR) rus gc.a gc_cpp.o
+ ./if_mach M68K AMIGA touch dont_ar_4
+ ./if_mach M68K AMIGA $(AR) -vrus gc.a gc_cpp.o
+ ./if_not_there dont_ar_4 $(AR) ru gc.a gc_cpp.o
+ ./if_not_there dont_ar_4 $(RANLIB) gc.a || cat /dev/null
+ ./test_cpp 1
+ echo > c++
+
+dyn_load_sunos53.o: dyn_load.c
+ $(CC) $(CFLAGS) -DSUNOS53_SHARED_LIB -c $(srcdir)/dyn_load.c -o $@
+
+# SunOS5 shared library version of the collector
+sunos5gc.so: $(OBJS) dyn_load_sunos53.o
+ $(CC) -G -o sunos5gc.so $(OBJS) dyn_load_sunos53.o $(AO_INSTALL_DIR)/lib/libatomic_ops.a -ldl
+ ln sunos5gc.so libgc.so
+
+# Alpha/OSF shared library version of the collector
+libalphagc.so: $(OBJS)
+ ld -shared -o libalphagc.so $(OBJS) dyn_load.o -lc
+ ln libalphagc.so libgc.so
+
+# IRIX shared library version of the collector
+libirixgc.so: $(OBJS) dyn_load.o
+ ld -shared $(ABI_FLAG) -o libirixgc.so $(OBJS) dyn_load.o -lc
+ ln libirixgc.so libgc.so
+
+# Linux shared library version of the collector
+liblinuxgc.so: $(OBJS) dyn_load.o
+ gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o
+ ln liblinuxgc.so libgc.so
+
+# Build gctest with dynamic library
+dyn_test:
+ $(CC) $(CFLAGS) -o gctest tests/test.c libgc.so `./threadlibs`
+ ./gctest
+
+# Alternative Linux rule. This is preferable, but is likely to break the
+# Makefile for some non-linux platforms.
+# LIBOBJS= $(patsubst %.o, %.lo, $(OBJS))
+#
+#.SUFFIXES: .lo $(SUFFIXES)
+#
+#.c.lo:
+# $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c $< -o $@
+#
+# liblinuxgc.so: $(LIBOBJS) dyn_load.lo
+# gcc -shared -Wl,-soname=libgc.so.0 -o libgc.so.0 $(LIBOBJS) dyn_load.lo
+# touch liblinuxgc.so
+
+mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_sgi_mach_dep.s \
+ $(srcdir)/mips_ultrix_mach_dep.s \
+ $(srcdir)/rs6000_mach_dep.s \
+ $(srcdir)/sparc_mach_dep.S $(srcdir)/sparc_sunos4_mach_dep.s \
+ $(srcdir)/ia64_save_regs_in_stack.s \
+ $(srcdir)/sparc_netbsd_mach_dep.s $(UTILS)
+ rm -f mach_dep.o
+ ./if_mach SPARC SOLARIS $(CC) -c -o mach_dep2.o $(srcdir)/sparc_mach_dep.S
+ ./if_mach SPARC OPENBSD $(AS) -o mach_dep2.o $(srcdir)/sparc_sunos4_mach_dep.s
+ ./if_mach SPARC NETBSD $(AS) -o mach_dep2.o $(srcdir)/sparc_netbsd_mach_dep.s
+ ./if_mach SPARC "" $(CC) -c -o mach_dep1.o $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+ ./if_mach SPARC "" ld -r -o mach_dep.o mach_dep1.o mach_dep2.o
+ ./if_mach IA64 "" as $(AS_ABI_FLAG) -o ia64_save_regs_in_stack.o $(srcdir)/ia64_save_regs_in_stack.s
+ ./if_mach IA64 "" $(CC) -c -o mach_dep1.o $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+ ./if_mach IA64 "" ld -r -o mach_dep.o mach_dep1.o ia64_save_regs_in_stack.o
+ ./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+
+mark_rts.o: $(srcdir)/mark_rts.c $(UTILS)
+ rm -f mark_rts.o
+ -./if_mach ALPHA OSF1 $(CC) -c $(CFLAGS) -Wo,-notail $(srcdir)/mark_rts.c
+ ./if_not_there mark_rts.o $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c
+# Work-around for DEC optimizer tail recursion elimination bug.
+# The ALPHA-specific line should be removed if gcc is used.
+
+alloc.o: version.h
+
+cord:
+ mkdir cord
+
+cord/cordbscs.o: cord $(srcdir)/cord/cordbscs.c $(CORD_INCLUDE_FILES)
+ $(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordbscs.c
+ mv cordbscs.o cord/cordbscs.o
+# not all compilers understand -o filename
+
+cord/cordxtra.o: cord $(srcdir)/cord/cordxtra.c $(CORD_INCLUDE_FILES)
+ $(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordxtra.c
+ mv cordxtra.o cord/cordxtra.o
+
+cord/cordprnt.o: cord $(srcdir)/cord/cordprnt.c $(CORD_INCLUDE_FILES)
+ $(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordprnt.c
+ mv cordprnt.o cord/cordprnt.o
+
+cord/cordtest: $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a $(UTILS)
+ rm -f cord/cordtest
+ ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a -lucb
+ ./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a -ldld `./threadlibs`
+ ./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a `./threadlibs`
+ ./if_not_there cord/cordtest $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a `./threadlibs`
+
+cord/de: $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(UTILS)
+ rm -f cord/de
+ ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -lucb `./threadlibs`
+ ./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -ldld `./threadlibs`
+ ./if_mach POWERPC AIX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses
+ ./if_mach POWERPC DARWIN $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a
+ ./if_mach I386 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs`
+ ./if_mach ALPHA LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs`
+ ./if_mach IA64 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs`
+ ./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses
+ ./if_not_there cord/de $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) `./threadlibs`
+
+if_mach: $(srcdir)/if_mach.c $(srcdir)/include/private/gcconfig.h
+ $(HOSTCC) $(HOSTCFLAGS) -o if_mach $(srcdir)/if_mach.c
+
+threadlibs: $(srcdir)/threadlibs.c $(srcdir)/include/private/gcconfig.h Makefile
+ $(HOSTCC) $(HOSTCFLAGS) -o threadlibs $(srcdir)/threadlibs.c
+
+if_not_there: $(srcdir)/if_not_there.c
+ $(HOSTCC) $(HOSTCFLAGS) -o if_not_there $(srcdir)/if_not_there.c
+
+clean:
+ rm -f gc.a *.o *.exe tests/*.o gctest gctest_dyn_link test_cpp \
+ setjmp_test mon.out gmon.out a.out core if_not_there if_mach \
+ threadlibs $(CORD_OBJS) cord/cordtest cord/de
+ -rm -f *~
+
+gctest: tests/test.o gc.a $(UTILS)
+ rm -f gctest
+ ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o gctest tests/test.o gc.a -lucb
+ ./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o gctest tests/test.o gc.a -ldld `./threadlibs`
+ ./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o gctest tests/test.o gc.a `./threadlibs`
+ ./if_not_there gctest $(CC) $(CFLAGS) -o gctest tests/test.o gc.a `./threadlibs`
+
+# If an optimized setjmp_test generates a segmentation fault,
+# odds are your compiler is broken. Gctest may still work.
+# Try compiling setjmp_t.c unoptimized.
+setjmp_test: $(srcdir)/setjmp_t.c $(srcdir)/include/gc.h $(UTILS) $(AO_INSTALL_DIR)
+ $(CC) $(CFLAGS) -o setjmp_test $(srcdir)/setjmp_t.c
+
+test: KandRtest cord/cordtest
+ cord/cordtest
+
+# Those tests that work even with a K&R C compiler:
+KandRtest: setjmp_test gctest
+ ./setjmp_test
+ ./gctest
+
+add_gc_prefix: $(srcdir)/add_gc_prefix.c $(srcdir)/version.h
+ $(CC) -o add_gc_prefix $(srcdir)/add_gc_prefix.c
+
+gcname: $(srcdir)/gcname.c $(srcdir)/version.h
+ $(CC) -o gcname $(srcdir)/gcname.c
+
+#We assume this is being done from source directory.
+dist gc.tar: $(SRCS) $(DOC_FILES) $(OTHER_FILES) add_gc_prefix gcname
+ cp Makefile Makefile.old
+ cp Makefile.direct Makefile
+ CC=$(CC) ./configure_atomic_ops.sh
+ cd $(AO_SRC_DIR); make dist
+ if test $(srcdir)/libatomic_ops-$(AO_VERSION) = $(AO_SRC_DIR); \
+ then \
+ mv $(AO_SRC_DIR) $(AO_SRC_DIR).bak ; \
+ tar xvfz $(AO_SRC_DIR).bak/libatomic_ops-$(AO_VERSION).tar.gz ; \
+ else \
+ tar xvfz $(AO_SRC_DIR)/libatomic_ops-$(AO_VERSION).tar.gz ; \
+ fi
+ rm -f `./gcname`
+ ln -s . `./gcname`
+ ./add_gc_prefix $(SRCS) $(DOC_FILES) $(OTHER_FILES) libatomic_ops-$(AO_VERSION) > /tmp/gc.tar-files
+ tar cvfh gc.tar `cat /tmp/gc.tar-files`
+ cp gc.tar `./gcname`.tar
+ gzip `./gcname`.tar
+ rm `./gcname`
+
+gc.tar.Z: gc.tar
+ compress gc.tar
+
+gc.tar.gz: gc.tar
+ gzip gc.tar
+
+lint: $(CSRCS) tests/test.c
+ lint -DLINT $(CSRCS) tests/test.c | egrep -v "possible pointer alignment problem|abort|exit|sbrk|mprotect|syscall|change in ANSI|improper alignment"
+
+# BTL: added to test shared library version of collector.
+# Currently works only under SunOS5. Requires GC_INIT call from statically
+# loaded client code.
+ABSDIR = `pwd`
+gctest_dyn_link: tests/test.o libgc.so
+ $(CC) -L$(ABSDIR) -R$(ABSDIR) -o gctest_dyn_link tests/test.o -lgc -ldl -lthread
+
+gctest_irix_dyn_link: tests/test.o libirixgc.so
+ $(CC) -L$(ABSDIR) -o gctest_irix_dyn_link tests/test.o -lirixgc
+
+# The following appear to be dead, especially since libgc_globals.h
+# is apparently lost.
+test_dll.o: tests/test.c libgc_globals.h
+ $(CC) $(CFLAGS) -DGC_USE_DLL -c tests/test.c -o test_dll.o
+
+test_dll: test_dll.o libgc_dll.a libgc.dll
+ $(CC) test_dll.o -L$(ABSDIR) -lgc_dll -o test_dll
+
+SYM_PREFIX-libgc=GC
+
+# Uncomment the following line to build a GNU win32 DLL
+# include Makefile.DLLs
+
+reserved_namespace: $(SRCS)
+ for file in $(SRCS) tests/test.c tests/test_cpp.cc; do \
+ sed s/GC_/_GC_/g < $$file > tmp; \
+ cp tmp $$file; \
+ done
+
+user_namespace: $(SRCS)
+ for file in $(SRCS) tests/test.c tests/test_cpp.cc; do \
+ sed s/_GC_/GC_/g < $$file > tmp; \
+ cp tmp $$file; \
+ done
diff --git a/tools/build/v2/engine/boehm_gc/Makefile.dj b/tools/build/v2/engine/boehm_gc/Makefile.dj
new file mode 100644
index 0000000000..4618eb8456
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/Makefile.dj
@@ -0,0 +1,428 @@
+# This Makefile is intended only for DJGPP use.
+# It is mainly a copy of the main Makefile, but tends to get out of sync
+# with it. A merge would probably be appropriate.
+
+# Primary targets:
+# gc.a - builds basic library
+# libgc.a - builds library for use with g++ "-fgc-keyword" extension
+# -fgc-keyword was never really available. Historical
+# interest only.
+# c++ - adds C++ interface to library
+# cords - adds cords (heavyweight strings) to library
+# test - prints porting information, then builds basic version of gc.a,
+# and runs some tests of collector and cords. Does not add cords or
+# c++ interface to gc.a
+# cord/de$(EXE_SUFFIX) - builds dumb editor based on cords.
+ABI_FLAG=
+CC=gcc $(ABI_FLAG)
+CXX=gxx $(ABI_FLAG)
+AS=gcc -c -x assembler-with-cpp $(ABI_FLAG)
+# The above doesn't work with gas, which doesn't run cpp.
+# Define AS as `gcc -c -x assembler-with-cpp' instead.
+# Under Irix 6, you will have to specify the ABI (-o32, -n32, or -64)
+# if you use something other than the default ABI on your machine.
+
+# special defines for DJGPP
+CXXLD=gxx $(ABI_FLAG)
+EXE_SUFFIX=.exe
+
+srcdir= .
+VPATH= $(srcdir)
+
+CFLAGS= -gstabs+ -O2 -I$(srcdir)/include -DATOMIC_UNCOLLECTABLE -DALL_INTERIOR_POINTERS -DNO_EXECUTE_PERMISSION
+
+# Setjmp_test may yield overly optimistic results when compiled
+# without optimization.
+# -DFIND_LEAK causes GC_find_leak to be initially set.
+# This causes the collector to assume that all inaccessible
+# objects should have been explicitly deallocated, and reports exceptions.
+# Finalization and the test program are not usable in this mode.
+# -DALL_INTERIOR_POINTERS allows all pointers to the interior
+# of objects to be recognized. (See gc_priv.h for consequences.)
+# -DSMALL_CONFIG tries to tune the collector for small heap sizes,
+# usually causing it to use less space in such situations.
+# Incremental collection no longer works in this case.
+# -DLARGE_CONFIG tunes the collector for unusually large heaps.
+# Necessary for heaps larger than about 500 MB on most machines.
+# Recommended for heaps larger than about 64 MB.
+# -DDONT_ADD_BYTE_AT_END is meaningful only with
+# -DALL_INTERIOR_POINTERS. Normally -DALL_INTERIOR_POINTERS
+# causes all objects to be padded so that pointers just past the end of
+# an object can be recognized. This can be expensive. (The padding
+# is normally more than one byte due to alignment constraints.)
+# -DDONT_ADD_BYTE_AT_END disables the padding.
+# -DNO_SIGNALS does not disable signals during critical parts of
+# the GC process. This is no less correct than many malloc
+# implementations, and it sometimes has a significant performance
+# impact. However, it is dangerous for many not-quite-ANSI C
+# programs that call things like printf in asynchronous signal handlers.
+# This is on by default. Turning it off has not been extensively tested with
+# compilers that reorder stores. It should have been.
+# -DNO_EXECUTE_PERMISSION may cause some or all of the heap to not
+# have execute permission, i.e. it may be impossible to execute
+# code from the heap. Currently this only affects the incremental
+# collector on UNIX machines. It may greatly improve its performance,
+# since this may avoid some expensive cache synchronization.
+# -DGC_NO_OPERATOR_NEW_ARRAY declares that the C++ compiler does not support
+# the new syntax "operator new[]" for allocating and deleting arrays.
+# See gc_cpp.h for details. No effect on the C part of the collector.
+# This is defined implicitly in a few environments. Must also be defined
+# by clients that use gc_cpp.h.
+# -DREDIRECT_MALLOC=X causes malloc, realloc, and free to be defined
+# as aliases for X, GC_realloc, and GC_free, respectively.
+# Calloc is redefined in terms of the new malloc. X should
+# be either GC_malloc or GC_malloc_uncollectable.
+# The former is occasionally useful for working around leaks in code
+# you don't want to (or can't) look at. It may not work for
+# existing code, but it often does. Neither works on all platforms,
+# since some ports use malloc or calloc to obtain system memory.
+# (Probably works for UNIX, and win32.)
+# -DIGNORE_FREE turns calls to free into a noop. Only useful with
+# -DREDIRECT_MALLOC.
+# -DNO_DEBUGGING removes GC_dump and the debugging routines it calls.
+# Reduces code size slightly at the expense of debuggability.
+# -DJAVA_FINALIZATION makes it somewhat safer to finalize objects out of
+# order by specifying a nonstandard finalization mark procedure (see
+# finalize.c). Objects reachable from finalizable objects will be marked
+# in a sepearte postpass, and hence their memory won't be reclaimed.
+# Not recommended unless you are implementing a language that specifies
+# these semantics. Since 5.0, determines only only the initial value
+# of GC_java_finalization variable.
+# -DFINALIZE_ON_DEMAND causes finalizers to be run only in response
+# to explicit GC_invoke_finalizers() calls.
+# In 5.0 this became runtime adjustable, and this only determines the
+# initial value of GC_finalize_on_demand.
+# -DATOMIC_UNCOLLECTABLE includes code for GC_malloc_atomic_uncollectable.
+# This is useful if either the vendor malloc implementation is poor,
+# or if REDIRECT_MALLOC is used.
+# -DHBLKSIZE=ddd, where ddd is a power of 2 between 512 and 16384, explicitly
+# sets the heap block size. Each heap block is devoted to a single size and
+# kind of object. For the incremental collector it makes sense to match
+# the most likely page size. Otherwise large values result in more
+# fragmentation, but generally better performance for large heaps.
+# -DPRINT_BLACK_LIST Whenever a black list entry is added, i.e. whenever
+# the garbage collector detects a value that looks almost, but not quite,
+# like a pointer, print both the address containing the value, and the
+# value of the near-bogus-pointer. Can be used to identifiy regions of
+# memory that are likely to contribute misidentified pointers.
+# -DKEEP_BACK_PTRS Add code to save back pointers in debugging headers
+# for objects allocated with the debugging allocator. If all objects
+# through GC_MALLOC with GC_DEBUG defined, this allows the client
+# to determine how particular or randomly chosen objects are reachable
+# for debugging/profiling purposes. The gc_backptr.h interface is
+# implemented only if this is defined.
+# -DGC_ASSERTIONS Enable some internal GC assertion checking. Currently
+# this facility is only used in a few places. It is intended primarily
+# for debugging of the garbage collector itself, but could also
+# -DDBG_HDRS_ALL Make sure that all objects have debug headers. Increases
+# the reliability (from 99.9999% to 100%) of some of the debugging
+# code (especially KEEP_BACK_PTRS). Makes -DSHORT_DBG_HDRS possible.
+# Assumes that all client allocation is done through debugging
+# allocators.
+# -DSHORT_DBG_HDRS Assume that all objects have debug headers. Shorten
+# the headers to minimize object size, at the expense of checking for
+# writes past the end of an object. This is intended for environments
+# in which most client code is written in a "safe" language, such as
+# Scheme or Java. Assumes that all client allocation is done using
+# the GC_debug_ functions (or through the macros that expand to these.
+# (Also eliminates the field for the requested object size.)
+# occasionally be useful for debugging of client code. Slows down the
+# collector somewhat, but not drastically.
+# -DCHECKSUMS reports on erroneously clear dirty bits, and unexpectedly
+# altered stubborn objects, at substantial performance cost.
+# Use only for debugging of the incremental collector.
+# -DGC_GCJ_SUPPORT includes support for gcj (and possibly other systems
+# that include a pointer to a type descriptor in each allocated object).
+# Building this way requires an ANSI C compiler.
+# -DUSE_I686_PREFETCH causes the collector to issue Pentium III style
+# prefetch instructions. No effect except on X86 Linux platforms.
+# Assumes a very recent gcc-compatible compiler and assembler.
+# (Gas prefetcht0 support was added around May 1999.)
+# Empirically the code appears to still run correctly on Pentium II
+# processors, though with no performance benefit. May not run on other
+# X86 processors? In some cases this improves performance by
+# 15% or so.
+# -DUSE_3DNOW_PREFETCH causes the collector to issue AMD 3DNow style
+# prefetch instructions. Same restrictions as USE_I686_PREFETCH.
+# UNTESTED!!
+# -DGC_USE_LD_WRAP in combination with the gld flags listed in README.linux
+# causes the collector some system and pthread calls in a more transparent
+# fashion than the usual macro-based approach. Requires GNU ld, and
+# currently probably works only with Linux.
+
+
+CXXFLAGS= $(CFLAGS) -DGC_OPERATOR_NEW_ARRAY
+AR= ar
+RANLIB= ranlib
+
+
+OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.o gcj_mlc.o specific.o
+
+CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c
+
+CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c include/cord.h include/ec.h include/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC cord/SCOPTIONS.amiga cord/SMakefile.amiga
+
+CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o
+
+SRCS= $(CSRCS) mips_sgi_mach_dep.S rs6000_mach_dep.s alpha_mach_dep.S \
+ sparc_mach_dep.S include/gc.h include/gc_typed.h \
+ include/private/gc_hdrs.h include/private/gc_priv.h \
+ include/private/gcconfig.h include/private/gc_mark.h \
+ include/gc_inline.h gc.man \
+ threadlibs.c if_mach.c if_not_there.c gc_cpp.cc include/gc_cpp.h \
+ include/weakpointer.h include/private/gc_locks.h \
+ gcc_support.c mips_ultrix_mach_dep.s include/gc_alloc.h \
+ include/new_gc_alloc.h include/javaxfc.h sparc_sunos4_mach_dep.s \
+ include/private/solaris_threads.h include/gc_backptr.h \
+ hpux_test_and_clear.s include/gc_gcj.h \
+ include/gc_local_alloc.h include/private/dbg_mlc.h \
+ include/private/specific.h \
+ include/leak_detector.h $(CORD_SRCS)
+
+OTHER_FILES= Makefile PCR-Makefile OS2_MAKEFILE NT_MAKEFILE BCC_MAKEFILE \
+ README tests/test.c test_cpp.cc setjmp_t.c SMakefile.amiga \
+ SCoptions.amiga README.amiga README.win32 cord/README \
+ README.rs6000 README.QUICK callprocs pc_excludes \
+ barrett_diagram README.OS2 README.Mac MacProjects.sit.hqx \
+ MacOS.c EMX_MAKEFILE README.debugging \
+ Mac_files/datastart.c Mac_files/dataend.c \
+ Mac_files/MacOS_config.h Mac_files/MacOS_Test_config.h \
+ add_gc_prefix.c README.solaris2 README.sgi README.hp README.uts \
+ win32_threads.c NT_THREADS_MAKEFILE gc.mak README.dj Makefile.dj \
+ README.alpha README.linux README.MacOSX version.h Makefile.DLLs \
+ WCC_MAKEFILE nursery.c include/gc_nursery.h include/gc_copy_descr.h
+
+CORD_INCLUDE_FILES= $(srcdir)/include/gc.h $(srcdir)/include/cord.h \
+ $(srcdir)/include/ec.h $(srcdir)/include/private/cord_pos.h
+
+UTILS= if_mach$(EXE_SUFFIX) if_not_there$(EXE_SUFFIX)
+
+# Libraries needed for curses applications. Only needed for de.
+CURSES= -lcurses -ltermlib
+
+# The following is irrelevant on most systems. But a few
+# versions of make otherwise fork the shell specified in
+# the SHELL environment variable.
+SHELL= /bin/sh
+
+SPECIALCFLAGS = -I$(srcdir)/include
+# Alternative flags to the C compiler for mach_dep.c.
+# Mach_dep.c often doesn't like optimization, and it's
+# not time-critical anyway.
+# Set SPECIALCFLAGS to -q nodirect_code on Encore.
+
+all: gc.a gctest$(EXE_SUFFIX)
+
+$(OBJS) test.o dyn_load.o dyn_load_sunos53.o: \
+ $(srcdir)/include/private/gc_priv.h \
+ $(srcdir)/include/private/gc_hdrs.h $(srcdir)/include/private/gc_locks.h \
+ $(srcdir)/include/gc.h \
+ $(srcdir)/include/private/gcconfig.h $(srcdir)/include/gc_typed.h \
+ Makefile
+# The dependency on Makefile is needed. Changing
+# options affects the size of GC_arrays,
+# invalidating all .o files that rely on gc_priv.h
+
+mark.o typd_mlc.o finalize.o: $(srcdir)/include/gc_mark.h
+
+base_lib gc.a: $(OBJS) dyn_load.o $(UTILS)
+ echo > base_lib
+ rm -f on_sparc_sunos5_1
+ ./if_mach SPARC SOLARIS touch on_sparc_sunos5_1
+ ./if_mach SPARC SOLARIS $(AR) rus gc.a $(OBJS) dyn_load.o
+ ./if_not_there on_sparc_sunos5_1 $(AR) ru gc.a $(OBJS) dyn_load.o
+ -./if_not_there on_sparc_sunos5_1 $(RANLIB) gc.a
+# ignore ranlib failure; that usually means it doesn't exist, and isn't needed
+
+cords: $(CORD_OBJS) cord/cordtest$(EXE_SUFFIX) $(UTILS)
+ rm -f on_sparc_sunos5_3
+ ./if_mach SPARC SOLARIS touch on_sparc_sunos5_3
+ ./if_mach SPARC SOLARIS $(AR) rus gc.a $(CORD_OBJS)
+ ./if_not_there on_sparc_sunos5_3 $(AR) ru gc.a $(CORD_OBJS)
+ -./if_not_there on_sparc_sunos5_3 $(RANLIB) gc.a
+
+gc_cpp.o: $(srcdir)/gc_cpp.cc $(srcdir)/include/gc_cpp.h $(srcdir)/include/gc.h Makefile
+ $(CXX) -c $(CXXFLAGS) $(srcdir)/gc_cpp.cc
+
+test_cpp$(EXE_SUFFIX): $(srcdir)/test_cpp.cc $(srcdir)/include/gc_cpp.h gc_cpp.o $(srcdir)/include/gc.h \
+base_lib $(UTILS)
+ rm -f test_cpp test_cpp$(EXE_SUFFIX)
+ ./if_mach HP_PA "" $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/test_cpp.cc gc_cpp.o gc.a -ldld
+ ./if_not_there test_cpp$(EXE_SUFFIX) $(CXXLD) $(CXXFLAGS) -o test_cpp$(EXE_SUFFIX) $(srcdir)/test_cpp.cc gc_cpp.o gc.a
+ rm -f test_cpp
+
+c++: gc_cpp.o $(srcdir)/include/gc_cpp.h test_cpp$(EXE_SUFFIX)
+ rm -f on_sparc_sunos5_4
+ ./if_mach SPARC SOLARIS touch on_sparc_sunos5_4
+ ./if_mach SPARC SOLARIS $(AR) rus gc.a gc_cpp.o
+ ./if_not_there on_sparc_sunos5_4 $(AR) ru gc.a gc_cpp.o
+ -./if_not_there on_sparc_sunos5_4 $(RANLIB) gc.a
+ ./test_cpp$(EXE_SUFFIX) 1
+ echo > c++
+
+dyn_load_sunos53.o: dyn_load.c
+ $(CC) $(CFLAGS) -DSUNOS53_SHARED_LIB -c $(srcdir)/dyn_load.c -o $@
+
+# SunOS5 shared library version of the collector
+sunos5gc.so: $(OBJS) dyn_load_sunos53.o
+ $(CC) -G -o sunos5gc.so $(OBJS) dyn_load_sunos53.o -ldl
+ ln sunos5gc.so libgc.so
+
+# Alpha/OSF shared library version of the collector
+libalphagc.so: $(OBJS)
+ ld -shared -o libalphagc.so $(OBJS) dyn_load.o -lc
+ ln libalphagc.so libgc.so
+
+# IRIX shared library version of the collector
+libirixgc.so: $(OBJS) dyn_load.o
+ ld -shared $(ABI_FLAG) -o libirixgc.so $(OBJS) dyn_load.o -lc
+ ln libirixgc.so libgc.so
+
+# Linux shared library version of the collector
+liblinuxgc.so: $(OBJS) dyn_load.o
+ gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o -lo
+ ln liblinuxgc.so libgc.so
+
+mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_sgi_mach_dep.S $(srcdir)/mips_ultrix_mach_dep.s \
+ $(srcdir)/rs6000_mach_dep.s $(UTILS)
+ rm -f mach_dep.o
+ ./if_mach MIPS IRIX5 $(AS) -o mach_dep.o $(srcdir)/mips_sgi_mach_dep.S
+ ./if_mach MIPS RISCOS $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s
+ ./if_mach MIPS ULTRIX $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s
+ ./if_mach POWERPC AIX $(AS) -o mach_dep.o $(srcdir)/rs6000_mach_dep.s
+ ./if_mach ALPHA "" $(AS) -o mach_dep.o $(srcdir)/alpha_mach_dep.S
+ ./if_mach SPARC SOLARIS $(AS) -o mach_dep.o $(srcdir)/sparc_mach_dep.S
+ ./if_mach SPARC SUNOS4 $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s
+ ./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+
+mark_rts.o: $(srcdir)/mark_rts.c if_mach if_not_there $(UTILS)
+ rm -f mark_rts.o
+ -./if_mach ALPHA OSF1 $(CC) -c $(CFLAGS) -Wo,-notail $(srcdir)/mark_rts.c
+ ./if_not_there mark_rts.o $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c
+# Work-around for DEC optimizer tail recursion elimination bug.
+# The ALPHA-specific line should be removed if gcc is used.
+
+alloc.o: version.h
+
+cord/cordbscs.o: $(srcdir)/cord/cordbscs.c $(CORD_INCLUDE_FILES)
+ $(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordbscs.c
+ mv cordbscs.o cord/cordbscs.o
+# not all compilers understand -o filename
+
+cord/cordxtra.o: $(srcdir)/cord/cordxtra.c $(CORD_INCLUDE_FILES)
+ $(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordxtra.c
+ mv cordxtra.o cord/cordxtra.o
+
+cord/cordprnt.o: $(srcdir)/cord/cordprnt.c $(CORD_INCLUDE_FILES)
+ $(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordprnt.c
+ mv cordprnt.o cord/cordprnt.o
+
+cord/cordtest$(EXE_SUFFIX): $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a $(UTILS) /tmp
+ rm -f cord/cordtest$(EXE_SUFFIX)
+ ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/cordtest$(EXE_SUFFIX) $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a -lucb
+ ./if_mach HP_PA "" $(CC) $(CFLAGS) -o cord/cordtest$(EXE_SUFFIX) $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a -ldld
+ ./if_not_there cord/cordtest$(EXE_SUFFIX) $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a
+ rm -f cord/cordtest cordtest
+ -mv cordtest$(EXE_SUFFIX) cord/
+
+/tmp: $(UTILS)
+ ./if_not_there /tmp mkdir /tmp
+
+cord/de$(EXE_SUFFIX): $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(UTILS)
+ rm -f cord/de cord/de$(EXE_SUFFIX)
+ ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -lucb `./threadlibs`
+ ./if_mach HP_PA "" $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -ldld
+ ./if_mach RS6000 "" $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses
+ ./if_mach I386 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs`
+ ./if_mach ALPHA LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses
+ ./if_not_there cord/de$(EXE_SUFFIX) $(CC) $(CFLAGS) -o cord/de$(EXE_SUFFIX) $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES)
+
+if_mach$(EXE_SUFFIX): $(srcdir)/if_mach.c $(srcdir)/include/private/gcconfig.h
+ rm -f if_mach if_mach$(EXE_SUFFIX)
+ $(CC) $(CFLAGS) -o if_mach $(srcdir)/if_mach.c
+
+threadlibs$(EXE_SUFFIX): $(srcdir)/threadlibs.c $(srcdir)include/private/gcconfig.h Makefile
+ rm -f threadlibs threadlibs$(EXE_SUFFIX)
+ $(CC) $(CFLAGS) -o threadlibs $(srcdir)/threadlibs.c
+
+if_not_there$(EXE_SUFFIX): $(srcdir)/if_not_there.c
+ rm -f if_not_there if_not_there$(EXE_SUFFIX)
+ $(CC) $(CFLAGS) -o if_not_there $(srcdir)/if_not_there.c
+
+# Clean removes *.o several times,
+# because as the first one doesn't seem to get them all!
+clean:
+ rm -f gc.a *.o
+ rm -f *.o
+ rm -f *.o
+ rm -f cord/*.o
+ rm -f gctest gctest_dyn_link test_cpp
+ rm -f setjmp_test mon.out gmon.out a.out core if_not_there if_mach
+ rm -f threadlibs $(CORD_OBJS) cordtest cord/cordtest de cord/de
+ rm -f gctest$(EXE_SUFFIX) gctest_dyn_link$(EXE_SUFFIX) test_cpp$(EXE_SUFFIX)
+ rm -f setjmp_test$(EXE_SUFFIX) if_not_there$(EXE_SUFFIX) if_mach$(EXE_SUFFIX)
+ rm -f threadlibs$(EXE_SUFFIX) cord/cordtest$(EXE_SUFFIX)
+ -rm -f *~
+
+gctest$(EXE_SUFFIX): tests/test.o gc.a if_mach$(EXE_SUFFIX) if_not_there$(EXE_SUFFIX)
+ rm -f gctest gctest$(EXE_SUFFIX)
+ ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o gctest tests/test.o gc.a -lucb
+ ./if_mach HP_PA "" $(CC) $(CFLAGS) -o gctest tests/test.o gc.a -ldld
+ ./if_not_there gctest$(EXE_SUFFIX) $(CC) $(CFLAGS) -o gctest$(EXE_SUFFIX) tests/test.o gc.a
+ rm -f gctest
+
+# If an optimized setjmp_test generates a segmentation fault,
+# odds are your compiler is broken. Gctest may still work.
+# Try compiling setjmp_t.c unoptimized.
+setjmp_test$(EXE_SUFFIX): $(srcdir)/setjmp_t.c $(srcdir)/include/gc.h \
+ if_mach$(EXE_SUFFIX) if_not_there$(EXE_SUFFIX)
+ rm -f setjmp_test$(EXE_SUFFIX)
+ $(CC) $(CFLAGS) -o setjmp_test $(srcdir)/setjmp_t.c
+ rm -f setjmp_test
+
+test: KandRtest cord/cordtest$(EXE_SUFFIX)
+ ./cord/cordtest$(EXE_SUFFIX)
+
+# Those tests that work even with a K&R C compiler:
+KandRtest: setjmp_test$(EXE_SUFFIX) gctest$(EXE_SUFFIX)
+ ./setjmp_test$(EXE_SUFFIX)
+ ./gctest$(EXE_SUFFIX)
+
+add_gc_prefix$(EXE_SUFFIX): add_gc_prefix.c
+ $(CC) -o add_gc_prefix$(EXE_SUFFIX) $(srcdir)/add_gc_prefix.c
+ rm -f add_gc_prefix
+
+gc.tar: $(SRCS) $(OTHER_FILES) add_gc_prefix
+ ./add_gc_prefix$(EXE_SUFFIX) $(SRCS) $(OTHER_FILES) > /tmp/gc.tar-files
+ (cd $(srcdir)/.. ; tar cvfh - `cat /tmp/gc.tar-files`) > gc.tar
+
+pc_gc.tar: $(SRCS) $(OTHER_FILES)
+ tar cvfX pc_gc.tar pc_excludes $(SRCS) $(OTHER_FILES)
+
+gc.tar.Z: gc.tar
+ compress gc.tar
+
+gc.tar.gz: gc.tar
+ gzip gc.tar
+
+lint: $(CSRCS) tests/test.c
+ lint -DLINT $(CSRCS) tests/test.c | egrep -v "possible pointer alignment problem|abort|exit|sbrk|mprotect|syscall"
+
+# BTL: added to test shared library version of collector.
+# Currently works only under SunOS5. Requires GC_INIT call from statically
+# loaded client code.
+ABSDIR = `pwd`
+gctest_dyn_link: test.o libgc.so
+ $(CC) -L$(ABSDIR) -R$(ABSDIR) -o gctest_dyn_link test.o -lgc -ldl -lthread
+
+test_dll.o: tests/test.c libgc_globals.h
+ $(CC) $(CFLAGS) -DGC_USE_DLL -c tests/test.c -o test_dll.o
+
+test_dll: test_dll.o libgc_dll.a libgc.dll
+ $(CC) test_dll.o -L$(ABSDIR) -lgc_dll -o test_dll
+
+SYM_PREFIX-libgc=GC
+
+# Uncomment the following line to build a GNU win32 DLL
+# include Makefile.DLLs
+
diff --git a/tools/build/v2/engine/boehm_gc/Makefile.in b/tools/build/v2/engine/boehm_gc/Makefile.in
new file mode 100644
index 0000000000..f4dbe12d67
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/Makefile.in
@@ -0,0 +1,1405 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved.
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose, provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+#
+# Original author: Tom Tromey
+# Severely truncated by Hans-J. Boehm
+# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
+# Modified by: Petter Urkedal <petter.urkedal@nordita.dk> (2005-04)
+
+#
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose, provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+#
+# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
+# Modified by: Petter Urkedal <petter.urkedal@nordita.dk>
+
+#
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose, provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+
+#
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose, provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+#
+# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
+# Modified by: Petter Urkedal <petter.urkedal@nordita.dk>
+
+
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+check_PROGRAMS = gctest$(EXEEXT) leaktest$(EXEEXT) middletest$(EXEEXT) \
+ $(am__EXEEXT_1) $(am__EXEEXT_2)
+
+# C Library: Architecture Dependent
+# ---------------------------------
+@PTHREADS_TRUE@am__append_1 = pthread_support.c pthread_stop_world.c
+@DARWIN_THREADS_TRUE@am__append_2 = darwin_stop_world.c
+@WIN32_THREADS_TRUE@am__append_3 = win32_threads.c
+
+# C++ Interface
+# -------------
+@CPLUSPLUS_TRUE@am__append_4 = libgccpp.la
+@CPLUSPLUS_TRUE@am__append_5 = include/gc_cpp.h include/gc_allocator.h
+DIST_COMMON = $(am__configure_deps) $(am__pkginclude_HEADERS_DIST) \
+ $(dist_noinst_HEADERS) $(dist_noinst_SCRIPTS) \
+ $(dist_pkgconfig_DATA) $(dist_pkgdata_DATA) $(include_HEADERS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/bdw-gc.pc.in $(srcdir)/cord/cord.am \
+ $(srcdir)/doc/doc.am $(srcdir)/include/include.am \
+ $(srcdir)/tests/tests.am $(top_srcdir)/configure ChangeLog \
+ compile config.guess config.sub depcomp install-sh ltmain.sh \
+ missing mkinstalldirs
+
+#TESTS += tracetest$(EXEEXT)
+#check_PROGRAMS += tracetest
+#tracetest_SOURCES = tests/trace_test.c
+#tracetest_LDADD = $(test_ldadd)
+@THREADS_TRUE@am__append_6 = threadleaktest$(EXEEXT)
+@THREADS_TRUE@am__append_7 = threadleaktest
+@CPLUSPLUS_TRUE@am__append_8 = test_cpp$(EXEEXT)
+@CPLUSPLUS_TRUE@am__append_9 = test_cpp
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/libtool.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno configure.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES = bdw-gc.pc
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
+ "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(includedir)" \
+ "$(DESTDIR)$(pkgincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libcord_la_DEPENDENCIES = $(top_builddir)/libgc.la
+am__dirstamp = $(am__leading_dot)dirstamp
+am_libcord_la_OBJECTS = cord/cordbscs.lo cord/cordprnt.lo \
+ cord/cordtest.lo cord/cordxtra.lo
+libcord_la_OBJECTS = $(am_libcord_la_OBJECTS)
+am__DEPENDENCIES_1 =
+am__libgc_la_SOURCES_DIST = allchblk.c alloc.c blacklst.c checksums.c \
+ dbg_mlc.c dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c \
+ headers.c malloc.c mallocx.c mark.c mark_rts.c misc.c \
+ new_hblk.c obj_map.c os_dep.c pcr_interface.c ptr_chck.c \
+ real_malloc.c reclaim.c specific.c stubborn.c typd_mlc.c \
+ backgraph.c thread_local_alloc.c pthread_support.c \
+ pthread_stop_world.c darwin_stop_world.c win32_threads.c
+@PTHREADS_TRUE@am__objects_1 = pthread_support.lo \
+@PTHREADS_TRUE@ pthread_stop_world.lo
+@DARWIN_THREADS_TRUE@am__objects_2 = darwin_stop_world.lo
+@WIN32_THREADS_TRUE@am__objects_3 = win32_threads.lo
+am_libgc_la_OBJECTS = allchblk.lo alloc.lo blacklst.lo checksums.lo \
+ dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \
+ headers.lo malloc.lo mallocx.lo mark.lo mark_rts.lo misc.lo \
+ new_hblk.lo obj_map.lo os_dep.lo pcr_interface.lo ptr_chck.lo \
+ real_malloc.lo reclaim.lo specific.lo stubborn.lo typd_mlc.lo \
+ backgraph.lo thread_local_alloc.lo $(am__objects_1) \
+ $(am__objects_2) $(am__objects_3)
+@NEED_ATOMIC_OPS_ASM_FALSE@@USE_INTERNAL_LIBATOMIC_OPS_TRUE@nodist_libgc_la_OBJECTS = atomic_ops.lo
+@NEED_ATOMIC_OPS_ASM_TRUE@nodist_libgc_la_OBJECTS = \
+@NEED_ATOMIC_OPS_ASM_TRUE@ atomic_ops_sysdeps.lo
+libgc_la_OBJECTS = $(am_libgc_la_OBJECTS) $(nodist_libgc_la_OBJECTS)
+@CPLUSPLUS_TRUE@libgccpp_la_DEPENDENCIES = $(top_builddir)/libgc.la
+am__libgccpp_la_SOURCES_DIST = gc_cpp.cc
+@CPLUSPLUS_TRUE@am_libgccpp_la_OBJECTS = gc_cpp.lo
+libgccpp_la_OBJECTS = $(am_libgccpp_la_OBJECTS)
+@CPLUSPLUS_TRUE@am_libgccpp_la_rpath = -rpath $(libdir)
+@THREADS_TRUE@am__EXEEXT_1 = threadleaktest$(EXEEXT)
+@CPLUSPLUS_TRUE@am__EXEEXT_2 = test_cpp$(EXEEXT)
+am_gctest_OBJECTS = tests/test.$(OBJEXT)
+gctest_OBJECTS = $(am_gctest_OBJECTS)
+am__DEPENDENCIES_2 = $(top_builddir)/libgc.la $(am__DEPENDENCIES_1)
+am_leaktest_OBJECTS = tests/leak_test.$(OBJEXT)
+leaktest_OBJECTS = $(am_leaktest_OBJECTS)
+leaktest_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_middletest_OBJECTS = tests/middle.$(OBJEXT)
+middletest_OBJECTS = $(am_middletest_OBJECTS)
+middletest_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am__test_cpp_SOURCES_DIST = tests/test_cpp.cc
+@CPLUSPLUS_TRUE@am_test_cpp_OBJECTS = tests/test_cpp.$(OBJEXT)
+test_cpp_OBJECTS = $(am_test_cpp_OBJECTS)
+@CPLUSPLUS_TRUE@test_cpp_DEPENDENCIES = libgccpp.la \
+@CPLUSPLUS_TRUE@ $(am__DEPENDENCIES_2)
+am__threadleaktest_SOURCES_DIST = tests/thread_leak_test.c
+@THREADS_TRUE@am_threadleaktest_OBJECTS = \
+@THREADS_TRUE@ tests/thread_leak_test.$(OBJEXT)
+threadleaktest_OBJECTS = $(am_threadleaktest_OBJECTS)
+@THREADS_TRUE@threadleaktest_DEPENDENCIES = $(am__DEPENDENCIES_2)
+SCRIPTS = $(dist_noinst_SCRIPTS)
+DEFAULT_INCLUDES =
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS)
+LTCCASCOMPILE = $(LIBTOOL) --mode=compile $(CCAS) $(AM_CCASFLAGS) \
+ $(CCASFLAGS)
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcord_la_SOURCES) $(libgc_la_SOURCES) \
+ $(EXTRA_libgc_la_SOURCES) $(nodist_libgc_la_SOURCES) \
+ $(libgccpp_la_SOURCES) $(gctest_SOURCES) $(leaktest_SOURCES) \
+ $(middletest_SOURCES) $(test_cpp_SOURCES) \
+ $(threadleaktest_SOURCES)
+DIST_SOURCES = $(libcord_la_SOURCES) $(am__libgc_la_SOURCES_DIST) \
+ $(EXTRA_libgc_la_SOURCES) $(am__libgccpp_la_SOURCES_DIST) \
+ $(gctest_SOURCES) $(leaktest_SOURCES) $(middletest_SOURCES) \
+ $(am__test_cpp_SOURCES_DIST) \
+ $(am__threadleaktest_SOURCES_DIST)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-exec-recursive install-info-recursive \
+ install-recursive installcheck-recursive installdirs-recursive \
+ pdf-recursive ps-recursive uninstall-info-recursive \
+ uninstall-recursive
+dist_pkgconfigDATA_INSTALL = $(INSTALL_DATA)
+dist_pkgdataDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(dist_pkgconfig_DATA) $(dist_pkgdata_DATA)
+includeHEADERS_INSTALL = $(INSTALL_HEADER)
+am__pkginclude_HEADERS_DIST = include/gc_cpp.h include/gc_allocator.h \
+ include/gc.h include/gc_typed.h include/gc_inline.h \
+ include/gc_mark.h include/weakpointer.h include/new_gc_alloc.h \
+ include/gc_backptr.h include/gc_gcj.h include/leak_detector.h \
+ include/gc_amiga_redirects.h include/gc_pthread_redirects.h \
+ include/gc_config_macros.h include/gc_tiny_fl.h
+pkgincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(dist_noinst_HEADERS) $(include_HEADERS) \
+ $(pkginclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASFLAGS = @CCASFLAGS@ $(DEFS)
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COMPILER_XLC_FALSE = @COMPILER_XLC_FALSE@
+COMPILER_XLC_TRUE = @COMPILER_XLC_TRUE@
+CPLUSPLUS_FALSE = @CPLUSPLUS_FALSE@
+CPLUSPLUS_TRUE = @CPLUSPLUS_TRUE@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CXXINCLUDES = @CXXINCLUDES@
+CYGPATH_W = @CYGPATH_W@
+DARWIN_THREADS_FALSE = @DARWIN_THREADS_FALSE@
+DARWIN_THREADS_TRUE = @DARWIN_THREADS_TRUE@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLE_GCJ_SUPPORT_FALSE = @ENABLE_GCJ_SUPPORT_FALSE@
+ENABLE_GCJ_SUPPORT_TRUE = @ENABLE_GCJ_SUPPORT_TRUE@
+EXEEXT = @EXEEXT@
+EXTRA_TEST_LIBS = @EXTRA_TEST_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GC_CFLAGS = @GC_CFLAGS@
+GC_VERSION = @GC_VERSION@
+GREP = @GREP@
+INCLUDES = @INCLUDES@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+NEED_ATOMIC_OPS_ASM_FALSE = @NEED_ATOMIC_OPS_ASM_FALSE@
+NEED_ATOMIC_OPS_ASM_TRUE = @NEED_ATOMIC_OPS_ASM_TRUE@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREADS_FALSE = @PTHREADS_FALSE@
+PTHREADS_TRUE = @PTHREADS_TRUE@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+THREADDLLIBS = @THREADDLLIBS@
+THREADS_FALSE = @THREADS_FALSE@
+THREADS_TRUE = @THREADS_TRUE@
+UNWINDLIBS = @UNWINDLIBS@
+USE_INTERNAL_LIBATOMIC_OPS_FALSE = @USE_INTERNAL_LIBATOMIC_OPS_FALSE@
+USE_INTERNAL_LIBATOMIC_OPS_TRUE = @USE_INTERNAL_LIBATOMIC_OPS_TRUE@
+USE_LIBDIR_FALSE = @USE_LIBDIR_FALSE@
+USE_LIBDIR_TRUE = @USE_LIBDIR_TRUE@
+VERSION = @VERSION@
+WIN32_THREADS_FALSE = @WIN32_THREADS_FALSE@
+WIN32_THREADS_TRUE = @WIN32_THREADS_TRUE@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+addlibs = @addlibs@
+addobjs = @addobjs@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+atomic_ops_libs = @atomic_ops_libs@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+extra_ldflags_libgc = @extra_ldflags_libgc@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_all = @target_all@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+
+# We currently use the source files directly from libatomic_ops, if we
+# use the internal version. This is done since libatomic_ops doesn't
+# use libtool, since it has no real use for it. But that seems to make
+# it hard to use either the resulting object files or libraries.
+# Thus there seems too be no real reason to recusively build in the
+# libatomic_ops directory.
+# if USE_INTERNAL_LIBATOMICS_OPS
+# SUBDIRS = @maybe_libatomic_ops@
+# else
+# SUBDIRS =
+# endif
+SUBDIRS =
+
+# Initialize variables so that we can declare files locally.
+
+# FIXME: If Visual C++ users use Makefile.am, this should go into
+# pkginclude_HEADERS with proper AM_CONDITIONALization. Otherwise
+# delete this comment.
+
+# documentation which is not installed
+#
+
+# other makefiles
+# :GOTCHA: deliberately we do not include 'Makefile'
+
+# files used by makefiles other than Makefile.am
+#
+
+# The libatomic_ops library. This is not ideal, since we pick up junk from
+# there. The hard-coded version number should also go.
+
+# :FIXME: why do we distribute this one???
+#
+EXTRA_DIST = gc_cpp.cpp README.QUICK BCC_MAKEFILE NT_MAKEFILE \
+ NT_THREADS_MAKEFILE OS2_MAKEFILE PCR-Makefile digimars.mak \
+ EMX_MAKEFILE Makefile.direct Makefile.dj Makefile.DLLs \
+ SMakefile.amiga WCC_MAKEFILE configure_atomic_ops.sh \
+ NT_STATIC_THREADS_MAKEFILE NT_X64_STATIC_THREADS_MAKEFILE \
+ add_gc_prefix.c gcname.c if_mach.c if_not_there.c \
+ hpux_test_and_clear.s gc.mak MacOS.c MacProjects.sit.hqx \
+ mach_dep.c setjmp_t.c threadlibs.c AmigaOS.c \
+ Mac_files/datastart.c Mac_files/dataend.c \
+ Mac_files/MacOS_config.h Mac_files/MacOS_Test_config.h \
+ include/private/msvc_dbg.h msvc_dbg.c libatomic_ops-1.2 \
+ libtool.m4 cord/cordbscs.c cord/cordtest.c cord/de.c \
+ cord/cordprnt.c cord/cordxtra.c cord/de_cmds.h cord/de_win.h \
+ cord/de_win.c cord/de_win.RC cord/de_win.ICO
+
+# C Library
+# ---------
+lib_LTLIBRARIES = libgc.la $(am__append_4) libcord.la
+include_HEADERS =
+
+# installed headers
+#
+pkginclude_HEADERS = $(am__append_5) include/gc.h include/gc_typed.h \
+ include/gc_inline.h include/gc_mark.h include/gc_cpp.h \
+ include/weakpointer.h include/new_gc_alloc.h \
+ include/gc_allocator.h include/gc_backptr.h include/gc_gcj.h \
+ include/leak_detector.h include/gc_amiga_redirects.h \
+ include/gc_pthread_redirects.h include/gc_config_macros.h \
+ include/gc_tiny_fl.h
+
+# headers which are not installed
+# (see include/include.am for more)
+#
+
+# headers which are not installed
+#
+dist_noinst_HEADERS = version.h include/private/gc_hdrs.h \
+ include/private/gc_priv.h include/private/gcconfig.h \
+ include/private/gc_pmark.h include/private/gc_locks.h \
+ include/private/dbg_mlc.h include/private/specific.h \
+ include/private/cord_pos.h include/private/pthread_support.h \
+ include/private/pthread_stop_world.h \
+ include/private/darwin_semaphore.h \
+ include/private/darwin_stop_world.h \
+ include/private/thread_local_alloc.h include/cord.h \
+ include/ec.h include/javaxfc.h
+TESTS = gctest$(EXEEXT) leaktest$(EXEEXT) middletest$(EXEEXT) \
+ $(am__append_6) $(am__append_8)
+pkgconfigdir = $(libdir)/pkgconfig
+dist_pkgconfig_DATA = bdw-gc.pc
+libgc_la_SOURCES = allchblk.c alloc.c blacklst.c checksums.c dbg_mlc.c \
+ dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c malloc.c \
+ mallocx.c mark.c mark_rts.c misc.c new_hblk.c obj_map.c \
+ os_dep.c pcr_interface.c ptr_chck.c real_malloc.c reclaim.c \
+ specific.c stubborn.c typd_mlc.c backgraph.c \
+ thread_local_alloc.c $(am__append_1) $(am__append_2) \
+ $(am__append_3)
+@NEED_ATOMIC_OPS_ASM_TRUE@nodist_libgc_la_SOURCES = atomic_ops_sysdeps.S
+@USE_INTERNAL_LIBATOMIC_OPS_TRUE@nodist_libgc_la_SOURCES = atomic_ops.c
+
+# Include THREADDLLIBS here to ensure that the correct versions of
+# linuxthread semaphore functions get linked:
+libgc_la_LIBADD = @addobjs@ $(THREADDLLIBS) $(UNWINDLIBS)
+libgc_la_DEPENDENCIES = @addobjs@
+libgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info 1:3:0 -no-undefined
+EXTRA_libgc_la_SOURCES = alpha_mach_dep.S \
+ mips_sgi_mach_dep.s mips_ultrix_mach_dep.s \
+ rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \
+ sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
+
+@CPLUSPLUS_TRUE@libgccpp_la_SOURCES = gc_cpp.cc
+@CPLUSPLUS_TRUE@libgccpp_la_LIBADD = $(top_builddir)/libgc.la
+@CPLUSPLUS_TRUE@libgccpp_la_LDFLAGS = -version-info 1:3:0 -no-undefined
+
+# Misc
+# ----
+AM_CXXFLAGS = @GC_CFLAGS@
+AM_CFLAGS = @GC_CFLAGS@
+@COMPILER_XLC_FALSE@ASM_CPP_OPTIONS = -Wp,-P -x assembler-with-cpp
+
+#all_objs = @addobjs@ $(libgc_la_OBJECTS)
+#$(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \
+#include/private/gc_hdrs.h include/gc.h include/gc_gcj.h \
+#include/gc_pthread_redirects.h include/gc_config_macros.h \
+#include/private/thread_local_alloc.h include/private_support.h \
+#include/private/pthread_stop_world.h \
+#include/gc_mark.h @addincludes@
+@COMPILER_XLC_TRUE@ASM_CPP_OPTIONS =
+dist_noinst_SCRIPTS = callprocs configure.host
+
+# this is an auxiliary shell file used by Makefile and Makefile.direct
+#
+CONFIG_STATUS_DEPENDENCIES = $(srcdir)/configure.host
+libcord_la_LIBADD = $(top_builddir)/libgc.la
+libcord_la_LDFLAGS = -version-info 1:3:0 -no-undefined
+libcord_la_SOURCES = \
+ cord/cordbscs.c \
+ cord/cordprnt.c \
+ cord/cordtest.c \
+ cord/cordxtra.c
+
+
+# Common libs to _LDADD for all tests.
+test_ldadd = $(top_builddir)/libgc.la $(EXTRA_TEST_LIBS)
+gctest_SOURCES = tests/test.c
+gctest_LDADD = $(test_ldadd)
+gctest_DEPENDENCIES = $(top_builddir)/libgc.la
+leaktest_SOURCES = tests/leak_test.c
+leaktest_LDADD = $(test_ldadd)
+middletest_SOURCES = tests/middle.c
+middletest_LDADD = $(test_ldadd)
+@THREADS_TRUE@threadleaktest_SOURCES = tests/thread_leak_test.c
+@THREADS_TRUE@threadleaktest_LDADD = $(test_ldadd)
+@CPLUSPLUS_TRUE@test_cpp_SOURCES = tests/test_cpp.cc
+@CPLUSPLUS_TRUE@test_cpp_LDADD = libgccpp.la $(test_ldadd)
+
+# installed documentation
+#
+dist_pkgdata_DATA = \
+ doc/barrett_diagram \
+ doc/debugging.html \
+ doc/gc.man \
+ doc/gcdescr.html \
+ doc/README \
+ doc/README.amiga \
+ doc/README.arm.cross \
+ doc/README.autoconf \
+ doc/README.changes \
+ doc/README.contributors \
+ doc/README.cords \
+ doc/README.DGUX386 \
+ doc/README.dj \
+ doc/README.environment \
+ doc/README.ews4800 \
+ doc/README.hp \
+ doc/README.linux \
+ doc/README.Mac \
+ doc/README.MacOSX \
+ doc/README.macros \
+ doc/README.OS2 \
+ doc/README.rs6000 \
+ doc/README.sgi \
+ doc/README.solaris2 \
+ doc/README.uts \
+ doc/README.win32 \
+ doc/README.win64 \
+ doc/overview.html \
+ doc/tree.html \
+ doc/leak.html \
+ doc/gcinterface.html \
+ doc/scale.html \
+ doc/README.darwin \
+ doc/simple_example.html \
+ doc/porting.html
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .lo .o .obj .s
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/include/include.am $(srcdir)/cord/cord.am $(srcdir)/tests/tests.am $(srcdir)/doc/doc.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+ cd $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+bdw-gc.pc: $(top_builddir)/config.status $(srcdir)/bdw-gc.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+cord/$(am__dirstamp):
+ @$(mkdir_p) cord
+ @: > cord/$(am__dirstamp)
+cord/$(DEPDIR)/$(am__dirstamp):
+ @$(mkdir_p) cord/$(DEPDIR)
+ @: > cord/$(DEPDIR)/$(am__dirstamp)
+cord/cordbscs.lo: cord/$(am__dirstamp) cord/$(DEPDIR)/$(am__dirstamp)
+cord/cordprnt.lo: cord/$(am__dirstamp) cord/$(DEPDIR)/$(am__dirstamp)
+cord/cordtest.lo: cord/$(am__dirstamp) cord/$(DEPDIR)/$(am__dirstamp)
+cord/cordxtra.lo: cord/$(am__dirstamp) cord/$(DEPDIR)/$(am__dirstamp)
+libcord.la: $(libcord_la_OBJECTS) $(libcord_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libcord_la_LDFLAGS) $(libcord_la_OBJECTS) $(libcord_la_LIBADD) $(LIBS)
+libgc.la: $(libgc_la_OBJECTS) $(libgc_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libgc_la_LDFLAGS) $(libgc_la_OBJECTS) $(libgc_la_LIBADD) $(LIBS)
+libgccpp.la: $(libgccpp_la_OBJECTS) $(libgccpp_la_DEPENDENCIES)
+ $(CXXLINK) $(am_libgccpp_la_rpath) $(libgccpp_la_LDFLAGS) $(libgccpp_la_OBJECTS) $(libgccpp_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+tests/$(am__dirstamp):
+ @$(mkdir_p) tests
+ @: > tests/$(am__dirstamp)
+tests/$(DEPDIR)/$(am__dirstamp):
+ @$(mkdir_p) tests/$(DEPDIR)
+ @: > tests/$(DEPDIR)/$(am__dirstamp)
+tests/test.$(OBJEXT): tests/$(am__dirstamp) \
+ tests/$(DEPDIR)/$(am__dirstamp)
+gctest$(EXEEXT): $(gctest_OBJECTS) $(gctest_DEPENDENCIES)
+ @rm -f gctest$(EXEEXT)
+ $(LINK) $(gctest_LDFLAGS) $(gctest_OBJECTS) $(gctest_LDADD) $(LIBS)
+tests/leak_test.$(OBJEXT): tests/$(am__dirstamp) \
+ tests/$(DEPDIR)/$(am__dirstamp)
+leaktest$(EXEEXT): $(leaktest_OBJECTS) $(leaktest_DEPENDENCIES)
+ @rm -f leaktest$(EXEEXT)
+ $(LINK) $(leaktest_LDFLAGS) $(leaktest_OBJECTS) $(leaktest_LDADD) $(LIBS)
+tests/middle.$(OBJEXT): tests/$(am__dirstamp) \
+ tests/$(DEPDIR)/$(am__dirstamp)
+middletest$(EXEEXT): $(middletest_OBJECTS) $(middletest_DEPENDENCIES)
+ @rm -f middletest$(EXEEXT)
+ $(LINK) $(middletest_LDFLAGS) $(middletest_OBJECTS) $(middletest_LDADD) $(LIBS)
+tests/test_cpp.$(OBJEXT): tests/$(am__dirstamp) \
+ tests/$(DEPDIR)/$(am__dirstamp)
+test_cpp$(EXEEXT): $(test_cpp_OBJECTS) $(test_cpp_DEPENDENCIES)
+ @rm -f test_cpp$(EXEEXT)
+ $(CXXLINK) $(test_cpp_LDFLAGS) $(test_cpp_OBJECTS) $(test_cpp_LDADD) $(LIBS)
+tests/thread_leak_test.$(OBJEXT): tests/$(am__dirstamp) \
+ tests/$(DEPDIR)/$(am__dirstamp)
+threadleaktest$(EXEEXT): $(threadleaktest_OBJECTS) $(threadleaktest_DEPENDENCIES)
+ @rm -f threadleaktest$(EXEEXT)
+ $(LINK) $(threadleaktest_LDFLAGS) $(threadleaktest_OBJECTS) $(threadleaktest_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f cord/cordbscs.$(OBJEXT)
+ -rm -f cord/cordbscs.lo
+ -rm -f cord/cordprnt.$(OBJEXT)
+ -rm -f cord/cordprnt.lo
+ -rm -f cord/cordtest.$(OBJEXT)
+ -rm -f cord/cordtest.lo
+ -rm -f cord/cordxtra.$(OBJEXT)
+ -rm -f cord/cordxtra.lo
+ -rm -f tests/leak_test.$(OBJEXT)
+ -rm -f tests/middle.$(OBJEXT)
+ -rm -f tests/test.$(OBJEXT)
+ -rm -f tests/test_cpp.$(OBJEXT)
+ -rm -f tests/thread_leak_test.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/allchblk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomic_ops.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backgraph.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blacklst.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checksums.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/darwin_stop_world.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbg_mlc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyn_load.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/finalize.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gc_cpp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gc_dlopen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gcj_mlc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/headers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mallocx.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mark.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mark_rts.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/new_hblk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/obj_map.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_dep.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcr_interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pthread_stop_world.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pthread_support.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptr_chck.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/real_malloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reclaim.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/specific.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stubborn.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_local_alloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/typd_mlc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32_threads.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@cord/$(DEPDIR)/cordbscs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@cord/$(DEPDIR)/cordprnt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@cord/$(DEPDIR)/cordtest.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@cord/$(DEPDIR)/cordxtra.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/leak_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/middle.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_cpp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/thread_leak_test.Po@am__quote@
+
+.S.o:
+ $(CCASCOMPILE) -c $<
+
+.S.obj:
+ $(CCASCOMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.o:
+@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`; \
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`; \
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`; \
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Plo"; else rm -f "$$depbase.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+.cc.o:
+@am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`; \
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`; \
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`; \
+@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Plo"; else rm -f "$$depbase.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+.s.o:
+ $(CCASCOMPILE) -c $<
+
+.s.obj:
+ $(CCASCOMPILE) -c `$(CYGPATH_W) '$<'`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf cord/.libs cord/_libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-dist_pkgconfigDATA: $(dist_pkgconfig_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgconfigdir)" || $(mkdir_p) "$(DESTDIR)$(pkgconfigdir)"
+ @list='$(dist_pkgconfig_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(dist_pkgconfigDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ $(dist_pkgconfigDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+
+uninstall-dist_pkgconfigDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_pkgconfig_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+install-dist_pkgdataDATA: $(dist_pkgdata_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(pkgdatadir)"
+ @list='$(dist_pkgdata_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(dist_pkgdataDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdatadir)/$$f'"; \
+ $(dist_pkgdataDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdatadir)/$$f"; \
+ done
+
+uninstall-dist_pkgdataDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_pkgdata_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(pkgdatadir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgdatadir)/$$f"; \
+ done
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(includedir)" || $(mkdir_p) "$(DESTDIR)$(includedir)"
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
+ $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(includedir)/$$f"; \
+ done
+install-pkgincludeHEADERS: $(pkginclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgincludedir)" || $(mkdir_p) "$(DESTDIR)$(pkgincludedir)"
+ @list='$(pkginclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(pkgincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgincludedir)/$$f'"; \
+ $(pkgincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgincludedir)/$$f"; \
+ done
+
+uninstall-pkgincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkginclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(pkgincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgincludedir)/$$f"; \
+ done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list='$(TESTS)'; \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *" $$tst "*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ echo "XPASS: $$tst"; \
+ ;; \
+ *) \
+ echo "PASS: $$tst"; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *" $$tst "*) \
+ xfail=`expr $$xfail + 1`; \
+ echo "XFAIL: $$tst"; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ echo "FAIL: $$tst"; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ echo "SKIP: $$tst"; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all tests failed"; \
+ else \
+ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ skipped="($$skip tests were not run)"; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ mkdir $(distdir)
+ $(mkdir_p) $(distdir)/. $(distdir)/Mac_files $(distdir)/cord $(distdir)/doc $(distdir)/include $(distdir)/include/private $(distdir)/tests
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(mkdir_p) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r $(distdir)
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
+distuninstallcheck:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) $(DATA) $(HEADERS)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(pkgincludedir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -rm -f cord/$(DEPDIR)/$(am__dirstamp)
+ -rm -f cord/$(am__dirstamp)
+ -rm -f tests/$(DEPDIR)/$(am__dirstamp)
+ -rm -f tests/$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \
+ clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf ./$(DEPDIR) cord/$(DEPDIR) tests/$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-dist_pkgconfigDATA install-dist_pkgdataDATA \
+ install-includeHEADERS install-pkgincludeHEADERS
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR) cord/$(DEPDIR) tests/$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-dist_pkgconfigDATA uninstall-dist_pkgdataDATA \
+ uninstall-includeHEADERS uninstall-info-am \
+ uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \
+ check-TESTS check-am clean clean-checkPROGRAMS clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-recursive ctags \
+ ctags-recursive dist dist-all dist-bzip2 dist-gzip dist-shar \
+ dist-tarZ dist-zip distcheck distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-recursive \
+ distclean-tags distcleancheck distdir distuninstallcheck dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dist_pkgconfigDATA \
+ install-dist_pkgdataDATA install-exec install-exec-am \
+ install-includeHEADERS install-info install-info-am \
+ install-libLTLIBRARIES install-man install-pkgincludeHEADERS \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ maintainer-clean-recursive mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \
+ pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-dist_pkgconfigDATA uninstall-dist_pkgdataDATA \
+ uninstall-includeHEADERS uninstall-info-am \
+ uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS
+
+.s.lo:
+ $(LTCOMPILE) $(ASM_CPP_OPTIONS) -c $<
+
+.S.lo:
+ $(LTCOMPILE) $(ASM_CPP_OPTIONS) -c $<
+
+#
+# :GOTCHA: GNU make rule for making .s out of .S is flawed,
+# it will not remove dest if building fails
+.S.s:
+ if $(CPP) $< >$@ ; then :; else rm -f $@; fi
+
+# Putting these at the top causes cord to be built first, and not find libgc.a
+# on HP/UX. There may be a better fix.
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tools/build/v2/engine/boehm_gc/NT_MAKEFILE b/tools/build/v2/engine/boehm_gc/NT_MAKEFILE
new file mode 100755
index 0000000000..c8739effc6
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/NT_MAKEFILE
@@ -0,0 +1,60 @@
+# Makefile for Windows NT. Assumes Microsoft compiler, and a single thread.
+# DLLs are included in the root set under NT, but not under win32S.
+# Use "nmake nodebug=1 all" for optimized versions of library, gctest and editor.
+
+MY_CPU=X86
+CPU=$(MY_CPU)
+!include <ntwin32.mak>
+
+OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj malloc.obj stubborn.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gc_cpp.obj mallocx.obj msvc_dbg.obj
+
+all: gctest.exe cord\de.exe test_cpp.exe
+
+.c.obj:
+ $(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DALL_INTERIOR_POINTERS -D__STDC__ -DGC_NOT_DLL -DGC_BUILD $*.c /Fo$*.obj
+
+.cpp.obj:
+ $(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -DGC_BUILD $*.CPP /Fo$*.obj
+
+$(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\private\msvc_dbg.h
+
+gc.lib: $(OBJS)
+ lib /MACHINE:i386 /out:gc.lib $(OBJS)
+# The original NT SDK used lib32 instead of lib
+
+gctest.exe: tests\test.obj gc.lib
+# The following works for win32 debugging. For win32s debugging use debugtype:coff
+# and add mapsympe line.
+# This produces a "GUI" applications that opens no windows and writes to the log file
+# "gc.log". This is done to make the result runnable under win32s.
+ $(link) -debug:full -debugtype:cv $(guiflags) -stack:131072 -out:$*.exe tests\test.obj $(guilibs) gc.lib
+# mapsympe -n -o gctest.sym gctest.exe
+
+cord\de_win.rbj: cord\de_win.res
+ cvtres /MACHINE:$(MY_CPU) /OUT:cord\de_win.rbj cord\de_win.res
+
+cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h cord\de_cmds.h
+
+cord\de_win.res: cord\de_win.rc cord\de_win.h cord\de_cmds.h
+ $(rc) $(rcvars) -r -fo cord\de_win.res cord\de_win.rc
+
+# Cord/de is a real win32 gui application.
+cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib
+ $(link) -debug:full -debugtype:cv $(guiflags) -stack:16384 -out:cord\de.exe cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib $(guilibs)
+
+gc_cpp.obj: include\gc_cpp.h include\gc.h
+
+gc_cpp.cpp: gc_cpp.cc
+ copy gc_cpp.cc gc_cpp.cpp
+
+test_cpp.cpp: tests\test_cpp.cc
+ copy tests\test_cpp.cc test_cpp.cpp
+
+# This generates the C++ test executable. The executable expects
+# a single numeric argument, which is the number of iterations.
+# The output appears in the file "gc.log".
+test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib
+ $(link) -debug:full -debugtype:cv $(guiflags) -stack:16384 -out:test_cpp.exe test_cpp.obj gc.lib $(guilibs)
+
+
+
diff --git a/tools/build/v2/engine/boehm_gc/NT_STATIC_THREADS_MAKEFILE b/tools/build/v2/engine/boehm_gc/NT_STATIC_THREADS_MAKEFILE
new file mode 100644
index 0000000000..d0f912751e
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/NT_STATIC_THREADS_MAKEFILE
@@ -0,0 +1,74 @@
+# Makefile for Windows NT. Assumes Microsoft compiler.
+# DLLs are included in the root set under NT, but not under win32S.
+# Use "nmake nodebug=1 all" for optimized versions of library, gctest and editor.
+
+MY_CPU=X86
+CPU=$(MY_CPU)
+!include <ntwin32.mak>
+
+# Make sure that .cc is not viewed as a suffix. It is for VC++2005, but
+# not earlier versions. We can deal with either, but not inconsistency.
+.SUFFIXES:
+.SUFFIXES: .obj .cpp .c
+
+# Atomic_ops installation directory. For win32, the source directory
+# should do, since we only need the headers.
+# We assume this was manually unpacked, since I'm not sure there is
+# a Windows standard command line tool to do this.
+AO_VERSION=1.2
+AO_SRC_DIR=libatomic_ops-$(AO_VERSION)/src
+AO_INCLUDE_DIR=$(AO_SRC_DIR)
+
+OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj malloc.obj stubborn.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gc_cpp.obj mallocx.obj win32_threads.obj msvc_dbg.obj thread_local_alloc.obj
+
+all: gctest.exe cord\de.exe test_cpp.exe
+
+.c.obj:
+ $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -D__STDC__ -DGC_NOT_DLL -DGC_WIN32_THREADS -DTHREAD_LOCAL_ALLOC $*.c /Fo$*.obj
+
+.cpp.obj:
+ $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL $*.CPP -DGC_WIN32_THREADS -DTHREAD_LOCAL_ALLOC /Fo$*.obj
+
+$(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\private\msvc_dbg.h
+
+gc.lib: $(OBJS)
+ lib /MACHINE:i386 /out:gc.lib $(OBJS)
+# The original NT SDK used lib32 instead of lib
+
+gctest.exe: tests\test.obj gc.lib
+# The following works for win32 debugging. For win32s debugging use debugtype:coff
+# and add mapsympe line.
+# This produces a "GUI" applications that opens no windows and writes to the log file
+# "gc.log". This is done to make the result runnable under win32s.
+ $(link) -debug:full -debugtype:cv $(guiflags) -stack:131072 -out:$*.exe tests\test.obj $(guilibs) gc.lib
+# mapsympe -n -o gctest.sym gctest.exe
+
+cord\de_win.rbj: cord\de_win.res
+ cvtres /MACHINE:$(MY_CPU) /OUT:cord\de_win.rbj cord\de_win.res
+
+cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h cord\de_cmds.h
+
+cord\de_win.res: cord\de_win.rc cord\de_win.h cord\de_cmds.h
+ $(rc) $(rcvars) -r -fo cord\de_win.res cord\de_win.rc
+
+# Cord/de is a real win32 gui application.
+cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib
+ $(link) -debug:full -debugtype:cv $(guiflags) -stack:16384 -out:cord\de.exe cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib $(guilibs)
+
+gc_cpp.obj: include\gc_cpp.h include\gc.h
+
+gc_cpp.cpp: gc_cpp.cc
+ copy gc_cpp.cc gc_cpp.cpp
+
+test_cpp.cpp: tests\test_cpp.cc
+ copy tests\test_cpp.cc test_cpp.cpp
+
+# This generates the C++ test executable. The executable expects
+# a single numeric argument, which is the number of iterations.
+# The output appears in the file "gc.log".
+test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib
+ $(link) -debug:full -debugtype:cv $(guiflags) -stack:16384 -out:test_cpp.exe test_cpp.obj gc.lib $(guilibs)
+
+AO_SCR_DIR:
+ tar xvfz $(AO_SRC_DIR).tar.gz;
+
diff --git a/tools/build/v2/engine/boehm_gc/NT_THREADS_MAKEFILE b/tools/build/v2/engine/boehm_gc/NT_THREADS_MAKEFILE
new file mode 100644
index 0000000000..5c02c9023c
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/NT_THREADS_MAKEFILE
@@ -0,0 +1,2220 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.10
+# This has been hand-edited way too many times.
+# A clean, manually generated makefile would be an improvement.
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+AO_VERSION=1.2
+!IF "$(CFG)" == ""
+CFG=gctest - Win32 Release
+!MESSAGE No configuration specified. Defaulting to cord - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "gc - Win32 Release" && "$(CFG)" != "gc - Win32 Debug" &&\
+ "$(CFG)" != "gctest - Win32 Release" && "$(CFG)" != "gctest - Win32 Debug" &&\
+ "$(CFG)" != "cord - Win32 Release" && "$(CFG)" != "cord - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gc.mak" CFG="cord - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "gc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "gctest - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "gctest - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "cord - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "cord - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "gctest - Win32 Debug"
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : ".\Release\gc.dll" ".\Release\gc.bsc"
+
+CLEAN :
+ -@erase ".\Release\allchblk.obj"
+ -@erase ".\Release\allchblk.sbr"
+ -@erase ".\Release\alloc.obj"
+ -@erase ".\Release\alloc.sbr"
+ -@erase ".\Release\blacklst.obj"
+ -@erase ".\Release\blacklst.sbr"
+ -@erase ".\Release\checksums.obj"
+ -@erase ".\Release\checksums.sbr"
+ -@erase ".\Release\dbg_mlc.obj"
+ -@erase ".\Release\dbg_mlc.sbr"
+ -@erase ".\Release\dyn_load.obj"
+ -@erase ".\Release\dyn_load.sbr"
+ -@erase ".\Release\finalize.obj"
+ -@erase ".\Release\finalize.sbr"
+ -@erase ".\Release\gc.bsc"
+ -@erase ".\Release\gc_cpp.obj"
+ -@erase ".\Release\gc_cpp.sbr"
+ -@erase ".\Release\gc.dll"
+ -@erase ".\Release\gc.exp"
+ -@erase ".\Release\gc.lib"
+ -@erase ".\Release\headers.obj"
+ -@erase ".\Release\headers.sbr"
+ -@erase ".\Release\mach_dep.obj"
+ -@erase ".\Release\mach_dep.sbr"
+ -@erase ".\Release\malloc.obj"
+ -@erase ".\Release\malloc.sbr"
+ -@erase ".\Release\mallocx.obj"
+ -@erase ".\Release\mallocx.sbr"
+ -@erase ".\Release\mark.obj"
+ -@erase ".\Release\mark.sbr"
+ -@erase ".\Release\mark_rts.obj"
+ -@erase ".\Release\mark_rts.sbr"
+ -@erase ".\Release\misc.obj"
+ -@erase ".\Release\misc.sbr"
+ -@erase ".\Release\new_hblk.obj"
+ -@erase ".\Release\new_hblk.sbr"
+ -@erase ".\Release\obj_map.obj"
+ -@erase ".\Release\obj_map.sbr"
+ -@erase ".\Release\os_dep.obj"
+ -@erase ".\Release\os_dep.sbr"
+ -@erase ".\Release\ptr_chck.obj"
+ -@erase ".\Release\ptr_chck.sbr"
+ -@erase ".\Release\reclaim.obj"
+ -@erase ".\Release\reclaim.sbr"
+ -@erase ".\Release\stubborn.obj"
+ -@erase ".\Release\stubborn.sbr"
+ -@erase ".\Release\typd_mlc.obj"
+ -@erase ".\Release\typd_mlc.sbr"
+ -@erase ".\Release\win32_threads.obj"
+ -@erase ".\Release\win32_threads.sbr"
+ -@erase ".\Release\msvc_dbg.obj"
+ -@erase ".\Release\msvc_dbg.sbr"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "GC_BUILD" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR /YX /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "GC_BUILD" /D\
+ "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D\
+ "GC_WIN32_THREADS" /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch" \
+ /Ilibatomic_ops-$(AO_VERSION)/src /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Release/
+CPP_SBRS=.\Release/
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gc.bsc"
+BSC32_SBRS= \
+ ".\Release\allchblk.sbr" \
+ ".\Release\alloc.sbr" \
+ ".\Release\blacklst.sbr" \
+ ".\Release\checksums.sbr" \
+ ".\Release\dbg_mlc.sbr" \
+ ".\Release\dyn_load.sbr" \
+ ".\Release\finalize.sbr" \
+ ".\Release\gc_cpp.sbr" \
+ ".\Release\headers.sbr" \
+ ".\Release\mach_dep.sbr" \
+ ".\Release\malloc.sbr" \
+ ".\Release\mallocx.sbr" \
+ ".\Release\mark.sbr" \
+ ".\Release\mark_rts.sbr" \
+ ".\Release\misc.sbr" \
+ ".\Release\new_hblk.sbr" \
+ ".\Release\obj_map.sbr" \
+ ".\Release\os_dep.sbr" \
+ ".\Release\ptr_chck.sbr" \
+ ".\Release\reclaim.sbr" \
+ ".\Release\stubborn.sbr" \
+ ".\Release\typd_mlc.sbr" \
+ ".\Release\msvc_dbg.sbr" \
+ ".\Release\win32_threads.sbr"
+
+".\Release\gc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\
+ /pdb:"$(OUTDIR)/gc.pdb" /machine:I386 /out:"$(OUTDIR)/gc.dll"\
+ /implib:"$(OUTDIR)/gc.lib"
+LINK32_OBJS= \
+ ".\Release\allchblk.obj" \
+ ".\Release\alloc.obj" \
+ ".\Release\blacklst.obj" \
+ ".\Release\checksums.obj" \
+ ".\Release\dbg_mlc.obj" \
+ ".\Release\dyn_load.obj" \
+ ".\Release\finalize.obj" \
+ ".\Release\gc_cpp.obj" \
+ ".\Release\headers.obj" \
+ ".\Release\mach_dep.obj" \
+ ".\Release\malloc.obj" \
+ ".\Release\mallocx.obj" \
+ ".\Release\mark.obj" \
+ ".\Release\mark_rts.obj" \
+ ".\Release\misc.obj" \
+ ".\Release\new_hblk.obj" \
+ ".\Release\obj_map.obj" \
+ ".\Release\os_dep.obj" \
+ ".\Release\ptr_chck.obj" \
+ ".\Release\reclaim.obj" \
+ ".\Release\stubborn.obj" \
+ ".\Release\typd_mlc.obj" \
+ ".\Release\msvc_dbg.obj" \
+ ".\Release\win32_threads.obj"
+
+".\Release\gc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+OUTDIR=.\Debug
+INTDIR=.\Debug
+
+ALL : ".\Debug\gc.dll" ".\Debug\gc.bsc"
+
+CLEAN :
+ -@erase ".\Debug\allchblk.obj"
+ -@erase ".\Debug\allchblk.sbr"
+ -@erase ".\Debug\alloc.obj"
+ -@erase ".\Debug\alloc.sbr"
+ -@erase ".\Debug\blacklst.obj"
+ -@erase ".\Debug\blacklst.sbr"
+ -@erase ".\Debug\checksums.obj"
+ -@erase ".\Debug\checksums.sbr"
+ -@erase ".\Debug\dbg_mlc.obj"
+ -@erase ".\Debug\dbg_mlc.sbr"
+ -@erase ".\Debug\dyn_load.obj"
+ -@erase ".\Debug\dyn_load.sbr"
+ -@erase ".\Debug\finalize.obj"
+ -@erase ".\Debug\finalize.sbr"
+ -@erase ".\Debug\gc_cpp.obj"
+ -@erase ".\Debug\gc_cpp.sbr"
+ -@erase ".\Debug\gc.bsc"
+ -@erase ".\Debug\gc.dll"
+ -@erase ".\Debug\gc.exp"
+ -@erase ".\Debug\gc.lib"
+ -@erase ".\Debug\gc.map"
+ -@erase ".\Debug\gc.pdb"
+ -@erase ".\Debug\headers.obj"
+ -@erase ".\Debug\headers.sbr"
+ -@erase ".\Debug\mach_dep.obj"
+ -@erase ".\Debug\mach_dep.sbr"
+ -@erase ".\Debug\malloc.obj"
+ -@erase ".\Debug\malloc.sbr"
+ -@erase ".\Debug\mallocx.obj"
+ -@erase ".\Debug\mallocx.sbr"
+ -@erase ".\Debug\mark.obj"
+ -@erase ".\Debug\mark.sbr"
+ -@erase ".\Debug\mark_rts.obj"
+ -@erase ".\Debug\mark_rts.sbr"
+ -@erase ".\Debug\misc.obj"
+ -@erase ".\Debug\misc.sbr"
+ -@erase ".\Debug\new_hblk.obj"
+ -@erase ".\Debug\new_hblk.sbr"
+ -@erase ".\Debug\obj_map.obj"
+ -@erase ".\Debug\obj_map.sbr"
+ -@erase ".\Debug\os_dep.obj"
+ -@erase ".\Debug\os_dep.sbr"
+ -@erase ".\Debug\ptr_chck.obj"
+ -@erase ".\Debug\ptr_chck.sbr"
+ -@erase ".\Debug\reclaim.obj"
+ -@erase ".\Debug\reclaim.sbr"
+ -@erase ".\Debug\stubborn.obj"
+ -@erase ".\Debug\stubborn.sbr"
+ -@erase ".\Debug\typd_mlc.obj"
+ -@erase ".\Debug\typd_mlc.sbr"
+ -@erase ".\Debug\vc40.idb"
+ -@erase ".\Debug\vc40.pdb"
+ -@erase ".\Debug\win32_threads.obj"
+ -@erase ".\Debug\win32_threads.sbr"
+ -@erase ".\Debug\msvc_dbg.obj"
+ -@erase ".\Debug\msvc_dbg.sbr"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG" /D "GC_BUILD" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG" /D "GC_BUILD"\
+ /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" \
+ /D "GC_ASSERTIONS" /D "__STDC__" /D\
+ "GC_WIN32_THREADS" /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch" /YX /Fo"$(INTDIR)/"\
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=.\Debug/
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gc.bsc"
+BSC32_SBRS= \
+ ".\Debug\allchblk.sbr" \
+ ".\Debug\alloc.sbr" \
+ ".\Debug\blacklst.sbr" \
+ ".\Debug\checksums.sbr" \
+ ".\Debug\dbg_mlc.sbr" \
+ ".\Debug\dyn_load.sbr" \
+ ".\Debug\finalize.sbr" \
+ ".\Debug\gc_cpp.sbr" \
+ ".\Debug\headers.sbr" \
+ ".\Debug\mach_dep.sbr" \
+ ".\Debug\malloc.sbr" \
+ ".\Debug\mallocx.sbr" \
+ ".\Debug\mark.sbr" \
+ ".\Debug\mark_rts.sbr" \
+ ".\Debug\misc.sbr" \
+ ".\Debug\new_hblk.sbr" \
+ ".\Debug\obj_map.sbr" \
+ ".\Debug\os_dep.sbr" \
+ ".\Debug\ptr_chck.sbr" \
+ ".\Debug\reclaim.sbr" \
+ ".\Debug\stubborn.sbr" \
+ ".\Debug\typd_mlc.sbr" \
+ ".\Debug\msvc_dbg.sbr" \
+ ".\Debug\win32_threads.sbr"
+
+".\Debug\gc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\
+ /pdb:"$(OUTDIR)/gc.pdb" /map:"$(INTDIR)/gc.map" /debug /machine:I386\
+ /out:"$(OUTDIR)/gc.dll" /implib:"$(OUTDIR)/gc.lib"
+LINK32_OBJS= \
+ ".\Debug\allchblk.obj" \
+ ".\Debug\alloc.obj" \
+ ".\Debug\blacklst.obj" \
+ ".\Debug\checksums.obj" \
+ ".\Debug\dbg_mlc.obj" \
+ ".\Debug\dyn_load.obj" \
+ ".\Debug\finalize.obj" \
+ ".\Debug\gc_cpp.obj" \
+ ".\Debug\headers.obj" \
+ ".\Debug\mach_dep.obj" \
+ ".\Debug\malloc.obj" \
+ ".\Debug\mallocx.obj" \
+ ".\Debug\mark.obj" \
+ ".\Debug\mark_rts.obj" \
+ ".\Debug\misc.obj" \
+ ".\Debug\new_hblk.obj" \
+ ".\Debug\obj_map.obj" \
+ ".\Debug\os_dep.obj" \
+ ".\Debug\ptr_chck.obj" \
+ ".\Debug\reclaim.obj" \
+ ".\Debug\stubborn.obj" \
+ ".\Debug\typd_mlc.obj" \
+ ".\Debug\msvc_dbg.obj" \
+ ".\Debug\win32_threads.obj"
+
+".\Debug\gc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "gctest\Release"
+# PROP BASE Intermediate_Dir "gctest\Release"
+# PROP BASE Target_Dir "gctest"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "gctest\Release"
+# PROP Intermediate_Dir "gctest\Release"
+# PROP Target_Dir "gctest"
+OUTDIR=.\gctest\Release
+INTDIR=.\gctest\Release
+
+ALL : "gc - Win32 Release" ".\Release\gctest.exe"
+
+CLEAN :
+ -@erase ".\gctest\Release\test.obj"
+ -@erase ".\Release\gctest.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+test.c : tests\test.c
+ copy tests\test.c test.c
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /YX /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
+ "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS"\
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fp"$(INTDIR)/gctest.pch" \
+ /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\gctest\Release/
+CPP_SBRS=.\.
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gctest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"Release/gctest.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/gctest.pdb" /machine:I386 /out:"Release/gctest.exe"
+LINK32_OBJS= \
+ ".\gctest\Release\test.obj" \
+ ".\Release\gc.lib"
+
+".\Release\gctest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "gctest\Debug"
+# PROP BASE Intermediate_Dir "gctest\Debug"
+# PROP BASE Target_Dir "gctest"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "gctest\Debug"
+# PROP Intermediate_Dir "gctest\Debug"
+# PROP Target_Dir "gctest"
+OUTDIR=.\gctest\Debug
+INTDIR=.\gctest\Debug
+
+ALL : "gc - Win32 Debug" ".\Debug\gctest.exe" ".\gctest\Debug\gctest.bsc"
+
+CLEAN :
+ -@erase ".\Debug\gctest.exe"
+ -@erase ".\gctest\Debug\gctest.bsc"
+ -@erase ".\gctest\Debug\gctest.map"
+ -@erase ".\gctest\Debug\gctest.pdb"
+ -@erase ".\gctest\Debug\test.obj"
+ -@erase ".\gctest\Debug\test.sbr"
+ -@erase ".\gctest\Debug\vc40.idb"
+ -@erase ".\gctest\Debug\vc40.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\
+ /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR"$(INTDIR)/"\
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fp"$(INTDIR)/gctest.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\gctest\Debug/
+CPP_SBRS=.\gctest\Debug/
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gctest.bsc"
+BSC32_SBRS= \
+ ".\gctest\Debug\test.sbr"
+
+".\gctest\Debug\gctest.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:no /map /debug /machine:I386 /out:"Debug/gctest.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/gctest.pdb" /map:"$(INTDIR)/gctest.map" /debug /machine:I386\
+ /out:"Debug/gctest.exe"
+LINK32_OBJS= \
+ ".\Debug\gc.lib" \
+ ".\gctest\Debug\test.obj"
+
+".\Debug\gctest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "cord - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "cord\Release"
+# PROP BASE Intermediate_Dir "cord\Release"
+# PROP BASE Target_Dir "cord"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "cord\Release"
+# PROP Intermediate_Dir "cord\Release"
+# PROP Target_Dir "cord"
+OUTDIR=.\cord\Release
+INTDIR=.\cord\Release
+
+ALL : "gc - Win32 Release" ".\Release\de.exe"
+
+CLEAN :
+ -@erase ".\cord\Release\cordbscs.obj"
+ -@erase ".\cord\Release\cordxtra.obj"
+ -@erase ".\cord\Release\de.obj"
+ -@erase ".\cord\Release\de_win.obj"
+ -@erase ".\cord\Release\de_win.res"
+ -@erase ".\Release\de.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /YX /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "." /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
+ /Ilibatomic_ops-$(AO_VERSION)/src "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\cord\Release/
+CPP_SBRS=.\.
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)/de_win.res" /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/cord.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"Release/de.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)/de.pdb"\
+ /machine:I386 /out:"Release/de.exe"
+LINK32_OBJS= \
+ ".\cord\Release\cordbscs.obj" \
+ ".\cord\Release\cordxtra.obj" \
+ ".\cord\Release\de.obj" \
+ ".\cord\Release\de_win.obj" \
+ ".\cord\Release\de_win.res" \
+ ".\Release\gc.lib"
+
+".\Release\de.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "cord\Debug"
+# PROP BASE Intermediate_Dir "cord\Debug"
+# PROP BASE Target_Dir "cord"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "cord\Debug"
+# PROP Intermediate_Dir "cord\Debug"
+# PROP Target_Dir "cord"
+OUTDIR=.\cord\Debug
+INTDIR=.\cord\Debug
+
+ALL : "gc - Win32 Debug" ".\Debug\de.exe"
+
+CLEAN :
+ -@erase ".\cord\Debug\cordbscs.obj"
+ -@erase ".\cord\Debug\cordxtra.obj"
+ -@erase ".\cord\Debug\de.obj"
+ -@erase ".\cord\Debug\de.pdb"
+ -@erase ".\cord\Debug\de_win.obj"
+ -@erase ".\cord\Debug\de_win.res"
+ -@erase ".\cord\Debug\vc40.idb"
+ -@erase ".\cord\Debug\vc40.pdb"
+ -@erase ".\Debug\de.exe"
+ -@erase ".\Debug\de.ilk"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "." /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "." /I include /D "_DEBUG" /D "WIN32" /D\
+ "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX\
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\cord\Debug/
+CPP_SBRS=.\.
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)/de_win.res" /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/cord.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/de.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:yes\
+ /pdb:"$(OUTDIR)/de.pdb" /debug /machine:I386 /out:"Debug/de.exe"
+LINK32_OBJS= \
+ ".\cord\Debug\cordbscs.obj" \
+ ".\cord\Debug\cordxtra.obj" \
+ ".\cord\Debug\de.obj" \
+ ".\cord\Debug\de_win.obj" \
+ ".\cord\Debug\de_win.res" \
+ ".\Debug\gc.lib"
+
+".\Debug\de.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+################################################################################
+# Begin Target
+
+# Name "gc - Win32 Release"
+# Name "gc - Win32 Debug"
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\gc_cpp.cpp
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_RECLA=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\gc_cpp.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_RECLA=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\gc_cpp.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+".\Release\gc_cpp.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_RECLA=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\gc_cpp.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_RECLA=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\gc_cpp.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+".\Debug\gc_cpp.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\reclaim.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_RECLA=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_RECLA=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\reclaim.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+".\Release\reclaim.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_RECLA=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_RECLA=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\reclaim.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+".\Debug\reclaim.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\os_dep.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_OS_DE=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OS_DE=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+ ".\vd\PCR_VD.h"\
+
+
+".\Release\os_dep.obj" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+".\Release\os_dep.sbr" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_OS_DE=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OS_DE=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+ ".\vd\PCR_VD.h"\
+
+
+".\Debug\os_dep.obj" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+".\Debug\os_dep.sbr" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\misc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MISC_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MISC_=\
+ ".\il\PCR_IL.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\misc.obj" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+".\Release\misc.sbr" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MISC_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MISC_=\
+ ".\il\PCR_IL.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\misc.obj" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+".\Debug\misc.sbr" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mark_rts.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MARK_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mark_rts.obj" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+".\Release\mark_rts.sbr" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MARK_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mark_rts.obj" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+".\Debug\mark_rts.sbr" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mach_dep.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MACH_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MACH_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mach_dep.obj" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+".\Release\mach_dep.sbr" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MACH_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MACH_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mach_dep.obj" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+".\Debug\mach_dep.sbr" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\headers.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_HEADE=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_HEADE=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\headers.obj" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+".\Release\headers.sbr" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_HEADE=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_HEADE=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\headers.obj" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+".\Debug\headers.sbr" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\alloc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_ALLOC=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLOC=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\alloc.obj" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+".\Release\alloc.sbr" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_ALLOC=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLOC=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\alloc.obj" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+".\Debug\alloc.sbr" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\allchblk.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_ALLCH=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLCH=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\allchblk.obj" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+".\Release\allchblk.sbr" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_ALLCH=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLCH=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\allchblk.obj" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+".\Debug\allchblk.sbr" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\stubborn.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_STUBB=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_STUBB=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\stubborn.obj" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+".\Release\stubborn.sbr" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_STUBB=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_STUBB=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\stubborn.obj" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+".\Debug\stubborn.sbr" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\obj_map.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_OBJ_M=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OBJ_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\obj_map.obj" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+".\Release\obj_map.sbr" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_OBJ_M=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OBJ_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\obj_map.obj" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+".\Debug\obj_map.sbr" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\new_hblk.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_NEW_H=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_NEW_H=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\new_hblk.obj" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+".\Release\new_hblk.sbr" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_NEW_H=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_NEW_H=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\new_hblk.obj" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+".\Debug\new_hblk.sbr" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mark.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MARK_C=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mark.obj" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+".\Release\mark.sbr" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MARK_C=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mark.obj" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+".\Debug\mark.sbr" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\malloc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MALLO=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLO=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\malloc.obj" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+".\Release\malloc.sbr" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MALLO=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLO=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\malloc.obj" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+".\Debug\malloc.sbr" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mallocx.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MALLX=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLX=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mallocx.obj" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+".\Release\mallocx.sbr" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MALLX=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLX=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mallocx.obj" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+".\Debug\mallocx.sbr" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\finalize.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_FINAL=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_FINAL=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\finalize.obj" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+".\Release\finalize.sbr" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_FINAL=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_FINAL=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\finalize.obj" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+".\Debug\finalize.sbr" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\dbg_mlc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_DBG_M=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DBG_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\dbg_mlc.obj" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+".\Release\dbg_mlc.sbr" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_DBG_M=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DBG_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\dbg_mlc.obj" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+".\Debug\dbg_mlc.sbr" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\blacklst.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_BLACK=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_BLACK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\blacklst.obj" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+".\Release\blacklst.sbr" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_BLACK=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_BLACK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\blacklst.obj" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+".\Debug\blacklst.sbr" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\typd_mlc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_TYPD_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\gc_typed.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_TYPD_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\typd_mlc.obj" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+".\Release\typd_mlc.sbr" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_TYPD_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\gc_typed.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_TYPD_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\typd_mlc.obj" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+".\Debug\typd_mlc.sbr" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\ptr_chck.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_PTR_C=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_PTR_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\ptr_chck.obj" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+".\Release\ptr_chck.sbr" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_PTR_C=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_PTR_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\ptr_chck.obj" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+".\Debug\ptr_chck.sbr" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\dyn_load.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_DYN_L=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DYN_L=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\dyn_load.obj" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+".\Release\dyn_load.sbr" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_DYN_L=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DYN_L=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\dyn_load.obj" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+".\Debug\dyn_load.sbr" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\win32_threads.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_WIN32=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_WIN32=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\win32_threads.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+".\Release\win32_threads.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_WIN32=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_WIN32=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\win32_threads.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+".\Debug\win32_threads.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\msvc_dbg.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_WIN32=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\private\msvc_dbg.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_WIN32=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\msvc_dbg.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+".\Release\msvc_dbg.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_WIN32=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\private\msvc_dbg.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_WIN32=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\msvc_dbg.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+".\Debug\msvc_dbg.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\checksums.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_CHECK=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_CHECK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\checksums.obj" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+".\Release\checksums.sbr" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_CHECK=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_CHECK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\checksums.obj" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+".\Debug\checksums.sbr" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+# End Target
+################################################################################
+# Begin Target
+
+# Name "gctest - Win32 Release"
+# Name "gctest - Win32 Debug"
+
+!IF "$(CFG)" == "gctest - Win32 Release"
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Project Dependency
+
+# Project_Dep_Name "gc"
+
+!IF "$(CFG)" == "gctest - Win32 Release"
+
+"gc - Win32 Release" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+"gc - Win32 Debug" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Debug"
+
+!ENDIF
+
+# End Project Dependency
+################################################################################
+# Begin Source File
+
+SOURCE=.\tests\test.c
+DEP_CPP_TEST_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\gc_typed.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_TEST_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+!IF "$(CFG)" == "gctest - Win32 Release"
+
+
+".\gctest\Release\test.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+
+".\gctest\Debug\test.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
+
+".\gctest\Debug\test.sbr" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+# End Target
+################################################################################
+# Begin Target
+
+# Name "cord - Win32 Release"
+# Name "cord - Win32 Debug"
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Project Dependency
+
+# Project_Dep_Name "gc"
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+"gc - Win32 Release" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+"gc - Win32 Debug" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Debug"
+
+!ENDIF
+
+# End Project Dependency
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\de_win.c
+DEP_CPP_DE_WI=\
+ ".\include\cord.h"\
+ ".\cord\de_cmds.h"\
+ ".\cord\de_win.h"\
+ ".\include\private\cord_pos.h"\
+
+NODEP_CPP_DE_WI=\
+ ".\include\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\de_win.obj" : $(SOURCE) $(DEP_CPP_DE_WI) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\de_win.obj" : $(SOURCE) $(DEP_CPP_DE_WI) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\de.c
+DEP_CPP_DE_C2e=\
+ ".\include\cord.h"\
+ ".\cord\de_cmds.h"\
+ ".\cord\de_win.h"\
+ ".\include\private\cord_pos.h"\
+
+NODEP_CPP_DE_C2e=\
+ ".\include\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\de.obj" : $(SOURCE) $(DEP_CPP_DE_C2e) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\de.obj" : $(SOURCE) $(DEP_CPP_DE_C2e) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\cordxtra.c
+DEP_CPP_CORDX=\
+ ".\include\cord.h"\
+ ".\include\ec.h"\
+ ".\include\private\cord_pos.h"\
+
+NODEP_CPP_CORDX=\
+ ".\include\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\cordxtra.obj" : $(SOURCE) $(DEP_CPP_CORDX) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\cordxtra.obj" : $(SOURCE) $(DEP_CPP_CORDX) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\cordbscs.c
+DEP_CPP_CORDB=\
+ ".\include\cord.h"\
+ ".\include\private\cord_pos.h"\
+
+NODEP_CPP_CORDB=\
+ ".\include\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\cordbscs.obj" : $(SOURCE) $(DEP_CPP_CORDB) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\cordbscs.obj" : $(SOURCE) $(DEP_CPP_CORDB) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\de_win.RC
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\de_win.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x809 /fo"$(INTDIR)/de_win.res" /i "cord" /d "NDEBUG" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\de_win.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x809 /fo"$(INTDIR)/de_win.res" /i "cord" /d "_DEBUG" $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/tools/build/v2/engine/boehm_gc/NT_X64_STATIC_THREADS_MAKEFILE b/tools/build/v2/engine/boehm_gc/NT_X64_STATIC_THREADS_MAKEFILE
new file mode 100644
index 0000000000..91a0f60efc
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/NT_X64_STATIC_THREADS_MAKEFILE
@@ -0,0 +1,74 @@
+# Makefile for Windows NT. Assumes Microsoft compiler.
+# DLLs are included in the root set under NT, but not under win32S.
+# Use "nmake nodebug=1 all" for optimized versions of library, gctest and editor.
+
+MY_CPU=AMD64
+CPU=$(MY_CPU)
+!include <ntwin32.mak>
+
+# Make sure that .cc is not viewed as a suffix. It is for VC++2005, but
+# not earlier versions. We can deal with either, but not inconsistency.
+.SUFFIXES:
+.SUFFIXES: .obj .cpp .c
+
+# Atomic_ops installation directory. For win32, the source directory
+# should do, since we only need the headers.
+# We assume this was manually unpacked, since I'm not sure there is
+# a Windows standard command line tool to do this.
+AO_VERSION=1.2
+AO_SRC_DIR=libatomic_ops-$(AO_VERSION)/src
+AO_INCLUDE_DIR=$(AO_SRC_DIR)
+
+OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj malloc.obj stubborn.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gc_cpp.obj mallocx.obj win32_threads.obj msvc_dbg.obj thread_local_alloc.obj
+
+all: gctest.exe cord\de.exe test_cpp.exe
+
+.c.obj:
+ $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -D__STDC__ -DGC_NOT_DLL -DGC_WIN32_THREADS -DTHREAD_LOCAL_ALLOC $*.c /Fo$*.obj /wd4701 -D_CRT_SECURE_NO_DEPRECATE
+# Disable "may not be initialized" warnings. They're too approximate.
+# Disable crt security warnings, since unfortunately they warn about all sorts
+# of safe uses of strncpy. It would be nice to leave the rest enabled.
+
+.cpp.obj:
+ $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL $*.CPP -DGC_WIN32_THREADS -DTHREAD_LOCAL_ALLOC /Fo$*.obj -D_CRT_SECURE_NO_DEPRECATE
+
+$(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\private\msvc_dbg.h
+
+gc.lib: $(OBJS)
+ lib /MACHINE:X64 /out:gc.lib $(OBJS)
+
+gctest.exe: tests\test.obj gc.lib
+# This produces a "GUI" applications that opens no windows and writes to the log file
+# "gc.log". This was done to make the result runnable under win32s and
+# should be fixed.
+ $(link) $(ldebug) $(guiflags) -stack:131072 -out:$*.exe tests\test.obj $(guilibs) gc.lib
+
+cord\de_win.rbj: cord\de_win.res
+ cvtres /MACHINE:$(MY_CPU) /OUT:cord\de_win.rbj cord\de_win.res
+
+cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h cord\de_cmds.h
+
+cord\de_win.res: cord\de_win.rc cord\de_win.h cord\de_cmds.h
+ $(rc) $(rcvars) -r -fo cord\de_win.res cord\de_win.rc
+
+# Cord/de is a real win32 gui application.
+cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib
+ $(link) $(ldebug) $(guiflags) -stack:16384 -out:cord\de.exe cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib $(guilibs)
+
+gc_cpp.obj: include\gc_cpp.h include\gc.h
+
+gc_cpp.cpp: gc_cpp.cc
+ copy gc_cpp.cc gc_cpp.cpp
+
+test_cpp.cpp: tests\test_cpp.cc
+ copy tests\test_cpp.cc test_cpp.cpp
+
+# This generates the C++ test executable. The executable expects
+# a single numeric argument, which is the number of iterations.
+# The output appears in the file "gc.log".
+test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib
+ $(link) $(ldebug) $(guiflags) -stack:16384 -out:test_cpp.exe test_cpp.obj gc.lib $(guilibs)
+
+AO_SCR_DIR:
+ tar xvfz $(AO_SRC_DIR).tar.gz;
+
diff --git a/tools/build/v2/engine/boehm_gc/OS2_MAKEFILE b/tools/build/v2/engine/boehm_gc/OS2_MAKEFILE
new file mode 100644
index 0000000000..c6bad7abcb
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/OS2_MAKEFILE
@@ -0,0 +1,45 @@
+# Makefile for OS/2. Assumes IBM's compiler, static linking, and a single thread.
+# Adding dynamic linking support seems easy, but takes a little bit of work.
+# Adding thread support may be nontrivial, since we haven't yet figured out how to
+# look at another thread's registers.
+
+# Significantly revised for GC version 4.4 by Mark Boulter (Jan 1994).
+
+OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj malloc.obj stubborn.obj typd_mlc.obj ptr_chck.obj mallocx.obj
+
+CORDOBJS= cord\cordbscs.obj cord\cordxtra.obj cord\cordprnt.obj
+
+CC= icc
+CFLAGS= /O /Q /DSMALL_CONFIG /DALL_INTERIOR_POINTERS
+# Use /Ti instead of /O for debugging
+# Setjmp_test may yield overly optimistic results when compiled
+# without optimization.
+
+all: $(OBJS) gctest.exe cord\cordtest.exe
+
+$(OBJS) test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h
+
+## ERASE THE LIB FIRST - if it is already there then this command will fail
+## (make sure its there or erase will fail!)
+gc.lib: $(OBJS)
+ echo . > gc.lib
+ erase gc.lib
+ LIB gc.lib $(OBJS), gc.lst
+
+mach_dep.obj: mach_dep.c
+ $(CC) $(CFLAGS) /C mach_dep.c
+
+gctest.exe: test.obj gc.lib
+ $(CC) $(CFLAGS) /B"/STACK:524288" /Fegctest test.obj gc.lib
+
+cord\cordbscs.obj: cord\cordbscs.c include\cord.h include\private\cord_pos.h
+ $(CC) $(CFLAGS) /C /Focord\cordbscs cord\cordbscs.c
+
+cord\cordxtra.obj: cord\cordxtra.c include\cord.h include\private\cord_pos.h include\ec.h
+ $(CC) $(CFLAGS) /C /Focord\cordxtra cord\cordxtra.c
+
+cord\cordprnt.obj: cord\cordprnt.c include\cord.h include\private\cord_pos.h include\ec.h
+ $(CC) $(CFLAGS) /C /Focord\cordprnt cord\cordprnt.c
+
+cord\cordtest.exe: cord\cordtest.c include\cord.h include\private\cord_pos.h include\ec.h $(CORDOBJS) gc.lib
+ $(CC) $(CFLAGS) /B"/STACK:65536" /Fecord\cordtest cord\cordtest.c gc.lib $(CORDOBJS)
diff --git a/tools/build/v2/engine/boehm_gc/PCR-Makefile b/tools/build/v2/engine/boehm_gc/PCR-Makefile
new file mode 100644
index 0000000000..db4c9f0181
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/PCR-Makefile
@@ -0,0 +1,68 @@
+#
+# Default target
+#
+
+default: gc.o
+
+include ../config/common.mk
+
+#
+# compilation flags, etc.
+#
+
+
+CPPFLAGS = $(INCLUDE) $(CONFIG_CPPFLAGS) \
+ -DPCR_NO_RENAME -DPCR_NO_HOSTDEP_ERR
+#CFLAGS = -DPCR $(CONFIG_CFLAGS)
+CFLAGS = -DPCR $(CONFIG_CFLAGS)
+SPECIALCFLAGS = # For code involving asm's
+
+ASPPFLAGS = $(INCLUDE) $(CONFIG_ASPPFLAGS) \
+ -DPCR_NO_RENAME -DPCR_NO_HOSTDEP_ERR -DASM
+
+ASFLAGS = $(CONFIG_ASFLAGS)
+
+LDRFLAGS = $(CONFIG_LDRFLAGS)
+
+LDFLAGS = $(CONFIG_LDFLAGS)
+
+#
+#
+#
+#
+# BEGIN PACKAGE-SPECIFIC PART
+#
+#
+#
+#
+
+# Fix to point to local pcr installation directory.
+PCRDIR= ..
+
+COBJ= alloc.o reclaim.o allchblk.o misc.o os_dep.o mark_rts.o headers.o mark.o obj_map.o pcr_interface.o blacklst.o finalize.o new_hblk.o real_malloc.o dyn_load.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o typd_mlc.o ptr_chck.o mallocx.o
+
+CSRC= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c typd_mlc.c ptr_chck.c mallocx.c
+
+SHELL= /bin/sh
+
+default: gc.o
+
+gc.o: $(COBJ) mach_dep.o
+ $(LDR) $(CONFIG_LDRFLAGS) -o gc.o $(COBJ) mach_dep.o
+
+
+mach_dep.o: mach_dep.c mips_mach_dep.s rs6000_mach_dep.s if_mach if_not_there
+ rm -f mach_dep.o
+ ./if_mach MIPS "" as -o mach_dep.o mips_mach_dep.s
+ ./if_mach POWERPC AIX as -o mach_dep.o rs6000_mach_dep.s
+ ./if_mach ALPHA "" as -o mach_dep.o alpha_mach_dep.s
+ ./if_mach SPARC SOLARIS as -o mach_dep.o sparc_mach_dep.s
+ ./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) mach_dep.c
+
+if_mach: if_mach.c gcconfig.h
+ $(CC) $(CFLAGS) -o if_mach if_mach.c
+
+if_not_there: if_not_there.c
+ $(CC) $(CFLAGS) -o if_not_there if_not_there.c
+
+
diff --git a/tools/build/v2/engine/boehm_gc/README.QUICK b/tools/build/v2/engine/boehm_gc/README.QUICK
new file mode 100644
index 0000000000..5ffa505c9e
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/README.QUICK
@@ -0,0 +1,88 @@
+Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+Copyright (c) 1999-2001 by Hewlett-Packard. All rights reserved.
+
+THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+
+Permission is hereby granted to use or copy this program
+for any purpose, provided the above notices are retained on all copies.
+Permission to modify the code and to distribute modified code is granted,
+provided the above notices are retained, and a notice that the code was
+modified is included with the above copyright notice.
+
+A few files have other copyright holders. A few of the files needed
+to use the GNU-style build procedure come with a modified GPL license
+that appears not to significantly restrict use of the collector, though
+use of those files for a purpose other than building the collector may
+require the resulting code to be covered by the GPL.
+
+For more details and the names of other contributors, see the
+doc/README* files and include/gc.h. This file describes typical use of
+the collector on a machine that is already supported.
+
+For the version number, see doc/README or version.h.
+
+INSTALLATION:
+Under UN*X, Linux:
+Alternative 1 (the old way): type "make test" in this directory.
+ Link against gc.a. With the most recent GC distributions
+ you may have to copy Makefile.direct to Makefile first.
+
+Alternative 2 (the new way): type
+ "./configure --prefix=<dir>; make; make check; make install".
+ Link against <dir>/lib/libgc.a or <dir>/lib/libgc.so.
+ See README.autoconf for details
+
+Under Windows 95, 98, Me, NT, or 2000:
+copy the appropriate makefile to MAKEFILE, read it, and type "nmake test".
+(Under Windows, this assumes you have Microsoft command-line tools
+installed, and suitably configured.)
+Read the machine specific README in the doc directory if one exists.
+
+If you need thread support, you will need to follow the special
+platform-dependent instructions (win32), or define GC_THREADS
+as described in Makefile (Makefile.direct), or possibly use
+--enable-threads=posix when running the configure script.
+
+If you wish to use the cord (structured string) library with the stand-alone
+Makefile.direct, type "make cords", after copying to "Makefile".
+(This requires an ANSI C compiler. You may
+need to redefine CC in the Makefile. The CORD_printf implementation in
+cordprnt.c is known to be less than perfectly portable. The rest of the
+package should still work.)
+
+If you wish to use the collector from C++, type "make c++", or use
+--enable-cplusplus with the configure script. With Makefile.direct,
+hese add further files to gc.a and to the include subdirectory. With the
+alternat build process,this generates libgccpp.
+See cord/cord.h and include/gc_cpp.h.
+
+TYPICAL USE:
+Include "gc.h" from the include subdirectory. Link against the
+appropriate library ("gc.a" under UN*X). Replace calls to malloc
+by calls to GC_MALLOC, and calls to realloc by calls to GC_REALLOC.
+If the object is known to never contain pointers, use GC_MALLOC_ATOMIC
+instead of GC_MALLOC.
+
+Define GC_DEBUG before including gc.h for additional checking.
+
+More documentation on the collector interface can be found at
+http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcinterface.html,
+in doc/README and other files in the doc directory, and in include/gc.h .
+
+WARNINGS:
+
+Do not store the only pointer to an object in memory allocated
+with system malloc, since the collector usually does not scan
+memory allocated in this way.
+
+Use with threads may be supported on your system, but requires the
+collector to be built with thread support. See Makefile. The collector
+does not guarantee to scan thread-local storage (e.g. of the kind
+accessed with pthread_getspecific()). The collector does scan
+thread stacks though, so generally the best solution is to ensure that
+any pointers stored in thread-local storage are also stored on the
+thread's stack for the duration of their lifetime.
+
diff --git a/tools/build/v2/engine/boehm_gc/SMakefile.amiga b/tools/build/v2/engine/boehm_gc/SMakefile.amiga
new file mode 100644
index 0000000000..94fb723865
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/SMakefile.amiga
@@ -0,0 +1,177 @@
+
+# Rewritten smakefile for amiga / sas/c. -Kjetil M.
+# Dont use the cord-package if you define parm=both or parm=reg.
+
+
+#----------------TOOLS--------------------------------
+CC=sc
+LINKER=slink
+LIBER=oml
+
+#----------------CPU OPTIONS--------------------------
+
+CPU=68060
+
+#----------------FPU OPTIONS--------------------------
+
+MATH=8
+MATHLIB=LIB:scm881.lib
+
+#----------------COMPILER OPTIONS---------------------
+
+IGNORE= IGNORE=85 IGNORE=154 IGNORE=161 IGNORE=100
+
+OPTIMIZE=optimize optimizetime optglobal optimizerdepth=100 optimizerpeephole optloop OPTSCHED optimizerinlocal optimizerrecurdepth=100
+# optimizerinline optimizercomplexity=100
+
+OPT= $(OPTIMIZE) CPU=$(CPU) math=$(MATH) NOSTACKCHECK VERBOSE \
+MAPHUNK NOVERSION NOICONS nodebug \
+parm=reg \
+DEFINE __USE_SYSBASE
+
+
+SOPT= $(OPT) $(IGNORE) \
+DEFINE AMIGA_SKIP_SEG \
+DEFINE ATOMIC_UNCOLLECTABLE \
+DEFINE GC_AMIGA_FASTALLOC \
+DEFINE GC_AMIGA_RETRY \
+DEFINE GC_AMIGA_PRINTSTATS \
+DEFINE GC_AMIGA_GC
+
+
+#DEFINE ALL_INTERIOR_POINTERS \
+
+
+SCOPT= $(SOPT) define GC_AMIGA_MAKINGLIB
+
+CSCOPT= $(OPT) DEFINE AMIGA IGNORE=100 IGNORE=161
+
+#------------------LINKING----------------------------
+
+
+all: gctest setjmp_t cord/cordtest
+
+clean:
+ delete *.lib gctest setjmp_t *.o *.lnk cord/*.o cord/*.lib cord/*.lnk cord/cordtest
+ smake
+
+test: setjmp_t gctest cord/cordtest
+ setjmp_t
+ gctest
+ cord/cordtest
+
+gctest: gc$(CPU).lib GCAmigaOS$(CPU).lib test.o
+ $(LINKER) LIB:c.o test.o TO gctest LIB gc$(CPU).lib LIB:sc.lib $(MATHLIB)
+
+setjmp_t: setjmp_t.o gc.h
+ $(LINKER) LIB:c.o setjmp_t.o to setjmp_t lib LIB:sc.lib
+
+cord/cordtest: cord/cordtest.o cord/cord$(CPU).lib gc$(CPU).lib
+ slink LIB:c.o cord/cordtest.o LIB $(MATHLIB) gc$(CPU).lib cord/cord$(CPU).lib LIB:sc.lib TO cord/cordtest
+
+
+#------------------LIBBING----------------------------
+
+OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o real_malloc.o dyn_load.o dbg_mlc.o malloc.o stubborn.o checksums.o typd_mlc.o ptr_chck.o mallocx.o
+
+gc$(CPU).lib: $(OBJS)
+ $(LIBER) gc$(CPU).lib r $(OBJS)
+
+
+COBJS = cord/cordbscs.o cord/cordprnt.o cord/cordxtra.o
+
+cord/cord$(CPU).lib: $(COBJS)
+ oml cord/cord$(CPU).lib r $(COBJS)
+
+#------------------COMPILING--------------------------
+
+INC= gc_private.h gc_hdrs.h gc.h gcconfig.h
+
+alloc.o : alloc.c $(INC)
+ $(CC) alloc.c $(SCOPT) ignore=7
+
+reclaim.o : reclaim.c $(INC)
+ $(CC) reclaim.c $(SCOPT)
+
+allchblk.o : allchblk.c $(INC)
+ $(CC) allchblk.c $(SCOPT)
+
+misc.o : misc.c $(INC)
+ $(CC) misc.c $(SCOPT)
+
+os_dep.o : os_dep.c $(INC) AmigaOS.c
+ $(CC) os_dep.c $(SCOPT)
+
+mark_rts.o : mark_rts.c $(INC)
+ $(CC) mark_rts.c $(SCOPT)
+
+headers.o : headers.c $(INC)
+ $(CC) headers.c $(SCOPT)
+
+mark.o : mark.c $(INC)
+ $(CC) mark.c $(SCOPT)
+
+obj_map.o : obj_map.c $(INC)
+ $(CC) obj_map.c $(SCOPT)
+
+blacklst.o : blacklst.c $(INC)
+ $(CC) blacklst.c $(SCOPT)
+
+finalize.o : finalize.c $(INC)
+ $(CC) finalize.c $(SCOPT) noopt #Could sas/c still have problems with this one? Gctest sometimes fails to finalize all.
+
+new_hblk.o : new_hblk.c $(INC)
+ $(CC) new_hblk.c $(SCOPT)
+
+real_malloc.o : real_malloc.c $(INC)
+ $(CC) real_malloc.c $(SCOPT)
+
+dyn_load.o : dyn_load.c $(INC)
+ $(CC) dyn_load.c $(SCOPT)
+
+dbg_mlc.o : dbg_mlc.c $(INC)
+ $(CC) dbg_mlc.c $(SCOPT)
+
+malloc.o : malloc.c $(INC)
+ $(CC) malloc.c $(SCOPT)
+
+mallocx.o : mallocx.c $(INC)
+ $(CC) mallocx.c $(SCOPT)
+
+stubborn.o : stubborn.c $(INC)
+ $(CC) stubborn.c $(SCOPT)
+
+checksums.o : checksums.c $(INC)
+ $(CC) checksums.c $(SCOPT)
+
+typd_mlc.o: typd_mlc.c $(INC)
+ $(CC) typd_mlc.c $(SCOPT)
+
+mach_dep.o : mach_dep.c $(INC)
+ $(CC) mach_dep.c $(SCOPT)
+
+ptr_chck.o: ptr_chck.c $(INC)
+ $(CC) ptr_chck.c $(SCOPT)
+
+test.o : test.c $(INC)
+ $(CC) test.c $(SOPT)
+
+setjmp_t: setjmp_t.c gc.h
+ $(CC) setjmp_t.c $(SOPT)
+
+
+# cords:
+
+cord/cordbscs.o: cord/cordbscs.c
+ sc cord/cordbscs.c $(CSCOPT)
+
+cord/cordprnt.o: cord/cordprnt.c
+ sc cord/cordprnt.c $(CSCOPT)
+
+cord/cordxtra.o: cord/cordxtra.c
+ sc cord/cordxtra.c $(CSCOPT)
+
+cord/cordtest.o: cord/cordtest.c
+ sc cord/cordtest.c $(CSCOPT)
+
+
diff --git a/tools/build/v2/engine/boehm_gc/WCC_MAKEFILE b/tools/build/v2/engine/boehm_gc/WCC_MAKEFILE
new file mode 100644
index 0000000000..6b1d78baec
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/WCC_MAKEFILE
@@ -0,0 +1,196 @@
+# Makefile for Watcom C/C++ 10.5, 10.6, 11.0 on NT, OS2 and DOS4GW.
+# May work with Watcom 10.0.
+
+# Uncoment one of the lines below for cross compilation.
+SYSTEM=MSWIN32
+#SYSTEM=DOS4GW
+#SYSTEM=OS2
+
+# The collector can be built either as dynamic or as static library.
+# Select the library type you need.
+#MAKE_AS_DLL=1
+MAKE_AS_LIB=1
+
+# Select calling conventions.
+# Possible choices are r and s.
+CALLING=s
+
+# Select target CPU.
+# Possible choices are 3, 4, 5, and 6.
+# The last choice available only since version 11.0.
+CPU=5
+
+# Set optimization options.
+# Watcom before 11.0 does not support option "-oh".
+OPTIM=-oneatx -s
+#OPTIM=-ohneatx -s
+
+DEFS=-DALL_INTERIOR_POINTERS #-DSMALL_CONFIG #-DGC_DEBUG
+
+
+#####
+
+!ifndef SYSTEM
+!ifdef __MSDOS__
+SYSTEM=DOS4GW
+!else ifdef __NT__
+SYSTEM=MSWIN32
+!else ifdef __OS2__
+SYSTEM=OS2
+!else
+SYSTEM=Unknown
+!endif
+!endif
+
+!define $(SYSTEM)
+
+!ifdef DOS4GW
+SYSFLAG=-DDOS4GW -bt=dos
+!else ifdef MSWIN32
+SYSFLAG=-DMSWIN32 -bt=nt
+!else ifdef OS2
+SYSFLAG=-DOS2 -bt=os2
+!else
+!error undefined or unsupported target platform: $(SYSTEM)
+!endif
+!ifdef MAKE_AS_DLL
+DLLFLAG=-bd -DGC_DLL
+TEST_DLLFLAG=-DGC_DLL
+!else ifdef MAKE_AS_LIB
+DLLFLAG=
+TEST_DLLFLAG=
+!else
+!error Either MAKE_AS_LIB or MAKE_AS_DLL should be defined
+!endif
+
+CC=wcc386
+CXX=wpp386
+
+# -DUSE_GENERIC is required !
+CFLAGS=-$(CPU)$(CALLING) $(OPTIM) -zp4 -zc $(SYSFLAG) $(DLLFLAG) -DGC_BUILD -DUSE_GENERIC $(DEFS)
+CXXFLAGS= $(CFLAGS)
+TEST_CFLAGS=-$(CPU)$(CALLING) $(OPTIM) -zp4 -zc $(SYSFLAG) $(TEST_DLLFLAG) $(DEFS)
+TEST_CXXFLAGS= $(TEST_CFLAGS)
+
+OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj &
+ mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj &
+ obj_map.obj blacklst.obj finalize.obj new_hblk.obj &
+ dbg_mlc.obj malloc.obj stubborn.obj dyn_load.obj &
+ typd_mlc.obj ptr_chck.obj mallocx.obj
+
+all: gc.lib gctest.exe test_cpp.exe
+
+!ifdef MAKE_AS_DLL
+
+gc.lib: gc.dll gc_cpp.obj
+ *wlib -b -c -n -p=512 $@ +gc.dll +gc_cpp.obj
+
+gc.dll: $(OBJS) .AUTODEPEND
+ @%create $*.lnk
+!ifdef DOS4GW
+ @%append $*.lnk sys os2v2_dll
+!else ifdef MSWIN32
+ @%append $*.lnk sys nt_dll
+!else ifdef OS2
+ @%append $*.lnk sys os2v2_dll
+!endif
+ @%append $*.lnk name $*
+ @for %i in ($(OBJS)) do @%append $*.lnk file '%i'
+!ifeq CALLING s
+ @%append $*.lnk export GC_is_marked
+ @%append $*.lnk export GC_incr_bytes_allocd
+ @%append $*.lnk export GC_incr_bytes_freed
+ @%append $*.lnk export GC_generic_malloc_words_small
+!else
+ @%append $*.lnk export GC_is_marked_
+ @%append $*.lnk export GC_incr_bytes_allocd_
+ @%append $*.lnk export GC_incr_bytes_freed_
+ @%append $*.lnk export GC_generic_malloc_words_small_
+!endif
+ *wlink @$*.lnk
+!else
+gc.lib: $(OBJS) gc_cpp.obj
+ @%create $*.lb1
+ @for %i in ($(OBJS)) do @%append $*.lb1 +'%i'
+ @%append $*.lb1 +'gc_cpp.obj'
+ *wlib -b -c -n -p=512 $@ @$*.lb1
+
+!endif
+
+
+gctest.exe: test.obj gc.lib
+ %create $*.lnk
+!ifdef DOS4GW
+ @%append $*.lnk sys dos4g
+!else ifdef MSWIN32
+ @%append $*.lnk sys nt
+!else ifdef OS2
+ @%append $*.lnk sys os2v2
+!endif
+ @%append $*.lnk op case
+ @%append $*.lnk op stack=256K
+ @%append $*.lnk name $*
+ @%append $*.lnk file test.obj
+ @%append $*.lnk library gc.lib
+!ifdef MAKE_AS_DLL
+!ifeq CALLING s
+ @%append $*.lnk import GC_is_marked gc
+!else
+ @%append $*.lnk import GC_is_marked_ gc
+!endif
+!endif
+ *wlink @$*.lnk
+test_cpp.exe: test_cpp.obj gc.lib
+ %create $*.lnk
+!ifdef DOS4GW
+ @%append $*.lnk sys dos4g
+!else ifdef MSWIN32
+ @%append $*.lnk sys nt
+!else ifdef OS2
+ @%append $*.lnk sys os2v2
+!endif
+ @%append $*.lnk op case
+ @%append $*.lnk op stack=256K
+ @%append $*.lnk name $*
+ @%append $*.lnk file test_cpp.obj
+ @%append $*.lnk library gc.lib
+!ifdef MAKE_AS_DLL
+!ifeq CALLING s
+ @%append $*.lnk import GC_incr_bytes_allocd gc
+ @%append $*.lnk import GC_incr_bytes_freed gc
+ @%append $*.lnk import GC_generic_malloc_words_small gc
+!else
+ @%append $*.lnk import GC_incr_bytes_allocd_ gc
+ @%append $*.lnk import GC_incr_bytes_freed_ gc
+ @%append $*.lnk import GC_generic_malloc_words_small_ gc
+!endif
+!endif
+ *wlink @$*.lnk
+
+gc_cpp.obj: gc_cpp.cc .AUTODEPEND
+ $(CXX) $(TEST_CXXFLAGS) -iinclude $*.cc
+test.obj: tests\test.c .AUTODEPEND
+ $(CC) $(TEST_CFLAGS) $*.c
+test_cpp.obj: tests\test_cpp.cc .AUTODEPEND
+ $(CXX) $(TEST_CXXFLAGS) -iinclude $*.cc
+
+
+.c.obj: .AUTODEPEND
+ $(CC) $(CFLAGS) $*.c
+
+.cc.obj: .AUTODEPEND
+ $(CXX) $(CXXFLAGS) $*.cc
+
+clean : .SYMBOLIC
+ @if exist *.obj del *.obj
+ @if exist *.map del *.map
+ @if exist *.lnk del *.lnk
+ @if exist *.lb1 del *.lb1
+ @if exist *.sym del *.sym
+ @if exist *.err del *.err
+ @if exist *.tmp del *.tmp
+ @if exist *.lst del *.lst
+ @if exist *.exe del *.exe
+ @if exist *.log del *.log
+ @if exist *.lib del *.lib
+ @if exist *.dll del *.dll
diff --git a/tools/build/v2/engine/boehm_gc/acinclude.m4 b/tools/build/v2/engine/boehm_gc/acinclude.m4
new file mode 100644
index 0000000000..72602a0040
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/acinclude.m4
@@ -0,0 +1,49 @@
+#
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose, provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+#
+# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
+
+# GC_SET_VERSION
+# sets and AC_DEFINEs GC_VERSION_MAJOR, GC_VERSION_MINOR and GC_ALPHA_VERSION
+# based on the contents of PACKAGE_VERSION; PACKAGE_VERSION must conform to
+# [0-9]+[.][0-9]+(alpha[0.9]+)?
+# in lex syntax; if there is no alpha number, GC_ALPHA_VERSION is empty
+#
+AC_DEFUN(GC_SET_VERSION, [
+ AC_MSG_CHECKING(GC version numbers)
+ GC_VERSION_MAJOR=`echo $PACKAGE_VERSION | sed 's/^\([[0-9]][[0-9]]*\)[[.]].*$/\1/g'`
+ GC_VERSION_MINOR=`echo $PACKAGE_VERSION | sed 's/^[[^.]]*[[.]]\([[0-9]][[0-9]]*\).*$/\1/g'`
+ GC_ALPHA_VERSION=`echo $PACKAGE_VERSION | sed 's/^[[^.]]*[[.]][[0-9]]*//'`
+
+ case "$GC_ALPHA_VERSION" in
+ alpha*)
+ GC_ALPHA_VERSION=`echo $GC_ALPHA_VERSION \
+ | sed 's/alpha\([[0-9]][[0-9]]*\)/\1/'` ;;
+ *) GC_ALPHA_MAJOR='' ;;
+ esac
+
+ if test :$GC_VERSION_MAJOR: = :: \
+ -o :$GC_VERSION_MINOR: = :: ;
+ then
+ AC_MSG_RESULT(invalid)
+ AC_MSG_ERROR([nonconforming PACKAGE_VERSION='$PACKAGE_VERSION'])
+ fi
+
+ AC_DEFINE_UNQUOTED(GC_VERSION_MAJOR, $GC_VERSION_MAJOR)
+ AC_DEFINE_UNQUOTED(GC_VERSION_MINOR, $GC_VERSION_MINOR)
+ if test :$GC_ALPHA_VERSION: != :: ; then
+ AC_DEFINE_UNQUOTED(GC_ALPHA_VERSION, $GC_ALPHA_VERSION)
+ fi
+ AC_MSG_RESULT(major=$GC_VERSION_MAJOR minor=$GC_VERSION_MINOR \
+${GC_ALPHA_VERSION:+alpha=}$GC_ALPHA_VERSION)
+])
+
+sinclude(libtool.m4)
diff --git a/tools/build/v2/engine/boehm_gc/aclocal.m4 b/tools/build/v2/engine/boehm_gc/aclocal.m4
new file mode 100644
index 0000000000..8d195b5182
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/aclocal.m4
@@ -0,0 +1,929 @@
+# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION so it can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+ [AM_AUTOMAKE_VERSION([1.9.6])])
+
+# Figure out how to run the assembler. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_PROG_AS
+# ----------
+AC_DEFUN([AM_PROG_AS],
+[# By default we simply use the C compiler to build assembly code.
+AC_REQUIRE([AC_PROG_CC])
+test "${CCAS+set}" = set || CCAS=$CC
+test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS
+AC_ARG_VAR([CCAS], [assembler compiler command (defaults to CC)])
+AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)])
+])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 7
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])
+AC_SUBST([$1_FALSE])
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # So let's grep whole file.
+ if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 12
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.58])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+ test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $1 | $1:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+AC_DEFUN([AM_MAINTAINER_MODE],
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ dnl maintainer-mode is disabled by default
+ AC_ARG_ENABLE(maintainer-mode,
+[ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer],
+ USE_MAINTAINER_MODE=$enableval,
+ USE_MAINTAINER_MODE=no)
+ AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+ AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes])
+ MAINT=$MAINTAINER_MODE_TRUE
+ AC_SUBST(MAINT)dnl
+]
+)
+
+AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Copyright (C) 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_PROG_CC_C_O
+# --------------
+# Like AC_PROG_CC_C_O, but changed for automake.
+AC_DEFUN([AM_PROG_CC_C_O],
+[AC_REQUIRE([AC_PROG_CC_C_O])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+ac_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
+if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
+#
+# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
+# created by `make install' are always world readable, even if the
+# installer happens to have an overly restrictive umask (e.g. 077).
+# This was a mistake. There are at least two reasons why we must not
+# use `-m 0755':
+# - it causes special bits like SGID to be ignored,
+# - it may be too restrictive (some setups expect 775 directories).
+#
+# Do not use -m 0755 and let people choose whatever they expect by
+# setting umask.
+#
+# We cannot accept any implementation of `mkdir' that recognizes `-p'.
+# Some implementations (such as Solaris 8's) are not thread-safe: if a
+# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c'
+# concurrently, both version can detect that a/ is missing, but only
+# one can create it and the other will error out. Consequently we
+# restrict ourselves to GNU make (using the --version option ensures
+# this.)
+AC_DEFUN([AM_PROG_MKDIR_P],
+[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ # We used to keeping the `.' as first argument, in order to
+ # allow $(mkdir_p) to be used without argument. As in
+ # $(mkdir_p) $(somedir)
+ # where $(somedir) is conditionally defined. However this is wrong
+ # for two reasons:
+ # 1. if the package is installed by a user who cannot write `.'
+ # make install will fail,
+ # 2. the above comment should most certainly read
+ # $(mkdir_p) $(DESTDIR)$(somedir)
+ # so it does not work when $(somedir) is undefined and
+ # $(DESTDIR) is not.
+ # To support the latter case, we have to write
+ # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+ # so the `.' trick is pointless.
+ mkdir_p='mkdir -p --'
+else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ for d in ./-p ./--version;
+ do
+ test -d $d && rmdir $d
+ done
+ # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+ if test -f "$ac_aux_dir/mkinstalldirs"; then
+ mkdir_p='$(mkinstalldirs)'
+ else
+ mkdir_p='$(install_sh) -d'
+ fi
+fi
+AC_SUBST([mkdir_p])])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([acinclude.m4])
diff --git a/tools/build/v2/engine/boehm_gc/add_gc_prefix.c b/tools/build/v2/engine/boehm_gc/add_gc_prefix.c
new file mode 100644
index 0000000000..59515c7866
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/add_gc_prefix.c
@@ -0,0 +1,20 @@
+# include <stdio.h>
+# include "version.h"
+
+int main(argc, argv, envp)
+int argc;
+char ** argv;
+char ** envp;
+{
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (GC_ALPHA_VERSION == GC_NOT_ALPHA) {
+ printf("gc%d.%d/%s ", GC_VERSION_MAJOR, GC_VERSION_MINOR, argv[i]);
+ } else {
+ printf("gc%d.%dalpha%d/%s ", GC_VERSION_MAJOR,
+ GC_VERSION_MINOR, GC_ALPHA_VERSION, argv[i]);
+ }
+ }
+ return(0);
+}
diff --git a/tools/build/v2/engine/boehm_gc/allchblk.c b/tools/build/v2/engine/boehm_gc/allchblk.c
new file mode 100644
index 0000000000..0cec29d60e
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/allchblk.c
@@ -0,0 +1,850 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1998-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* #define DEBUG */
+#include <stdio.h>
+#include "private/gc_priv.h"
+
+GC_bool GC_use_entire_heap = 0;
+
+/*
+ * Free heap blocks are kept on one of several free lists,
+ * depending on the size of the block. Each free list is doubly linked.
+ * Adjacent free blocks are coalesced.
+ */
+
+
+# define MAX_BLACK_LIST_ALLOC (2*HBLKSIZE)
+ /* largest block we will allocate starting on a black */
+ /* listed block. Must be >= HBLKSIZE. */
+
+
+# define UNIQUE_THRESHOLD 32
+ /* Sizes up to this many HBLKs each have their own free list */
+# define HUGE_THRESHOLD 256
+ /* Sizes of at least this many heap blocks are mapped to a */
+ /* single free list. */
+# define FL_COMPRESSION 8
+ /* In between sizes map this many distinct sizes to a single */
+ /* bin. */
+
+# define N_HBLK_FLS (HUGE_THRESHOLD - UNIQUE_THRESHOLD)/FL_COMPRESSION \
+ + UNIQUE_THRESHOLD
+
+struct hblk * GC_hblkfreelist[N_HBLK_FLS+1] = { 0 };
+
+#ifndef USE_MUNMAP
+
+ word GC_free_bytes[N_HBLK_FLS+1] = { 0 };
+ /* Number of free bytes on each list. */
+
+ /* Is bytes + the number of free bytes on lists n .. N_HBLK_FLS */
+ /* > GC_max_large_allocd_bytes? */
+# ifdef __GNUC__
+ __inline__
+# endif
+ static GC_bool GC_enough_large_bytes_left(word bytes, int n)
+ {
+ int i;
+ for (i = N_HBLK_FLS; i >= n; --i) {
+ bytes += GC_free_bytes[i];
+ if (bytes > GC_max_large_allocd_bytes) return TRUE;
+ }
+ return FALSE;
+ }
+
+# define INCR_FREE_BYTES(n, b) GC_free_bytes[n] += (b);
+
+# define FREE_ASSERT(e) GC_ASSERT(e)
+
+#else /* USE_MUNMAP */
+
+# define INCR_FREE_BYTES(n, b)
+# define FREE_ASSERT(e)
+
+#endif /* USE_MUNMAP */
+
+/* Map a number of blocks to the appropriate large block free list index. */
+int GC_hblk_fl_from_blocks(word blocks_needed)
+{
+ if (blocks_needed <= UNIQUE_THRESHOLD) return (int)blocks_needed;
+ if (blocks_needed >= HUGE_THRESHOLD) return N_HBLK_FLS;
+ return (int)(blocks_needed - UNIQUE_THRESHOLD)/FL_COMPRESSION
+ + UNIQUE_THRESHOLD;
+
+}
+
+# define PHDR(hhdr) HDR(hhdr -> hb_prev)
+# define NHDR(hhdr) HDR(hhdr -> hb_next)
+
+# ifdef USE_MUNMAP
+# define IS_MAPPED(hhdr) (((hhdr) -> hb_flags & WAS_UNMAPPED) == 0)
+# else /* !USE_MMAP */
+# define IS_MAPPED(hhdr) 1
+# endif /* USE_MUNMAP */
+
+# if !defined(NO_DEBUGGING)
+void GC_print_hblkfreelist()
+{
+ struct hblk * h;
+ word total_free = 0;
+ hdr * hhdr;
+ word sz;
+ unsigned i;
+
+ for (i = 0; i <= N_HBLK_FLS; ++i) {
+ h = GC_hblkfreelist[i];
+# ifdef USE_MUNMAP
+ if (0 != h) GC_printf("Free list %ld:\n",
+ (unsigned long)i);
+# else
+ if (0 != h) GC_printf("Free list %lu (Total size %lu):\n",
+ i, (unsigned long)GC_free_bytes[i]);
+# endif
+ while (h != 0) {
+ hhdr = HDR(h);
+ sz = hhdr -> hb_sz;
+ GC_printf("\t%p size %lu ", h, (unsigned long)sz);
+ total_free += sz;
+ if (GC_is_black_listed(h, HBLKSIZE) != 0) {
+ GC_printf("start black listed\n");
+ } else if (GC_is_black_listed(h, hhdr -> hb_sz) != 0) {
+ GC_printf("partially black listed\n");
+ } else {
+ GC_printf("not black listed\n");
+ }
+ h = hhdr -> hb_next;
+ }
+ }
+# ifndef USE_MUNMAP
+ if (total_free != GC_large_free_bytes) {
+ GC_printf("GC_large_free_bytes = %lu (INCONSISTENT!!)\n",
+ (unsigned long) GC_large_free_bytes);
+ }
+# endif
+ GC_printf("Total of %lu bytes on free list\n", (unsigned long)total_free);
+}
+
+/* Return the free list index on which the block described by the header */
+/* appears, or -1 if it appears nowhere. */
+int free_list_index_of(hdr *wanted)
+{
+ struct hblk * h;
+ hdr * hhdr;
+ int i;
+
+ for (i = 0; i <= N_HBLK_FLS; ++i) {
+ h = GC_hblkfreelist[i];
+ while (h != 0) {
+ hhdr = HDR(h);
+ if (hhdr == wanted) return i;
+ h = hhdr -> hb_next;
+ }
+ }
+ return -1;
+}
+
+void GC_dump_regions()
+{
+ unsigned i;
+ ptr_t start, end;
+ ptr_t p;
+ size_t bytes;
+ hdr *hhdr;
+ for (i = 0; i < GC_n_heap_sects; ++i) {
+ start = GC_heap_sects[i].hs_start;
+ bytes = GC_heap_sects[i].hs_bytes;
+ end = start + bytes;
+ /* Merge in contiguous sections. */
+ while (i+1 < GC_n_heap_sects && GC_heap_sects[i+1].hs_start == end) {
+ ++i;
+ end = GC_heap_sects[i].hs_start + GC_heap_sects[i].hs_bytes;
+ }
+ GC_printf("***Section from %p to %p\n", start, end);
+ for (p = start; p < end;) {
+ hhdr = HDR(p);
+ GC_printf("\t%p ", p);
+ if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
+ GC_printf("Missing header!!(%d)\n", hhdr);
+ p += HBLKSIZE;
+ continue;
+ }
+ if (HBLK_IS_FREE(hhdr)) {
+ int correct_index = GC_hblk_fl_from_blocks(
+ divHBLKSZ(hhdr -> hb_sz));
+ int actual_index;
+
+ GC_printf("\tfree block of size 0x%lx bytes",
+ (unsigned long)(hhdr -> hb_sz));
+ if (IS_MAPPED(hhdr)) {
+ GC_printf("\n");
+ } else {
+ GC_printf("(unmapped)\n");
+ }
+ actual_index = free_list_index_of(hhdr);
+ if (-1 == actual_index) {
+ GC_printf("\t\tBlock not on free list %d!!\n",
+ correct_index);
+ } else if (correct_index != actual_index) {
+ GC_printf("\t\tBlock on list %d, should be on %d!!\n",
+ actual_index, correct_index);
+ }
+ p += hhdr -> hb_sz;
+ } else {
+ GC_printf("\tused for blocks of size 0x%lx bytes\n",
+ (unsigned long)(hhdr -> hb_sz));
+ p += HBLKSIZE * OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
+ }
+ }
+ }
+}
+
+# endif /* NO_DEBUGGING */
+
+/* Initialize hdr for a block containing the indicated size and */
+/* kind of objects. */
+/* Return FALSE on failure. */
+static GC_bool setup_header(hdr * hhdr, struct hblk *block, size_t byte_sz,
+ int kind, unsigned flags)
+{
+ word descr;
+ size_t granules;
+
+ /* Set size, kind and mark proc fields */
+ hhdr -> hb_sz = byte_sz;
+ hhdr -> hb_obj_kind = (unsigned char)kind;
+ hhdr -> hb_flags = (unsigned char)flags;
+ hhdr -> hb_block = block;
+ descr = GC_obj_kinds[kind].ok_descriptor;
+ if (GC_obj_kinds[kind].ok_relocate_descr) descr += byte_sz;
+ hhdr -> hb_descr = descr;
+
+# ifdef MARK_BIT_PER_OBJ
+ /* Set hb_inv_sz as portably as possible. */
+ /* We set it to the smallest value such that sz * inv_sz > 2**32 */
+ /* This may be more precision than necessary. */
+ if (byte_sz > MAXOBJBYTES) {
+ hhdr -> hb_inv_sz = LARGE_INV_SZ;
+ } else {
+ word inv_sz;
+
+# if CPP_WORDSZ == 64
+ inv_sz = ((word)1 << 32)/byte_sz;
+ if (((inv_sz*byte_sz) >> 32) == 0) ++inv_sz;
+# else /* 32 bit words */
+ GC_ASSERT(byte_sz >= 4);
+ inv_sz = ((unsigned)1 << 31)/byte_sz;
+ inv_sz *= 2;
+ while (inv_sz*byte_sz > byte_sz) ++inv_sz;
+# endif
+ hhdr -> hb_inv_sz = inv_sz;
+ }
+# else /* MARK_BIT_PER_GRANULE */
+ hhdr -> hb_large_block = (unsigned char)(byte_sz > MAXOBJBYTES);
+ granules = BYTES_TO_GRANULES(byte_sz);
+ if (EXPECT(!GC_add_map_entry(granules), FALSE)) {
+ /* Make it look like a valid block. */
+ hhdr -> hb_sz = HBLKSIZE;
+ hhdr -> hb_descr = 0;
+ hhdr -> hb_large_block = TRUE;
+ hhdr -> hb_map = 0;
+ return FALSE;
+ } else {
+ size_t index = (hhdr -> hb_large_block? 0 : granules);
+ hhdr -> hb_map = GC_obj_map[index];
+ }
+# endif /* MARK_BIT_PER_GRANULE */
+
+ /* Clear mark bits */
+ GC_clear_hdr_marks(hhdr);
+
+ hhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
+ return(TRUE);
+}
+
+#define FL_UNKNOWN -1
+/*
+ * Remove hhdr from the appropriate free list.
+ * We assume it is on the nth free list, or on the size
+ * appropriate free list if n is FL_UNKNOWN.
+ */
+void GC_remove_from_fl(hdr *hhdr, int n)
+{
+ int index;
+
+ GC_ASSERT(((hhdr -> hb_sz) & (HBLKSIZE-1)) == 0);
+# ifndef USE_MUNMAP
+ /* We always need index to mainatin free counts. */
+ if (FL_UNKNOWN == n) {
+ index = GC_hblk_fl_from_blocks(divHBLKSZ(hhdr -> hb_sz));
+ } else {
+ index = n;
+ }
+# endif
+ if (hhdr -> hb_prev == 0) {
+# ifdef USE_MUNMAP
+ if (FL_UNKNOWN == n) {
+ index = GC_hblk_fl_from_blocks(divHBLKSZ(hhdr -> hb_sz));
+ } else {
+ index = n;
+ }
+# endif
+ GC_ASSERT(HDR(GC_hblkfreelist[index]) == hhdr);
+ GC_hblkfreelist[index] = hhdr -> hb_next;
+ } else {
+ hdr *phdr;
+ GET_HDR(hhdr -> hb_prev, phdr);
+ phdr -> hb_next = hhdr -> hb_next;
+ }
+ FREE_ASSERT(GC_free_bytes[index] >= hhdr -> hb_sz);
+ INCR_FREE_BYTES(index, - (signed_word)(hhdr -> hb_sz));
+ if (0 != hhdr -> hb_next) {
+ hdr * nhdr;
+ GC_ASSERT(!IS_FORWARDING_ADDR_OR_NIL(NHDR(hhdr)));
+ GET_HDR(hhdr -> hb_next, nhdr);
+ nhdr -> hb_prev = hhdr -> hb_prev;
+ }
+}
+
+/*
+ * Return a pointer to the free block ending just before h, if any.
+ */
+struct hblk * GC_free_block_ending_at(struct hblk *h)
+{
+ struct hblk * p = h - 1;
+ hdr * phdr;
+
+ GET_HDR(p, phdr);
+ while (0 != phdr && IS_FORWARDING_ADDR_OR_NIL(phdr)) {
+ p = FORWARDED_ADDR(p,phdr);
+ phdr = HDR(p);
+ }
+ if (0 != phdr) {
+ if(HBLK_IS_FREE(phdr)) {
+ return p;
+ } else {
+ return 0;
+ }
+ }
+ p = GC_prev_block(h - 1);
+ if (0 != p) {
+ phdr = HDR(p);
+ if (HBLK_IS_FREE(phdr) && (ptr_t)p + phdr -> hb_sz == (ptr_t)h) {
+ return p;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Add hhdr to the appropriate free list.
+ * We maintain individual free lists sorted by address.
+ */
+void GC_add_to_fl(struct hblk *h, hdr *hhdr)
+{
+ int index = GC_hblk_fl_from_blocks(divHBLKSZ(hhdr -> hb_sz));
+ struct hblk *second = GC_hblkfreelist[index];
+ hdr * second_hdr;
+# ifdef GC_ASSERTIONS
+ struct hblk *next = (struct hblk *)((word)h + hhdr -> hb_sz);
+ hdr * nexthdr = HDR(next);
+ struct hblk *prev = GC_free_block_ending_at(h);
+ hdr * prevhdr = HDR(prev);
+ GC_ASSERT(nexthdr == 0 || !HBLK_IS_FREE(nexthdr) || !IS_MAPPED(nexthdr));
+ GC_ASSERT(prev == 0 || !HBLK_IS_FREE(prevhdr) || !IS_MAPPED(prevhdr));
+# endif
+ GC_ASSERT(((hhdr -> hb_sz) & (HBLKSIZE-1)) == 0);
+ GC_hblkfreelist[index] = h;
+ INCR_FREE_BYTES(index, hhdr -> hb_sz);
+ FREE_ASSERT(GC_free_bytes[index] <= GC_large_free_bytes)
+ hhdr -> hb_next = second;
+ hhdr -> hb_prev = 0;
+ if (0 != second) {
+ GET_HDR(second, second_hdr);
+ second_hdr -> hb_prev = h;
+ }
+ hhdr -> hb_flags |= FREE_BLK;
+}
+
+#ifdef USE_MUNMAP
+
+/* Unmap blocks that haven't been recently touched. This is the only way */
+/* way blocks are ever unmapped. */
+void GC_unmap_old(void)
+{
+ struct hblk * h;
+ hdr * hhdr;
+ word sz;
+ unsigned short last_rec, threshold;
+ int i;
+# define UNMAP_THRESHOLD 6
+
+ for (i = 0; i <= N_HBLK_FLS; ++i) {
+ for (h = GC_hblkfreelist[i]; 0 != h; h = hhdr -> hb_next) {
+ hhdr = HDR(h);
+ if (!IS_MAPPED(hhdr)) continue;
+ threshold = (unsigned short)(GC_gc_no - UNMAP_THRESHOLD);
+ last_rec = hhdr -> hb_last_reclaimed;
+ if ((last_rec > GC_gc_no || last_rec < threshold)
+ && threshold < GC_gc_no /* not recently wrapped */) {
+ sz = hhdr -> hb_sz;
+ GC_unmap((ptr_t)h, sz);
+ hhdr -> hb_flags |= WAS_UNMAPPED;
+ }
+ }
+ }
+}
+
+/* Merge all unmapped blocks that are adjacent to other free */
+/* blocks. This may involve remapping, since all blocks are either */
+/* fully mapped or fully unmapped. */
+void GC_merge_unmapped(void)
+{
+ struct hblk * h, *next;
+ hdr * hhdr, *nexthdr;
+ word size, nextsize;
+ int i;
+
+ for (i = 0; i <= N_HBLK_FLS; ++i) {
+ h = GC_hblkfreelist[i];
+ while (h != 0) {
+ GET_HDR(h, hhdr);
+ size = hhdr->hb_sz;
+ next = (struct hblk *)((word)h + size);
+ GET_HDR(next, nexthdr);
+ /* Coalesce with successor, if possible */
+ if (0 != nexthdr && HBLK_IS_FREE(nexthdr)) {
+ nextsize = nexthdr -> hb_sz;
+ if (IS_MAPPED(hhdr)) {
+ GC_ASSERT(!IS_MAPPED(nexthdr));
+ /* make both consistent, so that we can merge */
+ if (size > nextsize) {
+ GC_remap((ptr_t)next, nextsize);
+ } else {
+ GC_unmap((ptr_t)h, size);
+ hhdr -> hb_flags |= WAS_UNMAPPED;
+ }
+ } else if (IS_MAPPED(nexthdr)) {
+ GC_ASSERT(!IS_MAPPED(hhdr));
+ if (size > nextsize) {
+ GC_unmap((ptr_t)next, nextsize);
+ } else {
+ GC_remap((ptr_t)h, size);
+ hhdr -> hb_flags &= ~WAS_UNMAPPED;
+ hhdr -> hb_last_reclaimed = nexthdr -> hb_last_reclaimed;
+ }
+ } else {
+ /* Unmap any gap in the middle */
+ GC_unmap_gap((ptr_t)h, size, (ptr_t)next, nexthdr -> hb_sz);
+ }
+ /* If they are both unmapped, we merge, but leave unmapped. */
+ GC_remove_from_fl(hhdr, i);
+ GC_remove_from_fl(nexthdr, FL_UNKNOWN);
+ hhdr -> hb_sz += nexthdr -> hb_sz;
+ GC_remove_header(next);
+ GC_add_to_fl(h, hhdr);
+ /* Start over at beginning of list */
+ h = GC_hblkfreelist[i];
+ } else /* not mergable with successor */ {
+ h = hhdr -> hb_next;
+ }
+ } /* while (h != 0) ... */
+ } /* for ... */
+}
+
+#endif /* USE_MUNMAP */
+
+/*
+ * Return a pointer to a block starting at h of length bytes.
+ * Memory for the block is mapped.
+ * Remove the block from its free list, and return the remainder (if any)
+ * to its appropriate free list.
+ * May fail by returning 0.
+ * The header for the returned block must be set up by the caller.
+ * If the return value is not 0, then hhdr is the header for it.
+ */
+struct hblk * GC_get_first_part(struct hblk *h, hdr *hhdr,
+ size_t bytes, int index)
+{
+ word total_size = hhdr -> hb_sz;
+ struct hblk * rest;
+ hdr * rest_hdr;
+
+ GC_ASSERT((total_size & (HBLKSIZE-1)) == 0);
+ GC_remove_from_fl(hhdr, index);
+ if (total_size == bytes) return h;
+ rest = (struct hblk *)((word)h + bytes);
+ rest_hdr = GC_install_header(rest);
+ if (0 == rest_hdr) {
+ /* FIXME: This is likely to be very bad news ... */
+ WARN("Header allocation failed: Dropping block.\n", 0);
+ return(0);
+ }
+ rest_hdr -> hb_sz = total_size - bytes;
+ rest_hdr -> hb_flags = 0;
+# ifdef GC_ASSERTIONS
+ /* Mark h not free, to avoid assertion about adjacent free blocks. */
+ hhdr -> hb_flags &= ~FREE_BLK;
+# endif
+ GC_add_to_fl(rest, rest_hdr);
+ return h;
+}
+
+/*
+ * H is a free block. N points at an address inside it.
+ * A new header for n has already been set up. Fix up h's header
+ * to reflect the fact that it is being split, move it to the
+ * appropriate free list.
+ * N replaces h in the original free list.
+ *
+ * Nhdr is not completely filled in, since it is about to allocated.
+ * It may in fact end up on the wrong free list for its size.
+ * (Hence adding it to a free list is silly. But this path is hopefully
+ * rare enough that it doesn't matter. The code is cleaner this way.)
+ */
+void GC_split_block(struct hblk *h, hdr *hhdr, struct hblk *n,
+ hdr *nhdr, int index /* Index of free list */)
+{
+ word total_size = hhdr -> hb_sz;
+ word h_size = (word)n - (word)h;
+ struct hblk *prev = hhdr -> hb_prev;
+ struct hblk *next = hhdr -> hb_next;
+
+ /* Replace h with n on its freelist */
+ nhdr -> hb_prev = prev;
+ nhdr -> hb_next = next;
+ nhdr -> hb_sz = total_size - h_size;
+ nhdr -> hb_flags = 0;
+ if (0 != prev) {
+ HDR(prev) -> hb_next = n;
+ } else {
+ GC_hblkfreelist[index] = n;
+ }
+ if (0 != next) {
+ HDR(next) -> hb_prev = n;
+ }
+ INCR_FREE_BYTES(index, -(signed_word)h_size);
+ FREE_ASSERT(GC_free_bytes[index] > 0);
+# ifdef GC_ASSERTIONS
+ nhdr -> hb_flags &= ~FREE_BLK;
+ /* Don't fail test for consecutive */
+ /* free blocks in GC_add_to_fl. */
+# endif
+# ifdef USE_MUNMAP
+ hhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
+# endif
+ hhdr -> hb_sz = h_size;
+ GC_add_to_fl(h, hhdr);
+ nhdr -> hb_flags |= FREE_BLK;
+}
+
+struct hblk *
+GC_allochblk_nth(size_t sz/* bytes */, int kind, unsigned flags, int n);
+
+/*
+ * Allocate (and return pointer to) a heap block
+ * for objects of size sz bytes, searching the nth free list.
+ *
+ * NOTE: We set obj_map field in header correctly.
+ * Caller is responsible for building an object freelist in block.
+ *
+ * The client is responsible for clearing the block, if necessary.
+ */
+struct hblk *
+GC_allochblk(size_t sz, int kind, unsigned flags/* IGNORE_OFF_PAGE or 0 */)
+{
+ word blocks;
+ int start_list;
+ int i;
+
+ GC_ASSERT((sz & (GRANULE_BYTES - 1)) == 0);
+ blocks = OBJ_SZ_TO_BLOCKS(sz);
+ start_list = GC_hblk_fl_from_blocks(blocks);
+ for (i = start_list; i <= N_HBLK_FLS; ++i) {
+ struct hblk * result = GC_allochblk_nth(sz, kind, flags, i);
+ if (0 != result) {
+ return result;
+ }
+ }
+ return 0;
+}
+/*
+ * The same, but with search restricted to nth free list.
+ * Flags is IGNORE_OFF_PAGE or zero.
+ * Unlike the above, sz is in bytes.
+ */
+struct hblk *
+GC_allochblk_nth(size_t sz, int kind, unsigned flags, int n)
+{
+ struct hblk *hbp;
+ hdr * hhdr; /* Header corr. to hbp */
+ /* Initialized after loop if hbp !=0 */
+ /* Gcc uninitialized use warning is bogus. */
+ struct hblk *thishbp;
+ hdr * thishdr; /* Header corr. to hbp */
+ signed_word size_needed; /* number of bytes in requested objects */
+ signed_word size_avail; /* bytes available in this block */
+
+ size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS(sz);
+
+ /* search for a big enough block in free list */
+ hbp = GC_hblkfreelist[n];
+ for(; 0 != hbp; hbp = hhdr -> hb_next) {
+ GET_HDR(hbp, hhdr);
+ size_avail = hhdr->hb_sz;
+ if (size_avail < size_needed) continue;
+ if (size_avail != size_needed
+ && !GC_use_entire_heap
+ && !GC_dont_gc
+ && USED_HEAP_SIZE >= GC_requested_heapsize
+ && !TRUE_INCREMENTAL && GC_should_collect()) {
+# ifdef USE_MUNMAP
+ continue;
+# else
+ /* If we have enough large blocks left to cover any */
+ /* previous request for large blocks, we go ahead */
+ /* and split. Assuming a steady state, that should */
+ /* be safe. It means that we can use the full */
+ /* heap if we allocate only small objects. */
+ if (!GC_enough_large_bytes_left(GC_large_allocd_bytes, n)) {
+ continue;
+ }
+ /* If we are deallocating lots of memory from */
+ /* finalizers, fail and collect sooner rather */
+ /* than later. */
+ if (GC_finalizer_bytes_freed > (GC_heapsize >> 4)) {
+ continue;
+ }
+# endif /* !USE_MUNMAP */
+ }
+ /* If the next heap block is obviously better, go on. */
+ /* This prevents us from disassembling a single large block */
+ /* to get tiny blocks. */
+ {
+ signed_word next_size;
+
+ thishbp = hhdr -> hb_next;
+ if (thishbp != 0) {
+ GET_HDR(thishbp, thishdr);
+ next_size = (signed_word)(thishdr -> hb_sz);
+ if (next_size < size_avail
+ && next_size >= size_needed
+ && !GC_is_black_listed(thishbp, (word)size_needed)) {
+ continue;
+ }
+ }
+ }
+ if ( !IS_UNCOLLECTABLE(kind) &&
+ (kind != PTRFREE || size_needed > MAX_BLACK_LIST_ALLOC)) {
+ struct hblk * lasthbp = hbp;
+ ptr_t search_end = (ptr_t)hbp + size_avail - size_needed;
+ signed_word orig_avail = size_avail;
+ signed_word eff_size_needed = ((flags & IGNORE_OFF_PAGE)?
+ HBLKSIZE
+ : size_needed);
+
+
+ while ((ptr_t)lasthbp <= search_end
+ && (thishbp = GC_is_black_listed(lasthbp,
+ (word)eff_size_needed))
+ != 0) {
+ lasthbp = thishbp;
+ }
+ size_avail -= (ptr_t)lasthbp - (ptr_t)hbp;
+ thishbp = lasthbp;
+ if (size_avail >= size_needed) {
+ if (thishbp != hbp &&
+ 0 != (thishdr = GC_install_header(thishbp))) {
+ /* Make sure it's mapped before we mangle it. */
+# ifdef USE_MUNMAP
+ if (!IS_MAPPED(hhdr)) {
+ GC_remap((ptr_t)hbp, hhdr -> hb_sz);
+ hhdr -> hb_flags &= ~WAS_UNMAPPED;
+ }
+# endif
+ /* Split the block at thishbp */
+ GC_split_block(hbp, hhdr, thishbp, thishdr, n);
+ /* Advance to thishbp */
+ hbp = thishbp;
+ hhdr = thishdr;
+ /* We must now allocate thishbp, since it may */
+ /* be on the wrong free list. */
+ }
+ } else if (size_needed > (signed_word)BL_LIMIT
+ && orig_avail - size_needed
+ > (signed_word)BL_LIMIT) {
+ /* Punt, since anything else risks unreasonable heap growth. */
+ if (++GC_large_alloc_warn_suppressed
+ >= GC_large_alloc_warn_interval) {
+ WARN("Repeated allocation of very large block "
+ "(appr. size %ld):\n"
+ "\tMay lead to memory leak and poor performance.\n",
+ size_needed);
+ GC_large_alloc_warn_suppressed = 0;
+ }
+ size_avail = orig_avail;
+ } else if (size_avail == 0 && size_needed == HBLKSIZE
+ && IS_MAPPED(hhdr)) {
+ if (!GC_find_leak) {
+ static unsigned count = 0;
+
+ /* The block is completely blacklisted. We need */
+ /* to drop some such blocks, since otherwise we spend */
+ /* all our time traversing them if pointerfree */
+ /* blocks are unpopular. */
+ /* A dropped block will be reconsidered at next GC. */
+ if ((++count & 3) == 0) {
+ /* Allocate and drop the block in small chunks, to */
+ /* maximize the chance that we will recover some */
+ /* later. */
+ word total_size = hhdr -> hb_sz;
+ struct hblk * limit = hbp + divHBLKSZ(total_size);
+ struct hblk * h;
+ struct hblk * prev = hhdr -> hb_prev;
+
+ GC_large_free_bytes -= total_size;
+ GC_remove_from_fl(hhdr, n);
+ for (h = hbp; h < limit; h++) {
+ if (h == hbp || 0 != (hhdr = GC_install_header(h))) {
+ (void) setup_header(
+ hhdr, h,
+ HBLKSIZE,
+ PTRFREE, 0); /* Cant fail */
+ if (GC_debugging_started) {
+ BZERO(h, HBLKSIZE);
+ }
+ }
+ }
+ /* Restore hbp to point at free block */
+ hbp = prev;
+ if (0 == hbp) {
+ return GC_allochblk_nth(sz, kind, flags, n);
+ }
+ hhdr = HDR(hbp);
+ }
+ }
+ }
+ }
+ if( size_avail >= size_needed ) {
+# ifdef USE_MUNMAP
+ if (!IS_MAPPED(hhdr)) {
+ GC_remap((ptr_t)hbp, hhdr -> hb_sz);
+ hhdr -> hb_flags &= ~WAS_UNMAPPED;
+ }
+# endif
+ /* hbp may be on the wrong freelist; the parameter n */
+ /* is important. */
+ hbp = GC_get_first_part(hbp, hhdr, size_needed, n);
+ break;
+ }
+ }
+
+ if (0 == hbp) return 0;
+
+ /* Add it to map of valid blocks */
+ if (!GC_install_counts(hbp, (word)size_needed)) return(0);
+ /* This leaks memory under very rare conditions. */
+
+ /* Set up header */
+ if (!setup_header(hhdr, hbp, sz, kind, flags)) {
+ GC_remove_counts(hbp, (word)size_needed);
+ return(0); /* ditto */
+ }
+
+ /* Notify virtual dirty bit implementation that we are about to write. */
+ /* Ensure that pointerfree objects are not protected if it's avoidable. */
+ GC_remove_protection(hbp, divHBLKSZ(size_needed),
+ (hhdr -> hb_descr == 0) /* pointer-free */);
+
+ /* We just successfully allocated a block. Restart count of */
+ /* consecutive failures. */
+ {
+ extern unsigned GC_fail_count;
+
+ GC_fail_count = 0;
+ }
+
+ GC_large_free_bytes -= size_needed;
+
+ GC_ASSERT(IS_MAPPED(hhdr));
+ return( hbp );
+}
+
+struct hblk * GC_freehblk_ptr = 0; /* Search position hint for GC_freehblk */
+
+/*
+ * Free a heap block.
+ *
+ * Coalesce the block with its neighbors if possible.
+ *
+ * All mark words are assumed to be cleared.
+ */
+void
+GC_freehblk(struct hblk *hbp)
+{
+struct hblk *next, *prev;
+hdr *hhdr, *prevhdr, *nexthdr;
+signed_word size;
+
+
+ GET_HDR(hbp, hhdr);
+ size = hhdr->hb_sz;
+ size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(size);
+ GC_remove_counts(hbp, (word)size);
+ hhdr->hb_sz = size;
+# ifdef USE_MUNMAP
+ hhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
+# endif
+
+ /* Check for duplicate deallocation in the easy case */
+ if (HBLK_IS_FREE(hhdr)) {
+ GC_printf("Duplicate large block deallocation of %p\n", hbp);
+ ABORT("Duplicate large block deallocation");
+ }
+
+ GC_ASSERT(IS_MAPPED(hhdr));
+ hhdr -> hb_flags |= FREE_BLK;
+ next = (struct hblk *)((word)hbp + size);
+ GET_HDR(next, nexthdr);
+ prev = GC_free_block_ending_at(hbp);
+ /* Coalesce with successor, if possible */
+ if(0 != nexthdr && HBLK_IS_FREE(nexthdr) && IS_MAPPED(nexthdr)) {
+ GC_remove_from_fl(nexthdr, FL_UNKNOWN);
+ hhdr -> hb_sz += nexthdr -> hb_sz;
+ GC_remove_header(next);
+ }
+ /* Coalesce with predecessor, if possible. */
+ if (0 != prev) {
+ prevhdr = HDR(prev);
+ if (IS_MAPPED(prevhdr)) {
+ GC_remove_from_fl(prevhdr, FL_UNKNOWN);
+ prevhdr -> hb_sz += hhdr -> hb_sz;
+# ifdef USE_MUNMAP
+ prevhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
+# endif
+ GC_remove_header(hbp);
+ hbp = prev;
+ hhdr = prevhdr;
+ }
+ }
+ /* FIXME: It is not clear we really always want to do these merges */
+ /* with -DUSE_MUNMAP, since it updates ages and hence prevents */
+ /* unmapping. */
+
+ GC_large_free_bytes += size;
+ GC_add_to_fl(hbp, hhdr);
+}
+
diff --git a/tools/build/v2/engine/boehm_gc/alloc.c b/tools/build/v2/engine/boehm_gc/alloc.c
new file mode 100644
index 0000000000..94a968e0af
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/alloc.c
@@ -0,0 +1,1023 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1998 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+
+# include "private/gc_priv.h"
+
+# include <stdio.h>
+# if !defined(MACOS) && !defined(MSWINCE)
+# include <signal.h>
+# include <sys/types.h>
+# endif
+
+/*
+ * Separate free lists are maintained for different sized objects
+ * up to MAXOBJBYTES.
+ * The call GC_allocobj(i,k) ensures that the freelist for
+ * kind k objects of size i points to a non-empty
+ * free list. It returns a pointer to the first entry on the free list.
+ * In a single-threaded world, GC_allocobj may be called to allocate
+ * an object of (small) size i as follows:
+ *
+ * opp = &(GC_objfreelist[i]);
+ * if (*opp == 0) GC_allocobj(i, NORMAL);
+ * ptr = *opp;
+ * *opp = obj_link(ptr);
+ *
+ * Note that this is very fast if the free list is non-empty; it should
+ * only involve the execution of 4 or 5 simple instructions.
+ * All composite objects on freelists are cleared, except for
+ * their first word.
+ */
+
+/*
+ * The allocator uses GC_allochblk to allocate large chunks of objects.
+ * These chunks all start on addresses which are multiples of
+ * HBLKSZ. Each allocated chunk has an associated header,
+ * which can be located quickly based on the address of the chunk.
+ * (See headers.c for details.)
+ * This makes it possible to check quickly whether an
+ * arbitrary address corresponds to an object administered by the
+ * allocator.
+ */
+
+word GC_non_gc_bytes = 0; /* Number of bytes not intended to be collected */
+
+word GC_gc_no = 0;
+
+#ifndef SMALL_CONFIG
+ int GC_incremental = 0; /* By default, stop the world. */
+#endif
+
+int GC_parallel = FALSE; /* By default, parallel GC is off. */
+
+int GC_full_freq = 19; /* Every 20th collection is a full */
+ /* collection, whether we need it */
+ /* or not. */
+
+GC_bool GC_need_full_gc = FALSE;
+ /* Need full GC do to heap growth. */
+
+#ifdef THREADS
+ GC_bool GC_world_stopped = FALSE;
+# define IF_THREADS(x) x
+#else
+# define IF_THREADS(x)
+#endif
+
+word GC_used_heap_size_after_full = 0;
+
+char * GC_copyright[] =
+{"Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers ",
+"Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. ",
+"Copyright (c) 1996-1998 by Silicon Graphics. All rights reserved. ",
+"Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved. ",
+"THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY",
+" EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.",
+"See source code for details." };
+
+# include "version.h"
+
+/* some more variables */
+
+extern signed_word GC_bytes_found; /* Number of reclaimed bytes */
+ /* after garbage collection */
+
+GC_bool GC_dont_expand = 0;
+
+word GC_free_space_divisor = 3;
+
+extern GC_bool GC_collection_in_progress();
+ /* Collection is in progress, or was abandoned. */
+
+int GC_never_stop_func (void) { return(0); }
+
+unsigned long GC_time_limit = TIME_LIMIT;
+
+CLOCK_TYPE GC_start_time; /* Time at which we stopped world. */
+ /* used only in GC_timeout_stop_func. */
+
+int GC_n_attempts = 0; /* Number of attempts at finishing */
+ /* collection within GC_time_limit. */
+
+#if defined(SMALL_CONFIG) || defined(NO_CLOCK)
+# define GC_timeout_stop_func GC_never_stop_func
+#else
+ int GC_timeout_stop_func (void)
+ {
+ CLOCK_TYPE current_time;
+ static unsigned count = 0;
+ unsigned long time_diff;
+
+ if ((count++ & 3) != 0) return(0);
+ GET_TIME(current_time);
+ time_diff = MS_TIME_DIFF(current_time,GC_start_time);
+ if (time_diff >= GC_time_limit) {
+ if (GC_print_stats) {
+ GC_log_printf("Abandoning stopped marking after ");
+ GC_log_printf("%lu msecs", time_diff);
+ GC_log_printf("(attempt %d)\n", GC_n_attempts);
+ }
+ return(1);
+ }
+ return(0);
+ }
+#endif /* !SMALL_CONFIG */
+
+/* Return the minimum number of words that must be allocated between */
+/* collections to amortize the collection cost. */
+static word min_bytes_allocd()
+{
+# ifdef THREADS
+ /* We punt, for now. */
+ signed_word stack_size = 10000;
+# else
+ int dummy;
+ signed_word stack_size = (ptr_t)(&dummy) - GC_stackbottom;
+# endif
+ word total_root_size; /* includes double stack size, */
+ /* since the stack is expensive */
+ /* to scan. */
+ word scan_size; /* Estimate of memory to be scanned */
+ /* during normal GC. */
+
+ if (stack_size < 0) stack_size = -stack_size;
+ total_root_size = 2 * stack_size + GC_root_size;
+ scan_size = 2 * GC_composite_in_use + GC_atomic_in_use
+ + total_root_size;
+ if (TRUE_INCREMENTAL) {
+ return scan_size / (2 * GC_free_space_divisor);
+ } else {
+ return scan_size / GC_free_space_divisor;
+ }
+}
+
+/* Return the number of bytes allocated, adjusted for explicit storage */
+/* management, etc.. This number is used in deciding when to trigger */
+/* collections. */
+word GC_adj_bytes_allocd(void)
+{
+ signed_word result;
+ signed_word expl_managed =
+ (signed_word)GC_non_gc_bytes
+ - (signed_word)GC_non_gc_bytes_at_gc;
+
+ /* Don't count what was explicitly freed, or newly allocated for */
+ /* explicit management. Note that deallocating an explicitly */
+ /* managed object should not alter result, assuming the client */
+ /* is playing by the rules. */
+ result = (signed_word)GC_bytes_allocd
+ - (signed_word)GC_bytes_freed
+ + (signed_word)GC_finalizer_bytes_freed
+ - expl_managed;
+ if (result > (signed_word)GC_bytes_allocd) {
+ result = GC_bytes_allocd;
+ /* probably client bug or unfortunate scheduling */
+ }
+ result += GC_bytes_finalized;
+ /* We count objects enqueued for finalization as though they */
+ /* had been reallocated this round. Finalization is user */
+ /* visible progress. And if we don't count this, we have */
+ /* stability problems for programs that finalize all objects. */
+ if (result < (signed_word)(GC_bytes_allocd >> 3)) {
+ /* Always count at least 1/8 of the allocations. We don't want */
+ /* to collect too infrequently, since that would inhibit */
+ /* coalescing of free storage blocks. */
+ /* This also makes us partially robust against client bugs. */
+ return(GC_bytes_allocd >> 3);
+ } else {
+ return(result);
+ }
+}
+
+
+/* Clear up a few frames worth of garbage left at the top of the stack. */
+/* This is used to prevent us from accidentally treating garbade left */
+/* on the stack by other parts of the collector as roots. This */
+/* differs from the code in misc.c, which actually tries to keep the */
+/* stack clear of long-lived, client-generated garbage. */
+void GC_clear_a_few_frames()
+{
+# define NWORDS 64
+ word frames[NWORDS];
+ int i;
+
+ for (i = 0; i < NWORDS; i++) frames[i] = 0;
+}
+
+/* Heap size at which we need a collection to avoid expanding past */
+/* limits used by blacklisting. */
+static word GC_collect_at_heapsize = (word)(-1);
+
+/* Have we allocated enough to amortize a collection? */
+GC_bool GC_should_collect(void)
+{
+ return(GC_adj_bytes_allocd() >= min_bytes_allocd()
+ || GC_heapsize >= GC_collect_at_heapsize);
+}
+
+
+void GC_notify_full_gc(void)
+{
+ if (GC_start_call_back != (void (*) (void))0) {
+ (*GC_start_call_back)();
+ }
+}
+
+GC_bool GC_is_full_gc = FALSE;
+
+/*
+ * Initiate a garbage collection if appropriate.
+ * Choose judiciously
+ * between partial, full, and stop-world collections.
+ * Assumes lock held, signals disabled.
+ */
+void GC_maybe_gc(void)
+{
+ static int n_partial_gcs = 0;
+
+ if (GC_should_collect()) {
+ if (!GC_incremental) {
+ GC_gcollect_inner();
+ n_partial_gcs = 0;
+ return;
+ } else {
+# ifdef PARALLEL_MARK
+ GC_wait_for_reclaim();
+# endif
+ if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {
+ if (GC_print_stats) {
+ GC_log_printf(
+ "***>Full mark for collection %lu after %ld allocd bytes\n",
+ (unsigned long)GC_gc_no+1,
+ (long)GC_bytes_allocd);
+ }
+ GC_promote_black_lists();
+ (void)GC_reclaim_all((GC_stop_func)0, TRUE);
+ GC_clear_marks();
+ n_partial_gcs = 0;
+ GC_notify_full_gc();
+ GC_is_full_gc = TRUE;
+ } else {
+ n_partial_gcs++;
+ }
+ }
+ /* We try to mark with the world stopped. */
+ /* If we run out of time, this turns into */
+ /* incremental marking. */
+# ifndef NO_CLOCK
+ if (GC_time_limit != GC_TIME_UNLIMITED) { GET_TIME(GC_start_time); }
+# endif
+ if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED?
+ GC_never_stop_func : GC_timeout_stop_func)) {
+# ifdef SAVE_CALL_CHAIN
+ GC_save_callers(GC_last_stack);
+# endif
+ GC_finish_collection();
+ } else {
+ if (!GC_is_full_gc) {
+ /* Count this as the first attempt */
+ GC_n_attempts++;
+ }
+ }
+ }
+}
+
+
+/*
+ * Stop the world garbage collection. Assumes lock held, signals disabled.
+ * If stop_func is not GC_never_stop_func, then abort if stop_func returns TRUE.
+ * Return TRUE if we successfully completed the collection.
+ */
+GC_bool GC_try_to_collect_inner(GC_stop_func stop_func)
+{
+ CLOCK_TYPE start_time, current_time;
+ if (GC_dont_gc) return FALSE;
+ if (GC_incremental && GC_collection_in_progress()) {
+ if (GC_print_stats) {
+ GC_log_printf(
+ "GC_try_to_collect_inner: finishing collection in progress\n");
+ }
+ /* Just finish collection already in progress. */
+ while(GC_collection_in_progress()) {
+ if (stop_func()) return(FALSE);
+ GC_collect_a_little_inner(1);
+ }
+ }
+ if (stop_func == GC_never_stop_func) GC_notify_full_gc();
+ if (GC_print_stats) {
+ GET_TIME(start_time);
+ GC_log_printf(
+ "Initiating full world-stop collection %lu after %ld allocd bytes\n",
+ (unsigned long)GC_gc_no+1, (long)GC_bytes_allocd);
+ }
+ GC_promote_black_lists();
+ /* Make sure all blocks have been reclaimed, so sweep routines */
+ /* don't see cleared mark bits. */
+ /* If we're guaranteed to finish, then this is unnecessary. */
+ /* In the find_leak case, we have to finish to guarantee that */
+ /* previously unmarked objects are not reported as leaks. */
+# ifdef PARALLEL_MARK
+ GC_wait_for_reclaim();
+# endif
+ if ((GC_find_leak || stop_func != GC_never_stop_func)
+ && !GC_reclaim_all(stop_func, FALSE)) {
+ /* Aborted. So far everything is still consistent. */
+ return(FALSE);
+ }
+ GC_invalidate_mark_state(); /* Flush mark stack. */
+ GC_clear_marks();
+# ifdef SAVE_CALL_CHAIN
+ GC_save_callers(GC_last_stack);
+# endif
+ GC_is_full_gc = TRUE;
+ if (!GC_stopped_mark(stop_func)) {
+ if (!GC_incremental) {
+ /* We're partially done and have no way to complete or use */
+ /* current work. Reestablish invariants as cheaply as */
+ /* possible. */
+ GC_invalidate_mark_state();
+ GC_unpromote_black_lists();
+ } /* else we claim the world is already still consistent. We'll */
+ /* finish incrementally. */
+ return(FALSE);
+ }
+ GC_finish_collection();
+ if (GC_print_stats) {
+ GET_TIME(current_time);
+ GC_log_printf("Complete collection took %lu msecs\n",
+ MS_TIME_DIFF(current_time,start_time));
+ }
+ return(TRUE);
+}
+
+
+
+/*
+ * Perform n units of garbage collection work. A unit is intended to touch
+ * roughly GC_RATE pages. Every once in a while, we do more than that.
+ * This needs to be a fairly large number with our current incremental
+ * GC strategy, since otherwise we allocate too much during GC, and the
+ * cleanup gets expensive.
+ */
+# define GC_RATE 10
+# define MAX_PRIOR_ATTEMPTS 1
+ /* Maximum number of prior attempts at world stop marking */
+ /* A value of 1 means that we finish the second time, no matter */
+ /* how long it takes. Doesn't count the initial root scan */
+ /* for a full GC. */
+
+int GC_deficit = 0; /* The number of extra calls to GC_mark_some */
+ /* that we have made. */
+
+void GC_collect_a_little_inner(int n)
+{
+ int i;
+
+ if (GC_dont_gc) return;
+ if (GC_incremental && GC_collection_in_progress()) {
+ for (i = GC_deficit; i < GC_RATE*n; i++) {
+ if (GC_mark_some((ptr_t)0)) {
+ /* Need to finish a collection */
+# ifdef SAVE_CALL_CHAIN
+ GC_save_callers(GC_last_stack);
+# endif
+# ifdef PARALLEL_MARK
+ GC_wait_for_reclaim();
+# endif
+ if (GC_n_attempts < MAX_PRIOR_ATTEMPTS
+ && GC_time_limit != GC_TIME_UNLIMITED) {
+ GET_TIME(GC_start_time);
+ if (!GC_stopped_mark(GC_timeout_stop_func)) {
+ GC_n_attempts++;
+ break;
+ }
+ } else {
+ (void)GC_stopped_mark(GC_never_stop_func);
+ }
+ GC_finish_collection();
+ break;
+ }
+ }
+ if (GC_deficit > 0) GC_deficit -= GC_RATE*n;
+ if (GC_deficit < 0) GC_deficit = 0;
+ } else {
+ GC_maybe_gc();
+ }
+}
+
+int GC_collect_a_little(void)
+{
+ int result;
+ DCL_LOCK_STATE;
+
+ LOCK();
+ GC_collect_a_little_inner(1);
+ result = (int)GC_collection_in_progress();
+ UNLOCK();
+ if (!result && GC_debugging_started) GC_print_all_smashed();
+ return(result);
+}
+
+/*
+ * Assumes lock is held, signals are disabled.
+ * We stop the world.
+ * If stop_func() ever returns TRUE, we may fail and return FALSE.
+ * Increment GC_gc_no if we succeed.
+ */
+GC_bool GC_stopped_mark(GC_stop_func stop_func)
+{
+ unsigned i;
+ int dummy;
+ CLOCK_TYPE start_time, current_time;
+
+ if (GC_print_stats)
+ GET_TIME(start_time);
+
+# if defined(REGISTER_LIBRARIES_EARLY)
+ GC_cond_register_dynamic_libraries();
+# endif
+ STOP_WORLD();
+ IF_THREADS(GC_world_stopped = TRUE);
+ if (GC_print_stats) {
+ GC_log_printf("--> Marking for collection %lu ",
+ (unsigned long)GC_gc_no + 1);
+ GC_log_printf("after %lu allocd bytes\n",
+ (unsigned long) GC_bytes_allocd);
+ }
+# ifdef MAKE_BACK_GRAPH
+ if (GC_print_back_height) {
+ GC_build_back_graph();
+ }
+# endif
+
+ /* Mark from all roots. */
+ /* Minimize junk left in my registers and on the stack */
+ GC_clear_a_few_frames();
+ GC_noop(0,0,0,0,0,0);
+ GC_initiate_gc();
+ for(i = 0;;i++) {
+ if ((*stop_func)()) {
+ if (GC_print_stats) {
+ GC_log_printf("Abandoned stopped marking after ");
+ GC_log_printf("%u iterations\n", i);
+ }
+ GC_deficit = i; /* Give the mutator a chance. */
+ IF_THREADS(GC_world_stopped = FALSE);
+ START_WORLD();
+ return(FALSE);
+ }
+ if (GC_mark_some((ptr_t)(&dummy))) break;
+ }
+
+ GC_gc_no++;
+ if (GC_print_stats) {
+ GC_log_printf("Collection %lu reclaimed %ld bytes",
+ (unsigned long)GC_gc_no - 1,
+ (long)GC_bytes_found);
+ GC_log_printf(" ---> heapsize = %lu bytes\n",
+ (unsigned long) GC_heapsize);
+ /* Printf arguments may be pushed in funny places. Clear the */
+ /* space. */
+ GC_log_printf("");
+ }
+
+ /* Check all debugged objects for consistency */
+ if (GC_debugging_started) {
+ (*GC_check_heap)();
+ }
+
+ IF_THREADS(GC_world_stopped = FALSE);
+ START_WORLD();
+ if (GC_print_stats) {
+ GET_TIME(current_time);
+ GC_log_printf("World-stopped marking took %lu msecs\n",
+ MS_TIME_DIFF(current_time,start_time));
+ }
+ return(TRUE);
+}
+
+/* Set all mark bits for the free list whose first entry is q */
+void GC_set_fl_marks(ptr_t q)
+{
+ ptr_t p;
+ struct hblk * h, * last_h = 0;
+ hdr *hhdr; /* gcc "might be uninitialized" warning is bogus. */
+ IF_PER_OBJ(size_t sz;)
+ unsigned bit_no;
+
+ for (p = q; p != 0; p = obj_link(p)){
+ h = HBLKPTR(p);
+ if (h != last_h) {
+ last_h = h;
+ hhdr = HDR(h);
+ IF_PER_OBJ(sz = hhdr->hb_sz;)
+ }
+ bit_no = MARK_BIT_NO((ptr_t)p - (ptr_t)h, sz);
+ if (!mark_bit_from_hdr(hhdr, bit_no)) {
+ set_mark_bit_from_hdr(hhdr, bit_no);
+ ++hhdr -> hb_n_marks;
+ }
+ }
+}
+
+#ifdef GC_ASSERTIONS
+/* Check that all mark bits for the free list whose first entry is q */
+/* are set. */
+void GC_check_fl_marks(ptr_t q)
+{
+ ptr_t p;
+
+ for (p = q; p != 0; p = obj_link(p)){
+ if (!GC_is_marked(p)) {
+ GC_err_printf("Unmarked object %p on list %p\n", p, q);
+ ABORT("Unmarked local free list entry.");
+ }
+ }
+}
+#endif
+
+/* Clear all mark bits for the free list whose first entry is q */
+/* Decrement GC_bytes_found by number of bytes on free list. */
+void GC_clear_fl_marks(ptr_t q)
+{
+ ptr_t p;
+ struct hblk * h, * last_h = 0;
+ hdr *hhdr;
+ size_t sz;
+ unsigned bit_no;
+
+ for (p = q; p != 0; p = obj_link(p)){
+ h = HBLKPTR(p);
+ if (h != last_h) {
+ last_h = h;
+ hhdr = HDR(h);
+ sz = hhdr->hb_sz; /* Normally set only once. */
+ }
+ bit_no = MARK_BIT_NO((ptr_t)p - (ptr_t)h, sz);
+ if (mark_bit_from_hdr(hhdr, bit_no)) {
+ size_t n_marks = hhdr -> hb_n_marks - 1;
+ clear_mark_bit_from_hdr(hhdr, bit_no);
+# ifdef PARALLEL_MARK
+ /* Appr. count, don't decrement to zero! */
+ if (0 != n_marks) {
+ hhdr -> hb_n_marks = n_marks;
+ }
+# else
+ hhdr -> hb_n_marks = n_marks;
+# endif
+ }
+ GC_bytes_found -= sz;
+ }
+}
+
+#if defined(GC_ASSERTIONS) && defined(THREADS) && defined(THREAD_LOCAL_ALLOC)
+extern void GC_check_tls(void);
+#endif
+
+/* Finish up a collection. Assumes lock is held, signals are disabled, */
+/* but the world is otherwise running. */
+void GC_finish_collection()
+{
+ CLOCK_TYPE start_time;
+ CLOCK_TYPE finalize_time;
+ CLOCK_TYPE done_time;
+
+# if defined(GC_ASSERTIONS) && defined(THREADS) \
+ && defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
+ /* Check that we marked some of our own data. */
+ /* FIXME: Add more checks. */
+ GC_check_tls();
+# endif
+
+ if (GC_print_stats)
+ GET_TIME(start_time);
+
+ GC_bytes_found = 0;
+# if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
+ if (getenv("GC_PRINT_ADDRESS_MAP") != 0) {
+ GC_print_address_map();
+ }
+# endif
+ COND_DUMP;
+ if (GC_find_leak) {
+ /* Mark all objects on the free list. All objects should be */
+ /* marked when we're done. */
+ {
+ word size; /* current object size */
+ unsigned kind;
+ ptr_t q;
+
+ for (kind = 0; kind < GC_n_kinds; kind++) {
+ for (size = 1; size <= MAXOBJGRANULES; size++) {
+ q = GC_obj_kinds[kind].ok_freelist[size];
+ if (q != 0) GC_set_fl_marks(q);
+ }
+ }
+ }
+ GC_start_reclaim(TRUE);
+ /* The above just checks; it doesn't really reclaim anything. */
+ }
+
+ GC_finalize();
+# ifdef STUBBORN_ALLOC
+ GC_clean_changing_list();
+# endif
+
+ if (GC_print_stats)
+ GET_TIME(finalize_time);
+
+ if (GC_print_back_height) {
+# ifdef MAKE_BACK_GRAPH
+ GC_traverse_back_graph();
+# else
+# ifndef SMALL_CONFIG
+ GC_err_printf("Back height not available: "
+ "Rebuild collector with -DMAKE_BACK_GRAPH\n");
+# endif
+# endif
+ }
+
+ /* Clear free list mark bits, in case they got accidentally marked */
+ /* (or GC_find_leak is set and they were intentionally marked). */
+ /* Also subtract memory remaining from GC_bytes_found count. */
+ /* Note that composite objects on free list are cleared. */
+ /* Thus accidentally marking a free list is not a problem; only */
+ /* objects on the list itself will be marked, and that's fixed here. */
+ {
+ word size; /* current object size */
+ ptr_t q; /* pointer to current object */
+ unsigned kind;
+
+ for (kind = 0; kind < GC_n_kinds; kind++) {
+ for (size = 1; size <= MAXOBJGRANULES; size++) {
+ q = GC_obj_kinds[kind].ok_freelist[size];
+ if (q != 0) GC_clear_fl_marks(q);
+ }
+ }
+ }
+
+
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf("Bytes recovered before sweep - f.l. count = %ld\n",
+ (long)GC_bytes_found);
+
+ /* Reconstruct free lists to contain everything not marked */
+ GC_start_reclaim(FALSE);
+ if (GC_print_stats) {
+ GC_log_printf("Heap contains %lu pointer-containing "
+ "+ %lu pointer-free reachable bytes\n",
+ (unsigned long)GC_composite_in_use,
+ (unsigned long)GC_atomic_in_use);
+ }
+ if (GC_is_full_gc) {
+ GC_used_heap_size_after_full = USED_HEAP_SIZE;
+ GC_need_full_gc = FALSE;
+ } else {
+ GC_need_full_gc =
+ USED_HEAP_SIZE - GC_used_heap_size_after_full
+ > min_bytes_allocd();
+ }
+
+ if (GC_print_stats == VERBOSE) {
+ GC_log_printf(
+ "Immediately reclaimed %ld bytes in heap of size %lu bytes",
+ (long)GC_bytes_found,
+ (unsigned long)GC_heapsize);
+# ifdef USE_MUNMAP
+ GC_log_printf("(%lu unmapped)", (unsigned long)GC_unmapped_bytes);
+# endif
+ GC_log_printf("\n");
+ }
+
+ /* Reset or increment counters for next cycle */
+ GC_n_attempts = 0;
+ GC_is_full_gc = FALSE;
+ GC_bytes_allocd_before_gc += GC_bytes_allocd;
+ GC_non_gc_bytes_at_gc = GC_non_gc_bytes;
+ GC_bytes_allocd = 0;
+ GC_bytes_freed = 0;
+ GC_finalizer_bytes_freed = 0;
+
+# ifdef USE_MUNMAP
+ GC_unmap_old();
+# endif
+ if (GC_print_stats) {
+ GET_TIME(done_time);
+ GC_log_printf("Finalize + initiate sweep took %lu + %lu msecs\n",
+ MS_TIME_DIFF(finalize_time,start_time),
+ MS_TIME_DIFF(done_time,finalize_time));
+ }
+}
+
+/* Externally callable routine to invoke full, stop-world collection */
+int GC_try_to_collect(GC_stop_func stop_func)
+{
+ int result;
+ DCL_LOCK_STATE;
+
+ if (!GC_is_initialized) GC_init();
+ if (GC_debugging_started) GC_print_all_smashed();
+ GC_INVOKE_FINALIZERS();
+ LOCK();
+ ENTER_GC();
+ if (!GC_is_initialized) GC_init_inner();
+ /* Minimize junk left in my registers */
+ GC_noop(0,0,0,0,0,0);
+ result = (int)GC_try_to_collect_inner(stop_func);
+ EXIT_GC();
+ UNLOCK();
+ if(result) {
+ if (GC_debugging_started) GC_print_all_smashed();
+ GC_INVOKE_FINALIZERS();
+ }
+ return(result);
+}
+
+void GC_gcollect(void)
+{
+ (void)GC_try_to_collect(GC_never_stop_func);
+ if (GC_have_errors) GC_print_all_errors();
+}
+
+word GC_n_heap_sects = 0; /* Number of sections currently in heap. */
+
+/*
+ * Use the chunk of memory starting at p of size bytes as part of the heap.
+ * Assumes p is HBLKSIZE aligned, and bytes is a multiple of HBLKSIZE.
+ */
+void GC_add_to_heap(struct hblk *p, size_t bytes)
+{
+ hdr * phdr;
+
+ if (GC_n_heap_sects >= MAX_HEAP_SECTS) {
+ ABORT("Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS");
+ }
+ phdr = GC_install_header(p);
+ if (0 == phdr) {
+ /* This is extremely unlikely. Can't add it. This will */
+ /* almost certainly result in a 0 return from the allocator, */
+ /* which is entirely appropriate. */
+ return;
+ }
+ GC_heap_sects[GC_n_heap_sects].hs_start = (ptr_t)p;
+ GC_heap_sects[GC_n_heap_sects].hs_bytes = bytes;
+ GC_n_heap_sects++;
+ phdr -> hb_sz = bytes;
+ phdr -> hb_flags = 0;
+ GC_freehblk(p);
+ GC_heapsize += bytes;
+ if ((ptr_t)p <= (ptr_t)GC_least_plausible_heap_addr
+ || GC_least_plausible_heap_addr == 0) {
+ GC_least_plausible_heap_addr = (void *)((ptr_t)p - sizeof(word));
+ /* Making it a little smaller than necessary prevents */
+ /* us from getting a false hit from the variable */
+ /* itself. There's some unintentional reflection */
+ /* here. */
+ }
+ if ((ptr_t)p + bytes >= (ptr_t)GC_greatest_plausible_heap_addr) {
+ GC_greatest_plausible_heap_addr = (void *)((ptr_t)p + bytes);
+ }
+}
+
+# if !defined(NO_DEBUGGING)
+void GC_print_heap_sects(void)
+{
+ unsigned i;
+
+ GC_printf("Total heap size: %lu\n", (unsigned long) GC_heapsize);
+ for (i = 0; i < GC_n_heap_sects; i++) {
+ ptr_t start = GC_heap_sects[i].hs_start;
+ size_t len = GC_heap_sects[i].hs_bytes;
+ struct hblk *h;
+ unsigned nbl = 0;
+
+ GC_printf("Section %d from %p to %p ", i,
+ start, start + len);
+ for (h = (struct hblk *)start; h < (struct hblk *)(start + len); h++) {
+ if (GC_is_black_listed(h, HBLKSIZE)) nbl++;
+ }
+ GC_printf("%lu/%lu blacklisted\n", (unsigned long)nbl,
+ (unsigned long)(len/HBLKSIZE));
+ }
+}
+# endif
+
+void * GC_least_plausible_heap_addr = (void *)ONES;
+void * GC_greatest_plausible_heap_addr = 0;
+
+static INLINE ptr_t GC_max(ptr_t x, ptr_t y)
+{
+ return(x > y? x : y);
+}
+
+static INLINE ptr_t GC_min(ptr_t x, ptr_t y)
+{
+ return(x < y? x : y);
+}
+
+void GC_set_max_heap_size(GC_word n)
+{
+ GC_max_heapsize = n;
+}
+
+GC_word GC_max_retries = 0;
+
+/*
+ * this explicitly increases the size of the heap. It is used
+ * internally, but may also be invoked from GC_expand_hp by the user.
+ * The argument is in units of HBLKSIZE.
+ * Tiny values of n are rounded up.
+ * Returns FALSE on failure.
+ */
+GC_bool GC_expand_hp_inner(word n)
+{
+ word bytes;
+ struct hblk * space;
+ word expansion_slop; /* Number of bytes by which we expect the */
+ /* heap to expand soon. */
+
+ if (n < MINHINCR) n = MINHINCR;
+ bytes = n * HBLKSIZE;
+ /* Make sure bytes is a multiple of GC_page_size */
+ {
+ word mask = GC_page_size - 1;
+ bytes += mask;
+ bytes &= ~mask;
+ }
+
+ if (GC_max_heapsize != 0 && GC_heapsize + bytes > GC_max_heapsize) {
+ /* Exceeded self-imposed limit */
+ return(FALSE);
+ }
+ space = GET_MEM(bytes);
+ if( space == 0 ) {
+ if (GC_print_stats) {
+ GC_log_printf("Failed to expand heap by %ld bytes\n",
+ (unsigned long)bytes);
+ }
+ return(FALSE);
+ }
+ if (GC_print_stats) {
+ GC_log_printf("Increasing heap size by %lu after %lu allocated bytes\n",
+ (unsigned long)bytes,
+ (unsigned long)GC_bytes_allocd);
+ }
+ expansion_slop = min_bytes_allocd() + 4*MAXHINCR*HBLKSIZE;
+ if ((GC_last_heap_addr == 0 && !((word)space & SIGNB))
+ || (GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space)) {
+ /* Assume the heap is growing up */
+ GC_greatest_plausible_heap_addr =
+ (void *)GC_max((ptr_t)GC_greatest_plausible_heap_addr,
+ (ptr_t)space + bytes + expansion_slop);
+ } else {
+ /* Heap is growing down */
+ GC_least_plausible_heap_addr =
+ (void *)GC_min((ptr_t)GC_least_plausible_heap_addr,
+ (ptr_t)space - expansion_slop);
+ }
+# if defined(LARGE_CONFIG)
+ if (((ptr_t)GC_greatest_plausible_heap_addr <= (ptr_t)space + bytes
+ || (ptr_t)GC_least_plausible_heap_addr >= (ptr_t)space)
+ && GC_heapsize > 0) {
+ /* GC_add_to_heap will fix this, but ... */
+ WARN("Too close to address space limit: blacklisting ineffective\n", 0);
+ }
+# endif
+ GC_prev_heap_addr = GC_last_heap_addr;
+ GC_last_heap_addr = (ptr_t)space;
+ GC_add_to_heap(space, bytes);
+ /* Force GC before we are likely to allocate past expansion_slop */
+ GC_collect_at_heapsize =
+ GC_heapsize + expansion_slop - 2*MAXHINCR*HBLKSIZE;
+# if defined(LARGE_CONFIG)
+ if (GC_collect_at_heapsize < GC_heapsize /* wrapped */)
+ GC_collect_at_heapsize = (word)(-1);
+# endif
+ return(TRUE);
+}
+
+/* Really returns a bool, but it's externally visible, so that's clumsy. */
+/* Arguments is in bytes. */
+int GC_expand_hp(size_t bytes)
+{
+ int result;
+ DCL_LOCK_STATE;
+
+ LOCK();
+ if (!GC_is_initialized) GC_init_inner();
+ result = (int)GC_expand_hp_inner(divHBLKSZ((word)bytes));
+ if (result) GC_requested_heapsize += bytes;
+ UNLOCK();
+ return(result);
+}
+
+unsigned GC_fail_count = 0;
+ /* How many consecutive GC/expansion failures? */
+ /* Reset by GC_allochblk. */
+
+GC_bool GC_collect_or_expand(word needed_blocks, GC_bool ignore_off_page)
+{
+ if (!GC_incremental && !GC_dont_gc &&
+ ((GC_dont_expand && GC_bytes_allocd > 0) || GC_should_collect())) {
+ GC_gcollect_inner();
+ } else {
+ word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor)
+ + needed_blocks;
+
+ if (blocks_to_get > MAXHINCR) {
+ word slop;
+
+ /* Get the minimum required to make it likely that we */
+ /* can satisfy the current request in the presence of black- */
+ /* listing. This will probably be more than MAXHINCR. */
+ if (ignore_off_page) {
+ slop = 4;
+ } else {
+ slop = 2*divHBLKSZ(BL_LIMIT);
+ if (slop > needed_blocks) slop = needed_blocks;
+ }
+ if (needed_blocks + slop > MAXHINCR) {
+ blocks_to_get = needed_blocks + slop;
+ } else {
+ blocks_to_get = MAXHINCR;
+ }
+ }
+ if (!GC_expand_hp_inner(blocks_to_get)
+ && !GC_expand_hp_inner(needed_blocks)) {
+ if (GC_fail_count++ < GC_max_retries) {
+ WARN("Out of Memory! Trying to continue ...\n", 0);
+ GC_gcollect_inner();
+ } else {
+# if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC)
+ WARN("Out of Memory! Returning NIL!\n", 0);
+# endif
+ return(FALSE);
+ }
+ } else {
+ if (GC_fail_count && GC_print_stats) {
+ GC_printf("Memory available again ...\n");
+ }
+ }
+ }
+ return(TRUE);
+}
+
+/*
+ * Make sure the object free list for size gran (in granules) is not empty.
+ * Return a pointer to the first object on the free list.
+ * The object MUST BE REMOVED FROM THE FREE LIST BY THE CALLER.
+ * Assumes we hold the allocator lock and signals are disabled.
+ *
+ */
+ptr_t GC_allocobj(size_t gran, int kind)
+{
+ void ** flh = &(GC_obj_kinds[kind].ok_freelist[gran]);
+ GC_bool tried_minor = FALSE;
+
+ if (gran == 0) return(0);
+
+ while (*flh == 0) {
+ ENTER_GC();
+ /* Do our share of marking work */
+ if(TRUE_INCREMENTAL) GC_collect_a_little_inner(1);
+ /* Sweep blocks for objects of this size */
+ GC_continue_reclaim(gran, kind);
+ EXIT_GC();
+ if (*flh == 0) {
+ GC_new_hblk(gran, kind);
+ }
+ if (*flh == 0) {
+ ENTER_GC();
+ if (GC_incremental && GC_time_limit == GC_TIME_UNLIMITED
+ && ! tried_minor ) {
+ GC_collect_a_little_inner(1);
+ tried_minor = TRUE;
+ } else {
+ if (!GC_collect_or_expand((word)1,FALSE)) {
+ EXIT_GC();
+ return(0);
+ }
+ }
+ EXIT_GC();
+ }
+ }
+ /* Successful allocation; reset failure count. */
+ GC_fail_count = 0;
+
+ return(*flh);
+}
diff --git a/tools/build/v2/engine/boehm_gc/alpha_mach_dep.S b/tools/build/v2/engine/boehm_gc/alpha_mach_dep.S
new file mode 100644
index 0000000000..d4def2405f
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/alpha_mach_dep.S
@@ -0,0 +1,86 @@
+ .arch ev6
+
+ .text
+ .align 4
+ .globl GC_push_regs
+ .ent GC_push_regs 2
+GC_push_regs:
+ ldgp $gp, 0($27)
+ lda $sp, -16($sp)
+ stq $26, 0($sp)
+ .mask 0x04000000, 0
+ .frame $sp, 16, $26, 0
+
+/* $0 integer result */
+/* $1-$8 temp regs - not preserved cross calls */
+/* $9-$15 call saved regs */
+/* $16-$21 argument regs - not preserved cross calls */
+/* $22-$28 temp regs - not preserved cross calls */
+/* $29 global pointer - not preserved cross calls */
+/* $30 stack pointer */
+
+# define call_push(x) \
+ mov x, $16; \
+ jsr $26, GC_push_one; \
+ ldgp $gp, 0($26)
+
+ call_push($9)
+ call_push($10)
+ call_push($11)
+ call_push($12)
+ call_push($13)
+ call_push($14)
+ call_push($15)
+
+/* $f0-$f1 floating point results */
+/* $f2-$f9 call saved regs */
+/* $f10-$f30 temp regs - not preserved cross calls */
+
+ /* Use the most efficient transfer method for this hardware. */
+ /* Bit 1 detects the FIX extension, which includes ftoit. */
+ amask 2, $0
+ bne $0, $use_stack
+
+#undef call_push
+#define call_push(x) \
+ ftoit x, $16; \
+ jsr $26, GC_push_one; \
+ ldgp $gp, 0($26)
+
+ call_push($f2)
+ call_push($f3)
+ call_push($f4)
+ call_push($f5)
+ call_push($f6)
+ call_push($f7)
+ call_push($f8)
+ call_push($f9)
+
+ ldq $26, 0($sp)
+ lda $sp, 16($sp)
+ ret $31, ($26), 1
+
+ .align 4
+$use_stack:
+
+#undef call_push
+#define call_push(x) \
+ stt x, 8($sp); \
+ ldq $16, 8($sp); \
+ jsr $26, GC_push_one; \
+ ldgp $gp, 0($26)
+
+ call_push($f2)
+ call_push($f3)
+ call_push($f4)
+ call_push($f5)
+ call_push($f6)
+ call_push($f7)
+ call_push($f8)
+ call_push($f9)
+
+ ldq $26, 0($sp)
+ lda $sp, 16($sp)
+ ret $31, ($26), 1
+
+ .end GC_push_regs
diff --git a/tools/build/v2/engine/boehm_gc/backgraph.c b/tools/build/v2/engine/boehm_gc/backgraph.c
new file mode 100644
index 0000000000..59c330f467
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/backgraph.c
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+/*
+ * This implements a full, though not well-tuned, representation of the
+ * backwards points-to graph. This is used to test for non-GC-robust
+ * data structures; the code is not used during normal garbage collection.
+ *
+ * One restriction is that we drop all back-edges from nodes with very
+ * high in-degree, and simply add them add them to a list of such
+ * nodes. They are then treated as permanent roots. Id this by itself
+ * doesn't introduce a space leak, then such nodes can't contribute to
+ * a growing space leak.
+ */
+
+#ifdef MAKE_BACK_GRAPH
+
+#define MAX_IN 10 /* Maximum in-degree we handle directly */
+
+#include "private/dbg_mlc.h"
+#include <unistd.h>
+
+#if !defined(DBG_HDRS_ALL) || (ALIGNMENT != CPP_WORDSZ/8) || !defined(UNIX_LIKE)
+# error Configuration doesnt support MAKE_BACK_GRAPH
+#endif
+
+/* We store single back pointers directly in the object's oh_bg_ptr field. */
+/* If there is more than one ptr to an object, we store q | FLAG_MANY, */
+/* where q is a pointer to a back_edges object. */
+/* Every once in a while we use a back_edges object even for a single */
+/* pointer, since we need the other fields in the back_edges structure to */
+/* be present in some fraction of the objects. Otherwise we get serious */
+/* performance issues. */
+#define FLAG_MANY 2
+
+typedef struct back_edges_struct {
+ word n_edges; /* Number of edges, including those in continuation */
+ /* structures. */
+ unsigned short flags;
+# define RETAIN 1 /* Directly points to a reachable object; */
+ /* retain for next GC. */
+ unsigned short height_gc_no;
+ /* If height > 0, then the GC_gc_no value when it */
+ /* was computed. If it was computed this cycle, then */
+ /* it is current. If it was computed during the */
+ /* last cycle, then it represents the old height, */
+ /* which is only saved for live objects referenced by */
+ /* dead ones. This may grow due to refs from newly */
+ /* dead objects. */
+ signed_word height;
+ /* Longest path through unreachable nodes to this node */
+ /* that we found using depth first search. */
+
+# define HEIGHT_UNKNOWN ((signed_word)(-2))
+# define HEIGHT_IN_PROGRESS ((signed_word)(-1))
+ ptr_t edges[MAX_IN];
+ struct back_edges_struct *cont;
+ /* Pointer to continuation structure; we use only the */
+ /* edges field in the continuation. */
+ /* also used as free list link. */
+} back_edges;
+
+/* Allocate a new back edge structure. Should be more sophisticated */
+/* if this were production code. */
+#define MAX_BACK_EDGE_STRUCTS 100000
+static back_edges *back_edge_space = 0;
+int GC_n_back_edge_structs = 0; /* Serves as pointer to never used */
+ /* back_edges space. */
+static back_edges *avail_back_edges = 0;
+ /* Pointer to free list of deallocated */
+ /* back_edges structures. */
+
+static back_edges * new_back_edges(void)
+{
+ if (0 == back_edge_space) {
+ back_edge_space = (back_edges *)
+ GET_MEM(MAX_BACK_EDGE_STRUCTS*sizeof(back_edges));
+ }
+ if (0 != avail_back_edges) {
+ back_edges * result = avail_back_edges;
+ avail_back_edges = result -> cont;
+ result -> cont = 0;
+ return result;
+ }
+ if (GC_n_back_edge_structs >= MAX_BACK_EDGE_STRUCTS - 1) {
+ ABORT("needed too much space for back edges: adjust "
+ "MAX_BACK_EDGE_STRUCTS");
+ }
+ return back_edge_space + (GC_n_back_edge_structs++);
+}
+
+/* Deallocate p and its associated continuation structures. */
+static void deallocate_back_edges(back_edges *p)
+{
+ back_edges *last = p;
+
+ while (0 != last -> cont) last = last -> cont;
+ last -> cont = avail_back_edges;
+ avail_back_edges = p;
+}
+
+/* Table of objects that are currently on the depth-first search */
+/* stack. Only objects with in-degree one are in this table. */
+/* Other objects are identified using HEIGHT_IN_PROGRESS. */
+/* FIXME: This data structure NEEDS IMPROVEMENT. */
+#define INITIAL_IN_PROGRESS 10000
+static ptr_t * in_progress_space = 0;
+static size_t in_progress_size = 0;
+static size_t n_in_progress = 0;
+
+static void push_in_progress(ptr_t p)
+{
+ if (n_in_progress >= in_progress_size)
+ if (in_progress_size == 0) {
+ in_progress_size = INITIAL_IN_PROGRESS;
+ in_progress_space = (ptr_t *)GET_MEM(in_progress_size * sizeof(ptr_t));
+ } else {
+ ptr_t * new_in_progress_space;
+ in_progress_size *= 2;
+ new_in_progress_space = (ptr_t *)
+ GET_MEM(in_progress_size * sizeof(ptr_t));
+ BCOPY(in_progress_space, new_in_progress_space,
+ n_in_progress * sizeof(ptr_t));
+ in_progress_space = new_in_progress_space;
+ /* FIXME: This just drops the old space. */
+ }
+ if (in_progress_space == 0)
+ ABORT("MAKE_BACK_GRAPH: Out of in-progress space: "
+ "Huge linear data structure?");
+ in_progress_space[n_in_progress++] = p;
+}
+
+static GC_bool is_in_progress(ptr_t p)
+{
+ int i;
+ for (i = 0; i < n_in_progress; ++i) {
+ if (in_progress_space[i] == p) return TRUE;
+ }
+ return FALSE;
+}
+
+static void pop_in_progress(ptr_t p)
+{
+ --n_in_progress;
+ GC_ASSERT(in_progress_space[n_in_progress] == p);
+}
+
+#define GET_OH_BG_PTR(p) \
+ (ptr_t)REVEAL_POINTER(((oh *)(p)) -> oh_bg_ptr)
+#define SET_OH_BG_PTR(p,q) (((oh *)(p)) -> oh_bg_ptr) = HIDE_POINTER(q)
+
+/* Execute s once for each predecessor q of p in the points-to graph. */
+/* s should be a bracketed statement. We declare q. */
+#define FOR_EACH_PRED(q, p, s) \
+ { \
+ ptr_t q = GET_OH_BG_PTR(p); \
+ if (!((word)q & FLAG_MANY)) { \
+ if (q && !((word)q & 1)) s \
+ /* !((word)q & 1) checks for a misnterpreted freelist link */ \
+ } else { \
+ back_edges *orig_be_ = (back_edges *)((word)q & ~FLAG_MANY); \
+ back_edges *be_ = orig_be_; \
+ int total_, local_; \
+ int n_edges_ = be_ -> n_edges; \
+ for (total_ = 0, local_ = 0; total_ < n_edges_; ++local_, ++total_) { \
+ if (local_ == MAX_IN) { \
+ be_ = be_ -> cont; \
+ local_ = 0; \
+ } \
+ q = be_ -> edges[local_]; s \
+ } \
+ } \
+ }
+
+/* Ensure that p has a back_edges structure associated with it. */
+static void ensure_struct(ptr_t p)
+{
+ ptr_t old_back_ptr = GET_OH_BG_PTR(p);
+
+ if (!((word)old_back_ptr & FLAG_MANY)) {
+ back_edges *be = new_back_edges();
+ be -> flags = 0;
+ if (0 == old_back_ptr) {
+ be -> n_edges = 0;
+ } else {
+ be -> n_edges = 1;
+ be -> edges[0] = old_back_ptr;
+ }
+ be -> height = HEIGHT_UNKNOWN;
+ be -> height_gc_no = GC_gc_no - 1;
+ GC_ASSERT(be >= back_edge_space);
+ SET_OH_BG_PTR(p, (word)be | FLAG_MANY);
+ }
+}
+
+/* Add the (forward) edge from p to q to the backward graph. Both p */
+/* q are pointers to the object base, i.e. pointers to an oh. */
+static void add_edge(ptr_t p, ptr_t q)
+{
+ ptr_t old_back_ptr = GET_OH_BG_PTR(q);
+ back_edges * be, *be_cont;
+ word i;
+ static unsigned random_number = 13;
+# define GOT_LUCKY_NUMBER (((++random_number) & 0x7f) == 0)
+ /* A not very random number we use to occasionally allocate a */
+ /* back_edges structure even for a single backward edge. This */
+ /* prevents us from repeatedly tracing back through very long */
+ /* chains, since we will have some place to store height and */
+ /* in_progress flags along the way. */
+
+ GC_ASSERT(p == GC_base(p) && q == GC_base(q));
+ if (!GC_HAS_DEBUG_INFO(q) || !GC_HAS_DEBUG_INFO(p)) {
+ /* This is really a misinterpreted free list link, since we saw */
+ /* a pointer to a free list. Dont overwrite it! */
+ return;
+ }
+ if (0 == old_back_ptr) {
+ SET_OH_BG_PTR(q, p);
+ if (GOT_LUCKY_NUMBER) ensure_struct(q);
+ return;
+ }
+ /* Check whether it was already in the list of predecessors. */
+ FOR_EACH_PRED(pred, q, { if (p == pred) return; });
+ ensure_struct(q);
+ old_back_ptr = GET_OH_BG_PTR(q);
+ be = (back_edges *)((word)old_back_ptr & ~FLAG_MANY);
+ for (i = be -> n_edges, be_cont = be; i > MAX_IN;
+ be_cont = be_cont -> cont, i -= MAX_IN) {}
+ if (i == MAX_IN) {
+ be_cont -> cont = new_back_edges();
+ be_cont = be_cont -> cont;
+ i = 0;
+ }
+ be_cont -> edges[i] = p;
+ be -> n_edges++;
+ if (be -> n_edges == 100) {
+# if 0
+ if (GC_print_stats) {
+ GC_err_printf("The following object has in-degree >= 100:\n");
+ GC_print_heap_obj(q);
+ }
+# endif
+ }
+}
+
+typedef void (*per_object_func)(ptr_t p, size_t n_bytes, word gc_descr);
+
+static void per_object_helper(struct hblk *h, word fn)
+{
+ hdr * hhdr = HDR(h);
+ size_t sz = hhdr -> hb_sz;
+ word descr = hhdr -> hb_descr;
+ per_object_func f = (per_object_func)fn;
+ int i = 0;
+
+ do {
+ f((ptr_t)(h -> hb_body + i), sz, descr);
+ i += sz;
+ } while (i + sz <= BYTES_TO_WORDS(HBLKSIZE));
+}
+
+void GC_apply_to_each_object(per_object_func f)
+{
+ GC_apply_to_all_blocks(per_object_helper, (word)f);
+}
+
+static void reset_back_edge(ptr_t p, size_t n_bytes, word gc_descr)
+{
+ /* Skip any free list links, or dropped blocks */
+ if (GC_HAS_DEBUG_INFO(p)) {
+ ptr_t old_back_ptr = GET_OH_BG_PTR(p);
+ if ((word)old_back_ptr & FLAG_MANY) {
+ back_edges *be = (back_edges *)((word)old_back_ptr & ~FLAG_MANY);
+ if (!(be -> flags & RETAIN)) {
+ deallocate_back_edges(be);
+ SET_OH_BG_PTR(p, 0);
+ } else {
+ word *currentp;
+
+ GC_ASSERT(GC_is_marked(p));
+
+ /* Back edges may point to objects that will not be retained. */
+ /* Delete them for now, but remember the height. */
+ /* Some will be added back at next GC. */
+ be -> n_edges = 0;
+ if (0 != be -> cont) {
+ deallocate_back_edges(be -> cont);
+ be -> cont = 0;
+ }
+
+ GC_ASSERT(GC_is_marked(p));
+
+ /* We only retain things for one GC cycle at a time. */
+ be -> flags &= ~RETAIN;
+ }
+ } else /* Simple back pointer */ {
+ /* Clear to avoid dangling pointer. */
+ SET_OH_BG_PTR(p, 0);
+ }
+ }
+}
+
+static void add_back_edges(ptr_t p, size_t n_bytes, word gc_descr)
+{
+ word *currentp = (word *)(p + sizeof(oh));
+
+ /* For now, fix up non-length descriptors conservatively. */
+ if((gc_descr & GC_DS_TAGS) != GC_DS_LENGTH) {
+ gc_descr = n_bytes;
+ }
+ while (currentp < (word *)(p + gc_descr)) {
+ word current = *currentp++;
+ FIXUP_POINTER(current);
+ if (current >= (word)GC_least_plausible_heap_addr &&
+ current <= (word)GC_greatest_plausible_heap_addr) {
+ ptr_t target = GC_base((void *)current);
+ if (0 != target) {
+ add_edge(p, target);
+ }
+ }
+ }
+}
+
+/* Rebuild the representation of the backward reachability graph. */
+/* Does not examine mark bits. Can be called before GC. */
+void GC_build_back_graph(void)
+{
+ GC_apply_to_each_object(add_back_edges);
+}
+
+/* Return an approximation to the length of the longest simple path */
+/* through unreachable objects to p. We refer to this as the height */
+/* of p. */
+static word backwards_height(ptr_t p)
+{
+ word result;
+ ptr_t back_ptr = GET_OH_BG_PTR(p);
+ back_edges *be;
+
+ if (0 == back_ptr) return 1;
+ if (!((word)back_ptr & FLAG_MANY)) {
+ if (is_in_progress(p)) return 0; /* DFS back edge, i.e. we followed */
+ /* an edge to an object already */
+ /* on our stack: ignore */
+ push_in_progress(p);
+ result = backwards_height(back_ptr)+1;
+ pop_in_progress(p);
+ return result;
+ }
+ be = (back_edges *)((word)back_ptr & ~FLAG_MANY);
+ if (be -> height >= 0 && be -> height_gc_no == GC_gc_no)
+ return be -> height;
+ /* Ignore back edges in DFS */
+ if (be -> height == HEIGHT_IN_PROGRESS) return 0;
+ result = (be -> height > 0? be -> height : 1);
+ be -> height = HEIGHT_IN_PROGRESS;
+ FOR_EACH_PRED(q, p, {
+ word this_height;
+ if (GC_is_marked(q) && !(FLAG_MANY & (word)GET_OH_BG_PTR(p))) {
+ if (GC_print_stats)
+ GC_log_printf("Found bogus pointer from 0x%lx to 0x%lx\n", q, p);
+ /* Reachable object "points to" unreachable one. */
+ /* Could be caused by our lax treatment of GC descriptors. */
+ this_height = 1;
+ } else {
+ this_height = backwards_height(q);
+ }
+ if (this_height >= result) result = this_height + 1;
+ });
+ be -> height = result;
+ be -> height_gc_no = GC_gc_no;
+ return result;
+}
+
+word GC_max_height;
+ptr_t GC_deepest_obj;
+
+/* Compute the maximum height of every unreachable predecessor p of a */
+/* reachable object. Arrange to save the heights of all such objects p */
+/* so that they can be used in calculating the height of objects in the */
+/* next GC. */
+/* Set GC_max_height to be the maximum height we encounter, and */
+/* GC_deepest_obj to be the corresponding object. */
+static void update_max_height(ptr_t p, size_t n_bytes, word gc_descr)
+{
+ if (GC_is_marked(p) && GC_HAS_DEBUG_INFO(p)) {
+ int i;
+ word p_height = 0;
+ ptr_t p_deepest_obj = 0;
+ ptr_t back_ptr;
+ back_edges *be = 0;
+
+ /* If we remembered a height last time, use it as a minimum. */
+ /* It may have increased due to newly unreachable chains pointing */
+ /* to p, but it can't have decreased. */
+ back_ptr = GET_OH_BG_PTR(p);
+ if (0 != back_ptr && ((word)back_ptr & FLAG_MANY)) {
+ be = (back_edges *)((word)back_ptr & ~FLAG_MANY);
+ if (be -> height != HEIGHT_UNKNOWN) p_height = be -> height;
+ }
+ FOR_EACH_PRED(q, p, {
+ if (!GC_is_marked(q) && GC_HAS_DEBUG_INFO(q)) {
+ word q_height;
+
+ q_height = backwards_height(q);
+ if (q_height > p_height) {
+ p_height = q_height;
+ p_deepest_obj = q;
+ }
+ }
+ });
+ if (p_height > 0) {
+ /* Remember the height for next time. */
+ if (be == 0) {
+ ensure_struct(p);
+ back_ptr = GET_OH_BG_PTR(p);
+ be = (back_edges *)((word)back_ptr & ~FLAG_MANY);
+ }
+ be -> flags |= RETAIN;
+ be -> height = p_height;
+ be -> height_gc_no = GC_gc_no;
+ }
+ if (p_height > GC_max_height) {
+ GC_max_height = p_height;
+ GC_deepest_obj = p_deepest_obj;
+ }
+ }
+}
+
+word GC_max_max_height = 0;
+
+void GC_traverse_back_graph(void)
+{
+ GC_max_height = 0;
+ GC_apply_to_each_object(update_max_height);
+ if (0 != GC_deepest_obj)
+ GC_set_mark_bit(GC_deepest_obj); /* Keep it until we can print it. */
+}
+
+void GC_print_back_graph_stats(void)
+{
+ GC_printf("Maximum backwards height of reachable objects at GC %lu is %ld\n",
+ (unsigned long) GC_gc_no, (unsigned long)GC_max_height);
+ if (GC_max_height > GC_max_max_height) {
+ GC_max_max_height = GC_max_height;
+ GC_printf("The following unreachable object is last in a longest chain "
+ "of unreachable objects:\n");
+ GC_print_heap_obj(GC_deepest_obj);
+ }
+ if (GC_print_stats) {
+ GC_log_printf("Needed max total of %ld back-edge structs\n",
+ GC_n_back_edge_structs);
+ }
+ GC_apply_to_each_object(reset_back_edge);
+ GC_deepest_obj = 0;
+}
+
+#endif /* MAKE_BACK_GRAPH */
diff --git a/tools/build/v2/engine/boehm_gc/bdw-gc.pc b/tools/build/v2/engine/boehm_gc/bdw-gc.pc
new file mode 100644
index 0000000000..55fc3346f8
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/bdw-gc.pc
@@ -0,0 +1,10 @@
+prefix=/usr/local
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: Boehm-Demers-Weiser Conservative Garbage Collector
+Description: A garbage collector for C and C++
+Version: 7.0
+Libs: -L${libdir} -lgc
+Cflags: -I${includedir}
diff --git a/tools/build/v2/engine/boehm_gc/bdw-gc.pc.in b/tools/build/v2/engine/boehm_gc/bdw-gc.pc.in
new file mode 100644
index 0000000000..ef4c23410d
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/bdw-gc.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Boehm-Demers-Weiser Conservative Garbage Collector
+Description: A garbage collector for C and C++
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lgc
+Cflags: -I${includedir}
diff --git a/tools/build/v2/engine/boehm_gc/blacklst.c b/tools/build/v2/engine/boehm_gc/blacklst.c
new file mode 100644
index 0000000000..afcad9c216
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/blacklst.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, August 9, 1995 6:09 pm PDT */
+# include "private/gc_priv.h"
+
+/*
+ * We maintain several hash tables of hblks that have had false hits.
+ * Each contains one bit per hash bucket; If any page in the bucket
+ * has had a false hit, we assume that all of them have.
+ * See the definition of page_hash_table in gc_private.h.
+ * False hits from the stack(s) are much more dangerous than false hits
+ * from elsewhere, since the former can pin a large object that spans the
+ * block, eventhough it does not start on the dangerous block.
+ */
+
+/*
+ * Externally callable routines are:
+
+ * GC_add_to_black_list_normal
+ * GC_add_to_black_list_stack
+ * GC_promote_black_lists
+ * GC_is_black_listed
+ *
+ * All require that the allocator lock is held.
+ */
+
+/* Pointers to individual tables. We replace one table by another by */
+/* switching these pointers. */
+word * GC_old_normal_bl;
+ /* Nonstack false references seen at last full */
+ /* collection. */
+word * GC_incomplete_normal_bl;
+ /* Nonstack false references seen since last */
+ /* full collection. */
+word * GC_old_stack_bl;
+word * GC_incomplete_stack_bl;
+
+word GC_total_stack_black_listed;
+
+word GC_black_list_spacing = MINHINCR*HBLKSIZE; /* Initial rough guess */
+
+void GC_clear_bl(word *);
+
+void GC_default_print_heap_obj_proc(ptr_t p)
+{
+ ptr_t base = GC_base(p);
+
+ GC_err_printf("start: %p, appr. length: %ld", base,
+ (unsigned long)GC_size(base));
+}
+
+void (*GC_print_heap_obj) (ptr_t p) = GC_default_print_heap_obj_proc;
+
+void GC_print_source_ptr(ptr_t p)
+{
+ ptr_t base = GC_base(p);
+ if (0 == base) {
+ if (0 == p) {
+ GC_err_printf("in register");
+ } else {
+ GC_err_printf("in root set");
+ }
+ } else {
+ GC_err_printf("in object at ");
+ (*GC_print_heap_obj)(base);
+ }
+}
+
+void GC_bl_init(void)
+{
+ if (!GC_all_interior_pointers) {
+ GC_old_normal_bl = (word *)
+ GC_scratch_alloc((word)(sizeof (page_hash_table)));
+ GC_incomplete_normal_bl = (word *)GC_scratch_alloc
+ ((word)(sizeof(page_hash_table)));
+ if (GC_old_normal_bl == 0 || GC_incomplete_normal_bl == 0) {
+ GC_err_printf("Insufficient memory for black list\n");
+ EXIT();
+ }
+ GC_clear_bl(GC_old_normal_bl);
+ GC_clear_bl(GC_incomplete_normal_bl);
+ }
+ GC_old_stack_bl = (word *)GC_scratch_alloc((word)(sizeof(page_hash_table)));
+ GC_incomplete_stack_bl = (word *)GC_scratch_alloc
+ ((word)(sizeof(page_hash_table)));
+ if (GC_old_stack_bl == 0 || GC_incomplete_stack_bl == 0) {
+ GC_err_printf("Insufficient memory for black list\n");
+ EXIT();
+ }
+ GC_clear_bl(GC_old_stack_bl);
+ GC_clear_bl(GC_incomplete_stack_bl);
+}
+
+void GC_clear_bl(word *doomed)
+{
+ BZERO(doomed, sizeof(page_hash_table));
+}
+
+void GC_copy_bl(word *old, word *new)
+{
+ BCOPY(old, new, sizeof(page_hash_table));
+}
+
+static word total_stack_black_listed(void);
+
+/* Signal the completion of a collection. Turn the incomplete black */
+/* lists into new black lists, etc. */
+void GC_promote_black_lists(void)
+{
+ word * very_old_normal_bl = GC_old_normal_bl;
+ word * very_old_stack_bl = GC_old_stack_bl;
+
+ GC_old_normal_bl = GC_incomplete_normal_bl;
+ GC_old_stack_bl = GC_incomplete_stack_bl;
+ if (!GC_all_interior_pointers) {
+ GC_clear_bl(very_old_normal_bl);
+ }
+ GC_clear_bl(very_old_stack_bl);
+ GC_incomplete_normal_bl = very_old_normal_bl;
+ GC_incomplete_stack_bl = very_old_stack_bl;
+ GC_total_stack_black_listed = total_stack_black_listed();
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf("%ld bytes in heap blacklisted for interior pointers\n",
+ (unsigned long)GC_total_stack_black_listed);
+ if (GC_total_stack_black_listed != 0) {
+ GC_black_list_spacing =
+ HBLKSIZE*(GC_heapsize/GC_total_stack_black_listed);
+ }
+ if (GC_black_list_spacing < 3 * HBLKSIZE) {
+ GC_black_list_spacing = 3 * HBLKSIZE;
+ }
+ if (GC_black_list_spacing > MAXHINCR * HBLKSIZE) {
+ GC_black_list_spacing = MAXHINCR * HBLKSIZE;
+ /* Makes it easier to allocate really huge blocks, which otherwise */
+ /* may have problems with nonuniform blacklist distributions. */
+ /* This way we should always succeed immediately after growing the */
+ /* heap. */
+ }
+}
+
+void GC_unpromote_black_lists(void)
+{
+ if (!GC_all_interior_pointers) {
+ GC_copy_bl(GC_old_normal_bl, GC_incomplete_normal_bl);
+ }
+ GC_copy_bl(GC_old_stack_bl, GC_incomplete_stack_bl);
+}
+
+/* P is not a valid pointer reference, but it falls inside */
+/* the plausible heap bounds. */
+/* Add it to the normal incomplete black list if appropriate. */
+#ifdef PRINT_BLACK_LIST
+ void GC_add_to_black_list_normal(word p, ptr_t source)
+#else
+ void GC_add_to_black_list_normal(word p)
+#endif
+{
+ if (!(GC_modws_valid_offsets[p & (sizeof(word)-1)])) return;
+ {
+ word index = PHT_HASH((word)p);
+
+ if (HDR(p) == 0 || get_pht_entry_from_index(GC_old_normal_bl, index)) {
+# ifdef PRINT_BLACK_LIST
+ if (!get_pht_entry_from_index(GC_incomplete_normal_bl, index)) {
+ GC_err_printf(
+ "Black listing (normal) %p referenced from %p ",
+ (ptr_t) p, source);
+ GC_print_source_ptr(source);
+ GC_err_puts("\n");
+ }
+# endif
+ set_pht_entry_from_index(GC_incomplete_normal_bl, index);
+ } /* else this is probably just an interior pointer to an allocated */
+ /* object, and isn't worth black listing. */
+ }
+}
+
+/* And the same for false pointers from the stack. */
+#ifdef PRINT_BLACK_LIST
+ void GC_add_to_black_list_stack(word p, ptr_t source)
+ ptr_t source;
+#else
+ void GC_add_to_black_list_stack(word p)
+#endif
+{
+ word index = PHT_HASH((word)p);
+
+ if (HDR(p) == 0 || get_pht_entry_from_index(GC_old_stack_bl, index)) {
+# ifdef PRINT_BLACK_LIST
+ if (!get_pht_entry_from_index(GC_incomplete_stack_bl, index)) {
+ GC_err_printf(
+ "Black listing (stack) %p referenced from %p ",
+ (ptr_t)p, source);
+ GC_print_source_ptr(source);
+ GC_err_puts("\n");
+ }
+# endif
+ set_pht_entry_from_index(GC_incomplete_stack_bl, index);
+ }
+}
+
+/*
+ * Is the block starting at h of size len bytes black listed? If so,
+ * return the address of the next plausible r such that (r, len) might not
+ * be black listed. (R may not actually be in the heap. We guarantee only
+ * that every smaller value of r after h is also black listed.)
+ * If (h,len) is not black listed, return 0.
+ * Knows about the structure of the black list hash tables.
+ */
+struct hblk * GC_is_black_listed(struct hblk *h, word len)
+{
+ word index = PHT_HASH((word)h);
+ word i;
+ word nblocks = divHBLKSZ(len);
+
+ if (!GC_all_interior_pointers) {
+ if (get_pht_entry_from_index(GC_old_normal_bl, index)
+ || get_pht_entry_from_index(GC_incomplete_normal_bl, index)) {
+ return(h+1);
+ }
+ }
+
+ for (i = 0; ; ) {
+ if (GC_old_stack_bl[divWORDSZ(index)] == 0
+ && GC_incomplete_stack_bl[divWORDSZ(index)] == 0) {
+ /* An easy case */
+ i += WORDSZ - modWORDSZ(index);
+ } else {
+ if (get_pht_entry_from_index(GC_old_stack_bl, index)
+ || get_pht_entry_from_index(GC_incomplete_stack_bl, index)) {
+ return(h+i+1);
+ }
+ i++;
+ }
+ if (i >= nblocks) break;
+ index = PHT_HASH((word)(h+i));
+ }
+ return(0);
+}
+
+
+/* Return the number of blacklisted blocks in a given range. */
+/* Used only for statistical purposes. */
+/* Looks only at the GC_incomplete_stack_bl. */
+word GC_number_stack_black_listed(struct hblk *start, struct hblk *endp1)
+{
+ register struct hblk * h;
+ word result = 0;
+
+ for (h = start; h < endp1; h++) {
+ word index = PHT_HASH((word)h);
+
+ if (get_pht_entry_from_index(GC_old_stack_bl, index)) result++;
+ }
+ return(result);
+}
+
+
+/* Return the total number of (stack) black-listed bytes. */
+static word total_stack_black_listed(void)
+{
+ register unsigned i;
+ word total = 0;
+
+ for (i = 0; i < GC_n_heap_sects; i++) {
+ struct hblk * start = (struct hblk *) GC_heap_sects[i].hs_start;
+ size_t len = (word) GC_heap_sects[i].hs_bytes;
+ struct hblk * endp1 = start + len/HBLKSIZE;
+
+ total += GC_number_stack_black_listed(start, endp1);
+ }
+ return(total * HBLKSIZE);
+}
+
diff --git a/tools/build/v2/engine/boehm_gc/callprocs b/tools/build/v2/engine/boehm_gc/callprocs
new file mode 100755
index 0000000000..a8793f0b72
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/callprocs
@@ -0,0 +1,4 @@
+#!/bin/sh
+GC_DEBUG=1
+export GC_DEBUG
+$* 2>&1 | awk '{print "0x3e=c\""$0"\""};/^\t##PC##=/ {if ($2 != 0) {print $2"?i"}}' | adb $1 | sed "s/^ >/>/"
diff --git a/tools/build/v2/engine/boehm_gc/checksums.c b/tools/build/v2/engine/boehm_gc/checksums.c
new file mode 100644
index 0000000000..0942acb48b
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/checksums.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 1992-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, March 29, 1995 12:51 pm PST */
+# ifdef CHECKSUMS
+
+# include "private/gc_priv.h"
+
+/* This is debugging code intended to verify the results of dirty bit */
+/* computations. Works only in a single threaded environment. */
+/* We assume that stubborn objects are changed only when they are */
+/* enabled for writing. (Certain kinds of writing are actually */
+/* safe under other conditions.) */
+# define NSUMS 10000
+
+# define OFFSET 0x10000
+
+typedef struct {
+ GC_bool new_valid;
+ word old_sum;
+ word new_sum;
+ struct hblk * block; /* Block to which this refers + OFFSET */
+ /* to hide it from collector. */
+} page_entry;
+
+page_entry GC_sums [NSUMS];
+
+word GC_checksum(h)
+struct hblk *h;
+{
+ register word *p = (word *)h;
+ register word *lim = (word *)(h+1);
+ register word result = 0;
+
+ while (p < lim) {
+ result += *p++;
+ }
+ return(result | 0x80000000 /* doesn't look like pointer */);
+}
+
+# ifdef STUBBORN_ALLOC
+/* Check whether a stubborn object from the given block appears on */
+/* the appropriate free list. */
+GC_bool GC_on_free_list(struct hblk *h)
+struct hblk *h;
+{
+ hdr * hhdr = HDR(h);
+ int sz = BYTES_TO_WORDS(hhdr -> hb_sz);
+ ptr_t p;
+
+ if (sz > MAXOBJWORDS) return(FALSE);
+ for (p = GC_sobjfreelist[sz]; p != 0; p = obj_link(p)) {
+ if (HBLKPTR(p) == h) return(TRUE);
+ }
+ return(FALSE);
+}
+# endif
+
+int GC_n_dirty_errors;
+int GC_n_changed_errors;
+int GC_n_clean;
+int GC_n_dirty;
+
+void GC_update_check_page(struct hblk *h, int index)
+{
+ page_entry *pe = GC_sums + index;
+ register hdr * hhdr = HDR(h);
+ struct hblk *b;
+
+ if (pe -> block != 0 && pe -> block != h + OFFSET) ABORT("goofed");
+ pe -> old_sum = pe -> new_sum;
+ pe -> new_sum = GC_checksum(h);
+# if !defined(MSWIN32) && !defined(MSWINCE)
+ if (pe -> new_sum != 0x80000000 && !GC_page_was_ever_dirty(h)) {
+ GC_printf("GC_page_was_ever_dirty(%p) is wrong\n", h);
+ }
+# endif
+ if (GC_page_was_dirty(h)) {
+ GC_n_dirty++;
+ } else {
+ GC_n_clean++;
+ }
+ b = h;
+ while (IS_FORWARDING_ADDR_OR_NIL(hhdr) && hhdr != 0) {
+ b -= (word)hhdr;
+ hhdr = HDR(b);
+ }
+ if (pe -> new_valid
+ && hhdr != 0 && hhdr -> hb_descr != 0 /* may contain pointers */
+ && pe -> old_sum != pe -> new_sum) {
+ if (!GC_page_was_dirty(h) || !GC_page_was_ever_dirty(h)) {
+ /* Set breakpoint here */GC_n_dirty_errors++;
+ }
+# ifdef STUBBORN_ALLOC
+ if (!HBLK_IS_FREE(hhdr)
+ && hhdr -> hb_obj_kind == STUBBORN
+ && !GC_page_was_changed(h)
+ && !GC_on_free_list(h)) {
+ /* if GC_on_free_list(h) then reclaim may have touched it */
+ /* without any allocations taking place. */
+ /* Set breakpoint here */GC_n_changed_errors++;
+ }
+# endif
+ }
+ pe -> new_valid = TRUE;
+ pe -> block = h + OFFSET;
+}
+
+unsigned long GC_bytes_in_used_blocks;
+
+void GC_add_block(h, dummy)
+struct hblk *h;
+word dummy;
+{
+ hdr * hhdr = HDR(h);
+ bytes = hhdr -> hb_sz;
+
+ bytes += HBLKSIZE-1;
+ bytes &= ~(HBLKSIZE-1);
+ GC_bytes_in_used_blocks += bytes;
+}
+
+void GC_check_blocks()
+{
+ unsigned long bytes_in_free_blocks = GC_large_free_bytes;
+
+ GC_bytes_in_used_blocks = 0;
+ GC_apply_to_all_blocks(GC_add_block, (word)0);
+ GC_printf("GC_bytes_in_used_blocks = %lu, bytes_in_free_blocks = %lu ",
+ GC_bytes_in_used_blocks, bytes_in_free_blocks);
+ GC_printf("GC_heapsize = %lu\n", (unsigned long)GC_heapsize);
+ if (GC_bytes_in_used_blocks + bytes_in_free_blocks != GC_heapsize) {
+ GC_printf("LOST SOME BLOCKS!!\n");
+ }
+}
+
+/* Should be called immediately after GC_read_dirty and GC_read_changed. */
+void GC_check_dirty()
+{
+ register int index;
+ register unsigned i;
+ register struct hblk *h;
+ register ptr_t start;
+
+ GC_check_blocks();
+
+ GC_n_dirty_errors = 0;
+ GC_n_changed_errors = 0;
+ GC_n_clean = 0;
+ GC_n_dirty = 0;
+
+ index = 0;
+ for (i = 0; i < GC_n_heap_sects; i++) {
+ start = GC_heap_sects[i].hs_start;
+ for (h = (struct hblk *)start;
+ h < (struct hblk *)(start + GC_heap_sects[i].hs_bytes);
+ h++) {
+ GC_update_check_page(h, index);
+ index++;
+ if (index >= NSUMS) goto out;
+ }
+ }
+out:
+ GC_printf("Checked %lu clean and %lu dirty pages\n",
+ (unsigned long) GC_n_clean, (unsigned long) GC_n_dirty);
+ if (GC_n_dirty_errors > 0) {
+ GC_printf("Found %lu dirty bit errors\n",
+ (unsigned long)GC_n_dirty_errors);
+ }
+ if (GC_n_changed_errors > 0) {
+ GC_printf("Found %lu changed bit errors\n",
+ (unsigned long)GC_n_changed_errors);
+ GC_printf("These may be benign (provoked by nonpointer changes)\n");
+# ifdef THREADS
+ GC_printf(
+ "Also expect 1 per thread currently allocating a stubborn obj.\n");
+# endif
+ }
+}
+
+# else
+
+extern int GC_quiet;
+ /* ANSI C doesn't allow translation units to be empty. */
+ /* So we guarantee this one is nonempty. */
+
+# endif /* CHECKSUMS */
diff --git a/tools/build/v2/engine/boehm_gc/compile b/tools/build/v2/engine/boehm_gc/compile
new file mode 100755
index 0000000000..3d2170320e
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/compile
@@ -0,0 +1,142 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand `-c -o'.
+
+scriptversion=2004-10-12.08
+
+# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case $1 in
+ '')
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand `-c -o'.
+Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file `INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit 0
+ ;;
+ -v | --v*)
+ echo "compile $scriptversion"
+ exit 0
+ ;;
+esac
+
+ofile=
+cfile=
+eat=
+
+for arg
+do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as `compile cc -o foo foo.c'.
+ # So we strip `-o arg' only if arg is an object.
+ eat=1
+ case $2 in
+ *.o | *.obj)
+ ofile=$2
+ ;;
+ *)
+ set x "$@" -o "$2"
+ shift
+ ;;
+ esac
+ ;;
+ *.c)
+ cfile=$1
+ set x "$@" "$1"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+ # If no `-o' option was seen then we might have been invoked from a
+ # pattern rule where we don't need one. That is ok -- this is a
+ # normal compilation that the losing compiler can handle. If no
+ # `.c' file was seen then we are probably linking. That is also
+ # ok.
+ exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use `[/.-]' here to ensure that we don't use the same name
+# that we are using for the .o file. Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
+while true; do
+ if mkdir "$lockdir" >/dev/null 2>&1; then
+ break
+ fi
+ sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+ mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+ mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/tools/build/v2/engine/boehm_gc/config.guess b/tools/build/v2/engine/boehm_gc/config.guess
new file mode 100755
index 0000000000..7924ac077d
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/config.guess
@@ -0,0 +1,1500 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+# Inc.
+
+timestamp='2006-06-06'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ x86:Interix*:[345]*)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ EM64T:Interix*:[345]*)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^LIBC/{
+ s: ::g
+ p
+ }'`"
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/build/v2/engine/boehm_gc/config.sub b/tools/build/v2/engine/boehm_gc/config.sub
new file mode 100644
index 0000000000..70584b007e
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/config.sub
@@ -0,0 +1,1608 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+# Inc.
+
+timestamp='2006-06-06'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/build/v2/engine/boehm_gc/configure b/tools/build/v2/engine/boehm_gc/configure
new file mode 100755
index 0000000000..e2092d1cf1
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/configure
@@ -0,0 +1,23503 @@
+#! /bin/sh
+# From configure.ac Revision: 1.25 .
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61 for gc 7.0.
+#
+# Report bugs to <Hans.Boehm@hp.com>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
+ ;;
+esac
+
+echo=${ECHO-echo}
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+ echo_test_string=`eval $cmd` &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+ then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+ else
+ # Try using printf.
+ echo='printf %s\n'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "$0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+ ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+
+tagnames=${tagnames+${tagnames},}CXX
+
+tagnames=${tagnames+${tagnames},}F77
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='gc'
+PACKAGE_TARNAME='gc'
+PACKAGE_VERSION='7.0'
+PACKAGE_STRING='gc 7.0'
+PACKAGE_BUGREPORT='Hans.Boehm@hp.com'
+
+ac_unique_file="gcj_mlc.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+target
+target_cpu
+target_vendor
+target_os
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+CYGPATH_W
+PACKAGE
+VERSION
+ACLOCAL
+AUTOCONF
+AUTOMAKE
+AUTOHEADER
+MAKEINFO
+install_sh
+STRIP
+INSTALL_STRIP_PROGRAM
+mkdir_p
+AWK
+SET_MAKE
+am__leading_dot
+AMTAR
+am__tar
+am__untar
+MAINTAINER_MODE_TRUE
+MAINTAINER_MODE_FALSE
+MAINT
+GC_VERSION
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+DEPDIR
+am__include
+am__quote
+AMDEP_TRUE
+AMDEP_FALSE
+AMDEPBACKSLASH
+CCDEPMODE
+am__fastdepCC_TRUE
+am__fastdepCC_FALSE
+CXX
+CXXFLAGS
+ac_ct_CXX
+CXXDEPMODE
+am__fastdepCXX_TRUE
+am__fastdepCXX_FALSE
+CCAS
+CCASFLAGS
+AR
+RANLIB
+GC_CFLAGS
+THREADDLLIBS
+THREADS_TRUE
+THREADS_FALSE
+PTHREADS_TRUE
+PTHREADS_FALSE
+DARWIN_THREADS_TRUE
+DARWIN_THREADS_FALSE
+WIN32_THREADS_TRUE
+WIN32_THREADS_FALSE
+COMPILER_XLC_TRUE
+COMPILER_XLC_FALSE
+extra_ldflags_libgc
+EXTRA_TEST_LIBS
+target_all
+CPLUSPLUS_TRUE
+CPLUSPLUS_FALSE
+INCLUDES
+CXXINCLUDES
+addobjs
+addlibs
+GREP
+EGREP
+LN_S
+ECHO
+CPP
+CXXCPP
+F77
+FFLAGS
+ac_ct_F77
+LIBTOOL
+ENABLE_GCJ_SUPPORT_TRUE
+ENABLE_GCJ_SUPPORT_FALSE
+UNWINDLIBS
+USE_LIBDIR_TRUE
+USE_LIBDIR_FALSE
+subdirs
+USE_INTERNAL_LIBATOMIC_OPS_TRUE
+USE_INTERNAL_LIBATOMIC_OPS_FALSE
+NEED_ATOMIC_OPS_ASM_TRUE
+NEED_ATOMIC_OPS_ASM_FALSE
+atomic_ops_libs
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CCAS
+CCASFLAGS
+CPP
+CXXCPP
+F77
+FFLAGS'
+ac_subdirs_all='libatomic_ops'
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures gc 7.0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/gc]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of gc 7.0:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --enable-threads=TYPE choose threading package
+ --enable-parallel-mark parallelize marking and free list construction
+ --enable-cplusplus install C++ support
+ --enable-shared[=PKGS] build shared libraries [default=yes]
+ --enable-static[=PKGS] build static libraries [default=yes]
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=yes]
+ --disable-libtool-lock avoid locking (might break parallel builds)
+ --disable-gcj-support Disable support for gcj.
+ --disable-java-finalization
+ Disable support for java finalization.
+ --disable-atomic-uncollectible
+ Disable support for atomic uncollectible allocation.
+ --enable-redirect-malloc
+ Redirect malloc and friends to GC routines
+ --enable-large-config Optimize for large (> 100 MB) heap or root set
+ --enable-gc-debug include full support for pointer backtracing etc.
+ --enable-gc-assertions collector-internal assertion checking
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-ecos enable runtime eCos target support
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+ --with-pic try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-tags[=TAGS] include additional configurations [automatic]
+ --with-target-subdir=SUBDIR
+ configuring with a cross compiler
+ --with-cross-host=HOST configuring with a cross compiler
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CCAS assembler compiler command (defaults to CC)
+ CCASFLAGS assembler compiler flags (defaults to CFLAGS)
+ CPP C preprocessor
+ CXXCPP C++ preprocessor
+ F77 Fortran 77 compiler command
+ FFLAGS Fortran 77 compiler flags
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <Hans.Boehm@hp.com>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+gc configure 7.0
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by gc $as_me 7.0, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ ## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)?
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6; }
+if test "${ac_cv_target+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
+else
+ ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5
+echo "$as_me: error: invalid value of canonical target" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+
+ { echo "$as_me:$LINENO: checking GC version numbers" >&5
+echo $ECHO_N "checking GC version numbers... $ECHO_C" >&6; }
+ GC_VERSION_MAJOR=`echo $PACKAGE_VERSION | sed 's/^\([0-9][0-9]*\)[.].*$/\1/g'`
+ GC_VERSION_MINOR=`echo $PACKAGE_VERSION | sed 's/^[^.]*[.]\([0-9][0-9]*\).*$/\1/g'`
+ GC_ALPHA_VERSION=`echo $PACKAGE_VERSION | sed 's/^[^.]*[.][0-9]*//'`
+
+ case "$GC_ALPHA_VERSION" in
+ alpha*)
+ GC_ALPHA_VERSION=`echo $GC_ALPHA_VERSION \
+ | sed 's/alpha\([0-9][0-9]*\)/\1/'` ;;
+ *) GC_ALPHA_MAJOR='' ;;
+ esac
+
+ if test :$GC_VERSION_MAJOR: = :: \
+ -o :$GC_VERSION_MINOR: = :: ;
+ then
+ { echo "$as_me:$LINENO: result: invalid" >&5
+echo "${ECHO_T}invalid" >&6; }
+ { { echo "$as_me:$LINENO: error: nonconforming PACKAGE_VERSION='$PACKAGE_VERSION'" >&5
+echo "$as_me: error: nonconforming PACKAGE_VERSION='$PACKAGE_VERSION'" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ cat >>confdefs.h <<_ACEOF
+#define GC_VERSION_MAJOR $GC_VERSION_MAJOR
+_ACEOF
+
+ cat >>confdefs.h <<_ACEOF
+#define GC_VERSION_MINOR $GC_VERSION_MINOR
+_ACEOF
+
+ if test :$GC_ALPHA_VERSION: != :: ; then
+ cat >>confdefs.h <<_ACEOF
+#define GC_ALPHA_VERSION $GC_ALPHA_VERSION
+_ACEOF
+
+ fi
+ { echo "$as_me:$LINENO: result: major=$GC_VERSION_MAJOR minor=$GC_VERSION_MINOR \
+${GC_ALPHA_VERSION:+alpha=}$GC_ALPHA_VERSION" >&5
+echo "${ECHO_T}major=$GC_VERSION_MAJOR minor=$GC_VERSION_MINOR \
+${GC_ALPHA_VERSION:+alpha=}$GC_ALPHA_VERSION" >&6; }
+
+am__api_version="1.9"
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $. echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm -f conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ # We used to keeping the `.' as first argument, in order to
+ # allow $(mkdir_p) to be used without argument. As in
+ # $(mkdir_p) $(somedir)
+ # where $(somedir) is conditionally defined. However this is wrong
+ # for two reasons:
+ # 1. if the package is installed by a user who cannot write `.'
+ # make install will fail,
+ # 2. the above comment should most certainly read
+ # $(mkdir_p) $(DESTDIR)$(somedir)
+ # so it does not work when $(somedir) is undefined and
+ # $(DESTDIR) is not.
+ # To support the latter case, we have to write
+ # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+ # so the `.' trick is pointless.
+ mkdir_p='mkdir -p --'
+else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ for d in ./-p ./--version;
+ do
+ test -d $d && rmdir $d
+ done
+ # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+ if test -f "$ac_aux_dir/mkinstalldirs"; then
+ mkdir_p='$(mkinstalldirs)'
+ else
+ mkdir_p='$(install_sh) -d'
+ fi
+fi
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ SET_MAKE=
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+ test -f $srcdir/config.status; then
+ { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='gc'
+ VERSION='7.0'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+{ echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5
+echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6; }
+ # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then
+ enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+ USE_MAINTAINER_MODE=no
+fi
+
+ { echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5
+echo "${ECHO_T}$USE_MAINTAINER_MODE" >&6; }
+
+
+if test $USE_MAINTAINER_MODE = yes; then
+ MAINTAINER_MODE_TRUE=
+ MAINTAINER_MODE_FALSE='#'
+else
+ MAINTAINER_MODE_TRUE='#'
+ MAINTAINER_MODE_FALSE=
+fi
+
+ MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+
+
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+
+
+{ echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+
+
+if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CC" am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+
+
+if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+if test "x$CC" != xcc; then
+ { echo "$as_me:$LINENO: checking whether $CC and cc understand -c and -o together" >&5
+echo $ECHO_N "checking whether $CC and cc understand -c and -o together... $ECHO_C" >&6; }
+else
+ { echo "$as_me:$LINENO: checking whether cc understands -c and -o together" >&5
+echo $ECHO_N "checking whether cc understands -c and -o together... $ECHO_C" >&6; }
+fi
+set dummy $CC; ac_cc=`echo $2 |
+ sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+# Make sure it works both with $CC and with simple cc.
+# We do the test twice because some compilers refuse to overwrite an
+# existing .o file with -o, though they will create one.
+ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+rm -f conftest2.*
+if { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ test -f conftest2.$ac_objext && { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); };
+then
+ eval ac_cv_prog_cc_${ac_cc}_c_o=yes
+ if test "x$CC" != xcc; then
+ # Test first that cc exists at all.
+ if { ac_try='cc -c conftest.$ac_ext >&5'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+ rm -f conftest2.*
+ if { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ test -f conftest2.$ac_objext && { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); };
+ then
+ # cc works too.
+ :
+ else
+ # cc exists but doesn't like -o.
+ eval ac_cv_prog_cc_${ac_cc}_c_o=no
+ fi
+ fi
+ fi
+else
+ eval ac_cv_prog_cc_${ac_cc}_c_o=no
+fi
+rm -f core conftest*
+
+fi
+if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define NO_MINUS_C_MINUS_O 1
+_ACEOF
+
+fi
+
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+ac_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CXXFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CXX" am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+
+
+if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+fi
+
+
+
+# By default we simply use the C compiler to build assembly code.
+
+test "${CCAS+set}" = set || CCAS=$CC
+test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS
+
+
+
+## FIXME: really needed? (AC_LIBTOOL already provides this)
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_AR="ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+ # :)
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+. ${srcdir}/configure.host
+
+GC_CFLAGS=${gc_cflags}
+
+
+# Check whether --enable-threads was given.
+if test "${enable_threads+set}" = set; then
+ enableval=$enable_threads; THREADS=$enableval
+else
+ { echo "$as_me:$LINENO: checking for thread model used by GCC" >&5
+echo $ECHO_N "checking for thread model used by GCC... $ECHO_C" >&6; }
+ THREADS=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
+ if test -z "$THREADS"; then
+ THREADS=no
+ fi
+ { echo "$as_me:$LINENO: result: $THREADS" >&5
+echo "${ECHO_T}$THREADS" >&6; }
+fi
+
+
+# Check whether --enable-parallel-mark was given.
+if test "${enable_parallel_mark+set}" = set; then
+ enableval=$enable_parallel_mark; case "$THREADS" in
+ no | none | single)
+ { { echo "$as_me:$LINENO: error: Parallel mark requires --enable-threads=x spec" >&5
+echo "$as_me: error: Parallel mark requires --enable-threads=x spec" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-cplusplus was given.
+if test "${enable_cplusplus+set}" = set; then
+ enableval=$enable_cplusplus;
+fi
+
+
+INCLUDES=-I${srcdir}/include
+THREADDLLIBS=
+need_atomic_ops_asm=false
+## Libraries needed to support dynamic loading and/or threads.
+case "$THREADS" in
+ no | none | single)
+ THREADS=none
+ ;;
+ posix | pthreads)
+ THREADS=posix
+ THREADDLLIBS=-lpthread
+ case "$host" in
+ x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* | alpha-*-linux*)
+ cat >>confdefs.h <<\_ACEOF
+#define GC_LINUX_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define _REENTRANT 1
+_ACEOF
+
+ if test "${enable_parallel_mark}" = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define PARALLEL_MARK 1
+_ACEOF
+
+ fi
+ cat >>confdefs.h <<\_ACEOF
+#define THREAD_LOCAL_ALLOC 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: WARNING: \"Explict GC_INIT() calls may be required.\"" >&5
+echo "$as_me: WARNING: \"Explict GC_INIT() calls may be required.\"" >&2;};
+ ;;
+ *-*-linux*)
+ cat >>confdefs.h <<\_ACEOF
+#define GC_LINUX_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define _REENTRANT 1
+_ACEOF
+
+ ;;
+ *-*-aix*)
+ cat >>confdefs.h <<\_ACEOF
+#define GC_AIX_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define _REENTRANT 1
+_ACEOF
+
+ ;;
+ *-*-hpux11*)
+ { echo "$as_me:$LINENO: WARNING: \"Only HP/UX 11 POSIX threads are supported.\"" >&5
+echo "$as_me: WARNING: \"Only HP/UX 11 POSIX threads are supported.\"" >&2;}
+ cat >>confdefs.h <<\_ACEOF
+#define GC_HPUX_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define _POSIX_C_SOURCE 199506L
+_ACEOF
+
+ if test "${enable_parallel_mark}" = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define PARALLEL_MARK 1
+_ACEOF
+
+ fi
+ cat >>confdefs.h <<\_ACEOF
+#define THREAD_LOCAL_ALLOC 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: WARNING: \"Explict GC_INIT() calls may be required.\"" >&5
+echo "$as_me: WARNING: \"Explict GC_INIT() calls may be required.\"" >&2;};
+ THREADDLLIBS="-lpthread -lrt"
+ # HPUX needs REENTRANT for the _r calls.
+
+cat >>confdefs.h <<\_ACEOF
+#define _REENTRANT 1
+_ACEOF
+
+ ;;
+ *-*-hpux10*)
+ { echo "$as_me:$LINENO: WARNING: \"Only HP-UX 11 POSIX threads are supported.\"" >&5
+echo "$as_me: WARNING: \"Only HP-UX 11 POSIX threads are supported.\"" >&2;}
+ ;;
+ *-*-freebsd*)
+ { echo "$as_me:$LINENO: WARNING: \"FreeBSD does not yet fully support threads with Boehm GC.\"" >&5
+echo "$as_me: WARNING: \"FreeBSD does not yet fully support threads with Boehm GC.\"" >&2;}
+ cat >>confdefs.h <<\_ACEOF
+#define GC_FREEBSD_THREADS 1
+_ACEOF
+
+ INCLUDES="$INCLUDES -pthread"
+ ;;
+ *-*-kfreebsd*-gnu)
+ cat >>confdefs.h <<\_ACEOF
+#define GC_FREEBSD_THREADS 1
+_ACEOF
+
+ INCLUDES="$INCLUDES -pthread"
+ THREADDLLIBS=-pthread
+ cat >>confdefs.h <<\_ACEOF
+#define _REENTRANT 1
+_ACEOF
+
+ if test "${enable_parallel_mark}" = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define PARALLEL_MARK 1
+_ACEOF
+
+ fi
+ cat >>confdefs.h <<\_ACEOF
+#define THREAD_LOCAL_ALLOC 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define USE_COMPILER_TLS 1
+_ACEOF
+
+ ;;
+ *-*-gnu*)
+ cat >>confdefs.h <<\_ACEOF
+#define GC_GNU_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define _REENTRANT 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define THREAD_LOCAL_ALLOC 1
+_ACEOF
+
+ ;;
+ *-*-netbsd*)
+ { echo "$as_me:$LINENO: WARNING: \"Only on NetBSD 2.0 or later.\"" >&5
+echo "$as_me: WARNING: \"Only on NetBSD 2.0 or later.\"" >&2;}
+ cat >>confdefs.h <<\_ACEOF
+#define GC_NETBSD_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define _REENTRANT 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define _PTHREADS 1
+_ACEOF
+
+ THREADDLLIBS="-lpthread -lrt"
+ ;;
+ *-*-solaris*)
+ cat >>confdefs.h <<\_ACEOF
+#define GC_SOLARIS_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define THREAD_LOCAL_ALLOC 1
+_ACEOF
+
+ THREADDLLIBS="-lpthread -lrt"
+ if test "$GCC" != yes; then
+ CFLAGS="$CFLAGS -O"
+ need_atomic_ops_asm=true
+ fi
+ ;;
+ *-*-irix*)
+ cat >>confdefs.h <<\_ACEOF
+#define GC_IRIX_THREADS 1
+_ACEOF
+
+ ;;
+ *-*-cygwin*)
+ cat >>confdefs.h <<\_ACEOF
+#define GC_WIN32_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define THREAD_LOCAL_ALLOC 1
+_ACEOF
+
+ win32_threads=true
+ ;;
+ *-*-darwin*)
+ cat >>confdefs.h <<\_ACEOF
+#define GC_DARWIN_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define THREAD_LOCAL_ALLOC 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: WARNING: \"Explict GC_INIT() calls may be required.\"" >&5
+echo "$as_me: WARNING: \"Explict GC_INIT() calls may be required.\"" >&2;};
+ if test "${enable_parallel_mark}" = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define PARALLEL_MARK 1
+_ACEOF
+
+ fi
+ darwin_threads=true
+ ;;
+ *-*-osf*)
+ cat >>confdefs.h <<\_ACEOF
+#define GC_OSF1_THREADS 1
+_ACEOF
+
+ if test "${enable_parallel_mark}" = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define PARALLEL_MARK 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define THREAD_LOCAL_ALLOC 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: WARNING: \"Explict GC_INIT() calls may be required.\"" >&5
+echo "$as_me: WARNING: \"Explict GC_INIT() calls may be required.\"" >&2;};
+ # May want to enable it in other cases, too.
+ # Measurements havent yet been done.
+ fi
+ INCLUDES="$INCLUDES -pthread"
+ THREADDLLIBS="-lpthread -lrt"
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: \"Pthreads not supported by the GC on this platform.\"" >&5
+echo "$as_me: error: \"Pthreads not supported by the GC on this platform.\"" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+ ;;
+ win32)
+ cat >>confdefs.h <<\_ACEOF
+#define GC_WIN32_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define NO_GETENV 1
+_ACEOF
+
+ ;;
+ dgux386)
+ THREADS=dgux386
+ { echo "$as_me:$LINENO: result: $THREADDLLIBS" >&5
+echo "${ECHO_T}$THREADDLLIBS" >&6; }
+ # Use pthread GCC switch
+ THREADDLLIBS=-pthread
+ if test "${enable_parallel_mark}" = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define PARALLEL_MARK 1
+_ACEOF
+
+ fi
+ cat >>confdefs.h <<\_ACEOF
+#define THREAD_LOCAL_ALLOC 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: WARNING: \"Explict GC_INIT() calls may be required.\"" >&5
+echo "$as_me: WARNING: \"Explict GC_INIT() calls may be required.\"" >&2;};
+ cat >>confdefs.h <<\_ACEOF
+#define GC_DGUX386_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define DGUX_THREADS 1
+_ACEOF
+
+ # Enable _POSIX4A_DRAFT10_SOURCE with flag -pthread
+ INCLUDES="-pthread $INCLUDES"
+ ;;
+ aix)
+ THREADS=posix
+ THREADDLLIBS=-lpthread
+ cat >>confdefs.h <<\_ACEOF
+#define GC_AIX_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define _REENTRANT 1
+_ACEOF
+
+ ;;
+ decosf1 | irix | mach | os2 | solaris | dce | vxworks)
+ { { echo "$as_me:$LINENO: error: thread package $THREADS not yet supported" >&5
+echo "$as_me: error: thread package $THREADS not yet supported" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: $THREADS is an unknown thread package" >&5
+echo "$as_me: error: $THREADS is an unknown thread package" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+esac
+
+
+
+if test x$THREADS != xnone; then
+ THREADS_TRUE=
+ THREADS_FALSE='#'
+else
+ THREADS_TRUE='#'
+ THREADS_FALSE=
+fi
+
+
+
+if test x$THREADS = xposix; then
+ PTHREADS_TRUE=
+ PTHREADS_FALSE='#'
+else
+ PTHREADS_TRUE='#'
+ PTHREADS_FALSE=
+fi
+
+
+
+if test x$darwin_threads = xtrue; then
+ DARWIN_THREADS_TRUE=
+ DARWIN_THREADS_FALSE='#'
+else
+ DARWIN_THREADS_TRUE='#'
+ DARWIN_THREADS_FALSE=
+fi
+
+
+
+if test x$win32_threads = xtrue; then
+ WIN32_THREADS_TRUE=
+ WIN32_THREADS_FALSE='#'
+else
+ WIN32_THREADS_TRUE='#'
+ WIN32_THREADS_FALSE=
+fi
+
+
+case "$host" in
+ powerpc-*-darwin*)
+ powerpc_darwin=true
+ ;;
+esac
+
+# Darwin needs a few extra special tests to deal with variation in the
+# system headers.
+case "$host" in
+ powerpc*-*-darwin*)
+
+{ echo "$as_me:$LINENO: checking for ppc_thread_state_t.r0" >&5
+echo $ECHO_N "checking for ppc_thread_state_t.r0... $ECHO_C" >&6; }
+if test "${ac_cv_member_ppc_thread_state_t_r0+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <mach/thread_status.h>
+
+int
+main ()
+{
+static ppc_thread_state_t ac_aggr;
+if (ac_aggr.r0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_ppc_thread_state_t_r0=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <mach/thread_status.h>
+
+int
+main ()
+{
+static ppc_thread_state_t ac_aggr;
+if (sizeof ac_aggr.r0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_ppc_thread_state_t_r0=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_member_ppc_thread_state_t_r0=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_ppc_thread_state_t_r0" >&5
+echo "${ECHO_T}$ac_cv_member_ppc_thread_state_t_r0" >&6; }
+if test $ac_cv_member_ppc_thread_state_t_r0 = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAS_PPC_THREAD_STATE_R0 1
+_ACEOF
+
+fi
+
+ { echo "$as_me:$LINENO: checking for ppc_thread_state_t.__r0" >&5
+echo $ECHO_N "checking for ppc_thread_state_t.__r0... $ECHO_C" >&6; }
+if test "${ac_cv_member_ppc_thread_state_t___r0+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <mach/thread_status.h>
+
+int
+main ()
+{
+static ppc_thread_state_t ac_aggr;
+if (ac_aggr.__r0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_ppc_thread_state_t___r0=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <mach/thread_status.h>
+
+int
+main ()
+{
+static ppc_thread_state_t ac_aggr;
+if (sizeof ac_aggr.__r0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_ppc_thread_state_t___r0=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_member_ppc_thread_state_t___r0=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_ppc_thread_state_t___r0" >&5
+echo "${ECHO_T}$ac_cv_member_ppc_thread_state_t___r0" >&6; }
+if test $ac_cv_member_ppc_thread_state_t___r0 = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAS_PPC_THREAD_STATE___R0 1
+_ACEOF
+
+fi
+
+ { echo "$as_me:$LINENO: checking for ppc_thread_state64_t.r0" >&5
+echo $ECHO_N "checking for ppc_thread_state64_t.r0... $ECHO_C" >&6; }
+if test "${ac_cv_member_ppc_thread_state64_t_r0+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <mach/thread_status.h>
+
+int
+main ()
+{
+static ppc_thread_state64_t ac_aggr;
+if (ac_aggr.r0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_ppc_thread_state64_t_r0=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <mach/thread_status.h>
+
+int
+main ()
+{
+static ppc_thread_state64_t ac_aggr;
+if (sizeof ac_aggr.r0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_ppc_thread_state64_t_r0=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_member_ppc_thread_state64_t_r0=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_ppc_thread_state64_t_r0" >&5
+echo "${ECHO_T}$ac_cv_member_ppc_thread_state64_t_r0" >&6; }
+if test $ac_cv_member_ppc_thread_state64_t_r0 = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAS_PPC_THREAD_STATE64_R0 1
+_ACEOF
+
+fi
+
+ { echo "$as_me:$LINENO: checking for ppc_thread_state64_t.__r0" >&5
+echo $ECHO_N "checking for ppc_thread_state64_t.__r0... $ECHO_C" >&6; }
+if test "${ac_cv_member_ppc_thread_state64_t___r0+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <mach/thread_status.h>
+
+int
+main ()
+{
+static ppc_thread_state64_t ac_aggr;
+if (ac_aggr.__r0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_ppc_thread_state64_t___r0=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <mach/thread_status.h>
+
+int
+main ()
+{
+static ppc_thread_state64_t ac_aggr;
+if (sizeof ac_aggr.__r0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_ppc_thread_state64_t___r0=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_member_ppc_thread_state64_t___r0=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_ppc_thread_state64_t___r0" >&5
+echo "${ECHO_T}$ac_cv_member_ppc_thread_state64_t___r0" >&6; }
+if test $ac_cv_member_ppc_thread_state64_t___r0 = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAS_PPC_THREAD_STATE64___R0 1
+_ACEOF
+
+fi
+
+ ;;
+ i?86*-*-darwin*)
+ { echo "$as_me:$LINENO: checking for x86_thread_state32_t.eax" >&5
+echo $ECHO_N "checking for x86_thread_state32_t.eax... $ECHO_C" >&6; }
+if test "${ac_cv_member_x86_thread_state32_t_eax+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/cdefs.h>
+ #include <mach/thread_status.h>
+
+int
+main ()
+{
+static x86_thread_state32_t ac_aggr;
+if (ac_aggr.eax)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_x86_thread_state32_t_eax=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/cdefs.h>
+ #include <mach/thread_status.h>
+
+int
+main ()
+{
+static x86_thread_state32_t ac_aggr;
+if (sizeof ac_aggr.eax)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_x86_thread_state32_t_eax=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_member_x86_thread_state32_t_eax=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_x86_thread_state32_t_eax" >&5
+echo "${ECHO_T}$ac_cv_member_x86_thread_state32_t_eax" >&6; }
+if test $ac_cv_member_x86_thread_state32_t_eax = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAS_X86_THREAD_STATE32_EAX 1
+_ACEOF
+
+fi
+
+ { echo "$as_me:$LINENO: checking for x86_thread_state32_t.__eax" >&5
+echo $ECHO_N "checking for x86_thread_state32_t.__eax... $ECHO_C" >&6; }
+if test "${ac_cv_member_x86_thread_state32_t___eax+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/cdefs.h>
+ #include <mach/thread_status.h>
+
+int
+main ()
+{
+static x86_thread_state32_t ac_aggr;
+if (ac_aggr.__eax)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_x86_thread_state32_t___eax=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/cdefs.h>
+ #include <mach/thread_status.h>
+
+int
+main ()
+{
+static x86_thread_state32_t ac_aggr;
+if (sizeof ac_aggr.__eax)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_x86_thread_state32_t___eax=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_member_x86_thread_state32_t___eax=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_x86_thread_state32_t___eax" >&5
+echo "${ECHO_T}$ac_cv_member_x86_thread_state32_t___eax" >&6; }
+if test $ac_cv_member_x86_thread_state32_t___eax = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAS_X86_THREAD_STATE32___EAX 1
+_ACEOF
+
+fi
+
+ ;;
+ x86_64-*-darwin*)
+ { echo "$as_me:$LINENO: checking for x86_thread_state64_t.rax" >&5
+echo $ECHO_N "checking for x86_thread_state64_t.rax... $ECHO_C" >&6; }
+if test "${ac_cv_member_x86_thread_state64_t_rax+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/cdefs.h>
+ #include <mach/thread_status.h>
+
+int
+main ()
+{
+static x86_thread_state64_t ac_aggr;
+if (ac_aggr.rax)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_x86_thread_state64_t_rax=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/cdefs.h>
+ #include <mach/thread_status.h>
+
+int
+main ()
+{
+static x86_thread_state64_t ac_aggr;
+if (sizeof ac_aggr.rax)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_x86_thread_state64_t_rax=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_member_x86_thread_state64_t_rax=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_x86_thread_state64_t_rax" >&5
+echo "${ECHO_T}$ac_cv_member_x86_thread_state64_t_rax" >&6; }
+if test $ac_cv_member_x86_thread_state64_t_rax = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAS_X86_THREAD_STATE64_RAX 1
+_ACEOF
+
+fi
+
+ { echo "$as_me:$LINENO: checking for x86_thread_state64_t.__rax" >&5
+echo $ECHO_N "checking for x86_thread_state64_t.__rax... $ECHO_C" >&6; }
+if test "${ac_cv_member_x86_thread_state64_t___rax+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/cdefs.h>
+ #include <mach/thread_status.h>
+
+int
+main ()
+{
+static x86_thread_state64_t ac_aggr;
+if (ac_aggr.__rax)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_x86_thread_state64_t___rax=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/cdefs.h>
+ #include <mach/thread_status.h>
+
+int
+main ()
+{
+static x86_thread_state64_t ac_aggr;
+if (sizeof ac_aggr.__rax)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_x86_thread_state64_t___rax=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_member_x86_thread_state64_t___rax=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_x86_thread_state64_t___rax" >&5
+echo "${ECHO_T}$ac_cv_member_x86_thread_state64_t___rax" >&6; }
+if test $ac_cv_member_x86_thread_state64_t___rax = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAS_X86_THREAD_STATE64___RAX 1
+_ACEOF
+
+fi
+
+ ;;
+ *) ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for xlc" >&5
+echo $ECHO_N "checking for xlc... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ #ifndef __xlC__
+ # error
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ compiler_xlc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ compiler_xlc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $compiler_xlc" >&5
+echo "${ECHO_T}$compiler_xlc" >&6; }
+
+
+if test $compiler_xlc = yes; then
+ COMPILER_XLC_TRUE=
+ COMPILER_XLC_FALSE='#'
+else
+ COMPILER_XLC_TRUE='#'
+ COMPILER_XLC_FALSE=
+fi
+
+if test $compiler_xlc = yes -a "$powerpc_darwin" = true; then
+ # the darwin stack-frame-walking code is completely broken on xlc
+ cat >>confdefs.h <<\_ACEOF
+#define DARWIN_DONT_PARSE_STACK 1
+_ACEOF
+
+fi
+
+# We never want libdl on darwin. It is a fake libdl that just ends up making
+# dyld calls anyway
+case "$host" in
+ *-*-darwin*) ;;
+ *)
+ { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+ THREADDLLIBS="$THREADDLLIBS -ldl"
+fi
+
+ ;;
+esac
+
+# extra LD Flags which are required for targets
+case "${host}" in
+ *-*-darwin*)
+ extra_ldflags_libgc=-Wl,-single_module
+ ;;
+esac
+
+
+
+
+target_all=libgc.la
+
+
+TARGET_ECOS="no"
+
+# Check whether --with-ecos was given.
+if test "${with_ecos+set}" = set; then
+ withval=$with_ecos; TARGET_ECOS="$with_ecos"
+
+fi
+
+
+addobjs=
+addlibs=
+CXXINCLUDES=
+case "$TARGET_ECOS" in
+ no)
+ ;;
+ *)
+ cat >>confdefs.h <<\_ACEOF
+#define ECOS 1
+_ACEOF
+
+ CXXINCLUDES="-I${TARGET_ECOS}/include"
+ addobjs="$addobjs ecos.lo"
+ ;;
+esac
+
+
+
+if test "${enable_cplusplus}" = yes; then
+ CPLUSPLUS_TRUE=
+ CPLUSPLUS_FALSE='#'
+else
+ CPLUSPLUS_TRUE='#'
+ CPLUSPLUS_FALSE=
+fi
+
+
+
+
+
+
+
+# Configuration of shared libraries
+#
+{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; }
+# Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval=$enable_shared; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_shared=yes
+fi
+
+
+
+case "$host" in
+ alpha-*-openbsd*)
+ enable_shared=no
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ *)
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ;;
+esac
+
+# Configuration of machine-dependent code
+#
+{ echo "$as_me:$LINENO: checking which machine-dependent code should be used" >&5
+echo $ECHO_N "checking which machine-dependent code should be used... $ECHO_C" >&6; }
+machdep=
+case "$host" in
+ alpha-*-openbsd*)
+ machdep="mach_dep.lo"
+ if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then
+ { echo "$as_me:$LINENO: WARNING: OpenBSD/Alpha without dlopen(). Shared library support is disabled" >&5
+echo "$as_me: WARNING: OpenBSD/Alpha without dlopen(). Shared library support is disabled" >&2;}
+ fi
+ ;;
+ alpha*-*-linux*)
+ machdep="mach_dep.lo"
+ ;;
+ i?86-*-solaris2.[89] | i?86-*-solaris2.1?)
+ cat >>confdefs.h <<\_ACEOF
+#define SOLARIS25_PROC_VDB_BUG_FIXED 1
+_ACEOF
+
+ ;;
+ mipstx39-*-elf*)
+ machdep="mach_dep.lo"
+ cat >>confdefs.h <<\_ACEOF
+#define STACKBASE __stackbase
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define DATASTART_IS_ETEXT 1
+_ACEOF
+
+ ;;
+ mips-dec-ultrix*)
+ machdep="mach-dep.lo"
+ ;;
+ mips-nec-sysv*|mips-unknown-sysv*)
+ ;;
+ mips*-*-linux*)
+ ;;
+ mips-*-*)
+ machdep="mach_dep.lo"
+ ;;
+ sparc-*-netbsd*)
+ machdep="mach_dep.lo sparc_netbsd_mach_dep.lo"
+ ;;
+ sparc-sun-solaris2.3)
+ machdep="mach_dep.lo sparc_mach_dep.lo"
+ cat >>confdefs.h <<\_ACEOF
+#define SUNOS53_SHARED_LIB 1
+_ACEOF
+
+ ;;
+ sparc*-sun-solaris2.*)
+ machdep="mach_dep.lo sparc_mach_dep.lo"
+ ;;
+ ia64-*-*)
+ machdep="mach_dep.lo ia64_save_regs_in_stack.lo"
+ ;;
+esac
+if test x"$machdep" = x; then
+{ echo "$as_me:$LINENO: result: $machdep" >&5
+echo "${ECHO_T}$machdep" >&6; }
+ machdep="mach_dep.lo"
+fi
+addobjs="$addobjs $machdep"
+
+
+
+# Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then
+ enableval=$enable_static; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_static=yes
+fi
+
+
+# Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+ enableval=$enable_fast_install; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_fast_install=yes
+fi
+
+
+{ echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; }
+if test "${lt_cv_path_SED+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+
+fi
+
+SED=$lt_cv_path_SED
+{ echo "$as_me:$LINENO: result: $SED" >&5
+echo "${ECHO_T}$SED" >&6; }
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+ # Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_GREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+ # Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_EGREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ { echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+else
+ { echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ { echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+{ echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6; }
+if test "${lt_cv_ld_reload_flag+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_ld_reload_flag='-r'
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; }
+if test "${lt_cv_path_NM+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
+echo "${ECHO_T}$lt_cv_path_NM" >&6; }
+NM="$lt_cv_path_NM"
+
+{ echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6; }
+fi
+
+{ echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5
+echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6; }
+if test "${lt_cv_deplibs_check_method+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[45]*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump'.
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | kfreebsd*-gnu | dragonfly*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix3*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+nto-qnx*)
+ lt_cv_deplibs_check_method=unknown
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6; }
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+ enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '#line 6857 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ { echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6; }
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ lt_cv_cc_needs_belf=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ lt_cv_cc_needs_belf=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6; }
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *) LD="${LD-ld} -64" ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in dlfcn.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## -------------------------------- ##
+## Report this to Hans.Boehm@hp.com ##
+## -------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; }
+if test -z "$CXXCPP"; then
+ if test "${ac_cv_prog_CXXCPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+fi
+
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$F77"; then
+ ac_cv_prog_F77="$F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+F77=$ac_cv_prog_F77
+if test -n "$F77"; then
+ { echo "$as_me:$LINENO: result: $F77" >&5
+echo "${ECHO_T}$F77" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$F77" && break
+ done
+fi
+if test -z "$F77"; then
+ ac_ct_F77=$F77
+ for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_F77"; then
+ ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_F77="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_F77=$ac_cv_prog_ac_ct_F77
+if test -n "$ac_ct_F77"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
+echo "${ECHO_T}$ac_ct_F77" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_F77" && break
+done
+
+ if test "x$ac_ct_F77" = x; then
+ F77=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ F77=$ac_ct_F77
+ fi
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+rm -f a.out
+
+# If we don't use `.F' as extension, the preprocessor is not run on the
+# input file. (Note that this only needs to work for GNU compilers.)
+ac_save_ext=$ac_ext
+ac_ext=F
+{ echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; }
+if test "${ac_cv_f77_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+#ifndef __GNUC__
+ choke me
+#endif
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_f77_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_f77_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; }
+ac_ext=$ac_save_ext
+ac_test_FFLAGS=${FFLAGS+set}
+ac_save_FFLAGS=$FFLAGS
+FFLAGS=
+{ echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
+echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_f77_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ FFLAGS=-g
+cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_f77_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_f77_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_prog_f77_g=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
+echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; }
+if test "$ac_test_FFLAGS" = set; then
+ FFLAGS=$ac_save_FFLAGS
+elif test $ac_cv_prog_f77_g = yes; then
+ if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+ FFLAGS="-g -O2"
+ else
+ FFLAGS="-g"
+ fi
+else
+ if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+ FFLAGS="-O2"
+ else
+ FFLAGS=
+ fi
+fi
+
+G77=`test $ac_compiler_gnu = yes && echo yes`
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+
+# find the maximum length of command line arguments
+{ echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
+echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; }
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \
+ = "XX$teststring") >/dev/null 2>&1 &&
+ new_result=`expr "X$teststring" : ".*" 2>&1` &&
+ lt_cv_sys_max_cmd_len=$new_result &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on massive
+ # amounts of additional arguments before passing them to the linker.
+ # It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ ;;
+ esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+ { echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
+echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; }
+else
+ { echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6; }
+fi
+
+
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
+echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; }
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw* | pw32*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDEGRST]'
+ fi
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+linux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDGIRSTW]'
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[BCDEGRST]'
+ ;;
+osf*)
+ symcode='[BCDEGQRST]'
+ ;;
+solaris*)
+ symcode='[BDRT]'
+ ;;
+sco3.2v5*)
+ symcode='[DT]'
+ ;;
+sysv4.2uw2*)
+ symcode='[DT]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[ABDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
+ (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if grep ' nm_test_var$' "$nlist" >/dev/null; then
+ if grep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+ cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ { echo "$as_me:$LINENO: result: failed" >&5
+echo "${ECHO_T}failed" >&6; }
+else
+ { echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6; }
+fi
+
+{ echo "$as_me:$LINENO: checking for objdir" >&5
+echo $ECHO_N "checking for objdir... $ECHO_C" >&6; }
+if test "${lt_cv_objdir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
+echo "${ECHO_T}$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_AR="ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ { echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/${ac_tool_prefix}file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ { echo "$as_me:$LINENO: checking for file" >&5
+echo $ECHO_N "checking for file... $ECHO_C" >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ else
+ MAGIC_CMD=:
+ fi
+fi
+
+ fi
+ ;;
+esac
+
+enable_dlopen=no
+enable_win32_dll=no
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+ enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then
+ withval=$with_pic; pic_mode="$withval"
+else
+ pic_mode=default
+fi
+
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}\n'
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:9120: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:9124: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic='-qnocommon'
+ lt_prog_compiler_wl='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl='-Qoption ld '
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic='-Kconform_pic'
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_can_build_shared=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic='-pic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:9388: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:9392: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_prog_compiler_pic_works" = xyes; then
+ case $lt_prog_compiler_pic in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+ esac
+else
+ lt_prog_compiler_pic=
+ lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic=
+ ;;
+ *)
+ lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works=yes
+ fi
+ else
+ lt_prog_compiler_static_works=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; }
+
+if test x"$lt_prog_compiler_static_works" = xyes; then
+ :
+else
+ lt_prog_compiler_static=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:9492: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:9496: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+ runpath_var=
+ allow_undefined_flag=
+ enable_shared_with_static_runtimes=no
+ archive_cmds=
+ archive_expsym_cmds=
+ old_archive_From_new_cmds=
+ old_archive_from_expsyms_cmds=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ thread_safe_flag_spec=
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_flag_spec_ld=
+ hardcode_libdir_separator=
+ hardcode_direct=no
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=unsupported
+ link_all_deplibs=unknown
+ hardcode_automatic=no
+ module_cmds=
+ module_expsym_cmds=
+ always_export_symbols=no
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ allow_undefined_flag=unsupported
+ always_export_symbols=no
+ enable_shared_with_static_runtimes=yes
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds=''
+ hardcode_direct=yes
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct=yes
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag="-z nodefs"
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag=' ${wl}-bernotok'
+ allow_undefined_flag=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec='$convenience'
+ archive_cmds_need_lc=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc=no
+ hardcode_direct=no
+ hardcode_automatic=yes
+ hardcode_shlibpath_var=unsupported
+ whole_archive_flag_spec=''
+ link_all_deplibs=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+
+ hardcode_direct=yes
+ export_dynamic_flag_spec='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld='+b $libdir'
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ ;;
+ *)
+ hardcode_direct=yes
+ export_dynamic_flag_spec='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ link_all_deplibs=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ newsos6)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_shlibpath_var=no
+ ;;
+
+ openbsd*)
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ hardcode_libdir_separator=:
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds='$CC -r -o $output$reload_objs'
+ hardcode_direct=no
+ ;;
+ motorola)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag='${wl}-z,text'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag='${wl}-z,text'
+ allow_undefined_flag='${wl}-z,nodefs'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ export_dynamic_flag_spec='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs" >&5
+echo "${ECHO_T}$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl
+ pic_flag=$lt_prog_compiler_pic
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc=no
+ else
+ archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ { echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
+echo "${ECHO_T}$archive_cmds_need_lc" >&6; }
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var" || \
+ test "X$hardcode_automatic" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no &&
+ test "$hardcode_minus_L" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action" >&5
+echo "${ECHO_T}$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+striplib=
+old_striplib=
+{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+ ;;
+ *)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ esac
+fi
+
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+
+fi
+
+ ;;
+
+ *)
+ { echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; }
+if test "${ac_cv_func_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_shl_load || defined __stub___shl_load
+choke me
+#endif
+
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6; }
+if test $ac_cv_func_shl_load = yes; then
+ lt_cv_dlopen="shl_load"
+else
+ { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dld_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dld_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; }
+if test $ac_cv_lib_dld_shl_load = yes; then
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
+else
+ { echo "$as_me:$LINENO: checking for dlopen" >&5
+echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; }
+if test "${ac_cv_func_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define dlopen innocuous_dlopen
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef dlopen
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_dlopen || defined __stub___dlopen
+choke me
+#endif
+
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+echo "${ECHO_T}$ac_cv_func_dlopen" >&6; }
+if test $ac_cv_func_dlopen = yes; then
+ lt_cv_dlopen="dlopen"
+else
+ { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_svld_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_svld_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; }
+if test $ac_cv_lib_svld_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+ { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dld_dld_link=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dld_dld_link=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; }
+if test $ac_cv_lib_dld_dld_link = yes; then
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 11800 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self" >&6; }
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 11900 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; }
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+# Report which library types will actually be built
+{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; }
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; }
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+{ echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6; }
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler \
+ CC \
+ LD \
+ lt_prog_compiler_wl \
+ lt_prog_compiler_pic \
+ lt_prog_compiler_static \
+ lt_prog_compiler_no_builtin_flag \
+ export_dynamic_flag_spec \
+ thread_safe_flag_spec \
+ whole_archive_flag_spec \
+ enable_shared_with_static_runtimes \
+ old_archive_cmds \
+ old_archive_from_new_cmds \
+ predep_objects \
+ postdep_objects \
+ predeps \
+ postdeps \
+ compiler_lib_search_path \
+ archive_cmds \
+ archive_expsym_cmds \
+ postinstall_cmds \
+ postuninstall_cmds \
+ old_archive_from_expsyms_cmds \
+ allow_undefined_flag \
+ no_undefined_flag \
+ export_symbols_cmds \
+ hardcode_libdir_flag_spec \
+ hardcode_libdir_flag_spec_ld \
+ hardcode_libdir_separator \
+ hardcode_automatic \
+ module_cmds \
+ module_expsym_cmds \
+ lt_cv_prog_compiler_c_o \
+ exclude_expsyms \
+ include_expsyms; do
+
+ case $var in
+ old_archive_cmds | \
+ old_archive_from_new_cmds | \
+ archive_cmds | \
+ archive_expsym_cmds | \
+ module_cmds | \
+ module_expsym_cmds | \
+ old_archive_from_expsyms_cmds | \
+ export_symbols_cmds | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="${ofile}T"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ $rm -f "$cfgfile"
+ { echo "$as_me:$LINENO: creating $ofile" >&5
+echo "$as_me: creating $ofile" >&6;}
+
+ cat <<__EOF__ >> "$cfgfile"
+#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+
+ case $host_os in
+ aix3*)
+ cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" || \
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+# Check whether --with-tags was given.
+if test "${with_tags+set}" = set; then
+ withval=$with_tags; tagnames="$withval"
+fi
+
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+ if test ! -f "${ofile}"; then
+ { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;}
+ fi
+
+ if test -z "$LTCC"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+ if test -z "$LTCC"; then
+ { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;}
+ else
+ { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5
+echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;}
+ fi
+ fi
+ if test -z "$LTCFLAGS"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+ fi
+
+ # Extract list of available tagged configurations in $ofile.
+ # Note that this assumes the entire list is on one line.
+ available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for tagname in $tagnames; do
+ IFS="$lt_save_ifs"
+ # Check whether tagname contains only valid characters
+ case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in
+ "") ;;
+ *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5
+echo "$as_me: error: invalid tag name: $tagname" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+ then
+ { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5
+echo "$as_me: error: tag name \"$tagname\" already exists" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ # Update the list of available tags.
+ if test -n "$tagname"; then
+ echo appending configuration tag \"$tagname\" to $ofile
+
+ case $tagname in
+ CXX)
+ if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_flag_spec_ld_CXX=
+hardcode_libdir_separator_CXX=
+hardcode_minus_L_CXX=no
+hardcode_shlibpath_var_CXX=unsupported
+hardcode_automatic_CXX=no
+module_cmds_CXX=
+module_expsym_cmds_CXX=
+link_all_deplibs_CXX=unknown
+old_archive_cmds_CXX=$old_archive_cmds
+no_undefined_flag_CXX=
+whole_archive_flag_spec_CXX=
+enable_shared_with_static_runtimes_CXX=no
+
+# Dependencies to place before and after the object being linked:
+predep_objects_CXX=
+postdep_objects_CXX=
+predeps_CXX=
+postdeps_CXX=
+compiler_lib_search_path_CXX=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+objext_CXX=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+ $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+ $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+compiler_CXX=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+ lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+else
+ lt_prog_compiler_no_builtin_flag_CXX=
+fi
+
+if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ { echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+else
+ { echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ { echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+ grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_CXX=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+ld_shlibs_CXX=yes
+case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_CXX=''
+ hardcode_direct_CXX=yes
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_CXX=yes
+ else
+ # We have old collect2
+ hardcode_direct_CXX=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_CXX=yes
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ hardcode_libdir_separator_CXX=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_CXX=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_CXX='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_CXX="-z nodefs"
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_CXX=' ${wl}-bernotok'
+ allow_undefined_flag_CXX=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_CXX='$convenience'
+ archive_cmds_need_lc_CXX=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_CXX=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ allow_undefined_flag_CXX=unsupported
+ always_export_symbols_CXX=no
+ enable_shared_with_static_runtimes_CXX=yes
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_direct_CXX=no
+ hardcode_automatic_CXX=yes
+ hardcode_shlibpath_var_CXX=unsupported
+ whole_archive_flag_spec_CXX=''
+ link_all_deplibs_CXX=yes
+
+ if test "$GXX" = yes ; then
+ lt_int_apple_cc_single_mod=no
+ output_verbose_link_cmd='echo'
+ if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+ lt_int_apple_cc_single_mod=yes
+ fi
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ else
+ archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ fi
+ module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ freebsd[12]*)
+ # C++ shared libraries reported to be fairly broken before switch to ELF
+ ld_shlibs_CXX=no
+ ;;
+ freebsd-elf*)
+ archive_cmds_need_lc_CXX=no
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ ld_shlibs_CXX=yes
+ ;;
+ gnu*)
+ ;;
+ hpux9*)
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_CXX='+b $libdir'
+ ;;
+ *)
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ ;;
+ *)
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ interix3*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+ fi
+ fi
+ link_all_deplibs_CXX=yes
+ ;;
+ esac
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc*)
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ esac
+ ;;
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ m88k*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ ld_shlibs_CXX=no
+ ;;
+ openbsd*)
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd='echo'
+ ;;
+ osf3*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx*)
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -o $oldlib $oldobjs'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx*)
+ allow_undefined_flag_CXX=' -expect_unresolved \*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+ $rm $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ psos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ archive_cmds_need_lc_CXX=yes
+ no_undefined_flag_CXX=' -zdefs'
+ archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_shlibpath_var_CXX=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The C++ compiler is used as linker so we must use $wl
+ # flag to pass the commands to the underlying system
+ # linker. We must also pass each convience library through
+ # to the system linker between allextract/defaultextract.
+ # The C++ compiler will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ link_all_deplibs_CXX=yes
+
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+ if $CC --version | grep -v '^2\.7' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
+ fi
+ ;;
+ esac
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ no_undefined_flag_CXX='${wl}-z,text'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ # So that behaviour is only enabled if SCOABSPATH is set to a
+ # non-empty value in the environment. Most likely only useful for
+ # creating official distributions of packages.
+ # This is a hack until libtool officially supports absolute path
+ # names for shared libraries.
+ no_undefined_flag_CXX='${wl}-z,text'
+ allow_undefined_flag_CXX='${wl}-z,nodefs'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+ export_dynamic_flag_spec_CXX='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+GCC_CXX="$GXX"
+LD_CXX="$LD"
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+
+cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+EOF
+
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ # The `*' in the case matches for architectures that use `case' in
+ # $output_verbose_cmd can trigger glob expansion during the loop
+ # eval without this substitution.
+ output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+ for p in `eval $output_verbose_link_cmd`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" \
+ || test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$compiler_lib_search_path_CXX"; then
+ compiler_lib_search_path_CXX="${prev}${p}"
+ else
+ compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$postdeps_CXX"; then
+ postdeps_CXX="${prev}${p}"
+ else
+ postdeps_CXX="${postdeps_CXX} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$predep_objects_CXX"; then
+ predep_objects_CXX="$p"
+ else
+ predep_objects_CXX="$predep_objects_CXX $p"
+ fi
+ else
+ if test -z "$postdep_objects_CXX"; then
+ postdep_objects_CXX="$p"
+ else
+ postdep_objects_CXX="$postdep_objects_CXX $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling CXX test program"
+fi
+
+$rm -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+case $host_os in
+interix3*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ predep_objects_CXX=
+ postdep_objects_CXX=
+ postdeps_CXX=
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ postdeps_CXX='-lCstd -lCrun'
+ ;;
+ esac
+ ;;
+esac
+
+
+case " $postdeps_CXX " in
+*" -lc "*) archive_cmds_need_lc_CXX=no ;;
+esac
+
+lt_prog_compiler_wl_CXX=
+lt_prog_compiler_pic_CXX=
+lt_prog_compiler_static_CXX=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ fi
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | os2* | pw32*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_CXX='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ lt_prog_compiler_pic_CXX=
+ ;;
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_CXX=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix4* | aix5*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ else
+ lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_CXX='-qnocommon'
+ lt_prog_compiler_wl_CXX='-Wl,'
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ lt_prog_compiler_pic_CXX='+Z'
+ fi
+ ;;
+ aCC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ icpc* | ecpc*)
+ # Intel C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-static'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler.
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-fpic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ lt_prog_compiler_pic_CXX='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ lt_prog_compiler_wl_CXX='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ lt_prog_compiler_pic_CXX='-pic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ lt_prog_compiler_can_build_shared_CXX=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_CXX"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_CXX=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:14240: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:14244: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_CXX=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then
+ case $lt_prog_compiler_pic_CXX in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+ esac
+else
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_can_build_shared_CXX=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_CXX=
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_CXX=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_CXX=yes
+ fi
+ else
+ lt_prog_compiler_static_works_CXX=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6; }
+
+if test x"$lt_prog_compiler_static_works_CXX" = xyes; then
+ :
+else
+ lt_prog_compiler_static_CXX=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_CXX=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:14344: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:14348: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_CXX=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix4* | aix5*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ export_symbols_cmds_CXX="$ltdll_cmds"
+ ;;
+ cygwin* | mingw*)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ *)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_CXX" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_CXX=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_CXX in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_CXX
+ pic_flag=$lt_prog_compiler_pic_CXX
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+ allow_undefined_flag_CXX=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_CXX=no
+ else
+ archive_cmds_need_lc_CXX=yes
+ fi
+ allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6; }
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_CXX=
+if test -n "$hardcode_libdir_flag_spec_CXX" || \
+ test -n "$runpath_var_CXX" || \
+ test "X$hardcode_automatic_CXX" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_CXX" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
+ test "$hardcode_minus_L_CXX" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_CXX=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_CXX=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_CXX=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5
+echo "${ECHO_T}$hardcode_action_CXX" >&6; }
+
+if test "$hardcode_action_CXX" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_CXX \
+ CC_CXX \
+ LD_CXX \
+ lt_prog_compiler_wl_CXX \
+ lt_prog_compiler_pic_CXX \
+ lt_prog_compiler_static_CXX \
+ lt_prog_compiler_no_builtin_flag_CXX \
+ export_dynamic_flag_spec_CXX \
+ thread_safe_flag_spec_CXX \
+ whole_archive_flag_spec_CXX \
+ enable_shared_with_static_runtimes_CXX \
+ old_archive_cmds_CXX \
+ old_archive_from_new_cmds_CXX \
+ predep_objects_CXX \
+ postdep_objects_CXX \
+ predeps_CXX \
+ postdeps_CXX \
+ compiler_lib_search_path_CXX \
+ archive_cmds_CXX \
+ archive_expsym_cmds_CXX \
+ postinstall_cmds_CXX \
+ postuninstall_cmds_CXX \
+ old_archive_from_expsyms_cmds_CXX \
+ allow_undefined_flag_CXX \
+ no_undefined_flag_CXX \
+ export_symbols_cmds_CXX \
+ hardcode_libdir_flag_spec_CXX \
+ hardcode_libdir_flag_spec_ld_CXX \
+ hardcode_libdir_separator_CXX \
+ hardcode_automatic_CXX \
+ module_cmds_CXX \
+ module_expsym_cmds_CXX \
+ lt_cv_prog_compiler_c_o_CXX \
+ exclude_expsyms_CXX \
+ include_expsyms_CXX; do
+
+ case $var in
+ old_archive_cmds_CXX | \
+ old_archive_from_new_cmds_CXX | \
+ archive_cmds_CXX | \
+ archive_expsym_cmds_CXX | \
+ module_cmds_CXX | \
+ module_expsym_cmds_CXX | \
+ old_archive_from_expsyms_cmds_CXX | \
+ export_symbols_cmds_CXX | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_CXX
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_CXX
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_CXX
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_CXX"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ F77)
+ if test -n "$F77" && test "X$F77" != "Xno"; then
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+archive_cmds_need_lc_F77=no
+allow_undefined_flag_F77=
+always_export_symbols_F77=no
+archive_expsym_cmds_F77=
+export_dynamic_flag_spec_F77=
+hardcode_direct_F77=no
+hardcode_libdir_flag_spec_F77=
+hardcode_libdir_flag_spec_ld_F77=
+hardcode_libdir_separator_F77=
+hardcode_minus_L_F77=no
+hardcode_automatic_F77=no
+module_cmds_F77=
+module_expsym_cmds_F77=
+link_all_deplibs_F77=unknown
+old_archive_cmds_F77=$old_archive_cmds
+no_undefined_flag_F77=
+whole_archive_flag_spec_F77=
+enable_shared_with_static_runtimes_F77=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+objext_F77=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code=" subroutine t\n return\n end\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=" program t\n end\n"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+compiler_F77=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; }
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; }
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+{ echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6; }
+
+GCC_F77="$G77"
+LD_F77="$LD"
+
+lt_prog_compiler_wl_F77=
+lt_prog_compiler_pic_F77=
+lt_prog_compiler_static_F77=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_static_F77='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_F77='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_F77='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared_F77=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_F77=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_F77='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic_F77='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_F77='-Bstatic'
+ else
+ lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_F77='-qnocommon'
+ lt_prog_compiler_wl_F77='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_F77='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static_F77='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-fpic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl_F77='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl_F77='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl_F77='-Qoption ld '
+ lt_prog_compiler_pic_F77='-PIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic_F77='-Kconform_pic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_can_build_shared_F77=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic_F77='-pic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared_F77=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_F77"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_F77=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_F77"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:15914: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:15918: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_F77=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_F77" = xyes; then
+ case $lt_prog_compiler_pic_F77 in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;;
+ esac
+else
+ lt_prog_compiler_pic_F77=
+ lt_prog_compiler_can_build_shared_F77=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_F77=
+ ;;
+ *)
+ lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_F77=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_F77=yes
+ fi
+ else
+ lt_prog_compiler_static_works_F77=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6; }
+
+if test x"$lt_prog_compiler_static_works_F77" = xyes; then
+ :
+else
+ lt_prog_compiler_static_F77=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_F77=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:16018: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:16022: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_F77=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+ runpath_var=
+ allow_undefined_flag_F77=
+ enable_shared_with_static_runtimes_F77=no
+ archive_cmds_F77=
+ archive_expsym_cmds_F77=
+ old_archive_From_new_cmds_F77=
+ old_archive_from_expsyms_cmds_F77=
+ export_dynamic_flag_spec_F77=
+ whole_archive_flag_spec_F77=
+ thread_safe_flag_spec_F77=
+ hardcode_libdir_flag_spec_F77=
+ hardcode_libdir_flag_spec_ld_F77=
+ hardcode_libdir_separator_F77=
+ hardcode_direct_F77=no
+ hardcode_minus_L_F77=no
+ hardcode_shlibpath_var_F77=unsupported
+ link_all_deplibs_F77=unknown
+ hardcode_automatic_F77=no
+ module_cmds_F77=
+ module_expsym_cmds_F77=
+ always_export_symbols_F77=no
+ export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms_F77=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs_F77=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_F77='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_F77=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs_F77=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs_F77=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_F77=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ allow_undefined_flag_F77=unsupported
+ always_export_symbols_F77=no
+ enable_shared_with_static_runtimes_F77=yes
+ export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct_F77=no
+ hardcode_shlibpath_var_F77=no
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_F77='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs_F77=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs_F77=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs_F77" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec_F77=
+ export_dynamic_flag_spec_F77=
+ whole_archive_flag_spec_F77=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag_F77=unsupported
+ always_export_symbols_F77=yes
+ archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L_F77=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct_F77=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_F77=''
+ hardcode_direct_F77=yes
+ hardcode_libdir_separator_F77=':'
+ link_all_deplibs_F77=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_F77=yes
+ else
+ # We have old collect2
+ hardcode_direct_F77=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_F77=yes
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_libdir_separator_F77=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_F77=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_F77='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_f77_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_F77="-z nodefs"
+ archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_f77_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_F77=' ${wl}-bernotok'
+ allow_undefined_flag_F77=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_F77='$convenience'
+ archive_cmds_need_lc_F77=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs_F77=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec_F77=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec_F77=' '
+ allow_undefined_flag_F77=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds_F77='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path_F77='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes_F77=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_F77='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_F77=no
+ hardcode_direct_F77=no
+ hardcode_automatic_F77=yes
+ hardcode_shlibpath_var_F77=unsupported
+ whole_archive_flag_spec_F77=''
+ link_all_deplibs_F77=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_F77=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs_F77=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes
+ hardcode_minus_L_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_direct_F77=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+
+ hardcode_direct_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_F77='+b $libdir'
+ hardcode_direct_F77=no
+ hardcode_shlibpath_var_F77=no
+ ;;
+ *)
+ hardcode_direct_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld_F77='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ link_all_deplibs_F77=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ newsos6)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ openbsd*)
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_F77='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ ;;
+ *)
+ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+ allow_undefined_flag_F77=unsupported
+ archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag_F77=' -expect_unresolved \*'
+ archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag_F77=' -expect_unresolved \*'
+ archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec_F77='-rpath $libdir'
+ fi
+ hardcode_libdir_separator_F77=:
+ ;;
+
+ solaris*)
+ no_undefined_flag_F77=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_shlibpath_var_F77=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs_F77=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_direct_F77=yes
+ hardcode_minus_L_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds_F77='$CC -r -o $output$reload_objs'
+ hardcode_direct_F77=no
+ ;;
+ motorola)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_F77=no
+ export_dynamic_flag_spec_F77='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_F77=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs_F77=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag_F77='${wl}-z,text'
+ archive_cmds_need_lc_F77=no
+ hardcode_shlibpath_var_F77=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag_F77='${wl}-z,text'
+ allow_undefined_flag_F77='${wl}-z,nodefs'
+ archive_cmds_need_lc_F77=no
+ hardcode_shlibpath_var_F77=no
+ hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_F77=':'
+ link_all_deplibs_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ *)
+ ld_shlibs_F77=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5
+echo "${ECHO_T}$ld_shlibs_F77" >&6; }
+test "$ld_shlibs_F77" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_F77" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_F77=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_F77 in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_F77
+ pic_flag=$lt_prog_compiler_pic_F77
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_F77
+ allow_undefined_flag_F77=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_F77=no
+ else
+ archive_cmds_need_lc_F77=yes
+ fi
+ allow_undefined_flag_F77=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6; }
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_F77=
+if test -n "$hardcode_libdir_flag_spec_F77" || \
+ test -n "$runpath_var_F77" || \
+ test "X$hardcode_automatic_F77" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_F77" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no &&
+ test "$hardcode_minus_L_F77" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_F77=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_F77=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_F77=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5
+echo "${ECHO_T}$hardcode_action_F77" >&6; }
+
+if test "$hardcode_action_F77" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_F77 \
+ CC_F77 \
+ LD_F77 \
+ lt_prog_compiler_wl_F77 \
+ lt_prog_compiler_pic_F77 \
+ lt_prog_compiler_static_F77 \
+ lt_prog_compiler_no_builtin_flag_F77 \
+ export_dynamic_flag_spec_F77 \
+ thread_safe_flag_spec_F77 \
+ whole_archive_flag_spec_F77 \
+ enable_shared_with_static_runtimes_F77 \
+ old_archive_cmds_F77 \
+ old_archive_from_new_cmds_F77 \
+ predep_objects_F77 \
+ postdep_objects_F77 \
+ predeps_F77 \
+ postdeps_F77 \
+ compiler_lib_search_path_F77 \
+ archive_cmds_F77 \
+ archive_expsym_cmds_F77 \
+ postinstall_cmds_F77 \
+ postuninstall_cmds_F77 \
+ old_archive_from_expsyms_cmds_F77 \
+ allow_undefined_flag_F77 \
+ no_undefined_flag_F77 \
+ export_symbols_cmds_F77 \
+ hardcode_libdir_flag_spec_F77 \
+ hardcode_libdir_flag_spec_ld_F77 \
+ hardcode_libdir_separator_F77 \
+ hardcode_automatic_F77 \
+ module_cmds_F77 \
+ module_expsym_cmds_F77 \
+ lt_cv_prog_compiler_c_o_F77 \
+ exclude_expsyms_F77 \
+ include_expsyms_F77; do
+
+ case $var in
+ old_archive_cmds_F77 | \
+ old_archive_from_new_cmds_F77 | \
+ archive_cmds_F77 | \
+ archive_expsym_cmds_F77 | \
+ module_cmds_F77 | \
+ module_expsym_cmds_F77 | \
+ old_archive_from_expsyms_cmds_F77 | \
+ export_symbols_cmds_F77 | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_F77
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_F77
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_F77
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_F77
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_F77
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_F77
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_F77
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_F77
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_F77
+archive_expsym_cmds=$lt_archive_expsym_cmds_F77
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_F77
+module_expsym_cmds=$lt_module_expsym_cmds_F77
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_F77
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_F77
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_F77
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_F77
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_F77
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_F77
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_F77
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_F77
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_F77
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_F77
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_F77
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_F77"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_F77
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_F77
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_F77
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_F77
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ GCJ)
+ if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+objext_GCJ=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+compiler_GCJ=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+archive_cmds_need_lc_GCJ=no
+
+old_archive_cmds_GCJ=$old_archive_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+
+lt_prog_compiler_no_builtin_flag_GCJ=
+
+if test "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin'
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:18220: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:18224: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+lt_prog_compiler_wl_GCJ=
+lt_prog_compiler_pic_GCJ=
+lt_prog_compiler_static_GCJ=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_static_GCJ='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_GCJ='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared_GCJ=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_GCJ=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic_GCJ='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ else
+ lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_GCJ='-qnocommon'
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-fpic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl_GCJ='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl_GCJ='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl_GCJ='-Qoption ld '
+ lt_prog_compiler_pic_GCJ='-PIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic_GCJ='-Kconform_pic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_can_build_shared_GCJ=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic_GCJ='-pic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared_GCJ=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_GCJ"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_GCJ=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_GCJ"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:18488: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:18492: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_GCJ=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then
+ case $lt_prog_compiler_pic_GCJ in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;;
+ esac
+else
+ lt_prog_compiler_pic_GCJ=
+ lt_prog_compiler_can_build_shared_GCJ=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_GCJ=
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_GCJ=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_GCJ=yes
+ fi
+ else
+ lt_prog_compiler_static_works_GCJ=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6; }
+
+if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then
+ :
+else
+ lt_prog_compiler_static_GCJ=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_GCJ=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:18592: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:18596: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_GCJ=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+ runpath_var=
+ allow_undefined_flag_GCJ=
+ enable_shared_with_static_runtimes_GCJ=no
+ archive_cmds_GCJ=
+ archive_expsym_cmds_GCJ=
+ old_archive_From_new_cmds_GCJ=
+ old_archive_from_expsyms_cmds_GCJ=
+ export_dynamic_flag_spec_GCJ=
+ whole_archive_flag_spec_GCJ=
+ thread_safe_flag_spec_GCJ=
+ hardcode_libdir_flag_spec_GCJ=
+ hardcode_libdir_flag_spec_ld_GCJ=
+ hardcode_libdir_separator_GCJ=
+ hardcode_direct_GCJ=no
+ hardcode_minus_L_GCJ=no
+ hardcode_shlibpath_var_GCJ=unsupported
+ link_all_deplibs_GCJ=unknown
+ hardcode_automatic_GCJ=no
+ module_cmds_GCJ=
+ module_expsym_cmds_GCJ=
+ always_export_symbols_GCJ=no
+ export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms_GCJ=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs_GCJ=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_GCJ=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs_GCJ=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs_GCJ=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_GCJ=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ allow_undefined_flag_GCJ=unsupported
+ always_export_symbols_GCJ=no
+ enable_shared_with_static_runtimes_GCJ=yes
+ export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs_GCJ=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs_GCJ=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs_GCJ" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec_GCJ=
+ export_dynamic_flag_spec_GCJ=
+ whole_archive_flag_spec_GCJ=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag_GCJ=unsupported
+ always_export_symbols_GCJ=yes
+ archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L_GCJ=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct_GCJ=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_GCJ=''
+ hardcode_direct_GCJ=yes
+ hardcode_libdir_separator_GCJ=':'
+ link_all_deplibs_GCJ=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_GCJ=yes
+ else
+ # We have old collect2
+ hardcode_direct_GCJ=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_GCJ=yes
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_libdir_separator_GCJ=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_GCJ=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_GCJ='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_GCJ="-z nodefs"
+ archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_GCJ=' ${wl}-bernotok'
+ allow_undefined_flag_GCJ=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_GCJ='$convenience'
+ archive_cmds_need_lc_GCJ=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs_GCJ=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec_GCJ=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec_GCJ=' '
+ allow_undefined_flag_GCJ=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds_GCJ='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes_GCJ=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_GCJ=no
+ hardcode_direct_GCJ=no
+ hardcode_automatic_GCJ=yes
+ hardcode_shlibpath_var_GCJ=unsupported
+ whole_archive_flag_spec_GCJ=''
+ link_all_deplibs_GCJ=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_GCJ=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs_GCJ=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes
+ hardcode_minus_L_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_direct_GCJ=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+
+ hardcode_direct_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_GCJ='+b $libdir'
+ hardcode_direct_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+ *)
+ hardcode_direct_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ link_all_deplibs_GCJ=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ newsos6)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ openbsd*)
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+ allow_undefined_flag_GCJ=unsupported
+ archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag_GCJ=' -expect_unresolved \*'
+ archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag_GCJ=' -expect_unresolved \*'
+ archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec_GCJ='-rpath $libdir'
+ fi
+ hardcode_libdir_separator_GCJ=:
+ ;;
+
+ solaris*)
+ no_undefined_flag_GCJ=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs_GCJ=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_minus_L_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds_GCJ='$CC -r -o $output$reload_objs'
+ hardcode_direct_GCJ=no
+ ;;
+ motorola)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_GCJ=no
+ export_dynamic_flag_spec_GCJ='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_GCJ=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs_GCJ=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag_GCJ='${wl}-z,text'
+ archive_cmds_need_lc_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag_GCJ='${wl}-z,text'
+ allow_undefined_flag_GCJ='${wl}-z,nodefs'
+ archive_cmds_need_lc_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_GCJ=':'
+ link_all_deplibs_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ *)
+ ld_shlibs_GCJ=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5
+echo "${ECHO_T}$ld_shlibs_GCJ" >&6; }
+test "$ld_shlibs_GCJ" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_GCJ" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_GCJ=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_GCJ in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_GCJ
+ pic_flag=$lt_prog_compiler_pic_GCJ
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ
+ allow_undefined_flag_GCJ=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_GCJ=no
+ else
+ archive_cmds_need_lc_GCJ=yes
+ fi
+ allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6; }
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_GCJ=
+if test -n "$hardcode_libdir_flag_spec_GCJ" || \
+ test -n "$runpath_var_GCJ" || \
+ test "X$hardcode_automatic_GCJ" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_GCJ" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no &&
+ test "$hardcode_minus_L_GCJ" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_GCJ=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_GCJ=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_GCJ=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5
+echo "${ECHO_T}$hardcode_action_GCJ" >&6; }
+
+if test "$hardcode_action_GCJ" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_GCJ \
+ CC_GCJ \
+ LD_GCJ \
+ lt_prog_compiler_wl_GCJ \
+ lt_prog_compiler_pic_GCJ \
+ lt_prog_compiler_static_GCJ \
+ lt_prog_compiler_no_builtin_flag_GCJ \
+ export_dynamic_flag_spec_GCJ \
+ thread_safe_flag_spec_GCJ \
+ whole_archive_flag_spec_GCJ \
+ enable_shared_with_static_runtimes_GCJ \
+ old_archive_cmds_GCJ \
+ old_archive_from_new_cmds_GCJ \
+ predep_objects_GCJ \
+ postdep_objects_GCJ \
+ predeps_GCJ \
+ postdeps_GCJ \
+ compiler_lib_search_path_GCJ \
+ archive_cmds_GCJ \
+ archive_expsym_cmds_GCJ \
+ postinstall_cmds_GCJ \
+ postuninstall_cmds_GCJ \
+ old_archive_from_expsyms_cmds_GCJ \
+ allow_undefined_flag_GCJ \
+ no_undefined_flag_GCJ \
+ export_symbols_cmds_GCJ \
+ hardcode_libdir_flag_spec_GCJ \
+ hardcode_libdir_flag_spec_ld_GCJ \
+ hardcode_libdir_separator_GCJ \
+ hardcode_automatic_GCJ \
+ module_cmds_GCJ \
+ module_expsym_cmds_GCJ \
+ lt_cv_prog_compiler_c_o_GCJ \
+ exclude_expsyms_GCJ \
+ include_expsyms_GCJ; do
+
+ case $var in
+ old_archive_cmds_GCJ | \
+ old_archive_from_new_cmds_GCJ | \
+ archive_cmds_GCJ | \
+ archive_expsym_cmds_GCJ | \
+ module_cmds_GCJ | \
+ module_expsym_cmds_GCJ | \
+ old_archive_from_expsyms_cmds_GCJ | \
+ export_symbols_cmds_GCJ | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_GCJ
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_GCJ
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_GCJ
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_GCJ
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_GCJ
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_GCJ
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_GCJ
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_GCJ
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_GCJ
+archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_GCJ
+module_expsym_cmds=$lt_module_expsym_cmds_GCJ
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_GCJ
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_GCJ
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_GCJ
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_GCJ
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_GCJ
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_GCJ
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_GCJ
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_GCJ
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_GCJ
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_GCJ"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_GCJ
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_GCJ
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_GCJ
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_GCJ
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ RC)
+
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+objext_RC=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+compiler_RC=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+lt_cv_prog_compiler_c_o_RC=yes
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_RC \
+ CC_RC \
+ LD_RC \
+ lt_prog_compiler_wl_RC \
+ lt_prog_compiler_pic_RC \
+ lt_prog_compiler_static_RC \
+ lt_prog_compiler_no_builtin_flag_RC \
+ export_dynamic_flag_spec_RC \
+ thread_safe_flag_spec_RC \
+ whole_archive_flag_spec_RC \
+ enable_shared_with_static_runtimes_RC \
+ old_archive_cmds_RC \
+ old_archive_from_new_cmds_RC \
+ predep_objects_RC \
+ postdep_objects_RC \
+ predeps_RC \
+ postdeps_RC \
+ compiler_lib_search_path_RC \
+ archive_cmds_RC \
+ archive_expsym_cmds_RC \
+ postinstall_cmds_RC \
+ postuninstall_cmds_RC \
+ old_archive_from_expsyms_cmds_RC \
+ allow_undefined_flag_RC \
+ no_undefined_flag_RC \
+ export_symbols_cmds_RC \
+ hardcode_libdir_flag_spec_RC \
+ hardcode_libdir_flag_spec_ld_RC \
+ hardcode_libdir_separator_RC \
+ hardcode_automatic_RC \
+ module_cmds_RC \
+ module_expsym_cmds_RC \
+ lt_cv_prog_compiler_c_o_RC \
+ exclude_expsyms_RC \
+ include_expsyms_RC; do
+
+ case $var in
+ old_archive_cmds_RC | \
+ old_archive_from_new_cmds_RC | \
+ archive_cmds_RC | \
+ archive_expsym_cmds_RC | \
+ module_cmds_RC | \
+ module_expsym_cmds_RC | \
+ old_archive_from_expsyms_cmds_RC | \
+ export_symbols_cmds_RC | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_RC
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_RC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_RC
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_RC
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_RC
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_RC
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_RC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_RC
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_RC
+archive_expsym_cmds=$lt_archive_expsym_cmds_RC
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_RC
+module_expsym_cmds=$lt_module_expsym_cmds_RC
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_RC
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_RC
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_RC
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_RC
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_RC
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_RC
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_RC
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_RC
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_RC
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_RC
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_RC
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_RC"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_RC
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_RC
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_RC
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_RC
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ ;;
+
+ *)
+ { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5
+echo "$as_me: error: Unsupported tag name: $tagname" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+ # Append the new tag name to the list of available tags.
+ if test -n "$tagname" ; then
+ available_tags="$available_tags $tagname"
+ fi
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ # Now substitute the updated list of available tags.
+ if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+ mv "${ofile}T" "$ofile"
+ chmod +x "$ofile"
+ else
+ rm -f "${ofile}T"
+ { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5
+echo "$as_me: error: unable to update list of available tagged configurations." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Prevent multiple expansion
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Check for AViiON Machines running DGUX
+#
+ac_is_dgux=no
+if test "${ac_cv_header_sys_dg_sys_info_h+set}" = set; then
+ { echo "$as_me:$LINENO: checking for sys/dg_sys_info.h" >&5
+echo $ECHO_N "checking for sys/dg_sys_info.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_sys_dg_sys_info_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_dg_sys_info_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_dg_sys_info_h" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking sys/dg_sys_info.h usability" >&5
+echo $ECHO_N "checking sys/dg_sys_info.h usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <sys/dg_sys_info.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking sys/dg_sys_info.h presence" >&5
+echo $ECHO_N "checking sys/dg_sys_info.h presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/dg_sys_info.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: sys/dg_sys_info.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: sys/dg_sys_info.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: sys/dg_sys_info.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: sys/dg_sys_info.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: sys/dg_sys_info.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: sys/dg_sys_info.h: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## -------------------------------- ##
+## Report this to Hans.Boehm@hp.com ##
+## -------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for sys/dg_sys_info.h" >&5
+echo $ECHO_N "checking for sys/dg_sys_info.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_sys_dg_sys_info_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_sys_dg_sys_info_h=$ac_header_preproc
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_dg_sys_info_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_dg_sys_info_h" >&6; }
+
+fi
+if test $ac_cv_header_sys_dg_sys_info_h = yes; then
+ ac_is_dgux=yes;
+fi
+
+
+
+ ## :GOTCHA: we do not check anything but sys/dg_sys_info.h
+if test $ac_is_dgux = yes; then
+ if test "$enable_full_debug" = "yes"; then
+ CFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
+ CXXFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
+ else
+ CFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
+ CXXFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
+ fi
+
+
+fi
+
+
+# Check whether --with-target-subdir was given.
+if test "${with_target_subdir+set}" = set; then
+ withval=$with_target_subdir;
+fi
+
+
+# Check whether --with-cross-host was given.
+if test "${with_cross_host+set}" = set; then
+ withval=$with_cross_host;
+fi
+
+
+# automake wants to see AC_EXEEXT. But we don't need it. And having
+# it is actually a problem, because the compiler we're passed can't
+# necessarily do a full link. So we fool automake here.
+if false; then
+ # autoconf 2.50 runs AC_EXEEXT by default, and the macro expands
+ # to nothing, so nothing would remain between `then' and `fi' if it
+ # were not for the `:' below.
+ :
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether Solaris gcc optimization fix is necessary" >&5
+echo $ECHO_N "checking whether Solaris gcc optimization fix is necessary... $ECHO_C" >&6; }
+case "$host" in
+ *aix*)
+ if test "$GCC" = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ new_CFLAGS=
+ for i in $CFLAGS; do
+ case "$i" in
+ -O*)
+ ;;
+ *)
+ new_CFLAGS="$new_CFLAGS $i"
+ ;;
+ esac
+ done
+ CFLAGS="$new_CFLAGS"
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ fi
+ ;;
+ *) { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; } ;;
+esac
+
+cat >>confdefs.h <<\_ACEOF
+#define NO_EXECUTE_PERMISSION 1
+_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
+#define ALL_INTERIOR_POINTERS 1
+_ACEOF
+
+
+
+# Check whether --enable-gcj-support was given.
+if test "${enable_gcj_support+set}" = set; then
+ enableval=$enable_gcj_support;
+fi
+
+
+
+if test x"$enable_gcj_support" != xno; then
+ ENABLE_GCJ_SUPPORT_TRUE=
+ ENABLE_GCJ_SUPPORT_FALSE='#'
+else
+ ENABLE_GCJ_SUPPORT_TRUE='#'
+ ENABLE_GCJ_SUPPORT_FALSE=
+fi
+
+if test x"$enable_gcj_support" != xno; then
+
+cat >>confdefs.h <<\_ACEOF
+#define GC_GCJ_SUPPORT 1
+_ACEOF
+
+fi
+
+# Check whether --enable-java-finalization was given.
+if test "${enable_java_finalization+set}" = set; then
+ enableval=$enable_java_finalization;
+fi
+
+if test x"$enable_java_finalization" != xno; then
+ cat >>confdefs.h <<\_ACEOF
+#define JAVA_FINALIZATION 1
+_ACEOF
+
+fi
+
+# Check whether --enable-atomic-uncollectable was given.
+if test "${enable_atomic_uncollectable+set}" = set; then
+ enableval=$enable_atomic_uncollectable;
+fi
+
+if test x"$enable_atomic_uncollectible" != x"no"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ATOMIC_UNCOLLECTABLE 1
+_ACEOF
+
+fi
+
+# Check whether --enable-redirect-malloc was given.
+if test "${enable_redirect_malloc+set}" = set; then
+ enableval=$enable_redirect_malloc;
+fi
+
+
+if test "${enable_redirect_malloc}" = yes; then
+ if test "${enable_full_debug}" = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define REDIRECT_MALLOC GC_debug_malloc_replacement
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define REDIRECT_REALLOC GC_debug_realloc_replacement
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define REDIRECT_FREE GC_debug_free
+_ACEOF
+
+ else
+ cat >>confdefs.h <<\_ACEOF
+#define REDIRECT_MALLOC GC_malloc
+_ACEOF
+
+ fi
+fi
+
+# Check whether --enable-large-config was given.
+if test "${enable_large_config+set}" = set; then
+ enableval=$enable_large_config;
+fi
+
+
+if test "${enable_large_config}" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define LARGE_CONFIG 1
+_ACEOF
+
+fi
+
+if test -n "${with_cross_host}"; then
+ cat >>confdefs.h <<\_ACEOF
+#define NO_CLOCK 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define SMALL_CONFIG 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define NO_DEBUGGING 1
+_ACEOF
+
+fi
+
+
+
+UNWINDLIBS=
+# Check whether --enable-gc-debug was given.
+if test "${enable_gc_debug+set}" = set; then
+ enableval=$enable_gc_debug; if test "$enable_gc_debug" = "yes"; then
+ { echo "$as_me:$LINENO: WARNING: \"Should define GC_DEBUG and use debug alloc. in clients.\"" >&5
+echo "$as_me: WARNING: \"Should define GC_DEBUG and use debug alloc. in clients.\"" >&2;}
+ cat >>confdefs.h <<\_ACEOF
+#define KEEP_BACK_PTRS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define DBG_HDRS_ALL 1
+_ACEOF
+
+ case $host in
+ ia64-*-linux* )
+ cat >>confdefs.h <<\_ACEOF
+#define MAKE_BACK_GRAPH 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define SAVE_CALL_COUNT 8
+_ACEOF
+
+ { echo "$as_me:$LINENO: checking for backtrace in -lunwind" >&5
+echo $ECHO_N "checking for backtrace in -lunwind... $ECHO_C" >&6; }
+if test "${ac_cv_lib_unwind_backtrace+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lunwind $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char backtrace ();
+int
+main ()
+{
+return backtrace ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_unwind_backtrace=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_unwind_backtrace=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_unwind_backtrace" >&5
+echo "${ECHO_T}$ac_cv_lib_unwind_backtrace" >&6; }
+if test $ac_cv_lib_unwind_backtrace = yes; then
+
+ cat >>confdefs.h <<\_ACEOF
+#define GC_HAVE_BUILTIN_BACKTRACE 1
+_ACEOF
+
+ UNWINDLIBS=-lunwind
+ { echo "$as_me:$LINENO: WARNING: \"Client code may need to link against libunwind.\"" >&5
+echo "$as_me: WARNING: \"Client code may need to link against libunwind.\"" >&2;}
+
+fi
+
+ ;;
+ x86-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* )
+ cat >>confdefs.h <<\_ACEOF
+#define MAKE_BACK_GRAPH 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: WARNING: \"Client must not use -fomit-frame-pointer.\"" >&5
+echo "$as_me: WARNING: \"Client must not use -fomit-frame-pointer.\"" >&2;}
+ cat >>confdefs.h <<\_ACEOF
+#define SAVE_CALL_COUNT 8
+_ACEOF
+
+ ;;
+ i345686-*-dgux*)
+ cat >>confdefs.h <<\_ACEOF
+#define MAKE_BACK_GRAPH 1
+_ACEOF
+
+ ;;
+ esac
+ fi
+fi
+
+
+
+
+# Check whether --enable-gc-assertions was given.
+if test "${enable_gc_assertions+set}" = set; then
+ enableval=$enable_gc_assertions;
+fi
+
+if test "${enable_gc_assertions}" = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define GC_ASSERTIONS 1
+_ACEOF
+
+fi
+
+
+
+if test -z "$with_cross_host"; then
+ USE_LIBDIR_TRUE=
+ USE_LIBDIR_FALSE='#'
+else
+ USE_LIBDIR_TRUE='#'
+ USE_LIBDIR_FALSE=
+fi
+
+
+
+
+atomic_ops_libs=-latomic_ops
+if test "${ac_cv_header_atomic_ops_h+set}" = set; then
+ { echo "$as_me:$LINENO: checking for atomic_ops.h" >&5
+echo $ECHO_N "checking for atomic_ops.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_atomic_ops_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_atomic_ops_h" >&5
+echo "${ECHO_T}$ac_cv_header_atomic_ops_h" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking atomic_ops.h usability" >&5
+echo $ECHO_N "checking atomic_ops.h usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <atomic_ops.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking atomic_ops.h presence" >&5
+echo $ECHO_N "checking atomic_ops.h presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <atomic_ops.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: atomic_ops.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: atomic_ops.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: atomic_ops.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: atomic_ops.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: atomic_ops.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: atomic_ops.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: atomic_ops.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: atomic_ops.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: atomic_ops.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: atomic_ops.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: atomic_ops.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: atomic_ops.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: atomic_ops.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: atomic_ops.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: atomic_ops.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: atomic_ops.h: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## -------------------------------- ##
+## Report this to Hans.Boehm@hp.com ##
+## -------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for atomic_ops.h" >&5
+echo $ECHO_N "checking for atomic_ops.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_atomic_ops_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_atomic_ops_h=$ac_header_preproc
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_atomic_ops_h" >&5
+echo "${ECHO_T}$ac_cv_header_atomic_ops_h" >&6; }
+
+fi
+if test $ac_cv_header_atomic_ops_h = yes; then
+ { echo "$as_me:$LINENO: Using pre-installed libatomic_ops" >&5
+echo "$as_me: Using pre-installed libatomic_ops" >&6;}
+else
+ ao_dir=
+ for candidate in ${srcdir}/libatomic_ops*; do
+ case $candidate in
+ *.tar.gz)
+ ;;
+ *install)
+ ;;
+ *)
+ if test -e "$candidate"; then
+ ao_dir="$candidate"
+ fi
+ ;;
+ esac
+ done
+ if test -z "$ao_dir"; then
+ { { echo "$as_me:$LINENO: error: Missig libatomic_ops." >&5
+echo "$as_me: error: Missig libatomic_ops." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ ao_version="${ao_dir#*libatomic_ops-}"
+ { echo "$as_me:$LINENO: Using internal version of libatomic_ops" >&5
+echo "$as_me: Using internal version of libatomic_ops" >&6;}
+
+ test -e ${srcdir}/libatomic_ops \
+ || ln -s ${ao_dir} ${srcdir}/libatomic_ops
+ subdirs="$subdirs libatomic_ops"
+
+
+ test -e ${srcdir}/atomic_ops.c \
+ || ln -s ${srcdir}/libatomic_ops/src/atomic_ops.c \
+ ${srcdir}/atomic_ops.c
+
+ test -e ${srcdir}/atomic_ops_sysdeps.S \
+ || ln -s ${srcdir}/libatomic_ops/src/atomic_ops_sysdeps.S \
+ ${srcdir}/atomic_ops_sysdeps.S
+
+ GC_CFLAGS="${GC_CFLAGS} -I \$(top_srcdir)/libatomic_ops/src"
+ maybe_libatomic_ops="libatomic_ops"
+
+fi
+
+
+
+
+
+if test -n "$maybe_libatomic_ops" -a "$THREADS" != "none"; then
+ USE_INTERNAL_LIBATOMIC_OPS_TRUE=
+ USE_INTERNAL_LIBATOMIC_OPS_FALSE='#'
+else
+ USE_INTERNAL_LIBATOMIC_OPS_TRUE='#'
+ USE_INTERNAL_LIBATOMIC_OPS_FALSE=
+fi
+
+
+
+if test -n "$maybe_libatomic_ops" -a x$need_atomic_ops_asm = xtrue; then
+ NEED_ATOMIC_OPS_ASM_TRUE=
+ NEED_ATOMIC_OPS_ASM_FALSE='#'
+else
+ NEED_ATOMIC_OPS_ASM_TRUE='#'
+ NEED_ATOMIC_OPS_ASM_FALSE=
+fi
+
+
+
+
+ac_config_files="$ac_config_files Makefile bdw-gc.pc"
+
+
+ac_config_commands="$ac_config_commands default"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${THREADS_TRUE}" && test -z "${THREADS_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"THREADS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"THREADS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${PTHREADS_TRUE}" && test -z "${PTHREADS_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"PTHREADS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"PTHREADS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${DARWIN_THREADS_TRUE}" && test -z "${DARWIN_THREADS_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"DARWIN_THREADS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"DARWIN_THREADS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${WIN32_THREADS_TRUE}" && test -z "${WIN32_THREADS_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"WIN32_THREADS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"WIN32_THREADS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${COMPILER_XLC_TRUE}" && test -z "${COMPILER_XLC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"COMPILER_XLC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"COMPILER_XLC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${CPLUSPLUS_TRUE}" && test -z "${CPLUSPLUS_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"CPLUSPLUS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"CPLUSPLUS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${ENABLE_GCJ_SUPPORT_TRUE}" && test -z "${ENABLE_GCJ_SUPPORT_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"ENABLE_GCJ_SUPPORT\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"ENABLE_GCJ_SUPPORT\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${USE_LIBDIR_TRUE}" && test -z "${USE_LIBDIR_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"USE_LIBDIR\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"USE_LIBDIR\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${USE_INTERNAL_LIBATOMIC_OPS_TRUE}" && test -z "${USE_INTERNAL_LIBATOMIC_OPS_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"USE_INTERNAL_LIBATOMIC_OPS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"USE_INTERNAL_LIBATOMIC_OPS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${NEED_ATOMIC_OPS_ASM_TRUE}" && test -z "${NEED_ATOMIC_OPS_ASM_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"NEED_ATOMIC_OPS_ASM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"NEED_ATOMIC_OPS_ASM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by gc $as_me 7.0, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+gc config.status 7.0
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+ srcdir=${srcdir}
+ host=${host}
+ CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ CC="${CC}"
+ DEFS="$DEFS"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "bdw-gc.pc") CONFIG_FILES="$CONFIG_FILES bdw-gc.pc" ;;
+ "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+target!$target$ac_delim
+target_cpu!$target_cpu$ac_delim
+target_vendor!$target_vendor$ac_delim
+target_os!$target_os$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+CYGPATH_W!$CYGPATH_W$ac_delim
+PACKAGE!$PACKAGE$ac_delim
+VERSION!$VERSION$ac_delim
+ACLOCAL!$ACLOCAL$ac_delim
+AUTOCONF!$AUTOCONF$ac_delim
+AUTOMAKE!$AUTOMAKE$ac_delim
+AUTOHEADER!$AUTOHEADER$ac_delim
+MAKEINFO!$MAKEINFO$ac_delim
+install_sh!$install_sh$ac_delim
+STRIP!$STRIP$ac_delim
+INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim
+mkdir_p!$mkdir_p$ac_delim
+AWK!$AWK$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+am__leading_dot!$am__leading_dot$ac_delim
+AMTAR!$AMTAR$ac_delim
+am__tar!$am__tar$ac_delim
+am__untar!$am__untar$ac_delim
+MAINTAINER_MODE_TRUE!$MAINTAINER_MODE_TRUE$ac_delim
+MAINTAINER_MODE_FALSE!$MAINTAINER_MODE_FALSE$ac_delim
+MAINT!$MAINT$ac_delim
+GC_VERSION!$GC_VERSION$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+DEPDIR!$DEPDIR$ac_delim
+am__include!$am__include$ac_delim
+am__quote!$am__quote$ac_delim
+AMDEP_TRUE!$AMDEP_TRUE$ac_delim
+AMDEP_FALSE!$AMDEP_FALSE$ac_delim
+AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim
+CCDEPMODE!$CCDEPMODE$ac_delim
+am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim
+am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+CXXDEPMODE!$CXXDEPMODE$ac_delim
+am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim
+am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim
+CCAS!$CCAS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+CEOF$ac_eof
+_ACEOF
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+CCASFLAGS!$CCASFLAGS$ac_delim
+AR!$AR$ac_delim
+RANLIB!$RANLIB$ac_delim
+GC_CFLAGS!$GC_CFLAGS$ac_delim
+THREADDLLIBS!$THREADDLLIBS$ac_delim
+THREADS_TRUE!$THREADS_TRUE$ac_delim
+THREADS_FALSE!$THREADS_FALSE$ac_delim
+PTHREADS_TRUE!$PTHREADS_TRUE$ac_delim
+PTHREADS_FALSE!$PTHREADS_FALSE$ac_delim
+DARWIN_THREADS_TRUE!$DARWIN_THREADS_TRUE$ac_delim
+DARWIN_THREADS_FALSE!$DARWIN_THREADS_FALSE$ac_delim
+WIN32_THREADS_TRUE!$WIN32_THREADS_TRUE$ac_delim
+WIN32_THREADS_FALSE!$WIN32_THREADS_FALSE$ac_delim
+COMPILER_XLC_TRUE!$COMPILER_XLC_TRUE$ac_delim
+COMPILER_XLC_FALSE!$COMPILER_XLC_FALSE$ac_delim
+extra_ldflags_libgc!$extra_ldflags_libgc$ac_delim
+EXTRA_TEST_LIBS!$EXTRA_TEST_LIBS$ac_delim
+target_all!$target_all$ac_delim
+CPLUSPLUS_TRUE!$CPLUSPLUS_TRUE$ac_delim
+CPLUSPLUS_FALSE!$CPLUSPLUS_FALSE$ac_delim
+INCLUDES!$INCLUDES$ac_delim
+CXXINCLUDES!$CXXINCLUDES$ac_delim
+addobjs!$addobjs$ac_delim
+addlibs!$addlibs$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+LN_S!$LN_S$ac_delim
+ECHO!$ECHO$ac_delim
+CPP!$CPP$ac_delim
+CXXCPP!$CXXCPP$ac_delim
+F77!$F77$ac_delim
+FFLAGS!$FFLAGS$ac_delim
+ac_ct_F77!$ac_ct_F77$ac_delim
+LIBTOOL!$LIBTOOL$ac_delim
+ENABLE_GCJ_SUPPORT_TRUE!$ENABLE_GCJ_SUPPORT_TRUE$ac_delim
+ENABLE_GCJ_SUPPORT_FALSE!$ENABLE_GCJ_SUPPORT_FALSE$ac_delim
+UNWINDLIBS!$UNWINDLIBS$ac_delim
+USE_LIBDIR_TRUE!$USE_LIBDIR_TRUE$ac_delim
+USE_LIBDIR_FALSE!$USE_LIBDIR_FALSE$ac_delim
+subdirs!$subdirs$ac_delim
+USE_INTERNAL_LIBATOMIC_OPS_TRUE!$USE_INTERNAL_LIBATOMIC_OPS_TRUE$ac_delim
+USE_INTERNAL_LIBATOMIC_OPS_FALSE!$USE_INTERNAL_LIBATOMIC_OPS_FALSE$ac_delim
+NEED_ATOMIC_OPS_ASM_TRUE!$NEED_ATOMIC_OPS_ASM_TRUE$ac_delim
+NEED_ATOMIC_OPS_ASM_FALSE!$NEED_ATOMIC_OPS_ASM_FALSE$ac_delim
+atomic_ops_libs!$atomic_ops_libs$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 47; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :C $CONFIG_COMMANDS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+
+
+ :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # So let's grep whole file.
+ if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir=$dirpart/$fdir
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+ ;;
+
+ esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+#
+# CONFIG_SUBDIRS section.
+#
+if test "$no_recursion" != yes; then
+
+ # Remove --cache-file and --srcdir arguments so they do not pile up.
+ ac_sub_configure_args=
+ ac_prev=
+ eval "set x $ac_configure_args"
+ shift
+ for ac_arg
+ do
+ if test -n "$ac_prev"; then
+ ac_prev=
+ continue
+ fi
+ case $ac_arg in
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \
+ | --c=*)
+ ;;
+ --config-cache | -C)
+ ;;
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ ;;
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ ;;
+ *)
+ case $ac_arg in
+ *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ ac_sub_configure_args="$ac_sub_configure_args '$ac_arg'" ;;
+ esac
+ done
+
+ # Always prepend --prefix to ensure using the same prefix
+ # in subdir configurations.
+ ac_arg="--prefix=$prefix"
+ case $ac_arg in
+ *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args"
+
+ # Pass --silent
+ if test "$silent" = yes; then
+ ac_sub_configure_args="--silent $ac_sub_configure_args"
+ fi
+
+ ac_popdir=`pwd`
+ for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue
+
+ # Do not complain, so a configure script can configure whichever
+ # parts of a large source tree are present.
+ test -d "$srcdir/$ac_dir" || continue
+
+ ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)"
+ echo "$as_me:$LINENO: $ac_msg" >&5
+ echo "$ac_msg" >&6
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ cd "$ac_dir"
+
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ ac_sub_configure=$ac_srcdir/configure.gnu
+ elif test -f "$ac_srcdir/configure"; then
+ ac_sub_configure=$ac_srcdir/configure
+ elif test -f "$ac_srcdir/configure.in"; then
+ # This should be Cygnus configure.
+ ac_sub_configure=$ac_aux_dir/configure
+ else
+ { echo "$as_me:$LINENO: WARNING: no configuration information is in $ac_dir" >&5
+echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;}
+ ac_sub_configure=
+ fi
+
+ # The recursion is here.
+ if test -n "$ac_sub_configure"; then
+ # Make the cache file name correct relative to the subdirectory.
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;;
+ *) # Relative name.
+ ac_sub_cache_file=$ac_top_build_prefix$cache_file ;;
+ esac
+
+ { echo "$as_me:$LINENO: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5
+echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;}
+ # The eval makes quoting arguments work.
+ eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \
+ --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" ||
+ { { echo "$as_me:$LINENO: error: $ac_sub_configure failed for $ac_dir" >&5
+echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ cd "$ac_popdir"
+ done
+fi
+
diff --git a/tools/build/v2/engine/boehm_gc/configure.ac b/tools/build/v2/engine/boehm_gc/configure.ac
new file mode 100644
index 0000000000..7922b13fc4
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/configure.ac
@@ -0,0 +1,658 @@
+# Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved.
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose, provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+#
+# Original author: Tom Tromey
+# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
+
+dnl Process this file with autoconf to produce configure.
+
+# Initialization
+# ==============
+
+AC_INIT(gc,7.0,Hans.Boehm@hp.com)
+ ## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)?
+AC_CONFIG_SRCDIR(gcj_mlc.c)
+AC_CANONICAL_TARGET
+AC_PREREQ(2.53)
+AC_REVISION($Revision: 1.25 $)
+GC_SET_VERSION
+AM_INIT_AUTOMAKE([foreign dist-bzip2 subdir-objects nostdinc])
+AM_MAINTAINER_MODE
+
+AC_SUBST(PACKAGE)
+AC_SUBST(GC_VERSION)
+
+AM_PROG_CC_C_O
+AC_PROG_CXX
+
+AM_PROG_AS
+## FIXME: really needed? (AC_LIBTOOL already provides this)
+AC_CHECK_TOOL(AR, ar)
+AC_CHECK_TOOL(RANLIB, ranlib, :) # :)
+
+AC_PROG_INSTALL
+
+. ${srcdir}/configure.host
+
+GC_CFLAGS=${gc_cflags}
+AC_SUBST(GC_CFLAGS)
+
+AC_ARG_ENABLE(threads,
+ [AC_HELP_STRING([--enable-threads=TYPE], [choose threading package])],
+ THREADS=$enableval,
+ [ AC_MSG_CHECKING([for thread model used by GCC])
+ THREADS=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
+ if test -z "$THREADS"; then
+ THREADS=no
+ fi
+ AC_MSG_RESULT([$THREADS]) ])
+
+AC_ARG_ENABLE(parallel-mark,
+ [AC_HELP_STRING([--enable-parallel-mark],
+ [parallelize marking and free list construction])],
+ [case "$THREADS" in
+ no | none | single)
+ AC_MSG_ERROR([Parallel mark requires --enable-threads=x spec])
+ ;;
+ esac ]
+)
+
+AC_ARG_ENABLE(cplusplus,
+ [AC_HELP_STRING([--enable-cplusplus], [install C++ support])])
+
+INCLUDES=-I${srcdir}/include
+THREADDLLIBS=
+need_atomic_ops_asm=false
+## Libraries needed to support dynamic loading and/or threads.
+case "$THREADS" in
+ no | none | single)
+ THREADS=none
+ ;;
+ posix | pthreads)
+ THREADS=posix
+ THREADDLLIBS=-lpthread
+ case "$host" in
+ x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* | alpha-*-linux*)
+ AC_DEFINE(GC_LINUX_THREADS)
+ AC_DEFINE(_REENTRANT)
+ if test "${enable_parallel_mark}" = yes; then
+ AC_DEFINE(PARALLEL_MARK)
+ fi
+ AC_DEFINE(THREAD_LOCAL_ALLOC)
+ AC_MSG_WARN("Explict GC_INIT() calls may be required.");
+ ;;
+ *-*-linux*)
+ AC_DEFINE(GC_LINUX_THREADS)
+ AC_DEFINE(_REENTRANT)
+ ;;
+ *-*-aix*)
+ AC_DEFINE(GC_AIX_THREADS)
+ AC_DEFINE(_REENTRANT)
+ ;;
+ *-*-hpux11*)
+ AC_MSG_WARN("Only HP/UX 11 POSIX threads are supported.")
+ AC_DEFINE(GC_HPUX_THREADS)
+ AC_DEFINE(_POSIX_C_SOURCE,199506L)
+ if test "${enable_parallel_mark}" = yes; then
+ AC_DEFINE(PARALLEL_MARK)
+ fi
+ AC_DEFINE(THREAD_LOCAL_ALLOC)
+ AC_MSG_WARN("Explict GC_INIT() calls may be required.");
+ THREADDLLIBS="-lpthread -lrt"
+ # HPUX needs REENTRANT for the _r calls.
+ AC_DEFINE(_REENTRANT, 1, [Required define if using POSIX threads])
+ ;;
+ *-*-hpux10*)
+ AC_MSG_WARN("Only HP-UX 11 POSIX threads are supported.")
+ ;;
+ *-*-freebsd*)
+ AC_MSG_WARN("FreeBSD does not yet fully support threads with Boehm GC.")
+ AC_DEFINE(GC_FREEBSD_THREADS)
+ INCLUDES="$INCLUDES -pthread"
+ ;;
+ *-*-kfreebsd*-gnu)
+ AC_DEFINE(GC_FREEBSD_THREADS)
+ INCLUDES="$INCLUDES -pthread"
+ THREADDLLIBS=-pthread
+ AC_DEFINE(_REENTRANT)
+ if test "${enable_parallel_mark}" = yes; then
+ AC_DEFINE(PARALLEL_MARK)
+ fi
+ AC_DEFINE(THREAD_LOCAL_ALLOC)
+ AC_DEFINE(USE_COMPILER_TLS)
+ ;;
+ *-*-gnu*)
+ AC_DEFINE(GC_GNU_THREADS)
+ AC_DEFINE(_REENTRANT)
+ AC_DEFINE(THREAD_LOCAL_ALLOC)
+ ;;
+ *-*-netbsd*)
+ AC_MSG_WARN("Only on NetBSD 2.0 or later.")
+ AC_DEFINE(GC_NETBSD_THREADS)
+ AC_DEFINE(_REENTRANT)
+ AC_DEFINE(_PTHREADS)
+ THREADDLLIBS="-lpthread -lrt"
+ ;;
+ *-*-solaris*)
+ AC_DEFINE(GC_SOLARIS_THREADS)
+ AC_DEFINE(THREAD_LOCAL_ALLOC)
+ THREADDLLIBS="-lpthread -lrt"
+ if test "$GCC" != yes; then
+ CFLAGS="$CFLAGS -O"
+ need_atomic_ops_asm=true
+ fi
+ ;;
+ *-*-irix*)
+ AC_DEFINE(GC_IRIX_THREADS)
+ ;;
+ *-*-cygwin*)
+ AC_DEFINE(GC_WIN32_THREADS)
+ AC_DEFINE(THREAD_LOCAL_ALLOC)
+ win32_threads=true
+ ;;
+ *-*-darwin*)
+ AC_DEFINE(GC_DARWIN_THREADS)
+ AC_DEFINE(THREAD_LOCAL_ALLOC)
+ AC_MSG_WARN("Explict GC_INIT() calls may be required.");
+ if test "${enable_parallel_mark}" = yes; then
+ AC_DEFINE(PARALLEL_MARK)
+ fi
+ darwin_threads=true
+ ;;
+ *-*-osf*)
+ AC_DEFINE(GC_OSF1_THREADS)
+ if test "${enable_parallel_mark}" = yes; then
+ AC_DEFINE(PARALLEL_MARK)
+ AC_DEFINE(THREAD_LOCAL_ALLOC)
+ AC_MSG_WARN("Explict GC_INIT() calls may be required.");
+ # May want to enable it in other cases, too.
+ # Measurements havent yet been done.
+ fi
+ INCLUDES="$INCLUDES -pthread"
+ THREADDLLIBS="-lpthread -lrt"
+ ;;
+ *)
+ AC_MSG_ERROR("Pthreads not supported by the GC on this platform.")
+ ;;
+ esac
+ ;;
+ win32)
+ AC_DEFINE(GC_WIN32_THREADS)
+ dnl Wine getenv may not return NULL for missing entry
+ AC_DEFINE(NO_GETENV)
+ ;;
+ dgux386)
+ THREADS=dgux386
+ AC_MSG_RESULT($THREADDLLIBS)
+ # Use pthread GCC switch
+ THREADDLLIBS=-pthread
+ if test "${enable_parallel_mark}" = yes; then
+ AC_DEFINE(PARALLEL_MARK)
+ fi
+ AC_DEFINE(THREAD_LOCAL_ALLOC)
+ AC_MSG_WARN("Explict GC_INIT() calls may be required.");
+ AC_DEFINE(GC_DGUX386_THREADS)
+ AC_DEFINE(DGUX_THREADS)
+ # Enable _POSIX4A_DRAFT10_SOURCE with flag -pthread
+ INCLUDES="-pthread $INCLUDES"
+ ;;
+ aix)
+ THREADS=posix
+ THREADDLLIBS=-lpthread
+ AC_DEFINE(GC_AIX_THREADS)
+ AC_DEFINE(_REENTRANT)
+ ;;
+ decosf1 | irix | mach | os2 | solaris | dce | vxworks)
+ AC_MSG_ERROR(thread package $THREADS not yet supported)
+ ;;
+ *)
+ AC_MSG_ERROR($THREADS is an unknown thread package)
+ ;;
+esac
+AC_SUBST(THREADDLLIBS)
+AM_CONDITIONAL(THREADS, test x$THREADS != xnone)
+AM_CONDITIONAL(PTHREADS, test x$THREADS = xposix)
+AM_CONDITIONAL(DARWIN_THREADS, test x$darwin_threads = xtrue)
+AM_CONDITIONAL(WIN32_THREADS, test x$win32_threads = xtrue)
+
+case "$host" in
+ powerpc-*-darwin*)
+ powerpc_darwin=true
+ ;;
+esac
+
+# Darwin needs a few extra special tests to deal with variation in the
+# system headers.
+case "$host" in
+ powerpc*-*-darwin*)
+ AC_CHECK_MEMBER(ppc_thread_state_t.r0,
+ AC_DEFINE(HAS_PPC_THREAD_STATE_R0,1,
+ [ppc_thread_state_t has field r0]),,
+ [#include <mach/thread_status.h>])
+ AC_CHECK_MEMBER(ppc_thread_state_t.__r0,
+ AC_DEFINE(HAS_PPC_THREAD_STATE___R0,1,dnl
+ [ppc_thread_state_t has field __r0]),,
+ [#include <mach/thread_status.h>])
+ AC_CHECK_MEMBER(ppc_thread_state64_t.r0,
+ AC_DEFINE(HAS_PPC_THREAD_STATE64_R0,1,dnl
+ [ppc_thread_state64_t has field r0]),,
+ [#include <mach/thread_status.h>])
+ AC_CHECK_MEMBER(ppc_thread_state64_t.__r0,
+ AC_DEFINE(HAS_PPC_THREAD_STATE64___R0,1,dnl
+ [ppc_thread_state64_t has field __r0]),,
+ [#include <mach/thread_status.h>])
+ ;;
+ i?86*-*-darwin*)
+ AC_CHECK_MEMBER(x86_thread_state32_t.eax,
+ AC_DEFINE(HAS_X86_THREAD_STATE32_EAX,1,dnl
+ [x86_thread_state32_t has field eax]),,
+ [#include <sys/cdefs.h>
+ #include <mach/thread_status.h>])
+ AC_CHECK_MEMBER(x86_thread_state32_t.__eax,
+ AC_DEFINE(HAS_X86_THREAD_STATE32___EAX,1,dnl
+ [x86_thread_state32_t has field __eax]),,
+ [#include <sys/cdefs.h>
+ #include <mach/thread_status.h>])
+ ;;
+ x86_64-*-darwin*)
+ AC_CHECK_MEMBER(x86_thread_state64_t.rax,
+ AC_DEFINE(HAS_X86_THREAD_STATE64_RAX,1,dnl
+ [x86_thread_state64_t has field rax]),,
+ [#include <sys/cdefs.h>
+ #include <mach/thread_status.h>])
+ AC_CHECK_MEMBER(x86_thread_state64_t.__rax,
+ AC_DEFINE(HAS_X86_THREAD_STATE64___RAX,1,dnl
+ [x86_thread_state64_t has field __rax]),,
+ [#include <sys/cdefs.h>
+ #include <mach/thread_status.h>])
+ ;;
+ *) ;;
+esac
+
+AC_MSG_CHECKING(for xlc)
+AC_TRY_COMPILE([],[
+ #ifndef __xlC__
+ # error
+ #endif
+], [compiler_xlc=yes], [compiler_xlc=no])
+AC_MSG_RESULT($compiler_xlc)
+AM_CONDITIONAL(COMPILER_XLC,test $compiler_xlc = yes)
+if test $compiler_xlc = yes -a "$powerpc_darwin" = true; then
+ # the darwin stack-frame-walking code is completely broken on xlc
+ AC_DEFINE(DARWIN_DONT_PARSE_STACK)
+fi
+
+# We never want libdl on darwin. It is a fake libdl that just ends up making
+# dyld calls anyway
+case "$host" in
+ *-*-darwin*) ;;
+ *)
+ AC_CHECK_LIB(dl, dlopen, THREADDLLIBS="$THREADDLLIBS -ldl")
+ ;;
+esac
+
+# extra LD Flags which are required for targets
+case "${host}" in
+ *-*-darwin*)
+ extra_ldflags_libgc=-Wl,-single_module
+ ;;
+esac
+AC_SUBST(extra_ldflags_libgc)
+
+AC_SUBST(EXTRA_TEST_LIBS)
+
+target_all=libgc.la
+AC_SUBST(target_all)
+
+dnl If the target is an eCos system, use the appropriate eCos
+dnl I/O routines.
+dnl FIXME: this should not be a local option but a global target
+dnl system; at present there is no eCos target.
+TARGET_ECOS="no"
+AC_ARG_WITH(ecos,
+[ --with-ecos enable runtime eCos target support],
+TARGET_ECOS="$with_ecos"
+)
+
+addobjs=
+addlibs=
+CXXINCLUDES=
+case "$TARGET_ECOS" in
+ no)
+ ;;
+ *)
+ AC_DEFINE(ECOS)
+ CXXINCLUDES="-I${TARGET_ECOS}/include"
+ addobjs="$addobjs ecos.lo"
+ ;;
+esac
+
+AM_CONDITIONAL(CPLUSPLUS, test "${enable_cplusplus}" = yes)
+
+AC_SUBST(CXX)
+
+AC_SUBST(INCLUDES)
+AC_SUBST(CXXINCLUDES)
+
+# Configuration of shared libraries
+#
+AC_MSG_CHECKING(whether to build shared libraries)
+AC_ENABLE_SHARED
+
+case "$host" in
+ alpha-*-openbsd*)
+ enable_shared=no
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ AC_MSG_RESULT(yes)
+ ;;
+esac
+
+# Configuration of machine-dependent code
+#
+AC_MSG_CHECKING(which machine-dependent code should be used)
+machdep=
+case "$host" in
+ alpha-*-openbsd*)
+ machdep="mach_dep.lo"
+ if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then
+ AC_MSG_WARN(OpenBSD/Alpha without dlopen(). Shared library support is disabled)
+ fi
+ ;;
+ alpha*-*-linux*)
+ machdep="mach_dep.lo"
+ ;;
+ i?86-*-solaris2.[[89]] | i?86-*-solaris2.1?)
+ AC_DEFINE(SOLARIS25_PROC_VDB_BUG_FIXED)
+ ;;
+ mipstx39-*-elf*)
+ machdep="mach_dep.lo"
+ AC_DEFINE(STACKBASE, __stackbase)
+ AC_DEFINE(DATASTART_IS_ETEXT)
+ ;;
+ mips-dec-ultrix*)
+ machdep="mach-dep.lo"
+ ;;
+ mips-nec-sysv*|mips-unknown-sysv*)
+ ;;
+ mips*-*-linux*)
+ ;;
+ mips-*-*)
+ machdep="mach_dep.lo"
+ dnl AC_DEFINE(NO_EXECUTE_PERMISSION)
+ dnl This is now redundant, but it is also important for incremental GC
+ dnl performance under Irix.
+ ;;
+ sparc-*-netbsd*)
+ machdep="mach_dep.lo sparc_netbsd_mach_dep.lo"
+ ;;
+ sparc-sun-solaris2.3)
+ machdep="mach_dep.lo sparc_mach_dep.lo"
+ AC_DEFINE(SUNOS53_SHARED_LIB)
+ ;;
+ sparc*-sun-solaris2.*)
+ machdep="mach_dep.lo sparc_mach_dep.lo"
+ ;;
+ ia64-*-*)
+ machdep="mach_dep.lo ia64_save_regs_in_stack.lo"
+ ;;
+esac
+if test x"$machdep" = x; then
+AC_MSG_RESULT($machdep)
+ machdep="mach_dep.lo"
+fi
+addobjs="$addobjs $machdep"
+AC_SUBST(addobjs)
+AC_SUBST(addlibs)
+
+AC_PROG_LIBTOOL
+
+#
+# Check for AViiON Machines running DGUX
+#
+ac_is_dgux=no
+AC_CHECK_HEADER(sys/dg_sys_info.h,
+[ac_is_dgux=yes;])
+
+ ## :GOTCHA: we do not check anything but sys/dg_sys_info.h
+if test $ac_is_dgux = yes; then
+ if test "$enable_full_debug" = "yes"; then
+ CFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
+ CXXFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
+ else
+ CFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
+ CXXFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
+ fi
+ AC_SUBST(CFLAGS)
+ AC_SUBST(CXXFLAGS)
+fi
+
+dnl We use these options to decide which functions to include.
+AC_ARG_WITH(target-subdir,
+[ --with-target-subdir=SUBDIR
+ configuring with a cross compiler])
+AC_ARG_WITH(cross-host,
+[ --with-cross-host=HOST configuring with a cross compiler])
+
+# automake wants to see AC_EXEEXT. But we don't need it. And having
+# it is actually a problem, because the compiler we're passed can't
+# necessarily do a full link. So we fool automake here.
+if false; then
+ # autoconf 2.50 runs AC_EXEEXT by default, and the macro expands
+ # to nothing, so nothing would remain between `then' and `fi' if it
+ # were not for the `:' below.
+ :
+ AC_EXEEXT
+fi
+
+dnl As of 4.13a2, the collector will not properly work on Solaris when
+dnl built with gcc and -O. So we remove -O in the appropriate case.
+dnl Not needed anymore on Solaris.
+AC_MSG_CHECKING(whether Solaris gcc optimization fix is necessary)
+case "$host" in
+ *aix*)
+ if test "$GCC" = yes; then
+ AC_MSG_RESULT(yes)
+ new_CFLAGS=
+ for i in $CFLAGS; do
+ case "$i" in
+ -O*)
+ ;;
+ *)
+ new_CFLAGS="$new_CFLAGS $i"
+ ;;
+ esac
+ done
+ CFLAGS="$new_CFLAGS"
+ else
+ AC_MSG_RESULT(no)
+ fi
+ ;;
+ *) AC_MSG_RESULT(no) ;;
+esac
+
+dnl Include defines that have become de facto standard.
+dnl ALL_INTERIOR_POINTERS can be overridden in startup code.
+AC_DEFINE(NO_EXECUTE_PERMISSION)
+AC_DEFINE(ALL_INTERIOR_POINTERS)
+
+
+dnl Interface Selection
+dnl -------------------
+dnl
+dnl By default, make the library as general as possible.
+dnl enable_gcj_support=no
+AC_ARG_ENABLE(gcj-support,
+ [AC_HELP_STRING([--disable-gcj-support],
+ [Disable support for gcj.])])
+AM_CONDITIONAL(ENABLE_GCJ_SUPPORT,
+ [test x"$enable_gcj_support" != xno])
+if test x"$enable_gcj_support" != xno; then
+ AC_DEFINE(GC_GCJ_SUPPORT, 1, [Define to include support for gcj])
+fi
+
+AC_ARG_ENABLE(java-finalization,
+ [AC_HELP_STRING([--disable-java-finalization],
+ [Disable support for java finalization.])])
+if test x"$enable_java_finalization" != xno; then
+ AC_DEFINE(JAVA_FINALIZATION)
+fi
+
+AC_ARG_ENABLE(atomic-uncollectable,
+ [AC_HELP_STRING([--disable-atomic-uncollectible],
+ [Disable support for atomic uncollectible allocation.])])
+if test x"$enable_atomic_uncollectible" != x"no"; then
+ AC_DEFINE(ATOMIC_UNCOLLECTABLE, 1,
+ [Define to enable atomic uncollectible allocation.])
+fi
+
+AC_ARG_ENABLE(redirect-malloc,
+ [AC_HELP_STRING([--enable-redirect-malloc],
+ [Redirect malloc and friends to GC routines])])
+
+if test "${enable_redirect_malloc}" = yes; then
+ if test "${enable_full_debug}" = yes; then
+ AC_DEFINE(REDIRECT_MALLOC, GC_debug_malloc_replacement)
+ AC_DEFINE(REDIRECT_REALLOC, GC_debug_realloc_replacement)
+ AC_DEFINE(REDIRECT_FREE, GC_debug_free)
+ else
+ AC_DEFINE(REDIRECT_MALLOC, GC_malloc)
+ fi
+fi
+
+AC_ARG_ENABLE(large-config,
+ [AC_HELP_STRING([--enable-large-config],
+ [Optimize for large (> 100 MB) heap or root set])])
+
+if test "${enable_large_config}" = yes; then
+ AC_DEFINE(LARGE_CONFIG, 1, [Define to optimize for large heaps or root sets])
+fi
+
+dnl This is something of a hack. When cross-compiling we turn off
+dnl some functionality. We also enable the "small" configuration.
+dnl These is only correct when targetting an embedded system. FIXME.
+if test -n "${with_cross_host}"; then
+ AC_DEFINE(NO_CLOCK)
+ AC_DEFINE(SMALL_CONFIG)
+ AC_DEFINE(NO_DEBUGGING)
+fi
+
+
+dnl Debugging
+dnl ---------
+
+UNWINDLIBS=
+AC_ARG_ENABLE(gc-debug,
+[AC_HELP_STRING([--enable-gc-debug],
+ [include full support for pointer backtracing etc.])],
+[ if test "$enable_gc_debug" = "yes"; then
+ AC_MSG_WARN("Should define GC_DEBUG and use debug alloc. in clients.")
+ AC_DEFINE(KEEP_BACK_PTRS)
+ AC_DEFINE(DBG_HDRS_ALL)
+ case $host in
+ ia64-*-linux* )
+ AC_DEFINE(MAKE_BACK_GRAPH)
+ AC_DEFINE(SAVE_CALL_COUNT, 8)
+ AC_CHECK_LIB(unwind, backtrace, [
+ AC_DEFINE(GC_HAVE_BUILTIN_BACKTRACE)
+ UNWINDLIBS=-lunwind
+ AC_MSG_WARN("Client code may need to link against libunwind.")
+ ])
+ ;;
+ x86-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* )
+ AC_DEFINE(MAKE_BACK_GRAPH)
+ AC_MSG_WARN("Client must not use -fomit-frame-pointer.")
+ AC_DEFINE(SAVE_CALL_COUNT, 8)
+ ;;
+ i[3456]86-*-dgux*)
+ AC_DEFINE(MAKE_BACK_GRAPH)
+ ;;
+ esac ]
+ fi)
+
+AC_SUBST(UNWINDLIBS)
+
+AC_ARG_ENABLE(gc-assertions,
+ [AC_HELP_STRING([--enable-gc-assertions],
+ [collector-internal assertion checking])])
+if test "${enable_gc_assertions}" = yes; then
+ AC_DEFINE(GC_ASSERTIONS)
+fi
+
+AM_CONDITIONAL(USE_LIBDIR, test -z "$with_cross_host")
+
+
+dnl Atomic Ops
+dnl ----------
+
+atomic_ops_libs=-latomic_ops
+AC_CHECK_HEADER(atomic_ops.h,
+ [ AC_MSG_NOTICE([Using pre-installed libatomic_ops]) ],
+ [ ao_dir=
+ for candidate in ${srcdir}/libatomic_ops*; do
+ case $candidate in
+ *.tar.gz)
+ ;;
+ *install)
+ dnl generated by alternate Makefile.
+ ;;
+ *)
+ if test -e "$candidate"; then
+ ao_dir="$candidate"
+ fi
+ ;;
+ esac
+ done
+ if test -z "$ao_dir"; then
+ AC_MSG_ERROR([Missig libatomic_ops.])
+ fi
+ ao_version="${ao_dir#*libatomic_ops-}"
+ AC_MSG_NOTICE([Using internal version of libatomic_ops])
+
+ dnl Automake does not accept shell variables in AC_CONFIG_SUBDIRS
+ test -e ${srcdir}/libatomic_ops \
+ || ln -s ${ao_dir} ${srcdir}/libatomic_ops
+ AC_CONFIG_SUBDIRS(libatomic_ops)
+
+ dnl Also copy the source files to be linked in.
+ test -e ${srcdir}/atomic_ops.c \
+ || ln -s ${srcdir}/libatomic_ops/src/atomic_ops.c \
+ ${srcdir}/atomic_ops.c
+
+ test -e ${srcdir}/atomic_ops_sysdeps.S \
+ || ln -s ${srcdir}/libatomic_ops/src/atomic_ops_sysdeps.S \
+ ${srcdir}/atomic_ops_sysdeps.S
+
+ dnl This gets the source include files, which is often close enough.
+ dnl It also makes atomic_ops_sysdeps.S assemble.
+ GC_CFLAGS="${GC_CFLAGS} -I \$(top_srcdir)/libatomic_ops/src"
+ maybe_libatomic_ops="libatomic_ops"
+ ])
+
+AM_CONDITIONAL(USE_INTERNAL_LIBATOMIC_OPS,
+ test -n "$maybe_libatomic_ops" -a "$THREADS" != "none")
+AM_CONDITIONAL(NEED_ATOMIC_OPS_ASM, test -n "$maybe_libatomic_ops" -a x$need_atomic_ops_asm = xtrue)
+AC_SUBST(atomic_ops_libs)
+
+dnl Produce the Files
+dnl -----------------
+
+AC_CONFIG_FILES([Makefile bdw-gc.pc])
+
+AC_CONFIG_COMMANDS([default],,
+ [ srcdir=${srcdir}
+ host=${host}
+ CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ CC="${CC}"
+ DEFS="$DEFS" ])
+
+AC_OUTPUT
diff --git a/tools/build/v2/engine/boehm_gc/configure.host b/tools/build/v2/engine/boehm_gc/configure.host
new file mode 100644
index 0000000000..a98a0a7cb3
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/configure.host
@@ -0,0 +1,61 @@
+# configure.host
+
+# This shell script handles all host based configuration for the garbage
+# collector.
+# It sets various shell variables based on the the host and the
+# configuration options. You can modify this shell script without
+# needing to rerun autoconf.
+
+# This shell script should be invoked as
+# . configure.host
+# If it encounters an error, it will exit with a message.
+
+# It uses the following shell variables:
+# host The configuration host
+# host_cpu The configuration host CPU
+# target_optspace --enable-target-optspace ("yes", "no", "")
+# GCC should be "yes" if using gcc
+
+# It sets the following shell variables:
+# gc_cflags Special CFLAGS to use when building
+
+gc_cflags=""
+
+# We should set -fexceptions if we are using gcc and might be used
+# inside something like gcj. This is the zeroth approximation:
+if test :"$GCC": = :yes: ; then
+ gc_cflags="${gc_cflags} -fexceptions"
+else
+ case "$host" in
+ hppa*-*-hpux* )
+ if test :$GCC: != :"yes": ; then
+ gc_cflags="${gc_flags} +ESdbgasm"
+ fi
+ # :TODO: actaully we should check using Autoconf if
+ # the compiler supports this option.
+ ;;
+ esac
+fi
+
+case "${target_optspace}:${host}" in
+ yes:*)
+ gc_cflags="${gc_cflags} -Os"
+ ;;
+ :m32r-* | :d10v-* | :d30v-*)
+ gc_cflags="${gc_cflags} -Os"
+ ;;
+ no:* | :*)
+ # Nothing.
+ ;;
+esac
+
+# Set any host dependent compiler flags.
+# THIS TABLE IS SORTED. KEEP IT THAT WAY.
+
+case "${host}" in
+ mips-tx39-*|mipstx39-unknown-*)
+ gc_cflags="${gc_cflags} -G 0"
+ ;;
+ *)
+ ;;
+esac
diff --git a/tools/build/v2/engine/boehm_gc/configure_atomic_ops.sh b/tools/build/v2/engine/boehm_gc/configure_atomic_ops.sh
new file mode 100755
index 0000000000..6a0e31a710
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/configure_atomic_ops.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+P=`pwd`/libatomic_ops-install
+cd libatomic_ops-*[0-9]
+./configure --prefix=$P
diff --git a/tools/build/v2/engine/boehm_gc/cord/cord.am b/tools/build/v2/engine/boehm_gc/cord/cord.am
new file mode 100644
index 0000000000..fc5e8cc203
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/cord/cord.am
@@ -0,0 +1,17 @@
+
+lib_LTLIBRARIES += libcord.la
+
+libcord_la_LIBADD = $(top_builddir)/libgc.la
+libcord_la_LDFLAGS = -version-info 1:3:0 -no-undefined
+
+libcord_la_SOURCES = \
+ cord/cordbscs.c \
+ cord/cordprnt.c \
+ cord/cordtest.c \
+ cord/cordxtra.c
+
+
+EXTRA_DIST += \
+ cord/cordbscs.c cord/cordtest.c cord/de.c \
+ cord/cordprnt.c cord/cordxtra.c cord/de_cmds.h \
+ cord/de_win.h cord/de_win.c cord/de_win.RC cord/de_win.ICO
diff --git a/tools/build/v2/engine/boehm_gc/cord/cordbscs.c b/tools/build/v2/engine/boehm_gc/cord/cordbscs.c
new file mode 100644
index 0000000000..d83f4067de
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/cord/cordbscs.c
@@ -0,0 +1,919 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ * Author: Hans-J. Boehm (boehm@parc.xerox.com)
+ */
+/* Boehm, October 3, 1994 5:19 pm PDT */
+# include "gc.h"
+# include "cord.h"
+# include <stdlib.h>
+# include <stdio.h>
+# include <string.h>
+
+/* An implementation of the cord primitives. These are the only */
+/* Functions that understand the representation. We perform only */
+/* minimal checks on arguments to these functions. Out of bounds */
+/* arguments to the iteration functions may result in client functions */
+/* invoked on garbage data. In most cases, client functions should be */
+/* programmed defensively enough that this does not result in memory */
+/* smashes. */
+
+typedef void (* oom_fn)(void);
+
+oom_fn CORD_oom_fn = (oom_fn) 0;
+
+# define OUT_OF_MEMORY { if (CORD_oom_fn != (oom_fn) 0) (*CORD_oom_fn)(); \
+ ABORT("Out of memory\n"); }
+# define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); }
+
+typedef unsigned long word;
+
+typedef union {
+ struct Concatenation {
+ char null;
+ char header;
+ char depth; /* concatenation nesting depth. */
+ unsigned char left_len;
+ /* Length of left child if it is sufficiently */
+ /* short; 0 otherwise. */
+# define MAX_LEFT_LEN 255
+ word len;
+ CORD left; /* length(left) > 0 */
+ CORD right; /* length(right) > 0 */
+ } concatenation;
+ struct Function {
+ char null;
+ char header;
+ char depth; /* always 0 */
+ char left_len; /* always 0 */
+ word len;
+ CORD_fn fn;
+ void * client_data;
+ } function;
+ struct Generic {
+ char null;
+ char header;
+ char depth;
+ char left_len;
+ word len;
+ } generic;
+ char string[1];
+} CordRep;
+
+# define CONCAT_HDR 1
+
+# define FN_HDR 4
+# define SUBSTR_HDR 6
+ /* Substring nodes are a special case of function nodes. */
+ /* The client_data field is known to point to a substr_args */
+ /* structure, and the function is either CORD_apply_access_fn */
+ /* or CORD_index_access_fn. */
+
+/* The following may be applied only to function and concatenation nodes: */
+#define IS_CONCATENATION(s) (((CordRep *)s)->generic.header == CONCAT_HDR)
+
+#define IS_FUNCTION(s) ((((CordRep *)s)->generic.header & FN_HDR) != 0)
+
+#define IS_SUBSTR(s) (((CordRep *)s)->generic.header == SUBSTR_HDR)
+
+#define LEN(s) (((CordRep *)s) -> generic.len)
+#define DEPTH(s) (((CordRep *)s) -> generic.depth)
+#define GEN_LEN(s) (CORD_IS_STRING(s) ? strlen(s) : LEN(s))
+
+#define LEFT_LEN(c) ((c) -> left_len != 0? \
+ (c) -> left_len \
+ : (CORD_IS_STRING((c) -> left) ? \
+ (c) -> len - GEN_LEN((c) -> right) \
+ : LEN((c) -> left)))
+
+#define SHORT_LIMIT (sizeof(CordRep) - 1)
+ /* Cords shorter than this are C strings */
+
+
+/* Dump the internal representation of x to stdout, with initial */
+/* indentation level n. */
+void CORD_dump_inner(CORD x, unsigned n)
+{
+ register size_t i;
+
+ for (i = 0; i < (size_t)n; i++) {
+ fputs(" ", stdout);
+ }
+ if (x == 0) {
+ fputs("NIL\n", stdout);
+ } else if (CORD_IS_STRING(x)) {
+ for (i = 0; i <= SHORT_LIMIT; i++) {
+ if (x[i] == '\0') break;
+ putchar(x[i]);
+ }
+ if (x[i] != '\0') fputs("...", stdout);
+ putchar('\n');
+ } else if (IS_CONCATENATION(x)) {
+ register struct Concatenation * conc =
+ &(((CordRep *)x) -> concatenation);
+ printf("Concatenation: %p (len: %d, depth: %d)\n",
+ x, (int)(conc -> len), (int)(conc -> depth));
+ CORD_dump_inner(conc -> left, n+1);
+ CORD_dump_inner(conc -> right, n+1);
+ } else /* function */{
+ register struct Function * func =
+ &(((CordRep *)x) -> function);
+ if (IS_SUBSTR(x)) printf("(Substring) ");
+ printf("Function: %p (len: %d): ", x, (int)(func -> len));
+ for (i = 0; i < 20 && i < func -> len; i++) {
+ putchar((*(func -> fn))(i, func -> client_data));
+ }
+ if (i < func -> len) fputs("...", stdout);
+ putchar('\n');
+ }
+}
+
+/* Dump the internal representation of x to stdout */
+void CORD_dump(CORD x)
+{
+ CORD_dump_inner(x, 0);
+ fflush(stdout);
+}
+
+CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
+{
+ register size_t result_len;
+ register size_t lenx;
+ register int depth;
+
+ if (x == CORD_EMPTY) return(y);
+ if (leny == 0) return(x);
+ if (CORD_IS_STRING(x)) {
+ lenx = strlen(x);
+ result_len = lenx + leny;
+ if (result_len <= SHORT_LIMIT) {
+ register char * result = GC_MALLOC_ATOMIC(result_len+1);
+
+ if (result == 0) OUT_OF_MEMORY;
+ memcpy(result, x, lenx);
+ memcpy(result + lenx, y, leny);
+ result[result_len] = '\0';
+ return((CORD) result);
+ } else {
+ depth = 1;
+ }
+ } else {
+ register CORD right;
+ register CORD left;
+ register char * new_right;
+ register size_t right_len;
+
+ lenx = LEN(x);
+
+ if (leny <= SHORT_LIMIT/2
+ && IS_CONCATENATION(x)
+ && CORD_IS_STRING(right = ((CordRep *)x) -> concatenation.right)) {
+ /* Merge y into right part of x. */
+ if (!CORD_IS_STRING(left = ((CordRep *)x) -> concatenation.left)) {
+ right_len = lenx - LEN(left);
+ } else if (((CordRep *)x) -> concatenation.left_len != 0) {
+ right_len = lenx - ((CordRep *)x) -> concatenation.left_len;
+ } else {
+ right_len = strlen(right);
+ }
+ result_len = right_len + leny; /* length of new_right */
+ if (result_len <= SHORT_LIMIT) {
+ new_right = GC_MALLOC_ATOMIC(result_len + 1);
+ memcpy(new_right, right, right_len);
+ memcpy(new_right + right_len, y, leny);
+ new_right[result_len] = '\0';
+ y = new_right;
+ leny = result_len;
+ x = left;
+ lenx -= right_len;
+ /* Now fall through to concatenate the two pieces: */
+ }
+ if (CORD_IS_STRING(x)) {
+ depth = 1;
+ } else {
+ depth = DEPTH(x) + 1;
+ }
+ } else {
+ depth = DEPTH(x) + 1;
+ }
+ result_len = lenx + leny;
+ }
+ {
+ /* The general case; lenx, result_len is known: */
+ register struct Concatenation * result;
+
+ result = GC_NEW(struct Concatenation);
+ if (result == 0) OUT_OF_MEMORY;
+ result->header = CONCAT_HDR;
+ result->depth = depth;
+ if (lenx <= MAX_LEFT_LEN) result->left_len = lenx;
+ result->len = result_len;
+ result->left = x;
+ result->right = y;
+ if (depth >= MAX_DEPTH) {
+ return(CORD_balance((CORD)result));
+ } else {
+ return((CORD) result);
+ }
+ }
+}
+
+
+CORD CORD_cat(CORD x, CORD y)
+{
+ register size_t result_len;
+ register int depth;
+ register size_t lenx;
+
+ if (x == CORD_EMPTY) return(y);
+ if (y == CORD_EMPTY) return(x);
+ if (CORD_IS_STRING(y)) {
+ return(CORD_cat_char_star(x, y, strlen(y)));
+ } else if (CORD_IS_STRING(x)) {
+ lenx = strlen(x);
+ depth = DEPTH(y) + 1;
+ } else {
+ register int depthy = DEPTH(y);
+
+ lenx = LEN(x);
+ depth = DEPTH(x) + 1;
+ if (depthy >= depth) depth = depthy + 1;
+ }
+ result_len = lenx + LEN(y);
+ {
+ register struct Concatenation * result;
+
+ result = GC_NEW(struct Concatenation);
+ if (result == 0) OUT_OF_MEMORY;
+ result->header = CONCAT_HDR;
+ result->depth = depth;
+ if (lenx <= MAX_LEFT_LEN) result->left_len = lenx;
+ result->len = result_len;
+ result->left = x;
+ result->right = y;
+ if (depth >= MAX_DEPTH) {
+ return(CORD_balance((CORD)result));
+ } else {
+ return((CORD) result);
+ }
+ }
+}
+
+
+
+CORD CORD_from_fn(CORD_fn fn, void * client_data, size_t len)
+{
+ if (len <= 0) return(0);
+ if (len <= SHORT_LIMIT) {
+ register char * result;
+ register size_t i;
+ char buf[SHORT_LIMIT+1];
+ register char c;
+
+ for (i = 0; i < len; i++) {
+ c = (*fn)(i, client_data);
+ if (c == '\0') goto gen_case;
+ buf[i] = c;
+ }
+ buf[i] = '\0';
+ result = GC_MALLOC_ATOMIC(len+1);
+ if (result == 0) OUT_OF_MEMORY;
+ strcpy(result, buf);
+ result[len] = '\0';
+ return((CORD) result);
+ }
+ gen_case:
+ {
+ register struct Function * result;
+
+ result = GC_NEW(struct Function);
+ if (result == 0) OUT_OF_MEMORY;
+ result->header = FN_HDR;
+ /* depth is already 0 */
+ result->len = len;
+ result->fn = fn;
+ result->client_data = client_data;
+ return((CORD) result);
+ }
+}
+
+size_t CORD_len(CORD x)
+{
+ if (x == 0) {
+ return(0);
+ } else {
+ return(GEN_LEN(x));
+ }
+}
+
+struct substr_args {
+ CordRep * sa_cord;
+ size_t sa_index;
+};
+
+char CORD_index_access_fn(size_t i, void * client_data)
+{
+ register struct substr_args *descr = (struct substr_args *)client_data;
+
+ return(((char *)(descr->sa_cord))[i + descr->sa_index]);
+}
+
+char CORD_apply_access_fn(size_t i, void * client_data)
+{
+ register struct substr_args *descr = (struct substr_args *)client_data;
+ register struct Function * fn_cord = &(descr->sa_cord->function);
+
+ return((*(fn_cord->fn))(i + descr->sa_index, fn_cord->client_data));
+}
+
+/* A version of CORD_substr that simply returns a function node, thus */
+/* postponing its work. The fourth argument is a function that may */
+/* be used for efficient access to the ith character. */
+/* Assumes i >= 0 and i + n < length(x). */
+CORD CORD_substr_closure(CORD x, size_t i, size_t n, CORD_fn f)
+{
+ register struct substr_args * sa = GC_NEW(struct substr_args);
+ CORD result;
+
+ if (sa == 0) OUT_OF_MEMORY;
+ sa->sa_cord = (CordRep *)x;
+ sa->sa_index = i;
+ result = CORD_from_fn(f, (void *)sa, n);
+ ((CordRep *)result) -> function.header = SUBSTR_HDR;
+ return (result);
+}
+
+# define SUBSTR_LIMIT (10 * SHORT_LIMIT)
+ /* Substrings of function nodes and flat strings shorter than */
+ /* this are flat strings. Othewise we use a functional */
+ /* representation, which is significantly slower to access. */
+
+/* A version of CORD_substr that assumes i >= 0, n > 0, and i + n < length(x).*/
+CORD CORD_substr_checked(CORD x, size_t i, size_t n)
+{
+ if (CORD_IS_STRING(x)) {
+ if (n > SUBSTR_LIMIT) {
+ return(CORD_substr_closure(x, i, n, CORD_index_access_fn));
+ } else {
+ register char * result = GC_MALLOC_ATOMIC(n+1);
+
+ if (result == 0) OUT_OF_MEMORY;
+ strncpy(result, x+i, n);
+ result[n] = '\0';
+ return(result);
+ }
+ } else if (IS_CONCATENATION(x)) {
+ register struct Concatenation * conc
+ = &(((CordRep *)x) -> concatenation);
+ register size_t left_len;
+ register size_t right_len;
+
+ left_len = LEFT_LEN(conc);
+ right_len = conc -> len - left_len;
+ if (i >= left_len) {
+ if (n == right_len) return(conc -> right);
+ return(CORD_substr_checked(conc -> right, i - left_len, n));
+ } else if (i+n <= left_len) {
+ if (n == left_len) return(conc -> left);
+ return(CORD_substr_checked(conc -> left, i, n));
+ } else {
+ /* Need at least one character from each side. */
+ register CORD left_part;
+ register CORD right_part;
+ register size_t left_part_len = left_len - i;
+
+ if (i == 0) {
+ left_part = conc -> left;
+ } else {
+ left_part = CORD_substr_checked(conc -> left, i, left_part_len);
+ }
+ if (i + n == right_len + left_len) {
+ right_part = conc -> right;
+ } else {
+ right_part = CORD_substr_checked(conc -> right, 0,
+ n - left_part_len);
+ }
+ return(CORD_cat(left_part, right_part));
+ }
+ } else /* function */ {
+ if (n > SUBSTR_LIMIT) {
+ if (IS_SUBSTR(x)) {
+ /* Avoid nesting substring nodes. */
+ register struct Function * f = &(((CordRep *)x) -> function);
+ register struct substr_args *descr =
+ (struct substr_args *)(f -> client_data);
+
+ return(CORD_substr_closure((CORD)descr->sa_cord,
+ i + descr->sa_index,
+ n, f -> fn));
+ } else {
+ return(CORD_substr_closure(x, i, n, CORD_apply_access_fn));
+ }
+ } else {
+ char * result;
+ register struct Function * f = &(((CordRep *)x) -> function);
+ char buf[SUBSTR_LIMIT+1];
+ register char * p = buf;
+ register char c;
+ register int j;
+ register int lim = i + n;
+
+ for (j = i; j < lim; j++) {
+ c = (*(f -> fn))(j, f -> client_data);
+ if (c == '\0') {
+ return(CORD_substr_closure(x, i, n, CORD_apply_access_fn));
+ }
+ *p++ = c;
+ }
+ *p = '\0';
+ result = GC_MALLOC_ATOMIC(n+1);
+ if (result == 0) OUT_OF_MEMORY;
+ strcpy(result, buf);
+ return(result);
+ }
+ }
+}
+
+CORD CORD_substr(CORD x, size_t i, size_t n)
+{
+ register size_t len = CORD_len(x);
+
+ if (i >= len || n <= 0) return(0);
+ /* n < 0 is impossible in a correct C implementation, but */
+ /* quite possible under SunOS 4.X. */
+ if (i + n > len) n = len - i;
+# ifndef __STDC__
+ if (i < 0) ABORT("CORD_substr: second arg. negative");
+ /* Possible only if both client and C implementation are buggy. */
+ /* But empirically this happens frequently. */
+# endif
+ return(CORD_substr_checked(x, i, n));
+}
+
+/* See cord.h for definition. We assume i is in range. */
+int CORD_iter5(CORD x, size_t i, CORD_iter_fn f1,
+ CORD_batched_iter_fn f2, void * client_data)
+{
+ if (x == 0) return(0);
+ if (CORD_IS_STRING(x)) {
+ register const char *p = x+i;
+
+ if (*p == '\0') ABORT("2nd arg to CORD_iter5 too big");
+ if (f2 != CORD_NO_FN) {
+ return((*f2)(p, client_data));
+ } else {
+ while (*p) {
+ if ((*f1)(*p, client_data)) return(1);
+ p++;
+ }
+ return(0);
+ }
+ } else if (IS_CONCATENATION(x)) {
+ register struct Concatenation * conc
+ = &(((CordRep *)x) -> concatenation);
+
+
+ if (i > 0) {
+ register size_t left_len = LEFT_LEN(conc);
+
+ if (i >= left_len) {
+ return(CORD_iter5(conc -> right, i - left_len, f1, f2,
+ client_data));
+ }
+ }
+ if (CORD_iter5(conc -> left, i, f1, f2, client_data)) {
+ return(1);
+ }
+ return(CORD_iter5(conc -> right, 0, f1, f2, client_data));
+ } else /* function */ {
+ register struct Function * f = &(((CordRep *)x) -> function);
+ register size_t j;
+ register size_t lim = f -> len;
+
+ for (j = i; j < lim; j++) {
+ if ((*f1)((*(f -> fn))(j, f -> client_data), client_data)) {
+ return(1);
+ }
+ }
+ return(0);
+ }
+}
+
+#undef CORD_iter
+int CORD_iter(CORD x, CORD_iter_fn f1, void * client_data)
+{
+ return(CORD_iter5(x, 0, f1, CORD_NO_FN, client_data));
+}
+
+int CORD_riter4(CORD x, size_t i, CORD_iter_fn f1, void * client_data)
+{
+ if (x == 0) return(0);
+ if (CORD_IS_STRING(x)) {
+ register const char *p = x + i;
+ register char c;
+
+ for(;;) {
+ c = *p;
+ if (c == '\0') ABORT("2nd arg to CORD_riter4 too big");
+ if ((*f1)(c, client_data)) return(1);
+ if (p == x) break;
+ p--;
+ }
+ return(0);
+ } else if (IS_CONCATENATION(x)) {
+ register struct Concatenation * conc
+ = &(((CordRep *)x) -> concatenation);
+ register CORD left_part = conc -> left;
+ register size_t left_len;
+
+ left_len = LEFT_LEN(conc);
+ if (i >= left_len) {
+ if (CORD_riter4(conc -> right, i - left_len, f1, client_data)) {
+ return(1);
+ }
+ return(CORD_riter4(left_part, left_len - 1, f1, client_data));
+ } else {
+ return(CORD_riter4(left_part, i, f1, client_data));
+ }
+ } else /* function */ {
+ register struct Function * f = &(((CordRep *)x) -> function);
+ register size_t j;
+
+ for (j = i; ; j--) {
+ if ((*f1)((*(f -> fn))(j, f -> client_data), client_data)) {
+ return(1);
+ }
+ if (j == 0) return(0);
+ }
+ }
+}
+
+int CORD_riter(CORD x, CORD_iter_fn f1, void * client_data)
+{
+ return(CORD_riter4(x, CORD_len(x) - 1, f1, client_data));
+}
+
+/*
+ * The following functions are concerned with balancing cords.
+ * Strategy:
+ * Scan the cord from left to right, keeping the cord scanned so far
+ * as a forest of balanced trees of exponentialy decreasing length.
+ * When a new subtree needs to be added to the forest, we concatenate all
+ * shorter ones to the new tree in the appropriate order, and then insert
+ * the result into the forest.
+ * Crucial invariants:
+ * 1. The concatenation of the forest (in decreasing order) with the
+ * unscanned part of the rope is equal to the rope being balanced.
+ * 2. All trees in the forest are balanced.
+ * 3. forest[i] has depth at most i.
+ */
+
+typedef struct {
+ CORD c;
+ size_t len; /* Actual length of c */
+} ForestElement;
+
+static size_t min_len [ MAX_DEPTH ];
+
+static int min_len_init = 0;
+
+int CORD_max_len;
+
+typedef ForestElement Forest [ MAX_DEPTH ];
+ /* forest[i].len >= fib(i+1) */
+ /* The string is the concatenation */
+ /* of the forest in order of DECREASING */
+ /* indices. */
+
+void CORD_init_min_len()
+{
+ register int i;
+ register size_t last, previous, current;
+
+ min_len[0] = previous = 1;
+ min_len[1] = last = 2;
+ for (i = 2; i < MAX_DEPTH; i++) {
+ current = last + previous;
+ if (current < last) /* overflow */ current = last;
+ min_len[i] = current;
+ previous = last;
+ last = current;
+ }
+ CORD_max_len = last - 1;
+ min_len_init = 1;
+}
+
+
+void CORD_init_forest(ForestElement * forest, size_t max_len)
+{
+ register int i;
+
+ for (i = 0; i < MAX_DEPTH; i++) {
+ forest[i].c = 0;
+ if (min_len[i] > max_len) return;
+ }
+ ABORT("Cord too long");
+}
+
+/* Add a leaf to the appropriate level in the forest, cleaning */
+/* out lower levels as necessary. */
+/* Also works if x is a balanced tree of concatenations; however */
+/* in this case an extra concatenation node may be inserted above x; */
+/* This node should not be counted in the statement of the invariants. */
+void CORD_add_forest(ForestElement * forest, CORD x, size_t len)
+{
+ register int i = 0;
+ register CORD sum = CORD_EMPTY;
+ register size_t sum_len = 0;
+
+ while (len > min_len[i + 1]) {
+ if (forest[i].c != 0) {
+ sum = CORD_cat(forest[i].c, sum);
+ sum_len += forest[i].len;
+ forest[i].c = 0;
+ }
+ i++;
+ }
+ /* Sum has depth at most 1 greter than what would be required */
+ /* for balance. */
+ sum = CORD_cat(sum, x);
+ sum_len += len;
+ /* If x was a leaf, then sum is now balanced. To see this */
+ /* consider the two cases in which forest[i-1] either is or is */
+ /* not empty. */
+ while (sum_len >= min_len[i]) {
+ if (forest[i].c != 0) {
+ sum = CORD_cat(forest[i].c, sum);
+ sum_len += forest[i].len;
+ /* This is again balanced, since sum was balanced, and has */
+ /* allowable depth that differs from i by at most 1. */
+ forest[i].c = 0;
+ }
+ i++;
+ }
+ i--;
+ forest[i].c = sum;
+ forest[i].len = sum_len;
+}
+
+CORD CORD_concat_forest(ForestElement * forest, size_t expected_len)
+{
+ register int i = 0;
+ CORD sum = 0;
+ size_t sum_len = 0;
+
+ while (sum_len != expected_len) {
+ if (forest[i].c != 0) {
+ sum = CORD_cat(forest[i].c, sum);
+ sum_len += forest[i].len;
+ }
+ i++;
+ }
+ return(sum);
+}
+
+/* Insert the frontier of x into forest. Balanced subtrees are */
+/* treated as leaves. This potentially adds one to the depth */
+/* of the final tree. */
+void CORD_balance_insert(CORD x, size_t len, ForestElement * forest)
+{
+ register int depth;
+
+ if (CORD_IS_STRING(x)) {
+ CORD_add_forest(forest, x, len);
+ } else if (IS_CONCATENATION(x)
+ && ((depth = DEPTH(x)) >= MAX_DEPTH
+ || len < min_len[depth])) {
+ register struct Concatenation * conc
+ = &(((CordRep *)x) -> concatenation);
+ size_t left_len = LEFT_LEN(conc);
+
+ CORD_balance_insert(conc -> left, left_len, forest);
+ CORD_balance_insert(conc -> right, len - left_len, forest);
+ } else /* function or balanced */ {
+ CORD_add_forest(forest, x, len);
+ }
+}
+
+
+CORD CORD_balance(CORD x)
+{
+ Forest forest;
+ register size_t len;
+
+ if (x == 0) return(0);
+ if (CORD_IS_STRING(x)) return(x);
+ if (!min_len_init) CORD_init_min_len();
+ len = LEN(x);
+ CORD_init_forest(forest, len);
+ CORD_balance_insert(x, len, forest);
+ return(CORD_concat_forest(forest, len));
+}
+
+
+/* Position primitives */
+
+/* Private routines to deal with the hard cases only: */
+
+/* P contains a prefix of the path to cur_pos. Extend it to a full */
+/* path and set up leaf info. */
+/* Return 0 if past the end of cord, 1 o.w. */
+void CORD__extend_path(register CORD_pos p)
+{
+ register struct CORD_pe * current_pe = &(p[0].path[p[0].path_len]);
+ register CORD top = current_pe -> pe_cord;
+ register size_t pos = p[0].cur_pos;
+ register size_t top_pos = current_pe -> pe_start_pos;
+ register size_t top_len = GEN_LEN(top);
+
+ /* Fill in the rest of the path. */
+ while(!CORD_IS_STRING(top) && IS_CONCATENATION(top)) {
+ register struct Concatenation * conc =
+ &(((CordRep *)top) -> concatenation);
+ register size_t left_len;
+
+ left_len = LEFT_LEN(conc);
+ current_pe++;
+ if (pos >= top_pos + left_len) {
+ current_pe -> pe_cord = top = conc -> right;
+ current_pe -> pe_start_pos = top_pos = top_pos + left_len;
+ top_len -= left_len;
+ } else {
+ current_pe -> pe_cord = top = conc -> left;
+ current_pe -> pe_start_pos = top_pos;
+ top_len = left_len;
+ }
+ p[0].path_len++;
+ }
+ /* Fill in leaf description for fast access. */
+ if (CORD_IS_STRING(top)) {
+ p[0].cur_leaf = top;
+ p[0].cur_start = top_pos;
+ p[0].cur_end = top_pos + top_len;
+ } else {
+ p[0].cur_end = 0;
+ }
+ if (pos >= top_pos + top_len) p[0].path_len = CORD_POS_INVALID;
+}
+
+char CORD__pos_fetch(register CORD_pos p)
+{
+ /* Leaf is a function node */
+ struct CORD_pe * pe = &((p)[0].path[(p)[0].path_len]);
+ CORD leaf = pe -> pe_cord;
+ register struct Function * f = &(((CordRep *)leaf) -> function);
+
+ if (!IS_FUNCTION(leaf)) ABORT("CORD_pos_fetch: bad leaf");
+ return ((*(f -> fn))(p[0].cur_pos - pe -> pe_start_pos, f -> client_data));
+}
+
+void CORD__next(register CORD_pos p)
+{
+ register size_t cur_pos = p[0].cur_pos + 1;
+ register struct CORD_pe * current_pe = &((p)[0].path[(p)[0].path_len]);
+ register CORD leaf = current_pe -> pe_cord;
+
+ /* Leaf is not a string or we're at end of leaf */
+ p[0].cur_pos = cur_pos;
+ if (!CORD_IS_STRING(leaf)) {
+ /* Function leaf */
+ register struct Function * f = &(((CordRep *)leaf) -> function);
+ register size_t start_pos = current_pe -> pe_start_pos;
+ register size_t end_pos = start_pos + f -> len;
+
+ if (cur_pos < end_pos) {
+ /* Fill cache and return. */
+ register size_t i;
+ register size_t limit = cur_pos + FUNCTION_BUF_SZ;
+ register CORD_fn fn = f -> fn;
+ register void * client_data = f -> client_data;
+
+ if (limit > end_pos) {
+ limit = end_pos;
+ }
+ for (i = cur_pos; i < limit; i++) {
+ p[0].function_buf[i - cur_pos] =
+ (*fn)(i - start_pos, client_data);
+ }
+ p[0].cur_start = cur_pos;
+ p[0].cur_leaf = p[0].function_buf;
+ p[0].cur_end = limit;
+ return;
+ }
+ }
+ /* End of leaf */
+ /* Pop the stack until we find two concatenation nodes with the */
+ /* same start position: this implies we were in left part. */
+ {
+ while (p[0].path_len > 0
+ && current_pe[0].pe_start_pos != current_pe[-1].pe_start_pos) {
+ p[0].path_len--;
+ current_pe--;
+ }
+ if (p[0].path_len == 0) {
+ p[0].path_len = CORD_POS_INVALID;
+ return;
+ }
+ }
+ p[0].path_len--;
+ CORD__extend_path(p);
+}
+
+void CORD__prev(register CORD_pos p)
+{
+ register struct CORD_pe * pe = &(p[0].path[p[0].path_len]);
+
+ if (p[0].cur_pos == 0) {
+ p[0].path_len = CORD_POS_INVALID;
+ return;
+ }
+ p[0].cur_pos--;
+ if (p[0].cur_pos >= pe -> pe_start_pos) return;
+
+ /* Beginning of leaf */
+
+ /* Pop the stack until we find two concatenation nodes with the */
+ /* different start position: this implies we were in right part. */
+ {
+ register struct CORD_pe * current_pe = &((p)[0].path[(p)[0].path_len]);
+
+ while (p[0].path_len > 0
+ && current_pe[0].pe_start_pos == current_pe[-1].pe_start_pos) {
+ p[0].path_len--;
+ current_pe--;
+ }
+ }
+ p[0].path_len--;
+ CORD__extend_path(p);
+}
+
+#undef CORD_pos_fetch
+#undef CORD_next
+#undef CORD_prev
+#undef CORD_pos_to_index
+#undef CORD_pos_to_cord
+#undef CORD_pos_valid
+
+char CORD_pos_fetch(register CORD_pos p)
+{
+ if (p[0].cur_start <= p[0].cur_pos && p[0].cur_pos < p[0].cur_end) {
+ return(p[0].cur_leaf[p[0].cur_pos - p[0].cur_start]);
+ } else {
+ return(CORD__pos_fetch(p));
+ }
+}
+
+void CORD_next(CORD_pos p)
+{
+ if (p[0].cur_pos < p[0].cur_end - 1) {
+ p[0].cur_pos++;
+ } else {
+ CORD__next(p);
+ }
+}
+
+void CORD_prev(CORD_pos p)
+{
+ if (p[0].cur_end != 0 && p[0].cur_pos > p[0].cur_start) {
+ p[0].cur_pos--;
+ } else {
+ CORD__prev(p);
+ }
+}
+
+size_t CORD_pos_to_index(CORD_pos p)
+{
+ return(p[0].cur_pos);
+}
+
+CORD CORD_pos_to_cord(CORD_pos p)
+{
+ return(p[0].path[0].pe_cord);
+}
+
+int CORD_pos_valid(CORD_pos p)
+{
+ return(p[0].path_len != CORD_POS_INVALID);
+}
+
+void CORD_set_pos(CORD_pos p, CORD x, size_t i)
+{
+ if (x == CORD_EMPTY) {
+ p[0].path_len = CORD_POS_INVALID;
+ return;
+ }
+ p[0].path[0].pe_cord = x;
+ p[0].path[0].pe_start_pos = 0;
+ p[0].path_len = 0;
+ p[0].cur_pos = i;
+ CORD__extend_path(p);
+}
diff --git a/tools/build/v2/engine/boehm_gc/cord/cordprnt.c b/tools/build/v2/engine/boehm_gc/cord/cordprnt.c
new file mode 100644
index 0000000000..6d278feda6
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/cord/cordprnt.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* An sprintf implementation that understands cords. This is probably */
+/* not terribly portable. It assumes an ANSI stdarg.h. It further */
+/* assumes that I can make copies of va_list variables, and read */
+/* arguments repeatedly by applyting va_arg to the copies. This */
+/* could be avoided at some performance cost. */
+/* We also assume that unsigned and signed integers of various kinds */
+/* have the same sizes, and can be cast back and forth. */
+/* We assume that void * and char * have the same size. */
+/* All this cruft is needed because we want to rely on the underlying */
+/* sprintf implementation whenever possible. */
+/* Boehm, September 21, 1995 6:00 pm PDT */
+
+#include "cord.h"
+#include "ec.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include "gc.h"
+
+#define CONV_SPEC_LEN 50 /* Maximum length of a single */
+ /* conversion specification. */
+#define CONV_RESULT_LEN 50 /* Maximum length of any */
+ /* conversion with default */
+ /* width and prec. */
+
+
+static int ec_len(CORD_ec x)
+{
+ return(CORD_len(x[0].ec_cord) + (x[0].ec_bufptr - x[0].ec_buf));
+}
+
+/* Possible nonumeric precision values. */
+# define NONE -1
+# define VARIABLE -2
+/* Copy the conversion specification from CORD_pos into the buffer buf */
+/* Return negative on error. */
+/* Source initially points one past the leading %. */
+/* It is left pointing at the conversion type. */
+/* Assign field width and precision to *width and *prec. */
+/* If width or prec is *, VARIABLE is assigned. */
+/* Set *left to 1 if left adjustment flag is present. */
+/* Set *long_arg to 1 if long flag ('l' or 'L') is present, or to */
+/* -1 if 'h' is present. */
+static int extract_conv_spec(CORD_pos source, char *buf,
+ int * width, int *prec, int *left, int * long_arg)
+{
+ register int result = 0;
+ register int current_number = 0;
+ register int saw_period = 0;
+ register int saw_number = 0;
+ register int chars_so_far = 0;
+ register char current;
+
+ *width = NONE;
+ buf[chars_so_far++] = '%';
+ while(CORD_pos_valid(source)) {
+ if (chars_so_far >= CONV_SPEC_LEN) return(-1);
+ current = CORD_pos_fetch(source);
+ buf[chars_so_far++] = current;
+ switch(current) {
+ case '*':
+ saw_number = 1;
+ current_number = VARIABLE;
+ break;
+ case '0':
+ if (!saw_number) {
+ /* Zero fill flag; ignore */
+ break;
+ } /* otherwise fall through: */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ saw_number = 1;
+ current_number *= 10;
+ current_number += current - '0';
+ break;
+ case '.':
+ saw_period = 1;
+ if(saw_number) {
+ *width = current_number;
+ saw_number = 0;
+ }
+ current_number = 0;
+ break;
+ case 'l':
+ case 'L':
+ *long_arg = 1;
+ current_number = 0;
+ break;
+ case 'h':
+ *long_arg = -1;
+ current_number = 0;
+ break;
+ case ' ':
+ case '+':
+ case '#':
+ current_number = 0;
+ break;
+ case '-':
+ *left = 1;
+ current_number = 0;
+ break;
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ case 'c':
+ case 'C':
+ case 's':
+ case 'S':
+ case 'p':
+ case 'n':
+ case 'r':
+ goto done;
+ default:
+ return(-1);
+ }
+ CORD_next(source);
+ }
+ return(-1);
+ done:
+ if (saw_number) {
+ if (saw_period) {
+ *prec = current_number;
+ } else {
+ *prec = NONE;
+ *width = current_number;
+ }
+ } else {
+ *prec = NONE;
+ }
+ buf[chars_so_far] = '\0';
+ return(result);
+}
+
+int CORD_vsprintf(CORD * out, CORD format, va_list args)
+{
+ CORD_ec result;
+ register int count;
+ register char current;
+ CORD_pos pos;
+ char conv_spec[CONV_SPEC_LEN + 1];
+
+ CORD_ec_init(result);
+ for (CORD_set_pos(pos, format, 0); CORD_pos_valid(pos); CORD_next(pos)) {
+ current = CORD_pos_fetch(pos);
+ if (current == '%') {
+ CORD_next(pos);
+ if (!CORD_pos_valid(pos)) return(-1);
+ current = CORD_pos_fetch(pos);
+ if (current == '%') {
+ CORD_ec_append(result, current);
+ } else {
+ int width, prec;
+ int left_adj = 0;
+ int long_arg = 0;
+ CORD arg;
+ size_t len;
+
+ if (extract_conv_spec(pos, conv_spec,
+ &width, &prec,
+ &left_adj, &long_arg) < 0) {
+ return(-1);
+ }
+ current = CORD_pos_fetch(pos);
+ switch(current) {
+ case 'n':
+ /* Assign length to next arg */
+ if (long_arg == 0) {
+ int * pos_ptr;
+ pos_ptr = va_arg(args, int *);
+ *pos_ptr = ec_len(result);
+ } else if (long_arg > 0) {
+ long * pos_ptr;
+ pos_ptr = va_arg(args, long *);
+ *pos_ptr = ec_len(result);
+ } else {
+ short * pos_ptr;
+ pos_ptr = va_arg(args, short *);
+ *pos_ptr = ec_len(result);
+ }
+ goto done;
+ case 'r':
+ /* Append cord and any padding */
+ if (width == VARIABLE) width = va_arg(args, int);
+ if (prec == VARIABLE) prec = va_arg(args, int);
+ arg = va_arg(args, CORD);
+ len = CORD_len(arg);
+ if (prec != NONE && len > prec) {
+ if (prec < 0) return(-1);
+ arg = CORD_substr(arg, 0, prec);
+ len = prec;
+ }
+ if (width != NONE && len < width) {
+ char * blanks = GC_MALLOC_ATOMIC(width-len+1);
+
+ memset(blanks, ' ', width-len);
+ blanks[width-len] = '\0';
+ if (left_adj) {
+ arg = CORD_cat(arg, blanks);
+ } else {
+ arg = CORD_cat(blanks, arg);
+ }
+ }
+ CORD_ec_append_cord(result, arg);
+ goto done;
+ case 'c':
+ if (width == NONE && prec == NONE) {
+ register char c;
+
+ c = (char)va_arg(args, int);
+ CORD_ec_append(result, c);
+ goto done;
+ }
+ break;
+ case 's':
+ if (width == NONE && prec == NONE) {
+ char * str = va_arg(args, char *);
+ register char c;
+
+ while ((c = *str++)) {
+ CORD_ec_append(result, c);
+ }
+ goto done;
+ }
+ break;
+ default:
+ break;
+ }
+ /* Use standard sprintf to perform conversion */
+ {
+ register char * buf;
+ va_list vsprintf_args;
+ int max_size = 0;
+ int res;
+# ifdef __va_copy
+ __va_copy(vsprintf_args, args);
+# else
+# if defined(__GNUC__) && !defined(__DJGPP__) /* and probably in other cases */
+ va_copy(vsprintf_args, args);
+# else
+ vsprintf_args = args;
+# endif
+# endif
+ if (width == VARIABLE) width = va_arg(args, int);
+ if (prec == VARIABLE) prec = va_arg(args, int);
+ if (width != NONE) max_size = width;
+ if (prec != NONE && prec > max_size) max_size = prec;
+ max_size += CONV_RESULT_LEN;
+ if (max_size >= CORD_BUFSZ) {
+ buf = GC_MALLOC_ATOMIC(max_size + 1);
+ } else {
+ if (CORD_BUFSZ - (result[0].ec_bufptr-result[0].ec_buf)
+ < max_size) {
+ CORD_ec_flush_buf(result);
+ }
+ buf = result[0].ec_bufptr;
+ }
+ switch(current) {
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'c':
+ if (long_arg <= 0) {
+ (void) va_arg(args, int);
+ } else if (long_arg > 0) {
+ (void) va_arg(args, long);
+ }
+ break;
+ case 's':
+ case 'p':
+ (void) va_arg(args, char *);
+ break;
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ (void) va_arg(args, double);
+ break;
+ default:
+ return(-1);
+ }
+ res = vsprintf(buf, conv_spec, vsprintf_args);
+ len = (size_t)res;
+ if ((char *)(GC_word)res == buf) {
+ /* old style vsprintf */
+ len = strlen(buf);
+ } else if (res < 0) {
+ return(-1);
+ }
+ if (buf != result[0].ec_bufptr) {
+ register char c;
+
+ while ((c = *buf++)) {
+ CORD_ec_append(result, c);
+ }
+ } else {
+ result[0].ec_bufptr = buf + len;
+ }
+ }
+ done:;
+ }
+ } else {
+ CORD_ec_append(result, current);
+ }
+ }
+ count = ec_len(result);
+ *out = CORD_balance(CORD_ec_to_cord(result));
+ return(count);
+}
+
+int CORD_sprintf(CORD * out, CORD format, ...)
+{
+ va_list args;
+ int result;
+
+ va_start(args, format);
+ result = CORD_vsprintf(out, format, args);
+ va_end(args);
+ return(result);
+}
+
+int CORD_fprintf(FILE * f, CORD format, ...)
+{
+ va_list args;
+ int result;
+ CORD out;
+
+ va_start(args, format);
+ result = CORD_vsprintf(&out, format, args);
+ va_end(args);
+ if (result > 0) CORD_put(out, f);
+ return(result);
+}
+
+int CORD_vfprintf(FILE * f, CORD format, va_list args)
+{
+ int result;
+ CORD out;
+
+ result = CORD_vsprintf(&out, format, args);
+ if (result > 0) CORD_put(out, f);
+ return(result);
+}
+
+int CORD_printf(CORD format, ...)
+{
+ va_list args;
+ int result;
+ CORD out;
+
+ va_start(args, format);
+ result = CORD_vsprintf(&out, format, args);
+ va_end(args);
+ if (result > 0) CORD_put(out, stdout);
+ return(result);
+}
+
+int CORD_vprintf(CORD format, va_list args)
+{
+ int result;
+ CORD out;
+
+ result = CORD_vsprintf(&out, format, args);
+ if (result > 0) CORD_put(out, stdout);
+ return(result);
+}
diff --git a/tools/build/v2/engine/boehm_gc/cord/cordtest.c b/tools/build/v2/engine/boehm_gc/cord/cordtest.c
new file mode 100644
index 0000000000..08333ca043
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/cord/cordtest.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, August 24, 1994 11:58 am PDT */
+# include "gc.h" /* For GC_INIT() only */
+# include "cord.h"
+# include <string.h>
+# include <stdio.h>
+# include <stdlib.h>
+/* This is a very incomplete test of the cord package. It knows about */
+/* a few internals of the package (e.g. when C strings are returned) */
+/* that real clients shouldn't rely on. */
+
+# define ABORT(string) \
+{ int x = 0; fprintf(stderr, "FAILED: %s\n", string); x = 1 / x; abort(); }
+
+int count;
+
+int test_fn(char c, void * client_data)
+{
+ if (client_data != (void *)13) ABORT("bad client data");
+ if (count < 64*1024+1) {
+ if ((count & 1) == 0) {
+ if (c != 'b') ABORT("bad char");
+ } else {
+ if (c != 'a') ABORT("bad char");
+ }
+ count++;
+ return(0);
+ } else {
+ if (c != 'c') ABORT("bad char");
+ count++;
+ return(1);
+ }
+}
+
+char id_cord_fn(size_t i, void * client_data)
+{
+ return((char)i);
+}
+
+void test_basics()
+{
+ CORD x = CORD_from_char_star("ab");
+ register int i;
+ char c;
+ CORD y;
+ CORD_pos p;
+
+ x = CORD_cat(x,x);
+ if (!CORD_IS_STRING(x)) ABORT("short cord should usually be a string");
+ if (strcmp(x, "abab") != 0) ABORT("bad CORD_cat result");
+
+ for (i = 1; i < 16; i++) {
+ x = CORD_cat(x,x);
+ }
+ x = CORD_cat(x,"c");
+ if (CORD_len(x) != 128*1024+1) ABORT("bad length");
+
+ count = 0;
+ if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN, (void *)13) == 0) {
+ ABORT("CORD_iter5 failed");
+ }
+ if (count != 64*1024 + 2) ABORT("CORD_iter5 failed");
+
+ count = 0;
+ CORD_set_pos(p, x, 64*1024-1);
+ while(CORD_pos_valid(p)) {
+ (void) test_fn(CORD_pos_fetch(p), (void *)13);
+ CORD_next(p);
+ }
+ if (count != 64*1024 + 2) ABORT("Position based iteration failed");
+
+ y = CORD_substr(x, 1023, 5);
+ if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string");
+ if (strcmp(y, "babab") != 0) ABORT("bad CORD_substr result");
+
+ y = CORD_substr(x, 1024, 8);
+ if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string");
+ if (strcmp(y, "abababab") != 0) ABORT("bad CORD_substr result");
+
+ y = CORD_substr(x, 128*1024-1, 8);
+ if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string");
+ if (strcmp(y, "bc") != 0) ABORT("bad CORD_substr result");
+
+ x = CORD_balance(x);
+ if (CORD_len(x) != 128*1024+1) ABORT("bad length");
+
+ count = 0;
+ if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN, (void *)13) == 0) {
+ ABORT("CORD_iter5 failed");
+ }
+ if (count != 64*1024 + 2) ABORT("CORD_iter5 failed");
+
+ y = CORD_substr(x, 1023, 5);
+ if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string");
+ if (strcmp(y, "babab") != 0) ABORT("bad CORD_substr result");
+ y = CORD_from_fn(id_cord_fn, 0, 13);
+ i = 0;
+ CORD_set_pos(p, y, i);
+ while(CORD_pos_valid(p)) {
+ c = CORD_pos_fetch(p);
+ if(c != i) ABORT("Traversal of function node failed");
+ CORD_next(p); i++;
+ }
+ if (i != 13) ABORT("Bad apparent length for function node");
+}
+
+void test_extras()
+{
+# if defined(__OS2__) || defined(__DJGPP__)
+# define FNAME1 "tmp1"
+# define FNAME2 "tmp2"
+# elif defined(AMIGA)
+# define FNAME1 "T:tmp1"
+# define FNAME2 "T:tmp2"
+# else
+# define FNAME1 "/tmp/cord_test"
+# define FNAME2 "/tmp/cord_test2"
+# endif
+ register int i;
+ CORD y = "abcdefghijklmnopqrstuvwxyz0123456789";
+ CORD x = "{}";
+ CORD w, z;
+ FILE *f;
+ FILE *f1a, *f1b, *f2;
+
+ w = CORD_cat(CORD_cat(y,y),y);
+ z = CORD_catn(3,y,y,y);
+ if (CORD_cmp(w,z) != 0) ABORT("CORD_catn comparison wrong");
+ for (i = 1; i < 100; i++) {
+ x = CORD_cat(x, y);
+ }
+ z = CORD_balance(x);
+ if (CORD_cmp(x,z) != 0) ABORT("balanced string comparison wrong");
+ if (CORD_cmp(x,CORD_cat(z, CORD_nul(13))) >= 0) ABORT("comparison 2");
+ if (CORD_cmp(CORD_cat(x, CORD_nul(13)), z) <= 0) ABORT("comparison 3");
+ if (CORD_cmp(x,CORD_cat(z, "13")) >= 0) ABORT("comparison 4");
+ if ((f = fopen(FNAME1, "w")) == 0) ABORT("open failed");
+ if (CORD_put(z,f) == EOF) ABORT("CORD_put failed");
+ if (fclose(f) == EOF) ABORT("fclose failed");
+ w = CORD_from_file(f1a = fopen(FNAME1, "rb"));
+ if (CORD_len(w) != CORD_len(z)) ABORT("file length wrong");
+ if (CORD_cmp(w,z) != 0) ABORT("file comparison wrong");
+ if (CORD_cmp(CORD_substr(w, 50*36+2, 36), y) != 0)
+ ABORT("file substr wrong");
+ z = CORD_from_file_lazy(f1b = fopen(FNAME1, "rb"));
+ if (CORD_cmp(w,z) != 0) ABORT("File conversions differ");
+ if (CORD_chr(w, 0, '9') != 37) ABORT("CORD_chr failed 1");
+ if (CORD_chr(w, 3, 'a') != 38) ABORT("CORD_chr failed 2");
+ if (CORD_rchr(w, CORD_len(w) - 1, '}') != 1) ABORT("CORD_rchr failed");
+ x = y;
+ for (i = 1; i < 14; i++) {
+ x = CORD_cat(x,x);
+ }
+ if ((f = fopen(FNAME2, "w")) == 0) ABORT("2nd open failed");
+# ifdef __DJGPP__
+ /* FIXME: DJGPP workaround. Why does this help? */
+ if (fflush(f) != 0) ABORT("fflush failed");
+# endif
+ if (CORD_put(x,f) == EOF) ABORT("CORD_put failed");
+ if (fclose(f) == EOF) ABORT("fclose failed");
+ w = CORD_from_file(f2 = fopen(FNAME2, "rb"));
+ if (CORD_len(w) != CORD_len(x)) ABORT("file length wrong");
+ if (CORD_cmp(w,x) != 0) ABORT("file comparison wrong");
+ if (CORD_cmp(CORD_substr(w, 1000*36, 36), y) != 0)
+ ABORT("file substr wrong");
+ if (strcmp(CORD_to_char_star(CORD_substr(w, 1000*36, 36)), y) != 0)
+ ABORT("char * file substr wrong");
+ if (strcmp(CORD_substr(w, 1000*36, 2), "ab") != 0)
+ ABORT("short file substr wrong");
+ if (CORD_str(x,1,"9a") != 35) ABORT("CORD_str failed 1");
+ if (CORD_str(x,0,"9abcdefghijk") != 35) ABORT("CORD_str failed 2");
+ if (CORD_str(x,0,"9abcdefghijx") != CORD_NOT_FOUND)
+ ABORT("CORD_str failed 3");
+ if (CORD_str(x,0,"9>") != CORD_NOT_FOUND) ABORT("CORD_str failed 4");
+ if (remove(FNAME1) != 0) {
+ /* On some systems, e.g. OS2, this may fail if f1 is still open. */
+ if ((fclose(f1a) == EOF) & (fclose(f1b) == EOF))
+ ABORT("fclose(f1) failed");
+ if (remove(FNAME1) != 0) ABORT("remove 1 failed");
+ }
+ if (remove(FNAME2) != 0) {
+ if (fclose(f2) == EOF) ABORT("fclose(f2) failed");
+ if (remove(FNAME2) != 0) ABORT("remove 2 failed");
+ }
+}
+
+void test_printf()
+{
+ CORD result;
+ char result2[200];
+ long l;
+ short s;
+ CORD x;
+
+ if (CORD_sprintf(&result, "%7.2f%ln", 3.14159F, &l) != 7)
+ ABORT("CORD_sprintf failed 1");
+ if (CORD_cmp(result, " 3.14") != 0)ABORT("CORD_sprintf goofed 1");
+ if (l != 7) ABORT("CORD_sprintf goofed 2");
+ if (CORD_sprintf(&result, "%-7.2s%hn%c%s", "abcd", &s, 'x', "yz") != 10)
+ ABORT("CORD_sprintf failed 2");
+ if (CORD_cmp(result, "ab xyz") != 0)ABORT("CORD_sprintf goofed 3");
+ if (s != 7) ABORT("CORD_sprintf goofed 4");
+ x = "abcdefghij";
+ x = CORD_cat(x,x);
+ x = CORD_cat(x,x);
+ x = CORD_cat(x,x);
+ if (CORD_sprintf(&result, "->%-120.78r!\n", x) != 124)
+ ABORT("CORD_sprintf failed 3");
+ (void) sprintf(result2, "->%-120.78s!\n", CORD_to_char_star(x));
+ if (CORD_cmp(result, result2) != 0)ABORT("CORD_sprintf goofed 5");
+}
+
+int main()
+{
+# ifdef THINK_C
+ printf("cordtest:\n");
+# endif
+ GC_INIT();
+ test_basics();
+ test_extras();
+ test_printf();
+ CORD_fprintf(stderr, "SUCCEEDED\n");
+ return(0);
+}
diff --git a/tools/build/v2/engine/boehm_gc/cord/cordxtra.c b/tools/build/v2/engine/boehm_gc/cord/cordxtra.c
new file mode 100644
index 0000000000..b0a746226c
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/cord/cordxtra.c
@@ -0,0 +1,621 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ * Author: Hans-J. Boehm (boehm@parc.xerox.com)
+ */
+/*
+ * These are functions on cords that do not need to understand their
+ * implementation. They serve also serve as example client code for
+ * cord_basics.
+ */
+/* Boehm, December 8, 1995 1:53 pm PST */
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+# include <stdarg.h>
+# include "cord.h"
+# include "ec.h"
+# define I_HIDE_POINTERS /* So we get access to allocation lock. */
+ /* We use this for lazy file reading, */
+ /* so that we remain independent */
+ /* of the threads primitives. */
+# include "gc.h"
+
+/* For now we assume that pointer reads and writes are atomic, */
+/* i.e. another thread always sees the state before or after */
+/* a write. This might be false on a Motorola M68K with */
+/* pointers that are not 32-bit aligned. But there probably */
+/* aren't too many threads packages running on those. */
+# define ATOMIC_WRITE(x,y) (x) = (y)
+# define ATOMIC_READ(x) (*(x))
+
+/* The standard says these are in stdio.h, but they aren't always: */
+# ifndef SEEK_SET
+# define SEEK_SET 0
+# endif
+# ifndef SEEK_END
+# define SEEK_END 2
+# endif
+
+# define BUFSZ 2048 /* Size of stack allocated buffers when */
+ /* we want large buffers. */
+
+typedef void (* oom_fn)(void);
+
+# define OUT_OF_MEMORY { if (CORD_oom_fn != (oom_fn) 0) (*CORD_oom_fn)(); \
+ ABORT("Out of memory\n"); }
+# define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); }
+
+CORD CORD_cat_char(CORD x, char c)
+{
+ register char * string;
+
+ if (c == '\0') return(CORD_cat(x, CORD_nul(1)));
+ string = GC_MALLOC_ATOMIC(2);
+ if (string == 0) OUT_OF_MEMORY;
+ string[0] = c;
+ string[1] = '\0';
+ return(CORD_cat_char_star(x, string, 1));
+}
+
+CORD CORD_catn(int nargs, ...)
+{
+ register CORD result = CORD_EMPTY;
+ va_list args;
+ register int i;
+
+ va_start(args, nargs);
+ for (i = 0; i < nargs; i++) {
+ register CORD next = va_arg(args, CORD);
+ result = CORD_cat(result, next);
+ }
+ va_end(args);
+ return(result);
+}
+
+typedef struct {
+ size_t len;
+ size_t count;
+ char * buf;
+} CORD_fill_data;
+
+int CORD_fill_proc(char c, void * client_data)
+{
+ register CORD_fill_data * d = (CORD_fill_data *)client_data;
+ register size_t count = d -> count;
+
+ (d -> buf)[count] = c;
+ d -> count = ++count;
+ if (count >= d -> len) {
+ return(1);
+ } else {
+ return(0);
+ }
+}
+
+int CORD_batched_fill_proc(const char * s, void * client_data)
+{
+ register CORD_fill_data * d = (CORD_fill_data *)client_data;
+ register size_t count = d -> count;
+ register size_t max = d -> len;
+ register char * buf = d -> buf;
+ register const char * t = s;
+
+ while((buf[count] = *t++) != '\0') {
+ count++;
+ if (count >= max) {
+ d -> count = count;
+ return(1);
+ }
+ }
+ d -> count = count;
+ return(0);
+}
+
+/* Fill buf with len characters starting at i. */
+/* Assumes len characters are available. */
+void CORD_fill_buf(CORD x, size_t i, size_t len, char * buf)
+{
+ CORD_fill_data fd;
+
+ fd.len = len;
+ fd.buf = buf;
+ fd.count = 0;
+ (void)CORD_iter5(x, i, CORD_fill_proc, CORD_batched_fill_proc, &fd);
+}
+
+int CORD_cmp(CORD x, CORD y)
+{
+ CORD_pos xpos;
+ CORD_pos ypos;
+ register size_t avail, yavail;
+
+ if (y == CORD_EMPTY) return(x != CORD_EMPTY);
+ if (x == CORD_EMPTY) return(-1);
+ if (CORD_IS_STRING(y) && CORD_IS_STRING(x)) return(strcmp(x,y));
+ CORD_set_pos(xpos, x, 0);
+ CORD_set_pos(ypos, y, 0);
+ for(;;) {
+ if (!CORD_pos_valid(xpos)) {
+ if (CORD_pos_valid(ypos)) {
+ return(-1);
+ } else {
+ return(0);
+ }
+ }
+ if (!CORD_pos_valid(ypos)) {
+ return(1);
+ }
+ if ((avail = CORD_pos_chars_left(xpos)) <= 0
+ || (yavail = CORD_pos_chars_left(ypos)) <= 0) {
+ register char xcurrent = CORD_pos_fetch(xpos);
+ register char ycurrent = CORD_pos_fetch(ypos);
+ if (xcurrent != ycurrent) return(xcurrent - ycurrent);
+ CORD_next(xpos);
+ CORD_next(ypos);
+ } else {
+ /* process as many characters as we can */
+ register int result;
+
+ if (avail > yavail) avail = yavail;
+ result = strncmp(CORD_pos_cur_char_addr(xpos),
+ CORD_pos_cur_char_addr(ypos), avail);
+ if (result != 0) return(result);
+ CORD_pos_advance(xpos, avail);
+ CORD_pos_advance(ypos, avail);
+ }
+ }
+}
+
+int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start, size_t len)
+{
+ CORD_pos xpos;
+ CORD_pos ypos;
+ register size_t count;
+ register long avail, yavail;
+
+ CORD_set_pos(xpos, x, x_start);
+ CORD_set_pos(ypos, y, y_start);
+ for(count = 0; count < len;) {
+ if (!CORD_pos_valid(xpos)) {
+ if (CORD_pos_valid(ypos)) {
+ return(-1);
+ } else {
+ return(0);
+ }
+ }
+ if (!CORD_pos_valid(ypos)) {
+ return(1);
+ }
+ if ((avail = CORD_pos_chars_left(xpos)) <= 0
+ || (yavail = CORD_pos_chars_left(ypos)) <= 0) {
+ register char xcurrent = CORD_pos_fetch(xpos);
+ register char ycurrent = CORD_pos_fetch(ypos);
+ if (xcurrent != ycurrent) return(xcurrent - ycurrent);
+ CORD_next(xpos);
+ CORD_next(ypos);
+ count++;
+ } else {
+ /* process as many characters as we can */
+ register int result;
+
+ if (avail > yavail) avail = yavail;
+ count += avail;
+ if (count > len) avail -= (count - len);
+ result = strncmp(CORD_pos_cur_char_addr(xpos),
+ CORD_pos_cur_char_addr(ypos), (size_t)avail);
+ if (result != 0) return(result);
+ CORD_pos_advance(xpos, (size_t)avail);
+ CORD_pos_advance(ypos, (size_t)avail);
+ }
+ }
+ return(0);
+}
+
+char * CORD_to_char_star(CORD x)
+{
+ register size_t len = CORD_len(x);
+ char * result = GC_MALLOC_ATOMIC(len + 1);
+
+ if (result == 0) OUT_OF_MEMORY;
+ CORD_fill_buf(x, 0, len, result);
+ result[len] = '\0';
+ return(result);
+}
+
+CORD CORD_from_char_star(const char *s)
+{
+ char * result;
+ size_t len = strlen(s);
+
+ if (0 == len) return(CORD_EMPTY);
+ result = GC_MALLOC_ATOMIC(len + 1);
+ if (result == 0) OUT_OF_MEMORY;
+ memcpy(result, s, len+1);
+ return(result);
+}
+
+const char * CORD_to_const_char_star(CORD x)
+{
+ if (x == 0) return("");
+ if (CORD_IS_STRING(x)) return((const char *)x);
+ return(CORD_to_char_star(x));
+}
+
+char CORD_fetch(CORD x, size_t i)
+{
+ CORD_pos xpos;
+
+ CORD_set_pos(xpos, x, i);
+ if (!CORD_pos_valid(xpos)) ABORT("bad index?");
+ return(CORD_pos_fetch(xpos));
+}
+
+
+int CORD_put_proc(char c, void * client_data)
+{
+ register FILE * f = (FILE *)client_data;
+
+ return(putc(c, f) == EOF);
+}
+
+int CORD_batched_put_proc(const char * s, void * client_data)
+{
+ register FILE * f = (FILE *)client_data;
+
+ return(fputs(s, f) == EOF);
+}
+
+
+int CORD_put(CORD x, FILE * f)
+{
+ if (CORD_iter5(x, 0, CORD_put_proc, CORD_batched_put_proc, f)) {
+ return(EOF);
+ } else {
+ return(1);
+ }
+}
+
+typedef struct {
+ size_t pos; /* Current position in the cord */
+ char target; /* Character we're looking for */
+} chr_data;
+
+int CORD_chr_proc(char c, void * client_data)
+{
+ register chr_data * d = (chr_data *)client_data;
+
+ if (c == d -> target) return(1);
+ (d -> pos) ++;
+ return(0);
+}
+
+int CORD_rchr_proc(char c, void * client_data)
+{
+ register chr_data * d = (chr_data *)client_data;
+
+ if (c == d -> target) return(1);
+ (d -> pos) --;
+ return(0);
+}
+
+int CORD_batched_chr_proc(const char *s, void * client_data)
+{
+ register chr_data * d = (chr_data *)client_data;
+ register char * occ = strchr(s, d -> target);
+
+ if (occ == 0) {
+ d -> pos += strlen(s);
+ return(0);
+ } else {
+ d -> pos += occ - s;
+ return(1);
+ }
+}
+
+size_t CORD_chr(CORD x, size_t i, int c)
+{
+ chr_data d;
+
+ d.pos = i;
+ d.target = c;
+ if (CORD_iter5(x, i, CORD_chr_proc, CORD_batched_chr_proc, &d)) {
+ return(d.pos);
+ } else {
+ return(CORD_NOT_FOUND);
+ }
+}
+
+size_t CORD_rchr(CORD x, size_t i, int c)
+{
+ chr_data d;
+
+ d.pos = i;
+ d.target = c;
+ if (CORD_riter4(x, i, CORD_rchr_proc, &d)) {
+ return(d.pos);
+ } else {
+ return(CORD_NOT_FOUND);
+ }
+}
+
+/* Find the first occurrence of s in x at position start or later. */
+/* This uses an asymptotically poor algorithm, which should typically */
+/* perform acceptably. We compare the first few characters directly, */
+/* and call CORD_ncmp whenever there is a partial match. */
+/* This has the advantage that we allocate very little, or not at all. */
+/* It's very fast if there are few close misses. */
+size_t CORD_str(CORD x, size_t start, CORD s)
+{
+ CORD_pos xpos;
+ size_t xlen = CORD_len(x);
+ size_t slen;
+ register size_t start_len;
+ const char * s_start;
+ unsigned long s_buf = 0; /* The first few characters of s */
+ unsigned long x_buf = 0; /* Start of candidate substring. */
+ /* Initialized only to make compilers */
+ /* happy. */
+ unsigned long mask = 0;
+ register size_t i;
+ register size_t match_pos;
+
+ if (s == CORD_EMPTY) return(start);
+ if (CORD_IS_STRING(s)) {
+ s_start = s;
+ slen = strlen(s);
+ } else {
+ s_start = CORD_to_char_star(CORD_substr(s, 0, sizeof(unsigned long)));
+ slen = CORD_len(s);
+ }
+ if (xlen < start || xlen - start < slen) return(CORD_NOT_FOUND);
+ start_len = slen;
+ if (start_len > sizeof(unsigned long)) start_len = sizeof(unsigned long);
+ CORD_set_pos(xpos, x, start);
+ for (i = 0; i < start_len; i++) {
+ mask <<= 8;
+ mask |= 0xff;
+ s_buf <<= 8;
+ s_buf |= (unsigned char)s_start[i];
+ x_buf <<= 8;
+ x_buf |= (unsigned char)CORD_pos_fetch(xpos);
+ CORD_next(xpos);
+ }
+ for (match_pos = start; ; match_pos++) {
+ if ((x_buf & mask) == s_buf) {
+ if (slen == start_len ||
+ CORD_ncmp(x, match_pos + start_len,
+ s, start_len, slen - start_len) == 0) {
+ return(match_pos);
+ }
+ }
+ if ( match_pos == xlen - slen ) {
+ return(CORD_NOT_FOUND);
+ }
+ x_buf <<= 8;
+ x_buf |= (unsigned char)CORD_pos_fetch(xpos);
+ CORD_next(xpos);
+ }
+}
+
+void CORD_ec_flush_buf(CORD_ec x)
+{
+ register size_t len = x[0].ec_bufptr - x[0].ec_buf;
+ char * s;
+
+ if (len == 0) return;
+ s = GC_MALLOC_ATOMIC(len+1);
+ memcpy(s, x[0].ec_buf, len);
+ s[len] = '\0';
+ x[0].ec_cord = CORD_cat_char_star(x[0].ec_cord, s, len);
+ x[0].ec_bufptr = x[0].ec_buf;
+}
+
+void CORD_ec_append_cord(CORD_ec x, CORD s)
+{
+ CORD_ec_flush_buf(x);
+ x[0].ec_cord = CORD_cat(x[0].ec_cord, s);
+}
+
+/*ARGSUSED*/
+char CORD_nul_func(size_t i, void * client_data)
+{
+ return((char)(unsigned long)client_data);
+}
+
+
+CORD CORD_chars(char c, size_t i)
+{
+ return(CORD_from_fn(CORD_nul_func, (void *)(unsigned long)c, i));
+}
+
+CORD CORD_from_file_eager(FILE * f)
+{
+ register int c;
+ CORD_ec ecord;
+
+ CORD_ec_init(ecord);
+ for(;;) {
+ c = getc(f);
+ if (c == 0) {
+ /* Append the right number of NULs */
+ /* Note that any string of NULs is rpresented in 4 words, */
+ /* independent of its length. */
+ register size_t count = 1;
+
+ CORD_ec_flush_buf(ecord);
+ while ((c = getc(f)) == 0) count++;
+ ecord[0].ec_cord = CORD_cat(ecord[0].ec_cord, CORD_nul(count));
+ }
+ if (c == EOF) break;
+ CORD_ec_append(ecord, c);
+ }
+ (void) fclose(f);
+ return(CORD_balance(CORD_ec_to_cord(ecord)));
+}
+
+/* The state maintained for a lazily read file consists primarily */
+/* of a large direct-mapped cache of previously read values. */
+/* We could rely more on stdio buffering. That would have 2 */
+/* disadvantages: */
+/* 1) Empirically, not all fseek implementations preserve the */
+/* buffer whenever they could. */
+/* 2) It would fail if 2 different sections of a long cord */
+/* were being read alternately. */
+/* We do use the stdio buffer for read ahead. */
+/* To guarantee thread safety in the presence of atomic pointer */
+/* writes, cache lines are always replaced, and never modified in */
+/* place. */
+
+# define LOG_CACHE_SZ 14
+# define CACHE_SZ (1 << LOG_CACHE_SZ)
+# define LOG_LINE_SZ 9
+# define LINE_SZ (1 << LOG_LINE_SZ)
+
+typedef struct {
+ size_t tag;
+ char data[LINE_SZ];
+ /* data[i%LINE_SZ] = ith char in file if tag = i/LINE_SZ */
+} cache_line;
+
+typedef struct {
+ FILE * lf_file;
+ size_t lf_current; /* Current file pointer value */
+ cache_line * volatile lf_cache[CACHE_SZ/LINE_SZ];
+} lf_state;
+
+# define MOD_CACHE_SZ(n) ((n) & (CACHE_SZ - 1))
+# define DIV_CACHE_SZ(n) ((n) >> LOG_CACHE_SZ)
+# define MOD_LINE_SZ(n) ((n) & (LINE_SZ - 1))
+# define DIV_LINE_SZ(n) ((n) >> LOG_LINE_SZ)
+# define LINE_START(n) ((n) & ~(LINE_SZ - 1))
+
+typedef struct {
+ lf_state * state;
+ size_t file_pos; /* Position of needed character. */
+ cache_line * new_cache;
+} refill_data;
+
+/* Executed with allocation lock. */
+static char refill_cache(client_data)
+refill_data * client_data;
+{
+ register lf_state * state = client_data -> state;
+ register size_t file_pos = client_data -> file_pos;
+ FILE *f = state -> lf_file;
+ size_t line_start = LINE_START(file_pos);
+ size_t line_no = DIV_LINE_SZ(MOD_CACHE_SZ(file_pos));
+ cache_line * new_cache = client_data -> new_cache;
+
+ if (line_start != state -> lf_current
+ && fseek(f, line_start, SEEK_SET) != 0) {
+ ABORT("fseek failed");
+ }
+ if (fread(new_cache -> data, sizeof(char), LINE_SZ, f)
+ <= file_pos - line_start) {
+ ABORT("fread failed");
+ }
+ new_cache -> tag = DIV_LINE_SZ(file_pos);
+ /* Store barrier goes here. */
+ ATOMIC_WRITE(state -> lf_cache[line_no], new_cache);
+ state -> lf_current = line_start + LINE_SZ;
+ return(new_cache->data[MOD_LINE_SZ(file_pos)]);
+}
+
+char CORD_lf_func(size_t i, void * client_data)
+{
+ register lf_state * state = (lf_state *)client_data;
+ register cache_line * volatile * cl_addr =
+ &(state -> lf_cache[DIV_LINE_SZ(MOD_CACHE_SZ(i))]);
+ register cache_line * cl = (cache_line *)ATOMIC_READ(cl_addr);
+
+ if (cl == 0 || cl -> tag != DIV_LINE_SZ(i)) {
+ /* Cache miss */
+ refill_data rd;
+
+ rd.state = state;
+ rd.file_pos = i;
+ rd.new_cache = GC_NEW_ATOMIC(cache_line);
+ if (rd.new_cache == 0) OUT_OF_MEMORY;
+ return((char)(GC_word)
+ GC_call_with_alloc_lock((GC_fn_type) refill_cache, &rd));
+ }
+ return(cl -> data[MOD_LINE_SZ(i)]);
+}
+
+/*ARGSUSED*/
+void CORD_lf_close_proc(void * obj, void * client_data)
+{
+ if (fclose(((lf_state *)obj) -> lf_file) != 0) {
+ ABORT("CORD_lf_close_proc: fclose failed");
+ }
+}
+
+CORD CORD_from_file_lazy_inner(FILE * f, size_t len)
+{
+ register lf_state * state = GC_NEW(lf_state);
+ register int i;
+
+ if (state == 0) OUT_OF_MEMORY;
+ if (len != 0) {
+ /* Dummy read to force buffer allocation. */
+ /* This greatly increases the probability */
+ /* of avoiding deadlock if buffer allocation */
+ /* is redirected to GC_malloc and the */
+ /* world is multithreaded. */
+ char buf[1];
+
+ (void) fread(buf, 1, 1, f);
+ rewind(f);
+ }
+ state -> lf_file = f;
+ for (i = 0; i < CACHE_SZ/LINE_SZ; i++) {
+ state -> lf_cache[i] = 0;
+ }
+ state -> lf_current = 0;
+ GC_REGISTER_FINALIZER(state, CORD_lf_close_proc, 0, 0, 0);
+ return(CORD_from_fn(CORD_lf_func, state, len));
+}
+
+CORD CORD_from_file_lazy(FILE * f)
+{
+ register long len;
+
+ if (fseek(f, 0l, SEEK_END) != 0) {
+ ABORT("Bad fd argument - fseek failed");
+ }
+ if ((len = ftell(f)) < 0) {
+ ABORT("Bad fd argument - ftell failed");
+ }
+ rewind(f);
+ return(CORD_from_file_lazy_inner(f, (size_t)len));
+}
+
+# define LAZY_THRESHOLD (128*1024 + 1)
+
+CORD CORD_from_file(FILE * f)
+{
+ register long len;
+
+ if (fseek(f, 0l, SEEK_END) != 0) {
+ ABORT("Bad fd argument - fseek failed");
+ }
+ if ((len = ftell(f)) < 0) {
+ ABORT("Bad fd argument - ftell failed");
+ }
+ rewind(f);
+ if (len < LAZY_THRESHOLD) {
+ return(CORD_from_file_eager(f));
+ } else {
+ return(CORD_from_file_lazy_inner(f, (size_t)len));
+ }
+}
diff --git a/tools/build/v2/engine/boehm_gc/cord/de.c b/tools/build/v2/engine/boehm_gc/cord/de.c
new file mode 100644
index 0000000000..989e19a888
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/cord/de.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ * Author: Hans-J. Boehm (boehm@parc.xerox.com)
+ */
+/*
+ * A really simple-minded text editor based on cords.
+ * Things it does right:
+ * No size bounds.
+ * Inbounded undo.
+ * Shouldn't crash no matter what file you invoke it on (e.g. /vmunix)
+ * (Make sure /vmunix is not writable before you try this.)
+ * Scrolls horizontally.
+ * Things it does wrong:
+ * It doesn't handle tabs reasonably (use "expand" first).
+ * The command set is MUCH too small.
+ * The redisplay algorithm doesn't let curses do the scrolling.
+ * The rule for moving the window over the file is suboptimal.
+ */
+/* Boehm, February 6, 1995 12:27 pm PST */
+
+/* Boehm, May 19, 1994 2:20 pm PDT */
+#include <stdio.h>
+#include "gc.h"
+#include "cord.h"
+
+#ifdef THINK_C
+#define MACINTOSH
+#include <ctype.h>
+#endif
+
+#if defined(__BORLANDC__) && !defined(WIN32)
+ /* If this is DOS or win16, we'll fail anyway. */
+ /* Might as well assume win32. */
+# define WIN32
+#endif
+
+#if defined(WIN32)
+# include <windows.h>
+# include "de_win.h"
+#elif defined(MACINTOSH)
+# include <console.h>
+/* curses emulation. */
+# define initscr()
+# define endwin()
+# define nonl()
+# define noecho() csetmode(C_NOECHO, stdout)
+# define cbreak() csetmode(C_CBREAK, stdout)
+# define refresh()
+# define addch(c) putchar(c)
+# define standout() cinverse(1, stdout)
+# define standend() cinverse(0, stdout)
+# define move(line,col) cgotoxy(col + 1, line + 1, stdout)
+# define clrtoeol() ccleol(stdout)
+# define de_error(s) { fprintf(stderr, s); getchar(); }
+# define LINES 25
+# define COLS 80
+#else
+# include <curses.h>
+# define de_error(s) { fprintf(stderr, s); sleep(2); }
+#endif
+#include "de_cmds.h"
+
+/* List of line number to position mappings, in descending order. */
+/* There may be holes. */
+typedef struct LineMapRep {
+ int line;
+ size_t pos;
+ struct LineMapRep * previous;
+} * line_map;
+
+/* List of file versions, one per edit operation */
+typedef struct HistoryRep {
+ CORD file_contents;
+ struct HistoryRep * previous;
+ line_map map; /* Invalid for first record "now" */
+} * history;
+
+history now = 0;
+CORD current; /* == now -> file_contents. */
+size_t current_len; /* Current file length. */
+line_map current_map = 0; /* Current line no. to pos. map */
+size_t current_map_size = 0; /* Number of current_map entries. */
+ /* Not always accurate, but reset */
+ /* by prune_map. */
+# define MAX_MAP_SIZE 3000
+
+/* Current display position */
+int dis_line = 0;
+int dis_col = 0;
+
+# define ALL -1
+# define NONE - 2
+int need_redisplay = 0; /* Line that needs to be redisplayed. */
+
+
+/* Current cursor position. Always within file. */
+int line = 0;
+int col = 0;
+size_t file_pos = 0; /* Character position corresponding to cursor. */
+
+/* Invalidate line map for lines > i */
+void invalidate_map(int i)
+{
+ while(current_map -> line > i) {
+ current_map = current_map -> previous;
+ current_map_size--;
+ }
+}
+
+/* Reduce the number of map entries to save space for huge files. */
+/* This also affects maps in histories. */
+void prune_map()
+{
+ line_map map = current_map;
+ int start_line = map -> line;
+
+ current_map_size = 0;
+ for(; map != 0; map = map -> previous) {
+ current_map_size++;
+ if (map -> line < start_line - LINES && map -> previous != 0) {
+ map -> previous = map -> previous -> previous;
+ }
+ }
+}
+/* Add mapping entry */
+void add_map(int line, size_t pos)
+{
+ line_map new_map = GC_NEW(struct LineMapRep);
+
+ if (current_map_size >= MAX_MAP_SIZE) prune_map();
+ new_map -> line = line;
+ new_map -> pos = pos;
+ new_map -> previous = current_map;
+ current_map = new_map;
+ current_map_size++;
+}
+
+
+
+/* Return position of column *c of ith line in */
+/* current file. Adjust *c to be within the line.*/
+/* A 0 pointer is taken as 0 column. */
+/* Returns CORD_NOT_FOUND if i is too big. */
+/* Assumes i > dis_line. */
+size_t line_pos(int i, int *c)
+{
+ int j;
+ size_t cur;
+ size_t next;
+ line_map map = current_map;
+
+ while (map -> line > i) map = map -> previous;
+ if (map -> line < i - 2) /* rebuild */ invalidate_map(i);
+ for (j = map -> line, cur = map -> pos; j < i;) {
+ cur = CORD_chr(current, cur, '\n');
+ if (cur == current_len-1) return(CORD_NOT_FOUND);
+ cur++;
+ if (++j > current_map -> line) add_map(j, cur);
+ }
+ if (c != 0) {
+ next = CORD_chr(current, cur, '\n');
+ if (next == CORD_NOT_FOUND) next = current_len - 1;
+ if (next < cur + *c) {
+ *c = next - cur;
+ }
+ cur += *c;
+ }
+ return(cur);
+}
+
+void add_hist(CORD s)
+{
+ history new_file = GC_NEW(struct HistoryRep);
+
+ new_file -> file_contents = current = s;
+ current_len = CORD_len(s);
+ new_file -> previous = now;
+ if (now != 0) now -> map = current_map;
+ now = new_file;
+}
+
+void del_hist(void)
+{
+ now = now -> previous;
+ current = now -> file_contents;
+ current_map = now -> map;
+ current_len = CORD_len(current);
+}
+
+/* Current screen_contents; a dynamically allocated array of CORDs */
+CORD * screen = 0;
+int screen_size = 0;
+
+# ifndef WIN32
+/* Replace a line in the curses stdscr. All control characters are */
+/* displayed as upper case characters in standout mode. This isn't */
+/* terribly appropriate for tabs. */
+void replace_line(int i, CORD s)
+{
+ register int c;
+ CORD_pos p;
+ size_t len = CORD_len(s);
+
+ if (screen == 0 || LINES > screen_size) {
+ screen_size = LINES;
+ screen = (CORD *)GC_MALLOC(screen_size * sizeof(CORD));
+ }
+# if !defined(MACINTOSH)
+ /* A gross workaround for an apparent curses bug: */
+ if (i == LINES-1 && len == COLS) {
+ s = CORD_substr(s, 0, CORD_len(s) - 1);
+ }
+# endif
+ if (CORD_cmp(screen[i], s) != 0) {
+ move(i, 0); clrtoeol(); move(i,0);
+
+ CORD_FOR (p, s) {
+ c = CORD_pos_fetch(p) & 0x7f;
+ if (iscntrl(c)) {
+ standout(); addch(c + 0x40); standend();
+ } else {
+ addch(c);
+ }
+ }
+ screen[i] = s;
+ }
+}
+#else
+# define replace_line(i,s) invalidate_line(i)
+#endif
+
+/* Return up to COLS characters of the line of s starting at pos, */
+/* returning only characters after the given column. */
+CORD retrieve_line(CORD s, size_t pos, unsigned column)
+{
+ CORD candidate = CORD_substr(s, pos, column + COLS);
+ /* avoids scanning very long lines */
+ int eol = CORD_chr(candidate, 0, '\n');
+ int len;
+
+ if (eol == CORD_NOT_FOUND) eol = CORD_len(candidate);
+ len = (int)eol - (int)column;
+ if (len < 0) len = 0;
+ return(CORD_substr(s, pos + column, len));
+}
+
+# ifdef WIN32
+# define refresh();
+
+ CORD retrieve_screen_line(int i)
+ {
+ register size_t pos;
+
+ invalidate_map(dis_line + LINES); /* Prune search */
+ pos = line_pos(dis_line + i, 0);
+ if (pos == CORD_NOT_FOUND) return(CORD_EMPTY);
+ return(retrieve_line(current, pos, dis_col));
+ }
+# endif
+
+/* Display the visible section of the current file */
+void redisplay(void)
+{
+ register int i;
+
+ invalidate_map(dis_line + LINES); /* Prune search */
+ for (i = 0; i < LINES; i++) {
+ if (need_redisplay == ALL || need_redisplay == i) {
+ register size_t pos = line_pos(dis_line + i, 0);
+
+ if (pos == CORD_NOT_FOUND) break;
+ replace_line(i, retrieve_line(current, pos, dis_col));
+ if (need_redisplay == i) goto done;
+ }
+ }
+ for (; i < LINES; i++) replace_line(i, CORD_EMPTY);
+done:
+ refresh();
+ need_redisplay = NONE;
+}
+
+int dis_granularity;
+
+/* Update dis_line, dis_col, and dis_pos to make cursor visible. */
+/* Assumes line, col, dis_line, dis_pos are in bounds. */
+void normalize_display()
+{
+ int old_line = dis_line;
+ int old_col = dis_col;
+
+ dis_granularity = 1;
+ if (LINES > 15 && COLS > 15) dis_granularity = 2;
+ while (dis_line > line) dis_line -= dis_granularity;
+ while (dis_col > col) dis_col -= dis_granularity;
+ while (line >= dis_line + LINES) dis_line += dis_granularity;
+ while (col >= dis_col + COLS) dis_col += dis_granularity;
+ if (old_line != dis_line || old_col != dis_col) {
+ need_redisplay = ALL;
+ }
+}
+
+# if defined(WIN32)
+# elif defined(MACINTOSH)
+# define move_cursor(x,y) cgotoxy(x + 1, y + 1, stdout)
+# else
+# define move_cursor(x,y) move(y,x)
+# endif
+
+/* Adjust display so that cursor is visible; move cursor into position */
+/* Update screen if necessary. */
+void fix_cursor(void)
+{
+ normalize_display();
+ if (need_redisplay != NONE) redisplay();
+ move_cursor(col - dis_col, line - dis_line);
+ refresh();
+# ifndef WIN32
+ fflush(stdout);
+# endif
+}
+
+/* Make sure line, col, and dis_pos are somewhere inside file. */
+/* Recompute file_pos. Assumes dis_pos is accurate or past eof */
+void fix_pos()
+{
+ int my_col = col;
+
+ if ((size_t)line > current_len) line = current_len;
+ file_pos = line_pos(line, &my_col);
+ if (file_pos == CORD_NOT_FOUND) {
+ for (line = current_map -> line, file_pos = current_map -> pos;
+ file_pos < current_len;
+ line++, file_pos = CORD_chr(current, file_pos, '\n') + 1);
+ line--;
+ file_pos = line_pos(line, &col);
+ } else {
+ col = my_col;
+ }
+}
+
+#if defined(WIN32)
+# define beep() Beep(1000 /* Hz */, 300 /* msecs */)
+#elif defined(MACINTOSH)
+# define beep() SysBeep(1)
+#else
+/*
+ * beep() is part of some curses packages and not others.
+ * We try to match the type of the builtin one, if any.
+ */
+#ifdef __STDC__
+ int beep(void)
+#else
+ int beep()
+#endif
+{
+ putc('\007', stderr);
+ return(0);
+}
+#endif
+
+# define NO_PREFIX -1
+# define BARE_PREFIX -2
+int repeat_count = NO_PREFIX; /* Current command prefix. */
+
+int locate_mode = 0; /* Currently between 2 ^Ls */
+CORD locate_string = CORD_EMPTY; /* Current search string. */
+
+char * arg_file_name;
+
+#ifdef WIN32
+/* Change the current position to whatever is currently displayed at */
+/* the given SCREEN coordinates. */
+void set_position(int c, int l)
+{
+ line = l + dis_line;
+ col = c + dis_col;
+ fix_pos();
+ move_cursor(col - dis_col, line - dis_line);
+}
+#endif /* WIN32 */
+
+/* Perform the command associated with character c. C may be an */
+/* integer > 256 denoting a windows command, one of the above control */
+/* characters, or another ASCII character to be used as either a */
+/* character to be inserted, a repeat count, or a search string, */
+/* depending on the current state. */
+void do_command(int c)
+{
+ int i;
+ int need_fix_pos;
+ FILE * out;
+
+ if ( c == '\r') c = '\n';
+ if (locate_mode) {
+ size_t new_pos;
+
+ if (c == LOCATE) {
+ locate_mode = 0;
+ locate_string = CORD_EMPTY;
+ return;
+ }
+ locate_string = CORD_cat_char(locate_string, (char)c);
+ new_pos = CORD_str(current, file_pos - CORD_len(locate_string) + 1,
+ locate_string);
+ if (new_pos != CORD_NOT_FOUND) {
+ need_redisplay = ALL;
+ new_pos += CORD_len(locate_string);
+ for (;;) {
+ file_pos = line_pos(line + 1, 0);
+ if (file_pos > new_pos) break;
+ line++;
+ }
+ col = new_pos - line_pos(line, 0);
+ file_pos = new_pos;
+ fix_cursor();
+ } else {
+ locate_string = CORD_substr(locate_string, 0,
+ CORD_len(locate_string) - 1);
+ beep();
+ }
+ return;
+ }
+ if (c == REPEAT) {
+ repeat_count = BARE_PREFIX; return;
+ } else if (c < 0x100 && isdigit(c)){
+ if (repeat_count == BARE_PREFIX) {
+ repeat_count = c - '0'; return;
+ } else if (repeat_count != NO_PREFIX) {
+ repeat_count = 10 * repeat_count + c - '0'; return;
+ }
+ }
+ if (repeat_count == NO_PREFIX) repeat_count = 1;
+ if (repeat_count == BARE_PREFIX && (c == UP || c == DOWN)) {
+ repeat_count = LINES - dis_granularity;
+ }
+ if (repeat_count == BARE_PREFIX) repeat_count = 8;
+ need_fix_pos = 0;
+ for (i = 0; i < repeat_count; i++) {
+ switch(c) {
+ case LOCATE:
+ locate_mode = 1;
+ break;
+ case TOP:
+ line = col = file_pos = 0;
+ break;
+ case UP:
+ if (line != 0) {
+ line--;
+ need_fix_pos = 1;
+ }
+ break;
+ case DOWN:
+ line++;
+ need_fix_pos = 1;
+ break;
+ case LEFT:
+ if (col != 0) {
+ col--; file_pos--;
+ }
+ break;
+ case RIGHT:
+ if (CORD_fetch(current, file_pos) == '\n') break;
+ col++; file_pos++;
+ break;
+ case UNDO:
+ del_hist();
+ need_redisplay = ALL; need_fix_pos = 1;
+ break;
+ case BS:
+ if (col == 0) {
+ beep();
+ break;
+ }
+ col--; file_pos--;
+ /* fall through: */
+ case DEL:
+ if (file_pos == current_len-1) break;
+ /* Can't delete trailing newline */
+ if (CORD_fetch(current, file_pos) == '\n') {
+ need_redisplay = ALL; need_fix_pos = 1;
+ } else {
+ need_redisplay = line - dis_line;
+ }
+ add_hist(CORD_cat(
+ CORD_substr(current, 0, file_pos),
+ CORD_substr(current, file_pos+1, current_len)));
+ invalidate_map(line);
+ break;
+ case WRITE:
+ {
+ CORD name = CORD_cat(CORD_from_char_star(arg_file_name),
+ ".new");
+
+ if ((out = fopen(CORD_to_const_char_star(name), "wb")) == NULL
+ || CORD_put(current, out) == EOF) {
+ de_error("Write failed\n");
+ need_redisplay = ALL;
+ } else {
+ fclose(out);
+ }
+ }
+ break;
+ default:
+ {
+ CORD left_part = CORD_substr(current, 0, file_pos);
+ CORD right_part = CORD_substr(current, file_pos, current_len);
+
+ add_hist(CORD_cat(CORD_cat_char(left_part, (char)c),
+ right_part));
+ invalidate_map(line);
+ if (c == '\n') {
+ col = 0; line++; file_pos++;
+ need_redisplay = ALL;
+ } else {
+ col++; file_pos++;
+ need_redisplay = line - dis_line;
+ }
+ break;
+ }
+ }
+ }
+ if (need_fix_pos) fix_pos();
+ fix_cursor();
+ repeat_count = NO_PREFIX;
+}
+
+/* OS independent initialization */
+
+void generic_init(void)
+{
+ FILE * f;
+ CORD initial;
+
+ if ((f = fopen(arg_file_name, "rb")) == NULL) {
+ initial = "\n";
+ } else {
+ initial = CORD_from_file(f);
+ if (initial == CORD_EMPTY
+ || CORD_fetch(initial, CORD_len(initial)-1) != '\n') {
+ initial = CORD_cat(initial, "\n");
+ }
+ }
+ add_map(0,0);
+ add_hist(initial);
+ now -> map = current_map;
+ now -> previous = now; /* Can't back up further: beginning of the world */
+ need_redisplay = ALL;
+ fix_cursor();
+}
+
+#ifndef WIN32
+
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ int c;
+
+#if defined(MACINTOSH)
+ console_options.title = "\pDumb Editor";
+ cshow(stdout);
+ argc = ccommand(&argv);
+#endif
+ GC_INIT();
+
+ if (argc != 2) goto usage;
+ arg_file_name = argv[1];
+ setvbuf(stdout, GC_MALLOC_ATOMIC(8192), _IOFBF, 8192);
+ initscr();
+ noecho(); nonl(); cbreak();
+ generic_init();
+ while ((c = getchar()) != QUIT) {
+ if (c == EOF) break;
+ do_command(c);
+ }
+done:
+ move(LINES-1, 0);
+ clrtoeol();
+ refresh();
+ nl();
+ echo();
+ endwin();
+ exit(0);
+usage:
+ fprintf(stderr, "Usage: %s file\n", argv[0]);
+ fprintf(stderr, "Cursor keys: ^B(left) ^F(right) ^P(up) ^N(down)\n");
+ fprintf(stderr, "Undo: ^U Write to <file>.new: ^W");
+ fprintf(stderr, "Quit:^D Repeat count: ^R[n]\n");
+ fprintf(stderr, "Top: ^T Locate (search, find): ^L text ^L\n");
+ exit(1);
+}
+
+#endif /* !WIN32 */
diff --git a/tools/build/v2/engine/boehm_gc/cord/de_cmds.h b/tools/build/v2/engine/boehm_gc/cord/de_cmds.h
new file mode 100644
index 0000000000..f42ddcf2da
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/cord/de_cmds.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, May 19, 1994 2:24 pm PDT */
+
+#ifndef DE_CMDS_H
+
+# define DE_CMDS_H
+
+# define UP 16 /* ^P */
+# define DOWN 14 /* ^N */
+# define LEFT 2 /* ^B */
+# define RIGHT 6 /* ^F */
+# define DEL 127 /* ^? */
+# define BS 8 /* ^H */
+# define UNDO 21 /* ^U */
+# define WRITE 23 /* ^W */
+# define QUIT 4 /* ^D */
+# define REPEAT 18 /* ^R */
+# define LOCATE 12 /* ^L */
+# define TOP 20 /* ^T */
+
+#endif
+
diff --git a/tools/build/v2/engine/boehm_gc/cord/de_win.ICO b/tools/build/v2/engine/boehm_gc/cord/de_win.ICO
new file mode 100644
index 0000000000..b20ac3ee16
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/cord/de_win.ICO
Binary files differ
diff --git a/tools/build/v2/engine/boehm_gc/cord/de_win.RC b/tools/build/v2/engine/boehm_gc/cord/de_win.RC
new file mode 100644
index 0000000000..554a300438
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/cord/de_win.RC
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to copy this garbage collector for any purpose,
+ * provided the above notices are retained on all copies.
+ */
+/* Boehm, May 13, 1994 9:50 am PDT */
+
+#include "windows.h"
+#include "de_cmds.h"
+#include "de_win.h"
+
+
+
+ABOUTBOX DIALOG 19, 21, 163, 47
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About Demonstration Text Editor"
+BEGIN
+ ICON "DE", -1, 8, 8, 13, 13, WS_CHILD | WS_VISIBLE
+ LTEXT "Demonstration Text Editor", -1, 44, 8, 118, 8, WS_CHILD | WS_VISIBLE | WS_GROUP
+ LTEXT "Version 4.1", -1, 44, 16, 60, 8, WS_CHILD | WS_VISIBLE | WS_GROUP
+ PUSHBUTTON "OK", IDOK, 118, 27, 24, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+END
+
+
+DE MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&Save\t^W", IDM_FILESAVE
+ MENUITEM "E&xit\t^D", IDM_FILEEXIT
+ END
+
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "Page &Down\t^R^N", IDM_EDITPDOWN
+ MENUITEM "Page &Up\t^R^P", IDM_EDITPUP
+ MENUITEM "U&ndo\t^U", IDM_EDITUNDO
+ MENUITEM "&Locate\t^L ... ^L", IDM_EDITLOCATE
+ MENUITEM "D&own\t^N", IDM_EDITDOWN
+ MENUITEM "U&p\t^P", IDM_EDITUP
+ MENUITEM "Le&ft\t^B", IDM_EDITLEFT
+ MENUITEM "&Right\t^F", IDM_EDITRIGHT
+ MENUITEM "Delete &Backward\tBS", IDM_EDITBS
+ MENUITEM "Delete F&orward\tDEL", IDM_EDITDEL
+ MENUITEM "&Top\t^T", IDM_EDITTOP
+ END
+
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&Contents", IDM_HELPCONTENTS
+ MENUITEM "&About...", IDM_HELPABOUT
+ END
+
+ MENUITEM "Page_&Down", IDM_EDITPDOWN
+ MENUITEM "Page_&Up", IDM_EDITPUP
+END
+
+
+DE ACCELERATORS
+BEGIN
+ "^R", IDM_EDITREPEAT
+ "^N", IDM_EDITDOWN
+ "^P", IDM_EDITUP
+ "^L", IDM_EDITLOCATE
+ "^B", IDM_EDITLEFT
+ "^F", IDM_EDITRIGHT
+ "^T", IDM_EDITTOP
+ VK_DELETE, IDM_EDITDEL, VIRTKEY
+ VK_BACK, IDM_EDITBS, VIRTKEY
+END
+
+
+DE ICON cord\de_win.ICO
+
diff --git a/tools/build/v2/engine/boehm_gc/cord/de_win.c b/tools/build/v2/engine/boehm_gc/cord/de_win.c
new file mode 100644
index 0000000000..1871736e39
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/cord/de_win.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, February 6, 1995 12:29 pm PST */
+
+/*
+ * The MS Windows specific part of de.
+ * This started as the generic Windows application template
+ * made available by Rob Haack (rhaack@polaris.unm.edu), but
+ * significant parts didn't survive to the final version.
+ *
+ * This was written by a nonexpert windows programmer.
+ */
+
+
+#include "windows.h"
+#include "gc.h"
+#include "cord.h"
+#include "de_cmds.h"
+#include "de_win.h"
+
+int LINES = 0;
+int COLS = 0;
+
+char szAppName[] = "DE";
+char FullAppName[] = "Demonstration Editor";
+
+HWND hwnd;
+
+void de_error(char *s)
+{
+ MessageBox( hwnd, (LPSTR) s,
+ (LPSTR) FullAppName,
+ MB_ICONINFORMATION | MB_OK );
+ InvalidateRect(hwnd, NULL, TRUE);
+}
+
+int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR command_line, int nCmdShow)
+{
+ MSG msg;
+ WNDCLASS wndclass;
+ HANDLE hAccel;
+
+# ifdef THREAD_LOCAL_ALLOC
+ GC_INIT(); /* Required if GC is built with THREAD_LOCAL_ALLOC */
+ /* Always safe, but this is used as a GC test. */
+# endif
+
+ if (!hPrevInstance)
+ {
+ wndclass.style = CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = DLGWINDOWEXTRA;
+ wndclass.hInstance = hInstance;
+ wndclass.hIcon = LoadIcon (hInstance, szAppName);
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
+ wndclass.lpszMenuName = "DE";
+ wndclass.lpszClassName = szAppName;
+
+ if (RegisterClass (&wndclass) == 0) {
+ char buf[50];
+
+ sprintf(buf, "RegisterClass: error code: 0x%X", GetLastError());
+ de_error(buf);
+ return(0);
+ }
+ }
+
+ /* Empirically, the command line does not include the command name ...
+ if (command_line != 0) {
+ while (isspace(*command_line)) command_line++;
+ while (*command_line != 0 && !isspace(*command_line)) command_line++;
+ while (isspace(*command_line)) command_line++;
+ } */
+
+ if (command_line == 0 || *command_line == 0) {
+ de_error("File name argument required");
+ return( 0 );
+ } else {
+ char *p = command_line;
+
+ while (*p != 0 && !isspace(*p)) p++;
+ arg_file_name = CORD_to_char_star(
+ CORD_substr(command_line, 0, p - command_line));
+ }
+
+ hwnd = CreateWindow (szAppName,
+ FullAppName,
+ WS_OVERLAPPEDWINDOW | WS_CAPTION, /* Window style */
+ CW_USEDEFAULT, 0, /* default pos. */
+ CW_USEDEFAULT, 0, /* default width, height */
+ NULL, /* No parent */
+ NULL, /* Window class menu */
+ hInstance, NULL);
+ if (hwnd == NULL) {
+ char buf[50];
+
+ sprintf(buf, "CreateWindow: error code: 0x%X", GetLastError());
+ de_error(buf);
+ return(0);
+ }
+
+ ShowWindow (hwnd, nCmdShow);
+
+ hAccel = LoadAccelerators( hInstance, szAppName );
+
+ while (GetMessage (&msg, NULL, 0, 0))
+ {
+ if( !TranslateAccelerator( hwnd, hAccel, &msg ) )
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ }
+ return msg.wParam;
+}
+
+/* Return the argument with all control characters replaced by blanks. */
+char * plain_chars(char * text, size_t len)
+{
+ char * result = GC_MALLOC_ATOMIC(len + 1);
+ register size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (iscntrl(text[i])) {
+ result[i] = ' ';
+ } else {
+ result[i] = text[i];
+ }
+ }
+ result[len] = '\0';
+ return(result);
+}
+
+/* Return the argument with all non-control-characters replaced by */
+/* blank, and all control characters c replaced by c + 32. */
+char * control_chars(char * text, size_t len)
+{
+ char * result = GC_MALLOC_ATOMIC(len + 1);
+ register size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (iscntrl(text[i])) {
+ result[i] = text[i] + 0x40;
+ } else {
+ result[i] = ' ';
+ }
+ }
+ result[len] = '\0';
+ return(result);
+}
+
+int char_width;
+int char_height;
+
+void get_line_rect(int line, int win_width, RECT * rectp)
+{
+ rectp -> top = line * char_height;
+ rectp -> bottom = rectp->top + char_height;
+ rectp -> left = 0;
+ rectp -> right = win_width;
+}
+
+int caret_visible = 0; /* Caret is currently visible. */
+
+int screen_was_painted = 0;/* Screen has been painted at least once. */
+
+void update_cursor(void);
+
+INT_PTR CALLBACK AboutBoxCallback( HWND hDlg, UINT message,
+ WPARAM wParam, LPARAM lParam )
+{
+ switch( message )
+ {
+ case WM_INITDIALOG:
+ SetFocus( GetDlgItem( hDlg, IDOK ) );
+ break;
+
+ case WM_COMMAND:
+ switch( wParam )
+ {
+ case IDOK:
+ EndDialog( hDlg, TRUE );
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog( hDlg, TRUE );
+ return TRUE;
+
+ }
+ return FALSE;
+}
+
+LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ static HANDLE hInstance;
+ HDC dc;
+ PAINTSTRUCT ps;
+ RECT client_area;
+ RECT this_line;
+ RECT dummy;
+ TEXTMETRIC tm;
+ register int i;
+ int id;
+
+ switch (message)
+ {
+ case WM_CREATE:
+ hInstance = ( (LPCREATESTRUCT) lParam)->hInstance;
+ dc = GetDC(hwnd);
+ SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
+ GetTextMetrics(dc, &tm);
+ ReleaseDC(hwnd, dc);
+ char_width = tm.tmAveCharWidth;
+ char_height = tm.tmHeight + tm.tmExternalLeading;
+ GetClientRect(hwnd, &client_area);
+ COLS = (client_area.right - client_area.left)/char_width;
+ LINES = (client_area.bottom - client_area.top)/char_height;
+ generic_init();
+ return(0);
+
+ case WM_CHAR:
+ if (wParam == QUIT) {
+ SendMessage( hwnd, WM_CLOSE, 0, 0L );
+ } else {
+ do_command((int)wParam);
+ }
+ return(0);
+
+ case WM_SETFOCUS:
+ CreateCaret(hwnd, NULL, char_width, char_height);
+ ShowCaret(hwnd);
+ caret_visible = 1;
+ update_cursor();
+ return(0);
+
+ case WM_KILLFOCUS:
+ HideCaret(hwnd);
+ DestroyCaret();
+ caret_visible = 0;
+ return(0);
+
+ case WM_LBUTTONUP:
+ {
+ unsigned xpos = LOWORD(lParam); /* From left */
+ unsigned ypos = HIWORD(lParam); /* from top */
+
+ set_position( xpos/char_width, ypos/char_height );
+ return(0);
+ }
+
+ case WM_COMMAND:
+ id = LOWORD(wParam);
+ if (id & EDIT_CMD_FLAG) {
+ if (id & REPEAT_FLAG) do_command(REPEAT);
+ do_command(CHAR_CMD(id));
+ return( 0 );
+ } else {
+ switch(id) {
+ case IDM_FILEEXIT:
+ SendMessage( hwnd, WM_CLOSE, 0, 0L );
+ return( 0 );
+
+ case IDM_HELPABOUT:
+ if( DialogBox( hInstance, "ABOUTBOX",
+ hwnd, AboutBoxCallback ) )
+ InvalidateRect( hwnd, NULL, TRUE );
+ return( 0 );
+ case IDM_HELPCONTENTS:
+ de_error(
+ "Cursor keys: ^B(left) ^F(right) ^P(up) ^N(down)\n"
+ "Undo: ^U Write: ^W Quit:^D Repeat count: ^R[n]\n"
+ "Top: ^T Locate (search, find): ^L text ^L\n");
+ return( 0 );
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow( hwnd );
+ return 0;
+
+ case WM_DESTROY:
+ PostQuitMessage (0);
+ GC_win32_free_heap();
+ return 0;
+
+ case WM_PAINT:
+ dc = BeginPaint(hwnd, &ps);
+ GetClientRect(hwnd, &client_area);
+ COLS = (client_area.right - client_area.left)/char_width;
+ LINES = (client_area.bottom - client_area.top)/char_height;
+ SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
+ for (i = 0; i < LINES; i++) {
+ get_line_rect(i, client_area.right, &this_line);
+ if (IntersectRect(&dummy, &this_line, &ps.rcPaint)) {
+ CORD raw_line = retrieve_screen_line(i);
+ size_t len = CORD_len(raw_line);
+ char * text = CORD_to_char_star(raw_line);
+ /* May contain embedded NULLs */
+ char * plain = plain_chars(text, len);
+ char * blanks = CORD_to_char_star(CORD_chars(' ',
+ COLS - len));
+ char * control = control_chars(text, len);
+# define RED RGB(255,0,0)
+
+ SetBkMode(dc, OPAQUE);
+ SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));
+
+ TextOut(dc, this_line.left, this_line.top,
+ plain, (int)len);
+ TextOut(dc, this_line.left + (int)len * char_width,
+ this_line.top,
+ blanks, (int)(COLS - len));
+ SetBkMode(dc, TRANSPARENT);
+ SetTextColor(dc, RED);
+ TextOut(dc, this_line.left, this_line.top,
+ control, (int)strlen(control));
+ }
+ }
+ EndPaint(hwnd, &ps);
+ screen_was_painted = 1;
+ return 0;
+ }
+ return DefWindowProc (hwnd, message, wParam, lParam);
+}
+
+int last_col;
+int last_line;
+
+void move_cursor(int c, int l)
+{
+ last_col = c;
+ last_line = l;
+
+ if (caret_visible) update_cursor();
+}
+
+void update_cursor(void)
+{
+ SetCaretPos(last_col * char_width, last_line * char_height);
+ ShowCaret(hwnd);
+}
+
+void invalidate_line(int i)
+{
+ RECT line;
+
+ if (!screen_was_painted) return;
+ /* Invalidating a rectangle before painting seems result in a */
+ /* major performance problem. */
+ get_line_rect(i, COLS*char_width, &line);
+ InvalidateRect(hwnd, &line, FALSE);
+}
+
diff --git a/tools/build/v2/engine/boehm_gc/cord/de_win.h b/tools/build/v2/engine/boehm_gc/cord/de_win.h
new file mode 100644
index 0000000000..57a47b45c4
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/cord/de_win.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, May 19, 1994 2:25 pm PDT */
+
+/* cord.h, de_cmds.h, and windows.h should be included before this. */
+
+
+# define OTHER_FLAG 0x100
+# define EDIT_CMD_FLAG 0x200
+# define REPEAT_FLAG 0x400
+
+# define CHAR_CMD(i) ((i) & 0xff)
+
+/* MENU: DE */
+#define IDM_FILESAVE (EDIT_CMD_FLAG + WRITE)
+#define IDM_FILEEXIT (OTHER_FLAG + 1)
+#define IDM_HELPABOUT (OTHER_FLAG + 2)
+#define IDM_HELPCONTENTS (OTHER_FLAG + 3)
+
+#define IDM_EDITPDOWN (REPEAT_FLAG + EDIT_CMD_FLAG + DOWN)
+#define IDM_EDITPUP (REPEAT_FLAG + EDIT_CMD_FLAG + UP)
+#define IDM_EDITUNDO (EDIT_CMD_FLAG + UNDO)
+#define IDM_EDITLOCATE (EDIT_CMD_FLAG + LOCATE)
+#define IDM_EDITDOWN (EDIT_CMD_FLAG + DOWN)
+#define IDM_EDITUP (EDIT_CMD_FLAG + UP)
+#define IDM_EDITLEFT (EDIT_CMD_FLAG + LEFT)
+#define IDM_EDITRIGHT (EDIT_CMD_FLAG + RIGHT)
+#define IDM_EDITBS (EDIT_CMD_FLAG + BS)
+#define IDM_EDITDEL (EDIT_CMD_FLAG + DEL)
+#define IDM_EDITREPEAT (EDIT_CMD_FLAG + REPEAT)
+#define IDM_EDITTOP (EDIT_CMD_FLAG + TOP)
+
+
+
+
+/* Windows UI stuff */
+
+LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
+ UINT wParam, LONG lParam);
+
+LRESULT CALLBACK AboutBox( HWND hDlg, UINT message,
+ UINT wParam, LONG lParam );
+
+
+/* Screen dimensions. Maintained by de_win.c. */
+extern int LINES;
+extern int COLS;
+
+/* File being edited. */
+extern char * arg_file_name;
+
+/* Current display position in file. Maintained by de.c */
+extern int dis_line;
+extern int dis_col;
+
+/* Current cursor position in file. */
+extern int line;
+extern int col;
+
+/*
+ * Calls from de_win.c to de.c
+ */
+
+CORD retrieve_screen_line(int i);
+ /* Get the contents of i'th screen line. */
+ /* Relies on COLS. */
+
+void set_position(int x, int y);
+ /* Set column, row. Upper left of window = (0,0). */
+
+void do_command(int);
+ /* Execute an editor command. */
+ /* Agument is a command character or one */
+ /* of the IDM_ commands. */
+
+void generic_init(void);
+ /* OS independent initialization */
+
+
+/*
+ * Calls from de.c to de_win.c
+ */
+
+void move_cursor(int column, int line);
+ /* Physically move the cursor on the display, */
+ /* so that it appears at */
+ /* (column, line). */
+
+void invalidate_line(int line);
+ /* Invalidate line i on the screen. */
+
+void de_error(char *s);
+ /* Display error message. */ \ No newline at end of file
diff --git a/tools/build/v2/engine/boehm_gc/darwin_stop_world.c b/tools/build/v2/engine/boehm_gc/darwin_stop_world.c
new file mode 100644
index 0000000000..a2f0926453
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/darwin_stop_world.c
@@ -0,0 +1,599 @@
+#include "private/pthread_support.h"
+
+/* This probably needs more porting work to ppc64. */
+
+# if defined(GC_DARWIN_THREADS)
+
+/* From "Inside Mac OS X - Mach-O Runtime Architecture" published by Apple
+ Page 49:
+ "The space beneath the stack pointer, where a new stack frame would normally
+ be allocated, is called the red zone. This area as shown in Figure 3-2 may
+ be used for any purpose as long as a new stack frame does not need to be
+ added to the stack."
+
+ Page 50: "If a leaf procedure's red zone usage would exceed 224 bytes, then
+ it must set up a stack frame just like routines that call other routines."
+*/
+#ifdef POWERPC
+# if CPP_WORDSZ == 32
+# define PPC_RED_ZONE_SIZE 224
+# elif CPP_WORDSZ == 64
+# define PPC_RED_ZONE_SIZE 320
+# endif
+#endif
+
+typedef struct StackFrame {
+ unsigned long savedSP;
+ unsigned long savedCR;
+ unsigned long savedLR;
+ unsigned long reserved[2];
+ unsigned long savedRTOC;
+} StackFrame;
+
+unsigned long FindTopOfStack(unsigned long stack_start)
+{
+ StackFrame *frame;
+
+ if (stack_start == 0) {
+# ifdef POWERPC
+# if CPP_WORDSZ == 32
+ __asm__ volatile("lwz %0,0(r1)" : "=r" (frame));
+# else
+ __asm__ volatile("ld %0,0(r1)" : "=r" (frame));
+# endif
+# endif
+ } else {
+ frame = (StackFrame *)stack_start;
+ }
+
+# ifdef DEBUG_THREADS
+ /* GC_printf("FindTopOfStack start at sp = %p\n", frame); */
+# endif
+ do {
+ if (frame->savedSP == 0)
+ break;
+ /* if there are no more stack frames, stop */
+
+ frame = (StackFrame*)frame->savedSP;
+
+ /* we do these next two checks after going to the next frame
+ because the LR for the first stack frame in the loop
+ is not set up on purpose, so we shouldn't check it. */
+ if ((frame->savedLR & ~3) == 0)
+ break; /* if the next LR is bogus, stop */
+ if ((~(frame->savedLR) & ~3) == 0)
+ break; /* ditto */
+ } while (1);
+
+# ifdef DEBUG_THREADS
+ /* GC_printf("FindTopOfStack finish at sp = %p\n", frame); */
+# endif
+
+ return (unsigned long)frame;
+}
+
+#ifdef DARWIN_DONT_PARSE_STACK
+void GC_push_all_stacks()
+{
+ int i;
+ kern_return_t r;
+ GC_thread p;
+ pthread_t me;
+ ptr_t lo, hi;
+ GC_THREAD_STATE_T state;
+ /* MACHINE_THREAD_STATE_COUNT doesn't seem to be defined everywhere. */
+ /* Hence we use our own version. */
+ mach_msg_type_number_t thread_state_count = GC_MACH_THREAD_STATE_COUNT;
+
+ me = pthread_self();
+ if (!GC_thr_initialized)
+ GC_thr_init();
+
+ for(i = 0; i < THREAD_TABLE_SZ; i++) {
+ for(p = GC_threads[i]; p != 0; p = p->next) {
+ if(p->flags & FINISHED) continue;
+ if(pthread_equal(p->id, me)) {
+ lo = GC_approx_sp();
+ } else {
+ /* Get the thread state (registers, etc) */
+ r = thread_get_state(p->stop_info.mach_thread, GC_MACH_THREAD_STATE,
+ (natural_t*)&state, &thread_state_count);
+
+# ifdef DEBUG_THREADS
+ GC_printf("thread_get_state return value = %d\n", r);
+# endif
+
+ if(r != KERN_SUCCESS)
+ ABORT("thread_get_state failed");
+
+# if defined(I386)
+ lo = (void*)state . THREAD_FLD (esp);
+ GC_push_one(state . THREAD_FLD (eax));
+ GC_push_one(state . THREAD_FLD (ebx));
+ GC_push_one(state . THREAD_FLD (ecx));
+ GC_push_one(state . THREAD_FLD (edx));
+ GC_push_one(state . THREAD_FLD (edi));
+ GC_push_one(state . THREAD_FLD (esi));
+ GC_push_one(state . THREAD_FLD (ebp));
+
+# elif defined(X86_64)
+ lo = (void*)state . THREAD_FLD (rsp);
+ GC_push_one(state . THREAD_FLD (rax));
+ GC_push_one(state . THREAD_FLD (rbx));
+ GC_push_one(state . THREAD_FLD (rcx));
+ GC_push_one(state . THREAD_FLD (rdx));
+ GC_push_one(state . THREAD_FLD (rdi));
+ GC_push_one(state . THREAD_FLD (rsi));
+ GC_push_one(state . THREAD_FLD (rbp));
+ GC_push_one(state . THREAD_FLD (rsp));
+ GC_push_one(state . THREAD_FLD (r8));
+ GC_push_one(state . THREAD_FLD (r9));
+ GC_push_one(state . THREAD_FLD (r10));
+ GC_push_one(state . THREAD_FLD (r11));
+ GC_push_one(state . THREAD_FLD (r12));
+ GC_push_one(state . THREAD_FLD (r13));
+ GC_push_one(state . THREAD_FLD (r14));
+ GC_push_one(state . THREAD_FLD (r15));
+ GC_push_one(state . THREAD_FLD (rip));
+ GC_push_one(state . THREAD_FLD (rflags));
+ GC_push_one(state . THREAD_FLD (cs));
+ GC_push_one(state . THREAD_FLD (fs));
+ GC_push_one(state . THREAD_FLD (gs));
+
+# elif defined(POWERPC)
+ lo = (void*)(state . THREAD_FLD (r1) - PPC_RED_ZONE_SIZE);
+
+ GC_push_one(state . THREAD_FLD (r0));
+ GC_push_one(state . THREAD_FLD (r2));
+ GC_push_one(state . THREAD_FLD (r3));
+ GC_push_one(state . THREAD_FLD (r4));
+ GC_push_one(state . THREAD_FLD (r5));
+ GC_push_one(state . THREAD_FLD (r6));
+ GC_push_one(state . THREAD_FLD (r7));
+ GC_push_one(state . THREAD_FLD (r8));
+ GC_push_one(state . THREAD_FLD (r9));
+ GC_push_one(state . THREAD_FLD (r10));
+ GC_push_one(state . THREAD_FLD (r11));
+ GC_push_one(state . THREAD_FLD (r12));
+ GC_push_one(state . THREAD_FLD (r13));
+ GC_push_one(state . THREAD_FLD (r14));
+ GC_push_one(state . THREAD_FLD (r15));
+ GC_push_one(state . THREAD_FLD (r16));
+ GC_push_one(state . THREAD_FLD (r17));
+ GC_push_one(state . THREAD_FLD (r18));
+ GC_push_one(state . THREAD_FLD (r19));
+ GC_push_one(state . THREAD_FLD (r20));
+ GC_push_one(state . THREAD_FLD (r21));
+ GC_push_one(state . THREAD_FLD (r22));
+ GC_push_one(state . THREAD_FLD (r23));
+ GC_push_one(state . THREAD_FLD (r24));
+ GC_push_one(state . THREAD_FLD (r25));
+ GC_push_one(state . THREAD_FLD (r26));
+ GC_push_one(state . THREAD_FLD (r27));
+ GC_push_one(state . THREAD_FLD (r28));
+ GC_push_one(state . THREAD_FLD (r29));
+ GC_push_one(state . THREAD_FLD (r30));
+ GC_push_one(state . THREAD_FLD (r31));
+# else
+# error FIXME for non-x86 || ppc architectures
+# endif
+ } /* p != me */
+ if(p->flags & MAIN_THREAD)
+ hi = GC_stackbottom;
+ else
+ hi = p->stack_end;
+# if DEBUG_THREADS
+ GC_printf("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n",
+ (unsigned long) p -> id, (unsigned long) lo,
+ (unsigned long) hi);
+# endif
+ GC_push_all_stack(lo, hi);
+ } /* for(p=GC_threads[i]...) */
+ } /* for(i=0;i<THREAD_TABLE_SZ...) */
+}
+
+#else /* !DARWIN_DONT_PARSE_STACK; Use FindTopOfStack() */
+
+void GC_push_all_stacks()
+{
+ unsigned int i;
+ task_t my_task;
+ kern_return_t r;
+ mach_port_t me;
+ ptr_t lo, hi;
+ thread_act_array_t act_list = 0;
+ mach_msg_type_number_t listcount = 0;
+
+ me = mach_thread_self();
+ if (!GC_thr_initialized)
+ GC_thr_init();
+
+ my_task = current_task();
+ r = task_threads(my_task, &act_list, &listcount);
+ if(r != KERN_SUCCESS)
+ ABORT("task_threads failed");
+ for(i = 0; i < listcount; i++) {
+ thread_act_t thread = act_list[i];
+ if (thread == me) {
+ lo = GC_approx_sp();
+ hi = (ptr_t)FindTopOfStack(0);
+ } else {
+# if defined(POWERPC)
+ GC_THREAD_STATE_T info;
+ mach_msg_type_number_t outCount = THREAD_STATE_MAX;
+ r = thread_get_state(thread, GC_MACH_THREAD_STATE, (natural_t *)&info,
+ &outCount);
+ if(r != KERN_SUCCESS)
+ ABORT("task_get_state failed");
+
+ lo = (void*)(info . THREAD_FLD (r1) - PPC_RED_ZONE_SIZE);
+ hi = (ptr_t)FindTopOfStack(info . THREAD_FLD (r1));
+
+ GC_push_one(info . THREAD_FLD (r0));
+ GC_push_one(info . THREAD_FLD (r2));
+ GC_push_one(info . THREAD_FLD (r3));
+ GC_push_one(info . THREAD_FLD (r4));
+ GC_push_one(info . THREAD_FLD (r5));
+ GC_push_one(info . THREAD_FLD (r6));
+ GC_push_one(info . THREAD_FLD (r7));
+ GC_push_one(info . THREAD_FLD (r8));
+ GC_push_one(info . THREAD_FLD (r9));
+ GC_push_one(info . THREAD_FLD (r10));
+ GC_push_one(info . THREAD_FLD (r11));
+ GC_push_one(info . THREAD_FLD (r12));
+ GC_push_one(info . THREAD_FLD (r13));
+ GC_push_one(info . THREAD_FLD (r14));
+ GC_push_one(info . THREAD_FLD (r15));
+ GC_push_one(info . THREAD_FLD (r16));
+ GC_push_one(info . THREAD_FLD (r17));
+ GC_push_one(info . THREAD_FLD (r18));
+ GC_push_one(info . THREAD_FLD (r19));
+ GC_push_one(info . THREAD_FLD (r20));
+ GC_push_one(info . THREAD_FLD (r21));
+ GC_push_one(info . THREAD_FLD (r22));
+ GC_push_one(info . THREAD_FLD (r23));
+ GC_push_one(info . THREAD_FLD (r24));
+ GC_push_one(info . THREAD_FLD (r25));
+ GC_push_one(info . THREAD_FLD (r26));
+ GC_push_one(info . THREAD_FLD (r27));
+ GC_push_one(info . THREAD_FLD (r28));
+ GC_push_one(info . THREAD_FLD (r29));
+ GC_push_one(info . THREAD_FLD (r30));
+ GC_push_one(info . THREAD_FLD (r31));
+
+# elif defined(I386)
+ /* FIXME: Remove after testing: */
+ WARN("This is completely untested and likely will not work\n", 0);
+ GC_THREAD_STATE_T info;
+ mach_msg_type_number_t outCount = THREAD_STATE_MAX;
+ r = thread_get_state(thread, GC_MACH_THREAD_STATE, (natural_t *)&info,
+ &outCount);
+ if(r != KERN_SUCCESS)
+ ABORT("task_get_state failed");
+
+ lo = (void*)info . THREAD_FLD (esp);
+ hi = (ptr_t)FindTopOfStack(info . THREAD_FLD (esp));
+
+ GC_push_one(info . THREAD_FLD (eax));
+ GC_push_one(info . THREAD_FLD (ebx));
+ GC_push_one(info . THREAD_FLD (ecx));
+ GC_push_one(info . THREAD_FLD (edx));
+ GC_push_one(info . THREAD_FLD (edi));
+ GC_push_one(info . THREAD_FLD (esi));
+ /* GC_push_one(info . THREAD_FLD (ebp)); */
+ /* GC_push_one(info . THREAD_FLD (esp)); */
+ GC_push_one(info . THREAD_FLD (ss));
+ GC_push_one(info . THREAD_FLD (eip));
+ GC_push_one(info . THREAD_FLD (cs));
+ GC_push_one(info . THREAD_FLD (ds));
+ GC_push_one(info . THREAD_FLD (es));
+ GC_push_one(info . THREAD_FLD (fs));
+ GC_push_one(info . THREAD_FLD (gs));
+
+# elif defined(X86_64)
+ GC_THREAD_STATE_T info;
+ mach_msg_type_number_t outCount = THREAD_STATE_MAX;
+ r = thread_get_state(thread, GC_MACH_THREAD_STATE, (natural_t *)&info,
+ &outCount);
+ if(r != KERN_SUCCESS)
+ ABORT("task_get_state failed");
+
+ lo = (void*)info . THREAD_FLD (rsp);
+ hi = (ptr_t)FindTopOfStack(info . THREAD_FLD (rsp));
+
+ GC_push_one(info . THREAD_FLD (rax));
+ GC_push_one(info . THREAD_FLD (rbx));
+ GC_push_one(info . THREAD_FLD (rcx));
+ GC_push_one(info . THREAD_FLD (rdx));
+ GC_push_one(info . THREAD_FLD (rdi));
+ GC_push_one(info . THREAD_FLD (rsi));
+ GC_push_one(info . THREAD_FLD (rbp));
+ GC_push_one(info . THREAD_FLD (rsp));
+ GC_push_one(info . THREAD_FLD (r8));
+ GC_push_one(info . THREAD_FLD (r9));
+ GC_push_one(info . THREAD_FLD (r10));
+ GC_push_one(info . THREAD_FLD (r11));
+ GC_push_one(info . THREAD_FLD (r12));
+ GC_push_one(info . THREAD_FLD (r13));
+ GC_push_one(info . THREAD_FLD (r14));
+ GC_push_one(info . THREAD_FLD (r15));
+ GC_push_one(info . THREAD_FLD (rip));
+ GC_push_one(info . THREAD_FLD (rflags));
+ GC_push_one(info . THREAD_FLD (cs));
+ GC_push_one(info . THREAD_FLD (fs));
+ GC_push_one(info . THREAD_FLD (gs));
+
+# else
+# error FIXME for non-x86 || ppc architectures
+# endif
+ }
+# if DEBUG_THREADS
+ GC_printf("Darwin: Stack for thread 0x%lx = [%p,%p)\n",
+ (unsigned long) thread, lo, hi);
+# endif
+ GC_push_all_stack(lo, hi);
+ mach_port_deallocate(my_task, thread);
+ } /* for(p=GC_threads[i]...) */
+ vm_deallocate(my_task, (vm_address_t)act_list,
+ sizeof(thread_t) * listcount);
+ mach_port_deallocate(my_task, me);
+}
+#endif /* !DARWIN_DONT_PARSE_STACK */
+
+static mach_port_t GC_mach_handler_thread;
+static int GC_use_mach_handler_thread = 0;
+
+static struct GC_mach_thread GC_mach_threads[THREAD_TABLE_SZ];
+static int GC_mach_threads_count;
+
+void GC_stop_init()
+{
+ int i;
+
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ GC_mach_threads[i].thread = 0;
+ GC_mach_threads[i].already_suspended = 0;
+ }
+ GC_mach_threads_count = 0;
+}
+
+/* returns true if there's a thread in act_list that wasn't in old_list */
+int GC_suspend_thread_list(thread_act_array_t act_list, int count,
+ thread_act_array_t old_list, int old_count)
+{
+ mach_port_t my_thread = mach_thread_self();
+ int i, j;
+
+ int changed = 0;
+
+ for(i = 0; i < count; i++) {
+ thread_act_t thread = act_list[i];
+# if DEBUG_THREADS
+ GC_printf("Attempting to suspend thread %p\n", thread);
+# endif
+ /* find the current thread in the old list */
+ int found = 0;
+ for(j = 0; j < old_count; j++) {
+ thread_act_t old_thread = old_list[j];
+ if (old_thread == thread) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ /* add it to the GC_mach_threads list */
+ GC_mach_threads[GC_mach_threads_count].thread = thread;
+ /* default is not suspended */
+ GC_mach_threads[GC_mach_threads_count].already_suspended = 0;
+ changed = 1;
+ }
+
+ if (thread != my_thread
+ && (!GC_use_mach_handler_thread
+ || (GC_use_mach_handler_thread
+ && GC_mach_handler_thread != thread))) {
+ struct thread_basic_info info;
+ mach_msg_type_number_t outCount = THREAD_INFO_MAX;
+ kern_return_t kern_result = thread_info(thread, THREAD_BASIC_INFO,
+ (thread_info_t)&info, &outCount);
+ if(kern_result != KERN_SUCCESS) {
+ /* the thread may have quit since the thread_threads () call
+ * we mark already_suspended so it's not dealt with anymore later
+ */
+ if (!found) {
+ GC_mach_threads[GC_mach_threads_count].already_suspended = TRUE;
+ GC_mach_threads_count++;
+ }
+ continue;
+ }
+# if DEBUG_THREADS
+ GC_printf("Thread state for 0x%lx = %d\n", (unsigned long)thread,
+ info.run_state);
+# endif
+ if (!found) {
+ GC_mach_threads[GC_mach_threads_count].already_suspended
+ = info.suspend_count;
+ }
+ if (info.suspend_count)
+ continue;
+
+# if DEBUG_THREADS
+ GC_printf("Suspending 0x%lx\n", (unsigned long)thread);
+# endif
+ /* Suspend the thread */
+ kern_result = thread_suspend(thread);
+ if(kern_result != KERN_SUCCESS) {
+ /* the thread may have quit since the thread_threads () call
+ * we mark already_suspended so it's not dealt with anymore later
+ */
+ if (!found) {
+ GC_mach_threads[GC_mach_threads_count].already_suspended = TRUE;
+ GC_mach_threads_count++;
+ }
+ continue;
+ }
+ }
+ if (!found) GC_mach_threads_count++;
+ }
+ mach_port_deallocate(current_task(), my_thread);
+ return changed;
+}
+
+
+/* Caller holds allocation lock. */
+void GC_stop_world()
+{
+ unsigned int i, changes;
+ task_t my_task = current_task();
+ mach_port_t my_thread = mach_thread_self();
+ kern_return_t kern_result;
+ thread_act_array_t act_list, prev_list;
+ mach_msg_type_number_t listcount, prevcount;
+
+# if DEBUG_THREADS
+ GC_printf("Stopping the world from 0x%lx\n",
+ (unsigned long)mach_thread_self());
+# endif
+
+ /* clear out the mach threads list table */
+ GC_stop_init();
+
+ /* Make sure all free list construction has stopped before we start. */
+ /* No new construction can start, since free list construction is */
+ /* required to acquire and release the GC lock before it starts, */
+ /* and we have the lock. */
+# ifdef PARALLEL_MARK
+ GC_acquire_mark_lock();
+ GC_ASSERT(GC_fl_builder_count == 0);
+ /* We should have previously waited for it to become zero. */
+# endif /* PARALLEL_MARK */
+
+ /* Loop stopping threads until you have gone over the whole list
+ twice without a new one appearing. thread_create() won't
+ return (and thus the thread stop) until the new thread
+ exists, so there is no window whereby you could stop a
+ thread, recognise it is stopped, but then have a new thread
+ it created before stopping show up later.
+ */
+
+ changes = 1;
+ prev_list = NULL;
+ prevcount = 0;
+ do {
+ int result;
+ kern_result = task_threads(my_task, &act_list, &listcount);
+
+ if(kern_result == KERN_SUCCESS) {
+ result = GC_suspend_thread_list(act_list, listcount, prev_list,
+ prevcount);
+ changes = result;
+
+ if(prev_list != NULL) {
+ for(i = 0; i < prevcount; i++)
+ mach_port_deallocate(my_task, prev_list[i]);
+
+ vm_deallocate(my_task, (vm_address_t)prev_list,
+ sizeof(thread_t) * prevcount);
+ }
+ prev_list = act_list;
+ prevcount = listcount;
+ }
+ } while (changes);
+ GC_ASSERT(prev_list != 0);
+ for(i = 0; i < prevcount; i++)
+ mach_port_deallocate(my_task, prev_list[i]);
+
+ vm_deallocate(my_task, (vm_address_t)act_list,
+ sizeof(thread_t) * listcount);
+
+# ifdef MPROTECT_VDB
+ if(GC_incremental) {
+ extern void GC_mprotect_stop();
+ GC_mprotect_stop();
+ }
+# endif
+
+# ifdef PARALLEL_MARK
+ GC_release_mark_lock();
+# endif
+# if DEBUG_THREADS
+ GC_printf("World stopped from 0x%lx\n", (unsigned long)my_thread);
+# endif
+
+ mach_port_deallocate(my_task, my_thread);
+}
+
+/* Caller holds allocation lock, and has held it continuously since */
+/* the world stopped. */
+void GC_start_world()
+{
+ task_t my_task = current_task();
+ mach_port_t my_thread = mach_thread_self();
+ unsigned int i;
+ int j;
+ kern_return_t kern_result;
+ thread_act_array_t act_list;
+ mach_msg_type_number_t listcount;
+ struct thread_basic_info info;
+ mach_msg_type_number_t outCount = THREAD_INFO_MAX;
+
+# if DEBUG_THREADS
+ GC_printf("World starting\n");
+# endif
+
+# ifdef MPROTECT_VDB
+ if(GC_incremental) {
+ extern void GC_mprotect_resume();
+ GC_mprotect_resume();
+ }
+# endif
+
+ kern_result = task_threads(my_task, &act_list, &listcount);
+ for(i = 0; i < listcount; i++) {
+ thread_act_t thread = act_list[i];
+ if (thread != my_thread
+ && (!GC_use_mach_handler_thread
+ || (GC_use_mach_handler_thread
+ && GC_mach_handler_thread != thread))) {
+ for(j = 0; j < GC_mach_threads_count; j++) {
+ if (thread == GC_mach_threads[j].thread) {
+ if (GC_mach_threads[j].already_suspended) {
+# if DEBUG_THREADS
+ GC_printf("Not resuming already suspended thread %p\n", thread);
+# endif
+ continue;
+ }
+ kern_result = thread_info(thread, THREAD_BASIC_INFO,
+ (thread_info_t)&info, &outCount);
+ if(kern_result != KERN_SUCCESS)
+ ABORT("thread_info failed");
+# if DEBUG_THREADS
+ GC_printf("Thread state for 0x%lx = %d\n", (unsigned long)thread,
+ info.run_state);
+ GC_printf("Resuming 0x%lx\n", (unsigned long)thread);
+# endif
+ /* Resume the thread */
+ kern_result = thread_resume(thread);
+ if(kern_result != KERN_SUCCESS)
+ ABORT("thread_resume failed");
+ }
+ }
+ }
+ mach_port_deallocate(my_task, thread);
+ }
+ vm_deallocate(my_task, (vm_address_t)act_list,
+ sizeof(thread_t) * listcount);
+
+ mach_port_deallocate(my_task, my_thread);
+# if DEBUG_THREADS
+ GC_printf("World started\n");
+# endif
+}
+
+void GC_darwin_register_mach_handler_thread(mach_port_t thread)
+{
+ GC_mach_handler_thread = thread;
+ GC_use_mach_handler_thread = 1;
+}
+
+#endif
diff --git a/tools/build/v2/engine/boehm_gc/dbg_mlc.c b/tools/build/v2/engine/boehm_gc/dbg_mlc.c
new file mode 100644
index 0000000000..4b72e390ac
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/dbg_mlc.c
@@ -0,0 +1,1053 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1997 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2007 Free Software Foundation, Inc
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include "private/dbg_mlc.h"
+
+void GC_default_print_heap_obj_proc();
+GC_API void GC_register_finalizer_no_order
+ (void * obj, GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void * *ocd);
+
+
+#ifndef SHORT_DBG_HDRS
+/* Check whether object with base pointer p has debugging info */
+/* p is assumed to point to a legitimate object in our part */
+/* of the heap. */
+/* This excludes the check as to whether the back pointer is */
+/* odd, which is added by the GC_HAS_DEBUG_INFO macro. */
+/* Note that if DBG_HDRS_ALL is set, uncollectable objects */
+/* on free lists may not have debug information set. Thus it's */
+/* not always safe to return TRUE, even if the client does */
+/* its part. */
+GC_bool GC_has_other_debug_info(ptr_t p)
+{
+ register oh * ohdr = (oh *)p;
+ register ptr_t body = (ptr_t)(ohdr + 1);
+ register word sz = GC_size((ptr_t) ohdr);
+
+ if (HBLKPTR((ptr_t)ohdr) != HBLKPTR((ptr_t)body)
+ || sz < DEBUG_BYTES + EXTRA_BYTES) {
+ return(FALSE);
+ }
+ if (ohdr -> oh_sz == sz) {
+ /* Object may have had debug info, but has been deallocated */
+ return(FALSE);
+ }
+ if (ohdr -> oh_sf == (START_FLAG ^ (word)body)) return(TRUE);
+ if (((word *)ohdr)[BYTES_TO_WORDS(sz)-1] == (END_FLAG ^ (word)body)) {
+ return(TRUE);
+ }
+ return(FALSE);
+}
+#endif
+
+#ifdef KEEP_BACK_PTRS
+
+# include <stdlib.h>
+
+# if defined(LINUX) || defined(SOLARIS) \
+ || defined(HPUX) || defined(IRIX5) || defined(OSF1)
+# define RANDOM() random()
+# else
+# define RANDOM() (long)rand()
+# endif
+
+ /* Store back pointer to source in dest, if that appears to be possible. */
+ /* This is not completely safe, since we may mistakenly conclude that */
+ /* dest has a debugging wrapper. But the error probability is very */
+ /* small, and this shouldn't be used in production code. */
+ /* We assume that dest is the real base pointer. Source will usually */
+ /* be a pointer to the interior of an object. */
+ void GC_store_back_pointer(ptr_t source, ptr_t dest)
+ {
+ if (GC_HAS_DEBUG_INFO(dest)) {
+ ((oh *)dest) -> oh_back_ptr = HIDE_BACK_PTR(source);
+ }
+ }
+
+ void GC_marked_for_finalization(ptr_t dest) {
+ GC_store_back_pointer(MARKED_FOR_FINALIZATION, dest);
+ }
+
+ /* Store information about the object referencing dest in *base_p */
+ /* and *offset_p. */
+ /* source is root ==> *base_p = address, *offset_p = 0 */
+ /* source is heap object ==> *base_p != 0, *offset_p = offset */
+ /* Returns 1 on success, 0 if source couldn't be determined. */
+ /* Dest can be any address within a heap object. */
+ GC_ref_kind GC_get_back_ptr_info(void *dest, void **base_p, size_t *offset_p)
+ {
+ oh * hdr = (oh *)GC_base(dest);
+ ptr_t bp;
+ ptr_t bp_base;
+ if (!GC_HAS_DEBUG_INFO((ptr_t) hdr)) return GC_NO_SPACE;
+ bp = REVEAL_POINTER(hdr -> oh_back_ptr);
+ if (MARKED_FOR_FINALIZATION == bp) return GC_FINALIZER_REFD;
+ if (MARKED_FROM_REGISTER == bp) return GC_REFD_FROM_REG;
+ if (NOT_MARKED == bp) return GC_UNREFERENCED;
+# if ALIGNMENT == 1
+ /* Heuristically try to fix off by 1 errors we introduced by */
+ /* insisting on even addresses. */
+ {
+ ptr_t alternate_ptr = bp + 1;
+ ptr_t target = *(ptr_t *)bp;
+ ptr_t alternate_target = *(ptr_t *)alternate_ptr;
+
+ if (alternate_target >= GC_least_plausible_heap_addr
+ && alternate_target <= GC_greatest_plausible_heap_addr
+ && (target < GC_least_plausible_heap_addr
+ || target > GC_greatest_plausible_heap_addr)) {
+ bp = alternate_ptr;
+ }
+ }
+# endif
+ bp_base = GC_base(bp);
+ if (0 == bp_base) {
+ *base_p = bp;
+ *offset_p = 0;
+ return GC_REFD_FROM_ROOT;
+ } else {
+ if (GC_HAS_DEBUG_INFO(bp_base)) bp_base += sizeof(oh);
+ *base_p = bp_base;
+ *offset_p = bp - bp_base;
+ return GC_REFD_FROM_HEAP;
+ }
+ }
+
+ /* Generate a random heap address. */
+ /* The resulting address is in the heap, but */
+ /* not necessarily inside a valid object. */
+ void *GC_generate_random_heap_address(void)
+ {
+ int i;
+ long heap_offset = RANDOM();
+ if (GC_heapsize > RAND_MAX) {
+ heap_offset *= RAND_MAX;
+ heap_offset += RANDOM();
+ }
+ heap_offset %= GC_heapsize;
+ /* This doesn't yield a uniform distribution, especially if */
+ /* e.g. RAND_MAX = 1.5* GC_heapsize. But for typical cases, */
+ /* it's not too bad. */
+ for (i = 0; i < GC_n_heap_sects; ++ i) {
+ size_t size = GC_heap_sects[i].hs_bytes;
+ if (heap_offset < size) {
+ return GC_heap_sects[i].hs_start + heap_offset;
+ } else {
+ heap_offset -= size;
+ }
+ }
+ ABORT("GC_generate_random_heap_address: size inconsistency");
+ /*NOTREACHED*/
+ return 0;
+ }
+
+ /* Generate a random address inside a valid marked heap object. */
+ void *GC_generate_random_valid_address(void)
+ {
+ ptr_t result;
+ ptr_t base;
+ for (;;) {
+ result = GC_generate_random_heap_address();
+ base = GC_base(result);
+ if (0 == base) continue;
+ if (!GC_is_marked(base)) continue;
+ return result;
+ }
+ }
+
+ /* Print back trace for p */
+ void GC_print_backtrace(void *p)
+ {
+ void *current = p;
+ int i;
+ GC_ref_kind source;
+ size_t offset;
+ void *base;
+
+ GC_print_heap_obj(GC_base(current));
+ GC_err_printf("\n");
+ for (i = 0; ; ++i) {
+ source = GC_get_back_ptr_info(current, &base, &offset);
+ if (GC_UNREFERENCED == source) {
+ GC_err_printf("Reference could not be found\n");
+ goto out;
+ }
+ if (GC_NO_SPACE == source) {
+ GC_err_printf("No debug info in object: Can't find reference\n");
+ goto out;
+ }
+ GC_err_printf("Reachable via %d levels of pointers from ",
+ (unsigned long)i);
+ switch(source) {
+ case GC_REFD_FROM_ROOT:
+ GC_err_printf("root at %p\n\n", base);
+ goto out;
+ case GC_REFD_FROM_REG:
+ GC_err_printf("root in register\n\n");
+ goto out;
+ case GC_FINALIZER_REFD:
+ GC_err_printf("list of finalizable objects\n\n");
+ goto out;
+ case GC_REFD_FROM_HEAP:
+ GC_err_printf("offset %ld in object:\n", (unsigned long)offset);
+ /* Take GC_base(base) to get real base, i.e. header. */
+ GC_print_heap_obj(GC_base(base));
+ GC_err_printf("\n");
+ break;
+ }
+ current = base;
+ }
+ out:;
+ }
+
+ /* Force a garbage collection and generate a backtrace from a */
+ /* random heap address. */
+ void GC_generate_random_backtrace_no_gc(void)
+ {
+ void * current;
+ current = GC_generate_random_valid_address();
+ GC_printf("\n****Chose address %p in object\n", current);
+ GC_print_backtrace(current);
+ }
+
+ void GC_generate_random_backtrace(void)
+ {
+ GC_gcollect();
+ GC_generate_random_backtrace_no_gc();
+ }
+
+#endif /* KEEP_BACK_PTRS */
+
+# define CROSSES_HBLK(p, sz) \
+ (((word)(p + sizeof(oh) + sz - 1) ^ (word)p) >= HBLKSIZE)
+/* Store debugging info into p. Return displaced pointer. */
+/* Assumes we don't hold allocation lock. */
+ptr_t GC_store_debug_info(ptr_t p, word sz, const char *string, word integer)
+{
+ register word * result = (word *)((oh *)p + 1);
+ DCL_LOCK_STATE;
+
+ /* There is some argument that we should dissble signals here. */
+ /* But that's expensive. And this way things should only appear */
+ /* inconsistent while we're in the handler. */
+ LOCK();
+ GC_ASSERT(GC_size(p) >= sizeof(oh) + sz);
+ GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz)));
+# ifdef KEEP_BACK_PTRS
+ ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);
+# endif
+# ifdef MAKE_BACK_GRAPH
+ ((oh *)p) -> oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0);
+# endif
+ ((oh *)p) -> oh_string = string;
+ ((oh *)p) -> oh_int = integer;
+# ifndef SHORT_DBG_HDRS
+ ((oh *)p) -> oh_sz = sz;
+ ((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
+ ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
+ result[SIMPLE_ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
+# endif
+ UNLOCK();
+ return((ptr_t)result);
+}
+
+#ifdef DBG_HDRS_ALL
+/* Store debugging info into p. Return displaced pointer. */
+/* This version assumes we do hold the allocation lock. */
+ptr_t GC_store_debug_info_inner(ptr_t p, word sz, char *string, word integer)
+{
+ register word * result = (word *)((oh *)p + 1);
+
+ /* There is some argument that we should disable signals here. */
+ /* But that's expensive. And this way things should only appear */
+ /* inconsistent while we're in the handler. */
+ GC_ASSERT(GC_size(p) >= sizeof(oh) + sz);
+ GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz)));
+# ifdef KEEP_BACK_PTRS
+ ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);
+# endif
+# ifdef MAKE_BACK_GRAPH
+ ((oh *)p) -> oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0);
+# endif
+ ((oh *)p) -> oh_string = string;
+ ((oh *)p) -> oh_int = integer;
+# ifndef SHORT_DBG_HDRS
+ ((oh *)p) -> oh_sz = sz;
+ ((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
+ ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
+ result[SIMPLE_ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
+# endif
+ return((ptr_t)result);
+}
+#endif
+
+#ifndef SHORT_DBG_HDRS
+/* Check the object with debugging info at ohdr */
+/* return NIL if it's OK. Else return clobbered */
+/* address. */
+ptr_t GC_check_annotated_obj(oh *ohdr)
+{
+ register ptr_t body = (ptr_t)(ohdr + 1);
+ register word gc_sz = GC_size((ptr_t)ohdr);
+ if (ohdr -> oh_sz + DEBUG_BYTES > gc_sz) {
+ return((ptr_t)(&(ohdr -> oh_sz)));
+ }
+ if (ohdr -> oh_sf != (START_FLAG ^ (word)body)) {
+ return((ptr_t)(&(ohdr -> oh_sf)));
+ }
+ if (((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1] != (END_FLAG ^ (word)body)) {
+ return((ptr_t)((word *)ohdr + BYTES_TO_WORDS(gc_sz)-1));
+ }
+ if (((word *)body)[SIMPLE_ROUNDED_UP_WORDS(ohdr -> oh_sz)]
+ != (END_FLAG ^ (word)body)) {
+ return((ptr_t)((word *)body + SIMPLE_ROUNDED_UP_WORDS(ohdr -> oh_sz)));
+ }
+ return(0);
+}
+#endif /* !SHORT_DBG_HDRS */
+
+static GC_describe_type_fn GC_describe_type_fns[MAXOBJKINDS] = {0};
+
+void GC_register_describe_type_fn(int kind, GC_describe_type_fn fn)
+{
+ GC_describe_type_fns[kind] = fn;
+}
+
+/* Print a type description for the object whose client-visible address */
+/* is p. */
+void GC_print_type(ptr_t p)
+{
+ hdr * hhdr = GC_find_header(p);
+ char buffer[GC_TYPE_DESCR_LEN + 1];
+ int kind = hhdr -> hb_obj_kind;
+
+ if (0 != GC_describe_type_fns[kind] && GC_is_marked(GC_base(p))) {
+ /* This should preclude free list objects except with */
+ /* thread-local allocation. */
+ buffer[GC_TYPE_DESCR_LEN] = 0;
+ (GC_describe_type_fns[kind])(p, buffer);
+ GC_ASSERT(buffer[GC_TYPE_DESCR_LEN] == 0);
+ GC_err_puts(buffer);
+ } else {
+ switch(kind) {
+ case PTRFREE:
+ GC_err_puts("PTRFREE");
+ break;
+ case NORMAL:
+ GC_err_puts("NORMAL");
+ break;
+ case UNCOLLECTABLE:
+ GC_err_puts("UNCOLLECTABLE");
+ break;
+# ifdef ATOMIC_UNCOLLECTABLE
+ case AUNCOLLECTABLE:
+ GC_err_puts("ATOMIC UNCOLLECTABLE");
+ break;
+# endif
+ case STUBBORN:
+ GC_err_puts("STUBBORN");
+ break;
+ default:
+ GC_err_printf("kind %d, descr 0x%lx", kind,
+ (unsigned long)(hhdr -> hb_descr));
+ }
+ }
+}
+
+
+
+void GC_print_obj(ptr_t p)
+{
+ register oh * ohdr = (oh *)GC_base(p);
+
+ GC_ASSERT(I_DONT_HOLD_LOCK());
+ GC_err_printf("%p (", ((ptr_t)ohdr + sizeof(oh)));
+ GC_err_puts(ohdr -> oh_string);
+# ifdef SHORT_DBG_HDRS
+ GC_err_printf(":%ld, ", (unsigned long)(ohdr -> oh_int));
+# else
+ GC_err_printf(":%ld, sz=%ld, ", (unsigned long)(ohdr -> oh_int),
+ (unsigned long)(ohdr -> oh_sz));
+# endif
+ GC_print_type((ptr_t)(ohdr + 1));
+ GC_err_puts(")\n");
+ PRINT_CALL_CHAIN(ohdr);
+}
+
+void GC_debug_print_heap_obj_proc(ptr_t p)
+{
+ GC_ASSERT(I_DONT_HOLD_LOCK());
+ if (GC_HAS_DEBUG_INFO(p)) {
+ GC_print_obj(p);
+ } else {
+ GC_default_print_heap_obj_proc(p);
+ }
+}
+
+#ifndef SHORT_DBG_HDRS
+void GC_print_smashed_obj(ptr_t p, ptr_t clobbered_addr)
+{
+ register oh * ohdr = (oh *)GC_base(p);
+
+ GC_ASSERT(I_DONT_HOLD_LOCK());
+ GC_err_printf("%p in object at %p(", clobbered_addr, p);
+ if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))
+ || ohdr -> oh_string == 0) {
+ GC_err_printf("<smashed>, appr. sz = %ld)\n",
+ (GC_size((ptr_t)ohdr) - DEBUG_BYTES));
+ } else {
+ if (ohdr -> oh_string[0] == '\0') {
+ GC_err_puts("EMPTY(smashed?)");
+ } else {
+ GC_err_puts(ohdr -> oh_string);
+ }
+ GC_err_printf(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
+ (unsigned long)(ohdr -> oh_sz));
+ PRINT_CALL_CHAIN(ohdr);
+ }
+}
+#endif
+
+void GC_check_heap_proc (void);
+
+void GC_print_all_smashed_proc (void);
+
+void GC_do_nothing(void) {}
+
+void GC_start_debugging(void)
+{
+# ifndef SHORT_DBG_HDRS
+ GC_check_heap = GC_check_heap_proc;
+ GC_print_all_smashed = GC_print_all_smashed_proc;
+# else
+ GC_check_heap = GC_do_nothing;
+ GC_print_all_smashed = GC_do_nothing;
+# endif
+ GC_print_heap_obj = GC_debug_print_heap_obj_proc;
+ GC_debugging_started = TRUE;
+ GC_register_displacement((word)sizeof(oh));
+}
+
+size_t GC_debug_header_size = sizeof(oh);
+
+void GC_debug_register_displacement(size_t offset)
+{
+ GC_register_displacement(offset);
+ GC_register_displacement((word)sizeof(oh) + offset);
+}
+
+void * GC_debug_malloc(size_t lb, GC_EXTRA_PARAMS)
+{
+ void * result = GC_malloc(lb + DEBUG_BYTES);
+
+ if (result == 0) {
+ GC_err_printf("GC_debug_malloc(%lu) returning NIL (",
+ (unsigned long) lb);
+ GC_err_puts(s);
+ GC_err_printf(":%ld)\n", (unsigned long)i);
+ return(0);
+ }
+ if (!GC_debugging_started) {
+ GC_start_debugging();
+ }
+ ADD_CALL_CHAIN(result, ra);
+ return (GC_store_debug_info(result, (word)lb, s, (word)i));
+}
+
+void * GC_debug_malloc_ignore_off_page(size_t lb, GC_EXTRA_PARAMS)
+{
+ void * result = GC_malloc_ignore_off_page(lb + DEBUG_BYTES);
+
+ if (result == 0) {
+ GC_err_printf("GC_debug_malloc_ignore_off_page(%lu) returning NIL (",
+ (unsigned long) lb);
+ GC_err_puts(s);
+ GC_err_printf(":%lu)\n", (unsigned long)i);
+ return(0);
+ }
+ if (!GC_debugging_started) {
+ GC_start_debugging();
+ }
+ ADD_CALL_CHAIN(result, ra);
+ return (GC_store_debug_info(result, (word)lb, s, (word)i));
+}
+
+void * GC_debug_malloc_atomic_ignore_off_page(size_t lb, GC_EXTRA_PARAMS)
+{
+ void * result = GC_malloc_atomic_ignore_off_page(lb + DEBUG_BYTES);
+
+ if (result == 0) {
+ GC_err_printf("GC_debug_malloc_atomic_ignore_off_page(%lu)"
+ " returning NIL (", (unsigned long) lb);
+ GC_err_puts(s);
+ GC_err_printf(":%lu)\n", (unsigned long)i);
+ return(0);
+ }
+ if (!GC_debugging_started) {
+ GC_start_debugging();
+ }
+ ADD_CALL_CHAIN(result, ra);
+ return (GC_store_debug_info(result, (word)lb, s, (word)i));
+}
+
+# ifdef DBG_HDRS_ALL
+/*
+ * An allocation function for internal use.
+ * Normally internally allocated objects do not have debug information.
+ * But in this case, we need to make sure that all objects have debug
+ * headers.
+ * We assume debugging was started in collector initialization,
+ * and we already hold the GC lock.
+ */
+ void * GC_debug_generic_malloc_inner(size_t lb, int k)
+ {
+ void * result = GC_generic_malloc_inner(lb + DEBUG_BYTES, k);
+
+ if (result == 0) {
+ GC_err_printf("GC internal allocation (%lu bytes) returning NIL\n",
+ (unsigned long) lb);
+ return(0);
+ }
+ ADD_CALL_CHAIN(result, GC_RETURN_ADDR);
+ return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0));
+ }
+
+ void * GC_debug_generic_malloc_inner_ignore_off_page(size_t lb, int k)
+ {
+ void * result = GC_generic_malloc_inner_ignore_off_page(
+ lb + DEBUG_BYTES, k);
+
+ if (result == 0) {
+ GC_err_printf("GC internal allocation (%lu bytes) returning NIL\n",
+ (unsigned long) lb);
+ return(0);
+ }
+ ADD_CALL_CHAIN(result, GC_RETURN_ADDR);
+ return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0));
+ }
+# endif
+
+#ifdef STUBBORN_ALLOC
+void * GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
+{
+ void * result = GC_malloc_stubborn(lb + DEBUG_BYTES);
+
+ if (result == 0) {
+ GC_err_printf("GC_debug_malloc(%lu) returning NIL (",
+ (unsigned long) lb);
+ GC_err_puts(s);
+ GC_err_printf(":%lu)\n", (unsigned long)i);
+ return(0);
+ }
+ if (!GC_debugging_started) {
+ GC_start_debugging();
+ }
+ ADD_CALL_CHAIN(result, ra);
+ return (GC_store_debug_info(result, (word)lb, s, (word)i));
+}
+
+void GC_debug_change_stubborn(void *p)
+{
+ void * q = GC_base(p);
+ hdr * hhdr;
+
+ if (q == 0) {
+ GC_err_printf("Bad argument: %p to GC_debug_change_stubborn\n", p);
+ ABORT("GC_debug_change_stubborn: bad arg");
+ }
+ hhdr = HDR(q);
+ if (hhdr -> hb_obj_kind != STUBBORN) {
+ GC_err_printf("GC_debug_change_stubborn arg not stubborn: %p\n", p);
+ ABORT("GC_debug_change_stubborn: arg not stubborn");
+ }
+ GC_change_stubborn(q);
+}
+
+void GC_debug_end_stubborn_change(void *p)
+{
+ register void * q = GC_base(p);
+ register hdr * hhdr;
+
+ if (q == 0) {
+ GC_err_printf("Bad argument: %p to GC_debug_end_stubborn_change\n", p);
+ ABORT("GC_debug_end_stubborn_change: bad arg");
+ }
+ hhdr = HDR(q);
+ if (hhdr -> hb_obj_kind != STUBBORN) {
+ GC_err_printf("debug_end_stubborn_change arg not stubborn: %p\n", p);
+ ABORT("GC_debug_end_stubborn_change: arg not stubborn");
+ }
+ GC_end_stubborn_change(q);
+}
+
+#else /* !STUBBORN_ALLOC */
+
+void * GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
+{
+ return GC_debug_malloc(lb, OPT_RA s, i);
+}
+
+void GC_debug_change_stubborn(void *p)
+{
+}
+
+void GC_debug_end_stubborn_change(void *p)
+{
+}
+
+#endif /* !STUBBORN_ALLOC */
+
+void * GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)
+{
+ void * result = GC_malloc_atomic(lb + DEBUG_BYTES);
+
+ if (result == 0) {
+ GC_err_printf("GC_debug_malloc_atomic(%lu) returning NIL (",
+ (unsigned long) lb);
+ GC_err_puts(s);
+ GC_err_printf(":%lu)\n", (unsigned long)i);
+ return(0);
+ }
+ if (!GC_debugging_started) {
+ GC_start_debugging();
+ }
+ ADD_CALL_CHAIN(result, ra);
+ return (GC_store_debug_info(result, (word)lb, s, (word)i));
+}
+
+char *GC_debug_strdup(const char *str, GC_EXTRA_PARAMS)
+{
+ char *copy;
+ if (str == NULL) return NULL;
+ copy = GC_debug_malloc_atomic(strlen(str) + 1, OPT_RA s, i);
+ if (copy == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ strcpy(copy, str);
+ return copy;
+}
+
+void * GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)
+{
+ void * result = GC_malloc_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES);
+
+ if (result == 0) {
+ GC_err_printf("GC_debug_malloc_uncollectable(%lu) returning NIL (",
+ (unsigned long) lb);
+ GC_err_puts(s);
+ GC_err_printf(":%lu)\n", (unsigned long)i);
+ return(0);
+ }
+ if (!GC_debugging_started) {
+ GC_start_debugging();
+ }
+ ADD_CALL_CHAIN(result, ra);
+ return (GC_store_debug_info(result, (word)lb, s, (word)i));
+}
+
+#ifdef ATOMIC_UNCOLLECTABLE
+void * GC_debug_malloc_atomic_uncollectable(size_t lb, GC_EXTRA_PARAMS)
+{
+ void * result =
+ GC_malloc_atomic_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES);
+
+ if (result == 0) {
+ GC_err_printf(
+ "GC_debug_malloc_atomic_uncollectable(%lu) returning NIL (",
+ (unsigned long) lb);
+ GC_err_puts(s);
+ GC_err_printf(":%lu)\n", (unsigned long)i);
+ return(0);
+ }
+ if (!GC_debugging_started) {
+ GC_start_debugging();
+ }
+ ADD_CALL_CHAIN(result, ra);
+ return (GC_store_debug_info(result, (word)lb, s, (word)i));
+}
+#endif /* ATOMIC_UNCOLLECTABLE */
+
+void GC_debug_free(void * p)
+{
+ ptr_t base;
+ ptr_t clobbered;
+
+ if (0 == p) return;
+ base = GC_base(p);
+ if (base == 0) {
+ GC_err_printf("Attempt to free invalid pointer %p\n", p);
+ ABORT("free(invalid pointer)");
+ }
+ if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
+ GC_err_printf(
+ "GC_debug_free called on pointer %p wo debugging info\n", p);
+ } else {
+# ifndef SHORT_DBG_HDRS
+ clobbered = GC_check_annotated_obj((oh *)base);
+ if (clobbered != 0) {
+ if (((oh *)base) -> oh_sz == GC_size(base)) {
+ GC_err_printf(
+ "GC_debug_free: found previously deallocated (?) object at ");
+ } else {
+ GC_err_printf("GC_debug_free: found smashed location at ");
+ }
+ GC_print_smashed_obj(p, clobbered);
+ }
+ /* Invalidate size */
+ ((oh *)base) -> oh_sz = GC_size(base);
+# endif /* SHORT_DBG_HDRS */
+ }
+ if (GC_find_leak) {
+ GC_free(base);
+ } else {
+ hdr * hhdr = HDR(p);
+ GC_bool uncollectable = FALSE;
+
+ if (hhdr -> hb_obj_kind == UNCOLLECTABLE) {
+ uncollectable = TRUE;
+ }
+# ifdef ATOMIC_UNCOLLECTABLE
+ if (hhdr -> hb_obj_kind == AUNCOLLECTABLE) {
+ uncollectable = TRUE;
+ }
+# endif
+ if (uncollectable) {
+ GC_free(base);
+ } else {
+ size_t i;
+ size_t obj_sz = BYTES_TO_WORDS(hhdr -> hb_sz - sizeof(oh));
+
+ for (i = 0; i < obj_sz; ++i) ((word *)p)[i] = 0xdeadbeef;
+ GC_ASSERT((word *)p + i == (word *)(base + hhdr -> hb_sz));
+ }
+ } /* !GC_find_leak */
+}
+
+#ifdef THREADS
+
+extern void GC_free_inner(void * p);
+
+/* Used internally; we assume it's called correctly. */
+void GC_debug_free_inner(void * p)
+{
+ GC_free_inner(GC_base(p));
+}
+#endif
+
+void * GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS)
+{
+ void * base = GC_base(p);
+ ptr_t clobbered;
+ void * result;
+ size_t copy_sz = lb;
+ size_t old_sz;
+ hdr * hhdr;
+
+ if (p == 0) return(GC_debug_malloc(lb, OPT_RA s, i));
+ if (base == 0) {
+ GC_err_printf("Attempt to reallocate invalid pointer %p\n", p);
+ ABORT("realloc(invalid pointer)");
+ }
+ if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
+ GC_err_printf(
+ "GC_debug_realloc called on pointer %p wo debugging info\n", p);
+ return(GC_realloc(p, lb));
+ }
+ hhdr = HDR(base);
+ switch (hhdr -> hb_obj_kind) {
+# ifdef STUBBORN_ALLOC
+ case STUBBORN:
+ result = GC_debug_malloc_stubborn(lb, OPT_RA s, i);
+ break;
+# endif
+ case NORMAL:
+ result = GC_debug_malloc(lb, OPT_RA s, i);
+ break;
+ case PTRFREE:
+ result = GC_debug_malloc_atomic(lb, OPT_RA s, i);
+ break;
+ case UNCOLLECTABLE:
+ result = GC_debug_malloc_uncollectable(lb, OPT_RA s, i);
+ break;
+# ifdef ATOMIC_UNCOLLECTABLE
+ case AUNCOLLECTABLE:
+ result = GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i);
+ break;
+# endif
+ default:
+ GC_err_printf("GC_debug_realloc: encountered bad kind\n");
+ ABORT("bad kind");
+ }
+# ifdef SHORT_DBG_HDRS
+ old_sz = GC_size(base) - sizeof(oh);
+# else
+ clobbered = GC_check_annotated_obj((oh *)base);
+ if (clobbered != 0) {
+ GC_err_printf("GC_debug_realloc: found smashed location at ");
+ GC_print_smashed_obj(p, clobbered);
+ }
+ old_sz = ((oh *)base) -> oh_sz;
+# endif
+ if (old_sz < copy_sz) copy_sz = old_sz;
+ if (result == 0) return(0);
+ BCOPY(p, result, copy_sz);
+ GC_debug_free(p);
+ return(result);
+}
+
+#ifndef SHORT_DBG_HDRS
+
+/* List of smashed objects. We defer printing these, since we can't */
+/* always print them nicely with the allocation lock held. */
+/* We put them here instead of in GC_arrays, since it may be useful to */
+/* be able to look at them with the debugger. */
+#define MAX_SMASHED 20
+ptr_t GC_smashed[MAX_SMASHED];
+unsigned GC_n_smashed = 0;
+
+void GC_add_smashed(ptr_t smashed)
+{
+ GC_ASSERT(GC_is_marked(GC_base(smashed)));
+ GC_smashed[GC_n_smashed] = smashed;
+ if (GC_n_smashed < MAX_SMASHED - 1) ++GC_n_smashed;
+ /* In case of overflow, we keep the first MAX_SMASHED-1 */
+ /* entries plus the last one. */
+ GC_have_errors = TRUE;
+}
+
+/* Print all objects on the list. Clear the list. */
+void GC_print_all_smashed_proc(void)
+{
+ unsigned i;
+
+ GC_ASSERT(I_DONT_HOLD_LOCK());
+ if (GC_n_smashed == 0) return;
+ GC_err_printf("GC_check_heap_block: found smashed heap objects:\n");
+ for (i = 0; i < GC_n_smashed; ++i) {
+ GC_print_smashed_obj(GC_base(GC_smashed[i]), GC_smashed[i]);
+ GC_smashed[i] = 0;
+ }
+ GC_n_smashed = 0;
+}
+
+/* Check all marked objects in the given block for validity */
+/* Avoid GC_apply_to_each_object for performance reasons. */
+/*ARGSUSED*/
+void GC_check_heap_block(struct hblk *hbp, word dummy)
+{
+ struct hblkhdr * hhdr = HDR(hbp);
+ size_t sz = hhdr -> hb_sz;
+ size_t bit_no;
+ char *p, *plim;
+
+ p = hbp->hb_body;
+ bit_no = 0;
+ if (sz > MAXOBJBYTES) {
+ plim = p;
+ } else {
+ plim = hbp->hb_body + HBLKSIZE - sz;
+ }
+ /* go through all words in block */
+ while( p <= plim ) {
+ if( mark_bit_from_hdr(hhdr, bit_no)
+ && GC_HAS_DEBUG_INFO((ptr_t)p)) {
+ ptr_t clobbered = GC_check_annotated_obj((oh *)p);
+
+ if (clobbered != 0) GC_add_smashed(clobbered);
+ }
+ bit_no += MARK_BIT_OFFSET(sz);
+ p += sz;
+ }
+}
+
+
+/* This assumes that all accessible objects are marked, and that */
+/* I hold the allocation lock. Normally called by collector. */
+void GC_check_heap_proc(void)
+{
+# ifndef SMALL_CONFIG
+ /* Ignore gcc no effect warning on the following. */
+ GC_STATIC_ASSERT((sizeof(oh) & (GRANULE_BYTES - 1)) == 0);
+ /* FIXME: Should we check for twice that alignment? */
+# endif
+ GC_apply_to_all_blocks(GC_check_heap_block, (word)0);
+}
+
+#endif /* !SHORT_DBG_HDRS */
+
+struct closure {
+ GC_finalization_proc cl_fn;
+ void * cl_data;
+};
+
+void * GC_make_closure(GC_finalization_proc fn, void * data)
+{
+ struct closure * result =
+# ifdef DBG_HDRS_ALL
+ (struct closure *) GC_debug_malloc(sizeof (struct closure),
+ GC_EXTRAS);
+# else
+ (struct closure *) GC_malloc(sizeof (struct closure));
+# endif
+
+ result -> cl_fn = fn;
+ result -> cl_data = data;
+ return((void *)result);
+}
+
+void GC_debug_invoke_finalizer(void * obj, void * data)
+{
+ register struct closure * cl = (struct closure *) data;
+
+ (*(cl -> cl_fn))((void *)((char *)obj + sizeof(oh)), cl -> cl_data);
+}
+
+/* Set ofn and ocd to reflect the values we got back. */
+static void store_old (void *obj, GC_finalization_proc my_old_fn,
+ struct closure *my_old_cd, GC_finalization_proc *ofn,
+ void **ocd)
+{
+ if (0 != my_old_fn) {
+ if (my_old_fn != GC_debug_invoke_finalizer) {
+ GC_err_printf("Debuggable object at %p had non-debug finalizer.\n",
+ obj);
+ /* This should probably be fatal. */
+ } else {
+ if (ofn) *ofn = my_old_cd -> cl_fn;
+ if (ocd) *ocd = my_old_cd -> cl_data;
+ }
+ } else {
+ if (ofn) *ofn = 0;
+ if (ocd) *ocd = 0;
+ }
+}
+
+void GC_debug_register_finalizer(void * obj, GC_finalization_proc fn,
+ void * cd, GC_finalization_proc *ofn,
+ void * *ocd)
+{
+ GC_finalization_proc my_old_fn;
+ void * my_old_cd;
+ ptr_t base = GC_base(obj);
+ if (0 == base) return;
+ if ((ptr_t)obj - base != sizeof(oh)) {
+ GC_err_printf(
+ "GC_debug_register_finalizer called with non-base-pointer %p\n",
+ obj);
+ }
+ if (0 == fn) {
+ GC_register_finalizer(base, 0, 0, &my_old_fn, &my_old_cd);
+ } else {
+ GC_register_finalizer(base, GC_debug_invoke_finalizer,
+ GC_make_closure(fn,cd), &my_old_fn, &my_old_cd);
+ }
+ store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
+}
+
+void GC_debug_register_finalizer_no_order
+ (void * obj, GC_finalization_proc fn,
+ void * cd, GC_finalization_proc *ofn,
+ void * *ocd)
+{
+ GC_finalization_proc my_old_fn;
+ void * my_old_cd;
+ ptr_t base = GC_base(obj);
+ if (0 == base) return;
+ if ((ptr_t)obj - base != sizeof(oh)) {
+ GC_err_printf(
+ "GC_debug_register_finalizer_no_order called with "
+ "non-base-pointer %p\n",
+ obj);
+ }
+ if (0 == fn) {
+ GC_register_finalizer_no_order(base, 0, 0, &my_old_fn, &my_old_cd);
+ } else {
+ GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer,
+ GC_make_closure(fn,cd), &my_old_fn,
+ &my_old_cd);
+ }
+ store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
+}
+
+void GC_debug_register_finalizer_unreachable
+ (void * obj, GC_finalization_proc fn,
+ void * cd, GC_finalization_proc *ofn,
+ void * *ocd)
+{
+ GC_finalization_proc my_old_fn;
+ void * my_old_cd;
+ ptr_t base = GC_base(obj);
+ if (0 == base) return;
+ if ((ptr_t)obj - base != sizeof(oh)) {
+ GC_err_printf(
+ "GC_debug_register_finalizer_unreachable called with "
+ "non-base-pointer %p\n",
+ obj);
+ }
+ if (0 == fn) {
+ GC_register_finalizer_unreachable(base, 0, 0, &my_old_fn, &my_old_cd);
+ } else {
+ GC_register_finalizer_unreachable(base, GC_debug_invoke_finalizer,
+ GC_make_closure(fn,cd), &my_old_fn,
+ &my_old_cd);
+ }
+ store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
+}
+
+void GC_debug_register_finalizer_ignore_self
+ (void * obj, GC_finalization_proc fn,
+ void * cd, GC_finalization_proc *ofn,
+ void * *ocd)
+{
+ GC_finalization_proc my_old_fn;
+ void * my_old_cd;
+ ptr_t base = GC_base(obj);
+ if (0 == base) return;
+ if ((ptr_t)obj - base != sizeof(oh)) {
+ GC_err_printf(
+ "GC_debug_register_finalizer_ignore_self called with "
+ "non-base-pointer %p\n", obj);
+ }
+ if (0 == fn) {
+ GC_register_finalizer_ignore_self(base, 0, 0, &my_old_fn, &my_old_cd);
+ } else {
+ GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer,
+ GC_make_closure(fn,cd), &my_old_fn,
+ &my_old_cd);
+ }
+ store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
+}
+
+#ifdef GC_ADD_CALLER
+# define RA GC_RETURN_ADDR,
+#else
+# define RA
+#endif
+
+void * GC_debug_malloc_replacement(size_t lb)
+{
+ return GC_debug_malloc(lb, RA "unknown", 0);
+}
+
+void * GC_debug_realloc_replacement(void *p, size_t lb)
+{
+ return GC_debug_realloc(p, lb, RA "unknown", 0);
+}
diff --git a/tools/build/v2/engine/boehm_gc/depcomp b/tools/build/v2/engine/boehm_gc/depcomp
new file mode 100755
index 0000000000..3480ce4e96
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/depcomp
@@ -0,0 +1,436 @@
+#! /bin/sh
+
+# depcomp - compile a program generating dependencies as side-effects
+# Copyright 1999, 2000 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+# `libtool' can also be set to `yes' or `no'.
+
+if test -z "$depfile"; then
+ base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'`
+ dir=`echo "$object" | sed 's,/.*$,/,'`
+ if test "$dir" = "$object"; then
+ dir=
+ fi
+ # FIXME: should be _deps on DOS.
+ depfile="$dir.deps/$base"
+fi
+
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+ "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> $depfile
+ echo >> $depfile
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> $depfile
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. This file always lives in the current directory.
+ # Also, the AIX compiler puts `$object:' at the start of each line;
+ # $object doesn't have directory information.
+ stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'`
+ tmpdepfile="$stripped.u"
+ outname="$stripped.o"
+ if test "$libtool" = yes; then
+ "$@" -Wc,-M
+ else
+ "$@" -M
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+ sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in `foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+
+ base=`echo "$object" | sed -e 's/\.o$//' -e 's/\.lo$//'`
+ tmpdepfile1="$base.o.d"
+ tmpdepfile2="$base.d"
+ if test "$libtool" = yes; then
+ "$@" -Wc,-MD
+ else
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ if test -f "$tmpdepfile1"; then
+ tmpdepfile="$tmpdepfile1"
+ else
+ tmpdepfile="$tmpdepfile2"
+ fi
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a space and a tab in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ test -z "$dashmflag" && dashmflag=-M
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*) # this is libtool, let us make it quiet
+ for arg
+ do # cycle over the arguments
+ case "$arg" in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ # X makedepend
+ (
+ shift
+ cleared=no
+ for arg in "$@"; do
+ case $cleared in no)
+ set ""; shift
+ cleared=yes
+ esac
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift;;
+ -*)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift;;
+ esac
+ done
+ obj_suffix="`echo $object | sed 's/^.*\././'`"
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*)
+ for arg
+ do # cycle over the arguments
+ case $arg in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ "$@" -E |
+ sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*)
+ for arg
+ do # cycle over the arguments
+ case $arg in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ for arg
+ do
+ case "$arg" in
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/tools/build/v2/engine/boehm_gc/digimars.mak b/tools/build/v2/engine/boehm_gc/digimars.mak
new file mode 100644
index 0000000000..2080611826
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/digimars.mak
@@ -0,0 +1,90 @@
+# Makefile to build Hans Boehm garbage collector using the Digital Mars
+# compiler from www.digitalmars.com
+# Written by Walter Bright
+
+
+DEFINES=-DNDEBUG -DGC_BUILD -D_WINDOWS -DGC_DLL -DALL_INTERIOR_POINTERS -D__STDC__ -DWIN32_THREADS
+CFLAGS=-Iinclude $(DEFINES) -wx -g
+LFLAGS=/ma/implib/co
+CC=sc
+
+.c.obj:
+ $(CC) -c $(CFLAGS) $*
+
+.cpp.obj:
+ $(CC) -c $(CFLAGS) -Aa $*
+
+OBJS= \
+ allchblk.obj\
+ alloc.obj\
+ blacklst.obj\
+ checksums.obj\
+ dbg_mlc.obj\
+ dyn_load.obj\
+ finalize.obj\
+ gc_cpp.obj\
+ headers.obj\
+ mach_dep.obj\
+ malloc.obj\
+ mallocx.obj\
+ mark.obj\
+ mark_rts.obj\
+ misc.obj\
+ new_hblk.obj\
+ obj_map.obj\
+ os_dep.obj\
+ ptr_chck.obj\
+ reclaim.obj\
+ stubborn.obj\
+ typd_mlc.obj\
+ win32_threads.obj
+
+targets: gc.dll gc.lib gctest.exe
+
+gc.dll: $(OBJS) gc.def digimars.mak
+ sc -ogc.dll $(OBJS) -L$(LFLAGS) gc.def kernel32.lib user32.lib
+
+gc.def: digimars.mak
+ echo LIBRARY GC >gc.def
+ echo DESCRIPTION "Hans Boehm Garbage Collector" >>gc.def
+ echo EXETYPE NT >>gc.def
+ echo EXPORTS >>gc.def
+ echo GC_is_visible_print_proc >>gc.def
+ echo GC_is_valid_displacement_print_proc >>gc.def
+
+clean:
+ del gc.def
+ del $(OBJS)
+
+
+gctest.exe : gc.lib tests\test.obj
+ sc -ogctest.exe tests\test.obj gc.lib
+
+tests\test.obj : tests\test.c
+ $(CC) -c -g -DNDEBUG -DGC_BUILD -D_WINDOWS -DGC_DLL \
+ -DALL_INTERIOR_POINTERS -DWIN32_THREADS \
+ -Iinclude tests\test.c -otests\test.obj
+
+allchblk.obj: allchblk.c
+alloc.obj: alloc.c
+blacklst.obj: blacklst.c
+checksums.obj: checksums.c
+dbg_mlc.obj: dbg_mlc.c
+dyn_load.obj: dyn_load.c
+finalize.obj: finalize.c
+gc_cpp.obj: gc_cpp.cpp
+headers.obj: headers.c
+mach_dep.obj: mach_dep.c
+malloc.obj: malloc.c
+mallocx.obj: mallocx.c
+mark.obj: mark.c
+mark_rts.obj: mark_rts.c
+misc.obj: misc.c
+new_hblk.obj: new_hblk.c
+obj_map.obj: obj_map.c
+os_dep.obj: os_dep.c
+ptr_chck.obj: ptr_chck.c
+reclaim.obj: reclaim.c
+stubborn.obj: stubborn.c
+typd_mlc.obj: typd_mlc.c
+win32_threads.obj: win32_threads.c
diff --git a/tools/build/v2/engine/boehm_gc/doc/README b/tools/build/v2/engine/boehm_gc/doc/README
new file mode 100644
index 0000000000..33a6740bcc
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README
@@ -0,0 +1,548 @@
+Copyright (c) 1988, 1989 Hans-J. Boehm, Alan J. Demers
+Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
+Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+Copyright (c) 1999-2005 Hewlett-Packard Development Company, L.P.
+
+The file linux_threads.c is also
+Copyright (c) 1998 by Fergus Henderson. All rights reserved.
+
+The files Makefile.am, and configure.in are
+Copyright (c) 2001 by Red Hat Inc. All rights reserved.
+
+Several files supporting GNU-style builds are copyrighted by the Free
+Software Foundation, and carry a different license from that given
+below. The files included in the libatomic_ops distribution (included
+here) use either the license below, or a similar MIT-style license,
+or, for some files not actually used by the garbage-collector library, the
+GPL.
+
+THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+
+Permission is hereby granted to use or copy this program
+for any purpose, provided the above notices are retained on all copies.
+Permission to modify the code and to distribute modified code is granted,
+provided the above notices are retained, and a notice that the code was
+modified is included with the above copyright notice.
+
+A few of the files needed to use the GNU-style build procedure come with
+slightly different licenses, though they are all similar in spirit. A few
+are GPL'ed, but with an exception that should cover all uses in the
+collector. (If you are concerned about such things, I recommend you look
+at the notice in config.guess or ltmain.sh.)
+
+This is version 7.0 of a conservative garbage collector for C and C++.
+
+You might find a more recent version of this at
+
+http://www.hpl.hp.com/personal/Hans_Boehm/gc
+
+OVERVIEW
+
+ This is intended to be a general purpose, garbage collecting storage
+allocator. The algorithms used are described in:
+
+Boehm, H., and M. Weiser, "Garbage Collection in an Uncooperative Environment",
+Software Practice & Experience, September 1988, pp. 807-820.
+
+Boehm, H., A. Demers, and S. Shenker, "Mostly Parallel Garbage Collection",
+Proceedings of the ACM SIGPLAN '91 Conference on Programming Language Design
+and Implementation, SIGPLAN Notices 26, 6 (June 1991), pp. 157-164.
+
+Boehm, H., "Space Efficient Conservative Garbage Collection", Proceedings
+of the ACM SIGPLAN '91 Conference on Programming Language Design and
+Implementation, SIGPLAN Notices 28, 6 (June 1993), pp. 197-206.
+
+Boehm H., "Reducing Garbage Collector Cache Misses", Proceedings of the
+2000 International Symposium on Memory Management.
+
+ Possible interactions between the collector and optimizing compilers are
+discussed in
+
+Boehm, H., and D. Chase, "A Proposal for GC-safe C Compilation",
+The Journal of C Language Translation 4, 2 (December 1992).
+
+and
+
+Boehm H., "Simple GC-safe Compilation", Proceedings
+of the ACM SIGPLAN '96 Conference on Programming Language Design and
+Implementation.
+
+(Some of these are also available from
+http://www.hpl.hp.com/personal/Hans_Boehm/papers/, among other places.)
+
+ Unlike the collector described in the second reference, this collector
+operates either with the mutator stopped during the entire collection
+(default) or incrementally during allocations. (The latter is supported
+on fewer machines.) On the most common platforms, it can be built
+with or without thread support. On a few platforms, it can take advantage
+of a multiprocessor to speed up garbage collection.
+
+ Many of the ideas underlying the collector have previously been explored
+by others. Notably, some of the run-time systems developed at Xerox PARC
+in the early 1980s conservatively scanned thread stacks to locate possible
+pointers (cf. Paul Rovner, "On Adding Garbage Collection and Runtime Types
+to a Strongly-Typed Statically Checked, Concurrent Language" Xerox PARC
+CSL 84-7). Doug McIlroy wrote a simpler fully conservative collector that
+was part of version 8 UNIX (tm), but appears to not have received
+widespread use.
+
+ Rudimentary tools for use of the collector as a leak detector are included
+(see http://www.hpl.hp.com/personal/Hans_Boehm/gc/leak.html),
+as is a fairly sophisticated string package "cord" that makes use of the
+collector. (See doc/README.cords and H.-J. Boehm, R. Atkinson, and M. Plass,
+"Ropes: An Alternative to Strings", Software Practice and Experience 25, 12
+(December 1995), pp. 1315-1330. This is very similar to the "rope" package
+in Xerox Cedar, or the "rope" package in the SGI STL or the g++ distribution.)
+
+Further collector documantation can be found at
+
+http://www.hpl.hp.com/personal/Hans_Boehm/gc
+
+
+GENERAL DESCRIPTION
+
+ This is a garbage collecting storage allocator that is intended to be
+used as a plug-in replacement for C's malloc.
+
+ Since the collector does not require pointers to be tagged, it does not
+attempt to ensure that all inaccessible storage is reclaimed. However,
+in our experience, it is typically more successful at reclaiming unused
+memory than most C programs using explicit deallocation. Unlike manually
+introduced leaks, the amount of unreclaimed memory typically stays
+bounded.
+
+ In the following, an "object" is defined to be a region of memory allocated
+by the routines described below.
+
+ Any objects not intended to be collected must be pointed to either
+from other such accessible objects, or from the registers,
+stack, data, or statically allocated bss segments. Pointers from
+the stack or registers may point to anywhere inside an object.
+The same is true for heap pointers if the collector is compiled with
+ALL_INTERIOR_POINTERS defined, or GC_all_interior_pointers is otherwise
+set, as is now the default.
+
+Compiling without ALL_INTERIOR_POINTERS may reduce accidental retention
+of garbage objects, by requiring pointers from the heap to to the beginning
+of an object. But this no longer appears to be a significant
+issue for most programs occupying a small fraction of the possible
+address space.
+
+There are a number of routines which modify the pointer recognition
+algorithm. GC_register_displacement allows certain interior pointers
+to be recognized even if ALL_INTERIOR_POINTERS is nor defined.
+GC_malloc_ignore_off_page allows some pointers into the middle of large objects
+to be disregarded, greatly reducing the probablility of accidental
+retention of large objects. For most purposes it seems best to compile
+with ALL_INTERIOR_POINTERS and to use GC_malloc_ignore_off_page if
+you get collector warnings from allocations of very large objects.
+See README.debugging for details.
+
+ WARNING: pointers inside memory allocated by the standard "malloc" are not
+seen by the garbage collector. Thus objects pointed to only from such a
+region may be prematurely deallocated. It is thus suggested that the
+standard "malloc" be used only for memory regions, such as I/O buffers, that
+are guaranteed not to contain pointers to garbage collectable memory.
+Pointers in C language automatic, static, or register variables,
+are correctly recognized. (Note that GC_malloc_uncollectable has semantics
+similar to standard malloc, but allocates objects that are traced by the
+collector.)
+
+ WARNING: the collector does not always know how to find pointers in data
+areas that are associated with dynamic libraries. This is easy to
+remedy IF you know how to find those data areas on your operating
+system (see GC_add_roots). Code for doing this under SunOS, IRIX 5.X and 6.X,
+HP/UX, Alpha OSF/1, Linux, and win32 is included and used by default. (See
+README.win32 for win32 details.) On other systems pointers from dynamic
+library data areas may not be considered by the collector.
+If you're writing a program that depends on the collector scanning
+dynamic library data areas, it may be a good idea to include at least
+one call to GC_is_visible() to ensure that those areas are visible
+to the collector.
+
+ Note that the garbage collector does not need to be informed of shared
+read-only data. However if the shared library mechanism can introduce
+discontiguous data areas that may contain pointers, then the collector does
+need to be informed.
+
+ Signal processing for most signals may be deferred during collection,
+and during uninterruptible parts of the allocation process.
+Like standard ANSI C mallocs, by default it is unsafe to invoke
+malloc (and other GC routines) from a signal handler while another
+malloc call may be in progress. Removing -DNO_SIGNALS from Makefile
+attempts to remedy that. But that may not be reliable with a compiler that
+substantially reorders memory operations inside GC_malloc.
+
+ The allocator/collector can also be configured for thread-safe operation.
+(Full signal safety can also be achieved, but only at the cost of two system
+calls per malloc, which is usually unacceptable.)
+WARNING: the collector does not guarantee to scan thread-local storage
+(e.g. of the kind accessed with pthread_getspecific()). The collector
+does scan thread stacks, though, so generally the best solution is to
+ensure that any pointers stored in thread-local storage are also
+stored on the thread's stack for the duration of their lifetime.
+(This is arguably a longstanding bug, but it hasn't been fixed yet.)
+
+INSTALLATION AND PORTABILITY
+
+ As distributed, the collector operates silently
+In the event of problems, this can usually be changed by defining the
+GC_PRINT_STATS or GC_PRINT_VERBOSE_STATS environment variables. This
+will result in a few lines of descriptive output for each collection.
+(The given statistics exhibit a few peculiarities.
+Things don't appear to add up for a variety of reasons, most notably
+fragmentation losses. These are probably much more significant for the
+contrived program "test.c" than for your application.)
+
+ On most Un*x-like platforms, the collector can be built either using a
+GNU autoconf-based build infrastructure (type "configure; make" in the
+simplest case), or with a classic makefile by itself (type
+"cp Makefile.direct Makefile; make"). Here we focus on the latter option.
+On other platforms, typically only the latter option is available, though
+with a different supplied Makefile.)
+
+ Typing "make test" nstead of "make" will automatically build the collector
+and then run setjmp_test and gctest. Setjmp_test will give you information
+about configuring the collector, which is useful primarily if you have
+a machine that's not already supported. Gctest is a somewhat superficial
+test of collector functionality. Failure is indicated by a core dump or
+a message to the effect that the collector is broken. Gctest takes about
+a second to two to run on reasonable 2007 vintage desktops.
+It may use up to about 30MB of memory. (The
+multi-threaded version will use more. 64-bit versions may use more.)
+"Make test" will also, as its last step, attempt to build and test the
+"cord" string library.)
+
+ The Makefile will generate a library gc.a which you should link against.
+Typing "make cords" will add the cord library to gc.a.
+Note that this requires an ANSI C compiler.
+
+ It is suggested that if you need to replace a piece of the collector
+(e.g. GC_mark_rts.c) you simply list your version ahead of gc.a on the
+ld command line, rather than replacing the one in gc.a. (This will
+generate numerous warnings under some versions of AIX, but it still
+works.)
+
+ All include files that need to be used by clients will be put in the
+include subdirectory. (Normally this is just gc.h. "Make cords" adds
+"cord.h" and "ec.h".)
+
+ The collector currently is designed to run essentially unmodified on
+machines that use a flat 32-bit or 64-bit address space.
+That includes the vast majority of Workstations and X86 (X >= 3) PCs.
+(The list here was deleted because it was getting too long and constantly
+out of date.)
+
+ In a few cases (Amiga, OS/2, Win32, MacOS) a separate makefile
+or equivalent is supplied. Many of these have separate README.system
+files.
+
+ Dynamic libraries are completely supported only under SunOS/Solaris,
+(and even that support is not functional on the last Sun 3 release),
+Linux, FreeBSD, NetBSD, IRIX 5&6, HP/UX, Win32 (not Win32S) and OSF/1
+on DEC AXP machines plus perhaps a few others listed near the top
+of dyn_load.c. On other machines we recommend that you do one of
+the following:
+
+ 1) Add dynamic library support (and send us the code).
+ 2) Use static versions of the libraries.
+ 3) Arrange for dynamic libraries to use the standard malloc.
+ This is still dangerous if the library stores a pointer to a
+ garbage collected object. But nearly all standard interfaces
+ prohibit this, because they deal correctly with pointers
+ to stack allocated objects. (Strtok is an exception. Don't
+ use it.)
+
+ In all cases we assume that pointer alignment is consistent with that
+enforced by the standard C compilers. If you use a nonstandard compiler
+you may have to adjust the alignment parameters defined in gc_priv.h.
+Note that this may also be an issue with packed records/structs, if those
+enforce less alignment for pointers.
+
+ A port to a machine that is not byte addressed, or does not use 32 bit
+or 64 bit addresses will require a major effort. A port to plain MSDOS
+or win16 is hard.
+
+ For machines not already mentioned, or for nonstandard compilers,
+some porting suggestions are provided in the "porting.html" file.
+
+THE C INTERFACE TO THE ALLOCATOR
+
+ The following routines are intended to be directly called by the user.
+Note that usually only GC_malloc is necessary. GC_clear_roots and GC_add_roots
+calls may be required if the collector has to trace from nonstandard places
+(e.g. from dynamic library data areas on a machine on which the
+collector doesn't already understand them.) On some machines, it may
+be desirable to set GC_stacktop to a good approximation of the stack base.
+(This enhances code portability on HP PA machines, since there is no
+good way for the collector to compute this value.) Client code may include
+"gc.h", which defines all of the following, plus many others.
+
+1) GC_malloc(nbytes)
+ - allocate an object of size nbytes. Unlike malloc, the object is
+ cleared before being returned to the user. Gc_malloc will
+ invoke the garbage collector when it determines this to be appropriate.
+ GC_malloc may return 0 if it is unable to acquire sufficient
+ space from the operating system. This is the most probable
+ consequence of running out of space. Other possible consequences
+ are that a function call will fail due to lack of stack space,
+ or that the collector will fail in other ways because it cannot
+ maintain its internal data structures, or that a crucial system
+ process will fail and take down the machine. Most of these
+ possibilities are independent of the malloc implementation.
+
+2) GC_malloc_atomic(nbytes)
+ - allocate an object of size nbytes that is guaranteed not to contain any
+ pointers. The returned object is not guaranteed to be cleared.
+ (Can always be replaced by GC_malloc, but results in faster collection
+ times. The collector will probably run faster if large character
+ arrays, etc. are allocated with GC_malloc_atomic than if they are
+ statically allocated.)
+
+3) GC_realloc(object, new_size)
+ - change the size of object to be new_size. Returns a pointer to the
+ new object, which may, or may not, be the same as the pointer to
+ the old object. The new object is taken to be atomic iff the old one
+ was. If the new object is composite and larger than the original object,
+ then the newly added bytes are cleared (we hope). This is very likely
+ to allocate a new object, unless MERGE_SIZES is defined in gc_priv.h.
+ Even then, it is likely to recycle the old object only if the object
+ is grown in small additive increments (which, we claim, is generally bad
+ coding practice.)
+
+4) GC_free(object)
+ - explicitly deallocate an object returned by GC_malloc or
+ GC_malloc_atomic. Not necessary, but can be used to minimize
+ collections if performance is critical. Probably a performance
+ loss for very small objects (<= 8 bytes).
+
+5) GC_expand_hp(bytes)
+ - Explicitly increase the heap size. (This is normally done automatically
+ if a garbage collection failed to GC_reclaim enough memory. Explicit
+ calls to GC_expand_hp may prevent unnecessarily frequent collections at
+ program startup.)
+
+6) GC_malloc_ignore_off_page(bytes)
+ - identical to GC_malloc, but the client promises to keep a pointer to
+ the somewhere within the first 256 bytes of the object while it is
+ live. (This pointer should nortmally be declared volatile to prevent
+ interference from compiler optimizations.) This is the recommended
+ way to allocate anything that is likely to be larger than 100Kbytes
+ or so. (GC_malloc may result in failure to reclaim such objects.)
+
+7) GC_set_warn_proc(proc)
+ - Can be used to redirect warnings from the collector. Such warnings
+ should be rare, and should not be ignored during code development.
+
+8) GC_enable_incremental()
+ - Enables generational and incremental collection. Useful for large
+ heaps on machines that provide access to page dirty information.
+ Some dirty bit implementations may interfere with debugging
+ (by catching address faults) and place restrictions on heap arguments
+ to system calls (since write faults inside a system call may not be
+ handled well).
+
+9) Several routines to allow for registration of finalization code.
+ User supplied finalization code may be invoked when an object becomes
+ unreachable. To call (*f)(obj, x) when obj becomes inaccessible, use
+ GC_register_finalizer(obj, f, x, 0, 0);
+ For more sophisticated uses, and for finalization ordering issues,
+ see gc.h.
+
+ The global variable GC_free_space_divisor may be adjusted up from its
+default value of 4 to use less space and more collection time, or down for
+the opposite effect. Setting it to 1 or 0 will effectively disable collections
+and cause all allocations to simply grow the heap.
+
+ The variable GC_non_gc_bytes, which is normally 0, may be changed to reflect
+the amount of memory allocated by the above routines that should not be
+considered as a candidate for collection. Careless use may, of course, result
+in excessive memory consumption.
+
+ Some additional tuning is possible through the parameters defined
+near the top of gc_priv.h.
+
+ If only GC_malloc is intended to be used, it might be appropriate to define:
+
+#define malloc(n) GC_malloc(n)
+#define calloc(m,n) GC_malloc((m)*(n))
+
+ For small pieces of VERY allocation intensive code, gc_inl.h
+includes some allocation macros that may be used in place of GC_malloc
+and friends.
+
+ All externally visible names in the garbage collector start with "GC_".
+To avoid name conflicts, client code should avoid this prefix, except when
+accessing garbage collector routines or variables.
+
+ There are provisions for allocation with explicit type information.
+This is rarely necessary. Details can be found in gc_typed.h.
+
+THE C++ INTERFACE TO THE ALLOCATOR:
+
+ The Ellis-Hull C++ interface to the collector is included in
+the collector distribution. If you intend to use this, type
+"make c++" after the initial build of the collector is complete.
+See gc_cpp.h for the definition of the interface. This interface
+tries to approximate the Ellis-Detlefs C++ garbage collection
+proposal without compiler changes.
+
+ Very often it will also be necessary to use gc_allocator.h and the
+allocator declared there to construct STL data structures. Otherwise
+subobjects of STL data structures wil be allcoated using a system
+allocator, and objects they refer to may be prematurely collected.
+
+USE AS LEAK DETECTOR:
+
+ The collector may be used to track down leaks in C programs that are
+intended to run with malloc/free (e.g. code with extreme real-time or
+portability constraints). To do so define FIND_LEAK in Makefile
+This will cause the collector to invoke the report_leak
+routine defined near the top of reclaim.c whenever an inaccessible
+object is found that has not been explicitly freed. Such objects will
+also be automatically reclaimed.
+ If all objects are allocated with GC_DEBUG_MALLOC (see next section), then
+the default version of report_leak will report at least the source file and
+line number at which the leaked object was allocated. This may sometimes be
+sufficient. (On a few machines, it will also report a cryptic stack trace.
+If this is not symbolic, it can somethimes be called into a sympolic stack
+trace by invoking program "foo" with "callprocs foo". Callprocs is a short
+shell script that invokes adb to expand program counter values to symbolic
+addresses. It was largely supplied by Scott Schwartz.)
+ Note that the debugging facilities described in the next section can
+sometimes be slightly LESS effective in leak finding mode, since in
+leak finding mode, GC_debug_free actually results in reuse of the object.
+(Otherwise the object is simply marked invalid.) Also note that the test
+program is not designed to run meaningfully in FIND_LEAK mode.
+Use "make gc.a" to build the collector.
+
+DEBUGGING FACILITIES:
+
+ The routines GC_debug_malloc, GC_debug_malloc_atomic, GC_debug_realloc,
+and GC_debug_free provide an alternate interface to the collector, which
+provides some help with memory overwrite errors, and the like.
+Objects allocated in this way are annotated with additional
+information. Some of this information is checked during garbage
+collections, and detected inconsistencies are reported to stderr.
+
+ Simple cases of writing past the end of an allocated object should
+be caught if the object is explicitly deallocated, or if the
+collector is invoked while the object is live. The first deallocation
+of an object will clear the debugging info associated with an
+object, so accidentally repeated calls to GC_debug_free will report the
+deallocation of an object without debugging information. Out of
+memory errors will be reported to stderr, in addition to returning
+NIL.
+
+ GC_debug_malloc checking during garbage collection is enabled
+with the first call to GC_debug_malloc. This will result in some
+slowdown during collections. If frequent heap checks are desired,
+this can be achieved by explicitly invoking GC_gcollect, e.g. from
+the debugger.
+
+ GC_debug_malloc allocated objects should not be passed to GC_realloc
+or GC_free, and conversely. It is however acceptable to allocate only
+some objects with GC_debug_malloc, and to use GC_malloc for other objects,
+provided the two pools are kept distinct. In this case, there is a very
+low probablility that GC_malloc allocated objects may be misidentified as
+having been overwritten. This should happen with probability at most
+one in 2**32. This probability is zero if GC_debug_malloc is never called.
+
+ GC_debug_malloc, GC_malloc_atomic, and GC_debug_realloc take two
+additional trailing arguments, a string and an integer. These are not
+interpreted by the allocator. They are stored in the object (the string is
+not copied). If an error involving the object is detected, they are printed.
+
+ The macros GC_MALLOC, GC_MALLOC_ATOMIC, GC_REALLOC, GC_FREE, and
+GC_REGISTER_FINALIZER are also provided. These require the same arguments
+as the corresponding (nondebugging) routines. If gc.h is included
+with GC_DEBUG defined, they call the debugging versions of these
+functions, passing the current file name and line number as the two
+extra arguments, where appropriate. If gc.h is included without GC_DEBUG
+defined, then all these macros will instead be defined to their nondebugging
+equivalents. (GC_REGISTER_FINALIZER is necessary, since pointers to
+objects with debugging information are really pointers to a displacement
+of 16 bytes form the object beginning, and some translation is necessary
+when finalization routines are invoked. For details, about what's stored
+in the header, see the definition of the type oh in debug_malloc.c)
+
+INCREMENTAL/GENERATIONAL COLLECTION:
+
+The collector normally interrupts client code for the duration of
+a garbage collection mark phase. This may be unacceptable if interactive
+response is needed for programs with large heaps. The collector
+can also run in a "generational" mode, in which it usually attempts to
+collect only objects allocated since the last garbage collection.
+Furthermore, in this mode, garbage collections run mostly incrementally,
+with a small amount of work performed in response to each of a large number of
+GC_malloc requests.
+
+This mode is enabled by a call to GC_enable_incremental().
+
+Incremental and generational collection is effective in reducing
+pause times only if the collector has some way to tell which objects
+or pages have been recently modified. The collector uses two sources
+of information:
+
+1. Information provided by the VM system. This may be provided in
+one of several forms. Under Solaris 2.X (and potentially under other
+similar systems) information on dirty pages can be read from the
+/proc file system. Under other systems (currently SunOS4.X) it is
+possible to write-protect the heap, and catch the resulting faults.
+On these systems we require that system calls writing to the heap
+(other than read) be handled specially by client code.
+See os_dep.c for details.
+
+2. Information supplied by the programmer. We define "stubborn"
+objects to be objects that are rarely changed. Such an object
+can be allocated (and enabled for writing) with GC_malloc_stubborn.
+Once it has been initialized, the collector should be informed with
+a call to GC_end_stubborn_change. Subsequent writes that store
+pointers into the object must be preceded by a call to
+GC_change_stubborn.
+
+This mechanism performs best for objects that are written only for
+initialization, and such that only one stubborn object is writable
+at once. It is typically not worth using for short-lived
+objects. Stubborn objects are treated less efficiently than pointerfree
+(atomic) objects.
+
+A rough rule of thumb is that, in the absence of VM information, garbage
+collection pauses are proportional to the amount of pointerful storage
+plus the amount of modified "stubborn" storage that is reachable during
+the collection.
+
+Initial allocation of stubborn objects takes longer than allocation
+of other objects, since other data structures need to be maintained.
+
+We recommend against random use of stubborn objects in client
+code, since bugs caused by inappropriate writes to stubborn objects
+are likely to be very infrequently observed and hard to trace.
+However, their use may be appropriate in a few carefully written
+library routines that do not make the objects themselves available
+for writing by client code.
+
+
+BUGS:
+
+ Any memory that does not have a recognizable pointer to it will be
+reclaimed. Exclusive-or'ing forward and backward links in a list
+doesn't cut it.
+ Some C optimizers may lose the last undisguised pointer to a memory
+object as a consequence of clever optimizations. This has almost
+never been observed in practice. Send mail to boehm@acm.org
+for suggestions on how to fix your compiler.
+ This is not a real-time collector. In the standard configuration,
+percentage of time required for collection should be constant across
+heap sizes. But collection pauses will increase for larger heaps.
+They will decrease with the number of processors if parallel marking
+is enabled.
+(On 2007 vintage machines, GC times may be on the order of 5 msecs
+per MB of accessible memory that needs to be scanned and processor.
+Your mileage may vary.) The incremental/generational collection facility
+may help in some cases.
+ Please address bug reports to boehm@acm.org. If you are
+contemplating a major addition, you might also send mail to ask whether
+it's already been done (or whether we tried and discarded it).
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.DGUX386 b/tools/build/v2/engine/boehm_gc/doc/README.DGUX386
new file mode 100644
index 0000000000..9d6d84788e
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.DGUX386
@@ -0,0 +1,215 @@
+ Garbage Collector (parallel iversion) for ix86 DG/UX Release R4.20MU07
+
+
+ *READ* the file README.QUICK.
+
+ You need the GCC-3.0.3 rev (DG/UX) compiler to build this tree.
+ This compiler has the new "dgux386" threads package implemented.
+ It also supports the switch "-pthread" needed to link correctly
+ the DG/UX's -lrte -lthread with -lgcc and the system's -lc.
+ Finally we support parralleli-mark for the SMP DG/UX machines.
+ To build the garbage collector do:
+
+ ./configure --enable-parallel-mark
+ make
+ make gctest
+
+ Before you run "gctest" you need to set your LD_LIBRARY_PATH
+ correctly so that "gctest" can find the shared library libgc.
+ Alternatively you can do a configuration
+
+ ./configure --enable-parallel-mark --disable-shared
+
+ to build only the static version of libgc.
+
+ To enable debugging messages please do:
+ 1) Add the "--enable-full-debug" flag during configuration.
+ 2) Edit the file linux-threads.c and uncommnect the line:
+
+ /* #define DEBUG_THREADS 1 */ to --->
+
+ #define DEBUG_THREADS 1
+
+ Then give "make" as usual.
+
+ In a machine with 4 CPUs (my own machine) the option parallel
+ mark (aka --enable-parallel-mark) makes a BIG difference.
+
+ Takis Psarogiannakopoulos
+ University of Cambridge
+ Centre for Mathematical Sciences
+ Department of Pure Mathematics
+ Wilberforce Road
+ Cambridge CB3 0WB ,UK , <takis@XFree86.Org>
+ January 2002
+
+
+Note (HB):
+ The integration of this patch is currently not complete.
+ The following patches against 6.1alpha3 where hard to move
+ to alpha4, and are not integrated. There may also be minor
+ problems with stylistic corrections made by me.
+
+
+--- ltconfig.ORIG Mon Jan 28 20:22:18 2002
++++ ltconfig Mon Jan 28 20:44:00 2002
+@@ -689,6 +689,11 @@
+ pic_flag=-Kconform_pic
+ fi
+ ;;
++ dgux*)
++ pic_flag='-fPIC'
++ link_static='-Bstatic'
++ wl='-Wl,'
++ ;;
+ *)
+ pic_flag='-fPIC'
+ ;;
+@@ -718,6 +723,12 @@
+ # We can build DLLs from non-PIC.
+ ;;
+
++ dgux*)
++ pic_flag='-KPIC'
++ link_static='-Bstatic'
++ wl='-Wl,'
++ ;;
++
+ osf3* | osf4* | osf5*)
+ # All OSF/1 code is PIC.
+ wl='-Wl,'
+@@ -1154,6 +1165,22 @@
+ fi
+ ;;
+
++ dgux*)
++ ld_shlibs=yes
++ # For both C/C++ ommit the deplibs. This is because we relying on the fact
++ # that compilation of execitables will put them in correct order
++ # in any case and sometimes are wrong when listed as deplibs (or missing some deplibs)
++ # However when GNU ld and --whole-archive needs to be used we have the problem
++ # that if the -fPIC *_s.a archive is linked through deplibs list we ommiting crucial
++ # .lo/.o files from the created shared lib. This I think is not the case here.
++ archive_cmds='$CC -shared -h $soname -o $lib $libobjs $linkopts'
++ thread_safe_flag_spec='-pthread'
++ wlarc=
++ hardcode_libdir_flag_spec='-L$libdir'
++ hardcode_shlibpath_var=no
++ ac_cv_archive_cmds_needs_lc=no
++ ;;
++
+ cygwin* | mingw*)
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+@@ -1497,7 +1524,7 @@
+ ;;
+
+ dgux*)
+- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
++ archive_cmds='$CC -shared -h $soname -o $lib $libobjs $linkopts'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+@@ -2092,12 +2119,17 @@
+ ;;
+
+ dgux*)
+- version_type=linux
++ version_type=dgux
+ need_lib_prefix=no
+ need_version=no
+- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+- soname_spec='${libname}${release}.so$major'
++ library_names_spec='$libname.so$versuffix'
++ soname_spec='$libname.so$versuffix'
+ shlibpath_var=LD_LIBRARY_PATH
++ thread_safe_flag_spec='-pthread'
++ wlarc=
++ hardcode_libdir_flag_spec='-L$libdir'
++ hardcode_shlibpath_var=no
++ ac_cv_archive_cmds_needs_lc=no
+ ;;
+
+ sysv4*MP*)
+
+
+--- ltmain.sh.ORIG Mon Jan 28 20:31:18 2002
++++ ltmain.sh Tue Jan 29 00:11:29 2002
+@@ -1072,11 +1072,38 @@
+ esac
+ ;;
+
++ -thread*)
++ # DG/UX GCC 2.95.x, 3.x.x rev (DG/UX) links -lthread
++ # with the switch -threads
++ if test "$arg" = "-threads"; then
++ case "$host" in
++ i[3456]86-*-dgux*)
++ deplibs="$deplibs $arg"
++ continue
++ ;;
++ esac
++ fi
++ ;;
++
++ -pthread*)
++ # DG/UX GCC 2.95.x, 3.x.x rev (DG/UX) links -lthread
++ # with the switch -pthread
++ if test "$arg" = "-pthread"; then
++ case "$host" in
++ i[3456]86-*-dgux*)
++ deplibs="$deplibs $arg"
++ continue
++ ;;
++ esac
++ fi
++ ;;
++
+ -l*)
+ if test "$arg" = "-lc"; then
+ case "$host" in
+- *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
++ *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos* | i[3456]86-*-dgux*)
+ # These systems don't actually have c library (as such)
++ # It is wrong in DG/UX to add -lc when creating shared/dynamic objs/libs
+ continue
+ ;;
+ esac
+@@ -1248,6 +1275,12 @@
+ temp_deplibs=
+ for deplib in $dependency_libs; do
+ case "$deplib" in
++ -thread*)
++ temp_deplibs="$temp_deplibs $deplib"
++ ;;
++ -pthread)
++ temp_deplibs="$temp_deplibs $deplib"
++ ;;
+ -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ case " $rpath $xrpath " in
+ *" $temp_xrpath "*) ;;
+@@ -1709,6 +1742,13 @@
+ done
+ ;;
+
++ dgux)
++ # Leave mostly blank for DG/UX
++ major=
++ versuffix=".$current.$revision";
++ verstring=
++ ;;
++
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+@@ -1792,8 +1832,9 @@
+
+ dependency_libs="$deplibs"
+ case "$host" in
+- *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
++ *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos* | i[3456]86-*-dgux*)
+ # these systems don't actually have a c library (as such)!
++ # It is wrong in DG/UX to add -lc when creating shared/dynamic objs/libs
+ ;;
+ *)
+ # Add libc to deplibs on all other systems.
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.Mac b/tools/build/v2/engine/boehm_gc/doc/README.Mac
new file mode 100644
index 0000000000..ae9c1d5e59
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.Mac
@@ -0,0 +1,390 @@
+The contents of this file are old and pertain to pre-MacOSX versions.
+You probably really wanted README.darwin.
+
+---------------------------------------------
+
+Patrick Beard's Notes for building GC v4.12 with CodeWarrior Pro 2:
+----------------------------------------------------------------------------
+The current build environment for the collector is CodeWarrior Pro 2.
+Projects for CodeWarrior Pro 2 (and for quite a few older versions)
+are distributed in the file Mac_projects.sit.hqx. The project file
+:Mac_projects:gc.prj builds static library versions of the collector.
+:Mac_projects:gctest.prj builds the GC test suite.
+
+Configuring the collector is still done by editing the files
+:Mac_files:MacOS_config.h and :Mac_files:MacOS_Test_config.h.
+
+Lars Farm's suggestions on building the collector:
+----------------------------------------------------------------------------
+Garbage Collection on MacOS - a manual 'MakeFile'
+-------------------------------------------------
+
+Project files and IDE's are great on the Macintosh, but they do have
+problems when used as distribution media. This note tries to provide
+porting instructions in pure TEXT form to avoid those problems. A manual
+'makefile' if you like.
+
+ GC version: 4.12a2
+ Codewarrior: CWPro1
+ date: 18 July 1997
+
+The notes may or may not apply to earlier or later versions of the
+GC/CWPro. Actually, they do apply to earlier versions of both except that
+until recently a project could only build one target so each target was a
+separate project. The notes will most likely apply to future versions too.
+Possibly with minor tweaks.
+
+This is just to record my experiences. These notes do not mean I now
+provide a supported port of the GC to MacOS. It works for me. If it works
+for you, great. If it doesn't, sorry, try again...;-) Still, if you find
+errors, please let me know.
+
+ mailto: lars.farm@ite.mh.se
+
+ address: Lars Farm
+ Krönvägen 33b
+ 856 44 Sundsvall
+ Sweden
+
+Porting to MacOS is a bit more complex than it first seems. Which MacOS?
+68K/PowerPC? Which compiler? Each supports both 68K and PowerPC and offer a
+large number of (unique to each environment) compiler settings. Each
+combination of compiler/68K/PPC/settings require a unique combination of
+standard libraries. And the IDE's does not select them for you. They don't
+even check that the library is built with compatible setting and this is
+the major source of problems when porting the GC (and otherwise too).
+
+You will have to make choices when you configure the GC. I've made some
+choices here, but there are other combinations of settings and #defines
+that work too.
+
+As for target settings the major obstacles may be:
+- 68K Processor: check "4-byte Ints".
+- PPC Processor: uncheck "Store Static Data in TOC".
+
+What you need to do:
+===================
+
+1) Build the GC as a library
+2) Test that the library works with 'test.c'.
+3) Test that the C++ interface 'gc_cpp.cc/h' works with 'test_cpp.cc'.
+
+1) The Libraries:
+=================
+I made one project with four targets (68K/PPC tempmem or appheap). One target
+will suffice if you're able to decide which one you want. I wasn't...
+
+Codewarrior allows a large number of compiler/linker settings. I used these:
+
+Settings shared by all targets:
+------------------------------
+o Access Paths:
+ - User Paths: the GC folder
+ - System Paths: {Compiler}:Metrowerks Standard Library:
+ {Compiler}:MacOS Support:Headers:
+ {Compiler}:MacOS Support:MacHeaders:
+o C/C++ language:
+ - inlining: normal
+ - direct to SOM: off
+ - enable/check: exceptions, RTTI, bool (and if you like pool strings)
+
+PowerPC target settings
+-----------------------
+o Target Settings:
+ - name of target
+ - MacOS PPC Linker
+o PPC Target
+ - name of library
+o C/C++ language
+ - prefix file as described below
+o PPC Processor
+ - Struct Alignment: PowerPC
+ - uncheck "Store Static Data in TOC" -- important!
+ I don't think the others matter, I use full optimization and its ok
+o PPC Linker
+ - Factory Settings (SYM file with full paths, faster linking, dead-strip
+ static init, Main: __start)
+
+
+68K target settings
+-------------------
+o Target Settings:
+ - name of target
+ - MacOS 68K Linker
+o 68K Target
+ - name of library
+ - A5 relative data
+o C/C++ language
+ - prefix file as described below
+o 68K Processor
+ - Code model: smart
+ - Struct alignment: 68K
+ - FP: SANE
+ - enable 4-Byte Ints -- important!
+ I don't think the others matter. I selected...
+ - enable: 68020
+ - enable: global register allocation
+o IR Optimizer
+ - enable: Optimize Space, Optimize Speed
+ I suppose the others would work too, but haven't tried...
+o 68K Linker
+ - Factory Settings (New Style MacsBug,SYM file with full paths,
+ A6 Frames, fast link, Merge compiler glue into segment 1,
+ dead-strip static init)
+
+Prefix Files to configure the GC sources
+----------------------------------------
+The Codewarrior equivalent of commandline compilers -DNAME=X is to use
+prefix-files. A TEXT file that is automatically #included before the first byte
+of every source file. I used these:
+
+---- ( cut here ) ---- gc_prefix_tempmem.h -- 68K and PPC -----
+ #include "gc_prefix_common.h"
+ #undef USE_TEMPORARY_MEMORY
+ #define USE_TEMPORARY_MEMORY
+---- ( cut here ) ---- gc_prefix_appmem.h -- 68K and PPC -----
+ #include "gc_prefix_common.h"
+ #undef USE_TEMPORARY_MEMORY
+// #define USE_TEMPORARY_MEMORY
+
+---- ( cut here ) ---- gc_prefix_common.h --------------------
+// gc_prefix_common.h
+// ------------------
+// Codewarrior prefix file to configure the GC libraries
+//
+// prefix files are the Codewarrior equivalent of the
+// command line option -Dname=x frequently seen in makefiles
+
+#if !__MWERKS__
+ #error only tried this with Codewarrior
+#endif
+
+#if macintosh
+ #define MSL_USE_PRECOMPILED_HEADERS 0
+ #include <ansi_prefix.mac.h>
+ #ifndef __STDC__
+ #define __STDC__ 0
+ #endif
+
+ // See list of #defines to configure the library in: 'MakeFile'
+ // see also README
+
+ #define SILENT // no collection messages. In case
+ // of trouble you might want this off
+ #define ALL_INTERIOR_POINTERS // follows interior pointers.
+//#define DONT_ADD_BYTE_AT_END // disables the padding if defined.
+//#define SMALL_CONFIG // whether to use a smaller heap.
+ #define NO_SIGNALS // signals aren't real on the Macintosh.
+ #define ATOMIC_UNCOLLECTABLE // GC_malloc_atomic_uncollectable()
+
+ // define either or none as per personal preference
+ // used in malloc.c
+ #define REDIRECT_MALLOC GC_malloc
+//#define REDIRECT_MALLOC GC_malloc_uncollectable
+ // if REDIRECT_MALLOC is #defined make sure that the GC library
+ // is listed before the ANSI/ISO libs in the Codewarrior
+ // 'Link order' panel
+//#define IGNORE_FREE
+
+ // mac specific configs
+//#define USE_TEMPORARY_MEMORY // use Macintosh temporary memory.
+//#define SHARED_LIBRARY_BUILD // build for use in a shared library.
+
+#else
+ // could build Win32 here too, or in the future
+ // Rhapsody PPC-mach, Rhapsody PPC-MacOS,
+ // Rhapsody Intel-mach, Rhapsody Intel-Win32,...
+ // ... ugh this will get messy ...
+#endif
+
+// make sure ints are at least 32-bit
+// ( could be set to 16-bit by compiler settings (68K) )
+
+struct gc_private_assert_intsize_{ char x[ sizeof(int)>=4 ? 1 : 0 ]; };
+
+#if __powerc
+ #if __option(toc_data)
+ #error turn off "store static data in TOC" when using GC
+ // ... or find a way to add TOC to the root set...(?)
+ #endif
+#endif
+---- ( cut here ) ---- end of gc_prefix_common.h -----------------
+
+Files to build the GC libraries:
+--------------------------------
+ allchblk.c
+ alloc.c
+ blacklst.c
+ checksums.c
+ dbg_mlc.c
+ finalize.c
+ headers.c
+ mach_dep.c
+ MacOS.c -- contains MacOS code
+ malloc.c
+ mallocx.c
+ mark.c
+ mark_rts.c
+ misc.c
+ new_hblk.c
+ obj_map.c
+ os_dep.c -- contains MacOS code
+ ptr_chck.c
+ reclaim.c
+ stubborn.c
+ typd_mlc.c
+ gc++.cc -- this is 'gc_cpp.cc' with less 'inline' and
+ -- throw std::bad_alloc when out of memory
+ -- gc_cpp.cc works just fine too
+
+2) Test that the library works with 'test.c'.
+=============================================
+
+The test app is just an ordinary ANSI-C console app. Make sure settings
+match the library you're testing.
+
+Files
+-----
+ test.c
+ the GC library to test -- link order before ANSI libs
+ suitable Mac+ANSI libraries
+
+prefix:
+------
+---- ( cut here ) ---- gc_prefix_testlib.h -- all libs -----
+#define MSL_USE_PRECOMPILED_HEADERS 0
+#include <ansi_prefix.mac.h>
+#undef NDEBUG
+
+#define ALL_INTERIOR_POINTERS /* for GC_priv.h */
+---- ( cut here ) ----
+
+3) Test that the C++ interface 'gc_cpp.cc/h' works with 'test_cpp.cc'.
+
+The test app is just an ordinary ANSI-C console app. Make sure settings match
+the library you're testing.
+
+Files
+-----
+ test_cpp.cc
+ the GC library to test -- link order before ANSI libs
+ suitable Mac+ANSI libraries
+
+prefix:
+------
+same as for test.c
+
+For convenience I used one test-project with several targets so that all
+test apps are build at once. Two for each library to test: test.c and
+gc_app.cc. When I was satisfied that the libraries were ok. I put the
+libraries + gc.h + the c++ interface-file in a folder that I then put into
+the MSL hierarchy so that I don't have to alter access-paths in projects
+that use the GC.
+
+After that, just add the proper GC library to your project and the GC is in
+action! malloc will call GC_malloc and free GC_free, new/delete too. You
+don't have to call free or delete. You may have to be a bit cautious about
+delete if you're freeing other resources than RAM. See gc_cpp.h. You can
+also keep coding as always with delete/free. That works too. If you want,
+"include <gc.h> and tweak it's use a bit.
+
+Symantec SPM
+============
+It has been a while since I tried the GC in SPM, but I think that the above
+instructions should be sufficient to guide you through in SPM too. SPM
+needs to know where the global data is. Use the files 'datastart.c' and
+'dataend.c'. Put 'datastart.c' at the top of your project and 'dataend.c'
+at the bottom of your project so that all data is surrounded. This is not
+needed in Codewarrior because it provides intrinsic variables
+__datastart__, __data_end__ that wraps all globals.
+
+Source Changes (GC 4.12a2)
+==========================
+Very few. Just one tiny in the GC, not strictly needed.
+- MacOS.c line 131 in routine GC_MacFreeTemporaryMemory()
+ change # if !defined(SHARED_LIBRARY_BUILD)
+ to # if !defined(SILENT) && !defined(SHARED_LIBRARY_BUILD)
+ To turn off a message when the application quits (actually, I faked
+ this change by #defining SHARED_LIBRARY_BUILD in a statically linked
+ library for more than a year without ill effects but perhaps this is
+ better).
+
+- test_cpp.cc
+ made the first lines of main() look like this:
+ ------------
+ int main( int argc, char* argv[] ) {
+ #endif
+ #if macintosh // MacOS
+ char* argv_[] = {"test_cpp","10"}; // doesn't
+ argv=argv_; // have a
+ argc = sizeof(argv_)/sizeof(argv_[0]); // commandline
+ #endif //
+
+ int i, iters, n;
+ # ifndef __GNUC__
+ alloc dummy_to_fool_the_compiler_into_doing_things_it_currently_cant_handle;
+ ------------
+
+- config.h [now gcconfig.h]
+ __MWERKS__ does not have to mean MACOS. You can use Codewarrior to
+ build a Win32 or BeOS library and soon a Rhapsody library. You may
+ have to change that #if...
+
+
+
+ It worked for me, hope it works for you.
+
+ Lars Farm
+ 18 July 1997
+----------------------------------------------------------------------------
+
+
+Patrick Beard's instructions (may be dated):
+
+v4.3 of the collector now runs under Symantec C++/THINK C v7.0.4, and
+Metrowerks C/C++ v4.5 both 68K and PowerPC. Project files are provided
+to build and test the collector under both development systems.
+
+Configuration
+-------------
+
+To configure the collector, under both development systems, a prefix file
+is used to set preprocessor directives. This file is called "MacOS_config.h".
+Also to test the collector, "MacOS_Test_config.h" is provided.
+
+Testing
+-------
+
+To test the collector (always a good idea), build one of the gctest projects,
+gctest.¹ (Symantec C++/THINK C), mw/gctest.68K.¹, or mw/gctest.PPC.¹. The
+test will ask you how many times to run; 1 should be sufficient.
+
+Building
+--------
+
+For your convenience project files for the major Macintosh development
+systems are provided.
+
+For Symantec C++/THINK C, you must build the two projects gclib-1.¹ and
+gclib-2.¹. It has to be split up because the collector has more than 32k
+of static data and no library can have more than this in the Symantec
+environment. (Future versions will probably fix this.)
+
+For Metrowerks C/C++ 4.5 you build gc.68K.¹/gc.PPC.¹ and the result will
+be a library called gc.68K.lib/gc.PPC.lib.
+
+Using
+-----
+
+Under Symantec C++/THINK C, you can just add the gclib-1.¹ and gclib-2.¹
+projects to your own project. Under Metrowerks, you add gc.68K.lib or
+gc.PPC.lib and two additional files. You add the files called datastart.c
+and dataend.c to your project, bracketing all files that use the collector.
+See mw/gctest.¹ for an example.
+
+Include the projects/libraries you built above into your own project,
+#include "gc.h", and call GC_malloc. You don't have to call GC_free.
+
+
+Patrick C. Beard
+January 4, 1995
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.MacOSX b/tools/build/v2/engine/boehm_gc/doc/README.MacOSX
new file mode 100644
index 0000000000..f5333d51ad
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.MacOSX
@@ -0,0 +1 @@
+See README.darwin for the latest Darwin/MacOSX information.
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.OS2 b/tools/build/v2/engine/boehm_gc/doc/README.OS2
new file mode 100644
index 0000000000..5345bbd0f6
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.OS2
@@ -0,0 +1,6 @@
+The code assumes static linking, and a single thread. The editor de has
+not been ported. The cord test program has. The supplied OS2_MAKEFILE
+assumes the IBM C Set/2 environment, but the code shouldn't.
+
+Since we haven't figured out hoe to do perform partial links or to build static
+libraries, clients currently need to link against a long list of executables.
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.amiga b/tools/build/v2/engine/boehm_gc/doc/README.amiga
new file mode 100644
index 0000000000..730dce3fe9
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.amiga
@@ -0,0 +1,322 @@
+===========================================================================
+ Kjetil S. Matheussen's notes (28-11-2000)
+===========================================================================
+Compiles under SAS/C again. Should allso still compile under other
+amiga compilers without big changes. I haven't checked if it still
+works under gcc, because I don't have gcc for amiga. But I have
+updated 'Makefile', and hope it compiles fine.
+
+
+WHATS NEW:
+
+1.
+ Made a pretty big effort in preventing GCs allocating-functions from returning
+ chip-mem.
+
+ The lower part of the new file AmigaOS.c does this in various ways, mainly by
+ wrapping GC_malloc, GC_malloc_atomic, GC_malloc_uncollectable,
+ GC_malloc_atomic_uncollectable, GC_malloc_stubborn, GC_malloc_ignore_off_page
+ and GC_malloc_atomic_ignore_off_page. GC_realloc is allso wrapped, but
+ doesn't do the same effort in preventing to return chip-mem.
+ Other allocating-functions (f.ex. GC_*_typed_) can probably be
+ used without any problems, but beware that the warn hook will not be called.
+ In case of problems, don't define GC_AMIGA_FASTALLOC.
+
+ Programs using more time actually using the memory allocated
+ (instead of just allocate and free rapidly) have
+ the most to earn on this, but even gctest now normally runs twice
+ as fast and uses less memory, on my poor 8MB machine.
+
+ The changes have only effect when there is no more
+ fast-mem left. But with the way GC works, it
+ could happen quite often. Beware that an atexit handler had to be added,
+ so using the abort() function will make a big memory-loss.
+ If you absolutely must call abort() instead of exit(), try calling
+ the GC_amiga_free_all_mem function before abort().
+
+ New amiga-spesific compilation flags:
+
+ GC_AMIGA_FASTALLOC - By NOT defining this option, GC will work like before,
+ it will not try to force fast-mem out of the OS, and
+ it will use normal calloc for allocation, and the rest
+ of the following flags will have no effect.
+
+ GC_AMIGA_ONLYFAST - Makes GC never to return chip-mem. GC_AMIGA_RETRY have
+ no effect if this flag is set.
+
+ GC_AMIGA_GC - If gc returns NULL, do a GC_gcollect, and try again. This
+ usually is a success with the standard GC configuration.
+ It is allso the most important flag to set to prevent
+ GC from returning chip-mem. Beware that it slows down a lot
+ when a program is rapidly allocating/deallocating when
+ theres either very little fast-memory left or verly little
+ chip-memory left. Its not a very common situation, but gctest
+ sometimes (very rare) use many minutes because of this.
+
+ GC_AMIGA_RETRY - If gc succeed allocating memory, but it is chip-mem,
+ try again and see if it is fast-mem. Most of the time,
+ it will actually return fast-mem for the second try.
+ I have set max number of retries to 9 or size/5000. You
+ can change this if you like. (see GC_amiga_rec_alloc())
+
+ GC_AMIGA_PRINTSTATS - Gather some statistics during the execution of a
+ program, and prints out the info when the atexit-handler
+ is called.
+
+ My reccomendation is to set all this flags, except GC_AMIGA_PRINTSTATS and
+ GC_AMIGA_ONLYFAST.
+
+ If your program demands high response-time, you should
+ not define GC_AMIGA_GC, and possible allso define GC_AMIGA_ONLYFAST.
+ GC_AMIGA_RETRY does not seem to slow down much.
+
+ Allso, when compiling up programs, and GC_AMIGA_FASTALLOC was not defined when
+ compilling gc, you can define GC_AMIGA_MAKINGLIB to avoid having these allocation-
+ functions wrapped. (see gc.h)
+
+ Note that GC_realloc must not be called before any of
+ the other above mentioned allocating-functions have been called. (shouldn't be
+ any programs doing so either, I hope).
+
+ Another note. The allocation-function is wrapped when defining
+ GC_AMIGA_FASTALLOC by letting the function go thru the new
+ GC_amiga_allocwrapper_do function-pointer (see gc.h). Means that
+ sending function-pointers, such as GC_malloc, GC_malloc_atomic, etc.,
+ for later to be called like f.ex this, (*GC_malloc_functionpointer)(size),
+ will not wrap the function. This is normally not a big problem, unless
+ all allocation function is called like this, which will cause the
+ atexit un-allocating function never to be called. Then you either
+ have to manually add the atexit handler, or call the allocation-
+ functions function-pointer functions like this;
+ (*GC_amiga_allocwrapper_do)(size,GC_malloc_functionpointer).
+ There are probably better ways this problem could be handled, unfortunately,
+ I didn't find any without rewriting or replacing a lot of the GC-code, which
+ I really didn't want to. (Making new GC_malloc_* functions, and just
+ define f.ex GC_malloc as GC_amiga_malloc should allso work).
+
+
+ New amiga-spesific function:
+
+ void GC_amiga_set_toany(void (*func)(void));
+
+ 'func' is a function that will be called right before gc has to change
+ allocation-method from MEMF_FAST to MEMF_ANY. Ie. when it is likely
+ it will return chip-mem.
+
+
+2. A few small compiler-spesific additions to make it compile with SAS/C again.
+
+3. Updated and rewritten the smakefile, so that it works again and that
+ the "unnecesarry" 'SCOPTIONS' files could be removed. Allso included
+ the cord-smakefile stuff in the main smakefile, so that the cord smakefile
+ could be removed too. By writing smake -f Smakefile.smk, both gc.lib and
+ cord.lib will be made.
+
+
+
+STILL MISSING:
+
+Programs can not be started from workbench, at least not for SAS/C. (Martin
+Tauchmanns note about that it now works with workbench is definitely wrong
+when concerning SAS/C). I guess it works if you use the old "#if 0'ed"-code,
+but I haven't tested it. I think the reason for MT to replace the
+"#if 0'ed"-code was only because it was a bit to SAS/C-spesific. But I
+don't know. An iconx-script solves this problem anyway.
+
+
+BEWARE!
+
+-To run gctest, set the stack to around 200000 bytes first.
+-SAS/C-spesific: cord will crash if you compile gc.lib with
+ either parm=reg or parm=both. (missing legal prototypes for
+ function-pointers someplace is the reason I guess.).
+
+
+tested with software: Radium, http://www.stud.ifi.uio.no/~ksvalast/radium/
+
+tested with hardware: MC68060
+
+
+-ksvalast@ifi.uio.no
+
+
+===========================================================================
+ Martin Tauchmann's notes (1-Apr-99)
+===========================================================================
+
+Works now, also with the GNU-C compiler V2.7.2.1. <ftp://ftp.unina.it/pub/amiga/geekgadgets/amiga/m68k/snapshots/971125/amiga-bin/>
+Modify the `Makefile`
+CC=cc $(ABI_FLAG)
+to
+CC=gcc $(ABI_FLAG)
+
+TECHNICAL NOTES
+
+- `GC_get_stack_base()`, `GC_register_data_segments()` works now with every
+ C compiler; also Workbench.
+
+- Removed AMIGA_SKIP_SEG, but the Code-Segment must not be scanned by GC.
+
+
+PROBLEMS
+- When the Linker, does`t merge all Code-Segments to an single one. LD of GCC
+ do it always.
+
+- With ixemul.library V47.3, when an GC program launched from another program
+ (example: `Make` or `if_mach M68K AMIGA gctest`), `GC_register_data_segments()`
+ found the Segment-List of the caller program.
+ Can be fixed, if the run-time initialization code (for C programs, usually *crt0*)
+ support `__data` and `__bss`.
+
+- PowerPC Amiga currently not supported.
+
+- Dynamic libraries (dyn_load.c) not supported.
+
+
+TESTED WITH SOFTWARE
+
+`Optimized Oberon 2 C` (oo2c) <http://cognac.informatik.uni-kl.de/download/index.html>
+
+
+TESTED WITH HARDWARE
+
+MC68030
+
+
+CONTACT
+
+Please, contact me at <martintauchmann@bigfoot.com>, when you change the
+Amiga port. <http://martintauchmann.home.pages.de>
+
+===========================================================================
+ Michel Schinz's notes
+===========================================================================
+WHO DID WHAT
+
+The original Amiga port was made by Jesper Peterson. I (Michel Schinz)
+modified it slightly to reflect the changes made in the new official
+distributions, and to take advantage of the new SAS/C 6.x features. I also
+created a makefile to compile the "cord" package (see the cord
+subdirectory).
+
+TECHNICAL NOTES
+
+In addition to Jesper's notes, I have the following to say:
+
+- Starting with version 4.3, gctest checks to see if the code segment is
+ added to the root set or not, and complains if it is. Previous versions
+ of this Amiga port added the code segment to the root set, so I tried to
+ fix that. The only problem is that, as far as I know, it is impossible to
+ know which segments are code segments and which are data segments (there
+ are indeed solutions to this problem, like scanning the program on disk
+ or patch the LoadSeg functions, but they are rather complicated). The
+ solution I have chosen (see os_dep.c) is to test whether the program
+ counter is in the segment we are about to add to the root set, and if it
+ is, to skip the segment. The problems are that this solution is rather
+ awkward and that it works only for one code segment. This means that if
+ your program has more than one code segment, all of them but one will be
+ added to the root set. This isn't a big problem in fact, since the
+ collector will continue to work correctly, but it may be slower.
+
+ Anyway, the code which decides whether to skip a segment or not can be
+ removed simply by not defining AMIGA_SKIP_SEG. But notice that if you do
+ so, gctest will complain (it will say that "GC_is_visible produced wrong
+ failure indication"). However, it may be useful if you happen to have
+ pointers stored in a code segment (you really shouldn't).
+
+ If anyone has a good solution to the problem of finding, when a program
+ is loaded in memory, whether a segment is a code or a data segment,
+ please let me know.
+
+PROBLEMS
+
+If you have any problem with this version, please contact me at
+schinz@alphanet.ch (but do *not* send long files, since we pay for
+every mail!).
+
+===========================================================================
+ Jesper Peterson's notes
+===========================================================================
+
+ADDITIONAL NOTES FOR AMIGA PORT
+
+These notes assume some familiarity with Amiga internals.
+
+WHY I PORTED TO THE AMIGA
+
+The sole reason why I made this port was as a first step in getting
+the Sather(*) language on the Amiga. A port of this language will
+be done as soon as the Sather 1.0 sources are made available to me.
+Given this motivation, the garbage collection (GC) port is rather
+minimal.
+
+(*) For information on Sather read the comp.lang.sather newsgroup.
+
+LIMITATIONS
+
+This port assumes that the startup code linked with target programs
+is that supplied with SAS/C versions 6.0 or later. This allows
+assumptions to be made about where to find the stack base pointer
+and data segments when programs are run from WorkBench, as opposed
+to running from the CLI. The compiler dependent code is all in the
+GC_get_stack_base() and GC_register_data_segments() functions, but
+may spread as I add Amiga specific features.
+
+Given that SAS/C was assumed, the port is set up to be built with
+"smake" using the "SMakefile". Compiler options in "SCoptions" can
+be set with "scopts" program. Both "smake" and "scopts" are part of
+the SAS/C commercial development system.
+
+In keeping with the porting philosophy outlined above, this port
+will not behave well with Amiga specific code. Especially not inter-
+process comms via messages, and setting up public structures like
+Intuition objects or anything else in the system lists. For the
+time being the use of this library is limited to single threaded
+ANSI/POSIX compliant or near-complient code. (ie. Stick to stdio
+for now). Given this limitation there is currently no mechanism for
+allocating "CHIP" or "PUBLIC" memory under the garbage collector.
+I'll add this after giving it considerable thought. The major
+problem is the entire physical address space may have to me scanned,
+since there is no telling who we may have passed memory to.
+
+If you allocate your own stack in client code, you will have to
+assign the pointer plus stack size to GC_stackbottom.
+
+The initial stack size of the target program can be compiled in by
+setting the __stack symbol (see SAS documentaion). It can be over-
+ridden from the CLI by running the AmigaDOS "stack" program, or from
+the WorkBench by setting the stack size in the tool types window.
+
+SAS/C COMPILER OPTIONS (SCoptions)
+
+You may wish to check the "CPU" code option is appropriate for your
+intended target system.
+
+Under no circumstances set the "StackExtend" code option in either
+compiling the library or *ANY* client code.
+
+All benign compiler warnings have been suppressed. These mainly
+involve lack of prototypes in the code, and dead assignments
+detected by the optimizer.
+
+THE GOOD NEWS
+
+The library as it stands is compatible with the GigaMem commercial
+virtual memory software, and probably similar PD software.
+
+The performance of "gctest" on an Amiga 2630 (68030 @ 25Mhz)
+compares favourably with an HP9000 with similar architecture (a 325
+with a 68030 I think).
+
+-----------------------------------------------------------------------
+
+The Amiga port has been brought to you by:
+
+Jesper Peterson.
+
+jep@mtiame.mtia.oz.au (preferred, but 1 week turnaround)
+jep@orca1.vic.design.telecom.au (that's orca<one>, 1 day turnaround)
+
+At least one of these addresses should be around for a while, even
+though I don't work for either of the companies involved.
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.arm.cross b/tools/build/v2/engine/boehm_gc/doc/README.arm.cross
new file mode 100644
index 0000000000..96744edaf6
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.arm.cross
@@ -0,0 +1,68 @@
+From: Margaret Fleck
+
+Here's the key details of what worked for me, in case anyone else needs them.
+There may well be better ways to do some of this, but ....
+ -- Margaret
+
+
+The badge4 has a StrongArm-1110 processor and a StrongArm-1111 coprocessor.
+
+Assume that the garbage collector distribution is unpacked into /home/arm/gc6.0,
+which is visible to both the ARM machine and a linux desktop (e.g. via NFS mounting).
+
+Assume that you have a file /home/arm/config.site with contents something like the
+example attached below. Notice that our local ARM toolchain lives in
+/skiff/local.
+
+Go to /home/arm/gc6.0 directory. Do
+ CONFIG_SITE=/home/arm/config.site ./configure --target=arm-linux
+--prefix=/home/arm/gc6.0
+
+On your desktop, do:
+ make
+ make install
+The main garbage collector library should now be in ../gc6.0/lib/libgc.so.
+
+To test the garbage collector, first do the following on your desktop
+ make gctest
+ ./gctest
+Then do the following on the ARM machine
+ cd .libs
+ ./lt-gctest
+
+Do not try to do "make test" (the usual way of running the test
+program). This does not work and seems to erase some of the important
+files.
+
+The gctest program claims to have succeeded. Haven't run any further tests
+with it, though I'll be doing so in the near future.
+
+-------------------------------
+# config.site for configure
+
+# Modified from the one provided by Bradley D. LaRonde
+# Edited by Andrej Cedilnik <acedil1@csee.umbc.edu>
+# Used some of solutions by Tilman Vogel <Tilman.Vogel@web.de>
+# Ported for iPAQ Familiar by Oliver Kurth <oliver.kurth@innominate.com>
+# Further modified by Margaret Fleck for the badge4
+
+HOSTCC=gcc
+
+# Names of the cross-compilers
+CC=/skiff/local/bin/arm-linux-gcc
+CXX=/skiff/local/bin/arm-linux-gcc
+
+# The cross compiler specific options
+CFLAGS="-O2 -fno-exceptions"
+CXXFLAGS="-O2 -fno-exceptions"
+CPPFLAGS="-O2 -fno-exceptions"
+LDFLAGS=""
+
+# Some other programs
+AR=/skiff/local/bin/arm-linux-ar
+RANLIB=/skiff/local/bin/arm-linux-ranlib
+NM=/skiff/local/bin/arm-linux-nm
+ac_cv_path_NM=/skiff/local/bin/arm-linux-nm
+ac_cv_func_setpgrp_void=yes
+x_includes=/skiff/local/arm-linux/include/X11
+x_libraries=/skiff/local/arm-linux/lib/X11
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.autoconf b/tools/build/v2/engine/boehm_gc/doc/README.autoconf
new file mode 100644
index 0000000000..53fcf5a50b
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.autoconf
@@ -0,0 +1,59 @@
+As of GC6.0alpha8, we attempt to support GNU-style builds based on automake,
+autoconf and libtool. This is based almost entirely on Tom Tromey's work
+with gcj.
+
+To build and install libraries use
+
+configure; make; make install
+
+The advantages of this process are:
+
+1) It should eventually do a better job of automatically determining the
+right compiler to use, etc. It probably already does in some cases.
+
+2) It tries to automatically set a good set of default GC parameters for
+the platform (e.g. thread support). It provides an easier way to configure
+some of the others.
+
+3) It integrates better with other projects using a GNU-style build process.
+
+4) It builds both dynamic and static libraries.
+
+The known disadvantages are:
+
+1) The build scripts are much more complex and harder to debug (though largely
+standard). I don't understand them all, and there's probably lots of redundant
+stuff.
+
+2) It probably doesn't work on all Un*x-like platforms yet. It probably will
+never work on the rest.
+
+3) The scripts are not yet complete. Some of the standard GNU targets don't
+yet work. (Corrections/additions are very welcome.)
+
+The distribution should contain all files needed to run "configure" and "make",
+as well as the sources needed to regenerate the derived files. (If I missed
+some, please let me know.)
+
+Note that the distribution comes with a "Makefile" which will be overwritten
+by "configure" with one that is not at all equiavelent to the original. The
+distribution contains a copy of the original "Makefile" in "Makefile.direct".
+
+Important options to configure:
+
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [/usr/local]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --enable-threads=TYPE choose threading package
+ --enable-parallel-mark parallelize marking and free list construction
+ --enable-full-debug include full support for pointer backtracing etc.
+
+Unless --prefix is set (or --exec-prefix or one of the more obscure options),
+make install will install libgc.a and libgc.so in /usr/local/bin, which
+would typically require the "make install" to be run as root.
+
+Most commonly --enable-threads=posix or will be needed. --enable-parallel-mark
+is recommended for multiprocessors if it is supported on the platform.
+
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.changes b/tools/build/v2/engine/boehm_gc/doc/README.changes
new file mode 100644
index 0000000000..27bf33eaaa
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.changes
@@ -0,0 +1,2594 @@
+This is a rough history of garbage collector bugs and versions.
+
+This has been maintained with varying diligence over the years.
+
+I made an attempt to include recent contributors here. I apologize for any
+omissions.
+
+RECENT UPDATES ARE RECORDED IN ../ChangeLog FILE INSTEAD TO CONFORM TO
+MORE COMMON CONVENTIONS.
+
+-------------------------
+
+ Version 1.3 and immediately preceding versions contained spurious
+assembly language assignments to TMP_SP. Only the assignment in the PC/RT
+code is necessary. On other machines, with certain compiler options,
+the assignments can lead to an unsaved register being overwritten.
+Known to cause problems under SunOS 3.5 WITHOUT the -O option. (With
+-O the compiler recognizes it as dead code. It probably shouldn't,
+but that's another story.)
+
+ Version 1.4 and earlier versions used compile time determined values
+for the stack base. This no longer works on Sun 3s, since Sun 3/80s use
+a different stack base. We now use a straightforward heuristic on all
+machines on which it is known to work (incl. Sun 3s) and compile-time
+determined values for the rest. There should really be library calls
+to determine such values.
+
+ Version 1.5 and earlier did not ensure 8 byte alignment for objects
+allocated on a sparc based machine.
+
+ Version 1.8 added ULTRIX support in gc_private.h.
+
+ Version 1.9 fixed a major bug in gc_realloc.
+
+ Version 2.0 introduced a consistent naming convention for collector
+routines and added support for registering dynamic library data segments
+in the standard mark_roots.c. Most of the data structures were revamped.
+The treatment of interior pointers was completely changed. Finalization
+was added. Support for locking was added. Object kinds were added.
+We added a black listing facility to avoid allocating at addresses known
+to occur as integers somewhere in the address space. Much of this
+was accomplished by adapting ideas and code from the PCR collector.
+The test program was changed and expanded.
+
+ Version 2.1 was the first stable version since 1.9, and added support
+for PPCR.
+
+ Version 2.2 added debugging allocation, and fixed various bugs. Among them:
+- GC_realloc could fail to extend the size of the object for certain large object sizes.
+- A blatant subscript range error in GC_printf, which unfortunately
+ wasn't exercised on machines with sufficient stack alignment constraints.
+- GC_register_displacement did the wrong thing if it was called after
+ any allocation had taken place.
+- The leak finding code would eventually break after 2048 byte
+ byte objects leaked.
+- interface.c didn't compile.
+- The heap size remained much too small for large stacks.
+- The stack clearing code behaved badly for large stacks, and perhaps
+ on HP/PA machines.
+
+ Version 2.3 added ALL_INTERIOR_POINTERS and fixed the following bugs:
+- Missing declaration of etext in the A/UX version.
+- Some PCR root-finding problems.
+- Blacklisting was not 100% effective, because the plausible future
+ heap bounds were being miscalculated.
+- GC_realloc didn't handle out-of-memory correctly.
+- GC_base could return a nonzero value for addresses inside free blocks.
+- test.c wasn't really thread safe, and could erroneously report failure
+ in a multithreaded environment. (The locking primitives need to be
+ replaced for other threads packages.)
+- GC_CONS was thoroughly broken.
+- On a SPARC with dynamic linking, signals stayed diabled while the
+ client code was running.
+ (Thanks to Manuel Serrano at INRIA for reporting the last two.)
+
+ Version 2.4 added GC_free_space_divisor as a tuning knob, added
+ support for OS/2 and linux, and fixed the following bugs:
+- On machines with unaligned pointers (e.g. Sun 3), every 128th word could
+ fail to be considered for marking.
+- Dynamic_load.c erroneously added 4 bytes to the length of the data and
+ bss sections of the dynamic library. This could result in a bad memory
+ reference if the actual length was a multiple of a page. (Observed on
+ Sun 3. Can probably also happen on a Sun 4.)
+ (Thanks to Robert Brazile for pointing out that the Sun 3 version
+ was broken. Dynamic library handling is still broken on Sun 3s
+ under 4.1.1U1, but apparently not 4.1.1. If you have such a machine,
+ use -Bstatic.)
+
+ Version 2.5 fixed the following bugs:
+- Removed an explicit call to exit(1)
+- Fixed calls to GC_printf and GC_err_printf, so the correct number of
+ arguments are always supplied. The OS/2 C compiler gets confused if
+ the number of actuals and the number of formals differ. (ANSI C
+ doesn't require this to work. The ANSI sanctioned way of doing things
+ causes too many compatibility problems.)
+
+ Version 3.0 added generational/incremental collection and stubborn
+ objects.
+
+ Version 3.1 added the following features:
+- A workaround for a SunOS 4.X SPARC C compiler
+ misfeature that caused problems when the collector was turned into
+ a dynamic library.
+- A fix for a bug in GC_base that could result in a memory fault.
+- A fix for a performance bug (and several other misfeatures) pointed
+ out by Dave Detlefs and Al Dosser.
+- Use of dirty bit information for static data under Solaris 2.X.
+- DEC Alpha/OSF1 support (thanks to Al Dosser).
+- Incremental collection on more platforms.
+- A more refined heap expansion policy. Less space usage by default.
+- Various minor enhancements to reduce space usage, and to reduce
+ the amount of memory scanned by the collector.
+- Uncollectable allocation without per object overhead.
+- More conscientious handling of out-of-memory conditions.
+- Fixed a bug in debugging stubborn allocation.
+- Fixed a bug that resulted in occasional erroneous reporting of smashed
+ objects with debugging allocation.
+- Fixed bogus leak reports of size 4096 blocks with FIND_LEAK.
+
+ Version 3.2 fixed a serious and not entirely repeatable bug in
+ the incremental collector. It appeared only when dirty bit info
+ on the roots was available, which is normally only under Solaris.
+ It also added GC_general_register_disappearing_link, and some
+ testing code. Interface.c disappeared.
+
+ Version 3.3 fixes several bugs and adds new ports:
+- PCR-specific bugs.
+- Missing locking in GC_free, redundant FASTUNLOCK
+ in GC_malloc_stubborn, and 2 bugs in
+ GC_unregister_disappearing_link.
+ All of the above were pointed out by Neil Sharman
+ (neil@cs.mu.oz.au).
+- Common symbols allocated by the SunOS4.X dynamic loader
+ were not included in the root set.
+- Bug in GC_finalize (reported by Brian Beuning and Al Dosser)
+- Merged Amiga port from Jesper Peterson (untested)
+- Merged NeXT port from Thomas Funke (significantly
+ modified and untested)
+
+ Version 3.4:
+- Fixed a performance bug in GC_realloc.
+- Updated the amiga port.
+- Added NetBSD and 386BSD ports.
+- Added cord library.
+- Added trivial performance enhancement for
+ ALL_INTERIOR_POINTERS. (Don't scan last word.)
+
+ Version 3.5
+- Minor collections now mark from roots only once, if that
+ doesn't cause an excessive pause.
+- The stack clearing heuristic was refined to prevent anomalies
+ with very heavily recursive programs and sparse stacks.
+- Fixed a bug that prevented mark stack growth in some cases.
+ GC_objects_are_marked should be set to TRUE after a call
+ to GC_push_roots and as part of GC_push_marked, since
+ both can now set mark bits. I think this is only a performance
+ bug, but I wouldn't bet on it. It's certainly very hard to argue
+ that the old version was correct.
+- Fixed an incremental collection bug that prevented it from
+ working at all when HBLKSIZE != getpagesize()
+- Changed dynamic_loading.c to include gc_priv.h before testing
+ DYNAMIC_LOADING. SunOS dynamic library scanning
+ must have been broken in 3.4.
+- Object size rounding now adapts to program behavior.
+- Added a workaround (provided by Manuel Serrano and
+ colleagues) to a long-standing SunOS 4.X (and 3.X?) ld bug
+ that I had incorrectly assumed to have been squished.
+ The collector was broken if the text segment size was within
+ 32 bytes of a multiple of 8K bytes, and if the beginning of
+ the data segment contained interesting roots. The workaround
+ assumes a demand-loadable executable. The original may have
+ have "worked" in some other cases.
+- Added dynamic library support under IRIX5.
+- Added support for EMX under OS/2 (thanks to Ari Huttunen).
+
+Version 3.6:
+- fixed a bug in the mark stack growth code that was introduced
+ in 3.4.
+- fixed Makefile to work around DEC AXP compiler tail recursion
+ bug.
+
+Version 3.7:
+- Added a workaround for an HP/UX compiler bug.
+- Fixed another stack clearing performance bug. Reworked
+ that code once more.
+
+Version 4.0:
+- Added support for Solaris threads (which was possible
+ only by reimplementing some fraction of Solaris threads,
+ since Sun doesn't currently make the thread debugging
+ interface available).
+- Added non-threads win32 and win32S support.
+- (Grudgingly, with suitable muttering of obscenities) renamed
+ files so that the collector distribution could live on a FAT
+ file system. Files that are guaranteed to be useless on
+ a PC still have long names. Gc_inline.h and gc_private.h
+ still exist, but now just include gc_inl.h and gc_priv.h.
+- Fixed a really obscure bug in finalization that could cause
+ undetected mark stack overflows. (I would be surprised if
+ any real code ever tickled this one.)
+- Changed finalization code to dynamically resize the hash
+ tables it maintains. (This probably does not matter for well-
+ -written code. It no doubt does for C++ code that overuses
+ destructors.)
+- Added typed allocation primitives. Rewrote the marker to
+ accommodate them with more reasonable efficiency. This
+ change should also speed up marking for GC_malloc allocated
+ objects a little. See gc_typed.h for new primitives.
+- Improved debugging facilities slightly. Allocation time
+ stack traces are now kept by default on SPARC/SUNOS4.
+ (Thanks to Scott Schwartz.)
+- Added better support for small heap applications.
+- Significantly extended cord package. Fixed a bug in the
+ implementation of lazily read files. Printf and friends now
+ have cord variants. Cord traversals are a bit faster.
+- Made ALL_INTERIOR_POINTERS recognition the default.
+- Fixed de so that it can run in constant space, independent
+ of file size. Added simple string searching to cords and de.
+- Added the Hull-Ellis C++ interface.
+- Added dynamic library support for OSF/1.
+ (Thanks to Al Dosser and Tim Bingham at DEC.)
+- Changed argument to GC_expand_hp to be expressed
+ in units of bytes instead of heap blocks. (Necessary
+ since the heap block size now varies depending on
+ configuration. The old version was never very clean.)
+- Added GC_get_heap_size(). The previous "equivalent"
+ was broken.
+- Restructured the Makefile a bit.
+
+Since version 4.0:
+- Changed finalization implementation to guarantee that
+ finalization procedures are called outside of the allocation
+ lock, making direct use of the interface a little less dangerous.
+ MAY BREAK EXISTING CLIENTS that assume finalizers
+ are protected by a lock. Since there seem to be few multithreaded
+ clients that use finalization, this is hopefully not much of
+ a problem.
+- Fixed a gross bug in CORD_prev.
+- Fixed a bug in blacklst.c that could result in unbounded
+ heap growth during startup on machines that do not clear
+ memory obtained from the OS (e.g. win32S).
+- Ported de editor to win32/win32S. (This is now the only
+ version with a mouse-sensitive UI.)
+- Added GC_malloc_ignore_off_page to allocate large arrays
+ in the presence of ALL_INTERIOR_POINTERS.
+- Changed GC_call_with_alloc_lock to not disable signals in
+ the single-threaded case.
+- Reduced retry count in GC_collect_or_expand for garbage
+ collecting when out of memory.
+- Made uncollectable allocations bypass black-listing, as they
+ should.
+- Fixed a bug in typed_test in test.c that could cause (legitimate)
+ GC crashes.
+- Fixed some potential synchronization problems in finalize.c
+- Fixed a real locking problem in typd_mlc.c.
+- Worked around an AIX 3.2 compiler feature that results in
+ out of bounds memory references.
+- Partially worked around an IRIX5.2 beta problem (which may
+ or may not persist to the final release).
+- Fixed a bug in the heap integrity checking code that could
+ result in explicitly deallocated objects being identified as
+ smashed. Fixed a bug in the dbg_mlc stack saving code
+ that caused old argument pointers to be considered live.
+- Fixed a bug in CORD_ncmp (and hence CORD_str).
+- Repaired the OS2 port, which had suffered from bit rot
+ in 4.0. Worked around what appears to be CSet/2 V1.0
+ optimizer bug.
+- Fixed a Makefile bug for target "c++".
+
+Since version 4.1:
+- Multiple bug fixes/workarounds in the Solaris threads version.
+ (It occasionally failed to locate some register contents for
+ marking. It also turns out that thr_suspend and friends are
+ unreliable in Solaris 2.3. Dirty bit reads appear
+ to be unreliable under some weird
+ circumstances. My stack marking code
+ contained a serious performance bug. The new code is
+ extremely defensive, and has not failed in several cpu
+ hours of testing. But no guarantees ...)
+- Added MacOS support (thanks to Patrick Beard.)
+- Fixed several syntactic bugs in gc_c++.h and friends. (These
+ didn't bother g++, but did bother most other compilers.)
+ Fixed gc_c++.h finalization interface. (It didn't.)
+- 64 bit alignment for allocated objects was not guaranteed in a
+ few cases in which it should have been.
+- Added GC_malloc_atomic_ignore_off_page.
+- Added GC_collect_a_little.
+- Added some prototypes to gc.h.
+- Some other minor bug fixes (notably in Makefile).
+- Fixed OS/2 / EMX port (thanks to Ari Huttunen).
+- Fixed AmigaDOS port. (thanks to Michel Schinz).
+- Fixed the DATASTART definition under Solaris. There
+ was a 1 in 16K chance of the collector missing the first
+ 64K of static data (and thus crashing).
+- Fixed some blatant anachronisms in the README file.
+- Fixed PCR-Makefile for upcoming PPCR release.
+
+Since version 4.2:
+- Fixed SPARC alignment problem with GC_DEBUG.
+- Fixed Solaris threads /proc workaround. The real
+ problem was an interaction with mprotect.
+- Incorporated fix from Patrick Beard for gc_c++.h (now gc_cpp.h).
+- Slightly improved allocator space utilization by
+ fixing the GC_size_map mechanism.
+- Integrated some Sony News and MIPS RISCos 4.51
+ patches. (Thanks to Nobuyuki Hikichi of
+ Software Research Associates, Inc. Japan)
+- Fixed HP_PA alignment problem. (Thanks to
+ xjam@cork.cs.berkeley.edu.)
+- Added GC_same_obj and friends. Changed GC_base
+ to return 0 for pointers past the end of large objects.
+ Improved GC_base performance with ALL_INTERIOR_POINTERS
+ on machines with a slow integer mod operation.
+ Added GC_PTR_ADD, GC_PTR_STORE, etc. to prepare
+ for preprocessor.
+- changed the default on most UNIX machines to be that
+ signals are not disabled during critical GC operations.
+ This is still ANSI-conforming, though somewhat dangerous
+ in the presence of signal handlers. But the performance
+ cost of the alternative is sometimes problematic.
+ Can be changed back with a minor Makefile edit.
+- renamed IS_STRING in gc.h, to CORD_IS_STRING, thus
+ following my own naming convention. Added the function
+ CORD_to_const_char_star.
+- Fixed a gross bug in GC_finalize. Symptom: occasional
+ address faults in that function. (Thanks to Anselm
+ Baird-Smith (Anselm.BairdSmith@inria.fr)
+- Added port to ICL DRS6000 running DRS/NX. Restructured
+ things a bit to factor out common code, and remove obsolete
+ code. Collector should now run under SUNOS5 with either
+ mprotect or /proc dirty bits. (Thanks to Douglas Steel
+ (doug@wg.icl.co.uk)).
+- More bug fixes and workarounds for Solaris 2.X. (These were
+ mostly related to putting the collector in a dynamic library,
+ which didn't really work before. Also SOLARIS_THREADS
+ didn't interact well with dl_open.) Thanks to btlewis@eng.sun.com.
+- Fixed a serious performance bug on the DEC Alpha. The text
+ segment was getting registered as part of the root set.
+ (Amazingly, the result was still fast enough that the bug
+ was not conspicuous.) The fix works on OSF/1, version 1.3.
+ Hopefully it also works on other versions of OSF/1 ...
+- Fixed a bug in GC_clear_roots.
+- Fixed a bug in GC_generic_malloc_words_small that broke
+ gc_inl.h. (Reported by Antoine de Maricourt. I broke it
+ in trying to tweak the Mac port.)
+- Fixed some problems with cord/de under Linux.
+- Fixed some cord problems, notably with CORD_riter4.
+- Added DG/UX port.
+ Thanks to Ben A. Mesander (ben@piglet.cr.usgs.gov)
+- Added finalization registration routines with weaker ordering
+ constraints. (This is necessary for C++ finalization with
+ multiple inheritance, since the compiler often adds self-cycles.)
+- Filled the holes in the SCO port. (Thanks to Michael Arnoldus
+ <chime@proinf.dk>.)
+- John Ellis' additions to the C++ support: From John:
+
+* I completely rewrote the documentation in the interface gc_c++.h
+(later renamed gc_cpp.h). I've tried to make it both clearer and more
+precise.
+
+* The definition of accessibility now ignores pointers from an
+finalizable object (an object with a clean-up function) to itself.
+This allows objects with virtual base classes to be finalizable by the
+collector. Compilers typically implement virtual base classes using
+pointers from an object to itself, which under the old definition of
+accessibility prevented objects with virtual base classes from ever
+being collected or finalized.
+
+* gc_cleanup now includes gc as a virtual base. This was enabled by
+the change in the definition of accessibility.
+
+* I added support for operator new[]. Since most (all?) compilers
+don't yet support operator new[], it is conditionalized on
+-DOPERATOR_NEW_ARRAY. The code is untested, but its trivial and looks
+correct.
+
+* The test program test_gc_c++ (later renamed test_cpp.cc)
+tries to test for the C++-specific functionality not tested by the
+other programs.
+- Added <unistd.h> include to misc.c. (Needed for ppcr.)
+- Added PowerMac port. (Thanks to Patrick Beard again.)
+- Fixed "srcdir"-related Makefile problems. Changed things so
+ that all externally visible include files always appear in the
+ include subdirectory of the source. Made gc.h directly
+ includable from C++ code. (These were at Per
+ Bothner's suggestion.)
+- Changed Intel code to also mark from ebp (Kevin Warne's
+ suggestion).
+- Renamed C++ related files so they could live in a FAT
+ file system. (Charles Fiterman's suggestion.)
+- Changed Windows NT Makefile to include C++ support in
+ gc.lib. Added C++ test as Makefile target.
+
+Since version 4.3:
+ - ASM_CLEAR_CODE was erroneously defined for HP
+ PA machines, resulting in a compile error.
+ - Fixed OS/2 Makefile to create a library. (Thanks to
+ Mark Boulter (mboulter@vnet.ibm.com)).
+ - Gc_cleanup objects didn't work if they were created on
+ the stack. Fixed.
+ - One copy of Gc_cpp.h in the distribution was out of
+ synch, and failed to document some known compiler
+ problems with explicit destructor invocation. Partially
+ fixed. There are probably other compilers on which
+ gc_cleanup is miscompiled.
+ - Fixed Makefile to pass C compiler flags to C++ compiler.
+ - Added Mac fixes.
+ - Fixed os_dep.c to work around what appears to be
+ a new and different VirtualQuery bug under newer
+ versions of win32S.
+ - GC_non_gc_bytes was not correctly maintained by
+ GC_free. Fixed. Thanks to James Clark (jjc@jclark.com).
+ - Added GC_set_max_heap_size.
+ - Changed allocation code to ignore blacklisting if it is preventing
+ use of a very large block of memory. This has the advantage
+ that naive code allocating very large objects is much more
+ likely to work. The downside is you might no
+ longer find out that such code should really use
+ GC_malloc_ignore_off_page.
+ - Changed GC_printf under win32 to close and reopen the file
+ between calls. FAT file systems otherwise make the log file
+ useless for debugging.
+ - Added GC_try_to_collect and GC_get_bytes_since_gc. These
+ allow starting an abortable collection during idle times.
+ This facility does not require special OS support. (Thanks to
+ Michael Spertus of Geodesic Systems for suggesting this. It was
+ actually an easy addition. Kumar Srikantan previously added a similar
+ facility to a now ancient version of the collector. At the time
+ this was much harder, and the result was less convincing.)
+ - Added some support for the Borland development environment. (Thanks
+ to John Ellis and Michael Spertus.)
+ - Removed a misfeature from checksums.c that caused unexpected
+ heap growth. (Thanks to Scott Schwartz.)
+ - Changed finalize.c to call WARN if it encounters a finalization cycle.
+ WARN is defined in gc_priv.h to write a message, usually to stdout.
+ In many environments, this may be inappropriate.
+ - Renamed NO_PARAMS in gc.h to GC_NO_PARAMS, thus adhering to my own
+ naming convention.
+ - Added GC_set_warn_proc to intercept warnings.
+ - Fixed Amiga port. (Thanks to Michel Schinz (schinz@alphanet.ch).)
+ - Fixed a bug in mark.c that could result in an access to unmapped
+ memory from GC_mark_from_mark_stack on machines with unaligned
+ pointers.
+ - Fixed a win32 specific performance bug that could result in scanning of
+ objects allocated with the system malloc.
+ - Added REDIRECT_MALLOC.
+
+Since version 4.4:
+ - Fixed many minor and one major README bugs. (Thanks to Franklin Chen
+ (chen@adi.com) for pointing out many of them.)
+ - Fixed ALPHA/OSF/1 dynamic library support. (Thanks to Jonathan Bachrach
+ (jonathan@harlequin.com)).
+ - Added incremental GC support (MPROTECT_VDB) for Linux (with some
+ help from Bruno Haible).
+ - Altered SPARC recognition tests in gc.h and config.h (mostly as
+ suggested by Fergus Henderson).
+ - Added basic incremental GC support for win32, as implemented by
+ Windows NT and Windows 95. GC_enable_incremental is a noop
+ under win32s, which doesn't implement enough of the VM interface.
+ - Added -DLARGE_CONFIG.
+ - Fixed GC_..._ignore_off_page to also function without
+ -DALL_INTERIOR_POINTERS.
+ - (Hopefully) fixed RS/6000 port. (Only the test was broken.)
+ - Fixed a performance bug in the nonincremental collector running
+ on machines supporting incremental collection with MPROTECT_VDB
+ (e.g. SunOS 4, DEC AXP). This turned into a correctness bug under
+ win32s with win32 incremental collection. (Not all memory protection
+ was disabled.)
+ - Fixed some ppcr related bit rot.
+ - Caused dynamic libraries to be unregistered before reregistering.
+ The old way turned out to be a performance bug on some machines.
+ - GC_root_size was not properly maintained under MSWIN32.
+ - Added -DNO_DEBUGGING and GC_dump.
+ - Fixed a couple of bugs arising with SOLARIS_THREADS +
+ REDIRECT_MALLOC.
+ - Added NetBSD/M68K port. (Thanks to Peter Seebach
+ <seebs@taniemarie.solon.com>.)
+ - Fixed a serious realloc bug. For certain object sizes, the collector
+ wouldn't scan the expanded part of the object. (Thanks to Clay Spence
+ (cds@peanut.sarnoff.com) for noticing the problem, and helping me to
+ track it down.)
+
+Since version 4.5:
+ - Added Linux ELF support. (Thanks to Arrigo Triulzi <arrigo@ic.ac.uk>.)
+ - GC_base crashed if it was called before any other GC_ routines.
+ This could happen if a gc_cleanup object was allocated outside the heap
+ before any heap allocation.
+ - The heap expansion heuristic was not stable if all objects had finalization
+ enabled. Fixed finalize.c to count memory in finalization queue and
+ avoid explicit deallocation. Changed alloc.c to also consider this count.
+ (This is still not recommended. It's expensive if nothing else.) Thanks
+ to John Ellis for pointing this out.
+ - GC_malloc_uncollectable(0) was broken. Thanks to Phong Vo for pointing
+ this out.
+ - The collector didn't compile under Linux 1.3.X. (Thanks to Fred Gilham for
+ pointing this out.) The current workaround is ugly, but expected to be
+ temporary.
+ - Fixed a formatting problem for SPARC stack traces.
+ - Fixed some '=='s in os_dep.c that should have been assignments.
+ Fortunately these were in code that should never be executed anyway.
+ (Thanks to Fergus Henderson.)
+ - Fixed the heap block allocator to only drop blacklisted blocks in small
+ chunks. Made BL_LIMIT self adjusting. (Both of these were in response
+ to heap growth observed by Paul Graham.)
+ - Fixed the Metrowerks/68K Mac code to also mark from a6. (Thanks
+ to Patrick Beard.)
+ - Significantly updated README.debugging.
+ - Fixed some problems with longjmps out of signal handlers, especially under
+ Solaris. Added a workaround for the fact that siglongjmp doesn't appear to
+ do the right thing with -lthread under Solaris.
+ - Added MSDOS/djgpp port. (Thanks to Mitch Harris (maharri@uiuc.edu).)
+ - Added "make reserved_namespace" and "make user_namespace". The
+ first renames ALL "GC_xxx" identifiers as "_GC_xxx". The second is the
+ inverse transformation. Note that doing this is guaranteed to break all
+ clients written for the other names.
+ - descriptor field for kind NORMAL in GC_obj_kinds with ADD_BYTE_AT_END
+ defined should be -ALIGNMENT not WORDS_TO_BYTES(-1). This is
+ a serious bug on machines with pointer alignment of less than a word.
+ - GC_ignore_self_finalize_mark_proc didn't handle pointers to very near the
+ end of the object correctly. Caused failures of the C++ test on a DEC Alpha
+ with g++.
+ - gc_inl.h still had problems. Partially fixed. Added warnings at the
+ beginning to hopefully specify the remaining dangers.
+ - Added DATAEND definition to config.h.
+ - Fixed some of the .h file organization. Fixed "make floppy".
+
+Since version 4.6:
+ - Fixed some compilation problems with -DCHECKSUMS (thanks to Ian Searle)
+ - Updated some Mac specific files to synchronize with Patrick Beard.
+ - Fixed a serious bug for machines with non-word-aligned pointers.
+ (Thanks to Patrick Beard for pointing out the problem. The collector
+ should fail almost any conceivable test immediately on such machines.)
+
+Since version 4.7:
+ - Changed a "comment" in a MacOS specific part of mach-dep.c that caused
+ gcc to fail on other platforms.
+
+Since version 4.8
+ - More README.debugging fixes.
+ - Objects ready for finalization, but not finalized in the same GC
+ cycle, could be prematurely collected. This occasionally happened
+ in test_cpp.
+ - Too little memory was obtained from the system for very large
+ objects. That could cause a heap explosion if these objects were
+ not contiguous (e.g. under PCR), and too much of them was blacklisted.
+ - Due to an improper initialization, the collector was too hesitant to
+ allocate blacklisted objects immediately after system startup.
+ - Moved GC_arrays from the data into the bss segment by not explicitly
+ initializing it to zero. This significantly
+ reduces the size of executables, and probably avoids some disk accesses
+ on program startup. It's conceivable that it might break a port that I
+ didn't test.
+ - Fixed EMX_MAKEFILE to reflect the gc_c++.h to gc_cpp.h renaming which
+ occurred a while ago.
+
+Since 4.9:
+ - Fixed a typo around a call to GC_collect_or_expand in alloc.c. It broke
+ handling of out of memory. (Thanks to Patrick Beard for noticing.)
+
+Since 4.10:
+ - Rationalized (hopefully) GC_try_to_collect in an incremental collection
+ environment. It appeared to not handle a call while a collection was in
+ progress, and was otherwise too conservative.
+ - Merged GC_reclaim_or_delete_all into GC_reclaim_all to get rid of some
+ code.
+ - Added Patrick Beard's Mac fixes, with substantial completely untested
+ modifications.
+ - Fixed the MPROTECT_VDB code to deal with large pages and imprecise
+ fault addresses (as on an UltraSPARC running Solaris 2.5). Note that this
+ was not a problem in the default configuration, which uses PROC_VDB.
+ - The DEC Alpha assembly code needed to restore $gp between calls.
+ Thanks to Fergus Henderson for tracking this down and supplying a
+ patch.
+ - The write command for "de" was completely broken for large files.
+ I used the easiest portable fix, which involved changing the semantics
+ so that f.new is written instead of overwriting f. That's safer anyway.
+ - Added README.solaris2 with a discussion of the possible problems of
+ mixing the collector's sbrk allocation with malloc/realloc.
+ - Changed the data segment starting address for SGI machines. The
+ old code failed under IRIX6.
+ - Required double word alignment for MIPS.
+ - Various minor fixes to remove warnings.
+ - Attempted to fix some Solaris threads problems reported by Zhiying Chen.
+ In particular, the collector could try to fork a thread with the
+ world stopped as part of GC_thr_init. It also failed to deal with
+ the case in which the original thread terminated before the whole
+ process did.
+ - Added -DNO_EXECUTE_PERMISSION. This has a major performance impact
+ on the incremental collector under Irix, and perhaps under other
+ operating systems.
+ - Added some code to support allocating the heap with mmap. This may
+ be preferable under some circumstances.
+ - Integrated dynamic library support for HP.
+ (Thanks to Knut Tvedten <knuttv@ifi.uio.no>.)
+ - Integrated James Clark's win32 threads support, and made a number
+ of changes to it, many of which were suggested by Pontus Rydin.
+ This is still not 100% solid.
+ - Integrated Alistair Crooks' support for UTS4 running on an Amdahl
+ 370-class machine.
+ - Fixed a serious bug in explicitly typed allocation. Objects requiring
+ large descriptors where handled in a way that usually resulted in
+ a segmentation fault in the marker. (Thanks to Jeremy Fitzhardinge
+ for helping to track this down.)
+ - Added partial support for GNU win32 development. (Thanks to Fergus
+ Henderson.)
+ - Added optional support for Java-style finalization semantics. (Thanks
+ to Patrick Bridges.) This is recommended only for Java implementations.
+ - GC_malloc_uncollectable faulted instead of returning 0 when out of
+ memory. (Thanks to dan@math.uiuc.edu for noticing.)
+ - Calls to GC_base before the collector was initialized failed on a
+ DEC Alpha. (Thanks to Matthew Flatt.)
+ - Added base pointer checking to GC_REGISTER_FINALIZER in debugging
+ mode, at the suggestion of Jeremy Fitzhardinge.
+ - GC_debug_realloc failed for uncollectable objects. (Thanks to
+ Jeremy Fitzhardinge.)
+ - Explicitly typed allocation could crash if it ran out of memory.
+ (Thanks to Jeremy Fitzhardinge.)
+ - Added minimal support for a DEC Alpha running Linux.
+ - Fixed a problem with allocation of objects whose size overflowed
+ ptrdiff_t. (This now fails unconditionally, as it should.)
+ - Added the beginning of Irix pthread support.
+ - Integrated Xiaokun Zhu's fixes for djgpp 2.01.
+ - Added SGI-style STL allocator support (gc_alloc.h).
+ - Fixed a serious bug in README.solaris2. Multithreaded programs must include
+ gc.h with SOLARIS_THREADS defined.
+ - Changed GC_free so it actually deallocates uncollectable objects.
+ (Thanks to Peter Chubb for pointing out the problem.)
+ - Added Linux ELF support for dynamic libararies. (Thanks again to
+ Patrick Bridges.)
+ - Changed the Borland cc configuration so that the assembler is not
+ required.
+ - Fixed a bug in the C++ test that caused it to fail in 64-bit
+ environments.
+
+Since 4.11:
+ - Fixed ElfW definition in dyn_load.c. (Thanks to Fergus Henderson.)
+ This prevented the dynamic library support from compiling on some
+ older ELF Linux systems.
+ - Fixed UTS4 port (which I apparently mangled during the integration)
+ (Thanks to again to Alistair Crooks.)
+ - "Make C++" failed on Suns with SC4.0, due to a problem with "bool".
+ Fixed in gc_priv.h.
+ - Added more pieces for GNU win32. (Thanks to Timothy N. Newsham.)
+ The current state of things should suffice for at least some
+ applications.
+ - Changed the out of memory retry count handling as suggested by
+ Kenjiro Taura. (This matters only if GC_max_retries > 0, which
+ is no longer the default.)
+ - If a /proc read failed repeatedly, GC_written_pages was not updated
+ correctly. (Thanks to Peter Chubb for diagnosing this.)
+ - Under unlikely circumstances, the allocator could infinite loop in
+ an out of memory situation. (Thanks again to Kenjiro Taura for
+ identifying the problem and supplying a fix.)
+ - Fixed a syntactic error in the DJGPP code. (Thanks to Fergus
+ Henderson for finding this by inspection.) Also fixed a test program
+ problem with DJGPP (Thanks to Peter Monks.)
+ - Atomic uncollectable objects were not treated correctly by the
+ incremental collector. This resulted in weird log statistics and
+ occasional performance problems. (Thanks to Peter Chubb for pointing
+ this out.)
+ - Fixed some problems resulting from compilers that dont define
+ __STDC__. In this case void * and char * were used inconsistently
+ in some cases. (Void * should not have been used at all. If
+ you have an ANSI superset compiler that does not define __STDC__,
+ please compile with -D__STDC__=0. Thanks to Manuel Serrano and others
+ for pointing out the problem.)
+ - Fixed a compilation problem on Irix with -n32 and -DIRIX_THREADS.
+ Also fixed some other IRIX_THREADS problems which may or may not have
+ had observable symptoms.
+ - Fixed an HP PA compilation problem in dyn_load.c. (Thanks to
+ Philippe Queinnec.)
+ - SEGV fault handlers sometimes did not get reset correctly. (Thanks
+ to David Pickens.)
+ - Added a fix for SOLARIS_THREADS on Intel. (Thanks again to David
+ Pickens.) This probably needs more work to become functional.
+ - Fixed struct sigcontext_struct in os_dep.c for compilation under
+ Linux 2.1.X. (Thanks to Fergus Henderson.)
+ - Changed the DJGPP STACKBOTTOM and DATASTART values to those suggested
+ by Kristian Kristensen. These may still not be right, but it is
+ it is likely to work more often than what was there before. They may
+ even be exactly right.
+ - Added a #include <string.h> to test_cpp.cc. This appears to help
+ with HP/UX and gcc. (Thanks to assar@sics.se.)
+ - Version 4.11 failed to run in incremental mode on recent 64-bit Irix
+ kernels. This was a problem related to page unaligned heap segments.
+ Changed the code to page align heap sections on all platforms.
+ (I had mistakenly identified this as a kernel problem earlier.
+ It was not.)
+ - Version 4.11 did not make allocated storage executable, except on
+ one or two platforms, due to a bug in a #if test. (Thanks to Dave
+ Grove for pointing this out.)
+ - Added sparc_sunos4_mach_dep.s to support Sun's compilers under SunOS4.
+ - Added GC_exclude_static_roots.
+ - Fixed the object size mapping algorithm. This shouldn't matter,
+ but the old code was ugly.
+ - Heap checking code could die if one of the allocated objects was
+ larger than its base address. (Unsigned underflow problem. Thanks
+ to Clay Spence for isolating the problem.)
+ - Added RS6000 (AIX) dynamic library support and fixed STACK_BOTTOM.
+ (Thanks to Fred Stearns.)
+ - Added Fergus Henderson's patches for improved robustness with large
+ heaps and lots of blacklisting.
+ - Added Peter Chubb's changes to support Solaris Pthreads, to support
+ MMAP allocation in Solaris, to allow Solaris to find dynamic libraries
+ through /proc, to add malloc_typed_ignore_off_page, and a few other
+ minor features and bug fixes.
+ - The Solaris 2 port should not use sbrk. I received confirmation from
+ Sun that the use of sbrk and malloc in the same program is not
+ supported. The collector now defines USE_MMAP by default on Solaris.
+ - Replaced the djgpp makefile with Gary Leavens' version.
+ - Fixed MSWIN32 detection test.
+ - Added Fergus Henderson's patches to allow putting the collector into
+ a DLL under GNU win32.
+ - Added Ivan V. Demakov's port to Watcom C on X86.
+ - Added Ian Piumarta's Linux/PowerPC port.
+ - On Brian Burton's suggestion added PointerFreeGC to the placement
+ options in gc_cpp.h. This is of course unsafe, and may be controversial.
+ On the other hand, it seems to be needed often enough that it's worth
+ adding as a standard facility.
+
+Since 4.12:
+ - Fixed a crucial bug in the Watcom port. There was a redundant decl
+ of GC_push_one in gc_priv.h.
+ - Added FINALIZE_ON_DEMAND.
+ - Fixed some pre-ANSI cc problems in test.c.
+ - Removed getpagesize() use for Solaris. It seems to be missing in one
+ or two versions.
+ - Fixed bool handling for SPARCCompiler version 4.2.
+ - Fixed some files in include that had gotten unlinked from the main
+ copy.
+ - Some RS/6000 fixes (missing casts). Thanks to Toralf Foerster.
+ - Fixed several problems in GC_debug_realloc, affecting mostly the
+ FIND_LEAK case.
+ - GC_exclude_static_roots contained a buggy unsigned comparison to
+ terminate a loop. (Thanks to Wilson Ho.)
+ - CORD_str failed if the substring occurred at the last possible position.
+ (Only affects cord users.)
+ - Fixed Linux code to deal with RedHat 5.0 and integrated Peter Bigot's
+ os_dep.c code for dealing with various Linux versions.
+ - Added workaround for Irix pthreads sigaction bug and possible signal
+ misdirection problems.
+Since alpha1:
+ - Changed RS6000 STACKBOTTOM.
+ - Integrated Patrick Beard's Mac changes.
+ - Alpha1 didn't compile on Irix m.n, m < 6.
+ - Replaced Makefile.dj with a new one from Gary Leavens.
+ - Added Andrew Stitcher's changes to support SCO OpenServer.
+ - Added PRINT_BLACK_LIST, to allow debugging of high densities of false
+ pointers.
+ - Added code to debug allocator to keep track of return address
+ in GC_malloc caller, thus giving a bit more context.
+ - Changed default behavior of large block allocator to more
+ aggressively avoid fragmentation. This is likely to slow down the
+ collector when it succeeds at reducing space cost.
+ - Integrated Fergus Henderson's CYGWIN32 changes. They are untested,
+ but needed for newer versions.
+ - USE_MMAP had some serious bugs. This caused the collector to fail
+ consistently on Solaris with -DSMALL_CONFIG.
+ - Added Linux threads support, thanks largely to Fergus Henderson.
+Since alpha2:
+ - Fixed more Linux threads problems.
+ - Changed default GC_free_space_divisor to 3 with new large block allocation.
+ (Thanks to Matthew Flatt for some measurements that suggest the old
+ value sometimes favors space too much over time.)
+ - More CYGWIN32 fixes.
+ - Integrated Tyson-Dowd's Linux-M68K port.
+ - Minor HP PA and DEC UNIX fixes from Fergus Henderson.
+ - Integrated Christoffe Raffali's Linux-SPARC changes.
+ - Allowed for one more GC fixup iteration after a full GC in incremental
+ mode. Some quick measurements suggested that this significantly
+ reduces pause times even with smaller GC_RATE values.
+ - Moved some more GC data structures into GC_arrays. This decreases
+ pause times and GC overhead, but makes debugging slightly less convenient.
+ - Fixed namespace pollution problem ("excl_table").
+ - Made GC_incremental a constant for -DSMALL_CONFIG, hopefully shrinking
+ that slightly.
+ - Added some win32 threads fixes.
+ - Integrated Ivan Demakov and David Stes' Watcom fixes.
+ - Various other minor fixes contributed by many people.
+ - Renamed config.h to gcconfig.h, since config.h tends to be used for
+ many other things.
+ - Integrated Matthew Flatt's support for 68K MacOS "far globals".
+ - Fixed up some of the dynamic library Makefile targets for consistency
+ across platforms.
+ - Fixed a USE_MMAP typo that caused out-of-memory handling to fail
+ on Solaris.
+ - Added code to test.c to test thread creation a bit more.
+ - Integrated GC_win32_free_heap, as suggested by Ivan Demakov.
+ - Fixed Solaris 2.7 stack base finding problem. (This may actually
+ have been done in an earlier alpha release.)
+Since alpha3:
+ - Fixed MSWIN32 recognition test, which interfered with cygwin.
+ - Removed unnecessary gc_watcom.asm from distribution. Removed
+ some obsolete README.win32 text.
+ - Added Alpha Linux incremental GC support. (Thanks to Philipp Tomsich
+ for code for retrieving the fault address in a signal handler.)
+ Changed Linux signal handler context argument to be a pointer.
+ - Took care of some new warnings generated by the 7.3 SGI compiler.
+ - Integrated Phillip Musumeci's FreeBSD/ELF fixes.
+ - -DIRIX_THREADS was broken with the -o32 ABI (typo in gc_priv.h>
+
+Since 4.13:
+ - Fixed GC_print_source_ptr to not use a prototype.
+ - generalized CYGWIN test.
+ - gc::new did the wrong thing with PointerFreeGC placement.
+ (Thanks to Rauli Ruohonen.)
+ - In the ALL_INTERIOR_POINTERS (default) case, some callee-save register
+ values could fail to be scanned if the register was saved and
+ reused in a GC frame. This showed up in verbose mode with gctest
+ compiled with an unreleased SGI compiler. I vaguely recall an old
+ bug report that may have been related. The bug was probably quite old.
+ (The problem was that the stack scanning could be deferred until
+ after the relevant frame was overwritten, and the new save location
+ might be outside the scanned area. Fixed by more eager stack scanning.)
+ - PRINT_BLACK_LIST had some problems. A few source addresses were garbage.
+ - Replaced Makefile.dj and added -I flags to cord make targets.
+ (Thanks to Gary Leavens.)
+ - GC_try_to_collect was broken with the nonincremental collector.
+ - gc_cleanup destructors could pass the wrong address to
+ GC_register_finalizer_ignore_self in the presence of multiple
+ inheritance. (Thanks to Darrell Schiebel.)
+ - Changed PowerPC Linux stack finding code.
+
+Since 4.14alpha1
+ - -DSMALL_CONFIG did not work reliably with large (> 4K) pages.
+ Recycling the mark stack during expansion could result in a size
+ zero heap segment, which confused things. (This was probably also an
+ issue with the normal config and huge pages.)
+ - Did more work to make sure that callee-save registers were scanned
+ completely, even with the setjmp-based code. Added USE_GENERIC_PUSH_REGS
+ macro to facilitate testing on machines I have access to.
+ - Added code to explicitly push register contents for win32 threads.
+ This seems to be necessary. (Thanks to Pierre de Rop.)
+
+Since 4.14alpha2
+ - changed STACKBOTTOM for DJGPP (Thanks to Salvador Eduardo Tropea).
+
+Since 4.14
+ - Reworked large block allocator. Now uses multiple doubly linked free
+ lists to approximate best fit.
+ - Changed heap expansion heuristic. Entirely free blocks are no longer
+ counted towards the heap size. This seems to have a major impact on
+ heap size stability; the old version could expand the heap way too
+ much in the presence of large block fragmentation.
+ - added -DGC_ASSERTIONS and some simple assertions inside the collector.
+ This is mainlyt for collector debugging.
+ - added -DUSE_MUNMAP to allow the heap to shrink. Suupported on only
+ a few UNIX-like platforms for now.
+ - added GC_dump_regions() for debugging of fragmentation issues.
+ - Changed PowerPC pointer alignment under Linux to 4. (This needs
+ checking by someone who has one. The suggestions came to me via a
+ rather circuitous path.)
+ - Changed the Linux/Alpha port to walk the data segment backwards until
+ it encounters a SIGSEGV. The old way to find the start of the data
+ segment broke with a recent release.
+ - cordxtra.c needed to call GC_REGISTER_FINALIZER instead of
+ GC_register_finalizer, so that it would continue to work with GC_DEBUG.
+ - allochblk sometimes cleared the wrong block for debugging purposes
+ when it dropped blacklisted blocks. This could result in spurious
+ error reports with GC_DEBUG.
+ - added MACOS X Server support. (Thanks to Andrew Stone.)
+ - Changed the Solaris threads code to ignore stack limits > 8 MB with
+ a warning. Empirically, it is not safe to access arbitrary pages
+ in such large stacks. And the dirty bit implementation does not
+ guarantee that none of them will be accessed.
+ - Integrated Martin Tauchmann's Amiga changes.
+ - Integrated James Dominy's OpenBSD/SPARC port.
+
+Since 5.0alpha1
+ - Fixed bugs introduced in alpha1 (OpenBSD & large block initialization).
+ - Added -DKEEP_BACK_PTRS and backptr.h interface. (The implementation
+ idea came from Al Demers.)
+
+Since 5.0alpha2
+ - Added some highly incomplete code to support a copied young generation.
+ Comments on nursery.h are appreciated.
+ - Changed -DFIND_LEAK, -DJAVA_FINALIZATION, and -DFINALIZE_ON_DEMAND,
+ so the same effect could be obtained with a runtime switch. This is
+ a step towards standardizing on a single dynamic GC library.
+ - Significantly changed the way leak detection is handled, as a consequence
+ of the above.
+
+Since 5.0 alpha3
+ - Added protection fault handling patch for Linux/M68K from Fergus
+ Henderson and Roman Hodek.
+ - Removed the tests for SGI_SOURCE in new_gc_alloc.h. This was causing that
+ interface to fail on nonSGI platforms.
+ - Changed the Linux stack finding code to use /proc, after changing it
+ to use HEURISTIC1. (Thanks to David Mossberger for pointing out the
+ /proc hook.)
+ - Added HP/UX incremental GC support and HP/UX 11 thread support.
+ Thread support is currently still flakey.
+ - Added basic Linux/IA64 support.
+ - Integrated Anthony Green's PicoJava support.
+ - Integrated Scott Ananian's StrongARM/NetBSD support.
+ - Fixed some fairly serious performance bugs in the incremental
+ collector. These have probably been there essentially forever.
+ (Mark bits were sometimes set before scanning dirty pages.
+ The reclaim phase unnecessarily dirtied full small object pages.)
+ - Changed the reclaim phase to ignore nearly full pages to avoid
+ touching them.
+ - Limited GC_black_list_spacing to roughly the heap growth increment.
+ - Changed full collection triggering heuristic to decrease full GC
+ frequency by default, but to explicitly trigger full GCs during
+ heap growth. This doesn't always improve things, but on average it's
+ probably a win.
+ - GC_debug_free(0, ...) failed. Thanks to Fergus Henderson for the
+ bug report and fix.
+
+Since 5.0 alpha4
+ - GC_malloc_explicitly_typed and friends sometimes failed to
+ initialize first word.
+ - Added allocation routines and support in the marker for mark descriptors
+ in a type structure referenced by the first word of an object. This was
+ introduced to support gcj, but hopefully in a way that makes it
+ generically useful.
+ - Added GC_requested_heapsize, and inhibited collections in nonincremental
+ mode if the actual used heap size is less than what was explicitly
+ requested.
+ - The Solaris pthreads version of GC_pthread_create didn't handle a NULL
+ attribute pointer. Solaris thread support used the wrong default thread
+ stack size. (Thanks to Melissa O'Neill for the patch.)
+ - Changed PUSH_CONTENTS macro to no longer modify first parameter.
+ This usually doesn't matter, but it was certainly an accident waiting
+ to happen ...
+ - Added GC_register_finalizer_no_order and friends to gc.h. They're
+ needed by Java implementations.
+ - Integrated a fix for a win32 deadlock resulting from clock() calling
+ malloc. (Thanks to Chris Dodd.)
+ - Integrated Hiroshi Kawashima's port to Linux/MIPS. This was designed
+ for a handheld platform, and may or may not be sufficient for other
+ machines.
+ - Fixed a va_arg problem with the %c specifier in cordprnt.c. It appears
+ that this was always broken, but recent versions of gcc are the first to
+ report the (statically detectable) bug.
+ - Added an attempt at a more general solution to dlopen races/deadlocks.
+ GC_dlopen now temporarily disables collection. Still not ideal, but ...
+ - Added -DUSE_I686_PREFETCH, -DUSE_3DNOW_PREFETCH, and support for IA64
+ prefetch instructions. May improve performance measurably, but I'm not
+ sure the code will run correctly on processors that don't support the
+ instruction. Won't build except with very recent gcc.
+ - Added caching for header lookups in the marker. This seems to result
+ in a barely measurable performance gain. Added support for interleaved
+ lookups of two pointers, but unconfigured that since the performance
+ gain is currently near zero, and it adds to code size.
+ - Changed Linux DATA_START definition to check both data_start and
+ __data_start, since nothing else seems to be portable.
+ - Added -DUSE_LD_WRAP to optionally take advantage of the GNU ld function
+ wrapping mechanism. Probably currently useful only on Linux.
+ - Moved some variables for the scratch allocator into GC_arrays, on
+ Martin Hirzel's suggestion.
+ - Fixed a win32 threads bug that caused the collector to not look for
+ interior pointers from one of the thread stacks without
+ ALL_INTERIOR_POINTERS. (Thanks to Jeff Sturm.)
+ - Added Mingw32 support. (Thanks again to Jeff Sturm for the patch.)
+ - Changed the alpha port to use the generic register scanning code instead
+ of alpha_mach_dep.s. Alpha_mach_dep.s doesn't look for pointers in fp
+ registers, but gcc sometimes spills pointers there. (Thanks to Manuel
+ Serrano for helping me debug this by email.) Changed the IA64 code to
+ do something similar for similar reasons.
+
+[5.0alpha5 doesn't really exist, but it may have escaped.]
+
+Since 5.0alpha6:
+ - -DREDIRECT_MALLOC was broken in alpha6. Fixed.
+ - Cleaned up gc_ccp.h slightly, thus also causing the HP C++ compiler to
+ accept it.
+ - Removed accidental reference to dbg_mlc.c, which caused dbg_mlc.o to be
+ linked into every executable.
+ - Added PREFETCH to bitmap marker. Changed it to use the header cache.
+ - GC_push_marked sometimes pushed one object too many, resulting in a
+ segmentation fault in GC_mark_from_mark_stack. This was probably an old
+ bug. It finally showed up in gctest on win32.
+ - Gc_priv.h erroneously #defined GC_incremental to be TRUE instead of FALSE
+ when SMALL_CONFIG was defined. This was no doubt a major performance bug for
+ the default win32 configuration.
+ - Removed -DSMALL_CONFIG from NT_MAKEFILE. It seemed like an anchronism now
+ that the average PC has 64MB or so.
+ - Integrated Bryce McKinley's patches for linux threads and dynamic loading
+ from the libgcj tree. Turned on dynamic loading support for Linux/PPC.
+ - Changed the stack finding code to use environ on HP/UX. (Thanks
+ to Gustavo Rodriguez-Rivera for the suggestion.) This should probably
+ be done on other platforms, too. Since I can't test those, that'll
+ wait until after 5.0.
+
+Since 5.0alpha7:
+ - Fixed threadlibs.c for linux threads. -DUSE_LD_WRAP was broken and
+ -ldl was omitted. Fixed Linux stack finding code to handle
+ -DUSE_LD_WRAP correctly.
+ - Added MSWIN32 exception handler around marker, so that the collector
+ can recover from root segments that are unmapped during the collection.
+ This caused occasional failures under Windows 98, and may also be
+ an issue under Windows NT/2000.
+
+Since 5.0
+ - Fixed a gc.h header bug which showed up under Irix. (Thanks to
+ Dan Sullivan.)
+ - Fixed a typo in GC_double_descr in typd_mlc.c.
+ This probably could result in objects described by array descriptors not
+ getting traced correctly. (Thanks to Ben Hutchings for pointing this out.)
+ - The block nearly full tests in reclaim.c were not correct for 64 bit
+ environments. This could result in unnecessary heap growth under unlikely
+ conditions.
+
+Since 5.1
+ - dyn_load.c declared GC_scratch_last_end_ptr as an extern even if it
+ was defined as a macro. This prevented the collector from building on
+ Irix.
+ - We quietly assumed that indirect mark descriptors were never 0.
+ Our own typed allocation interface violated that. This could result
+ in segmentation faults in the marker with typed allocation.
+ - Fixed a _DUSE_MUNMAP bug in the heap block allocation code.
+ (Thanks to Ben Hutchings for the patch.)
+ - Taught the collector about VC++ handling array operator new.
+ (Thanks again to Ben Hutchings for the patch.)
+ - The two copies of gc_hdrs.h had diverged. Made one a link to the other
+ again.
+
+Since 5.2 (A few 5.2 patches are not in 6.0alpha1)
+ - Fixed _end declaration for OSF1.
+ - There were lots of spurious leak reports in leak detection mode, caused
+ by the fact that some pages were not being swept, and hence unmarked
+ objects weren't making it onto free lists. (This bug dated back to 5.0.)
+ - Fixed a typo in the liblinuxgc.so Makefile rule.
+ - Added the GetExitCodeThread to Win32 GC_stop_world to (mostly) work
+ around a Windows 95 GetOpenFileName problem. (Thanks to Jacob Navia.)
+
+Since 5.3
+ - Fixed a typo that prevented compilation with -DUSE_3DNOW_PREFETCH.
+ (Thanks to Shawn Wagner for actually testing this.)
+ - Fixed GC_is_thread_stack in solaris_threads.c. It forgot to return a value
+ in the common case. I wonder why nobody noticed?
+ - Fixed another silly syntax problem in GC_double_descr. (Thanks to
+ Fergus Henderson for finding it.)
+ - Fixed a GC_gcj_malloc bug: It tended to release the allocator lock twice.
+
+Since 5.4 (A few 5.3 patches are not in 6.0alpha2)
+ - Added HP/PA prefetch support.
+ - Added -DDBG_HDRS_ALL and -DSHORT_DBG_HDRS to reduce the cost and improve
+ the reliability of generating pointer backtrace information, e.g. in
+ the Bigloo environment.
+ - Added parallel marking support (-DPARALLEL_MARK). This currently
+ works only under IA32 and IA64 Linux, but it shouldn't be hard to adapt
+ to other platforms. This is intended to be a lighter-weight (less
+ new code, probably not as scalable) solution than the work by Toshio Endo
+ et al, at the University of Tokyo. A number of their ideas were
+ reused, though the code wasn't, and the underlying data structure
+ is significantly different. In particular, we keep the global mark
+ stack as a single shared data structure, but most of the work is done
+ on smaller thread-local mark stacks.
+ - Changed GC_malloc_many to be cheaper, and to require less mutual exclusion
+ with -DPARALLEL_MARK.
+ - Added full support for thread local allocation under Linux
+ (-DTHREAD_LOCAL_ALLOC). This is a thin veneer on GC_malloc_many, and
+ should be easily portable to other platforms, especially those that
+ support pthreads.
+ - CLEAR_DOUBLE was not always getting invoked when it should have been.
+ - GC_gcj_malloc and friends used different out of memory handling than
+ everything else, probably because I forgot about one when I implemented
+ the other. They now both call GC_oom_fn(), not GC_oom_action().
+ - Integrated Jakub Jelinek's fixes for Linux/SPARC.
+ - Moved GC_objfreelist, GC_aobjfreelist, and GC_words_allocd out of
+ GC_arrays, and separately registered the first two as excluded roots.
+ This makes code compiled with gc_inl.h less dependent on the
+ collector version. (It would be nice to remove the inclusion of
+ gc_priv.h by gc_inl.h completely, but we're not there yet. The
+ locking definitions in gc_priv.h are still referenced.)
+ This change was later coniditoned on SEPARATE_GLOBALS, which
+ is not defined by default, since it involves a performance hit.
+ - Register GC_obj_kinds separately as an excluded root region. The
+ attempt to register it with GC_arrays was usually failing. (This wasn't
+ serious, but seemed to generate some confusion.)
+ - Moved backptr.h to gc_backptr.h.
+
+Since 6.0alpha1
+ - Added USE_MARK_BYTES to reduce the need for compare-and-swap on platforms
+ for which that's expensive.
+ - Fixed a locking bug ib GC_gcj_malloc and some locking assertion problems.
+ - Added a missing volatile to OR_WORD and renamed the parameter to
+ GC_compare_and_swap so it's not a C++ reserved word. (Thanks to
+ Toshio Endo for pointing out both of those.)
+ - Changed Linux dynamic library registration code to look at /proc/self/maps
+ instead of the rld data structures when REDIRECT_MALLOC is defined.
+ Otherwise some of the rld data data structures may be prematurely garbage
+ collected. (Thanks to Eric Benson for helping to track this down.)
+ - Fixed USE_LD_WRAP a bit more, so it should now work without threads.
+ - Renamed XXX_THREADS macros to GC_XXX_THREADS for namespace correctness.
+ Tomporarily added some backward compatibility definitions. Renamed
+ USE_LD_WRAP to GC_USE_LD_WRAP.
+ - Many MACOSX POWERPC changes, some additions to the gctest output, and
+ a few minor generic bug fixes. (Thanks to Dietmar Planitzer.)
+
+Since 6.0 alpha2
+ - Fixed the /proc/self/maps code to not seek, since that apparently is not
+ reliable across all interesting kernels.
+ - Fixed some compilation problems in the absence of PARALLEL_MARK
+ (introduced in alpha2).
+ - Fixed an algorithmic problem with PARALLEL_MARK. If work needs to
+ be given back to the main mark "stack", the BOTTOM entries of the local
+ stack should be given away, not the top ones. This has substantial
+ performance impact, especially for > 2 processors, from what I can tell.
+ - Extracted gc_lock.h from gc_priv.h. This should eventually make it a
+ bit easier to avoid including gc_priv.h in clients.
+ - Moved all include files to include/ and removed duplicate links to the
+ same file. The old scheme was a bad idea because it was too easy to get the
+ copies out of sync, and many systems don't support hard links.
+ Unfortunately, it's likely that I broke some of the non-Unix Makefiles in
+ the process, although I tried to update them appropriately.
+ - Removed the partial support for a copied nursery. It's not clear that
+ this would be a tremendous win, since we don't consistently lose to
+ generational copying collectors. And it would significantly complicate
+ many things. May be reintroduced if/when it really turns out to win.
+ - Removed references to IRIX_JDK_THREADS, since I believe there never
+ were and never will be any clients.
+ - Added some code to linux_threads.c to possibly support HPUX threads
+ using the Linux code. Unfortunately, it doesn't work yet, and is
+ currently disabled.
+ - Added support under Linux/X86 for saving the call chain, both in (debug)
+ objects for client debugging, and in GC_arrays._last_stack for GC
+ debugging. This was previously supported only under Solaris. It is
+ not enabled by default under X86, since it requires that code be compiled
+ to explicitly dave frame pointers on the call stack. (With gcc this
+ currently happens by default, but is often turned off explicitly.)
+ To turn it on, define SAVE_CALL_CHAIN.
+
+Since 6.0 alpha3
+ - Moved up the detection of mostly full blocks to the initiatiation of the
+ sweep phase. This eliminates some lock conention in the PARALLEL_MARK case,
+ as multiple threads try to look at mostly full blocks concurrently.
+ - Restored the code in GC_malloc_many that grabs a prefix of the global
+ free list. This avoids the case in which every GC_malloc_many call
+ tries and fails to allocate a new heap block, and the returns a single
+ object from the global free list.
+ - Some minor fixes in new_hblk.c. (Attempted to build free lists in order
+ of increasing addresses instead of decreasing addresses for cache performance
+ reasons. But this seems to be only a very minor gain with -DEAGER_SWEEP,
+ and a loss in other cases. So the change was backed out.)
+ - Fixed some of the documentation. (Thanks in large part to Fergus
+ Henderson.)
+ - Fixed the Linux USE_PROC_FOR_LIBRARIES code to deal with apps that perform
+ large numbers of mmaps. (Thanks to Eric Benson.) Also fixed that code to
+ deal with short reads.
+ - Added GC_get_total_bytes().
+ - Fixed leak detection mode to avoid spurious messages under linuxthreads.
+ (This should also now be easy for the other supported threads packages.
+ But the code is tricky enough that I'm hesitant to do it without being able
+ to test. Everything allocated in the GC thread support itself should be
+ explicitly deallocated.)
+ - Made it possible (with luck) to redirect malloc to GC_local_malloc.
+
+Since 6.0 alpha4
+ - Changed the definition of GC_pause in linux_threads.c to use a volatile
+ asm. Some versions of gcc apparently optimize away writes to local volatile
+ variables. This caused poor locking behaviour starting at about
+ 4 processors.
+ - Added GC_start_blocking(), GC_end_blocking() calls and wrapper for sleep
+ to linux_threads.c.
+ The first two calls could be used to generally avoid sending GC signals to
+ blocked threads, avoiding both premature wakeups and unnecessary overhead.
+ - Fixed a serious bug in thread-local allocation. At thread termination,
+ GC_free could get called on small integers. Changed the code for thread
+ termination to more efficiently return left-over free-lists.
+ - Integrated Kjetil Matheussen's BeOS support.
+ - Rearranged the directory structure to create the doc and tests
+ subdirectories.
+ - Sort of integrated Eric Benson's patch for OSF1. This provided basic
+ OSF1 thread support by suitably extending hpux_irix_threads.c. Based
+ on earlier email conversations with David Butenhof, I suspect that it
+ will be more reliable in the long run to base this on linux_threads.c
+ instead. Thus I attempted to patch up linux_threads.c based on Eric's code.
+ The result is almost certainly broken, but hopefully close enough that
+ someone with access to a machine can pick it up.
+ - Integrated lots of minor changes from the NetBSD distribution. (These
+ were supplied by David Brownlee. I'm not sure about the original
+ authors.)
+ - Hacked a bit more on the HP/UX thread-support in linux_threads.c. It
+ now appears to work in the absence of incremental collection. Renamed
+ hpux_irix_threads.c back to irix_threads.c, and removed the attempt to
+ support HPUX there.
+ - Changed gc.h to define _REENTRANT in cases in which it should already
+ have been defined. It is still safer to also define it on the command
+ line.
+
+Since 6.0alpha5:
+ - Changed the definition of DATASTART on ALPHA and IA64, where data_start
+ and __data_start are not defined by earlier versions of glibc. This might
+ need to be fixed on other platforms as well.
+ - Changed the way the stack base and backing store base are found on IA64.
+ This should now remain reliable on future kernels. But since it relies
+ on /proc, it will no longer work in the simulated NUE environment.
+ - Made the call to random() in dbg_mlc.c with -DKEEP_BACK_PTRS dependent
+ on the OS. On non-Unix systems, rand() should be used instead. Handled
+ small RAND_MAX. (Thanks to Peter Ross for pointing this out.)
+ - Fixed the cord make rules to create the cord subdirectory, if necessary.
+ (Thanks to Doug Moen.)
+ - Changed fo_object_size calculation in finalize.c. Turned finalization
+ of nonheap object into a no-op. Removed anachronism from GC_size()
+ implementation.
+ - Changed GC_push_dirty call in solaris_threads.c to GC_push_selected.
+ It was missed in a previous renaming. (Thanks to Vladimir Tsichevski
+ for pointing this out.)
+ - Arranged to not not mask SIGABRT in linux_threads.c. (Thanks to Bryce
+ McKinlay.)
+ - Added GC_no_dls hook for applications that want to register their own
+ roots.
+ - Integrated Kjetil Matheussen's Amiga changes.
+ - Added FREEBSD_STACKBOTTOM. Changed the X86/FreeBSD port to use it.
+ (Thanks to Matthew Flatt.)
+ - Added pthread_detach interception for platforms supported by linux_threads.c
+ and irix_threads.c. Should also be added for Solaris?
+ - Changed the USE_MMAP code to check for the case in which we got the
+ high end of the address space, i.e. mem_ptr + mem_sz == 0. It appears
+ that this can happen under Solaris 7. It seems to be allowed by what
+ I would claim is an oversight in the mmap specification. (Thanks to Toshio
+ Endo for pointing out the problem.)
+ - Cleanup of linux_threads.c. Some code was originally cloned from
+ irix_threads.c and now unnecessary. Some comments were obviously wrong.
+ - (Mostly) fixed a longstanding problem with setting of dirty bits from
+ a signal handler. In the presence of threads, dirty bits could get lost,
+ since the etting of a bit in the bit vector was not atomic with respect
+ to other updates. The fix is 100% correct only for platforms for which
+ GC_test_and_set is defined. The goal is to make that all platforms with
+ thread support. Matters only if incremental GC and threads are both
+ enabled.
+ - made GC_all_interior_pointers (a.k.a. ALL_INTERIOR_POINTERS) an
+ initialization time, instead of build-time option. This is a
+ nontrivial, high risk change. It should slow down the code measurably
+ only if MERGE_SIZES is not defined, which is a very nonstandard
+ configuration.
+ - Added doc/README.environment, and implemented what it describes. This
+ allows a number of additional configuration options to be set through
+ the environment. It documents a few previously undocumented options.
+ - Integrated Eric Benson's leak testing improvements.
+ - Removed the option to throw away the beginning of each page (DISCARD_WORDS).
+ This became less and less useful as processors enforce stricter alignment.
+ And it hadn't been tested in ages, and was thus probably broken anyway.
+
+Since 6.0alpha6:
+ - Added GC_finalizer_notifier. Fixed GC_finalize_on_demand. (The variable
+ actually wasn't being tested at the right points. The build-time flag
+ was.)
+ - Added Tom Tromey's S390 Linux patch.
+ - Added code to push GC_finalize_now in GC_push_finalizer_structures.
+ (Thanks to Matthew Flatt.)
+ - Added GC_push_gc_structures() to push all GC internal roots.
+ - Integrated some FreeBSD changes from Matthew Flatt.
+ - It looks like USRSTACK is not always correctly defined under Solaris.
+ Hacked gcconfig.h to attempt to work around the problem. The result
+ is not well tested. (Thanks again to Matthew Flatt for pointing this
+ out. The gross hack is mine. - HB)
+ - Added Ji-Yong Chung's win32 threads and C++ fixes.
+ - Arranged for hpux_test_and_clear.s to no longer be needed or built.
+ It was causing build problems with gas, and it's not clear this is
+ better than the pthreads alternative on this platform.
+ - Some MINGW32 fixes from Hubert Garavel.
+ - Added Initial Hitachi SH4 port from Kaz Kojima.
+ - Ported thread-local allocation and parallel mark code to HP/UX on PA_RISC.
+ - Made include/gc_mark.h more public and separated out the really private
+ pieces. This is probably still not quite sufficient for clients that
+ want to supply their own kind of type information. But it's a start.
+ This involved lots of identifier renaming to make it namespace clean.
+ - Added GC_dont_precollect for clients that need complete control over
+ the root set.
+ - GC_is_visible didn't do the right thing with gcj objects. (Not that
+ many people are likely to care, but ...)
+ - Don't redefine read with GC_USE_LD_WRAP.
+ - Initial port to LINUX/HP_PA. Incremental collection and threads are not
+ yet supported. (Incremental collection should work if you have the
+ right kernel. Threads may work with a sufficiently patched pthread
+ library.)
+ - Changed gcconfig.h to recognize __i386__ as an alternative to i386 in
+ many places. (Thanks to Benjamin Lerman.)
+ - Made win32_threads.c more tolerant of detaching a thread that it didn't
+ know about. (Thanks to Paul Nash.)
+ - Added Makefile.am and configure.in from gcc to the distribution, with
+ minimal changes. For the moment, those are just placeholders. In the
+ future, we're planning to switch to a GNU-style build environment for
+ Un*x-like systems, though the old Makefile will remain as a backup.
+ - Turned off STUBBORN_ALLOC by default, and added it back as a Makefile
+ option.
+ - Redistributed some functions between malloc.c and mallocx.c, so that
+ simple statically linked apps no longer pull in mallocx.o.
+ - Changed large object allocation to clear the first and last few words
+ of each block before releassing the lock. Otherwise the marker could see
+ objects with nonsensical type descriptors.
+ - Fixed a couple of subtle problems that could result in not recognizing
+ interior pointers from the stack. (I believe these were introduced
+ in 6.0alpha6.)
+ - GC_debug_free_inner called GC_free, which tried to reacquire the
+ allocator lock, and hence deadlocked. (DBG_HDRS_ALL probably never worked
+ with threads?)
+ - Fixed several problems with back traces. Accidental references to a free
+ list could cause the free list pointer to be overwritten by a back pointer.
+ There seemed to be some problems with the encoding of root and finalizer
+ references.
+
+Since 6.0alpha7:
+ - Changed GC_debug_malloc_replacement and GC_debug_realloc_replacement
+ so that they compile under Irix. (Thanks to Dave Love.)
+ - Updated powerpc_macosx_mach_dep.s so that it works if the collector
+ is in a dynamic library. (Thanks to Andrew Begel.)
+ - Transformed README.debugging into debugging.html, updating and
+ expanding it in the process. Added gcdescr.html and tree.html
+ from the web site to the GC distribution.
+ - Fixed several problems related to PRINT_BLACK_LIST. This involved
+ restructuring some of the marker macros.
+ - Fixed some problems with the sizing of objects with debug information.
+ Finalization was broken KEEP_BACK_PTRS or PRINT_BLACK_LIST. Reduced the
+ object size with SHORT_DEBUG_HDRS by another word.
+ - The "Needed to allocate blacklisted ..." warning had inadvertently
+ been turned off by default, due to a buggy test in allchblk.c. Turned
+ it back on.
+ - Removed the marker macros to deal with 2 pointers in interleaved fashion.
+ They were messy and the performance improvement seemed minimal. We'll
+ leave such scheduling issues to the compiler.
+ - Changed Linux/PowerPC test to also check for __powerpc__ in response
+ to a discussion on the gcc mailing list.
+ - On Matthew Flatt's suggestion removed the "static" from the jmp_buf
+ declaration in GC_generic_push_regs. This was causing problems in
+ systems that register all of their own roots. It looks far more correct
+ to me without the "static" anyway.
+ - Fixed several problems with thread local allocation of pointerfree or
+ typed objects. The collector was reclaiming thread-local free lists, since
+ it wasn't following the link fields.
+ - There was apparently a long-standing race condition related to multithreaded
+ incremental collection. A collection could be started and a thread stopped
+ between the memory unprotect system call and the setting of the
+ corresponding dirt bit. I believe this did not affect Solaris or PCR, which
+ use a different dirty-bit implementation. Fixed this by installing
+ signal handlers with sigaction instead of signal, and disabling the thread
+ suspend signal while in the write-protect handler. (It is unclear
+ whether this scenario ever actually occurred. I found it while tracking
+ down the following:)
+ - Incremental collection did not cooperate correctly with the PARALLEL_MARK
+ implementation of GC_malloc_many or the local_malloc primitves. It still
+ doesn't work well, but it shouldn't lose memory anymore.
+ - Integrated some changes from the gcc source tree that I had previously
+ missed. (Thanks to Bryce McKinley for the reminder/diff.)
+ - Added Makefile.direct as a copy of the default Makefile, which would
+ normally be overwritten if configure is run.
+ - Changed the gc.tar target in Makefile.direct to embed the version number
+ in the gc directory name. This will affect future tar file distributions.
+ - Changed the Irix dynamic library finding code to no longer try to
+ eliminate writable text segments under Irix6.x, since that is probably no
+ longer necessary, and can apparently be unsafe on occasion. (Thanks to
+ Shiro Kawai for pointing this out.)
+ - GC_cleanup with GC_DEBUG enabled passed a real object base address to
+ GC_debug_register_finalizer_ignore_self, which expected a pointer past the
+ debug header. Call GC_register_finalizer_ignore_self instead, even with
+ debugging enabled. (Thanks to Jean-Daniel Fekete for catching this.)
+ - The collector didn't build with call chain saving enabled but NARGS=0.
+ (Thanks to Maarten Thibaut.)
+ - Fixed up the GNU-style build files enough so that they work in some
+ obvious cases.
+ - Added initial port to Digital Mars compiler for win32. (Thanks to Walter
+ Bright.)
+
+Since 6.0alpha8:
+ - added README.macros.
+ - Made gc.mak a symbolic link to work around winzip's tendency to ignore
+ hard links.
+ - Simplified the setting of NEED_FIND_LIMIT in os_dep.c, possibly breaking
+ it on untested platforms.
+ - Integrated initial GNU HURD port. (Thanks to Chris Lingard and Igor
+ Khavkine.)
+ - A few more fixes for Digital Mars compiler (Walter Bright).
+ - Fixed gcc version recognition. Renamed OPERATOR_NEW_ARRAY to
+ GC_OPERATOR_NEW_ARRAY. Changed GC_OPERATOR_NEW_ARRAY to be the default.
+ It can be overridden with -DGC_NO_OPERATOR_NEW_ARRAY. (Thanks to
+ Cesar Eduardo Barros.)
+ - Changed the byte size to free-list mapping in thread local allocation
+ so that size 0 allocations are handled correctly.
+ - Fixed Linux/MIPS stackbottom for new toolchain. (Thanks to Ryan Murray.)
+ - Changed finalization registration to invoke GC_oom_fn when it runs out
+ of memory.
+ - Removed lvalue cast in finalize.c. This caused some debug configurations
+ not to build with some non-gcc compilers.
+
+Since 6.0alpha9:
+ - Two more bug fixes for KEEP_BACK_PTRS and DBG_HDRS_ALL.
+ - Fixed a stack clearing problem that resulted in SIGILL with a
+ misaligned stack pointer for multithreaded SPARC builds.
+ - Integrated another HURD patch (thanks to Igor Khavkine).
+
+Since 6.0:
+ - Non-debug, atomic allocations could result in bogus smashed object
+ reports with debugging on. (Thanks to Patrick Doyle for the small
+ test case.)
+ - Fixed GC_get_register_stack_base (Itanium only) to work around a glibc
+ 2.2.4 bug.
+ - Initial port to HP/UX on Itanium. Thread support and both 32 and 64
+ bit ABIs appear to work. Parallel mark support doesn't yet, due to
+ some inline assembly code issues. Thread local allocation does appear
+ to work.
+ - ifdef'ed out glibc2.1/Itanium workaround. I suspect nobody is using
+ that combination anymore.
+ - Added a patch to make new_gc_alloc.h usable with gcc3.0. (Thanks to
+ Dimitris Vyzovitis for the patch.)
+ - Debugged 64-bit support on HP/UX PA-RISC.
+ - Turned on dynamic loading support for FreeBSD/ELF. (Thanks to Peter
+ Housel.)
+ - Unregistering of finalizers with debugging allocation was broken.
+ (Thanks to Jani Kajala for the test case.)
+ - Old finalizers were not returned correctly from GC_debug_register_finalizer.
+ - Disabled MPROTECT_VDB for Linux/M68K based on a report that it doesn't work.
+ - Cleaned up some statistics gathering code in reclaim.c (Thanks to Walter
+ Bright.)
+ - Added some support for OpenBSD/ELF/Linux. (Thanks to Suzuki Toshiya.)
+ - Added Jakub Jelinek's patch to use dl_iterate_phdr for dynamic library
+ traversal to dyn_load.c. Changed it to weakly reference dl_iterate_phdr,
+ so that the old code is stilll used with old versions of glibc.
+ - Cleaned up feature test macros for various threads packages and
+ integrated (partially functional) FreeBSD threads code from Loren Rittle.
+ It's likely that the cleanup broke something, since it touched lots of
+ code. It's also likelly that it fixed some unreported bugs in the
+ less common thread implementations, since some of the original code
+ didn't stand up to close scrutiny. Support for the next pthreads
+ implementation should be easier to add.
+
+Since 6.1alpha1:
+ - No longer wrap read by default in multithreaded applications. It was
+ pointed out on the libgcj list that this holds the allocation lock for
+ way too long if the read blocks. For now, reads into the heap are
+ broken with incremental collection. It's possible to turn this back on
+ if you make sure that read calls don't block (e.g. by calling select
+ first).
+ - Fix ifdef in Solaris_threads.h to refer to GC_SOLARIS_THREADS.
+ - Added check for environment variable GC_IGNORE_GCJ_INFO.
+ - Added printing of stop-the-world GC times if GC_PRINT_STATS environment
+ variable is set.
+ - The calloc definition in leak_detector.h was missing parentheses, and
+ realloc was missing a second argument to GC_REALLOC.
+ (Thanks to Elrond (elrond<at>samba-tng.org).)
+ - Added GC_PRINT_BACK_HEIGHT environment variable and associated
+ code, mostly in the new file backgraph.c. See doc/README.environment.
+ - Added -DUSE_GLOBAL_ALLOC to work around a Windows NT issue. (Thanks to
+ Jonathan Clark.)
+ - Integrated port to NEC EWS4800 (MIPS-based workstation, with somewhat
+ different address-space layout). This may help for other machines with
+ holes in the data segment. (Thanks to Hironori Sakamoto.)
+ - Changed the order in which GC_push_roots and friends push things onto
+ the mark stack. GC_push_all calls need to come first, since we can't
+ necessarily recovere if those overflow the mark stack. (Thanks to
+ Matthew Flatt for tracking down the problem.)
+ - Some minor cleanups to mostly support the Intel compiler on Linux/IA64.
+
+Since 6.1 alpha2:
+ - Minor cleanup on the gcconfig.h section for SPARC.
+ - Minor fix to support Intel compiler for I386/Linux. (Thanks to Sven
+ Hartrumpf.)
+ - Added SPARC V9 (64-bit) support. (Thanks to Jeff Sturm.)
+ - Restructured the way in which we determine whether or not to keep
+ call stacks for debug allocation. By default SAVE_CALL_COUNT is
+ now zero on all platforms. Added SAVE_CALL_NARGS parameters.
+ If possible, use execinfo.h to capture call stack. (This should
+ add support for a number of new platforms, though often at
+ considerable runtime expense.)
+ - Try to print symbolic information for call stacks. On Linux, we
+ do this with a combination of execinfo.h and running addr2line in
+ a separate process. This is both much more expensive and much more
+ useful. Amazingly, it seems to be fast enough for most purposes.
+ - Redefined strdup if -DREDIRECT_MALLOC is given.
+ - Changed incremental collector and MPROTECT_VDB implementation so that,
+ under favorable conditions, pointerfree objects are not protected.
+ Added GC_incremental_protection_needs() to determine ahead of time whether
+ pointerfree objects may be protected. Replaced GC_write_hint() with
+ GC_remove_protection().
+ - Added test for GC_ENABLE_INCREMENTAL environment variable.
+ - Made GC_time_limit runtime configurable. Added GC_PAUSE_TIME_TARGET
+ environment variable.
+ - Eliminated GC_page_sz, a duplicate of GC_page_size.
+ - Caused the Solaris and Irix thread creation primitives to call
+ GC_init_inner().
+
+Since 6.1alpha3:
+ - Fixed typo in sparc_mach_dep.S, preventing the 64-bit version from
+ building. Increased 64-bit heap size limit in test.c slightly, since
+ a functional SPARC collector seems to slightly exceed the old limits.
+ (Thanks again to Jeff Sturm.)
+ - Use NPRGREG in solaris_threads.c, thus printing all registers if things
+ go wrong.
+ - Added GC_MARKERS environment variable to allow use of a single marker
+ thread on an MP without confusing the lock implementation.
+ - Collect much less aggressively in incremental mode with GC_TIME_UNLIMITED.
+ This is really a purely generational mode, and we can afford to
+ postpone the collection until the heap is (nearly) full.
+ - Remove read() wrapper for MPROTECT_VDB. It was causing more harm than
+ good. It is often no longer needed if system calls avoid writing to
+ pointerfull heap objects.
+ - Fix MACOSX test in gcconfig.h. (Thanks to John Clements.)
+ - Change GC_test_and_set so that it consistently has one argument.
+ Add spaces to ::: in powerpc assembly code in gc_locks.h.
+ (Thanks to Ryan Murray.)
+ - Fixed a formatting error in dbg_mlc.c. Added prototype to GC_abort()
+ declaration. (Thanks to Michael Smith.)
+ - Removed "source" argument to GC_find_start(). Eliminate GC_FIND_START().
+ - Added win32 recognition code in configure.in. Changed some of the
+ dllimport/export defines in gc.h. (Thanks to Adam Megacz.)
+ - GC_malloc_many didn't set hb_last_reclaimed when it called
+ GC_reclaim_generic. (I'm not sure this matters much, but ...)
+ - Allocating uncollectable objects with debug information sometimes
+ allocated objects that were one byte too small, since uncollectable
+ objects don't have the extra byte added at the end. (Thanks to
+ Wink Saville for pointing this out.)
+ - Added a bit more assertion checking to make sure that gcj objects
+ on free lists never have a nonzero second word.
+ - Replaced BCC_MAKEFILE with an up-to-date one. (Thanks to
+ Andre Leiradella.)
+ - Upgraded libtool, cinfigure.in and some related files to hopefully
+ support NetBSD/SPARC. (Thanks to Adrian Bunk.) Unfortunately,
+ libtool 1.4.2 seemed to be buggy due to missing quotes in several
+ "test" invocations. Fixed those in the ltmain.sh script.
+ - Some win32-specific patches, including the introduction of
+ GC_CreateThread. (Thanks to Adam Megacz.)
+ - Merged in gcj changes from Anthony Green to support embedded systems.
+ - Tried to consistently rename preprocessed assembly files with a capital
+ .S extension.
+ - Use alpha_mach_dep.S on ALPHA again. It doesn't really matter, but this
+ makes our distribution consistent with the gcc one, avoiding future merge
+ problems.
+ - Move GET_MEM definition into gcconfig.h. Include gcconfig.h slightly
+ later in gc_priv.h to avoid forward references to ptr_t.
+ - Add some testing of local allocation to test.c.
+ - Change definition of INVALID_QTID in specific.h. The -1 value was used
+ inconsistently, and too likely to collide with a valid stack address.
+ Some general clean-up of specific.[ch]. Added assertions. (Thanks
+ to Michael Smith for tracking down an intermittent bug to this
+ general area. I'm not sure it has been squashed yet, however.)
+ - On Pthread systems it was not safe to call GC_malloc() between fork()
+ and exec(). According to the applicable standards, it doesn't appear
+ to be safe to call malloc() or many other libc functions either, thus
+ it's not clear this is fixable. Added experimental support for
+ -DHANDLE_FORK in linux_threads.c which tries to support it. It may
+ succeed if libc does the right thing. I'm not sure whether it does.
+ (Thanks to Kenneth Schalk for pointing out this issue.)
+ - Documented thread local allocation primitives to require an
+ explicit GC_init call. GC_init_parallel is no longer declared to
+ be a constructor function, since that isn't portable and often
+ seems to lead to initialization order problems.
+ - Changed gc_cpp.cc and gc_cpp.h in one more attempt to make them
+ compatible with Visual C++ 6. (Thanks to Wink Saville for the
+ patch.)
+ - Some more patches for Linux on HP PA-RISC.
+ - Added include/gc_allocator.h. It implements (hopefully) standard
+ conforming (as opposed to SGI-style) allocators that allocate
+ collectable (gc_allocator) or GC-traceable, but not collectable
+ (traceable_allocator) objects. This borrows heavily from libstc++,
+ which borrows heavily from the SGI implementation, this part of
+ which was written by Matt Austern. Changed test_cpp.cc to very
+ minimally test this.
+ - On Linux/X86, retry mmap with a different start argument. That should
+ allow the collector to use more (closer to 3GB) of the address space.
+ (Thanks to Jeffrey Mark Siskind for tracking this down.)
+ - Force 64 bit alignment with GCJ support. (Reflects Bryce McKinley's
+ patch to the gcc tree.)
+ - Refined the choice of sa_handler vs. sa_sigaction in GC_dirty_init
+ to accomodate some glibc5 systems. (Thanks to Dan Fandrich for the
+ patch.)
+ - Compensated for the fact that current versions of glibc set
+ __libc_stack_end incorrectly on Linux/IA64 while initialization code
+ is running. This could cause the collector to miss 16 bytes of
+ the memory stack if GC_malloc or friends where called before main().
+ - Mostly integrated Takis Psarogiannakopoulos' port to DG/UX Inix 86.
+ This will probably take another iteration to work, since his
+ patch conflicted with the libtool upgrade.
+ - Added README.arm.cross containing some information about cross-
+ compiling to an ARM processor from Margaret Fleck.
+
+Since 6.1alpha4:
+ - Added GC_finalizer_mem_freed, and changed some of the code that
+ decided on heap expansion to look at it. Memory explicitly
+ deallocated by finalizers essentially needs to be counted as reclaimed
+ by the GC. Otherwise there are cases in which the heap can grow
+ unboundedly. (Thanks to Mark Reichert for the test case.)
+ - Integrated Adam Megacz patches to not scan dynamic libraries if
+ we are compiling with gcc on win32. Otherwise we need structured
+ exception handling to deal with asynchronously unmapped root
+ segments, and gcc doesn't directly support that.
+ - Integrated Anthony Green's patch to support Wine.
+ - GC_OPERATOR_NEW_ARRAY was misspelled OPERATOR_NEW_ARRAY in several
+ places, including gc_cpp.cc. (Thanks to Wink Saville for pointing
+ this out.)
+ - Integrated Loren James Rittle's Alpha FreeBSD patches. In
+ response to Richard Henderson's suggestion, these also
+ changed the declarations of symbols like _end on many platforms to
+ that they wouldn't mistakenly be declared as short data symbols.
+ - Integrated changes from the Debian distribution. (Thanks to Ryan Murray
+ for pointing these out.) Fix C++ comments in POWERPC port. Add ARM32
+ incremental GC support. Get rid of USE_GENERIC_PUSH_REGS for alpha/Linux,
+ this time for real. Use va_copy to get rid of cord printf problems
+ (finally).
+ - Close file descriptor used to count cpus. Thanks to Jeff Sturm for
+ pointing out the omission.
+ - Don't just drop gcj free lists in GC_start_reclaim, since that can
+ eventually cause the marker to see a bogus mark descriptor in the
+ dropped objects. The usual symptom was a very intermittent segmentation
+ fault in the marker. This mattered only if one of the GC_gcj_malloc
+ variants was used. (Thanks to Michael Smith, Jeff Sturm, Bryce
+ McKinley and Tom Tromey for helping to track this down.)
+ - Fixed Linux and Solaris/64 SPARC configuration. (Thanks to David Miller,
+ Jeff Sturm, Tom Tromey, and Christian Joensson.)
+ - Fixed a typo in strdup definition. (Thanks to Gerard A Allan.)
+ - Changed Makefile.direct to invoke $(CC) to assemble alpha_mach_dep.S.
+ This is needed on Linux. I'm not sure whether it's better or worse
+ on Tru64.
+ - Changed gc_cpp.h once more to declare operator new and friends only in
+ a Microsoft environment. This may need further fine tuning. (Thanks to
+ Johannes Schmidt for pointing out that the older code breaks on gcc3.0.4.)
+ - Don't ever override strdup if it's already macro defined. (Thanks to
+ Adnan Ali for pointing out the problem.)
+ - Changed gc_cpp.h yet again to also overload placement new. Due to the
+ C++ overloading rules, the other overloaded new operations otherwise hide
+ placement new, which causes many STL uses to break. (Thanks to Reza
+ Shahidi for reporting this, and to Matt Austern for proposing a fix.)
+ - Integrated cygwin pthreads support from Dan Bonachea.
+ - Turn on DYNAMIC_LOADING for NetBSD. (Thanks to Krister Walfridsson.)
+ - Changed printing code to print more complete GC times.
+ - Applied Mark Mitchell's Irix patch to correct some bitrot.
+ - Clarified which object-printing routines in dbg_mlc.c should hold
+ the allocation lock. Restructured the code to allow reasonable object
+ printing with -DREDIRECT_MALLOC.
+ - Fix the Linux mmap code to always start with 0x1000 as the initial hint.
+ Minor patches for 64-bit AIX, particularly to STACKBOTTOM.
+ (Thanks again to Jeffrey Mark Siskind.)
+ - Renamed "SUSPENDED" flag for Solaris threads support to avoid a conflict
+ with a system header. (Thanks to Philp Brown.)
+ - Cause win32_threads.c to handle an out of range stack pointer correctly,
+ though currently with a warning. (Thanks to Jonathan Clark for
+ observing that win32 applications may temporarily use the stack
+ pointer for other purposes, and suggesting a fix. Unfortunately, it's
+ not clear that there is a complete solution to this problem.)
+
+Since 6.1alpha5:
+ - Added GC_MAXIMUM_HEAP_SIZE environment variable.
+ - Fix configure.in for MIPS/LINUX. (Thanks to H.J. Lu.)
+ - Double page hash table size for -DLARGE_CONFIG.
+ - Integrated Bo Thorsen's X86-64 support.
+ - STACKBOTTOM definition for LINUX/MIPS was partially changed back.
+ (Thanks to H.J. Lu and Hiroshi Kawashima for resolving this.)
+ - Replaced all occurrences of LINUX_DATA_START in gcconfig.h with
+ SEARCH_FOR_DATA_START. It doesn't hurt to falll back to a search.
+ And __data_start doesn't seem to get defined correctly of the GC
+ library is loaded with LD_PRELOAD, e.g. for leak detection.
+ - If the GC_find_leak environment variable is set, do a
+ atexit(GC_gcollect) to give us at least one chance to detect leaks.
+ This may report some very benign leaks, but ...
+ - Addeded REDIRECT_FREE. It's necessary if we want leak detection with
+ LD_PRELOAD.
+ - Defer printing of leaked objects, as for smashed objects.
+ - Fixed process and descriptor leak in GC_print_callers. Try for
+ line number even if we got function name.)
+ - Ported parallel GC support and thread local allocation to Alpha.
+ Not yet well-tested.
+ - Added GC_DUMP_REGULARLY and added finalization statistics to GC_dump().
+ - Fixed Makefile.am to mention alpha_mach_dep.S instead of the defunct
+ alpha_mach_dep.s. (Thanks to Fergus Henderson.)
+ - Incorporated a change to new_gc_alloc.h, suggested by Johannes Schmidt,
+ which should make it work with gcc3.1. (I would still like to encourage
+ use of gc_allocator.h instead.)
+ - Use alpha_mach_dep.S only on Linux. (It's not clear that this is
+ optimal, but it otherwise didn't build on Tru64. Thanks to Fergus
+ Henderson.)
+ - Added ifdef to guard free() in os_dep.c. Otherwise we get a
+ compilation error on Irix. (Thanks to Dai Sato.)
+ - Added an experimental version of GC_memalign to mallocx.c. This can't
+ always work, since we don't handle alignment requests in the hblk-level
+ allocator, and we can't handle arbitrary pointer displacements unless
+ GC_all_interior_pointers is enabled. But it should work for alignment
+ requests up to HBLKSIZE. This is not yet documented in the standard
+ places.
+ - Finally debugged the OSF1/Tru64 thread support. This needs more testing,
+ since I needed to add a somewhat unconvincing workaround for signal
+ delivery issues that I don't yet completely understand. But it does
+ pass my tests, even in parallel GC mode. Incremental GC support is
+ disabled if thread support is enabled, due to the signal issues.
+ - Eliminated name-space-incorrect definition of _cdecl from gc_cpp.h.
+ - Added GC_debug_malloc_replacement and GC_debug_realloc_replacement
+ declarations to gc.h. On IA64, this is required for REDIRECT_MALLOC
+ to work correctly with these.
+ - Fixed Linux USE_PROC_FOR_LIBRARIES to work with a 64-bit /proc format.
+
+Since 6.1:
+ - Guard the test for GC_DUMP_REGULARLY in misc.c with
+ "#ifndef NO_DEBUGGING". Otherwise it fails to build with NO_DEBUGGING
+ defined. (Thanks to Manuel Serrano.)
+ - Message about retrying suspend signals was incorrectly generated even when
+ flag was not set.
+ - Cleaned up MACOSX/NEXT root registration code. There was apparently a
+ separate ifdef case in GC_register_data_segments() for no reason.
+ - Removed MPROTECT_VDB for MACOSX port, based on one negative report.
+ - Arrange for gc.h and friends to be correctly installed with GNU-style
+ "make install".
+ - Enable the GNU-style build facility include C++ support in the library
+ with --enable-cplusplus. (Thanks to Thomas Maier for some of the patch.)
+ - Mark from GC_thread_key in linux_threads.c, in case that's allocated
+ from the garbage collected heap, as it is with our own thread-specific
+ storage implementation. (Thanks to Jeff Sturm.)
+ - Mark all free list header blocks if they are heap allocated. This avoids
+ some unnecessary tracing. And it remains correct if we clear the
+ root set. (Thanks to Jeff Sturm for identifying the bug.)
+ - Improved S390/Linux support. Add S390/Linux 64-bit support. (Thanks
+ to Ulrich Weigand.)
+ - Corrected the spelling of GC_{M,C}ALLOC_EXPLICTLY_TYPED to
+ GC_{M,C}ALLOC_EXPLICITLY_TYPED in gc_typed.h. This is technically
+ an interface change. Based on the fact that nobody reported this,
+ I suspect/hope there were no clients.
+ - Cleaned up gc_typed.h so that (1) it adds an extern "C" declaration
+ when appropriate, (2) doesn't generate references to undefined internal
+ macros, and (3) allows easier manual construction of descriptors.
+ - Close the file descriptor used by GC_print_address_map().
+ - Set the "close-on-exec" bit for various file descriptors maintained
+ for the collector's internal use.
+ - Added a hack to find memory segments owned by the system allocator
+ under win32. Based on my tests, this tends to eventually find all
+ segments, though it may take a while. There appear to be cleaner,
+ but slower solutions under NT/XP. But they rely on an API that's
+ unsupported under 9X.
+ - Changed Linux PowerPC stack finding to LINUX_STACKBOTTOM. (Thanks
+ to Akira Tagoh for pointing out that HEURISTIC1 doesn't work on
+ 64-bit kernels.)
+ - Added GC_set_free_space_divisor to avoid some Windows dll issues.
+ - Added FIXUP_POINTER, POINTER_SHIFT, POINTER_MASK to allow preprocessing
+ of candidate pointers for tagging, etc.
+ - Always lock around GC_notify_full_gc(). Simplified code for
+ invoking GC_notify_full_gc().
+ - Changed the way DATASTART is defined on FreeBSD to be robust against
+ an unmapped page after etext. (Thanks to Hironori Sakamoto for
+ tracking down the intermittent failure.)
+ - Made GC_enable() and GC_disable() official. Deprecated direct update
+ of GC_dont_gc. Changed GC_gcollect to be a noop when garbage collection
+ is disabled.
+ - Call GC_register_dynamic_libraries before stopping the world on Linux,
+ in order to avoid a potential deadlock due to the dl_iterate_phdr lock.
+ - Introduced a more general mechanism for platform-dependent code to
+ decide whether the main data segment should be handled separately
+ from dynamic libraries, or registered by GC_register_dynamic_libraries.
+ The latter is more reliable and easier on Linux with dl_iterate_phdr.
+
+Since 6.2alpha1:
+ - Fixed the completely broken FreeBSD code in 6.2alpha1. (Thanks to
+ Hironori Sakamoto for the patch.)
+ - Changed IRIX reference in dbg_mlc.c to IRIX5. (Thanks to Marcus Herbert.)
+ - Attempted to work around the problems with .S filenames and the SGI
+ compiler. (Reported by several people. Untested.)
+ - Worked around an HP/UX make issue with the GNU-style build process.
+ - Fixed the --enable-cplusplus build machinery to allow builds without
+ a C++ compiler. (That was always the intent ...)
+ - Changed the debugging allocation macros to explicitly pass the return
+ address for Linux and XXXBSD on hardware for which we can't get stack
+ traces. Use __builtin_return_address(0) to generate it when possible.
+ Some of the configuration work was cleaned up (good) and moved to gc.h
+ (bad, but necessary). This should make leak detection more useful
+ on a number of platforms. (Thanks to Fabian Thylman for the suggestion.)
+ - Fixed compilation problems in dbg_mlc.c with GC_ADD_CALLER.
+ - Bumped revision number for dynamic library.
+
+Since 6.2alpha2:
+ - Don't include execinfo.h in os_dep.c when it's not needed, and may not exist.
+
+Since 6.2alpha3:
+ - Use LINUX_STACKBOTTOM for >= glibc2.2 on Linux/MIPS. (See Debian bug
+ # 177204)
+ - Integrated Jeff Sturm and Jesse Rosenstock's MACOSX threads patches.
+ - Integrated Grzegorz Jakacki's substantial GNU build patch. "Make dist"
+ should now work for the GNU build process. Documentation files
+ are installed under share/gc.
+ - Tweaked gc_cpp.h to again support the Borland compiler. (Thanks to
+ Rene Girard for pointing out the problems.)
+ - Updated BCC_MAKEFILE (thanks to Rene Girard).
+ - Added GC_ASSERT check for minimum thread stack size.
+ - Added --enable-gc-assertions.
+ - Added some web documentation to the distribution. Updated it in the
+ process.
+ - Separate gc_conf_macros.h from gc.h.
+ - Added generic GC_THREADS client-defined macro to set the appropriate
+ GC_XXX_THREADS internal macro. (gc_config_macros.h.)
+ - Add debugging versions of _ignore_off_page allocation primitves.
+ - Moved declarations of GC_make_closure and GC_debug_invoke_finalizer
+ from gc.h to gc_priv.h.
+ - Reset GC_fail_count even if only a small allocation succeeds.
+ - Integrated Brian Alliet's patch for dynamic library support on Darwin.
+ - gc_cpp.h's gc_cleanup destructor called GC_REGISTER_FINALIZER_IGNORE_SELF
+ when it should have called the lower case version, since it was
+ explicitly computing a base pointer.
+
+Since 6.2alpha4:
+ - GC_invoke_finalizers could, under rare conditions, set
+ GC_finalizer_mem_freed to an essentially random value. This could
+ possibly cause unbounded heap growth for long-running applications
+ under some conditions. (The bug was introduced in 6.1alpha5, and
+ is not in gcc3.3. Thanks to Ben Hutchings for finding it.)
+ - Attempted to sanitize the various DLL macros. GC_USE_DLL disappeared.
+ GC_DLL is used instead. All internal tests are now on GC_DLL.
+ README.macros is now more precise about the intended meaning.
+ - Include DllMain in the multithreaded win32 version only if the
+ collector is actually built as a dll. (Thanks to Mohan Embar for
+ a version of the patch.)
+ - Hide the cygwin threadAttach/Detach functions. They were violating our
+ namespace rules.
+ - Fixed an assertion in GC_check_heap_proc. Added GC_STATIC_ASSERT.
+ (Thanks again to Ben Hutchings.)
+ - Removed some obsolete definitions for Linux/PowerPC in gcconfig.h.
+ - CORD_cat was not rebalancing unbalanced trees in some cases, violating
+ a CORD invariant. Also tweaked the rebalancing rule for
+ CORD_cat_char_star. (Thanks to Alexandr Petrosian for the bug report
+ and patch.)
+ - Added hand-coded structured exception handling support to mark.c.
+ This should enable support of dynamic libraries under win32 with
+ gcc-compiled code. (Thanks to Ranjit Mathew for the patch.)
+ Turned on dynamic library scanning for win32/gcc.
+ - Removed some remnants of read wrapping. (Thanks to Kenneth Schalk.)
+ GC_USE_LD_WRAP ws probably broken in recent versions.
+ - The build could fail on some platforms since gcconfig.h could include
+ declarations mentioning ptr_t, which was not defined, e.g. when if_mach
+ was built. (Thanks to Yann Dirson for pointing this out.) Also
+ cleaned up tests for GC_PRIVATE_H in gcconfig.h a bit.
+ - The GC_LOOP_ON_ABORT environment variable interfered with incremental
+ collection, since the write fault handler was erroneously overridden.
+ Handlers are now set up in the correct order.
+ - It used to be possible to call GC_mark_thread_local_free_lists() while
+ the world was not stopped during an incremental GC. This was not safe.
+ Fortunately, it was also unnecessary. Added GC_world_stopped flag
+ to avoid it. (This caused occasional crashes in GC_set_fl_marks
+ with thread local allocation and incremental GC. This probably happened
+ primarily on old, slow multiprocessors.)
+ - Allowed overriding of MAX_THREADS in win32_threads.c from the build
+ command line. (Patch from Yannis Bres.)
+ - Taught the IA64/linux code to determine the register backing store base from
+ /proc/self/maps after checking the __libc symbol, but before guessing.
+ (__libc symbols are on the endangered list, and the guess is likely to not
+ always be right for 2.6 kernels.) Restructured the code to read and parse
+ /proc/self/maps so it only exists in one place (all platforms).
+ - The -DUSE_PROC_FOR_LIBRARIES code was broken on Linux. It claimed that it
+ also registered the main data segment, but didn't actually do so. (I don't
+ think anyone actually uses this configuration, but ...)
+ - Made another attempt to get --enablecplusplus to do the right thing.
+ Since there are unavoidable problems with C programs linking against a
+ dynamic library that includes C++ code, I separated out the c++ code into
+ libgccpp.
+
+Since 6.2alpha5:
+ - There was an extra underscore in the name of GC_save_registers_in_stack
+ for NetBSD/SPARC. (Thanks to Jaap Boender for the patch.)
+ - Integrated Brian Alliet's patch for Darwin. This restructured the
+ linuxthreads/pthreads support to separate generic pthreads support
+ from more the system-dependent thread-stopping code. I believe this
+ should make it easier to eliminate the code duplication between
+ pthreads platforms in the future. The patch included some other
+ code cleanups.
+ - Integrated Dan Bonachea's patch to support AIX threads. This required
+ substantial manual integration, mostly due to conflicts with other
+ recent threads changes. It may take another iteration to
+ get it to work.
+ - Removed HPUX/PA-RISC support from aix_irix_threads.c. It wasn't used
+ anyway and it cluttered up the code. And anything we can do to migrate
+ towards generic pthreads support is a good thing.
+ - Added a more explicit test for tracing of function arguments to test.c.
+ (Thanks to Dan Grayson.)
+ - Added Akira Tagoh's PowerPC64 patch.
+ - Fixed some bit rot in the Cygwin port. (Thanks to Dan Bonachea for
+ pointing it out.) Gc.h now includes just windows.h, not winbase.h.
+ - Declared GC_save_regs_in_stack() in gc_priv.h. Remove other declarations.
+ - Changed --enable-cplusplus to use automake consitionals. The old way
+ confused libtool. "Make install" didn't work correctly for the old version.
+ Previously --enable-cplusplus was broken on cygwin.
+ - Changed the C version of GC_push_regs to fail at compile time if it is
+ generated with an empty body. This seems to have been the cause of one
+ or two subtle failures on unusual platforms. Those failures should
+ now occur at build time and be easily fixable.
+
+Since 6.2alpha6:
+ - Integrated a second round of Irix/AIX patches from Dan Bonachea.
+ Renamed mips_sgi_mach_dep.S back to mips_sgi_mach_dep.s, since it requires
+ the Irix assembler to do the C preprocessing; gcc -E doesn't work.
+ - Fixed Makefile.direct for DARWIN. (Thanks to Manuel Serrano.)
+ - There was a race between GC_pthread_detach and thread exit that could
+ result in a thread structure being deallocated by GC_pthread_detach
+ eventhough it was still needed by the thread exit code. (Thanks to
+ Dick Porter for the small test case that allowed this to be debugged.)
+ - Fixed version parsing for non-alpha versions in acinclude.m4 and
+ version checking in version.h.
+
+Since 6.2:
+ - Integrated some NetBSD patches forwarded to me by Marc Recht. These
+ were already in the NetBSD package.
+ - GC_pthread_create waited for the semaphore even if pthread_create failed.
+ Thanks to Dick Porter for the pthread_support.c patch. Applied the
+ analogous fix for aix_irix_threads.c.
+ - Added Rainer Orth's Tru64 fixes.
+ - The check for exceeding the thread table size in win32 threadDetach
+ was incorrect. (Thanks to Alexandr Petrosian for the patch.)
+ - Applied Andrew Begel's patch to correct some reentrancy issues
+ with dynamic loading on Darwin.
+ - GC_CreateThread() was neglecting to duplicate the thread handle in
+ the table. (Thanks to Tum Nguyen for the patch.)
+ - Pass +ESdbgasm only on PA-RISC machines with vendor compiler.
+ (Thanks to Roger Sayle for the patch.)
+ - Applied more AIX threads patches from Scott Ananian.
+
+Since 6.3alpha1:
+ - Reenabled I_HOLD_LOCK assertion in aix_irix_threads.h.
+ - Put back the WINABI qualifier for GC_CreateThread. (Thanks to
+ Danny Smith for the patch. 6.3alpha1 had the qualifier in one place
+ but not elsewhere, which was clearly wrong.)
+ - Sometimes explicitly define __private_extern__ before DARWIN dyld.h
+ include. (Thanks to Andreas Tobker for postting the patch.)
+ - Included signal.h from pthread_support.c. Removed GC_looping_handler,
+ which was dead code.
+ - GC_find_start was misdeclared by gc_pmark.h if PRINT_BLACK_LIST was
+ defined. (Thanks to Glauco Masotti for testing and reporting this.)
+ Changed GC_find_start to never just return 0. According to its
+ comment it doesn't, and it's unclear that's correct.
+ - GC_alloc_large had several largely compensating bugs in the
+ computation of GC_words_wasted. (It was confused about bytes vs.
+ words in two places.)
+ - Integrated Slava Sysoltev's patch to support more recent versions of
+ the Intel compiler on IA64/Linux.
+ - Changed win32 spinlock initialization to conditionally set a spin count.
+ (Emmanual Stumpf pointed out that enabling this makes a large performance
+ difference on win32 multiprocessors.) Also cleaned up the win32 spinlock
+ initialization code a bit.
+ - Fixed thread support for HP/UX/IA64. The register backing store base for
+ the main thread was sometimes not set correctly. (Thanks to Laurent
+ Morichetti.)
+ - Added -DEMPTY_GETENV_RESULTS flag to work around Wine problem.
+ - Declare GC_stack_alloc and GC_stack_free in solaris_threads.h to
+ avoid 64-bit size mismatches. (Thanks to Bernie Solomon.)
+ - Fixed GC_generic_push_regs to avoid a potential and very unfortunate
+ tail call optimization. This could lead to prematurely reclaimed
+ objects on configurations that used the generic routine and the new
+ build infrastructure (which potentially optimizes mach_dep.c).
+ This was a serious bug, but it's unclear whether it has resulted in
+ any real failures.
+ - Fixed CORD_str to deal with signed characters. (Thanks to Alexandr
+ Petrosian for noticing the problem and supplying the patch.)
+ - Merged a couple of NOSYS/ECOS tests into os_dep.c from gcj. (Thanks
+ to Anthony Green.)
+ - Partially merged a win32 patch from Ben Hutchings, and substantially
+ revised other parts of win32_threads.c. It had several problems.
+ Under MinGW with a statically linked library, the main thread was
+ not registered. Cygwin detached threads leaked thread descriptors.
+ There were several race conditions. For now, unfortunately the
+ static threads limit remains, though we increased it, and made table
+ traversal cost depend on the actual thread count.
+ There is also still some code duplication with pthread_support.c.
+ (Thread descriptors did become much smaller, since Ben Hutchings
+ removed the thread context from them.)
+ - Integrated a Solaris configure.in patch from Rainer Orth.
+ - Added GC_IGNORE_FB and associated warning to very partially address
+ the issue of the collector treating a mapped frame buffer as part
+ of the root set. (Thanks to David Peroutka for providing some
+ insight. More would be helpful. Is there anything that can be used
+ to at least partially identify such memory segments?)
+
+Since 6.3alpha2:
+ - Removed -DSMALL_CONFIG from BCC_MAKEFILE.
+ - Changed macros to test for an ARM processor (Patch from Richard Earnshaw.)
+ - Mostly applied a DJGPP patch from Doug Kaufman. Especially Makefile.dj
+ had suffered from serious bit rot.
+ - Rewrote GC_apply_to_maps, eliminating an off-by-one subscript error,
+ and a call to alloca (for lcc compatibility).
+ - Changed USE_MUNMAP behavior on posixy platforms to immediately remap
+ the memory with PROT_NONE instead of unmapping it. The latter risks
+ an intervening mmap grabbing the address space out from underneath us.
+ Updated this code to reflect a cleaner patch from Ulrich Drepper.
+ - Replaced _T with _Tp in new_gc_alloc.h to avoid a MACOS X conflict.
+ (Patch from Andrew Begel.)
+ - Dynamically choose whether or not lock should spin on win32. (Thanks
+ to Maurizio Vairani for the patch.) This may be a significant performance
+ improvement for win32.
+ - Fix Makefile.direct to actually include NT_STATIC_THREADS_MAKEFILE
+ in the distribution. (Again thanks to Maurizio Vairani.)
+ - Maybe_install_looping_handler() was accidentally exported, violating
+ our name space convention.
+ - Made os_dep.c use sigsetjmp and SA_NODEFER for NetBSD. (Thanks to
+ Christian Limpach.) (I generalized the patch to use sigsetjmp on all
+ UNIX_LIKE platforms, admittedly a slightly risky move. But it may avoid
+ similar problems on some other platforms. I also cleaned up the defn
+ of UNIX_LIKE a bit. - Hans)
+ - Integrated Andrew Begel's Darwin threads patch, adjusted according to
+ some of Fergus Hendersons's comments. (Patch didn't apply cleanly,
+ errors are possible.)
+ - Added another test or two for the Intel 8.0 compiler to avoid
+ confusing it with gcc. The single-threaded collector should now build
+ with icc, at least on ia64.
+
+Since 6.3alpha3:
+ - USE_MMAP was broken by confusion in the code dealing with USE_MMAP_ANON.
+ (This was pointed out, and fixes were suggested by several other people.)
+ - Darwin supprt was broken in alpha3 as a result of my misintegration of
+ Andrew Begel's patches. Fixed with another patch from Andrew Begel.
+ - A new sanity check in pthread_stop_world.c:GC_push_all_stacks() was
+ overly aggressive. We may collect from an unregistered thread during
+ thread creation. Fixed by explicitly checking for that case. (Added
+ GC_in_thread_creation.)
+
+Since 6.3alpha4:
+ - Fix & vs && typo in GC_generic_malloc and
+ GC_generic_malloc_ignore_off_page. (Propagated from the gcc tree.)
+ - Removed SA_NODEFER hack from NetBSD and Solaris write-protect handler.
+ (According to Christian Limpach, the NetBSD problem is fixed.
+ Presumably so is the Solaris 2.3 problem.)
+ - Removed placement delete from gc_cpp.h for the SGI compiler.
+ (Thanks to Simon Gornall for the patch.)
+ - Changed semantics of the GC_IGNORE_FB environment variable, based
+ on experimentation by Nicolas Cannasse pointing out that the old
+ interpretation was useless. We still need help in identifying win32
+ graphics memory mappings. The current "solution" is a hack.
+ - Removed "MAKEOVERRIDES =" from Makefile.am and thus Makefile.in.
+ It probably made more sense in the gcc context.
+ - Explicitly ensure that NEED_FIND_LIMIT is defined for {Open,Net}BSD/ELF.
+ - Replaced USE_HPUX_TLS macro by USE_COMPILER_TLS, since gcc often
+ supports the same extension on various platforms.
+ - Added some basic (completely untested) defines for win64, in support
+ of future work.
+ - Declared GC_jmp_buf in os_dep.s as JMP_BUF instead of jmp_buf, fixing
+ a memory overwrite bug on Solaris and perhaps other platforms.
+ - Added 0 != __libc_stack_end test to GC_linux_stack_base. (Thanks to Jakub
+ Jelinek, both for the patch, and for explaining the problem to me.)
+ Otherwise "prelink"ing could cause the collector to fail.
+ - Changed default thread local storage implementation to USE_PTHREAD_SPECIFIC
+ for HP/UX with gcc. The compiler-based implementation appears to work
+ only with the vendor compiler.
+ - Export GC_debug_header_size and GC_USR_PTR_FROM_BASE from gc_mark.h,
+ making client mark code cleaner and less dependent on GC version.
+ - Export several new procedures and GC_generic_malloc from gc_mark.h
+ to support user-defined kinds. Use the new procedures to replace existing
+ code in gcj_mlc.c and typd_mlc.c.
+ - Added support for GC_BACKTRACES.
+ - Fixed a remaining problem in CORD_str with signed characters. (Thanks
+ to Alexandr Petrosian for the patch.)
+ - Removed supposedly redundant, but very buggy, definitions of finalizer
+ macros from javaxfc.h. Fortunately this file probably has no users.
+ The correct declarations were already in gc.h.
+ - Also need to set GC_in_thread_creation while waiting for GC during
+ thread termination, since it is also possible to collect from an
+ unregistered thread in that case.
+ - Define NO_GETENV for Windows CE, since getenv doesn't appear to exist.
+ + some other minor WinCE fixes. (Thanks to Alain Novak.)
+ - Added GC_register_describe_type_fn.
+ - Arrange for debugging finalizer registration to ignore non-heap
+ registrations, since the regular version of the routine also behaves
+ that way.
+ - GC_gcj_malloc and friends need to check for finalizers waiting to be run.
+ One of the more obscure allocation routines with missing a LOCK() call.
+ - Fixed cvtres invocations in NT_MAKEFILE and NT_STATIC_THREADS_MAKEFILE
+ to work with VS.NET.
+ - Cleaned up GC_INIT calls in test. Updated gc.man to encourage GC_INIT
+ use in portable code.
+ - Taught the GC to use libunwind if --enable-full-debug is specified on
+ IA64 and libunwind is present.
+ - The USE_MUNMAP code could get confused about the age of a block and
+ prematurely unmap it. GC_unmap_old had a bug related to wrapping of
+ GC_gc_no. GC_freehblk and GC_merge_unmapped didn't maintain
+ hb_last_reclaimed reasonably when blocks were merged. The code was
+ fixed to reflect original intent, but that may not always be an
+ improvement. See todo list item.
+
+Since 6.3alpha5:
+ - Define USE_GENERIC_PUSH_REGS for NetBSD/M68K.
+ - Fixed the X86_64 PREFETCH macros to correctly handle ia32e (which uses
+ different prefetch instructions from AMD64). (Thanks to H.J. Lu.)
+ - GC_config_macros.h did not correctly define GC_WIN32_THREADS from
+ GC_THREADS.
+ - Added simple_example.html.
+ - Merged Andrew Gray's patch to correctly restore signal handlers on
+ FreeBSD.
+ - Merged a patch from Andreas Jaeger to deal with prefetch-related warnings
+ on x86-64. Added some other casts so that the PREFETCH macros
+ always get a ptr_t argument. Removed some casts inthe PREFETCH
+ implementations.
+ - At Jesse Jones suggestion: Added a header guard for gc_allocator.h
+ and changed GC_debug_free to clobber contents of deallocated object.
+ - The signal masking code in pthread_stop_world.c contained some errors.
+ In particular SIGSEGV was masked in the handler, in spite of the fact that
+ it wrote to the heap. This could lead to an uncaught SIGSEGV, which
+ apparently became much more likely in Linux 2.6. Also fixed some
+ typos, and reduced code duplication in the same area.
+ - Remove ltconfig, clean up configure messages for DGUX (thanks to
+ Adrian Bunk for the patches).
+ - Integrated NetBSD/OpenBSD patches from Marc Recht and Matthias Drochner.
+
+Since 6.3alpha6:
+ - Compile test_cpp.cc with CXXCOMPILE instead of COMPILE.
+ - Very large allocations could cause a collector hang. Correct
+ calculation of GC_collect_at_heapsize.
+ - GC_print_hblkfreelist printed some bogus results if USE_MUNMAP
+ was defined.
+ - Include gc_config_macros.h in threadlibs.c.
+ - Correct MacOSX thread stop code. (Thanks to Dick Porter.)
+ - SMALL_OBJ definition was off by one. This could cause crashes
+ at startup. (Thanks to Zoltan Varga for narrowing this down to
+ a trivial test case.)
+ - Integrate Paolo Molara's patch to deal with a race in the Darwin
+ thread stopping code.
+ - Changed X86_64 implementation to use SA_SIGINFO in the MPROTECT_VDB
+ implementation. The old approach appears to have been broken by
+ recent kernels.
+ - Added GC_ATTR_UNUSED to eliminate a warning in gc_allocator.h (Thanks
+ to Andrew Begel.)
+ - Fix GC_task_self declaration in os_dep.c. (Thanks to Andrew Pinski.)
+ - Increase INITIAL_BUF_SZ in os_dep.c for Solaris /proc reads.
+
+Since gc6.3:
+ - Merge gcconfig.h changes from gcc tree.
+ - Unconditionally include gc_priv.h in solaris_pthreads.c, win32_threads.h,
+ aix_irix_threads.c, and solaris_threads.c to get thread definitions.
+ - Start marker threads in GC_thr_init, so that they get started even
+ if no other threads are ever started. (Oddly enough, the parallel
+ collector worked correctly, though not well, with no helper threads.)
+ - Go ahead and split large blocks in GC_allochblk_nth if GC_dont_gc
+ is set. (Thanks to Alexander Petrossian.)
+ - GC_PRINT_BACK_HEIGHT would deadlock with thread support.
+ - Let in_progress_space in backgraph.s grow dynamically.
+ - Fix README.solaris2. The GC_thr_init() hack doesn't work anymore.
+ - Convert GC_finalizer_mem_freed to bytes in allchblk.c.
+ - Add missing declaration for GC_generic_malloc_words_small_inner.
+ Without it, s390x breaks. (Thanks to Ulrich Weigand.)
+ - Applied several MacOSX patches to support older tool chains.
+ (Thanks to Stefan Ring.)
+ - Bug fix for NetBSD/amd64. (Thanks to Marc Recht.) Add NetBSD/sh3
+ support. (Thanks to Uchiyama Yasushi.)
+ - Fixed an uninitialized variable in cordprnt.c. (Thanks to gcc for
+ providing the warning.)
+ - Eliminated some, but not all, gcc -Wall warnings.
+ - Changed some old style casts to reinterpret_cast in new_gc_alloc.h.
+ (Thanks to Dan Grayson.)
+ - GC_extend_size_map shouldn't adjust for GC_all_interior_pointers if
+ GC_DONT_ADD_BYTE_AT_END is set.
+ - Changed some (long) casts to (word) in preparation for win64.
+ (Thanks to Peter Colson.)
+ - Changed "int stack_size" declaration in pthread_support.c to use
+ size_t. (Only mattered with GC_ASSERTIONS enabled.)
+ - Added CRIS (etrax) support. (Thanks to Simon Posnjak and
+ Hans-Peter Nilsson.)
+ - Removed GC_IGNORE_FB frame buffer recognition, and replaced
+ it with a check that the mapping type is MEM_IMAGE.
+ In theory, this should work much better, but it is a high
+ risk change for win32. (Thanks to Ashley Bone for the crucial
+ experimental data behind this, and to Rutger Ovidus for
+ some further experiments.)
+ - GC_allochblk_nth incremented GC_words_wasted by bytes rather than
+ words.
+ - Consider GC_words_wasted in GC_adj_words_allocd only if it is within
+ reason. (A hack to avoid some extremely unlikely scenarios in which
+ we manage to allocate only "wasted" space. 7.0 has a better fix.)
+ - Changed PowerPC GC_clear implementation to use lwsync instead of
+ eieio, since the documentation recommends against eieio, and
+ it seems to be incorrect if the preceding memory op is a load.
+ - Fixed print_block_list to print the correct kind number for
+ STUBBORN. (Thanks to Rutger Ovidus.)
+ - Have configure.in generate an error if it is asked to support
+ pthreads, but doesn't know how to.
+ - Added Kazuhiro Inaoka's patch for Renesas M32R support.
+ - Have the GNU build mechanism link with -ldl. Rename THREADLIBS
+ to THREADDLLIBS to reflect this. (Thanks to Sven Verdoolaege.)
+ - Added Hannes Mehnert's patch for FreeBSD/SPARC support.
+ - Merged some FreeBSD specific patches to threadlibs.c and dyn_load.c.
+ (Thanks tp John Merryweather Cooper.)
+ - Define MPROTECT_VDB on MACOSX only if threads are being used, since the
+ dirty page tracking mechanism uses threads. (This avoids an undefined
+ reference to _GC_darwin_register_mach_handler_thread.)
+ - By popular demand, use __libc symbols only if we are built with
+ USE_LIBC_PRIVATES, which is off by default, and not otherwise documented.
+ - Ignore GC_enable_incremental() requests when KEEP_BACK_PTRS is set.
+ The GC itself will dirty lots of pages in this cases, probably making
+ it counterproductive on all platforms. And the DARWIN port crashes.
+
+Since gc6.4:
+ - Integrated Paolo Molaro's patch to deal with EINTR in sem_wait.
+ - Make GC_approx_sp() write to dummy location to ensure that stack
+ is grown here, when sp looks reasonable, rather than later, when
+ it might look like a bad memory reference. (Problem was never
+ observed that I know of. But on rereading the code it seemed
+ dubious.)
+ - Separate out GC_with_callee_saves_pushed and sometimes call
+ it from GC_suspend_handler in pthread_stop_world.c. Callee-save
+ register values sometimes failed to get traced under HP/UX on
+ PA-RISC. Linux/IA64 had the same problem, though non-stacked
+ callee-save registers seem to be so rarely used there that nobody
+ ever noticed.
+ - Integrated an ancient Darwin powerpc_darwin_machine_dep.s patch
+ from Andreas Tobler, which I had lost.
+ - Fix compare_and_exchange implementation for gcc/IA64 to deal with
+ pickier compiler versions.
+ - Fixed Itanium 32-bit ABI support (HP/UX). In particular, the
+ compare_and_exchange implementation didn't consider that possibility.
+ - Undefine GC_pthread_detach in win32_threads.c. (Thanks to
+ Tagliapietra Tommaso.)
+ - Fixed inclusion of frame.h for NETBSD in os_dep.c.
+ - Applied Dan Bonachea's patch to use mmap on AIX.
+ - Several fixes to resurrect the Irix port on recent OS versions.
+ - Change ALPHA to use LINUX_STACKBOTTOM.
+ - Change SPARC64/LINUX to also use LINUX_STACKBOTTOM. Deal with potential
+ bad values of __libc_stack_end on that platform. (Thanks to David Miller.)
+ - Relax gctest to allow larger heap if ALIGN_DOUBLE isn't set.
+ (Unnecessary in 7.0)
+ - Force a define of __STDC__=0 for the IBM compiler on AIX, so that
+ we get prototypes. (Unnecessary in 7.0)
+ - GC_INIT definition for AIX and CYGWIN referred to DATASTART and DATAEND
+ which are only defined in private include files.
+ - Integrated some small gcconfig.h patches from Dan Bonachea. Also
+ relaxed assertion about FreeBSD stack size in pthread_support.c.
+ - Integrated Andrew Begel's darwin_stop_world.c patch for 64-bit
+ support. This may need additional work.
+ - Avoided potentially infinite recursion in GC_save_callers if
+ the system backtrace calls malloc. The workaround currently requires
+ __thread support if this code is used with threads.
+ - Avoided another similar infinite recursion by conditionally
+ invoking GC_save_callers in alloc.c. (Thanks to Matthias Andree
+ for helping to track down both of these.)
+ - Removed all traces of aix_irix_threads.c. AIX and Irix now use
+ pthread_support.c and pthread_stop_world.c. The old code appeared
+ to be unreliable for AIX, and was not regularly maintained.
+ - On Irix, ignore segments with MA_FETCHOP or MA_NOTCACHED attributed;
+ they're not always safe to read.
+ - Fixed a previously vacuous assertion (diagnosed by the SGI compiler)
+ in GC_remove_from_fl.
+ - Fix stack_size assertion in GC_pthread_create.
+ - Fix assertion in GC_steal_mark_stack.
+
+Since gc6.5:
+ - Fix CPU count detection for Irix and FreeBSD. (Thanks to Dan Bonachea.)
+ - Integrate Dan Bonachea's patch for the IBM XLC compiler on Darwin.
+ - Integrated Andreas Tobler's FreeBSD/PowerPC patch.
+ - Don't access the GC thread structure from the restart handler. It's
+ unsafe, since the handler may run too late. (Thanks to Ben Maurer for
+ tracking this down.)
+ - Applied Christian Thalinger's patch to change comment syntax in
+ alpha_mach_dep.S.
+ - Added test for GC_no_dls in GC_dyld_image_add for DARWIN. (Thanks to
+ Juan Jose Garcia Ripoli).
+ - Use LINUX_STACKBOTTOM for Linux/SH and LINUX/ARM. (Thanks to Sugioka
+ Toshinobu and Christian Thalinger.)
+ - Rewrote GC_parse_map_entry. This assumed a fixed column layout of
+ /proc/self/maps on Linux. This ceased to be true about 2 years ago.
+ The old code is probably quite problemetic with -DREDIRECT_MALLOC. It
+ is also used by default for IA64, though I haven't seen actual failures
+ there.
+ - More consistently define HBLKSIZE to 4096 on 64 bit architectures with
+ 4K pages. (Thanks to Andrew Haley.)
+ - With win32 threads, GC_stop_world needs to acquire GC_write_cs. (Thanks
+ to Ben Hutchings for the observation and patch.)
+ - Move up struct callinfo declaration to make gcc 4.0.2. happy.
+
+Since 6.6:
+ - Add "int" to Solaris "end" and "etext" declaration in gc.h. Declared
+ the symbols with underscores and as arrays, since that's what's actually
+ used. Perhaps this could all just be removed? (Thanks to John Bowman.)
+ - Fixed ARM GC_test_and_set code. (Thanks to Kazu Hirata and Paul Brook.)
+ - Added casts for assignments to hb_last_reclaimed, which truncate the
+ value. Added a cast to GC_adj_words_allocd. Use GetModuleHandleA
+ when retrieving a handle to kernel32.dll under win32. (Thanks to the
+ Visual Prolog developers.)
+ - Added Tandem S-Series support. (Thanks to Craig McDaniel. A modified
+ version of his patch was applied, and hence breakage is probably not
+ his fault.)
+ - Remove spurious gc:: qualifier for operator delete[] in gc_cpp.h.
+ (Thanks to Hanno Boeck.)
+ - Changed a test for LINUX in config_macros.h to one for __linux__.
+ - Add prototypes for GC_finalizer_notifier and GC_thr_init. (Thanks to
+ David Ayers.)
+ - Use ld instead of nonexitent ldz instruction in Darwin FindTopOfStack.
+ (Thanks to Andreas Tobler.)
+ - Add support for Darwin/X86. (Thanks to Geoff Norton and the Mono
+ developers.)
+ - Merge in some recent gcc fixes. Add ppc64 asm code. (Thanks to Bryce
+ McKinley and other gcj developers.)
+ - Scan MEM_PRIVATE sections under Windows ME and predecessors.
+ - Interior pointers with some largish offsets into large objects could
+ be ignored, if GC_all_interior_pointers was set. (Oddly this worked
+ correctly for stack references if it was not set. Otherwise it failed
+ for both stack and heap references.) Thanks to Andrew McKinlay for the
+ critical test case.
+ - Integrated Tatsuya Bizenn's NETBSD threads support, with some
+ untested changes.
+ - Added GC_strdup and friends to make leak detection work correctly
+ for strdup clients. (Thanks to Jon Moore.) Fixed the existing strdup
+ with malloc redirection to handle a null malloc return correctly.
+
+Since gc6.7:
+ - Added some support for Dragonfly BSD. (Thanks to Joerg Sonnenberger and
+ Thomas Klausner.)
+ - Improvements to the HP/UX section of configure.in/configure.ac.
+ (Thanks to Andreas Tobler)
+ - GC_unix_get_mem could neglect to release the malloc lock on Irix, under
+ extremely unlikely circumstances. Thanks to Jean-Baptiste Nivois for
+ some careful code reading.
+ - Added support for kFreeBSD + glibc (Thanks to Petr Salinger)
+ - Fix more MacOS threads memory leaks (Thanks to Allan Hsu)
+ - Added initial Solaris/X86-64 support (Thanks to Rainer Orth)
+
+Since gc6.8:
+ - Fix typo in PREFETCH implementation for X86_64. (Thanks to Peter Wang.)
+ - Fix M68K LINUX port. (Thanks to Debian packagers.)
+ - __GNUC__ was misspelled as __GNUC in new_gc_alloc.h. (Thanks to Peter Wang.)
+ - Integrated Allan Hsu's patch for OS X VM deallocation problems.
+ - Applied FreeBSD/X86_64 patch.
+
+Since gc6.9:
+ - Remove GC_PROTO, VOLATILE, GC_PTR, and GC_CONST. Assume ANSI C compiler
+ and use ANSI constructs unconditionally.
+ - Introduce #elif and #error in some of the appropriate places.
+ - Remove GC_printf cruft. Use stdargs.
+ - Remove separate Solaris threads support. Use the more generic Posix
+ implementation.
+ - Use atomic_ops for atomic operations and memory barriers.
+ - Clean up MPROTECT_VDB implementation. Use SA_SIGINFO wherever
+ possible.
+ - Remove broken SIGNALS stuff.
+ - Use size_t instead of word, where appropriate.
+ - Add .S.o rule to Makefile.am.
+ - Officially unsupport SunOS4, several old flavors of M68K (SunOS4,
+ A/UX, HP), IBM PC/RTs and RISCOS/Irix4. (I doubt the old code worked.
+ If anyone cares, these should be easy to resurrect.)
+ - Add EXPECT() in some critical places.
+ - Redefined hb_sz and hb_body to deal with bytes rather than words.
+ This affected a great deal of code. I would like to consistently use
+ byte offsets and sizes where there's not a convincing reason to do
+ otherwise.
+ - Redefined several other variables (GC_mem_found, GC_words_allocd)
+ etc. to use units of bytes. Most of these were also renamed to
+ reflect that fact.
+ - Killed as many "register" declarations as possible.
+ - Partially replaced stubborn allocation with manual write barrier.
+ It's currently broken.
+ - Restructured mark code, to allow mark bits to be kept either on
+ a per allocation granule or per object basis. The emphasis is
+ now on the -DUSE_MARK_BYTES option, since individual bits perform
+ quite badly on hyperthreaded P4s, and are probably suboptimal on
+ other architectures. -DUSE_MARK_BITS is currently broken, and may
+ be resurrected only for the single-threaded case. This significantly
+ reduced the cache footprint required by auxiliary GC data structures.
+ It also reduces space overhead for small heaps. It probably slows
+ things down slightly if interior pointers are very common.
+ - As part of the above, we now maintain an approximate count of set
+ mark bits in each heap block.
+ - As part of the above, the semantics of hb_map changed drastically.
+ For MARK_BIT_PER_OBJ, it doesn't exist. For MARK_BIT_PER_GRANULE,
+ it is purely a way to replace a mod instruction with a table lookup.
+ (Somewhat to my surprise, this still wins on modern hardware.)
+ - Removed PRINTSTATS, GATHERSTATS, and SILENT macros. Everything is
+ now controlled by GC_print_stats variable and GC_PRINT_STATS
+ and new GC_PRINT_VERBOSE_STATS environment variables.
+ - Add GC_log_printf and use it consistently for logging output.
+ - Unconditionally count the objects we reclaim in the sweep phase.
+ For thread local allocation, we need that anyway, and we expect
+ that's increasingly the only case that matters. And it simplifies
+ the code. In general expect minor performance hacks that benefit
+ only the single-threaded case to disappear.
+ - Remove GC_quiet from gc.h and elsewhere.
+ - Changed the heap expansion heuristic, and the definition of
+ GC_free_space_divisor, to refer to live data size, instead of total
+ heap size. I believe this is much more robust. It wasn't previously
+ possible, because we didn't have access to live data size.
+ - Thread local allocation added the extra byte in twice: Once in
+ thread_local_alloc, and once in malloc_many.
+ - Removed GC_malloc_words_small and GC_gcj_fast_malloc. A new
+ mechanism based on the thread local allocation data structures
+ is expected to be added instead. This should allow inlined code
+ that is both fast and doesn't rely on collector internals.
+ - Changed both free lists and reclaim lists to be indexed by granules
+ instead of words, norming halving their size.
+ - MERGE_SIZE is now the only option, and the macro was removed.
+ (Without it, we need a memory reference to GC_all_interior_pointers
+ anyway. Thus it costs us nothing.)
+ - Change GC_size_map to map to granules instead of words. Make sure
+ that every possible size up to TINY_FREELISTS is present.
+ - Split of macros need for fast inline allocation into gc_tiny_fl.h
+ in anticipation of a new inline allocator that doesn't rely on GC
+ internals.
+ - Changed thread local allocation to use GRANULE_BYTES and TINY_FREELISTS
+ in anticipation of a merge with the inline allocation code.
+ - Removed ALIGN_DOUBLE. This is mostly handled by GRANULE_BYTES.
+ - Make locking on most platforms conditional on GC_need_to_lock.
+
+Since gc7.0alpha1:
+ - GC_bytes_allocd was incremented by a possibly uninitialized variable
+ in GC_generic_malloc_inner. (Bug introduced in gc7.0alpha1. Thanks
+ to Ben Hutchings for tracking it down.)
+ - Win32 fixes. (Thanks to Ben Hutchings and Maurizio Vairani.)
+ - Integrated Ben Hutchings' GetWriteWatch-based virtual dirty bit
+ implementation for win32.
+ - Removed pc_gc.tar and floppy targets in Makefile.direct. Removed
+ pc_excludes file.
+ - No longer include GC_bytes_wasted when evaluating allocation progress.
+ Since we are now counting live memory, it no longer makes sense.
+ - Applied Davide Angelocola's configury patch. There are now separate
+ Makefile.am's in the cord and tests subdirectory, more tests, etc.
+ - Renamed configure.in to configure.ac.
+ - Merged a very small number of Nathanael Nerode's configure.ac
+ cleanups from the gcc tree. Unfortunately, that file is a bit
+ different from ours.
+ - Changed EINTR handling in sem_wait slightly.
+ - Restructure the root marking code. Remove all traces of
+ USE_GENERIC_PUSH_REGS, and effectively make it the default.
+ Make it easier to pass a context pointer to the mark routine, in
+ case we ever want to do precise stack marking.
+ - Replace GC_start_blocking() and GC_end_blocking() with GC_do_blocking().
+ This remains undocumented, and only implemented for pthreads. But it
+ removes an otherwise unavoidable race with stores of callee-save
+ registers.
+ - Fix GC_n_mark_bits for the default MARK_BIT_PER_GRANULE case. This
+ resulted in bogus complaints in heap dumps.
+ - Upgrade to libatomic_ops-1.0, and update build structure to match.
+ - Remove SRC_M3 support. Clean up lock initialization code in misc.c.
+ - Removed gc_local_alloc.h. If THREAD_LOCAL_ALLOC is defined, the
+ thread local allocation routines are now called automatically.
+ - Renamed gc_inl.h back to gc_inline.h. Changed the interface appreciably
+ since locking has turned into a dominant issue, and in-line allocation
+ only makes sense if it's no worse than thread-local allocation.
+ Gc_inline.h is now also used to implement thread-local allocation.
+ - Finished replacing stubborn allocation with manual write barrier.
+ Untested.
+ - Use thread-local allocation code by default.
+ - Added GC_register_my_thread and friends for Posix and win32.
+ - Patch for GWW_VDB from Ben Hutchings.
+ - Removed explicit THREAD_LOCAL_ALLOC tests, since that now always
+ redefines GC_malloc.
+ - Removed now unused AIX memory allocation code.
+ - Various minor fixes for bugs introduced in 7.0alpha1.
+
+Since gc7.0alpha2
+ - Added support for dlopen-based interception of pthread functions.
+ This is only half done. The gc.h redefinitions currently interfere.
+ - Integrated major automake overhaul from Petter Urkedal.
+
+Since gc7.0alpha3
+ (various 6.5, 6.6 changes)
+ - Removed GC_brief_async_signal_safe_sleep and used atomic_ops instead.
+ (Thanks to Ben Maurer.)
+ - Integrated build patches from David Angelocola and Petter Urkedal.
+ - Fix dynamic-linker-based pthread call redirection.
+ - Renamed RS6000 to POWERPC/AIX.
+ - Allow recovery from SIGSEGV in marker on Linux. This works around
+ a race in thread stack marking if /proc is used to find roots. We do
+ that by default with malloc redirection and threads. This involved
+ moving some GC_find_limit and SETJMP related declarations to gc_priv.h.
+ - Added doc/porting.html file.
+ - Added ADD_HEAP_GUARD_PAGES for sbrk/*nix platforms to debug extreme
+ memory overwrite errors.
+ - Added trivial NO_INCREMENTAL flag to facilitate debugging.
+ - Added GC_getattr_np-based GC_get_stack_base (untested).
+ - Separated thread local allocation into a separate file and added the
+ beginning of win32 support for that.
+
+Since gc7.0alpha4
+ (more 6.6, 6.7 changes)
+ - Some Solaris fixes, including some more general changes in how
+ the assembly pieces of mach_dep.c are handled.
+ - Removed a lot of SOLARIS_THREADS-specific code that was only
+ needed with the old implementation. This included many (mostly no-op)
+ versions of GC_is_fresh.
+ - Don't use atomic_ops in gc_locks.h unless we need threads.
+ - Fixed USE_MARK_BITS, which is once againthe default without PARALLEL_MARK.
+ - Removed Solaris GC_INIT hack. It's a workaround for a long dead bug,
+ and it seemed to be wrong anyway.
+ - Changed win32_threads.c to require preprocessor-based interception
+ of thread routines by default. A client call to GC_use_DllMain is
+ now required to get the old behavior in which DllMain is used to implicitly
+ register threads. This was doen for uniformity with other platforms, and
+ because the DllMain solution seemed to require very tricky code which,
+ at least in the past, imposed hard bounds onthe number of threads.
+ - Many small changes to make thread support work again on Cygwin.
+ - Moved definition of allocator lock etc. to pthread_support.c and
+ win32_threads.c for those two cases.
+ - Got rid of the FASTLOCK() machinery. It doesn't seem useful on modern
+ platforms.
+ - Cleaned up the uncollectable allocation routines, speeding up the
+ slower paths. The code did enough unnecessary work off the critical path
+ that the underlying logic was getting hard to extract.
+ - No longer turn off THREAD_LOCAL_ALLOC with DBG_HDRS_ALL. Indications
+ are it just works, and I think the reasons for it not working disappeared
+ a while ago.
+ - Fixed bugs in hb_n_marks calculation and assertion.
+ - Don't use __builtin_expect for pre-3.0 gcc.
+ - Define GWW_VDB only for recent Microsoft tool chains.
+ - Add overview.html to doc directory.
+ - Fix NT_STATIC_THREADS_MAKEFILE, various compiler warnings.
+ - Made thread local allocation sort of work with Cygwin. The code should
+ be there to deal with other Windows variants, But non-Cygwin Windows
+ threads need more bug fixes.
+
+Since gc7.0alpha5
+ (more 6.7 changes)
+ - Declare GC_dump() in gc.h.
+ - Add --enable-large-config, which just defines the LARGE_CONFIG macro.
+ - Make GlobalAlloc address alignment a bit more intuitive. (Thanks to
+ Charles Mills.)
+ - Use #elif in the definitions of GET_MEM.
+ - Overhaul porting.html. Remove corresponding text from README.
+ - Fix typo in DARWIN section of gcconfig.h.
+ - Fix Darwin thread memory leak. (Thanks to Bruce Mitchener.)
+ - Update x86 AO_test_and_set implementation to use "=q".
+ - Add $(EXEEXT) to many tests in tests/tests.am. (Corresponds to a
+ 6.7 fix, which no longer applied.)
+ - Fix Darwin/PPC port.
+ - Fix Cygwin/threads port.
+ - Fix gcj malloc support.
+ - For GNU-style make, don't build libatomic_ops unless threads are requested.
+ This should allow single-threaded builds on platforms which do not
+ currently support libatomic_ops.
+ - Clean up and hopefully fix the CFLAGS calculation for GNU build.
+ (Substantially improves things on HP/UX.)
+ - Integrated Andrei Polushin's Visual C++ patches. These provide for
+ stack traces, better C++ debug support, and better log file handling.
+ Note that these change the location of the log file to a the path of the
+ executable with a .log extension. To get the old behavior back, define
+ OLD_WIN32_LOG_FILE. For the time being, I'm checking his project
+ files and the like into a windows-untested subdirectory. They
+ are almost certainly already out of date, but better than what we had
+ before.
+ - Fixed some win32 threads bugs, and added support for _beginthreadex.
+ - Fix zero size thread local allocation so that explicit deallocation
+ works correctly.
+ - Removed serious bug in GC_malloc_uncollectable(large size).
+ - Do not try to do thread-local gcj allocation in incremental mode. There
+ are races in setting up the descriptor.
+ - Add GC_INIT() to middle.c, fix some more GC_printfn calls.
+ - Some assertions erroneously used I_HOLD_LOCK() negatively, eventhough
+ it can now spuriously return TRUE.
+ - Rename SUNOS5 macro and OS name to SOLARIS and SUNOS5DL to SOLARISDL.
+ - On Linux and some Un*x variants, allocate memory by first trying sbrk,
+ and then switching to mmap if that fails.
+ - Fixed /proc/x/maps reading to deal with asynchronous deletions.
+ - Fix REDIRECT_MALLOC with threads on Linux. It now usually seems to work
+ with ugly hacks that include having calloc behave differently when it is
+ called from ld.so or the pthreads library. A reasonable amount of
+ infrastructure was added to support some of this. Thanks to Roland McGrath
+ for ideas and information.
+ - Import various updated build scripts.
+ - Add GC_register_has_static_roots_callback. (Thanks to Andrew Haley.)
+ - Fix serious bugs in GC_malloc_atomic_uncollectable().
+ - Return GC_SUCCESS form GC_get_stack_base().
+ - Fix several atomic_ops problems on IA64 with HP Compiler.
+ - Update to atomic_ops-1.2.
+ - Fix hb_n_marks description and reclaim.c assertion.
+ - Various additional win32 threads fixes.
+ - Enable GC_ASSERTIONS for Debug build with NT_THREADS_MAKEFILE.
+
+[gc7.0alpha7 was released and version bumped to gc7.0alpha8]
+
+Since first gc7.0alpha8 version:
+ [ Some gc6.9 changes ]
+ - Change FindTopOfStack decl in darwin_stop_world.c.
+ - Move some static tests from misc.c to gcconfig.h. Use #error.
+ - Add GC_print_free_list() function. (Thanks to Bruce Hoult.)
+ - Add GC_GNU_THREADS support on HURD. (Thanks to Aleksey Demakov,
+ Barry DeFreese, and possibly other Debian maintainers.)
+ - __GNUC__ was misspelled as __GNUC in thread_local_alloc.h.
+ (Thanks to Peter Wang.)
+ - Integrated various MacOSX patches and tried to reconcile them.
+ Thanks to Allan Hsu, several contributers at Apple, and probably
+ others.
+ - Added some casts to powerpc.h in libatomic_ops to silence warnings.
+
+FOR FURTHER UPDATES SEE ../ChangeLog FILE.
+
+To do:
+ - REDIRECT_MALLOC and threads combination should work on more platforms,
+ and needs more testing on Linux.
+ - Clone marker inner loop to support arch-dependent prefetching,
+ and counting of objects marked for finalization.
+ - The USE_MUNMAP code should really use a separate data structure
+ indexed by physical page to keep track of time since last use of
+ a page. Using hblk headers means we lose track of ages when
+ blocks are merged, and we can't unmap pages that have been allocated and
+ dropped by the blacklisting code. I suspect both of these matter.
+ - A dynamic libgc.so references dlopen unconditionally, but doesn't link
+ against libdl.
+ - GC_proc_fd for Solaris is not correctly updated in response to a
+ fork() call. Thus incremental collection in the child won't work
+ correctly. (Thanks to Ben Cottrell for pointing this out.)
+ - --enable-redirect-malloc is mostly untested and known not to work
+ on some platforms.
+ - There seem to be outstanding issues on Solaris/X86, possibly with
+ finding the data segment starting address. Information/patches would
+ be appreciated.
+ - Very large root set sizes (> 16 MB or so) could cause the collector
+ to abort with an unexpected mark stack overflow. (Thanks again to
+ Peter Chubb.) NOT YET FIXED. Workaround is to increase the initial
+ size.
+ - The SGI version of the collector marks from mmapped pages, even
+ if they are not part of dynamic library static data areas. This
+ causes performance problems with some SGI libraries that use mmap
+ as a bitmap allocator. NOT YET FIXED. It may be possible to turn
+ off DYNAMIC_LOADING in the collector as a workaround. It may also
+ be possible to conditionally intercept mmap and use GC_exclude_static_roots.
+ The real fix is to walk rld data structures, which looks possible.
+ - Incremental collector should handle large objects better. Currently,
+ it looks like the whole object is treated as dirty if any part of it
+ is.
+
+FOR FURTHER UPDATES SEE ../ChangeLog FILE.
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.contributors b/tools/build/v2/engine/boehm_gc/doc/README.contributors
new file mode 100644
index 0000000000..fd5c95f229
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.contributors
@@ -0,0 +1,57 @@
+This is an attempt to acknowledge early contributions to the garbage
+collector. Later contributions should instead be mentioned in
+README.changes.
+
+HISTORY -
+
+ Early versions of this collector were developed as a part of research
+projects supported in part by the National Science Foundation
+and the Defense Advance Research Projects Agency.
+
+The garbage collector originated as part of the run-time system for
+the Russell programming language implementation. The first version of the
+garbage collector was written primarily by Al Demers. It was then refined
+and mostly rewritten, primarily by Hans-J. Boehm, at Cornell U.,
+the University of Washington, Rice University (where it was first used for
+C and assembly code), Xerox PARC, SGI, and HP Labs. However, significant
+contributions have also been made by many others.
+
+Some other contributors:
+
+More recent contributors are mentioned in the modification history in
+README.changes. My apologies for any omissions.
+
+The SPARC specific code was originally contributed by Mark Weiser.
+The Encore Multimax modifications were supplied by
+Kevin Kenny (kenny@m.cs.uiuc.edu). The adaptation to the IBM PC/RT is largely
+due to Vernon Lee, on machines made available to Rice by IBM.
+Much of the HP specific code and a number of good suggestions for improving the
+generic code are due to Walter Underwood.
+Robert Brazile (brazile@diamond.bbn.com) originally supplied the ULTRIX code.
+Al Dosser (dosser@src.dec.com) and Regis Cridlig (Regis.Cridlig@cl.cam.ac.uk)
+subsequently provided updates and information on variation between ULTRIX
+systems. Parag Patel (parag@netcom.com) supplied the A/UX code.
+Jesper Peterson(jep@mtiame.mtia.oz.au), Michel Schinz, and
+Martin Tauchmann (martintauchmann@bigfoot.com) supplied the Amiga port.
+Thomas Funke (thf@zelator.in-berlin.de(?)) and
+Brian D.Carlstrom (bdc@clark.lcs.mit.edu) supplied the NeXT ports.
+Douglas Steel (doug@wg.icl.co.uk) provided ICL DRS6000 code.
+Bill Janssen (janssen@parc.xerox.com) supplied the SunOS dynamic loader
+specific code. Manuel Serrano (serrano@cornas.inria.fr) supplied linux and
+Sony News specific code. Al Dosser provided Alpha/OSF/1 code. He and
+Dave Detlefs(detlefs@src.dec.com) also provided several generic bug fixes.
+Alistair G. Crooks(agc@uts.amdahl.com) supplied the NetBSD and 386BSD ports.
+Jeffrey Hsu (hsu@soda.berkeley.edu) provided the FreeBSD port.
+Brent Benson (brent@jade.ssd.csd.harris.com) ported the collector to
+a Motorola 88K processor running CX/UX (Harris NightHawk).
+Ari Huttunen (Ari.Huttunen@hut.fi) generalized the OS/2 port to
+nonIBM development environments (a nontrivial task).
+Patrick Beard (beard@cs.ucdavis.edu) provided the initial MacOS port.
+David Chase, then at Olivetti Research, suggested several improvements.
+Scott Schwartz (schwartz@groucho.cse.psu.edu) supplied some of the
+code to save and print call stacks for leak detection on a SPARC.
+Jesse Hull and John Ellis supplied the C++ interface code.
+Zhong Shao performed much of the experimentation that led to the
+current typed allocation facility. (His dynamic type inference code hasn't
+made it into the released version of the collector, yet.)
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.cords b/tools/build/v2/engine/boehm_gc/doc/README.cords
new file mode 100644
index 0000000000..3485e0145a
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.cords
@@ -0,0 +1,53 @@
+Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
+
+THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+
+Permission is hereby granted to use or copy this program
+for any purpose, provided the above notices are retained on all copies.
+Permission to modify the code and to distribute modified code is granted,
+provided the above notices are retained, and a notice that the code was
+modified is included with the above copyright notice.
+
+Please send bug reports to Hans-J. Boehm (Hans_Boehm@hp.com or
+boehm@acm.org).
+
+This is a string packages that uses a tree-based representation.
+See cord.h for a description of the functions provided. Ec.h describes
+"extensible cords", which are essentially output streams that write
+to a cord. These allow for efficient construction of cords without
+requiring a bound on the size of a cord.
+
+More details on the data structure can be found in
+
+Boehm, Atkinson, and Plass, "Ropes: An Alternative to Strings",
+Software Practice and Experience 25, 12, December 1995, pp. 1315-1330.
+
+A fundamentally similar "rope" data structure is also part of SGI's standard
+template library implementation, and its descendents, which include the
+GNU C++ library. That uses reference counting by default.
+There is a short description of that data structure at
+http://reality.sgi.com/boehm/ropeimpl.html . (The more official location
+http://www.sgi.com/tech/stl/ropeimpl.html is missing a figure.)
+
+All of these are descendents of the "ropes" in Xerox Cedar.
+
+de.c is a very dumb text editor that illustrates the use of cords.
+It maintains a list of file versions. Each version is simply a
+cord representing the file contents. Nonetheless, standard
+editing operations are efficient, even on very large files.
+(Its 3 line "user manual" can be obtained by invoking it without
+arguments. Note that ^R^N and ^R^P move the cursor by
+almost a screen. It does not understand tabs, which will show
+up as highlighred "I"s. Use the UNIX "expand" program first.)
+To build the editor, type "make cord/de" in the gc directory.
+
+This package assumes an ANSI C compiler such as gcc. It will
+not compile with an old-style K&R compiler.
+
+Note that CORD_printf iand friends use C functions with variable numbers
+of arguments in non-standard-conforming ways. This code is known to
+break on some platforms, notably PowerPC. It should be possible to
+build the remainder of the library (everything but cordprnt.c) on
+any platform that supports the collector.
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.darwin b/tools/build/v2/engine/boehm_gc/doc/README.darwin
new file mode 100644
index 0000000000..b413ff3385
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.darwin
@@ -0,0 +1,142 @@
+Darwin/MacOSX Support - December 16, 2003
+=========================================
+
+Important Usage Notes
+=====================
+
+GC_init() MUST be called before calling any other GC functions. This
+is necessary to properly register segments in dynamic libraries. This
+call is required even if you code does not use dynamic libraries as the
+dyld code handles registering all data segments.
+
+When your use of the garbage collector is confined to dylibs and you
+cannot call GC_init() before your libraries' static initializers have
+run and perhaps called GC_malloc(), create an initialization routine
+for each library to call GC_init():
+
+#include <gc/gc.h>
+extern "C" void my_library_init() { GC_init(); }
+
+Compile this code into a my_library_init.o, and link it into your
+dylib. When you link the dylib, pass the -init argument with
+_my_library_init (e.g. gcc -dynamiclib -o my_library.dylib a.o b.o c.o
+my_library_init.o -init _my_library_init). This causes
+my_library_init() to be called before any static initializers, and
+will initialize the garbage collector properly.
+
+Note: It doesn't hurt to call GC_init() more than once, so it's best,
+if you have an application or set of libraries that all use the
+garbage collector, to create an initialization routine for each of
+them that calls GC_init(). Better safe than sorry.
+
+The incremental collector is still a bit flaky on darwin. It seems to
+work reliably with workarounds for a few possible bugs in place however
+these workaround may not work correctly in all cases. There may also
+be additional problems that I have not found.
+
+Thread-local GC allocation will not work with threads that are not
+created using the GC-provided override of pthread_create(). Threads
+created without the GC-provided pthread_create() do not have the
+necessary data structures in the GC to store this data.
+
+
+Implementation Information
+==========================
+Darwin/MacOSX support is nearly complete. Thread support is reliable on
+Darwin 6.x (MacOSX 10.2) and there have been reports of success on older
+Darwin versions (MacOSX 10.1). Shared library support had also been
+added and the gc can be run from a shared library. There is currently only
+support for Darwin/PPC although adding x86 support should be trivial.
+
+Thread support is implemented in terms of mach thread_suspend and
+thread_resume calls. These provide a very clean interface to thread
+suspension. This implementation doesn't rely on pthread_kill so the
+code works on Darwin < 6.0 (MacOSX 10.1). All the code to stop and
+start the world is located in darwin_stop_world.c.
+
+Since not all uses of the GC enable clients to override pthread_create()
+before threads have been created, the code for stopping the world has
+been rewritten to look for threads using Mach kernel calls. Each
+thread identified in this way is suspended and resumed as above. In
+addition, since Mach kernel threads do not contain pointers to their
+stacks, a stack-walking function has been written to find the stack
+limits. Given an initial stack pointer (for the current thread, a
+pointer to a stack-allocated local variable will do; for a non-active
+thread, we grab the value of register 1 (on PowerPC)), it
+will walk the PPC Mach-O-ABI compliant stack chain until it reaches the
+top of the stack. This appears to work correctly for GCC-compiled C,
+C++, Objective-C, and Objective-C++ code, as well as for Java
+programs that use JNI. If you run code that does not follow the stack
+layout or stack pointer conventions laid out in the PPC Mach-O ABI,
+then this will likely crash the garbage collector.
+
+The original incremental collector support unfortunatelly no longer works
+on recent Darwin versions. It also relied on some undocumented kernel
+structures. Mach, however, does have a very clean interface to exception
+handing. The current implementation uses Mach's exception handling.
+
+Much thanks goes to Andrew Stone, Dietmar Planitzer, Andrew Begel,
+Jeff Sturm, and Jesse Rosenstock for all their work on the
+Darwin/OS X port.
+
+-Brian Alliet
+brian@brianweb.net
+
+gc_cpp.h usage
+==============
+
+Replacement of operator new and delete is apparently not supported with
+dynamic libraries. This means that applications using gc_cpp.h
+(including the built-in test) will probably not work correctly with
+the collector in a dynamic library, unless special care is taken.
+
+See
+http://article.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/1421
+for some details.
+
+- Hans Boehm (based on information from Andrew Begel)
+
+
+Older Information (Most of this no longer applies to the current code)
+======================================================================
+
+While the GC should work on MacOS X Server, MacOS X and Darwin, I only tested
+it on MacOS X Server.
+I've added a PPC assembly version of GC_push_regs(), thus the setjmp() hack is
+no longer necessary. Incremental collection is supported via mprotect/signal.
+The current solution isn't really optimal because the signal handler must decode
+the faulting PPC machine instruction in order to find the correct heap address.
+Further, it must poke around in the register state which the kernel saved away
+in some obscure register state structure before it calls the signal handler -
+needless to say the layout of this structure is no where documented.
+Threads and dynamic libraries are not yet supported (adding dynamic library
+support via the low-level dyld API shouldn't be that hard).
+
+The original MacOS X port was brought to you by Andrew Stone.
+
+
+June, 1 2000
+
+Dietmar Planitzer
+dave.pl@ping.at
+
+Note from Andrew Begel:
+
+One more fix to enable gc.a to link successfully into a shared library for
+MacOS X. You have to add -fno-common to the CFLAGS in the Makefile. MacOSX
+disallows common symbols in anything that eventually finds its way into a
+shared library. (I don't completely understand why, but -fno-common seems to
+work and doesn't mess up the garbage collector's functionality).
+
+Feb 26, 2003
+
+Jeff Sturm and Jesse Rosenstock provided a patch that adds thread support.
+GC_MACOSX_THREADS should be defined in the build and in clients. Real
+dynamic library support is still missing, i.e. dynamic library data segments
+are still not scanned. Code that stores pointers to the garbage collected
+heap in statically allocated variables should not reside in a dynamic
+library. This still doesn't appear to be 100% reliable.
+
+Mar 10, 2003
+Brian Alliet contributed dynamic library support for MacOSX. It could also
+use more testing.
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.dj b/tools/build/v2/engine/boehm_gc/doc/README.dj
new file mode 100644
index 0000000000..613bc423cb
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.dj
@@ -0,0 +1,12 @@
+[Original version supplied by Xiaokun Zhu <xiaokun@aero.gla.ac.uk>]
+[This version came mostly from Gary Leavens. ]
+
+Look first at Makefile.dj, and possibly change the definitions of
+RM and MV if you don't have rm and mv installed.
+Then use Makefile.dj to compile the garbage collector.
+For example, you can do:
+
+ make -f Makefile.dj test
+
+All the tests should work fine.
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.environment b/tools/build/v2/engine/boehm_gc/doc/README.environment
new file mode 100644
index 0000000000..d50d37094c
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.environment
@@ -0,0 +1,135 @@
+The garbage collector looks at a number of environment variables which are
+then used to affect its operation. These are examined only on Un*x-like
+platforms and win32.
+
+GC_INITIAL_HEAP_SIZE=<bytes> - Initial heap size in bytes. May speed up
+ process start-up.
+
+GC_MAXIMUM_HEAP_SIZE=<bytes> - Maximum collected heap size.
+
+GC_LOOP_ON_ABORT - Causes the collector abort routine to enter a tight loop.
+ This may make it easier to debug, such a process, especially
+ for multithreaded platforms that don't produce usable core
+ files, or if a core file would be too large. On some
+ platforms, this also causes SIGSEGV to be caught and
+ result in an infinite loop in a handler, allowing
+ similar debugging techniques.
+
+GC_PRINT_STATS - Turn on GC logging. Not functional with -DSMALL_CONFIG.
+
+GC_LOG_FILE - The name of the log file. Stderr by default.
+
+GC_PRINT_VERBOSE_STATS - Turn on even more logging.
+
+GC_DUMP_REGULARLY - Generate a GC debugging dump GC_dump() on startup
+ and during every collection. Very verbose. Useful
+ if you have a bug to report, but please include only the
+ last complete dump.
+
+GC_BACKTRACES=<n> - Generate n random backtraces (for heap profiling) after
+ each GC. Collector must have been built with
+ KEEP_BACK_PTRS. This won't generate useful output unless
+ most objects in the heap were allocated through debug
+ allocators. This is intended to be only a statistical
+ sample; individual traces may be erroneous due to
+ concurrent heap mutation.
+
+GC_PRINT_ADDRESS_MAP - Linux only. Dump /proc/self/maps, i.e. various address
+ maps for the process, to stderr on every GC. Useful for
+ mapping root addresses to source for deciphering leak
+ reports.
+
+GC_NPROCS=<n> - Linux w/threads only. Explicitly sets the number of processors
+ that the GC should expect to use. Note that setting this to 1
+ when multiple processors are available will preserve
+ correctness, but may lead to really horrible performance,
+ since the lock implementation will immediately yield without
+ first spinning.
+
+GC_MARKERS=<n> - Linux w/threads and parallel marker only. Set the number
+ of marker threads. This is normally set to the number of
+ processors. It is safer to adjust GC_MARKERS than GC_NPROCS,
+ since GC_MARKERS has no impact on the lock implementation.
+
+GC_NO_BLACKLIST_WARNING - Prevents the collector from issuing
+ warnings about allocations of very large blocks.
+ Deprecated. Use GC_LARGE_ALLOC_WARN_INTERVAL instead.
+
+GC_LARGE_ALLOC_WARN_INTERVAL=<n> - Print every nth warning about very large
+ block allocations, starting with the nth one. Small values
+ of n are generally benign, in that a bounded number of
+ such warnings generally indicate at most a bounded leak.
+ For best results it should be set at 1 during testing.
+ Default is 5. Very large numbers effectively disable the
+ warning.
+
+GC_IGNORE_GCJ_INFO - Ignore the type descriptors implicitly supplied by
+ GC_gcj_malloc and friends. This is useful for debugging
+ descriptor generation problems, and possibly for
+ temporarily working around such problems. It forces a
+ fully conservative scan of all heap objects except
+ those known to be pointerfree, and may thus have other
+ adverse effects.
+
+GC_PRINT_BACK_HEIGHT - Print max length of chain through unreachable objects
+ ending in a reachable one. If this number remains
+ bounded, then the program is "GC robust". This ensures
+ that a fixed number of misidentified pointers can only
+ result in a bounded space leak. This currently only
+ works if debugging allocation is used throughout.
+ It increases GC space and time requirements appreciably.
+ This feature is still somewhat experimental, and requires
+ that the collector have been built with MAKE_BACK_GRAPH
+ defined. For details, see Boehm, "Bounding Space Usage
+ of Conservative Garbage Collectors", POPL 2001, or
+ http://lib.hpl.hp.com/techpubs/2001/HPL-2001-251.html .
+
+GC_RETRY_SIGNALS, GC_NO_RETRY_SIGNALS - Try to compensate for lost
+ thread suspend signals in linux_threads.c. On by
+ default for GC_OSF1_THREADS, off otherwise. Note
+ that this does not work around a possible loss of
+ thread restart signals. This seems to be necessary for
+ some versions of Tru64. Since we've previously seen
+ similar issues on some other operating systems, it
+ was turned into a runtime flag to enable last-minute
+ work-arounds.
+
+The following turn on runtime flags that are also program settable. Checked
+only during initialization. We expect that they will usually be set through
+other means, but this may help with debugging and testing:
+
+GC_ENABLE_INCREMENTAL - Turn on incremental collection at startup. Note that,
+ depending on platform and collector configuration, this
+ may involve write protecting pieces of the heap to
+ track modifications. These pieces may include pointerfree
+ objects or not. Although this is intended to be
+ transparent, it may cause unintended system call failures.
+ Use with caution.
+
+GC_PAUSE_TIME_TARGET - Set the desired garbage collector pause time in msecs.
+ This only has an effect if incremental collection is
+ enabled. If a collection requires appreciably more time
+ than this, the client will be restarted, and the collector
+ will need to do additional work to compensate. The
+ special value "999999" indicates that pause time is
+ unlimited, and the incremental collector will behave
+ completely like a simple generational collector. If
+ the collector is configured for parallel marking, and
+ run on a multiprocessor, incremental collection should
+ only be used with unlimited pause time.
+
+GC_FIND_LEAK - Turns on GC_find_leak and thus leak detection. Forces a
+ collection at program termination to detect leaks that would
+ otherwise occur after the last GC.
+
+GC_ALL_INTERIOR_POINTERS - Turns on GC_all_interior_pointers and thus interior
+ pointer recognition.
+
+GC_DONT_GC - Turns off garbage collection. Use cautiously.
+
+GC_TRACE=addr - Intended for collector debugging. Requires that the collector
+ have been built with ENABLE_TRACE defined. Causes the debugger
+ to log information about the tracing of address ranges containing
+ addr. Typically addr is the address that contains a pointer to
+ an object that mysteriously failed to get marked. Addr must be
+ specified as a hexadecimal integer.
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.ews4800 b/tools/build/v2/engine/boehm_gc/doc/README.ews4800
new file mode 100644
index 0000000000..80bca2b3d9
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.ews4800
@@ -0,0 +1,81 @@
+GC on EWS4800
+-------------
+
+1. About EWS4800
+ EWS4800 is 32bit/64bit workstation.
+
+ Vender: NEC Corporation
+ OS: UX/4800 R9.* - R13.* (SystemV R4.2)
+ CPU: R4000, R4400, R10000 (MIPS)
+
+2. Compiler
+
+ 32bit:
+ Use ANSI C compiler.
+ CC = /usr/abiccs/bin/cc
+
+ 64bit:
+ Use 64bit ANSI C compiler.
+ CC = /usr/ccs64/bin/cc
+ AR = /usr/ccs64/bin/ar
+
+3. ELF file format
+ *** Caution: The following infomation is empirical. ***
+
+ 32bit:
+ ELF file has an unique format. (See a.out(4) and end(3C).)
+
+ &_start
+ : text segment
+ &etext
+ DATASTART
+ : data segment (initialized)
+ &edata
+ DATASTART2
+ : data segment (uninitialized)
+ &end
+
+ Here, DATASTART and DATASTART2 are macros of GC, and are defined as
+ the following equations. (See include/private/gcconfig.h.)
+ The algorithm for DATASTART is similar with the function
+ GC_SysVGetDataStart() in os_dep.c.
+
+ DATASTART = ((&etext + 0x3ffff) & ~0x3ffff) + (&etext & 0xffff)
+
+ Dynamically linked:
+ DATASTART2 = (&_gp + 0x8000 + 0x3ffff) & ~0x3ffff
+
+ Statically linked:
+ DATASTART2 = &edata
+
+ GC has to check addresses both between DATASTART and &edata, and
+ between DATASTART2 and &end. If a program accesses between &etext
+ and DATASTART, or between &edata and DATASTART2, the segmentation
+ error occurs and the program stops.
+
+ If a program is statically linked, there is not a gap between
+ &edata and DATASTART2. The global symbol &_DYNAMIC_LINKING is used
+ for the detection.
+
+ 64bit:
+ ELF file has a simple format. (See end(3C).)
+
+ _ftext
+ : text segment
+ _etext
+ _fdata = DATASTART
+ : data segment (initialized)
+ _edata
+ _fbss
+ : data segment (uninitialized)
+ _end = DATAEND
+
+--
+Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>
+
+
+When using the new "configure; make" build process, please
+run configure with the --disable-shared option. "Make check" does not
+yet pass with dynamic libraries. Ther reasons for that are not yet
+understood. (HB, paraphrasing message from Hironori SAKAMOTO.)
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.hp b/tools/build/v2/engine/boehm_gc/doc/README.hp
new file mode 100644
index 0000000000..caa8bdd19f
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.hp
@@ -0,0 +1,18 @@
+Dynamic loading support requires that executables be linked with -ldld.
+The alternative is to build the collector without defining DYNAMIC_LOADING
+in gcconfig.h and ensuring that all garbage collectable objects are
+accessible without considering statically allocated variables in dynamic
+libraries.
+
+The collector should compile with either plain cc or cc -Ae. Cc -Aa
+fails to define _HPUX_SOURCE and thus will not configure the collector
+correctly.
+
+Incremental collection support was reccently added, and should now work.
+
+In spite of past claims, pthread support under HP/UX 11 should now work.
+Define GC_HPUX_THREADS for the build. Incremental collection still does not
+work in combination with it.
+
+The stack finding code can be confused by putenv calls before collector
+initialization. Call GC_malloc or GC_init before any putenv calls.
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.linux b/tools/build/v2/engine/boehm_gc/doc/README.linux
new file mode 100644
index 0000000000..3c50181487
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.linux
@@ -0,0 +1,131 @@
+See README.alpha for Linux on DEC AXP info.
+
+This file applies mostly to Linux/Intel IA32. Ports to Linux on an M68K, IA64,
+SPARC, MIPS, Alpha and PowerPC are also integrated. They should behave
+similarly, except that the PowerPC port lacks incremental GC support, and
+it is unknown to what extent the Linux threads code is functional.
+See below for M68K specific notes.
+
+Incremental GC is generally supported.
+
+Dynamic libraries are supported on an ELF system. A static executable
+should be linked with the gcc option "-Wl,-defsym,_DYNAMIC=0".
+
+The collector appears to work reliably with Linux threads, but beware
+of older versions of glibc and gdb.
+
+The garbage collector uses SIGPWR and SIGXCPU if it is used with
+Linux threads. These should not be touched by the client program.
+
+To use threads, you need to abide by the following requirements:
+
+1) You need to use LinuxThreads or NPTL (which are included in libc6).
+
+ The collector relies on some implementation details of the LinuxThreads
+ package. This code may not work on other
+ pthread implementations (in particular it will *not* work with
+ MIT pthreads).
+
+2) You must compile the collector with -DGC_LINUX_THREADS (or
+ just -DGC_THREADS) and -D_REENTRANT specified in the Makefile.
+
+3a) Every file that makes thread calls should define GC_LINUX_THREADS and
+ _REENTRANT and then include gc.h. Gc.h redefines some of the
+ pthread primitives as macros which also provide the collector with
+ information it requires.
+
+3b) A new alternative to (3a) is to build the collector and compile GC clients
+ with -DGC_USE_LD_WRAP, and to link the final program with
+
+ (for ld) --wrap read --wrap dlopen --wrap pthread_create \
+ --wrap pthread_join --wrap pthread_detach \
+ --wrap pthread_sigmask --wrap sleep
+
+ (for gcc) -Wl,--wrap -Wl,read -Wl,--wrap -Wl,dlopen -Wl,--wrap \
+ -Wl,pthread_create -Wl,--wrap -Wl,pthread_join -Wl,--wrap \
+ -Wl,pthread_detach -Wl,--wrap -Wl,pthread_sigmask \
+ -Wl,--wrap -Wl,sleep
+
+ In any case, _REENTRANT should be defined during compilation.
+
+4) Dlopen() disables collection during its execution. (It can't run
+ concurrently with the collector, since the collector looks at its
+ data structures. It can't acquire the allocator lock, since arbitrary
+ user startup code may run as part of dlopen().) Under unusual
+ conditions, this may cause unexpected heap growth.
+
+5) The combination of GC_LINUX_THREADS, REDIRECT_MALLOC, and incremental
+ collection is probably not fully reliable, though it now seems to work
+ in simple cases.
+
+6) Thread local storage may not be viewed as part of the root set by the
+ collector. This probably depends on the linuxthreads version. For the
+ time being, any collectable memory referenced by thread local storage should
+ also be referenced from elsewhere, or be allocated as uncollectable.
+ (This is really a bug that should be fixed somehow. The current GC
+ version probably gets things right if there are not too many tls locations
+ and if dlopen is not used.)
+
+
+M68K LINUX:
+(From Richard Zidlicky)
+The bad news is that it can crash every linux-m68k kernel on a 68040,
+so an additional test is needed somewhere on startup. I have meanwhile
+patches to correct the problem in 68040 buserror handler but it is not
+yet in any standard kernel.
+
+Here is a simple test program to detect whether the kernel has the
+problem. It could be run as a separate check in configure or tested
+upon startup. If it fails (return !0) than mprotect can't be used
+on that system.
+
+/*
+ * test for bug that may crash 68040 based Linux
+ */
+
+#include <sys/mman.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+char *membase;
+int pagesize=4096;
+int pageshift=12;
+int x_taken=0;
+
+int sighandler(int sig)
+{
+ mprotect(membase,pagesize,PROT_READ|PROT_WRITE);
+ x_taken=1;
+}
+
+main()
+{
+ long l;
+
+ signal(SIGSEGV,sighandler);
+ l=(long)mmap(NULL,pagesize,PROT_READ,MAP_PRIVATE | MAP_ANON,-1,0);
+ if (l==-1)
+ {
+ perror("mmap/malloc");
+ abort();
+ }
+ membase=(char*)l;
+ *(long*)(membase+sizeof(long))=123456789;
+ if (*(long*)(membase+sizeof(long)) != 123456789 )
+ {
+ fprintf(stderr,"writeback failed !\n");
+ exit(1);
+ }
+ if (!x_taken)
+ {
+ fprintf(stderr,"exception not taken !\n");
+ exit(1);
+ }
+ fprintf(stderr,"vmtest Ok\n");
+ exit(0);
+}
+
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.macros b/tools/build/v2/engine/boehm_gc/doc/README.macros
new file mode 100644
index 0000000000..6a9a1fdcb3
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.macros
@@ -0,0 +1,82 @@
+The collector uses a large amount of conditional compilation in order to
+deal with platform dependencies. This violates a number of known coding
+standards. On the other hand, it seems to be the only practical way to
+support this many platforms without excessive code duplication.
+
+A few guidelines have mostly been followed in order to keep this manageable:
+
+1) #if and #ifdef directives are properly indented whenever easily possible.
+All known C compilers allow whitespace between the "#" and the "if" to make
+this possible. ANSI C also allows white space before the "#", though we
+avoid that. It has the known disadvantages that it differs from the normal
+GNU conventions, and that it makes patches larger than otherwise necessary.
+In my opinion, it's still well worth it, for the same reason that we indent
+ordinary "if" statements.
+
+2) Whenever possible, tests are performed on the macros defined in gcconfig.h
+instead of directly testing patform-specific predefined macros. This makes it
+relatively easy to adapt to new compilers with a different set of predefined
+macros. Currently these macros generally identify platforms instead of
+features. In many cases, this is a mistake.
+
+Many of the tested configuration macros are at least somewhat defined in
+either include/private/gcconfig.h or in Makefile.direct. Here is an attempt
+at defining some of the remainder: (Thanks to Walter Bright for suggesting
+this. This is a work in progress)
+
+MACRO EXPLANATION
+----- -----------
+
+__DMC__ Always #define'd by the Digital Mars compiler. Expands
+ to the compiler version number in hex, i.e. 0x810 is
+ version 8.1b0
+
+_ENABLE_ARRAYNEW
+ #define'd by the Digital Mars C++ compiler when
+ operator new[] and delete[] are separately
+ overloadable. Used in gc_cpp.h.
+
+_MSC_VER Expands to the Visual C++ compiler version. Assumed to
+ not be defined for other compilers (at least if they behave
+ appreciably differently).
+
+_DLL Defined by Visual C++ if dynamic libraries are being built
+ or used. Used to test whether __declspec(dllimport) or
+ __declspec(dllexport) needs to be added to declarations
+ to support the case in which the collector is in a dll.
+
+GC_DLL User-settable macro that forces the effect of _DLL. Set
+ by gc.h if _DLL is defined and GC_NOT_DLL is undefined.
+ This is the macro that is tested internally to determine
+ whether the GC is in its own dynamic library. May need
+ to be set by clients before including gc.h. Note that
+ inside the GC implementation it indicates that the
+ collector is in its own dynamic library, should export
+ its symbols, etc. But in clients it indicates that the
+ GC resides in a different DLL, its entry points should
+ be referenced accordingly, and precautions may need to
+ be taken to properly deal with statically allocated
+ variables in the main program. Used only for MS Windows.
+
+GC_NOT_DLL User-settable macro that overrides _DLL, e.g. if dynamic
+ libraries are used, but the collector is in a static library.
+
+__STDC__ Assumed to be defined only by compilers that understand
+ prototypes and other C89 features. Its value is generally
+ not used, since we are fine with most nonconforming extensions.
+
+SUNOS5SIGS Solaris-like signal handling. This is probably misnamed,
+ since it really doesn't guarantee much more than Posix.
+ Currently set only for Solaris2.X, HPUX, and DRSNX. Should
+ probably be set for some other platforms.
+
+PCR Set if the collector is being built as part of the Xerox
+ Portable Common Runtime.
+
+USE_COMPILER_TLS Assume the existence of __thread-style thread-local
+ storage. Set automatically for thread-local allocation with
+ the HP/UX vendor compiler. Usable with gcc on sufficiently
+ up-to-date ELF platforms.
+
+
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.rs6000 b/tools/build/v2/engine/boehm_gc/doc/README.rs6000
new file mode 100644
index 0000000000..f5630b20a3
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.rs6000
@@ -0,0 +1,9 @@
+We have so far failed to find a good way to determine the stack base.
+It is highly recommended that GC_stackbottom be set explicitly on program
+startup. The supplied value sometimes causes failure under AIX 4.1, though
+it appears to work under 3.X. HEURISTIC2 seems to work under 4.1, but
+involves a substantial performance penalty, and will fail if there is
+no limit on stack size.
+
+There is no thread support. (I assume recent versions of AIX provide
+pthreads? I no longer have access to a machine ...)
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.sgi b/tools/build/v2/engine/boehm_gc/doc/README.sgi
new file mode 100644
index 0000000000..7bdb50a4ef
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.sgi
@@ -0,0 +1,41 @@
+Performance of the incremental collector can be greatly enhanced with
+-DNO_EXECUTE_PERMISSION.
+
+The collector should run with all of the -32, -n32 and -64 ABIs. Remember to
+define the AS macro in the Makefile to be "as -64", or "as -n32".
+
+If you use -DREDIRECT_MALLOC=GC_malloc with C++ code, your code should make
+at least one explicit call to malloc instead of new to ensure that the proper
+version of malloc is linked in.
+
+Sproc threads are not supported in this version, though there may exist other
+ports.
+
+Pthreads support is provided. This requires that:
+
+1) You compile the collector with -DGC_IRIX_THREADS specified in the Makefile.
+
+2) You have the latest pthreads patches installed.
+
+(Though the collector makes only documented pthread calls,
+it relies on signal/threads interactions working just right in ways
+that are not required by the standard. It is unlikely that this code
+will run on other pthreads platforms. But please tell me if it does.)
+
+3) Every file that makes thread calls should define IRIX_THREADS and then
+include gc.h. Gc.h redefines some of the pthread primitives as macros which
+also provide the collector with information it requires.
+
+4) pthread_cond_wait and pthread_cond_timed_wait should be prepared for
+premature wakeups. (I believe the pthreads and realted standards require this
+anyway. Irix pthreads often terminate a wait if a signal arrives.
+The garbage collector uses signals to stop threads.)
+
+5) It is expensive to stop a thread waiting in IO at the time the request is
+initiated. Applications with many such threads may not exhibit acceptable
+performance with the collector. (Increasing the heap size may help.)
+
+6) The collector should not be compiled with -DREDIRECT_MALLOC. This
+confuses some library calls made by the pthreads implementation, which
+expect the standard malloc.
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.solaris2 b/tools/build/v2/engine/boehm_gc/doc/README.solaris2
new file mode 100644
index 0000000000..73620342f3
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.solaris2
@@ -0,0 +1,64 @@
+The collector supports both incremental collection and threads under
+Solaris 2. The incremental collector normally retrieves page dirty information
+through the appropriate /proc calls. But it can also be configured
+(by defining MPROTECT_VDB instead of PROC_VDB in gcconfig.h) to use mprotect
+and signals. This may result in shorter pause times, but it is no longer
+safe to issue arbitrary system calls that write to the heap.
+
+Under other UNIX versions,
+the collector normally obtains memory through sbrk. There is some reason
+to expect that this is not safe if the client program also calls the system
+malloc, or especially realloc. The sbrk man page strongly suggests this is
+not safe: "Many library routines use malloc() internally, so use brk()
+and sbrk() only when you know that malloc() definitely will not be used by
+any library routine." This doesn't make a lot of sense to me, since there
+seems to be no documentation as to which routines can transitively call malloc.
+Nonetheless, under Solaris2, the collector now (since 4.12) allocates
+memory using mmap by default. (It defines USE_MMAP in gcconfig.h.)
+You may want to reverse this decisions if you use -DREDIRECT_MALLOC=...
+
+
+SOLARIS THREADS:
+
+The collector must be compiled with -DGC_SOLARIS_THREADS (thr_ functions)
+or -DGC_THREADS to be thread safe. This assumes use of the pthread_
+interface. Old style Solaris threads are no longer supported.
+
+It is also essential that gc.h be included in files that call thr_create,
+thr_join, thr_suspend, thr_continue, or dlopen. Gc.h macro defines
+these to also do GC bookkeeping, etc. Gc.h must be included with
+one or both of these macros defined, otherwise
+these replacements are not visible.
+A collector built in this way way only be used by programs that are
+linked with the threads library.
+
+Since 5.0 alpha5, dlopen disables collection temporarily,
+unless USE_PROC_FOR_LIBRARIES is defined. In some unlikely cases, this
+can result in unpleasant heap growth. But it seems better than the
+race/deadlock issues we had before.
+
+If solaris_threads are used on an X86 processor with malloc redirected to
+GC_malloc, it is necessary to call GC_thr_init explicitly before forking the
+first thread. (This avoids a deadlock arising from calling GC_thr_init
+with the allocation lock held.)
+
+It appears that there is a problem in using gc_cpp.h in conjunction with
+Solaris threads and Sun's C++ runtime. Apparently the overloaded new operator
+is invoked by some iostream initialization code before threads are correctly
+initialized. As a result, call to thr_self() in garbage collector
+initialization segfaults. Currently the only known workaround is to not
+invoke the garbage collector from a user defined global operator new, or to
+have it invoke the garbage-collector's allocators only after main has started.
+(Note that the latter requires a moderately expensive test in operator
+delete.)
+
+I encountered "symbol <unknown>: offet .... is non-aligned" errors. These
+appear to be traceable to the use of the GNU assembler with the Sun linker.
+The former appears to generate a relocation not understood by the latter.
+The fix appears to be to use a consistent tool chain. (As a non-Solaris-expert
+my solution involved hacking the libtool script, but I'm sure you can
+do something less ugly.)
+
+Hans-J. Boehm
+(The above contains my personal opinions, which are probably not shared
+by anyone else.)
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.uts b/tools/build/v2/engine/boehm_gc/doc/README.uts
new file mode 100644
index 0000000000..6be49667d7
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.uts
@@ -0,0 +1,2 @@
+Alistair Crooks supplied the port. He used Lexa C version 2.1.3 with
+-Xa to compile.
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.win32 b/tools/build/v2/engine/boehm_gc/doc/README.win32
new file mode 100644
index 0000000000..1dce2b9e78
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.win32
@@ -0,0 +1,221 @@
+The collector has at various times been compiled under Windows 95 & later, NT,
+and XP, with the original Microsoft SDK, with Visual C++ 2.0, 4.0, and 6, with
+the GNU win32 tools, with Borland 4.5, with Watcom C, and recently
+with the Digital Mars compiler. It is likely that some of these have been
+broken in the meantime. Patches are appreciated.
+
+For historical reasons,
+the collector test program "gctest" is linked as a GUI application,
+but does not open any windows. Its output normally appears in the file
+"gctest.exe.log". It may be started from the file manager. The hour glass
+cursor may appear as long as it's running. If it is started from the
+command line, it will usually run in the background. Wait a few
+minutes (a few seconds on a modern machine) before you check the output.
+You should see either a failure indication or a "Collector appears to
+work" message.
+
+The cord test program has not been ported (but should port
+easily). A toy editor (cord/de.exe) based on cords (heavyweight
+strings represented as trees) has been ported and is included.
+It runs fine under either win32 or win32S. It serves as an example
+of a true Windows application, except that it was written by a
+nonexpert Windows programmer. (There are some peculiarities
+in the way files are displayed. The <cr> is displayed explicitly
+for standard DOS text files. As in the UNIX version, control
+characters are displayed explicitly, but in this case as red text.
+This may be suboptimal for some tastes and/or sets of default
+window colors.)
+
+In general -DREDIRECT_MALLOC is unlikely to work unless the
+application is completely statically linked.
+
+The collector normally allocates memory from the OS with VirtualAlloc.
+This appears to cause problems under Windows NT and Windows 2000 (but
+not Windows 95/98) if the memory is later passed to CreateDIBitmap.
+To work around this problem, build the collector with -DUSE_GLOBAL_ALLOC.
+This is currently incompatible with -DUSE_MUNMAP. (Thanks to Jonathan
+Clark for tracking this down. There's some chance this may be fixed
+in 6.1alpha4, since we now separate heap sections with an unused page.)
+
+[Threads and incremental collection are discussed near the end, below.]
+
+Microsoft Tools
+---------------
+For Microsoft development tools, rename NT_MAKEFILE as
+MAKEFILE. (Make sure that the CPU environment variable is defined
+to be i386.) In order to use the gc_cpp.h C++ interface, all
+client code should include gc_cpp.h.
+
+For historical reasons,
+the collector test program "gctest" is linked as a GUI application,
+but does not open any windows. Its output appears in the file
+"gc.log". It may be started from the file manager. The hour glass
+cursor may appear as long as it's running. If it is started from the
+command line, it will usually run in the background. Wait a few
+minutes (a few seconds on a modern machine) before you check the output.
+You should see either a failure indication or a "Collector appears to
+work" message.
+
+If you would prefer a VC++.NET project file, ask boehm@acm.org. One has
+been contributed, but it seems to contain some absolute paths etc., so
+it can presumably only be a starting point, and is not in the standard
+distribution. It is unclear (to me, Hans Boehm) whether it is feasible to
+change that.
+
+Clients may need to define GC_NOT_DLL before including gc.h, if the
+collector was built as a static library (as it normally is in the
+absence of thread support).
+
+GNU Tools
+---------
+The collector should be buildable under Cygwin with either the old standard
+Makefile, or possibly with the "configure --diable-shared;make" machinery.
+(For the latter use --enable-threads=posix for thread support.) The major issue
+here seems to be that dynamic library support is not currently enabled for
+Cygwin. (This is probably fixable without a great deal of difficulty by
+reusing the standard WIN32 code. But it requires some tweaking.) As a result
+of this, "configure; make; make check" currently does not completely succeed,
+though the static library appears to be OK when used only from the main
+programs, and correspondingly the Makefile.direct self tests succeed.
+
+Mingw32 builds are not regularly tested, and may or may not work.
+The following paragraph is probably obsolete:
+
+For GNU-win32, use the regular makefile, possibly after uncommenting
+the line "include Makefile.DLLs". The latter should be necessary only
+if you want to package the collector as a DLL.
+[Is the following sentence obsolete? -HB] The GNU-win32 port is
+believed to work only for b18, not b19, probably due to linker changes
+in b19. This is probably fixable with a different definition of
+DATASTART and DATAEND in gcconfig.h.
+
+Borland Tools
+-------------
+[Rarely tested.]
+For Borland tools, use BCC_MAKEFILE. Note that
+Borland's compiler defaults to 1 byte alignment in structures (-a1),
+whereas Visual C++ appears to default to 8 byte alignment (/Zp8).
+The garbage collector in its default configuration EXPECTS AT
+LEAST 4 BYTE ALIGNMENT. Thus the BORLAND DEFAULT MUST
+BE OVERRIDDEN. (In my opinion, it should usually be anyway.
+I expect that -a1 introduces major performance penalties on a
+486 or Pentium.) Note that this changes structure layouts. (As a last
+resort, gcconfig.h can be changed to allow 1 byte alignment. But
+this has significant negative performance implications.)
+The Makefile is set up to assume Borland 4.5. If you have another
+version, change the line near the top. By default, it does not
+require the assembler. If you do have the assembler, I recommend
+removing the -DUSE_GENERIC.
+
+
+Watcom compiler
+---------------
+
+Ivan V. Demakov's README for the Watcom port:
+
+The collector has been compiled with Watcom C 10.6 and 11.0.
+It runs under win32, win32s, and even under msdos with dos4gw
+dos-extender. It should also run under OS/2, though this isn't
+tested. Under win32 the collector can be built either as dll
+or as static library.
+
+Note that all compilations were done under Windows 95 or NT.
+For unknown reason compiling under Windows 3.11 for NT (one
+attempt has been made) leads to broken executables.
+
+Incremental collection is not supported.
+
+cord is not ported.
+
+Before compiling you may need to edit WCC_MAKEFILE to set target
+platform, library type (dynamic or static), calling conventions, and
+optimization options.
+
+To compile the collector and testing programs use the command:
+ wmake -f WCC_MAKEFILE
+
+All programs using gc should be compiled with 4-byte alignment.
+For further explanations on this see comments about Borland.
+
+If the gc is compiled as dll, the macro ``GC_DLL'' should be defined before
+including "gc.h" (for example, with -DGC_DLL compiler option). It's
+important, otherwise resulting programs will not run.
+
+Ivan Demakov (email: ivan@tgrad.nsk.su)
+
+Incremental Collection
+----------------------
+There is some support for incremental collection. By default, the
+collector chooses between explicit page protection, anf GetWriteWatch-based
+write tracking automatically, depending on the platform.
+
+The former is slow and interacts poorly with a debugger.
+Pages are protected. Protection faults are caught by a handler
+installed at the bottom of the handler
+stack. Whenever possible, I recommend adding a call to
+GC_enable_incremental at the last possible moment, after most
+debugging is complete. No system
+calls are wrapped by the collector itself. It may be necessary
+to wrap ReadFile calls that use a buffer in the heap, so that the
+call does not encounter a protection fault while it's running.
+(As usual, none of this is an issue unless GC_enable_incremental
+is called.)
+
+Note that incremental collection is disabled with -DSMALL_CONFIG.
+
+Threads
+-------
+
+This version of the collector by default handles threads similarly
+to other platforms. James Clark's code which tracks threads attached
+to the collector DLL still exists, but requires that both
+- the collector is built in a DLL with GC_DLL defined, and
+- GC_use_DllMain() is called before GC initialization, which
+ in turn must happen before creating additional threads.
+We generally recommend avoiding this if possible, since it seems to
+be less than 100% reliable.
+
+Use NT_THREADS_MAKEFILE (a.k.a gc.mak) instead of NT_MAKEFILE
+to build a version that supports both kinds of thread tracking.
+To build the garbage collector
+test with VC++ from the command line, use
+
+nmake /F ".\gc.mak" CFG="gctest - Win32 Release"
+
+This requires that the subdirectory gctest\Release exist.
+The test program and DLL will reside in the Release directory.
+
+This version currently supports incremental collection only if it is
+enabled before any additional threads are created.
+
+Since 6.3alpha2, threads are also better supported in static library builds
+with Microsoft tools (use NT_STATIC_THREADS_MAKEFILE) and with the GNU
+tools. In all cases,the collector must be built with GC_WIN32_THREADS
+defined, even if the Cygwin pthreads interface is used.
+(NT_STATIC_THREADS_MAKEFILE does this implicitly. Under Cygwin,
+./configure --enable-threads=posix defines GC_WIN32_THREADS.)
+
+For the normal, non-dll-based thread tracking to work properly,
+threads should be created with GC_CreateThread or GC_beginthreadex,
+and exit normally or call GC_endthreadex or GC_ExitThread. (For
+Cygwin, use standard pthread calls instead.) As in the pthread
+case, including gc.h will redefine CreateThread, _beginthreadex,
+_endthreadex, and ExitThread to call the GC_ versions instead.
+
+Note that, as usual, GC_CreateThread tends to introduce resource leaks
+that are avoided by GC_beginthreadex. There is currently no equivalent of
+_beginthread, and it should not be used.
+
+GC_INIT should be called from the main executable before other GC calls.
+
+We strongly advise against using the TerminateThread() win32 API call,
+especially with the garbage collector. Any use is likely to provoke a
+crash in the GC, since it makes it impossible for the collector to
+correctly track threads.
+
+To build the collector for Mingw32 Pthreads, use Makefile.direct and
+explicitly set GC_WIN32_PTHREADS. Use -DPTW32_STATIC_LIB for the static
+threads library. Note that the DEBUG_WIN32_PTHREADS support in
+win32_threads.c is currently broken and looking for someone to debug it.
+(This information and the port came from Romano Paolo Tenca).
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/README.win64 b/tools/build/v2/engine/boehm_gc/doc/README.win64
new file mode 100644
index 0000000000..9db0e78c61
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/README.win64
@@ -0,0 +1,17 @@
+64-bit Windows on AMD64/Intel EM64T is somewhat supported in the 7.0
+release. A collector can be built with Microsoft Visual C++ 2005.
+The resulting test programs have been known to work at least once.
+More testing would clearly be helpful.
+
+Currently only NT_X64_STATIC_THREADS_MAKEFILE has been used in
+this environment. Copy this file to MAKEFILE, and then type "nmake"
+in a Visual C++ command line window to build the static library
+and the usual test programs. To verify that the colllector is
+at least somewhat functional, run gctest.exe. This should create
+gctest.exe.log after a few seconds.
+
+This process is completely analogous to NT_STATIC_THREADS_MAKEFILE
+for the 32-bit version.
+
+Note that currently a few warnings are still generated by default,
+and a number of others have been explicitly turned off in the makefile.
diff --git a/tools/build/v2/engine/boehm_gc/doc/barrett_diagram b/tools/build/v2/engine/boehm_gc/doc/barrett_diagram
new file mode 100644
index 0000000000..27e80dc15c
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/barrett_diagram
@@ -0,0 +1,106 @@
+This is an ASCII diagram of the data structure used to check pointer
+validity. It was provided by Dave Barrett <barrett@asgard.cs.colorado.edu>,
+and should be of use to others attempting to understand the code.
+The data structure in GC4.X is essentially the same. -HB
+
+
+
+
+ Data Structure used by GC_base in gc3.7:
+ 21-Apr-94
+
+
+
+
+ 63 LOG_TOP_SZ[11] LOG_BOTTOM_SZ[10] LOG_HBLKSIZE[13]
+ +------------------+----------------+------------------+------------------+
+ p:| | TL_HASH(hi) | | HBLKDISPL(p) |
+ +------------------+----------------+------------------+------------------+
+ \-----------------------HBLKPTR(p)-------------------/
+ \------------hi-------------------/
+ \______ ________/ \________ _______/ \________ _______/
+ V V V
+ | | |
+ GC_top_index[] | | |
+ --- +--------------+ | | |
+ ^ | | | | |
+ | | | | | |
+ TOP +--------------+<--+ | |
+ _SZ +-<| [] | * | |
+(items)| +--------------+ if 0 < bi< HBLKSIZE | |
+ | | | | then large object | |
+ | | | | starts at the bi'th | |
+ v | | | HBLK before p. | i |
+ --- | +--------------+ | (word- |
+ v | aligned) |
+ bi= |GET_BI(p){->hash_link}->key==hi | |
+ v | |
+ | (bottom_index) \ scratch_alloc'd | |
+ | ( struct bi ) / by get_index() | |
+ --- +->+--------------+ | |
+ ^ | | | |
+ ^ | | | |
+ BOTTOM | | ha=GET_HDR_ADDR(p) | |
+_SZ(items)+--------------+<----------------------+ +-------+
+ | +--<| index[] | |
+ | | +--------------+ GC_obj_map: v
+ | | | | from / +-+-+-----+-+-+-+-+ ---
+ v | | | GC_add < 0| | | | | | | | ^
+ --- | +--------------+ _map_entry \ +-+-+-----+-+-+-+-+ |
+ | | asc_link | +-+-+-----+-+-+-+-+ MAXOBJSZ
+ | +--------------+ +-->| | | j | | | | | +1
+ | | key | | +-+-+-----+-+-+-+-+ |
+ | +--------------+ | +-+-+-----+-+-+-+-+ |
+ | | hash_link | | | | | | | | | | v
+ | +--------------+ | +-+-+-----+-+-+-+-+ ---
+ | | |<--MAX_OFFSET--->|
+ | | (bytes)
+HDR(p)| GC_find_header(p) | |<--MAP_ENTRIES-->|
+ | \ from | =HBLKSIZE/WORDSZ
+ | (hdr) (struct hblkhdr) / alloc_hdr() | (1024 on Alpha)
+ +-->+----------------------+ | (8/16 bits each)
+GET_HDR(p)| word hb_sz (words) | |
+ +----------------------+ |
+ | struct hblk *hb_next | |
+ +----------------------+ |
+ |mark_proc hb_mark_proc| |
+ +----------------------+ |
+ | char * hb_map |>-------------+
+ +----------------------+
+ | ushort hb_obj_kind |
+ +----------------------+
+ | hb_last_reclaimed |
+ --- +----------------------+
+ ^ | |
+ MARK_BITS| hb_marks[] | *if hdr is free, hb_sz + DISCARD_WORDS
+_SZ(words)| | is the size of a heap chunk (struct hblk)
+ v | | of at least MININCR*HBLKSIZE bytes (below),
+ --- +----------------------+ otherwise, size of each object in chunk.
+
+Dynamic data structures above are interleaved throughout the heap in blocks of
+size MININCR * HBLKSIZE bytes as done by gc_scratch_alloc which cannot be
+freed; free lists are used (e.g. alloc_hdr). HBLKs's below are collected.
+
+ (struct hblk)
+ --- +----------------------+ < HBLKSIZE --- --- DISCARD_
+ ^ |garbage[DISCARD_WORDS]| aligned ^ ^ HDR_BYTES WORDS
+ | | | | v (bytes) (words)
+ | +-----hb_body----------+ < WORDSZ | --- ---
+ | | | aligned | ^ ^
+ | | Object 0 | | hb_sz |
+ | | | i |(word- (words)|
+ | | | (bytes)|aligned) v |
+ | + - - - - - - - - - - -+ --- | --- |
+ | | | ^ | ^ |
+ n * | | j (words) | hb_sz BODY_SZ
+ HBLKSIZE | Object 1 | v v | (words)
+ (bytes) | |--------------- v MAX_OFFSET
+ | + - - - - - - - - - - -+ --- (bytes)
+ | | | !All_INTERIOR_PTRS ^ |
+ | | | sets j only for hb_sz |
+ | | Object N | valid object offsets. | |
+ v | | All objects WORDSZ v v
+ --- +----------------------+ aligned. --- ---
+
+DISCARD_WORDS is normally zero. Indeed the collector has not been tested
+with another value in ages.
diff --git a/tools/build/v2/engine/boehm_gc/doc/debugging.html b/tools/build/v2/engine/boehm_gc/doc/debugging.html
new file mode 100644
index 0000000000..7c65f2bb40
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/debugging.html
@@ -0,0 +1,306 @@
+<HTML>
+<HEAD>
+<TITLE>Debugging Garbage Collector Related Problems</title>
+</head>
+<BODY>
+<H1>Debugging Garbage Collector Related Problems</h1>
+This page contains some hints on
+debugging issues specific to
+the Boehm-Demers-Weiser conservative garbage collector.
+It applies both to debugging issues in client code that manifest themselves
+as collector misbehavior, and to debugging the collector itself.
+<P>
+If you suspect a bug in the collector itself, it is strongly recommended
+that you try the latest collector release, even if it is labelled as "alpha",
+before proceeding.
+<H2>Bus Errors and Segmentation Violations</h2>
+<P>
+If the fault occurred in GC_find_limit, or with incremental collection enabled,
+this is probably normal. The collector installs handlers to take care of
+these. You will not see these unless you are using a debugger.
+Your debugger <I>should</i> allow you to continue.
+It's often preferable to tell the debugger to ignore SIGBUS and SIGSEGV
+("<TT>handle SIGSEGV SIGBUS nostop noprint</tt>" in gdb,
+"<TT>ignore SIGSEGV SIGBUS</tt>" in most versions of dbx)
+and set a breakpoint in <TT>abort</tt>.
+The collector will call abort if the signal had another cause,
+and there was not other handler previously installed.
+<P>
+We recommend debugging without incremental collection if possible.
+(This applies directly to UNIX systems.
+Debugging with incremental collection under win32 is worse. See README.win32.)
+<P>
+If the application generates an unhandled SIGSEGV or equivalent, it may
+often be easiest to set the environment variable GC_LOOP_ON_ABORT. On many
+platforms, this will cause the collector to loop in a handler when the
+SIGSEGV is encountered (or when the collector aborts for some other reason),
+and a debugger can then be attached to the looping
+process. This sidesteps common operating system problems related
+to incomplete core files for multithreaded applications, etc.
+<H2>Other Signals</h2>
+On most platforms, the multithreaded version of the collector needs one or
+two other signals for internal use by the collector in stopping threads.
+It is normally wise to tell the debugger to ignore these. On Linux,
+the collector currently uses SIGPWR and SIGXCPU by default.
+<H2>Warning Messages About Needing to Allocate Blacklisted Blocks</h2>
+The garbage collector generates warning messages of the form
+<PRE>
+Needed to allocate blacklisted block at 0x...
+</pre>
+or
+<PRE>
+Repeated allocation of very large block ...
+</pre>
+when it needs to allocate a block at a location that it knows to be
+referenced by a false pointer. These false pointers can be either permanent
+(<I>e.g.</i> a static integer variable that never changes) or temporary.
+In the latter case, the warning is largely spurious, and the block will
+eventually be reclaimed normally.
+In the former case, the program will still run correctly, but the block
+will never be reclaimed. Unless the block is intended to be
+permanent, the warning indicates a memory leak.
+<OL>
+<LI>Ignore these warnings while you are using GC_DEBUG. Some of the routines
+mentioned below don't have debugging equivalents. (Alternatively, write
+the missing routines and send them to me.)
+<LI>Replace allocator calls that request large blocks with calls to
+<TT>GC_malloc_ignore_off_page</tt> or
+<TT>GC_malloc_atomic_ignore_off_page</tt>. You may want to set a
+breakpoint in <TT>GC_default_warn_proc</tt> to help you identify such calls.
+Make sure that a pointer to somewhere near the beginning of the resulting block
+is maintained in a (preferably volatile) variable as long as
+the block is needed.
+<LI>
+If the large blocks are allocated with realloc, we suggest instead allocating
+them with something like the following. Note that the realloc size increment
+should be fairly large (e.g. a factor of 3/2) for this to exhibit reasonable
+performance. But we all know we should do that anyway.
+<PRE>
+void * big_realloc(void *p, size_t new_size)
+{
+ size_t old_size = GC_size(p);
+ void * result;
+
+ if (new_size <= 10000) return(GC_realloc(p, new_size));
+ if (new_size <= old_size) return(p);
+ result = GC_malloc_ignore_off_page(new_size);
+ if (result == 0) return(0);
+ memcpy(result,p,old_size);
+ GC_free(p);
+ return(result);
+}
+</pre>
+
+<LI> In the unlikely case that even relatively small object
+(&lt;20KB) allocations are triggering these warnings, then your address
+space contains lots of "bogus pointers", i.e. values that appear to
+be pointers but aren't. Usually this can be solved by using GC_malloc_atomic
+or the routines in gc_typed.h to allocate large pointer-free regions of bitmaps, etc. Sometimes the problem can be solved with trivial changes of encoding
+in certain values. It is possible, to identify the source of the bogus
+pointers by building the collector with <TT>-DPRINT_BLACK_LIST</tt>,
+which will cause it to print the "bogus pointers", along with their location.
+
+<LI> If you get only a fixed number of these warnings, you are probably only
+introducing a bounded leak by ignoring them. If the data structures being
+allocated are intended to be permanent, then it is also safe to ignore them.
+The warnings can be turned off by calling GC_set_warn_proc with a procedure
+that ignores these warnings (e.g. by doing absolutely nothing).
+</ol>
+
+<H2>The Collector References a Bad Address in <TT>GC_malloc</tt></h2>
+
+This typically happens while the collector is trying to remove an entry from
+its free list, and the free list pointer is bad because the free list link
+in the last allocated object was bad.
+<P>
+With &gt; 99% probability, you wrote past the end of an allocated object.
+Try setting <TT>GC_DEBUG</tt> before including <TT>gc.h</tt> and
+allocating with <TT>GC_MALLOC</tt>. This will try to detect such
+overwrite errors.
+
+<H2>Unexpectedly Large Heap</h2>
+
+Unexpected heap growth can be due to one of the following:
+<OL>
+<LI> Data structures that are being unintentionally retained. This
+is commonly caused by data structures that are no longer being used,
+but were not cleared, or by caches growing without bounds.
+<LI> Pointer misidentification. The garbage collector is interpreting
+integers or other data as pointers and retaining the "referenced"
+objects. A common symptom is that GC_dump() shows much of the heap
+as black-listed.
+<LI> Heap fragmentation. This should never result in unbounded growth,
+but it may account for larger heaps. This is most commonly caused
+by allocation of large objects. On some platforms it can be reduced
+by building with -DUSE_MUNMAP, which will cause the collector to unmap
+memory corresponding to pages that have not been recently used.
+<LI> Per object overhead. This is usually a relatively minor effect, but
+it may be worth considering. If the collector recognizes interior
+pointers, object sizes are increased, so that one-past-the-end pointers
+are correctly recognized. The collector can be configured not to do this
+(<TT>-DDONT_ADD_BYTE_AT_END</tt>).
+<P>
+The collector rounds up object sizes so the result fits well into the
+chunk size (<TT>HBLKSIZE</tt>, normally 4K on 32 bit machines, 8K
+on 64 bit machines) used by the collector. Thus it may be worth avoiding
+objects of size 2K + 1 (or 2K if a byte is being added at the end.)
+</ol>
+The last two cases can often be identified by looking at the output
+of a call to <TT>GC_dump()</tt>. Among other things, it will print the
+list of free heap blocks, and a very brief description of all chunks in
+the heap, the object sizes they correspond to, and how many live objects
+were found in the chunk at the last collection.
+<P>
+Growing data structures can usually be identified by
+<OL>
+<LI> Building the collector with <TT>-DKEEP_BACK_PTRS</tt>,
+<LI> Preferably using debugging allocation (defining <TT>GC_DEBUG</tt>
+before including <TT>gc.h</tt> and allocating with <TT>GC_MALLOC</tt>),
+so that objects will be identified by their allocation site,
+<LI> Running the application long enough so
+that most of the heap is composed of "leaked" memory, and
+<LI> Then calling <TT>GC_generate_random_backtrace()</tt> from backptr.h
+a few times to determine why some randomly sampled objects in the heap are
+being retained.
+</ol>
+<P>
+The same technique can often be used to identify problems with false
+pointers, by noting whether the reference chains printed by
+<TT>GC_generate_random_backtrace()</tt> involve any misidentified pointers.
+An alternate technique is to build the collector with
+<TT>-DPRINT_BLACK_LIST</tt> which will cause it to report values that
+are almost, but not quite, look like heap pointers. It is very likely that
+actual false pointers will come from similar sources.
+<P>
+In the unlikely case that false pointers are an issue, it can usually
+be resolved using one or more of the following techniques:
+<OL>
+<LI> Use <TT>GC_malloc_atomic</tt> for objects containing no pointers.
+This is especially important for large arrays containing compressed data,
+pseudo-random numbers, and the like. It is also likely to improve GC
+performance, perhaps drastically so if the application is paging.
+<LI> If you allocate large objects containing only
+one or two pointers at the beginning, either try the typed allocation
+primitives is <TT>gc_typed.h</tt>, or separate out the pointerfree component.
+<LI> Consider using <TT>GC_malloc_ignore_off_page()</tt>
+to allocate large objects. (See <TT>gc.h</tt> and above for details.
+Large means &gt; 100K in most environments.)
+<LI> If your heap size is larger than 100MB or so, build the collector with
+-DLARGE_CONFIG. This allows the collector to keep more precise black-list
+information.
+<LI> If you are using heaps close to, or larger than, a gigabyte on a 32-bit
+machine, you may want to consider moving to a platform with 64-bit pointers.
+This is very likely to resolve any false pointer issues.
+</ol>
+<H2>Prematurely Reclaimed Objects</h2>
+The usual symptom of this is a segmentation fault, or an obviously overwritten
+value in a heap object. This should, of course, be impossible. In practice,
+it may happen for reasons like the following:
+<OL>
+<LI> The collector did not intercept the creation of threads correctly in
+a multithreaded application, <I>e.g.</i> because the client called
+<TT>pthread_create</tt> without including <TT>gc.h</tt>, which redefines it.
+<LI> The last pointer to an object in the garbage collected heap was stored
+somewhere were the collector couldn't see it, <I>e.g.</i> in an
+object allocated with system <TT>malloc</tt>, in certain types of
+<TT>mmap</tt>ed files,
+or in some data structure visible only to the OS. (On some platforms,
+thread-local storage is one of these.)
+<LI> The last pointer to an object was somehow disguised, <I>e.g.</i> by
+XORing it with another pointer.
+<LI> Incorrect use of <TT>GC_malloc_atomic</tt> or typed allocation.
+<LI> An incorrect <TT>GC_free</tt> call.
+<LI> The client program overwrote an internal garbage collector data structure.
+<LI> A garbage collector bug.
+<LI> (Empirically less likely than any of the above.) A compiler optimization
+that disguised the last pointer.
+</ol>
+The following relatively simple techniques should be tried first to narrow
+down the problem:
+<OL>
+<LI> If you are using the incremental collector try turning it off for
+debugging.
+<LI> If you are using shared libraries, try linking statically. If that works,
+ensure that DYNAMIC_LOADING is defined on your platform.
+<LI> Try to reproduce the problem with fully debuggable unoptimized code.
+This will eliminate the last possibility, as well as making debugging easier.
+<LI> Try replacing any suspect typed allocation and <TT>GC_malloc_atomic</tt>
+calls with calls to <TT>GC_malloc</tt>.
+<LI> Try removing any GC_free calls (<I>e.g.</i> with a suitable
+<TT>#define</tt>).
+<LI> Rebuild the collector with <TT>-DGC_ASSERTIONS</tt>.
+<LI> If the following works on your platform (i.e. if gctest still works
+if you do this), try building the collector with
+<TT>-DREDIRECT_MALLOC=GC_malloc_uncollectable</tt>. This will cause
+the collector to scan memory allocated with malloc.
+</ol>
+If all else fails, you will have to attack this with a debugger.
+Suggested steps:
+<OL>
+<LI> Call <TT>GC_dump()</tt> from the debugger around the time of the failure. Verify
+that the collectors idea of the root set (i.e. static data regions which
+it should scan for pointers) looks plausible. If not, i.e. if it doesn't
+include some static variables, report this as
+a collector bug. Be sure to describe your platform precisely, since this sort
+of problem is nearly always very platform dependent.
+<LI> Especially if the failure is not deterministic, try to isolate it to
+a relatively small test case.
+<LI> Set a break point in <TT>GC_finish_collection</tt>. This is a good
+point to examine what has been marked, i.e. found reachable, by the
+collector.
+<LI> If the failure is deterministic, run the process
+up to the last collection before the failure.
+Note that the variable <TT>GC_gc_no</tt> counts collections and can be used
+to set a conditional breakpoint in the right one. It is incremented just
+before the call to GC_finish_collection.
+If object <TT>p</tt> was prematurely recycled, it may be helpful to
+look at <TT>*GC_find_header(p)</tt> at the failure point.
+The <TT>hb_last_reclaimed</tt> field will identify the collection number
+during which its block was last swept.
+<LI> Verify that the offending object still has its correct contents at
+this point.
+Then call <TT>GC_is_marked(p)</tt> from the debugger to verify that the
+object has not been marked, and is about to be reclaimed. Note that
+<TT>GC_is_marked(p)</tt> expects the real address of an object (the
+address of the debug header if there is one), and thus it may
+be more appropriate to call <TT>GC_is_marked(GC_base(p))</tt>
+instead.
+<LI> Determine a path from a root, i.e. static variable, stack, or
+register variable,
+to the reclaimed object. Call <TT>GC_is_marked(q)</tt> for each object
+<TT>q</tt> along the path, trying to locate the first unmarked object, say
+<TT>r</tt>.
+<LI> If <TT>r</tt> is pointed to by a static root,
+verify that the location
+pointing to it is part of the root set printed by <TT>GC_dump()</tt>. If it
+is on the stack in the main (or only) thread, verify that
+<TT>GC_stackbottom</tt> is set correctly to the base of the stack. If it is
+in another thread stack, check the collector's thread data structure
+(<TT>GC_thread[]</tt> on several platforms) to make sure that stack bounds
+are set correctly.
+<LI> If <TT>r</tt> is pointed to by heap object <TT>s</tt>, check that the
+collector's layout description for <TT>s</tt> is such that the pointer field
+will be scanned. Call <TT>*GC_find_header(s)</tt> to look at the descriptor
+for the heap chunk. The <TT>hb_descr</tt> field specifies the layout
+of objects in that chunk. See gc_mark.h for the meaning of the descriptor.
+(If it's low order 2 bits are zero, then it is just the length of the
+object prefix to be scanned. This form is always used for objects allocated
+with <TT>GC_malloc</tt> or <TT>GC_malloc_atomic</tt>.)
+<LI> If the failure is not deterministic, you may still be able to apply some
+of the above technique at the point of failure. But remember that objects
+allocated since the last collection will not have been marked, even if the
+collector is functioning properly. On some platforms, the collector
+can be configured to save call chains in objects for debugging.
+Enabling this feature will also cause it to save the call stack at the
+point of the last GC in GC_arrays._last_stack.
+<LI> When looking at GC internal data structures remember that a number
+of <TT>GC_</tt><I>xxx</i> variables are really macro defined to
+<TT>GC_arrays._</tt><I>xxx</i>, so that
+the collector can avoid scanning them.
+</ol>
+</body>
+</html>
+
+
+
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/doc.am b/tools/build/v2/engine/boehm_gc/doc/doc.am
new file mode 100644
index 0000000000..8d5f67d333
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/doc.am
@@ -0,0 +1,55 @@
+#
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose, provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+#
+# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
+# Modified by: Petter Urkedal <petter.urkedal@nordita.dk>
+
+## Process this file with automake to produce Makefile.in.
+
+# installed documentation
+#
+dist_pkgdata_DATA = \
+ doc/barrett_diagram \
+ doc/debugging.html \
+ doc/gc.man \
+ doc/gcdescr.html \
+ doc/README \
+ doc/README.amiga \
+ doc/README.arm.cross \
+ doc/README.autoconf \
+ doc/README.changes \
+ doc/README.contributors \
+ doc/README.cords \
+ doc/README.DGUX386 \
+ doc/README.dj \
+ doc/README.environment \
+ doc/README.ews4800 \
+ doc/README.hp \
+ doc/README.linux \
+ doc/README.Mac \
+ doc/README.MacOSX \
+ doc/README.macros \
+ doc/README.OS2 \
+ doc/README.rs6000 \
+ doc/README.sgi \
+ doc/README.solaris2 \
+ doc/README.uts \
+ doc/README.win32 \
+ doc/README.win64 \
+ doc/overview.html \
+ doc/tree.html \
+ doc/leak.html \
+ doc/gcinterface.html \
+ doc/scale.html \
+ doc/README.darwin \
+ doc/simple_example.html \
+ doc/porting.html
+
diff --git a/tools/build/v2/engine/boehm_gc/doc/gc.man b/tools/build/v2/engine/boehm_gc/doc/gc.man
new file mode 100644
index 0000000000..2a550c7124
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/gc.man
@@ -0,0 +1,97 @@
+.TH GC_MALLOC 1L "2 October 2003"
+.SH NAME
+GC_malloc, GC_malloc_atomic, GC_free, GC_realloc, GC_enable_incremental, GC_register_finalizer, GC_malloc_ignore_off_page, GC_malloc_atomic_ignore_off_page, GC_set_warn_proc \- Garbage collecting malloc replacement
+.SH SYNOPSIS
+#include "gc.h"
+.br
+void * GC_malloc(size_t size);
+.br
+void GC_free(void *ptr);
+.br
+void * GC_realloc(void *ptr, size_t size);
+.br
+.sp
+cc ... gc.a
+.LP
+.SH DESCRIPTION
+.I GC_malloc
+and
+.I GC_free
+are plug-in replacements for standard malloc and free. However,
+.I
+GC_malloc
+will attempt to reclaim inaccessible space automatically by invoking a conservative garbage collector at appropriate points. The collector traverses all data structures accessible by following pointers from the machines registers, stack(s), data, and bss segments. Inaccessible structures will be reclaimed. A machine word is considered to be a valid pointer if it is an address inside an object allocated by
+.I
+GC_malloc
+or friends.
+.LP
+In most cases it is preferable to call the macros GC_MALLOC, GC_FREE, etc.
+instead of calling GC_malloc and friends directly. This allows debugging
+versions of the routines to be substituted by defining GC_DEBUG before
+including gc.h.
+.LP
+See the documentation in the include file gc_cpp.h for an alternate, C++ specific interface to the garbage collector.
+.LP
+Unlike the standard implementations of malloc,
+.I
+GC_malloc
+clears the newly allocated storage.
+.I
+GC_malloc_atomic
+does not. Furthermore, it informs the collector that the resulting object will never contain any pointers, and should therefore not be scanned by the collector.
+.LP
+.I
+GC_free
+can be used to deallocate objects, but its use is optional, and generally discouraged.
+.I
+GC_realloc
+has the standard realloc semantics. It preserves pointer-free-ness.
+.I
+GC_register_finalizer
+allows for registration of functions that are invoked when an object becomes inaccessible.
+.LP
+The garbage collector tries to avoid allocating memory at locations that already appear to be referenced before allocation. (Such apparent ``pointers'' are usually large integers and the like that just happen to look like an address.) This may make it hard to allocate very large objects. An attempt to do so may generate a warning.
+.LP
+.I
+GC_malloc_ignore_off_page
+and
+.I
+GC_malloc_atomic_ignore_off_page
+inform the collector that the client code will always maintain a pointer to near the beginning of the object (within the first 512 bytes), and that pointers beyond that can be ignored by the collector. This makes it much easier for the collector to place large objects. These are recommended for large object allocation. (Objects expected to be larger than about 100KBytes should be allocated this way.)
+.LP
+It is also possible to use the collector to find storage leaks in programs destined to be run with standard malloc/free. The collector can be compiled for thread-safe operation. Unlike standard malloc, it is safe to call malloc after a previous malloc call was interrupted by a signal, provided the original malloc call is not resumed.
+.LP
+The collector may, on rare occasion produce warning messages. On UNIX machines these appear on stderr. Warning messages can be filtered, redirected, or ignored with
+.I
+GC_set_warn_proc
+This is recommended for production code. See gc.h for details.
+.LP
+Fully portable code should call
+.I
+GC_INIT
+from the main program before making any other GC calls.
+On most platforms this does nothing and the collector is initialized on first use.
+On a few platforms explicit initialization is necessary. And it can never hurt.
+.LP
+Debugging versions of many of the above routines are provided as macros. Their names are identical to the above, but consist of all capital letters. If GC_DEBUG is defined before gc.h is included, these routines do additional checking, and allow the leak detecting version of the collector to produce slightly more useful output. Without GC_DEBUG defined, they behave exactly like the lower-case versions.
+.LP
+On some machines, collection will be performed incrementally after a call to
+.I
+GC_enable_incremental.
+This may temporarily write protect pages in the heap. See the README file for more information on how this interacts with system calls that write to the heap.
+.LP
+Other facilities not discussed here include limited facilities to support incremental collection on machines without appropriate VM support, provisions for providing more explicit object layout information to the garbage collector, more direct support for ``weak'' pointers, support for ``abortable'' garbage collections during idle time, etc.
+.LP
+.SH "SEE ALSO"
+The README and gc.h files in the distribution. More detailed definitions of the functions exported by the collector are given there. (The above list is not complete.)
+.LP
+The web site at http://www.hpl.hp.com/personal/Hans_Boehm/gc .
+.LP
+Boehm, H., and M. Weiser, "Garbage Collection in an Uncooperative Environment",
+\fISoftware Practice & Experience\fP, September 1988, pp. 807-820.
+.LP
+The malloc(3) man page.
+.LP
+.SH AUTHOR
+Hans-J. Boehm (Hans.Boehm@hp.com).
+Some of the code was written by others, most notably Alan Demers.
diff --git a/tools/build/v2/engine/boehm_gc/doc/gcdescr.html b/tools/build/v2/engine/boehm_gc/doc/gcdescr.html
new file mode 100644
index 0000000000..dc08470e40
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/gcdescr.html
@@ -0,0 +1,621 @@
+<HTML>
+<HEAD>
+ <TITLE> Conservative GC Algorithmic Overview </TITLE>
+ <AUTHOR> Hans-J. Boehm, HP Labs (Some of this was written at SGI)</author>
+</HEAD>
+<BODY>
+<H1> <I>This is under construction, and may always be.</i> </h1>
+<H1> Conservative GC Algorithmic Overview </h1>
+<P>
+This is a description of the algorithms and data structures used in our
+conservative garbage collector. I expect the level of detail to increase
+with time. For a survey of GC algorithms, see for example
+<A HREF="ftp://ftp.cs.utexas.edu/pub/garbage/gcsurvey.ps"> Paul Wilson's
+excellent paper</a>. For an overview of the collector interface,
+see <A HREF="gcinterface.html">here</a>.
+<P>
+This description is targeted primarily at someone trying to understand the
+source code. It specifically refers to variable and function names.
+It may also be useful for understanding the algorithms at a higher level.
+<P>
+The description here assumes that the collector is used in default mode.
+In particular, we assume that it used as a garbage collector, and not just
+a leak detector. We initially assume that it is used in stop-the-world,
+non-incremental mode, though the presence of the incremental collector
+will be apparent in the design.
+We assume the default finalization model, but the code affected by that
+is very localized.
+<H2> Introduction </h2>
+The garbage collector uses a modified mark-sweep algorithm. Conceptually
+it operates roughly in four phases, which are performed occasionally
+as part of a memory allocation:
+
+<OL>
+
+<LI>
+<I>Preparation</i> Each object has an associated mark bit.
+Clear all mark bits, indicating that all objects
+are potentially unreachable.
+
+<LI>
+<I>Mark phase</i> Marks all objects that can be reachable via chains of
+pointers from variables. Often the collector has no real information
+about the location of pointer variables in the heap, so it
+views all static data areas, stacks and registers as potentially containing
+pointers. Any bit patterns that represent addresses inside
+heap objects managed by the collector are viewed as pointers.
+Unless the client program has made heap object layout information
+available to the collector, any heap objects found to be reachable from
+variables are again scanned similarly.
+
+<LI>
+<I>Sweep phase</i> Scans the heap for inaccessible, and hence unmarked,
+objects, and returns them to an appropriate free list for reuse. This is
+not really a separate phase; even in non incremental mode this is operation
+is usually performed on demand during an allocation that discovers an empty
+free list. Thus the sweep phase is very unlikely to touch a page that
+would not have been touched shortly thereafter anyway.
+
+<LI>
+<I>Finalization phase</i> Unreachable objects which had been registered
+for finalization are enqueued for finalization outside the collector.
+
+</ol>
+
+<P>
+The remaining sections describe the memory allocation data structures,
+and then the last 3 collection phases in more detail. We conclude by
+outlining some of the additional features implemented in the collector.
+
+<H2>Allocation</h2>
+The collector includes its own memory allocator. The allocator obtains
+memory from the system in a platform-dependent way. Under UNIX, it
+uses either <TT>malloc</tt>, <TT>sbrk</tt>, or <TT>mmap</tt>.
+<P>
+Most static data used by the allocator, as well as that needed by the
+rest of the garbage collector is stored inside the
+<TT>_GC_arrays</tt> structure.
+This allows the garbage collector to easily ignore the collectors own
+data structures when it searches for root pointers. Other allocator
+and collector internal data structures are allocated dynamically
+with <TT>GC_scratch_alloc</tt>. <TT>GC_scratch_alloc</tt> does not
+allow for deallocation, and is therefore used only for permanent data
+structures.
+<P>
+The allocator allocates objects of different <I>kinds</i>.
+Different kinds are handled somewhat differently by certain parts
+of the garbage collector. Certain kinds are scanned for pointers,
+others are not. Some may have per-object type descriptors that
+determine pointer locations. Or a specific kind may correspond
+to one specific object layout. Two built-in kinds are uncollectable.
+One (<TT>STUBBORN</tt>) is immutable without special precautions.
+In spite of that, it is very likely that most C clients of the
+collector currently
+use at most two kinds: <TT>NORMAL</tt> and <TT>PTRFREE</tt> objects.
+The <A HREF="http://gcc.gnu.org/java">gcj</a> runtime also makes
+heavy use of a kind (allocated with GC_gcj_malloc) that stores
+type information at a known offset in method tables.
+<P>
+The collector uses a two level allocator. A large block is defined to
+be one larger than half of <TT>HBLKSIZE</tt>, which is a power of 2,
+typically on the order of the page size.
+<P>
+Large block sizes are rounded up to
+the next multiple of <TT>HBLKSIZE</tt> and then allocated by
+<TT>GC_allochblk</tt>. Recent versions of the collector
+use an approximate best fit algorithm by keeping free lists for
+several large block sizes.
+The actual
+implementation of <TT>GC_allochblk</tt>
+is significantly complicated by black-listing issues
+(see below).
+<P>
+Small blocks are allocated in chunks of size <TT>HBLKSIZE</tt>.
+Each chunk is
+dedicated to only one object size and kind. The allocator maintains
+separate free lists for each size and kind of object.
+<P>
+Once a large block is split for use in smaller objects, it can only
+be used for objects of that size, unless the collector discovers a completely
+empty chunk. Completely empty chunks are restored to the appropriate
+large block free list.
+<P>
+In order to avoid allocating blocks for too many distinct object sizes,
+the collector normally does not directly allocate objects of every possible
+request size. Instead request are rounded up to one of a smaller number
+of allocated sizes, for which free lists are maintained. The exact
+allocated sizes are computed on demand, but subject to the constraint
+that they increase roughly in geometric progression. Thus objects
+requested early in the execution are likely to be allocated with exactly
+the requested size, subject to alignment constraints.
+See <TT>GC_init_size_map</tt> for details.
+<P>
+The actual size rounding operation during small object allocation is
+implemented as a table lookup in <TT>GC_size_map</tt>.
+<P>
+Both collector initialization and computation of allocated sizes are
+handled carefully so that they do not slow down the small object fast
+allocation path. An attempt to allocate before the collector is initialized,
+or before the appropriate <TT>GC_size_map</tt> entry is computed,
+will take the same path as an allocation attempt with an empty free list.
+This results in a call to the slow path code (<TT>GC_generic_malloc_inner</tt>)
+which performs the appropriate initialization checks.
+<P>
+In non-incremental mode, we make a decision about whether to garbage collect
+whenever an allocation would otherwise have failed with the current heap size.
+If the total amount of allocation since the last collection is less than
+the heap size divided by <TT>GC_free_space_divisor</tt>, we try to
+expand the heap. Otherwise, we initiate a garbage collection. This ensures
+that the amount of garbage collection work per allocated byte remains
+constant.
+<P>
+The above is in fact an oversimplification of the real heap expansion
+and GC triggering heuristic, which adjusts slightly for root size
+and certain kinds of
+fragmentation. In particular:
+<UL>
+<LI> Programs with a large root set size and
+little live heap memory will expand the heap to amortize the cost of
+scanning the roots.
+<LI> Versions 5.x of the collector actually collect more frequently in
+nonincremental mode. The large block allocator usually refuses to split
+large heap blocks once the garbage collection threshold is
+reached. This often has the effect of collecting well before the
+heap fills up, thus reducing fragmentation and working set size at the
+expense of GC time. Versions 6.x choose an intermediate strategy depending
+on how much large object allocation has taken place in the past.
+(If the collector is configured to unmap unused pages, versions 6.x
+use the 5.x strategy.)
+<LI> In calculating the amount of allocation since the last collection we
+give partial credit for objects we expect to be explicitly deallocated.
+Even if all objects are explicitly managed, it is often desirable to collect
+on rare occasion, since that is our only mechanism for coalescing completely
+empty chunks.
+</ul>
+<P>
+It has been suggested that this should be adjusted so that we favor
+expansion if the resulting heap still fits into physical memory.
+In many cases, that would no doubt help. But it is tricky to do this
+in a way that remains robust if multiple application are contending
+for a single pool of physical memory.
+
+<H2>Mark phase</h2>
+
+At each collection, the collector marks all objects that are
+possibly reachable from pointer variables. Since it cannot generally
+tell where pointer variables are located, it scans the following
+<I>root segments</i> for pointers:
+<UL>
+<LI>The registers. Depending on the architecture, this may be done using
+assembly code, or by calling a <TT>setjmp</tt>-like function which saves
+register contents on the stack.
+<LI>The stack(s). In the case of a single-threaded application,
+on most platforms this
+is done by scanning the memory between (an approximation of) the current
+stack pointer and <TT>GC_stackbottom</tt>. (For Itanium, the register stack
+scanned separately.) The <TT>GC_stackbottom</tt> variable is set in
+a highly platform-specific way depending on the appropriate configuration
+information in <TT>gcconfig.h</tt>. Note that the currently active
+stack needs to be scanned carefully, since callee-save registers of
+client code may appear inside collector stack frames, which may
+change during the mark process. This is addressed by scanning
+some sections of the stack "eagerly", effectively capturing a snapshot
+at one point in time.
+<LI>Static data region(s). In the simplest case, this is the region
+between <TT>DATASTART</tt> and <TT>DATAEND</tt>, as defined in
+<TT>gcconfig.h</tt>. However, in most cases, this will also involve
+static data regions associated with dynamic libraries. These are
+identified by the mostly platform-specific code in <TT>dyn_load.c</tt>.
+</ul>
+The marker maintains an explicit stack of memory regions that are known
+to be accessible, but that have not yet been searched for contained pointers.
+Each stack entry contains the starting address of the block to be scanned,
+as well as a descriptor of the block. If no layout information is
+available for the block, then the descriptor is simply a length.
+(For other possibilities, see <TT>gc_mark.h</tt>.)
+<P>
+At the beginning of the mark phase, all root segments
+(as described above) are pushed on the
+stack by <TT>GC_push_roots</tt>. (Registers and eagerly processed
+stack sections are processed by pushing the referenced objects instead
+of the stack section itself.) If <TT>ALL_INTERIOR_PTRS</tt> is not
+defined, then stack roots require special treatment. In this case, the
+normal marking code ignores interior pointers, but <TT>GC_push_all_stack</tt>
+explicitly checks for interior pointers and pushes descriptors for target
+objects.
+<P>
+The marker is structured to allow incremental marking.
+Each call to <TT>GC_mark_some</tt> performs a small amount of
+work towards marking the heap.
+It maintains
+explicit state in the form of <TT>GC_mark_state</tt>, which
+identifies a particular sub-phase. Some other pieces of state, most
+notably the mark stack, identify how much work remains to be done
+in each sub-phase. The normal progression of mark states for
+a stop-the-world collection is:
+<OL>
+<LI> <TT>MS_INVALID</tt> indicating that there may be accessible unmarked
+objects. In this case <TT>GC_objects_are_marked</tt> will simultaneously
+be false, so the mark state is advanced to
+<LI> <TT>MS_PUSH_UNCOLLECTABLE</tt> indicating that it suffices to push
+uncollectable objects, roots, and then mark everything reachable from them.
+<TT>Scan_ptr</tt> is advanced through the heap until all uncollectable
+objects are pushed, and objects reachable from them are marked.
+At that point, the next call to <TT>GC_mark_some</tt> calls
+<TT>GC_push_roots</tt> to push the roots. It the advances the
+mark state to
+<LI> <TT>MS_ROOTS_PUSHED</tt> asserting that once the mark stack is
+empty, all reachable objects are marked. Once in this state, we work
+only on emptying the mark stack. Once this is completed, the state
+changes to
+<LI> <TT>MS_NONE</tt> indicating that reachable objects are marked.
+</ol>
+
+The core mark routine <TT>GC_mark_from</tt>, is called
+repeatedly by several of the sub-phases when the mark stack starts to fill
+up. It is also called repeatedly in <TT>MS_ROOTS_PUSHED</tt> state
+to empty the mark stack.
+The routine is designed to only perform a limited amount of marking at
+each call, so that it can also be used by the incremental collector.
+It is fairly carefully tuned, since it usually consumes a large majority
+of the garbage collection time.
+<P>
+The fact that it perform a only a small amount of work per call also
+allows it to be used as the core routine of the parallel marker. In that
+case it is normally invoked on thread-private mark stacks instead of the
+global mark stack. More details can be found in
+<A HREF="scale.html">scale.html</a>
+<P>
+The marker correctly handles mark stack overflows. Whenever the mark stack
+overflows, the mark state is reset to <TT>MS_INVALID</tt>.
+Since there are already marked objects in the heap,
+this eventually forces a complete
+scan of the heap, searching for pointers, during which any unmarked objects
+referenced by marked objects are again pushed on the mark stack. This
+process is repeated until the mark phase completes without a stack overflow.
+Each time the stack overflows, an attempt is made to grow the mark stack.
+All pieces of the collector that push regions onto the mark stack have to be
+careful to ensure forward progress, even in case of repeated mark stack
+overflows. Every mark attempt results in additional marked objects.
+<P>
+Each mark stack entry is processed by examining all candidate pointers
+in the range described by the entry. If the region has no associated
+type information, then this typically requires that each 4-byte aligned
+quantity (8-byte aligned with 64-bit pointers) be considered a candidate
+pointer.
+<P>
+We determine whether a candidate pointer is actually the address of
+a heap block. This is done in the following steps:
+<NL>
+<LI> The candidate pointer is checked against rough heap bounds.
+These heap bounds are maintained such that all actual heap objects
+fall between them. In order to facilitate black-listing (see below)
+we also include address regions that the heap is likely to expand into.
+Most non-pointers fail this initial test.
+<LI> The candidate pointer is divided into two pieces; the most significant
+bits identify a <TT>HBLKSIZE</tt>-sized page in the address space, and
+the least significant bits specify an offset within that page.
+(A hardware page may actually consist of multiple such pages.
+HBLKSIZE is usually the page size divided by a small power of two.)
+<LI>
+The page address part of the candidate pointer is looked up in a
+<A HREF="tree.html">table</a>.
+Each table entry contains either 0, indicating that the page is not part
+of the garbage collected heap, a small integer <I>n</i>, indicating
+that the page is part of large object, starting at least <I>n</i> pages
+back, or a pointer to a descriptor for the page. In the first case,
+the candidate pointer i not a true pointer and can be safely ignored.
+In the last two cases, we can obtain a descriptor for the page containing
+the beginning of the object.
+<LI>
+The starting address of the referenced object is computed.
+The page descriptor contains the size of the object(s)
+in that page, the object kind, and the necessary mark bits for those
+objects. The size information can be used to map the candidate pointer
+to the object starting address. To accelerate this process, the page header
+also contains a pointer to a precomputed map of page offsets to displacements
+from the beginning of an object. The use of this map avoids a
+potentially slow integer remainder operation in computing the object
+start address.
+<LI>
+The mark bit for the target object is checked and set. If the object
+was previously unmarked, the object is pushed on the mark stack.
+The descriptor is read from the page descriptor. (This is computed
+from information <TT>GC_obj_kinds</tt> when the page is first allocated.)
+</nl>
+<P>
+At the end of the mark phase, mark bits for left-over free lists are cleared,
+in case a free list was accidentally marked due to a stray pointer.
+
+<H2>Sweep phase</h2>
+
+At the end of the mark phase, all blocks in the heap are examined.
+Unmarked large objects are immediately returned to the large object free list.
+Each small object page is checked to see if all mark bits are clear.
+If so, the entire page is returned to the large object free list.
+Small object pages containing some reachable object are queued for later
+sweeping, unless we determine that the page contains very little free
+space, in which case it is not examined further.
+<P>
+This initial sweep pass touches only block headers, not
+the blocks themselves. Thus it does not require significant paging, even
+if large sections of the heap are not in physical memory.
+<P>
+Nonempty small object pages are swept when an allocation attempt
+encounters an empty free list for that object size and kind.
+Pages for the correct size and kind are repeatedly swept until at
+least one empty block is found. Sweeping such a page involves
+scanning the mark bit array in the page header, and building a free
+list linked through the first words in the objects themselves.
+This does involve touching the appropriate data page, but in most cases
+it will be touched only just before it is used for allocation.
+Hence any paging is essentially unavoidable.
+<P>
+Except in the case of pointer-free objects, we maintain the invariant
+that any object in a small object free list is cleared (except possibly
+for the link field). Thus it becomes the burden of the small object
+sweep routine to clear objects. This has the advantage that we can
+easily recover from accidentally marking a free list, though that could
+also be handled by other means. The collector currently spends a fair
+amount of time clearing objects, and this approach should probably be
+revisited.
+<P>
+In most configurations, we use specialized sweep routines to handle common
+small object sizes. Since we allocate one mark bit per word, it becomes
+easier to examine the relevant mark bits if the object size divides
+the word length evenly. We also suitably unroll the inner sweep loop
+in each case. (It is conceivable that profile-based procedure cloning
+in the compiler could make this unnecessary and counterproductive. I
+know of no existing compiler to which this applies.)
+<P>
+The sweeping of small object pages could be avoided completely at the expense
+of examining mark bits directly in the allocator. This would probably
+be more expensive, since each allocation call would have to reload
+a large amount of state (e.g. next object address to be swept, position
+in mark bit table) before it could do its work. The current scheme
+keeps the allocator simple and allows useful optimizations in the sweeper.
+
+<H2>Finalization</h2>
+Both <TT>GC_register_disappearing_link</tt> and
+<TT>GC_register_finalizer</tt> add the request to a corresponding hash
+table. The hash table is allocated out of collected memory, but
+the reference to the finalizable object is hidden from the collector.
+Currently finalization requests are processed non-incrementally at the
+end of a mark cycle.
+<P>
+The collector makes an initial pass over the table of finalizable objects,
+pushing the contents of unmarked objects onto the mark stack.
+After pushing each object, the marker is invoked to mark all objects
+reachable from it. The object itself is not explicitly marked.
+This assures that objects on which a finalizer depends are neither
+collected nor finalized.
+<P>
+If in the process of marking from an object the
+object itself becomes marked, we have uncovered
+a cycle involving the object. This usually results in a warning from the
+collector. Such objects are not finalized, since it may be
+unsafe to do so. See the more detailed
+<A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/finalization.html"> discussion of finalization semantics</a>.
+<P>
+Any objects remaining unmarked at the end of this process are added to
+a queue of objects whose finalizers can be run. Depending on collector
+configuration, finalizers are dequeued and run either implicitly during
+allocation calls, or explicitly in response to a user request.
+(Note that the former is unfortunately both the default and not generally safe.
+If finalizers perform synchronization, it may result in deadlocks.
+Nontrivial finalizers generally need to perform synchronization, and
+thus require a different collector configuration.)
+<P>
+The collector provides a mechanism for replacing the procedure that is
+used to mark through objects. This is used both to provide support for
+Java-style unordered finalization, and to ignore certain kinds of cycles,
+<I>e.g.</i> those arising from C++ implementations of virtual inheritance.
+
+<H2>Generational Collection and Dirty Bits</h2>
+We basically use the concurrent and generational GC algorithm described in
+<A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/papers/pldi91.ps.Z">"Mostly Parallel Garbage Collection"</a>,
+by Boehm, Demers, and Shenker.
+<P>
+The most significant modification is that
+the collector always starts running in the allocating thread.
+There is no separate garbage collector thread. (If parallel GC is
+enabled, helper threads may also be woken up.)
+If an allocation attempt either requests a large object, or encounters
+an empty small object free list, and notices that there is a collection
+in progress, it immediately performs a small amount of marking work
+as described above.
+<P>
+This change was made both because we wanted to easily accommodate
+single-threaded environments, and because a separate GC thread requires
+very careful control over the scheduler to prevent the mutator from
+out-running the collector, and hence provoking unneeded heap growth.
+<P>
+In incremental mode, the heap is always expanded when we encounter
+insufficient space for an allocation. Garbage collection is triggered
+whenever we notice that more than
+<TT>GC_heap_size</tt>/2 * <TT>GC_free_space_divisor</tt>
+bytes of allocation have taken place.
+After <TT>GC_full_freq</tt> minor collections a major collection
+is started.
+<P>
+All collections initially run interrupted until a predetermined
+amount of time (50 msecs by default) has expired. If this allows
+the collection to complete entirely, we can avoid correcting
+for data structure modifications during the collection. If it does
+not complete, we return control to the mutator, and perform small
+amounts of additional GC work during those later allocations that
+cannot be satisfied from small object free lists. When marking completes,
+the set of modified pages is retrieved, and we mark once again from
+marked objects on those pages, this time with the mutator stopped.
+<P>
+We keep track of modified pages using one of several distinct mechanisms:
+<OL>
+<LI>
+Through explicit mutator cooperation. Currently this requires
+the use of <TT>GC_malloc_stubborn</tt>, and is rarely used.
+<LI>
+(<TT>MPROTECT_VDB</tt>) By write-protecting physical pages and
+catching write faults. This is
+implemented for many Unix-like systems and for win32. It is not possible
+in a few environments.
+<LI>
+(<TT>PROC_VDB</tt>) By retrieving dirty bit information from /proc.
+(Currently only Sun's
+Solaris supports this. Though this is considerably cleaner, performance
+may actually be better with mprotect and signals.)
+<LI>
+(<TT>PCR_VDB</tt>) By relying on an external dirty bit implementation, in this
+case the one in Xerox PCR.
+<LI>
+(<TT>DEFAULT_VDB</tt>) By treating all pages as dirty. This is the default if
+none of the other techniques is known to be usable, and
+<TT>GC_malloc_stubborn</tt> is not used. Practical only for testing, or if
+the vast majority of objects use <TT>GC_malloc_stubborn</tt>.
+</ol>
+
+<H2>Black-listing</h2>
+
+The collector implements <I>black-listing</i> of pages, as described
+in
+<A HREF="http://www.acm.org/pubs/citations/proceedings/pldi/155090/p197-boehm/">
+Boehm, ``Space Efficient Conservative Collection'', PLDI '93</a>, also available
+<A HREF="papers/pldi93.ps.Z">here</a>.
+<P>
+During the mark phase, the collector tracks ``near misses'', i.e. attempts
+to follow a ``pointer'' to just outside the garbage-collected heap, or
+to a currently unallocated page inside the heap. Pages that have been
+the targets of such near misses are likely to be the targets of
+misidentified ``pointers'' in the future. To minimize the future
+damage caused by such misidentifications they will be allocated only to
+small pointerfree objects.
+<P>
+The collector understands two different kinds of black-listing. A
+page may be black listed for interior pointer references
+(<TT>GC_add_to_black_list_stack</tt>), if it was the target of a near
+miss from a location that requires interior pointer recognition,
+<I>e.g.</i> the stack, or the heap if <TT>GC_all_interior_pointers</tt>
+is set. In this case, we also avoid allocating large blocks that include
+this page.
+<P>
+If the near miss came from a source that did not require interior
+pointer recognition, it is black-listed with
+<TT>GC_add_to_black_list_normal</tt>.
+A page black-listed in this way may appear inside a large object,
+so long as it is not the first page of a large object.
+<P>
+The <TT>GC_allochblk</tt> routine respects black-listing when assigning
+a block to a particular object kind and size. It occasionally
+drops (i.e. allocates and forgets) blocks that are completely black-listed
+in order to avoid excessively long large block free lists containing
+only unusable blocks. This would otherwise become an issue
+if there is low demand for small pointerfree objects.
+
+<H2>Thread support</h2>
+We support several different threading models. Unfortunately Pthreads,
+the only reasonably well standardized thread model, supports too narrow
+an interface for conservative garbage collection. There appears to be
+no completely portable way to allow the collector
+to coexist with various Pthreads
+implementations. Hence we currently support only the more
+common Pthreads implementations.
+<P>
+In particular, it is very difficult for the collector to stop all other
+threads in the system and examine the register contents. This is currently
+accomplished with very different mechanisms for some Pthreads
+implementations. The Solaris implementation temporarily disables much
+of the user-level threads implementation by stopping kernel-level threads
+("lwp"s). The Linux/HPUX/OSF1 and Irix implementations sends signals to
+individual Pthreads and has them wait in the signal handler.
+<P>
+The Linux and Irix implementations use
+only documented Pthreads calls, but rely on extensions to their semantics.
+The Linux implementation <TT>linux_threads.c</tt> relies on only very
+mild extensions to the pthreads semantics, and already supports a large number
+of other Unix-like pthreads implementations. Our goal is to make this the
+only pthread support in the collector.
+<P>
+(The Irix implementation is separate only for historical reasons and should
+clearly be merged. The current Solaris implementation probably performs
+better in the uniprocessor case, but does not support thread operations in the
+collector. Hence it cannot support the parallel marker.)
+<P>
+All implementations must
+intercept thread creation and a few other thread-specific calls to allow
+enumeration of threads and location of thread stacks. This is current
+accomplished with <TT># define</tt>'s in <TT>gc.h</tt>
+(really <TT>gc_pthread_redirects.h</tt>), or optionally
+by using ld's function call wrapping mechanism under Linux.
+<P>
+Recent versions of the collector support several facilites to enhance
+the processor-scalability and thread performance of the collector.
+These are discussed in more detail <A HREF="scale.html">here</a>.
+We briefly outline the data approach to thread-local allocation in the
+next section.
+<H2>Thread-local allocation</h2>
+If thread-local allocation is enabled, the collector keeps separate
+arrays of free lists for each thread. Thread-local allocation
+is currently only supported on a few platforms.
+<P>
+The free list arrays associated
+with each thread are only used to satisfy requests for objects that
+are both very small, and belong to one of a small number of well-known
+kinds. These currently include "normal" and pointer-free objects.
+Depending onthe configuration, "gcj" objects may also be included.
+<P>
+Thread-local free list entries contain either a pointer to the first
+element of a free list, or they contain a counter of the number of
+allocation "granules" allocated so far. Initially they contain the
+value one, i.e. a small counter value.
+<P>
+Thread-local allocation allocates directly through the global
+allocator, if the object is of a size or kind not covered by the
+local free lists.
+<P>
+If there is an appropriate local free list, the allocator checks whether it
+contains a sufficiently small counter value. If so, the counter is simply
+incremented by the counter value, and the global allocator is used.
+In this way, the initial few allocations of a given size bypass the local
+allocator. A thread that only allocates a handful of objects of a given
+size will not build up its own free list for that size. This avoids
+wasting space for unpopular objects sizes or kinds.
+<P>
+Once the counter passes a threshold, <TT>GC_malloc_many</tt> is called
+to allocate roughly <TT>HBLKSIZE</tt> space and put it on the corresponding
+local free list. Further allocations of that size and kind then use
+this free list, and no longer need to acquire the allocation lock.
+The allocation procedure is otherwise similar to the global free lists.
+The local free lists are also linked using the first word in the object.
+In most cases this means they require considerably less time.
+<P>
+Local free lists are treated buy most of the rest of the collector
+as though they were in-use reachable data. This requires some care,
+since pointer-free objects are not normally traced, and hence a special
+tracing procedure is required to mark all objects on pointer-free and
+gcj local free lists.
+<P>
+On thread exit, any remaining thread-local free list entries are
+transferred back to the global free list.
+<P>
+Note that if the collector is configured for thread-local allocation,
+GC versions before 7 do not invoke the thread-local allocator by default.
+<TT>GC_malloc</tt> only uses thread-local allocation in version 7 and later.
+In earlier versions, <TT>GC_MALLOC</tt> (all caps) may be directed
+to use thread-local allocation by defining <TT>GC_REDIRECT_TO_LOCAL</tt>
+and then include <TT>gc_local_alloc.h</tt>.
+<P>
+For some more details see <A HREF="scale.html">here</a>, and the
+technical report entitled
+<A HREF="http://www.hpl.hp.com/techreports/2000/HPL-2000-165.html">
+``Fast Multiprocessor Memory Allocation and Garbage Collection''
+</a>
+<P>
+<HR>
+<P>
+Comments are appreciated. Please send mail to
+<A HREF="mailto:boehm@acm.org"><TT>boehm@acm.org</tt></a> or
+<A HREF="mailto:Hans.Boehm@hp.com"><TT>Hans.Boehm@hp.com</tt></a>
+<P>
+This is a modified copy of a page written while the author was at SGI.
+The original was <A HREF="http://reality.sgi.com/boehm/gcdescr.html">here</a>.
+</body>
+</html>
diff --git a/tools/build/v2/engine/boehm_gc/doc/gcinterface.html b/tools/build/v2/engine/boehm_gc/doc/gcinterface.html
new file mode 100644
index 0000000000..74230aa6ca
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/gcinterface.html
@@ -0,0 +1,278 @@
+<!DOCTYPE HTML>
+<HEAD>
+<TITLE>Garbage Collector Interface</TITLE>
+</HEAD>
+<BODY>
+<H1>C Interface</h1>
+On many platforms, a single-threaded garbage collector library can be built
+to act as a plug-in malloc replacement.
+(Build with <TT>-DREDIRECT_MALLOC=GC_malloc -DIGNORE_FREE</tt>.)
+This is often the best way to deal with third-party libraries
+which leak or prematurely free objects. <TT>-DREDIRECT_MALLOC</tt> is intended
+primarily as an easy way to adapt old code, not for new development.
+<P>
+New code should use the interface discussed below.
+<P>
+Code must be linked against the GC library. On most UNIX platforms,
+depending on how the collector is built, this will be <TT>gc.a</tt>
+or <TT>libgc.{a,so}</tt>.
+<P>
+The following describes the standard C interface to the garbage collector.
+It is not a complete definition of the interface. It describes only the
+most commonly used functionality, approximately in decreasing order of
+frequency of use.
+The full interface is described in
+<A HREF="http://hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gch.txt">gc.h</a>
+or <TT>gc.h</tt> in the distribution.
+<P>
+Clients should include <TT>gc.h</tt>.
+<P>
+In the case of multithreaded code,
+<TT>gc.h</tt> should be included after the threads header file, and
+after defining the appropriate <TT>GC_</tt><I>XXXX</i><TT>_THREADS</tt> macro.
+(For 6.2alpha4 and later, simply defining <TT>GC_THREADS</tt> should suffice.)
+The header file <TT>gc.h</tt> must be included
+in files that use either GC or threads primitives, since threads primitives
+will be redefined to cooperate with the GC on many platforms.
+<P>
+Thread users should also be aware that on many platforms objects reachable
+only from thread-local variables may be prematurely reclaimed.
+Thus objects pointed to by thread-local variables should also be pointed to
+by a globally visible data structure. (This is viewed as a bug, but as
+one that is exceedingly hard to fix without some libc hooks.)
+<DL>
+<DT> <B>void * GC_MALLOC(size_t <I>nbytes</i>)</b>
+<DD>
+Allocates and clears <I>nbytes</i> of storage.
+Requires (amortized) time proportional to <I>nbytes</i>.
+The resulting object will be automatically deallocated when unreferenced.
+References from objects allocated with the system malloc are usually not
+considered by the collector. (See <TT>GC_MALLOC_UNCOLLECTABLE</tt>, however.)
+<TT>GC_MALLOC</tt> is a macro which invokes <TT>GC_malloc</tt> by default or,
+if <TT>GC_DEBUG</tt>
+is defined before <TT>gc.h</tt> is included, a debugging version that checks
+occasionally for overwrite errors, and the like.
+<DT> <B>void * GC_MALLOC_ATOMIC(size_t <I>nbytes</i>)</b>
+<DD>
+Allocates <I>nbytes</i> of storage.
+Requires (amortized) time proportional to <I>nbytes</i>.
+The resulting object will be automatically deallocated when unreferenced.
+The client promises that the resulting object will never contain any pointers.
+The memory is not cleared.
+This is the preferred way to allocate strings, floating point arrays,
+bitmaps, etc.
+More precise information about pointer locations can be communicated to the
+collector using the interface in
+<A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc_typedh.txt">gc_typed.h</a> in the distribution.
+<DT> <B>void * GC_MALLOC_UNCOLLECTABLE(size_t <I>nbytes</i>)</b>
+<DD>
+Identical to <TT>GC_MALLOC</tt>,
+except that the resulting object is not automatically
+deallocated. Unlike the system-provided malloc, the collector does
+scan the object for pointers to garbage-collectable memory, even if the
+block itself does not appear to be reachable. (Objects allocated in this way
+are effectively treated as roots by the collector.)
+<DT> <B> void * GC_REALLOC(void *<I>old</i>, size_t <I>new_size</i>) </b>
+<DD>
+Allocate a new object of the indicated size and copy (a prefix of) the
+old object into the new object. The old object is reused in place if
+convenient. If the original object was allocated with
+<TT>GC_MALLOC_ATOMIC</tt>,
+the new object is subject to the same constraints. If it was allocated
+as an uncollectable object, then the new object is uncollectable, and
+the old object (if different) is deallocated.
+<DT> <B> void GC_FREE(void *<I>dead</i>) </b>
+<DD>
+Explicitly deallocate an object. Typically not useful for small
+collectable objects.
+<DT> <B> void * GC_MALLOC_IGNORE_OFF_PAGE(size_t <I>nbytes</i>) </b>
+<DD>
+<DT> <B> void * GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(size_t <I>nbytes</i>) </b>
+<DD>
+Analogous to <TT>GC_MALLOC</tt> and <TT>GC_MALLOC_ATOMIC</tt>,
+except that the client
+guarantees that as long
+as the resulting object is of use, a pointer is maintained to someplace
+inside the first 512 bytes of the object. This pointer should be declared
+volatile to avoid interference from compiler optimizations.
+(Other nonvolatile pointers to the object may exist as well.)
+This is the
+preferred way to allocate objects that are likely to be &gt; 100KBytes in size.
+It greatly reduces the risk that such objects will be accidentally retained
+when they are no longer needed. Thus space usage may be significantly reduced.
+<DT> <B> void GC_INIT(void) </b>
+<DD>
+On some platforms, it is necessary to invoke this
+<I>from the main executable, not from a dynamic library,</i> before
+the initial invocation of a GC routine. It is recommended that this be done
+in portable code, though we try to ensure that it expands to a no-op
+on as many platforms as possible. As of GC 7.0, it is required if
+thread-local allocation is enabled in the collector build, and <TT>malloc</tt>
+is not redirected to <TT>GC_malloc</tt>.
+<DT> <B> void GC_gcollect(void) </b>
+<DD>
+Explicitly force a garbage collection.
+<DT> <B> void GC_enable_incremental(void) </b>
+<DD>
+Cause the garbage collector to perform a small amount of work
+every few invocations of <TT>GC_MALLOC</tt> or the like, instead of performing
+an entire collection at once. This is likely to increase total
+running time. It will improve response on a platform that either has
+suitable support in the garbage collector (Linux and most Unix
+versions, win32 if the collector was suitably built) or if "stubborn"
+allocation is used (see
+<A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gch.txt">gc.h</a>).
+On many platforms this interacts poorly with system calls
+that write to the garbage collected heap.
+<DT> <B> GC_warn_proc GC_set_warn_proc(GC_warn_proc <I>p</i>) </b>
+<DD>
+Replace the default procedure used by the collector to print warnings.
+The collector
+may otherwise write to sterr, most commonly because GC_malloc was used
+in a situation in which GC_malloc_ignore_off_page would have been more
+appropriate. See <A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gch.txt">gc.h</a> for details.
+<DT> <B> void GC_REGISTER_FINALIZER(...) </b>
+<DD>
+Register a function to be called when an object becomes inaccessible.
+This is often useful as a backup method for releasing system resources
+(<I>e.g.</i> closing files) when the object referencing them becomes
+inaccessible.
+It is not an acceptable method to perform actions that must be performed
+in a timely fashion.
+See <A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gch.txt">gc.h</a> for details of the interface.
+See <A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/finalization.html">here</a> for a more detailed discussion
+of the design.
+<P>
+Note that an object may become inaccessible before client code is done
+operating on objects referenced by its fields.
+Suitable synchronization is usually required.
+See <A HREF="http://portal.acm.org/citation.cfm?doid=604131.604153">here</a>
+or <A HREF="http://www.hpl.hp.com/techreports/2002/HPL-2002-335.html">here</a>
+for details.
+</dl>
+<P>
+If you are concerned with multiprocessor performance and scalability,
+you should consider enabling and using thread local allocation (<I>e.g.</i>
+<TT>GC_LOCAL_MALLOC</tt>, see <TT>gc_local_alloc.h</tt>. If your platform
+supports it, you should build the collector with parallel marking support
+(<TT>-DPARALLEL_MARK</tt>, or <TT>--enable-parallel-mark</tt>).
+<P>
+If the collector is used in an environment in which pointer location
+information for heap objects is easily available, this can be passed on
+to the collector using the interfaces in either <TT>gc_typed.h</tt>
+or <TT>gc_gcj.h</tt>.
+<P>
+The collector distribution also includes a <B>string package</b> that takes
+advantage of the collector. For details see
+<A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/cordh.txt">cord.h</a>
+
+<H1>C++ Interface</h1>
+The C++ interface is implemented as a thin layer on the C interface.
+Unfortunately, this thin layer appears to be very sensitive to variations
+in C++ implementations, particularly since it tries to replace the global
+::new operator, something that appears to not be well-standardized.
+Your platform may need minor adjustments in this layer (gc_cpp.cc, gc_cpp.h,
+and possibly gc_allocator.h). Such changes do not require understanding
+of collector internals, though they may require a good understanding of
+your platform. (Patches enhancing portability are welcome.
+But it's easy to break one platform by fixing another.)
+<P>
+Usage of the collector from C++ is also complicated by the fact that there
+are many "standard" ways to allocate memory in C++. The default ::new
+operator, default malloc, and default STL allocators allocate memory
+that is not garbage collected, and is not normally "traced" by the
+collector. This means that any pointers in memory allocated by these
+default allocators will not be seen by the collector. Garbage-collectable
+memory referenced only by pointers stored in such default-allocated
+objects is likely to be reclaimed prematurely by the collector.
+<P>
+It is the programmers responsibility to ensure that garbage-collectable
+memory is referenced by pointers stored in one of
+<UL>
+<LI> Program variables
+<LI> Garbage-collected objects
+<LI> Uncollected but "traceable" objects
+</ul>
+"Traceable" objects are not necessarily reclaimed by the collector,
+but are scanned for pointers to collectable objects.
+They are usually allocated by <TT>GC_MALLOC_UNCOLLECTABLE</tt>, as described
+above, and through some interfaces described below.
+<P>
+(On most platforms, the collector may not trace correctly from in-flight
+exception objects. Thus objects thrown as exceptions should only
+point to otherwise reachable memory. This is another bug whose
+proper repair requires platform hooks.)
+<P>
+The easiest way to ensure that collectable objects are properly referenced
+is to allocate only collectable objects. This requires that every
+allocation go through one of the following interfaces, each one of
+which replaces a standard C++ allocation mechanism:
+<DL>
+<DT> <B> STL allocators </b>
+<DD>
+<P>
+Recent versions of the collector also include a more standard-conforming
+allocator implementation in <TT>gc_allocator.h</tt>. It defines
+<UL>
+<LI> traceable_allocator
+<LI> gc_allocator
+</ul>
+which may be used either directly to allocate memory or to instantiate
+container templates.
+The former allocates uncollectable but traced memory.
+The latter allocates garbage-collected memory.
+<P>
+These should work with any fully standard-conforming C++ compiler.
+<P>
+Users of the <A HREF="http://www.sgi.com/tech/stl">SGI extended STL</a>
+or its derivatives (including most g++ versions)
+can alternatively include <TT>new_gc_alloc.h</tt> before including
+STL header files.
+(<TT>gc_alloc.h</tt> corresponds to now obsolete versions of the
+SGI STL.) This interface is no longer recommended, but it has existed
+for much longer.
+<P>
+This defines SGI-style allocators
+<UL>
+<LI> alloc
+<LI> single_client_alloc
+<LI> gc_alloc
+<LI> single_client_gc_alloc
+</ul>
+The first two allocate uncollectable but traced
+memory, while the second two allocate collectable memory.
+The single_client versions are not safe for concurrent access by
+multiple threads, but are faster.
+<P>
+For an example, click <A HREF="http://hpl.hp.com/personal/Hans_Boehm/gc/gc_alloc_exC.txt">here</a>.
+<DT> <B> Class inheritance based interface </b>
+<DD>
+Users may include gc_cpp.h and then cause members of classes to
+be allocated in garbage collectable memory by having those classes
+inherit from class gc.
+For details see <A HREF="http://hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc_cpph.txt">gc_cpp.h</a>.
+<P>
+Linking against libgccpp in addition to the gc library overrides
+::new (and friends) to allocate traceable memory but uncollectable
+memory, making it safe to refer to collectable objects from the resulting
+memory.
+<DT> <B> C interface </b>
+<DD>
+It is also possible to use the C interface from
+<A HREF="http://hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gch.txt">gc.h</a> directly.
+On platforms which use malloc to implement ::new, it should usually be possible
+to use a version of the collector that has been compiled as a malloc
+replacement. It is also possible to replace ::new and other allocation
+functions suitably, as is done by libgccpp.
+<P>
+Note that user-implemented small-block allocation often works poorly with
+an underlying garbage-collected large block allocator, since the collector
+has to view all objects accessible from the user's free list as reachable.
+This is likely to cause problems if <TT>GC_MALLOC</tt>
+is used with something like
+the original HP version of STL.
+This approach works well with the SGI versions of the STL only if the
+<TT>malloc_alloc</tt> allocator is used.
+</dl>
+</body>
+</html>
diff --git a/tools/build/v2/engine/boehm_gc/doc/leak.html b/tools/build/v2/engine/boehm_gc/doc/leak.html
new file mode 100644
index 0000000000..8f460c9f68
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/leak.html
@@ -0,0 +1,200 @@
+<HTML>
+<HEAD>
+<TITLE>Using the Garbage Collector as Leak Detector</title>
+</head>
+<BODY>
+<H1>Using the Garbage Collector as Leak Detector</h1>
+The garbage collector may be used as a leak detector.
+In this case, the primary function of the collector is to report
+objects that were allocated (typically with <TT>GC_MALLOC</tt>),
+not deallocated (normally with <TT>GC_FREE</tt>), but are
+no longer accessible. Since the object is no longer accessible,
+there in normally no way to deallocate the object at a later time;
+thus it can safely be assumed that the object has been "leaked".
+<P>
+This is substantially different from counting leak detectors,
+which simply verify that all allocated objects are eventually
+deallocated. A garbage-collector based leak detector can provide
+somewhat more precise information when an object was leaked.
+More importantly, it does not report objects that are never
+deallocated because they are part of "permanent" data structures.
+Thus it does not require all objects to be deallocated at process
+exit time, a potentially useless activity that often triggers
+large amounts of paging.
+<P>
+All non-ancient versions of the garbage collector provide
+leak detection support. Version 5.3 adds the following
+features:
+<OL>
+<LI> Leak detection mode can be initiated at run-time by
+setting GC_find_leak instead of building the collector with FIND_LEAK
+defined. This variable should be set to a nonzero value
+at program startup.
+<LI> Leaked objects should be reported and then correctly garbage collected.
+Prior versions either reported leaks or functioned as a garbage collector.
+</ol>
+For the rest of this description we will give instructions that work
+with any reasonable version of the collector.
+<P>
+To use the collector as a leak detector, follow the following steps:
+<OL>
+<LI> Build the collector with -DFIND_LEAK. Otherwise use default
+build options.
+<LI> Change the program so that all allocation and deallocation goes
+through the garbage collector.
+<LI> Arrange to call <TT>GC_gcollect</tt> at appropriate points to check
+for leaks.
+(For sufficiently long running programs, this will happen implicitly,
+but probably not with sufficient frequency.)
+</ol>
+The second step can usually be accomplished with the
+<TT>-DREDIRECT_MALLOC=GC_malloc</tt> option when the collector is built,
+or by defining <TT>malloc</tt>, <TT>calloc</tt>,
+<TT>realloc</tt> and <TT>free</tt>
+to call the corresponding garbage collector functions.
+But this, by itself, will not yield very informative diagnostics,
+since the collector does not keep track of information about
+how objects were allocated. The error reports will include
+only object addresses.
+<P>
+For more precise error reports, as much of the program as possible
+should use the all uppercase variants of these functions, after
+defining <TT>GC_DEBUG</tt>, and then including <TT>gc.h</tt>.
+In this environment <TT>GC_MALLOC</tt> is a macro which causes
+at least the file name and line number at the allocation point to
+be saved as part of the object. Leak reports will then also include
+this information.
+<P>
+Many collector features (<I>e.g</i> stubborn objects, finalization,
+and disappearing links) are less useful in this context, and are not
+fully supported. Their use will usually generate additional bogus
+leak reports, since the collector itself drops some associated objects.
+<P>
+The same is generally true of thread support. However, as of 6.0alpha4,
+correct leak reports should be generated with linuxthreads.
+<P>
+On a few platforms (currently Solaris/SPARC, Irix, and, with -DSAVE_CALL_CHAIN,
+Linux/X86), <TT>GC_MALLOC</tt>
+also causes some more information about its call stack to be saved
+in the object. Such information is reproduced in the error
+reports in very non-symbolic form, but it can be very useful with the
+aid of a debugger.
+<H2>An Example</h2>
+The following header file <TT>leak_detector.h</tt> is included in the
+"include" subdirectory of the distribution:
+<PRE>
+#define GC_DEBUG
+#include "gc.h"
+#define malloc(n) GC_MALLOC(n)
+#define calloc(m,n) GC_MALLOC((m)*(n))
+#define free(p) GC_FREE(p)
+#define realloc(p,n) GC_REALLOC((p),(n))
+#define CHECK_LEAKS() GC_gcollect()
+</pre>
+<P>
+Assume the collector has been built with -DFIND_LEAK. (For very
+new versions of the collector, we could instead add the statement
+<TT>GC_find_leak = 1</tt> as the first statement in <TT>main</tt>.
+<P>
+The program to be tested for leaks can then look like:
+<PRE>
+#include "leak_detector.h"
+
+main() {
+ int *p[10];
+ int i;
+ /* GC_find_leak = 1; for new collector versions not */
+ /* compiled with -DFIND_LEAK. */
+ for (i = 0; i < 10; ++i) {
+ p[i] = malloc(sizeof(int)+i);
+ }
+ for (i = 1; i < 10; ++i) {
+ free(p[i]);
+ }
+ for (i = 0; i < 9; ++i) {
+ p[i] = malloc(sizeof(int)+i);
+ }
+ CHECK_LEAKS();
+}
+</pre>
+<P>
+On an Intel X86 Linux system this produces on the stderr stream:
+<PRE>
+Leaked composite object at 0x806dff0 (leak_test.c:8, sz=4)
+</pre>
+(On most unmentioned operating systems, the output is similar to this.
+If the collector had been built on Linux/X86 with -DSAVE_CALL_CHAIN,
+the output would be closer to the Solaris example. For this to work,
+the program should not be compiled with -fomit_frame_pointer.)
+<P>
+On Irix it reports
+<PRE>
+Leaked composite object at 0x10040fe0 (leak_test.c:8, sz=4)
+ Caller at allocation:
+ ##PC##= 0x10004910
+</pre>
+and on Solaris the error report is
+<PRE>
+Leaked composite object at 0xef621fc8 (leak_test.c:8, sz=4)
+ Call chain at allocation:
+ args: 4 (0x4), 200656 (0x30FD0)
+ ##PC##= 0x14ADC
+ args: 1 (0x1), -268436012 (0xEFFFFDD4)
+ ##PC##= 0x14A64
+</pre>
+In the latter two cases some additional information is given about
+how malloc was called when the leaked object was allocated. For
+Solaris, the first line specifies the arguments to <TT>GC_debug_malloc</tt>
+(the actual allocation routine), The second the program counter inside
+main, the third the arguments to <TT>main</tt>, and finally the program
+counter inside the caller to main (i.e. in the C startup code).
+<P>
+In the Irix case, only the address inside the caller to main is given.
+<P>
+In many cases, a debugger is needed to interpret the additional information.
+On systems supporting the "adb" debugger, the <TT>callprocs</tt> script
+can be used to replace program counter values with symbolic names.
+As of version 6.1, the collector tries to generate symbolic names for
+call stacks if it knows how to do so on the platform. This is true on
+Linux/X86, but not on most other platforms.
+<H2>Simplified leak detection under Linux</h2>
+Since version 6.1, it should be possible to run the collector in leak
+detection mode on a program a.out under Linux/X86 as follows:
+<OL>
+<LI> <I>Ensure that a.out is a single-threaded executable, or you are using
+a very recent (7.0alpha7+) collector version on Linux.</i>
+On most platforms this does not
+work at all for multithreaded programs.
+<LI> If possible, ensure that the addr2line program is installed in
+/usr/bin. (It comes with RedHat Linux.)
+<LI> If possible, compile a.out with full debug information.
+This will improve the quality of the leak reports. With this approach, it is
+no longer necessary to call GC_ routines explicitly, though that can also
+improve the quality of the leak reports.
+<LI> Build the collector and install it in directory <I>foo</i> as follows:
+<UL>
+<LI> <TT>configure --prefix=<I>foo</i> --enable-full-debug --enable-redirect-malloc
+--disable-threads</tt>
+<LI> <TT>make</tt>
+<LI> <TT>make install</tt>
+</ul>
+With a very recent collector on Linux, it may be safe to omit the <TT>--disable-threads</tt>.
+<LI> Set environment variables as follows:
+<UL>
+<LI> LD_PRELOAD=<I>foo</i>/lib/libgc.so
+<LI> GC_FIND_LEAK
+<LI> You may also want to set GC_PRINT_STATS (to confirm that the collector
+is running) and/or GC_LOOP_ON_ABORT (to facilitate debugging from another
+window if something goes wrong).
+</ul
+<LI> Simply run a.out as you normally would. Note that if you run anything
+else (<I>e.g.</i> your editor) with those environment variables set,
+it will also be leak tested. This may or may not be useful and/or
+embarrassing. It can generate
+mountains of leak reports if the application wasn't designed to avoid leaks,
+<I>e.g.</i> because it's always short-lived.
+</ol>
+This has not yet been thoroughly tested on large applications, but it's known
+to do the right thing on at least some small ones.
+</body>
+</html>
diff --git a/tools/build/v2/engine/boehm_gc/doc/overview.html b/tools/build/v2/engine/boehm_gc/doc/overview.html
new file mode 100644
index 0000000000..d31f937005
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/overview.html
@@ -0,0 +1,446 @@
+<!DOCTYPE HTML>
+<html><head><title>A garbage collector for C and C++</title></head>
+<body>
+<table bgcolor="#f0f0ff" cellpadding="10%">
+ <tbody><tr>
+ <td><a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcinterface.html">Interface Overview</a></td>
+ <td><a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/04tutorial.pdf">Tutorial Slides</a></td>
+ <td><a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/faq.html">FAQ</a></td>
+ <td><a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/simple_example.html">Example</a></td>
+ <td><a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source">Download</a></td>
+ <td><a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/license.txt">License</a></td>
+ </tr>
+</tbody></table>
+<h1>A garbage collector for C and C++</h1>
+<ul>
+<li><a href="#platforms">Platforms</a>
+</li><li><a href="#multiprocessors">Scalable multiprocessor versions</a>
+</li><li><a href="#details">Some collector details</a>
+</li><li><a href="#further">Further reading</a>
+</li><li><a href="#users">Current users</a>
+</li><li><a href="#collector">Local Links for this collector</a>
+</li><li><a href="#background">Local Background Links</a>
+</li><li><a href="#contacts">Contacts and Mailing List</a>
+</li></ul>
+[ This is an updated version of the page formerly at
+<tt>http://reality.sgi.com/boehm/gc.html</tt>
+and before that at
+<a href="ftp://parcftp.xerox.com/pub/gc/gc.html">
+<tt>ftp://parcftp.xerox.com/pub/gc/gc.html</tt></a>.]
+<p>
+The <a href="http://www.hpl.hp.com/personal/Hans_Boehm">Boehm</a>-<a href="http://www.cs.cornell.edu/annual_report/00-01/bios.htm#demers">Demers</a>-<a href="http://www-sul.stanford.edu/weiser/">Weiser</a>
+conservative garbage collector can
+be used as a garbage collecting
+replacement for C <tt>malloc</tt> or C++ <tt>new</tt>.
+It allows you to allocate memory basically as you normally would,
+without explicitly deallocating memory that is no longer useful.
+The collector automatically recycles memory when it determines
+that it can no longer be otherwise accessed.
+A simple example of such a use is given
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/simple_example.html">here</a>.
+</p><p>
+The collector is also used by a number of programming language
+implementations that either use C as intermediate code, want
+to facilitate easier interoperation with C libraries, or
+just prefer the simple collector interface.
+For a more detailed description of the interface, see
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcinterface.html">here</a>.
+</p><p>
+Alternatively, the garbage collector may be used as
+a <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/leak.html">leak detector</a>
+for C or C++ programs, though that is not its primary goal.
+</p><p>
+Typically several versions will be available.
+Usually you should first try to use
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc.tar.gz"><tt>gc_source/gc.tar.gz</tt></a>,
+which is normally an older, more stable version.
+</p><p>
+If that fails, try the latest explicitly numbered version
+in <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/">
+<tt>gc_source/</tt></a>.
+Later versions may contain additional features, platform support,
+or bug fixes, but are likely to be less well tested.
+Note that versions containing the letters <tt>alpha</tt> are even less
+well tested than others, especially on non-HP platforms.
+</p><p>
+A slightly older version of the garbage collector is now also
+included as part of the
+<a href="http://gcc.gnu.org/">GNU compiler</a>
+distribution. The source
+code for that version is available for browsing
+<a href="http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/boehm-gc/">here</a>.
+</p><p>
+The arguments for and against conservative garbage collection
+in C and C++ are briefly
+discussed in
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/issues.html">issues.html</a>. The beginnings of
+a frequently-asked-questions list are <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/faq.html">here</a>.
+</p><p>
+The garbage collector code is copyrighted by
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm">Hans-J. Boehm</a>,
+Alan J. Demers,
+<a href="http://www.xerox.com/">Xerox Corporation</a>,
+<a href="http://www.sgi.com/">Silicon Graphics</a>,
+and
+<a href="http://www.hp.com/">Hewlett-Packard Company</a>.
+It may be used and copied without payment of a fee under minimal restrictions.
+See the README file in the distribution or the
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/license.txt">license</a> for more details.
+<b>IT IS PROVIDED AS IS,
+WITH ABSOLUTELY NO WARRANTY EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK</b>.
+</p><p>
+Empirically, this collector works with most unmodified C programs,
+simply by replacing
+<tt>malloc</tt> with <tt>GC_malloc</tt> calls,
+replacing <tt>realloc</tt> with <tt>GC_realloc</tt> calls, and removing
+free calls. Exceptions are discussed
+in <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/issues.html">issues.html</a>.
+</p><h2><a name="platforms">Platforms</a></h2>
+The collector is not completely portable, but the distribution
+includes ports to most standard PC and UNIX/Linux platforms.
+The collector should work on Linux, *BSD, recent Windows versions,
+MacOS X, HP/UX, Solaris,
+Tru64, Irix and a few other operating systems.
+Some ports are more polished than others.
+<p>
+Irix pthreads, Linux threads, Win32 threads, Solaris threads
+(old style and pthreads),
+HP/UX 11 pthreads, Tru64 pthreads, and MacOS X threads are supported
+in recent versions.
+</p><h3>Separately distributed ports</h3>
+For MacOS 9/Classic use, Patrick Beard's latest port is available from
+<a href="http://homepage.mac.com/pcbeard/gc/">
+<tt>http://homepage.mac.com/pcbeard/gc/</tt></a>.
+(Unfortunately, that's now quite dated.
+I'm not in a position to test under MacOS. Although I try to
+incorporate changes, it is impossible for
+me to update the project file.)
+<p>
+Precompiled versions of the collector for NetBSD are available
+<a href="ftp://ftp.netbsd.org/pub/NetBSD/packages/pkgsrc/devel/boehm-gc/README.html">here</a>
+or
+<a href="http://www.netbsd.org/packages/devel/boehm-gc/README.html">here</a>.
+</p><p>
+<a href="http://www.debian.org/">Debian Linux</a> includes prepackaged
+versions of the collector.
+</p><h2><a name="multiprocessors">Scalable multiprocessor versions</a></h2>
+Kenjiro Taura, Toshio Endo, and Akinori Yonezawa have made available
+a <a href="http://www.yl.is.s.u-tokyo.ac.jp/gc/">parallel collector</a>
+based on this one. Their collector takes advantage of multiple processors
+during a collection. Starting with collector version 6.0alpha1
+we also do this, though with more modest processor scalability goals.
+Our approach is discussed briefly in
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/scale.html"><tt>scale.html</tt></a>.
+<h2><a name="details">Some Collector Details</a></h2>
+The collector uses a <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/complexity.html">mark-sweep</a> algorithm.
+It provides incremental and generational
+collection under operating systems which provide the right kind of
+virtual memory support. (Currently this includes SunOS[45], IRIX,
+OSF/1, Linux, and Windows, with varying restrictions.)
+It allows <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/finalization.html"><i>finalization</i></a> code
+to be invoked when an object is collected.
+It can take advantage of type information to locate pointers if such
+information is provided, but it is usually used without such information.
+ee the README and
+<tt>gc.h</tt> files in the distribution for more details.
+<p>
+For an overview of the implementation, see <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcdescr.html">here</a>.
+</p><p>
+The garbage collector distribution includes a C string
+(<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/cordh.txt"><i>cord</i></a>) package that provides
+for fast concatenation and substring operations on long strings.
+A simple curses- and win32-based editor that represents the entire file
+as a cord is included as a
+sample application.
+</p><p>
+Performance of the nonincremental collector is typically competitive
+with malloc/free implementations. Both space and time overhead are
+likely to be only slightly higher
+for programs written for malloc/free
+(see Detlefs, Dosser and Zorn's
+<a href="ftp://ftp.cs.colorado.edu/pub/techreports/zorn/CU-CS-665-93.ps.Z">Memory Allocation Costs in Large C and C++ Programs</a>.)
+For programs allocating primarily very small objects, the collector
+may be faster; for programs allocating primarily large objects it will
+be slower. If the collector is used in a multithreaded environment
+and configured for thread-local allocation, it may in some cases
+significantly outperform malloc/free allocation in time.
+</p><p>
+We also expect that in many cases any additional overhead
+will be more than compensated for by decreased copying etc.
+if programs are written
+and tuned for garbage collection.
+</p><h1><a name="further">Further Reading:</a></h1>
+<b>The beginnings of a frequently asked questions list for this
+collector are <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/faq.html">here</a></b>.
+<p>
+<b>The following provide information on garbage collection in general</b>:
+</p><p>
+Paul Wilson's <a href="ftp://ftp.cs.utexas.edu/pub/garbage">garbage collection ftp archive</a> and <a href="ftp://ftp.cs.utexas.edu/pub/garbage/gcsurvey.ps">GC survey</a>.
+</p><p>
+The Ravenbrook <a href="http://www.memorymanagement.org/">
+Memory Management Reference</a>.
+</p><p>
+David Chase's
+<a href="http://www.iecc.com/gclist/GC-faq.html">GC FAQ</a>.
+</p><p>
+Richard Jones'
+<a href="http://www.ukc.ac.uk/computer_science/Html/Jones/gc.html">
+GC page</a> and
+<a href="http://www.cs.kent.ac.uk/people/staff/rej/gcbook/gcbook.html">
+his book</a>.
+</p><p>
+<b>The following papers describe the collector algorithms we use
+and the underlying design decisions at
+a higher level.</b>
+</p><p>
+(Some of the lower level details can be found
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcdescr.html">here</a>.)
+</p><p>
+The first one is not available
+electronically due to copyright considerations. Most of the others are
+subject to ACM copyright.
+</p><p>
+Boehm, H., "Dynamic Memory Allocation and Garbage Collection", <i>Computers in Physics
+9</i>, 3, May/June 1995, pp. 297-303. This is directed at an otherwise sophisticated
+audience unfamiliar with memory allocation issues. The algorithmic details differ
+from those in the implementation. There is a related letter to the editor and a minor
+correction in the next issue.
+</p><p>
+Boehm, H., and <a href="http://www.ubiq.com/hypertext/weiser/weiser.html">M. Weiser</a>,
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/spe_gc_paper">"Garbage Collection in an Uncooperative Environment"</a>,
+<i>Software Practice &amp; Experience</i>, September 1988, pp. 807-820.
+</p><p>
+Boehm, H., A. Demers, and S. Shenker, <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/papers/pldi91.ps.Z">"Mostly Parallel Garbage Collection"</a>, Proceedings
+of the ACM SIGPLAN '91 Conference on Programming Language Design and Implementation,
+<i>SIGPLAN Notices 26</i>, 6 (June 1991), pp. 157-164.
+</p><p>
+Boehm, H., <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/papers/pldi93.ps.Z">"Space Efficient Conservative Garbage Collection"</a>, Proceedings of the ACM
+SIGPLAN '93 Conference on Programming Language Design and Implementation, <i>SIGPLAN
+Notices 28</i>, 6 (June 1993), pp. 197-206.
+</p><p>
+Boehm, H., "Reducing Garbage Collector Cache Misses",
+<i> Proceedings of the 2000 International Symposium on Memory Management </i>.
+<a href="http://portal.acm.org/citation.cfm?doid=362422.362438">
+Official version.</a>
+<a href="http://www.hpl.hp.com/techreports/2000/HPL-2000-99.html">
+Technical report version.</a> Describes the prefetch strategy
+incorporated into the collector for some platforms. Explains why
+the sweep phase of a "mark-sweep" collector should not really be
+a distinct phase.
+</p><p>
+M. Serrano, H. Boehm,
+"Understanding Memory Allocation of Scheme Programs",
+<i>Proceedings of the Fifth ACM SIGPLAN International Conference on
+Functional Programming</i>, 2000, Montreal, Canada, pp. 245-256.
+<a href="http://www.acm.org/pubs/citations/proceedings/fp/351240/p245-serrano/">
+Official version.</a>
+<a href="http://www.hpl.hp.com/techreports/2000/HPL-2000-62.html">
+Earlier Technical Report version.</a> Includes some discussion of the
+collector debugging facilities for identifying causes of memory retention.
+</p><p>
+Boehm, H.,
+"Fast Multiprocessor Memory Allocation and Garbage Collection",
+<a href="http://www.hpl.hp.com/techreports/2000/HPL-2000-165.html">
+HP Labs Technical Report HPL 2000-165</a>. Discusses the parallel
+collection algorithms, and presents some performance results.
+</p><p>
+Boehm, H., "Bounding Space Usage of Conservative Garbage Collectors",
+<i>Proceeedings of the 2002 ACM SIGPLAN-SIGACT Symposium on Principles of
+Programming Languages</i>, Jan. 2002, pp. 93-100.
+<a href="http://portal.acm.org/citation.cfm?doid=503272.503282">
+Official version.</a>
+<a href="http://www.hpl.hp.com/techreports/2001/HPL-2001-251.html">
+Technical report version.</a>
+Includes a discussion of a collector facility to much more reliably test for
+the potential of unbounded heap growth.
+</p><p>
+<b>The following papers discuss language and compiler restrictions necessary to guaranteed
+safety of conservative garbage collection.</b>
+</p><p>
+We thank John Levine and JCLT for allowing
+us to make the second paper available electronically, and providing PostScript for the final
+version.
+</p><p>
+Boehm, H., <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/papers/pldi96.ps.gz">``Simple
+Garbage-Collector-Safety''</a>, Proceedings
+of the ACM SIGPLAN '96 Conference on Programming Language Design
+and Implementation.
+</p><p>
+Boehm, H., and D. Chase, <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/papers/boecha.ps.gz">
+``A Proposal for Garbage-Collector-Safe C Compilation''</a>,
+<i>Journal of C Language Translation 4</i>, 2 (Decemeber 1992), pp. 126-141.
+</p><p>
+<b>Other related information: </b>
+</p><p>
+The Detlefs, Dosser and Zorn's <a href="ftp://ftp.cs.colorado.edu/pub/techreports/zorn/CU-CS-665-93.ps.Z">Memory Allocation Costs in Large C and C++ Programs</a>.
+ This is a performance comparison of the Boehm-Demers-Weiser collector to malloc/free,
+using programs written for malloc/free.
+</p><p>
+Joel Bartlett's <a href="ftp://ftp.digital.com/pub/DEC/CCgc">mostly copying conservative garbage collector for C++</a>.
+</p><p>
+John Ellis and David Detlef's <a href="ftp://parcftp.xerox.com/pub/ellis/gc/gc.ps">Safe Efficient Garbage Collection for C++</a> proposal.
+</p><p>
+Henry Baker's <a href="http://home.pipeline.com/%7Ehbaker1/">paper collection</a>.
+</p><p>
+Slides for Hans Boehm's <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/myths.ps">Allocation and GC Myths</a> talk.
+</p><h1><a name="users">Current users:</a></h1>
+Known current users of some variant of this collector include:
+<p>
+The runtime system for <a href="http://gcc.gnu.org/java">GCJ</a>,
+the static GNU java compiler.
+</p><p>
+<a href="http://w3m.sourceforge.net/">W3m</a>, a text-based web browser.
+</p><p>
+Some versions of the Xerox DocuPrint printer software.
+</p><p>
+The <a href="http://www.mozilla.org/">Mozilla</a> project, as leak
+detector.
+</p><p>
+The <a href="http://www.go-mono.com/">Mono</a> project,
+an open source implementation of the .NET development framework.
+</p><p>
+The <a href="http://www.gnu.org/projects/dotgnu/">DotGNU Portable.NET
+project</a>, another open source .NET implementation.
+</p><p>
+The <a href="http://irssi.org/">Irssi IRC client</a>.
+</p><p>
+<a href="http://titanium.cs.berkeley.edu/">The Berkeley Titanium project</a>.
+</p><p>
+<a href="http://www.nag.co.uk/nagware_fortran_compilers.asp">The NAGWare f90 Fortran 90 compiler</a>.
+</p><p>
+Elwood Corporation's <a href="http://www.elwood.com/eclipse-info/index.htm">
+Eclipse</a> Common Lisp system, C library, and translator.
+</p><p>
+The <a href="http://www-sop.inria.fr/mimosa/fp/Bigloo/">Bigloo
+Scheme</a>
+and <a href="http://kaolin.unice.fr/%7Eserrano/camloo.html">Camloo ML
+compilers</a>
+written by Manuel Serrano and others.
+</p><p>
+Brent Benson's <a href="http://ftp.cs.indiana.edu/pub/scheme-repository/imp/">libscheme</a>.
+</p><p>
+The <a href="http://www.cs.rice.edu/CS/PLT/packages/mzscheme/index.html">MzScheme</a> scheme implementation.
+</p><p>
+The <a href="http://www.cs.washington.edu/research/projects/cecil/www/cecil-home.html">University of Washington Cecil Implementation</a>.
+</p><p>
+<a href="http://www.icsi.berkeley.edu/Sather/">The Berkeley Sather implementation</a>.
+</p><p>
+<a href="http://www.cs.berkeley.edu/%7Eharmonia/">The Berkeley Harmonia Project</a>.
+</p><p>
+The <a href="http://www.cs.arizona.edu/sumatra/toba/">Toba</a> Java Virtual
+Machine to C translator.
+</p><p>
+The <a href="http://www.gwydiondylan.org/">Gwydion Dylan compiler</a>.
+</p><p>
+The <a href="http://gcc.gnu.org/onlinedocs/gcc/Objective-C.html">
+GNU Objective C runtime</a>.
+</p><p>
+<a href="http://www.math.uiuc.edu/Macaulay2">Macaulay 2</a>, a system to support
+research in algebraic geometry and commutative algebra.
+</p><p>
+The <a href="http://www.vestasys.org/">Vesta</a> configuration management
+system.
+</p><p>
+<a href="http://www.visual-prolog.com/vip6">Visual Prolog 6</a>.
+</p><p>
+<a href="http://asymptote.sf.net/">Asymptote LaTeX-compatible
+vector graphics language.</a>
+
+</p><h1><a name="collector">More collector information at this site</a></h1>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/simple_example.html">A simple illustration of how to build and
+use the collector.</a>.
+<p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcinterface.html">Description of alternate interfaces to the
+garbage collector.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/04tutorial.pdf">Slides from an ISMM 2004 tutorial about the GC.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/faq.html">A FAQ (frequently asked questions) list.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/leak.html">How to use the garbage collector as a leak detector.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/debugging.html">Some hints on debugging garbage collected
+applications.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcdescr.html">An overview of the implementation of the
+garbage collector.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/tree.html">The data structure used for fast pointer lookups.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/scale.html">Scalability of the collector to multiprocessors.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source">Directory containing garbage collector source.</a>
+
+</p><h1><a name="background">More background information at this site</a></h1>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/bounds.html">An attempt to establish a bound on space usage of
+conservative garbage collectors.</a>
+<p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/complexity.html">Mark-sweep versus copying garbage collectors
+and their complexity.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/conservative.html">Pros and cons of conservative garbage collectors,
+in comparison to other collectors.
+</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/issues.html">Issues related to garbage collection vs.
+manual memory management in C/C++.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/example.html">An example of a case in which garbage collection
+results in a much faster implementation as a result of reduced
+synchronization.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/nonmoving">Slide set discussing performance of nonmoving
+garbage collectors.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/popl03/web">
+Slide set discussing <i>Destructors, Finalizers, and Synchronization</i>
+(POPL 2003).</a>
+</p><p>
+<a href="http://portal.acm.org/citation.cfm?doid=604131.604153">
+Paper corresponding to above slide set.</a>
+(<a href="http://www.hpl.hp.com/techreports/2002/HPL-2002-335.html">
+Technical Report version</a>.)
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_bench.html">A Java/Scheme/C/C++ garbage collection benchmark.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/myths.ps">Slides for talk on memory allocation myths.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gctalk.ps">Slides for OOPSLA 98 garbage collection talk.</a>
+</p><p>
+<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/papers">Related papers.</a>
+</p><h1><a name="contacts">Contacts and Mailing List</a><a></a></h1>
+<a>We have recently set up two mailing list for collector announcements
+and discussions:
+</a><ul>
+<li><a href="mailto:gc-announce@linux.hpl.hp.com">gc-announce@linux.hpl.hp.com</a>
+is used for announcements of new versions. Postings are restricted.
+We expect this to always remain a very low volume list.
+</li><li><a href="mailto:gc@linux.hpl.hp.com">gc@linux.hpl.hp.com</a> is used for
+discussions, bug reports, and the like. Subscribers may post.
+On-topic posts by nonsubscribers will usually also be accepted, but
+it may take some time to review them.
+</li></ul>
+To subscribe to these lists, send a mail message containing the
+word "subscribe" to
+<a href="mailto:gc-announce-request@linux.hpl.hp.com?subject=subscribe">gc-announce-request@linux.hpl.hp.com</a>
+or to
+<a href="mailto:gc-request@linux.hpl.hp.com?subject=subscribe">gc-request@linux.hpl.hp.com</a>.
+(Please ignore the instructions about web-based subscription.
+The listed web site is behind the HP firewall.)
+<p>
+The archives for these lists appear
+<a href="http://www.hpl.hp.com/hosted/linux/mail-archives">here</a>.
+The gc list archive may also be read at
+<a href="http://dir.gmane.org/gmane.comp.programming.garbage-collection.boehmgc">gmane.org</a>.
+</p><p>
+Some prior discussion of the collector has taken place on the gcc
+java mailing list, whose archives appear
+<a href="http://gcc.gnu.org/ml/java/">here</a>, and also on
+<a href="http://lists.tunes.org/mailman/listinfo/gclist">gclist@iecc.com</a>.
+</p><p>
+Comments and bug reports may also be sent to
+(<a href="mailto:Hans_Boehm@hp.com">Hans.Boehm@hp.com</a>) or
+(<a href="mailto:boehm@acm.org">boehm@acm.org</a>), but the gc
+mailing list is usually preferred.
+
+</p></body></html>
diff --git a/tools/build/v2/engine/boehm_gc/doc/porting.html b/tools/build/v2/engine/boehm_gc/doc/porting.html
new file mode 100644
index 0000000000..5a06c228e5
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/porting.html
@@ -0,0 +1,333 @@
+<HTML>
+<HEAD>
+ <TITLE>Conservative GC Porting Directions</TITLE>
+</HEAD>
+<BODY>
+<H1>Conservative GC Porting Directions</h1>
+The collector is designed to be relatively easy to port, but is not
+portable code per se. The collector inherently has to perform operations,
+such as scanning the stack(s), that are not possible in portable C code.
+<P>
+All of the following assumes that the collector is being ported to a
+byte-addressable 32- or 64-bit machine. Currently all successful ports
+to 64-bit machines involve LP64 targets. The code base includes some
+provisions for P64 targets (notably win64), but that has not been tested.
+You are hereby discouraged from attempting a port to non-byte-addressable,
+or 8-bit, or 16-bit machines.
+<P>
+The difficulty of porting the collector varies greatly depending on the needed
+functionality. In the simplest case, only some small additions are needed
+for the <TT>include/private/gcconfig.h</tt> file. This is described in the
+following section. Later sections discuss some of the optional features,
+which typically involve more porting effort.
+<P>
+Note that the collector makes heavy use of <TT>ifdef</tt>s. Unlike
+some other software projects, we have concluded repeatedly that this is preferable
+to system dependent files, with code duplicated between the files.
+However, to keep this manageable, we do strongly believe in indenting
+<TT>ifdef</tt>s correctly (for historical reasons usually without the leading
+sharp sign). (Separate source files are of course fine if they don't result in
+code duplication.)
+<H2>Adding Platforms to <TT>gcconfig.h</tt></h2>
+If neither thread support, nor tracing of dynamic library data is required,
+these are often the only changes you will need to make.
+<P>
+The <TT>gcconfig.h</tt> file consists of three sections:
+<OL>
+<LI> A section that defines GC-internal macros
+that identify the architecture (e.g. <TT>IA64</tt> or <TT>I386</tt>)
+and operating system (e.g. <TT>LINUX</tt> or <TT>MSWIN32</tt>).
+This is usually done by testing predefined macros. By defining
+our own macros instead of using the predefined ones directly, we can
+impose a bit more consistency, and somewhat isolate ourselves from
+compiler differences.
+<P>
+It is relatively straightforward to add a new entry here. But please try
+to be consistent with the existing code. In particular, 64-bit variants
+of 32-bit architectures general are <I>not</i> treated as a new architecture.
+Instead we explicitly test for 64-bit-ness in the few places in which it
+matters. (The notable exception here is <TT>I386</tt> and <TT>X86_64</tt>.
+This is partially historical, and partially justified by the fact that there
+are arguably more substantial architecture and ABI differences here than
+for RISC variants.)
+<P>
+on GNU-based systems, <TT>cpp -dM empty_source_file.c</tt> seems to generate
+a set of predefined macros. On some other systems, the "verbose"
+compiler option may do so, or the manual page may list them.
+<LI>
+A section that defines a small number of platform-specific macros, which are
+then used directly by the collector. For simple ports, this is where most of
+the effort is required. We describe the macros below.
+<P>
+This section contains a subsection for each architecture (enclosed in a
+suitable <TT>ifdef</tt>. Each subsection usually contains some
+architecture-dependent defines, followed by several sets of OS-dependent
+defines, again enclosed in <TT>ifdef</tt>s.
+<LI>
+A section that fills in defaults for some macros left undefined in the preceding
+section, and defines some other macros that rarely need adjustment for
+new platforms. You will typically not have to touch these.
+If you are porting to an OS that
+was previously completely unsupported, it is likely that you will
+need to add another clause to the definition of <TT>GET_MEM</tt>.
+</ol>
+The following macros must be defined correctly for each architecture and operating
+system:
+<DL>
+<DT><TT>MACH_TYPE</tt>
+<DD>
+Defined to a string that represents the machine architecture. Usually
+just the macro name used to identify the architecture, but enclosed in quotes.
+<DT><TT>OS_TYPE</tt>
+<DD>
+Defined to a string that represents the operating system name. Usually
+just the macro name used to identify the operating system, but enclosed in quotes.
+<DT><TT>CPP_WORDSZ</tt>
+<DD>
+The word size in bits as a constant suitable for preprocessor tests,
+i.e. without casts or sizeof expressions. Currently always defined as
+either 64 or 32. For platforms supporting both 32- and 64-bit ABIs,
+this should be conditionally defined depending on the current ABI.
+There is a default of 32.
+<DT><TT>ALIGNMENT</tt>
+<DD>
+Defined to be the largest <TT>N</tt>, such that
+all pointer are guaranteed to be aligned on <TT>N</tt>-byte boundaries.
+defining it to be 1 will always work, but perform poorly.
+For all modern 32-bit platforms, this is 4. For all modern 64-bit
+platforms, this is 8. Whether or not X86 qualifies as a modern
+architecture here is compiler- and OS-dependent.
+<DT><TT>DATASTART</tt>
+<DD>
+The beginning of the main data segment. The collector will trace all
+memory between <TT>DATASTART</tt> and <TT>DATAEND</tt> for root pointers.
+On some platforms,this can be defined to a constant address,
+though experience has shown that to be risky. Ideally the linker will
+define a symbol (e.g. <TT>_data</tt> whose address is the beginning
+of the data segment. Sometimes the value can be computed using
+the <TT>GC_SysVGetDataStart</tt> function. Not used if either
+the next macro is defined, or if dynamic loading is supported, and the
+dynamic loading support defines a function
+<TT>GC_register_main_static_data()</tt> which returns false.
+<DT><TT>SEARCH_FOR_DATA_START</tt>
+<DD>
+If this is defined <TT>DATASTART</tt> will be defined to a dynamically
+computed value which is obtained by starting with the address of
+<TT>_end</tt> and walking backwards until non-addressable memory is found.
+This often works on Posix-like platforms. It makes it harder to debug
+client programs, since startup involves generating and catching a
+segmentation fault, which tends to confuse users.
+<DT><TT>DATAEND</tt>
+<DD>
+Set to the end of the main data segment. Defaults to <TT>end</tt>,
+where that is declared as an array. This works in some cases, since
+the linker introduces a suitable symbol.
+<DT><TT>DATASTART2, DATAEND2</tt>
+<DD>
+Some platforms have two discontiguous main data segments, e.g.
+for initialized and uninitialized data. If so, these two macros
+should be defined to the limits of the second main data segment.
+<DT><TT>STACK_GROWS_UP</tt>
+<DD>
+Should be defined if the stack (or thread stacks) grow towards higher
+addresses. (This appears to be true only on PA-RISC. If your architecture
+has more than one stack per thread, and is not already supported, you will
+need to do more work. Grep for "IA64" in the source for an example.)
+<DT><TT>STACKBOTTOM</tt>
+<DD>
+Defined to be the cool end of the stack, which is usually the
+highest address in the stack. It must bound the region of the
+stack that contains pointers into the GC heap. With thread support,
+this must be the cold end of the main stack, which typically
+cannot be found in the same way as the other thread stacks.
+If this is not defined and none of the following three macros
+is defined, client code must explicitly set
+<TT>GC_stackbottom</tt> to an appropriate value before calling
+<TT>GC_INIT()</tt> or any other <TT>GC_</tt> routine.
+<DT><TT>LINUX_STACKBOTTOM</tt>
+<DD>
+May be defined instead of <TT>STACKBOTTOM</tt>.
+If defined, then the cold end of the stack will be determined
+Currently we usually read it from /proc.
+<DT><TT>HEURISTIC1</tt>
+<DD>
+May be defined instead of <TT>STACKBOTTOM</tt>.
+<TT>STACK_GRAN</tt> should generally also be undefined and defined.
+The cold end of the stack is determined by taking an address inside
+<TT>GC_init's frame</tt>, and rounding it up to
+the next multiple of <TT>STACK_GRAN</tt>. This works well if the stack base is
+always aligned to a large power of two.
+(<TT>STACK_GRAN</tt> is predefined to 0x1000000, which is
+rarely optimal.)
+<DT><TT>HEURISTIC2</tt>
+<DD>
+May be defined instead of <TT>STACKBOTTOM</tt>.
+The cold end of the stack is determined by taking an address inside
+GC_init's frame, incrementing it repeatedly
+in small steps (decrement if <TT>STACK_GROWS_UP</tt>), and reading the value
+at each location. We remember the value when the first
+Segmentation violation or Bus error is signalled, round that
+to the nearest plausible page boundary, and use that as the
+stack base.
+<DT><TT>DYNAMIC_LOADING</tt>
+<DD>
+Should be defined if <TT>dyn_load.c</tt> has been updated for this
+platform and tracing of dynamic library roots is supported.
+<DT><TT>MPROTECT_VDB, PROC_VDB</tt>
+<DD>
+May be defined if the corresponding "virtual dirty bit"
+implementation in os_dep.c is usable on this platform. This
+allows incremental/generational garbage collection.
+<TT>MPROTECT_VDB</tt> identifies modified pages by
+write protecting the heap and catching faults.
+<TT>PROC_VDB</tt> uses the /proc primitives to read dirty bits.
+<DT><TT>PREFETCH, PREFETCH_FOR_WRITE</tt>
+<DD>
+The collector uses <TT>PREFETCH</tt>(<I>x</i>) to preload the cache
+with *<I>x</i>.
+This defaults to a no-op.
+<DT><TT>CLEAR_DOUBLE</tt>
+<DD>
+If <TT>CLEAR_DOUBLE</tt> is defined, then
+<TT>CLEAR_DOUBLE</tt>(x) is used as a fast way to
+clear the two words at GC_malloc-aligned address x. By default,
+word stores of 0 are used instead.
+<DT><TT>HEAP_START</tt>
+<DD>
+<TT>HEAP_START</tt> may be defined as the initial address hint for mmap-based
+allocation.
+<DT><TT>ALIGN_DOUBLE</tt>
+<DD>
+Should be defined if the architecture requires double-word alignment
+of <TT>GC_malloc</tt>ed memory, e.g. 8-byte alignment with a
+32-bit ABI. Most modern machines are likely to require this.
+This is no longer needed for GC7 and later.
+</dl>
+<H2>Additional requirements for a basic port</h2>
+In some cases, you may have to add additional platform-specific code
+to other files. A likely candidate is the implementation of
+<TT>GC_with_callee_saves_pushed</tt> in </tt>mach_dep.c</tt>.
+This ensure that register contents that the collector must trace
+from are copied to the stack. Typically this can be done portably,
+but on some platforms it may require assembly code, or just
+tweaking of conditional compilation tests.
+<P>
+For GC7, if your platform supports <TT>getcontext()</tt>, then definining
+the macro <TT>UNIX_LIKE</tt> for your OS in <TT>gcconfig.h</tt>
+(if it isn't defined there already) is likely to solve the problem.
+otherwise, if you are using gcc, <TT>_builtin_unwind_init()</tt>
+will be used, and should work fine. If that is not applicable either,
+the implementation will try to use <TT>setjmp()</tt>. This will work if your
+<TT>setjmp</tt> implementation saves all possibly pointer-valued registers
+into the buffer, as opposed to trying to unwind the stack at
+<TT>longjmp</tt> time. The <TT>setjmp_test</tt> test tries to determine this,
+but often doesn't get it right.
+<P>
+In GC6.x versions of the collector, tracing of registers
+was more commonly handled
+with assembly code. In GC7, this is generally to be avoided.
+<P>
+Most commonly <TT>os_dep.c</tt> will not require attention, but see below.
+<H2>Thread support</h2>
+Supporting threads requires that the collector be able to find and suspend
+all threads potentially accessing the garbage-collected heap, and locate
+any state associated with each thread that must be traced.
+<P>
+The functionality needed for thread support is generally implemented
+in one or more files specific to the particular thread interface.
+For example, somewhat portable pthread support is implemented
+in <TT>pthread_support.c</tt> and <TT>pthread_stop_world.c</tt>.
+The essential functionality consists of
+<DL>
+<DT><TT>GC_stop_world()</tt>
+<DD>
+Stops all threads which may access the garbage collected heap, other
+than the caller.
+<DT><TT>GC_start_world()</tt>
+<DD>
+Restart other threads.
+<DT><TT>GC_push_all_stacks()</tt>
+<DD>
+Push the contents of all thread stacks (or at least of pointer-containing
+regions in the thread stacks) onto the mark stack.
+</dl>
+These very often require that the garbage collector maintain its
+own data structures to track active threads.
+<P>
+In addition, <TT>LOCK</tt> and <TT>UNLOCK</tt> must be implemented
+in <TT>gc_locks.h</tt>
+<P>
+The easiest case is probably a new pthreads platform
+on which threads can be stopped
+with signals. In this case, the changes involve:
+<OL>
+<LI>Introducing a suitable <TT>GC_</tt><I>X</i><TT>_THREADS</tt> macro, which should
+be automatically defined by <TT>gc_config_macros.h</tt> in the right cases.
+It should also result in a definition of <TT>GC_PTHREADS</tt>, as for the
+existing cases.
+<LI>For GC7+, ensuring that the <TT>atomic_ops</tt> package at least
+minimally supports the platform.
+If incremental GC is needed, or if pthread locks don't
+perform adequately as the allocation lock, you will probably need to
+ensure that a sufficient <TT>atomic_ops</tt> port
+exists for the platform to provided an atomic test and set
+operation. (Current GC7 versions require more<TT>atomic_ops</tt>
+asupport than necessary. This is a bug.) For earlier versions define
+<TT>GC_test_and_set</tt> in <TT>gc_locks.h</tt>.
+<LI>Making any needed adjustments to <TT>pthread_stop_world.c</tt> and
+<TT>pthread_support.c</tt>. Ideally none should be needed. In fact,
+not all of this is as well standardized as one would like, and outright
+bugs requiring workarounds are common.
+</ol>
+Non-preemptive threads packages will probably require further work. Similarly
+thread-local allocation and parallel marking requires further work
+in <TT>pthread_support.c</tt>, and may require better <TT>atomic_ops</tt>
+support.
+<H2>Dynamic library support</h2>
+So long as <TT>DATASTART</tt> and <TT>DATAEND</tt> are defined correctly,
+the collector will trace memory reachable from file scope or <TT>static</tt>
+variables defined as part of the main executable. This is sufficient
+if either the program is statically linked, or if pointers to the
+garbage-collected heap are never stored in non-stack variables
+defined in dynamic libraries.
+<P>
+If dynamic library data sections must also be traced, then
+<UL>
+<LI><TT>DYNAMIC_LOADING</tt> must be defined in the appropriate section
+of <TT>gcconfig.h</tt>.
+<LI>An appropriate versions of the functions
+<TT>GC_register_dynamic_libraries()</tt> should be defined in
+<TT>dyn_load.c</tt>. This function should invoke
+<TT>GC_cond_add_roots(</tt><I>region_start, region_end</i><TT>, TRUE)</tt>
+on each dynamic library data section.
+</ul>
+<P>
+Implementations that scan for writable data segments are error prone, particularly
+in the presence of threads. They frequently result in race conditions
+when threads exit and stacks disappear. They may also accidentally trace
+large regions of graphics memory, or mapped files. On at least
+one occasion they have been known to try to trace device memory that
+could not safely be read in the manner the GC wanted to read it.
+<P>
+It is usually safer to walk the dynamic linker data structure, especially
+if the linker exports an interface to do so. But beware of poorly documented
+locking behavior in this case.
+<H2>Incremental GC support</h2>
+For incremental and generational collection to work, <TT>os_dep.c</tt>
+must contain a suitable "virtual dirty bit" implementation, which
+allows the collector to track which heap pages (assumed to be
+a multiple of the collectors block size) have been written during
+a certain time interval. The collector provides several
+implementations, which might be adapted. The default
+(<TT>DEFAULT_VDB</tt>) is a placeholder which treats all pages
+as having been written. This ensures correctness, but renders
+incremental and generational collection essentially useless.
+<H2>Stack traces for debug support</h2>
+If stack traces in objects are need for debug support,
+<TT>GC_dave_callers</tt> and <TT>GC_print_callers</tt> must be
+implemented.
+<H2>Disclaimer</h2>
+This is an initial pass at porting guidelines. Some things
+have no doubt been overlooked.
+</body>
+</html>
diff --git a/tools/build/v2/engine/boehm_gc/doc/scale.html b/tools/build/v2/engine/boehm_gc/doc/scale.html
new file mode 100644
index 0000000000..2e70148dfb
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/scale.html
@@ -0,0 +1,210 @@
+<HTML>
+<HEAD>
+<TITLE>Garbage collector scalability</TITLE>
+</HEAD>
+<BODY>
+<H1>Garbage collector scalability</h1>
+In its default configuration, the Boehm-Demers-Weiser garbage collector
+is not thread-safe. It can be made thread-safe for a number of environments
+by building the collector with the appropriate
+<TT>-D</tt><I>XXX</i><TT>-THREADS</tt> compilation
+flag. This has primarily two effects:
+<OL>
+<LI> It causes the garbage collector to stop all other threads when
+it needs to see a consistent memory state.
+<LI> It causes the collector to acquire a lock around essentially all
+allocation and garbage collection activity.
+</ol>
+Since a single lock is used for all allocation-related activity, only one
+thread can be allocating or collecting at one point. This inherently
+limits performance of multi-threaded applications on multiprocessors.
+<P>
+On most platforms, the allocator/collector lock is implemented as a
+spin lock with exponential back-off. Longer wait times are implemented
+by yielding and/or sleeping. If a collection is in progress, the pure
+spinning stage is skipped. This has the advantage that uncontested and
+thus most uniprocessor lock acquisitions are very cheap. It has the
+disadvantage that the application may sleep for small periods of time
+even when there is work to be done. And threads may be unnecessarily
+woken up for short periods. Nonetheless, this scheme empirically
+outperforms native queue-based mutual exclusion implementations in most
+cases, sometimes drastically so.
+<H2>Options for enhanced scalability</h2>
+Version 6.0 of the collector adds two facilities to enhance collector
+scalability on multiprocessors. As of 6.0alpha1, these are supported
+only under Linux on X86 and IA64 processors, though ports to other
+otherwise supported Pthreads platforms should be straightforward.
+They are intended to be used together.
+<UL>
+<LI>
+Building the collector with <TT>-DPARALLEL_MARK</tt> allows the collector to
+run the mark phase in parallel in multiple threads, and thus on multiple
+processors. The mark phase typically consumes the large majority of the
+collection time. Thus this largely parallelizes the garbage collector
+itself, though not the allocation process. Currently the marking is
+performed by the thread that triggered the collection, together with
+<I>N</i>-1 dedicated
+threads, where <I>N</i> is the number of processors detected by the collector.
+The dedicated threads are created once at initialization time.
+<P>
+A second effect of this flag is to switch to a more concurrent
+implementation of <TT>GC_malloc_many</tt>, so that free lists can be
+built, and memory can be cleared, by more than one thread concurrently.
+<LI>
+Building the collector with -DTHREAD_LOCAL_ALLOC adds support for thread
+local allocation. It does not, by itself, cause thread local allocation
+to be used. It simply allows the use of the interface in
+<TT>gc_local_alloc.h</tt>.
+<P>
+Memory returned from thread-local allocators is completely interchangeable
+with that returned by the standard allocators. It may be used by other
+threads. The only difference is that, if the thread allocates enough
+memory of a certain kind, it will build a thread-local free list for
+objects of that kind, and allocate from that. This greatly reduces
+locking. The thread-local free lists are refilled using
+<TT>GC_malloc_many</tt>.
+<P>
+An important side effect of this flag is to replace the default
+spin-then-sleep lock to be replace by a spin-then-queue based implementation.
+This <I>reduces performance</i> for the standard allocation functions,
+though it usually improves performance when thread-local allocation is
+used heavily, and thus the number of short-duration lock acquisitions
+is greatly reduced.
+</ul>
+<P>
+The easiest way to switch an application to thread-local allocation is to
+<OL>
+<LI> Define the macro <TT>GC_REDIRECT_TO_LOCAL</tt>,
+and then include the <TT>gc.h</tt>
+header in each client source file.
+<LI> Invoke <TT>GC_thr_init()</tt> before any allocation.
+<LI> Allocate using <TT>GC_MALLOC</tt>, <TT>GC_MALLOC_ATOMIC</tt>,
+and/or <TT>GC_GCJ_MALLOC</tt>.
+</ol>
+<H2>The Parallel Marking Algorithm</h2>
+We use an algorithm similar to
+<A HREF="http://www.yl.is.s.u-tokyo.ac.jp/gc/">that developed by
+Endo, Taura, and Yonezawa</a> at the University of Tokyo.
+However, the data structures and implementation are different,
+and represent a smaller change to the original collector source,
+probably at the expense of extreme scalability. Some of
+the refinements they suggest, <I>e.g.</i> splitting large
+objects, were also incorporated into out approach.
+<P>
+The global mark stack is transformed into a global work queue.
+Unlike the usual case, it never shrinks during a mark phase.
+The mark threads remove objects from the queue by copying them to a
+local mark stack and changing the global descriptor to zero, indicating
+that there is no more work to be done for this entry.
+This removal
+is done with no synchronization. Thus it is possible for more than
+one worker to remove the same entry, resulting in some work duplication.
+<P>
+The global work queue grows only if a marker thread decides to
+return some of its local mark stack to the global one. This
+is done if the global queue appears to be running low, or if
+the local stack is in danger of overflowing. It does require
+synchronization, but should be relatively rare.
+<P>
+The sequential marking code is reused to process local mark stacks.
+Hence the amount of additional code required for parallel marking
+is minimal.
+<P>
+It should be possible to use generational collection in the presence of the
+parallel collector, by calling <TT>GC_enable_incremental()</tt>.
+This does not result in fully incremental collection, since parallel mark
+phases cannot currently be interrupted, and doing so may be too
+expensive.
+<P>
+Gcj-style mark descriptors do not currently mix with the combination
+of local allocation and incremental collection. They should work correctly
+with one or the other, but not both.
+<P>
+The number of marker threads is set on startup to the number of
+available processors (or to the value of the <TT>GC_NPROCS</tt>
+environment variable). If only a single processor is detected,
+parallel marking is disabled.
+<P>
+Note that setting GC_NPROCS to 1 also causes some lock acquisitions inside
+the collector to immediately yield the processor instead of busy waiting
+first. In the case of a multiprocessor and a client with multiple
+simultaneously runnable threads, this may have disastrous performance
+consequences (e.g. a factor of 10 slowdown).
+<H2>Performance</h2>
+We conducted some simple experiments with a version of
+<A HREF="gc_bench.html">our GC benchmark</a> that was slightly modified to
+run multiple concurrent client threads in the same address space.
+Each client thread does the same work as the original benchmark, but they share
+a heap.
+This benchmark involves very little work outside of memory allocation.
+This was run with GC 6.0alpha3 on a dual processor Pentium III/500 machine
+under Linux 2.2.12.
+<P>
+Running with a thread-unsafe collector, the benchmark ran in 9
+seconds. With the simple thread-safe collector,
+built with <TT>-DLINUX_THREADS</tt>, the execution time
+increased to 10.3 seconds, or 23.5 elapsed seconds with two clients.
+(The times for the <TT>malloc</tt>/i<TT>free</tt> version
+with glibc <TT>malloc</tt>
+are 10.51 (standard library, pthreads not linked),
+20.90 (one thread, pthreads linked),
+and 24.55 seconds respectively. The benchmark favors a
+garbage collector, since most objects are small.)
+<P>
+The following table gives execution times for the collector built
+with parallel marking and thread-local allocation support
+(<TT>-DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC</tt>). We tested
+the client using either one or two marker threads, and running
+one or two client threads. Note that the client uses thread local
+allocation exclusively. With -DTHREAD_LOCAL_ALLOC the collector
+switches to a locking strategy that is better tuned to less frequent
+lock acquisition. The standard allocation primitives thus peform
+slightly worse than without -DTHREAD_LOCAL_ALLOC, and should be
+avoided in time-critical code.
+<P>
+(The results using <TT>pthread_mutex_lock</tt>
+directly for allocation locking would have been worse still, at
+least for older versions of linuxthreads.
+With THREAD_LOCAL_ALLOC, we first repeatedly try to acquire the
+lock with pthread_mutex_try_lock(), busy_waiting between attempts.
+After a fixed number of attempts, we use pthread_mutex_lock().)
+<P>
+These measurements do not use incremental collection, nor was prefetching
+enabled in the marker. We used the C version of the benchmark.
+All measurements are in elapsed seconds on an unloaded machine.
+<P>
+<TABLE BORDER ALIGN="CENTER">
+<TR><TH>Number of threads</th><TH>1 marker thread (secs.)</th>
+<TH>2 marker threads (secs.)</th></tr>
+<TR><TD>1 client</td><TD ALIGN="CENTER">10.45</td><TD ALIGN="CENTER">7.85</td>
+<TR><TD>2 clients</td><TD ALIGN="CENTER">19.95</td><TD ALIGN="CENTER">12.3</td>
+</table>
+<PP>
+The execution time for the single threaded case is slightly worse than with
+simple locking. However, even the single-threaded benchmark runs faster than
+even the thread-unsafe version if a second processor is available.
+The execution time for two clients with thread local allocation time is
+only 1.4 times the sequential execution time for a single thread in a
+thread-unsafe environment, even though it involves twice the client work.
+That represents close to a
+factor of 2 improvement over the 2 client case with the old collector.
+The old collector clearly
+still suffered from some contention overhead, in spite of the fact that the
+locking scheme had been fairly well tuned.
+<P>
+Full linear speedup (i.e. the same execution time for 1 client on one
+processor as 2 clients on 2 processors)
+is probably not achievable on this kind of
+hardware even with such a small number of processors,
+since the memory system is
+a major constraint for the garbage collector,
+the processors usually share a single memory bus, and thus
+the aggregate memory bandwidth does not increase in
+proportion to the number of processors.
+<P>
+These results are likely to be very sensitive to both hardware and OS
+issues. Preliminary experiments with an older Pentium Pro machine running
+an older kernel were far less encouraging.
+
+</body>
+</html>
diff --git a/tools/build/v2/engine/boehm_gc/doc/simple_example.html b/tools/build/v2/engine/boehm_gc/doc/simple_example.html
new file mode 100644
index 0000000000..0bc0953ef0
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/simple_example.html
@@ -0,0 +1,202 @@
+<HTML>
+<HEAD>
+<TITLE>Using the Garbage Collector: A simple example</title>
+</head>
+<BODY>
+<H1>Using the Garbage Collector: A simple example</h1>
+The following consists of step-by-step instructions for building and
+using the collector. We'll assume a Linux/gcc platform and
+a single-threaded application. <FONT COLOR=green>The green
+text contains information about other platforms or scenarios.
+It can be skipped, especially on first reading</font>.
+<H2>Building the collector</h2>
+If you haven't already so, unpack the collector and enter
+the newly created directory with
+<PRE>
+tar xvfz gc<version>.tar.gz
+cd gc<version>
+</pre>
+<P>
+You can configure, build, and install the collector in a private
+directory, say /home/xyz/gc, with the following commands:
+<PRE>
+./configure --prefix=/home/xyz/gc --disable-threads
+make
+make check
+make install
+</pre>
+Here the "<TT>make check</tt>" command is optional, but highly recommended.
+It runs a basic correctness test which usually takes well under a minute.
+<FONT COLOR=green>
+<H3>Other platforms</h3>
+On non-Unix, non-Linux platforms, the collector is usually built by copying
+the appropriate makefile (see the platform-specific README in doc/README.xxx
+in the distribution) to the file "Makefile" (overwriting the copy of
+Makefile.direct that was originally there), and then typing "make"
+(or "nmake" or ...). This builds the library in the source tree. You may
+want to move it and the files in the include directory to a more convenient
+place.
+<P>
+If you use a makefile that does not require running a configure script,
+you should first look at the makefile, and adjust any options that are
+documented there.
+<P>
+If your platform provides a "make" utility, that is generally preferred
+to platform- and compiler- dependent "project" files. (At least that is the
+strong preference of the would-be maintainer of those project files.)
+<H3>Threads</h3>
+If you need thread support, configure the collector with
+<PRE>
+--enable-threads=posix --enable-thread-local-alloc --enable-parallel-mark
+</pre>
+instead of
+<TT>--disable-threads</tt>
+If your target is a real old-fashioned uniprocessor (no "hyperthreading",
+etc.) you will want to omit <TT>--enable-parallel-mark</tt>.
+<H3>C++</h3>
+You will need to include the C++ support, which unfortunately tends to
+be among the least portable parts of the collector, since it seems
+to rely on some corner cases of the language. On Linux, it
+suffices to add <TT>--enable-cplusplus</tt> to the configure options.
+</font>
+<H2>Writing the program</h2>
+You will need a
+<PRE>
+#include "gc.h"
+</pre>
+at the beginning of every file that allocates memory through the
+garbage collector. Call <TT>GC_MALLOC</tt> wherever you would
+have call <TT>malloc</tt>. This initializes memory to zero like
+<TT>calloc</tt>; there is no need to explicitly clear the
+result.
+<P>
+If you know that an object will not contain pointers to the
+garbage-collected heap, and you don't need it to be initialized,
+call <TT>GC_MALLOC_ATOMIC</tt> instead.
+<P>
+A function <TT>GC_FREE</tt> is provided but need not be called.
+For very small objects, your program will probably perform better if
+you do not call it, and let the collector do its job.
+<P>
+A <TT>GC_REALLOC</tt> function behaves like the C library <TT>realloc</tt>.
+It allocates uninitialized pointer-free memory if the original
+object was allocated that way.
+<P>
+The following program <TT>loop.c</tt> is a trivial example:
+<PRE>
+#include "gc.h"
+#include &lt;assert.h&gt;
+#include &lt;stdio.h&gt;
+
+int main()
+{
+ int i;
+
+ GC_INIT(); /* Optional on Linux/X86; see below. */
+ for (i = 0; i < 10000000; ++i)
+ {
+ int **p = (int **) GC_MALLOC(sizeof(int *));
+ int *q = (int *) GC_MALLOC_ATOMIC(sizeof(int));
+ assert(*p == 0);
+ *p = (int *) GC_REALLOC(q, 2 * sizeof(int));
+ if (i % 100000 == 0)
+ printf("Heap size = %d\n", GC_get_heap_size());
+ }
+ return 0;
+}
+</pre>
+<FONT COLOR=green>
+<H3>Interaction with the system malloc</h3>
+It is usually best not to mix garbage-collected allocation with the system
+<TT>malloc-free</tt>. If you do, you need to be careful not to store
+pointers to the garbage-collected heap in memory allocated with the system
+<TT>malloc</tt>.
+<H3>Other Platforms</h3>
+On some other platforms it is necessary to call <TT>GC_INIT()</tt> from the main program,
+which is presumed to be part of the main executable, not a dynamic library.
+This can never hurt, and is thus generally good practice.
+
+<H3>Threads</h3>
+For a multithreaded program some more rules apply:
+<UL>
+<LI>
+Files that either allocate through the GC <I>or make thread-related calls</i>
+should first define the macro <TT>GC_THREADS</tt>, and then
+include <TT>"gc.h"</tt>. On some platforms this will redefine some
+threads primitives, e.g. to let the collector keep track of thread creation.
+<LI>
+To take advantage of fast thread-local allocation, use the following instead
+of including <TT>gc.h</tt>:
+<PRE>
+#define GC_REDIRECT_TO_LOCAL
+#include "gc_local_alloc.h"
+</pre>
+This will cause GC_MALLOC and GC_MALLOC_ATOMIC to keep per-thread allocation
+caches, and greatly reduce the number of lock acquisitions during allocation.
+</ul>
+
+<H3>C++</h3>
+In the case of C++, you need to be especially careful not to store pointers
+to the garbage-collected heap in areas that are not traced by the collector.
+The collector includes some <A HREF="gcinterface.html">alternate interfaces</a>
+to make that easier.
+
+<H3>Debugging</h3>
+Additional debug checks can be performed by defining <TT>GC_DEBUG</tt> before
+including <TT>gc.h</tt>. Additional options are available if the collector
+is also built with <TT>--enable-full_debug</tt> and all allocations are
+performed with <TT>GC_DEBUG</tt> defined.
+
+<H3>What if I can't rewrite/recompile my program?</h3>
+You may be able to build the collector with <TT>--enable-redirect-malloc</tt>
+and set the <TT>LD_PRELOAD</tt> environment variable to point to the resulting
+library, thus replacing the standard <TT>malloc</tt> with its garbage-collected
+counterpart. This is rather platform dependent. See the
+<A HREF="leak.html">leak detection documentation</a> for some more details.
+
+</font>
+
+<H2>Compiling and linking</h2>
+
+The above application <TT>loop.c</tt> test program can be compiled and linked
+with
+
+<PRE>
+cc -I/home/xyz/gc/include loop.c /home/xyz/gc/lib/libgc.a -o loop
+</pre>
+
+The <TT>-I</tt> option directs the compiler to the right include
+directory. In this case, we list the static library
+directly on the compile line; the dynamic library could have been
+used instead, provided we arranged for the dynamic loader to find
+it, e.g. by setting <TT>LD_LIBRARY_PATH</tt>.
+
+<FONT COLOR=green>
+
+<H3>Threads</h3>
+
+On pthread platforms, you will of course also have to link with
+<TT>-lpthread</tt>,
+and compile with any thread-safety options required by your compiler.
+On some platforms, you may also need to link with <TT>-ldl</tt>
+or <TT>-lrt</tt>.
+Looking at threadlibs.c in the GC build directory
+should give you the appropriate
+list if a plain <TT>-lpthread</tt> doesn't work.
+
+</font>
+
+<H2>Running the executable</h2>
+
+The executable can of course be run normally, e.g. by typing
+
+<PRE>
+./loop
+</pre>
+
+The operation of the collector is affected by a number of environment variables.
+For example, setting <TT>GC_PRINT_STATS</tt> produces some
+GC statistics on stdout.
+See <TT>README.environment</tt> in the distribution for details.
+</body>
+</html>
diff --git a/tools/build/v2/engine/boehm_gc/doc/tree.html b/tools/build/v2/engine/boehm_gc/doc/tree.html
new file mode 100644
index 0000000000..c46a281cc6
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/doc/tree.html
@@ -0,0 +1,199 @@
+<HTML>
+<HEAD>
+ <TITLE> Two-Level Tree Structure for Fast Pointer Lookup</TITLE>
+ <AUTHOR> Hans-J. Boehm, Silicon Graphics (now at HP)</author>
+</HEAD>
+<BODY>
+<H1>Two-Level Tree Structure for Fast Pointer Lookup</h1>
+<P>
+The conservative garbage collector described
+<A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/">here</a>
+uses a 2-level tree
+data structure to aid in fast pointer identification.
+This data structure is described in a bit more detail here, since
+<OL>
+<LI> Variations of the data structure are more generally useful.
+<LI> It appears to be hard to understand by reading the code.
+<LI> Some other collectors appear to use inferior data structures to
+solve the same problem.
+<LI> It is central to fast collector operation.
+</ol>
+A candidate pointer is divided into three sections, the <I>high</i>,
+<I>middle</i>, and <I>low</i> bits. The exact division between these
+three groups of bits is dependent on the detailed collector configuration.
+<P>
+The high and middle bits are used to look up an entry in the table described
+here. The resulting table entry consists of either a block descriptor
+(<TT>struct hblkhdr *</tt> or <TT>hdr *</tt>)
+identifying the layout of objects in the block, or an indication that this
+address range corresponds to the middle of a large block, together with a
+hint for locating the actual block descriptor. Such a hint consist
+of a displacement that can be subtracted from the middle bits of the candidate
+pointer without leaving the object.
+<P>
+In either case, the block descriptor (<TT>struct hblkhdr</tt>)
+refers to a table of object starting addresses (the <TT>hb_map</tt> field).
+The starting address table is indexed by the low bits if the candidate pointer.
+The resulting entry contains a displacement to the beginning of the object,
+or an indication that this cannot be a valid object pointer.
+(If all interior pointer are recognized, pointers into large objects
+are handled specially, as appropriate.)
+
+<H2>The Tree</h2>
+<P>
+The rest of this discussion focuses on the two level data structure
+used to map the high and middle bits to the block descriptor.
+<P>
+The high bits are used as an index into the <TT>GC_top_index</tt> (really
+<TT>GC_arrays._top_index</tt>) array. Each entry points to a
+<TT>bottom_index</tt> data structure. This structure in turn consists
+mostly of an array <TT>index</tt> indexed by the middle bits of
+the candidate pointer. The <TT>index</tt> array contains the actual
+<TT>hdr</tt> pointers.
+<P>
+Thus a pointer lookup consists primarily of a handful of memory references,
+and can be quite fast:
+<OL>
+<LI> The appropriate <TT>bottom_index</tt> pointer is looked up in
+<TT>GC_top_index</tt>, based on the high bits of the candidate pointer.
+<LI> The appropriate <TT>hdr</tt> pointer is looked up in the
+<TT>bottom_index</tt> structure, based on the middle bits.
+<LI> The block layout map pointer is retrieved from the <TT>hdr</tt>
+structure. (This memory reference is necessary since we try to share
+block layout maps.)
+<LI> The displacement to the beginning of the object is retrieved from the
+above map.
+</ol>
+<P>
+In order to conserve space, not all <TT>GC_top_index</tt> entries in fact
+point to distinct <TT>bottom_index</tt> structures. If no address with
+the corresponding high bits is part of the heap, then the entry points
+to <TT>GC_all_nils</tt>, a single <TT>bottom_index</tt> structure consisting
+only of NULL <TT>hdr</tt> pointers.
+<P>
+<TT>Bottom_index</tt> structures contain slightly more information than
+just <TT>hdr</tt> pointers. The <TT>asc_link</tt> field is used to link
+all <TT>bottom_index</tt> structures in ascending order for fast traversal.
+This list is pointed to be <TT>GC_all_bottom_indices</tt>.
+It is maintained with the aid of <TT>key</tt> field that contains the
+high bits corresponding to the <TT>bottom_index</tt>.
+
+<H2>64 bit addresses</h2>
+<P>
+In the case of 64 bit addresses, this picture is complicated slightly
+by the fact that one of the index structures would have to be huge to
+cover the entire address space with a two level tree. We deal with this
+by turning <TT>GC_top_index</tt> into a chained hash table, instead of
+a simple array. This adds a <TT>hash_link</tt> field to the
+<TT>bottom_index</tt> structure.
+<P>
+The "hash function" consists of dropping the high bits. This is cheap to
+compute, and guarantees that there will be no collisions if the heap
+is contiguous and not excessively large.
+
+<H2>A picture</h2>
+<P>
+The following is an ASCII diagram of the data structure.
+This was contributed by Dave Barrett several years ago.
+<PRE>
+
+ Data Structure used by GC_base in gc3.7:
+ 21-Apr-94
+
+
+
+
+ 63 LOG_TOP_SZ[11] LOG_BOTTOM_SZ[10] LOG_HBLKSIZE[13]
+ +------------------+----------------+------------------+------------------+
+ p:| | TL_HASH(hi) | | HBLKDISPL(p) |
+ +------------------+----------------+------------------+------------------+
+ \-----------------------HBLKPTR(p)-------------------/
+ \------------hi-------------------/
+ \______ ________/ \________ _______/ \________ _______/
+ V V V
+ | | |
+ GC_top_index[] | | |
+ --- +--------------+ | | |
+ ^ | | | | |
+ | | | | | |
+ TOP +--------------+<--+ | |
+ _SZ +-<| [] | * | |
+(items)| +--------------+ if 0 < bi< HBLKSIZE | |
+ | | | | then large object | |
+ | | | | starts at the bi'th | |
+ v | | | HBLK before p. | i |
+ --- | +--------------+ | (word- |
+ v | aligned) |
+ bi= |GET_BI(p){->hash_link}->key==hi | |
+ v | |
+ | (bottom_index) \ scratch_alloc'd | |
+ | ( struct bi ) / by get_index() | |
+ --- +->+--------------+ | |
+ ^ | | | |
+ ^ | | | |
+ BOTTOM | | ha=GET_HDR_ADDR(p) | |
+_SZ(items)+--------------+<----------------------+ +-------+
+ | +--<| index[] | |
+ | | +--------------+ GC_obj_map: v
+ | | | | from / +-+-+-----+-+-+-+-+ ---
+ v | | | GC_add < 0| | | | | | | | ^
+ --- | +--------------+ _map_entry \ +-+-+-----+-+-+-+-+ |
+ | | asc_link | +-+-+-----+-+-+-+-+ MAXOBJSZ
+ | +--------------+ +-->| | | j | | | | | +1
+ | | key | | +-+-+-----+-+-+-+-+ |
+ | +--------------+ | +-+-+-----+-+-+-+-+ |
+ | | hash_link | | | | | | | | | | v
+ | +--------------+ | +-+-+-----+-+-+-+-+ ---
+ | | |<--MAX_OFFSET--->|
+ | | (bytes)
+HDR(p)| GC_find_header(p) | |<--MAP_ENTRIES-->|
+ | \ from | =HBLKSIZE/WORDSZ
+ | (hdr) (struct hblkhdr) / alloc_hdr() | (1024 on Alpha)
+ +-->+----------------------+ | (8/16 bits each)
+GET_HDR(p)| word hb_sz (words) | |
+ +----------------------+ |
+ | struct hblk *hb_next | |
+ +----------------------+ |
+ |mark_proc hb_mark_proc| |
+ +----------------------+ |
+ | char * hb_map |>-------------+
+ +----------------------+
+ | ushort hb_obj_kind |
+ +----------------------+
+ | hb_last_reclaimed |
+ --- +----------------------+
+ ^ | |
+ MARK_BITS| hb_marks[] | *if hdr is free, hb_sz + DISCARD_WORDS
+_SZ(words)| | is the size of a heap chunk (struct hblk)
+ v | | of at least MININCR*HBLKSIZE bytes (below),
+ --- +----------------------+ otherwise, size of each object in chunk.
+
+Dynamic data structures above are interleaved throughout the heap in blocks of
+size MININCR * HBLKSIZE bytes as done by gc_scratch_alloc which cannot be
+freed; free lists are used (e.g. alloc_hdr). HBLK's below are collected.
+
+ (struct hblk)
+ --- +----------------------+ < HBLKSIZE --- --- DISCARD_
+ ^ |garbage[DISCARD_WORDS]| aligned ^ ^ HDR_BYTES WORDS
+ | | | | v (bytes) (words)
+ | +-----hb_body----------+ < WORDSZ | --- ---
+ | | | aligned | ^ ^
+ | | Object 0 | | hb_sz |
+ | | | i |(word- (words)|
+ | | | (bytes)|aligned) v |
+ | + - - - - - - - - - - -+ --- | --- |
+ | | | ^ | ^ |
+ n * | | j (words) | hb_sz BODY_SZ
+ HBLKSIZE | Object 1 | v v | (words)
+ (bytes) | |--------------- v MAX_OFFSET
+ | + - - - - - - - - - - -+ --- (bytes)
+ | | | !All_INTERIOR_PTRS ^ |
+ | | | sets j only for hb_sz |
+ | | Object N | valid object offsets. | |
+ v | | All objects WORDSZ v v
+ --- +----------------------+ aligned. --- ---
+
+DISCARD_WORDS is normally zero. Indeed the collector has not been tested
+with another value in ages.
+</pre>
+</body>
diff --git a/tools/build/v2/engine/boehm_gc/dyn_load.c b/tools/build/v2/engine/boehm_gc/dyn_load.c
new file mode 100644
index 0000000000..36968ba5d7
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/dyn_load.c
@@ -0,0 +1,1190 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1997 by Silicon Graphics. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ * Original author: Bill Janssen
+ * Heavily modified by Hans Boehm and others
+ */
+
+/*
+ * This is incredibly OS specific code for tracking down data sections in
+ * dynamic libraries. There appears to be no way of doing this quickly
+ * without groveling through undocumented data structures. We would argue
+ * that this is a bug in the design of the dlopen interface. THIS CODE
+ * MAY BREAK IN FUTURE OS RELEASES. If this matters to you, don't hesitate
+ * to let your vendor know ...
+ *
+ * None of this is safe with dlclose and incremental collection.
+ * But then not much of anything is safe in the presence of dlclose.
+ */
+#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__)) \
+ && !defined(_GNU_SOURCE)
+ /* Can't test LINUX, since this must be defined before other includes */
+# define _GNU_SOURCE
+#endif
+#if !defined(MACOS) && !defined(_WIN32_WCE)
+# include <sys/types.h>
+#endif
+#include "private/gc_priv.h"
+
+/* BTL: avoid circular redefinition of dlopen if GC_SOLARIS_THREADS defined */
+# if (defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS)) \
+ && defined(dlopen) && !defined(GC_USE_LD_WRAP)
+ /* To support threads in Solaris, gc.h interposes on dlopen by */
+ /* defining "dlopen" to be "GC_dlopen", which is implemented below. */
+ /* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the */
+ /* real system dlopen() in their implementation. We first remove */
+ /* gc.h's dlopen definition and restore it later, after GC_dlopen(). */
+# undef dlopen
+# define GC_must_restore_redefined_dlopen
+# else
+# undef GC_must_restore_redefined_dlopen
+# endif
+
+/* A user-supplied routine that is called to determine if a DSO must
+ be scanned by the gc. */
+static int (*GC_has_static_roots)(const char *, void *, size_t);
+
+
+#if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE)) \
+ && !defined(PCR)
+#if !defined(SOLARISDL) && !defined(IRIX5) && \
+ !defined(MSWIN32) && !defined(MSWINCE) && \
+ !(defined(ALPHA) && defined(OSF1)) && \
+ !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \
+ !defined(AIX) && !defined(SCO_ELF) && !defined(DGUX) && \
+ !(defined(FREEBSD) && defined(__ELF__)) && \
+ !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \
+ !defined(DARWIN) && !defined(CYGWIN32)
+ --> We only know how to find data segments of dynamic libraries for the
+ --> above. Additional SVR4 variants might not be too
+ --> hard to add.
+#endif
+
+#include <stdio.h>
+#ifdef SOLARISDL
+# include <sys/elf.h>
+# include <dlfcn.h>
+# include <link.h>
+#endif
+
+#if defined(NETBSD)
+# include <machine/elf_machdep.h>
+# define ELFSIZE ARCH_ELFSIZE
+#endif
+
+#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
+ (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
+ (defined(NETBSD) && defined(__ELF__)) || defined(HURD)
+# include <stddef.h>
+# include <elf.h>
+# include <link.h>
+#endif
+
+/* Newer versions of GNU/Linux define this macro. We
+ * define it similarly for any ELF systems that don't. */
+# ifndef ElfW
+# if defined(FREEBSD)
+# if __ELF_WORD_SIZE == 32
+# define ElfW(type) Elf32_##type
+# else
+# define ElfW(type) Elf64_##type
+# endif
+# elif defined(NETBSD)
+# if ELFSIZE == 32
+# define ElfW(type) Elf32_##type
+# else
+# define ElfW(type) Elf64_##type
+# endif
+# else
+# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
+# define ElfW(type) Elf32_##type
+# else
+# define ElfW(type) Elf64_##type
+# endif
+# endif
+# endif
+
+#if defined(SOLARISDL) && !defined(USE_PROC_FOR_LIBRARIES)
+
+#ifdef LINT
+ Elf32_Dyn _DYNAMIC;
+#endif
+
+static struct link_map *
+GC_FirstDLOpenedLinkMap()
+{
+ extern ElfW(Dyn) _DYNAMIC;
+ ElfW(Dyn) *dp;
+ struct r_debug *r;
+ static struct link_map * cachedResult = 0;
+ static ElfW(Dyn) *dynStructureAddr = 0;
+ /* BTL: added to avoid Solaris 5.3 ld.so _DYNAMIC bug */
+
+# ifdef SUNOS53_SHARED_LIB
+ /* BTL: Avoid the Solaris 5.3 bug that _DYNAMIC isn't being set */
+ /* up properly in dynamically linked .so's. This means we have */
+ /* to use its value in the set of original object files loaded */
+ /* at program startup. */
+ if( dynStructureAddr == 0 ) {
+ void* startupSyms = dlopen(0, RTLD_LAZY);
+ dynStructureAddr = (ElfW(Dyn)*)dlsym(startupSyms, "_DYNAMIC");
+ }
+# else
+ dynStructureAddr = &_DYNAMIC;
+# endif
+
+ if( dynStructureAddr == 0) {
+ return(0);
+ }
+ if( cachedResult == 0 ) {
+ int tag;
+ for( dp = ((ElfW(Dyn) *)(&_DYNAMIC)); (tag = dp->d_tag) != 0; dp++ ) {
+ if( tag == DT_DEBUG ) {
+ struct link_map *lm
+ = ((struct r_debug *)(dp->d_un.d_ptr))->r_map;
+ if( lm != 0 ) cachedResult = lm->l_next; /* might be NIL */
+ break;
+ }
+ }
+ }
+ return cachedResult;
+}
+
+#endif /* SOLARISDL ... */
+
+/* BTL: added to fix circular dlopen definition if GC_SOLARIS_THREADS defined */
+# if defined(GC_must_restore_redefined_dlopen)
+# define dlopen GC_dlopen
+# endif
+
+# if defined(SOLARISDL)
+/* Add dynamic library data sections to the root set. */
+# if !defined(PCR) && !defined(GC_SOLARIS_THREADS) && defined(THREADS)
+ --> fix mutual exclusion with dlopen
+# endif
+
+# ifndef USE_PROC_FOR_LIBRARIES
+void GC_register_dynamic_libraries()
+{
+ struct link_map *lm = GC_FirstDLOpenedLinkMap();
+
+
+ for (lm = GC_FirstDLOpenedLinkMap();
+ lm != (struct link_map *) 0; lm = lm->l_next)
+ {
+ ElfW(Ehdr) * e;
+ ElfW(Phdr) * p;
+ unsigned long offset;
+ char * start;
+ register int i;
+
+ e = (ElfW(Ehdr) *) lm->l_addr;
+ p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff));
+ offset = ((unsigned long)(lm->l_addr));
+ for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) {
+ switch( p->p_type ) {
+ case PT_LOAD:
+ {
+ if( !(p->p_flags & PF_W) ) break;
+ start = ((char *)(p->p_vaddr)) + offset;
+ GC_add_roots_inner(
+ start,
+ start + p->p_memsz,
+ TRUE
+ );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+# endif /* !USE_PROC ... */
+# endif /* SOLARISDL */
+
+#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
+ (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
+ (defined(NETBSD) && defined(__ELF__)) || defined(HURD)
+
+
+#ifdef USE_PROC_FOR_LIBRARIES
+
+#include <string.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define MAPS_BUF_SIZE (32*1024)
+
+extern ssize_t GC_repeat_read(int fd, char *buf, size_t count);
+ /* Repeatedly read until buffer is filled, or EOF is encountered */
+ /* Defined in os_dep.c. */
+
+char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end,
+ char **prot, unsigned int *maj_dev,
+ char **mapping_name);
+char *GC_get_maps(void);
+ /* From os_dep.c */
+
+word GC_register_map_entries(char *maps)
+{
+ char *prot;
+ char *buf_ptr = maps;
+ int count;
+ ptr_t start, end;
+ unsigned int maj_dev;
+ ptr_t least_ha, greatest_ha;
+ unsigned i;
+ ptr_t datastart = (ptr_t)(DATASTART);
+
+ /* Compute heap bounds. FIXME: Should work if heap and roots are */
+ /* interleaved? */
+ least_ha = (ptr_t)(word)(-1);
+ greatest_ha = 0;
+ for (i = 0; i < GC_n_heap_sects; ++i) {
+ ptr_t sect_start = GC_heap_sects[i].hs_start;
+ ptr_t sect_end = sect_start + GC_heap_sects[i].hs_bytes;
+ if (sect_start < least_ha) least_ha = sect_start;
+ if (sect_end > greatest_ha) greatest_ha = sect_end;
+ }
+ if (greatest_ha < (ptr_t)GC_scratch_last_end_ptr)
+ greatest_ha = (ptr_t)GC_scratch_last_end_ptr;
+
+ for (;;) {
+ buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, &prot, &maj_dev, 0);
+ if (buf_ptr == NULL) return 1;
+ if (prot[1] == 'w') {
+ /* This is a writable mapping. Add it to */
+ /* the root set unless it is already otherwise */
+ /* accounted for. */
+ if (start <= GC_stackbottom && end >= GC_stackbottom) {
+ /* Stack mapping; discard */
+ continue;
+ }
+# ifdef THREADS
+ /* This may fail, since a thread may already be */
+ /* unregistered, but its thread stack may still be there. */
+ /* That can fail because the stack may disappear while */
+ /* we're marking. Thus the marker is, and has to be */
+ /* prepared to recover from segmentation faults. */
+ if (GC_segment_is_thread_stack(start, end)) continue;
+ /* FIXME: REDIRECT_MALLOC actually works with threads on */
+ /* LINUX/IA64 if we omit this check. The problem is that */
+ /* thread stacks contain pointers to dynamic thread */
+ /* vectors, which may be reused due to thread caching. */
+ /* Currently they may not be marked if the thread is */
+ /* still live. */
+ /* For dead threads, we trace the whole stack, which is */
+ /* very suboptimal for performance reasons. */
+# endif
+ /* We no longer exclude the main data segment. */
+ if (start < least_ha && end > least_ha) {
+ end = least_ha;
+ }
+ if (start < greatest_ha && end > greatest_ha) {
+ start = greatest_ha;
+ }
+ if (start >= least_ha && end <= greatest_ha) continue;
+ GC_add_roots_inner((char *)start, (char *)end, TRUE);
+ }
+ }
+ return 1;
+}
+
+void GC_register_dynamic_libraries()
+{
+ if (!GC_register_map_entries(GC_get_maps()))
+ ABORT("Failed to read /proc for library registration.");
+}
+
+/* We now take care of the main data segment ourselves: */
+GC_bool GC_register_main_static_data()
+{
+ return FALSE;
+}
+
+# define HAVE_REGISTER_MAIN_STATIC_DATA
+
+#endif /* USE_PROC_FOR_LIBRARIES */
+
+#if !defined(USE_PROC_FOR_LIBRARIES)
+/* The following is the preferred way to walk dynamic libraries */
+/* For glibc 2.2.4+. Unfortunately, it doesn't work for older */
+/* versions. Thanks to Jakub Jelinek for most of the code. */
+
+# if (defined(LINUX) || defined (__GLIBC__)) /* Are others OK here, too? */ \
+ && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
+ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
+
+/* We have the header files for a glibc that includes dl_iterate_phdr. */
+/* It may still not be available in the library on the target system. */
+/* Thus we also treat it as a weak symbol. */
+#define HAVE_DL_ITERATE_PHDR
+
+static int GC_register_dynlib_callback(info, size, ptr)
+ struct dl_phdr_info * info;
+ size_t size;
+ void * ptr;
+{
+ const ElfW(Phdr) * p;
+ char * start;
+ register int i;
+
+ /* Make sure struct dl_phdr_info is at least as big as we need. */
+ if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
+ + sizeof (info->dlpi_phnum))
+ return -1;
+
+ p = info->dlpi_phdr;
+ for( i = 0; i < (int)(info->dlpi_phnum); ((i++),(p++)) ) {
+ switch( p->p_type ) {
+ case PT_LOAD:
+ {
+ if( !(p->p_flags & PF_W) ) break;
+ start = ((char *)(p->p_vaddr)) + info->dlpi_addr;
+
+ if (GC_has_static_roots
+ && !GC_has_static_roots(info->dlpi_name, start, p->p_memsz))
+ break;
+
+ GC_add_roots_inner(start, start + p->p_memsz, TRUE);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ * (int *)ptr = 1; /* Signal that we were called */
+ return 0;
+}
+
+/* Return TRUE if we succeed, FALSE if dl_iterate_phdr wasn't there. */
+
+#pragma weak dl_iterate_phdr
+
+GC_bool GC_register_dynamic_libraries_dl_iterate_phdr()
+{
+ if (dl_iterate_phdr) {
+ int did_something = 0;
+ dl_iterate_phdr(GC_register_dynlib_callback, &did_something);
+ if (!did_something) {
+ /* dl_iterate_phdr may forget the static data segment in */
+ /* statically linked executables. */
+ GC_add_roots_inner(DATASTART, (char *)(DATAEND), TRUE);
+# if defined(DATASTART2)
+ GC_add_roots_inner(DATASTART2, (char *)(DATAEND2), TRUE);
+# endif
+ }
+
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/* Do we need to separately register the main static data segment? */
+GC_bool GC_register_main_static_data()
+{
+ return (dl_iterate_phdr == 0);
+}
+
+#define HAVE_REGISTER_MAIN_STATIC_DATA
+
+# else /* !LINUX || version(glibc) < 2.2.4 */
+
+/* Dynamic loading code for Linux running ELF. Somewhat tested on
+ * Linux/x86, untested but hopefully should work on Linux/Alpha.
+ * This code was derived from the Solaris/ELF support. Thanks to
+ * whatever kind soul wrote that. - Patrick Bridges */
+
+/* This doesn't necessarily work in all cases, e.g. with preloaded
+ * dynamic libraries. */
+
+#if defined(NETBSD)
+# include <sys/exec_elf.h>
+/* for compatibility with 1.4.x */
+# ifndef DT_DEBUG
+# define DT_DEBUG 21
+# endif
+# ifndef PT_LOAD
+# define PT_LOAD 1
+# endif
+# ifndef PF_W
+# define PF_W 2
+# endif
+#else
+# include <elf.h>
+#endif
+#include <link.h>
+
+# endif
+
+#ifdef __GNUC__
+# pragma weak _DYNAMIC
+#endif
+extern ElfW(Dyn) _DYNAMIC[];
+
+static struct link_map *
+GC_FirstDLOpenedLinkMap()
+{
+ ElfW(Dyn) *dp;
+ static struct link_map *cachedResult = 0;
+
+ if( _DYNAMIC == 0) {
+ return(0);
+ }
+ if( cachedResult == 0 ) {
+ int tag;
+ for( dp = _DYNAMIC; (tag = dp->d_tag) != 0; dp++ ) {
+ if( tag == DT_DEBUG ) {
+ struct link_map *lm
+ = ((struct r_debug *)(dp->d_un.d_ptr))->r_map;
+ if( lm != 0 ) cachedResult = lm->l_next; /* might be NIL */
+ break;
+ }
+ }
+ }
+ return cachedResult;
+}
+
+
+void GC_register_dynamic_libraries()
+{
+ struct link_map *lm;
+
+
+# ifdef HAVE_DL_ITERATE_PHDR
+ if (GC_register_dynamic_libraries_dl_iterate_phdr()) {
+ return;
+ }
+# endif
+ lm = GC_FirstDLOpenedLinkMap();
+ for (lm = GC_FirstDLOpenedLinkMap();
+ lm != (struct link_map *) 0; lm = lm->l_next)
+ {
+ ElfW(Ehdr) * e;
+ ElfW(Phdr) * p;
+ unsigned long offset;
+ char * start;
+ register int i;
+
+ e = (ElfW(Ehdr) *) lm->l_addr;
+ p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff));
+ offset = ((unsigned long)(lm->l_addr));
+ for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) {
+ switch( p->p_type ) {
+ case PT_LOAD:
+ {
+ if( !(p->p_flags & PF_W) ) break;
+ start = ((char *)(p->p_vaddr)) + offset;
+ GC_add_roots_inner(start, start + p->p_memsz, TRUE);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+#endif /* !USE_PROC_FOR_LIBRARIES */
+
+#endif /* LINUX */
+
+#if defined(IRIX5) || (defined(USE_PROC_FOR_LIBRARIES) && !defined(LINUX))
+
+#include <sys/procfs.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <elf.h>
+#include <errno.h>
+#include <signal.h> /* Only for the following test. */
+#ifndef _sigargs
+# define IRIX6
+#endif
+
+extern void * GC_roots_present();
+ /* The type is a lie, since the real type doesn't make sense here, */
+ /* and we only test for NULL. */
+
+
+/* We use /proc to track down all parts of the address space that are */
+/* mapped by the process, and throw out regions we know we shouldn't */
+/* worry about. This may also work under other SVR4 variants. */
+void GC_register_dynamic_libraries()
+{
+ static int fd = -1;
+ char buf[30];
+ static prmap_t * addr_map = 0;
+ static int current_sz = 0; /* Number of records currently in addr_map */
+ static int needed_sz; /* Required size of addr_map */
+ int i;
+ long flags;
+ ptr_t start;
+ ptr_t limit;
+ ptr_t heap_start = (ptr_t)HEAP_START;
+ ptr_t heap_end = heap_start;
+
+# ifdef SOLARISDL
+# define MA_PHYS 0
+# endif /* SOLARISDL */
+
+ if (fd < 0) {
+ sprintf(buf, "/proc/%d", getpid());
+ /* The above generates a lint complaint, since pid_t varies. */
+ /* It's unclear how to improve this. */
+ fd = open(buf, O_RDONLY);
+ if (fd < 0) {
+ ABORT("/proc open failed");
+ }
+ }
+ if (ioctl(fd, PIOCNMAP, &needed_sz) < 0) {
+ GC_err_printf("fd = %d, errno = %d\n", fd, errno);
+ ABORT("/proc PIOCNMAP ioctl failed");
+ }
+ if (needed_sz >= current_sz) {
+ current_sz = needed_sz * 2 + 1;
+ /* Expansion, plus room for 0 record */
+ addr_map = (prmap_t *)GC_scratch_alloc((word)
+ (current_sz * sizeof(prmap_t)));
+ }
+ if (ioctl(fd, PIOCMAP, addr_map) < 0) {
+ GC_err_printf("fd = %d, errno = %d, needed_sz = %d, addr_map = 0x%X\n",
+ fd, errno, needed_sz, addr_map);
+ ABORT("/proc PIOCMAP ioctl failed");
+ };
+ if (GC_n_heap_sects > 0) {
+ heap_end = GC_heap_sects[GC_n_heap_sects-1].hs_start
+ + GC_heap_sects[GC_n_heap_sects-1].hs_bytes;
+ if (heap_end < GC_scratch_last_end_ptr) heap_end = GC_scratch_last_end_ptr;
+ }
+ for (i = 0; i < needed_sz; i++) {
+ flags = addr_map[i].pr_mflags;
+ if ((flags & (MA_BREAK | MA_STACK | MA_PHYS
+ | MA_FETCHOP | MA_NOTCACHED)) != 0) goto irrelevant;
+ if ((flags & (MA_READ | MA_WRITE)) != (MA_READ | MA_WRITE))
+ goto irrelevant;
+ /* The latter test is empirically useless in very old Irix */
+ /* versions. Other than the */
+ /* main data and stack segments, everything appears to be */
+ /* mapped readable, writable, executable, and shared(!!). */
+ /* This makes no sense to me. - HB */
+ start = (ptr_t)(addr_map[i].pr_vaddr);
+ if (GC_roots_present(start)) goto irrelevant;
+ if (start < heap_end && start >= heap_start)
+ goto irrelevant;
+# ifdef MMAP_STACKS
+ if (GC_is_thread_stack(start)) goto irrelevant;
+# endif /* MMAP_STACKS */
+
+ limit = start + addr_map[i].pr_size;
+ /* The following seemed to be necessary for very old versions */
+ /* of Irix, but it has been reported to discard relevant */
+ /* segments under Irix 6.5. */
+# ifndef IRIX6
+ if (addr_map[i].pr_off == 0 && strncmp(start, ELFMAG, 4) == 0) {
+ /* Discard text segments, i.e. 0-offset mappings against */
+ /* executable files which appear to have ELF headers. */
+ caddr_t arg;
+ int obj;
+# define MAP_IRR_SZ 10
+ static ptr_t map_irr[MAP_IRR_SZ];
+ /* Known irrelevant map entries */
+ static int n_irr = 0;
+ struct stat buf;
+ register int i;
+
+ for (i = 0; i < n_irr; i++) {
+ if (map_irr[i] == start) goto irrelevant;
+ }
+ arg = (caddr_t)start;
+ obj = ioctl(fd, PIOCOPENM, &arg);
+ if (obj >= 0) {
+ fstat(obj, &buf);
+ close(obj);
+ if ((buf.st_mode & 0111) != 0) {
+ if (n_irr < MAP_IRR_SZ) {
+ map_irr[n_irr++] = start;
+ }
+ goto irrelevant;
+ }
+ }
+ }
+# endif /* !IRIX6 */
+ GC_add_roots_inner(start, limit, TRUE);
+ irrelevant: ;
+ }
+ /* Dont keep cached descriptor, for now. Some kernels don't like us */
+ /* to keep a /proc file descriptor around during kill -9. */
+ if (close(fd) < 0) ABORT("Couldnt close /proc file");
+ fd = -1;
+}
+
+# endif /* USE_PROC || IRIX5 */
+
+# if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
+
+# define WIN32_LEAN_AND_MEAN
+# define NOSERVICE
+# include <windows.h>
+# include <stdlib.h>
+
+ /* We traverse the entire address space and register all segments */
+ /* that could possibly have been written to. */
+
+ extern GC_bool GC_is_heap_base (ptr_t p);
+
+# ifdef GC_WIN32_THREADS
+ extern void GC_get_next_stack(char *start, char **lo, char **hi);
+ void GC_cond_add_roots(char *base, char * limit)
+ {
+ char * curr_base = base;
+ char * next_stack_lo;
+ char * next_stack_hi;
+
+ if (base == limit) return;
+ for(;;) {
+ GC_get_next_stack(curr_base, &next_stack_lo, &next_stack_hi);
+ if (next_stack_lo >= limit) break;
+ GC_add_roots_inner(curr_base, next_stack_lo, TRUE);
+ curr_base = next_stack_hi;
+ }
+ if (curr_base < limit) GC_add_roots_inner(curr_base, limit, TRUE);
+ }
+# else
+ void GC_cond_add_roots(char *base, char * limit)
+ {
+ char dummy;
+ char * stack_top
+ = (char *) ((word)(&dummy) & ~(GC_sysinfo.dwAllocationGranularity-1));
+ if (base == limit) return;
+ if (limit > stack_top && base < GC_stackbottom) {
+ /* Part of the stack; ignore it. */
+ return;
+ }
+ GC_add_roots_inner(base, limit, TRUE);
+ }
+# endif
+
+# ifdef MSWINCE
+ /* Do we need to separately register the main static data segment? */
+ GC_bool GC_register_main_static_data()
+ {
+ return FALSE;
+ }
+# else /* win32 */
+ extern GC_bool GC_no_win32_dlls;
+
+ GC_bool GC_register_main_static_data()
+ {
+ return GC_no_win32_dlls;
+ }
+# endif /* win32 */
+
+# define HAVE_REGISTER_MAIN_STATIC_DATA
+
+# ifdef DEBUG_VIRTUALQUERY
+ void GC_dump_meminfo(MEMORY_BASIC_INFORMATION *buf)
+ {
+ GC_printf("BaseAddress = %lx, AllocationBase = %lx, RegionSize = %lx(%lu)\n",
+ buf -> BaseAddress, buf -> AllocationBase, buf -> RegionSize,
+ buf -> RegionSize);
+ GC_printf("\tAllocationProtect = %lx, State = %lx, Protect = %lx, "
+ "Type = %lx\n",
+ buf -> AllocationProtect, buf -> State, buf -> Protect,
+ buf -> Type);
+ }
+# endif /* DEBUG_VIRTUALQUERY */
+
+ extern GC_bool GC_wnt; /* Is Windows NT derivative. */
+ /* Defined and set in os_dep.c. */
+
+ void GC_register_dynamic_libraries()
+ {
+ MEMORY_BASIC_INFORMATION buf;
+ size_t result;
+ DWORD protect;
+ LPVOID p;
+ char * base;
+ char * limit, * new_limit;
+
+# ifdef MSWIN32
+ if (GC_no_win32_dlls) return;
+# endif
+ base = limit = p = GC_sysinfo.lpMinimumApplicationAddress;
+# if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)
+ /* Only the first 32 MB of address space belongs to the current process */
+ while (p < (LPVOID)0x02000000) {
+ result = VirtualQuery(p, &buf, sizeof(buf));
+ if (result == 0) {
+ /* Page is free; advance to the next possible allocation base */
+ new_limit = (char *)
+ (((DWORD) p + GC_sysinfo.dwAllocationGranularity)
+ & ~(GC_sysinfo.dwAllocationGranularity-1));
+ } else
+# else
+ while (p < GC_sysinfo.lpMaximumApplicationAddress) {
+ result = VirtualQuery(p, &buf, sizeof(buf));
+# endif
+ {
+ if (result != sizeof(buf)) {
+ ABORT("Weird VirtualQuery result");
+ }
+ new_limit = (char *)p + buf.RegionSize;
+ protect = buf.Protect;
+ if (buf.State == MEM_COMMIT
+ && (protect == PAGE_EXECUTE_READWRITE
+ || protect == PAGE_READWRITE)
+ && !GC_is_heap_base(buf.AllocationBase)
+ /* There is some evidence that we cannot always
+ * ignore MEM_PRIVATE sections under Windows ME
+ * and predecessors. Hence we now also check for
+ * that case. */
+ && (buf.Type == MEM_IMAGE ||
+ !GC_wnt && buf.Type == MEM_PRIVATE)) {
+# ifdef DEBUG_VIRTUALQUERY
+ GC_dump_meminfo(&buf);
+# endif
+ if ((char *)p != limit) {
+ GC_cond_add_roots(base, limit);
+ base = p;
+ }
+ limit = new_limit;
+ }
+ }
+ if (p > (LPVOID)new_limit /* overflow */) break;
+ p = (LPVOID)new_limit;
+ }
+ GC_cond_add_roots(base, limit);
+ }
+
+#endif /* MSWIN32 || MSWINCE || CYGWIN32 */
+
+#if defined(ALPHA) && defined(OSF1)
+
+#include <loader.h>
+
+void GC_register_dynamic_libraries()
+{
+ int status;
+ ldr_process_t mypid;
+
+ /* module */
+ ldr_module_t moduleid = LDR_NULL_MODULE;
+ ldr_module_info_t moduleinfo;
+ size_t moduleinfosize = sizeof(moduleinfo);
+ size_t modulereturnsize;
+
+ /* region */
+ ldr_region_t region;
+ ldr_region_info_t regioninfo;
+ size_t regioninfosize = sizeof(regioninfo);
+ size_t regionreturnsize;
+
+ /* Obtain id of this process */
+ mypid = ldr_my_process();
+
+ /* For each module */
+ while (TRUE) {
+
+ /* Get the next (first) module */
+ status = ldr_next_module(mypid, &moduleid);
+
+ /* Any more modules? */
+ if (moduleid == LDR_NULL_MODULE)
+ break; /* No more modules */
+
+ /* Check status AFTER checking moduleid because */
+ /* of a bug in the non-shared ldr_next_module stub */
+ if (status != 0 ) {
+ GC_printf("dynamic_load: status = %d\n", status);
+ {
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+ extern int errno;
+ if (errno <= sys_nerr) {
+ GC_printf("dynamic_load: %s\n", sys_errlist[errno]);
+ } else {
+ GC_printf("dynamic_load: %d\n", errno);
+ }
+ }
+ ABORT("ldr_next_module failed");
+ }
+
+ /* Get the module information */
+ status = ldr_inq_module(mypid, moduleid, &moduleinfo,
+ moduleinfosize, &modulereturnsize);
+ if (status != 0 )
+ ABORT("ldr_inq_module failed");
+
+ /* is module for the main program (i.e. nonshared portion)? */
+ if (moduleinfo.lmi_flags & LDR_MAIN)
+ continue; /* skip the main module */
+
+# ifdef DL_VERBOSE
+ GC_printf("---Module---\n");
+ GC_printf("Module ID = %16ld\n", moduleinfo.lmi_modid);
+ GC_printf("Count of regions = %16d\n", moduleinfo.lmi_nregion);
+ GC_printf("flags for module = %16lx\n", moduleinfo.lmi_flags);
+ GC_printf("pathname of module = \"%s\"\n", moduleinfo.lmi_name);
+# endif
+
+ /* For each region in this module */
+ for (region = 0; region < moduleinfo.lmi_nregion; region++) {
+
+ /* Get the region information */
+ status = ldr_inq_region(mypid, moduleid, region, &regioninfo,
+ regioninfosize, &regionreturnsize);
+ if (status != 0 )
+ ABORT("ldr_inq_region failed");
+
+ /* only process writable (data) regions */
+ if (! (regioninfo.lri_prot & LDR_W))
+ continue;
+
+# ifdef DL_VERBOSE
+ GC_printf("--- Region ---\n");
+ GC_printf("Region number = %16ld\n",
+ regioninfo.lri_region_no);
+ GC_printf("Protection flags = %016x\n", regioninfo.lri_prot);
+ GC_printf("Virtual address = %16p\n", regioninfo.lri_vaddr);
+ GC_printf("Mapped address = %16p\n", regioninfo.lri_mapaddr);
+ GC_printf("Region size = %16ld\n", regioninfo.lri_size);
+ GC_printf("Region name = \"%s\"\n", regioninfo.lri_name);
+# endif
+
+ /* register region as a garbage collection root */
+ GC_add_roots_inner (
+ (char *)regioninfo.lri_mapaddr,
+ (char *)regioninfo.lri_mapaddr + regioninfo.lri_size,
+ TRUE);
+
+ }
+ }
+}
+#endif
+
+#if defined(HPUX)
+
+#include <errno.h>
+#include <dl.h>
+
+extern char *sys_errlist[];
+extern int sys_nerr;
+
+void GC_register_dynamic_libraries()
+{
+ int status;
+ int index = 1; /* Ordinal position in shared library search list */
+ struct shl_descriptor *shl_desc; /* Shared library info, see dl.h */
+
+ /* For each dynamic library loaded */
+ while (TRUE) {
+
+ /* Get info about next shared library */
+ status = shl_get(index, &shl_desc);
+
+ /* Check if this is the end of the list or if some error occured */
+ if (status != 0) {
+# ifdef GC_HPUX_THREADS
+ /* I've seen errno values of 0. The man page is not clear */
+ /* as to whether errno should get set on a -1 return. */
+ break;
+# else
+ if (errno == EINVAL) {
+ break; /* Moved past end of shared library list --> finished */
+ } else {
+ if (errno <= sys_nerr) {
+ GC_printf("dynamic_load: %s\n", sys_errlist[errno]);
+ } else {
+ GC_printf("dynamic_load: %d\n", errno);
+ }
+ ABORT("shl_get failed");
+ }
+# endif
+ }
+
+# ifdef DL_VERBOSE
+ GC_printf("---Shared library---\n");
+ GC_printf("\tfilename = \"%s\"\n", shl_desc->filename);
+ GC_printf("\tindex = %d\n", index);
+ GC_printf("\thandle = %08x\n",
+ (unsigned long) shl_desc->handle);
+ GC_printf("\ttext seg. start = %08x\n", shl_desc->tstart);
+ GC_printf("\ttext seg. end = %08x\n", shl_desc->tend);
+ GC_printf("\tdata seg. start = %08x\n", shl_desc->dstart);
+ GC_printf("\tdata seg. end = %08x\n", shl_desc->dend);
+ GC_printf("\tref. count = %lu\n", shl_desc->ref_count);
+# endif
+
+ /* register shared library's data segment as a garbage collection root */
+ GC_add_roots_inner((char *) shl_desc->dstart,
+ (char *) shl_desc->dend, TRUE);
+
+ index++;
+ }
+}
+#endif /* HPUX */
+
+#ifdef AIX
+#pragma alloca
+#include <sys/ldr.h>
+#include <sys/errno.h>
+void GC_register_dynamic_libraries()
+{
+ int len;
+ char *ldibuf;
+ int ldibuflen;
+ struct ld_info *ldi;
+
+ ldibuf = alloca(ldibuflen = 8192);
+
+ while ( (len = loadquery(L_GETINFO,ldibuf,ldibuflen)) < 0) {
+ if (errno != ENOMEM) {
+ ABORT("loadquery failed");
+ }
+ ldibuf = alloca(ldibuflen *= 2);
+ }
+
+ ldi = (struct ld_info *)ldibuf;
+ while (ldi) {
+ len = ldi->ldinfo_next;
+ GC_add_roots_inner(
+ ldi->ldinfo_dataorg,
+ (ptr_t)(unsigned long)ldi->ldinfo_dataorg
+ + ldi->ldinfo_datasize,
+ TRUE);
+ ldi = len ? (struct ld_info *)((char *)ldi + len) : 0;
+ }
+}
+#endif /* AIX */
+
+#ifdef DARWIN
+
+/* __private_extern__ hack required for pre-3.4 gcc versions. */
+#ifndef __private_extern__
+# define __private_extern__ extern
+# include <mach-o/dyld.h>
+# undef __private_extern__
+#else
+# include <mach-o/dyld.h>
+#endif
+#include <mach-o/getsect.h>
+
+/*#define DARWIN_DEBUG*/
+
+const static struct {
+ const char *seg;
+ const char *sect;
+} GC_dyld_sections[] = {
+ { SEG_DATA, SECT_DATA },
+ { SEG_DATA, SECT_BSS },
+ { SEG_DATA, SECT_COMMON }
+};
+
+#ifdef DARWIN_DEBUG
+static const char *GC_dyld_name_for_hdr(const struct GC_MACH_HEADER *hdr) {
+ unsigned long i,c;
+ c = _dyld_image_count();
+ for(i=0;i<c;i++) if(_dyld_get_image_header(i) == hdr)
+ return _dyld_get_image_name(i);
+ return NULL;
+}
+#endif
+
+/* This should never be called by a thread holding the lock */
+static void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr, intptr_t slide)
+{
+ unsigned long start,end,i;
+ const struct GC_MACH_SECTION *sec;
+ if (GC_no_dls) return;
+ for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
+# if defined (__LP64__)
+ sec = getsectbynamefromheader_64(
+# else
+ sec = getsectbynamefromheader(
+# endif
+ hdr, GC_dyld_sections[i].seg,
+ GC_dyld_sections[i].sect);
+ if(sec == NULL || sec->size == 0) continue;
+ start = slide + sec->addr;
+ end = start + sec->size;
+# ifdef DARWIN_DEBUG
+ GC_printf("Adding section at %p-%p (%lu bytes) from image %s\n",
+ start,end,sec->size,GC_dyld_name_for_hdr(hdr));
+# endif
+ GC_add_roots((char*)start,(char*)end);
+ }
+# ifdef DARWIN_DEBUG
+ GC_print_static_roots();
+# endif
+}
+
+/* This should never be called by a thread holding the lock */
+static void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr,
+ intptr_t slide)
+{
+ unsigned long start,end,i;
+ const struct GC_MACH_SECTION *sec;
+ for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
+# if defined (__LP64__)
+ sec = getsectbynamefromheader_64(
+# else
+ sec = getsectbynamefromheader(
+# endif
+ hdr, GC_dyld_sections[i].seg,
+ GC_dyld_sections[i].sect);
+ if(sec == NULL || sec->size == 0) continue;
+ start = slide + sec->addr;
+ end = start + sec->size;
+# ifdef DARWIN_DEBUG
+ GC_printf("Removing section at %p-%p (%lu bytes) from image %s\n",
+ start,end,sec->size,GC_dyld_name_for_hdr(hdr));
+# endif
+ GC_remove_roots((char*)start,(char*)end);
+ }
+# ifdef DARWIN_DEBUG
+ GC_print_static_roots();
+# endif
+}
+
+void GC_register_dynamic_libraries() {
+ /* Currently does nothing. The callbacks are setup by GC_init_dyld()
+ The dyld library takes it from there. */
+}
+
+/* The _dyld_* functions have an internal lock so no _dyld functions
+ can be called while the world is stopped without the risk of a deadlock.
+ Because of this we MUST setup callbacks BEFORE we ever stop the world.
+ This should be called BEFORE any thread in created and WITHOUT the
+ allocation lock held. */
+
+void GC_init_dyld() {
+ static GC_bool initialized = FALSE;
+ char *bind_fully_env = NULL;
+
+ if(initialized) return;
+
+# ifdef DARWIN_DEBUG
+ GC_printf("Registering dyld callbacks...\n");
+# endif
+
+ /* Apple's Documentation:
+ When you call _dyld_register_func_for_add_image, the dynamic linker runtime
+ calls the specified callback (func) once for each of the images that is
+ currently loaded into the program. When a new image is added to the program,
+ your callback is called again with the mach_header for the new image, and the
+ virtual memory slide amount of the new image.
+
+ This WILL properly register already linked libraries and libraries
+ linked in the future
+ */
+
+ _dyld_register_func_for_add_image(GC_dyld_image_add);
+ _dyld_register_func_for_remove_image(GC_dyld_image_remove);
+
+ /* Set this early to avoid reentrancy issues. */
+ initialized = TRUE;
+
+ bind_fully_env = getenv("DYLD_BIND_AT_LAUNCH");
+
+ if (bind_fully_env == NULL) {
+# ifdef DARWIN_DEBUG
+ GC_printf("Forcing full bind of GC code...\n");
+# endif
+
+ if(!_dyld_bind_fully_image_containing_address((unsigned long*)GC_malloc))
+ GC_abort("_dyld_bind_fully_image_containing_address failed");
+ }
+
+}
+
+#define HAVE_REGISTER_MAIN_STATIC_DATA
+GC_bool GC_register_main_static_data()
+{
+ /* Already done through dyld callbacks */
+ return FALSE;
+}
+
+#endif /* DARWIN */
+
+#else /* !DYNAMIC_LOADING */
+
+#ifdef PCR
+
+# include "il/PCR_IL.h"
+# include "th/PCR_ThCtl.h"
+# include "mm/PCR_MM.h"
+
+void GC_register_dynamic_libraries()
+{
+ /* Add new static data areas of dynamically loaded modules. */
+ {
+ PCR_IL_LoadedFile * p = PCR_IL_GetLastLoadedFile();
+ PCR_IL_LoadedSegment * q;
+
+ /* Skip uncommited files */
+ while (p != NIL && !(p -> lf_commitPoint)) {
+ /* The loading of this file has not yet been committed */
+ /* Hence its description could be inconsistent. */
+ /* Furthermore, it hasn't yet been run. Hence its data */
+ /* segments can't possibly reference heap allocated */
+ /* objects. */
+ p = p -> lf_prev;
+ }
+ for (; p != NIL; p = p -> lf_prev) {
+ for (q = p -> lf_ls; q != NIL; q = q -> ls_next) {
+ if ((q -> ls_flags & PCR_IL_SegFlags_Traced_MASK)
+ == PCR_IL_SegFlags_Traced_on) {
+ GC_add_roots_inner
+ ((char *)(q -> ls_addr),
+ (char *)(q -> ls_addr) + q -> ls_bytes,
+ TRUE);
+ }
+ }
+ }
+ }
+}
+
+
+#else /* !PCR */
+
+void GC_register_dynamic_libraries(){}
+
+int GC_no_dynamic_loading;
+
+#endif /* !PCR */
+
+#endif /* !DYNAMIC_LOADING */
+
+#ifndef HAVE_REGISTER_MAIN_STATIC_DATA
+
+/* Do we need to separately register the main static data segment? */
+GC_bool GC_register_main_static_data()
+{
+ return TRUE;
+}
+
+/* Register a routine to filter dynamic library registration. */
+void
+GC_register_has_static_roots_callback
+ (int (*callback)(const char *, void *, size_t)) {
+ GC_has_static_roots = callback;
+}
+
+#endif /* HAVE_REGISTER_MAIN_STATIC_DATA */
+
diff --git a/tools/build/v2/engine/boehm_gc/finalize.c b/tools/build/v2/engine/boehm_gc/finalize.c
new file mode 100644
index 0000000000..6ae36c2ddc
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/finalize.c
@@ -0,0 +1,869 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (C) 2007 Free Software Foundation, Inc
+
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, February 1, 1996 1:19 pm PST */
+# define I_HIDE_POINTERS
+# include "private/gc_pmark.h"
+
+# ifdef FINALIZE_ON_DEMAND
+ int GC_finalize_on_demand = 1;
+# else
+ int GC_finalize_on_demand = 0;
+# endif
+
+# ifdef JAVA_FINALIZATION
+ int GC_java_finalization = 1;
+# else
+ int GC_java_finalization = 0;
+# endif
+
+/* Type of mark procedure used for marking from finalizable object. */
+/* This procedure normally does not mark the object, only its */
+/* descendents. */
+typedef void finalization_mark_proc(/* ptr_t finalizable_obj_ptr */);
+
+# define HASH3(addr,size,log_size) \
+ ((((word)(addr) >> 3) ^ ((word)(addr) >> (3+(log_size)))) \
+ & ((size) - 1))
+#define HASH2(addr,log_size) HASH3(addr, 1 << log_size, log_size)
+
+struct hash_chain_entry {
+ word hidden_key;
+ struct hash_chain_entry * next;
+};
+
+unsigned GC_finalization_failures = 0;
+ /* Number of finalization requests that failed for lack of memory. */
+
+static struct disappearing_link {
+ struct hash_chain_entry prolog;
+# define dl_hidden_link prolog.hidden_key
+ /* Field to be cleared. */
+# define dl_next(x) (struct disappearing_link *)((x) -> prolog.next)
+# define dl_set_next(x,y) (x) -> prolog.next = (struct hash_chain_entry *)(y)
+
+ word dl_hidden_obj; /* Pointer to object base */
+} **dl_head = 0;
+
+static signed_word log_dl_table_size = -1;
+ /* Binary log of */
+ /* current size of array pointed to by dl_head. */
+ /* -1 ==> size is 0. */
+
+word GC_dl_entries = 0; /* Number of entries currently in disappearing */
+ /* link table. */
+
+static struct finalizable_object {
+ struct hash_chain_entry prolog;
+# define fo_hidden_base prolog.hidden_key
+ /* Pointer to object base. */
+ /* No longer hidden once object */
+ /* is on finalize_now queue. */
+# define fo_next(x) (struct finalizable_object *)((x) -> prolog.next)
+# define fo_set_next(x,y) (x) -> prolog.next = (struct hash_chain_entry *)(y)
+ GC_finalization_proc fo_fn; /* Finalizer. */
+ ptr_t fo_client_data;
+ word fo_object_size; /* In bytes. */
+ finalization_mark_proc * fo_mark_proc; /* Mark-through procedure */
+} **fo_head = 0;
+
+struct finalizable_object * GC_finalize_now = 0;
+ /* LIst of objects that should be finalized now. */
+
+static signed_word log_fo_table_size = -1;
+
+word GC_fo_entries = 0;
+
+void GC_push_finalizer_structures(void)
+{
+ GC_push_all((ptr_t)(&dl_head), (ptr_t)(&dl_head) + sizeof(word));
+ GC_push_all((ptr_t)(&fo_head), (ptr_t)(&fo_head) + sizeof(word));
+ GC_push_all((ptr_t)(&GC_finalize_now),
+ (ptr_t)(&GC_finalize_now) + sizeof(word));
+}
+
+/* Double the size of a hash table. *size_ptr is the log of its current */
+/* size. May be a noop. */
+/* *table is a pointer to an array of hash headers. If we succeed, we */
+/* update both *table and *log_size_ptr. */
+/* Lock is held. Signals are disabled. */
+void GC_grow_table(struct hash_chain_entry ***table,
+ signed_word *log_size_ptr)
+{
+ register word i;
+ register struct hash_chain_entry *p;
+ signed_word log_old_size = *log_size_ptr;
+ signed_word log_new_size = log_old_size + 1;
+ word old_size = ((log_old_size == -1)? 0: (1 << log_old_size));
+ word new_size = (word)1 << log_new_size;
+ /* FIXME: Power of 2 size often gets rounded up to one more page. */
+ struct hash_chain_entry **new_table = (struct hash_chain_entry **)
+ GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE(
+ (size_t)new_size * sizeof(struct hash_chain_entry *), NORMAL);
+
+ if (new_table == 0) {
+ if (table == 0) {
+ ABORT("Insufficient space for initial table allocation");
+ } else {
+ return;
+ }
+ }
+ for (i = 0; i < old_size; i++) {
+ p = (*table)[i];
+ while (p != 0) {
+ ptr_t real_key = (ptr_t)REVEAL_POINTER(p -> hidden_key);
+ struct hash_chain_entry *next = p -> next;
+ size_t new_hash = HASH3(real_key, new_size, log_new_size);
+
+ p -> next = new_table[new_hash];
+ new_table[new_hash] = p;
+ p = next;
+ }
+ }
+ *log_size_ptr = log_new_size;
+ *table = new_table;
+}
+
+int GC_register_disappearing_link(void * * link)
+{
+ ptr_t base;
+
+ base = (ptr_t)GC_base((void *)link);
+ if (base == 0)
+ ABORT("Bad arg to GC_register_disappearing_link");
+ return(GC_general_register_disappearing_link(link, base));
+}
+
+int GC_general_register_disappearing_link(void * * link, void * obj)
+{
+ struct disappearing_link *curr_dl;
+ size_t index;
+ struct disappearing_link * new_dl;
+ DCL_LOCK_STATE;
+
+ if ((word)link & (ALIGNMENT-1))
+ ABORT("Bad arg to GC_general_register_disappearing_link");
+# ifdef THREADS
+ LOCK();
+# endif
+ if (log_dl_table_size == -1
+ || GC_dl_entries > ((word)1 << log_dl_table_size)) {
+ GC_grow_table((struct hash_chain_entry ***)(&dl_head),
+ &log_dl_table_size);
+ if (GC_print_stats) {
+ GC_log_printf("Grew dl table to %u entries\n",
+ (1 << log_dl_table_size));
+ }
+ }
+ index = HASH2(link, log_dl_table_size);
+ curr_dl = dl_head[index];
+ for (curr_dl = dl_head[index]; curr_dl != 0; curr_dl = dl_next(curr_dl)) {
+ if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) {
+ curr_dl -> dl_hidden_obj = HIDE_POINTER(obj);
+# ifdef THREADS
+ UNLOCK();
+# endif
+ return(1);
+ }
+ }
+ new_dl = (struct disappearing_link *)
+ GC_INTERNAL_MALLOC(sizeof(struct disappearing_link),NORMAL);
+ if (0 == new_dl) {
+# ifdef THREADS
+ UNLOCK();
+# endif
+ new_dl = (struct disappearing_link *)
+ GC_oom_fn(sizeof(struct disappearing_link));
+ if (0 == new_dl) {
+ GC_finalization_failures++;
+ return(0);
+ }
+ /* It's not likely we'll make it here, but ... */
+# ifdef THREADS
+ LOCK();
+# endif
+ }
+ new_dl -> dl_hidden_obj = HIDE_POINTER(obj);
+ new_dl -> dl_hidden_link = HIDE_POINTER(link);
+ dl_set_next(new_dl, dl_head[index]);
+ dl_head[index] = new_dl;
+ GC_dl_entries++;
+# ifdef THREADS
+ UNLOCK();
+# endif
+ return(0);
+}
+
+int GC_unregister_disappearing_link(void * * link)
+{
+ struct disappearing_link *curr_dl, *prev_dl;
+ size_t index;
+ DCL_LOCK_STATE;
+
+ LOCK();
+ index = HASH2(link, log_dl_table_size);
+ if (((word)link & (ALIGNMENT-1))) goto out;
+ prev_dl = 0; curr_dl = dl_head[index];
+ while (curr_dl != 0) {
+ if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) {
+ if (prev_dl == 0) {
+ dl_head[index] = dl_next(curr_dl);
+ } else {
+ dl_set_next(prev_dl, dl_next(curr_dl));
+ }
+ GC_dl_entries--;
+ UNLOCK();
+# ifdef DBG_HDRS_ALL
+ dl_set_next(curr_dl, 0);
+# else
+ GC_free((void *)curr_dl);
+# endif
+ return(1);
+ }
+ prev_dl = curr_dl;
+ curr_dl = dl_next(curr_dl);
+ }
+out:
+ UNLOCK();
+ return(0);
+}
+
+/* Possible finalization_marker procedures. Note that mark stack */
+/* overflow is handled by the caller, and is not a disaster. */
+GC_API void GC_normal_finalize_mark_proc(ptr_t p)
+{
+ hdr * hhdr = HDR(p);
+
+ PUSH_OBJ(p, hhdr, GC_mark_stack_top,
+ &(GC_mark_stack[GC_mark_stack_size]));
+}
+
+/* This only pays very partial attention to the mark descriptor. */
+/* It does the right thing for normal and atomic objects, and treats */
+/* most others as normal. */
+GC_API void GC_ignore_self_finalize_mark_proc(ptr_t p)
+{
+ hdr * hhdr = HDR(p);
+ word descr = hhdr -> hb_descr;
+ ptr_t q, r;
+ ptr_t scan_limit;
+ ptr_t target_limit = p + hhdr -> hb_sz - 1;
+
+ if ((descr & GC_DS_TAGS) == GC_DS_LENGTH) {
+ scan_limit = p + descr - sizeof(word);
+ } else {
+ scan_limit = target_limit + 1 - sizeof(word);
+ }
+ for (q = p; q <= scan_limit; q += ALIGNMENT) {
+ r = *(ptr_t *)q;
+ if (r < p || r > target_limit) {
+ GC_PUSH_ONE_HEAP(r, q);
+ }
+ }
+}
+
+/*ARGSUSED*/
+GC_API void GC_null_finalize_mark_proc(ptr_t p)
+{
+}
+
+/* Possible finalization_marker procedures. Note that mark stack */
+/* overflow is handled by the caller, and is not a disaster. */
+
+/* GC_unreachable_finalize_mark_proc is an alias for normal marking, */
+/* but it is explicitly tested for, and triggers different */
+/* behavior. Objects registered in this way are not finalized */
+/* if they are reachable by other finalizable objects, eve if those */
+/* other objects specify no ordering. */
+GC_API void GC_unreachable_finalize_mark_proc(ptr_t p)
+{
+ GC_normal_finalize_mark_proc(p);
+}
+
+
+
+/* Register a finalization function. See gc.h for details. */
+/* in the nonthreads case, we try to avoid disabling signals, */
+/* since it can be expensive. Threads packages typically */
+/* make it cheaper. */
+/* The last parameter is a procedure that determines */
+/* marking for finalization ordering. Any objects marked */
+/* by that procedure will be guaranteed to not have been */
+/* finalized when this finalizer is invoked. */
+GC_API void GC_register_finalizer_inner(void * obj,
+ GC_finalization_proc fn, void *cd,
+ GC_finalization_proc *ofn, void **ocd,
+ finalization_mark_proc mp)
+{
+ ptr_t base;
+ struct finalizable_object * curr_fo, * prev_fo;
+ size_t index;
+ struct finalizable_object *new_fo;
+ hdr *hhdr;
+ DCL_LOCK_STATE;
+
+# ifdef THREADS
+ LOCK();
+# endif
+ if (log_fo_table_size == -1
+ || GC_fo_entries > ((word)1 << log_fo_table_size)) {
+ GC_grow_table((struct hash_chain_entry ***)(&fo_head),
+ &log_fo_table_size);
+ if (GC_print_stats) {
+ GC_log_printf("Grew fo table to %u entries\n",
+ (1 << log_fo_table_size));
+ }
+ }
+ /* in the THREADS case signals are disabled and we hold allocation */
+ /* lock; otherwise neither is true. Proceed carefully. */
+ base = (ptr_t)obj;
+ index = HASH2(base, log_fo_table_size);
+ prev_fo = 0; curr_fo = fo_head[index];
+ while (curr_fo != 0) {
+ GC_ASSERT(GC_size(curr_fo) >= sizeof(struct finalizable_object));
+ if (curr_fo -> fo_hidden_base == HIDE_POINTER(base)) {
+ /* Interruption by a signal in the middle of this */
+ /* should be safe. The client may see only *ocd */
+ /* updated, but we'll declare that to be his */
+ /* problem. */
+ if (ocd) *ocd = (void *) (curr_fo -> fo_client_data);
+ if (ofn) *ofn = curr_fo -> fo_fn;
+ /* Delete the structure for base. */
+ if (prev_fo == 0) {
+ fo_head[index] = fo_next(curr_fo);
+ } else {
+ fo_set_next(prev_fo, fo_next(curr_fo));
+ }
+ if (fn == 0) {
+ GC_fo_entries--;
+ /* May not happen if we get a signal. But a high */
+ /* estimate will only make the table larger than */
+ /* necessary. */
+# if !defined(THREADS) && !defined(DBG_HDRS_ALL)
+ GC_free((void *)curr_fo);
+# endif
+ } else {
+ curr_fo -> fo_fn = fn;
+ curr_fo -> fo_client_data = (ptr_t)cd;
+ curr_fo -> fo_mark_proc = mp;
+ /* Reinsert it. We deleted it first to maintain */
+ /* consistency in the event of a signal. */
+ if (prev_fo == 0) {
+ fo_head[index] = curr_fo;
+ } else {
+ fo_set_next(prev_fo, curr_fo);
+ }
+ }
+# ifdef THREADS
+ UNLOCK();
+# endif
+ return;
+ }
+ prev_fo = curr_fo;
+ curr_fo = fo_next(curr_fo);
+ }
+ if (ofn) *ofn = 0;
+ if (ocd) *ocd = 0;
+ if (fn == 0) {
+# ifdef THREADS
+ UNLOCK();
+# endif
+ return;
+ }
+ GET_HDR(base, hhdr);
+ if (0 == hhdr) {
+ /* We won't collect it, hence finalizer wouldn't be run. */
+# ifdef THREADS
+ UNLOCK();
+# endif
+ return;
+ }
+ new_fo = (struct finalizable_object *)
+ GC_INTERNAL_MALLOC(sizeof(struct finalizable_object),NORMAL);
+ GC_ASSERT(GC_size(new_fo) >= sizeof(struct finalizable_object));
+ if (EXPECT(0 == new_fo, FALSE)) {
+# ifdef THREADS
+ UNLOCK();
+# endif
+ new_fo = (struct finalizable_object *)
+ GC_oom_fn(sizeof(struct finalizable_object));
+ if (0 == new_fo) {
+ GC_finalization_failures++;
+ return;
+ }
+ /* It's not likely we'll make it here, but ... */
+# ifdef THREADS
+ LOCK();
+# endif
+ }
+ new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
+ new_fo -> fo_fn = fn;
+ new_fo -> fo_client_data = (ptr_t)cd;
+ new_fo -> fo_object_size = hhdr -> hb_sz;
+ new_fo -> fo_mark_proc = mp;
+ fo_set_next(new_fo, fo_head[index]);
+ GC_fo_entries++;
+ fo_head[index] = new_fo;
+# ifdef THREADS
+ UNLOCK();
+# endif
+}
+
+void GC_register_finalizer(void * obj,
+ GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void ** ocd)
+{
+ GC_register_finalizer_inner(obj, fn, cd, ofn,
+ ocd, GC_normal_finalize_mark_proc);
+}
+
+void GC_register_finalizer_ignore_self(void * obj,
+ GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void ** ocd)
+{
+ GC_register_finalizer_inner(obj, fn, cd, ofn,
+ ocd, GC_ignore_self_finalize_mark_proc);
+}
+
+void GC_register_finalizer_no_order(void * obj,
+ GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void ** ocd)
+{
+ GC_register_finalizer_inner(obj, fn, cd, ofn,
+ ocd, GC_null_finalize_mark_proc);
+}
+
+static GC_bool need_unreachable_finalization = FALSE;
+ /* Avoid the work if this isn't used. */
+
+void GC_register_finalizer_unreachable(void * obj,
+ GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void ** ocd)
+{
+ need_unreachable_finalization = TRUE;
+ GC_ASSERT(GC_java_finalization);
+ GC_register_finalizer_inner(obj, fn, cd, ofn,
+ ocd, GC_unreachable_finalize_mark_proc);
+}
+
+#ifndef NO_DEBUGGING
+void GC_dump_finalization(void)
+{
+ struct disappearing_link * curr_dl;
+ struct finalizable_object * curr_fo;
+ ptr_t real_ptr, real_link;
+ int dl_size = (log_dl_table_size == -1 ) ? 0 : (1 << log_dl_table_size);
+ int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size);
+ int i;
+
+ GC_printf("Disappearing links:\n");
+ for (i = 0; i < dl_size; i++) {
+ for (curr_dl = dl_head[i]; curr_dl != 0; curr_dl = dl_next(curr_dl)) {
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj);
+ real_link = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link);
+ GC_printf("Object: %p, Link:%p\n", real_ptr, real_link);
+ }
+ }
+ GC_printf("Finalizers:\n");
+ for (i = 0; i < fo_size; i++) {
+ for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = fo_next(curr_fo)) {
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
+ GC_printf("Finalizable object: %p\n", real_ptr);
+ }
+ }
+}
+#endif
+
+/* Called with world stopped. Cause disappearing links to disappear, */
+/* and invoke finalizers. */
+void GC_finalize(void)
+{
+ struct disappearing_link * curr_dl, * prev_dl, * next_dl;
+ struct finalizable_object * curr_fo, * prev_fo, * next_fo;
+ ptr_t real_ptr, real_link;
+ size_t i;
+ size_t dl_size = (log_dl_table_size == -1 ) ? 0 : (1 << log_dl_table_size);
+ size_t fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size);
+
+ /* Make disappearing links disappear */
+ for (i = 0; i < dl_size; i++) {
+ curr_dl = dl_head[i];
+ prev_dl = 0;
+ while (curr_dl != 0) {
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj);
+ real_link = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link);
+ if (!GC_is_marked(real_ptr)) {
+ *(word *)real_link = 0;
+ next_dl = dl_next(curr_dl);
+ if (prev_dl == 0) {
+ dl_head[i] = next_dl;
+ } else {
+ dl_set_next(prev_dl, next_dl);
+ }
+ GC_clear_mark_bit((ptr_t)curr_dl);
+ GC_dl_entries--;
+ curr_dl = next_dl;
+ } else {
+ prev_dl = curr_dl;
+ curr_dl = dl_next(curr_dl);
+ }
+ }
+ }
+ /* Mark all objects reachable via chains of 1 or more pointers */
+ /* from finalizable objects. */
+ GC_ASSERT(GC_mark_state == MS_NONE);
+ for (i = 0; i < fo_size; i++) {
+ for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = fo_next(curr_fo)) {
+ GC_ASSERT(GC_size(curr_fo) >= sizeof(struct finalizable_object));
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
+ if (!GC_is_marked(real_ptr)) {
+ GC_MARKED_FOR_FINALIZATION(real_ptr);
+ GC_MARK_FO(real_ptr, curr_fo -> fo_mark_proc);
+ if (GC_is_marked(real_ptr)) {
+ WARN("Finalization cycle involving %lx\n", real_ptr);
+ }
+ }
+ }
+ }
+ /* Enqueue for finalization all objects that are still */
+ /* unreachable. */
+ GC_bytes_finalized = 0;
+ for (i = 0; i < fo_size; i++) {
+ curr_fo = fo_head[i];
+ prev_fo = 0;
+ while (curr_fo != 0) {
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
+ if (!GC_is_marked(real_ptr)) {
+ if (!GC_java_finalization) {
+ GC_set_mark_bit(real_ptr);
+ }
+ /* Delete from hash table */
+ next_fo = fo_next(curr_fo);
+ if (prev_fo == 0) {
+ fo_head[i] = next_fo;
+ } else {
+ fo_set_next(prev_fo, next_fo);
+ }
+ GC_fo_entries--;
+ /* Add to list of objects awaiting finalization. */
+ fo_set_next(curr_fo, GC_finalize_now);
+ GC_finalize_now = curr_fo;
+ /* unhide object pointer so any future collections will */
+ /* see it. */
+ curr_fo -> fo_hidden_base =
+ (word) REVEAL_POINTER(curr_fo -> fo_hidden_base);
+ GC_bytes_finalized +=
+ curr_fo -> fo_object_size
+ + sizeof(struct finalizable_object);
+ GC_ASSERT(GC_is_marked(GC_base((ptr_t)curr_fo)));
+ curr_fo = next_fo;
+ } else {
+ prev_fo = curr_fo;
+ curr_fo = fo_next(curr_fo);
+ }
+ }
+ }
+
+ if (GC_java_finalization) {
+ /* make sure we mark everything reachable from objects finalized
+ using the no_order mark_proc */
+ for (curr_fo = GC_finalize_now;
+ curr_fo != NULL; curr_fo = fo_next(curr_fo)) {
+ real_ptr = (ptr_t)curr_fo -> fo_hidden_base;
+ if (!GC_is_marked(real_ptr)) {
+ if (curr_fo -> fo_mark_proc == GC_null_finalize_mark_proc) {
+ GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
+ }
+ if (curr_fo -> fo_mark_proc != GC_unreachable_finalize_mark_proc) {
+ GC_set_mark_bit(real_ptr);
+ }
+ }
+ }
+
+ /* now revive finalize-when-unreachable objects reachable from
+ other finalizable objects */
+ if (need_unreachable_finalization) {
+ curr_fo = GC_finalize_now;
+ prev_fo = 0;
+ while (curr_fo != 0) {
+ next_fo = fo_next(curr_fo);
+ if (curr_fo -> fo_mark_proc == GC_unreachable_finalize_mark_proc) {
+ real_ptr = (ptr_t)curr_fo -> fo_hidden_base;
+ if (!GC_is_marked(real_ptr)) {
+ GC_set_mark_bit(real_ptr);
+ } else {
+ if (prev_fo == 0)
+ GC_finalize_now = next_fo;
+ else
+ fo_set_next(prev_fo, next_fo);
+
+ curr_fo -> fo_hidden_base =
+ (word) HIDE_POINTER(curr_fo -> fo_hidden_base);
+ GC_bytes_finalized -=
+ curr_fo -> fo_object_size + sizeof(struct finalizable_object);
+
+ i = HASH2(real_ptr, log_fo_table_size);
+ fo_set_next (curr_fo, fo_head[i]);
+ GC_fo_entries++;
+ fo_head[i] = curr_fo;
+ curr_fo = prev_fo;
+ }
+ }
+ prev_fo = curr_fo;
+ curr_fo = next_fo;
+ }
+ }
+ }
+
+ /* Remove dangling disappearing links. */
+ for (i = 0; i < dl_size; i++) {
+ curr_dl = dl_head[i];
+ prev_dl = 0;
+ while (curr_dl != 0) {
+ real_link = GC_base((ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link));
+ if (real_link != 0 && !GC_is_marked(real_link)) {
+ next_dl = dl_next(curr_dl);
+ if (prev_dl == 0) {
+ dl_head[i] = next_dl;
+ } else {
+ dl_set_next(prev_dl, next_dl);
+ }
+ GC_clear_mark_bit((ptr_t)curr_dl);
+ GC_dl_entries--;
+ curr_dl = next_dl;
+ } else {
+ prev_dl = curr_dl;
+ curr_dl = dl_next(curr_dl);
+ }
+ }
+ }
+}
+
+#ifndef JAVA_FINALIZATION_NOT_NEEDED
+
+/* Enqueue all remaining finalizers to be run - Assumes lock is
+ * held, and signals are disabled */
+void GC_enqueue_all_finalizers(void)
+{
+ struct finalizable_object * curr_fo, * prev_fo, * next_fo;
+ ptr_t real_ptr;
+ register int i;
+ int fo_size;
+
+ fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size);
+ GC_bytes_finalized = 0;
+ for (i = 0; i < fo_size; i++) {
+ curr_fo = fo_head[i];
+ prev_fo = 0;
+ while (curr_fo != 0) {
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
+ GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
+ GC_set_mark_bit(real_ptr);
+
+ /* Delete from hash table */
+ next_fo = fo_next(curr_fo);
+ if (prev_fo == 0) {
+ fo_head[i] = next_fo;
+ } else {
+ fo_set_next(prev_fo, next_fo);
+ }
+ GC_fo_entries--;
+
+ /* Add to list of objects awaiting finalization. */
+ fo_set_next(curr_fo, GC_finalize_now);
+ GC_finalize_now = curr_fo;
+
+ /* unhide object pointer so any future collections will */
+ /* see it. */
+ curr_fo -> fo_hidden_base =
+ (word) REVEAL_POINTER(curr_fo -> fo_hidden_base);
+
+ GC_bytes_finalized +=
+ curr_fo -> fo_object_size + sizeof(struct finalizable_object);
+ curr_fo = next_fo;
+ }
+ }
+
+ return;
+}
+
+/* Invoke all remaining finalizers that haven't yet been run.
+ * This is needed for strict compliance with the Java standard,
+ * which can make the runtime guarantee that all finalizers are run.
+ * Unfortunately, the Java standard implies we have to keep running
+ * finalizers until there are no more left, a potential infinite loop.
+ * YUCK.
+ * Note that this is even more dangerous than the usual Java
+ * finalizers, in that objects reachable from static variables
+ * may have been finalized when these finalizers are run.
+ * Finalizers run at this point must be prepared to deal with a
+ * mostly broken world.
+ * This routine is externally callable, so is called without
+ * the allocation lock.
+ */
+GC_API void GC_finalize_all(void)
+{
+ DCL_LOCK_STATE;
+
+ LOCK();
+ while (GC_fo_entries > 0) {
+ GC_enqueue_all_finalizers();
+ UNLOCK();
+ GC_INVOKE_FINALIZERS();
+ LOCK();
+ }
+ UNLOCK();
+}
+#endif
+
+/* Returns true if it is worth calling GC_invoke_finalizers. (Useful if */
+/* finalizers can only be called from some kind of `safe state' and */
+/* getting into that safe state is expensive.) */
+int GC_should_invoke_finalizers(void)
+{
+ return GC_finalize_now != 0;
+}
+
+/* Invoke finalizers for all objects that are ready to be finalized. */
+/* Should be called without allocation lock. */
+int GC_invoke_finalizers(void)
+{
+ struct finalizable_object * curr_fo;
+ int count = 0;
+ word bytes_freed_before;
+ DCL_LOCK_STATE;
+
+ while (GC_finalize_now != 0) {
+# ifdef THREADS
+ LOCK();
+# endif
+ if (count == 0) {
+ bytes_freed_before = GC_bytes_freed;
+ /* Don't do this outside, since we need the lock. */
+ }
+ curr_fo = GC_finalize_now;
+# ifdef THREADS
+ if (curr_fo != 0) GC_finalize_now = fo_next(curr_fo);
+ UNLOCK();
+ if (curr_fo == 0) break;
+# else
+ GC_finalize_now = fo_next(curr_fo);
+# endif
+ fo_set_next(curr_fo, 0);
+ (*(curr_fo -> fo_fn))((ptr_t)(curr_fo -> fo_hidden_base),
+ curr_fo -> fo_client_data);
+ curr_fo -> fo_client_data = 0;
+ ++count;
+# ifdef UNDEFINED
+ /* This is probably a bad idea. It throws off accounting if */
+ /* nearly all objects are finalizable. O.w. it shouldn't */
+ /* matter. */
+ GC_free((void *)curr_fo);
+# endif
+ }
+ /* bytes_freed_before is initialized whenever count != 0 */
+ if (count != 0 && bytes_freed_before != GC_bytes_freed) {
+ LOCK();
+ GC_finalizer_bytes_freed += (GC_bytes_freed - bytes_freed_before);
+ UNLOCK();
+ }
+ return count;
+}
+
+void (* GC_finalizer_notifier)() = (void (*) (void))0;
+
+static GC_word last_finalizer_notification = 0;
+
+void GC_notify_or_invoke_finalizers(void)
+{
+ /* This is a convenient place to generate backtraces if appropriate, */
+ /* since that code is not callable with the allocation lock. */
+# if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
+ static word last_back_trace_gc_no = 1; /* Skip first one. */
+
+ if (GC_gc_no > last_back_trace_gc_no) {
+ word i;
+
+# ifdef KEEP_BACK_PTRS
+ LOCK();
+ /* Stops when GC_gc_no wraps; that's OK. */
+ last_back_trace_gc_no = (word)(-1); /* disable others. */
+ for (i = 0; i < GC_backtraces; ++i) {
+ /* FIXME: This tolerates concurrent heap mutation, */
+ /* which may cause occasional mysterious results. */
+ /* We need to release the GC lock, since GC_print_callers */
+ /* acquires it. It probably shouldn't. */
+ UNLOCK();
+ GC_generate_random_backtrace_no_gc();
+ LOCK();
+ }
+ last_back_trace_gc_no = GC_gc_no;
+ UNLOCK();
+# endif
+# ifdef MAKE_BACK_GRAPH
+ if (GC_print_back_height)
+ GC_print_back_graph_stats();
+# endif
+ }
+# endif
+ if (GC_finalize_now == 0) return;
+ if (!GC_finalize_on_demand) {
+ (void) GC_invoke_finalizers();
+# ifndef THREADS
+ GC_ASSERT(GC_finalize_now == 0);
+# endif /* Otherwise GC can run concurrently and add more */
+ return;
+ }
+ if (GC_finalizer_notifier != (void (*) (void))0
+ && last_finalizer_notification != GC_gc_no) {
+ last_finalizer_notification = GC_gc_no;
+ GC_finalizer_notifier();
+ }
+}
+
+void * GC_call_with_alloc_lock(GC_fn_type fn, void * client_data)
+{
+ void * result;
+ DCL_LOCK_STATE;
+
+# ifdef THREADS
+ LOCK();
+ /* FIXME - This looks wrong!! */
+ SET_LOCK_HOLDER();
+# endif
+ result = (*fn)(client_data);
+# ifdef THREADS
+# ifndef GC_ASSERTIONS
+ UNSET_LOCK_HOLDER();
+# endif /* o.w. UNLOCK() does it implicitly */
+ UNLOCK();
+# endif
+ return(result);
+}
+
+#if !defined(NO_DEBUGGING)
+
+void GC_print_finalization_stats(void)
+{
+ struct finalizable_object *fo = GC_finalize_now;
+ size_t ready = 0;
+
+ GC_printf("%u finalization table entries; %u disappearing links\n",
+ GC_fo_entries, GC_dl_entries);
+ for (; 0 != fo; fo = fo_next(fo)) ++ready;
+ GC_printf("%u objects are eligible for immediate finalization\n", ready);
+}
+
+#endif /* NO_DEBUGGING */
diff --git a/tools/build/v2/engine/boehm_gc/gc.mak b/tools/build/v2/engine/boehm_gc/gc.mak
new file mode 100644
index 0000000000..5c02c9023c
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/gc.mak
@@ -0,0 +1,2220 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.10
+# This has been hand-edited way too many times.
+# A clean, manually generated makefile would be an improvement.
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+AO_VERSION=1.2
+!IF "$(CFG)" == ""
+CFG=gctest - Win32 Release
+!MESSAGE No configuration specified. Defaulting to cord - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "gc - Win32 Release" && "$(CFG)" != "gc - Win32 Debug" &&\
+ "$(CFG)" != "gctest - Win32 Release" && "$(CFG)" != "gctest - Win32 Debug" &&\
+ "$(CFG)" != "cord - Win32 Release" && "$(CFG)" != "cord - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gc.mak" CFG="cord - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "gc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "gctest - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "gctest - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "cord - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "cord - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "gctest - Win32 Debug"
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : ".\Release\gc.dll" ".\Release\gc.bsc"
+
+CLEAN :
+ -@erase ".\Release\allchblk.obj"
+ -@erase ".\Release\allchblk.sbr"
+ -@erase ".\Release\alloc.obj"
+ -@erase ".\Release\alloc.sbr"
+ -@erase ".\Release\blacklst.obj"
+ -@erase ".\Release\blacklst.sbr"
+ -@erase ".\Release\checksums.obj"
+ -@erase ".\Release\checksums.sbr"
+ -@erase ".\Release\dbg_mlc.obj"
+ -@erase ".\Release\dbg_mlc.sbr"
+ -@erase ".\Release\dyn_load.obj"
+ -@erase ".\Release\dyn_load.sbr"
+ -@erase ".\Release\finalize.obj"
+ -@erase ".\Release\finalize.sbr"
+ -@erase ".\Release\gc.bsc"
+ -@erase ".\Release\gc_cpp.obj"
+ -@erase ".\Release\gc_cpp.sbr"
+ -@erase ".\Release\gc.dll"
+ -@erase ".\Release\gc.exp"
+ -@erase ".\Release\gc.lib"
+ -@erase ".\Release\headers.obj"
+ -@erase ".\Release\headers.sbr"
+ -@erase ".\Release\mach_dep.obj"
+ -@erase ".\Release\mach_dep.sbr"
+ -@erase ".\Release\malloc.obj"
+ -@erase ".\Release\malloc.sbr"
+ -@erase ".\Release\mallocx.obj"
+ -@erase ".\Release\mallocx.sbr"
+ -@erase ".\Release\mark.obj"
+ -@erase ".\Release\mark.sbr"
+ -@erase ".\Release\mark_rts.obj"
+ -@erase ".\Release\mark_rts.sbr"
+ -@erase ".\Release\misc.obj"
+ -@erase ".\Release\misc.sbr"
+ -@erase ".\Release\new_hblk.obj"
+ -@erase ".\Release\new_hblk.sbr"
+ -@erase ".\Release\obj_map.obj"
+ -@erase ".\Release\obj_map.sbr"
+ -@erase ".\Release\os_dep.obj"
+ -@erase ".\Release\os_dep.sbr"
+ -@erase ".\Release\ptr_chck.obj"
+ -@erase ".\Release\ptr_chck.sbr"
+ -@erase ".\Release\reclaim.obj"
+ -@erase ".\Release\reclaim.sbr"
+ -@erase ".\Release\stubborn.obj"
+ -@erase ".\Release\stubborn.sbr"
+ -@erase ".\Release\typd_mlc.obj"
+ -@erase ".\Release\typd_mlc.sbr"
+ -@erase ".\Release\win32_threads.obj"
+ -@erase ".\Release\win32_threads.sbr"
+ -@erase ".\Release\msvc_dbg.obj"
+ -@erase ".\Release\msvc_dbg.sbr"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "GC_BUILD" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR /YX /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "GC_BUILD" /D\
+ "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D\
+ "GC_WIN32_THREADS" /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch" \
+ /Ilibatomic_ops-$(AO_VERSION)/src /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Release/
+CPP_SBRS=.\Release/
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gc.bsc"
+BSC32_SBRS= \
+ ".\Release\allchblk.sbr" \
+ ".\Release\alloc.sbr" \
+ ".\Release\blacklst.sbr" \
+ ".\Release\checksums.sbr" \
+ ".\Release\dbg_mlc.sbr" \
+ ".\Release\dyn_load.sbr" \
+ ".\Release\finalize.sbr" \
+ ".\Release\gc_cpp.sbr" \
+ ".\Release\headers.sbr" \
+ ".\Release\mach_dep.sbr" \
+ ".\Release\malloc.sbr" \
+ ".\Release\mallocx.sbr" \
+ ".\Release\mark.sbr" \
+ ".\Release\mark_rts.sbr" \
+ ".\Release\misc.sbr" \
+ ".\Release\new_hblk.sbr" \
+ ".\Release\obj_map.sbr" \
+ ".\Release\os_dep.sbr" \
+ ".\Release\ptr_chck.sbr" \
+ ".\Release\reclaim.sbr" \
+ ".\Release\stubborn.sbr" \
+ ".\Release\typd_mlc.sbr" \
+ ".\Release\msvc_dbg.sbr" \
+ ".\Release\win32_threads.sbr"
+
+".\Release\gc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\
+ /pdb:"$(OUTDIR)/gc.pdb" /machine:I386 /out:"$(OUTDIR)/gc.dll"\
+ /implib:"$(OUTDIR)/gc.lib"
+LINK32_OBJS= \
+ ".\Release\allchblk.obj" \
+ ".\Release\alloc.obj" \
+ ".\Release\blacklst.obj" \
+ ".\Release\checksums.obj" \
+ ".\Release\dbg_mlc.obj" \
+ ".\Release\dyn_load.obj" \
+ ".\Release\finalize.obj" \
+ ".\Release\gc_cpp.obj" \
+ ".\Release\headers.obj" \
+ ".\Release\mach_dep.obj" \
+ ".\Release\malloc.obj" \
+ ".\Release\mallocx.obj" \
+ ".\Release\mark.obj" \
+ ".\Release\mark_rts.obj" \
+ ".\Release\misc.obj" \
+ ".\Release\new_hblk.obj" \
+ ".\Release\obj_map.obj" \
+ ".\Release\os_dep.obj" \
+ ".\Release\ptr_chck.obj" \
+ ".\Release\reclaim.obj" \
+ ".\Release\stubborn.obj" \
+ ".\Release\typd_mlc.obj" \
+ ".\Release\msvc_dbg.obj" \
+ ".\Release\win32_threads.obj"
+
+".\Release\gc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+OUTDIR=.\Debug
+INTDIR=.\Debug
+
+ALL : ".\Debug\gc.dll" ".\Debug\gc.bsc"
+
+CLEAN :
+ -@erase ".\Debug\allchblk.obj"
+ -@erase ".\Debug\allchblk.sbr"
+ -@erase ".\Debug\alloc.obj"
+ -@erase ".\Debug\alloc.sbr"
+ -@erase ".\Debug\blacklst.obj"
+ -@erase ".\Debug\blacklst.sbr"
+ -@erase ".\Debug\checksums.obj"
+ -@erase ".\Debug\checksums.sbr"
+ -@erase ".\Debug\dbg_mlc.obj"
+ -@erase ".\Debug\dbg_mlc.sbr"
+ -@erase ".\Debug\dyn_load.obj"
+ -@erase ".\Debug\dyn_load.sbr"
+ -@erase ".\Debug\finalize.obj"
+ -@erase ".\Debug\finalize.sbr"
+ -@erase ".\Debug\gc_cpp.obj"
+ -@erase ".\Debug\gc_cpp.sbr"
+ -@erase ".\Debug\gc.bsc"
+ -@erase ".\Debug\gc.dll"
+ -@erase ".\Debug\gc.exp"
+ -@erase ".\Debug\gc.lib"
+ -@erase ".\Debug\gc.map"
+ -@erase ".\Debug\gc.pdb"
+ -@erase ".\Debug\headers.obj"
+ -@erase ".\Debug\headers.sbr"
+ -@erase ".\Debug\mach_dep.obj"
+ -@erase ".\Debug\mach_dep.sbr"
+ -@erase ".\Debug\malloc.obj"
+ -@erase ".\Debug\malloc.sbr"
+ -@erase ".\Debug\mallocx.obj"
+ -@erase ".\Debug\mallocx.sbr"
+ -@erase ".\Debug\mark.obj"
+ -@erase ".\Debug\mark.sbr"
+ -@erase ".\Debug\mark_rts.obj"
+ -@erase ".\Debug\mark_rts.sbr"
+ -@erase ".\Debug\misc.obj"
+ -@erase ".\Debug\misc.sbr"
+ -@erase ".\Debug\new_hblk.obj"
+ -@erase ".\Debug\new_hblk.sbr"
+ -@erase ".\Debug\obj_map.obj"
+ -@erase ".\Debug\obj_map.sbr"
+ -@erase ".\Debug\os_dep.obj"
+ -@erase ".\Debug\os_dep.sbr"
+ -@erase ".\Debug\ptr_chck.obj"
+ -@erase ".\Debug\ptr_chck.sbr"
+ -@erase ".\Debug\reclaim.obj"
+ -@erase ".\Debug\reclaim.sbr"
+ -@erase ".\Debug\stubborn.obj"
+ -@erase ".\Debug\stubborn.sbr"
+ -@erase ".\Debug\typd_mlc.obj"
+ -@erase ".\Debug\typd_mlc.sbr"
+ -@erase ".\Debug\vc40.idb"
+ -@erase ".\Debug\vc40.pdb"
+ -@erase ".\Debug\win32_threads.obj"
+ -@erase ".\Debug\win32_threads.sbr"
+ -@erase ".\Debug\msvc_dbg.obj"
+ -@erase ".\Debug\msvc_dbg.sbr"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG" /D "GC_BUILD" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG" /D "GC_BUILD"\
+ /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" \
+ /D "GC_ASSERTIONS" /D "__STDC__" /D\
+ "GC_WIN32_THREADS" /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch" /YX /Fo"$(INTDIR)/"\
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=.\Debug/
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gc.bsc"
+BSC32_SBRS= \
+ ".\Debug\allchblk.sbr" \
+ ".\Debug\alloc.sbr" \
+ ".\Debug\blacklst.sbr" \
+ ".\Debug\checksums.sbr" \
+ ".\Debug\dbg_mlc.sbr" \
+ ".\Debug\dyn_load.sbr" \
+ ".\Debug\finalize.sbr" \
+ ".\Debug\gc_cpp.sbr" \
+ ".\Debug\headers.sbr" \
+ ".\Debug\mach_dep.sbr" \
+ ".\Debug\malloc.sbr" \
+ ".\Debug\mallocx.sbr" \
+ ".\Debug\mark.sbr" \
+ ".\Debug\mark_rts.sbr" \
+ ".\Debug\misc.sbr" \
+ ".\Debug\new_hblk.sbr" \
+ ".\Debug\obj_map.sbr" \
+ ".\Debug\os_dep.sbr" \
+ ".\Debug\ptr_chck.sbr" \
+ ".\Debug\reclaim.sbr" \
+ ".\Debug\stubborn.sbr" \
+ ".\Debug\typd_mlc.sbr" \
+ ".\Debug\msvc_dbg.sbr" \
+ ".\Debug\win32_threads.sbr"
+
+".\Debug\gc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\
+ /pdb:"$(OUTDIR)/gc.pdb" /map:"$(INTDIR)/gc.map" /debug /machine:I386\
+ /out:"$(OUTDIR)/gc.dll" /implib:"$(OUTDIR)/gc.lib"
+LINK32_OBJS= \
+ ".\Debug\allchblk.obj" \
+ ".\Debug\alloc.obj" \
+ ".\Debug\blacklst.obj" \
+ ".\Debug\checksums.obj" \
+ ".\Debug\dbg_mlc.obj" \
+ ".\Debug\dyn_load.obj" \
+ ".\Debug\finalize.obj" \
+ ".\Debug\gc_cpp.obj" \
+ ".\Debug\headers.obj" \
+ ".\Debug\mach_dep.obj" \
+ ".\Debug\malloc.obj" \
+ ".\Debug\mallocx.obj" \
+ ".\Debug\mark.obj" \
+ ".\Debug\mark_rts.obj" \
+ ".\Debug\misc.obj" \
+ ".\Debug\new_hblk.obj" \
+ ".\Debug\obj_map.obj" \
+ ".\Debug\os_dep.obj" \
+ ".\Debug\ptr_chck.obj" \
+ ".\Debug\reclaim.obj" \
+ ".\Debug\stubborn.obj" \
+ ".\Debug\typd_mlc.obj" \
+ ".\Debug\msvc_dbg.obj" \
+ ".\Debug\win32_threads.obj"
+
+".\Debug\gc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "gctest\Release"
+# PROP BASE Intermediate_Dir "gctest\Release"
+# PROP BASE Target_Dir "gctest"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "gctest\Release"
+# PROP Intermediate_Dir "gctest\Release"
+# PROP Target_Dir "gctest"
+OUTDIR=.\gctest\Release
+INTDIR=.\gctest\Release
+
+ALL : "gc - Win32 Release" ".\Release\gctest.exe"
+
+CLEAN :
+ -@erase ".\gctest\Release\test.obj"
+ -@erase ".\Release\gctest.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+test.c : tests\test.c
+ copy tests\test.c test.c
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /YX /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
+ "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS"\
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fp"$(INTDIR)/gctest.pch" \
+ /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\gctest\Release/
+CPP_SBRS=.\.
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gctest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"Release/gctest.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/gctest.pdb" /machine:I386 /out:"Release/gctest.exe"
+LINK32_OBJS= \
+ ".\gctest\Release\test.obj" \
+ ".\Release\gc.lib"
+
+".\Release\gctest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "gctest\Debug"
+# PROP BASE Intermediate_Dir "gctest\Debug"
+# PROP BASE Target_Dir "gctest"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "gctest\Debug"
+# PROP Intermediate_Dir "gctest\Debug"
+# PROP Target_Dir "gctest"
+OUTDIR=.\gctest\Debug
+INTDIR=.\gctest\Debug
+
+ALL : "gc - Win32 Debug" ".\Debug\gctest.exe" ".\gctest\Debug\gctest.bsc"
+
+CLEAN :
+ -@erase ".\Debug\gctest.exe"
+ -@erase ".\gctest\Debug\gctest.bsc"
+ -@erase ".\gctest\Debug\gctest.map"
+ -@erase ".\gctest\Debug\gctest.pdb"
+ -@erase ".\gctest\Debug\test.obj"
+ -@erase ".\gctest\Debug\test.sbr"
+ -@erase ".\gctest\Debug\vc40.idb"
+ -@erase ".\gctest\Debug\vc40.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\
+ /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR"$(INTDIR)/"\
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fp"$(INTDIR)/gctest.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\gctest\Debug/
+CPP_SBRS=.\gctest\Debug/
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gctest.bsc"
+BSC32_SBRS= \
+ ".\gctest\Debug\test.sbr"
+
+".\gctest\Debug\gctest.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:no /map /debug /machine:I386 /out:"Debug/gctest.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/gctest.pdb" /map:"$(INTDIR)/gctest.map" /debug /machine:I386\
+ /out:"Debug/gctest.exe"
+LINK32_OBJS= \
+ ".\Debug\gc.lib" \
+ ".\gctest\Debug\test.obj"
+
+".\Debug\gctest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "cord - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "cord\Release"
+# PROP BASE Intermediate_Dir "cord\Release"
+# PROP BASE Target_Dir "cord"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "cord\Release"
+# PROP Intermediate_Dir "cord\Release"
+# PROP Target_Dir "cord"
+OUTDIR=.\cord\Release
+INTDIR=.\cord\Release
+
+ALL : "gc - Win32 Release" ".\Release\de.exe"
+
+CLEAN :
+ -@erase ".\cord\Release\cordbscs.obj"
+ -@erase ".\cord\Release\cordxtra.obj"
+ -@erase ".\cord\Release\de.obj"
+ -@erase ".\cord\Release\de_win.obj"
+ -@erase ".\cord\Release\de_win.res"
+ -@erase ".\Release\de.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /YX /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "." /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
+ /Ilibatomic_ops-$(AO_VERSION)/src "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\cord\Release/
+CPP_SBRS=.\.
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)/de_win.res" /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/cord.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"Release/de.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)/de.pdb"\
+ /machine:I386 /out:"Release/de.exe"
+LINK32_OBJS= \
+ ".\cord\Release\cordbscs.obj" \
+ ".\cord\Release\cordxtra.obj" \
+ ".\cord\Release\de.obj" \
+ ".\cord\Release\de_win.obj" \
+ ".\cord\Release\de_win.res" \
+ ".\Release\gc.lib"
+
+".\Release\de.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "cord\Debug"
+# PROP BASE Intermediate_Dir "cord\Debug"
+# PROP BASE Target_Dir "cord"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "cord\Debug"
+# PROP Intermediate_Dir "cord\Debug"
+# PROP Target_Dir "cord"
+OUTDIR=.\cord\Debug
+INTDIR=.\cord\Debug
+
+ALL : "gc - Win32 Debug" ".\Debug\de.exe"
+
+CLEAN :
+ -@erase ".\cord\Debug\cordbscs.obj"
+ -@erase ".\cord\Debug\cordxtra.obj"
+ -@erase ".\cord\Debug\de.obj"
+ -@erase ".\cord\Debug\de.pdb"
+ -@erase ".\cord\Debug\de_win.obj"
+ -@erase ".\cord\Debug\de_win.res"
+ -@erase ".\cord\Debug\vc40.idb"
+ -@erase ".\cord\Debug\vc40.pdb"
+ -@erase ".\Debug\de.exe"
+ -@erase ".\Debug\de.ilk"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "." /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "." /I include /D "_DEBUG" /D "WIN32" /D\
+ "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX\
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\cord\Debug/
+CPP_SBRS=.\.
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)/de_win.res" /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/cord.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/de.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:yes\
+ /pdb:"$(OUTDIR)/de.pdb" /debug /machine:I386 /out:"Debug/de.exe"
+LINK32_OBJS= \
+ ".\cord\Debug\cordbscs.obj" \
+ ".\cord\Debug\cordxtra.obj" \
+ ".\cord\Debug\de.obj" \
+ ".\cord\Debug\de_win.obj" \
+ ".\cord\Debug\de_win.res" \
+ ".\Debug\gc.lib"
+
+".\Debug\de.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+################################################################################
+# Begin Target
+
+# Name "gc - Win32 Release"
+# Name "gc - Win32 Debug"
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\gc_cpp.cpp
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_RECLA=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\gc_cpp.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_RECLA=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\gc_cpp.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+".\Release\gc_cpp.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_RECLA=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\gc_cpp.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_RECLA=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\gc_cpp.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+".\Debug\gc_cpp.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\reclaim.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_RECLA=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_RECLA=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\reclaim.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+".\Release\reclaim.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_RECLA=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_RECLA=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\reclaim.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+".\Debug\reclaim.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\os_dep.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_OS_DE=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OS_DE=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+ ".\vd\PCR_VD.h"\
+
+
+".\Release\os_dep.obj" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+".\Release\os_dep.sbr" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_OS_DE=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OS_DE=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+ ".\vd\PCR_VD.h"\
+
+
+".\Debug\os_dep.obj" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+".\Debug\os_dep.sbr" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\misc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MISC_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MISC_=\
+ ".\il\PCR_IL.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\misc.obj" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+".\Release\misc.sbr" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MISC_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MISC_=\
+ ".\il\PCR_IL.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\misc.obj" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+".\Debug\misc.sbr" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mark_rts.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MARK_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mark_rts.obj" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+".\Release\mark_rts.sbr" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MARK_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mark_rts.obj" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+".\Debug\mark_rts.sbr" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mach_dep.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MACH_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MACH_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mach_dep.obj" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+".\Release\mach_dep.sbr" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MACH_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MACH_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mach_dep.obj" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+".\Debug\mach_dep.sbr" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\headers.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_HEADE=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_HEADE=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\headers.obj" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+".\Release\headers.sbr" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_HEADE=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_HEADE=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\headers.obj" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+".\Debug\headers.sbr" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\alloc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_ALLOC=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLOC=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\alloc.obj" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+".\Release\alloc.sbr" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_ALLOC=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLOC=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\alloc.obj" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+".\Debug\alloc.sbr" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\allchblk.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_ALLCH=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLCH=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\allchblk.obj" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+".\Release\allchblk.sbr" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_ALLCH=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLCH=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\allchblk.obj" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+".\Debug\allchblk.sbr" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\stubborn.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_STUBB=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_STUBB=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\stubborn.obj" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+".\Release\stubborn.sbr" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_STUBB=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_STUBB=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\stubborn.obj" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+".\Debug\stubborn.sbr" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\obj_map.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_OBJ_M=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OBJ_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\obj_map.obj" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+".\Release\obj_map.sbr" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_OBJ_M=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OBJ_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\obj_map.obj" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+".\Debug\obj_map.sbr" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\new_hblk.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_NEW_H=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_NEW_H=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\new_hblk.obj" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+".\Release\new_hblk.sbr" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_NEW_H=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_NEW_H=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\new_hblk.obj" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+".\Debug\new_hblk.sbr" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mark.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MARK_C=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mark.obj" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+".\Release\mark.sbr" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MARK_C=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mark.obj" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+".\Debug\mark.sbr" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\malloc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MALLO=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLO=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\malloc.obj" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+".\Release\malloc.sbr" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MALLO=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLO=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\malloc.obj" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+".\Debug\malloc.sbr" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mallocx.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MALLX=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLX=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mallocx.obj" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+".\Release\mallocx.sbr" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MALLX=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLX=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mallocx.obj" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+".\Debug\mallocx.sbr" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\finalize.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_FINAL=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_FINAL=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\finalize.obj" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+".\Release\finalize.sbr" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_FINAL=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_FINAL=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\finalize.obj" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+".\Debug\finalize.sbr" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\dbg_mlc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_DBG_M=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DBG_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\dbg_mlc.obj" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+".\Release\dbg_mlc.sbr" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_DBG_M=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DBG_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\dbg_mlc.obj" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+".\Debug\dbg_mlc.sbr" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\blacklst.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_BLACK=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_BLACK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\blacklst.obj" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+".\Release\blacklst.sbr" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_BLACK=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_BLACK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\blacklst.obj" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+".\Debug\blacklst.sbr" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\typd_mlc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_TYPD_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\gc_typed.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_TYPD_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\typd_mlc.obj" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+".\Release\typd_mlc.sbr" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_TYPD_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\gc_typed.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_TYPD_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\typd_mlc.obj" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+".\Debug\typd_mlc.sbr" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\ptr_chck.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_PTR_C=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_PTR_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\ptr_chck.obj" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+".\Release\ptr_chck.sbr" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_PTR_C=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_pmark.h"\
+ ".\include\gc_mark.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_PTR_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\ptr_chck.obj" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+".\Debug\ptr_chck.sbr" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\dyn_load.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_DYN_L=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DYN_L=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\dyn_load.obj" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+".\Release\dyn_load.sbr" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_DYN_L=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DYN_L=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\dyn_load.obj" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+".\Debug\dyn_load.sbr" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\win32_threads.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_WIN32=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_WIN32=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\win32_threads.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+".\Release\win32_threads.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_WIN32=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_WIN32=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\win32_threads.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+".\Debug\win32_threads.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\msvc_dbg.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_WIN32=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\private\msvc_dbg.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_WIN32=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\msvc_dbg.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+".\Release\msvc_dbg.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_WIN32=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\private\msvc_dbg.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_WIN32=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\msvc_dbg.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+".\Debug\msvc_dbg.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\checksums.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_CHECK=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_CHECK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\checksums.obj" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+".\Release\checksums.sbr" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_CHECK=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_CHECK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\checksums.obj" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+".\Debug\checksums.sbr" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+# End Target
+################################################################################
+# Begin Target
+
+# Name "gctest - Win32 Release"
+# Name "gctest - Win32 Debug"
+
+!IF "$(CFG)" == "gctest - Win32 Release"
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Project Dependency
+
+# Project_Dep_Name "gc"
+
+!IF "$(CFG)" == "gctest - Win32 Release"
+
+"gc - Win32 Release" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+"gc - Win32 Debug" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Debug"
+
+!ENDIF
+
+# End Project Dependency
+################################################################################
+# Begin Source File
+
+SOURCE=.\tests\test.c
+DEP_CPP_TEST_=\
+ ".\include\private\gcconfig.h"\
+ ".\include\gc.h"\
+ ".\include\private\gc_hdrs.h"\
+ ".\include\private\gc_priv.h"\
+ ".\include\gc_typed.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_TEST_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+!IF "$(CFG)" == "gctest - Win32 Release"
+
+
+".\gctest\Release\test.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+
+".\gctest\Debug\test.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
+
+".\gctest\Debug\test.sbr" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+# End Target
+################################################################################
+# Begin Target
+
+# Name "cord - Win32 Release"
+# Name "cord - Win32 Debug"
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Project Dependency
+
+# Project_Dep_Name "gc"
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+"gc - Win32 Release" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+"gc - Win32 Debug" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Debug"
+
+!ENDIF
+
+# End Project Dependency
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\de_win.c
+DEP_CPP_DE_WI=\
+ ".\include\cord.h"\
+ ".\cord\de_cmds.h"\
+ ".\cord\de_win.h"\
+ ".\include\private\cord_pos.h"\
+
+NODEP_CPP_DE_WI=\
+ ".\include\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\de_win.obj" : $(SOURCE) $(DEP_CPP_DE_WI) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\de_win.obj" : $(SOURCE) $(DEP_CPP_DE_WI) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\de.c
+DEP_CPP_DE_C2e=\
+ ".\include\cord.h"\
+ ".\cord\de_cmds.h"\
+ ".\cord\de_win.h"\
+ ".\include\private\cord_pos.h"\
+
+NODEP_CPP_DE_C2e=\
+ ".\include\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\de.obj" : $(SOURCE) $(DEP_CPP_DE_C2e) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\de.obj" : $(SOURCE) $(DEP_CPP_DE_C2e) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\cordxtra.c
+DEP_CPP_CORDX=\
+ ".\include\cord.h"\
+ ".\include\ec.h"\
+ ".\include\private\cord_pos.h"\
+
+NODEP_CPP_CORDX=\
+ ".\include\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\cordxtra.obj" : $(SOURCE) $(DEP_CPP_CORDX) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\cordxtra.obj" : $(SOURCE) $(DEP_CPP_CORDX) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\cordbscs.c
+DEP_CPP_CORDB=\
+ ".\include\cord.h"\
+ ".\include\private\cord_pos.h"\
+
+NODEP_CPP_CORDB=\
+ ".\include\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\cordbscs.obj" : $(SOURCE) $(DEP_CPP_CORDB) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\cordbscs.obj" : $(SOURCE) $(DEP_CPP_CORDB) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\de_win.RC
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\de_win.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x809 /fo"$(INTDIR)/de_win.res" /i "cord" /d "NDEBUG" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\de_win.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x809 /fo"$(INTDIR)/de_win.res" /i "cord" /d "_DEBUG" $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/tools/build/v2/engine/boehm_gc/gc_cpp.cc b/tools/build/v2/engine/boehm_gc/gc_cpp.cc
new file mode 100644
index 0000000000..c4dc4cd256
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/gc_cpp.cc
@@ -0,0 +1,67 @@
+/*************************************************************************
+Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+
+THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+
+ Last modified on Sat Nov 19 19:31:14 PST 1994 by ellis
+ on Sat Jun 8 15:10:00 PST 1994 by boehm
+
+Permission is hereby granted to copy this code for any purpose,
+provided the above notices are retained on all copies.
+
+This implementation module for gc_c++.h provides an implementation of
+the global operators "new" and "delete" that calls the Boehm
+allocator. All objects allocated by this implementation will be
+non-collectable but part of the root set of the collector.
+
+You should ensure (using implementation-dependent techniques) that the
+linker finds this module before the library that defines the default
+built-in "new" and "delete".
+
+Authors: John R. Ellis and Jesse Hull
+
+**************************************************************************/
+/* Boehm, December 20, 1994 7:26 pm PST */
+
+#include "gc_cpp.h"
+
+void* operator new( size_t size ) {
+ return GC_MALLOC_UNCOLLECTABLE( size );}
+
+void operator delete( void* obj ) {
+ GC_FREE( obj );}
+
+#ifdef GC_OPERATOR_NEW_ARRAY
+
+void* operator new[]( size_t size ) {
+ return GC_MALLOC_UNCOLLECTABLE( size );}
+
+void operator delete[]( void* obj ) {
+ GC_FREE( obj );}
+
+#endif /* GC_OPERATOR_NEW_ARRAY */
+
+#ifdef _MSC_VER
+
+// This new operator is used by VC++ in case of Debug builds !
+void* operator new( size_t size,
+ int ,//nBlockUse,
+ const char * szFileName,
+ int nLine )
+{
+#ifndef GC_DEBUG
+ return GC_malloc_uncollectable( size );
+#else
+ return GC_debug_malloc_uncollectable(size, szFileName, nLine);
+#endif
+}
+
+// This new operator is used by VC++ 7.0 and later in Debug builds.
+void* operator new[](size_t size, int nBlockUse, const char* szFileName, int nLine)
+{
+ return operator new(size, nBlockUse, szFileName, nLine);
+}
+
+#endif /* _MSC_VER */
+
diff --git a/tools/build/v2/engine/boehm_gc/gc_cpp.cpp b/tools/build/v2/engine/boehm_gc/gc_cpp.cpp
new file mode 100644
index 0000000000..f6bd95e59a
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/gc_cpp.cpp
@@ -0,0 +1,2 @@
+// Visual C++ seems to prefer a .cpp extension to .cc
+#include "gc_cpp.cc"
diff --git a/tools/build/v2/engine/boehm_gc/gc_dlopen.c b/tools/build/v2/engine/boehm_gc/gc_dlopen.c
new file mode 100644
index 0000000000..51659d1e82
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/gc_dlopen.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1997 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ * Original author: Bill Janssen
+ * Heavily modified by Hans Boehm and others
+ */
+
+/*
+ * This used to be in dyn_load.c. It was extracted into a separate file
+ * to avoid having to link against libdl.{a,so} if the client doesn't call
+ * dlopen. Of course this fails if the collector is in a dynamic
+ * library. -HB
+ */
+
+#include "private/gc_priv.h"
+
+# if (defined(GC_PTHREADS) && !defined(GC_DARWIN_THREADS)) && !defined(GC_WIN32_PTHREADS)\
+ || defined(GC_SOLARIS_THREADS)
+
+# if defined(dlopen) && !defined(GC_USE_LD_WRAP)
+ /* To support various threads pkgs, gc.h interposes on dlopen by */
+ /* defining "dlopen" to be "GC_dlopen", which is implemented below. */
+ /* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the */
+ /* real system dlopen() in their implementation. We first remove */
+ /* gc.h's dlopen definition and restore it later, after GC_dlopen(). */
+# undef dlopen
+# endif
+
+ /* Make sure we're not in the middle of a collection, and make */
+ /* sure we don't start any. Returns previous value of GC_dont_gc. */
+ /* This is invoked prior to a dlopen call to avoid synchronization */
+ /* issues. We can't just acquire the allocation lock, since startup */
+ /* code in dlopen may try to allocate. */
+ /* This solution risks heap growth in the presence of many dlopen */
+ /* calls in either a multithreaded environment, or if the library */
+ /* initialization code allocates substantial amounts of GC'ed memory. */
+ /* But I don't know of a better solution. */
+ static void disable_gc_for_dlopen()
+ {
+ LOCK();
+ while (GC_incremental && GC_collection_in_progress()) {
+ GC_collect_a_little_inner(1000);
+ }
+ ++GC_dont_gc;
+ UNLOCK();
+ }
+
+ /* Redefine dlopen to guarantee mutual exclusion with */
+ /* GC_register_dynamic_libraries. */
+ /* Should probably happen for other operating systems, too. */
+
+#include <dlfcn.h>
+
+#ifdef GC_USE_LD_WRAP
+ void * __wrap_dlopen(const char *path, int mode)
+#else
+ void * GC_dlopen(const char *path, int mode)
+#endif
+{
+ void * result;
+
+# ifndef USE_PROC_FOR_LIBRARIES
+ disable_gc_for_dlopen();
+# endif
+# ifdef GC_USE_LD_WRAP
+ result = (void *)__real_dlopen(path, mode);
+# else
+ result = dlopen(path, mode);
+# endif
+# ifndef USE_PROC_FOR_LIBRARIES
+ GC_enable(); /* undoes disable_gc_for_dlopen */
+# endif
+ return(result);
+}
+# endif /* GC_PTHREADS || GC_SOLARIS_THREADS ... */
+
+
+
diff --git a/tools/build/v2/engine/boehm_gc/gcj_mlc.c b/tools/build/v2/engine/boehm_gc/gcj_mlc.c
new file mode 100644
index 0000000000..7e5beb1886
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/gcj_mlc.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+/* Boehm, July 31, 1995 5:02 pm PDT */
+
+#ifdef GC_GCJ_SUPPORT
+
+/*
+ * This is an allocator interface tuned for gcj (the GNU static
+ * java compiler).
+ *
+ * Each allocated object has a pointer in its first word to a vtable,
+ * which for our purposes is simply a structure describing the type of
+ * the object.
+ * This descriptor structure contains a GC marking descriptor at offset
+ * MARK_DESCR_OFFSET.
+ *
+ * It is hoped that this interface may also be useful for other systems,
+ * possibly with some tuning of the constants. But the immediate goal
+ * is to get better gcj performance.
+ *
+ * We assume:
+ * 1) We have an ANSI conforming C compiler.
+ * 2) Counting on explicit initialization of this interface is OK.
+ * 3) FASTLOCK is not a significant win.
+ */
+
+#include "private/gc_pmark.h"
+#include "gc_gcj.h"
+#include "private/dbg_mlc.h"
+
+GC_bool GC_gcj_malloc_initialized = FALSE;
+
+int GC_gcj_kind; /* Object kind for objects with descriptors */
+ /* in "vtable". */
+int GC_gcj_debug_kind; /* The kind of objects that is always marked */
+ /* with a mark proc call. */
+
+ptr_t * GC_gcjobjfreelist;
+ptr_t * GC_gcjdebugobjfreelist;
+
+/* Caller does not hold allocation lock. */
+void GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp)
+{
+ register int i;
+ GC_bool ignore_gcj_info;
+ DCL_LOCK_STATE;
+
+ GC_init(); /* In case it's not already done. */
+ LOCK();
+ if (GC_gcj_malloc_initialized) {
+ UNLOCK();
+ return;
+ }
+ GC_gcj_malloc_initialized = TRUE;
+ ignore_gcj_info = (0 != GETENV("GC_IGNORE_GCJ_INFO"));
+ if (GC_print_stats && ignore_gcj_info) {
+ GC_log_printf("Gcj-style type information is disabled!\n");
+ }
+ GC_ASSERT(GC_mark_procs[mp_index] == (GC_mark_proc)0); /* unused */
+ GC_mark_procs[mp_index] = (GC_mark_proc)mp;
+ if (mp_index >= GC_n_mark_procs) ABORT("GC_init_gcj_malloc: bad index");
+ /* Set up object kind gcj-style indirect descriptor. */
+ GC_gcjobjfreelist = (ptr_t *)GC_new_free_list_inner();
+ if (ignore_gcj_info) {
+ /* Use a simple length-based descriptor, thus forcing a fully */
+ /* conservative scan. */
+ GC_gcj_kind = GC_new_kind_inner((void **)GC_gcjobjfreelist,
+ (0 | GC_DS_LENGTH),
+ TRUE, TRUE);
+ } else {
+ GC_gcj_kind = GC_new_kind_inner(
+ (void **)GC_gcjobjfreelist,
+ (((word)(-MARK_DESCR_OFFSET - GC_INDIR_PER_OBJ_BIAS))
+ | GC_DS_PER_OBJECT),
+ FALSE, TRUE);
+ }
+ /* Set up object kind for objects that require mark proc call. */
+ if (ignore_gcj_info) {
+ GC_gcj_debug_kind = GC_gcj_kind;
+ GC_gcjdebugobjfreelist = GC_gcjobjfreelist;
+ } else {
+ GC_gcjdebugobjfreelist = (ptr_t *)GC_new_free_list_inner();
+ GC_gcj_debug_kind = GC_new_kind_inner(
+ (void **)GC_gcjdebugobjfreelist,
+ GC_MAKE_PROC(mp_index,
+ 1 /* allocated with debug info */),
+ FALSE, TRUE);
+ }
+ UNLOCK();
+}
+
+void * GC_clear_stack(void *);
+
+#define GENERAL_MALLOC(lb,k) \
+ GC_clear_stack(GC_generic_malloc_inner((word)lb, k))
+
+#define GENERAL_MALLOC_IOP(lb,k) \
+ GC_clear_stack(GC_generic_malloc_inner_ignore_off_page(lb, k))
+
+/* We need a mechanism to release the lock and invoke finalizers. */
+/* We don't really have an opportunity to do this on a rarely executed */
+/* path on which the lock is not held. Thus we check at a */
+/* rarely executed point at which it is safe to release the lock. */
+/* We do this even where we could just call GC_INVOKE_FINALIZERS, */
+/* since it's probably cheaper and certainly more uniform. */
+/* FIXME - Consider doing the same elsewhere? */
+static void maybe_finalize()
+{
+ static int last_finalized_no = 0;
+
+ if (GC_gc_no == last_finalized_no) return;
+ if (!GC_is_initialized) return;
+ UNLOCK();
+ GC_INVOKE_FINALIZERS();
+ last_finalized_no = GC_gc_no;
+ LOCK();
+}
+
+/* Allocate an object, clear it, and store the pointer to the */
+/* type structure (vtable in gcj). */
+/* This adds a byte at the end of the object if GC_malloc would.*/
+#ifdef THREAD_LOCAL_ALLOC
+ void * GC_core_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr)
+#else
+ void * GC_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr)
+#endif
+{
+ ptr_t op;
+ ptr_t * opp;
+ word lg;
+ DCL_LOCK_STATE;
+
+ if(SMALL_OBJ(lb)) {
+ lg = GC_size_map[lb];
+ opp = &(GC_gcjobjfreelist[lg]);
+ LOCK();
+ op = *opp;
+ if(EXPECT(op == 0, 0)) {
+ maybe_finalize();
+ op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
+ if (0 == op) {
+ UNLOCK();
+ return(GC_oom_fn(lb));
+ }
+ } else {
+ *opp = obj_link(op);
+ GC_bytes_allocd += GRANULES_TO_BYTES(lg);
+ }
+ *(void **)op = ptr_to_struct_containing_descr;
+ GC_ASSERT(((void **)op)[1] == 0);
+ UNLOCK();
+ } else {
+ LOCK();
+ maybe_finalize();
+ op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
+ if (0 == op) {
+ UNLOCK();
+ return(GC_oom_fn(lb));
+ }
+ *(void **)op = ptr_to_struct_containing_descr;
+ UNLOCK();
+ }
+ return((void *) op);
+}
+
+/* Similar to GC_gcj_malloc, but add debug info. This is allocated */
+/* with GC_gcj_debug_kind. */
+void * GC_debug_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr,
+ GC_EXTRA_PARAMS)
+{
+ void * result;
+
+ /* We're careful to avoid extra calls, which could */
+ /* confuse the backtrace. */
+ LOCK();
+ maybe_finalize();
+ result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
+ if (result == 0) {
+ UNLOCK();
+ GC_err_printf("GC_debug_gcj_malloc(%ld, %p) returning NIL (",
+ (unsigned long)lb, ptr_to_struct_containing_descr);
+ GC_err_puts(s);
+ GC_err_printf(":%d)\n", i);
+ return(GC_oom_fn(lb));
+ }
+ *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
+ UNLOCK();
+ if (!GC_debugging_started) {
+ GC_start_debugging();
+ }
+ ADD_CALL_CHAIN(result, ra);
+ return (GC_store_debug_info(result, (word)lb, s, (word)i));
+}
+
+void * GC_gcj_malloc_ignore_off_page(size_t lb,
+ void * ptr_to_struct_containing_descr)
+{
+ ptr_t op;
+ ptr_t * opp;
+ word lg;
+ DCL_LOCK_STATE;
+
+ if(SMALL_OBJ(lb)) {
+ lg = GC_size_map[lb];
+ opp = &(GC_gcjobjfreelist[lg]);
+ LOCK();
+ if( (op = *opp) == 0 ) {
+ maybe_finalize();
+ op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
+ lg = GC_size_map[lb]; /* May have been uninitialized. */
+ } else {
+ *opp = obj_link(op);
+ GC_bytes_allocd += GRANULES_TO_BYTES(lg);
+ }
+ *(void **)op = ptr_to_struct_containing_descr;
+ UNLOCK();
+ } else {
+ LOCK();
+ maybe_finalize();
+ op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
+ if (0 != op) {
+ *(void **)op = ptr_to_struct_containing_descr;
+ }
+ UNLOCK();
+ }
+ return((void *) op);
+}
+
+#else
+
+char GC_no_gcj_support;
+
+#endif /* GC_GCJ_SUPPORT */
diff --git a/tools/build/v2/engine/boehm_gc/gcname.c b/tools/build/v2/engine/boehm_gc/gcname.c
new file mode 100644
index 0000000000..e2119d7996
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/gcname.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include "version.h"
+
+int main()
+{
+ if (GC_ALPHA_VERSION == GC_NOT_ALPHA) {
+ printf("gc%d.%d", GC_VERSION_MAJOR, GC_VERSION_MINOR);
+ } else {
+ printf("gc%d.%dalpha%d", GC_VERSION_MAJOR,
+ GC_VERSION_MINOR, GC_ALPHA_VERSION);
+ }
+ return 0;
+}
diff --git a/tools/build/v2/engine/boehm_gc/headers.c b/tools/build/v2/engine/boehm_gc/headers.c
new file mode 100644
index 0000000000..6b4eb84922
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/headers.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/*
+ * This implements:
+ * 1. allocation of heap block headers
+ * 2. A map from addresses to heap block addresses to heap block headers
+ *
+ * Access speed is crucial. We implement an index structure based on a 2
+ * level tree.
+ */
+
+# include "private/gc_priv.h"
+
+bottom_index * GC_all_bottom_indices = 0;
+ /* Pointer to first (lowest addr) */
+ /* bottom_index. */
+
+bottom_index * GC_all_bottom_indices_end = 0;
+ /* Pointer to last (highest addr) */
+ /* bottom_index. */
+
+/* Non-macro version of header location routine */
+hdr * GC_find_header(ptr_t h)
+{
+# ifdef HASH_TL
+ hdr * result;
+ GET_HDR(h, result);
+ return(result);
+# else
+ return(HDR_INNER(h));
+# endif
+}
+
+/* Handle a header cache miss. Returns a pointer to the */
+/* header corresponding to p, if p can possibly be a valid */
+/* object pointer, and 0 otherwise. */
+/* GUARANTEED to return 0 for a pointer past the first page */
+/* of an object unless both GC_all_interior_pointers is set */
+/* and p is in fact a valid object pointer. */
+#ifdef PRINT_BLACK_LIST
+ hdr * GC_header_cache_miss(ptr_t p, hdr_cache_entry *hce, ptr_t source)
+#else
+ hdr * GC_header_cache_miss(ptr_t p, hdr_cache_entry *hce)
+#endif
+{
+ hdr *hhdr;
+ HC_MISS();
+ GET_HDR(p, hhdr);
+ if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
+ if (GC_all_interior_pointers) {
+ if (hhdr != 0) {
+ ptr_t current = p;
+
+ current = (ptr_t)HBLKPTR(current);
+ do {
+ current = current - HBLKSIZE*(word)hhdr;
+ hhdr = HDR(current);
+ } while(IS_FORWARDING_ADDR_OR_NIL(hhdr));
+ /* current points to near the start of the large object */
+ if (hhdr -> hb_flags & IGNORE_OFF_PAGE
+ || HBLK_IS_FREE(hhdr))
+ return 0;
+ if (p - current >= (ptrdiff_t)(hhdr->hb_sz)) {
+ GC_ADD_TO_BLACK_LIST_NORMAL(p, source);
+ /* Pointer past the end of the block */
+ return 0;
+ }
+ } else {
+ GC_ADD_TO_BLACK_LIST_NORMAL(p, source);
+ }
+ return hhdr;
+ /* Pointers past the first page are probably too rare */
+ /* to add them to the cache. We don't. */
+ /* And correctness relies on the fact that we don't. */
+ } else {
+ if (hhdr == 0) {
+ GC_ADD_TO_BLACK_LIST_NORMAL(p, source);
+ }
+ return 0;
+ }
+ } else {
+ if (HBLK_IS_FREE(hhdr)) {
+ GC_ADD_TO_BLACK_LIST_NORMAL(p, source);
+ return 0;
+ } else {
+ hce -> block_addr = (word)(p) >> LOG_HBLKSIZE;
+ hce -> hce_hdr = hhdr;
+ return hhdr;
+ }
+ }
+}
+
+/* Routines to dynamically allocate collector data structures that will */
+/* never be freed. */
+
+static ptr_t scratch_free_ptr = 0;
+
+/* GC_scratch_last_end_ptr is end point of last obtained scratch area. */
+/* GC_scratch_end_ptr is end point of current scratch area. */
+
+ptr_t GC_scratch_alloc(size_t bytes)
+{
+ register ptr_t result = scratch_free_ptr;
+
+ bytes += GRANULE_BYTES-1;
+ bytes &= ~(GRANULE_BYTES-1);
+ scratch_free_ptr += bytes;
+ if (scratch_free_ptr <= GC_scratch_end_ptr) {
+ return(result);
+ }
+ {
+ word bytes_to_get = MINHINCR * HBLKSIZE;
+
+ if (bytes_to_get <= bytes) {
+ /* Undo the damage, and get memory directly */
+ bytes_to_get = bytes;
+# ifdef USE_MMAP
+ bytes_to_get += GC_page_size - 1;
+ bytes_to_get &= ~(GC_page_size - 1);
+# endif
+ result = (ptr_t)GET_MEM(bytes_to_get);
+ scratch_free_ptr -= bytes;
+ GC_scratch_last_end_ptr = result + bytes;
+ return(result);
+ }
+ result = (ptr_t)GET_MEM(bytes_to_get);
+ if (result == 0) {
+ if (GC_print_stats)
+ GC_printf("Out of memory - trying to allocate less\n");
+ scratch_free_ptr -= bytes;
+ bytes_to_get = bytes;
+# ifdef USE_MMAP
+ bytes_to_get += GC_page_size - 1;
+ bytes_to_get &= ~(GC_page_size - 1);
+# endif
+ return((ptr_t)GET_MEM(bytes_to_get));
+ }
+ scratch_free_ptr = result;
+ GC_scratch_end_ptr = scratch_free_ptr + bytes_to_get;
+ GC_scratch_last_end_ptr = GC_scratch_end_ptr;
+ return(GC_scratch_alloc(bytes));
+ }
+}
+
+static hdr * hdr_free_list = 0;
+
+/* Return an uninitialized header */
+static hdr * alloc_hdr(void)
+{
+ register hdr * result;
+
+ if (hdr_free_list == 0) {
+ result = (hdr *) GC_scratch_alloc((word)(sizeof(hdr)));
+ } else {
+ result = hdr_free_list;
+ hdr_free_list = (hdr *) (result -> hb_next);
+ }
+ return(result);
+}
+
+static void free_hdr(hdr * hhdr)
+{
+ hhdr -> hb_next = (struct hblk *) hdr_free_list;
+ hdr_free_list = hhdr;
+}
+
+#ifdef USE_HDR_CACHE
+ word GC_hdr_cache_hits = 0;
+ word GC_hdr_cache_misses = 0;
+#endif
+
+void GC_init_headers(void)
+{
+ register unsigned i;
+
+ GC_all_nils = (bottom_index *)GC_scratch_alloc((word)sizeof(bottom_index));
+ BZERO(GC_all_nils, sizeof(bottom_index));
+ for (i = 0; i < TOP_SZ; i++) {
+ GC_top_index[i] = GC_all_nils;
+ }
+}
+
+/* Make sure that there is a bottom level index block for address addr */
+/* Return FALSE on failure. */
+static GC_bool get_index(word addr)
+{
+ word hi = (word)(addr) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE);
+ bottom_index * r;
+ bottom_index * p;
+ bottom_index ** prev;
+ bottom_index *pi;
+
+# ifdef HASH_TL
+ word i = TL_HASH(hi);
+ bottom_index * old;
+
+ old = p = GC_top_index[i];
+ while(p != GC_all_nils) {
+ if (p -> key == hi) return(TRUE);
+ p = p -> hash_link;
+ }
+ r = (bottom_index*)GC_scratch_alloc((word)(sizeof (bottom_index)));
+ if (r == 0) return(FALSE);
+ BZERO(r, sizeof (bottom_index));
+ r -> hash_link = old;
+ GC_top_index[i] = r;
+# else
+ if (GC_top_index[hi] != GC_all_nils) return(TRUE);
+ r = (bottom_index*)GC_scratch_alloc((word)(sizeof (bottom_index)));
+ if (r == 0) return(FALSE);
+ GC_top_index[hi] = r;
+ BZERO(r, sizeof (bottom_index));
+# endif
+ r -> key = hi;
+ /* Add it to the list of bottom indices */
+ prev = &GC_all_bottom_indices; /* pointer to p */
+ pi = 0; /* bottom_index preceding p */
+ while ((p = *prev) != 0 && p -> key < hi) {
+ pi = p;
+ prev = &(p -> asc_link);
+ }
+ r -> desc_link = pi;
+ if (0 == p) {
+ GC_all_bottom_indices_end = r;
+ } else {
+ p -> desc_link = r;
+ }
+ r -> asc_link = p;
+ *prev = r;
+ return(TRUE);
+}
+
+/* Install a header for block h. */
+/* The header is uninitialized. */
+/* Returns the header or 0 on failure. */
+struct hblkhdr * GC_install_header(struct hblk *h)
+{
+ hdr * result;
+
+ if (!get_index((word) h)) return(0);
+ result = alloc_hdr();
+ SET_HDR(h, result);
+# ifdef USE_MUNMAP
+ result -> hb_last_reclaimed = (unsigned short)GC_gc_no;
+# endif
+ return(result);
+}
+
+/* Set up forwarding counts for block h of size sz */
+GC_bool GC_install_counts(struct hblk *h, size_t sz/* bytes */)
+{
+ struct hblk * hbp;
+ word i;
+
+ for (hbp = h; (char *)hbp < (char *)h + sz; hbp += BOTTOM_SZ) {
+ if (!get_index((word) hbp)) return(FALSE);
+ }
+ if (!get_index((word)h + sz - 1)) return(FALSE);
+ for (hbp = h + 1; (char *)hbp < (char *)h + sz; hbp += 1) {
+ i = HBLK_PTR_DIFF(hbp, h);
+ SET_HDR(hbp, (hdr *)(i > MAX_JUMP? MAX_JUMP : i));
+ }
+ return(TRUE);
+}
+
+/* Remove the header for block h */
+void GC_remove_header(struct hblk *h)
+{
+ hdr ** ha;
+
+ GET_HDR_ADDR(h, ha);
+ free_hdr(*ha);
+ *ha = 0;
+}
+
+/* Remove forwarding counts for h */
+void GC_remove_counts(struct hblk *h, size_t sz/* bytes */)
+{
+ register struct hblk * hbp;
+
+ for (hbp = h+1; (char *)hbp < (char *)h + sz; hbp += 1) {
+ SET_HDR(hbp, 0);
+ }
+}
+
+/* Apply fn to all allocated blocks */
+/*VARARGS1*/
+void GC_apply_to_all_blocks(void (*fn)(struct hblk *h, word client_data),
+ word client_data)
+{
+ signed_word j;
+ bottom_index * index_p;
+
+ for (index_p = GC_all_bottom_indices; index_p != 0;
+ index_p = index_p -> asc_link) {
+ for (j = BOTTOM_SZ-1; j >= 0;) {
+ if (!IS_FORWARDING_ADDR_OR_NIL(index_p->index[j])) {
+ if (!HBLK_IS_FREE(index_p->index[j])) {
+ (*fn)(((struct hblk *)
+ (((index_p->key << LOG_BOTTOM_SZ) + (word)j)
+ << LOG_HBLKSIZE)),
+ client_data);
+ }
+ j--;
+ } else if (index_p->index[j] == 0) {
+ j--;
+ } else {
+ j -= (signed_word)(index_p->index[j]);
+ }
+ }
+ }
+}
+
+/* Get the next valid block whose address is at least h */
+/* Return 0 if there is none. */
+struct hblk * GC_next_used_block(struct hblk *h)
+{
+ register bottom_index * bi;
+ register word j = ((word)h >> LOG_HBLKSIZE) & (BOTTOM_SZ-1);
+
+ GET_BI(h, bi);
+ if (bi == GC_all_nils) {
+ register word hi = (word)h >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE);
+ bi = GC_all_bottom_indices;
+ while (bi != 0 && bi -> key < hi) bi = bi -> asc_link;
+ j = 0;
+ }
+ while(bi != 0) {
+ while (j < BOTTOM_SZ) {
+ hdr * hhdr = bi -> index[j];
+ if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
+ j++;
+ } else {
+ if (!HBLK_IS_FREE(hhdr)) {
+ return((struct hblk *)
+ (((bi -> key << LOG_BOTTOM_SZ) + j)
+ << LOG_HBLKSIZE));
+ } else {
+ j += divHBLKSZ(hhdr -> hb_sz);
+ }
+ }
+ }
+ j = 0;
+ bi = bi -> asc_link;
+ }
+ return(0);
+}
+
+/* Get the last (highest address) block whose address is */
+/* at most h. Return 0 if there is none. */
+/* Unlike the above, this may return a free block. */
+struct hblk * GC_prev_block(struct hblk *h)
+{
+ register bottom_index * bi;
+ register signed_word j = ((word)h >> LOG_HBLKSIZE) & (BOTTOM_SZ-1);
+
+ GET_BI(h, bi);
+ if (bi == GC_all_nils) {
+ register word hi = (word)h >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE);
+ bi = GC_all_bottom_indices_end;
+ while (bi != 0 && bi -> key > hi) bi = bi -> desc_link;
+ j = BOTTOM_SZ - 1;
+ }
+ while(bi != 0) {
+ while (j >= 0) {
+ hdr * hhdr = bi -> index[j];
+ if (0 == hhdr) {
+ --j;
+ } else if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
+ j -= (signed_word)hhdr;
+ } else {
+ return((struct hblk *)
+ (((bi -> key << LOG_BOTTOM_SZ) + j)
+ << LOG_HBLKSIZE));
+ }
+ }
+ j = BOTTOM_SZ - 1;
+ bi = bi -> desc_link;
+ }
+ return(0);
+}
diff --git a/tools/build/v2/engine/boehm_gc/hpux_test_and_clear.s b/tools/build/v2/engine/boehm_gc/hpux_test_and_clear.s
new file mode 100644
index 0000000000..f09b211404
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/hpux_test_and_clear.s
@@ -0,0 +1,21 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT GC_test_and_clear,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+GC_test_and_clear
+ .PROC
+ .CALLINFO FRAME=0,NO_CALLS
+ .ENTRY
+ ldcw,co (%r26),%r28
+ bv,n 0(%r2)
+ .EXIT
+ .PROCEND
diff --git a/tools/build/v2/engine/boehm_gc/ia64_save_regs_in_stack.s b/tools/build/v2/engine/boehm_gc/ia64_save_regs_in_stack.s
new file mode 100644
index 0000000000..3b18c0841d
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/ia64_save_regs_in_stack.s
@@ -0,0 +1,12 @@
+ .text
+ .align 16
+ .global GC_save_regs_in_stack
+ .proc GC_save_regs_in_stack
+GC_save_regs_in_stack:
+ .body
+ flushrs
+ ;;
+ mov r8=ar.bsp
+ br.ret.sptk.few rp
+ .endp GC_save_regs_in_stack
+
diff --git a/tools/build/v2/engine/boehm_gc/if_mach.c b/tools/build/v2/engine/boehm_gc/if_mach.c
new file mode 100644
index 0000000000..d6e0a70d74
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/if_mach.c
@@ -0,0 +1,25 @@
+/* Conditionally execute a command based on machine and OS from gcconfig.h */
+
+# include "private/gcconfig.h"
+# include <stdio.h>
+# include <string.h>
+# include <unistd.h>
+
+int main(int argc, char **argv, char **envp)
+{
+ if (argc < 4) goto Usage;
+ if (strcmp(MACH_TYPE, argv[1]) != 0) return(0);
+ if (strcmp(OS_TYPE, "") != 0 && strcmp(argv[2], "") != 0
+ && strcmp(OS_TYPE, argv[2]) != 0) return(0);
+ fprintf(stderr, "^^^^Starting command^^^^\n");
+ fflush(stdout);
+ execvp(argv[3], argv+3);
+ perror("Couldn't execute");
+
+Usage:
+ fprintf(stderr, "Usage: %s mach_type os_type command\n", argv[0]);
+ fprintf(stderr, "Currently mach_type = %s, os_type = %s\n",
+ MACH_TYPE, OS_TYPE);
+ return(1);
+}
+
diff --git a/tools/build/v2/engine/boehm_gc/if_not_there.c b/tools/build/v2/engine/boehm_gc/if_not_there.c
new file mode 100644
index 0000000000..7af6fba4e0
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/if_not_there.c
@@ -0,0 +1,38 @@
+/* Conditionally execute a command based if the file argv[1] doesn't exist */
+/* Except for execvp, we stick to ANSI C. */
+# include "private/gcconfig.h"
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
+#ifdef __DJGPP__
+#include <dirent.h>
+#endif /* __DJGPP__ */
+
+int main(int argc, char **argv, char **envp)
+{
+ FILE * f;
+#ifdef __DJGPP__
+ DIR * d;
+#endif /* __DJGPP__ */
+ if (argc < 3) goto Usage;
+ if ((f = fopen(argv[1], "rb")) != 0
+ || (f = fopen(argv[1], "r")) != 0) {
+ fclose(f);
+ return(0);
+ }
+#ifdef __DJGPP__
+ if ((d = opendir(argv[1])) != 0) {
+ closedir(d);
+ return(0);
+ }
+#endif
+ printf("^^^^Starting command^^^^\n");
+ fflush(stdout);
+ execvp(argv[2], argv+2);
+ exit(1);
+
+Usage:
+ fprintf(stderr, "Usage: %s file_name command\n", argv[0]);
+ return(1);
+}
+
diff --git a/tools/build/v2/engine/boehm_gc/include/cord.h b/tools/build/v2/engine/boehm_gc/include/cord.h
new file mode 100644
index 0000000000..926089e86f
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/cord.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ * Author: Hans-J. Boehm (boehm@parc.xerox.com)
+ */
+/* Boehm, October 5, 1995 4:20 pm PDT */
+
+/*
+ * Cords are immutable character strings. A number of operations
+ * on long cords are much more efficient than their strings.h counterpart.
+ * In particular, concatenation takes constant time independent of the length
+ * of the arguments. (Cords are represented as trees, with internal
+ * nodes representing concatenation and leaves consisting of either C
+ * strings or a functional description of the string.)
+ *
+ * The following are reasonable applications of cords. They would perform
+ * unacceptably if C strings were used:
+ * - A compiler that produces assembly language output by repeatedly
+ * concatenating instructions onto a cord representing the output file.
+ * - A text editor that converts the input file to a cord, and then
+ * performs editing operations by producing a new cord representing
+ * the file after echa character change (and keeping the old ones in an
+ * edit history)
+ *
+ * For optimal performance, cords should be built by
+ * concatenating short sections.
+ * This interface is designed for maximum compatibility with C strings.
+ * ASCII NUL characters may be embedded in cords using CORD_from_fn.
+ * This is handled correctly, but CORD_to_char_star will produce a string
+ * with embedded NULs when given such a cord.
+ *
+ * This interface is fairly big, largely for performance reasons.
+ * The most basic constants and functions:
+ *
+ * CORD - the type of a cord;
+ * CORD_EMPTY - empty cord;
+ * CORD_len(cord) - length of a cord;
+ * CORD_cat(cord1,cord2) - concatenation of two cords;
+ * CORD_substr(cord, start, len) - substring (or subcord);
+ * CORD_pos i; CORD_FOR(i, cord) { ... CORD_pos_fetch(i) ... } -
+ * examine each character in a cord. CORD_pos_fetch(i) is the char.
+ * CORD_fetch(int i) - Retrieve i'th character (slowly).
+ * CORD_cmp(cord1, cord2) - compare two cords.
+ * CORD_from_file(FILE * f) - turn a read-only file into a cord.
+ * CORD_to_char_star(cord) - convert to C string.
+ * (Non-NULL C constant strings are cords.)
+ * CORD_printf (etc.) - cord version of printf. Use %r for cords.
+ */
+# ifndef CORD_H
+
+# define CORD_H
+# include <stddef.h>
+# include <stdio.h>
+/* Cords have type const char *. This is cheating quite a bit, and not */
+/* 100% portable. But it means that nonempty character string */
+/* constants may be used as cords directly, provided the string is */
+/* never modified in place. The empty cord is represented by, and */
+/* can be written as, 0. */
+
+typedef const char * CORD;
+
+/* An empty cord is always represented as nil */
+# define CORD_EMPTY 0
+
+/* Is a nonempty cord represented as a C string? */
+#define CORD_IS_STRING(s) (*(s) != '\0')
+
+/* Concatenate two cords. If the arguments are C strings, they may */
+/* not be subsequently altered. */
+CORD CORD_cat(CORD x, CORD y);
+
+/* Concatenate a cord and a C string with known length. Except for the */
+/* empty string case, this is a special case of CORD_cat. Since the */
+/* length is known, it can be faster. */
+/* The string y is shared with the resulting CORD. Hence it should */
+/* not be altered by the caller. */
+CORD CORD_cat_char_star(CORD x, const char * y, size_t leny);
+
+/* Compute the length of a cord */
+size_t CORD_len(CORD x);
+
+/* Cords may be represented by functions defining the ith character */
+typedef char (* CORD_fn)(size_t i, void * client_data);
+
+/* Turn a functional description into a cord. */
+CORD CORD_from_fn(CORD_fn fn, void * client_data, size_t len);
+
+/* Return the substring (subcord really) of x with length at most n, */
+/* starting at position i. (The initial character has position 0.) */
+CORD CORD_substr(CORD x, size_t i, size_t n);
+
+/* Return the argument, but rebalanced to allow more efficient */
+/* character retrieval, substring operations, and comparisons. */
+/* This is useful only for cords that were built using repeated */
+/* concatenation. Guarantees log time access to the result, unless */
+/* x was obtained through a large number of repeated substring ops */
+/* or the embedded functional descriptions take longer to evaluate. */
+/* May reallocate significant parts of the cord. The argument is not */
+/* modified; only the result is balanced. */
+CORD CORD_balance(CORD x);
+
+/* The following traverse a cord by applying a function to each */
+/* character. This is occasionally appropriate, especially where */
+/* speed is crucial. But, since C doesn't have nested functions, */
+/* clients of this sort of traversal are clumsy to write. Consider */
+/* the functions that operate on cord positions instead. */
+
+/* Function to iteratively apply to individual characters in cord. */
+typedef int (* CORD_iter_fn)(char c, void * client_data);
+
+/* Function to apply to substrings of a cord. Each substring is a */
+/* a C character string, not a general cord. */
+typedef int (* CORD_batched_iter_fn)(const char * s, void * client_data);
+# define CORD_NO_FN ((CORD_batched_iter_fn)0)
+
+/* Apply f1 to each character in the cord, in ascending order, */
+/* starting at position i. If */
+/* f2 is not CORD_NO_FN, then multiple calls to f1 may be replaced by */
+/* a single call to f2. The parameter f2 is provided only to allow */
+/* some optimization by the client. This terminates when the right */
+/* end of this string is reached, or when f1 or f2 return != 0. In the */
+/* latter case CORD_iter returns != 0. Otherwise it returns 0. */
+/* The specified value of i must be < CORD_len(x). */
+int CORD_iter5(CORD x, size_t i, CORD_iter_fn f1,
+ CORD_batched_iter_fn f2, void * client_data);
+
+/* A simpler version that starts at 0, and without f2: */
+int CORD_iter(CORD x, CORD_iter_fn f1, void * client_data);
+# define CORD_iter(x, f1, cd) CORD_iter5(x, 0, f1, CORD_NO_FN, cd)
+
+/* Similar to CORD_iter5, but end-to-beginning. No provisions for */
+/* CORD_batched_iter_fn. */
+int CORD_riter4(CORD x, size_t i, CORD_iter_fn f1, void * client_data);
+
+/* A simpler version that starts at the end: */
+int CORD_riter(CORD x, CORD_iter_fn f1, void * client_data);
+
+/* Functions that operate on cord positions. The easy way to traverse */
+/* cords. A cord position is logically a pair consisting of a cord */
+/* and an index into that cord. But it is much faster to retrieve a */
+/* charcter based on a position than on an index. Unfortunately, */
+/* positions are big (order of a few 100 bytes), so allocate them with */
+/* caution. */
+/* Things in cord_pos.h should be treated as opaque, except as */
+/* described below. Also note that */
+/* CORD_pos_fetch, CORD_next and CORD_prev have both macro and function */
+/* definitions. The former may evaluate their argument more than once. */
+# include "private/cord_pos.h"
+
+/*
+ Visible definitions from above:
+
+ typedef <OPAQUE but fairly big> CORD_pos[1];
+
+ * Extract the cord from a position:
+ CORD CORD_pos_to_cord(CORD_pos p);
+
+ * Extract the current index from a position:
+ size_t CORD_pos_to_index(CORD_pos p);
+
+ * Fetch the character located at the given position:
+ char CORD_pos_fetch(CORD_pos p);
+
+ * Initialize the position to refer to the given cord and index.
+ * Note that this is the most expensive function on positions:
+ void CORD_set_pos(CORD_pos p, CORD x, size_t i);
+
+ * Advance the position to the next character.
+ * P must be initialized and valid.
+ * Invalidates p if past end:
+ void CORD_next(CORD_pos p);
+
+ * Move the position to the preceding character.
+ * P must be initialized and valid.
+ * Invalidates p if past beginning:
+ void CORD_prev(CORD_pos p);
+
+ * Is the position valid, i.e. inside the cord?
+ int CORD_pos_valid(CORD_pos p);
+*/
+# define CORD_FOR(pos, cord) \
+ for (CORD_set_pos(pos, cord, 0); CORD_pos_valid(pos); CORD_next(pos))
+
+
+/* An out of memory handler to call. May be supplied by client. */
+/* Must not return. */
+extern void (* CORD_oom_fn)(void);
+
+/* Dump the representation of x to stdout in an implementation defined */
+/* manner. Intended for debugging only. */
+void CORD_dump(CORD x);
+
+/* The following could easily be implemented by the client. They are */
+/* provided in cordxtra.c for convenience. */
+
+/* Concatenate a character to the end of a cord. */
+CORD CORD_cat_char(CORD x, char c);
+
+/* Concatenate n cords. */
+CORD CORD_catn(int n, /* CORD */ ...);
+
+/* Return the character in CORD_substr(x, i, 1) */
+char CORD_fetch(CORD x, size_t i);
+
+/* Return < 0, 0, or > 0, depending on whether x < y, x = y, x > y */
+int CORD_cmp(CORD x, CORD y);
+
+/* A generalization that takes both starting positions for the */
+/* comparison, and a limit on the number of characters to be compared. */
+int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start, size_t len);
+
+/* Find the first occurrence of s in x at position start or later. */
+/* Return the position of the first character of s in x, or */
+/* CORD_NOT_FOUND if there is none. */
+size_t CORD_str(CORD x, size_t start, CORD s);
+
+/* Return a cord consisting of i copies of (possibly NUL) c. Dangerous */
+/* in conjunction with CORD_to_char_star. */
+/* The resulting representation takes constant space, independent of i. */
+CORD CORD_chars(char c, size_t i);
+# define CORD_nul(i) CORD_chars('\0', (i))
+
+/* Turn a file into cord. The file must be seekable. Its contents */
+/* must remain constant. The file may be accessed as an immediate */
+/* result of this call and/or as a result of subsequent accesses to */
+/* the cord. Short files are likely to be immediately read, but */
+/* long files are likely to be read on demand, possibly relying on */
+/* stdio for buffering. */
+/* We must have exclusive access to the descriptor f, i.e. we may */
+/* read it at any time, and expect the file pointer to be */
+/* where we left it. Normally this should be invoked as */
+/* CORD_from_file(fopen(...)) */
+/* CORD_from_file arranges to close the file descriptor when it is no */
+/* longer needed (e.g. when the result becomes inaccessible). */
+/* The file f must be such that ftell reflects the actual character */
+/* position in the file, i.e. the number of characters that can be */
+/* or were read with fread. On UNIX systems this is always true. On */
+/* MS Windows systems, f must be opened in binary mode. */
+CORD CORD_from_file(FILE * f);
+
+/* Equivalent to the above, except that the entire file will be read */
+/* and the file pointer will be closed immediately. */
+/* The binary mode restriction from above does not apply. */
+CORD CORD_from_file_eager(FILE * f);
+
+/* Equivalent to the above, except that the file will be read on demand.*/
+/* The binary mode restriction applies. */
+CORD CORD_from_file_lazy(FILE * f);
+
+/* Turn a cord into a C string. The result shares no structure with */
+/* x, and is thus modifiable. */
+char * CORD_to_char_star(CORD x);
+
+/* Turn a C string into a CORD. The C string is copied, and so may */
+/* subsequently be modified. */
+CORD CORD_from_char_star(const char *s);
+
+/* Identical to the above, but the result may share structure with */
+/* the argument and is thus not modifiable. */
+const char * CORD_to_const_char_star(CORD x);
+
+/* Write a cord to a file, starting at the current position. No */
+/* trailing NULs are newlines are added. */
+/* Returns EOF if a write error occurs, 1 otherwise. */
+int CORD_put(CORD x, FILE * f);
+
+/* "Not found" result for the following two functions. */
+# define CORD_NOT_FOUND ((size_t)(-1))
+
+/* A vague analog of strchr. Returns the position (an integer, not */
+/* a pointer) of the first occurrence of (char) c inside x at position */
+/* i or later. The value i must be < CORD_len(x). */
+size_t CORD_chr(CORD x, size_t i, int c);
+
+/* A vague analog of strrchr. Returns index of the last occurrence */
+/* of (char) c inside x at position i or earlier. The value i */
+/* must be < CORD_len(x). */
+size_t CORD_rchr(CORD x, size_t i, int c);
+
+
+/* The following are also not primitive, but are implemented in */
+/* cordprnt.c. They provide functionality similar to the ANSI C */
+/* functions with corresponding names, but with the following */
+/* additions and changes: */
+/* 1. A %r conversion specification specifies a CORD argument. Field */
+/* width, precision, etc. have the same semantics as for %s. */
+/* (Note that %c,%C, and %S were already taken.) */
+/* 2. The format string is represented as a CORD. */
+/* 3. CORD_sprintf and CORD_vsprintf assign the result through the 1st */ /* argument. Unlike their ANSI C versions, there is no need to guess */
+/* the correct buffer size. */
+/* 4. Most of the conversions are implement through the native */
+/* vsprintf. Hence they are usually no faster, and */
+/* idiosyncracies of the native printf are preserved. However, */
+/* CORD arguments to CORD_sprintf and CORD_vsprintf are NOT copied; */
+/* the result shares the original structure. This may make them */
+/* very efficient in some unusual applications. */
+/* The format string is copied. */
+/* All functions return the number of characters generated or -1 on */
+/* error. This complies with the ANSI standard, but is inconsistent */
+/* with some older implementations of sprintf. */
+
+/* The implementation of these is probably less portable than the rest */
+/* of this package. */
+
+#ifndef CORD_NO_IO
+
+#include <stdarg.h>
+
+int CORD_sprintf(CORD * out, CORD format, ...);
+int CORD_vsprintf(CORD * out, CORD format, va_list args);
+int CORD_fprintf(FILE * f, CORD format, ...);
+int CORD_vfprintf(FILE * f, CORD format, va_list args);
+int CORD_printf(CORD format, ...);
+int CORD_vprintf(CORD format, va_list args);
+
+#endif /* CORD_NO_IO */
+
+# endif /* CORD_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/ec.h b/tools/build/v2/engine/boehm_gc/include/ec.h
new file mode 100644
index 0000000000..c829b83ad1
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/ec.h
@@ -0,0 +1,70 @@
+# ifndef EC_H
+# define EC_H
+
+# ifndef CORD_H
+# include "cord.h"
+# endif
+
+/* Extensible cords are strings that may be destructively appended to. */
+/* They allow fast construction of cords from characters that are */
+/* being read from a stream. */
+/*
+ * A client might look like:
+ *
+ * {
+ * CORD_ec x;
+ * CORD result;
+ * char c;
+ * FILE *f;
+ *
+ * ...
+ * CORD_ec_init(x);
+ * while(...) {
+ * c = getc(f);
+ * ...
+ * CORD_ec_append(x, c);
+ * }
+ * result = CORD_balance(CORD_ec_to_cord(x));
+ *
+ * If a C string is desired as the final result, the call to CORD_balance
+ * may be replaced by a call to CORD_to_char_star.
+ */
+
+# ifndef CORD_BUFSZ
+# define CORD_BUFSZ 128
+# endif
+
+typedef struct CORD_ec_struct {
+ CORD ec_cord;
+ char * ec_bufptr;
+ char ec_buf[CORD_BUFSZ+1];
+} CORD_ec[1];
+
+/* This structure represents the concatenation of ec_cord with */
+/* ec_buf[0 ... (ec_bufptr-ec_buf-1)] */
+
+/* Flush the buffer part of the extended chord into ec_cord. */
+/* Note that this is almost the only real function, and it is */
+/* implemented in 6 lines in cordxtra.c */
+void CORD_ec_flush_buf(CORD_ec x);
+
+/* Convert an extensible cord to a cord. */
+# define CORD_ec_to_cord(x) (CORD_ec_flush_buf(x), (x)[0].ec_cord)
+
+/* Initialize an extensible cord. */
+# define CORD_ec_init(x) ((x)[0].ec_cord = 0, (x)[0].ec_bufptr = (x)[0].ec_buf)
+
+/* Append a character to an extensible cord. */
+# define CORD_ec_append(x, c) \
+ { \
+ if ((x)[0].ec_bufptr == (x)[0].ec_buf + CORD_BUFSZ) { \
+ CORD_ec_flush_buf(x); \
+ } \
+ *((x)[0].ec_bufptr)++ = (c); \
+ }
+
+/* Append a cord to an extensible cord. Structure remains shared with */
+/* original. */
+void CORD_ec_append_cord(CORD_ec x, CORD s);
+
+# endif /* EC_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/gc.h b/tools/build/v2/engine/boehm_gc/include/gc.h
new file mode 100644
index 0000000000..cc950888f0
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc.h
@@ -0,0 +1,1139 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright 1999 by Hewlett-Packard Company. All rights reserved.
+ * Copyright (C) 2007 Free Software Foundation, Inc
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/*
+ * Note that this defines a large number of tuning hooks, which can
+ * safely be ignored in nearly all cases. For normal use it suffices
+ * to call only GC_MALLOC and perhaps GC_REALLOC.
+ * For better performance, also look at GC_MALLOC_ATOMIC, and
+ * GC_enable_incremental. If you need an action to be performed
+ * immediately before an object is collected, look at GC_register_finalizer.
+ * If you are using Solaris threads, look at the end of this file.
+ * Everything else is best ignored unless you encounter performance
+ * problems.
+ */
+
+#ifndef _GC_H
+
+# define _GC_H
+
+# include "gc_config_macros.h"
+
+# ifdef __cplusplus
+ extern "C" {
+# endif
+
+
+/* Define word and signed_word to be unsigned and signed types of the */
+/* size as char * or void *. There seems to be no way to do this */
+/* even semi-portably. The following is probably no better/worse */
+/* than almost anything else. */
+/* The ANSI standard suggests that size_t and ptr_diff_t might be */
+/* better choices. But those had incorrect definitions on some older */
+/* systems. Notably "typedef int size_t" is WRONG. */
+#ifndef _WIN64
+ typedef unsigned long GC_word;
+ typedef long GC_signed_word;
+#else
+ /* Win64 isn't really supported yet, but this is the first step. And */
+ /* it might cause error messages to show up in more plausible places. */
+ /* This needs basetsd.h, which is included by windows.h. */
+ typedef unsigned long long GC_word;
+ typedef long long GC_signed_word;
+#endif
+
+/* Public read-only variables */
+
+GC_API GC_word GC_gc_no;/* Counter incremented per collection. */
+ /* Includes empty GCs at startup. */
+
+GC_API int GC_parallel; /* GC is parallelized for performance on */
+ /* multiprocessors. Currently set only */
+ /* implicitly if collector is built with */
+ /* -DPARALLEL_MARK and if either: */
+ /* Env variable GC_NPROC is set to > 1, or */
+ /* GC_NPROC is not set and this is an MP. */
+ /* If GC_parallel is set, incremental */
+ /* collection is only partially functional, */
+ /* and may not be desirable. */
+
+
+/* Public R/W variables */
+
+GC_API void * (*GC_oom_fn) (size_t bytes_requested);
+ /* When there is insufficient memory to satisfy */
+ /* an allocation request, we return */
+ /* (*GC_oom_fn)(). By default this just */
+ /* returns 0. */
+ /* If it returns, it must return 0 or a valid */
+ /* pointer to a previously allocated heap */
+ /* object. */
+
+GC_API int GC_find_leak;
+ /* Do not actually garbage collect, but simply */
+ /* report inaccessible memory that was not */
+ /* deallocated with GC_free. Initial value */
+ /* is determined by FIND_LEAK macro. */
+
+GC_API int GC_all_interior_pointers;
+ /* Arrange for pointers to object interiors to */
+ /* be recognized as valid. May not be changed */
+ /* after GC initialization. */
+ /* Initial value is determined by */
+ /* -DALL_INTERIOR_POINTERS. */
+ /* Unless DONT_ADD_BYTE_AT_END is defined, this */
+ /* also affects whether sizes are increased by */
+ /* at least a byte to allow "off the end" */
+ /* pointer recognition. */
+ /* MUST BE 0 or 1. */
+
+GC_API int GC_finalize_on_demand;
+ /* If nonzero, finalizers will only be run in */
+ /* response to an explicit GC_invoke_finalizers */
+ /* call. The default is determined by whether */
+ /* the FINALIZE_ON_DEMAND macro is defined */
+ /* when the collector is built. */
+
+GC_API int GC_java_finalization;
+ /* Mark objects reachable from finalizable */
+ /* objects in a separate postpass. This makes */
+ /* it a bit safer to use non-topologically- */
+ /* ordered finalization. Default value is */
+ /* determined by JAVA_FINALIZATION macro. */
+ /* Enables register_finalizer_unreachable to */
+ /* work correctly. */
+
+GC_API void (* GC_finalizer_notifier)(void);
+ /* Invoked by the collector when there are */
+ /* objects to be finalized. Invoked at most */
+ /* once per GC cycle. Never invoked unless */
+ /* GC_finalize_on_demand is set. */
+ /* Typically this will notify a finalization */
+ /* thread, which will call GC_invoke_finalizers */
+ /* in response. */
+
+GC_API int GC_dont_gc; /* != 0 ==> Dont collect. In versions 6.2a1+, */
+ /* this overrides explicit GC_gcollect() calls. */
+ /* Used as a counter, so that nested enabling */
+ /* and disabling work correctly. Should */
+ /* normally be updated with GC_enable() and */
+ /* GC_disable() calls. */
+ /* Direct assignment to GC_dont_gc is */
+ /* deprecated. */
+
+GC_API int GC_dont_expand;
+ /* Dont expand heap unless explicitly requested */
+ /* or forced to. */
+
+GC_API int GC_use_entire_heap;
+ /* Causes the nonincremental collector to use the */
+ /* entire heap before collecting. This was the only */
+ /* option for GC versions < 5.0. This sometimes */
+ /* results in more large block fragmentation, since */
+ /* very larg blocks will tend to get broken up */
+ /* during each GC cycle. It is likely to result in a */
+ /* larger working set, but lower collection */
+ /* frequencies, and hence fewer instructions executed */
+ /* in the collector. */
+
+GC_API int GC_full_freq; /* Number of partial collections between */
+ /* full collections. Matters only if */
+ /* GC_incremental is set. */
+ /* Full collections are also triggered if */
+ /* the collector detects a substantial */
+ /* increase in the number of in-use heap */
+ /* blocks. Values in the tens are now */
+ /* perfectly reasonable, unlike for */
+ /* earlier GC versions. */
+
+GC_API GC_word GC_non_gc_bytes;
+ /* Bytes not considered candidates for collection. */
+ /* Used only to control scheduling of collections. */
+ /* Updated by GC_malloc_uncollectable and GC_free. */
+ /* Wizards only. */
+
+GC_API int GC_no_dls;
+ /* Don't register dynamic library data segments. */
+ /* Wizards only. Should be used only if the */
+ /* application explicitly registers all roots. */
+ /* In Microsoft Windows environments, this will */
+ /* usually also prevent registration of the */
+ /* main data segment as part of the root set. */
+
+GC_API GC_word GC_free_space_divisor;
+ /* We try to make sure that we allocate at */
+ /* least N/GC_free_space_divisor bytes between */
+ /* collections, where N is twice the number */
+ /* of traced bytes, plus the number of untraced */
+ /* bytes (bytes in "atomic" objects), plus */
+ /* a rough estimate of the root set size. */
+ /* N approximates GC tracing work per GC. */
+ /* Initially, GC_free_space_divisor = 3. */
+ /* Increasing its value will use less space */
+ /* but more collection time. Decreasing it */
+ /* will appreciably decrease collection time */
+ /* at the expense of space. */
+
+GC_API GC_word GC_max_retries;
+ /* The maximum number of GCs attempted before */
+ /* reporting out of memory after heap */
+ /* expansion fails. Initially 0. */
+
+
+GC_API char *GC_stackbottom; /* Cool end of user stack. */
+ /* May be set in the client prior to */
+ /* calling any GC_ routines. This */
+ /* avoids some overhead, and */
+ /* potentially some signals that can */
+ /* confuse debuggers. Otherwise the */
+ /* collector attempts to set it */
+ /* automatically. */
+ /* For multithreaded code, this is the */
+ /* cold end of the stack for the */
+ /* primordial thread. */
+
+GC_API int GC_dont_precollect; /* Don't collect as part of */
+ /* initialization. Should be set only */
+ /* if the client wants a chance to */
+ /* manually initialize the root set */
+ /* before the first collection. */
+ /* Interferes with blacklisting. */
+ /* Wizards only. */
+
+GC_API unsigned long GC_time_limit;
+ /* If incremental collection is enabled, */
+ /* We try to terminate collections */
+ /* after this many milliseconds. Not a */
+ /* hard time bound. Setting this to */
+ /* GC_TIME_UNLIMITED will essentially */
+ /* disable incremental collection while */
+ /* leaving generational collection */
+ /* enabled. */
+# define GC_TIME_UNLIMITED 999999
+ /* Setting GC_time_limit to this value */
+ /* will disable the "pause time exceeded"*/
+ /* tests. */
+
+/* Public procedures */
+
+/* Initialize the collector. This is only required when using thread-local
+ * allocation, since unlike the regular allocation routines, GC_local_malloc
+ * is not self-initializing. If you use GC_local_malloc you should arrange
+ * to call this somehow (e.g. from a constructor) before doing any allocation.
+ * For win32 threads, it needs to be called explicitly.
+ */
+GC_API void GC_init(void);
+
+/*
+ * general purpose allocation routines, with roughly malloc calling conv.
+ * The atomic versions promise that no relevant pointers are contained
+ * in the object. The nonatomic versions guarantee that the new object
+ * is cleared. GC_malloc_stubborn promises that no changes to the object
+ * will occur after GC_end_stubborn_change has been called on the
+ * result of GC_malloc_stubborn. GC_malloc_uncollectable allocates an object
+ * that is scanned for pointers to collectable objects, but is not itself
+ * collectable. The object is scanned even if it does not appear to
+ * be reachable. GC_malloc_uncollectable and GC_free called on the resulting
+ * object implicitly update GC_non_gc_bytes appropriately.
+ *
+ * Note that the GC_malloc_stubborn support is stubbed out by default
+ * starting in 6.0. GC_malloc_stubborn is an alias for GC_malloc unless
+ * the collector is built with STUBBORN_ALLOC defined.
+ */
+GC_API void * GC_malloc(size_t size_in_bytes);
+GC_API void * GC_malloc_atomic(size_t size_in_bytes);
+GC_API char * GC_strdup (const char *str);
+GC_API void * GC_malloc_uncollectable(size_t size_in_bytes);
+GC_API void * GC_malloc_stubborn(size_t size_in_bytes);
+
+/* The following is only defined if the library has been suitably */
+/* compiled: */
+GC_API void * GC_malloc_atomic_uncollectable(size_t size_in_bytes);
+
+/* Explicitly deallocate an object. Dangerous if used incorrectly. */
+/* Requires a pointer to the base of an object. */
+/* If the argument is stubborn, it should not be changeable when freed. */
+/* An object should not be enable for finalization when it is */
+/* explicitly deallocated. */
+/* GC_free(0) is a no-op, as required by ANSI C for free. */
+GC_API void GC_free(void * object_addr);
+
+/*
+ * Stubborn objects may be changed only if the collector is explicitly informed.
+ * The collector is implicitly informed of coming change when such
+ * an object is first allocated. The following routines inform the
+ * collector that an object will no longer be changed, or that it will
+ * once again be changed. Only nonNIL pointer stores into the object
+ * are considered to be changes. The argument to GC_end_stubborn_change
+ * must be exacly the value returned by GC_malloc_stubborn or passed to
+ * GC_change_stubborn. (In the second case it may be an interior pointer
+ * within 512 bytes of the beginning of the objects.)
+ * There is a performance penalty for allowing more than
+ * one stubborn object to be changed at once, but it is acceptable to
+ * do so. The same applies to dropping stubborn objects that are still
+ * changeable.
+ */
+GC_API void GC_change_stubborn(void *);
+GC_API void GC_end_stubborn_change(void *);
+
+/* Return a pointer to the base (lowest address) of an object given */
+/* a pointer to a location within the object. */
+/* I.e. map an interior pointer to the corresponding bas pointer. */
+/* Note that with debugging allocation, this returns a pointer to the */
+/* actual base of the object, i.e. the debug information, not to */
+/* the base of the user object. */
+/* Return 0 if displaced_pointer doesn't point to within a valid */
+/* object. */
+/* Note that a deallocated object in the garbage collected heap */
+/* may be considered valid, even if it has been deallocated with */
+/* GC_free. */
+GC_API void * GC_base(void * displaced_pointer);
+
+/* Given a pointer to the base of an object, return its size in bytes. */
+/* The returned size may be slightly larger than what was originally */
+/* requested. */
+GC_API size_t GC_size(void * object_addr);
+
+/* For compatibility with C library. This is occasionally faster than */
+/* a malloc followed by a bcopy. But if you rely on that, either here */
+/* or with the standard C library, your code is broken. In my */
+/* opinion, it shouldn't have been invented, but now we're stuck. -HB */
+/* The resulting object has the same kind as the original. */
+/* If the argument is stubborn, the result will have changes enabled. */
+/* It is an error to have changes enabled for the original object. */
+/* Follows ANSI comventions for NULL old_object. */
+GC_API void * GC_realloc(void * old_object, size_t new_size_in_bytes);
+
+/* Explicitly increase the heap size. */
+/* Returns 0 on failure, 1 on success. */
+GC_API int GC_expand_hp(size_t number_of_bytes);
+
+/* Limit the heap size to n bytes. Useful when you're debugging, */
+/* especially on systems that don't handle running out of memory well. */
+/* n == 0 ==> unbounded. This is the default. */
+GC_API void GC_set_max_heap_size(GC_word n);
+
+/* Inform the collector that a certain section of statically allocated */
+/* memory contains no pointers to garbage collected memory. Thus it */
+/* need not be scanned. This is sometimes important if the application */
+/* maps large read/write files into the address space, which could be */
+/* mistaken for dynamic library data segments on some systems. */
+GC_API void GC_exclude_static_roots(void * low_address,
+ void * high_address_plus_1);
+
+/* Clear the set of root segments. Wizards only. */
+GC_API void GC_clear_roots(void);
+
+/* Add a root segment. Wizards only. */
+GC_API void GC_add_roots(void * low_address, void * high_address_plus_1);
+
+/* Remove a root segment. Wizards only. */
+GC_API void GC_remove_roots(void * low_address, void * high_address_plus_1);
+
+/* Add a displacement to the set of those considered valid by the */
+/* collector. GC_register_displacement(n) means that if p was returned */
+/* by GC_malloc, then (char *)p + n will be considered to be a valid */
+/* pointer to p. N must be small and less than the size of p. */
+/* (All pointers to the interior of objects from the stack are */
+/* considered valid in any case. This applies to heap objects and */
+/* static data.) */
+/* Preferably, this should be called before any other GC procedures. */
+/* Calling it later adds to the probability of excess memory */
+/* retention. */
+/* This is a no-op if the collector has recognition of */
+/* arbitrary interior pointers enabled, which is now the default. */
+GC_API void GC_register_displacement(size_t n);
+
+/* The following version should be used if any debugging allocation is */
+/* being done. */
+GC_API void GC_debug_register_displacement(size_t n);
+
+/* Explicitly trigger a full, world-stop collection. */
+GC_API void GC_gcollect(void);
+
+/* Trigger a full world-stopped collection. Abort the collection if */
+/* and when stop_func returns a nonzero value. Stop_func will be */
+/* called frequently, and should be reasonably fast. This works even */
+/* if virtual dirty bits, and hence incremental collection is not */
+/* available for this architecture. Collections can be aborted faster */
+/* than normal pause times for incremental collection. However, */
+/* aborted collections do no useful work; the next collection needs */
+/* to start from the beginning. */
+/* Return 0 if the collection was aborted, 1 if it succeeded. */
+typedef int (* GC_stop_func)(void);
+GC_API int GC_try_to_collect(GC_stop_func stop_func);
+
+/* Return the number of bytes in the heap. Excludes collector private */
+/* data structures. Includes empty blocks and fragmentation loss. */
+/* Includes some pages that were allocated but never written. */
+GC_API size_t GC_get_heap_size(void);
+
+/* Return a lower bound on the number of free bytes in the heap. */
+GC_API size_t GC_get_free_bytes(void);
+
+/* Return the number of bytes allocated since the last collection. */
+GC_API size_t GC_get_bytes_since_gc(void);
+
+/* Return the total number of bytes allocated in this process. */
+/* Never decreases, except due to wrapping. */
+GC_API size_t GC_get_total_bytes(void);
+
+/* Disable garbage collection. Even GC_gcollect calls will be */
+/* ineffective. */
+GC_API void GC_disable(void);
+
+/* Reenable garbage collection. GC_disable() and GC_enable() calls */
+/* nest. Garbage collection is enabled if the number of calls to both */
+/* both functions is equal. */
+GC_API void GC_enable(void);
+
+/* Enable incremental/generational collection. */
+/* Not advisable unless dirty bits are */
+/* available or most heap objects are */
+/* pointerfree(atomic) or immutable. */
+/* Don't use in leak finding mode. */
+/* Ignored if GC_dont_gc is true. */
+/* Only the generational piece of this is */
+/* functional if GC_parallel is TRUE */
+/* or if GC_time_limit is GC_TIME_UNLIMITED. */
+/* Causes GC_local_gcj_malloc() to revert to */
+/* locked allocation. Must be called */
+/* before any GC_local_gcj_malloc() calls. */
+/* For best performance, should be called as early as possible. */
+/* On some platforms, calling it later may have adverse effects.*/
+/* Safe to call before GC_INIT(). Includes a GC_init() call. */
+GC_API void GC_enable_incremental(void);
+
+/* Does incremental mode write-protect pages? Returns zero or */
+/* more of the following, or'ed together: */
+#define GC_PROTECTS_POINTER_HEAP 1 /* May protect non-atomic objs. */
+#define GC_PROTECTS_PTRFREE_HEAP 2
+#define GC_PROTECTS_STATIC_DATA 4 /* Currently never. */
+#define GC_PROTECTS_STACK 8 /* Probably impractical. */
+
+#define GC_PROTECTS_NONE 0
+GC_API int GC_incremental_protection_needs(void);
+
+/* Perform some garbage collection work, if appropriate. */
+/* Return 0 if there is no more work to be done. */
+/* Typically performs an amount of work corresponding roughly */
+/* to marking from one page. May do more work if further */
+/* progress requires it, e.g. if incremental collection is */
+/* disabled. It is reasonable to call this in a wait loop */
+/* until it returns 0. */
+GC_API int GC_collect_a_little(void);
+
+/* Allocate an object of size lb bytes. The client guarantees that */
+/* as long as the object is live, it will be referenced by a pointer */
+/* that points to somewhere within the first 256 bytes of the object. */
+/* (This should normally be declared volatile to prevent the compiler */
+/* from invalidating this assertion.) This routine is only useful */
+/* if a large array is being allocated. It reduces the chance of */
+/* accidentally retaining such an array as a result of scanning an */
+/* integer that happens to be an address inside the array. (Actually, */
+/* it reduces the chance of the allocator not finding space for such */
+/* an array, since it will try hard to avoid introducing such a false */
+/* reference.) On a SunOS 4.X or MS Windows system this is recommended */
+/* for arrays likely to be larger than 100K or so. For other systems, */
+/* or if the collector is not configured to recognize all interior */
+/* pointers, the threshold is normally much higher. */
+GC_API void * GC_malloc_ignore_off_page(size_t lb);
+GC_API void * GC_malloc_atomic_ignore_off_page(size_t lb);
+
+#if defined(__sgi) && !defined(__GNUC__) && _COMPILER_VERSION >= 720
+# define GC_ADD_CALLER
+# define GC_RETURN_ADDR (GC_word)__return_address
+#endif
+
+#if defined(__linux__) || defined(__GLIBC__)
+# include <features.h>
+# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
+ && !defined(__ia64__)
+# ifndef GC_HAVE_BUILTIN_BACKTRACE
+# define GC_HAVE_BUILTIN_BACKTRACE
+# endif
+# endif
+# if defined(__i386__) || defined(__x86_64__)
+# define GC_CAN_SAVE_CALL_STACKS
+# endif
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1200 /* version 12.0+ (MSVC 6.0+) */ \
+ && !defined(_AMD64_)
+# ifndef GC_HAVE_NO_BUILTIN_BACKTRACE
+# define GC_HAVE_BUILTIN_BACKTRACE
+# endif
+#endif
+
+#if defined(GC_HAVE_BUILTIN_BACKTRACE) && !defined(GC_CAN_SAVE_CALL_STACKS)
+# define GC_CAN_SAVE_CALL_STACKS
+#endif
+
+#if defined(__sparc__)
+# define GC_CAN_SAVE_CALL_STACKS
+#endif
+
+/* If we're on an a platform on which we can't save call stacks, but */
+/* gcc is normally used, we go ahead and define GC_ADD_CALLER. */
+/* We make this decision independent of whether gcc is actually being */
+/* used, in order to keep the interface consistent, and allow mixing */
+/* of compilers. */
+/* This may also be desirable if it is possible but expensive to */
+/* retrieve the call chain. */
+#if (defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) \
+ || defined(__FreeBSD__) || defined(__DragonFly__)) & !defined(GC_CAN_SAVE_CALL_STACKS)
+# define GC_ADD_CALLER
+# if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
+ /* gcc knows how to retrieve return address, but we don't know */
+ /* how to generate call stacks. */
+# define GC_RETURN_ADDR (GC_word)__builtin_return_address(0)
+# else
+ /* Just pass 0 for gcc compatibility. */
+# define GC_RETURN_ADDR 0
+# endif
+#endif
+
+#ifdef GC_ADD_CALLER
+# define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__
+# define GC_EXTRA_PARAMS GC_word ra, const char * s, int i
+#else
+# define GC_EXTRAS __FILE__, __LINE__
+# define GC_EXTRA_PARAMS const char * s, int i
+#endif
+
+/* Debugging (annotated) allocation. GC_gcollect will check */
+/* objects allocated in this way for overwrites, etc. */
+GC_API void * GC_debug_malloc(size_t size_in_bytes, GC_EXTRA_PARAMS);
+GC_API void * GC_debug_malloc_atomic(size_t size_in_bytes, GC_EXTRA_PARAMS);
+GC_API char * GC_debug_strdup(const char *str, GC_EXTRA_PARAMS);
+GC_API void * GC_debug_malloc_uncollectable
+ (size_t size_in_bytes, GC_EXTRA_PARAMS);
+GC_API void * GC_debug_malloc_stubborn
+ (size_t size_in_bytes, GC_EXTRA_PARAMS);
+GC_API void * GC_debug_malloc_ignore_off_page
+ (size_t size_in_bytes, GC_EXTRA_PARAMS);
+GC_API void * GC_debug_malloc_atomic_ignore_off_page
+ (size_t size_in_bytes, GC_EXTRA_PARAMS);
+GC_API void GC_debug_free (void * object_addr);
+GC_API void * GC_debug_realloc
+ (void * old_object, size_t new_size_in_bytes, GC_EXTRA_PARAMS);
+GC_API void GC_debug_change_stubborn(void *);
+GC_API void GC_debug_end_stubborn_change(void *);
+
+/* Routines that allocate objects with debug information (like the */
+/* above), but just fill in dummy file and line number information. */
+/* Thus they can serve as drop-in malloc/realloc replacements. This */
+/* can be useful for two reasons: */
+/* 1) It allows the collector to be built with DBG_HDRS_ALL defined */
+/* even if some allocation calls come from 3rd party libraries */
+/* that can't be recompiled. */
+/* 2) On some platforms, the file and line information is redundant, */
+/* since it can be reconstructed from a stack trace. On such */
+/* platforms it may be more convenient not to recompile, e.g. for */
+/* leak detection. This can be accomplished by instructing the */
+/* linker to replace malloc/realloc with these. */
+GC_API void * GC_debug_malloc_replacement (size_t size_in_bytes);
+GC_API void * GC_debug_realloc_replacement
+ (void * object_addr, size_t size_in_bytes);
+
+# ifdef GC_DEBUG
+# define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS)
+# define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS)
+# define GC_STRDUP(s) GC_debug_strdup((s), GC_EXTRAS)
+# define GC_MALLOC_UNCOLLECTABLE(sz) \
+ GC_debug_malloc_uncollectable(sz, GC_EXTRAS)
+# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
+ GC_debug_malloc_ignore_off_page(sz, GC_EXTRAS)
+# define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \
+ GC_debug_malloc_atomic_ignore_off_page(sz, GC_EXTRAS)
+# define GC_REALLOC(old, sz) GC_debug_realloc(old, sz, GC_EXTRAS)
+# define GC_FREE(p) GC_debug_free(p)
+# define GC_REGISTER_FINALIZER(p, f, d, of, od) \
+ GC_debug_register_finalizer(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \
+ GC_debug_register_finalizer_ignore_self(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
+ GC_debug_register_finalizer_no_order(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
+ GC_debug_register_finalizer_unreachable(p, f, d, of, od)
+# define GC_MALLOC_STUBBORN(sz) GC_debug_malloc_stubborn(sz, GC_EXTRAS);
+# define GC_CHANGE_STUBBORN(p) GC_debug_change_stubborn(p)
+# define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p)
+# define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
+ GC_general_register_disappearing_link(link, GC_base(obj))
+# define GC_REGISTER_DISPLACEMENT(n) GC_debug_register_displacement(n)
+# else
+# define GC_MALLOC(sz) GC_malloc(sz)
+# define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz)
+# define GC_STRDUP(s) GC_strdup(s)
+# define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz)
+# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
+ GC_malloc_ignore_off_page(sz)
+# define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \
+ GC_malloc_atomic_ignore_off_page(sz)
+# define GC_REALLOC(old, sz) GC_realloc(old, sz)
+# define GC_FREE(p) GC_free(p)
+# define GC_REGISTER_FINALIZER(p, f, d, of, od) \
+ GC_register_finalizer(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \
+ GC_register_finalizer_ignore_self(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
+ GC_register_finalizer_no_order(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
+ GC_register_finalizer_unreachable(p, f, d, of, od)
+# define GC_MALLOC_STUBBORN(sz) GC_malloc_stubborn(sz)
+# define GC_CHANGE_STUBBORN(p) GC_change_stubborn(p)
+# define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p)
+# define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
+ GC_general_register_disappearing_link(link, obj)
+# define GC_REGISTER_DISPLACEMENT(n) GC_register_displacement(n)
+# endif
+/* The following are included because they are often convenient, and */
+/* reduce the chance for a misspecifed size argument. But calls may */
+/* expand to something syntactically incorrect if t is a complicated */
+/* type expression. */
+# define GC_NEW(t) (t *)GC_MALLOC(sizeof (t))
+# define GC_NEW_ATOMIC(t) (t *)GC_MALLOC_ATOMIC(sizeof (t))
+# define GC_NEW_STUBBORN(t) (t *)GC_MALLOC_STUBBORN(sizeof (t))
+# define GC_NEW_UNCOLLECTABLE(t) (t *)GC_MALLOC_UNCOLLECTABLE(sizeof (t))
+
+/* Finalization. Some of these primitives are grossly unsafe. */
+/* The idea is to make them both cheap, and sufficient to build */
+/* a safer layer, closer to Modula-3, Java, or PCedar finalization. */
+/* The interface represents my conclusions from a long discussion */
+/* with Alan Demers, Dan Greene, Carl Hauser, Barry Hayes, */
+/* Christian Jacobi, and Russ Atkinson. It's not perfect, and */
+/* probably nobody else agrees with it. Hans-J. Boehm 3/13/92 */
+typedef void (*GC_finalization_proc) (void * obj, void * client_data);
+
+GC_API void GC_register_finalizer(void * obj, GC_finalization_proc fn,
+ void * cd, GC_finalization_proc *ofn,
+ void * *ocd);
+GC_API void GC_debug_register_finalizer
+ (void * obj, GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void * *ocd);
+ /* When obj is no longer accessible, invoke */
+ /* (*fn)(obj, cd). If a and b are inaccessible, and */
+ /* a points to b (after disappearing links have been */
+ /* made to disappear), then only a will be */
+ /* finalized. (If this does not create any new */
+ /* pointers to b, then b will be finalized after the */
+ /* next collection.) Any finalizable object that */
+ /* is reachable from itself by following one or more */
+ /* pointers will not be finalized (or collected). */
+ /* Thus cycles involving finalizable objects should */
+ /* be avoided, or broken by disappearing links. */
+ /* All but the last finalizer registered for an object */
+ /* is ignored. */
+ /* Finalization may be removed by passing 0 as fn. */
+ /* Finalizers are implicitly unregistered just before */
+ /* they are invoked. */
+ /* The old finalizer and client data are stored in */
+ /* *ofn and *ocd. */
+ /* Fn is never invoked on an accessible object, */
+ /* provided hidden pointers are converted to real */
+ /* pointers only if the allocation lock is held, and */
+ /* such conversions are not performed by finalization */
+ /* routines. */
+ /* If GC_register_finalizer is aborted as a result of */
+ /* a signal, the object may be left with no */
+ /* finalization, even if neither the old nor new */
+ /* finalizer were NULL. */
+ /* Obj should be the nonNULL starting address of an */
+ /* object allocated by GC_malloc or friends. */
+ /* Note that any garbage collectable object referenced */
+ /* by cd will be considered accessible until the */
+ /* finalizer is invoked. */
+
+/* Another versions of the above follow. It ignores */
+/* self-cycles, i.e. pointers from a finalizable object to */
+/* itself. There is a stylistic argument that this is wrong, */
+/* but it's unavoidable for C++, since the compiler may */
+/* silently introduce these. It's also benign in that specific */
+/* case. And it helps if finalizable objects are split to */
+/* avoid cycles. */
+/* Note that cd will still be viewed as accessible, even if it */
+/* refers to the object itself. */
+GC_API void GC_register_finalizer_ignore_self
+ (void * obj, GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void * *ocd);
+GC_API void GC_debug_register_finalizer_ignore_self
+ (void * obj, GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void * *ocd);
+
+/* Another version of the above. It ignores all cycles. */
+/* It should probably only be used by Java implementations. */
+/* Note that cd will still be viewed as accessible, even if it */
+/* refers to the object itself. */
+GC_API void GC_register_finalizer_no_order
+ (void * obj, GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void * *ocd);
+GC_API void GC_debug_register_finalizer_no_order
+ (void * obj, GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void * *ocd);
+
+/* This is a special finalizer that is useful when an object's */
+/* finalizer must be run when the object is known to be no */
+/* longer reachable, not even from other finalizable objects. */
+/* It behaves like "normal" finalization, except that the */
+/* finalizer is not run while the object is reachable from */
+/* other objects specifying unordered finalization. */
+/* Effectively it allows an object referenced, possibly */
+/* indirectly, from an unordered finalizable object to override */
+/* the unordered finalization request. */
+/* This can be used in combination with finalizer_no_order so */
+/* as to release resources that must not be released while an */
+/* object can still be brought back to life by other */
+/* finalizers. */
+/* Only works if GC_java_finalization is set. Probably only */
+/* of interest when implementing a language that requires */
+/* unordered finalization (e.g. Java, C#). */
+GC_API void GC_register_finalizer_unreachable
+ (void * obj, GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void * *ocd);
+GC_API void GC_debug_register_finalizer_unreachable
+ (void * obj, GC_finalization_proc fn, void * cd,
+ GC_finalization_proc *ofn, void * *ocd);
+
+/* The following routine may be used to break cycles between */
+/* finalizable objects, thus causing cyclic finalizable */
+/* objects to be finalized in the correct order. Standard */
+/* use involves calling GC_register_disappearing_link(&p), */
+/* where p is a pointer that is not followed by finalization */
+/* code, and should not be considered in determining */
+/* finalization order. */
+GC_API int GC_register_disappearing_link(void * * link );
+ /* Link should point to a field of a heap allocated */
+ /* object obj. *link will be cleared when obj is */
+ /* found to be inaccessible. This happens BEFORE any */
+ /* finalization code is invoked, and BEFORE any */
+ /* decisions about finalization order are made. */
+ /* This is useful in telling the finalizer that */
+ /* some pointers are not essential for proper */
+ /* finalization. This may avoid finalization cycles. */
+ /* Note that obj may be resurrected by another */
+ /* finalizer, and thus the clearing of *link may */
+ /* be visible to non-finalization code. */
+ /* There's an argument that an arbitrary action should */
+ /* be allowed here, instead of just clearing a pointer. */
+ /* But this causes problems if that action alters, or */
+ /* examines connectivity. */
+ /* Returns 1 if link was already registered, 0 */
+ /* otherwise. */
+ /* Only exists for backward compatibility. See below: */
+
+GC_API int GC_general_register_disappearing_link (void * * link, void * obj);
+ /* A slight generalization of the above. *link is */
+ /* cleared when obj first becomes inaccessible. This */
+ /* can be used to implement weak pointers easily and */
+ /* safely. Typically link will point to a location */
+ /* holding a disguised pointer to obj. (A pointer */
+ /* inside an "atomic" object is effectively */
+ /* disguised.) In this way soft */
+ /* pointers are broken before any object */
+ /* reachable from them are finalized. Each link */
+ /* May be registered only once, i.e. with one obj */
+ /* value. This was added after a long email discussion */
+ /* with John Ellis. */
+ /* Obj must be a pointer to the first word of an object */
+ /* we allocated. It is unsafe to explicitly deallocate */
+ /* the object containing link. Explicitly deallocating */
+ /* obj may or may not cause link to eventually be */
+ /* cleared. */
+ /* This can be used to implement certain types of */
+ /* weak pointers. Note however that this generally */
+ /* requires that thje allocation lock is held (see */
+ /* GC_call_with_allock_lock() below) when the disguised */
+ /* pointer is accessed. Otherwise a strong pointer */
+ /* could be recreated between the time the collector */
+ /* decides to reclaim the object and the link is */
+ /* cleared. */
+
+GC_API int GC_unregister_disappearing_link (void * * link);
+ /* Returns 0 if link was not actually registered. */
+ /* Undoes a registration by either of the above two */
+ /* routines. */
+
+/* Returns !=0 if GC_invoke_finalizers has something to do. */
+GC_API int GC_should_invoke_finalizers(void);
+
+GC_API int GC_invoke_finalizers(void);
+ /* Run finalizers for all objects that are ready to */
+ /* be finalized. Return the number of finalizers */
+ /* that were run. Normally this is also called */
+ /* implicitly during some allocations. If */
+ /* GC-finalize_on_demand is nonzero, it must be called */
+ /* explicitly. */
+
+/* Explicitly tell the collector that an object is reachable */
+/* at a particular program point. This prevents the argument */
+/* pointer from being optimized away, even it is otherwise no */
+/* longer needed. It should have no visible effect in the */
+/* absence of finalizers or disappearing links. But it may be */
+/* needed to prevent finalizers from running while the */
+/* associated external resource is still in use. */
+/* The function is sometimes called keep_alive in other */
+/* settings. */
+# if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+# define GC_reachable_here(ptr) \
+ __asm__ volatile(" " : : "X"(ptr) : "memory");
+# else
+ GC_API void GC_noop1(GC_word x);
+# define GC_reachable_here(ptr) GC_noop1((GC_word)(ptr));
+#endif
+
+/* GC_set_warn_proc can be used to redirect or filter warning messages. */
+/* p may not be a NULL pointer. */
+typedef void (*GC_warn_proc) (char *msg, GC_word arg);
+GC_API GC_warn_proc GC_set_warn_proc(GC_warn_proc p);
+ /* Returns old warning procedure. */
+
+GC_API GC_word GC_set_free_space_divisor(GC_word value);
+ /* Set free_space_divisor. See above for definition. */
+ /* Returns old value. */
+
+/* The following is intended to be used by a higher level */
+/* (e.g. Java-like) finalization facility. It is expected */
+/* that finalization code will arrange for hidden pointers to */
+/* disappear. Otherwise objects can be accessed after they */
+/* have been collected. */
+/* Note that putting pointers in atomic objects or in */
+/* nonpointer slots of "typed" objects is equivalent to */
+/* disguising them in this way, and may have other advantages. */
+# if defined(I_HIDE_POINTERS) || defined(GC_I_HIDE_POINTERS)
+ typedef GC_word GC_hidden_pointer;
+# define HIDE_POINTER(p) (~(GC_hidden_pointer)(p))
+# define REVEAL_POINTER(p) ((void *)(HIDE_POINTER(p)))
+ /* Converting a hidden pointer to a real pointer requires verifying */
+ /* that the object still exists. This involves acquiring the */
+ /* allocator lock to avoid a race with the collector. */
+# endif /* I_HIDE_POINTERS */
+
+typedef void * (*GC_fn_type) (void * client_data);
+GC_API void * GC_call_with_alloc_lock (GC_fn_type fn, void * client_data);
+
+/* These routines are intended to explicitly notify the collector */
+/* of new threads. Often this is unnecessary because thread creation */
+/* is implicitly intercepted by the collector, using header-file */
+/* defines, or linker-based interception. In the long run the intent */
+/* is to always make redundant registration safe. In the short run, */
+/* this is being implemented a platform at a time. */
+/* The interface is complicated by the fact that we probably will not */
+/* ever be able to automatically determine the stack base for thread */
+/* stacks on all platforms. */
+
+/* Structure representing the base of a thread stack. On most */
+/* platforms this contains just a single address. */
+struct GC_stack_base {
+ void * mem_base; /* Base of memory stack. */
+# if defined(__ia64) || defined(__ia64__)
+ void * reg_base; /* Base of separate register stack. */
+# endif
+};
+
+typedef void * (*GC_stack_base_func)(struct GC_stack_base *sb, void *arg);
+
+/* Call a function with a stack base structure corresponding to */
+/* somewhere in the GC_call_with_stack_base frame. This often can */
+/* be used to provide a sufficiently accurate stack base. And we */
+/* implement it everywhere. */
+void * GC_call_with_stack_base(GC_stack_base_func fn, void *arg);
+
+/* Register the current thread, with the indicated stack base, as */
+/* a new thread whose stack(s) should be traced by the GC. If a */
+/* platform does not implicitly do so, this must be called before a */
+/* thread can allocate garbage collected memory, or assign pointers */
+/* to the garbage collected heap. Once registered, a thread will be */
+/* stopped during garbage collections. */
+/* Return codes: */
+#define GC_SUCCESS 0
+#define GC_DUPLICATE 1 /* Was already registered. */
+#define GC_NO_THREADS 2 /* No thread support in GC. */
+#define GC_UNIMPLEMENTED 3 /* Not yet implemented on this platform. */
+int GC_register_my_thread(struct GC_stack_base *);
+
+/* Unregister the current thread. The thread may no longer allocate */
+/* garbage collected memory or manipulate pointers to the */
+/* garbage collected heap after making this call. */
+/* Specifically, if it wants to return or otherwise communicate a */
+/* pointer to the garbage-collected heap to another thread, it must */
+/* do this before calling GC_unregister_my_thread, most probably */
+/* by saving it in a global data structure. */
+int GC_unregister_my_thread(void);
+
+/* Attempt to fill in the GC_stack_base structure with the stack base */
+/* for this thread. This appears to be required to implement anything */
+/* like the JNI AttachCurrentThread in an environment in which new */
+/* threads are not automatically registered with the collector. */
+/* It is also unfortunately hard to implement well on many platforms. */
+/* Returns GC_SUCCESS or GC_UNIMPLEMENTED. */
+int GC_get_stack_base(struct GC_stack_base *);
+
+/* The following routines are primarily intended for use with a */
+/* preprocessor which inserts calls to check C pointer arithmetic. */
+/* They indicate failure by invoking the corresponding _print_proc. */
+
+/* Check that p and q point to the same object. */
+/* Fail conspicuously if they don't. */
+/* Returns the first argument. */
+/* Succeeds if neither p nor q points to the heap. */
+/* May succeed if both p and q point to between heap objects. */
+GC_API void * GC_same_obj (void * p, void * q);
+
+/* Checked pointer pre- and post- increment operations. Note that */
+/* the second argument is in units of bytes, not multiples of the */
+/* object size. This should either be invoked from a macro, or the */
+/* call should be automatically generated. */
+GC_API void * GC_pre_incr (void * *p, size_t how_much);
+GC_API void * GC_post_incr (void * *p, size_t how_much);
+
+/* Check that p is visible */
+/* to the collector as a possibly pointer containing location. */
+/* If it isn't fail conspicuously. */
+/* Returns the argument in all cases. May erroneously succeed */
+/* in hard cases. (This is intended for debugging use with */
+/* untyped allocations. The idea is that it should be possible, though */
+/* slow, to add such a call to all indirect pointer stores.) */
+/* Currently useless for multithreaded worlds. */
+GC_API void * GC_is_visible (void * p);
+
+/* Check that if p is a pointer to a heap page, then it points to */
+/* a valid displacement within a heap object. */
+/* Fail conspicuously if this property does not hold. */
+/* Uninteresting with GC_all_interior_pointers. */
+/* Always returns its argument. */
+GC_API void * GC_is_valid_displacement (void * p);
+
+/* Explicitly dump the GC state. This is most often called from the */
+/* debugger, or by setting the GC_DUMP_REGULARLY environment variable, */
+/* but it may be useful to call it from client code during debugging. */
+void GC_dump(void);
+
+/* Safer, but slow, pointer addition. Probably useful mainly with */
+/* a preprocessor. Useful only for heap pointers. */
+#ifdef GC_DEBUG
+# define GC_PTR_ADD3(x, n, type_of_result) \
+ ((type_of_result)GC_same_obj((x)+(n), (x)))
+# define GC_PRE_INCR3(x, n, type_of_result) \
+ ((type_of_result)GC_pre_incr(&(x), (n)*sizeof(*x))
+# define GC_POST_INCR2(x, type_of_result) \
+ ((type_of_result)GC_post_incr(&(x), sizeof(*x))
+# ifdef __GNUC__
+# define GC_PTR_ADD(x, n) \
+ GC_PTR_ADD3(x, n, typeof(x))
+# define GC_PRE_INCR(x, n) \
+ GC_PRE_INCR3(x, n, typeof(x))
+# define GC_POST_INCR(x, n) \
+ GC_POST_INCR3(x, typeof(x))
+# else
+ /* We can't do this right without typeof, which ANSI */
+ /* decided was not sufficiently useful. Repeatedly */
+ /* mentioning the arguments seems too dangerous to be */
+ /* useful. So does not casting the result. */
+# define GC_PTR_ADD(x, n) ((x)+(n))
+# endif
+#else /* !GC_DEBUG */
+# define GC_PTR_ADD3(x, n, type_of_result) ((x)+(n))
+# define GC_PTR_ADD(x, n) ((x)+(n))
+# define GC_PRE_INCR3(x, n, type_of_result) ((x) += (n))
+# define GC_PRE_INCR(x, n) ((x) += (n))
+# define GC_POST_INCR2(x, n, type_of_result) ((x)++)
+# define GC_POST_INCR(x, n) ((x)++)
+#endif
+
+/* Safer assignment of a pointer to a nonstack location. */
+#ifdef GC_DEBUG
+# define GC_PTR_STORE(p, q) \
+ (*(void **)GC_is_visible(p) = GC_is_valid_displacement(q))
+#else /* !GC_DEBUG */
+# define GC_PTR_STORE(p, q) *((p) = (q))
+#endif
+
+/* Functions called to report pointer checking errors */
+GC_API void (*GC_same_obj_print_proc) (void * p, void * q);
+
+GC_API void (*GC_is_valid_displacement_print_proc) (void * p);
+
+GC_API void (*GC_is_visible_print_proc) (void * p);
+
+
+/* For pthread support, we generally need to intercept a number of */
+/* thread library calls. We do that here by macro defining them. */
+
+#if !defined(GC_USE_LD_WRAP) && \
+ (defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS))
+# include "gc_pthread_redirects.h"
+#endif
+
+# if defined(PCR) || defined(GC_SOLARIS_THREADS) || \
+ defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
+ /* Any flavor of threads. */
+/* This returns a list of objects, linked through their first */
+/* word. Its use can greatly reduce lock contention problems, since */
+/* the allocation lock can be acquired and released many fewer times. */
+/* It is used internally by gc_local_alloc.h, which provides a simpler */
+/* programming interface on Linux. */
+void * GC_malloc_many(size_t lb);
+#define GC_NEXT(p) (*(void * *)(p)) /* Retrieve the next element */
+ /* in returned list. */
+extern void GC_thr_init(void); /* Needed for Solaris/X86 ?? */
+
+#endif /* THREADS */
+
+/* Register a callback to control the scanning of dynamic libraries.
+ When the GC scans the static data of a dynamic library, it will
+ first call a user-supplied routine with filename of the library and
+ the address and length of the memory region. This routine should
+ return nonzero if that region should be scanned. */
+GC_API void
+GC_register_has_static_roots_callback
+ (int (*callback)(const char *, void *, size_t));
+
+
+#if defined(GC_WIN32_THREADS) && !defined(__CYGWIN32__) \
+ && !defined(__CYGWIN__) \
+ && !defined(GC_PTHREADS)
+
+#ifdef __cplusplus
+ } /* Including windows.h in an extern "C" context no longer works. */
+#endif
+
+# include <windows.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+ /*
+ * All threads must be created using GC_CreateThread or GC_beginthreadex,
+ * or must explicitly call GC_register_my_thread,
+ * so that they will be recorded in the thread table.
+ * For backwards compatibility, it is possible to build the GC
+ * with GC_DLL defined, and to call GC_use_DllMain().
+ * This implicitly registers all created threads, but appears to be
+ * less robust.
+ *
+ * Currently the collector expects all threads to fall through and
+ * terminate normally, or call GC_endthreadex() or GC_ExitThread,
+ * so that the thread is properly unregistered. (An explicit call
+ * to GC_unregister_my_thread() should also work, but risks unregistering
+ * the thread twice.)
+ */
+ GC_API HANDLE WINAPI GC_CreateThread(
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
+
+
+ GC_API uintptr_t GC_beginthreadex(
+ void *security, unsigned stack_size,
+ unsigned ( __stdcall *start_address )( void * ),
+ void *arglist, unsigned initflag, unsigned *thrdaddr);
+
+ GC_API void GC_endthreadex(unsigned retval);
+
+ GC_API void WINAPI GC_ExitThread(DWORD dwExitCode);
+
+# if defined(_WIN32_WCE)
+ /*
+ * win32_threads.c implements the real WinMain, which will start a new thread
+ * to call GC_WinMain after initializing the garbage collector.
+ */
+ GC_API int WINAPI GC_WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPWSTR lpCmdLine,
+ int nCmdShow );
+# ifndef GC_BUILD
+# define WinMain GC_WinMain
+# endif
+# endif /* defined(_WIN32_WCE) */
+
+ /*
+ * Use implicit thread registration via DllMain.
+ */
+GC_API void GC_use_DllMain(void);
+
+# define CreateThread GC_CreateThread
+# define ExitThread GC_ExitThread
+# define _beginthreadex GC_beginthreadex
+# define _endthreadex GC_endthreadex
+# define _beginthread { > "Please use _beginthreadex instead of _beginthread" < }
+
+#endif /* defined(GC_WIN32_THREADS) && !cygwin */
+
+ /*
+ * Fully portable code should call GC_INIT() from the main program
+ * before making any other GC_ calls. On most platforms this is a
+ * no-op and the collector self-initializes. But a number of platforms
+ * make that too hard.
+ * A GC_INIT call is required if the collector is built with THREAD_LOCAL_ALLOC
+ * defined and the initial allocation call is not to GC_malloc().
+ */
+#if defined(__CYGWIN32__) || defined (_AIX)
+ /*
+ * Similarly gnu-win32 DLLs need explicit initialization from
+ * the main program, as does AIX.
+ */
+# ifdef __CYGWIN32__
+ extern int _data_start__[];
+ extern int _data_end__[];
+ extern int _bss_start__[];
+ extern int _bss_end__[];
+# define GC_MAX(x,y) ((x) > (y) ? (x) : (y))
+# define GC_MIN(x,y) ((x) < (y) ? (x) : (y))
+# define GC_DATASTART ((void *) GC_MIN(_data_start__, _bss_start__))
+# define GC_DATAEND ((void *) GC_MAX(_data_end__, _bss_end__))
+# if defined(GC_DLL)
+# define GC_INIT() { GC_add_roots(GC_DATASTART, GC_DATAEND); \
+ GC_gcollect(); /* For blacklisting. */}
+# else
+ /* Main program init not required */
+# define GC_INIT() { GC_init(); }
+# endif
+# endif
+# if defined(_AIX)
+ extern int _data[], _end[];
+# define GC_DATASTART ((void *)((ulong)_data))
+# define GC_DATAEND ((void *)((ulong)_end))
+# define GC_INIT() { GC_add_roots(GC_DATASTART, GC_DATAEND); }
+# endif
+#else
+# define GC_INIT() { GC_init(); }
+#endif
+
+#if !defined(_WIN32_WCE) \
+ && ((defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \
+ || defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__))
+ /* win32S may not free all resources on process exit. */
+ /* This explicitly deallocates the heap. */
+ GC_API void GC_win32_free_heap ();
+#endif
+
+#if ( defined(_AMIGA) && !defined(GC_AMIGA_MAKINGLIB) )
+ /* Allocation really goes through GC_amiga_allocwrapper_do */
+# include "gc_amiga_redirects.h"
+#endif
+
+#if defined(GC_REDIRECT_TO_LOCAL) && !defined(GC_LOCAL_ALLOC_H)
+# include "gc_local_alloc.h"
+#endif
+
+#ifdef __cplusplus
+ } /* end of extern "C" */
+#endif
+
+#endif /* _GC_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/gc_allocator.h b/tools/build/v2/engine/boehm_gc/include/gc_allocator.h
new file mode 100644
index 0000000000..4f3117b3bd
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc_allocator.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 1996-1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * Copyright (c) 2002
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+/*
+ * This implements standard-conforming allocators that interact with
+ * the garbage collector. Gc_alloctor<T> allocates garbage-collectable
+ * objects of type T. Traceable_allocator<T> allocates objects that
+ * are not temselves garbage collected, but are scanned by the
+ * collector for pointers to collectable objects. Traceable_alloc
+ * should be used for explicitly managed STL containers that may
+ * point to collectable objects.
+ *
+ * This code was derived from an earlier version of the GNU C++ standard
+ * library, which itself was derived from the SGI STL implementation.
+ */
+
+#ifndef GC_ALLOCATOR_H
+
+#define GC_ALLOCATOR_H
+
+#include "gc.h"
+#include <new> // for placement new
+
+#if defined(__GNUC__)
+# define GC_ATTR_UNUSED __attribute__((unused))
+#else
+# define GC_ATTR_UNUSED
+#endif
+
+/* First some helpers to allow us to dispatch on whether or not a type
+ * is known to be pointerfree.
+ * These are private, except that the client may invoke the
+ * GC_DECLARE_PTRFREE macro.
+ */
+
+struct GC_true_type {};
+struct GC_false_type {};
+
+template <class GC_tp>
+struct GC_type_traits {
+ GC_false_type GC_is_ptr_free;
+};
+
+# define GC_DECLARE_PTRFREE(T) \
+template<> struct GC_type_traits<T> { GC_true_type GC_is_ptr_free; }
+
+GC_DECLARE_PTRFREE(char);
+GC_DECLARE_PTRFREE(signed char);
+GC_DECLARE_PTRFREE(unsigned char);
+GC_DECLARE_PTRFREE(signed short);
+GC_DECLARE_PTRFREE(unsigned short);
+GC_DECLARE_PTRFREE(signed int);
+GC_DECLARE_PTRFREE(unsigned int);
+GC_DECLARE_PTRFREE(signed long);
+GC_DECLARE_PTRFREE(unsigned long);
+GC_DECLARE_PTRFREE(float);
+GC_DECLARE_PTRFREE(double);
+GC_DECLARE_PTRFREE(long double);
+/* The client may want to add others. */
+
+// In the following GC_Tp is GC_true_type iff we are allocating a
+// pointerfree object.
+template <class GC_Tp>
+inline void * GC_selective_alloc(size_t n, GC_Tp) {
+ return GC_MALLOC(n);
+}
+
+template <>
+inline void * GC_selective_alloc<GC_true_type>(size_t n, GC_true_type) {
+ return GC_MALLOC_ATOMIC(n);
+}
+
+/* Now the public gc_allocator<T> class:
+ */
+template <class GC_Tp>
+class gc_allocator {
+public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef GC_Tp* pointer;
+ typedef const GC_Tp* const_pointer;
+ typedef GC_Tp& reference;
+ typedef const GC_Tp& const_reference;
+ typedef GC_Tp value_type;
+
+ template <class GC_Tp1> struct rebind {
+ typedef gc_allocator<GC_Tp1> other;
+ };
+
+ gc_allocator() {}
+ gc_allocator(const gc_allocator&) throw() {}
+# if !(GC_NO_MEMBER_TEMPLATES || 0 < _MSC_VER && _MSC_VER <= 1200)
+ // MSVC++ 6.0 do not support member templates
+ template <class GC_Tp1> gc_allocator(const gc_allocator<GC_Tp1>&) throw() {}
+# endif
+ ~gc_allocator() throw() {}
+
+ pointer address(reference GC_x) const { return &GC_x; }
+ const_pointer address(const_reference GC_x) const { return &GC_x; }
+
+ // GC_n is permitted to be 0. The C++ standard says nothing about what
+ // the return value is when GC_n == 0.
+ GC_Tp* allocate(size_type GC_n, const void* = 0) {
+ GC_type_traits<GC_Tp> traits;
+ return static_cast<GC_Tp *>
+ (GC_selective_alloc(GC_n * sizeof(GC_Tp),
+ traits.GC_is_ptr_free));
+ }
+
+ // __p is not permitted to be a null pointer.
+ void deallocate(pointer __p, size_type GC_ATTR_UNUSED GC_n)
+ { GC_FREE(__p); }
+
+ size_type max_size() const throw()
+ { return size_t(-1) / sizeof(GC_Tp); }
+
+ void construct(pointer __p, const GC_Tp& __val) { new(__p) GC_Tp(__val); }
+ void destroy(pointer __p) { __p->~GC_Tp(); }
+};
+
+template<>
+class gc_allocator<void> {
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef void* pointer;
+ typedef const void* const_pointer;
+ typedef void value_type;
+
+ template <class GC_Tp1> struct rebind {
+ typedef gc_allocator<GC_Tp1> other;
+ };
+};
+
+
+template <class GC_T1, class GC_T2>
+inline bool operator==(const gc_allocator<GC_T1>&, const gc_allocator<GC_T2>&)
+{
+ return true;
+}
+
+template <class GC_T1, class GC_T2>
+inline bool operator!=(const gc_allocator<GC_T1>&, const gc_allocator<GC_T2>&)
+{
+ return false;
+}
+
+/*
+ * And the public traceable_allocator class.
+ */
+
+// Note that we currently don't specialize the pointer-free case, since a
+// pointer-free traceable container doesn't make that much sense,
+// though it could become an issue due to abstraction boundaries.
+template <class GC_Tp>
+class traceable_allocator {
+public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef GC_Tp* pointer;
+ typedef const GC_Tp* const_pointer;
+ typedef GC_Tp& reference;
+ typedef const GC_Tp& const_reference;
+ typedef GC_Tp value_type;
+
+ template <class GC_Tp1> struct rebind {
+ typedef traceable_allocator<GC_Tp1> other;
+ };
+
+ traceable_allocator() throw() {}
+ traceable_allocator(const traceable_allocator&) throw() {}
+# if !(GC_NO_MEMBER_TEMPLATES || 0 < _MSC_VER && _MSC_VER <= 1200)
+ // MSVC++ 6.0 do not support member templates
+ template <class GC_Tp1> traceable_allocator
+ (const traceable_allocator<GC_Tp1>&) throw() {}
+# endif
+ ~traceable_allocator() throw() {}
+
+ pointer address(reference GC_x) const { return &GC_x; }
+ const_pointer address(const_reference GC_x) const { return &GC_x; }
+
+ // GC_n is permitted to be 0. The C++ standard says nothing about what
+ // the return value is when GC_n == 0.
+ GC_Tp* allocate(size_type GC_n, const void* = 0) {
+ return static_cast<GC_Tp*>(GC_MALLOC_UNCOLLECTABLE(GC_n * sizeof(GC_Tp)));
+ }
+
+ // __p is not permitted to be a null pointer.
+ void deallocate(pointer __p, size_type GC_ATTR_UNUSED GC_n)
+ { GC_FREE(__p); }
+
+ size_type max_size() const throw()
+ { return size_t(-1) / sizeof(GC_Tp); }
+
+ void construct(pointer __p, const GC_Tp& __val) { new(__p) GC_Tp(__val); }
+ void destroy(pointer __p) { __p->~GC_Tp(); }
+};
+
+template<>
+class traceable_allocator<void> {
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef void* pointer;
+ typedef const void* const_pointer;
+ typedef void value_type;
+
+ template <class GC_Tp1> struct rebind {
+ typedef traceable_allocator<GC_Tp1> other;
+ };
+};
+
+
+template <class GC_T1, class GC_T2>
+inline bool operator==(const traceable_allocator<GC_T1>&, const traceable_allocator<GC_T2>&)
+{
+ return true;
+}
+
+template <class GC_T1, class GC_T2>
+inline bool operator!=(const traceable_allocator<GC_T1>&, const traceable_allocator<GC_T2>&)
+{
+ return false;
+}
+
+#endif /* GC_ALLOCATOR_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/gc_amiga_redirects.h b/tools/build/v2/engine/boehm_gc/include/gc_amiga_redirects.h
new file mode 100644
index 0000000000..9e975c8c83
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc_amiga_redirects.h
@@ -0,0 +1,30 @@
+#ifndef GC_AMIGA_REDIRECTS_H
+
+# define GC_AMIGA_REDIRECTS_H
+
+# if ( defined(_AMIGA) && !defined(GC_AMIGA_MAKINGLIB) )
+ extern void *GC_amiga_realloc(void *old_object,size_t new_size_in_bytes);
+# define GC_realloc(a,b) GC_amiga_realloc(a,b)
+ extern void GC_amiga_set_toany(void (*func)(void));
+ extern int GC_amiga_free_space_divisor_inc;
+ extern void *(*GC_amiga_allocwrapper_do) \
+ (size_t size,void *(*AllocFunction)(size_t size2));
+# define GC_malloc(a) \
+ (*GC_amiga_allocwrapper_do)(a,GC_malloc)
+# define GC_malloc_atomic(a) \
+ (*GC_amiga_allocwrapper_do)(a,GC_malloc_atomic)
+# define GC_malloc_uncollectable(a) \
+ (*GC_amiga_allocwrapper_do)(a,GC_malloc_uncollectable)
+# define GC_malloc_stubborn(a) \
+ (*GC_amiga_allocwrapper_do)(a,GC_malloc_stubborn)
+# define GC_malloc_atomic_uncollectable(a) \
+ (*GC_amiga_allocwrapper_do)(a,GC_malloc_atomic_uncollectable)
+# define GC_malloc_ignore_off_page(a) \
+ (*GC_amiga_allocwrapper_do)(a,GC_malloc_ignore_off_page)
+# define GC_malloc_atomic_ignore_off_page(a) \
+ (*GC_amiga_allocwrapper_do)(a,GC_malloc_atomic_ignore_off_page)
+# endif /* _AMIGA && !GC_AMIGA_MAKINGLIB */
+
+#endif /* GC_AMIGA_REDIRECTS_H */
+
+
diff --git a/tools/build/v2/engine/boehm_gc/include/gc_backptr.h b/tools/build/v2/engine/boehm_gc/include/gc_backptr.h
new file mode 100644
index 0000000000..5899496e0f
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc_backptr.h
@@ -0,0 +1,65 @@
+/*
+ * This is a simple API to implement pointer back tracing, i.e.
+ * to answer questions such as "who is pointing to this" or
+ * "why is this object being retained by the collector"
+ *
+ * This API assumes that we have an ANSI C compiler.
+ *
+ * Most of these calls yield useful information on only after
+ * a garbage collection. Usually the client will first force
+ * a full collection and then gather information, preferably
+ * before much intervening allocation.
+ *
+ * The implementation of the interface is only about 99.9999%
+ * correct. It is intended to be good enough for profiling,
+ * but is not intended to be used with production code.
+ *
+ * Results are likely to be much more useful if all allocation is
+ * accomplished through the debugging allocators.
+ *
+ * The implementation idea is due to A. Demers.
+ */
+
+#ifndef GC_BACKPTR_H
+#define GC_BACKPTR_H
+/* Store information about the object referencing dest in *base_p */
+/* and *offset_p. */
+/* If multiple objects or roots point to dest, the one reported */
+/* will be the last on used by the garbage collector to trace the */
+/* object. */
+/* source is root ==> *base_p = address, *offset_p = 0 */
+/* source is heap object ==> *base_p != 0, *offset_p = offset */
+/* Returns 1 on success, 0 if source couldn't be determined. */
+/* Dest can be any address within a heap object. */
+typedef enum { GC_UNREFERENCED, /* No reference info available. */
+ GC_NO_SPACE, /* Dest not allocated with debug alloc */
+ GC_REFD_FROM_ROOT, /* Referenced directly by root *base_p */
+ GC_REFD_FROM_REG, /* Referenced from a register, i.e. */
+ /* a root without an address. */
+ GC_REFD_FROM_HEAP, /* Referenced from another heap obj. */
+ GC_FINALIZER_REFD /* Finalizable and hence accessible. */
+} GC_ref_kind;
+
+GC_ref_kind GC_get_back_ptr_info(void *dest, void **base_p, size_t *offset_p);
+
+/* Generate a random heap address. */
+/* The resulting address is in the heap, but */
+/* not necessarily inside a valid object. */
+void * GC_generate_random_heap_address(void);
+
+/* Generate a random address inside a valid marked heap object. */
+void * GC_generate_random_valid_address(void);
+
+/* Force a garbage collection and generate a backtrace from a */
+/* random heap address. */
+/* This uses the GC logging mechanism (GC_printf) to produce */
+/* output. It can often be called from a debugger. The */
+/* source in dbg_mlc.c also serves as a sample client. */
+void GC_generate_random_backtrace(void);
+
+/* Print a backtrace from a specific address. Used by the */
+/* above. The client should call GC_gcollect() immediately */
+/* before invocation. */
+void GC_print_backtrace(void *);
+
+#endif /* GC_BACKPTR_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/gc_config_macros.h b/tools/build/v2/engine/boehm_gc/include/gc_config_macros.h
new file mode 100644
index 0000000000..66abf0b1e3
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc_config_macros.h
@@ -0,0 +1,179 @@
+/*
+ * This should never be included directly. It is included only from gc.h.
+ * We separate it only to make gc.h more suitable as documentation.
+ *
+ * Some tests for old macros. These violate our namespace rules and will
+ * disappear shortly. Use the GC_ names.
+ */
+#if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS) \
+ || defined(_SOLARIS_PTHREADS) || defined(GC_SOLARIS_PTHREADS)
+ /* We no longer support old style Solaris threads. */
+ /* GC_SOLARIS_THREADS now means pthreads. */
+# ifndef GC_SOLARIS_THREADS
+# define GC_SOLARIS_THREADS
+# endif
+#endif
+#if defined(IRIX_THREADS)
+# define GC_IRIX_THREADS
+#endif
+#if defined(DGUX_THREADS)
+# if !defined(GC_DGUX386_THREADS)
+# define GC_DGUX386_THREADS
+# endif
+#endif
+#if defined(AIX_THREADS)
+# define GC_AIX_THREADS
+#endif
+#if defined(HPUX_THREADS)
+# define GC_HPUX_THREADS
+#endif
+#if defined(OSF1_THREADS)
+# define GC_OSF1_THREADS
+#endif
+#if defined(LINUX_THREADS)
+# define GC_LINUX_THREADS
+#endif
+#if defined(WIN32_THREADS)
+# define GC_WIN32_THREADS
+#endif
+#if defined(USE_LD_WRAP)
+# define GC_USE_LD_WRAP
+#endif
+
+#if !defined(_REENTRANT) && (defined(GC_SOLARIS_THREADS) \
+ || defined(GC_HPUX_THREADS) \
+ || defined(GC_AIX_THREADS) \
+ || defined(GC_LINUX_THREADS) \
+ || defined(GC_NETBSD_THREADS) \
+ || defined(GC_GNU_THREADS))
+# define _REENTRANT
+ /* Better late than never. This fails if system headers that */
+ /* depend on this were previously included. */
+#endif
+
+#if !defined(_PTHREADS) && defined(GC_NETBSD_THREADS)
+# define _PTHREADS
+#endif
+
+#if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
+# define _POSIX4A_DRAFT10_SOURCE 1
+#endif
+
+# if defined(GC_SOLARIS_THREADS) || defined(GC_FREEBSD_THREADS) || \
+ defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) || \
+ defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || \
+ defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \
+ defined(GC_AIX_THREADS) || defined(GC_NETBSD_THREADS) || \
+ (defined(GC_WIN32_THREADS) && defined(__CYGWIN32__)) || \
+ defined(GC_GNU_THREADS)
+# define GC_PTHREADS
+# endif
+
+#if defined(GC_WIN32_PTHREADS)
+# define GC_WIN32_THREADS
+# define GC_PTHREADS
+#endif
+
+#if defined(GC_THREADS) && !defined(GC_PTHREADS)
+# if defined(__linux__)
+# define GC_LINUX_THREADS
+# define GC_PTHREADS
+# endif
+# if !defined(__linux__) && (defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
+ || defined(hppa) || defined(__HPPA)) \
+ || (defined(__ia64) && defined(_HPUX_SOURCE))
+# define GC_HPUX_THREADS
+# define GC_PTHREADS
+# endif
+# if !defined(__linux__) && (defined(__alpha) || defined(__alpha__))
+# define GC_OSF1_THREADS
+# define GC_PTHREADS
+# endif
+# if defined(__mips) && !defined(__linux__)
+# define GC_IRIX_THREADS
+# define GC_PTHREADS
+# endif
+# if defined(__sparc) && !defined(__linux__) \
+ || defined(sun) && (defined(i386) || defined(__i386__))
+# define GC_SOLARIS_THREADS
+# define GC_PTHREADS
+# endif
+# if defined(__APPLE__) && defined(__MACH__)
+# define GC_DARWIN_THREADS
+# define GC_PTHREADS
+# endif
+# if !defined(GC_PTHREADS) && (defined(__FreeBSD__) || defined(__DragonFly__))
+# define GC_FREEBSD_THREADS
+# define GC_PTHREADS
+# endif
+# if !defined(GC_PTHREADS) && defined(__NetBSD__)
+# define GC_NETBSD_THREADS
+# define GC_PTHREADS
+# endif
+# if defined(DGUX) && (defined(i386) || defined(__i386__))
+# define GC_DGUX386_THREADS
+# define GC_PTHREADS
+# endif
+# if defined(_AIX)
+# define GC_AIX_THREADS
+# define GC_PTHREADS
+# endif
+#endif /* GC_THREADS */
+
+#if defined(GC_THREADS) && !defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) \
+ && (defined(_WIN32) || defined(_MSC_VER) || defined(__CYGWIN__) \
+ || defined(__MINGW32__) || defined(__BORLANDC__) \
+ || defined(_WIN32_WCE))
+# define GC_WIN32_THREADS
+# if defined(__CYGWIN__)
+# define GC_PTHREADS
+# endif
+#endif
+
+# define __GC
+# ifndef _WIN32_WCE
+# include <stddef.h>
+# if defined(__MINGW32__)
+# include <stdint.h>
+ /* We mention uintptr_t. */
+ /* Perhaps this should be included in pure msft environments */
+ /* as well? */
+# endif
+# else /* ! _WIN32_WCE */
+/* Yet more kluges for WinCE */
+# include <stdlib.h> /* size_t is defined here */
+ typedef long ptrdiff_t; /* ptrdiff_t is not defined */
+# endif
+
+#if defined(_DLL) && !defined(GC_NOT_DLL) && !defined(GC_DLL)
+# define GC_DLL
+#endif
+
+#if defined(__MINGW32__) && defined(GC_DLL)
+# ifdef GC_BUILD
+# define GC_API __declspec(dllexport)
+# else
+# define GC_API __declspec(dllimport)
+# endif
+#endif
+
+#if (defined(__DMC__) || defined(_MSC_VER)) && defined(GC_DLL)
+# ifdef GC_BUILD
+# define GC_API extern __declspec(dllexport)
+# else
+# define GC_API __declspec(dllimport)
+# endif
+#endif
+
+#if defined(__WATCOMC__) && defined(GC_DLL)
+# ifdef GC_BUILD
+# define GC_API extern __declspec(dllexport)
+# else
+# define GC_API extern __declspec(dllimport)
+# endif
+#endif
+
+#ifndef GC_API
+#define GC_API extern
+#endif
+
diff --git a/tools/build/v2/engine/boehm_gc/include/gc_cpp.h b/tools/build/v2/engine/boehm_gc/include/gc_cpp.h
new file mode 100644
index 0000000000..d3df211210
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc_cpp.h
@@ -0,0 +1,374 @@
+#ifndef GC_CPP_H
+#define GC_CPP_H
+/****************************************************************************
+Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+
+THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+
+Permission is hereby granted to use or copy this program for any
+purpose, provided the above notices are retained on all copies.
+Permission to modify the code and to distribute modified code is
+granted, provided the above notices are retained, and a notice that
+the code was modified is included with the above copyright notice.
+****************************************************************************
+
+C++ Interface to the Boehm Collector
+
+ John R. Ellis and Jesse Hull
+
+This interface provides access to the Boehm collector. It provides
+basic facilities similar to those described in "Safe, Efficient
+Garbage Collection for C++", by John R. Elis and David L. Detlefs
+(ftp://ftp.parc.xerox.com/pub/ellis/gc).
+
+All heap-allocated objects are either "collectable" or
+"uncollectable". Programs must explicitly delete uncollectable
+objects, whereas the garbage collector will automatically delete
+collectable objects when it discovers them to be inaccessible.
+Collectable objects may freely point at uncollectable objects and vice
+versa.
+
+Objects allocated with the built-in "::operator new" are uncollectable.
+
+Objects derived from class "gc" are collectable. For example:
+
+ class A: public gc {...};
+ A* a = new A; // a is collectable.
+
+Collectable instances of non-class types can be allocated using the GC
+(or UseGC) placement:
+
+ typedef int A[ 10 ];
+ A* a = new (GC) A;
+
+Uncollectable instances of classes derived from "gc" can be allocated
+using the NoGC placement:
+
+ class A: public gc {...};
+ A* a = new (NoGC) A; // a is uncollectable.
+
+The new(PointerFreeGC) syntax allows the allocation of collectable
+objects that are not scanned by the collector. This useful if you
+are allocating compressed data, bitmaps, or network packets. (In
+the latter case, it may remove danger of unfriendly network packets
+intentionally containing values that cause spurious memory retention.)
+
+Both uncollectable and collectable objects can be explicitly deleted
+with "delete", which invokes an object's destructors and frees its
+storage immediately.
+
+A collectable object may have a clean-up function, which will be
+invoked when the collector discovers the object to be inaccessible.
+An object derived from "gc_cleanup" or containing a member derived
+from "gc_cleanup" has a default clean-up function that invokes the
+object's destructors. Explicit clean-up functions may be specified as
+an additional placement argument:
+
+ A* a = ::new (GC, MyCleanup) A;
+
+An object is considered "accessible" by the collector if it can be
+reached by a path of pointers from static variables, automatic
+variables of active functions, or from some object with clean-up
+enabled; pointers from an object to itself are ignored.
+
+Thus, if objects A and B both have clean-up functions, and A points at
+B, B is considered accessible. After A's clean-up is invoked and its
+storage released, B will then become inaccessible and will have its
+clean-up invoked. If A points at B and B points to A, forming a
+cycle, then that's considered a storage leak, and neither will be
+collectable. See the interface gc.h for low-level facilities for
+handling such cycles of objects with clean-up.
+
+The collector cannot guarantee that it will find all inaccessible
+objects. In practice, it finds almost all of them.
+
+
+Cautions:
+
+1. Be sure the collector has been augmented with "make c++" or
+"--enable-cplusplus".
+
+2. If your compiler supports the new "operator new[]" syntax, then
+add -DGC_OPERATOR_NEW_ARRAY to the Makefile.
+
+If your compiler doesn't support "operator new[]", beware that an
+array of type T, where T is derived from "gc", may or may not be
+allocated as a collectable object (it depends on the compiler). Use
+the explicit GC placement to make the array collectable. For example:
+
+ class A: public gc {...};
+ A* a1 = new A[ 10 ]; // collectable or uncollectable?
+ A* a2 = new (GC) A[ 10 ]; // collectable
+
+3. The destructors of collectable arrays of objects derived from
+"gc_cleanup" will not be invoked properly. For example:
+
+ class A: public gc_cleanup {...};
+ A* a = new (GC) A[ 10 ]; // destructors not invoked correctly
+
+Typically, only the destructor for the first element of the array will
+be invoked when the array is garbage-collected. To get all the
+destructors of any array executed, you must supply an explicit
+clean-up function:
+
+ A* a = new (GC, MyCleanUp) A[ 10 ];
+
+(Implementing clean-up of arrays correctly, portably, and in a way
+that preserves the correct exception semantics requires a language
+extension, e.g. the "gc" keyword.)
+
+4. Compiler bugs (now hopefully history):
+
+* Solaris 2's CC (SC3.0) doesn't implement t->~T() correctly, so the
+destructors of classes derived from gc_cleanup won't be invoked.
+You'll have to explicitly register a clean-up function with
+new-placement syntax.
+
+* Evidently cfront 3.0 does not allow destructors to be explicitly
+invoked using the ANSI-conforming syntax t->~T(). If you're using
+cfront 3.0, you'll have to comment out the class gc_cleanup, which
+uses explicit invocation.
+
+5. GC name conflicts:
+
+Many other systems seem to use the identifier "GC" as an abbreviation
+for "Graphics Context". Since version 5.0, GC placement has been replaced
+by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
+
+****************************************************************************/
+
+#include "gc.h"
+
+#ifndef THINK_CPLUS
+# define GC_cdecl
+#else
+# define GC_cdecl _cdecl
+#endif
+
+#if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \
+ && !defined(_ENABLE_ARRAYNEW) /* Digimars */ \
+ && (defined(__BORLANDC__) && (__BORLANDC__ < 0x450) \
+ || (defined(__GNUC__) && \
+ (__GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 6)) \
+ || (defined(__WATCOMC__) && __WATCOMC__ < 1050))
+# define GC_NO_OPERATOR_NEW_ARRAY
+#endif
+
+#if !defined(GC_NO_OPERATOR_NEW_ARRAY) && !defined(GC_OPERATOR_NEW_ARRAY)
+# define GC_OPERATOR_NEW_ARRAY
+#endif
+
+#if ! defined ( __BORLANDC__ ) /* Confuses the Borland compiler. */ \
+ && ! defined ( __sgi )
+# define GC_PLACEMENT_DELETE
+#endif
+
+enum GCPlacement {UseGC,
+#ifndef GC_NAME_CONFLICT
+ GC=UseGC,
+#endif
+ NoGC, PointerFreeGC};
+
+class gc {public:
+ inline void* operator new( size_t size );
+ inline void* operator new( size_t size, GCPlacement gcp );
+ inline void* operator new( size_t size, void *p );
+ /* Must be redefined here, since the other overloadings */
+ /* hide the global definition. */
+ inline void operator delete( void* obj );
+# ifdef GC_PLACEMENT_DELETE
+ inline void operator delete( void*, void* );
+# endif
+
+#ifdef GC_OPERATOR_NEW_ARRAY
+ inline void* operator new[]( size_t size );
+ inline void* operator new[]( size_t size, GCPlacement gcp );
+ inline void* operator new[]( size_t size, void *p );
+ inline void operator delete[]( void* obj );
+# ifdef GC_PLACEMENT_DELETE
+ inline void operator delete[]( void*, void* );
+# endif
+#endif /* GC_OPERATOR_NEW_ARRAY */
+ };
+ /*
+ Instances of classes derived from "gc" will be allocated in the
+ collected heap by default, unless an explicit NoGC placement is
+ specified. */
+
+class gc_cleanup: virtual public gc {public:
+ inline gc_cleanup();
+ inline virtual ~gc_cleanup();
+private:
+ inline static void GC_cdecl cleanup( void* obj, void* clientData );};
+ /*
+ Instances of classes derived from "gc_cleanup" will be allocated
+ in the collected heap by default. When the collector discovers an
+ inaccessible object derived from "gc_cleanup" or containing a
+ member derived from "gc_cleanup", its destructors will be
+ invoked. */
+
+extern "C" {typedef void (*GCCleanUpFunc)( void* obj, void* clientData );}
+
+#ifdef _MSC_VER
+ // Disable warning that "no matching operator delete found; memory will
+ // not be freed if initialization throws an exception"
+# pragma warning(disable:4291)
+#endif
+
+inline void* operator new(
+ size_t size,
+ GCPlacement gcp,
+ GCCleanUpFunc cleanup = 0,
+ void* clientData = 0 );
+ /*
+ Allocates a collectable or uncollected object, according to the
+ value of "gcp".
+
+ For collectable objects, if "cleanup" is non-null, then when the
+ allocated object "obj" becomes inaccessible, the collector will
+ invoke the function "cleanup( obj, clientData )" but will not
+ invoke the object's destructors. It is an error to explicitly
+ delete an object allocated with a non-null "cleanup".
+
+ It is an error to specify a non-null "cleanup" with NoGC or for
+ classes derived from "gc_cleanup" or containing members derived
+ from "gc_cleanup". */
+
+
+#ifdef _MSC_VER
+ /** This ensures that the system default operator new[] doesn't get
+ * undefined, which is what seems to happen on VC++ 6 for some reason
+ * if we define a multi-argument operator new[].
+ * There seems to be really redirect new in this environment without
+ * including this everywhere.
+ */
+ void *operator new[]( size_t size );
+
+ void operator delete[](void* obj);
+
+ void* operator new( size_t size);
+
+ void operator delete(void* obj);
+
+ // This new operator is used by VC++ in case of Debug builds !
+ void* operator new( size_t size,
+ int ,//nBlockUse,
+ const char * szFileName,
+ int nLine );
+#endif /* _MSC_VER */
+
+
+#ifdef GC_OPERATOR_NEW_ARRAY
+
+inline void* operator new[](
+ size_t size,
+ GCPlacement gcp,
+ GCCleanUpFunc cleanup = 0,
+ void* clientData = 0 );
+ /*
+ The operator new for arrays, identical to the above. */
+
+#endif /* GC_OPERATOR_NEW_ARRAY */
+
+/****************************************************************************
+
+Inline implementation
+
+****************************************************************************/
+
+inline void* gc::operator new( size_t size ) {
+ return GC_MALLOC( size );}
+
+inline void* gc::operator new( size_t size, GCPlacement gcp ) {
+ if (gcp == UseGC)
+ return GC_MALLOC( size );
+ else if (gcp == PointerFreeGC)
+ return GC_MALLOC_ATOMIC( size );
+ else
+ return GC_MALLOC_UNCOLLECTABLE( size );}
+
+inline void* gc::operator new( size_t size, void *p ) {
+ return p;}
+
+inline void gc::operator delete( void* obj ) {
+ GC_FREE( obj );}
+
+#ifdef GC_PLACEMENT_DELETE
+ inline void gc::operator delete( void*, void* ) {}
+#endif
+
+#ifdef GC_OPERATOR_NEW_ARRAY
+
+inline void* gc::operator new[]( size_t size ) {
+ return gc::operator new( size );}
+
+inline void* gc::operator new[]( size_t size, GCPlacement gcp ) {
+ return gc::operator new( size, gcp );}
+
+inline void* gc::operator new[]( size_t size, void *p ) {
+ return p;}
+
+inline void gc::operator delete[]( void* obj ) {
+ gc::operator delete( obj );}
+
+#ifdef GC_PLACEMENT_DELETE
+ inline void gc::operator delete[]( void*, void* ) {}
+#endif
+
+#endif /* GC_OPERATOR_NEW_ARRAY */
+
+
+inline gc_cleanup::~gc_cleanup() {
+ GC_register_finalizer_ignore_self( GC_base(this), 0, 0, 0, 0 );}
+
+inline void gc_cleanup::cleanup( void* obj, void* displ ) {
+ ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();}
+
+inline gc_cleanup::gc_cleanup() {
+ GC_finalization_proc oldProc;
+ void* oldData;
+ void* base = GC_base( (void *) this );
+ if (0 != base) {
+ // Don't call the debug version, since this is a real base address.
+ GC_register_finalizer_ignore_self(
+ base, (GC_finalization_proc)cleanup, (void*) ((char*) this - (char*) base),
+ &oldProc, &oldData );
+ if (0 != oldProc) {
+ GC_register_finalizer_ignore_self( base, oldProc, oldData, 0, 0 );}}}
+
+inline void* operator new(
+ size_t size,
+ GCPlacement gcp,
+ GCCleanUpFunc cleanup,
+ void* clientData )
+{
+ void* obj;
+
+ if (gcp == UseGC) {
+ obj = GC_MALLOC( size );
+ if (cleanup != 0)
+ GC_REGISTER_FINALIZER_IGNORE_SELF(
+ obj, cleanup, clientData, 0, 0 );}
+ else if (gcp == PointerFreeGC) {
+ obj = GC_MALLOC_ATOMIC( size );}
+ else {
+ obj = GC_MALLOC_UNCOLLECTABLE( size );};
+ return obj;}
+
+
+#ifdef GC_OPERATOR_NEW_ARRAY
+
+inline void* operator new[](
+ size_t size,
+ GCPlacement gcp,
+ GCCleanUpFunc cleanup,
+ void* clientData )
+{
+ return ::operator new( size, gcp, cleanup, clientData );}
+
+#endif /* GC_OPERATOR_NEW_ARRAY */
+
+
+#endif /* GC_CPP_H */
+
diff --git a/tools/build/v2/engine/boehm_gc/include/gc_gcj.h b/tools/build/v2/engine/boehm_gc/include/gc_gcj.h
new file mode 100644
index 0000000000..699ddf5d48
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc_gcj.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright 1999 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* This file assumes the collector has been compiled with GC_GCJ_SUPPORT */
+/* and that an ANSI C compiler is available. */
+
+/*
+ * We allocate objects whose first word contains a pointer to a struct
+ * describing the object type. This struct contains a garbage collector mark
+ * descriptor at offset MARK_DESCR_OFFSET. Alternatively, the objects
+ * may be marked by the mark procedure passed to GC_init_gcj_malloc.
+ */
+
+#ifndef GC_GCJ_H
+
+#define GC_GCJ_H
+
+#ifndef MARK_DESCR_OFFSET
+# define MARK_DESCR_OFFSET sizeof(word)
+#endif
+ /* Gcj keeps GC descriptor as second word of vtable. This */
+ /* probably needs to be adjusted for other clients. */
+ /* We currently assume that this offset is such that: */
+ /* - all objects of this kind are large enough to have */
+ /* a value at that offset, and */
+ /* - it is not zero. */
+ /* These assumptions allow objects on the free list to be */
+ /* marked normally. */
+
+#ifndef _GC_H
+# include "gc.h"
+#endif
+
+/* The following allocators signal an out of memory condition with */
+/* return GC_oom_fn(bytes); */
+
+/* The following function must be called before the gcj allocators */
+/* can be invoked. */
+/* mp_index and mp are the index and mark_proc (see gc_mark.h) */
+/* respectively for the allocated objects. Mark_proc will be */
+/* used to build the descriptor for objects allocated through the */
+/* debugging interface. The mark_proc will be invoked on all such */
+/* objects with an "environment" value of 1. The client may choose */
+/* to use the same mark_proc for some of its generated mark descriptors.*/
+/* In that case, it should use a different "environment" value to */
+/* detect the presence or absence of the debug header. */
+/* Mp is really of type mark_proc, as defined in gc_mark.h. We don't */
+/* want to include that here for namespace pollution reasons. */
+extern void GC_init_gcj_malloc(int mp_index, void * /* really mark_proc */mp);
+
+/* Allocate an object, clear it, and store the pointer to the */
+/* type structure (vtable in gcj). */
+/* This adds a byte at the end of the object if GC_malloc would.*/
+extern void * GC_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr);
+/* The debug versions allocate such that the specified mark_proc */
+/* is always invoked. */
+extern void * GC_debug_gcj_malloc(size_t lb,
+ void * ptr_to_struct_containing_descr,
+ GC_EXTRA_PARAMS);
+
+/* Similar to GC_gcj_malloc, but assumes that a pointer to near the */
+/* beginning of the resulting object is always maintained. */
+extern void * GC_gcj_malloc_ignore_off_page(size_t lb,
+ void * ptr_to_struct_containing_descr);
+
+/* The kind numbers of normal and debug gcj objects. */
+/* Useful only for debug support, we hope. */
+extern int GC_gcj_kind;
+
+extern int GC_gcj_debug_kind;
+
+# ifdef GC_DEBUG
+# define GC_GCJ_MALLOC(s,d) GC_debug_gcj_malloc(s,d,GC_EXTRAS)
+# define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s,d) GC_debug_gcj_malloc(s,d,GC_EXTRAS)
+# else
+# define GC_GCJ_MALLOC(s,d) GC_gcj_malloc(s,d)
+# define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s,d) \
+ GC_gcj_malloc_ignore_off_page(s,d)
+# endif
+
+#endif /* GC_GCJ_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/gc_inline.h b/tools/build/v2/engine/boehm_gc/include/gc_inline.h
new file mode 100644
index 0000000000..da7e2e91f0
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc_inline.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* USE OF THIS FILE IS NOT RECOMMENDED unless GC_all_interior_pointers */
+/* is not set, or the collector has been built with */
+/* -DDONT_ADD_BYTE_AT_END, or the specified size includes a pointerfree */
+/* word at the end. In the standard collector configuration, */
+/* the final word of each object may not be scanned. */
+/* This interface is most useful for compilers that generate C. */
+/* It is also used internally for thread-local allocation, in which */
+/* case, the size is suitably adjusted by the caller. */
+/* Manual use is hereby discouraged. */
+
+#include "gc.h"
+#include "gc_tiny_fl.h"
+
+#if __GNUC__ >= 3
+# define GC_EXPECT(expr, outcome) __builtin_expect(expr,outcome)
+ /* Equivalent to (expr), but predict that usually (expr)==outcome. */
+#else
+# define GC_EXPECT(expr, outcome) (expr)
+#endif /* __GNUC__ */
+
+/* The ultimately general inline allocation macro. Allocate an object */
+/* of size bytes, putting the resulting pointer in result. Tiny_fl is */
+/* a "tiny" free list array, which will be used first, if the size */
+/* is appropriate. If bytes is too large, we allocate with */
+/* default_expr instead. If we need to refill the free list, we use */
+/* GC_generic_malloc_many with the indicated kind. */
+/* Tiny_fl should be an array of GC_TINY_FREELISTS void * pointers. */
+/* If num_direct is nonzero, and the individual free list pointers */
+/* are initialized to (void *)1, then we allocate numdirect granules */
+/* directly using gmalloc before putting multiple objects into the */
+/* tiny_fl entry. If num_direct is zero, then the free lists may also */
+/* be initialized to (void *)0. */
+/* We rely on much of this hopefully getting optimized away in the */
+/* num_direct = 0 case. */
+/* Particularly if bytes is constant, this should generate a small */
+/* amount of code. */
+# define GC_FAST_MALLOC_GRANS(result,granules,tiny_fl,num_direct,\
+ kind,default_expr,init) \
+{ \
+ if (GC_EXPECT(granules >= GC_TINY_FREELISTS,0)) { \
+ result = default_expr; \
+ } else { \
+ void **my_fl = tiny_fl + granules; \
+ void *my_entry=*my_fl; \
+ void *next; \
+ \
+ while (GC_EXPECT((GC_word)my_entry \
+ <= num_direct + GC_TINY_FREELISTS + 1, 0)) { \
+ /* Entry contains counter or NULL */ \
+ if ((GC_word)my_entry - 1 < num_direct) { \
+ /* Small counter value, not NULL */ \
+ *my_fl = (ptr_t)my_entry + granules + 1; \
+ result = default_expr; \
+ goto out; \
+ } else { \
+ /* Large counter or NULL */ \
+ GC_generic_malloc_many(((granules) == 0? GC_GRANULE_BYTES : \
+ RAW_BYTES_FROM_INDEX(granules)), \
+ kind, my_fl); \
+ my_entry = *my_fl; \
+ if (my_entry == 0) { \
+ result = GC_oom_fn(bytes); \
+ goto out; \
+ } \
+ } \
+ } \
+ next = *(void **)(my_entry); \
+ result = (void *)my_entry; \
+ *my_fl = next; \
+ init; \
+ PREFETCH_FOR_WRITE(next); \
+ GC_ASSERT(GC_size(result) >= bytes + EXTRA_BYTES); \
+ GC_ASSERT((kind) == PTRFREE || ((GC_word *)result)[1] == 0); \
+ out: ; \
+ } \
+}
+
+# define GC_WORDS_TO_WHOLE_GRANULES(n) \
+ GC_WORDS_TO_GRANULES((n) + GC_GRANULE_WORDS - 1)
+
+/* Allocate n words (NOT BYTES). X is made to point to the result. */
+/* This should really only be used if GC_all_interior_pointers is */
+/* not set, or DONT_ADD_BYTE_AT_END is set. See above. */
+/* The semantics changed in version 7.0; we no longer lock, and */
+/* the caller is responsible for supplying a cleared tiny_fl */
+/* free list array. For single-threaded applications, this may be */
+/* a global array. */
+# define GC_MALLOC_WORDS(result,n,tiny_fl) \
+{ \
+ size_t grans = WORDS_TO_WHOLE_GRANULES(n); \
+ GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \
+ NORMAL, GC_malloc(grans*GRANULE_BYTES), \
+ *(void **)result = 0); \
+}
+
+# define GC_MALLOC_ATOMIC_WORDS(result,n,tiny_fl) \
+{ \
+ size_t grans = WORDS_TO_WHOLE_GRANULES(n); \
+ GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \
+ PTRFREE, GC_malloc_atomic(grans*GRANULE_BYTES), \
+ /* no initialization */); \
+}
+
+
+/* And once more for two word initialized objects: */
+# define GC_CONS(result, first, second, tiny_fl) \
+{ \
+ size_t grans = WORDS_TO_WHOLE_GRANULES(2); \
+ GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \
+ NORMAL, GC_malloc(grans*GRANULE_BYTES), \
+ *(void **)result = (void *)(first)); \
+ ((void **)(result))[1] = (void *)(second); \
+}
diff --git a/tools/build/v2/engine/boehm_gc/include/gc_mark.h b/tools/build/v2/engine/boehm_gc/include/gc_mark.h
new file mode 100644
index 0000000000..8ee50b5d4d
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc_mark.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+/*
+ * This contains interfaces to the GC marker that are likely to be useful to
+ * clients that provide detailed heap layout information to the collector.
+ * This interface should not be used by normal C or C++ clients.
+ * It will be useful to runtimes for other languages.
+ *
+ * This is an experts-only interface! There are many ways to break the
+ * collector in subtle ways by using this functionality.
+ */
+#ifndef GC_MARK_H
+# define GC_MARK_H
+
+# ifndef GC_H
+# include "gc.h"
+# endif
+
+/* A client supplied mark procedure. Returns new mark stack pointer. */
+/* Primary effect should be to push new entries on the mark stack. */
+/* Mark stack pointer values are passed and returned explicitly. */
+/* Global variables decribing mark stack are not necessarily valid. */
+/* (This usually saves a few cycles by keeping things in registers.) */
+/* Assumed to scan about GC_PROC_BYTES on average. If it needs to do */
+/* much more work than that, it should do it in smaller pieces by */
+/* pushing itself back on the mark stack. */
+/* Note that it should always do some work (defined as marking some */
+/* objects) before pushing more than one entry on the mark stack. */
+/* This is required to ensure termination in the event of mark stack */
+/* overflows. */
+/* This procedure is always called with at least one empty entry on the */
+/* mark stack. */
+/* Currently we require that mark procedures look for pointers in a */
+/* subset of the places the conservative marker would. It must be safe */
+/* to invoke the normal mark procedure instead. */
+/* WARNING: Such a mark procedure may be invoked on an unused object */
+/* residing on a free list. Such objects are cleared, except for a */
+/* free list link field in the first word. Thus mark procedures may */
+/* not count on the presence of a type descriptor, and must handle this */
+/* case correctly somehow. */
+# define GC_PROC_BYTES 100
+struct GC_ms_entry;
+typedef struct GC_ms_entry * (*GC_mark_proc) (
+ GC_word * addr, struct GC_ms_entry * mark_stack_ptr,
+ struct GC_ms_entry * mark_stack_limit, GC_word env);
+
+# define GC_LOG_MAX_MARK_PROCS 6
+# define GC_MAX_MARK_PROCS (1 << GC_LOG_MAX_MARK_PROCS)
+
+/* In a few cases it's necessary to assign statically known indices to */
+/* certain mark procs. Thus we reserve a few for well known clients. */
+/* (This is necessary if mark descriptors are compiler generated.) */
+#define GC_RESERVED_MARK_PROCS 8
+# define GC_GCJ_RESERVED_MARK_PROC_INDEX 0
+
+/* Object descriptors on mark stack or in objects. Low order two */
+/* bits are tags distinguishing among the following 4 possibilities */
+/* for the high order 30 bits. */
+#define GC_DS_TAG_BITS 2
+#define GC_DS_TAGS ((1 << GC_DS_TAG_BITS) - 1)
+#define GC_DS_LENGTH 0 /* The entire word is a length in bytes that */
+ /* must be a multiple of 4. */
+#define GC_DS_BITMAP 1 /* 30 (62) bits are a bitmap describing pointer */
+ /* fields. The msb is 1 iff the first word */
+ /* is a pointer. */
+ /* (This unconventional ordering sometimes */
+ /* makes the marker slightly faster.) */
+ /* Zeroes indicate definite nonpointers. Ones */
+ /* indicate possible pointers. */
+ /* Only usable if pointers are word aligned. */
+#define GC_DS_PROC 2
+ /* The objects referenced by this object can be */
+ /* pushed on the mark stack by invoking */
+ /* PROC(descr). ENV(descr) is passed as the */
+ /* last argument. */
+# define GC_MAKE_PROC(proc_index, env) \
+ (((((env) << GC_LOG_MAX_MARK_PROCS) \
+ | (proc_index)) << GC_DS_TAG_BITS) | GC_DS_PROC)
+#define GC_DS_PER_OBJECT 3 /* The real descriptor is at the */
+ /* byte displacement from the beginning of the */
+ /* object given by descr & ~DS_TAGS */
+ /* If the descriptor is negative, the real */
+ /* descriptor is at (*<object_start>) - */
+ /* (descr & ~DS_TAGS) - GC_INDIR_PER_OBJ_BIAS */
+ /* The latter alternative can be used if each */
+ /* object contains a type descriptor in the */
+ /* first word. */
+ /* Note that in multithreaded environments */
+ /* per object descriptors maust be located in */
+ /* either the first two or last two words of */
+ /* the object, since only those are guaranteed */
+ /* to be cleared while the allocation lock is */
+ /* held. */
+#define GC_INDIR_PER_OBJ_BIAS 0x10
+
+extern void * GC_least_plausible_heap_addr;
+extern void * GC_greatest_plausible_heap_addr;
+ /* Bounds on the heap. Guaranteed valid */
+ /* Likely to include future heap expansion. */
+
+/* Handle nested references in a custom mark procedure. */
+/* Check if obj is a valid object. If so, ensure that it is marked. */
+/* If it was not previously marked, push its contents onto the mark */
+/* stack for future scanning. The object will then be scanned using */
+/* its mark descriptor. */
+/* Returns the new mark stack pointer. */
+/* Handles mark stack overflows correctly. */
+/* Since this marks first, it makes progress even if there are mark */
+/* stack overflows. */
+/* Src is the address of the pointer to obj, which is used only */
+/* for back pointer-based heap debugging. */
+/* It is strongly recommended that most objects be handled without mark */
+/* procedures, e.g. with bitmap descriptors, and that mark procedures */
+/* be reserved for exceptional cases. That will ensure that */
+/* performance of this call is not extremely performance critical. */
+/* (Otherwise we would need to inline GC_mark_and_push completely, */
+/* which would tie the client code to a fixed collector version.) */
+/* Note that mark procedures should explicitly call FIXUP_POINTER() */
+/* if required. */
+struct GC_ms_entry *GC_mark_and_push(void * obj,
+ struct GC_ms_entry * mark_stack_ptr,
+ struct GC_ms_entry * mark_stack_limit,
+ void * *src);
+
+#define GC_MARK_AND_PUSH(obj, msp, lim, src) \
+ (((GC_word)obj >= (GC_word)GC_least_plausible_heap_addr && \
+ (GC_word)obj <= (GC_word)GC_greatest_plausible_heap_addr)? \
+ GC_mark_and_push(obj, msp, lim, src) : \
+ msp)
+
+extern size_t GC_debug_header_size;
+ /* The size of the header added to objects allocated through */
+ /* the GC_debug routines. */
+ /* Defined as a variable so that client mark procedures don't */
+ /* need to be recompiled for collector version changes. */
+#define GC_USR_PTR_FROM_BASE(p) ((void *)((char *)(p) + GC_debug_header_size))
+
+/* And some routines to support creation of new "kinds", e.g. with */
+/* custom mark procedures, by language runtimes. */
+/* The _inner versions assume the caller holds the allocation lock. */
+
+/* Return a new free list array. */
+void ** GC_new_free_list(void);
+void ** GC_new_free_list_inner(void);
+
+/* Return a new kind, as specified. */
+unsigned GC_new_kind(void **free_list, GC_word mark_descriptor_template,
+ int add_size_to_descriptor, int clear_new_objects);
+ /* The last two parameters must be zero or one. */
+unsigned GC_new_kind_inner(void **free_list,
+ GC_word mark_descriptor_template,
+ int add_size_to_descriptor,
+ int clear_new_objects);
+
+/* Return a new mark procedure identifier, suitable for use as */
+/* the first argument in GC_MAKE_PROC. */
+unsigned GC_new_proc(GC_mark_proc);
+unsigned GC_new_proc_inner(GC_mark_proc);
+
+/* Allocate an object of a given kind. Note that in multithreaded */
+/* contexts, this is usually unsafe for kinds that have the descriptor */
+/* in the object itself, since there is otherwise a window in which */
+/* the descriptor is not correct. Even in the single-threaded case, */
+/* we need to be sure that cleared objects on a free list don't */
+/* cause a GC crash if they are accidentally traced. */
+void * GC_generic_malloc(size_t lb, int k);
+
+typedef void (*GC_describe_type_fn) (void *p, char *out_buf);
+ /* A procedure which */
+ /* produces a human-readable */
+ /* description of the "type" of object */
+ /* p into the buffer out_buf of length */
+ /* GC_TYPE_DESCR_LEN. This is used by */
+ /* the debug support when printing */
+ /* objects. */
+ /* These functions should be as robust */
+ /* as possible, though we do avoid */
+ /* invoking them on objects on the */
+ /* global free list. */
+# define GC_TYPE_DESCR_LEN 40
+
+void GC_register_describe_type_fn(int kind, GC_describe_type_fn knd);
+ /* Register a describe_type function */
+ /* to be used when printing objects */
+ /* of a particular kind. */
+
+#endif /* GC_MARK_H */
+
diff --git a/tools/build/v2/engine/boehm_gc/include/gc_pthread_redirects.h b/tools/build/v2/engine/boehm_gc/include/gc_pthread_redirects.h
new file mode 100644
index 0000000000..b567f63e14
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc_pthread_redirects.h
@@ -0,0 +1,54 @@
+/* Our pthread support normally needs to intercept a number of thread */
+/* calls. We arrange to do that here, if appropriate. */
+
+#ifndef GC_PTHREAD_REDIRECTS_H
+
+#define GC_PTHREAD_REDIRECTS_H
+
+#if !defined(GC_USE_LD_WRAP) && defined(GC_PTHREADS)
+/* We need to intercept calls to many of the threads primitives, so */
+/* that we can locate thread stacks and stop the world. */
+/* Note also that the collector cannot always see thread specific data. */
+/* Thread specific data should generally consist of pointers to */
+/* uncollectable objects (allocated with GC_malloc_uncollectable, */
+/* not the system malloc), which are deallocated using the destructor */
+/* facility in thr_keycreate. Alternatively, keep a redundant pointer */
+/* to thread specific data on the thread stack. */
+
+# include <pthread.h>
+# include <signal.h>
+
+ int GC_pthread_create(pthread_t *new_thread,
+ const pthread_attr_t *attr,
+ void *(*start_routine)(void *), void *arg);
+#ifndef GC_DARWIN_THREADS
+ int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset);
+#endif
+ int GC_pthread_join(pthread_t thread, void **retval);
+ int GC_pthread_detach(pthread_t thread);
+
+#if defined(GC_OSF1_THREADS) \
+ && defined(_PTHREAD_USE_MANGLED_NAMES_) && !defined(_PTHREAD_USE_PTDNAM_)
+/* Unless the compiler supports #pragma extern_prefix, the Tru64 UNIX
+ <pthread.h> redefines some POSIX thread functions to use mangled names.
+ If so, undef them before redefining. */
+# undef pthread_create
+# undef pthread_join
+# undef pthread_detach
+#endif
+
+# define pthread_create GC_pthread_create
+# define pthread_join GC_pthread_join
+# define pthread_detach GC_pthread_detach
+
+#ifndef GC_DARWIN_THREADS
+# ifdef pthread_sigmask
+# undef pthread_sigmask
+# endif /* pthread_sigmask */
+# define pthread_sigmask GC_pthread_sigmask
+# define dlopen GC_dlopen
+#endif
+
+#endif /* GC_xxxxx_THREADS */
+
+#endif /* GC_PTHREAD_REDIRECTS_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/gc_tiny_fl.h b/tools/build/v2/engine/boehm_gc/include/gc_tiny_fl.h
new file mode 100644
index 0000000000..52b6864b6b
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc_tiny_fl.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1999-2005 Hewlett-Packard Development Company, L.P.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#ifndef GC_TINY_FL_H
+#define GC_TINY_FL_H
+/*
+ * Constants and data structures for "tiny" free lists.
+ * These are used for thread-local allocation or in-lined allocators.
+ * Each global free list also essentially starts with one of these.
+ * However, global free lists are known to the GC. "Tiny" free lists
+ * are basically private to the client. Their contents are viewed as
+ * "in use" and marked accordingly by the core of the GC.
+ *
+ * Note that inlined code might know about the layout of these and the constants
+ * involved. Thus any change here may invalidate clients, and such changes should
+ * be avoided. Hence we keep this as simple as possible.
+ */
+
+/*
+ * We always set GRANULE_BYTES to twice the length of a pointer.
+ * This means that all allocation requests are rounded up to the next
+ * multiple of 16 on 64-bit architectures or 8 on 32-bit architectures.
+ * This appears to be a reasonable compromise between fragmentation overhead
+ * and space usage for mark bits (usually mark bytes).
+ * On many 64-bit architectures some memory references require 16-byte
+ * alignment, making this necessary anyway.
+ * For a few 32-bit architecture (e.g. x86), we may also need 16-byte alignment
+ * for certain memory references. But currently that does not seem to be the
+ * default for all conventional malloc implementations, so we ignore that
+ * problem.
+ * It would always be safe, and often useful, to be able to allocate very
+ * small objects with smaller alignment. But that would cost us mark bit
+ * space, so we no longer do so.
+ */
+#ifndef GC_GRANULE_BYTES
+ /* GC_GRANULE_BYTES should not be overridden in any instances of the GC */
+ /* library that may be shared between applications, since it affects */
+ /* the binary interface to the library. */
+# if defined(__LP64__) || defined (_LP64) || defined(_WIN64) \
+ || defined(__s390x__) || defined(__x86_64__) \
+ || defined(__alpha__) || defined(__powerpc64__) \
+ || defined(__arch64__)
+# define GC_GRANULE_BYTES 16
+# define GC_GRANULE_WORDS 2
+# else
+# define GC_GRANULE_BYTES 8
+# define GC_GRANULE_WORDS 2
+# endif
+#endif /* !GC_GRANULE_BYTES */
+
+#if GC_GRANULE_WORDS == 2
+# define GC_WORDS_TO_GRANULES(n) ((n)>>1)
+#else
+# define GC_WORDS_TO_GRANULES(n) ((n)*sizeof(void *)/GRANULE_BYTES)
+#endif
+
+/* A "tiny" free list header contains TINY_FREELISTS pointers to */
+/* singly linked lists of objects of different sizes, the ith one */
+/* containing objects i granules in size. Note that there is a list */
+/* of size zero objects. */
+#ifndef GC_TINY_FREELISTS
+# if GC_GRANULE_BYTES == 16
+# define GC_TINY_FREELISTS 25
+# else
+# define GC_TINY_FREELISTS 33 /* Up to and including 256 bytes */
+# endif
+#endif /* !GC_TINY_FREELISTS */
+
+/* The ith free list corresponds to size i*GRANULE_BYTES */
+/* Internally to the collector, the index can be computed with */
+/* ROUNDED_UP_GRANULES. Externally, we don't know whether */
+/* DONT_ADD_BYTE_AT_END is set, but the client should know. */
+
+/* Convert a free list index to the actual size of objects */
+/* on that list, including extra space we added. Not an */
+/* inverse of the above. */
+#define RAW_BYTES_FROM_INDEX(i) ((i) * GC_GRANULE_BYTES)
+
+#endif /* GC_TINY_FL_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/gc_typed.h b/tools/build/v2/engine/boehm_gc/include/gc_typed.h
new file mode 100644
index 0000000000..1086acdd12
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/gc_typed.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright 1996 Silicon Graphics. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/*
+ * Some simple primitives for allocation with explicit type information.
+ * Facilities for dynamic type inference may be added later.
+ * Should be used only for extremely performance critical applications,
+ * or if conservative collector leakage is otherwise a problem (unlikely).
+ * Note that this is implemented completely separately from the rest
+ * of the collector, and is not linked in unless referenced.
+ * This does not currently support GC_DEBUG in any interesting way.
+ */
+/* Boehm, May 19, 1994 2:13 pm PDT */
+
+#ifndef _GC_TYPED_H
+# define _GC_TYPED_H
+# ifndef _GC_H
+# include "gc.h"
+# endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+typedef GC_word * GC_bitmap;
+ /* The least significant bit of the first word is one if */
+ /* the first word in the object may be a pointer. */
+
+# define GC_WORDSZ (8*sizeof(GC_word))
+# define GC_get_bit(bm, index) \
+ (((bm)[index/GC_WORDSZ] >> (index%GC_WORDSZ)) & 1)
+# define GC_set_bit(bm, index) \
+ (bm)[index/GC_WORDSZ] |= ((GC_word)1 << (index%GC_WORDSZ))
+# define GC_WORD_OFFSET(t, f) (offsetof(t,f)/sizeof(GC_word))
+# define GC_WORD_LEN(t) (sizeof(t)/ sizeof(GC_word))
+# define GC_BITMAP_SIZE(t) ((GC_WORD_LEN(t) + GC_WORDSZ-1)/GC_WORDSZ)
+
+typedef GC_word GC_descr;
+
+GC_API GC_descr GC_make_descriptor(GC_bitmap bm, size_t len);
+ /* Return a type descriptor for the object whose layout */
+ /* is described by the argument. */
+ /* The least significant bit of the first word is one */
+ /* if the first word in the object may be a pointer. */
+ /* The second argument specifies the number of */
+ /* meaningful bits in the bitmap. The actual object */
+ /* may be larger (but not smaller). Any additional */
+ /* words in the object are assumed not to contain */
+ /* pointers. */
+ /* Returns a conservative approximation in the */
+ /* (unlikely) case of insufficient memory to build */
+ /* the descriptor. Calls to GC_make_descriptor */
+ /* may consume some amount of a finite resource. This */
+ /* is intended to be called once per type, not once */
+ /* per allocation. */
+
+/* It is possible to generate a descriptor for a C type T with */
+/* word aligned pointer fields f1, f2, ... as follows: */
+/* */
+/* GC_descr T_descr; */
+/* GC_word T_bitmap[GC_BITMAP_SIZE(T)] = {0}; */
+/* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f1)); */
+/* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f2)); */
+/* ... */
+/* T_descr = GC_make_descriptor(T_bitmap, GC_WORD_LEN(T)); */
+
+GC_API void * GC_malloc_explicitly_typed(size_t size_in_bytes, GC_descr d);
+ /* Allocate an object whose layout is described by d. */
+ /* The resulting object MAY NOT BE PASSED TO REALLOC. */
+ /* The returned object is cleared. */
+
+GC_API void * GC_malloc_explicitly_typed_ignore_off_page
+ (size_t size_in_bytes, GC_descr d);
+
+GC_API void * GC_calloc_explicitly_typed(size_t nelements,
+ size_t element_size_in_bytes,
+ GC_descr d);
+ /* Allocate an array of nelements elements, each of the */
+ /* given size, and with the given descriptor. */
+ /* The elemnt size must be a multiple of the byte */
+ /* alignment required for pointers. E.g. on a 32-bit */
+ /* machine with 16-bit aligned pointers, size_in_bytes */
+ /* must be a multiple of 2. */
+ /* Returned object is cleared. */
+
+#ifdef GC_DEBUG
+# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) GC_MALLOC(bytes)
+# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) GC_MALLOC(n*bytes)
+#else
+# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \
+ GC_malloc_explicitly_typed(bytes, d)
+# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
+ GC_calloc_explicitly_typed(n, bytes, d)
+#endif /* !GC_DEBUG */
+
+#ifdef __cplusplus
+ } /* matches extern "C" */
+#endif
+
+#endif /* _GC_TYPED_H */
+
diff --git a/tools/build/v2/engine/boehm_gc/include/include.am b/tools/build/v2/engine/boehm_gc/include/include.am
new file mode 100644
index 0000000000..78c57c346c
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/include.am
@@ -0,0 +1,54 @@
+#
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose, provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+#
+# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
+# Modified by: Petter Urkedal <petter.urkedal@nordita.dk>
+
+## Process this file with automake to produce part of Makefile.in.
+
+# installed headers
+#
+pkginclude_HEADERS += \
+ include/gc.h \
+ include/gc_typed.h \
+ include/gc_inline.h \
+ include/gc_mark.h \
+ include/gc_cpp.h \
+ include/weakpointer.h \
+ include/new_gc_alloc.h \
+ include/gc_allocator.h \
+ include/gc_backptr.h \
+ include/gc_gcj.h \
+ include/leak_detector.h \
+ include/gc_amiga_redirects.h \
+ include/gc_pthread_redirects.h \
+ include/gc_config_macros.h \
+ include/gc_tiny_fl.h
+
+# headers which are not installed
+#
+dist_noinst_HEADERS += \
+ include/private/gc_hdrs.h \
+ include/private/gc_priv.h \
+ include/private/gcconfig.h \
+ include/private/gc_pmark.h \
+ include/private/gc_locks.h \
+ include/private/dbg_mlc.h \
+ include/private/specific.h \
+ include/private/cord_pos.h \
+ include/private/pthread_support.h \
+ include/private/pthread_stop_world.h \
+ include/private/darwin_semaphore.h \
+ include/private/darwin_stop_world.h \
+ include/private/thread_local_alloc.h \
+ include/cord.h \
+ include/ec.h \
+ include/javaxfc.h
diff --git a/tools/build/v2/engine/boehm_gc/include/javaxfc.h b/tools/build/v2/engine/boehm_gc/include/javaxfc.h
new file mode 100644
index 0000000000..23e01005af
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/javaxfc.h
@@ -0,0 +1,21 @@
+# ifndef GC_H
+# include "gc.h"
+# endif
+
+/*
+ * Invoke all remaining finalizers that haven't yet been run.
+ * This is needed for strict compliance with the Java standard,
+ * which can make the runtime guarantee that all finalizers are run.
+ * This is problematic for several reasons:
+ * 1) It means that finalizers, and all methods calle by them,
+ * must be prepared to deal with objects that have been finalized in
+ * spite of the fact that they are still referenced by statically
+ * allocated pointer variables.
+ * 1) It may mean that we get stuck in an infinite loop running
+ * finalizers which create new finalizable objects, though that's
+ * probably unlikely.
+ * Thus this is not recommended for general use.
+ */
+void GC_finalize_all();
+
+
diff --git a/tools/build/v2/engine/boehm_gc/include/leak_detector.h b/tools/build/v2/engine/boehm_gc/include/leak_detector.h
new file mode 100644
index 0000000000..1d02f40076
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/leak_detector.h
@@ -0,0 +1,9 @@
+#define GC_DEBUG
+#include "gc.h"
+#define malloc(n) GC_MALLOC(n)
+#define calloc(m,n) GC_MALLOC((m)*(n))
+#define free(p) GC_FREE(p)
+#define realloc(p,n) GC_REALLOC((p),(n))
+#undef strdup
+#define strdup(s) GC_STRDUP((s))
+#define CHECK_LEAKS() GC_gcollect()
diff --git a/tools/build/v2/engine/boehm_gc/include/new_gc_alloc.h b/tools/build/v2/engine/boehm_gc/include/new_gc_alloc.h
new file mode 100644
index 0000000000..b4906af548
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/new_gc_alloc.h
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 1996-1998 by Silicon Graphics. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+//
+// This is a revision of gc_alloc.h for SGI STL versions > 3.0
+// Unlike earlier versions, it supplements the standard "alloc.h"
+// instead of replacing it.
+//
+// This is sloppy about variable names used in header files.
+// It also doesn't yet understand the new header file names or
+// namespaces.
+//
+// This assumes the collector has been compiled with -DATOMIC_UNCOLLECTABLE.
+// The user should also consider -DREDIRECT_MALLOC=GC_uncollectable_malloc,
+// to ensure that object allocated through malloc are traced.
+//
+// Some of this could be faster in the explicit deallocation case.
+// In particular, we spend too much time clearing objects on the
+// free lists. That could be avoided.
+//
+// This uses template classes with static members, and hence does not work
+// with g++ 2.7.2 and earlier.
+//
+// Unlike its predecessor, this one simply defines
+// gc_alloc
+// single_client_gc_alloc
+// traceable_alloc
+// single_client_traceable_alloc
+//
+// It does not redefine alloc. Nor does it change the default allocator,
+// though the user may wish to do so. (The argument against changing
+// the default allocator is that it may introduce subtle link compatibility
+// problems. The argument for changing it is that the usual default
+// allocator is usually a very bad choice for a garbage collected environment.)
+//
+// This code assumes that the collector itself has been compiled with a
+// compiler that defines __STDC__ .
+//
+
+#ifndef GC_ALLOC_H
+
+#include "gc.h"
+
+#if (__GNUC__ < 3)
+# include <stack> // A more portable way to get stl_alloc.h .
+#else
+# include <bits/stl_alloc.h>
+# ifndef __STL_BEGIN_NAMESPACE
+# define __STL_BEGIN_NAMESPACE namespace std {
+# define __STL_END_NAMESPACE };
+# endif
+#ifndef __STL_USE_STD_ALLOCATORS
+#define __STL_USE_STD_ALLOCATORS
+#endif
+#endif
+
+/* A hack to deal with gcc 3.1. If you are using gcc3.1 and later, */
+/* you should probably really use gc_allocator.h instead. */
+#if defined (__GNUC__) && \
+ (__GNUC__ > 3 || (__GNUC__ == 3 && (__GNUC_MINOR__ >= 1)))
+# define simple_alloc __simple_alloc
+#endif
+
+
+
+#define GC_ALLOC_H
+
+#include <stddef.h>
+#include <string.h>
+
+// The following need to match collector data structures.
+// We can't include gc_priv.h, since that pulls in way too much stuff.
+// This should eventually be factored out into another include file.
+
+extern "C" {
+ extern void ** const GC_objfreelist_ptr;
+ extern void ** const GC_aobjfreelist_ptr;
+ extern void ** const GC_uobjfreelist_ptr;
+ extern void ** const GC_auobjfreelist_ptr;
+
+ extern void GC_incr_bytes_allocd(size_t bytes);
+ extern void GC_incr_mem_freed(size_t words); /* FIXME: use bytes */
+
+ extern char * GC_generic_malloc_words_small(size_t word, int kind);
+ /* FIXME: Doesn't exist anymore. */
+}
+
+// Object kinds; must match PTRFREE, NORMAL, UNCOLLECTABLE, and
+// AUNCOLLECTABLE in gc_priv.h.
+
+enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2,
+ GC_AUNCOLLECTABLE = 3 };
+
+enum { GC_max_fast_bytes = 255 };
+
+enum { GC_bytes_per_word = sizeof(char *) };
+
+enum { GC_byte_alignment = 8 };
+
+enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
+
+inline void * &GC_obj_link(void * p)
+{ return *reinterpret_cast<void **>(p); }
+
+// Compute a number of words >= n+1 bytes.
+// The +1 allows for pointers one past the end.
+inline size_t GC_round_up(size_t n)
+{
+ return ((n + GC_byte_alignment)/GC_byte_alignment)*GC_word_alignment;
+}
+
+// The same but don't allow for extra byte.
+inline size_t GC_round_up_uncollectable(size_t n)
+{
+ return ((n + GC_byte_alignment - 1)/GC_byte_alignment)*GC_word_alignment;
+}
+
+template <int dummy>
+class GC_aux_template {
+public:
+ // File local count of allocated words. Occasionally this is
+ // added into the global count. A separate count is necessary since the
+ // real one must be updated with a procedure call.
+ static size_t GC_bytes_recently_allocd;
+
+ // Same for uncollectable mmory. Not yet reflected in either
+ // GC_bytes_recently_allocd or GC_non_gc_bytes.
+ static size_t GC_uncollectable_bytes_recently_allocd;
+
+ // Similar counter for explicitly deallocated memory.
+ static size_t GC_bytes_recently_freed;
+
+ // Again for uncollectable memory.
+ static size_t GC_uncollectable_bytes_recently_freed;
+
+ static void * GC_out_of_line_malloc(size_t nwords, int kind);
+};
+
+template <int dummy>
+size_t GC_aux_template<dummy>::GC_bytes_recently_allocd = 0;
+
+template <int dummy>
+size_t GC_aux_template<dummy>::GC_uncollectable_bytes_recently_allocd = 0;
+
+template <int dummy>
+size_t GC_aux_template<dummy>::GC_bytes_recently_freed = 0;
+
+template <int dummy>
+size_t GC_aux_template<dummy>::GC_uncollectable_bytes_recently_freed = 0;
+
+template <int dummy>
+void * GC_aux_template<dummy>::GC_out_of_line_malloc(size_t nwords, int kind)
+{
+ GC_bytes_recently_allocd += GC_uncollectable_bytes_recently_allocd;
+ GC_non_gc_bytes +=
+ GC_uncollectable_bytes_recently_allocd;
+ GC_uncollectable_bytes_recently_allocd = 0;
+
+ GC_bytes_recently_freed += GC_uncollectable_bytes_recently_freed;
+ GC_non_gc_bytes -= GC_uncollectable_bytes_recently_freed;
+ GC_uncollectable_bytes_recently_freed = 0;
+
+ GC_incr_bytes_allocd(GC_bytes_recently_allocd);
+ GC_bytes_recently_allocd = 0;
+
+ GC_incr_mem_freed(GC_bytes_per_word(GC_bytes_recently_freed));
+ GC_bytes_recently_freed = 0;
+
+ return GC_generic_malloc_words_small(nwords, kind);
+}
+
+typedef GC_aux_template<0> GC_aux;
+
+// A fast, single-threaded, garbage-collected allocator
+// We assume the first word will be immediately overwritten.
+// In this version, deallocation is not a noop, and explicit
+// deallocation is likely to help performance.
+template <int dummy>
+class single_client_gc_alloc_template {
+ public:
+ static void * allocate(size_t n)
+ {
+ size_t nwords = GC_round_up(n);
+ void ** flh;
+ void * op;
+
+ if (n > GC_max_fast_bytes) return GC_malloc(n);
+ flh = GC_objfreelist_ptr + nwords;
+ if (0 == (op = *flh)) {
+ return GC_aux::GC_out_of_line_malloc(nwords, GC_NORMAL);
+ }
+ *flh = GC_obj_link(op);
+ GC_aux::GC_bytes_recently_allocd += nwords * GC_bytes_per_word;
+ return op;
+ }
+ static void * ptr_free_allocate(size_t n)
+ {
+ size_t nwords = GC_round_up(n);
+ void ** flh;
+ void * op;
+
+ if (n > GC_max_fast_bytes) return GC_malloc_atomic(n);
+ flh = GC_aobjfreelist_ptr + nwords;
+ if (0 == (op = *flh)) {
+ return GC_aux::GC_out_of_line_malloc(nwords, GC_PTRFREE);
+ }
+ *flh = GC_obj_link(op);
+ GC_aux::GC_bytes_recently_allocd += nwords * GC_bytes_per_word;
+ return op;
+ }
+ static void deallocate(void *p, size_t n)
+ {
+ size_t nwords = GC_round_up(n);
+ void ** flh;
+
+ if (n > GC_max_fast_bytes) {
+ GC_free(p);
+ } else {
+ flh = GC_objfreelist_ptr + nwords;
+ GC_obj_link(p) = *flh;
+ memset(reinterpret_cast<char *>(p) + GC_bytes_per_word, 0,
+ GC_bytes_per_word * (nwords - 1));
+ *flh = p;
+ GC_aux::GC_bytes_recently_freed += nwords * GC_bytes_per_word;
+ }
+ }
+ static void ptr_free_deallocate(void *p, size_t n)
+ {
+ size_t nwords = GC_round_up(n);
+ void ** flh;
+
+ if (n > GC_max_fast_bytes) {
+ GC_free(p);
+ } else {
+ flh = GC_aobjfreelist_ptr + nwords;
+ GC_obj_link(p) = *flh;
+ *flh = p;
+ GC_aux::GC_bytes_recently_freed += nwords * GC_bytes_per_word;
+ }
+ }
+};
+
+typedef single_client_gc_alloc_template<0> single_client_gc_alloc;
+
+// Once more, for uncollectable objects.
+template <int dummy>
+class single_client_traceable_alloc_template {
+ public:
+ static void * allocate(size_t n)
+ {
+ size_t nwords = GC_round_up_uncollectable(n);
+ void ** flh;
+ void * op;
+
+ if (n > GC_max_fast_bytes) return GC_malloc_uncollectable(n);
+ flh = GC_uobjfreelist_ptr + nwords;
+ if (0 == (op = *flh)) {
+ return GC_aux::GC_out_of_line_malloc(nwords, GC_UNCOLLECTABLE);
+ }
+ *flh = GC_obj_link(op);
+ GC_aux::GC_uncollectable_bytes_recently_allocd +=
+ nwords * GC_bytes_per_word;
+ return op;
+ }
+ static void * ptr_free_allocate(size_t n)
+ {
+ size_t nwords = GC_round_up_uncollectable(n);
+ void ** flh;
+ void * op;
+
+ if (n > GC_max_fast_bytes) return GC_malloc_atomic_uncollectable(n);
+ flh = GC_auobjfreelist_ptr + nwords;
+ if (0 == (op = *flh)) {
+ return GC_aux::GC_out_of_line_malloc(nwords, GC_AUNCOLLECTABLE);
+ }
+ *flh = GC_obj_link(op);
+ GC_aux::GC_uncollectable_bytes_recently_allocd +=
+ nwords * GC_bytes_per_word;
+ return op;
+ }
+ static void deallocate(void *p, size_t n)
+ {
+ size_t nwords = GC_round_up_uncollectable(n);
+ void ** flh;
+
+ if (n > GC_max_fast_bytes) {
+ GC_free(p);
+ } else {
+ flh = GC_uobjfreelist_ptr + nwords;
+ GC_obj_link(p) = *flh;
+ *flh = p;
+ GC_aux::GC_uncollectable_bytes_recently_freed +=
+ nwords * GC_bytes_per_word;
+ }
+ }
+ static void ptr_free_deallocate(void *p, size_t n)
+ {
+ size_t nwords = GC_round_up_uncollectable(n);
+ void ** flh;
+
+ if (n > GC_max_fast_bytes) {
+ GC_free(p);
+ } else {
+ flh = GC_auobjfreelist_ptr + nwords;
+ GC_obj_link(p) = *flh;
+ *flh = p;
+ GC_aux::GC_uncollectable_bytes_recently_freed +=
+ nwords * GC_bytes_per_word;
+ }
+ }
+};
+
+typedef single_client_traceable_alloc_template<0> single_client_traceable_alloc;
+
+template < int dummy >
+class gc_alloc_template {
+ public:
+ static void * allocate(size_t n) { return GC_malloc(n); }
+ static void * ptr_free_allocate(size_t n)
+ { return GC_malloc_atomic(n); }
+ static void deallocate(void *, size_t) { }
+ static void ptr_free_deallocate(void *, size_t) { }
+};
+
+typedef gc_alloc_template < 0 > gc_alloc;
+
+template < int dummy >
+class traceable_alloc_template {
+ public:
+ static void * allocate(size_t n) { return GC_malloc_uncollectable(n); }
+ static void * ptr_free_allocate(size_t n)
+ { return GC_malloc_atomic_uncollectable(n); }
+ static void deallocate(void *p, size_t) { GC_free(p); }
+ static void ptr_free_deallocate(void *p, size_t) { GC_free(p); }
+};
+
+typedef traceable_alloc_template < 0 > traceable_alloc;
+
+// We want to specialize simple_alloc so that it does the right thing
+// for all pointerfree types. At the moment there is no portable way to
+// even approximate that. The following approximation should work for
+// SGI compilers, and recent versions of g++.
+
+# define __GC_SPECIALIZE(T,alloc) \
+class simple_alloc<T, alloc> { \
+public: \
+ static T *allocate(size_t n) \
+ { return 0 == n? 0 : \
+ reinterpret_cast<T*>(alloc::ptr_free_allocate(n * sizeof (T))); } \
+ static T *allocate(void) \
+ { return reinterpret_cast<T*>(alloc::ptr_free_allocate(sizeof (T))); } \
+ static void deallocate(T *p, size_t n) \
+ { if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
+ static void deallocate(T *p) \
+ { alloc::ptr_free_deallocate(p, sizeof (T)); } \
+};
+
+__STL_BEGIN_NAMESPACE
+
+__GC_SPECIALIZE(char, gc_alloc)
+__GC_SPECIALIZE(int, gc_alloc)
+__GC_SPECIALIZE(unsigned, gc_alloc)
+__GC_SPECIALIZE(float, gc_alloc)
+__GC_SPECIALIZE(double, gc_alloc)
+
+__GC_SPECIALIZE(char, traceable_alloc)
+__GC_SPECIALIZE(int, traceable_alloc)
+__GC_SPECIALIZE(unsigned, traceable_alloc)
+__GC_SPECIALIZE(float, traceable_alloc)
+__GC_SPECIALIZE(double, traceable_alloc)
+
+__GC_SPECIALIZE(char, single_client_gc_alloc)
+__GC_SPECIALIZE(int, single_client_gc_alloc)
+__GC_SPECIALIZE(unsigned, single_client_gc_alloc)
+__GC_SPECIALIZE(float, single_client_gc_alloc)
+__GC_SPECIALIZE(double, single_client_gc_alloc)
+
+__GC_SPECIALIZE(char, single_client_traceable_alloc)
+__GC_SPECIALIZE(int, single_client_traceable_alloc)
+__GC_SPECIALIZE(unsigned, single_client_traceable_alloc)
+__GC_SPECIALIZE(float, single_client_traceable_alloc)
+__GC_SPECIALIZE(double, single_client_traceable_alloc)
+
+__STL_END_NAMESPACE
+
+#ifdef __STL_USE_STD_ALLOCATORS
+
+__STL_BEGIN_NAMESPACE
+
+template <class _Tp>
+struct _Alloc_traits<_Tp, gc_alloc >
+{
+ static const bool _S_instanceless = true;
+ typedef simple_alloc<_Tp, gc_alloc > _Alloc_type;
+ typedef __allocator<_Tp, gc_alloc > allocator_type;
+};
+
+inline bool operator==(const gc_alloc&,
+ const gc_alloc&)
+{
+ return true;
+}
+
+inline bool operator!=(const gc_alloc&,
+ const gc_alloc&)
+{
+ return false;
+}
+
+template <class _Tp>
+struct _Alloc_traits<_Tp, single_client_gc_alloc >
+{
+ static const bool _S_instanceless = true;
+ typedef simple_alloc<_Tp, single_client_gc_alloc > _Alloc_type;
+ typedef __allocator<_Tp, single_client_gc_alloc > allocator_type;
+};
+
+inline bool operator==(const single_client_gc_alloc&,
+ const single_client_gc_alloc&)
+{
+ return true;
+}
+
+inline bool operator!=(const single_client_gc_alloc&,
+ const single_client_gc_alloc&)
+{
+ return false;
+}
+
+template <class _Tp>
+struct _Alloc_traits<_Tp, traceable_alloc >
+{
+ static const bool _S_instanceless = true;
+ typedef simple_alloc<_Tp, traceable_alloc > _Alloc_type;
+ typedef __allocator<_Tp, traceable_alloc > allocator_type;
+};
+
+inline bool operator==(const traceable_alloc&,
+ const traceable_alloc&)
+{
+ return true;
+}
+
+inline bool operator!=(const traceable_alloc&,
+ const traceable_alloc&)
+{
+ return false;
+}
+
+template <class _Tp>
+struct _Alloc_traits<_Tp, single_client_traceable_alloc >
+{
+ static const bool _S_instanceless = true;
+ typedef simple_alloc<_Tp, single_client_traceable_alloc > _Alloc_type;
+ typedef __allocator<_Tp, single_client_traceable_alloc > allocator_type;
+};
+
+inline bool operator==(const single_client_traceable_alloc&,
+ const single_client_traceable_alloc&)
+{
+ return true;
+}
+
+inline bool operator!=(const single_client_traceable_alloc&,
+ const single_client_traceable_alloc&)
+{
+ return false;
+}
+
+__STL_END_NAMESPACE
+
+#endif /* __STL_USE_STD_ALLOCATORS */
+
+#endif /* GC_ALLOC_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/private/cord_pos.h b/tools/build/v2/engine/boehm_gc/include/private/cord_pos.h
new file mode 100644
index 0000000000..d2b24bb8ab
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/cord_pos.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, May 19, 1994 2:23 pm PDT */
+# ifndef CORD_POSITION_H
+
+/* The representation of CORD_position. This is private to the */
+/* implementation, but the size is known to clients. Also */
+/* the implementation of some exported macros relies on it. */
+/* Don't use anything defined here and not in cord.h. */
+
+# define MAX_DEPTH 48
+ /* The maximum depth of a balanced cord + 1. */
+ /* We don't let cords get deeper than MAX_DEPTH. */
+
+struct CORD_pe {
+ CORD pe_cord;
+ size_t pe_start_pos;
+};
+
+/* A structure describing an entry on the path from the root */
+/* to current position. */
+typedef struct CORD_Pos {
+ size_t cur_pos;
+ int path_len;
+# define CORD_POS_INVALID (0x55555555)
+ /* path_len == INVALID <==> position invalid */
+ const char *cur_leaf; /* Current leaf, if it is a string. */
+ /* If the current leaf is a function, */
+ /* then this may point to function_buf */
+ /* containing the next few characters. */
+ /* Always points to a valid string */
+ /* containing the current character */
+ /* unless cur_end is 0. */
+ size_t cur_start; /* Start position of cur_leaf */
+ size_t cur_end; /* Ending position of cur_leaf */
+ /* 0 if cur_leaf is invalid. */
+ struct CORD_pe path[MAX_DEPTH + 1];
+ /* path[path_len] is the leaf corresponding to cur_pos */
+ /* path[0].pe_cord is the cord we point to. */
+# define FUNCTION_BUF_SZ 8
+ char function_buf[FUNCTION_BUF_SZ]; /* Space for next few chars */
+ /* from function node. */
+} CORD_pos[1];
+
+/* Extract the cord from a position: */
+CORD CORD_pos_to_cord(CORD_pos p);
+
+/* Extract the current index from a position: */
+size_t CORD_pos_to_index(CORD_pos p);
+
+/* Fetch the character located at the given position: */
+char CORD_pos_fetch(CORD_pos p);
+
+/* Initialize the position to refer to the give cord and index. */
+/* Note that this is the most expensive function on positions: */
+void CORD_set_pos(CORD_pos p, CORD x, size_t i);
+
+/* Advance the position to the next character. */
+/* P must be initialized and valid. */
+/* Invalidates p if past end: */
+void CORD_next(CORD_pos p);
+
+/* Move the position to the preceding character. */
+/* P must be initialized and valid. */
+/* Invalidates p if past beginning: */
+void CORD_prev(CORD_pos p);
+
+/* Is the position valid, i.e. inside the cord? */
+int CORD_pos_valid(CORD_pos p);
+
+char CORD__pos_fetch(CORD_pos);
+void CORD__next(CORD_pos);
+void CORD__prev(CORD_pos);
+
+#define CORD_pos_fetch(p) \
+ (((p)[0].cur_end != 0)? \
+ (p)[0].cur_leaf[(p)[0].cur_pos - (p)[0].cur_start] \
+ : CORD__pos_fetch(p))
+
+#define CORD_next(p) \
+ (((p)[0].cur_pos + 1 < (p)[0].cur_end)? \
+ (p)[0].cur_pos++ \
+ : (CORD__next(p), 0))
+
+#define CORD_prev(p) \
+ (((p)[0].cur_end != 0 && (p)[0].cur_pos > (p)[0].cur_start)? \
+ (p)[0].cur_pos-- \
+ : (CORD__prev(p), 0))
+
+#define CORD_pos_to_index(p) ((p)[0].cur_pos)
+
+#define CORD_pos_to_cord(p) ((p)[0].path[0].pe_cord)
+
+#define CORD_pos_valid(p) ((p)[0].path_len != CORD_POS_INVALID)
+
+/* Some grubby stuff for performance-critical friends: */
+#define CORD_pos_chars_left(p) ((long)((p)[0].cur_end) - (long)((p)[0].cur_pos))
+ /* Number of characters in cache. <= 0 ==> none */
+
+#define CORD_pos_advance(p,n) ((p)[0].cur_pos += (n) - 1, CORD_next(p))
+ /* Advance position by n characters */
+ /* 0 < n < CORD_pos_chars_left(p) */
+
+#define CORD_pos_cur_char_addr(p) \
+ (p)[0].cur_leaf + ((p)[0].cur_pos - (p)[0].cur_start)
+ /* address of current character in cache. */
+
+#endif
diff --git a/tools/build/v2/engine/boehm_gc/include/private/darwin_semaphore.h b/tools/build/v2/engine/boehm_gc/include/private/darwin_semaphore.h
new file mode 100644
index 0000000000..0f43982d5c
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/darwin_semaphore.h
@@ -0,0 +1,68 @@
+#ifndef GC_DARWIN_SEMAPHORE_H
+#define GC_DARWIN_SEMAPHORE_H
+
+#if !defined(GC_DARWIN_THREADS)
+#error darwin_semaphore.h included with GC_DARWIN_THREADS not defined
+#endif
+
+/*
+ This is a very simple semaphore implementation for darwin. It
+ is implemented in terms of pthreads calls so it isn't async signal
+ safe. This isn't a problem because signals aren't used to
+ suspend threads on darwin.
+*/
+
+typedef struct {
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ int value;
+} sem_t;
+
+static int sem_init(sem_t *sem, int pshared, int value) {
+ int ret;
+ if(pshared)
+ GC_abort("sem_init with pshared set");
+ sem->value = value;
+
+ ret = pthread_mutex_init(&sem->mutex,NULL);
+ if(ret < 0) return -1;
+ ret = pthread_cond_init(&sem->cond,NULL);
+ if(ret < 0) return -1;
+ return 0;
+}
+
+static int sem_post(sem_t *sem) {
+ if(pthread_mutex_lock(&sem->mutex) < 0)
+ return -1;
+ sem->value++;
+ if(pthread_cond_signal(&sem->cond) < 0) {
+ pthread_mutex_unlock(&sem->mutex);
+ return -1;
+ }
+ if(pthread_mutex_unlock(&sem->mutex) < 0)
+ return -1;
+ return 0;
+}
+
+static int sem_wait(sem_t *sem) {
+ if(pthread_mutex_lock(&sem->mutex) < 0)
+ return -1;
+ while(sem->value == 0) {
+ pthread_cond_wait(&sem->cond,&sem->mutex);
+ }
+ sem->value--;
+ if(pthread_mutex_unlock(&sem->mutex) < 0)
+ return -1;
+ return 0;
+}
+
+static int sem_destroy(sem_t *sem) {
+ int ret;
+ ret = pthread_cond_destroy(&sem->cond);
+ if(ret < 0) return -1;
+ ret = pthread_mutex_destroy(&sem->mutex);
+ if(ret < 0) return -1;
+ return 0;
+}
+
+#endif
diff --git a/tools/build/v2/engine/boehm_gc/include/private/darwin_stop_world.h b/tools/build/v2/engine/boehm_gc/include/private/darwin_stop_world.h
new file mode 100644
index 0000000000..f6f5314ee3
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/darwin_stop_world.h
@@ -0,0 +1,22 @@
+#ifndef GC_DARWIN_STOP_WORLD_H
+#define GC_DARWIN_STOP_WORLD_H
+
+#if !defined(GC_DARWIN_THREADS)
+#error darwin_stop_world.h included without GC_DARWIN_THREADS defined
+#endif
+
+#include <mach/mach.h>
+#include <mach/thread_act.h>
+
+struct thread_stop_info {
+ mach_port_t mach_thread;
+};
+
+struct GC_mach_thread {
+ thread_act_t thread;
+ int already_suspended;
+};
+
+void GC_darwin_register_mach_handler_thread(mach_port_t thread);
+
+#endif
diff --git a/tools/build/v2/engine/boehm_gc/include/private/dbg_mlc.h b/tools/build/v2/engine/boehm_gc/include/private/dbg_mlc.h
new file mode 100644
index 0000000000..fcd027c4fe
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/dbg_mlc.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1997 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/*
+ * This is mostly an internal header file. Typical clients should
+ * not use it. Clients that define their own object kinds with
+ * debugging allocators will probably want to include this, however.
+ * No attempt is made to keep the namespace clean. This should not be
+ * included from header files that are frequently included by clients.
+ */
+
+#ifndef _DBG_MLC_H
+
+#define _DBG_MLC_H
+
+# define I_HIDE_POINTERS
+# include "gc_priv.h"
+# ifdef KEEP_BACK_PTRS
+# include "gc_backptr.h"
+# endif
+
+#ifndef HIDE_POINTER
+ /* Gc.h was previously included, and hence the I_HIDE_POINTERS */
+ /* definition had no effect. Repeat the gc.h definitions here to */
+ /* get them anyway. */
+ typedef GC_word GC_hidden_pointer;
+# define HIDE_POINTER(p) (~(GC_hidden_pointer)(p))
+# define REVEAL_POINTER(p) ((void *)(HIDE_POINTER(p)))
+#endif /* HIDE_POINTER */
+
+# define START_FLAG ((word)0xfedcedcb)
+# define END_FLAG ((word)0xbcdecdef)
+ /* Stored both one past the end of user object, and one before */
+ /* the end of the object as seen by the allocator. */
+
+# if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST) \
+ || defined(MAKE_BACK_GRAPH)
+ /* Pointer "source"s that aren't real locations. */
+ /* Used in oh_back_ptr fields and as "source" */
+ /* argument to some marking functions. */
+# define NOT_MARKED (ptr_t)(0)
+# define MARKED_FOR_FINALIZATION (ptr_t)(2)
+ /* Object was marked because it is finalizable. */
+# define MARKED_FROM_REGISTER (ptr_t)(4)
+ /* Object was marked from a rgister. Hence the */
+ /* source of the reference doesn't have an address. */
+# endif /* KEEP_BACK_PTRS || PRINT_BLACK_LIST */
+
+/* Object header */
+typedef struct {
+# if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
+ /* We potentially keep two different kinds of back */
+ /* pointers. KEEP_BACK_PTRS stores a single back */
+ /* pointer in each reachable object to allow reporting */
+ /* of why an object was retained. MAKE_BACK_GRAPH */
+ /* builds a graph containing the inverse of all */
+ /* "points-to" edges including those involving */
+ /* objects that have just become unreachable. This */
+ /* allows detection of growing chains of unreachable */
+ /* objects. It may be possible to eventually combine */
+ /* both, but for now we keep them separate. Both */
+ /* kinds of back pointers are hidden using the */
+ /* following macros. In both cases, the plain version */
+ /* is constrained to have an least significant bit of 1,*/
+ /* to allow it to be distinguished from a free list */
+ /* link. This means the plain version must have an */
+ /* lsb of 0. */
+ /* Note that blocks dropped by black-listing will */
+ /* also have the lsb clear once debugging has */
+ /* started. */
+ /* We're careful never to overwrite a value with lsb 0. */
+# if ALIGNMENT == 1
+ /* Fudge back pointer to be even. */
+# define HIDE_BACK_PTR(p) HIDE_POINTER(~1 & (GC_word)(p))
+# else
+# define HIDE_BACK_PTR(p) HIDE_POINTER(p)
+# endif
+
+# ifdef KEEP_BACK_PTRS
+ GC_hidden_pointer oh_back_ptr;
+# endif
+# ifdef MAKE_BACK_GRAPH
+ GC_hidden_pointer oh_bg_ptr;
+# endif
+# if defined(KEEP_BACK_PTRS) != defined(MAKE_BACK_GRAPH)
+ /* Keep double-pointer-sized alignment. */
+ word oh_dummy;
+# endif
+# endif
+ const char * oh_string; /* object descriptor string */
+ word oh_int; /* object descriptor integers */
+# ifdef NEED_CALLINFO
+ struct callinfo oh_ci[NFRAMES];
+# endif
+# ifndef SHORT_DBG_HDRS
+ word oh_sz; /* Original malloc arg. */
+ word oh_sf; /* start flag */
+# endif /* SHORT_DBG_HDRS */
+} oh;
+/* The size of the above structure is assumed not to dealign things, */
+/* and to be a multiple of the word length. */
+
+#ifdef SHORT_DBG_HDRS
+# define DEBUG_BYTES (sizeof (oh))
+# define UNCOLLECTABLE_DEBUG_BYTES DEBUG_BYTES
+#else
+ /* Add space for END_FLAG, but use any extra space that was already */
+ /* added to catch off-the-end pointers. */
+ /* For uncollectable objects, the extra byte is not added. */
+# define UNCOLLECTABLE_DEBUG_BYTES (sizeof (oh) + sizeof (word))
+# define DEBUG_BYTES (UNCOLLECTABLE_DEBUG_BYTES - EXTRA_BYTES)
+#endif
+
+/* Round bytes to words without adding extra byte at end. */
+#define SIMPLE_ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
+
+/* ADD_CALL_CHAIN stores a (partial) call chain into an object */
+/* header. It may be called with or without the allocation */
+/* lock. */
+/* PRINT_CALL_CHAIN prints the call chain stored in an object */
+/* to stderr. It requires that we do not hold the lock. */
+#if defined(SAVE_CALL_CHAIN)
+ struct callinfo;
+ void GC_save_callers(struct callinfo info[NFRAMES]);
+ void GC_print_callers(struct callinfo info[NFRAMES]);
+# define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base)) -> oh_ci)
+# define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci)
+#elif defined(GC_ADD_CALLER)
+ struct callinfo;
+ void GC_print_callers(struct callinfo info[NFRAMES]);
+# define ADD_CALL_CHAIN(base, ra) ((oh *)(base)) -> oh_ci[0].ci_pc = (ra)
+# define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci)
+#else
+# define ADD_CALL_CHAIN(base, ra)
+# define PRINT_CALL_CHAIN(base)
+#endif
+
+# ifdef GC_ADD_CALLER
+# define OPT_RA ra,
+# else
+# define OPT_RA
+# endif
+
+
+/* Check whether object with base pointer p has debugging info */
+/* p is assumed to point to a legitimate object in our part */
+/* of the heap. */
+#ifdef SHORT_DBG_HDRS
+# define GC_has_other_debug_info(p) TRUE
+#else
+ GC_bool GC_has_other_debug_info(/* p */);
+#endif
+
+#if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
+# define GC_HAS_DEBUG_INFO(p) \
+ ((*((word *)p) & 1) && GC_has_other_debug_info(p))
+#else
+# define GC_HAS_DEBUG_INFO(p) GC_has_other_debug_info(p)
+#endif
+
+/* Store debugging info into p. Return displaced pointer. */
+/* Assumes we don't hold allocation lock. */
+ptr_t GC_store_debug_info(/* p, sz, string, integer */);
+
+#endif /* _DBG_MLC_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/private/gc_hdrs.h b/tools/build/v2/engine/boehm_gc/include/private/gc_hdrs.h
new file mode 100644
index 0000000000..559556ca78
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/gc_hdrs.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, July 11, 1995 11:54 am PDT */
+# ifndef GC_HEADERS_H
+# define GC_HEADERS_H
+typedef struct hblkhdr hdr;
+
+# if CPP_WORDSZ != 32 && CPP_WORDSZ < 36
+ --> Get a real machine.
+# endif
+
+/*
+ * The 2 level tree data structure that is used to find block headers.
+ * If there are more than 32 bits in a pointer, the top level is a hash
+ * table.
+ *
+ * This defines HDR, GET_HDR, and SET_HDR, the main macros used to
+ * retrieve and set object headers.
+ *
+ * We take advantage of a header lookup
+ * cache. This is a locally declared direct mapped cache, used inside
+ * the marker. The HC_GET_HDR macro uses and maintains this
+ * cache. Assuming we get reasonable hit rates, this shaves a few
+ * memory references from each pointer validation.
+ */
+
+# if CPP_WORDSZ > 32
+# define HASH_TL
+# endif
+
+/* Define appropriate out-degrees for each of the two tree levels */
+# ifdef SMALL_CONFIG
+# define LOG_BOTTOM_SZ 11
+ /* Keep top index size reasonable with smaller blocks. */
+# else
+# define LOG_BOTTOM_SZ 10
+# endif
+# ifndef HASH_TL
+# define LOG_TOP_SZ (WORDSZ - LOG_BOTTOM_SZ - LOG_HBLKSIZE)
+# else
+# define LOG_TOP_SZ 11
+# endif
+# define TOP_SZ (1 << LOG_TOP_SZ)
+# define BOTTOM_SZ (1 << LOG_BOTTOM_SZ)
+
+#ifndef SMALL_CONFIG
+# define USE_HDR_CACHE
+#endif
+
+/* #define COUNT_HDR_CACHE_HITS */
+
+# ifdef COUNT_HDR_CACHE_HITS
+ extern word GC_hdr_cache_hits;
+ extern word GC_hdr_cache_misses;
+# define HC_HIT() ++GC_hdr_cache_hits
+# define HC_MISS() ++GC_hdr_cache_misses
+# else
+# define HC_HIT()
+# define HC_MISS()
+# endif
+
+ typedef struct hce {
+ word block_addr; /* right shifted by LOG_HBLKSIZE */
+ hdr * hce_hdr;
+ } hdr_cache_entry;
+
+# define HDR_CACHE_SIZE 8 /* power of 2 */
+
+# define DECLARE_HDR_CACHE \
+ hdr_cache_entry hdr_cache[HDR_CACHE_SIZE]
+
+# define INIT_HDR_CACHE BZERO(hdr_cache, sizeof(hdr_cache))
+
+# define HCE(h) hdr_cache + (((word)(h) >> LOG_HBLKSIZE) & (HDR_CACHE_SIZE-1))
+
+# define HCE_VALID_FOR(hce,h) ((hce) -> block_addr == \
+ ((word)(h) >> LOG_HBLKSIZE))
+
+# define HCE_HDR(h) ((hce) -> hce_hdr)
+
+#ifdef PRINT_BLACK_LIST
+ hdr * GC_header_cache_miss(ptr_t p, hdr_cache_entry *hce, ptr_t source);
+# define HEADER_CACHE_MISS(p, hce, source) \
+ GC_header_cache_miss(p, hce, source)
+#else
+ hdr * GC_header_cache_miss(ptr_t p, hdr_cache_entry *hce);
+# define HEADER_CACHE_MISS(p, hce, source) GC_header_cache_miss(p, hce)
+#endif
+
+/* Set hhdr to the header for p. Analogous to GET_HDR below, */
+/* except that in the case of large objects, it */
+/* gets the header for the object beginning, if GC_all_interior_ptrs */
+/* is set. */
+/* Returns zero if p points to somewhere other than the first page */
+/* of an object, and it is not a valid pointer to the object. */
+# define HC_GET_HDR(p, hhdr, source, exit_label) \
+ { \
+ hdr_cache_entry * hce = HCE(p); \
+ if (EXPECT(HCE_VALID_FOR(hce, p), 1)) { \
+ HC_HIT(); \
+ hhdr = hce -> hce_hdr; \
+ } else { \
+ hhdr = HEADER_CACHE_MISS(p, hce, source); \
+ if (0 == hhdr) goto exit_label; \
+ } \
+ }
+
+typedef struct bi {
+ hdr * index[BOTTOM_SZ];
+ /*
+ * The bottom level index contains one of three kinds of values:
+ * 0 means we're not responsible for this block,
+ * or this is a block other than the first one in a free block.
+ * 1 < (long)X <= MAX_JUMP means the block starts at least
+ * X * HBLKSIZE bytes before the current address.
+ * A valid pointer points to a hdr structure. (The above can't be
+ * valid pointers due to the GET_MEM return convention.)
+ */
+ struct bi * asc_link; /* All indices are linked in */
+ /* ascending order... */
+ struct bi * desc_link; /* ... and in descending order. */
+ word key; /* high order address bits. */
+# ifdef HASH_TL
+ struct bi * hash_link; /* Hash chain link. */
+# endif
+} bottom_index;
+
+/* extern bottom_index GC_all_nils; - really part of GC_arrays */
+
+/* extern bottom_index * GC_top_index []; - really part of GC_arrays */
+ /* Each entry points to a bottom_index. */
+ /* On a 32 bit machine, it points to */
+ /* the index for a set of high order */
+ /* bits equal to the index. For longer */
+ /* addresses, we hash the high order */
+ /* bits to compute the index in */
+ /* GC_top_index, and each entry points */
+ /* to a hash chain. */
+ /* The last entry in each chain is */
+ /* GC_all_nils. */
+
+
+# define MAX_JUMP (HBLKSIZE - 1)
+
+# define HDR_FROM_BI(bi, p) \
+ ((bi)->index[((word)(p) >> LOG_HBLKSIZE) & (BOTTOM_SZ - 1)])
+# ifndef HASH_TL
+# define BI(p) (GC_top_index \
+ [(word)(p) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE)])
+# define HDR_INNER(p) HDR_FROM_BI(BI(p),p)
+# ifdef SMALL_CONFIG
+# define HDR(p) GC_find_header((ptr_t)(p))
+# else
+# define HDR(p) HDR_INNER(p)
+# endif
+# define GET_BI(p, bottom_indx) (bottom_indx) = BI(p)
+# define GET_HDR(p, hhdr) (hhdr) = HDR(p)
+# define SET_HDR(p, hhdr) HDR_INNER(p) = (hhdr)
+# define GET_HDR_ADDR(p, ha) (ha) = &(HDR_INNER(p))
+# else /* hash */
+/* Hash function for tree top level */
+# define TL_HASH(hi) ((hi) & (TOP_SZ - 1))
+/* Set bottom_indx to point to the bottom index for address p */
+# define GET_BI(p, bottom_indx) \
+ { \
+ register word hi = \
+ (word)(p) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE); \
+ register bottom_index * _bi = GC_top_index[TL_HASH(hi)]; \
+ \
+ while (_bi -> key != hi && _bi != GC_all_nils) \
+ _bi = _bi -> hash_link; \
+ (bottom_indx) = _bi; \
+ }
+# define GET_HDR_ADDR(p, ha) \
+ { \
+ register bottom_index * bi; \
+ \
+ GET_BI(p, bi); \
+ (ha) = &(HDR_FROM_BI(bi, p)); \
+ }
+# define GET_HDR(p, hhdr) { register hdr ** _ha; GET_HDR_ADDR(p, _ha); \
+ (hhdr) = *_ha; }
+# define SET_HDR(p, hhdr) { register hdr ** _ha; GET_HDR_ADDR(p, _ha); \
+ *_ha = (hhdr); }
+# define HDR(p) GC_find_header((ptr_t)(p))
+# endif
+
+/* Is the result a forwarding address to someplace closer to the */
+/* beginning of the block or NIL? */
+# define IS_FORWARDING_ADDR_OR_NIL(hhdr) ((size_t) (hhdr) <= MAX_JUMP)
+
+/* Get an HBLKSIZE aligned address closer to the beginning of the block */
+/* h. Assumes hhdr == HDR(h) and IS_FORWARDING_ADDR(hhdr). */
+# define FORWARDED_ADDR(h, hhdr) ((struct hblk *)(h) - (size_t)(hhdr))
+# endif /* GC_HEADERS_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/private/gc_locks.h b/tools/build/v2/engine/boehm_gc/include/private/gc_locks.h
new file mode 100644
index 0000000000..d7c83b07b9
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/gc_locks.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
+ *
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#ifndef GC_LOCKS_H
+#define GC_LOCKS_H
+
+/*
+ * Mutual exclusion between allocator/collector routines.
+ * Needed if there is more than one allocator thread.
+ * DCL_LOCK_STATE declares any local variables needed by LOCK and UNLOCK.
+ *
+ * Note that I_HOLD_LOCK and I_DONT_HOLD_LOCK are used only positively
+ * in assertions, and may return TRUE in the "dont know" case.
+ */
+# ifdef THREADS
+# include <atomic_ops.h>
+
+ void GC_noop1(word);
+# ifdef PCR
+# include <base/PCR_Base.h>
+# include <th/PCR_Th.h>
+ extern PCR_Th_ML GC_allocate_ml;
+# define DCL_LOCK_STATE \
+ PCR_ERes GC_fastLockRes; PCR_sigset_t GC_old_sig_mask
+# define LOCK() PCR_Th_ML_Acquire(&GC_allocate_ml)
+# define UNLOCK() PCR_Th_ML_Release(&GC_allocate_ml)
+# endif
+
+# if !defined(AO_HAVE_test_and_set_acquire) && defined(GC_PTHREADS)
+# define USE_PTHREAD_LOCKS
+# endif
+
+# if defined(GC_WIN32_THREADS) && defined(GC_PTHREADS)
+# define USE_PTHREAD_LOCKS
+# endif
+
+# if defined(GC_WIN32_THREADS) && !defined(USE_PTHREAD_LOCKS)
+# include <windows.h>
+# define NO_THREAD (DWORD)(-1)
+ extern DWORD GC_lock_holder;
+ GC_API CRITICAL_SECTION GC_allocate_ml;
+# ifdef GC_ASSERTIONS
+# define UNCOND_LOCK() \
+ { EnterCriticalSection(&GC_allocate_ml); \
+ SET_LOCK_HOLDER(); }
+# define UNCOND_UNLOCK() \
+ { GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \
+ LeaveCriticalSection(&GC_allocate_ml); }
+# else
+# define UNCOND_LOCK() EnterCriticalSection(&GC_allocate_ml);
+# define UNCOND_UNLOCK() LeaveCriticalSection(&GC_allocate_ml);
+# endif /* !GC_ASSERTIONS */
+# define SET_LOCK_HOLDER() GC_lock_holder = GetCurrentThreadId()
+# define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD
+# define I_HOLD_LOCK() (!GC_need_to_lock \
+ || GC_lock_holder == GetCurrentThreadId())
+# define I_DONT_HOLD_LOCK() (!GC_need_to_lock \
+ || GC_lock_holder != GetCurrentThreadId())
+# elif defined(GC_PTHREADS)
+# include <pthread.h>
+
+ /* Posix allows pthread_t to be a struct, though it rarely is. */
+ /* Unfortunately, we need to use a pthread_t to index a data */
+ /* structure. It also helps if comparisons don't involve a */
+ /* function call. Hence we introduce platform-dependent macros */
+ /* to compare pthread_t ids and to map them to integers. */
+ /* the mapping to integers does not need to result in different */
+ /* integers for each thread, though that should be true as much */
+ /* as possible. */
+ /* Refine to exclude platforms on which pthread_t is struct */
+# if !defined(GC_WIN32_PTHREADS)
+# define NUMERIC_THREAD_ID(id) ((unsigned long)(id))
+# define THREAD_EQUAL(id1, id2) ((id1) == (id2))
+# define NUMERIC_THREAD_ID_UNIQUE
+# else
+# if defined(GC_WIN32_PTHREADS)
+# define NUMERIC_THREAD_ID(id) ((unsigned long)(id.p))
+ /* Using documented internal details of win32_pthread library. */
+ /* Faster than pthread_equal(). Should not change with */
+ /* future versions of win32_pthread library. */
+# define THREAD_EQUAL(id1, id2) ((id1.p == id2.p) && (id1.x == id2.x))
+# undef NUMERIC_THREAD_ID_UNIQUE
+# else
+ /* Generic definitions that always work, but will result in */
+ /* poor performance and weak assertion checking. */
+# define NUMERIC_THREAD_ID(id) 1l
+# define THREAD_EQUAL(id1, id2) pthread_equal(id1, id2)
+# undef NUMERIC_THREAD_ID_UNIQUE
+# endif
+# endif
+# define NO_THREAD (-1l)
+ /* != NUMERIC_THREAD_ID(pthread_self()) for any thread */
+
+# if !defined(THREAD_LOCAL_ALLOC) && !defined(USE_PTHREAD_LOCKS)
+ /* In the THREAD_LOCAL_ALLOC case, the allocation lock tends to */
+ /* be held for long periods, if it is held at all. Thus spinning */
+ /* and sleeping for fixed periods are likely to result in */
+ /* significant wasted time. We thus rely mostly on queued locks. */
+# define USE_SPIN_LOCK
+ extern volatile AO_TS_t GC_allocate_lock;
+ extern void GC_lock(void);
+ /* Allocation lock holder. Only set if acquired by client through */
+ /* GC_call_with_alloc_lock. */
+# ifdef GC_ASSERTIONS
+# define UNCOND_LOCK() \
+ { if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \
+ GC_lock(); \
+ SET_LOCK_HOLDER(); }
+# define UNCOND_UNLOCK() \
+ { GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \
+ AO_CLEAR(&GC_allocate_lock); }
+# else
+# define UNCOND_LOCK() \
+ { if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \
+ GC_lock(); }
+# define UNCOND_UNLOCK() \
+ AO_CLEAR(&GC_allocate_lock)
+# endif /* !GC_ASSERTIONS */
+# else /* THREAD_LOCAL_ALLOC || USE_PTHREAD_LOCKS */
+# ifndef USE_PTHREAD_LOCKS
+# define USE_PTHREAD_LOCKS
+# endif
+# endif /* THREAD_LOCAL_ALLOC || USE_PTHREAD_LOCK */
+# ifdef USE_PTHREAD_LOCKS
+# include <pthread.h>
+ extern pthread_mutex_t GC_allocate_ml;
+# ifdef GC_ASSERTIONS
+# define UNCOND_LOCK() \
+ { GC_lock(); \
+ SET_LOCK_HOLDER(); }
+# define UNCOND_UNLOCK() \
+ { GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \
+ pthread_mutex_unlock(&GC_allocate_ml); }
+# else /* !GC_ASSERTIONS */
+# if defined(NO_PTHREAD_TRYLOCK)
+# define UNCOND_LOCK() GC_lock();
+# else /* !defined(NO_PTHREAD_TRYLOCK) */
+# define UNCOND_LOCK() \
+ { if (0 != pthread_mutex_trylock(&GC_allocate_ml)) GC_lock(); }
+# endif
+# define UNCOND_UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
+# endif /* !GC_ASSERTIONS */
+# endif /* USE_PTHREAD_LOCKS */
+# define SET_LOCK_HOLDER() \
+ GC_lock_holder = NUMERIC_THREAD_ID(pthread_self())
+# define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD
+# define I_HOLD_LOCK() \
+ (!GC_need_to_lock || \
+ GC_lock_holder == NUMERIC_THREAD_ID(pthread_self()))
+# ifndef NUMERIC_THREAD_ID_UNIQUE
+# define I_DONT_HOLD_LOCK() 1 /* Conservatively say yes */
+# else
+# define I_DONT_HOLD_LOCK() \
+ (!GC_need_to_lock \
+ || GC_lock_holder != NUMERIC_THREAD_ID(pthread_self()))
+# endif
+ extern volatile GC_bool GC_collecting;
+# define ENTER_GC() GC_collecting = 1;
+# define EXIT_GC() GC_collecting = 0;
+ extern void GC_lock(void);
+ extern unsigned long GC_lock_holder;
+# ifdef GC_ASSERTIONS
+ extern unsigned long GC_mark_lock_holder;
+# endif
+# endif /* GC_PTHREADS with linux_threads.c implementation */
+
+
+# else /* !THREADS */
+# define LOCK()
+# define UNLOCK()
+# define SET_LOCK_HOLDER()
+# define UNSET_LOCK_HOLDER()
+# define I_HOLD_LOCK() TRUE
+# define I_DONT_HOLD_LOCK() TRUE
+ /* Used only in positive assertions or to test whether */
+ /* we still need to acaquire the lock. TRUE works in */
+ /* either case. */
+# endif /* !THREADS */
+
+#if defined(UNCOND_LOCK) && !defined(LOCK)
+ GC_API GC_bool GC_need_to_lock;
+ /* At least two thread running; need to lock. */
+# define LOCK() if (GC_need_to_lock) { UNCOND_LOCK(); }
+# define UNLOCK() if (GC_need_to_lock) { UNCOND_UNLOCK(); }
+#endif
+
+# ifndef ENTER_GC
+# define ENTER_GC()
+# define EXIT_GC()
+# endif
+
+# ifndef DCL_LOCK_STATE
+# define DCL_LOCK_STATE
+# endif
+
+#endif /* GC_LOCKS_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/private/gc_pmark.h b/tools/build/v2/engine/boehm_gc/include/private/gc_pmark.h
new file mode 100644
index 0000000000..36083970ac
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/gc_pmark.h
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+/* Private declarations of GC marker data structures and macros */
+
+/*
+ * Declarations of mark stack. Needed by marker and client supplied mark
+ * routines. Transitively include gc_priv.h.
+ * (Note that gc_priv.h should not be included before this, since this
+ * includes dbg_mlc.h, which wants to include gc_priv.h AFTER defining
+ * I_HIDE_POINTERS.)
+ */
+#ifndef GC_PMARK_H
+# define GC_PMARK_H
+
+# if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST)
+# include "dbg_mlc.h"
+# endif
+# ifndef GC_MARK_H
+# include "../gc_mark.h"
+# endif
+# ifndef GC_PRIVATE_H
+# include "gc_priv.h"
+# endif
+
+/* The real declarations of the following is in gc_priv.h, so that */
+/* we can avoid scanning the following table. */
+/*
+extern mark_proc GC_mark_procs[MAX_MARK_PROCS];
+*/
+
+/*
+ * Mark descriptor stuff that should remain private for now, mostly
+ * because it's hard to export WORDSZ without including gcconfig.h.
+ */
+# define BITMAP_BITS (WORDSZ - GC_DS_TAG_BITS)
+# define PROC(descr) \
+ (GC_mark_procs[((descr) >> GC_DS_TAG_BITS) & (GC_MAX_MARK_PROCS-1)])
+# define ENV(descr) \
+ ((descr) >> (GC_DS_TAG_BITS + GC_LOG_MAX_MARK_PROCS))
+# define MAX_ENV \
+ (((word)1 << (WORDSZ - GC_DS_TAG_BITS - GC_LOG_MAX_MARK_PROCS)) - 1)
+
+
+extern unsigned GC_n_mark_procs;
+
+/* Number of mark stack entries to discard on overflow. */
+#define GC_MARK_STACK_DISCARDS (INITIAL_MARK_STACK_SIZE/8)
+
+typedef struct GC_ms_entry {
+ ptr_t mse_start; /* First word of object */
+ GC_word mse_descr; /* Descriptor; low order two bits are tags, */
+ /* identifying the upper 30 bits as one of the */
+ /* following: */
+} mse;
+
+extern size_t GC_mark_stack_size;
+
+extern mse * GC_mark_stack_limit;
+
+#ifdef PARALLEL_MARK
+ extern mse * volatile GC_mark_stack_top;
+#else
+ extern mse * GC_mark_stack_top;
+#endif
+
+extern mse * GC_mark_stack;
+
+#ifdef PARALLEL_MARK
+ /*
+ * Allow multiple threads to participate in the marking process.
+ * This works roughly as follows:
+ * The main mark stack never shrinks, but it can grow.
+ *
+ * The initiating threads holds the GC lock, and sets GC_help_wanted.
+ *
+ * Other threads:
+ * 1) update helper_count (while holding mark_lock.)
+ * 2) allocate a local mark stack
+ * repeatedly:
+ * 3) Steal a global mark stack entry by atomically replacing
+ * its descriptor with 0.
+ * 4) Copy it to the local stack.
+ * 5) Mark on the local stack until it is empty, or
+ * it may be profitable to copy it back.
+ * 6) If necessary, copy local stack to global one,
+ * holding mark lock.
+ * 7) Stop when the global mark stack is empty.
+ * 8) decrement helper_count (holding mark_lock).
+ *
+ * This is an experiment to see if we can do something along the lines
+ * of the University of Tokyo SGC in a less intrusive, though probably
+ * also less performant, way.
+ */
+ void GC_do_parallel_mark();
+ /* inititate parallel marking. */
+
+ extern GC_bool GC_help_wanted; /* Protected by mark lock */
+ extern unsigned GC_helper_count; /* Number of running helpers. */
+ /* Protected by mark lock */
+ extern unsigned GC_active_count; /* Number of active helpers. */
+ /* Protected by mark lock */
+ /* May increase and decrease */
+ /* within each mark cycle. But */
+ /* once it returns to 0, it */
+ /* stays zero for the cycle. */
+ /* GC_mark_stack_top is also protected by mark lock. */
+ /*
+ * GC_notify_all_marker() is used when GC_help_wanted is first set,
+ * when the last helper becomes inactive,
+ * when something is added to the global mark stack, and just after
+ * GC_mark_no is incremented.
+ * This could be split into multiple CVs (and probably should be to
+ * scale to really large numbers of processors.)
+ */
+#endif /* PARALLEL_MARK */
+
+/* Return a pointer to within 1st page of object. */
+/* Set *new_hdr_p to corr. hdr. */
+ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p);
+
+mse * GC_signal_mark_stack_overflow(mse *msp);
+
+/* Push the object obj with corresponding heap block header hhdr onto */
+/* the mark stack. */
+# define PUSH_OBJ(obj, hhdr, mark_stack_top, mark_stack_limit) \
+{ \
+ register word _descr = (hhdr) -> hb_descr; \
+ \
+ if (_descr != 0) { \
+ mark_stack_top++; \
+ if (mark_stack_top >= mark_stack_limit) { \
+ mark_stack_top = GC_signal_mark_stack_overflow(mark_stack_top); \
+ } \
+ mark_stack_top -> mse_start = (obj); \
+ mark_stack_top -> mse_descr = _descr; \
+ } \
+}
+
+/* Push the contents of current onto the mark stack if it is a valid */
+/* ptr to a currently unmarked object. Mark it. */
+/* If we assumed a standard-conforming compiler, we could probably */
+/* generate the exit_label transparently. */
+# define PUSH_CONTENTS(current, mark_stack_top, mark_stack_limit, \
+ source, exit_label) \
+{ \
+ hdr * my_hhdr; \
+ \
+ HC_GET_HDR(current, my_hhdr, source, exit_label); \
+ PUSH_CONTENTS_HDR(current, mark_stack_top, mark_stack_limit, \
+ source, exit_label, my_hhdr, TRUE); \
+exit_label: ; \
+}
+
+/* Set mark bit, exit if it was already set. */
+
+# ifdef USE_MARK_BITS
+# ifdef PARALLEL_MARK
+ /* The following may fail to exit even if the bit was already set. */
+ /* For our uses, that's benign: */
+# define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \
+ { \
+ if (!(*(addr) & (mask))) { \
+ AO_or((AO_t *)(addr), (mask); \
+ } else { \
+ goto label; \
+ } \
+ }
+# else
+# define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \
+ { \
+ word old = *(addr); \
+ word my_bits = (bits); \
+ if (old & my_bits) goto exit_label; \
+ *(addr) = (old | my_bits); \
+ }
+# endif /* !PARALLEL_MARK */
+# define SET_MARK_BIT_EXIT_IF_SET(hhdr,bit_no,exit_label) \
+ { \
+ word * mark_word_addr = hhdr -> hb_marks + divWORDSZ(bit_no); \
+ \
+ OR_WORD_EXIT_IF_SET(mark_word_addr, (word)1 << modWORDSZ(bit_no), \
+ exit_label); \
+ }
+# endif
+
+
+#ifdef USE_MARK_BYTES
+# if defined(I386) && defined(__GNUC__)
+# define LONG_MULT(hprod, lprod, x, y) { \
+ asm("mull %2" : "=a"(lprod), "=d"(hprod) : "g"(y), "0"(x)); \
+ }
+# else /* No in-line X86 assembly code */
+# define LONG_MULT(hprod, lprod, x, y) { \
+ unsigned long long prod = (unsigned long long)x \
+ * (unsigned long long)y; \
+ hprod = prod >> 32; \
+ lprod = (unsigned32)prod; \
+ }
+# endif
+
+ /* There is a race here, and we may set */
+ /* the bit twice in the concurrent case. This can result in the */
+ /* object being pushed twice. But that's only a performance issue. */
+# define SET_MARK_BIT_EXIT_IF_SET(hhdr,bit_no,exit_label) \
+ { \
+ char * mark_byte_addr = (char *)hhdr -> hb_marks + (bit_no); \
+ char mark_byte = *mark_byte_addr; \
+ \
+ if (mark_byte) goto exit_label; \
+ *mark_byte_addr = 1; \
+ }
+#endif /* USE_MARK_BYTES */
+
+#ifdef PARALLEL_MARK
+# define INCR_MARKS(hhdr) \
+ AO_store(&(hhdr -> hb_n_marks), AO_load(&(hhdr -> hb_n_marks))+1);
+#else
+# define INCR_MARKS(hhdr) ++(hhdr -> hb_n_marks)
+#endif
+
+#ifdef ENABLE_TRACE
+# define TRACE(source, cmd) \
+ if (GC_trace_addr != 0 && (ptr_t)(source) == GC_trace_addr) cmd
+# define TRACE_TARGET(target, cmd) \
+ if (GC_trace_addr != 0 && (target) == *(ptr_t *)GC_trace_addr) cmd
+#else
+# define TRACE(source, cmd)
+# define TRACE_TARGET(source, cmd)
+#endif
+/* If the mark bit corresponding to current is not set, set it, and */
+/* push the contents of the object on the mark stack. Current points */
+/* to the bginning of the object. We rely on the fact that the */
+/* preceding header calculation will succeed for a pointer past the */
+/* forst page of an object, only if it is in fact a valid pointer */
+/* to the object. Thus we can omit the otherwise necessary tests */
+/* here. Note in particular tha the "displ" value is the displacement */
+/* from the beggining of the heap block, which may itself be in the */
+/* interior of a large object. */
+#ifdef MARK_BIT_PER_GRANULE
+# define PUSH_CONTENTS_HDR(current, mark_stack_top, mark_stack_limit, \
+ source, exit_label, hhdr, do_offset_check) \
+{ \
+ size_t displ = HBLKDISPL(current); /* Displacement in block; in bytes. */\
+ /* displ is always within range. If current doesn't point to */ \
+ /* first block, then we are in the all_interior_pointers case, and */ \
+ /* it is safe to use any displacement value. */ \
+ size_t gran_displ = BYTES_TO_GRANULES(displ); \
+ size_t gran_offset = hhdr -> hb_map[gran_displ]; \
+ size_t byte_offset = displ & (GRANULE_BYTES - 1); \
+ ptr_t base = current; \
+ /* The following always fails for large block references. */ \
+ if (EXPECT((gran_offset | byte_offset) != 0, FALSE)) { \
+ if (hhdr -> hb_large_block) { \
+ /* gran_offset is bogus. */ \
+ size_t obj_displ; \
+ base = (ptr_t)(hhdr -> hb_block); \
+ obj_displ = (ptr_t)(current) - base; \
+ if (obj_displ != displ) { \
+ GC_ASSERT(obj_displ < hhdr -> hb_sz); \
+ /* Must be in all_interior_pointer case, not first block */ \
+ /* already did validity check on cache miss. */ \
+ ; \
+ } else { \
+ if (do_offset_check && !GC_valid_offsets[obj_displ]) { \
+ GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \
+ goto exit_label; \
+ } \
+ } \
+ gran_displ = 0; \
+ GC_ASSERT(hhdr -> hb_sz > HBLKSIZE || \
+ hhdr -> hb_block == HBLKPTR(current)); \
+ GC_ASSERT((ptr_t)(hhdr -> hb_block) <= (ptr_t) current); \
+ } else { \
+ size_t obj_displ = GRANULES_TO_BYTES(gran_offset) \
+ + byte_offset; \
+ if (do_offset_check && !GC_valid_offsets[obj_displ]) { \
+ GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \
+ goto exit_label; \
+ } \
+ gran_displ -= gran_offset; \
+ base -= obj_displ; \
+ } \
+ } \
+ GC_ASSERT(hhdr == GC_find_header(base)); \
+ GC_ASSERT(gran_displ % BYTES_TO_GRANULES(hhdr -> hb_sz) == 0); \
+ TRACE(source, GC_log_printf("GC:%d: passed validity tests\n",GC_gc_no)); \
+ SET_MARK_BIT_EXIT_IF_SET(hhdr, gran_displ, exit_label); \
+ TRACE(source, GC_log_printf("GC:%d: previously unmarked\n",GC_gc_no)); \
+ TRACE_TARGET(base, \
+ GC_log_printf("GC:%d: marking %p from %p instead\n", GC_gc_no, \
+ base, source)); \
+ INCR_MARKS(hhdr); \
+ GC_STORE_BACK_PTR((ptr_t)source, base); \
+ PUSH_OBJ(base, hhdr, mark_stack_top, mark_stack_limit); \
+}
+#endif /* MARK_BIT_PER_GRANULE */
+
+#ifdef MARK_BIT_PER_OBJ
+# define PUSH_CONTENTS_HDR(current, mark_stack_top, mark_stack_limit, \
+ source, exit_label, hhdr, do_offset_check) \
+{ \
+ size_t displ = HBLKDISPL(current); /* Displacement in block; in bytes. */\
+ unsigned32 low_prod, high_prod, offset_fraction; \
+ unsigned32 inv_sz = hhdr -> hb_inv_sz; \
+ ptr_t base = current; \
+ LONG_MULT(high_prod, low_prod, displ, inv_sz); \
+ /* product is > and within sz_in_bytes of displ * sz_in_bytes * 2**32 */ \
+ if (EXPECT(low_prod >> 16 != 0, FALSE)) { \
+ FIXME: fails if offset is a multiple of HBLKSIZE which becomes 0 \
+ if (inv_sz == LARGE_INV_SZ) { \
+ size_t obj_displ; \
+ base = (ptr_t)(hhdr -> hb_block); \
+ obj_displ = (ptr_t)(current) - base; \
+ if (obj_displ != displ) { \
+ GC_ASSERT(obj_displ < hhdr -> hb_sz); \
+ /* Must be in all_interior_pointer case, not first block */ \
+ /* already did validity check on cache miss. */ \
+ ; \
+ } else { \
+ if (do_offset_check && !GC_valid_offsets[obj_displ]) { \
+ GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \
+ goto exit_label; \
+ } \
+ } \
+ GC_ASSERT(hhdr -> hb_sz > HBLKSIZE || \
+ hhdr -> hb_block == HBLKPTR(current)); \
+ GC_ASSERT((ptr_t)(hhdr -> hb_block) < (ptr_t) current); \
+ } else { \
+ /* Accurate enough if HBLKSIZE <= 2**15. */ \
+ GC_ASSERT(HBLKSIZE <= (1 << 15)); \
+ size_t obj_displ = (((low_prod >> 16) + 1) * (hhdr -> hb_sz)) >> 16; \
+ if (do_offset_check && !GC_valid_offsets[obj_displ]) { \
+ GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \
+ goto exit_label; \
+ } \
+ base -= obj_displ; \
+ } \
+ } \
+ /* May get here for pointer to start of block not at */ \
+ /* beginning of object. If so, it's valid, and we're fine. */ \
+ GC_ASSERT(high_prod >= 0 && high_prod <= HBLK_OBJS(hhdr -> hb_sz)); \
+ TRACE(source, GC_log_printf("GC:%d: passed validity tests\n",GC_gc_no)); \
+ SET_MARK_BIT_EXIT_IF_SET(hhdr, high_prod, exit_label); \
+ TRACE(source, GC_log_printf("GC:%d: previously unmarked\n",GC_gc_no)); \
+ TRACE_TARGET(base, \
+ GC_log_printf("GC:%d: marking %p from %p instead\n", GC_gc_no, \
+ base, source)); \
+ INCR_MARKS(hhdr); \
+ GC_STORE_BACK_PTR((ptr_t)source, base); \
+ PUSH_OBJ(base, hhdr, mark_stack_top, mark_stack_limit); \
+}
+#endif /* MARK_BIT_PER_OBJ */
+
+#if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)
+# define PUSH_ONE_CHECKED_STACK(p, source) \
+ GC_mark_and_push_stack(p, (ptr_t)(source))
+#else
+# define PUSH_ONE_CHECKED_STACK(p, source) \
+ GC_mark_and_push_stack(p)
+#endif
+
+/*
+ * Push a single value onto mark stack. Mark from the object pointed to by p.
+ * Invoke FIXUP_POINTER(p) before any further processing.
+ * P is considered valid even if it is an interior pointer.
+ * Previously marked objects are not pushed. Hence we make progress even
+ * if the mark stack overflows.
+ */
+
+# if NEED_FIXUP_POINTER
+ /* Try both the raw version and the fixed up one. */
+# define GC_PUSH_ONE_STACK(p, source) \
+ if ((p) >= (ptr_t)GC_least_plausible_heap_addr \
+ && (p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
+ PUSH_ONE_CHECKED_STACK(p, source); \
+ } \
+ FIXUP_POINTER(p); \
+ if ((p) >= (ptr_t)GC_least_plausible_heap_addr \
+ && (p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
+ PUSH_ONE_CHECKED_STACK(p, source); \
+ }
+# else /* !NEED_FIXUP_POINTER */
+# define GC_PUSH_ONE_STACK(p, source) \
+ if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \
+ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
+ PUSH_ONE_CHECKED_STACK(p, source); \
+ }
+# endif
+
+
+/*
+ * As above, but interior pointer recognition as for
+ * normal heap pointers.
+ */
+# define GC_PUSH_ONE_HEAP(p,source) \
+ FIXUP_POINTER(p); \
+ if ((p) >= (ptr_t)GC_least_plausible_heap_addr \
+ && (p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
+ GC_mark_stack_top = GC_mark_and_push( \
+ (void *)(p), GC_mark_stack_top, \
+ GC_mark_stack_limit, (void * *)(source)); \
+ }
+
+/* Mark starting at mark stack entry top (incl.) down to */
+/* mark stack entry bottom (incl.). Stop after performing */
+/* about one page worth of work. Return the new mark stack */
+/* top entry. */
+mse * GC_mark_from(mse * top, mse * bottom, mse *limit);
+
+#define MARK_FROM_MARK_STACK() \
+ GC_mark_stack_top = GC_mark_from(GC_mark_stack_top, \
+ GC_mark_stack, \
+ GC_mark_stack + GC_mark_stack_size);
+
+/*
+ * Mark from one finalizable object using the specified
+ * mark proc. May not mark the object pointed to by
+ * real_ptr. That is the job of the caller, if appropriate.
+ * Note that this is called with the mutator running, but
+ * with us holding the allocation lock. This is safe only if the
+ * mutator needs tha allocation lock to reveal hidden pointers.
+ * FIXME: Why do we need the GC_mark_state test below?
+ */
+# define GC_MARK_FO(real_ptr, mark_proc) \
+{ \
+ (*(mark_proc))(real_ptr); \
+ while (!GC_mark_stack_empty()) MARK_FROM_MARK_STACK(); \
+ if (GC_mark_state != MS_NONE) { \
+ GC_set_mark_bit(real_ptr); \
+ while (!GC_mark_some((ptr_t)0)) {} \
+ } \
+}
+
+extern GC_bool GC_mark_stack_too_small;
+ /* We need a larger mark stack. May be */
+ /* set by client supplied mark routines.*/
+
+typedef int mark_state_t; /* Current state of marking, as follows:*/
+ /* Used to remember where we are during */
+ /* concurrent marking. */
+
+ /* We say something is dirty if it was */
+ /* written since the last time we */
+ /* retrieved dirty bits. We say it's */
+ /* grungy if it was marked dirty in the */
+ /* last set of bits we retrieved. */
+
+ /* Invariant I: all roots and marked */
+ /* objects p are either dirty, or point */
+ /* to objects q that are either marked */
+ /* or a pointer to q appears in a range */
+ /* on the mark stack. */
+
+# define MS_NONE 0 /* No marking in progress. I holds. */
+ /* Mark stack is empty. */
+
+# define MS_PUSH_RESCUERS 1 /* Rescuing objects are currently */
+ /* being pushed. I holds, except */
+ /* that grungy roots may point to */
+ /* unmarked objects, as may marked */
+ /* grungy objects above scan_ptr. */
+
+# define MS_PUSH_UNCOLLECTABLE 2
+ /* I holds, except that marked */
+ /* uncollectable objects above scan_ptr */
+ /* may point to unmarked objects. */
+ /* Roots may point to unmarked objects */
+
+# define MS_ROOTS_PUSHED 3 /* I holds, mark stack may be nonempty */
+
+# define MS_PARTIALLY_INVALID 4 /* I may not hold, e.g. because of M.S. */
+ /* overflow. However marked heap */
+ /* objects below scan_ptr point to */
+ /* marked or stacked objects. */
+
+# define MS_INVALID 5 /* I may not hold. */
+
+extern mark_state_t GC_mark_state;
+
+#endif /* GC_PMARK_H */
+
diff --git a/tools/build/v2/engine/boehm_gc/include/private/gc_priv.h b/tools/build/v2/engine/boehm_gc/include/private/gc_priv.h
new file mode 100644
index 0000000000..ec93ffea9c
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/gc_priv.h
@@ -0,0 +1,2040 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
+ *
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+
+# ifndef GC_PRIVATE_H
+# define GC_PRIVATE_H
+
+# include <stdlib.h>
+# if !(defined( sony_news ) )
+# include <stddef.h>
+# endif
+
+#ifdef DGUX
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/resource.h>
+#endif /* DGUX */
+
+#ifdef BSD_TIME
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/resource.h>
+#endif /* BSD_TIME */
+
+#ifdef PARALLEL_MARK
+# define AO_REQUIRE_CAS
+#endif
+
+#ifndef _GC_H
+# include "../gc.h"
+#endif
+
+#ifndef GC_TINY_FL_H
+# include "../gc_tiny_fl.h"
+#endif
+
+#ifndef GC_MARK_H
+# include "../gc_mark.h"
+#endif
+
+typedef GC_word word;
+typedef GC_signed_word signed_word;
+typedef unsigned int unsigned32;
+
+typedef int GC_bool;
+# define TRUE 1
+# define FALSE 0
+
+typedef char * ptr_t; /* A generic pointer to which we can add */
+ /* byte displacements and which can be used */
+ /* for address comparisons. */
+
+# ifndef GCCONFIG_H
+# include "gcconfig.h"
+# endif
+
+# ifndef HEADERS_H
+# include "gc_hdrs.h"
+# endif
+
+#if __GNUC__ >= 3
+# define EXPECT(expr, outcome) __builtin_expect(expr,outcome)
+ /* Equivalent to (expr), but predict that usually (expr)==outcome. */
+# define INLINE inline
+#else
+# define EXPECT(expr, outcome) (expr)
+# define INLINE
+#endif /* __GNUC__ */
+
+# ifndef GC_LOCKS_H
+# include "gc_locks.h"
+# endif
+
+# ifdef STACK_GROWS_DOWN
+# define COOLER_THAN >
+# define HOTTER_THAN <
+# define MAKE_COOLER(x,y) if ((x)+(y) > (x)) {(x) += (y);} \
+ else {(x) = (ptr_t)ONES;}
+# define MAKE_HOTTER(x,y) (x) -= (y)
+# else
+# define COOLER_THAN <
+# define HOTTER_THAN >
+# define MAKE_COOLER(x,y) if ((x)-(y) < (x)) {(x) -= (y);} else {(x) = 0;}
+# define MAKE_HOTTER(x,y) (x) += (y)
+# endif
+
+#if defined(AMIGA) && defined(__SASC)
+# define GC_FAR __far
+#else
+# define GC_FAR
+#endif
+
+
+/*********************************/
+/* */
+/* Definitions for conservative */
+/* collector */
+/* */
+/*********************************/
+
+/*********************************/
+/* */
+/* Easily changeable parameters */
+/* */
+/*********************************/
+
+/* #define STUBBORN_ALLOC */
+ /* Enable stubborm allocation, and thus a limited */
+ /* form of incremental collection w/o dirty bits. */
+
+/* #define ALL_INTERIOR_POINTERS */
+ /* Forces all pointers into the interior of an */
+ /* object to be considered valid. Also causes the */
+ /* sizes of all objects to be inflated by at least */
+ /* one byte. This should suffice to guarantee */
+ /* that in the presence of a compiler that does */
+ /* not perform garbage-collector-unsafe */
+ /* optimizations, all portable, strictly ANSI */
+ /* conforming C programs should be safely usable */
+ /* with malloc replaced by GC_malloc and free */
+ /* calls removed. There are several disadvantages: */
+ /* 1. There are probably no interesting, portable, */
+ /* strictly ANSI conforming C programs. */
+ /* 2. This option makes it hard for the collector */
+ /* to allocate space that is not ``pointed to'' */
+ /* by integers, etc. Under SunOS 4.X with a */
+ /* statically linked libc, we empiricaly */
+ /* observed that it would be difficult to */
+ /* allocate individual objects larger than 100K. */
+ /* Even if only smaller objects are allocated, */
+ /* more swap space is likely to be needed. */
+ /* Fortunately, much of this will never be */
+ /* touched. */
+ /* If you can easily avoid using this option, do. */
+ /* If not, try to keep individual objects small. */
+ /* This is now really controlled at startup, */
+ /* through GC_all_interior_pointers. */
+
+
+#define GC_INVOKE_FINALIZERS() GC_notify_or_invoke_finalizers()
+
+#if !defined(DONT_ADD_BYTE_AT_END)
+# define EXTRA_BYTES GC_all_interior_pointers
+# define MAX_EXTRA_BYTES 1
+#else
+# define EXTRA_BYTES 0
+# define MAX_EXTRA_BYTES 0
+#endif
+
+
+# ifndef LARGE_CONFIG
+# define MINHINCR 16 /* Minimum heap increment, in blocks of HBLKSIZE */
+ /* Must be multiple of largest page size. */
+# define MAXHINCR 2048 /* Maximum heap increment, in blocks */
+# else
+# define MINHINCR 64
+# define MAXHINCR 4096
+# endif
+
+# define TIME_LIMIT 50 /* We try to keep pause times from exceeding */
+ /* this by much. In milliseconds. */
+
+# define BL_LIMIT GC_black_list_spacing
+ /* If we need a block of N bytes, and we have */
+ /* a block of N + BL_LIMIT bytes available, */
+ /* and N > BL_LIMIT, */
+ /* but all possible positions in it are */
+ /* blacklisted, we just use it anyway (and */
+ /* print a warning, if warnings are enabled). */
+ /* This risks subsequently leaking the block */
+ /* due to a false reference. But not using */
+ /* the block risks unreasonable immediate */
+ /* heap growth. */
+
+/*********************************/
+/* */
+/* Stack saving for debugging */
+/* */
+/*********************************/
+
+#ifdef NEED_CALLINFO
+ struct callinfo {
+ word ci_pc; /* Caller, not callee, pc */
+# if NARGS > 0
+ word ci_arg[NARGS]; /* bit-wise complement to avoid retention */
+# endif
+# if (NFRAMES * (NARGS + 1)) % 2 == 1
+ /* Likely alignment problem. */
+ word ci_dummy;
+# endif
+ };
+#endif
+
+#ifdef SAVE_CALL_CHAIN
+
+/* Fill in the pc and argument information for up to NFRAMES of my */
+/* callers. Ignore my frame and my callers frame. */
+void GC_save_callers(struct callinfo info[NFRAMES]);
+
+void GC_print_callers(struct callinfo info[NFRAMES]);
+
+#endif
+
+
+/*********************************/
+/* */
+/* OS interface routines */
+/* */
+/*********************************/
+
+#ifdef BSD_TIME
+# undef CLOCK_TYPE
+# undef GET_TIME
+# undef MS_TIME_DIFF
+# define CLOCK_TYPE struct timeval
+# define GET_TIME(x) { struct rusage rusage; \
+ getrusage (RUSAGE_SELF, &rusage); \
+ x = rusage.ru_utime; }
+# define MS_TIME_DIFF(a,b) ((double) (a.tv_sec - b.tv_sec) * 1000.0 \
+ + (double) (a.tv_usec - b.tv_usec) / 1000.0)
+#else /* !BSD_TIME */
+# if defined(MSWIN32) || defined(MSWINCE)
+# include <windows.h>
+# include <winbase.h>
+# define CLOCK_TYPE DWORD
+# define GET_TIME(x) x = GetTickCount()
+# define MS_TIME_DIFF(a,b) ((long)((a)-(b)))
+# else /* !MSWIN32, !MSWINCE, !BSD_TIME */
+# include <time.h>
+# if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4)
+ clock_t clock(); /* Not in time.h, where it belongs */
+# endif
+# if defined(FREEBSD) && !defined(CLOCKS_PER_SEC)
+# include <machine/limits.h>
+# define CLOCKS_PER_SEC CLK_TCK
+# endif
+# if !defined(CLOCKS_PER_SEC)
+# define CLOCKS_PER_SEC 1000000
+/*
+ * This is technically a bug in the implementation. ANSI requires that
+ * CLOCKS_PER_SEC be defined. But at least under SunOS4.1.1, it isn't.
+ * Also note that the combination of ANSI C and POSIX is incredibly gross
+ * here. The type clock_t is used by both clock() and times(). But on
+ * some machines these use different notions of a clock tick, CLOCKS_PER_SEC
+ * seems to apply only to clock. Hence we use it here. On many machines,
+ * including SunOS, clock actually uses units of microseconds (which are
+ * not really clock ticks).
+ */
+# endif
+# define CLOCK_TYPE clock_t
+# define GET_TIME(x) x = clock()
+# define MS_TIME_DIFF(a,b) ((unsigned long) \
+ (1000.0*(double)((a)-(b))/(double)CLOCKS_PER_SEC))
+# endif /* !MSWIN32 */
+#endif /* !BSD_TIME */
+
+/* We use bzero and bcopy internally. They may not be available. */
+# if defined(SPARC) && defined(SUNOS4)
+# define BCOPY_EXISTS
+# endif
+# if defined(M68K) && defined(AMIGA)
+# define BCOPY_EXISTS
+# endif
+# if defined(M68K) && defined(NEXT)
+# define BCOPY_EXISTS
+# endif
+# if defined(VAX)
+# define BCOPY_EXISTS
+# endif
+# if defined(AMIGA)
+# include <string.h>
+# define BCOPY_EXISTS
+# endif
+# if defined(DARWIN)
+# include <string.h>
+# define BCOPY_EXISTS
+# endif
+
+# ifndef BCOPY_EXISTS
+# include <string.h>
+# define BCOPY(x,y,n) memcpy(y, x, (size_t)(n))
+# define BZERO(x,n) memset(x, 0, (size_t)(n))
+# else
+# define BCOPY(x,y,n) bcopy((void *)(x),(void *)(y),(size_t)(n))
+# define BZERO(x,n) bzero((void *)(x),(size_t)(n))
+# endif
+
+/*
+ * Stop and restart mutator threads.
+ */
+# ifdef PCR
+# include "th/PCR_ThCtl.h"
+# define STOP_WORLD() \
+ PCR_ThCtl_SetExclusiveMode(PCR_ThCtl_ExclusiveMode_stopNormal, \
+ PCR_allSigsBlocked, \
+ PCR_waitForever)
+# define START_WORLD() \
+ PCR_ThCtl_SetExclusiveMode(PCR_ThCtl_ExclusiveMode_null, \
+ PCR_allSigsBlocked, \
+ PCR_waitForever);
+# else
+# if defined(GC_SOLARIS_THREADS) || defined(GC_WIN32_THREADS) \
+ || defined(GC_PTHREADS)
+ void GC_stop_world();
+ void GC_start_world();
+# define STOP_WORLD() GC_stop_world()
+# define START_WORLD() GC_start_world()
+# else
+# define STOP_WORLD()
+# define START_WORLD()
+# endif
+# endif
+
+/* Abandon ship */
+# ifdef PCR
+# define ABORT(s) PCR_Base_Panic(s)
+# else
+# ifdef SMALL_CONFIG
+# define ABORT(msg) abort()
+# else
+ GC_API void GC_abort(const char * msg);
+# define ABORT(msg) GC_abort(msg)
+# endif
+# endif
+
+/* Exit abnormally, but without making a mess (e.g. out of memory) */
+# ifdef PCR
+# define EXIT() PCR_Base_Exit(1,PCR_waitForever)
+# else
+# define EXIT() (void)exit(1)
+# endif
+
+/* Print warning message, e.g. almost out of memory. */
+# define WARN(msg,arg) (*GC_current_warn_proc)("GC Warning: " msg, (GC_word)(arg))
+extern GC_warn_proc GC_current_warn_proc;
+
+/* Get environment entry */
+#if !defined(NO_GETENV)
+# if defined(EMPTY_GETENV_RESULTS)
+ /* Workaround for a reputed Wine bug. */
+ static inline char * fixed_getenv(const char *name)
+ {
+ char * tmp = getenv(name);
+ if (tmp == 0 || strlen(tmp) == 0)
+ return 0;
+ return tmp;
+ }
+# define GETENV(name) fixed_getenv(name)
+# else
+# define GETENV(name) getenv(name)
+# endif
+#else
+# define GETENV(name) 0
+#endif
+
+#if defined(DARWIN)
+# if defined(POWERPC)
+# if CPP_WORDSZ == 32
+# define GC_THREAD_STATE_T ppc_thread_state_t
+# define GC_MACH_THREAD_STATE PPC_THREAD_STATE
+# define GC_MACH_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT
+# define GC_MACH_HEADER mach_header
+# define GC_MACH_SECTION section
+# else
+# define GC_THREAD_STATE_T ppc_thread_state64_t
+# define GC_MACH_THREAD_STATE PPC_THREAD_STATE64
+# define GC_MACH_THREAD_STATE_COUNT PPC_THREAD_STATE64_COUNT
+# define GC_MACH_HEADER mach_header_64
+# define GC_MACH_SECTION section_64
+# endif
+# elif defined(I386) || defined(X86_64)
+# if CPP_WORDSZ == 32
+# define GC_THREAD_STATE_T x86_thread_state32_t
+# define GC_MACH_THREAD_STATE x86_THREAD_STATE32
+# define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
+# define GC_MACH_HEADER mach_header
+# define GC_MACH_SECTION section
+# else
+# define GC_THREAD_STATE_T x86_thread_state64_t
+# define GC_MACH_THREAD_STATE x86_THREAD_STATE64
+# define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
+# define GC_MACH_HEADER mach_header_64
+# define GC_MACH_SECTION section_64
+# endif
+# else
+# error define GC_THREAD_STATE_T
+# define GC_MACH_THREAD_STATE MACHINE_THREAD_STATE
+# define GC_MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT
+# endif
+/* Try to work out the right way to access thread state structure members.
+ The structure has changed its definition in different Darwin versions.
+ This now defaults to the (older) names without __, thus hopefully,
+ not breaking any existing Makefile.direct builds. */
+# if defined (HAS_PPC_THREAD_STATE___R0) \
+ || defined (HAS_PPC_THREAD_STATE64___R0) \
+ || defined (HAS_X86_THREAD_STATE32___EAX) \
+ || defined (HAS_X86_THREAD_STATE64___RAX)
+# define THREAD_FLD(x) __ ## x
+# else
+# define THREAD_FLD(x) x
+# endif
+#endif
+
+/*********************************/
+/* */
+/* Word-size-dependent defines */
+/* */
+/*********************************/
+
+#if CPP_WORDSZ == 32
+# define WORDS_TO_BYTES(x) ((x)<<2)
+# define BYTES_TO_WORDS(x) ((x)>>2)
+# define LOGWL ((word)5) /* log[2] of CPP_WORDSZ */
+# define modWORDSZ(n) ((n) & 0x1f) /* n mod size of word */
+# if ALIGNMENT != 4
+# define UNALIGNED
+# endif
+#endif
+
+#if CPP_WORDSZ == 64
+# define WORDS_TO_BYTES(x) ((x)<<3)
+# define BYTES_TO_WORDS(x) ((x)>>3)
+# define LOGWL ((word)6) /* log[2] of CPP_WORDSZ */
+# define modWORDSZ(n) ((n) & 0x3f) /* n mod size of word */
+# if ALIGNMENT != 8
+# define UNALIGNED
+# endif
+#endif
+
+/* The first TINY_FREELISTS free lists correspond to the first */
+/* TINY_FREELISTS multiples of GRANULE_BYTES, i.e. we keep */
+/* separate free lists for each multiple of GRANULE_BYTES */
+/* up to (TINY_FREELISTS-1) * GRANULE_BYTES. After that they */
+/* may be spread out further. */
+#include "../gc_tiny_fl.h"
+#define GRANULE_BYTES GC_GRANULE_BYTES
+#define TINY_FREELISTS GC_TINY_FREELISTS
+
+#define WORDSZ ((word)CPP_WORDSZ)
+#define SIGNB ((word)1 << (WORDSZ-1))
+#define BYTES_PER_WORD ((word)(sizeof (word)))
+#define ONES ((word)(signed_word)(-1))
+#define divWORDSZ(n) ((n) >> LOGWL) /* divide n by size of word */
+
+#if GRANULE_BYTES == 8
+# define BYTES_TO_GRANULES(n) ((n)>>3)
+# define GRANULES_TO_BYTES(n) ((n)<<3)
+# if CPP_WORDSZ == 64
+# define GRANULES_TO_WORDS(n) (n)
+# elif CPP_WORDSZ == 32
+# define GRANULES_TO_WORDS(n) ((n)<<1)
+# else
+# define GRANULES_TO_WORDS(n) BYTES_TO_WORDS(GRANULES_TO_BYTES(n))
+# endif
+#elif GRANULE_BYTES == 16
+# define BYTES_TO_GRANULES(n) ((n)>>4)
+# define GRANULES_TO_BYTES(n) ((n)<<4)
+# if CPP_WORDSZ == 64
+# define GRANULES_TO_WORDS(n) ((n)<<1)
+# elif CPP_WORDSZ == 32
+# define GRANULES_TO_WORDS(n) ((n)<<2)
+# else
+# define GRANULES_TO_WORDS(n) BYTES_TO_WORDS(GRANULES_TO_BYTES(n))
+# endif
+#else
+# error Bad GRANULE_BYTES value
+#endif
+
+/*********************/
+/* */
+/* Size Parameters */
+/* */
+/*********************/
+
+/* heap block size, bytes. Should be power of 2 */
+
+#ifndef HBLKSIZE
+# ifdef SMALL_CONFIG
+# define CPP_LOG_HBLKSIZE 10
+# else
+# if (CPP_WORDSZ == 32) || (defined(HPUX) && defined(HP_PA))
+ /* HPUX/PA seems to use 4K pages with the 64 bit ABI */
+# define CPP_LOG_HBLKSIZE 12
+# else
+# define CPP_LOG_HBLKSIZE 13
+# endif
+# endif
+#else
+# if HBLKSIZE == 512
+# define CPP_LOG_HBLKSIZE 9
+# endif
+# if HBLKSIZE == 1024
+# define CPP_LOG_HBLKSIZE 10
+# endif
+# if HBLKSIZE == 2048
+# define CPP_LOG_HBLKSIZE 11
+# endif
+# if HBLKSIZE == 4096
+# define CPP_LOG_HBLKSIZE 12
+# endif
+# if HBLKSIZE == 8192
+# define CPP_LOG_HBLKSIZE 13
+# endif
+# if HBLKSIZE == 16384
+# define CPP_LOG_HBLKSIZE 14
+# endif
+# ifndef CPP_LOG_HBLKSIZE
+ --> fix HBLKSIZE
+# endif
+# undef HBLKSIZE
+#endif
+# define CPP_HBLKSIZE (1 << CPP_LOG_HBLKSIZE)
+# define LOG_HBLKSIZE ((size_t)CPP_LOG_HBLKSIZE)
+# define HBLKSIZE ((size_t)CPP_HBLKSIZE)
+
+
+/* max size objects supported by freelist (larger objects are */
+/* allocated directly with allchblk(), by rounding to the next */
+/* multiple of HBLKSIZE. */
+
+#define CPP_MAXOBJBYTES (CPP_HBLKSIZE/2)
+#define MAXOBJBYTES ((size_t)CPP_MAXOBJBYTES)
+#define CPP_MAXOBJWORDS BYTES_TO_WORDS(CPP_MAXOBJBYTES)
+#define MAXOBJWORDS ((size_t)CPP_MAXOBJWORDS)
+#define CPP_MAXOBJGRANULES BYTES_TO_GRANULES(CPP_MAXOBJBYTES)
+#define MAXOBJGRANULES ((size_t)CPP_MAXOBJGRANULES)
+
+# define divHBLKSZ(n) ((n) >> LOG_HBLKSIZE)
+
+# define HBLK_PTR_DIFF(p,q) divHBLKSZ((ptr_t)p - (ptr_t)q)
+ /* Equivalent to subtracting 2 hblk pointers. */
+ /* We do it this way because a compiler should */
+ /* find it hard to use an integer division */
+ /* instead of a shift. The bundled SunOS 4.1 */
+ /* o.w. sometimes pessimizes the subtraction to */
+ /* involve a call to .div. */
+
+# define modHBLKSZ(n) ((n) & (HBLKSIZE-1))
+
+# define HBLKPTR(objptr) ((struct hblk *)(((word) (objptr)) & ~(HBLKSIZE-1)))
+
+# define HBLKDISPL(objptr) (((size_t) (objptr)) & (HBLKSIZE-1))
+
+/* Round up byte allocation requests to integral number of words, etc. */
+# define ROUNDED_UP_WORDS(n) \
+ BYTES_TO_WORDS((n) + (WORDS_TO_BYTES(1) - 1 + EXTRA_BYTES))
+# define ROUNDED_UP_GRANULES(n) \
+ BYTES_TO_GRANULES((n) + (GRANULE_BYTES - 1 + EXTRA_BYTES))
+# if MAX_EXTRA_BYTES == 0
+# define SMALL_OBJ(bytes) EXPECT((bytes) <= (MAXOBJBYTES), 1)
+# else
+# define SMALL_OBJ(bytes) \
+ (EXPECT((bytes) <= (MAXOBJBYTES - MAX_EXTRA_BYTES), 1) || \
+ (bytes) <= (MAXOBJBYTES - EXTRA_BYTES))
+ /* This really just tests bytes <= MAXOBJBYTES - EXTRA_BYTES. */
+ /* But we try to avoid looking up EXTRA_BYTES. */
+# endif
+# define ADD_SLOP(bytes) ((bytes) + EXTRA_BYTES)
+# ifndef MIN_WORDS
+# define MIN_WORDS 2 /* FIXME: obsolete */
+# endif
+
+
+/*
+ * Hash table representation of sets of pages.
+ * Implements a map from aligned HBLKSIZE chunks of the address space to one
+ * bit each.
+ * This assumes it is OK to spuriously set bits, e.g. because multiple
+ * addresses are represented by a single location.
+ * Used by black-listing code, and perhaps by dirty bit maintenance code.
+ */
+
+# ifdef LARGE_CONFIG
+# define LOG_PHT_ENTRIES 20 /* Collisions likely at 1M blocks, */
+ /* which is >= 4GB. Each table takes */
+ /* 128KB, some of which may never be */
+ /* touched. */
+# else
+# ifdef SMALL_CONFIG
+# define LOG_PHT_ENTRIES 14 /* Collisions are likely if heap grows */
+ /* to more than 16K hblks = 64MB. */
+ /* Each hash table occupies 2K bytes. */
+# else /* default "medium" configuration */
+# define LOG_PHT_ENTRIES 16 /* Collisions are likely if heap grows */
+ /* to more than 64K hblks >= 256MB. */
+ /* Each hash table occupies 8K bytes. */
+ /* Even for somewhat smaller heaps, */
+ /* say half that, collisions may be an */
+ /* issue because we blacklist */
+ /* addresses outside the heap. */
+# endif
+# endif
+# define PHT_ENTRIES ((word)1 << LOG_PHT_ENTRIES)
+# define PHT_SIZE (PHT_ENTRIES >> LOGWL)
+typedef word page_hash_table[PHT_SIZE];
+
+# define PHT_HASH(addr) ((((word)(addr)) >> LOG_HBLKSIZE) & (PHT_ENTRIES - 1))
+
+# define get_pht_entry_from_index(bl, index) \
+ (((bl)[divWORDSZ(index)] >> modWORDSZ(index)) & 1)
+# define set_pht_entry_from_index(bl, index) \
+ (bl)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index)
+# define clear_pht_entry_from_index(bl, index) \
+ (bl)[divWORDSZ(index)] &= ~((word)1 << modWORDSZ(index))
+/* And a dumb but thread-safe version of set_pht_entry_from_index. */
+/* This sets (many) extra bits. */
+# define set_pht_entry_from_index_safe(bl, index) \
+ (bl)[divWORDSZ(index)] = ONES
+
+
+
+/********************************************/
+/* */
+/* H e a p B l o c k s */
+/* */
+/********************************************/
+
+/* heap block header */
+#define HBLKMASK (HBLKSIZE-1)
+
+#define MARK_BITS_PER_HBLK (HBLKSIZE/GRANULE_BYTES)
+ /* upper bound */
+ /* We allocate 1 bit per allocation granule. */
+ /* If MARK_BIT_PER_GRANULE is defined, we use */
+ /* every nth bit, where n is the number of */
+ /* allocation granules per object. If */
+ /* MARK_BIT_PER_OBJ is defined, we only use the */
+ /* initial group of mark bits, and it is safe */
+ /* to allocate smaller header for large objects. */
+
+# ifdef USE_MARK_BYTES
+# define MARK_BITS_SZ (MARK_BITS_PER_HBLK + 1)
+ /* Unlike the other case, this is in units of bytes. */
+ /* Since we force doubleword alignment, we need at most one */
+ /* mark bit per 2 words. But we do allocate and set one */
+ /* extra mark bit to avoid an explicit check for the */
+ /* partial object at the end of each block. */
+# else
+# define MARK_BITS_SZ (MARK_BITS_PER_HBLK/CPP_WORDSZ + 1)
+# endif
+
+#ifdef PARALLEL_MARK
+# include <atomic_ops.h>
+ typedef AO_t counter_t;
+#else
+ typedef size_t counter_t;
+#endif
+
+/* We maintain layout maps for heap blocks containing objects of a given */
+/* size. Each entry in this map describes a byte offset and has the */
+/* following type. */
+struct hblkhdr {
+ struct hblk * hb_next; /* Link field for hblk free list */
+ /* and for lists of chunks waiting to be */
+ /* reclaimed. */
+ struct hblk * hb_prev; /* Backwards link for free list. */
+ struct hblk * hb_block; /* The corresponding block. */
+ unsigned char hb_obj_kind;
+ /* Kind of objects in the block. Each kind */
+ /* identifies a mark procedure and a set of */
+ /* list headers. Sometimes called regions. */
+ unsigned char hb_flags;
+# define IGNORE_OFF_PAGE 1 /* Ignore pointers that do not */
+ /* point to the first page of */
+ /* this object. */
+# define WAS_UNMAPPED 2 /* This is a free block, which has */
+ /* been unmapped from the address */
+ /* space. */
+ /* GC_remap must be invoked on it */
+ /* before it can be reallocated. */
+ /* Only set with USE_MUNMAP. */
+# define FREE_BLK 4 /* Block is free, i.e. not in use. */
+ unsigned short hb_last_reclaimed;
+ /* Value of GC_gc_no when block was */
+ /* last allocated or swept. May wrap. */
+ /* For a free block, this is maintained */
+ /* only for USE_MUNMAP, and indicates */
+ /* when the header was allocated, or */
+ /* when the size of the block last */
+ /* changed. */
+ size_t hb_sz; /* If in use, size in bytes, of objects in the block. */
+ /* if free, the size in bytes of the whole block */
+ word hb_descr; /* object descriptor for marking. See */
+ /* mark.h. */
+# ifdef MARK_BIT_PER_OBJ
+ unsigned32 hb_inv_sz; /* A good upper bound for 2**32/hb_sz. */
+ /* For large objects, we use */
+ /* LARGE_INV_SZ. */
+# define LARGE_INV_SZ (1 << 16)
+# else
+ unsigned char hb_large_block;
+ short * hb_map; /* Essentially a table of remainders */
+ /* mod BYTES_TO_GRANULES(hb_sz), except */
+ /* for large blocks. See GC_obj_map. */
+# endif
+ counter_t hb_n_marks; /* Number of set mark bits, excluding */
+ /* the one always set at the end. */
+ /* Currently it is concurrently */
+ /* updated and hence only approximate. */
+ /* But a zero value does guarantee that */
+ /* the block contains no marked */
+ /* objects. */
+ /* Ensuring this property means that we */
+ /* never decrement it to zero during a */
+ /* collection, and hence the count may */
+ /* be one too high. Due to concurrent */
+ /* updates, an arbitrary number of */
+ /* increments, but not all of them (!) */
+ /* may be lost, hence it may in theory */
+ /* be much too low. */
+ /* The count may also be too high if */
+ /* multiple mark threads mark the */
+ /* same object due to a race. */
+ /* Without parallel marking, the count */
+ /* is accurate. */
+# ifdef USE_MARK_BYTES
+ union {
+ char _hb_marks[MARK_BITS_SZ];
+ /* The i'th byte is 1 if the object */
+ /* starting at granule i or object i is */
+ /* marked, 0 o.w. */
+ /* The mark bit for the "one past the */
+ /* end" object is always set to avoid a */
+ /* special case test in the marker. */
+ word dummy; /* Force word alignment of mark bytes. */
+ } _mark_byte_union;
+# define hb_marks _mark_byte_union._hb_marks
+# else
+ word hb_marks[MARK_BITS_SZ];
+# endif /* !USE_MARK_BYTES */
+};
+
+# define ANY_INDEX 23 /* "Random" mark bit index for assertions */
+
+/* heap block body */
+
+# define HBLK_WORDS (HBLKSIZE/sizeof(word))
+# define HBLK_GRANULES (HBLKSIZE/GRANULE_BYTES)
+
+/* The number of objects in a block dedicated to a certain size. */
+/* may erroneously yield zero (instead of one) for large objects. */
+# define HBLK_OBJS(sz_in_bytes) (HBLKSIZE/(sz_in_bytes))
+
+struct hblk {
+ char hb_body[HBLKSIZE];
+};
+
+# define HBLK_IS_FREE(hdr) (((hdr) -> hb_flags & FREE_BLK) != 0)
+
+# define OBJ_SZ_TO_BLOCKS(sz) divHBLKSZ(sz + HBLKSIZE-1)
+ /* Size of block (in units of HBLKSIZE) needed to hold objects of */
+ /* given sz (in bytes). */
+
+/* Object free list link */
+# define obj_link(p) (*(void **)(p))
+
+# define LOG_MAX_MARK_PROCS 6
+# define MAX_MARK_PROCS (1 << LOG_MAX_MARK_PROCS)
+
+/* Root sets. Logically private to mark_rts.c. But we don't want the */
+/* tables scanned, so we put them here. */
+/* MAX_ROOT_SETS is the maximum number of ranges that can be */
+/* registered as static roots. */
+# ifdef LARGE_CONFIG
+# define MAX_ROOT_SETS 4096
+# else
+ /* GCJ LOCAL: MAX_ROOT_SETS increased to permit more shared */
+ /* libraries to be loaded. */
+# define MAX_ROOT_SETS 1024
+# endif
+
+# define MAX_EXCLUSIONS (MAX_ROOT_SETS/4)
+/* Maximum number of segments that can be excluded from root sets. */
+
+/*
+ * Data structure for excluded static roots.
+ */
+struct exclusion {
+ ptr_t e_start;
+ ptr_t e_end;
+};
+
+/* Data structure for list of root sets. */
+/* We keep a hash table, so that we can filter out duplicate additions. */
+/* Under Win32, we need to do a better job of filtering overlaps, so */
+/* we resort to sequential search, and pay the price. */
+struct roots {
+ ptr_t r_start;
+ ptr_t r_end;
+# if !defined(MSWIN32) && !defined(MSWINCE)
+ struct roots * r_next;
+# endif
+ GC_bool r_tmp;
+ /* Delete before registering new dynamic libraries */
+};
+
+#if !defined(MSWIN32) && !defined(MSWINCE)
+ /* Size of hash table index to roots. */
+# define LOG_RT_SIZE 6
+# define RT_SIZE (1 << LOG_RT_SIZE) /* Power of 2, may be != MAX_ROOT_SETS */
+#endif
+
+/* Lists of all heap blocks and free lists */
+/* as well as other random data structures */
+/* that should not be scanned by the */
+/* collector. */
+/* These are grouped together in a struct */
+/* so that they can be easily skipped by the */
+/* GC_mark routine. */
+/* The ordering is weird to make GC_malloc */
+/* faster by keeping the important fields */
+/* sufficiently close together that a */
+/* single load of a base register will do. */
+/* Scalars that could easily appear to */
+/* be pointers are also put here. */
+/* The main fields should precede any */
+/* conditionally included fields, so that */
+/* gc_inl.h will work even if a different set */
+/* of macros is defined when the client is */
+/* compiled. */
+
+struct _GC_arrays {
+ word _heapsize; /* Heap size in bytes. */
+ word _max_heapsize;
+ word _requested_heapsize; /* Heap size due to explicit expansion */
+ ptr_t _last_heap_addr;
+ ptr_t _prev_heap_addr;
+ word _large_free_bytes;
+ /* Total bytes contained in blocks on large object free */
+ /* list. */
+ word _large_allocd_bytes;
+ /* Total number of bytes in allocated large objects blocks. */
+ /* For the purposes of this counter and the next one only, a */
+ /* large object is one that occupies a block of at least */
+ /* 2*HBLKSIZE. */
+ word _max_large_allocd_bytes;
+ /* Maximum number of bytes that were ever allocated in */
+ /* large object blocks. This is used to help decide when it */
+ /* is safe to split up a large block. */
+ word _bytes_allocd_before_gc;
+ /* Number of words allocated before this */
+ /* collection cycle. */
+# ifndef SEPARATE_GLOBALS
+ word _bytes_allocd;
+ /* Number of words allocated during this collection cycle */
+# endif
+ word _bytes_finalized;
+ /* Approximate number of bytes in objects (and headers) */
+ /* That became ready for finalization in the last */
+ /* collection. */
+ word _non_gc_bytes_at_gc;
+ /* Number of explicitly managed bytes of storage */
+ /* at last collection. */
+ word _bytes_freed;
+ /* Number of explicitly deallocated bytes of memory */
+ /* since last collection. */
+ word _finalizer_bytes_freed;
+ /* Bytes of memory explicitly deallocated while */
+ /* finalizers were running. Used to approximate mem. */
+ /* explicitly deallocated by finalizers. */
+ ptr_t _scratch_end_ptr;
+ ptr_t _scratch_last_end_ptr;
+ /* Used by headers.c, and can easily appear to point to */
+ /* heap. */
+ GC_mark_proc _mark_procs[MAX_MARK_PROCS];
+ /* Table of user-defined mark procedures. There is */
+ /* a small number of these, which can be referenced */
+ /* by DS_PROC mark descriptors. See gc_mark.h. */
+
+# ifndef SEPARATE_GLOBALS
+ void *_objfreelist[MAXOBJGRANULES+1];
+ /* free list for objects */
+ void *_aobjfreelist[MAXOBJGRANULES+1];
+ /* free list for atomic objs */
+# endif
+
+ void *_uobjfreelist[MAXOBJGRANULES+1];
+ /* uncollectable but traced objs */
+ /* objects on this and auobjfreelist */
+ /* are always marked, except during */
+ /* garbage collections. */
+# ifdef ATOMIC_UNCOLLECTABLE
+ void *_auobjfreelist[MAXOBJGRANULES+1];
+# endif
+ /* uncollectable but traced objs */
+
+ word _composite_in_use;
+ /* Number of words in accessible composite */
+ /* objects. */
+ word _atomic_in_use;
+ /* Number of words in accessible atomic */
+ /* objects. */
+# ifdef USE_MUNMAP
+ word _unmapped_bytes;
+# endif
+
+ size_t _size_map[MAXOBJBYTES+1];
+ /* Number of words to allocate for a given allocation request in */
+ /* bytes. */
+
+# ifdef STUBBORN_ALLOC
+ ptr_t _sobjfreelist[MAXOBJGRANULES+1];
+# endif
+ /* free list for immutable objects */
+# ifdef MARK_BIT_PER_GRANULE
+ short * _obj_map[MAXOBJGRANULES+1];
+ /* If not NIL, then a pointer to a map of valid */
+ /* object addresses. */
+ /* _obj_map[sz_in_granules][i] is */
+ /* i % sz_in_granules. */
+ /* This is now used purely to replace a */
+ /* division in the marker by a table lookup. */
+ /* _obj_map[0] is used for large objects and */
+ /* contains all nonzero entries. This gets us */
+ /* out of the marker fast path without an extra */
+ /* test. */
+# define MAP_LEN BYTES_TO_GRANULES(HBLKSIZE)
+# endif
+# define VALID_OFFSET_SZ HBLKSIZE
+ char _valid_offsets[VALID_OFFSET_SZ];
+ /* GC_valid_offsets[i] == TRUE ==> i */
+ /* is registered as a displacement. */
+ char _modws_valid_offsets[sizeof(word)];
+ /* GC_valid_offsets[i] ==> */
+ /* GC_modws_valid_offsets[i%sizeof(word)] */
+# ifdef STUBBORN_ALLOC
+ page_hash_table _changed_pages;
+ /* Stubborn object pages that were changes since last call to */
+ /* GC_read_changed. */
+ page_hash_table _prev_changed_pages;
+ /* Stubborn object pages that were changes before last call to */
+ /* GC_read_changed. */
+# endif
+# if defined(PROC_VDB) || defined(MPROTECT_VDB) || \
+ defined(GWW_VDB) || defined(MANUAL_VDB)
+ page_hash_table _grungy_pages; /* Pages that were dirty at last */
+ /* GC_read_dirty. */
+# endif
+# if defined(MPROTECT_VDB) || defined(MANUAL_VDB)
+ volatile page_hash_table _dirty_pages;
+ /* Pages dirtied since last GC_read_dirty. */
+# endif
+# if defined(PROC_VDB) || defined(GWW_VDB)
+ page_hash_table _written_pages; /* Pages ever dirtied */
+# endif
+# ifdef LARGE_CONFIG
+# if CPP_WORDSZ > 32
+# define MAX_HEAP_SECTS 4096 /* overflows at roughly 64 GB */
+# else
+# define MAX_HEAP_SECTS 768 /* Separately added heap sections. */
+# endif
+# else
+# ifdef SMALL_CONFIG
+# define MAX_HEAP_SECTS 128 /* Roughly 256MB (128*2048*1K) */
+# else
+# define MAX_HEAP_SECTS 384 /* Roughly 3GB */
+# endif
+# endif
+ struct HeapSect {
+ ptr_t hs_start; size_t hs_bytes;
+ } _heap_sects[MAX_HEAP_SECTS];
+# if defined(MSWIN32) || defined(MSWINCE)
+ ptr_t _heap_bases[MAX_HEAP_SECTS];
+ /* Start address of memory regions obtained from kernel. */
+# endif
+# ifdef MSWINCE
+ word _heap_lengths[MAX_HEAP_SECTS];
+ /* Commited lengths of memory regions obtained from kernel. */
+# endif
+ struct roots _static_roots[MAX_ROOT_SETS];
+# if !defined(MSWIN32) && !defined(MSWINCE)
+ struct roots * _root_index[RT_SIZE];
+# endif
+ struct exclusion _excl_table[MAX_EXCLUSIONS];
+ /* Block header index; see gc_headers.h */
+ bottom_index * _all_nils;
+ bottom_index * _top_index [TOP_SZ];
+#ifdef ENABLE_TRACE
+ ptr_t _trace_addr;
+#endif
+#ifdef SAVE_CALL_CHAIN
+ struct callinfo _last_stack[NFRAMES]; /* Stack at last garbage collection.*/
+ /* Useful for debugging mysterious */
+ /* object disappearances. */
+ /* In the multithreaded case, we */
+ /* currently only save the calling */
+ /* stack. */
+#endif
+};
+
+GC_API GC_FAR struct _GC_arrays GC_arrays;
+
+# ifndef SEPARATE_GLOBALS
+# define GC_objfreelist GC_arrays._objfreelist
+# define GC_aobjfreelist GC_arrays._aobjfreelist
+# define GC_bytes_allocd GC_arrays._bytes_allocd
+# endif
+# define GC_uobjfreelist GC_arrays._uobjfreelist
+# ifdef ATOMIC_UNCOLLECTABLE
+# define GC_auobjfreelist GC_arrays._auobjfreelist
+# endif
+# define GC_sobjfreelist GC_arrays._sobjfreelist
+# define GC_valid_offsets GC_arrays._valid_offsets
+# define GC_modws_valid_offsets GC_arrays._modws_valid_offsets
+# ifdef STUBBORN_ALLOC
+# define GC_changed_pages GC_arrays._changed_pages
+# define GC_prev_changed_pages GC_arrays._prev_changed_pages
+# endif
+# ifdef MARK_BIT_PER_GRANULE
+# define GC_obj_map GC_arrays._obj_map
+# endif
+# define GC_last_heap_addr GC_arrays._last_heap_addr
+# define GC_prev_heap_addr GC_arrays._prev_heap_addr
+# define GC_large_free_bytes GC_arrays._large_free_bytes
+# define GC_large_allocd_bytes GC_arrays._large_allocd_bytes
+# define GC_max_large_allocd_bytes GC_arrays._max_large_allocd_bytes
+# define GC_bytes_finalized GC_arrays._bytes_finalized
+# define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc
+# define GC_bytes_freed GC_arrays._bytes_freed
+# define GC_finalizer_bytes_freed GC_arrays._finalizer_bytes_freed
+# define GC_scratch_end_ptr GC_arrays._scratch_end_ptr
+# define GC_scratch_last_end_ptr GC_arrays._scratch_last_end_ptr
+# define GC_mark_procs GC_arrays._mark_procs
+# define GC_heapsize GC_arrays._heapsize
+# define GC_max_heapsize GC_arrays._max_heapsize
+# define GC_requested_heapsize GC_arrays._requested_heapsize
+# define GC_bytes_allocd_before_gc GC_arrays._bytes_allocd_before_gc
+# define GC_heap_sects GC_arrays._heap_sects
+# define GC_last_stack GC_arrays._last_stack
+#ifdef ENABLE_TRACE
+#define GC_trace_addr GC_arrays._trace_addr
+#endif
+# ifdef USE_MUNMAP
+# define GC_unmapped_bytes GC_arrays._unmapped_bytes
+# endif
+# if defined(MSWIN32) || defined(MSWINCE)
+# define GC_heap_bases GC_arrays._heap_bases
+# endif
+# ifdef MSWINCE
+# define GC_heap_lengths GC_arrays._heap_lengths
+# endif
+# define GC_static_roots GC_arrays._static_roots
+# define GC_root_index GC_arrays._root_index
+# define GC_excl_table GC_arrays._excl_table
+# define GC_all_nils GC_arrays._all_nils
+# define GC_top_index GC_arrays._top_index
+# if defined(PROC_VDB) || defined(MPROTECT_VDB) || \
+ defined(GWW_VDB) || defined(MANUAL_VDB)
+# define GC_grungy_pages GC_arrays._grungy_pages
+# endif
+# if defined(MPROTECT_VDB) || defined(MANUAL_VDB)
+# define GC_dirty_pages GC_arrays._dirty_pages
+# endif
+# if defined(PROC_VDB) || defined(GWW_VDB)
+# define GC_written_pages GC_arrays._written_pages
+# endif
+# define GC_composite_in_use GC_arrays._composite_in_use
+# define GC_atomic_in_use GC_arrays._atomic_in_use
+# define GC_size_map GC_arrays._size_map
+
+# define beginGC_arrays ((ptr_t)(&GC_arrays))
+# define endGC_arrays (((ptr_t)(&GC_arrays)) + (sizeof GC_arrays))
+
+#define USED_HEAP_SIZE (GC_heapsize - GC_large_free_bytes)
+
+/* Object kinds: */
+# define MAXOBJKINDS 16
+
+extern struct obj_kind {
+ void **ok_freelist; /* Array of free listheaders for this kind of object */
+ /* Point either to GC_arrays or to storage allocated */
+ /* with GC_scratch_alloc. */
+ struct hblk **ok_reclaim_list;
+ /* List headers for lists of blocks waiting to be */
+ /* swept. */
+ /* Indexed by object size in granules. */
+ word ok_descriptor; /* Descriptor template for objects in this */
+ /* block. */
+ GC_bool ok_relocate_descr;
+ /* Add object size in bytes to descriptor */
+ /* template to obtain descriptor. Otherwise */
+ /* template is used as is. */
+ GC_bool ok_init; /* Clear objects before putting them on the free list. */
+} GC_obj_kinds[MAXOBJKINDS];
+
+# define beginGC_obj_kinds ((ptr_t)(&GC_obj_kinds))
+# define endGC_obj_kinds (beginGC_obj_kinds + (sizeof GC_obj_kinds))
+
+/* Variables that used to be in GC_arrays, but need to be accessed by */
+/* inline allocation code. If they were in GC_arrays, the inlined */
+/* allocation code would include GC_arrays offsets (as it did), which */
+/* introduce maintenance problems. */
+
+#ifdef SEPARATE_GLOBALS
+ word GC_bytes_allocd;
+ /* Number of words allocated during this collection cycle */
+ ptr_t GC_objfreelist[MAXOBJGRANULES+1];
+ /* free list for NORMAL objects */
+# define beginGC_objfreelist ((ptr_t)(&GC_objfreelist))
+# define endGC_objfreelist (beginGC_objfreelist + sizeof(GC_objfreelist))
+
+ ptr_t GC_aobjfreelist[MAXOBJGRANULES+1];
+ /* free list for atomic (PTRFREE) objs */
+# define beginGC_aobjfreelist ((ptr_t)(&GC_aobjfreelist))
+# define endGC_aobjfreelist (beginGC_aobjfreelist + sizeof(GC_aobjfreelist))
+#endif
+
+/* Predefined kinds: */
+# define PTRFREE 0
+# define NORMAL 1
+# define UNCOLLECTABLE 2
+# ifdef ATOMIC_UNCOLLECTABLE
+# define AUNCOLLECTABLE 3
+# define STUBBORN 4
+# define IS_UNCOLLECTABLE(k) (((k) & ~1) == UNCOLLECTABLE)
+# else
+# define STUBBORN 3
+# define IS_UNCOLLECTABLE(k) ((k) == UNCOLLECTABLE)
+# endif
+
+extern unsigned GC_n_kinds;
+
+GC_API word GC_fo_entries;
+
+extern word GC_n_heap_sects; /* Number of separately added heap */
+ /* sections. */
+
+extern word GC_page_size;
+
+# if defined(MSWIN32) || defined(MSWINCE)
+ struct _SYSTEM_INFO;
+ extern struct _SYSTEM_INFO GC_sysinfo;
+ extern word GC_n_heap_bases; /* See GC_heap_bases. */
+# endif
+
+extern word GC_total_stack_black_listed;
+ /* Number of bytes on stack blacklist. */
+
+extern word GC_black_list_spacing;
+ /* Average number of bytes between blacklisted */
+ /* blocks. Approximate. */
+ /* Counts only blocks that are */
+ /* "stack-blacklisted", i.e. that are */
+ /* problematic in the interior of an object. */
+
+extern struct hblk * GC_hblkfreelist[];
+ /* List of completely empty heap blocks */
+ /* Linked through hb_next field of */
+ /* header structure associated with */
+ /* block. */
+
+extern GC_bool GC_objects_are_marked; /* There are marked objects in */
+ /* the heap. */
+
+#ifndef SMALL_CONFIG
+ extern GC_bool GC_incremental;
+ /* Using incremental/generational collection. */
+# define TRUE_INCREMENTAL \
+ (GC_incremental && GC_time_limit != GC_TIME_UNLIMITED)
+ /* True incremental, not just generational, mode */
+#else
+# define GC_incremental FALSE
+ /* Hopefully allow optimizer to remove some code. */
+# define TRUE_INCREMENTAL FALSE
+#endif
+
+extern GC_bool GC_dirty_maintained;
+ /* Dirty bits are being maintained, */
+ /* either for incremental collection, */
+ /* or to limit the root set. */
+
+extern word GC_root_size; /* Total size of registered root sections */
+
+extern GC_bool GC_debugging_started; /* GC_debug_malloc has been called. */
+
+extern long GC_large_alloc_warn_interval;
+ /* Interval between unsuppressed warnings. */
+
+extern long GC_large_alloc_warn_suppressed;
+ /* Number of warnings suppressed so far. */
+
+#ifdef THREADS
+ extern GC_bool GC_world_stopped;
+#endif
+
+/* Operations */
+# ifndef abs
+# define abs(x) ((x) < 0? (-(x)) : (x))
+# endif
+
+
+/* Marks are in a reserved area in */
+/* each heap block. Each word has one mark bit associated */
+/* with it. Only those corresponding to the beginning of an */
+/* object are used. */
+
+/* Set mark bit correctly, even if mark bits may be concurrently */
+/* accessed. */
+#ifdef PARALLEL_MARK
+# define OR_WORD(addr, bits) \
+ { AO_or((volatile AO_t *)(addr), (AO_t)bits); }
+#else
+# define OR_WORD(addr, bits) *(addr) |= (bits)
+#endif
+
+/* Mark bit operations */
+
+/*
+ * Retrieve, set, clear the nth mark bit in a given heap block.
+ *
+ * (Recall that bit n corresponds to nth object or allocation granule
+ * relative to the beginning of the block, including unused words)
+ */
+
+#ifdef USE_MARK_BYTES
+# define mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n])
+# define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n]) = 1
+# define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[n]) = 0
+#else /* !USE_MARK_BYTES */
+# define mark_bit_from_hdr(hhdr,n) (((hhdr)->hb_marks[divWORDSZ(n)] \
+ >> (modWORDSZ(n))) & (word)1)
+# define set_mark_bit_from_hdr(hhdr,n) \
+ OR_WORD((hhdr)->hb_marks+divWORDSZ(n), \
+ (word)1 << modWORDSZ(n))
+# define clear_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \
+ &= ~((word)1 << modWORDSZ(n))
+#endif /* !USE_MARK_BYTES */
+
+#ifdef MARK_BIT_PER_OBJ
+# define MARK_BIT_NO(offset, sz) (((unsigned)(offset))/(sz))
+ /* Get the mark bit index corresponding to the given byte */
+ /* offset and size (in bytes). */
+# define MARK_BIT_OFFSET(sz) 1
+ /* Spacing between useful mark bits. */
+# define IF_PER_OBJ(x) x
+# define FINAL_MARK_BIT(sz) ((sz) > MAXOBJBYTES? 1 : HBLK_OBJS(sz))
+ /* Position of final, always set, mark bit. */
+#else /* MARK_BIT_PER_GRANULE */
+# define MARK_BIT_NO(offset, sz) BYTES_TO_GRANULES((unsigned)(offset))
+# define MARK_BIT_OFFSET(sz) BYTES_TO_GRANULES(sz)
+# define IF_PER_OBJ(x)
+# define FINAL_MARK_BIT(sz) \
+ ((sz) > MAXOBJBYTES? MARK_BITS_PER_HBLK \
+ : BYTES_TO_GRANULES(sz * HBLK_OBJS(sz)))
+#endif
+
+/* Important internal collector routines */
+
+ptr_t GC_approx_sp(void);
+
+GC_bool GC_should_collect(void);
+
+void GC_apply_to_all_blocks(void (*fn) (struct hblk *h, word client_data),
+ word client_data);
+ /* Invoke fn(hbp, client_data) for each */
+ /* allocated heap block. */
+struct hblk * GC_next_used_block(struct hblk * h);
+ /* Return first in-use block >= h */
+struct hblk * GC_prev_block(struct hblk * h);
+ /* Return last block <= h. Returned block */
+ /* is managed by GC, but may or may not be in */
+ /* use. */
+void GC_mark_init(void);
+void GC_clear_marks(void); /* Clear mark bits for all heap objects. */
+void GC_invalidate_mark_state(void);
+ /* Tell the marker that marked */
+ /* objects may point to unmarked */
+ /* ones, and roots may point to */
+ /* unmarked objects. */
+ /* Reset mark stack. */
+GC_bool GC_mark_stack_empty(void);
+GC_bool GC_mark_some(ptr_t cold_gc_frame);
+ /* Perform about one pages worth of marking */
+ /* work of whatever kind is needed. Returns */
+ /* quickly if no collection is in progress. */
+ /* Return TRUE if mark phase finished. */
+void GC_initiate_gc(void);
+ /* initiate collection. */
+ /* If the mark state is invalid, this */
+ /* becomes full colleection. Otherwise */
+ /* it's partial. */
+void GC_push_all(ptr_t bottom, ptr_t top);
+ /* Push everything in a range */
+ /* onto mark stack. */
+void GC_push_selected(ptr_t bottom, ptr_t top,
+ int (*dirty_fn) (struct hblk *h),
+ void (*push_fn) (ptr_t bottom, ptr_t top) );
+ /* Push all pages h in [b,t) s.t. */
+ /* select_fn(h) != 0 onto mark stack. */
+#ifndef SMALL_CONFIG
+ void GC_push_conditional (ptr_t b, ptr_t t, GC_bool all);
+#else
+# define GC_push_conditional(b, t, all) GC_push_all(b, t)
+#endif
+ /* Do either of the above, depending */
+ /* on the third arg. */
+void GC_push_all_stack (ptr_t b, ptr_t t);
+ /* As above, but consider */
+ /* interior pointers as valid */
+void GC_push_all_eager (ptr_t b, ptr_t t);
+ /* Same as GC_push_all_stack, but */
+ /* ensures that stack is scanned */
+ /* immediately, not just scheduled */
+ /* for scanning. */
+#ifndef THREADS
+ void GC_push_all_stack_partially_eager(ptr_t bottom, ptr_t top,
+ ptr_t cold_gc_frame);
+ /* Similar to GC_push_all_eager, but only the */
+ /* part hotter than cold_gc_frame is scanned */
+ /* immediately. Needed to ensure that callee- */
+ /* save registers are not missed. */
+#else
+ /* In the threads case, we push part of the current thread stack */
+ /* with GC_push_all_eager when we push the registers. This gets the */
+ /* callee-save registers that may disappear. The remainder of the */
+ /* stacks are scheduled for scanning in *GC_push_other_roots, which */
+ /* is thread-package-specific. */
+#endif
+void GC_push_current_stack(ptr_t cold_gc_frame, void *context);
+ /* Push enough of the current stack eagerly to */
+ /* ensure that callee-save registers saved in */
+ /* GC frames are scanned. */
+ /* In the non-threads case, schedule entire */
+ /* stack for scanning. */
+ /* The second argument is a pointer to the */
+ /* (possibly null) thread context, for */
+ /* (currently hypothetical) more precise */
+ /* stack scanning. */
+void GC_push_roots(GC_bool all, ptr_t cold_gc_frame);
+ /* Push all or dirty roots. */
+extern void (*GC_push_other_roots)(void);
+ /* Push system or application specific roots */
+ /* onto the mark stack. In some environments */
+ /* (e.g. threads environments) this is */
+ /* predfined to be non-zero. A client supplied */
+ /* replacement should also call the original */
+ /* function. */
+extern void GC_push_gc_structures(void);
+ /* Push GC internal roots. These are normally */
+ /* included in the static data segment, and */
+ /* Thus implicitly pushed. But we must do this */
+ /* explicitly if normal root processing is */
+ /* disabled. Calls the following: */
+ extern void GC_push_finalizer_structures(void);
+ extern void GC_push_stubborn_structures (void);
+# ifdef THREADS
+ extern void GC_push_thread_structures (void);
+# endif
+extern void (*GC_start_call_back) (void);
+ /* Called at start of full collections. */
+ /* Not called if 0. Called with allocation */
+ /* lock held. */
+ /* 0 by default. */
+void GC_push_regs_and_stack(ptr_t cold_gc_frame);
+
+void GC_push_regs(void);
+
+void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
+ ptr_t arg);
+
+# if defined(SPARC) || defined(IA64)
+ /* Cause all stacked registers to be saved in memory. Return a */
+ /* pointer to the top of the corresponding memory stack. */
+ ptr_t GC_save_regs_in_stack(void);
+# endif
+ /* Push register contents onto mark stack. */
+ /* If NURSERY is defined, the default push */
+ /* action can be overridden with GC_push_proc */
+
+# ifdef NURSERY
+ extern void (*GC_push_proc)(ptr_t);
+# endif
+# if defined(MSWIN32) || defined(MSWINCE)
+ void __cdecl GC_push_one(word p);
+# else
+ void GC_push_one(word p);
+ /* If p points to an object, mark it */
+ /* and push contents on the mark stack */
+ /* Pointer recognition test always */
+ /* accepts interior pointers, i.e. this */
+ /* is appropriate for pointers found on */
+ /* stack. */
+# endif
+# if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)
+ void GC_mark_and_push_stack(ptr_t p, ptr_t source);
+ /* Ditto, omits plausibility test */
+# else
+ void GC_mark_and_push_stack(ptr_t p);
+# endif
+void GC_push_marked(struct hblk * h, hdr * hhdr);
+ /* Push contents of all marked objects in h onto */
+ /* mark stack. */
+#ifdef SMALL_CONFIG
+# define GC_push_next_marked_dirty(h) GC_push_next_marked(h)
+#else
+ struct hblk * GC_push_next_marked_dirty(struct hblk * h);
+ /* Invoke GC_push_marked on next dirty block above h. */
+ /* Return a pointer just past the end of this block. */
+#endif /* !SMALL_CONFIG */
+struct hblk * GC_push_next_marked(struct hblk * h);
+ /* Ditto, but also mark from clean pages. */
+struct hblk * GC_push_next_marked_uncollectable(struct hblk * h);
+ /* Ditto, but mark only from uncollectable pages. */
+GC_bool GC_stopped_mark(GC_stop_func stop_func);
+ /* Stop world and mark from all roots */
+ /* and rescuers. */
+void GC_clear_hdr_marks(hdr * hhdr);
+ /* Clear the mark bits in a header */
+void GC_set_hdr_marks(hdr * hhdr);
+ /* Set the mark bits in a header */
+void GC_set_fl_marks(ptr_t p);
+ /* Set all mark bits associated with */
+ /* a free list. */
+#ifdef GC_ASSERTIONS
+ void GC_check_fl_marks(ptr_t p);
+ /* Check that all mark bits */
+ /* associated with a free list are */
+ /* set. Abort if not. */
+#endif
+void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp);
+void GC_remove_roots_inner(ptr_t b, ptr_t e);
+GC_bool GC_is_static_root(ptr_t p);
+ /* Is the address p in one of the registered static */
+ /* root sections? */
+# if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION)
+GC_bool GC_is_tmp_root(ptr_t p);
+ /* Is the address p in one of the temporary static */
+ /* root sections? */
+# endif
+void GC_register_dynamic_libraries(void);
+ /* Add dynamic library data sections to the root set. */
+void GC_cond_register_dynamic_libraries(void);
+ /* Remove and reregister dynamic libraries if we're */
+ /* configured to do that at each GC. */
+
+GC_bool GC_register_main_static_data(void);
+ /* We need to register the main data segment. Returns */
+ /* TRUE unless this is done implicitly as part of */
+ /* dynamic library registration. */
+
+/* Machine dependent startup routines */
+ptr_t GC_get_main_stack_base(void); /* Cold end of stack */
+#ifdef IA64
+ ptr_t GC_get_register_stack_base(void);
+ /* Cold end of register stack. */
+#endif
+void GC_register_data_segments(void);
+
+/* Black listing: */
+void GC_bl_init(void);
+# ifdef PRINT_BLACK_LIST
+ void GC_add_to_black_list_normal(word p, ptr_t source);
+ /* Register bits as a possible future false */
+ /* reference from the heap or static data */
+# define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \
+ if (GC_all_interior_pointers) { \
+ GC_add_to_black_list_stack((word)(bits), (source)); \
+ } else { \
+ GC_add_to_black_list_normal((word)(bits), (source)); \
+ }
+# else
+ void GC_add_to_black_list_normal(word p);
+# define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \
+ if (GC_all_interior_pointers) { \
+ GC_add_to_black_list_stack((word)(bits)); \
+ } else { \
+ GC_add_to_black_list_normal((word)(bits)); \
+ }
+# endif
+
+# ifdef PRINT_BLACK_LIST
+ void GC_add_to_black_list_stack(word p, ptr_t source);
+# define GC_ADD_TO_BLACK_LIST_STACK(bits, source) \
+ GC_add_to_black_list_stack((word)(bits), (source))
+# else
+ void GC_add_to_black_list_stack(word p);
+# define GC_ADD_TO_BLACK_LIST_STACK(bits, source) \
+ GC_add_to_black_list_stack((word)(bits))
+# endif
+struct hblk * GC_is_black_listed(struct hblk * h, word len);
+ /* If there are likely to be false references */
+ /* to a block starting at h of the indicated */
+ /* length, then return the next plausible */
+ /* starting location for h that might avoid */
+ /* these false references. */
+void GC_promote_black_lists(void);
+ /* Declare an end to a black listing phase. */
+void GC_unpromote_black_lists(void);
+ /* Approximately undo the effect of the above. */
+ /* This actually loses some information, but */
+ /* only in a reasonably safe way. */
+word GC_number_stack_black_listed(struct hblk *start, struct hblk *endp1);
+ /* Return the number of (stack) blacklisted */
+ /* blocks in the range for statistical */
+ /* purposes. */
+
+ptr_t GC_scratch_alloc(size_t bytes);
+ /* GC internal memory allocation for */
+ /* small objects. Deallocation is not */
+ /* possible. */
+
+/* Heap block layout maps: */
+GC_bool GC_add_map_entry(size_t sz);
+ /* Add a heap block map for objects of */
+ /* size sz to obj_map. */
+ /* Return FALSE on failure. */
+void GC_register_displacement_inner(size_t offset);
+ /* Version of GC_register_displacement */
+ /* that assumes lock is already held */
+ /* and signals are already disabled. */
+
+void GC_initialize_offsets(void);
+ /* Initialize GC_valid_offsets, */
+ /* depending on current */
+ /* GC_all_interior_pointers settings. */
+
+/* hblk allocation: */
+void GC_new_hblk(size_t size_in_granules, int kind);
+ /* Allocate a new heap block, and build */
+ /* a free list in it. */
+
+ptr_t GC_build_fl(struct hblk *h, size_t words, GC_bool clear, ptr_t list);
+ /* Build a free list for objects of */
+ /* size sz in block h. Append list to */
+ /* end of the free lists. Possibly */
+ /* clear objects on the list. Normally */
+ /* called by GC_new_hblk, but also */
+ /* called explicitly without GC lock. */
+
+struct hblk * GC_allochblk (size_t size_in_bytes, int kind,
+ unsigned flags);
+ /* Allocate a heap block, inform */
+ /* the marker that block is valid */
+ /* for objects of indicated size. */
+
+ptr_t GC_alloc_large (size_t lb, int k, unsigned flags);
+ /* Allocate a large block of size lb bytes. */
+ /* The block is not cleared. */
+ /* Flags is 0 or IGNORE_OFF_PAGE. */
+ /* Calls GC_allchblk to do the actual */
+ /* allocation, but also triggers GC and/or */
+ /* heap expansion as appropriate. */
+ /* Does not update GC_bytes_allocd, but does */
+ /* other accounting. */
+
+ptr_t GC_alloc_large_and_clear(size_t lb, int k, unsigned flags);
+ /* As above, but clear block if appropriate */
+ /* for kind k. */
+
+void GC_freehblk(struct hblk * p);
+ /* Deallocate a heap block and mark it */
+ /* as invalid. */
+
+/* Misc GC: */
+void GC_init_inner(void);
+GC_bool GC_expand_hp_inner(word n);
+void GC_start_reclaim(int abort_if_found);
+ /* Restore unmarked objects to free */
+ /* lists, or (if abort_if_found is */
+ /* TRUE) report them. */
+ /* Sweeping of small object pages is */
+ /* largely deferred. */
+void GC_continue_reclaim(size_t sz, int kind);
+ /* Sweep pages of the given size and */
+ /* kind, as long as possible, and */
+ /* as long as the corr. free list is */
+ /* empty. Sz is in granules. */
+void GC_reclaim_or_delete_all(void);
+ /* Arrange for all reclaim lists to be */
+ /* empty. Judiciously choose between */
+ /* sweeping and discarding each page. */
+GC_bool GC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old);
+ /* Reclaim all blocks. Abort (in a */
+ /* consistent state) if f returns TRUE. */
+ptr_t GC_reclaim_generic(struct hblk * hbp, hdr *hhdr, size_t sz,
+ GC_bool init, ptr_t list, signed_word *count);
+ /* Rebuild free list in hbp with */
+ /* header hhdr, with objects of size sz */
+ /* bytes. Add list to the end of the */
+ /* free list. Add the number of */
+ /* reclaimed bytes to *count. */
+GC_bool GC_block_empty(hdr * hhdr);
+ /* Block completely unmarked? */
+GC_bool GC_never_stop_func(void);
+ /* Returns FALSE. */
+GC_bool GC_try_to_collect_inner(GC_stop_func f);
+
+ /* Collect; caller must have acquired */
+ /* lock and disabled signals. */
+ /* Collection is aborted if f returns */
+ /* TRUE. Returns TRUE if it completes */
+ /* successfully. */
+# define GC_gcollect_inner() \
+ (void) GC_try_to_collect_inner(GC_never_stop_func)
+void GC_finish_collection(void);
+ /* Finish collection. Mark bits are */
+ /* consistent and lock is still held. */
+GC_bool GC_collect_or_expand(word needed_blocks, GC_bool ignore_off_page);
+ /* Collect or expand heap in an attempt */
+ /* make the indicated number of free */
+ /* blocks available. Should be called */
+ /* until the blocks are available or */
+ /* until it fails by returning FALSE. */
+
+extern GC_bool GC_is_initialized; /* GC_init() has been run. */
+
+#if defined(MSWIN32) || defined(MSWINCE)
+ void GC_deinit(void);
+ /* Free any resources allocated by */
+ /* GC_init */
+#endif
+
+void GC_collect_a_little_inner(int n);
+ /* Do n units worth of garbage */
+ /* collection work, if appropriate. */
+ /* A unit is an amount appropriate for */
+ /* HBLKSIZE bytes of allocation. */
+/* void * GC_generic_malloc(size_t lb, int k); */
+ /* Allocate an object of the given */
+ /* kind. By default, there are only */
+ /* a few kinds: composite(pointerfree), */
+ /* atomic, uncollectable, etc. */
+ /* We claim it's possible for clever */
+ /* client code that understands GC */
+ /* internals to add more, e.g. to */
+ /* communicate object layout info */
+ /* to the collector. */
+ /* The actual decl is in gc_mark.h. */
+void * GC_generic_malloc_ignore_off_page(size_t b, int k);
+ /* As above, but pointers past the */
+ /* first page of the resulting object */
+ /* are ignored. */
+void * GC_generic_malloc_inner(size_t lb, int k);
+ /* Ditto, but I already hold lock, etc. */
+void * GC_generic_malloc_inner_ignore_off_page(size_t lb, int k);
+ /* Allocate an object, where */
+ /* the client guarantees that there */
+ /* will always be a pointer to the */
+ /* beginning of the object while the */
+ /* object is live. */
+void GC_generic_malloc_many(size_t lb, int k, void **result);
+ /* Store a pointer to a list of newly */
+ /* allocated objects of kind k and size */
+ /* lb in *result. */
+ /* Caler must make sure that *result is */
+ /* traced even if objects are ptrfree. */
+ptr_t GC_allocobj(size_t sz, int kind);
+ /* Make the indicated */
+ /* free list nonempty, and return its */
+ /* head. Sz is in granules. */
+
+/* Allocation routines that bypass the thread local cache. */
+/* Used internally. */
+#ifdef THREAD_LOCAL_ALLOC
+ void * GC_core_malloc(size_t);
+ void * GC_core_malloc_atomic(size_t);
+# ifdef GC_GCJ_SUPPORT
+ void *GC_core_gcj_malloc(size_t, void *);
+# endif
+#endif /* THREAD_LOCAL_ALLOC */
+
+void GC_free_inner(void * p);
+void GC_debug_free_inner(void * p);
+
+void GC_init_headers(void);
+struct hblkhdr * GC_install_header(struct hblk *h);
+ /* Install a header for block h. */
+ /* Return 0 on failure, or the header */
+ /* otherwise. */
+GC_bool GC_install_counts(struct hblk * h, size_t sz);
+ /* Set up forwarding counts for block */
+ /* h of size sz. */
+ /* Return FALSE on failure. */
+void GC_remove_header(struct hblk * h);
+ /* Remove the header for block h. */
+void GC_remove_counts(struct hblk * h, size_t sz);
+ /* Remove forwarding counts for h. */
+hdr * GC_find_header(ptr_t h); /* Debugging only. */
+
+void GC_finalize(void);
+ /* Perform all indicated finalization actions */
+ /* on unmarked objects. */
+ /* Unreachable finalizable objects are enqueued */
+ /* for processing by GC_invoke_finalizers. */
+ /* Invoked with lock. */
+
+void GC_notify_or_invoke_finalizers(void);
+ /* If GC_finalize_on_demand is not set, invoke */
+ /* eligible finalizers. Otherwise: */
+ /* Call *GC_finalizer_notifier if there are */
+ /* finalizers to be run, and we haven't called */
+ /* this procedure yet this GC cycle. */
+
+GC_API void * GC_make_closure(GC_finalization_proc fn, void * data);
+GC_API void GC_debug_invoke_finalizer(void * obj, void * data);
+ /* Auxiliary fns to make finalization work */
+ /* correctly with displaced pointers introduced */
+ /* by the debugging allocators. */
+
+void GC_add_to_heap(struct hblk *p, size_t bytes);
+ /* Add a HBLKSIZE aligned chunk to the heap. */
+
+void GC_print_obj(ptr_t p);
+ /* P points to somewhere inside an object with */
+ /* debugging info. Print a human readable */
+ /* description of the object to stderr. */
+extern void (*GC_check_heap)(void);
+ /* Check that all objects in the heap with */
+ /* debugging info are intact. */
+ /* Add any that are not to GC_smashed list. */
+extern void (*GC_print_all_smashed) (void);
+ /* Print GC_smashed if it's not empty. */
+ /* Clear GC_smashed list. */
+extern void GC_print_all_errors (void);
+ /* Print smashed and leaked objects, if any. */
+ /* Clear the lists of such objects. */
+extern void (*GC_print_heap_obj) (ptr_t p);
+ /* If possible print s followed by a more */
+ /* detailed description of the object */
+ /* referred to by p. */
+#if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
+ void GC_print_address_map (void);
+ /* Print an address map of the process. */
+#endif
+
+extern GC_bool GC_have_errors; /* We saw a smashed or leaked object. */
+ /* Call error printing routine */
+ /* occasionally. */
+
+#ifndef SMALL_CONFIG
+ extern int GC_print_stats; /* Nonzero generates basic GC log. */
+ /* VERBOSE generates add'l messages. */
+#else
+# define GC_print_stats 0
+ /* Will this keep the message character strings from the executable? */
+ /* It should ... */
+#endif
+#define VERBOSE 2
+
+#ifndef NO_DEBUGGING
+ extern GC_bool GC_dump_regularly; /* Generate regular debugging dumps. */
+# define COND_DUMP if (GC_dump_regularly) GC_dump();
+#else
+# define COND_DUMP
+#endif
+
+#ifdef KEEP_BACK_PTRS
+ extern long GC_backtraces;
+ void GC_generate_random_backtrace_no_gc(void);
+#endif
+
+extern GC_bool GC_print_back_height;
+
+#ifdef MAKE_BACK_GRAPH
+ void GC_print_back_graph_stats(void);
+#endif
+
+/* Macros used for collector internal allocation. */
+/* These assume the collector lock is held. */
+#ifdef DBG_HDRS_ALL
+ extern void * GC_debug_generic_malloc_inner(size_t lb, int k);
+ extern void * GC_debug_generic_malloc_inner_ignore_off_page(size_t lb,
+ int k);
+# define GC_INTERNAL_MALLOC GC_debug_generic_malloc_inner
+# define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE \
+ GC_debug_generic_malloc_inner_ignore_off_page
+# ifdef THREADS
+# define GC_INTERNAL_FREE GC_debug_free_inner
+# else
+# define GC_INTERNAL_FREE GC_debug_free
+# endif
+#else
+# define GC_INTERNAL_MALLOC GC_generic_malloc_inner
+# define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE \
+ GC_generic_malloc_inner_ignore_off_page
+# ifdef THREADS
+# define GC_INTERNAL_FREE GC_free_inner
+# else
+# define GC_INTERNAL_FREE GC_free
+# endif
+#endif
+
+/* Memory unmapping: */
+#ifdef USE_MUNMAP
+ void GC_unmap_old(void);
+ void GC_merge_unmapped(void);
+ void GC_unmap(ptr_t start, size_t bytes);
+ void GC_remap(ptr_t start, size_t bytes);
+ void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2, size_t bytes2);
+#endif
+
+/* Virtual dirty bit implementation: */
+/* Each implementation exports the following: */
+void GC_read_dirty(void);
+ /* Retrieve dirty bits. */
+GC_bool GC_page_was_dirty(struct hblk *h);
+ /* Read retrieved dirty bits. */
+GC_bool GC_page_was_ever_dirty(struct hblk *h);
+ /* Could the page contain valid heap pointers? */
+void GC_remove_protection(struct hblk *h, word nblocks,
+ GC_bool pointerfree);
+ /* h is about to be writteni or allocated. Ensure */
+ /* that it's not write protected by the virtual */
+ /* dirty bit implementation. */
+
+void GC_dirty_init(void);
+
+/* Slow/general mark bit manipulation: */
+GC_API GC_bool GC_is_marked(ptr_t p);
+void GC_clear_mark_bit(ptr_t p);
+void GC_set_mark_bit(ptr_t p);
+
+/* Stubborn objects: */
+void GC_read_changed(void); /* Analogous to GC_read_dirty */
+GC_bool GC_page_was_changed(struct hblk * h);
+ /* Analogous to GC_page_was_dirty */
+void GC_clean_changing_list(void);
+ /* Collect obsolete changing list entries */
+void GC_stubborn_init(void);
+
+/* Debugging print routines: */
+void GC_print_block_list(void);
+void GC_print_hblkfreelist(void);
+void GC_print_heap_sects(void);
+void GC_print_static_roots(void);
+void GC_print_finalization_stats(void);
+/* void GC_dump(void); - declared in gc.h */
+
+#ifdef KEEP_BACK_PTRS
+ void GC_store_back_pointer(ptr_t source, ptr_t dest);
+ void GC_marked_for_finalization(ptr_t dest);
+# define GC_STORE_BACK_PTR(source, dest) GC_store_back_pointer(source, dest)
+# define GC_MARKED_FOR_FINALIZATION(dest) GC_marked_for_finalization(dest)
+#else
+# define GC_STORE_BACK_PTR(source, dest)
+# define GC_MARKED_FOR_FINALIZATION(dest)
+#endif
+
+/* Make arguments appear live to compiler */
+# ifdef __WATCOMC__
+ void GC_noop(void*, ...);
+# else
+# ifdef __DMC__
+ GC_API void GC_noop(...);
+# else
+ GC_API void GC_noop();
+# endif
+# endif
+
+void GC_noop1(word);
+
+/* Logging and diagnostic output: */
+GC_API void GC_printf (const char * format, ...);
+ /* A version of printf that doesn't allocate, */
+ /* 1K total output length. */
+ /* (We use sprintf. Hopefully that doesn't */
+ /* allocate for long arguments.) */
+GC_API void GC_err_printf(const char * format, ...);
+GC_API void GC_log_printf(const char * format, ...);
+void GC_err_puts(const char *s);
+ /* Write s to stderr, don't buffer, don't add */
+ /* newlines, don't ... */
+
+#if defined(LINUX) && !defined(SMALL_CONFIG)
+ void GC_err_write(const char *buf, size_t len);
+ /* Write buf to stderr, don't buffer, don't add */
+ /* newlines, don't ... */
+#endif
+
+
+# ifdef GC_ASSERTIONS
+# define GC_ASSERT(expr) if(!(expr)) {\
+ GC_err_printf("Assertion failure: %s:%ld\n", \
+ __FILE__, (unsigned long)__LINE__); \
+ ABORT("assertion failure"); }
+# else
+# define GC_ASSERT(expr)
+# endif
+
+/* Check a compile time assertion at compile time. The error */
+/* message for failure is a bit baroque, but ... */
+#if defined(mips) && !defined(__GNUC__)
+/* DOB: MIPSPro C gets an internal error taking the sizeof an array type.
+ This code works correctly (ugliness is to avoid "unused var" warnings) */
+# define GC_STATIC_ASSERT(expr) do { if (0) { char j[(expr)? 1 : -1]; j[0]='\0'; j[0]=j[0]; } } while(0)
+#else
+# define GC_STATIC_ASSERT(expr) sizeof(char[(expr)? 1 : -1])
+#endif
+
+# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+ /* We need additional synchronization facilities from the thread */
+ /* support. We believe these are less performance critical */
+ /* than the main garbage collector lock; standard pthreads-based */
+ /* implementations should be sufficient. */
+
+ /* The mark lock and condition variable. If the GC lock is also */
+ /* acquired, the GC lock must be acquired first. The mark lock is */
+ /* used to both protect some variables used by the parallel */
+ /* marker, and to protect GC_fl_builder_count, below. */
+ /* GC_notify_all_marker() is called when */
+ /* the state of the parallel marker changes */
+ /* in some significant way (see gc_mark.h for details). The */
+ /* latter set of events includes incrementing GC_mark_no. */
+ /* GC_notify_all_builder() is called when GC_fl_builder_count */
+ /* reaches 0. */
+
+ extern void GC_acquire_mark_lock();
+ extern void GC_release_mark_lock();
+ extern void GC_notify_all_builder();
+ /* extern void GC_wait_builder(); */
+ extern void GC_wait_for_reclaim();
+
+ extern word GC_fl_builder_count; /* Protected by mark lock. */
+# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
+# ifdef PARALLEL_MARK
+ extern void GC_notify_all_marker();
+ extern void GC_wait_marker();
+ extern word GC_mark_no; /* Protected by mark lock. */
+
+ extern void GC_help_marker(word my_mark_no);
+ /* Try to help out parallel marker for mark cycle */
+ /* my_mark_no. Returns if the mark cycle finishes or */
+ /* was already done, or there was nothing to do for */
+ /* some other reason. */
+# endif /* PARALLEL_MARK */
+
+# if defined(GC_PTHREADS)
+ /* We define the thread suspension signal here, so that we can refer */
+ /* to it in the dirty bit implementation, if necessary. Ideally we */
+ /* would allocate a (real-time ?) signal using the standard mechanism.*/
+ /* unfortunately, there is no standard mechanism. (There is one */
+ /* in Linux glibc, but it's not exported.) Thus we continue to use */
+ /* the same hard-coded signals we've always used. */
+# if !defined(SIG_SUSPEND)
+# if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS)
+# if defined(SPARC) && !defined(SIGPWR)
+ /* SPARC/Linux doesn't properly define SIGPWR in <signal.h>.
+ * It is aliased to SIGLOST in asm/signal.h, though. */
+# define SIG_SUSPEND SIGLOST
+# else
+ /* Linuxthreads itself uses SIGUSR1 and SIGUSR2. */
+# define SIG_SUSPEND SIGPWR
+# endif
+# else /* !GC_LINUX_THREADS */
+# if defined(_SIGRTMIN)
+# define SIG_SUSPEND _SIGRTMIN + 6
+# else
+# define SIG_SUSPEND SIGRTMIN + 6
+# endif
+# endif
+# endif /* !SIG_SUSPEND */
+
+# endif
+
+/* Some macros for setjmp that works across signal handlers */
+/* were possible, and a couple of routines to facilitate */
+/* catching accesses to bad addresses when that's */
+/* possible/needed. */
+#ifdef UNIX_LIKE
+# include <setjmp.h>
+# if defined(SUNOS5SIGS) && !defined(FREEBSD)
+# include <sys/siginfo.h>
+# endif
+ /* Define SETJMP and friends to be the version that restores */
+ /* the signal mask. */
+# define SETJMP(env) sigsetjmp(env, 1)
+# define LONGJMP(env, val) siglongjmp(env, val)
+# define JMP_BUF sigjmp_buf
+#else
+# ifdef ECOS
+# define SETJMP(env) hal_setjmp(env)
+# else
+# define SETJMP(env) setjmp(env)
+# endif
+# define LONGJMP(env, val) longjmp(env, val)
+# define JMP_BUF jmp_buf
+#endif
+
+/* Do we need the GC_find_limit machinery to find the end of a */
+/* data segment. */
+# if defined(HEURISTIC2) || defined(SEARCH_FOR_DATA_START)
+# define NEED_FIND_LIMIT
+# endif
+
+# if !defined(STACKBOTTOM) && defined(HEURISTIC2)
+# define NEED_FIND_LIMIT
+# endif
+
+# if (defined(SVR4) || defined(AUX) || defined(DGUX) \
+ || (defined(LINUX) && defined(SPARC))) && !defined(PCR)
+# define NEED_FIND_LIMIT
+# endif
+
+#if defined(FREEBSD) && (defined(I386) || defined(X86_64) || defined(powerpc) \
+ || defined(__powerpc__))
+# include <machine/trap.h>
+# if !defined(PCR)
+# define NEED_FIND_LIMIT
+# endif
+#endif
+
+#if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__) \
+ && !defined(NEED_FIND_LIMIT)
+ /* Used by GC_init_netbsd_elf() in os_dep.c. */
+# define NEED_FIND_LIMIT
+#endif
+
+#if defined(IA64) && !defined(NEED_FIND_LIMIT)
+# define NEED_FIND_LIMIT
+ /* May be needed for register backing store base. */
+#endif
+
+# if defined(NEED_FIND_LIMIT) || \
+ defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)
+JMP_BUF GC_jmp_buf;
+
+/* Set up a handler for address faults which will longjmp to */
+/* GC_jmp_buf; */
+extern void GC_setup_temporary_fault_handler(void);
+
+/* Undo the effect of GC_setup_temporary_fault_handler. */
+extern void GC_reset_fault_handler(void);
+
+# endif /* Need to handle address faults. */
+
+# endif /* GC_PRIVATE_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/private/gcconfig.h b/tools/build/v2/engine/boehm_gc/include/private/gcconfig.h
new file mode 100644
index 0000000000..20f35bc3a1
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/gcconfig.h
@@ -0,0 +1,2339 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 2000-2004 Hewlett-Packard Development Company, L.P.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/*
+ * This header is private to the gc. It is almost always included from
+ * gc_priv.h. However it is possible to include it by itself if just the
+ * configuration macros are needed. In that
+ * case, a few declarations relying on types declared in gc_priv.h will be
+ * omitted.
+ */
+
+#ifndef GCCONFIG_H
+
+# define GCCONFIG_H
+
+# ifndef GC_PRIVATE_H
+ /* Fake ptr_t declaration, just to avoid compilation errors. */
+ /* This avoids many instances if "ifndef GC_PRIVATE_H" below. */
+ typedef struct GC_undefined_struct * ptr_t;
+# include <stddef.h> /* For size_t etc. */
+# endif
+
+/* Machine dependent parameters. Some tuning parameters can be found */
+/* near the top of gc_private.h. */
+
+/* Machine specific parts contributed by various people. See README file. */
+
+/* First a unified test for Linux: */
+# if defined(linux) || defined(__linux__)
+# ifndef LINUX
+# define LINUX
+# endif
+# endif
+
+/* And one for NetBSD: */
+# if defined(__NetBSD__)
+# define NETBSD
+# endif
+
+/* And one for OpenBSD: */
+# if defined(__OpenBSD__)
+# define OPENBSD
+# endif
+
+/* And one for FreeBSD: */
+# if (defined(__FreeBSD__) || defined(__DragonFly__) || \
+ defined(__FreeBSD_kernel__)) && !defined(FREEBSD)
+# define FREEBSD
+# endif
+
+/* Determine the machine type: */
+# if defined(__arm__) || defined(__thumb__)
+# define ARM32
+# if !defined(LINUX) && !defined(NETBSD)
+# define NOSYS
+# define mach_type_known
+# endif
+# endif
+# if defined(sun) && defined(mc68000)
+# error SUNOS4 no longer supported
+# endif
+# if defined(hp9000s300)
+# error M68K based HP machines no longer supported.
+# endif
+# if defined(OPENBSD) && defined(m68k)
+# define M68K
+# define mach_type_known
+# endif
+# if defined(OPENBSD) && defined(__sparc__)
+# define SPARC
+# define mach_type_known
+# endif
+# if defined(NETBSD) && (defined(m68k) || defined(__m68k__))
+# define M68K
+# define mach_type_known
+# endif
+# if defined(NETBSD) && defined(__powerpc__)
+# define POWERPC
+# define mach_type_known
+# endif
+# if defined(NETBSD) && (defined(__arm32__) || defined(__arm__))
+# define ARM32
+# define mach_type_known
+# endif
+# if defined(NETBSD) && defined(__sh__)
+# define SH
+# define mach_type_known
+# endif
+# if defined(vax)
+# define VAX
+# ifdef ultrix
+# define ULTRIX
+# else
+# define BSD
+# endif
+# define mach_type_known
+# endif
+# if defined(__NetBSD__) && defined(__vax__)
+# define VAX
+# define mach_type_known
+# endif
+# if defined(mips) || defined(__mips) || defined(_mips)
+# define MIPS
+# if defined(nec_ews) || defined(_nec_ews)
+# define EWS4800
+# endif
+# if !defined(LINUX) && !defined(EWS4800) && !defined(NETBSD)
+# if defined(ultrix) || defined(__ultrix)
+# define ULTRIX
+# else
+# define IRIX5 /* or IRIX 6.X */
+# endif
+# endif /* !LINUX */
+# if defined(__NetBSD__) && defined(__MIPSEL__)
+# undef ULTRIX
+# endif
+# define mach_type_known
+# endif
+# if defined(DGUX) && (defined(i386) || defined(__i386__))
+# define I386
+# ifndef _USING_DGUX
+# define _USING_DGUX
+# endif
+# define mach_type_known
+# endif
+# if defined(sequent) && (defined(i386) || defined(__i386__))
+# define I386
+# define SEQUENT
+# define mach_type_known
+# endif
+# if defined(sun) && (defined(i386) || defined(__i386__))
+# define I386
+# define SOLARIS
+# define mach_type_known
+# endif
+# if defined(sun) && defined(__amd64)
+# define X86_64
+# define SOLARIS
+# define mach_type_known
+# endif
+# if (defined(__OS2__) || defined(__EMX__)) && defined(__32BIT__)
+# define I386
+# define OS2
+# define mach_type_known
+# endif
+# if defined(ibm032)
+# error IBM PC/RT no longer supported.
+# endif
+# if defined(sun) && (defined(sparc) || defined(__sparc))
+# define SPARC
+ /* Test for SunOS 5.x */
+# include <errno.h>
+# define SOLARIS
+# define mach_type_known
+# endif
+# if defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \
+ && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__FreeBSD__) \
+ && !defined(__DragonFly__)
+# define SPARC
+# define DRSNX
+# define mach_type_known
+# endif
+# if defined(_IBMR2)
+# define POWERPC
+# define AIX
+# define mach_type_known
+# endif
+# if defined(__NetBSD__) && defined(__sparc__)
+# define SPARC
+# define mach_type_known
+# endif
+# if defined(_M_XENIX) && defined(_M_SYSV) && defined(_M_I386)
+ /* The above test may need refinement */
+# define I386
+# if defined(_SCO_ELF)
+# define SCO_ELF
+# else
+# define SCO
+# endif
+# define mach_type_known
+# endif
+# if defined(_AUX_SOURCE)
+# error A/UX no longer supported
+# endif
+# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
+ || defined(hppa) || defined(__hppa__)
+# define HP_PA
+# if !defined(LINUX) && !defined(HPUX)
+# define HPUX
+# endif
+# define mach_type_known
+# endif
+# if defined(__ia64) && defined(_HPUX_SOURCE)
+# define IA64
+# ifndef HPUX
+# define HPUX
+# endif
+# define mach_type_known
+# endif
+# if defined(__BEOS__) && defined(_X86_)
+# define I386
+# define BEOS
+# define mach_type_known
+# endif
+# if defined(LINUX) && (defined(i386) || defined(__i386__))
+# define I386
+# define mach_type_known
+# endif
+# if defined(LINUX) && defined(__x86_64__)
+# define X86_64
+# define mach_type_known
+# endif
+# if defined(LINUX) && (defined(__ia64__) || defined(__ia64))
+# define IA64
+# define mach_type_known
+# endif
+# if defined(LINUX) && defined(__arm__)
+# define ARM32
+# define mach_type_known
+# endif
+# if defined(LINUX) && defined(__cris__)
+# ifndef CRIS
+# define CRIS
+# endif
+# define mach_type_known
+# endif
+# if defined(LINUX) && (defined(powerpc) || defined(__powerpc__) || \
+ defined(powerpc64) || defined(__powerpc64__))
+# define POWERPC
+# define mach_type_known
+# endif
+# if defined(FREEBSD) && (defined(powerpc) || defined(__powerpc__))
+# define POWERPC
+# define mach_type_known
+# endif
+# if defined(LINUX) && defined(__mc68000__)
+# define M68K
+# define mach_type_known
+# endif
+# if defined(LINUX) && (defined(sparc) || defined(__sparc__))
+# define SPARC
+# define mach_type_known
+# endif
+# if defined(LINUX) && defined(__arm__)
+# define ARM32
+# define mach_type_known
+# endif
+# if defined(LINUX) && defined(__sh__)
+# define SH
+# define mach_type_known
+# endif
+# if defined(LINUX) && defined(__m32r__)
+# define M32R
+# define mach_type_known
+# endif
+# if defined(__alpha) || defined(__alpha__)
+# define ALPHA
+# if !defined(LINUX) && !defined(NETBSD) && !defined(OPENBSD) && !defined(FREEBSD)
+# define OSF1 /* a.k.a Digital Unix */
+# endif
+# define mach_type_known
+# endif
+# if defined(_AMIGA) && !defined(AMIGA)
+# define AMIGA
+# endif
+# ifdef AMIGA
+# define M68K
+# define mach_type_known
+# endif
+# if defined(THINK_C) || defined(__MWERKS__) && !defined(__powerc)
+# define M68K
+# define MACOS
+# define mach_type_known
+# endif
+# if defined(__MWERKS__) && defined(__powerc) && !defined(__MACH__)
+# define POWERPC
+# define MACOS
+# define mach_type_known
+# endif
+# if defined(macosx) || (defined(__APPLE__) && defined(__MACH__))
+# define DARWIN
+# if defined(__ppc__) || defined(__ppc64__)
+# define POWERPC
+# define mach_type_known
+# elif defined(__x86_64__)
+# define X86_64
+# define mach_type_known
+# elif defined(__i386__)
+# define I386
+# define mach_type_known
+# endif
+# endif
+# if defined(NeXT) && defined(mc68000)
+# define M68K
+# define NEXT
+# define mach_type_known
+# endif
+# if defined(NeXT) && (defined(i386) || defined(__i386__))
+# define I386
+# define NEXT
+# define mach_type_known
+# endif
+# if defined(__OpenBSD__) && (defined(i386) || defined(__i386__))
+# define I386
+# define OPENBSD
+# define mach_type_known
+# endif
+# if defined(FREEBSD) && (defined(i386) || defined(__i386__))
+# define I386
+# define mach_type_known
+# endif
+# if defined(FREEBSD) && defined(__x86_64__)
+# define X86_64
+# define mach_type_known
+# endif
+# if defined(__NetBSD__) && (defined(i386) || defined(__i386__))
+# define I386
+# define mach_type_known
+# endif
+# if defined(__NetBSD__) && defined(__x86_64__)
+# define X86_64
+# define mach_type_known
+# endif
+# if defined(FREEBSD) && defined(__sparc__)
+# define SPARC
+# define mach_type_known
+# endif
+# if defined(bsdi) && (defined(i386) || defined(__i386__))
+# define I386
+# define BSDI
+# define mach_type_known
+# endif
+# if !defined(mach_type_known) && defined(__386BSD__)
+# define I386
+# define THREE86BSD
+# define mach_type_known
+# endif
+# if defined(_CX_UX) && defined(_M88K)
+# define M88K
+# define CX_UX
+# define mach_type_known
+# endif
+# if defined(DGUX) && defined(m88k)
+# define M88K
+ /* DGUX defined */
+# define mach_type_known
+# endif
+# if defined(_WIN32_WCE)
+ /* SH3, SH4, MIPS already defined for corresponding architectures */
+# if defined(SH3) || defined(SH4)
+# define SH
+# endif
+# if defined(x86)
+# define I386
+# endif
+# if defined(ARM)
+# define ARM32
+# endif
+# define MSWINCE
+# define mach_type_known
+# else
+# if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \
+ || defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__)
+# if defined(__LP64__) || defined(_WIN64)
+# define X86_64
+# else
+# define I386
+# endif
+# define MSWIN32 /* or Win64 */
+# define mach_type_known
+# endif
+# if defined(_MSC_VER) && defined(_M_IA64)
+# define IA64
+# define MSWIN32 /* Really win64, but we don't treat 64-bit */
+ /* variants as a differnt platform. */
+# endif
+# endif
+# if defined(__DJGPP__)
+# define I386
+# ifndef DJGPP
+# define DJGPP /* MSDOS running the DJGPP port of GCC */
+# endif
+# define mach_type_known
+# endif
+# if defined(__CYGWIN32__) || defined(__CYGWIN__)
+# define I386
+# define CYGWIN32
+# define mach_type_known
+# endif
+# if defined(__MINGW32__)
+# define I386
+# define MSWIN32
+# define mach_type_known
+# endif
+# if defined(__BORLANDC__)
+# define I386
+# define MSWIN32
+# define mach_type_known
+# endif
+# if defined(_UTS) && !defined(mach_type_known)
+# define S370
+# define UTS4
+# define mach_type_known
+# endif
+# if defined(__pj__)
+# error PicoJava no longer supported
+ /* The implementation had problems, and I haven't heard of users */
+ /* in ages. If you want it resurrected, let me know. */
+# endif
+# if defined(__embedded__) && defined(PPC)
+# define POWERPC
+# define NOSYS
+# define mach_type_known
+# endif
+/* Ivan Demakov */
+# if defined(__WATCOMC__) && defined(__386__)
+# define I386
+# if !defined(OS2) && !defined(MSWIN32) && !defined(DOS4GW)
+# if defined(__OS2__)
+# define OS2
+# else
+# if defined(__WINDOWS_386__) || defined(__NT__)
+# define MSWIN32
+# else
+# define DOS4GW
+# endif
+# endif
+# endif
+# define mach_type_known
+# endif
+# if defined(__s390__) && defined(LINUX)
+# define S390
+# define mach_type_known
+# endif
+# if defined(__GNU__)
+# if defined(__i386__)
+/* The Debian Hurd running on generic PC */
+# define HURD
+# define I386
+# define mach_type_known
+# endif
+# endif
+# if defined(__TANDEM)
+ /* Nonstop S-series */
+ /* FIXME: Should recognize Integrity series? */
+# define MIPS
+# define NONSTOP
+# define mach_type_known
+# endif
+
+/* Feel free to add more clauses here */
+
+/* Or manually define the machine type here. A machine type is */
+/* characterized by the architecture. Some */
+/* machine types are further subdivided by OS. */
+/* Macros such as LINUX, FREEBSD, etc. distinguish them. */
+/* SYSV on an M68K actually means A/UX. */
+/* The distinction in these cases is usually the stack starting address */
+# ifndef mach_type_known
+# error "The collector has not been ported to this machine/OS combination."
+# endif
+ /* Mapping is: M68K ==> Motorola 680X0 */
+ /* (NEXT, and SYSV (A/UX), */
+ /* MACOS and AMIGA variants) */
+ /* I386 ==> Intel 386 */
+ /* (SEQUENT, OS2, SCO, LINUX, NETBSD, */
+ /* FREEBSD, THREE86BSD, MSWIN32, */
+ /* BSDI,SOLARIS, NEXT, other variants) */
+ /* NS32K ==> Encore Multimax */
+ /* MIPS ==> R2000 through R14K */
+ /* (many variants) */
+ /* VAX ==> DEC VAX */
+ /* (BSD, ULTRIX variants) */
+ /* HP_PA ==> HP9000/700 & /800 */
+ /* HP/UX, LINUX */
+ /* SPARC ==> SPARC v7/v8/v9 */
+ /* (SOLARIS, LINUX, DRSNX variants) */
+ /* ALPHA ==> DEC Alpha */
+ /* (OSF1 and LINUX variants) */
+ /* M88K ==> Motorola 88XX0 */
+ /* (CX_UX and DGUX) */
+ /* S370 ==> 370-like machine */
+ /* running Amdahl UTS4 */
+ /* S390 ==> 390-like machine */
+ /* running LINUX */
+ /* ARM32 ==> Intel StrongARM */
+ /* IA64 ==> Intel IPF */
+ /* (e.g. Itanium) */
+ /* (LINUX and HPUX) */
+ /* SH ==> Hitachi SuperH */
+ /* (LINUX & MSWINCE) */
+ /* X86_64 ==> AMD x86-64 */
+ /* POWERPC ==> IBM/Apple PowerPC */
+ /* (MACOS(<=9),DARWIN(incl.MACOSX),*/
+ /* LINUX, NETBSD, AIX, NOSYS */
+ /* variants) */
+ /* Handles 32 and 64-bit variants. */
+ /* CRIS ==> Axis Etrax */
+ /* M32R ==> Renesas M32R */
+
+
+/*
+ * For each architecture and OS, the following need to be defined:
+ *
+ * CPP_WORDSZ is a simple integer constant representing the word size.
+ * in bits. We assume byte addressibility, where a byte has 8 bits.
+ * We also assume CPP_WORDSZ is either 32 or 64.
+ * (We care about the length of pointers, not hardware
+ * bus widths. Thus a 64 bit processor with a C compiler that uses
+ * 32 bit pointers should use CPP_WORDSZ of 32, not 64. Default is 32.)
+ *
+ * MACH_TYPE is a string representation of the machine type.
+ * OS_TYPE is analogous for the OS.
+ *
+ * ALIGNMENT is the largest N, such that
+ * all pointer are guaranteed to be aligned on N byte boundaries.
+ * defining it to be 1 will always work, but perform poorly.
+ *
+ * DATASTART is the beginning of the data segment.
+ * On some platforms SEARCH_FOR_DATA_START is defined.
+ * SEARCH_FOR_DATASTART will cause GC_data_start to
+ * be set to an address determined by accessing data backwards from _end
+ * until an unmapped page is found. DATASTART will be defined to be
+ * GC_data_start.
+ * On UNIX-like systems, the collector will scan the area between DATASTART
+ * and DATAEND for root pointers.
+ *
+ * DATAEND, if not `end' where `end' is defined as ``extern int end[];''.
+ * RTH suggests gaining access to linker script synth'd values with
+ * this idiom instead of `&end' where `end' is defined as ``extern int end;'' .
+ * Otherwise, ``GCC will assume these are in .sdata/.sbss'' and it will, e.g.,
+ * cause failures on alpha*-*-* with ``-msmall-data or -fpic'' or mips-*-*
+ * without any special options.
+ *
+ * STACKBOTTOM is the cool end of the stack, which is usually the
+ * highest address in the stack.
+ * Under PCR or OS/2, we have other ways of finding thread stacks.
+ * For each machine, the following should:
+ * 1) define STACK_GROWS_UP if the stack grows toward higher addresses, and
+ * 2) define exactly one of
+ * STACKBOTTOM (should be defined to be an expression)
+ * LINUX_STACKBOTTOM
+ * HEURISTIC1
+ * HEURISTIC2
+ * If STACKBOTTOM is defined, then it's value will be used directly as the
+ * stack base. If LINUX_STACKBOTTOM is defined, then it will be determined
+ * with a method appropriate for most Linux systems. Currently we look
+ * first for __libc_stack_end, and if that fails read it from /proc.
+ * If either of the last two macros are defined, then STACKBOTTOM is computed
+ * during collector startup using one of the following two heuristics:
+ * HEURISTIC1: Take an address inside GC_init's frame, and round it up to
+ * the next multiple of STACK_GRAN.
+ * HEURISTIC2: Take an address inside GC_init's frame, increment it repeatedly
+ * in small steps (decrement if STACK_GROWS_UP), and read the value
+ * at each location. Remember the value when the first
+ * Segmentation violation or Bus error is signalled. Round that
+ * to the nearest plausible page boundary, and use that instead
+ * of STACKBOTTOM.
+ *
+ * Gustavo Rodriguez-Rivera points out that on most (all?) Unix machines,
+ * the value of environ is a pointer that can serve as STACKBOTTOM.
+ * I expect that HEURISTIC2 can be replaced by this approach, which
+ * interferes far less with debugging. However it has the disadvantage
+ * that it's confused by a putenv call before the collector is initialized.
+ * This could be dealt with by intercepting putenv ...
+ *
+ * If no expression for STACKBOTTOM can be found, and neither of the above
+ * heuristics are usable, the collector can still be used with all of the above
+ * undefined, provided one of the following is done:
+ * 1) GC_mark_roots can be changed to somehow mark from the correct stack(s)
+ * without reference to STACKBOTTOM. This is appropriate for use in
+ * conjunction with thread packages, since there will be multiple stacks.
+ * (Allocating thread stacks in the heap, and treating them as ordinary
+ * heap data objects is also possible as a last resort. However, this is
+ * likely to introduce significant amounts of excess storage retention
+ * unless the dead parts of the thread stacks are periodically cleared.)
+ * 2) Client code may set GC_stackbottom before calling any GC_ routines.
+ * If the author of the client code controls the main program, this is
+ * easily accomplished by introducing a new main program, setting
+ * GC_stackbottom to the address of a local variable, and then calling
+ * the original main program. The new main program would read something
+ * like:
+ *
+ * # include "gc_private.h"
+ *
+ * main(argc, argv, envp)
+ * int argc;
+ * char **argv, **envp;
+ * {
+ * int dummy;
+ *
+ * GC_stackbottom = (ptr_t)(&dummy);
+ * return(real_main(argc, argv, envp));
+ * }
+ *
+ *
+ * Each architecture may also define the style of virtual dirty bit
+ * implementation to be used:
+ * MPROTECT_VDB: Write protect the heap and catch faults.
+ * GWW_VDB: Use win32 GetWriteWatch primitive.
+ * PROC_VDB: Use the SVR4 /proc primitives to read dirty bits.
+ *
+ * The first and second one may be combined, in which case a runtime
+ * selection will be made, based on GetWriteWatch availability.
+ *
+ * An architecture may define DYNAMIC_LOADING if dynamic_load.c
+ * defined GC_register_dynamic_libraries() for the architecture.
+ *
+ * An architecture may define PREFETCH(x) to preload the cache with *x.
+ * This defaults to a no-op.
+ *
+ * PREFETCH_FOR_WRITE(x) is used if *x is about to be written.
+ *
+ * An architecture may also define CLEAR_DOUBLE(x) to be a fast way to
+ * clear the two words at GC_malloc-aligned address x. By default,
+ * word stores of 0 are used instead.
+ *
+ * HEAP_START may be defined as the initial address hint for mmap-based
+ * allocation.
+ */
+
+/* If we are using a recent version of gcc, we can use __builtin_unwind_init()
+ * to push the relevant registers onto the stack.
+ */
+# if defined(__GNUC__) && ((__GNUC__ >= 3) || \
+ (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)) \
+ && !defined(__INTEL_COMPILER) && !defined(__PATHCC__)
+# define HAVE_BUILTIN_UNWIND_INIT
+# endif
+
+# define STACK_GRAN 0x1000000
+# ifdef M68K
+# define MACH_TYPE "M68K"
+# define ALIGNMENT 2
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# define HEURISTIC2
+# ifdef __ELF__
+# define DATASTART GC_data_start
+# define DYNAMIC_LOADING
+# else
+ extern char etext[];
+# define DATASTART ((ptr_t)(etext))
+# endif
+# endif
+# ifdef NETBSD
+# define OS_TYPE "NETBSD"
+# define HEURISTIC2
+# ifdef __ELF__
+# define DATASTART GC_data_start
+# define DYNAMIC_LOADING
+# else
+ extern char etext[];
+# define DATASTART ((ptr_t)(etext))
+# endif
+# endif
+# ifdef LINUX
+# define OS_TYPE "LINUX"
+# define LINUX_STACKBOTTOM
+# define MPROTECT_VDB
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# include <features.h>
+# if defined(__GLIBC__)&& __GLIBC__>=2
+# define SEARCH_FOR_DATA_START
+# else /* !GLIBC2 */
+ extern char **__environ;
+# define DATASTART ((ptr_t)(&__environ))
+ /* hideous kludge: __environ is the first */
+ /* word in crt0.o, and delimits the start */
+ /* of the data segment, no matter which */
+ /* ld options were passed through. */
+ /* We could use _etext instead, but that */
+ /* would include .rodata, which may */
+ /* contain large read-only data tables */
+ /* that we'd rather not scan. */
+# endif /* !GLIBC2 */
+ extern int _end[];
+# define DATAEND (_end)
+# else
+ extern int etext[];
+# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
+# endif
+# endif
+# ifdef AMIGA
+# define OS_TYPE "AMIGA"
+ /* STACKBOTTOM and DATASTART handled specially */
+ /* in os_dep.c */
+# define DATAEND /* not needed */
+# define GETPAGESIZE() 4096
+# endif
+# ifdef MACOS
+# ifndef __LOWMEM__
+# include <LowMem.h>
+# endif
+# define OS_TYPE "MACOS"
+ /* see os_dep.c for details of global data segments. */
+# define STACKBOTTOM ((ptr_t) LMGetCurStackBase())
+# define DATAEND /* not needed */
+# define GETPAGESIZE() 4096
+# endif
+# ifdef NEXT
+# define OS_TYPE "NEXT"
+# define DATASTART ((ptr_t) get_etext())
+# define STACKBOTTOM ((ptr_t) 0x4000000)
+# define DATAEND /* not needed */
+# endif
+# endif
+
+# if defined(POWERPC)
+# define MACH_TYPE "POWERPC"
+# ifdef MACOS
+# define ALIGNMENT 2 /* Still necessary? Could it be 4? */
+# ifndef __LOWMEM__
+# include <LowMem.h>
+# endif
+# define OS_TYPE "MACOS"
+ /* see os_dep.c for details of global data segments. */
+# define STACKBOTTOM ((ptr_t) LMGetCurStackBase())
+# define DATAEND /* not needed */
+# endif
+# ifdef LINUX
+# if defined(__powerpc64__)
+# define ALIGNMENT 8
+# define CPP_WORDSZ 64
+# ifndef HBLKSIZE
+# define HBLKSIZE 4096
+# endif
+# else
+# define ALIGNMENT 4
+# endif
+# define OS_TYPE "LINUX"
+ /* HEURISTIC1 has been reliably reported to fail for a 32-bit */
+ /* executable on a 64 bit kernel. */
+# define LINUX_STACKBOTTOM
+# define DYNAMIC_LOADING
+# define SEARCH_FOR_DATA_START
+ extern int _end[];
+# define DATAEND (_end)
+# endif
+# ifdef DARWIN
+# define OS_TYPE "DARWIN"
+# define DYNAMIC_LOADING
+# if defined(__ppc64__)
+# define ALIGNMENT 8
+# define CPP_WORDSZ 64
+# define STACKBOTTOM ((ptr_t) 0x7fff5fc00000)
+# define CACHE_LINE_SIZE 64
+# ifndef HBLKSIZE
+# define HBLKSIZE 4096
+# endif
+# else
+# define ALIGNMENT 4
+# define STACKBOTTOM ((ptr_t) 0xc0000000)
+# endif
+ /* XXX: see get_end(3), get_etext() and get_end() should not be used.
+ These aren't used when dyld support is enabled (it is by default) */
+# define DATASTART ((ptr_t) get_etext())
+# define DATAEND ((ptr_t) get_end())
+# define USE_MMAP
+# define USE_MMAP_ANON
+# ifdef GC_DARWIN_THREADS
+# define MPROTECT_VDB
+# endif
+# include <unistd.h>
+# define GETPAGESIZE() getpagesize()
+# if defined(USE_PPC_PREFETCH) && defined(__GNUC__)
+ /* The performance impact of prefetches is untested */
+# define PREFETCH(x) \
+ __asm__ __volatile__ ("dcbt 0,%0" : : "r" ((const void *) (x)))
+# define PREFETCH_FOR_WRITE(x) \
+ __asm__ __volatile__ ("dcbtst 0,%0" : : "r" ((const void *) (x)))
+# endif
+ /* There seems to be some issues with trylock hanging on darwin. This
+ should be looked into some more */
+# define NO_PTHREAD_TRYLOCK
+# endif
+# ifdef FREEBSD
+# define ALIGNMENT 4
+# define OS_TYPE "FREEBSD"
+# ifndef GC_FREEBSD_THREADS
+# define MPROTECT_VDB
+# endif
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# define FREEBSD_STACKBOTTOM
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+ extern char etext[];
+ extern char * GC_FreeBSDGetDataStart();
+# define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
+# endif
+# ifdef NETBSD
+# define ALIGNMENT 4
+# define OS_TYPE "NETBSD"
+# define HEURISTIC2
+ extern char etext[];
+# define DATASTART GC_data_start
+# define DYNAMIC_LOADING
+# endif
+# ifdef AIX
+# define OS_TYPE "AIX"
+# undef ALIGNMENT /* in case it's defined */
+# ifdef IA64
+# undef IA64
+ /* DOB: some AIX installs stupidly define IA64 in */
+ /* /usr/include/sys/systemcfg.h */
+# endif
+# ifdef __64BIT__
+# define ALIGNMENT 8
+# define CPP_WORDSZ 64
+# define STACKBOTTOM ((ptr_t)0x1000000000000000)
+# else
+# define ALIGNMENT 4
+# define CPP_WORDSZ 32
+# define STACKBOTTOM ((ptr_t)((ulong)&errno))
+# endif
+# define USE_MMAP
+# define USE_MMAP_ANON
+ /* From AIX linker man page:
+ _text Specifies the first location of the program.
+ _etext Specifies the first location after the program.
+ _data Specifies the first location of the data.
+ _edata Specifies the first location after the initialized data
+ _end or end Specifies the first location after all data.
+ */
+ extern int _data[], _end[];
+# define DATASTART ((ptr_t)((ulong)_data))
+# define DATAEND ((ptr_t)((ulong)_end))
+ extern int errno;
+# define DYNAMIC_LOADING
+ /* For really old versions of AIX, this may have to be removed. */
+# endif
+
+# ifdef NOSYS
+# define ALIGNMENT 4
+# define OS_TYPE "NOSYS"
+ extern void __end[], __dso_handle[];
+# define DATASTART (__dso_handle) /* OK, that's ugly. */
+# define DATAEND (__end)
+ /* Stack starts at 0xE0000000 for the simulator. */
+# undef STACK_GRAN
+# define STACK_GRAN 0x10000000
+# define HEURISTIC1
+# endif
+# endif
+
+# ifdef VAX
+# define MACH_TYPE "VAX"
+# define ALIGNMENT 4 /* Pointers are longword aligned by 4.2 C compiler */
+ extern char etext[];
+# define DATASTART ((ptr_t)(etext))
+# ifdef BSD
+# define OS_TYPE "BSD"
+# define HEURISTIC1
+ /* HEURISTIC2 may be OK, but it's hard to test. */
+# endif
+# ifdef ULTRIX
+# define OS_TYPE "ULTRIX"
+# define STACKBOTTOM ((ptr_t) 0x7fffc800)
+# endif
+# endif
+
+# ifdef SPARC
+# define MACH_TYPE "SPARC"
+# if defined(__arch64__) || defined(__sparcv9)
+# define ALIGNMENT 8
+# define CPP_WORDSZ 64
+# define ELF_CLASS ELFCLASS64
+# else
+# define ALIGNMENT 4 /* Required by hardware */
+# define CPP_WORDSZ 32
+# endif
+ /* Don't define USE_ASM_PUSH_REGS. We do use an asm helper, but */
+ /* not to push the registers on the mark stack. */
+# ifdef SOLARIS
+# define OS_TYPE "SOLARIS"
+ extern int _etext[];
+ extern int _end[];
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
+# define DATAEND (_end)
+# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
+# define USE_MMAP
+ /* Otherwise we now use calloc. Mmap may result in the */
+ /* heap interleaved with thread stacks, which can result in */
+ /* excessive blacklisting. Sbrk is unusable since it */
+ /* doesn't interact correctly with the system malloc. */
+# endif
+# ifdef USE_MMAP
+# define HEAP_START (ptr_t)0x40000000
+# else
+# define HEAP_START DATAEND
+# endif
+# define PROC_VDB
+/* HEURISTIC1 reportedly no longer works under 2.7. */
+/* HEURISTIC2 probably works, but this appears to be preferable. */
+/* Apparently USRSTACK is defined to be USERLIMIT, but in some */
+/* installations that's undefined. We work around this with a */
+/* gross hack: */
+# include <sys/vmparam.h>
+# ifdef USERLIMIT
+ /* This should work everywhere, but doesn't. */
+# define STACKBOTTOM USRSTACK
+# else
+# define HEURISTIC2
+# endif
+# include <unistd.h>
+# define GETPAGESIZE() sysconf(_SC_PAGESIZE)
+ /* getpagesize() appeared to be missing from at least one */
+ /* Solaris 5.4 installation. Weird. */
+# define DYNAMIC_LOADING
+# endif
+# ifdef DRSNX
+# define OS_TYPE "DRSNX"
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+ extern int etext[];
+# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)
+# define MPROTECT_VDB
+# define STACKBOTTOM ((ptr_t) 0xdfff0000)
+# define DYNAMIC_LOADING
+# endif
+# ifdef LINUX
+# define OS_TYPE "LINUX"
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# else
+ Linux Sparc/a.out not supported
+# endif
+ extern int _end[];
+ extern int _etext[];
+# define DATAEND (_end)
+# define SVR4
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# ifdef __arch64__
+# define DATASTART GC_SysVGetDataStart(0x100000, (ptr_t)_etext)
+# else
+# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
+# endif
+# define LINUX_STACKBOTTOM
+# endif
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# define STACKBOTTOM ((ptr_t) 0xf8000000)
+ extern int etext[];
+# define DATASTART ((ptr_t)(etext))
+# endif
+# ifdef NETBSD
+# define OS_TYPE "NETBSD"
+# define HEURISTIC2
+# ifdef __ELF__
+# define DATASTART GC_data_start
+# define DYNAMIC_LOADING
+# else
+ extern char etext[];
+# define DATASTART ((ptr_t)(etext))
+# endif
+# endif
+# ifdef FREEBSD
+# define OS_TYPE "FREEBSD"
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# define FREEBSD_STACKBOTTOM
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+ extern char etext[];
+ extern char edata[];
+ extern char end[];
+# define NEED_FIND_LIMIT
+# define DATASTART ((ptr_t)(&etext))
+# define DATAEND (GC_find_limit (DATASTART, TRUE))
+# define DATASTART2 ((ptr_t)(&edata))
+# define DATAEND2 ((ptr_t)(&end))
+# endif
+# endif
+
+# ifdef I386
+# define MACH_TYPE "I386"
+# if defined(__LP64__) || defined(_WIN64)
+# error This should be handled as X86_64
+# else
+# define CPP_WORDSZ 32
+# define ALIGNMENT 4
+ /* Appears to hold for all "32 bit" compilers */
+ /* except Borland. The -a4 option fixes */
+ /* Borland. */
+ /* Ivan Demakov: For Watcom the option is -zp4. */
+# endif
+# ifdef SEQUENT
+# define OS_TYPE "SEQUENT"
+ extern int etext[];
+# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
+# define STACKBOTTOM ((ptr_t) 0x3ffff000)
+# endif
+# ifdef BEOS
+# define OS_TYPE "BEOS"
+# include <OS.h>
+# define GETPAGESIZE() B_PAGE_SIZE
+ extern int etext[];
+# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
+# endif
+# ifdef SOLARIS
+# define OS_TYPE "SOLARIS"
+ extern int _etext[], _end[];
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)
+# define DATAEND (_end)
+/* # define STACKBOTTOM ((ptr_t)(_start)) worked through 2.7, */
+/* but reportedly breaks under 2.8. It appears that the stack */
+/* base is a property of the executable, so this should not break */
+/* old executables. */
+/* HEURISTIC2 probably works, but this appears to be preferable. */
+# include <sys/vm.h>
+# define STACKBOTTOM USRSTACK
+/* At least in Solaris 2.5, PROC_VDB gives wrong values for dirty bits. */
+/* It appears to be fixed in 2.8 and 2.9. */
+# ifdef SOLARIS25_PROC_VDB_BUG_FIXED
+# define PROC_VDB
+# endif
+# define DYNAMIC_LOADING
+# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
+# define USE_MMAP
+ /* Otherwise we now use calloc. Mmap may result in the */
+ /* heap interleaved with thread stacks, which can result in */
+ /* excessive blacklisting. Sbrk is unusable since it */
+ /* doesn't interact correctly with the system malloc. */
+# endif
+# ifdef USE_MMAP
+# define HEAP_START (ptr_t)0x40000000
+# else
+# define HEAP_START DATAEND
+# endif
+# endif
+# ifdef SCO
+# define OS_TYPE "SCO"
+ extern int etext[];
+# define DATASTART ((ptr_t)((((word) (etext)) + 0x3fffff) \
+ & ~0x3fffff) \
+ +((word)etext & 0xfff))
+# define STACKBOTTOM ((ptr_t) 0x7ffffffc)
+# endif
+# ifdef SCO_ELF
+# define OS_TYPE "SCO_ELF"
+ extern int etext[];
+# define DATASTART ((ptr_t)(etext))
+# define STACKBOTTOM ((ptr_t) 0x08048000)
+# define DYNAMIC_LOADING
+# define ELF_CLASS ELFCLASS32
+# endif
+# ifdef DGUX
+# define OS_TYPE "DGUX"
+ extern int _etext, _end;
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)(&_etext))
+# define DATAEND (&_end)
+# define STACK_GROWS_DOWN
+# define HEURISTIC2
+# include <unistd.h>
+# define GETPAGESIZE() sysconf(_SC_PAGESIZE)
+# define DYNAMIC_LOADING
+# ifndef USE_MMAP
+# define USE_MMAP
+# endif /* USE_MMAP */
+# define MAP_FAILED (void *) -1
+# ifdef USE_MMAP
+# define HEAP_START (ptr_t)0x40000000
+# else /* USE_MMAP */
+# define HEAP_START DATAEND
+# endif /* USE_MMAP */
+# endif /* DGUX */
+
+# ifdef LINUX
+# define OS_TYPE "LINUX"
+# define LINUX_STACKBOTTOM
+# if 0
+# define HEURISTIC1
+# undef STACK_GRAN
+# define STACK_GRAN 0x10000000
+ /* STACKBOTTOM is usually 0xc0000000, but this changes with */
+ /* different kernel configurations. In particular, systems */
+ /* with 2GB physical memory will usually move the user */
+ /* address space limit, and hence initial SP to 0x80000000. */
+# endif
+# if !defined(GC_LINUX_THREADS) || !defined(REDIRECT_MALLOC)
+# define MPROTECT_VDB
+# else
+ /* We seem to get random errors in incremental mode, */
+ /* possibly because Linux threads is itself a malloc client */
+ /* and can't deal with the signals. */
+# endif
+# define HEAP_START (ptr_t)0x1000
+ /* This encourages mmap to give us low addresses, */
+ /* thus allowing the heap to grow to ~3GB */
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# ifdef UNDEFINED /* includes ro data */
+ extern int _etext[];
+# define DATASTART ((ptr_t)((((word) (_etext)) + 0xfff) & ~0xfff))
+# endif
+# include <features.h>
+# if defined(__GLIBC__) && __GLIBC__ >= 2
+# define SEARCH_FOR_DATA_START
+# else
+ extern char **__environ;
+# define DATASTART ((ptr_t)(&__environ))
+ /* hideous kludge: __environ is the first */
+ /* word in crt0.o, and delimits the start */
+ /* of the data segment, no matter which */
+ /* ld options were passed through. */
+ /* We could use _etext instead, but that */
+ /* would include .rodata, which may */
+ /* contain large read-only data tables */
+ /* that we'd rather not scan. */
+# endif
+ extern int _end[];
+# define DATAEND (_end)
+# else
+ extern int etext[];
+# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
+# endif
+# ifdef USE_I686_PREFETCH
+ /* FIXME: Thus should use __builtin_prefetch, but we'll leave that */
+ /* for the next rtelease. */
+# define PREFETCH(x) \
+ __asm__ __volatile__ (" prefetchnta %0": : "m"(*(char *)(x)))
+ /* Empirically prefetcht0 is much more effective at reducing */
+ /* cache miss stalls for the targetted load instructions. But it */
+ /* seems to interfere enough with other cache traffic that the net */
+ /* result is worse than prefetchnta. */
+# if 0
+ /* Using prefetches for write seems to have a slight negative */
+ /* impact on performance, at least for a PIII/500. */
+# define PREFETCH_FOR_WRITE(x) \
+ __asm__ __volatile__ (" prefetcht0 %0": : "m"(*(char *)(x)))
+# endif
+# endif
+# ifdef USE_3DNOW_PREFETCH
+# define PREFETCH(x) \
+ __asm__ __volatile__ (" prefetch %0": : "m"(*(char *)(x)))
+# define PREFETCH_FOR_WRITE(x) \
+ __asm__ __volatile__ (" prefetchw %0": : "m"(*(char *)(x)))
+# endif
+# endif
+# ifdef CYGWIN32
+# define OS_TYPE "CYGWIN32"
+# define DATASTART ((ptr_t)GC_DATASTART) /* From gc.h */
+# define DATAEND ((ptr_t)GC_DATAEND)
+# undef STACK_GRAN
+# define STACK_GRAN 0x10000
+# define HEURISTIC1
+# endif
+# ifdef OS2
+# define OS_TYPE "OS2"
+ /* STACKBOTTOM and DATASTART are handled specially in */
+ /* os_dep.c. OS2 actually has the right */
+ /* system call! */
+# define DATAEND /* not needed */
+# endif
+# ifdef MSWIN32
+# define OS_TYPE "MSWIN32"
+ /* STACKBOTTOM and DATASTART are handled specially in */
+ /* os_dep.c. */
+# if !defined(__WATCOMC__)
+# define MPROTECT_VDB
+ /* We also avoided doing this in the past with GC_WIN32_THREADS */
+ /* Hopefully that's fixed. */
+# endif
+# if _MSC_VER >= 1300 /* .NET, i.e. > VisualStudio 6 */
+# define GWW_VDB
+# endif
+# define DATAEND /* not needed */
+# endif
+# ifdef MSWINCE
+# define OS_TYPE "MSWINCE"
+# define DATAEND /* not needed */
+# endif
+# ifdef DJGPP
+# define OS_TYPE "DJGPP"
+# include "stubinfo.h"
+ extern int etext[];
+ extern int _stklen;
+ extern int __djgpp_stack_limit;
+# define DATASTART ((ptr_t)((((word) (etext)) + 0x1ff) & ~0x1ff))
+/* # define STACKBOTTOM ((ptr_t)((word) _stubinfo + _stubinfo->size \
+ + _stklen)) */
+# define STACKBOTTOM ((ptr_t)((word) __djgpp_stack_limit + _stklen))
+ /* This may not be right. */
+# endif
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# endif
+# ifdef FREEBSD
+# define OS_TYPE "FREEBSD"
+# ifndef GC_FREEBSD_THREADS
+# define MPROTECT_VDB
+# endif
+# ifdef __GLIBC__
+# define SIG_SUSPEND (32+6)
+# define SIG_THR_RESTART (32+5)
+ extern int _end[];
+# define DATAEND (_end)
+# else
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# endif
+# define FREEBSD_STACKBOTTOM
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+ extern char etext[];
+ extern char * GC_FreeBSDGetDataStart(size_t, ptr_t);
+# define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext)
+# endif
+# ifdef NETBSD
+# define OS_TYPE "NETBSD"
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+# endif
+# ifdef THREE86BSD
+# define OS_TYPE "THREE86BSD"
+# endif
+# ifdef BSDI
+# define OS_TYPE "BSDI"
+# endif
+# if defined(OPENBSD) || defined(NETBSD) \
+ || defined(THREE86BSD) || defined(BSDI)
+# define HEURISTIC2
+ extern char etext[];
+# define DATASTART ((ptr_t)(etext))
+# endif
+# ifdef NEXT
+# define OS_TYPE "NEXT"
+# define DATASTART ((ptr_t) get_etext())
+# define STACKBOTTOM ((ptr_t)0xc0000000)
+# define DATAEND /* not needed */
+# endif
+# ifdef DOS4GW
+# define OS_TYPE "DOS4GW"
+ extern long __nullarea;
+ extern char _end;
+ extern char *_STACKTOP;
+ /* Depending on calling conventions Watcom C either precedes
+ or does not precedes with undescore names of C-variables.
+ Make sure startup code variables always have the same names. */
+ #pragma aux __nullarea "*";
+ #pragma aux _end "*";
+# define STACKBOTTOM ((ptr_t) _STACKTOP)
+ /* confused? me too. */
+# define DATASTART ((ptr_t) &__nullarea)
+# define DATAEND ((ptr_t) &_end)
+# endif
+# ifdef HURD
+# define OS_TYPE "HURD"
+# define STACK_GROWS_DOWN
+# define HEURISTIC2
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# define SEARCH_FOR_DATA_START
+ extern int _end[];
+# define DATAEND ((ptr_t) (_end))
+/* # define MPROTECT_VDB Not quite working yet? */
+# define DYNAMIC_LOADING
+# endif
+# ifdef DARWIN
+# define OS_TYPE "DARWIN"
+# define DARWIN_DONT_PARSE_STACK
+# define DYNAMIC_LOADING
+ /* XXX: see get_end(3), get_etext() and get_end() should not be used.
+ These aren't used when dyld support is enabled (it is by default) */
+# define DATASTART ((ptr_t) get_etext())
+# define DATAEND ((ptr_t) get_end())
+# define STACKBOTTOM ((ptr_t) 0xc0000000)
+# define USE_MMAP
+# define USE_MMAP_ANON
+# ifdef GC_DARWIN_THREADS
+# define MPROTECT_VDB
+# endif
+# include <unistd.h>
+# define GETPAGESIZE() getpagesize()
+ /* There seems to be some issues with trylock hanging on darwin. This
+ should be looked into some more */
+# define NO_PTHREAD_TRYLOCK
+# endif /* DARWIN */
+# endif
+
+# ifdef NS32K
+# define MACH_TYPE "NS32K"
+# define ALIGNMENT 4
+ extern char **environ;
+# define DATASTART ((ptr_t)(&environ))
+ /* hideous kludge: environ is the first */
+ /* word in crt0.o, and delimits the start */
+ /* of the data segment, no matter which */
+ /* ld options were passed through. */
+# define STACKBOTTOM ((ptr_t) 0xfffff000) /* for Encore */
+# endif
+
+# ifdef MIPS
+# define MACH_TYPE "MIPS"
+# ifdef LINUX
+ /* This was developed for a linuxce style platform. Probably */
+ /* needs to be tweaked for workstation class machines. */
+# define OS_TYPE "LINUX"
+# define DYNAMIC_LOADING
+ extern int _end[];
+# define DATAEND (_end)
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+# define ALIGNMENT 4
+# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 2 || __GLIBC__ > 2
+# define LINUX_STACKBOTTOM
+# else
+# define STACKBOTTOM 0x80000000
+# endif
+# endif /* Linux */
+# ifdef EWS4800
+# define HEURISTIC2
+# if defined(_MIPS_SZPTR) && (_MIPS_SZPTR == 64)
+ extern int _fdata[], _end[];
+# define DATASTART ((ptr_t)_fdata)
+# define DATAEND ((ptr_t)_end)
+# define CPP_WORDSZ _MIPS_SZPTR
+# define ALIGNMENT (_MIPS_SZPTR/8)
+# else
+ extern int etext[], edata[], end[];
+ extern int _DYNAMIC_LINKING[], _gp[];
+# define DATASTART ((ptr_t)((((word)etext + 0x3ffff) & ~0x3ffff) \
+ + ((word)etext & 0xffff)))
+# define DATAEND (edata)
+# define DATASTART2 (_DYNAMIC_LINKING \
+ ? (ptr_t)(((word)_gp + 0x8000 + 0x3ffff) & ~0x3ffff) \
+ : (ptr_t)edata)
+# define DATAEND2 (end)
+# define ALIGNMENT 4
+# endif
+# define OS_TYPE "EWS4800"
+# endif
+# ifdef ULTRIX
+# define HEURISTIC2
+# define DATASTART (ptr_t)0x10000000
+ /* Could probably be slightly higher since */
+ /* startup code allocates lots of stuff. */
+# define OS_TYPE "ULTRIX"
+# define ALIGNMENT 4
+# endif
+# ifdef IRIX5
+# define HEURISTIC2
+ extern int _fdata[];
+# define DATASTART ((ptr_t)(_fdata))
+# ifdef USE_MMAP
+# define HEAP_START (ptr_t)0x30000000
+# else
+# define HEAP_START DATASTART
+# endif
+ /* Lowest plausible heap address. */
+ /* In the MMAP case, we map there. */
+ /* In either case it is used to identify */
+ /* heap sections so they're not */
+ /* considered as roots. */
+# define OS_TYPE "IRIX5"
+/*# define MPROTECT_VDB DOB: this should work, but there is evidence */
+/* of recent breakage. */
+# ifdef _MIPS_SZPTR
+# define CPP_WORDSZ _MIPS_SZPTR
+# define ALIGNMENT (_MIPS_SZPTR/8)
+# else
+# define ALIGNMENT 4
+# endif
+# define DYNAMIC_LOADING
+# endif
+# ifdef MSWINCE
+# define OS_TYPE "MSWINCE"
+# define ALIGNMENT 4
+# define DATAEND /* not needed */
+# endif
+# if defined(NETBSD)
+# define OS_TYPE "NETBSD"
+# define ALIGNMENT 4
+# define HEURISTIC2
+# ifdef __ELF__
+ extern int etext[];
+# define DATASTART GC_data_start
+# define NEED_FIND_LIMIT
+# define DYNAMIC_LOADING
+# else
+# define DATASTART ((ptr_t) 0x10000000)
+# define STACKBOTTOM ((ptr_t) 0x7ffff000)
+# endif /* _ELF_ */
+# endif
+# if defined(NONSTOP)
+# define CPP_WORDSZ 32
+# define OS_TYPE "NONSTOP"
+# define ALIGNMENT 4
+# define DATASTART ((ptr_t) 0x08000000)
+ extern char **environ;
+# define DATAEND ((ptr_t)(environ - 0x10))
+# define STACKBOTTOM ((ptr_t) 0x4fffffff)
+# endif
+# endif
+
+# ifdef HP_PA
+# define MACH_TYPE "HP_PA"
+# ifdef __LP64__
+# define CPP_WORDSZ 64
+# define ALIGNMENT 8
+# else
+# define CPP_WORDSZ 32
+# define ALIGNMENT 4
+# endif
+# if !defined(GC_HPUX_THREADS) && !defined(GC_LINUX_THREADS)
+# ifndef LINUX /* For now. */
+# define MPROTECT_VDB
+# endif
+# else
+# ifdef PARALLEL_MARK
+# define USE_MARK_BYTES
+ /* Minimize compare-and-swap usage. */
+# endif
+# endif
+# define STACK_GROWS_UP
+# ifdef HPUX
+# define OS_TYPE "HPUX"
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+# if 0
+ /* The following appears to work for 7xx systems running HP/UX */
+ /* 9.xx Furthermore, it might result in much faster */
+ /* collections than HEURISTIC2, which may involve scanning */
+ /* segments that directly precede the stack. It is not the */
+ /* default, since it may not work on older machine/OS */
+ /* combinations. (Thanks to Raymond X.T. Nijssen for uncovering */
+ /* this.) */
+# define STACKBOTTOM ((ptr_t) 0x7b033000) /* from /etc/conf/h/param.h */
+# else
+ /* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */
+ /* to this. Note that the GC must be initialized before the */
+ /* first putenv call. */
+ extern char ** environ;
+# define STACKBOTTOM ((ptr_t)environ)
+# endif
+# define DYNAMIC_LOADING
+# include <unistd.h>
+# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
+# ifndef __GNUC__
+# define PREFETCH(x) { \
+ register long addr = (long)(x); \
+ (void) _asm ("LDW", 0, 0, addr, 0); \
+ }
+# endif
+# endif /* HPUX */
+# ifdef LINUX
+# define OS_TYPE "LINUX"
+# define LINUX_STACKBOTTOM
+# define DYNAMIC_LOADING
+# define SEARCH_FOR_DATA_START
+ extern int _end[];
+# define DATAEND (&_end)
+# endif /* LINUX */
+# endif /* HP_PA */
+
+# ifdef ALPHA
+# define MACH_TYPE "ALPHA"
+# define ALIGNMENT 8
+# define CPP_WORDSZ 64
+# ifdef NETBSD
+# define OS_TYPE "NETBSD"
+# define HEURISTIC2
+# define DATASTART GC_data_start
+# define ELFCLASS32 32
+# define ELFCLASS64 64
+# define ELF_CLASS ELFCLASS64
+# define DYNAMIC_LOADING
+# endif
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# define HEURISTIC2
+# ifdef __ELF__ /* since OpenBSD/Alpha 2.9 */
+# define DATASTART GC_data_start
+# define ELFCLASS32 32
+# define ELFCLASS64 64
+# define ELF_CLASS ELFCLASS64
+# else /* ECOFF, until OpenBSD/Alpha 2.7 */
+# define DATASTART ((ptr_t) 0x140000000)
+# endif
+# endif
+# ifdef FREEBSD
+# define OS_TYPE "FREEBSD"
+/* MPROTECT_VDB is not yet supported at all on FreeBSD/alpha. */
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# define FREEBSD_STACKBOTTOM
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+/* Handle unmapped hole alpha*-*-freebsd[45]* puts between etext and edata. */
+ extern char etext[];
+ extern char edata[];
+ extern char end[];
+# define NEED_FIND_LIMIT
+# define DATASTART ((ptr_t)(&etext))
+# define DATAEND (GC_find_limit (DATASTART, TRUE))
+# define DATASTART2 ((ptr_t)(&edata))
+# define DATAEND2 ((ptr_t)(&end))
+# endif
+# ifdef OSF1
+# define OS_TYPE "OSF1"
+# define DATASTART ((ptr_t) 0x140000000)
+ extern int _end[];
+# define DATAEND ((ptr_t) &_end)
+ extern char ** environ;
+ /* round up from the value of environ to the nearest page boundary */
+ /* Probably breaks if putenv is called before collector */
+ /* initialization. */
+# define STACKBOTTOM ((ptr_t)(((word)(environ) | (getpagesize()-1))+1))
+/* # define HEURISTIC2 */
+ /* Normally HEURISTIC2 is too conervative, since */
+ /* the text segment immediately follows the stack. */
+ /* Hence we give an upper pound. */
+ /* This is currently unused, since we disabled HEURISTIC2 */
+ extern int __start[];
+# define HEURISTIC2_LIMIT ((ptr_t)((word)(__start) & ~(getpagesize()-1)))
+# ifndef GC_OSF1_THREADS
+ /* Unresolved signal issues with threads. */
+# define MPROTECT_VDB
+# endif
+# define DYNAMIC_LOADING
+# endif
+# ifdef LINUX
+# define OS_TYPE "LINUX"
+# define LINUX_STACKBOTTOM
+# ifdef __ELF__
+# define SEARCH_FOR_DATA_START
+# define DYNAMIC_LOADING
+# else
+# define DATASTART ((ptr_t) 0x140000000)
+# endif
+ extern int _end[];
+# define DATAEND (_end)
+# define MPROTECT_VDB
+ /* Has only been superficially tested. May not */
+ /* work on all versions. */
+# endif
+# endif
+
+# ifdef IA64
+# define MACH_TYPE "IA64"
+# ifdef HPUX
+# ifdef _ILP32
+# define CPP_WORDSZ 32
+ /* Requires 8 byte alignment for malloc */
+# define ALIGNMENT 4
+# else
+# ifndef _LP64
+ ---> unknown ABI
+# endif
+# define CPP_WORDSZ 64
+ /* Requires 16 byte alignment for malloc */
+# define ALIGNMENT 8
+# endif
+# define OS_TYPE "HPUX"
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+ /* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */
+ /* to this. Note that the GC must be initialized before the */
+ /* first putenv call. */
+ extern char ** environ;
+# define STACKBOTTOM ((ptr_t)environ)
+# define HPUX_STACKBOTTOM
+# define DYNAMIC_LOADING
+# include <unistd.h>
+# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
+ /* The following was empirically determined, and is probably */
+ /* not very robust. */
+ /* Note that the backing store base seems to be at a nice */
+ /* address minus one page. */
+# define BACKING_STORE_DISPLACEMENT 0x1000000
+# define BACKING_STORE_ALIGNMENT 0x1000
+ extern ptr_t GC_register_stackbottom;
+# define BACKING_STORE_BASE GC_register_stackbottom
+ /* Known to be wrong for recent HP/UX versions!!! */
+# endif
+# ifdef LINUX
+# define CPP_WORDSZ 64
+# define ALIGNMENT 8
+# define OS_TYPE "LINUX"
+ /* The following works on NUE and older kernels: */
+/* # define STACKBOTTOM ((ptr_t) 0xa000000000000000l) */
+ /* This does not work on NUE: */
+# define LINUX_STACKBOTTOM
+ /* We also need the base address of the register stack */
+ /* backing store. This is computed in */
+ /* GC_linux_register_stack_base based on the following */
+ /* constants: */
+# define BACKING_STORE_ALIGNMENT 0x100000
+# define BACKING_STORE_DISPLACEMENT 0x80000000
+ extern ptr_t GC_register_stackbottom;
+# define BACKING_STORE_BASE GC_register_stackbottom
+# define SEARCH_FOR_DATA_START
+# ifdef __GNUC__
+# define DYNAMIC_LOADING
+# else
+ /* In the Intel compiler environment, we seem to end up with */
+ /* statically linked executables and an undefined reference */
+ /* to _DYNAMIC */
+# endif
+# define MPROTECT_VDB
+ /* Requires Linux 2.3.47 or later. */
+ extern int _end[];
+# define DATAEND (_end)
+# ifdef __GNUC__
+# ifndef __INTEL_COMPILER
+# define PREFETCH(x) \
+ __asm__ (" lfetch [%0]": : "r"(x))
+# define PREFETCH_FOR_WRITE(x) \
+ __asm__ (" lfetch.excl [%0]": : "r"(x))
+# define CLEAR_DOUBLE(x) \
+ __asm__ (" stf.spill [%0]=f0": : "r"((void *)(x)))
+# else
+# include <ia64intrin.h>
+# define PREFETCH(x) \
+ __lfetch(__lfhint_none, (x))
+# define PREFETCH_FOR_WRITE(x) \
+ __lfetch(__lfhint_nta, (x))
+# define CLEAR_DOUBLE(x) \
+ __stf_spill((void *)(x), 0)
+# endif // __INTEL_COMPILER
+# endif
+# endif
+# ifdef MSWIN32
+ /* FIXME: This is a very partial guess. There is no port, yet. */
+# define OS_TYPE "MSWIN32"
+ /* STACKBOTTOM and DATASTART are handled specially in */
+ /* os_dep.c. */
+# define DATAEND /* not needed */
+# if defined(_WIN64)
+# define CPP_WORDSZ 64
+# else
+# define CPP_WORDSZ 32 /* Is this possible? */
+# endif
+# define ALIGNMENT 8
+# define STRTOULL _strtoui64
+# endif
+# endif
+
+# ifdef M88K
+# define MACH_TYPE "M88K"
+# define ALIGNMENT 4
+ extern int etext[];
+# ifdef CX_UX
+# define OS_TYPE "CX_UX"
+# define DATASTART ((((word)etext + 0x3fffff) & ~0x3fffff) + 0x10000)
+# endif
+# ifdef DGUX
+# define OS_TYPE "DGUX"
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)
+# endif
+# define STACKBOTTOM ((char*)0xf0000000) /* determined empirically */
+# endif
+
+# ifdef S370
+ /* If this still works, and if anyone cares, this should probably */
+ /* be moved to the S390 category. */
+# define MACH_TYPE "S370"
+# define ALIGNMENT 4 /* Required by hardware */
+# ifdef UTS4
+# define OS_TYPE "UTS4"
+ extern int etext[];
+ extern int _etext[];
+ extern int _end[];
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
+# define DATAEND (_end)
+# define HEURISTIC2
+# endif
+# endif
+
+# ifdef S390
+# define MACH_TYPE "S390"
+# ifndef __s390x__
+# define ALIGNMENT 4
+# define CPP_WORDSZ 32
+# else
+# define ALIGNMENT 8
+# define CPP_WORDSZ 64
+# ifndef HBLKSIZE
+# define HBLKSIZE 4096
+# endif
+# endif
+# ifdef LINUX
+# define OS_TYPE "LINUX"
+# define LINUX_STACKBOTTOM
+# define DYNAMIC_LOADING
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+ extern int _end[];
+# define DATAEND (_end)
+# define CACHE_LINE_SIZE 256
+# define GETPAGESIZE() 4096
+# endif
+# endif
+
+# ifdef ARM32
+# define CPP_WORDSZ 32
+# define MACH_TYPE "ARM32"
+# define ALIGNMENT 4
+# ifdef NETBSD
+# define OS_TYPE "NETBSD"
+# define HEURISTIC2
+# ifdef __ELF__
+# define DATASTART GC_data_start
+# define DYNAMIC_LOADING
+# else
+ extern char etext[];
+# define DATASTART ((ptr_t)(etext))
+# endif
+# endif
+# ifdef LINUX
+# define OS_TYPE "LINUX"
+# define LINUX_STACKBOTTOM
+# undef STACK_GRAN
+# define STACK_GRAN 0x10000000
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# include <features.h>
+# if defined(__GLIBC__) && __GLIBC__ >= 2
+# define SEARCH_FOR_DATA_START
+# else
+ extern char **__environ;
+# define DATASTART ((ptr_t)(&__environ))
+ /* hideous kludge: __environ is the first */
+ /* word in crt0.o, and delimits the start */
+ /* of the data segment, no matter which */
+ /* ld options were passed through. */
+ /* We could use _etext instead, but that */
+ /* would include .rodata, which may */
+ /* contain large read-only data tables */
+ /* that we'd rather not scan. */
+# endif
+ extern int _end[];
+# define DATAEND (_end)
+# else
+ extern int etext[];
+# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
+# endif
+# endif
+# ifdef MSWINCE
+# define OS_TYPE "MSWINCE"
+# define DATAEND /* not needed */
+# endif
+# ifdef NOSYS
+ /* __data_start is usually defined in the target linker script. */
+ extern int __data_start[];
+# define DATASTART (ptr_t)(__data_start)
+ /* __stack_base__ is set in newlib/libc/sys/arm/crt0.S */
+ extern void *__stack_base__;
+# define STACKBOTTOM ((ptr_t) (__stack_base__))
+# endif
+#endif
+
+# ifdef CRIS
+# define MACH_TYPE "CRIS"
+# define CPP_WORDSZ 32
+# define ALIGNMENT 1
+# define OS_TYPE "LINUX"
+# define DYNAMIC_LOADING
+# define LINUX_STACKBOTTOM
+# define SEARCH_FOR_DATA_START
+ extern int _end[];
+# define DATAEND (_end)
+# endif
+
+# ifdef SH
+# define MACH_TYPE "SH"
+# define ALIGNMENT 4
+# ifdef MSWINCE
+# define OS_TYPE "MSWINCE"
+# define DATAEND /* not needed */
+# endif
+# ifdef LINUX
+# define OS_TYPE "LINUX"
+# define LINUX_STACKBOTTOM
+# define DYNAMIC_LOADING
+# define SEARCH_FOR_DATA_START
+ extern int _end[];
+# define DATAEND (_end)
+# endif
+# ifdef NETBSD
+# define OS_TYPE "NETBSD"
+# define HEURISTIC2
+# define DATASTART GC_data_start
+# define DYNAMIC_LOADING
+# endif
+# endif
+
+# ifdef SH4
+# define MACH_TYPE "SH4"
+# define OS_TYPE "MSWINCE"
+# define ALIGNMENT 4
+# define DATAEND /* not needed */
+# endif
+
+# ifdef M32R
+# define CPP_WORDSZ 32
+# define MACH_TYPE "M32R"
+# define ALIGNMENT 4
+# ifdef LINUX
+# define OS_TYPE "LINUX"
+# define LINUX_STACKBOTTOM
+# undef STACK_GRAN
+# define STACK_GRAN 0x10000000
+# define DYNAMIC_LOADING
+# define SEARCH_FOR_DATA_START
+ extern int _end[];
+# define DATAEND (_end)
+# endif
+# endif
+
+# ifdef X86_64
+# define MACH_TYPE "X86_64"
+# define ALIGNMENT 8
+# define CPP_WORDSZ 64
+# ifndef HBLKSIZE
+# define HBLKSIZE 4096
+# endif
+# define CACHE_LINE_SIZE 64
+# ifdef LINUX
+# define OS_TYPE "LINUX"
+# define LINUX_STACKBOTTOM
+# if !defined(GC_LINUX_THREADS) || !defined(REDIRECT_MALLOC)
+# define MPROTECT_VDB
+# else
+ /* We seem to get random errors in incremental mode, */
+ /* possibly because Linux threads is itself a malloc client */
+ /* and can't deal with the signals. */
+# endif
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# ifdef UNDEFINED /* includes ro data */
+ extern int _etext[];
+# define DATASTART ((ptr_t)((((word) (_etext)) + 0xfff) & ~0xfff))
+# endif
+# include <features.h>
+# define SEARCH_FOR_DATA_START
+ extern int _end[];
+# define DATAEND (_end)
+# else
+ extern int etext[];
+# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
+# endif
+# if defined(__GNUC__) && __GNUC__ >= 3
+# define PREFETCH(x) __builtin_prefetch((x), 0, 0)
+# define PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1)
+# endif
+# endif
+# ifdef DARWIN
+# define OS_TYPE "DARWIN"
+# define DARWIN_DONT_PARSE_STACK
+# define DYNAMIC_LOADING
+ /* XXX: see get_end(3), get_etext() and get_end() should not be used.
+ These aren't used when dyld support is enabled (it is by default) */
+# define DATASTART ((ptr_t) get_etext())
+# define DATAEND ((ptr_t) get_end())
+# define STACKBOTTOM ((ptr_t) 0x7fff5fc00000)
+# define USE_MMAP
+# define USE_MMAP_ANON
+# ifdef GC_DARWIN_THREADS
+# define MPROTECT_VDB
+# endif
+# include <unistd.h>
+# define GETPAGESIZE() getpagesize()
+ /* There seems to be some issues with trylock hanging on darwin. This
+ should be looked into some more */
+# define NO_PTHREAD_TRYLOCK
+# endif
+# ifdef FREEBSD
+# define OS_TYPE "FREEBSD"
+# ifndef GC_FREEBSD_THREADS
+# define MPROTECT_VDB
+# endif
+# ifdef __GLIBC__
+# define SIG_SUSPEND (32+6)
+# define SIG_THR_RESTART (32+5)
+ extern int _end[];
+# define DATAEND (_end)
+# else
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# endif
+# define FREEBSD_STACKBOTTOM
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+ extern char etext[];
+ extern char * GC_FreeBSDGetDataStart();
+# define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
+# endif
+# ifdef NETBSD
+# define OS_TYPE "NETBSD"
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+# define HEURISTIC2
+ extern char etext[];
+# define SEARCH_FOR_DATA_START
+# endif
+# ifdef SOLARIS
+# define OS_TYPE "SOLARIS"
+# define ELF_CLASS ELFCLASS64
+ extern int _etext[], _end[];
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)
+# define DATAEND (_end)
+/* # define STACKBOTTOM ((ptr_t)(_start)) worked through 2.7, */
+/* but reportedly breaks under 2.8. It appears that the stack */
+/* base is a property of the executable, so this should not break */
+/* old executables. */
+/* HEURISTIC2 probably works, but this appears to be preferable. */
+/* Apparently USRSTACK is defined to be USERLIMIT, but in some */
+/* installations that's undefined. We work around this with a */
+/* gross hack: */
+# include <sys/vmparam.h>
+# ifdef USERLIMIT
+ /* This should work everywhere, but doesn't. */
+# define STACKBOTTOM USRSTACK
+# else
+# define HEURISTIC2
+# endif
+/* At least in Solaris 2.5, PROC_VDB gives wrong values for dirty bits. */
+/* It appears to be fixed in 2.8 and 2.9. */
+# ifdef SOLARIS25_PROC_VDB_BUG_FIXED
+# define PROC_VDB
+# endif
+# define DYNAMIC_LOADING
+# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
+# define USE_MMAP
+ /* Otherwise we now use calloc. Mmap may result in the */
+ /* heap interleaved with thread stacks, which can result in */
+ /* excessive blacklisting. Sbrk is unusable since it */
+ /* doesn't interact correctly with the system malloc. */
+# endif
+# ifdef USE_MMAP
+# define HEAP_START (ptr_t)0x40000000
+# else
+# define HEAP_START DATAEND
+# endif
+# endif
+# ifdef MSWIN32
+# define OS_TYPE "MSWIN32"
+ /* STACKBOTTOM and DATASTART are handled specially in */
+ /* os_dep.c. */
+# if !defined(__WATCOMC__)
+# define MPROTECT_VDB
+ /* We also avoided doing this in the past with GC_WIN32_THREADS */
+ /* Hopefully that's fixed. */
+# endif
+# if _MSC_VER >= 1300 /* .NET, i.e. > VisualStudio 6 */
+# define GWW_VDB
+# endif
+# define DATAEND /* not needed */
+# endif
+# endif
+
+#if defined(LINUX) && defined(USE_MMAP)
+ /* The kernel may do a somewhat better job merging mappings etc. */
+ /* with anonymous mappings. */
+# define USE_MMAP_ANON
+#endif
+
+#if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC)
+ /* Nptl allocates thread stacks with mmap, which is fine. But it */
+ /* keeps a cache of thread stacks. Thread stacks contain the */
+ /* thread control blocks. These in turn contain a pointer to */
+ /* (sizeof (void *) from the beginning of) the dtv for thread-local */
+ /* storage, which is calloc allocated. If we don't scan the cached */
+ /* thread stacks, we appear to lose the dtv. This tends to */
+ /* result in something that looks like a bogus dtv count, which */
+ /* tends to result in a memset call on a block that is way too */
+ /* large. Sometimes we're lucky and the process just dies ... */
+ /* There seems to be a similar issue with some other memory */
+ /* allocated by the dynamic loader. */
+ /* This can be avoided by either: */
+ /* - Defining USE_PROC_FOR_LIBRARIES here. */
+ /* That performs very poorly, precisely because we end up */
+ /* scanning cached stacks. */
+ /* - Have calloc look at its callers. That is currently what we do.*/
+ /* In spite of the fact that it is gross and disgusting. */
+/* # define USE_PROC_FOR_LIBRARIES */
+#endif
+
+# ifndef STACK_GROWS_UP
+# define STACK_GROWS_DOWN
+# endif
+
+# ifndef CPP_WORDSZ
+# define CPP_WORDSZ 32
+# endif
+
+# ifndef OS_TYPE
+# define OS_TYPE ""
+# endif
+
+# ifndef DATAEND
+ extern int end[];
+# define DATAEND (end)
+# endif
+
+# if defined(SVR4) && !defined(GETPAGESIZE)
+# include <unistd.h>
+# define GETPAGESIZE() sysconf(_SC_PAGESIZE)
+# endif
+
+# ifndef GETPAGESIZE
+# if defined(SOLARIS) || defined(IRIX5) || defined(LINUX) \
+ || defined(NETBSD) || defined(FREEBSD) || defined(HPUX)
+# include <unistd.h>
+# endif
+# define GETPAGESIZE() getpagesize()
+# endif
+
+# if defined(SOLARIS) || defined(DRSNX) || defined(UTS4)
+ /* OS has SVR4 generic features. */
+ /* Probably others also qualify. */
+# define SVR4
+# endif
+
+# if defined(SOLARIS) || defined(DRSNX)
+ /* OS has SOLARIS style semi-undocumented interface */
+ /* to dynamic loader. */
+# define SOLARISDL
+ /* OS has SOLARIS style signal handlers. */
+# define SUNOS5SIGS
+# endif
+
+# if defined(HPUX)
+# define SUNOS5SIGS
+# endif
+
+# if defined(FREEBSD) && \
+ (defined(__DragonFly__) || __FreeBSD__ >= 4 || (__FreeBSD_kernel__ >= 4))
+# define SUNOS5SIGS
+# endif
+
+# ifdef GC_NETBSD_THREADS
+# define SIGRTMIN 33
+# define SIGRTMAX 63
+# endif
+
+# if defined(SVR4) || defined(LINUX) || defined(IRIX5) || defined(HPUX) \
+ || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \
+ || defined(DGUX) || defined(BSD) \
+ || defined(AIX) || defined(DARWIN) || defined(OSF1) \
+ || defined(HURD)
+# define UNIX_LIKE /* Basic Unix-like system calls work. */
+# endif
+
+# if CPP_WORDSZ != 32 && CPP_WORDSZ != 64
+ -> bad word size
+# endif
+
+# ifdef PCR
+# undef DYNAMIC_LOADING
+# undef STACKBOTTOM
+# undef HEURISTIC1
+# undef HEURISTIC2
+# undef PROC_VDB
+# undef MPROTECT_VDB
+# define PCR_VDB
+# endif
+
+# ifdef SMALL_CONFIG
+ /* Presumably not worth the space it takes. */
+# undef PROC_VDB
+# undef MPROTECT_VDB
+# endif
+
+# ifdef USE_MUNMAP
+# undef MPROTECT_VDB /* Can't deal with address space holes. */
+# endif
+
+# ifdef PARALLEL_MARK
+# undef MPROTECT_VDB /* For now. */
+# endif
+
+# if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB) \
+ && !defined(GWW_VDB)
+# define DEFAULT_VDB
+# endif
+
+# ifndef PREFETCH
+# define PREFETCH(x)
+# define NO_PREFETCH
+# endif
+
+# ifndef PREFETCH_FOR_WRITE
+# define PREFETCH_FOR_WRITE(x)
+# define NO_PREFETCH_FOR_WRITE
+# endif
+
+# ifndef CACHE_LINE_SIZE
+# define CACHE_LINE_SIZE 32 /* Wild guess */
+# endif
+
+# if defined(LINUX) || defined(HURD) || defined(__GLIBC__)
+# define REGISTER_LIBRARIES_EARLY
+ /* We sometimes use dl_iterate_phdr, which may acquire an internal */
+ /* lock. This isn't safe after the world has stopped. So we must */
+ /* call GC_register_dynamic_libraries before stopping the world. */
+ /* For performance reasons, this may be beneficial on other */
+ /* platforms as well, though it should be avoided in win32. */
+# endif /* LINUX */
+
+# if defined(SEARCH_FOR_DATA_START)
+ extern ptr_t GC_data_start;
+# define DATASTART GC_data_start
+# endif
+
+# ifndef CLEAR_DOUBLE
+# define CLEAR_DOUBLE(x) \
+ ((word*)x)[0] = 0; \
+ ((word*)x)[1] = 0;
+# endif /* CLEAR_DOUBLE */
+
+# if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC) \
+ && !defined(INCLUDE_LINUX_THREAD_DESCR)
+ /* Will not work, since libc and the dynamic loader use thread */
+ /* locals, sometimes as the only reference. */
+# define INCLUDE_LINUX_THREAD_DESCR
+# endif
+
+# if defined(GC_IRIX_THREADS) && !defined(IRIX5)
+ --> inconsistent configuration
+# endif
+# if defined(GC_LINUX_THREADS) && !defined(LINUX)
+ --> inconsistent configuration
+# endif
+# if defined(GC_NETBSD_THREADS) && !defined(NETBSD)
+ --> inconsistent configuration
+# endif
+# if defined(GC_SOLARIS_THREADS) && !defined(SOLARIS)
+ --> inconsistent configuration
+# endif
+# if defined(GC_HPUX_THREADS) && !defined(HPUX)
+ --> inconsistent configuration
+# endif
+# if defined(GC_AIX_THREADS) && !defined(_AIX)
+ --> inconsistent configuration
+# endif
+# if defined(GC_GNU_THREADS) && !defined(HURD)
+ --> inconsistent configuration
+# endif
+# if defined(GC_WIN32_THREADS) && !defined(MSWIN32) && !defined(CYGWIN32)
+ --> inconsistent configuration
+# endif
+
+# if defined(PCR) || defined(GC_WIN32_THREADS) || defined(GC_PTHREADS)
+# define THREADS
+# endif
+
+# if !defined(USE_MARK_BITS) && !defined(USE_MARK_BYTES)
+# if defined(THREADS) && defined(PARALLEL_MARK)
+# define USE_MARK_BYTES
+# else
+# define USE_MARK_BITS
+# endif
+# endif
+
+# if defined(MSWINCE)
+# define NO_GETENV
+# endif
+
+# if defined(SPARC)
+# define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */
+ /* include assembly code to do it well. */
+# endif
+
+ /* Can we save call chain in objects for debugging? */
+ /* SET NFRAMES (# of saved frames) and NARGS (#of args for each */
+ /* frame) to reasonable values for the platform. */
+ /* Set SAVE_CALL_CHAIN if we can. SAVE_CALL_COUNT can be specified */
+ /* at build time, though we feel free to adjust it slightly. */
+ /* Define NEED_CALLINFO if we either save the call stack or */
+ /* GC_ADD_CALLER is defined. */
+ /* GC_CAN_SAVE_CALL_STACKS is set in gc.h. */
+
+#if defined(SPARC)
+# define CAN_SAVE_CALL_ARGS
+#endif
+#if (defined(I386) || defined(X86_64)) && (defined(LINUX) || defined(__GLIBC__))
+ /* SAVE_CALL_CHAIN is supported if the code is compiled to save */
+ /* frame pointers by default, i.e. no -fomit-frame-pointer flag. */
+# define CAN_SAVE_CALL_ARGS
+#endif
+
+# if defined(SAVE_CALL_COUNT) && !defined(GC_ADD_CALLER) \
+ && defined(GC_CAN_SAVE_CALL_STACKS)
+# define SAVE_CALL_CHAIN
+# endif
+# ifdef SAVE_CALL_CHAIN
+# if defined(SAVE_CALL_NARGS) && defined(CAN_SAVE_CALL_ARGS)
+# define NARGS SAVE_CALL_NARGS
+# else
+# define NARGS 0 /* Number of arguments to save for each call. */
+# endif
+# endif
+# ifdef SAVE_CALL_CHAIN
+# ifndef SAVE_CALL_COUNT
+# define NFRAMES 6 /* Number of frames to save. Even for */
+ /* alignment reasons. */
+# else
+# define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1)
+# endif
+# define NEED_CALLINFO
+# endif /* SAVE_CALL_CHAIN */
+# ifdef GC_ADD_CALLER
+# define NFRAMES 1
+# define NARGS 0
+# define NEED_CALLINFO
+# endif
+
+# if defined(MAKE_BACK_GRAPH) && !defined(DBG_HDRS_ALL)
+# define DBG_HDRS_ALL
+# endif
+
+# if defined(POINTER_MASK) && !defined(POINTER_SHIFT)
+# define POINTER_SHIFT 0
+# endif
+
+# if defined(POINTER_SHIFT) && !defined(POINTER_MASK)
+# define POINTER_MASK ((GC_word)(-1))
+# endif
+
+# if !defined(FIXUP_POINTER) && defined(POINTER_MASK)
+# define FIXUP_POINTER(p) (p) = ((p) & (POINTER_MASK) << POINTER_SHIFT)
+# endif
+
+# if defined(FIXUP_POINTER)
+# define NEED_FIXUP_POINTER 1
+# else
+# define NEED_FIXUP_POINTER 0
+# define FIXUP_POINTER(p)
+# endif
+
+# if !defined(MARK_BIT_PER_GRANULE) && !defined(MARK_BIT_PER_OBJ)
+# define MARK_BIT_PER_GRANULE /* Usually faster */
+# endif
+
+/* Some static sanity tests. */
+# if defined(MARK_BIT_PER_GRANULE) && defined(MARK_BIT_PER_OBJ)
+# error Define only one of MARK_BIT_PER_GRANULE and MARK_BIT_PER_OBJ.
+# endif
+
+# if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
+# error "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd."
+# endif
+# if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
+# error "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd."
+# endif
+
+# if defined(REDIRECT_MALLOC) && defined(THREADS) && !defined(LINUX)
+# error "REDIRECT_MALLOC with THREADS works at most on Linux."
+# endif
+
+#ifdef GC_PRIVATE_H
+ /* This relies on some type definitions from gc_priv.h, from */
+ /* where it's normally included. */
+ /* */
+ /* How to get heap memory from the OS: */
+ /* Note that sbrk()-like allocation is preferred, since it */
+ /* usually makes it possible to merge consecutively allocated */
+ /* chunks. It also avoids unintented recursion with */
+ /* -DREDIRECT_MALLOC. */
+ /* GET_MEM() returns a HLKSIZE aligned chunk. */
+ /* 0 is taken to mean failure. */
+ /* In the case os USE_MMAP, the argument must also be a */
+ /* physical page size. */
+ /* GET_MEM is currently not assumed to retrieve 0 filled space, */
+ /* though we should perhaps take advantage of the case in which */
+ /* does. */
+ struct hblk; /* See gc_priv.h. */
+# if defined(PCR)
+ char * real_malloc();
+# define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \
+ + GC_page_size-1)
+# elif defined(OS2)
+ void * os2_alloc(size_t bytes);
+# define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc((size_t)bytes \
+ + GC_page_size) \
+ + GC_page_size-1)
+# elif defined(NEXT) || defined(DOS4GW) || defined(NONSTOP) || \
+ (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \
+ (defined(SOLARIS) && !defined(USE_MMAP))
+# define GET_MEM(bytes) HBLKPTR((size_t) calloc(1, (size_t)bytes + GC_page_size) \
+ + GC_page_size-1)
+# elif defined(MSWIN32)
+ extern ptr_t GC_win32_get_mem();
+# define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes)
+# elif defined(MACOS)
+# if defined(USE_TEMPORARY_MEMORY)
+ extern Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory);
+# define GET_MEM(bytes) HBLKPTR( \
+ GC_MacTemporaryNewPtr(bytes + GC_page_size, true) \
+ + GC_page_size-1)
+# else
+# define GET_MEM(bytes) HBLKPTR( \
+ NewPtrClear(bytes + GC_page_size) + GC_page_size-1)
+# endif
+# elif defined(MSWINCE)
+ extern ptr_t GC_wince_get_mem();
+# define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes)
+# elif defined(AMIGA) && defined(GC_AMIGA_FASTALLOC)
+ extern void *GC_amiga_get_mem(size_t size);
+# define GET_MEM(bytes) HBLKPTR((size_t) \
+ GC_amiga_get_mem((size_t)bytes + GC_page_size) \
+ + GC_page_size-1)
+# else
+ extern ptr_t GC_unix_get_mem();
+# define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes)
+# endif
+
+#endif /* GC_PRIVATE_H */
+
+# endif /* GCCONFIG_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/private/msvc_dbg.h b/tools/build/v2/engine/boehm_gc/include/private/msvc_dbg.h
new file mode 100644
index 0000000000..1d3030aaab
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/msvc_dbg.h
@@ -0,0 +1,69 @@
+/*
+ Copyright (c) 2004-2005 Andrei Polushin
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+#ifndef _MSVC_DBG_H
+#define _MSVC_DBG_H
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !MSVC_DBG_DLL
+#define MSVC_DBG_EXPORT
+#elif MSVC_DBG_BUILD
+#define MSVC_DBG_EXPORT __declspec(dllexport)
+#else
+#define MSVC_DBG_EXPORT __declspec(dllimport)
+#endif
+
+#ifndef MAX_SYM_NAME
+#define MAX_SYM_NAME 2000
+#endif
+
+typedef void* HANDLE;
+typedef struct _CONTEXT CONTEXT;
+
+MSVC_DBG_EXPORT size_t GetStackFrames(size_t skip, void* frames[], size_t maxFrames);
+MSVC_DBG_EXPORT size_t GetStackFramesFromContext(HANDLE hProcess, HANDLE hThread, CONTEXT* context, size_t skip, void* frames[], size_t maxFrames);
+
+MSVC_DBG_EXPORT size_t GetModuleNameFromAddress(void* address, char* moduleName, size_t size);
+MSVC_DBG_EXPORT size_t GetModuleNameFromStack(size_t skip, char* moduleName, size_t size);
+
+MSVC_DBG_EXPORT size_t GetSymbolNameFromAddress(void* address, char* symbolName, size_t size, size_t* offsetBytes);
+MSVC_DBG_EXPORT size_t GetSymbolNameFromStack(size_t skip, char* symbolName, size_t size, size_t* offsetBytes);
+
+MSVC_DBG_EXPORT size_t GetFileLineFromAddress(void* address, char* fileName, size_t size, size_t* lineNumber, size_t* offsetBytes);
+MSVC_DBG_EXPORT size_t GetFileLineFromStack(size_t skip, char* fileName, size_t size, size_t* lineNumber, size_t* offsetBytes);
+
+MSVC_DBG_EXPORT size_t GetDescriptionFromAddress(void* address, const char* format, char* description, size_t size);
+MSVC_DBG_EXPORT size_t GetDescriptionFromStack(void*const frames[], size_t count, const char* format, char* description[], size_t size);
+
+/* Compatibility with <execinfo.h> */
+MSVC_DBG_EXPORT int backtrace(void* addresses[], int count);
+MSVC_DBG_EXPORT char** backtrace_symbols(void*const addresses[], int count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif/*_MSVC_DBG_H*/
diff --git a/tools/build/v2/engine/boehm_gc/include/private/pthread_stop_world.h b/tools/build/v2/engine/boehm_gc/include/private/pthread_stop_world.h
new file mode 100644
index 0000000000..6f9197a1f6
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/pthread_stop_world.h
@@ -0,0 +1,11 @@
+#ifndef GC_PTHREAD_STOP_WORLD_H
+#define GC_PTHREAD_STOP_WORLD_H
+
+struct thread_stop_info {
+ word last_stop_count; /* GC_last_stop_count value when thread */
+ /* last successfully handled a suspend */
+ /* signal. */
+ ptr_t stack_ptr; /* Valid only when stopped. */
+};
+
+#endif
diff --git a/tools/build/v2/engine/boehm_gc/include/private/pthread_support.h b/tools/build/v2/engine/boehm_gc/include/private/pthread_support.h
new file mode 100644
index 0000000000..77f1ad1a90
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/pthread_support.h
@@ -0,0 +1,84 @@
+#ifndef GC_PTHREAD_SUPPORT_H
+#define GC_PTHREAD_SUPPORT_H
+
+# include "private/gc_priv.h"
+
+# if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS)
+
+#if defined(GC_DARWIN_THREADS)
+# include "private/darwin_stop_world.h"
+#else
+# include "private/pthread_stop_world.h"
+#endif
+
+#ifdef THREAD_LOCAL_ALLOC
+# include "thread_local_alloc.h"
+#endif /* THREAD_LOCAL_ALLOC */
+
+/* We use the allocation lock to protect thread-related data structures. */
+
+/* The set of all known threads. We intercept thread creation and */
+/* joins. */
+/* Protected by allocation/GC lock. */
+/* Some of this should be declared volatile, but that's inconsistent */
+/* with some library routine declarations. */
+typedef struct GC_Thread_Rep {
+ struct GC_Thread_Rep * next; /* More recently allocated threads */
+ /* with a given pthread id come */
+ /* first. (All but the first are */
+ /* guaranteed to be dead, but we may */
+ /* not yet have registered the join.) */
+ pthread_t id;
+ /* Extra bookkeeping information the stopping code uses */
+ struct thread_stop_info stop_info;
+
+ short flags;
+# define FINISHED 1 /* Thread has exited. */
+# define DETACHED 2 /* Thread is treated as detached. */
+ /* Thread may really be detached, or */
+ /* it may have have been explicitly */
+ /* registered, in which case we can */
+ /* deallocate its GC_Thread_Rep once */
+ /* it unregisters itself, since it */
+ /* may not return a GC pointer. */
+# define MAIN_THREAD 4 /* True for the original thread only. */
+ short thread_blocked; /* Protected by GC lock. */
+ /* Treated as a boolean value. If set, */
+ /* thread will acquire GC lock before */
+ /* doing any pointer manipulations, and */
+ /* has set its sp value. Thus it does */
+ /* not need to be sent a signal to stop */
+ /* it. */
+ ptr_t stack_end; /* Cold end of the stack. */
+# ifdef IA64
+ ptr_t backing_store_end;
+ ptr_t backing_store_ptr;
+# endif
+ void * status; /* The value returned from the thread. */
+ /* Used only to avoid premature */
+ /* reclamation of any data it might */
+ /* reference. */
+ /* This is unfortunately also the */
+ /* reason we need to intercept join */
+ /* and detach. */
+# ifdef THREAD_LOCAL_ALLOC
+ struct thread_local_freelists tlfs;
+# endif
+} * GC_thread;
+
+# define THREAD_TABLE_SZ 256 /* Must be power of 2 */
+extern volatile GC_thread GC_threads[THREAD_TABLE_SZ];
+
+extern GC_bool GC_thr_initialized;
+
+GC_thread GC_lookup_thread(pthread_t id);
+
+void GC_stop_init();
+
+extern GC_bool GC_in_thread_creation;
+ /* We may currently be in thread creation or destruction. */
+ /* Only set to TRUE while allocation lock is held. */
+ /* When set, it is OK to run GC from unknown thread. */
+
+#endif /* GC_PTHREADS && !GC_SOLARIS_THREADS.... etc */
+#endif /* GC_PTHREAD_SUPPORT_H */
diff --git a/tools/build/v2/engine/boehm_gc/include/private/specific.h b/tools/build/v2/engine/boehm_gc/include/private/specific.h
new file mode 100644
index 0000000000..fc2e8f9e66
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/specific.h
@@ -0,0 +1,96 @@
+/*
+ * This is a reimplementation of a subset of the pthread_getspecific/setspecific
+ * interface. This appears to outperform the standard linuxthreads one
+ * by a significant margin.
+ * The major restriction is that each thread may only make a single
+ * pthread_setspecific call on a single key. (The current data structure
+ * doesn't really require that. The restriction should be easily removable.)
+ * We don't currently support the destruction functions, though that
+ * could be done.
+ * We also currently assume that only one pthread_setspecific call
+ * can be executed at a time, though that assumption would be easy to remove
+ * by adding a lock.
+ */
+
+#include <errno.h>
+#include "atomic_ops.h"
+
+/* Called during key creation or setspecific. */
+/* For the GC we already hold lock. */
+/* Currently allocated objects leak on thread exit. */
+/* That's hard to fix, but OK if we allocate garbage */
+/* collected memory. */
+#define MALLOC_CLEAR(n) GC_INTERNAL_MALLOC(n, NORMAL)
+#define PREFIXED(name) GC_##name
+
+#define TS_CACHE_SIZE 1024
+#define CACHE_HASH(n) (((((long)n) >> 8) ^ (long)n) & (TS_CACHE_SIZE - 1))
+#define TS_HASH_SIZE 1024
+#define HASH(n) (((((long)n) >> 8) ^ (long)n) & (TS_HASH_SIZE - 1))
+
+/* An entry describing a thread-specific value for a given thread. */
+/* All such accessible structures preserve the invariant that if either */
+/* thread is a valid pthread id or qtid is a valid "quick tread id" */
+/* for a thread, then value holds the corresponding thread specific */
+/* value. This invariant must be preserved at ALL times, since */
+/* asynchronous reads are allowed. */
+typedef struct thread_specific_entry {
+ volatile AO_t qtid; /* quick thread id, only for cache */
+ void * value;
+ struct thread_specific_entry *next;
+ pthread_t thread;
+} tse;
+
+
+/* We represent each thread-specific datum as two tables. The first is */
+/* a cache, indexed by a "quick thread identifier". The "quick" thread */
+/* identifier is an easy to compute value, which is guaranteed to */
+/* determine the thread, though a thread may correspond to more than */
+/* one value. We typically use the address of a page in the stack. */
+/* The second is a hash table, indexed by pthread_self(). It is used */
+/* only as a backup. */
+
+/* Return the "quick thread id". Default version. Assumes page size, */
+/* or at least thread stack separation, is at least 4K. */
+/* Must be defined so that it never returns 0. (Page 0 can't really */
+/* be part of any stack, since that would make 0 a valid stack pointer.)*/
+static __inline__ unsigned long quick_thread_id() {
+ int dummy;
+ return (unsigned long)(&dummy) >> 12;
+}
+
+#define INVALID_QTID ((unsigned long)0)
+#define INVALID_THREADID ((pthread_t)0)
+
+typedef struct thread_specific_data {
+ tse * volatile cache[TS_CACHE_SIZE];
+ /* A faster index to the hash table */
+ tse * hash[TS_HASH_SIZE];
+ pthread_mutex_t lock;
+} tsd;
+
+typedef tsd * PREFIXED(key_t);
+
+extern int PREFIXED(key_create) (tsd ** key_ptr, void (* destructor)(void *));
+
+extern int PREFIXED(setspecific) (tsd * key, void * value);
+
+extern void PREFIXED(remove_specific) (tsd * key);
+
+/* An internal version of getspecific that assumes a cache miss. */
+void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid,
+ tse * volatile * cache_entry);
+
+static __inline__ void * PREFIXED(getspecific) (tsd * key) {
+ long qtid = quick_thread_id();
+ unsigned hash_val = CACHE_HASH(qtid);
+ tse * volatile * entry_ptr = key -> cache + hash_val;
+ tse * entry = *entry_ptr; /* Must be loaded only once. */
+ if (EXPECT(entry -> qtid == qtid, 1)) {
+ GC_ASSERT(entry -> thread == pthread_self());
+ return entry -> value;
+ }
+ return PREFIXED(slow_getspecific) (key, qtid, entry_ptr);
+}
+
+
diff --git a/tools/build/v2/engine/boehm_gc/include/private/thread_local_alloc.h b/tools/build/v2/engine/boehm_gc/include/private/thread_local_alloc.h
new file mode 100644
index 0000000000..4c2c5362fb
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/private/thread_local_alloc.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2000-2005 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* Included indirectly from a thread-library-specific file. */
+/* This is the interface for thread-local allocation, whose */
+/* implementation is mostly thread-library-independent. */
+/* Here we describe only the interface that needs to be known */
+/* and invoked from the thread support layer; the actual */
+/* implementation also exports GC_malloc and friends, which */
+/* are declared in gc.h. */
+
+#include "private/gc_priv.h"
+
+#if defined(THREAD_LOCAL_ALLOC)
+
+#include "gc_inline.h"
+
+
+# if defined USE_HPUX_TLS
+# error USE_HPUX_TLS macro was replaced by USE_COMPILER_TLS
+# endif
+
+# if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC) && \
+ !defined(USE_WIN32_COMPILER_TLS) && !defined(USE_COMPILER_TLS) && \
+ !defined(USE_CUSTOM_SPECIFIC)
+# if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
+# if defined(__GNUC__) /* Fixed for versions past 2.95? */
+# define USE_WIN32_SPECIFIC
+# else
+# define USE_WIN32_COMPILER_TLS
+# endif /* !GNU */
+# elif defined(LINUX) && !defined(ARM32) && \
+ (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >=3))
+# define USE_COMPILER_TLS
+# elif (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \
+ defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) || \
+ defined(GC_NETBSD_THREADS)
+# define USE_PTHREAD_SPECIFIC
+# elif defined(GC_HPUX_THREADS)
+# ifdef __GNUC__
+# define USE_PTHREAD_SPECIFIC
+ /* Empirically, as of gcc 3.3, USE_COMPILER_TLS doesn't work. */
+# else
+# define USE_COMPILER_TLS
+# endif
+# else
+# define USE_CUSTOM_SPECIFIC /* Use our own. */
+# endif
+# endif
+
+# include <stdlib.h>
+
+/* One of these should be declared as the tlfs field in the */
+/* structure pointed to by a GC_thread. */
+typedef struct thread_local_freelists {
+# ifdef THREAD_LOCAL_ALLOC
+ void * ptrfree_freelists[TINY_FREELISTS];
+ void * normal_freelists[TINY_FREELISTS];
+# ifdef GC_GCJ_SUPPORT
+ void * gcj_freelists[TINY_FREELISTS];
+# define ERROR_FL (void *)(-1)
+ /* Value used for gcj_freelist[-1]; allocation is */
+ /* erroneous. */
+# endif
+ /* Free lists contain either a pointer or a small count */
+ /* reflecting the number of granules allocated at that */
+ /* size. */
+ /* 0 ==> thread-local allocation in use, free list */
+ /* empty. */
+ /* > 0, <= DIRECT_GRANULES ==> Using global allocation, */
+ /* too few objects of this size have been */
+ /* allocated by this thread. */
+ /* >= HBLKSIZE => pointer to nonempty free list. */
+ /* > DIRECT_GRANULES, < HBLKSIZE ==> transition to */
+ /* local alloc, equivalent to 0. */
+# define DIRECT_GRANULES (HBLKSIZE/GRANULE_BYTES)
+ /* Don't use local free lists for up to this much */
+ /* allocation. */
+
+# endif
+} *GC_tlfs;
+
+# if defined(USE_PTHREAD_SPECIFIC)
+# define GC_getspecific pthread_getspecific
+# define GC_setspecific pthread_setspecific
+# define GC_key_create pthread_key_create
+# define GC_remove_specific(key) /* No need for cleanup on exit. */
+ typedef pthread_key_t GC_key_t;
+# elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS)
+# define GC_getspecific(x) (x)
+# define GC_setspecific(key, v) ((key) = (v), 0)
+# define GC_key_create(key, d) 0
+# define GC_remove_specific(key) /* No need for cleanup on exit. */
+ typedef void * GC_key_t;
+# elif defined(USE_WIN32_SPECIFIC)
+# include <windows.h>
+# define GC_getspecific TlsGetValue
+# define GC_setspecific(key, v) !TlsSetValue(key, v)
+ /* We assume 0 == success, msft does the opposite. */
+# define GC_key_create(key, d) \
+ ((d) != 0? (ABORT("Destructor unsupported by TlsAlloc"),0) \
+ : (*(key) = TlsAlloc(), 0))
+# define GC_remove_specific(key) /* No need for cleanup on thread exit. */
+ /* Need TlsFree on process exit/detach ? */
+ typedef DWORD GC_key_t;
+# elif defined(USE_CUSTOM_SPECIFIC)
+# include "private/specific.h"
+# else
+# error implement me
+# endif
+
+
+/* Each thread structure must be initialized. */
+/* This call must be made from the new thread. */
+/* Caller holds allocation lock. */
+void GC_init_thread_local(GC_tlfs p);
+
+/* Called when a thread is unregistered, or exits. */
+/* We hold the allocator lock. */
+void GC_destroy_thread_local(GC_tlfs p);
+
+/* The thread support layer must arrange to mark thread-local */
+/* free lists explicitly, since the link field is often */
+/* invisible to the marker. It knows hoe to find all threads; */
+/* we take care of an individual thread freelist structure. */
+void GC_mark_thread_local_fls_for(GC_tlfs p);
+
+extern
+#if defined(USE_COMPILER_TLS)
+ __thread
+#elif defined(USE_WIN32_COMPILER_TLS)
+ __declspec(thread)
+#endif
+GC_key_t GC_thread_key;
+
+/* This is set up by the thread_local_alloc implementation. But the */
+/* thread support layer calls GC_remove_specific(GC_thread_key) */
+/* before a thread exits. */
+/* And the thread support layer makes sure that GC_thread_key is traced,*/
+/* if necessary. */
+
+#endif /* THREAD_LOCAL_ALLOC */
diff --git a/tools/build/v2/engine/boehm_gc/include/weakpointer.h b/tools/build/v2/engine/boehm_gc/include/weakpointer.h
new file mode 100644
index 0000000000..84906b00a6
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/include/weakpointer.h
@@ -0,0 +1,221 @@
+#ifndef _weakpointer_h_
+#define _weakpointer_h_
+
+/****************************************************************************
+
+WeakPointer and CleanUp
+
+ Copyright (c) 1991 by Xerox Corporation. All rights reserved.
+
+ THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+
+ Permission is hereby granted to copy this code for any purpose,
+ provided the above notices are retained on all copies.
+
+ Last modified on Mon Jul 17 18:16:01 PDT 1995 by ellis
+
+****************************************************************************/
+
+/****************************************************************************
+
+WeakPointer
+
+A weak pointer is a pointer to a heap-allocated object that doesn't
+prevent the object from being garbage collected. Weak pointers can be
+used to track which objects haven't yet been reclaimed by the
+collector. A weak pointer is deactivated when the collector discovers
+its referent object is unreachable by normal pointers (reachability
+and deactivation are defined more precisely below). A deactivated weak
+pointer remains deactivated forever.
+
+****************************************************************************/
+
+
+template< class T > class WeakPointer {
+public:
+
+WeakPointer( T* t = 0 )
+ /* Constructs a weak pointer for *t. t may be null. It is an error
+ if t is non-null and *t is not a collected object. */
+ {impl = _WeakPointer_New( t );}
+
+T* Pointer()
+ /* wp.Pointer() returns a pointer to the referent object of wp or
+ null if wp has been deactivated (because its referent object
+ has been discovered unreachable by the collector). */
+ {return (T*) _WeakPointer_Pointer( this->impl );}
+
+int operator==( WeakPointer< T > wp2 )
+ /* Given weak pointers wp1 and wp2, if wp1 == wp2, then wp1 and
+ wp2 refer to the same object. If wp1 != wp2, then either wp1
+ and wp2 don't refer to the same object, or if they do, one or
+ both of them has been deactivated. (Note: If objects t1 and t2
+ are never made reachable by their clean-up functions, then
+ WeakPointer<T>(t1) == WeakPointer<T>(t2) if and only t1 == t2.) */
+ {return _WeakPointer_Equal( this->impl, wp2.impl );}
+
+int Hash()
+ /* Returns a hash code suitable for use by multiplicative- and
+ division-based hash tables. If wp1 == wp2, then wp1.Hash() ==
+ wp2.Hash(). */
+ {return _WeakPointer_Hash( this->impl );}
+
+private:
+void* impl;
+};
+
+/*****************************************************************************
+
+CleanUp
+
+A garbage-collected object can have an associated clean-up function
+that will be invoked some time after the collector discovers the
+object is unreachable via normal pointers. Clean-up functions can be
+used to release resources such as open-file handles or window handles
+when their containing objects become unreachable. If a C++ object has
+a non-empty explicit destructor (i.e. it contains programmer-written
+code), the destructor will be automatically registered as the object's
+initial clean-up function.
+
+There is no guarantee that the collector will detect every unreachable
+object (though it will find almost all of them). Clients should not
+rely on clean-up to cause some action to occur immediately -- clean-up
+is only a mechanism for improving resource usage.
+
+Every object with a clean-up function also has a clean-up queue. When
+the collector finds the object is unreachable, it enqueues it on its
+queue. The clean-up function is applied when the object is removed
+from the queue. By default, objects are enqueued on the garbage
+collector's queue, and the collector removes all objects from its
+queue after each collection. If a client supplies another queue for
+objects, it is his responsibility to remove objects (and cause their
+functions to be called) by polling it periodically.
+
+Clean-up queues allow clean-up functions accessing global data to
+synchronize with the main program. Garbage collection can occur at any
+time, and clean-ups invoked by the collector might access data in an
+inconsistent state. A client can control this by defining an explicit
+queue for objects and polling it at safe points.
+
+The following definitions are used by the specification below:
+
+Given a pointer t to a collected object, the base object BO(t) is the
+value returned by new when it created the object. (Because of multiple
+inheritance, t and BO(t) may not be the same address.)
+
+A weak pointer wp references an object *t if BO(wp.Pointer()) ==
+BO(t).
+
+***************************************************************************/
+
+template< class T, class Data > class CleanUp {
+public:
+
+static void Set( T* t, void c( Data* d, T* t ), Data* d = 0 )
+ /* Sets the clean-up function of object BO(t) to be <c, d>,
+ replacing any previously defined clean-up function for BO(t); c
+ and d can be null, but t cannot. Sets the clean-up queue for
+ BO(t) to be the collector's queue. When t is removed from its
+ clean-up queue, its clean-up will be applied by calling c(d,
+ t). It is an error if *t is not a collected object. */
+ {_CleanUp_Set( t, c, d );}
+
+static void Call( T* t )
+ /* Sets the new clean-up function for BO(t) to be null and, if the
+ old one is non-null, calls it immediately, even if BO(t) is
+ still reachable. Deactivates any weak pointers to BO(t). */
+ {_CleanUp_Call( t );}
+
+class Queue {public:
+ Queue()
+ /* Constructs a new queue. */
+ {this->head = _CleanUp_Queue_NewHead();}
+
+ void Set( T* t )
+ /* q.Set(t) sets the clean-up queue of BO(t) to be q. */
+ {_CleanUp_Queue_Set( this->head, t );}
+
+ int Call()
+ /* If q is non-empty, q.Call() removes the first object and
+ calls its clean-up function; does nothing if q is
+ empty. Returns true if there are more objects in the
+ queue. */
+ {return _CleanUp_Queue_Call( this->head );}
+
+ private:
+ void* head;
+ };
+};
+
+/**********************************************************************
+
+Reachability and Clean-up
+
+An object O is reachable if it can be reached via a non-empty path of
+normal pointers from the registers, stacks, global variables, or an
+object with a non-null clean-up function (including O itself),
+ignoring pointers from an object to itself.
+
+This definition of reachability ensures that if object B is accessible
+from object A (and not vice versa) and if both A and B have clean-up
+functions, then A will always be cleaned up before B. Note that as
+long as an object with a clean-up function is contained in a cycle of
+pointers, it will always be reachable and will never be cleaned up or
+collected.
+
+When the collector finds an unreachable object with a null clean-up
+function, it atomically deactivates all weak pointers referencing the
+object and recycles its storage. If object B is accessible from object
+A via a path of normal pointers, A will be discovered unreachable no
+later than B, and a weak pointer to A will be deactivated no later
+than a weak pointer to B.
+
+When the collector finds an unreachable object with a non-null
+clean-up function, the collector atomically deactivates all weak
+pointers referencing the object, redefines its clean-up function to be
+null, and enqueues it on its clean-up queue. The object then becomes
+reachable again and remains reachable at least until its clean-up
+function executes.
+
+The clean-up function is assured that its argument is the only
+accessible pointer to the object. Nothing prevents the function from
+redefining the object's clean-up function or making the object
+reachable again (for example, by storing the pointer in a global
+variable).
+
+If the clean-up function does not make its object reachable again and
+does not redefine its clean-up function, then the object will be
+collected by a subsequent collection (because the object remains
+unreachable and now has a null clean-up function). If the clean-up
+function does make its object reachable again and a clean-up function
+is subsequently redefined for the object, then the new clean-up
+function will be invoked the next time the collector finds the object
+unreachable.
+
+Note that a destructor for a collected object cannot safely redefine a
+clean-up function for its object, since after the destructor executes,
+the object has been destroyed into "raw memory". (In most
+implementations, destroying an object mutates its vtbl.)
+
+Finally, note that calling delete t on a collected object first
+deactivates any weak pointers to t and then invokes its clean-up
+function (destructor).
+
+**********************************************************************/
+
+extern "C" {
+ void* _WeakPointer_New( void* t );
+ void* _WeakPointer_Pointer( void* wp );
+ int _WeakPointer_Equal( void* wp1, void* wp2 );
+ int _WeakPointer_Hash( void* wp );
+ void _CleanUp_Set( void* t, void (*c)( void* d, void* t ), void* d );
+ void _CleanUp_Call( void* t );
+ void* _CleanUp_Queue_NewHead ();
+ void _CleanUp_Queue_Set( void* h, void* t );
+ int _CleanUp_Queue_Call( void* h );
+}
+
+#endif /* _weakpointer_h_ */
+
+
diff --git a/tools/build/v2/engine/boehm_gc/install-sh b/tools/build/v2/engine/boehm_gc/install-sh
new file mode 100755
index 0000000000..398a88e142
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ :
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=$mkdirprog
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ :
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ :
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ :
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+ '
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ :
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ :
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/tools/build/v2/engine/boehm_gc/libtool.m4 b/tools/build/v2/engine/boehm_gc/libtool.m4
new file mode 100644
index 0000000000..0f53cb592e
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/libtool.m4
@@ -0,0 +1,6397 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
+## Free Software Foundation, Inc.
+## Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+##
+## This file is free software; the Free Software Foundation gives
+## unlimited permission to copy and/or distribute it, with or without
+## modifications, as long as this notice is preserved.
+
+# serial 48 AC_PROG_LIBTOOL
+
+
+# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
+# -----------------------------------------------------------
+# If this macro is not defined by Autoconf, define it here.
+m4_ifdef([AC_PROVIDE_IFELSE],
+ [],
+ [m4_define([AC_PROVIDE_IFELSE],
+ [m4_ifdef([AC_PROVIDE_$1],
+ [$2], [$3])])])
+
+
+# AC_PROG_LIBTOOL
+# ---------------
+AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl
+dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX
+dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX.
+ AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [AC_LIBTOOL_CXX],
+ [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX
+ ])])
+dnl And a similar setup for Fortran 77 support
+ AC_PROVIDE_IFELSE([AC_PROG_F77],
+ [AC_LIBTOOL_F77],
+ [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77
+])])
+
+dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly.
+dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run
+dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both.
+ AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [ifdef([AC_PROG_GCJ],
+ [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+ ifdef([A][M_PROG_GCJ],
+ [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+ ifdef([LT_AC_PROG_GCJ],
+ [define([LT_AC_PROG_GCJ],
+ defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])])
+])])# AC_PROG_LIBTOOL
+
+
+# _AC_PROG_LIBTOOL
+# ----------------
+AC_DEFUN([_AC_PROG_LIBTOOL],
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Prevent multiple expansion
+define([AC_PROG_LIBTOOL], [])
+])# _AC_PROG_LIBTOOL
+
+
+# AC_LIBTOOL_SETUP
+# ----------------
+AC_DEFUN([AC_LIBTOOL_SETUP],
+[AC_PREREQ(2.50)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+AC_REQUIRE([AC_OBJEXT])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+dnl
+
+AC_LIBTOOL_SYS_MAX_CMD_LEN
+AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+AC_LIBTOOL_OBJDIR
+
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+_LT_AC_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
+
+# Same as above, but do not quote variable references.
+[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+AC_CHECK_TOOL(AR, ar, false)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(STRIP, strip, :)
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ AC_PATH_MAGIC
+ fi
+ ;;
+esac
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
+
+AC_ARG_ENABLE([libtool-lock],
+ [AC_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+AC_ARG_WITH([pic],
+ [AC_HELP_STRING([--with-pic],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [pic_mode="$withval"],
+ [pic_mode=default])
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+AC_LIBTOOL_LANG_C_CONFIG
+_LT_AC_TAGCONFIG
+])# AC_LIBTOOL_SETUP
+
+
+# _LT_AC_SYS_COMPILER
+# -------------------
+AC_DEFUN([_LT_AC_SYS_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_AC_SYS_COMPILER
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+AC_DEFUN([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+AC_DEFUN([_LT_COMPILER_BOILERPLATE],
+[ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+AC_DEFUN([_LT_LINKER_BOILERPLATE],
+[ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+])# _LT_LINKER_BOILERPLATE
+
+
+# _LT_AC_SYS_LIBPATH_AIX
+# ----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
+[AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_AC_SYS_LIBPATH_AIX
+
+
+# _LT_AC_SHELL_INIT(ARG)
+# ----------------------
+AC_DEFUN([_LT_AC_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+ [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+ [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_AC_SHELL_INIT
+
+
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[_LT_AC_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+ ;;
+esac
+
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X[$]1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+[$]*
+EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+ echo_test_string=`eval $cmd` &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+ then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+ else
+ # Try using printf.
+ echo='printf %s\n'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "[$]0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+ ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(ECHO)
+])])# _LT_AC_PROG_ECHO_BACKSLASH
+
+
+# _LT_AC_LOCK
+# -----------
+AC_DEFUN([_LT_AC_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+ [AC_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_PUSH(C)
+ AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_POP])
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *) LD="${LD-ld} -64" ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+ ])
+esac
+
+need_locks="$enable_libtool_lock"
+
+])# _LT_AC_LOCK
+
+
+# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$3"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ fi
+ $rm conftest*
+])
+
+if test x"[$]$2" = xyes; then
+ ifelse([$5], , :, [$5])
+else
+ ifelse([$6], , :, [$6])
+fi
+])# AC_LIBTOOL_COMPILER_OPTION
+
+
+# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [ACTION-SUCCESS], [ACTION-FAILURE])
+# ------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
+[AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $3"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&AS_MESSAGE_LOG_FD
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ else
+ $2=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+ ifelse([$4], , :, [$4])
+else
+ ifelse([$5], , :, [$5])
+fi
+])# AC_LIBTOOL_LINKER_OPTION
+
+
+# AC_LIBTOOL_SYS_MAX_CMD_LEN
+# --------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN],
+[# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \
+ = "XX$teststring") >/dev/null 2>&1 &&
+ new_result=`expr "X$teststring" : ".*" 2>&1` &&
+ lt_cv_sys_max_cmd_len=$new_result &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on massive
+ # amounts of additional arguments before passing them to the linker.
+ # It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ ;;
+ esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+ AC_MSG_RESULT(none)
+fi
+])# AC_LIBTOOL_SYS_MAX_CMD_LEN
+
+
+# _LT_AC_CHECK_DLFCN
+# ------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)dnl
+])# _LT_AC_CHECK_DLFCN
+
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ---------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+ [$4]
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}]
+EOF
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_dlunknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_AC_TRY_DLOPEN_SELF
+
+
+# AC_LIBTOOL_DLOPEN_SELF
+# ----------------------
+AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ])
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen="shl_load"],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen="dlopen"],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+])# AC_LIBTOOL_DLOPEN_SELF
+
+
+# AC_LIBTOOL_PROG_CC_C_O([TAGNAME])
+# ---------------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler
+AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+ fi
+ fi
+ chmod u+w . 2>&AS_MESSAGE_LOG_FD
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+])
+])# AC_LIBTOOL_PROG_CC_C_O
+
+
+# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME])
+# -----------------------------------------
+# Check to see if we can do hard links to lock some files if needed
+AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS],
+[AC_REQUIRE([_LT_AC_LOCK])dnl
+
+hard_links="nottested"
+if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test "$hard_links" = no; then
+ AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS
+
+
+# AC_LIBTOOL_OBJDIR
+# -----------------
+AC_DEFUN([AC_LIBTOOL_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+])# AC_LIBTOOL_OBJDIR
+
+
+# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME])
+# ----------------------------------------------
+# Check hardcoding attributes.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_AC_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \
+ test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \
+ test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+ test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then
+ # Linking always hardcodes the temporary library directory.
+ _LT_AC_TAGVAR(hardcode_action, $1)=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ _LT_AC_TAGVAR(hardcode_action, $1)=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ _LT_AC_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH
+
+
+# AC_LIBTOOL_SYS_LIB_STRIP
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP],
+[striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+fi
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+fi
+])# AC_LIBTOOL_SYS_LIB_STRIP
+
+
+# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
+[AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[[45]]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[[123]]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[[89]] | openbsd2.[[89]].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+])# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+
+
+# _LT_AC_TAGCONFIG
+# ----------------
+AC_DEFUN([_LT_AC_TAGCONFIG],
+[AC_ARG_WITH([tags],
+ [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
+ [include additional configurations @<:@automatic@:>@])],
+ [tagnames="$withval"])
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+ if test ! -f "${ofile}"; then
+ AC_MSG_WARN([output file `$ofile' does not exist])
+ fi
+
+ if test -z "$LTCC"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+ if test -z "$LTCC"; then
+ AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
+ else
+ AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
+ fi
+ fi
+ if test -z "$LTCFLAGS"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+ fi
+
+ # Extract list of available tagged configurations in $ofile.
+ # Note that this assumes the entire list is on one line.
+ available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for tagname in $tagnames; do
+ IFS="$lt_save_ifs"
+ # Check whether tagname contains only valid characters
+ case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in
+ "") ;;
+ *) AC_MSG_ERROR([invalid tag name: $tagname])
+ ;;
+ esac
+
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+ then
+ AC_MSG_ERROR([tag name \"$tagname\" already exists])
+ fi
+
+ # Update the list of available tags.
+ if test -n "$tagname"; then
+ echo appending configuration tag \"$tagname\" to $ofile
+
+ case $tagname in
+ CXX)
+ if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_LIBTOOL_LANG_CXX_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ F77)
+ if test -n "$F77" && test "X$F77" != "Xno"; then
+ AC_LIBTOOL_LANG_F77_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ GCJ)
+ if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+ AC_LIBTOOL_LANG_GCJ_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ RC)
+ AC_LIBTOOL_LANG_RC_CONFIG
+ ;;
+
+ *)
+ AC_MSG_ERROR([Unsupported tag name: $tagname])
+ ;;
+ esac
+
+ # Append the new tag name to the list of available tags.
+ if test -n "$tagname" ; then
+ available_tags="$available_tags $tagname"
+ fi
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ # Now substitute the updated list of available tags.
+ if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+ mv "${ofile}T" "$ofile"
+ chmod +x "$ofile"
+ else
+ rm -f "${ofile}T"
+ AC_MSG_ERROR([unable to update list of available tagged configurations.])
+ fi
+fi
+])# _LT_AC_TAGCONFIG
+
+
+# AC_LIBTOOL_DLOPEN
+# -----------------
+# enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN],
+ [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_DLOPEN
+
+
+# AC_LIBTOOL_WIN32_DLL
+# --------------------
+# declare package support for building win32 DLLs
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_WIN32_DLL
+
+
+# AC_ENABLE_SHARED([DEFAULT])
+# ---------------------------
+# implement the --enable-shared flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([shared],
+ [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+ [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_shared=]AC_ENABLE_SHARED_DEFAULT)
+])# AC_ENABLE_SHARED
+
+
+# AC_DISABLE_SHARED
+# -----------------
+# set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)
+])# AC_DISABLE_SHARED
+
+
+# AC_ENABLE_STATIC([DEFAULT])
+# ---------------------------
+# implement the --enable-static flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([static],
+ [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+ [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_static=]AC_ENABLE_STATIC_DEFAULT)
+])# AC_ENABLE_STATIC
+
+
+# AC_DISABLE_STATIC
+# -----------------
+# set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)
+])# AC_DISABLE_STATIC
+
+
+# AC_ENABLE_FAST_INSTALL([DEFAULT])
+# ---------------------------------
+# implement the --enable-fast-install flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([fast-install],
+ [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+ [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT)
+])# AC_ENABLE_FAST_INSTALL
+
+
+# AC_DISABLE_FAST_INSTALL
+# -----------------------
+# set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)
+])# AC_DISABLE_FAST_INSTALL
+
+
+# AC_LIBTOOL_PICMODE([MODE])
+# --------------------------
+# implement the --with-pic flag
+# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)
+])# AC_LIBTOOL_PICMODE
+
+
+# AC_PROG_EGREP
+# -------------
+# This is predefined starting with Autoconf 2.54, so this conditional
+# definition can be removed once we require Autoconf 2.54 or later.
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
+[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
+ [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi])
+ EGREP=$ac_cv_prog_egrep
+ AC_SUBST([EGREP])
+])])
+
+
+# AC_PATH_TOOL_PREFIX
+# -------------------
+# find a file program which can recognise shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] | ?:[\\/]*])
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="ifelse([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$1; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+])# AC_PATH_TOOL_PREFIX
+
+
+# AC_PATH_MAGIC
+# -------------
+# find a file program which can recognise a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])# AC_PATH_MAGIC
+
+
+# AC_PROG_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH([gnu-ld],
+ [AC_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test "$withval" = no || with_gnu_ld=yes],
+ [with_gnu_ld=no])
+AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])# AC_PROG_LD
+
+
+# AC_PROG_LD_GNU
+# --------------
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# AC_PROG_LD_GNU
+
+
+# AC_PROG_LD_RELOAD_FLAG
+# ----------------------
+# find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+ lt_cv_ld_reload_flag,
+ [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+])# AC_PROG_LD_RELOAD_FLAG
+
+
+# AC_DEPLIBS_CHECK_METHOD
+# -----------------------
+# how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognise dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[[45]]*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump'.
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | kfreebsd*-gnu | dragonfly*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix3*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+nto-qnx*)
+ lt_cv_deplibs_check_method=unknown
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+])# AC_DEPLIBS_CHECK_METHOD
+
+
+# AC_PROG_NM
+# ----------
+# find the pathname to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+])# AC_PROG_NM
+
+
+# AC_CHECK_LIBM
+# -------------
+# check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, cos, LIBM="-lm")
+ ;;
+esac
+])# AC_CHECK_LIBM
+
+
+# AC_LIBLTDL_CONVENIENCE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl convenience library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-convenience to the configure arguments. Note that
+# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided,
+# it is assumed to be `libltdl'. LIBLTDL will be prefixed with
+# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/'
+# (note the single quotes!). If your package is not flat and you're not
+# using automake, define top_builddir and top_srcdir appropriately in
+# the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ case $enable_ltdl_convenience in
+ no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+ "") enable_ltdl_convenience=yes
+ ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+ esac
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ # For backwards non-gettext consistent compatibility...
+ INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_CONVENIENCE
+
+
+# AC_LIBLTDL_INSTALLABLE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl installable library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-install to the configure arguments. Note that
+# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided,
+# and an installed libltdl is not found, it is assumed to be `libltdl'.
+# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with
+# '${top_srcdir}/' (note the single quotes!). If your package is not
+# flat and you're not using automake, define top_builddir and top_srcdir
+# appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ AC_CHECK_LIB(ltdl, lt_dlinit,
+ [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+ [if test x"$enable_ltdl_install" = xno; then
+ AC_MSG_WARN([libltdl not installed, but installation disabled])
+ else
+ enable_ltdl_install=yes
+ fi
+ ])
+ if test x"$enable_ltdl_install" = x"yes"; then
+ ac_configure_args="$ac_configure_args --enable-ltdl-install"
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ else
+ ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+ LIBLTDL="-lltdl"
+ LTDLINCL=
+ fi
+ # For backwards non-gettext consistent compatibility...
+ INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_INSTALLABLE
+
+
+# AC_LIBTOOL_CXX
+# --------------
+# enable support for C++ libraries
+AC_DEFUN([AC_LIBTOOL_CXX],
+[AC_REQUIRE([_LT_AC_LANG_CXX])
+])# AC_LIBTOOL_CXX
+
+
+# _LT_AC_LANG_CXX
+# ---------------
+AC_DEFUN([_LT_AC_LANG_CXX],
+[AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX])
+])# _LT_AC_LANG_CXX
+
+# _LT_AC_PROG_CXXCPP
+# ------------------
+AC_DEFUN([_LT_AC_PROG_CXXCPP],
+[
+AC_REQUIRE([AC_PROG_CXX])
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_PROG_CXXCPP
+fi
+])# _LT_AC_PROG_CXXCPP
+
+# AC_LIBTOOL_F77
+# --------------
+# enable support for Fortran 77 libraries
+AC_DEFUN([AC_LIBTOOL_F77],
+[AC_REQUIRE([_LT_AC_LANG_F77])
+])# AC_LIBTOOL_F77
+
+
+# _LT_AC_LANG_F77
+# ---------------
+AC_DEFUN([_LT_AC_LANG_F77],
+[AC_REQUIRE([AC_PROG_F77])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77])
+])# _LT_AC_LANG_F77
+
+
+# AC_LIBTOOL_GCJ
+# --------------
+# enable support for GCJ libraries
+AC_DEFUN([AC_LIBTOOL_GCJ],
+[AC_REQUIRE([_LT_AC_LANG_GCJ])
+])# AC_LIBTOOL_GCJ
+
+
+# _LT_AC_LANG_GCJ
+# ---------------
+AC_DEFUN([_LT_AC_LANG_GCJ],
+[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[],
+ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[],
+ [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])],
+ [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])],
+ [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ])
+])# _LT_AC_LANG_GCJ
+
+
+# AC_LIBTOOL_RC
+# -------------
+# enable support for Windows resource files
+AC_DEFUN([AC_LIBTOOL_RC],
+[AC_REQUIRE([LT_AC_PROG_RC])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC])
+])# AC_LIBTOOL_RC
+
+
+# AC_LIBTOOL_LANG_C_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG])
+AC_DEFUN([_LT_AC_LANG_C_CONFIG],
+[lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}\n'
+
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF
+
+# Report which library types will actually be built
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_C_CONFIG
+
+
+# AC_LIBTOOL_LANG_CXX_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)])
+AC_DEFUN([_LT_AC_LANG_CXX_CONFIG],
+[AC_LANG_PUSH(C++)
+AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Dependencies to place before and after the object being linked:
+_LT_AC_TAGVAR(predep_objects, $1)=
+_LT_AC_TAGVAR(postdep_objects, $1)=
+_LT_AC_TAGVAR(predeps, $1)=
+_LT_AC_TAGVAR(postdeps, $1)=
+_LT_AC_TAGVAR(compiler_lib_search_path, $1)=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+ $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+ $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+else
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+fi
+
+if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+ AC_PROG_LD
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+ grep 'no-whole-archive' > /dev/null; then
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+_LT_AC_TAGVAR(ld_shlibs, $1)=yes
+case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_AC_TAGVAR(archive_cmds, $1)=''
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ else
+ # We have old collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GXX" = yes ; then
+ lt_int_apple_cc_single_mod=no
+ output_verbose_link_cmd='echo'
+ if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+ lt_int_apple_cc_single_mod=yes
+ fi
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ fi
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ freebsd[[12]]*)
+ # C++ shared libraries reported to be fairly broken before switch to ELF
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ freebsd-elf*)
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+ gnu*)
+ ;;
+ hpux9*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+ ;;
+ *)
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ interix3*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+ fi
+ fi
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+ esac
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc*)
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ esac
+ ;;
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ m88k*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ openbsd*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd='echo'
+ ;;
+ osf3*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+ $rm $lib.exp'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ psos*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The C++ compiler is used as linker so we must use $wl
+ # flag to pass the commands to the underlying system
+ # linker. We must also pass each convience library through
+ # to the system linker between allextract/defaultextract.
+ # The C++ compiler will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+ if $CC --version | grep -v '^2\.7' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ fi
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+ fi
+ ;;
+ esac
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ # So that behaviour is only enabled if SCOABSPATH is set to a
+ # non-empty value in the environment. Most likely only useful for
+ # creating official distributions of packages.
+ # This is a hack until libtool officially supports absolute path
+ # names for shared libraries.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+esac
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_AC_TAGVAR(GCC, $1)="$GXX"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_POSTDEP_PREDEP($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+])# AC_LIBTOOL_LANG_CXX_CONFIG
+
+# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME])
+# ------------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library. It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+ifelse([$1],[],[cat > conftest.$ac_ext <<EOF
+int a;
+void foo (void) { a = 0; }
+EOF
+],[$1],[CXX],[cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+EOF
+],[$1],[F77],[cat > conftest.$ac_ext <<EOF
+ subroutine foo
+ implicit none
+ integer*4 a
+ a=0
+ return
+ end
+EOF
+],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF
+public class foo {
+ private int a;
+ public void bar (void) {
+ a = 0;
+ }
+};
+EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ # The `*' in the case matches for architectures that use `case' in
+ # $output_verbose_cmd can trigger glob expansion during the loop
+ # eval without this substitution.
+ output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+ for p in `eval $output_verbose_link_cmd`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" \
+ || test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+ else
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then
+ _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}"
+ else
+ _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then
+ _LT_AC_TAGVAR(predep_objects, $1)="$p"
+ else
+ _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p"
+ fi
+ else
+ if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then
+ _LT_AC_TAGVAR(postdep_objects, $1)="$p"
+ else
+ _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$rm -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+ifelse([$1],[CXX],
+[case $host_os in
+interix3*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ _LT_AC_TAGVAR(predep_objects,$1)=
+ _LT_AC_TAGVAR(postdep_objects,$1)=
+ _LT_AC_TAGVAR(postdeps,$1)=
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ _LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun'
+ ;;
+ esac
+ ;;
+esac
+])
+
+case " $_LT_AC_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+])# AC_LIBTOOL_POSTDEP_PREDEP
+
+# AC_LIBTOOL_LANG_F77_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)])
+AC_DEFUN([_LT_AC_LANG_F77_CONFIG],
+[AC_REQUIRE([AC_PROG_F77])
+AC_LANG_PUSH(Fortran 77)
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code=" subroutine t\n return\n end\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=" program t\n end\n"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+_LT_AC_TAGVAR(GCC, $1)="$G77"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_F77_CONFIG
+
+
+# AC_LIBTOOL_LANG_GCJ_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)])
+AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_GCJ_CONFIG
+
+
+# AC_LIBTOOL_LANG_RC_CONFIG
+# -------------------------
+# Ensure that the configuration vars for the Windows resource compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)])
+AC_DEFUN([_LT_AC_LANG_RC_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_RC_CONFIG
+
+
+# AC_LIBTOOL_CONFIG([TAGNAME])
+# ----------------------------
+# If TAGNAME is not passed, then create an initial libtool script
+# with a default configuration from the untagged config vars. Otherwise
+# add code to config.status for appending the configuration named by
+# TAGNAME from the matching tagged config vars.
+AC_DEFUN([AC_LIBTOOL_CONFIG],
+[# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ _LT_AC_TAGVAR(compiler, $1) \
+ _LT_AC_TAGVAR(CC, $1) \
+ _LT_AC_TAGVAR(LD, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \
+ _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \
+ _LT_AC_TAGVAR(old_archive_cmds, $1) \
+ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \
+ _LT_AC_TAGVAR(predep_objects, $1) \
+ _LT_AC_TAGVAR(postdep_objects, $1) \
+ _LT_AC_TAGVAR(predeps, $1) \
+ _LT_AC_TAGVAR(postdeps, $1) \
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1) \
+ _LT_AC_TAGVAR(archive_cmds, $1) \
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1) \
+ _LT_AC_TAGVAR(postinstall_cmds, $1) \
+ _LT_AC_TAGVAR(postuninstall_cmds, $1) \
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \
+ _LT_AC_TAGVAR(allow_undefined_flag, $1) \
+ _LT_AC_TAGVAR(no_undefined_flag, $1) \
+ _LT_AC_TAGVAR(export_symbols_cmds, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \
+ _LT_AC_TAGVAR(hardcode_automatic, $1) \
+ _LT_AC_TAGVAR(module_cmds, $1) \
+ _LT_AC_TAGVAR(module_expsym_cmds, $1) \
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
+ _LT_AC_TAGVAR(exclude_expsyms, $1) \
+ _LT_AC_TAGVAR(include_expsyms, $1); do
+
+ case $var in
+ _LT_AC_TAGVAR(old_archive_cmds, $1) | \
+ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \
+ _LT_AC_TAGVAR(archive_cmds, $1) | \
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \
+ _LT_AC_TAGVAR(module_cmds, $1) | \
+ _LT_AC_TAGVAR(module_expsym_cmds, $1) | \
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \
+ _LT_AC_TAGVAR(export_symbols_cmds, $1) | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\[$]0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'`
+ ;;
+ esac
+
+ifelse([$1], [],
+ [cfgfile="${ofile}T"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ $rm -f "$cfgfile"
+ AC_MSG_NOTICE([creating $ofile])],
+ [cfgfile="$ofile"])
+
+ cat <<__EOF__ >> "$cfgfile"
+ifelse([$1], [],
+[#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG],
+[# ### BEGIN LIBTOOL TAG CONFIG: $tagname])
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_[]_LT_AC_TAGVAR(compiler, $1)
+
+# Is the compiler the GNU C compiler?
+with_gcc=$_LT_AC_TAGVAR(GCC, $1)
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_[]_LT_AC_TAGVAR(LD, $1)
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1)
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1)
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1)
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1)
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1)
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1)
+archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1)
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1)
+module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1)
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1)
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1)
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1)
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1)
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1)
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1)
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1)
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1)
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1)
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1)
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1)
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1)
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1)
+
+# Symbols that must always be exported.
+include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1)
+
+ifelse([$1],[],
+[# ### END LIBTOOL CONFIG],
+[# ### END LIBTOOL TAG CONFIG: $tagname])
+
+__EOF__
+
+ifelse([$1],[], [
+ case $host_os in
+ aix3*)
+ cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" || \
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+])
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+])# AC_LIBTOOL_CONFIG
+
+
+# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+
+_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+ AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+ lt_cv_prog_compiler_rtti_exceptions,
+ [-fno-rtti -fno-exceptions], [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI
+
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDEGRST]]'
+ fi
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+linux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDGIRSTW]]'
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[[BCDEGRST]]'
+ ;;
+osf*)
+ symcode='[[BCDEGQRST]]'
+ ;;
+solaris*)
+ symcode='[[BDRT]]'
+ ;;
+sco3.2v5*)
+ symcode='[[DT]]'
+ ;;
+sysv4.2uw2*)
+ symcode='[[DT]]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[[ABDT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if grep ' nm_test_var$' "$nlist" >/dev/null; then
+ if grep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+ cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+
+# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME])
+# ---------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC],
+[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+ ifelse([$1],[CXX],[
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | os2* | pw32*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix4* | aix5*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ fi
+ ;;
+ aCC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ icpc* | ecpc*)
+ # Intel C++
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler.
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+],
+[
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC (with -KPIC) is the default.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ newsos6)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ ccc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All Alpha code is PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All OSF/1 code is PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ solaris*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ unicos*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+
+ uts4*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works],
+ _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1),
+ [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [],
+ [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in
+ "" | " "*) ;;
+ *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+ esac],
+ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\"
+AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+ _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1),
+ $lt_tmp_static_flag,
+ [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=])
+])
+
+
+# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME])
+# ------------------------------------
+# See if the linker supports building shared libraries.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
+[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ifelse([$1],[CXX],[
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix4* | aix5*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+ ;;
+ cygwin* | mingw*)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ *)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+],[
+ runpath_var=
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+ _LT_AC_TAGVAR(archive_cmds, $1)=
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)=
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ _LT_AC_TAGVAR(thread_safe_flag_spec, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=no
+ _LT_AC_TAGVAR(module_cmds, $1)=
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)=
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ _LT_AC_TAGVAR(include_expsyms, $1)=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ _LT_CC_BASENAME([$compiler])
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ interix3*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+
+ if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then
+ runpath_var=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_AC_TAGVAR(archive_cmds, $1)=''
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ else
+ # We have old collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ # see comment about different semantics on the GNU ld section
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ bsdi[[45]]*)
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
+ # FIXME: Should let the user specify the lib program.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ freebsd1*)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ newsos6)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ openbsd*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ else
+ case $host_os in
+ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ else
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ solaris*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;;
+ *)
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ ;;
+ motorola)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4.3*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+ # Assume -lc should be added
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $_LT_AC_TAGVAR(archive_cmds, $1) in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+ pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+ if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+ then
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ fi
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)])
+ ;;
+ esac
+ fi
+ ;;
+esac
+])# AC_LIBTOOL_PROG_LD_SHLIBS
+
+
+# _LT_AC_FILE_LTDLL_C
+# -------------------
+# Be careful that the start marker always follows a newline.
+AC_DEFUN([_LT_AC_FILE_LTDLL_C], [
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# # ifdef __CYGWIN32__
+# # define __CYGWIN__ __CYGWIN32__
+# # endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+# __hDllInstance_base = hInst;
+# return TRUE;
+# }
+# /* ltdll.c ends here */
+])# _LT_AC_FILE_LTDLL_C
+
+
+# _LT_AC_TAGVAR(VARNAME, [TAGNAME])
+# ---------------------------------
+AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])])
+
+
+# old names
+AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL])
+AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+AC_DEFUN([AM_PROG_LD], [AC_PROG_LD])
+AC_DEFUN([AM_PROG_NM], [AC_PROG_NM])
+
+# This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])
+
+AC_DEFUN([LT_AC_PROG_GCJ],
+[AC_CHECK_TOOL(GCJ, gcj, no)
+ test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+ AC_SUBST(GCJFLAGS)
+])
+
+AC_DEFUN([LT_AC_PROG_RC],
+[AC_CHECK_TOOL(RC, windres, no)
+])
+
+############################################################
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_SED. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+############################################################
+# LT_AC_PROG_SED
+# --------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible. Prefer GNU sed if found.
+AC_DEFUN([LT_AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+])
+SED=$lt_cv_path_SED
+AC_MSG_RESULT([$SED])
+])
diff --git a/tools/build/v2/engine/boehm_gc/ltmain.sh b/tools/build/v2/engine/boehm_gc/ltmain.sh
new file mode 100755
index 0000000000..06823e057a
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/ltmain.sh
@@ -0,0 +1,6863 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+basename="s,^.*/,,g"
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+progname=`echo "$progpath" | $SED $basename`
+modename="$progname"
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.5.22
+TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)"
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes.
+if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit $EXIT_SUCCESS
+fi
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ SP2NL='tr \040 \012'
+ NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ SP2NL='tr \100 \n'
+ NL2SP='tr \r\n \100\100'
+ ;;
+esac
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+ save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+ save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" $lt_nl"
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ $echo "$modename: not configured to build any kind of library" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+duplicate_deps=no
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible. If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+ my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+ if test "$run" = ":"; then
+ # Return a directory name, but don't create it in dry-run mode
+ my_tmpdir="${my_template}-$$"
+ else
+
+ # If mktemp works, use that first and foremost
+ my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+ if test ! -d "$my_tmpdir"; then
+ # Failing that, at least try and use $RANDOM to avoid a race
+ my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+ save_mktempdir_umask=`umask`
+ umask 0077
+ $mkdir "$my_tmpdir"
+ umask $save_mktempdir_umask
+ fi
+
+ # If we're not in dry-run mode, bomb out on failure
+ test -d "$my_tmpdir" || {
+ $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
+ exit $EXIT_FAILURE
+ }
+ fi
+
+ $echo "X$my_tmpdir" | $Xsed
+}
+
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+ win32_libid_type="unknown"
+ win32_fileres=`file -L $1 2>/dev/null`
+ case $win32_fileres in
+ *ar\ archive\ import\ library*) # definitely import
+ win32_libid_type="x86 archive import"
+ ;;
+ *ar\ archive*) # could be an import, or static
+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
+ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+ win32_nmres=`eval $NM -f posix -A $1 | \
+ $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'`
+ case $win32_nmres in
+ import*) win32_libid_type="x86 archive import";;
+ *) win32_libid_type="x86 archive static";;
+ esac
+ fi
+ ;;
+ *DLL*)
+ win32_libid_type="x86 DLL"
+ ;;
+ *executable*) # but shell scripts are "executable" too...
+ case $win32_fileres in
+ *MS\ Windows\ PE\ Intel*)
+ win32_libid_type="x86 DLL"
+ ;;
+ esac
+ ;;
+ esac
+ $echo $win32_libid_type
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+ if test -n "$available_tags" && test -z "$tagname"; then
+ CC_quoted=
+ for arg in $CC; do
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case $@ in
+ # Blanks in the command may have been stripped by the calling shell,
+ # but not from the CC environment variable when configure was run.
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
+ # Blanks at the start of $base_compile will cause this to fail
+ # if we don't check for them as well.
+ *)
+ for z in $available_tags; do
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+ CC_quoted=
+ for arg in $CC; do
+ # Double-quote args containing other shell metacharacters.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case "$@ " in
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
+ # The compiler in the base compile command matches
+ # the one in the tagged configuration.
+ # Assume this is the tagged configuration we want.
+ tagname=$z
+ break
+ ;;
+ esac
+ fi
+ done
+ # If $tagname still isn't set, then no tagged configuration
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ if test -z "$tagname"; then
+ $echo "$modename: unable to infer tagged configuration"
+ $echo "$modename: specify a tag with \`--tag'" 1>&2
+ exit $EXIT_FAILURE
+# else
+# $echo "$modename: using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+ f_ex_an_ar_dir="$1"; shift
+ f_ex_an_ar_oldlib="$1"
+
+ $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
+ $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
+ if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+ exit $EXIT_FAILURE
+ fi
+}
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+ my_gentop="$1"; shift
+ my_oldlibs=${1+"$@"}
+ my_oldobjs=""
+ my_xlib=""
+ my_xabs=""
+ my_xdir=""
+ my_status=""
+
+ $show "${rm}r $my_gentop"
+ $run ${rm}r "$my_gentop"
+ $show "$mkdir $my_gentop"
+ $run $mkdir "$my_gentop"
+ my_status=$?
+ if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+ exit $my_status
+ fi
+
+ for my_xlib in $my_oldlibs; do
+ # Extract the objects.
+ case $my_xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+ *) my_xabs=`pwd`"/$my_xlib" ;;
+ esac
+ my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+ my_xdir="$my_gentop/$my_xlib"
+
+ $show "${rm}r $my_xdir"
+ $run ${rm}r "$my_xdir"
+ $show "$mkdir $my_xdir"
+ $run $mkdir "$my_xdir"
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
+ exit $exit_status
+ fi
+ case $host in
+ *-darwin*)
+ $show "Extracting $my_xabs"
+ # Do not bother doing anything if just a dry run
+ if test -z "$run"; then
+ darwin_orig_dir=`pwd`
+ cd $my_xdir || exit $?
+ darwin_archive=$my_xabs
+ darwin_curdir=`pwd`
+ darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
+ darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+ if test -n "$darwin_arches"; then
+ darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+ darwin_arch=
+ $show "$darwin_base_archive has multiple architectures $darwin_arches"
+ for darwin_arch in $darwin_arches ; do
+ mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+ cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+ cd "$darwin_curdir"
+ $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+ done # $darwin_arches
+ ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+ darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+ lipo -create -output "$darwin_file" $darwin_files
+ done # $darwin_filelist
+ ${rm}r unfat-$$
+ cd "$darwin_orig_dir"
+ else
+ cd "$darwin_orig_dir"
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ fi # $darwin_arches
+ fi # $run
+ ;;
+ *)
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ ;;
+ esac
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+ done
+ func_extract_archives_result="$my_oldobjs"
+}
+# End of Shell function definitions
+#####################################
+
+# Darwin sucks
+eval std_shrext=\"$shrext_cmds\"
+
+disable_libs=no
+
+# Parse our command line options once, thoroughly.
+while test "$#" -gt 0
+do
+ arg="$1"
+ shift
+
+ case $arg in
+ -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ execute_dlfiles)
+ execute_dlfiles="$execute_dlfiles $arg"
+ ;;
+ tag)
+ tagname="$arg"
+ preserve_args="${preserve_args}=$arg"
+
+ # Check whether tagname contains only valid characters
+ case $tagname in
+ *[!-_A-Za-z0-9,/]*)
+ $echo "$progname: invalid tag name: $tagname" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $tagname in
+ CC)
+ # Don't test for the "default" C tag, as we know, it's there, but
+ # not specially marked.
+ ;;
+ *)
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
+ taglist="$taglist $tagname"
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
+ else
+ $echo "$progname: ignoring unknown tag $tagname" 1>&2
+ fi
+ ;;
+ esac
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case $arg in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+ $echo
+ $echo "Copyright (C) 2005 Free Software Foundation, Inc."
+ $echo "This is free software; see the source for copying conditions. There is NO"
+ $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+ exit $?
+ ;;
+
+ --config)
+ ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
+ # Now print the configurations for the tags.
+ for tagname in $taglist; do
+ ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
+ done
+ exit $?
+ ;;
+
+ --debug)
+ $echo "$progname: enabling shell trace mode"
+ set -x
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ $echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ $echo "enable shared libraries"
+ else
+ $echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ $echo "enable static libraries"
+ else
+ $echo "disable static libraries"
+ fi
+ exit $?
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --preserve-dup-deps) duplicate_deps="yes" ;;
+
+ --quiet | --silent)
+ show=:
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --tag)
+ prevopt="--tag"
+ prev=tag
+ preserve_args="$preserve_args --tag"
+ ;;
+ --tag=*)
+ set tag "$optarg" ${1+"$@"}
+ shift
+ prev=tag
+ preserve_args="$preserve_args --tag"
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+fi
+
+case $disable_libs in
+no)
+ ;;
+shared)
+ build_libtool_libs=no
+ build_old_libs=yes
+ ;;
+static)
+ build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+ ;;
+esac
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
+ $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
+ case $nonopt in
+ *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
+ mode=link
+ for arg
+ do
+ case $arg in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx | *strace | *truss)
+ mode=execute
+ ;;
+ *install*|cp|mv)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$modename --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case $mode in
+ # libtool compile mode
+ compile)
+ modename="$modename: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ srcfile="$nonopt" # always keep a non-empty value in "srcfile"
+ suppress_opt=yes
+ suppress_output=
+ arg_mode=normal
+ libobj=
+ later=
+
+ for arg
+ do
+ case $arg_mode in
+ arg )
+ # do not "continue". Instead, add this to base_compile
+ lastarg="$arg"
+ arg_mode=normal
+ ;;
+
+ target )
+ libobj="$arg"
+ arg_mode=normal
+ continue
+ ;;
+
+ normal )
+ # Accept any command-line options.
+ case $arg in
+ -o)
+ if test -n "$libobj" ; then
+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ arg_mode=target
+ continue
+ ;;
+
+ -static | -prefer-pic | -prefer-non-pic)
+ later="$later $arg"
+ continue
+ ;;
+
+ -no-suppress)
+ suppress_opt=no
+ continue
+ ;;
+
+ -Xcompiler)
+ arg_mode=arg # the next one goes into the "base_compile" arg list
+ continue # The current "srcfile" will either be retained or
+ ;; # replaced later. I would guess that would be a bug.
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+ lastarg=
+ save_ifs="$IFS"; IFS=','
+ for arg in $args; do
+ IFS="$save_ifs"
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ lastarg="$lastarg $arg"
+ done
+ IFS="$save_ifs"
+ lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+ # Add the arguments to base_compile.
+ base_compile="$base_compile $lastarg"
+ continue
+ ;;
+
+ * )
+ # Accept the current argument as the source file.
+ # The previous "srcfile" becomes the current argument.
+ #
+ lastarg="$srcfile"
+ srcfile="$arg"
+ ;;
+ esac # case $arg
+ ;;
+ esac # case $arg_mode
+
+ # Aesthetically quote the previous argument.
+ lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+ case $lastarg in
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, and some SunOS ksh mistreat backslash-escaping
+ # in scan sets (worked around with variable expansion),
+ # and furthermore cannot handle '|' '&' '(' ')' in scan sets
+ # at all, so we specify them separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ base_compile="$base_compile $lastarg"
+ done # for arg
+
+ case $arg_mode in
+ arg)
+ $echo "$modename: you must specify an argument for -Xcompile"
+ exit $EXIT_FAILURE
+ ;;
+ target)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *)
+ # Get the name of the library object.
+ [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ xform='[cCFSifmso]'
+ case $libobj in
+ *.ada) xform=ada ;;
+ *.adb) xform=adb ;;
+ *.ads) xform=ads ;;
+ *.asm) xform=asm ;;
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.ii) xform=ii ;;
+ *.class) xform=class ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ *.java) xform=java ;;
+ esac
+
+ libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+ case $libobj in
+ *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+ *)
+ $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ func_infer_tag $base_compile
+
+ for arg in $later; do
+ case $arg in
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+ esac
+ done
+
+ qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
+ case $qlibobj in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qlibobj="\"$qlibobj\"" ;;
+ esac
+ test "X$libobj" != "X$qlibobj" \
+ && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \
+ && $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
+ objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir=
+ else
+ xdir=$xdir/
+ fi
+ lobj=${xdir}$objdir/$objname
+
+ if test -z "$base_compile"; then
+ $echo "$modename: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $lobj $libobj ${libobj}T"
+ else
+ removelist="$lobj $libobj ${libobj}T"
+ fi
+
+ $run $rm $removelist
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2*)
+ pic_mode=default
+ ;;
+ esac
+ if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ removelist="$removelist $output_obj $lockfile"
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+ else
+ output_obj=
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until $run ln "$progpath" "$lockfile" 2>/dev/null; do
+ $show "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ $echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+ $echo "$srcfile" > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+ qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
+ case $qsrcfile in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qsrcfile="\"$qsrcfile\"" ;;
+ esac
+
+ $run $rm "$libobj" "${libobj}T"
+
+ # Create a libtool object file (analogous to a ".la" file),
+ # but don't create it if we're doing a dry run.
+ test -z "$run" && cat > ${libobj}T <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test "$pic_mode" != no; then
+ command="$base_compile $qsrcfile $pic_flag"
+ else
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ fi
+
+ if test ! -d "${xdir}$objdir"; then
+ $show "$mkdir ${xdir}$objdir"
+ $run $mkdir ${xdir}$objdir
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
+ exit $exit_status
+ fi
+ fi
+
+ if test -z "$output_obj"; then
+ # Place PIC objects in $objdir
+ command="$command -o $lobj"
+ fi
+
+ $run $rm "$lobj" "$output_obj"
+
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+ $show "$mv $output_obj $lobj"
+ if $run $mv $output_obj $lobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the PIC object to the libtool object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object='$objdir/$objname'
+
+EOF
+
+ # Allow error messages only from the first compilation.
+ if test "$suppress_opt" = yes; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ else
+ # No PIC object so indicate it doesn't exist in the libtool
+ # object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
+
+EOF
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ if test "$pic_mode" != yes; then
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ else
+ command="$base_compile $qsrcfile $pic_flag"
+ fi
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ $run $rm "$obj" "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed
+ if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+ $show "$mv $output_obj $obj"
+ if $run $mv $output_obj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+ else
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
+ fi
+
+ $run $mv "${libobj}T" "${libobj}"
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $run $rm "$lockfile"
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool link mode
+ link | relink)
+ modename="$modename: link"
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invocation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ libtool_args="$nonopt"
+ base_compile="$nonopt $@"
+ compile_command="$nonopt"
+ finalize_command="$nonopt"
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
+ inst_prefix_dir=
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ non_pic_objects=
+ notinst_path= # paths that contain not-installed libtool libraries
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+ vinfo_number=no
+
+ func_infer_tag $base_compile
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static"; then
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ else
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=built
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test "$#" -gt 0; do
+ arg="$1"
+ shift
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+ ;;
+ *) qarg=$arg ;;
+ esac
+ libtool_args="$libtool_args $qarg"
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case $prev in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ preload=yes
+ fi
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ continue
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ if test ! -f "$arg"; then
+ $echo "$modename: symbol file \`$arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir="$arg"
+ prev=
+ continue
+ ;;
+ precious_regex)
+ precious_files_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ objectlist)
+ if test -f "$arg"; then
+ save_arg=$arg
+ moreargs=
+ for fil in `cat $save_arg`
+ do
+# moreargs="$moreargs $fil"
+ arg=$fil
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ done
+ else
+ $echo "$modename: link input file \`$save_arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ arg=$save_arg
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case $arg in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ xcompiler)
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ xlinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $wl$qarg"
+ prev=
+ compile_command="$compile_command $wl$qarg"
+ finalize_command="$finalize_command $wl$qarg"
+ continue
+ ;;
+ xcclinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ shrext)
+ shrext_cmds="$arg"
+ prev=
+ continue
+ ;;
+ darwin_framework|darwin_framework_skip)
+ test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi # test -n "$prev"
+
+ prevarg="$arg"
+
+ case $arg in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+ continue
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: more than one -exported-symbols argument is not allowed"
+ exit $EXIT_FAILURE
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -framework|-arch|-isysroot)
+ case " $CC " in
+ *" ${arg} ${1} "* | *" ${arg} ${1} "*)
+ prev=darwin_framework_skip ;;
+ *) compiler_flags="$compiler_flags $arg"
+ prev=darwin_framework ;;
+ esac
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ continue
+ ;;
+
+ -inst-prefix-dir)
+ prev=inst_prefix
+ continue
+ ;;
+
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix* | /*-*-irix*)
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ ;;
+ esac
+ continue
+ ;;
+
+ -L*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ notinst_path="$notinst_path $dir"
+ fi
+ dir="$absdir"
+ ;;
+ esac
+ case "$deplibs " in
+ *" -L$dir "*) ;;
+ *)
+ deplibs="$deplibs -L$dir"
+ lib_search_path="$lib_search_path $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C and math libraries are in the System framework
+ deplibs="$deplibs -framework System"
+ continue
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ test "X$arg" = "X-lc" && continue
+ ;;
+ esac
+ elif test "X$arg" = "X-lc_r"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ continue
+ ;;
+
+ # Tru64 UNIX uses -model [arg] to determine the layout of C++
+ # classes, name mangling, and exception handling.
+ -model)
+ compile_command="$compile_command $arg"
+ compiler_flags="$compiler_flags $arg"
+ finalize_command="$finalize_command $arg"
+ prev=xcompiler
+ continue
+ ;;
+
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+ compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+ # -r[0-9][0-9]* specifies the processor on the SGI compiler
+ # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+ # +DA*, +DD* enable 64-bit mode on the HP compiler
+ # -q* pass through compiler args for the IBM compiler
+ # -m* pass through architecture-specific compiler args for GCC
+ # -m*, -t[45]*, -txscale* pass through architecture-specific
+ # compiler args for GCC
+ # -pg pass through profiling flag for GCC
+ # @file GCC response files
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \
+ -t[45]*|-txscale*|@*)
+
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ compiler_flags="$compiler_flags $arg"
+ continue
+ ;;
+
+ -shrext)
+ prev=shrext
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # in order for the loader to find any dlls it needs.
+ $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+ $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -objectlist)
+ prev=objectlist
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -precious-files-regex)
+ prev=precious_regex
+ continue
+ ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -static)
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+ -version-number)
+ prev=vinfo
+ vinfo_number=yes
+ continue
+ ;;
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Wl,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $wl$flag"
+ linker_flags="$linker_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
+ -XCClinker)
+ prev=xcclinker
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.$objext)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ ;;
+
+ *.$libext)
+ # An archive.
+ deplibs="$deplibs $arg"
+ old_deplibs="$old_deplibs $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ if test "$prev" = dlfiles; then
+ # This library was specified with -dlopen.
+ dlfiles="$dlfiles $arg"
+ prev=
+ elif test "$prev" = dlprefiles; then
+ # The library was specified with -dlpreopen.
+ dlprefiles="$dlprefiles $arg"
+ prev=
+ else
+ deplibs="$deplibs $arg"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done # argument parsing loop
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+ # Create the object directory.
+ if test ! -d "$output_objdir"; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
+ exit $exit_status
+ fi
+ fi
+
+ # Determine the type of output
+ case $output in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ case $host in
+ *cygwin* | *mingw* | *pw32*)
+ # don't eliminate duplications in $postdeps and $predeps
+ duplicate_compiler_generated_deps=yes
+ ;;
+ *)
+ duplicate_compiler_generated_deps=$duplicate_deps
+ ;;
+ esac
+ specialdeplibs=
+
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ libs="$libs $deplib"
+ done
+
+ if test "$linkmode" = lib; then
+ libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+ # Compute libraries that are listed more than once in $predeps
+ # $postdeps and mark them as special (i.e., whose duplicates are
+ # not to be eliminated).
+ pre_post_deps=
+ if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
+ for pre_post_dep in $predeps $postdeps; do
+ case "$pre_post_deps " in
+ *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+ esac
+ pre_post_deps="$pre_post_deps $pre_post_dep"
+ done
+ fi
+ pre_post_deps=
+ fi
+
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ case $linkmode in
+ lib)
+ passes="conv link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=no
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+ for pass in $passes; do
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan"; then
+ libs="$deplibs"
+ deplibs=
+ fi
+ if test "$linkmode" = prog; then
+ case $pass in
+ dlopen) libs="$dlfiles" ;;
+ dlpreopen) libs="$dlprefiles" ;;
+ link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+ esac
+ fi
+ if test "$pass" = dlopen; then
+ # Collect dlpreopened libraries
+ save_deplibs="$deplibs"
+ deplibs=
+ fi
+ for deplib in $libs; do
+ lib=
+ found=no
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags $deplib"
+ fi
+ continue
+ ;;
+ -l*)
+ if test "$linkmode" != lib && test "$linkmode" != prog; then
+ $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
+ continue
+ fi
+ name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+ for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ for search_ext in .la $std_shrext .so .a; do
+ # Search the libtool library
+ lib="$searchdir/lib${name}${search_ext}"
+ if test -f "$lib"; then
+ if test "$search_ext" = ".la"; then
+ found=yes
+ else
+ found=no
+ fi
+ break 2
+ fi
+ done
+ done
+ if test "$found" != yes; then
+ # deplib doesn't seem to be a libtool library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ else # deplib is a libtool library
+ # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+ # We need to do some special things here, and not later.
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $deplib "*)
+ if (${SED} -e '2q' $lib |
+ grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ library_names=
+ old_library=
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ for l in $old_library $library_names; do
+ ll="$l"
+ done
+ if test "X$ll" = "X$old_library" ; then # only static version available
+ found=no
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+ lib=$ladir/$old_library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ fi
+ ;; # -l
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test "$pass" = conv && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ prog)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test "$pass" = scan; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ *)
+ $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test "$pass" = link; then
+ dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la) lib="$deplib" ;;
+ *.$libext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ valid_a_lib=no
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ if eval $echo \"$deplib\" 2>/dev/null \
+ | $SED 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=yes
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=yes
+ ;;
+ esac
+ if test "$valid_a_lib" != yes; then
+ $echo
+ $echo "*** Warning: Trying to link with static lib archive $deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because the file extensions .$libext of this argument makes me believe"
+ $echo "*** that it is just a static archive that I should not used here."
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the"
+ $echo "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ fi
+ continue
+ ;;
+ prog)
+ if test "$pass" != link; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ elif test "$linkmode" = prog; then
+ if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ newdlprefiles="$newdlprefiles $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ newdlfiles="$newdlfiles $deplib"
+ fi
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=yes
+ continue
+ ;;
+ esac # case $deplib
+ if test "$found" = yes || test -f "$lib"; then :
+ else
+ $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variables installed, or shouldnotlink
+ installed=yes
+ shouldnotlink=no
+ avoidtemprpath=
+
+
+ # Read the .la file
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan" ||
+ { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+ test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+ test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+ fi
+
+ if test "$pass" = conv; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $ladir/$objdir/$old_library"
+ old_convenience="$old_convenience $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+ elif test "$linkmode" != prog && test "$linkmode" != lib; then
+ $echo "$modename: \`$lib' is not a convenience library" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ continue
+ fi # $pass = conv
+
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+ if test -z "$linklib"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$pass" = dlopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test -z "$dlname" ||
+ test "$dlopen_support" != yes ||
+ test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload. We also need to preload any
+ # dependent libraries so libltdl's deplib preloader doesn't
+ # bomb out in the load deplibs phase.
+ dlprefiles="$dlprefiles $lib $dependency_libs"
+ else
+ newdlfiles="$newdlfiles $lib"
+ fi
+ continue
+ fi # $pass = dlopen
+
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ abs_ladir="$ladir"
+ fi
+ ;;
+ esac
+ laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+ # Find the relevant object directory and library name.
+ if test "X$installed" = Xyes; then
+ if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ $echo "$modename: warning: library \`$lib' was moved." 1>&2
+ dir="$ladir"
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+ dir="$libdir"
+ absdir="$libdir"
+ fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+ else
+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ dir="$ladir"
+ absdir="$abs_ladir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ fi
+ fi # $installed = yes
+ name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+ # This library was specified with -dlpreopen.
+ if test "$pass" = dlpreopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ newdlprefiles="$newdlprefiles $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ newdlprefiles="$newdlprefiles $dir/$dlname"
+ else
+ newdlprefiles="$newdlprefiles $dir/$linklib"
+ fi
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test "$linkmode" = lib; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs" # used for prog,scan pass
+ fi
+ continue
+ fi
+
+
+ if test "$linkmode" = prog && test "$pass" != link; then
+ newlib_search_path="$newlib_search_path $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=no
+ if test "$link_all_deplibs" != no || test -z "$library_names" ||
+ test "$build_libtool_libs" = no; then
+ linkalldeplibs=yes
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+ esac
+ # Need to link against all dependency_libs?
+ if test "$linkalldeplibs" = yes; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ if test "$linkmode,$pass" = "prog,link"; then
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *" $absdir "*) ;;
+ *) temp_rpath="$temp_rpath $absdir" ;;
+ esac
+ fi
+
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi # $linkmode,$pass = prog,link...
+
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+ fi
+
+ link_static=no # Whether the deplib will be linked statically
+ use_static_libs=$prefer_static_libs
+ if test "$use_static_libs" = built && test "$installed" = yes ; then
+ use_static_libs=no
+ fi
+ if test -n "$library_names" &&
+ { test "$use_static_libs" = no || test -z "$old_library"; }; then
+ if test "$installed" = no; then
+ notinst_deplibs="$notinst_deplibs $lib"
+ need_relink=yes
+ fi
+ # This is a shared library
+
+ # Warn about portability, can't link against -module's on
+ # some systems (darwin)
+ if test "$shouldnotlink" = yes && test "$pass" = link ; then
+ $echo
+ if test "$linkmode" = prog; then
+ $echo "*** Warning: Linking the executable $output against the loadable module"
+ else
+ $echo "*** Warning: Linking the shared library $output against the loadable module"
+ fi
+ $echo "*** $linklib is not portable!"
+ fi
+ if test "$linkmode" = lib &&
+ test "$hardcode_into_libs" = yes; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+ libname=`eval \\$echo \"$libname_spec\"`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname="$dlname"
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin* | mingw*)
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+ esac
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot="$soname"
+ soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
+ newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ $show "extracting exported symbol list from \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$extract_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ $show "generating import library for \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$old_archive_from_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n "$old_archive_from_expsyms_cmds"
+
+ if test "$linkmode" = prog || test "$mode" != relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ add="$dir/$linklib"
+ case $host in
+ *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+ *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+ *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+ *-*-unixware7*) add_dir="-L$dir" ;;
+ *-*-darwin* )
+ # if the lib is a module then we can not link against
+ # it, someone is ignoring the new warnings I added
+ if /usr/bin/file -L $add 2> /dev/null |
+ $EGREP ": [^:]* bundle" >/dev/null ; then
+ $echo "** Warning, lib $linklib is a module, not a shared library"
+ if test -z "$old_library" ; then
+ $echo
+ $echo "** And there doesn't seem to be a static archive available"
+ $echo "** The link will probably fail, sorry"
+ else
+ add="$dir/$old_library"
+ fi
+ fi
+ esac
+ elif test "$hardcode_minus_L" = no; then
+ case $host in
+ *-*-sunos*) add_shlibpath="$dir" ;;
+ esac
+ add_dir="-L$dir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test "$hardcode_direct" = yes; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$dir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+ esac
+ fi
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test "$hardcode_direct" != yes && \
+ test "$hardcode_minus_L" != yes && \
+ test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test "$linkmode" = prog || test "$mode" = relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ add="-l$name"
+ elif test "$hardcode_automatic" = yes; then
+ if test -n "$inst_prefix_dir" &&
+ test -f "$inst_prefix_dir$libdir/$linklib" ; then
+ add="$inst_prefix_dir$libdir/$linklib"
+ else
+ add="$libdir/$linklib"
+ fi
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ fi
+
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+ elif test "$linkmode" = prog; then
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test "$build_libtool_libs" = yes; then
+ # Not a shared library
+ if test "$deplibs_check_method" != pass_all; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ $echo
+ $echo "*** Warning: This system can not link to static lib archive $lib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have."
+ if test "$module" = yes; then
+ $echo "*** But as you try to build a module library, libtool will still create "
+ $echo "*** a static module, that should work as long as the dlopening application"
+ $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test "$linkmode" = lib; then
+ if test -n "$dependency_libs" &&
+ { test "$hardcode_into_libs" != yes ||
+ test "$build_old_libs" = yes ||
+ test "$link_static" = yes; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ *) temp_deplibs="$temp_deplibs $libdir";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ newlib_search_path="$newlib_search_path $absdir"
+ # Link against this library
+ test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+
+ if test "$link_all_deplibs" != no; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) path="$deplib" ;;
+ *.la)
+ dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$deplib" && dir="."
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ fi
+ ;;
+ esac
+ if grep "^installed=no" $deplib > /dev/null; then
+ path="$absdir/$objdir"
+ else
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$absdir" != "$libdir"; then
+ $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+ fi
+ path="$absdir"
+ fi
+ depdepl=
+ case $host in
+ *-*-darwin*)
+ # we do not want to link against static libs,
+ # but need to link against shared
+ eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+ if test -n "$deplibrary_names" ; then
+ for tmp in $deplibrary_names ; do
+ depdepl=$tmp
+ done
+ if test -f "$path/$depdepl" ; then
+ depdepl="$path/$depdepl"
+ fi
+ # do not add paths which are already there
+ case " $newlib_search_path " in
+ *" $path "*) ;;
+ *) newlib_search_path="$newlib_search_path $path";;
+ esac
+ fi
+ path=""
+ ;;
+ *)
+ path="-L$path"
+ ;;
+ esac
+ ;;
+ -l*)
+ case $host in
+ *-*-darwin*)
+ # Again, we only want to link against shared libraries
+ eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
+ for tmp in $newlib_search_path ; do
+ if test -f "$tmp/lib$tmp_libs.dylib" ; then
+ eval depdepl="$tmp/lib$tmp_libs.dylib"
+ break
+ fi
+ done
+ path=""
+ ;;
+ *) continue ;;
+ esac
+ ;;
+ *) continue ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$path $deplibs" ;;
+ esac
+ case " $deplibs " in
+ *" $depdepl "*) ;;
+ *) deplibs="$depdepl $deplibs" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ dependency_libs="$newdependency_libs"
+ if test "$pass" = dlpreopen; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test "$pass" != dlopen; then
+ if test "$pass" != conv; then
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ fi
+
+ if test "$linkmode,$pass" != "prog,link"; then
+ vars="deplibs"
+ else
+ vars="compile_deplibs finalize_deplibs"
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ # FIXME: Pedantically, this is the right thing to do, so
+ # that some nasty dependency loop isn't accidentally
+ # broken:
+ #new_libs="$deplib $new_libs"
+ # Pragmatically, this seems to cause very few problems in
+ # practice:
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ -R*) ;;
+ *)
+ # And here is the reason: when a library appears more
+ # than once as an explicit dependence of a library, or
+ # is implicitly linked in more than once by the
+ # compiler, it is considered special, and multiple
+ # occurrences thereof are not removed. Compare this
+ # with having the same library being listed as a
+ # dependency of multiple other libraries: in this case,
+ # we know (pedantically, we assume) the library does not
+ # need to be listed more than once, so we keep only the
+ # last copy. This is not always right, but it is rare
+ # enough that we require users that really mean to play
+ # such unportable linking tricks to link the library
+ # using -Wl,-lname, so that libtool does not consider it
+ # for duplicate removal.
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+ # Last step: remove runtime libs from dependency_libs
+ # (they stay in deplibs)
+ tmp_libs=
+ for i in $dependency_libs ; do
+ case " $predeps $postdeps $compiler_lib_search_path " in
+ *" $i "*)
+ i=""
+ ;;
+ esac
+ if test -n "$i" ; then
+ tmp_libs="$tmp_libs $i"
+ fi
+ done
+ dependency_libs=$tmp_libs
+ done # for pass
+ if test "$linkmode" = prog; then
+ dlfiles="$newdlfiles"
+ dlprefiles="$newdlprefiles"
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+ fi
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ objs="$objs$old_deplibs"
+ ;;
+
+ lib)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case $outputname in
+ lib*)
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test "$module" = no; then
+ $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ else
+ libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ fi
+ ;;
+ esac
+
+ if test -n "$objs"; then
+ if test "$deplibs_check_method" != pass_all; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+ exit $EXIT_FAILURE
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the non-libtool"
+ $echo "*** objects $objs is not portable!"
+ libobjs="$libobjs $objs"
+ fi
+ fi
+
+ if test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+ fi
+
+ set dummy $rpath
+ if test "$#" -gt 2; then
+ $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ # Some compilers have problems with a `.al' extension so
+ # convenience libraries should have the same extension an
+ # archive normally would.
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+ fi
+ else
+
+ # Parse the version information argument.
+ save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+ if test -n "$8"; then
+ $echo "$modename: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # convert absolute version numbers to libtool ages
+ # this retains compatibility with .la files and attempts
+ # to make the code below a bit more comprehensible
+
+ case $vinfo_number in
+ yes)
+ number_major="$2"
+ number_minor="$3"
+ number_revision="$4"
+ #
+ # There are really only two kinds -- those that
+ # use the current revision as the major version
+ # and those that subtract age and use age as
+ # a minor version. But, then there is irix
+ # which has an extra 1 added just for fun
+ #
+ case $version_type in
+ darwin|linux|osf|windows)
+ current=`expr $number_major + $number_minor`
+ age="$number_minor"
+ revision="$number_revision"
+ ;;
+ freebsd-aout|freebsd-elf|sunos)
+ current="$number_major"
+ revision="$number_minor"
+ age="0"
+ ;;
+ irix|nonstopux)
+ current=`expr $number_major + $number_minor - 1`
+ age="$number_minor"
+ revision="$number_minor"
+ ;;
+ esac
+ ;;
+ no)
+ current="$2"
+ revision="$3"
+ age="$4"
+ ;;
+ esac
+
+ # Check that each of the things are valid numbers.
+ case $current in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $revision in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $age in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test "$age" -gt "$current"; then
+ $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case $version_type in
+ none) ;;
+
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ # Darwin ld doesn't like 0 for these options...
+ minor_current=`expr $current + 1`
+ verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
+ irix | nonstopux)
+ major=`expr $current - $age + 1`
+
+ case $version_type in
+ nonstopux) verstring_prefix=nonstopux ;;
+ *) verstring_prefix=sgi ;;
+ esac
+ verstring="$verstring_prefix$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test "$loop" -ne 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring_prefix$major.$iface:$verstring"
+ done
+
+ # Before this point, $major must not contain `.'.
+ major=.$major
+ versuffix="$major.$revision"
+ ;;
+
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ major=.`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test "$loop" -ne 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 filesystems.
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=
+ ;;
+ *)
+ verstring="0.0"
+ ;;
+ esac
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+ fi
+
+ if test "$mode" != relink; then
+ # Remove our outputs, but don't remove object files since they
+ # may have been created when compiling PIC objects.
+ removelist=
+ tempremovelist=`$echo "$output_objdir/*"`
+ for p in $tempremovelist; do
+ case $p in
+ *.$objext)
+ ;;
+ $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+ if test "X$precious_files_regex" != "X"; then
+ if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+ removelist="$removelist $p"
+ ;;
+ *) ;;
+ esac
+ done
+ if test -n "$removelist"; then
+ $show "${rm}r $removelist"
+ $run ${rm}r $removelist
+ fi
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+ for path in $notinst_path; do
+ lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
+ deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
+ dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
+ done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles="$dlfiles"
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) dlfiles="$dlfiles $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles="$dlprefiles"
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) dlprefiles="$dlprefiles $lib" ;;
+ esac
+ done
+
+ if test "$build_libtool_libs" = yes; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ deplibs="$deplibs -framework System"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test "$build_libtool_need_lc" = "yes"; then
+ deplibs="$deplibs -lc"
+ fi
+ ;;
+ esac
+ fi
+
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case $deplibs_check_method in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behavior.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $rm conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ $LTCC $LTCFLAGS -o conftest conftest.c $deplibs
+ if test "$?" -eq 0 ; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name=`expr $i : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" -ne "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which I believe you do not have"
+ $echo "*** because a test_compile did reveal that the linker did not use it for"
+ $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occurred in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ name=`expr $i : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ $rm conftest
+ $LTCC $LTCFLAGS -o conftest conftest.c $i
+ # Did it work?
+ if test "$?" -eq 0 ; then
+ ldd_output=`ldd conftest`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because a test_compile did reveal that the linker did not use this one"
+ $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ fi
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning! Library $i is needed by this library but I was not able to"
+ $echo "*** make it link in! You will probably need to install it or some"
+ $echo "*** library that it depends on before this library will be fully"
+ $echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name=`expr $a_deplib : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null \
+ | grep " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for file magic test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a file magic. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name=`expr $a_deplib : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test -n "$name" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ potlib="$potent_lib" # see symlink-check above in file_magic test
+ if eval $echo \"$potent_lib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a regex pattern. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+ -e 's/ -[LR][^ ]*//g'`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ for i in $predeps $postdeps ; do
+ # can't use Xsed below, because $i might contain '/'
+ tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
+ done
+ fi
+ if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \
+ | grep . >/dev/null; then
+ $echo
+ if test "X$deplibs_check_method" = "Xnone"; then
+ $echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ $echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ $echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ $echo
+ $echo "*** Warning: libtool could not satisfy all declared inter-library"
+ $echo "*** dependencies of module $libname. Therefore, libtool will create"
+ $echo "*** a static module, that should work as long as the dlopening"
+ $echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ $echo "*** The inter-library dependencies that have been dropped here will be"
+ $echo "*** automatically added whenever a program is linked with this library"
+ $echo "*** or is declared to -dlopen it."
+
+ if test "$allow_undefined" = no; then
+ $echo
+ $echo "*** Since this library must not contain undefined symbols,"
+ $echo "*** because either the platform does not support them or"
+ $echo "*** it was explicitly requested with -no-undefined,"
+ $echo "*** libtool will only create a static version of it."
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ deplibs="$new_libs"
+
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ if test "$hardcode_into_libs" = yes; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath="$finalize_rpath"
+ test "$mode" != relink && rpath="$compile_rpath$rpath"
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ dep_rpath="$dep_rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ if test -n "$hardcode_libdir_flag_spec_ld"; then
+ eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+ else
+ eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+ fi
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath="$finalize_shlibpath"
+ test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
+ # Get the real and link names of the library.
+ eval shared_ext=\"$shrext_cmds\"
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+ if test -z "$dlname"; then
+ dlname=$soname
+ fi
+
+ lib="$output_objdir/$realname"
+ linknames=
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ cmds=$export_symbols_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ if len=`expr "X$cmd" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ skipped_export=false
+ else
+ # The command line is too long to execute in one step.
+ $show "using reloadable object file for export list..."
+ skipped_export=:
+ # Break out early, otherwise skipped_export may be
+ # set to false by a later but shorter cmd.
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex"; then
+ $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+ $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+ $run eval '$mv "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+ fi
+
+ tmp_deplibs=
+ for test_deplib in $deplibs; do
+ case " $convenience " in
+ *" $test_deplib "*) ;;
+ *)
+ tmp_deplibs="$tmp_deplibs $test_deplib"
+ ;;
+ esac
+ done
+ deplibs="$tmp_deplibs"
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ libobjs="$libobjs $func_extract_archives_result"
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linker_flags="$linker_flags $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+ fi
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ eval test_cmds=\"$module_expsym_cmds\"
+ cmds=$module_expsym_cmds
+ else
+ eval test_cmds=\"$module_cmds\"
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval test_cmds=\"$archive_expsym_cmds\"
+ cmds=$archive_expsym_cmds
+ else
+ eval test_cmds=\"$archive_cmds\"
+ cmds=$archive_cmds
+ fi
+ fi
+
+ if test "X$skipped_export" != "X:" &&
+ len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ :
+ else
+ # The command line is too long to link in one step, link piecewise.
+ $echo "creating reloadable object files..."
+
+ # Save the value of $output and $libobjs because we want to
+ # use them later. If we have whole_archive_flag_spec, we
+ # want to use save_libobjs as it was before
+ # whole_archive_flag_spec was expanded, because we can't
+ # assume the linker understands whole_archive_flag_spec.
+ # This may have to be revisited, in case too many
+ # convenience libraries get linked in and end up exceeding
+ # the spec.
+ if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ fi
+ save_output=$output
+ output_la=`$echo "X$output" | $Xsed -e "$basename"`
+
+ # Clear the reloadable object creation command queue and
+ # initialize k to one.
+ test_cmds=
+ concat_cmds=
+ objlist=
+ delfiles=
+ last_robj=
+ k=1
+ output=$output_objdir/$output_la-${k}.$objext
+ # Loop over the list of objects to be linked.
+ for obj in $save_libobjs
+ do
+ eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+ if test "X$objlist" = X ||
+ { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len"; }; then
+ objlist="$objlist $obj"
+ else
+ # The command $test_cmds is almost too long, add a
+ # command to the queue.
+ if test "$k" -eq 1 ; then
+ # The first file doesn't have a previous command to add.
+ eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+ else
+ # All subsequent reloadable object files will link in
+ # the last one created.
+ eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
+ fi
+ last_robj=$output_objdir/$output_la-${k}.$objext
+ k=`expr $k + 1`
+ output=$output_objdir/$output_la-${k}.$objext
+ objlist=$obj
+ len=1
+ fi
+ done
+ # Handle the remaining objects by creating one last
+ # reloadable object file. All subsequent reloadable object
+ # files will link in the last one created.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+
+ if ${skipped_export-false}; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ libobjs=$output
+ # Append the command to create the export file.
+ eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
+ fi
+
+ # Set up a command to remove the reloadable object files
+ # after they are used.
+ i=0
+ while test "$i" -lt "$k"
+ do
+ i=`expr $i + 1`
+ delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
+ done
+
+ $echo "creating a temporary reloadable object file: $output"
+
+ # Loop through the commands generated above and execute them.
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $concat_cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ libobjs=$output
+ # Restore the value of output.
+ output=$save_output
+
+ if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ fi
+ # Expand the library linking commands again to reset the
+ # value of $libobjs for piecewise linking.
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ cmds=$module_expsym_cmds
+ else
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ cmds=$archive_expsym_cmds
+ else
+ cmds=$archive_cmds
+ fi
+ fi
+
+ # Append the command to remove the reloadable object files
+ # to the just-reset $cmds.
+ eval cmds=\"\$cmds~\$rm $delfiles\"
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS="$save_ifs"
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+
+ if test -n "$convenience"; then
+ if test -z "$whole_archive_flag_spec"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ fi
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+ fi
+
+ case $output in
+ *.lo)
+ if test -n "$objs$old_deplibs"; then
+ $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ libobj="$output"
+ obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${obj}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+ output="$obj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$build_libtool_libs" != yes; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ # $show "echo timestamp > $libobj"
+ # $run eval "echo timestamp > $libobj" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test -n "$pic_flag" || test "$pic_mode" != default; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ prog)
+ case $host in
+ *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+ esac
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+ fi
+
+ if test "$preload" = yes; then
+ if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+ test "$dlopen_self_static" = unknown; then
+ $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+ fi
+ fi
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ case $host in
+ *darwin*)
+ # Don't allow lazy linking, it breaks C++ global constructors
+ if test "$tagname" = CXX ; then
+ compile_command="$compile_command ${wl}-bind_at_load"
+ finalize_command="$finalize_command ${wl}-bind_at_load"
+ fi
+ ;;
+ esac
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $compile_deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $compile_deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ compile_deplibs="$new_libs"
+
+
+ compile_command="$compile_command $compile_deplibs"
+ finalize_command="$finalize_command $finalize_deplibs"
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$libdir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
+ ;;
+ esac
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ dlsyms=
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${outputname}S.c"
+ else
+ $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+ fi
+ fi
+
+ if test -n "$dlsyms"; then
+ case $dlsyms in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${outputname}.nm"
+
+ $show "$rm $nlist ${nlist}S ${nlist}T"
+ $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+ # Parse the name list into a source file.
+ $show "creating $output_objdir/$dlsyms"
+
+ test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ $show "generating symbol list for \`$output'"
+
+ test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for arg in $progfiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$outputname.exp"
+ $run $rm $export_symbols
+ $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ case $host in
+ *cygwin* | *mingw* )
+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ else
+ $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+ $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ case $host in
+ *cygwin* | *mingw* )
+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
+ $run eval '$echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -z "$run"; then
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $mv "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if grep -v "^: " < "$nlist" |
+ if sort -k 3 </dev/null >/dev/null 2>&1; then
+ sort -k 3
+ else
+ sort +2
+ fi |
+ uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+ else
+ $echo '/* NONE */' >> "$output_objdir/$dlsyms"
+ fi
+
+ $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+"
+
+ case $host in
+ *cygwin* | *mingw* )
+ $echo >> "$output_objdir/$dlsyms" "\
+/* DATA imports from DLLs on WIN32 can't be const, because
+ runtime relocations are performed -- see ld's documentation
+ on pseudo-relocs */
+struct {
+"
+ ;;
+ * )
+ $echo >> "$output_objdir/$dlsyms" "\
+const struct {
+"
+ ;;
+ esac
+
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ const char *name;
+ lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ fi
+
+ pic_flag_for_symtable=
+ case $host in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
+ esac;;
+ *-*-hpux*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag";;
+ esac
+ esac
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+ # Clean up the generated files.
+ $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+ $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+ # Transform the symbol file into the correct name.
+ case $host in
+ *cygwin* | *mingw* )
+ if test -f "$output_objdir/${outputname}.def" ; then
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
+ else
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ fi
+ ;;
+ * )
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ ;;
+ esac
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ fi
+
+ if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$link_command"
+ $run eval "$link_command"
+ exit_status=$?
+
+ # Delete the generated files.
+ if test -n "$dlsyms"; then
+ $show "$rm $output_objdir/${outputname}S.${objext}"
+ $run $rm "$output_objdir/${outputname}S.${objext}"
+ fi
+
+ exit $exit_status
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$no_install" = yes; then
+ # We don't need to create a wrapper script.
+ link_command="$compile_var$compile_command$compile_rpath"
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $run $rm $output
+ # Link the executable and exit
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+ $echo "$modename: \`$output' will be relinked during installation" 1>&2
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ relink_command="(cd `pwd`; $relink_command)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Quote $echo for shipping.
+ if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
+ case $progpath in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+ esac
+ qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*)
+ exeext=.exe
+ outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
+ *) exeext= ;;
+ esac
+ case $host in
+ *cygwin* | *mingw* )
+ output_name=`basename $output`
+ output_path=`dirname $output`
+ cwrappersource="$output_path/$objdir/lt-$output_name.c"
+ cwrapper="$output_path/$output_name.exe"
+ $rm $cwrappersource $cwrapper
+ trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+ cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+ Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+ The $output program cannot be directly executed until all the libtool
+ libraries that it depends on are installed.
+
+ This wrapper executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+
+ Currently, it simply execs the wrapper *script* "/bin/sh $output",
+ but could eventually absorb all of the scripts functionality and
+ exec $objdir/$outputname directly.
+*/
+EOF
+ cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+ defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# ifndef DIR_SEPARATOR_2
+# define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+# define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+/* -DDEBUG is fairly common in CFLAGS. */
+#undef DEBUG
+#if defined DEBUGWRAPPER
+# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
+#else
+# define DEBUG(format, ...)
+#endif
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+const char * base_name (const char *name);
+char * find_executable(const char *wrapper);
+int check_executable(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+ char **newargz;
+ int i;
+
+ program_name = (char *) xstrdup (base_name (argv[0]));
+ DEBUG("(main) argv[0] : %s\n",argv[0]);
+ DEBUG("(main) program_name : %s\n",program_name);
+ newargz = XMALLOC(char *, argc+2);
+EOF
+
+ cat >> $cwrappersource <<EOF
+ newargz[0] = (char *) xstrdup("$SHELL");
+EOF
+
+ cat >> $cwrappersource <<"EOF"
+ newargz[1] = find_executable(argv[0]);
+ if (newargz[1] == NULL)
+ lt_fatal("Couldn't find %s", argv[0]);
+ DEBUG("(main) found exe at : %s\n",newargz[1]);
+ /* we know the script has the same name, without the .exe */
+ /* so make sure newargz[1] doesn't end in .exe */
+ strendzap(newargz[1],".exe");
+ for (i = 1; i < argc; i++)
+ newargz[i+1] = xstrdup(argv[i]);
+ newargz[argc+1] = NULL;
+
+ for (i=0; i<argc+1; i++)
+ {
+ DEBUG("(main) newargz[%d] : %s\n",i,newargz[i]);
+ ;
+ }
+
+EOF
+
+ case $host_os in
+ mingw*)
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",(char const **)newargz);
+EOF
+ ;;
+ *)
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",newargz);
+EOF
+ ;;
+ esac
+
+ cat >> $cwrappersource <<"EOF"
+ return 127;
+}
+
+void *
+xmalloc (size_t num)
+{
+ void * p = (void *) malloc (num);
+ if (!p)
+ lt_fatal ("Memory exhausted");
+
+ return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+const char *
+base_name (const char *name)
+{
+ const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha ((unsigned char)name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return base;
+}
+
+int
+check_executable(const char * path)
+{
+ struct stat st;
+
+ DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
+ if ((!path) || (!*path))
+ return 0;
+
+ if ((stat (path, &st) >= 0) &&
+ (
+ /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
+#if defined (S_IXOTH)
+ ((st.st_mode & S_IXOTH) == S_IXOTH) ||
+#endif
+#if defined (S_IXGRP)
+ ((st.st_mode & S_IXGRP) == S_IXGRP) ||
+#endif
+ ((st.st_mode & S_IXUSR) == S_IXUSR))
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/* Searches for the full path of the wrapper. Returns
+ newly allocated full path name if found, NULL otherwise */
+char *
+find_executable (const char* wrapper)
+{
+ int has_slash = 0;
+ const char* p;
+ const char* p_next;
+ /* static buffer for getcwd */
+ char tmp[LT_PATHMAX + 1];
+ int tmp_len;
+ char* concat_name;
+
+ DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
+
+ if ((wrapper == NULL) || (*wrapper == '\0'))
+ return NULL;
+
+ /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+ else
+ {
+#endif
+ if (IS_DIR_SEPARATOR (wrapper[0]))
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ }
+#endif
+
+ for (p = wrapper; *p; p++)
+ if (*p == '/')
+ {
+ has_slash = 1;
+ break;
+ }
+ if (!has_slash)
+ {
+ /* no slashes; search PATH */
+ const char* path = getenv ("PATH");
+ if (path != NULL)
+ {
+ for (p = path; *p; p = p_next)
+ {
+ const char* q;
+ size_t p_len;
+ for (q = p; *q; q++)
+ if (IS_PATH_SEPARATOR(*q))
+ break;
+ p_len = q - p;
+ p_next = (*q == '\0' ? q : q + 1);
+ if (p_len == 0)
+ {
+ /* empty path: current directory */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ tmp_len = strlen(tmp);
+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+ }
+ else
+ {
+ concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, p, p_len);
+ concat_name[p_len] = '/';
+ strcpy (concat_name + p_len + 1, wrapper);
+ }
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+ }
+ /* not found in PATH; assume curdir */
+ }
+ /* Relative path | not found in path: prepend cwd */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ tmp_len = strlen(tmp);
+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ return NULL;
+}
+
+char *
+strendzap(char *str, const char *pat)
+{
+ size_t len, patlen;
+
+ assert(str != NULL);
+ assert(pat != NULL);
+
+ len = strlen(str);
+ patlen = strlen(pat);
+
+ if (patlen <= len)
+ {
+ str += len - patlen;
+ if (strcmp(str, pat) == 0)
+ *str = '\0';
+ }
+ return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode,
+ const char * message, va_list ap)
+{
+ fprintf (stderr, "%s: %s: ", program_name, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+ va_end (ap);
+}
+EOF
+ # we should really use a build-platform specific compiler
+ # here, but OTOH, the wrappers (shell script and this C one)
+ # are only useful if you want to execute the "real" binary.
+ # Since the "real" binary is built for $host, then this
+ # wrapper might as well be built for $host, too.
+ $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
+ ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
+
+ $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variable:
+ notinst_deplibs='$notinst_deplibs'
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ echo=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$echo will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $echo >> $output "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ $echo >> $output "\
+ program=lt-'$outputname'$exeext
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $mkdir \"\$progdir\"
+ else
+ $rm \"\$progdir/\$file\"
+ fi"
+
+ $echo >> $output "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
+ $echo \"\$relink_command_output\" >&2
+ $rm \"\$progdir/\$file\"
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $rm \"\$progdir/\$program\";
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $rm \"\$progdir/\$file\"
+ fi"
+ else
+ $echo >> $output "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ $echo >> $output "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $echo >> $output "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $echo >> $output "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $echo >> $output "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2*)
+ $echo >> $output "\
+ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $echo >> $output "\
+ exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $echo >> $output "\
+ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+ exit $EXIT_FAILURE
+ fi
+ else
+ # The program doesn't exist.
+ \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+ \$echo \"This script is just a wrapper for \$program.\" 1>&2
+ $echo \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi\
+"
+ chmod +x $output
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$old_deplibs $non_pic_objects"
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $addlibs
+ oldobjs="$oldobjs $func_extract_archives_result"
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ cmds=$old_archive_from_new_cmds
+ else
+ # POSIX demands no paths to be encoded in archives. We have
+ # to avoid creating archives with duplicate basenames if we
+ # might have to extract them afterwards, e.g., when creating a
+ # static archive out of a convenience library, or when linking
+ # the entirety of a libtool archive into another (currently
+ # not supported by libtool).
+ if (for obj in $oldobjs
+ do
+ $echo "X$obj" | $Xsed -e 's%^.*/%%'
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "copying selected object files to avoid basename conflicts..."
+
+ if test -z "$gentop"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "$mkdir $gentop"
+ $run $mkdir "$gentop"
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
+ exit $exit_status
+ fi
+ fi
+
+ save_oldobjs=$oldobjs
+ oldobjs=
+ counter=1
+ for obj in $save_oldobjs
+ do
+ objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ case " $oldobjs " in
+ " ") oldobjs=$obj ;;
+ *[\ /]"$objbase "*)
+ while :; do
+ # Make sure we don't pick an alternate name that also
+ # overlaps.
+ newobj=lt$counter-$objbase
+ counter=`expr $counter + 1`
+ case " $oldobjs " in
+ *[\ /]"$newobj "*) ;;
+ *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+ esac
+ done
+ $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+ $run ln "$obj" "$gentop/$newobj" ||
+ $run cp "$obj" "$gentop/$newobj"
+ oldobjs="$oldobjs $gentop/$newobj"
+ ;;
+ *) oldobjs="$oldobjs $obj" ;;
+ esac
+ done
+ fi
+
+ eval cmds=\"$old_archive_cmds\"
+
+ if len=`expr "X$cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ cmds=$old_archive_cmds
+ else
+ # the command line is too long to link in one step, link in parts
+ $echo "using piecewise archive linking..."
+ save_RANLIB=$RANLIB
+ RANLIB=:
+ objlist=
+ concat_cmds=
+ save_oldobjs=$oldobjs
+
+ # Is there a better way of finding the last object in the list?
+ for obj in $save_oldobjs
+ do
+ last_oldobj=$obj
+ done
+ for obj in $save_oldobjs
+ do
+ oldobjs="$objlist $obj"
+ objlist="$objlist $obj"
+ eval test_cmds=\"$old_archive_cmds\"
+ if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len"; then
+ :
+ else
+ # the above command should be used before it gets too long
+ oldobjs=$objlist
+ if test "$obj" = "$last_oldobj" ; then
+ RANLIB=$save_RANLIB
+ fi
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+ objlist=
+ fi
+ done
+ RANLIB=$save_RANLIB
+ oldobjs=$objlist
+ if test "X$oldobjs" = "X" ; then
+ eval cmds=\"\$concat_cmds\"
+ else
+ eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+ fi
+ fi
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ eval cmd=\"$cmd\"
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$generated"; then
+ $show "${rm}r$generated"
+ $run ${rm}r$generated
+ fi
+
+ # Now create the libtool archive.
+ case $output in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ $show "creating $output"
+
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ if test "$hardcode_automatic" = yes ; then
+ relink_command=
+ fi
+
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdependency_libs="$newdependency_libs $libdir/$name"
+ ;;
+ *) newdependency_libs="$newdependency_libs $deplib" ;;
+ esac
+ done
+ dependency_libs="$newdependency_libs"
+ newdlfiles=
+ for lib in $dlfiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlfiles="$newdlfiles $libdir/$name"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlprefiles="$newdlprefiles $libdir/$name"
+ done
+ dlprefiles="$newdlprefiles"
+ else
+ newdlfiles=
+ for lib in $dlfiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlfiles="$newdlfiles $abs"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlprefiles="$newdlprefiles $abs"
+ done
+ dlprefiles="$newdlprefiles"
+ fi
+ $rm $output
+ # place dlname in correct position for cygwin
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+ esac
+ $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+ if test "$installed" = no && test "$need_relink" = yes; then
+ $echo >> $output "\
+relink_command=\"$relink_command\""
+ fi
+ done
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+ $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+ ;;
+ esac
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool install mode
+ install)
+ modename="$modename: install"
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+ # Allow the use of GNU shtool's install command.
+ $echo "X$nonopt" | grep shtool > /dev/null; then
+ # Aesthetically quote it.
+ arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg=$nonopt
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest=$arg
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=yes ;;
+ -f)
+ case " $install_prog " in
+ *[\\\ /]cp\ *) ;;
+ *) prev=$arg ;;
+ esac
+ ;;
+ -g | -m | -o) prev=$arg ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*)
+ ;;
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest=$arg
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$modename: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$modename: no file or destination specified" 1>&2
+ else
+ $echo "$modename: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test "$#" -gt 2; then
+ $echo "$modename: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+ case $destdir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case $file in
+ *.lo) ;;
+ *)
+ $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case $file in
+ *.$libext)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ library_names=
+ old_library=
+ relink_command=
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+ # are installed to the same prefix.
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+ if test "$inst_prefix_dir" = "$destdir"; then
+ $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+ relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+ else
+ relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+ fi
+
+ $echo "$modename: warning: relinking \`$file'" 1>&2
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ srcname="$realname"
+ test -n "$relink_command" && srcname="$realname"T
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$srcname $destdir/$realname"
+ $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+ if test -n "$stripme" && test -n "$striplib"; then
+ $show "$striplib $destdir/$realname"
+ $run eval "$striplib $destdir/$realname" || exit $?
+ fi
+
+ if test "$#" -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ # Try `ln -sf' first, because the `ln' binary might depend on
+ # the symlink we replace! Solaris /bin/ln does not understand -f,
+ # so we also need to try rm && ln -s.
+ for linkname
+ do
+ if test "$linkname" != "$realname"; then
+ $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+ $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+ fi
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ cmds=$postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ instname="$dir/$name"i
+ $show "$install_prog $instname $destdir/$name"
+ $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case $destfile in
+ *.lo)
+ staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+ ;;
+ *.$objext)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # If the file is missing, and there is a .exe on the end, strip it
+ # because it is most likely a libtool script we actually want to
+ # install
+ stripped_ext=""
+ case $file in
+ *.exe)
+ if test ! -f "$file"; then
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ stripped_ext=".exe"
+ fi
+ ;;
+ esac
+
+ # Do a test to see if this is really a libtool program.
+ case $host in
+ *cygwin*|*mingw*)
+ wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
+ ;;
+ *)
+ wrapper=$file
+ ;;
+ esac
+ if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+ notinst_deplibs=
+ relink_command=
+
+ # Note that it is not necessary on cygwin/mingw to append a dot to
+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
+ # `FILE.' does not work on cygwin managed mounts.
+ #
+ # If there is no directory component, then add one.
+ case $wrapper in
+ */* | *\\*) . ${wrapper} ;;
+ *) . ./${wrapper} ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$notinst_deplibs"; then
+ $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ finalize=yes
+ for lib in $notinst_deplibs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ relink_command=
+ # Note that it is not necessary on cygwin/mingw to append a dot to
+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
+ # `FILE.' does not work on cygwin managed mounts.
+ #
+ # If there is no directory component, then add one.
+ case $wrapper in
+ */* | *\\*) . ${wrapper} ;;
+ *) . ./${wrapper} ;;
+ esac
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir=`func_mktempdir`
+ file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ ${rm}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ $echo "$modename: warning: cannot relink \`$file'" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyway
+ case $install_prog,$host in
+ */usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
+ ;;
+ esac
+ ;;
+ esac
+ $show "$install_prog$stripme $file $destfile"
+ $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+ test -n "$outputname" && ${rm}r "$tmpdir"
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ if test -n "$stripme" && test -n "$old_striplib"; then
+ $show "$old_striplib $oldlib"
+ $run eval "$old_striplib $oldlib" || exit $?
+ fi
+
+ # Do each command in the postinstall commands.
+ cmds=$old_postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+ else
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool finish mode
+ finish)
+ modename="$modename: finish"
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ cmds=$finish_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || admincmds="$admincmds
+ $cmd"
+ done
+ IFS="$save_ifs"
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $run eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ test "$show" = : && exit $EXIT_SUCCESS
+
+ $echo "X----------------------------------------------------------------------" | $Xsed
+ $echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ $echo " $libdir"
+ done
+ $echo
+ $echo "If you ever happen to want to link against installed libraries"
+ $echo "in a given directory, LIBDIR, you must either use libtool, and"
+ $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+ $echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ $echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ $echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ $echo " - add LIBDIR to the \`$runpath_var' environment variable"
+ $echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ $echo " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ $echo " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ $echo
+ $echo "See any operating system documentation about shared libraries for"
+ $echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ $echo "X----------------------------------------------------------------------" | $Xsed
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool execute mode
+ execute)
+ modename="$modename: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$modename: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit $EXIT_FAILURE
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test ! -f "$file"; then
+ $echo "$modename: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ dir=
+ case $file in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case $file in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved environment variables
+ if test "${save_LC_ALL+set}" = set; then
+ LC_ALL="$save_LC_ALL"; export LC_ALL
+ fi
+ if test "${save_LANG+set}" = set; then
+ LANG="$save_LANG"; export LANG
+ fi
+
+ # Now prepare to actually exec the command.
+ exec_cmd="\$cmd$args"
+ else
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ fi
+ $echo "$cmd$args"
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool clean and uninstall mode
+ clean | uninstall)
+ modename="$modename: $mode"
+ rm="$nonopt"
+ files=
+ rmforce=
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ for arg
+ do
+ case $arg in
+ -f) rm="$rm $arg"; rmforce=yes ;;
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$modename: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ rmdirs=
+
+ origobjdir="$objdir"
+ for file in $files; do
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$file"; then
+ dir=.
+ objdir="$origobjdir"
+ else
+ objdir="$dir/$origobjdir"
+ fi
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ test "$mode" = uninstall && objdir="$dir"
+
+ # Remember objdir for removal later, being careful to avoid duplicates
+ if test "$mode" = clean; then
+ case " $rmdirs " in
+ *" $objdir "*) ;;
+ *) rmdirs="$rmdirs $objdir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if (test -L "$file") >/dev/null 2>&1 \
+ || (test -h "$file") >/dev/null 2>&1 \
+ || test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif test "$rmforce" = yes; then
+ continue
+ fi
+
+ rmfiles="$file"
+
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $objdir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+ case "$mode" in
+ clean)
+ case " $library_names " in
+ # " " in the beginning catches empty $dlname
+ *" $dlname "*) ;;
+ *) rmfiles="$rmfiles $objdir/$dlname" ;;
+ esac
+ test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+ ;;
+ uninstall)
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ cmds=$postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ cmds=$old_postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+ # FIXME: should reinstall the best remaining shared library.
+ ;;
+ esac
+ fi
+ ;;
+
+ *.lo)
+ # Possibly a libtool object, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+
+ # Read the .lo file
+ . $dir/$name
+
+ # Add PIC object to the list of files to remove.
+ if test -n "$pic_object" \
+ && test "$pic_object" != none; then
+ rmfiles="$rmfiles $dir/$pic_object"
+ fi
+
+ # Add non-PIC object to the list of files to remove.
+ if test -n "$non_pic_object" \
+ && test "$non_pic_object" != none; then
+ rmfiles="$rmfiles $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test "$mode" = clean ; then
+ noexename=$name
+ case $file in
+ *.exe)
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ noexename=`$echo $name|${SED} 's,.exe$,,'`
+ # $file with .exe has already been added to rmfiles,
+ # add $file without .exe
+ rmfiles="$rmfiles $file"
+ ;;
+ esac
+ # Do a test to see if this is a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ relink_command=
+ . $dir/$noexename
+
+ # note $name still contains .exe if it was in $file originally
+ # as does the version of $file that was added into $rmfiles
+ rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+ if test "$fast_install" = yes && test -n "$relink_command"; then
+ rmfiles="$rmfiles $objdir/lt-$name"
+ fi
+ if test "X$noexename" != "X$name" ; then
+ rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles || exit_status=1
+ done
+ objdir="$origobjdir"
+
+ # Try to remove the ${objdir}s in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ $show "rmdir $dir"
+ $run rmdir $dir >/dev/null 2>&1
+ fi
+ done
+
+ exit $exit_status
+ ;;
+
+ "")
+ $echo "$modename: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test -z "$exec_cmd"; then
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+ eval exec $exec_cmd
+ exit $EXIT_FAILURE
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+-n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --tag=TAG use configuration variables from tag TAG
+ --version print version information
+
+MODE must be one of the following:
+
+ clean remove files from the build directory
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE.
+
+Report bugs to <bug-libtool@gnu.org>."
+ exit $EXIT_SUCCESS
+ ;;
+
+clean)
+ $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+compile)
+ $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -prefer-pic try to building PIC objects only
+ -prefer-non-pic try to building non-PIC objects only
+ -static always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+execute)
+ $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+finish)
+ $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+install)
+ $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+link)
+ $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -objectlist FILE Use a list of object files found in FILE to specify objects
+ -precious-files-regex REGEX
+ don't remove output files matching REGEX
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -static do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+uninstall)
+ $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+*)
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+esac
+
+$echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit $?
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries. Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them. This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration. But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+disable_libs=shared
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+disable_libs=static
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/tools/build/v2/engine/boehm_gc/mach_dep.c b/tools/build/v2/engine/boehm_gc/mach_dep.c
new file mode 100644
index 0000000000..4f05843c63
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/mach_dep.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, November 17, 1995 12:13 pm PST */
+# include "private/gc_priv.h"
+# include <stdio.h>
+# include <setjmp.h>
+# if defined(OS2) || defined(CX_UX)
+# define _setjmp(b) setjmp(b)
+# define _longjmp(b,v) longjmp(b,v)
+# endif
+# ifdef AMIGA
+# ifndef __GNUC__
+# include <dos.h>
+# else
+# include <machine/reg.h>
+# endif
+# endif
+
+#if defined(__MWERKS__) && !defined(POWERPC)
+
+asm static void PushMacRegisters()
+{
+ sub.w #4,sp // reserve space for one parameter.
+ move.l a2,(sp)
+ jsr GC_push_one
+ move.l a3,(sp)
+ jsr GC_push_one
+ move.l a4,(sp)
+ jsr GC_push_one
+# if !__option(a6frames)
+ // <pcb> perhaps a6 should be pushed if stack frames are not being used.
+ move.l a6,(sp)
+ jsr GC_push_one
+# endif
+ // skip a5 (globals), a6 (frame pointer), and a7 (stack pointer)
+ move.l d2,(sp)
+ jsr GC_push_one
+ move.l d3,(sp)
+ jsr GC_push_one
+ move.l d4,(sp)
+ jsr GC_push_one
+ move.l d5,(sp)
+ jsr GC_push_one
+ move.l d6,(sp)
+ jsr GC_push_one
+ move.l d7,(sp)
+ jsr GC_push_one
+ add.w #4,sp // fix stack.
+ rts
+}
+
+#endif /* __MWERKS__ */
+
+# if defined(SPARC) || defined(IA64)
+ /* Value returned from register flushing routine; either sp (SPARC) */
+ /* or ar.bsp (IA64) */
+ ptr_t GC_save_regs_ret_val;
+# endif
+
+/* Routine to mark from registers that are preserved by the C compiler. */
+/* This must be ported to every new architecture. It is noe optional, */
+/* and should not be used on platforms that are either UNIX-like, or */
+/* require thread support. */
+
+#undef HAVE_PUSH_REGS
+
+#if defined(USE_ASM_PUSH_REGS)
+# define HAVE_PUSH_REGS
+#else /* No asm implementation */
+void GC_push_regs()
+{
+# if defined(M68K) && defined(AMIGA)
+ /* AMIGA - could be replaced by generic code */
+ /* a0, a1, d0 and d1 are caller save */
+
+# ifdef __GNUC__
+ asm("subq.w &0x4,%sp"); /* allocate word on top of stack */
+
+ asm("mov.l %a2,(%sp)"); asm("jsr _GC_push_one");
+ asm("mov.l %a3,(%sp)"); asm("jsr _GC_push_one");
+ asm("mov.l %a4,(%sp)"); asm("jsr _GC_push_one");
+ asm("mov.l %a5,(%sp)"); asm("jsr _GC_push_one");
+ asm("mov.l %a6,(%sp)"); asm("jsr _GC_push_one");
+ /* Skip frame pointer and stack pointer */
+ asm("mov.l %d2,(%sp)"); asm("jsr _GC_push_one");
+ asm("mov.l %d3,(%sp)"); asm("jsr _GC_push_one");
+ asm("mov.l %d4,(%sp)"); asm("jsr _GC_push_one");
+ asm("mov.l %d5,(%sp)"); asm("jsr _GC_push_one");
+ asm("mov.l %d6,(%sp)"); asm("jsr _GC_push_one");
+ asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one");
+
+ asm("addq.w &0x4,%sp"); /* put stack back where it was */
+# define HAVE_PUSH_REGS
+# else /* !__GNUC__ */
+ GC_push_one(getreg(REG_A2));
+ GC_push_one(getreg(REG_A3));
+# ifndef __SASC
+ /* Can probably be changed to #if 0 -Kjetil M. (a4=globals)*/
+ GC_push_one(getreg(REG_A4));
+# endif
+ GC_push_one(getreg(REG_A5));
+ GC_push_one(getreg(REG_A6));
+ /* Skip stack pointer */
+ GC_push_one(getreg(REG_D2));
+ GC_push_one(getreg(REG_D3));
+ GC_push_one(getreg(REG_D4));
+ GC_push_one(getreg(REG_D5));
+ GC_push_one(getreg(REG_D6));
+ GC_push_one(getreg(REG_D7));
+# define HAVE_PUSH_REGS
+# endif /* !__GNUC__ */
+# endif /* AMIGA */
+
+# if defined(M68K) && defined(MACOS)
+# if defined(THINK_C)
+# define PushMacReg(reg) \
+ move.l reg,(sp) \
+ jsr GC_push_one
+ asm {
+ sub.w #4,sp ; reserve space for one parameter.
+ PushMacReg(a2);
+ PushMacReg(a3);
+ PushMacReg(a4);
+ ; skip a5 (globals), a6 (frame pointer), and a7 (stack pointer)
+ PushMacReg(d2);
+ PushMacReg(d3);
+ PushMacReg(d4);
+ PushMacReg(d5);
+ PushMacReg(d6);
+ PushMacReg(d7);
+ add.w #4,sp ; fix stack.
+ }
+# define HAVE_PUSH_REGS
+# undef PushMacReg
+# endif /* THINK_C */
+# if defined(__MWERKS__)
+ PushMacRegisters();
+# define HAVE_PUSH_REGS
+# endif /* __MWERKS__ */
+# endif /* MACOS */
+}
+#endif /* !USE_ASM_PUSH_REGS */
+
+#if defined(HAVE_PUSH_REGS) && defined(THREADS)
+# error GC_push_regs cannot be used with threads
+ /* Would fail for GC_do_blocking. There are probably other safety */
+ /* issues. */
+# undef HAVE_PUSH_REGS
+#endif
+
+#if !defined(HAVE_PUSH_REGS) && defined(UNIX_LIKE)
+# include <ucontext.h>
+#endif
+
+/* Ensure that either registers are pushed, or callee-save registers */
+/* are somewhere on the stack, and then call fn(arg, ctxt). */
+/* ctxt is either a pointer to a ucontext_t we generated, or NULL. */
+void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
+ ptr_t arg)
+{
+ word dummy;
+ void * context = 0;
+
+# if defined(HAVE_PUSH_REGS)
+ GC_push_regs();
+# elif defined(UNIX_LIKE) && !defined(DARWIN) && !defined(ARM32)
+ /* Older versions of Darwin seem to lack getcontext(). */
+ /* ARM Linux often doesn't support a real getcontext(). */
+ ucontext_t ctxt;
+ if (getcontext(&ctxt) < 0)
+ ABORT ("Getcontext failed: Use another register retrieval method?");
+ context = &ctxt;
+# if defined(SPARC) || defined(IA64)
+ /* On a register window machine, we need to save register */
+ /* contents on the stack for this to work. This may already be */
+ /* subsumed by the getcontext() call. */
+ {
+ GC_save_regs_ret_val = GC_save_regs_in_stack();
+ }
+# endif /* register windows. */
+# elif defined(HAVE_BUILTIN_UNWIND_INIT)
+ /* This was suggested by Richard Henderson as the way to */
+ /* force callee-save registers and register windows onto */
+ /* the stack. */
+ __builtin_unwind_init();
+# else /* !HAVE_BUILTIN_UNWIND_INIT && !UNIX_LIKE */
+ /* && !HAVE_PUSH_REGS */
+ /* Generic code */
+ /* The idea is due to Parag Patel at HP. */
+ /* We're not sure whether he would like */
+ /* to be he acknowledged for it or not. */
+ jmp_buf regs;
+ register word * i = (word *) regs;
+ register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
+
+ /* Setjmp doesn't always clear all of the buffer. */
+ /* That tends to preserve garbage. Clear it. */
+ for (; (char *)i < lim; i++) {
+ *i = 0;
+ }
+# if defined(MSWIN32) || defined(MSWINCE) \
+ || defined(UTS4) || defined(LINUX) || defined(EWS4800)
+ (void) setjmp(regs);
+# else
+ (void) _setjmp(regs);
+ /* We don't want to mess with signals. According to */
+ /* SUSV3, setjmp() may or may not save signal mask. */
+ /* _setjmp won't, but is less portable. */
+# endif
+# endif /* !HAVE_PUSH_REGS ... */
+ fn(arg, context);
+ /* Strongly discourage the compiler from treating the above */
+ /* as a tail-call, since that would pop the register */
+ /* contents before we get a chance to look at them. */
+ GC_noop1((word)(&dummy));
+}
+
+void GC_push_regs_and_stack(ptr_t cold_gc_frame)
+{
+ GC_with_callee_saves_pushed(GC_push_current_stack, cold_gc_frame);
+}
+
+#if defined(ASM_CLEAR_CODE)
+# ifdef LINT
+ /*ARGSUSED*/
+ ptr_t GC_clear_stack_inner(arg, limit)
+ ptr_t arg; word limit;
+ { return(arg); }
+ /* The real version is in a .S file */
+# endif
+#endif /* ASM_CLEAR_CODE */
diff --git a/tools/build/v2/engine/boehm_gc/malloc.c b/tools/build/v2/engine/boehm_gc/malloc.c
new file mode 100644
index 0000000000..94032640e6
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/malloc.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "private/gc_priv.h"
+
+extern void * GC_clear_stack(void *); /* in misc.c, behaves like identity */
+void GC_extend_size_map(size_t); /* in misc.c. */
+
+/* Allocate reclaim list for kind: */
+/* Return TRUE on success */
+GC_bool GC_alloc_reclaim_list(struct obj_kind *kind)
+{
+ struct hblk ** result = (struct hblk **)
+ GC_scratch_alloc((MAXOBJGRANULES+1) * sizeof(struct hblk *));
+ if (result == 0) return(FALSE);
+ BZERO(result, (MAXOBJGRANULES+1)*sizeof(struct hblk *));
+ kind -> ok_reclaim_list = result;
+ return(TRUE);
+}
+
+/* Allocate a large block of size lb bytes. */
+/* The block is not cleared. */
+/* Flags is 0 or IGNORE_OFF_PAGE. */
+/* We hold the allocation lock. */
+/* EXTRA_BYTES were already added to lb. */
+ptr_t GC_alloc_large(size_t lb, int k, unsigned flags)
+{
+ struct hblk * h;
+ word n_blocks;
+ ptr_t result;
+
+ /* Round up to a multiple of a granule. */
+ lb = (lb + GRANULE_BYTES - 1) & ~(GRANULE_BYTES - 1);
+ n_blocks = OBJ_SZ_TO_BLOCKS(lb);
+ if (!GC_is_initialized) GC_init_inner();
+ /* Do our share of marking work */
+ if(GC_incremental && !GC_dont_gc)
+ GC_collect_a_little_inner((int)n_blocks);
+ h = GC_allochblk(lb, k, flags);
+# ifdef USE_MUNMAP
+ if (0 == h) {
+ GC_merge_unmapped();
+ h = GC_allochblk(lb, k, flags);
+ }
+# endif
+ while (0 == h && GC_collect_or_expand(n_blocks, (flags != 0))) {
+ h = GC_allochblk(lb, k, flags);
+ }
+ if (h == 0) {
+ result = 0;
+ } else {
+ size_t total_bytes = n_blocks * HBLKSIZE;
+ if (n_blocks > 1) {
+ GC_large_allocd_bytes += total_bytes;
+ if (GC_large_allocd_bytes > GC_max_large_allocd_bytes)
+ GC_max_large_allocd_bytes = GC_large_allocd_bytes;
+ }
+ result = h -> hb_body;
+ }
+ return result;
+}
+
+
+/* Allocate a large block of size lb bytes. Clear if appropriate. */
+/* We hold the allocation lock. */
+/* EXTRA_BYTES were already added to lb. */
+ptr_t GC_alloc_large_and_clear(size_t lb, int k, unsigned flags)
+{
+ ptr_t result = GC_alloc_large(lb, k, flags);
+ word n_blocks = OBJ_SZ_TO_BLOCKS(lb);
+
+ if (0 == result) return 0;
+ if (GC_debugging_started || GC_obj_kinds[k].ok_init) {
+ /* Clear the whole block, in case of GC_realloc call. */
+ BZERO(result, n_blocks * HBLKSIZE);
+ }
+ return result;
+}
+
+/* allocate lb bytes for an object of kind k. */
+/* Should not be used to directly to allocate */
+/* objects such as STUBBORN objects that */
+/* require special handling on allocation. */
+/* First a version that assumes we already */
+/* hold lock: */
+void * GC_generic_malloc_inner(size_t lb, int k)
+{
+ void *op;
+
+ if(SMALL_OBJ(lb)) {
+ struct obj_kind * kind = GC_obj_kinds + k;
+ size_t lg = GC_size_map[lb];
+ void ** opp = &(kind -> ok_freelist[lg]);
+
+ if( (op = *opp) == 0 ) {
+ if (GC_size_map[lb] == 0) {
+ if (!GC_is_initialized) GC_init_inner();
+ if (GC_size_map[lb] == 0) GC_extend_size_map(lb);
+ return(GC_generic_malloc_inner(lb, k));
+ }
+ if (kind -> ok_reclaim_list == 0) {
+ if (!GC_alloc_reclaim_list(kind)) goto out;
+ }
+ op = GC_allocobj(lg, k);
+ if (op == 0) goto out;
+ }
+ *opp = obj_link(op);
+ obj_link(op) = 0;
+ GC_bytes_allocd += GRANULES_TO_BYTES(lg);
+ } else {
+ op = (ptr_t)GC_alloc_large_and_clear(ADD_SLOP(lb), k, 0);
+ GC_bytes_allocd += lb;
+ }
+
+out:
+ return op;
+}
+
+/* Allocate a composite object of size n bytes. The caller guarantees */
+/* that pointers past the first page are not relevant. Caller holds */
+/* allocation lock. */
+void * GC_generic_malloc_inner_ignore_off_page(size_t lb, int k)
+{
+ word lb_adjusted;
+ void * op;
+
+ if (lb <= HBLKSIZE)
+ return(GC_generic_malloc_inner(lb, k));
+ lb_adjusted = ADD_SLOP(lb);
+ op = GC_alloc_large_and_clear(lb_adjusted, k, IGNORE_OFF_PAGE);
+ GC_bytes_allocd += lb_adjusted;
+ return op;
+}
+
+void * GC_generic_malloc(size_t lb, int k)
+{
+ void * result;
+ DCL_LOCK_STATE;
+
+ if (GC_have_errors) GC_print_all_errors();
+ GC_INVOKE_FINALIZERS();
+ if (SMALL_OBJ(lb)) {
+ LOCK();
+ result = GC_generic_malloc_inner((word)lb, k);
+ UNLOCK();
+ } else {
+ size_t lw;
+ size_t lb_rounded;
+ word n_blocks;
+ GC_bool init;
+ lw = ROUNDED_UP_WORDS(lb);
+ lb_rounded = WORDS_TO_BYTES(lw);
+ n_blocks = OBJ_SZ_TO_BLOCKS(lb_rounded);
+ init = GC_obj_kinds[k].ok_init;
+ LOCK();
+ result = (ptr_t)GC_alloc_large(lb_rounded, k, 0);
+ if (0 != result) {
+ if (GC_debugging_started) {
+ BZERO(result, n_blocks * HBLKSIZE);
+ } else {
+# ifdef THREADS
+ /* Clear any memory that might be used for GC descriptors */
+ /* before we release the lock. */
+ ((word *)result)[0] = 0;
+ ((word *)result)[1] = 0;
+ ((word *)result)[lw-1] = 0;
+ ((word *)result)[lw-2] = 0;
+# endif
+ }
+ }
+ GC_bytes_allocd += lb_rounded;
+ UNLOCK();
+ if (init && !GC_debugging_started && 0 != result) {
+ BZERO(result, n_blocks * HBLKSIZE);
+ }
+ }
+ if (0 == result) {
+ return((*GC_oom_fn)(lb));
+ } else {
+ return(result);
+ }
+}
+
+
+#define GENERAL_MALLOC(lb,k) \
+ GC_clear_stack(GC_generic_malloc(lb, k))
+/* We make the GC_clear_stack_call a tail call, hoping to get more of */
+/* the stack. */
+
+/* Allocate lb bytes of atomic (pointerfree) data */
+#ifdef THREAD_LOCAL_ALLOC
+ void * GC_core_malloc_atomic(size_t lb)
+#else
+ void * GC_malloc_atomic(size_t lb)
+#endif
+{
+ void *op;
+ void ** opp;
+ size_t lg;
+ DCL_LOCK_STATE;
+
+ if(SMALL_OBJ(lb)) {
+ lg = GC_size_map[lb];
+ opp = &(GC_aobjfreelist[lg]);
+ LOCK();
+ if( EXPECT((op = *opp) == 0, 0) ) {
+ UNLOCK();
+ return(GENERAL_MALLOC((word)lb, PTRFREE));
+ }
+ *opp = obj_link(op);
+ GC_bytes_allocd += GRANULES_TO_BYTES(lg);
+ UNLOCK();
+ return((void *) op);
+ } else {
+ return(GENERAL_MALLOC((word)lb, PTRFREE));
+ }
+}
+
+/* provide a version of strdup() that uses the collector to allocate the
+ copy of the string */
+# ifdef __STDC__
+ char *GC_strdup(const char *s)
+# else
+ char *GC_strdup(s)
+ char *s;
+#endif
+{
+ char *copy;
+
+ if (s == NULL) return NULL;
+ if ((copy = GC_malloc_atomic(strlen(s) + 1)) == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ strcpy(copy, s);
+ return copy;
+}
+
+/* Allocate lb bytes of composite (pointerful) data */
+#ifdef THREAD_LOCAL_ALLOC
+ void * GC_core_malloc(size_t lb)
+#else
+ void * GC_malloc(size_t lb)
+#endif
+{
+ void *op;
+ void **opp;
+ size_t lg;
+ DCL_LOCK_STATE;
+
+ if(SMALL_OBJ(lb)) {
+ lg = GC_size_map[lb];
+ opp = (void **)&(GC_objfreelist[lg]);
+ LOCK();
+ if( EXPECT((op = *opp) == 0, 0) ) {
+ UNLOCK();
+ return(GENERAL_MALLOC((word)lb, NORMAL));
+ }
+ /* See above comment on signals. */
+ GC_ASSERT(0 == obj_link(op)
+ || (word)obj_link(op)
+ <= (word)GC_greatest_plausible_heap_addr
+ && (word)obj_link(op)
+ >= (word)GC_least_plausible_heap_addr);
+ *opp = obj_link(op);
+ obj_link(op) = 0;
+ GC_bytes_allocd += GRANULES_TO_BYTES(lg);
+ UNLOCK();
+ return op;
+ } else {
+ return(GENERAL_MALLOC(lb, NORMAL));
+ }
+}
+
+# ifdef REDIRECT_MALLOC
+
+/* Avoid unnecessary nested procedure calls here, by #defining some */
+/* malloc replacements. Otherwise we end up saving a */
+/* meaningless return address in the object. It also speeds things up, */
+/* but it is admittedly quite ugly. */
+# ifdef GC_ADD_CALLER
+# define RA GC_RETURN_ADDR,
+# else
+# define RA
+# endif
+# define GC_debug_malloc_replacement(lb) \
+ GC_debug_malloc(lb, RA "unknown", 0)
+
+void * malloc(size_t lb)
+ {
+ /* It might help to manually inline the GC_malloc call here. */
+ /* But any decent compiler should reduce the extra procedure call */
+ /* to at most a jump instruction in this case. */
+# if defined(I386) && defined(GC_SOLARIS_THREADS)
+ /*
+ * Thread initialisation can call malloc before
+ * we're ready for it.
+ * It's not clear that this is enough to help matters.
+ * The thread implementation may well call malloc at other
+ * inopportune times.
+ */
+ if (!GC_is_initialized) return sbrk(lb);
+# endif /* I386 && GC_SOLARIS_THREADS */
+ return((void *)REDIRECT_MALLOC(lb));
+ }
+
+#ifdef GC_LINUX_THREADS
+ static ptr_t GC_libpthread_start = 0;
+ static ptr_t GC_libpthread_end = 0;
+ static ptr_t GC_libld_start = 0;
+ static ptr_t GC_libld_end = 0;
+ extern GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp);
+ /* From os_dep.c */
+
+ void GC_init_lib_bounds(void)
+ {
+ if (GC_libpthread_start != 0) return;
+ if (!GC_text_mapping("/lib/tls/libpthread-",
+ &GC_libpthread_start, &GC_libpthread_end)
+ && !GC_text_mapping("/lib/libpthread-",
+ &GC_libpthread_start, &GC_libpthread_end)) {
+ WARN("Failed to find libpthread.so text mapping: Expect crash\n", 0);
+ /* This might still work with some versions of libpthread, */
+ /* so we don't abort. Perhaps we should. */
+ /* Generate message only once: */
+ GC_libpthread_start = (ptr_t)1;
+ }
+ if (!GC_text_mapping("/lib/ld-", &GC_libld_start, &GC_libld_end)) {
+ WARN("Failed to find ld.so text mapping: Expect crash\n", 0);
+ }
+ }
+#endif
+
+void * calloc(size_t n, size_t lb)
+{
+# if defined(GC_LINUX_THREADS) && !defined(USE_PROC_FOR_LIBRARIES)
+ /* libpthread allocated some memory that is only pointed to by */
+ /* mmapped thread stacks. Make sure it's not collectable. */
+ {
+ static GC_bool lib_bounds_set = FALSE;
+ ptr_t caller = (ptr_t)__builtin_return_address(0);
+ /* This test does not need to ensure memory visibility, since */
+ /* the bounds will be set when/if we create another thread. */
+ if (!lib_bounds_set) {
+ GC_init_lib_bounds();
+ lib_bounds_set = TRUE;
+ }
+ if (caller >= GC_libpthread_start && caller < GC_libpthread_end
+ || (caller >= GC_libld_start && caller < GC_libld_end))
+ return GC_malloc_uncollectable(n*lb);
+ /* The two ranges are actually usually adjacent, so there may */
+ /* be a way to speed this up. */
+ }
+# endif
+ return((void *)REDIRECT_MALLOC(n*lb));
+}
+
+#ifndef strdup
+# include <string.h>
+ char *strdup(const char *s)
+ {
+ size_t len = strlen(s) + 1;
+ char * result = ((char *)REDIRECT_MALLOC(len+1));
+ if (result == 0) {
+ errno = ENOMEM;
+ return 0;
+ }
+ BCOPY(s, result, len+1);
+ return result;
+ }
+#endif /* !defined(strdup) */
+ /* If strdup is macro defined, we assume that it actually calls malloc, */
+ /* and thus the right thing will happen even without overriding it. */
+ /* This seems to be true on most Linux systems. */
+
+#undef GC_debug_malloc_replacement
+
+# endif /* REDIRECT_MALLOC */
+
+/* Explicitly deallocate an object p. */
+void GC_free(void * p)
+{
+ struct hblk *h;
+ hdr *hhdr;
+ size_t sz; /* In bytes */
+ size_t ngranules; /* sz in granules */
+ void **flh;
+ int knd;
+ struct obj_kind * ok;
+ DCL_LOCK_STATE;
+
+ if (p == 0) return;
+ /* Required by ANSI. It's not my fault ... */
+ h = HBLKPTR(p);
+ hhdr = HDR(h);
+ sz = hhdr -> hb_sz;
+ ngranules = BYTES_TO_GRANULES(sz);
+ GC_ASSERT(GC_base(p) == p);
+# if defined(REDIRECT_MALLOC) && \
+ (defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \
+ || defined(MSWIN32))
+ /* For Solaris, we have to redirect malloc calls during */
+ /* initialization. For the others, this seems to happen */
+ /* implicitly. */
+ /* Don't try to deallocate that memory. */
+ if (0 == hhdr) return;
+# endif
+ knd = hhdr -> hb_obj_kind;
+ ok = &GC_obj_kinds[knd];
+ if (EXPECT((ngranules <= MAXOBJGRANULES), 1)) {
+ LOCK();
+ GC_bytes_freed += sz;
+ if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz;
+ /* Its unnecessary to clear the mark bit. If the */
+ /* object is reallocated, it doesn't matter. O.w. the */
+ /* collector will do it, since it's on a free list. */
+ if (ok -> ok_init) {
+ BZERO((word *)p + 1, sz-sizeof(word));
+ }
+ flh = &(ok -> ok_freelist[ngranules]);
+ obj_link(p) = *flh;
+ *flh = (ptr_t)p;
+ UNLOCK();
+ } else {
+ LOCK();
+ GC_bytes_freed += sz;
+ if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz;
+ GC_freehblk(h);
+ UNLOCK();
+ }
+}
+
+/* Explicitly deallocate an object p when we already hold lock. */
+/* Only used for internally allocated objects, so we can take some */
+/* shortcuts. */
+#ifdef THREADS
+void GC_free_inner(void * p)
+{
+ struct hblk *h;
+ hdr *hhdr;
+ size_t sz; /* bytes */
+ size_t ngranules; /* sz in granules */
+ void ** flh;
+ int knd;
+ struct obj_kind * ok;
+ DCL_LOCK_STATE;
+
+ h = HBLKPTR(p);
+ hhdr = HDR(h);
+ knd = hhdr -> hb_obj_kind;
+ sz = hhdr -> hb_sz;
+ ngranules = BYTES_TO_GRANULES(sz);
+ ok = &GC_obj_kinds[knd];
+ if (ngranules <= MAXOBJGRANULES) {
+ GC_bytes_freed += sz;
+ if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz;
+ if (ok -> ok_init) {
+ BZERO((word *)p + 1, sz-sizeof(word));
+ }
+ flh = &(ok -> ok_freelist[ngranules]);
+ obj_link(p) = *flh;
+ *flh = (ptr_t)p;
+ } else {
+ GC_bytes_freed += sz;
+ if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz;
+ GC_freehblk(h);
+ }
+}
+#endif /* THREADS */
+
+# if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE)
+# define REDIRECT_FREE GC_free
+# endif
+# ifdef REDIRECT_FREE
+ void free(void * p)
+ {
+# if defined(GC_LINUX_THREADS) && !defined(USE_PROC_FOR_LIBRARIES)
+ {
+ /* Don't bother with initialization checks. If nothing */
+ /* has been initialized, the check fails, and that's safe, */
+ /* since we haven't allocated uncollectable objects either. */
+ ptr_t caller = (ptr_t)__builtin_return_address(0);
+ /* This test does not need to ensure memory visibility, since */
+ /* the bounds will be set when/if we create another thread. */
+ if (caller >= GC_libpthread_start && caller > GC_libpthread_end) {
+ GC_free(p);
+ return;
+ }
+ }
+# endif
+# ifndef IGNORE_FREE
+ REDIRECT_FREE(p);
+# endif
+ }
+# endif /* REDIRECT_MALLOC */
diff --git a/tools/build/v2/engine/boehm_gc/mallocx.c b/tools/build/v2/engine/boehm_gc/mallocx.c
new file mode 100644
index 0000000000..4649b73ac9
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/mallocx.c
@@ -0,0 +1,574 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/*
+ * These are extra allocation routines which are likely to be less
+ * frequently used than those in malloc.c. They are separate in the
+ * hope that the .o file will be excluded from statically linked
+ * executables. We should probably break this up further.
+ */
+
+#include <stdio.h>
+#include "private/gc_priv.h"
+
+/* extern ptr_t GC_clear_stack(); /* in misc.c, behaves like identity */
+void GC_extend_size_map(); /* in misc.c. */
+GC_bool GC_alloc_reclaim_list(); /* in malloc.c */
+
+/* Some externally visible but unadvertised variables to allow access to */
+/* free lists from inlined allocators without including gc_priv.h */
+/* or introducing dependencies on internal data structure layouts. */
+void ** const GC_objfreelist_ptr = GC_objfreelist;
+void ** const GC_aobjfreelist_ptr = GC_aobjfreelist;
+void ** const GC_uobjfreelist_ptr = GC_uobjfreelist;
+# ifdef ATOMIC_UNCOLLECTABLE
+ void ** const GC_auobjfreelist_ptr = GC_auobjfreelist;
+# endif
+
+
+void * GC_generic_or_special_malloc(size_t lb, int knd)
+{
+ switch(knd) {
+# ifdef STUBBORN_ALLOC
+ case STUBBORN:
+ return(GC_malloc_stubborn((size_t)lb));
+# endif
+ case PTRFREE:
+ return(GC_malloc_atomic((size_t)lb));
+ case NORMAL:
+ return(GC_malloc((size_t)lb));
+ case UNCOLLECTABLE:
+ return(GC_malloc_uncollectable((size_t)lb));
+# ifdef ATOMIC_UNCOLLECTABLE
+ case AUNCOLLECTABLE:
+ return(GC_malloc_atomic_uncollectable((size_t)lb));
+# endif /* ATOMIC_UNCOLLECTABLE */
+ default:
+ return(GC_generic_malloc(lb,knd));
+ }
+}
+
+
+/* Change the size of the block pointed to by p to contain at least */
+/* lb bytes. The object may be (and quite likely will be) moved. */
+/* The kind (e.g. atomic) is the same as that of the old. */
+/* Shrinking of large blocks is not implemented well. */
+void * GC_realloc(void * p, size_t lb)
+{
+ struct hblk * h;
+ hdr * hhdr;
+ size_t sz; /* Current size in bytes */
+ size_t orig_sz; /* Original sz in bytes */
+ int obj_kind;
+
+ if (p == 0) return(GC_malloc(lb)); /* Required by ANSI */
+ h = HBLKPTR(p);
+ hhdr = HDR(h);
+ sz = hhdr -> hb_sz;
+ obj_kind = hhdr -> hb_obj_kind;
+ orig_sz = sz;
+
+ if (sz > MAXOBJBYTES) {
+ /* Round it up to the next whole heap block */
+ register word descr;
+
+ sz = (sz+HBLKSIZE-1) & (~HBLKMASK);
+ hhdr -> hb_sz = sz;
+ descr = GC_obj_kinds[obj_kind].ok_descriptor;
+ if (GC_obj_kinds[obj_kind].ok_relocate_descr) descr += sz;
+ hhdr -> hb_descr = descr;
+# ifdef MARK_BIT_PER_OBJ
+ GC_ASSERT(hhdr -> hb_inv_sz == LARGE_INV_SZ);
+# else
+ GC_ASSERT(hhdr -> hb_large_block &&
+ hhdr -> hb_map[ANY_INDEX] == 1);
+# endif
+ if (IS_UNCOLLECTABLE(obj_kind)) GC_non_gc_bytes += (sz - orig_sz);
+ /* Extra area is already cleared by GC_alloc_large_and_clear. */
+ }
+ if (ADD_SLOP(lb) <= sz) {
+ if (lb >= (sz >> 1)) {
+# ifdef STUBBORN_ALLOC
+ if (obj_kind == STUBBORN) GC_change_stubborn(p);
+# endif
+ if (orig_sz > lb) {
+ /* Clear unneeded part of object to avoid bogus pointer */
+ /* tracing. */
+ /* Safe for stubborn objects. */
+ BZERO(((ptr_t)p) + lb, orig_sz - lb);
+ }
+ return(p);
+ } else {
+ /* shrink */
+ void * result =
+ GC_generic_or_special_malloc((word)lb, obj_kind);
+
+ if (result == 0) return(0);
+ /* Could also return original object. But this */
+ /* gives the client warning of imminent disaster. */
+ BCOPY(p, result, lb);
+# ifndef IGNORE_FREE
+ GC_free(p);
+# endif
+ return(result);
+ }
+ } else {
+ /* grow */
+ void * result =
+ GC_generic_or_special_malloc((word)lb, obj_kind);
+
+ if (result == 0) return(0);
+ BCOPY(p, result, sz);
+# ifndef IGNORE_FREE
+ GC_free(p);
+# endif
+ return(result);
+ }
+}
+
+# if defined(REDIRECT_MALLOC) && !defined(REDIRECT_REALLOC)
+# define REDIRECT_REALLOC GC_realloc
+# endif
+
+# ifdef REDIRECT_REALLOC
+
+/* As with malloc, avoid two levels of extra calls here. */
+# ifdef GC_ADD_CALLER
+# define RA GC_RETURN_ADDR,
+# else
+# define RA
+# endif
+# define GC_debug_realloc_replacement(p, lb) \
+ GC_debug_realloc(p, lb, RA "unknown", 0)
+
+void * realloc(void * p, size_t lb)
+ {
+ return(REDIRECT_REALLOC(p, lb));
+ }
+
+# undef GC_debug_realloc_replacement
+# endif /* REDIRECT_REALLOC */
+
+
+/* Allocate memory such that only pointers to near the */
+/* beginning of the object are considered. */
+/* We avoid holding allocation lock while we clear memory. */
+void * GC_generic_malloc_ignore_off_page(size_t lb, int k)
+{
+ void *result;
+ size_t lw;
+ size_t lb_rounded;
+ word n_blocks;
+ GC_bool init;
+ DCL_LOCK_STATE;
+
+ if (SMALL_OBJ(lb))
+ return(GC_generic_malloc((word)lb, k));
+ lw = ROUNDED_UP_WORDS(lb);
+ lb_rounded = WORDS_TO_BYTES(lw);
+ n_blocks = OBJ_SZ_TO_BLOCKS(lb_rounded);
+ init = GC_obj_kinds[k].ok_init;
+ if (GC_have_errors) GC_print_all_errors();
+ GC_INVOKE_FINALIZERS();
+ LOCK();
+ result = (ptr_t)GC_alloc_large(ADD_SLOP(lb), k, IGNORE_OFF_PAGE);
+ if (0 != result) {
+ if (GC_debugging_started) {
+ BZERO(result, n_blocks * HBLKSIZE);
+ } else {
+# ifdef THREADS
+ /* Clear any memory that might be used for GC descriptors */
+ /* before we release the lock. */
+ ((word *)result)[0] = 0;
+ ((word *)result)[1] = 0;
+ ((word *)result)[lw-1] = 0;
+ ((word *)result)[lw-2] = 0;
+# endif
+ }
+ }
+ GC_bytes_allocd += lb_rounded;
+ UNLOCK();
+ if (0 == result) {
+ return((*GC_oom_fn)(lb));
+ } else {
+ if (init && !GC_debugging_started) {
+ BZERO(result, n_blocks * HBLKSIZE);
+ }
+ return(result);
+ }
+}
+
+void * GC_malloc_ignore_off_page(size_t lb)
+{
+ return((void *)GC_generic_malloc_ignore_off_page(lb, NORMAL));
+}
+
+void * GC_malloc_atomic_ignore_off_page(size_t lb)
+{
+ return((void *)GC_generic_malloc_ignore_off_page(lb, PTRFREE));
+}
+
+/* Increment GC_bytes_allocd from code that doesn't have direct access */
+/* to GC_arrays. */
+void GC_incr_bytes_allocd(size_t n)
+{
+ GC_bytes_allocd += n;
+}
+
+/* The same for GC_bytes_freed. */
+void GC_incr_bytes_freed(size_t n)
+{
+ GC_bytes_freed += n;
+}
+
+#if defined(THREADS)
+
+extern signed_word GC_bytes_found; /* Protected by GC lock. */
+
+#ifdef PARALLEL_MARK
+volatile signed_word GC_bytes_allocd_tmp = 0;
+ /* Number of bytes of memory allocated since */
+ /* we released the GC lock. Instead of */
+ /* reacquiring the GC lock just to add this in, */
+ /* we add it in the next time we reacquire */
+ /* the lock. (Atomically adding it doesn't */
+ /* work, since we would have to atomically */
+ /* update it in GC_malloc, which is too */
+ /* expensive.) */
+#endif /* PARALLEL_MARK */
+
+/* Return a list of 1 or more objects of the indicated size, linked */
+/* through the first word in the object. This has the advantage that */
+/* it acquires the allocation lock only once, and may greatly reduce */
+/* time wasted contending for the allocation lock. Typical usage would */
+/* be in a thread that requires many items of the same size. It would */
+/* keep its own free list in thread-local storage, and call */
+/* GC_malloc_many or friends to replenish it. (We do not round up */
+/* object sizes, since a call indicates the intention to consume many */
+/* objects of exactly this size.) */
+/* We assume that the size is a multiple of GRANULE_BYTES. */
+/* We return the free-list by assigning it to *result, since it is */
+/* not safe to return, e.g. a linked list of pointer-free objects, */
+/* since the collector would not retain the entire list if it were */
+/* invoked just as we were returning. */
+/* Note that the client should usually clear the link field. */
+void GC_generic_malloc_many(size_t lb, int k, void **result)
+{
+void *op;
+void *p;
+void **opp;
+size_t lw; /* Length in words. */
+size_t lg; /* Length in granules. */
+signed_word my_bytes_allocd = 0;
+struct obj_kind * ok = &(GC_obj_kinds[k]);
+DCL_LOCK_STATE;
+
+ GC_ASSERT((lb & (GRANULE_BYTES-1)) == 0);
+ if (!SMALL_OBJ(lb)) {
+ op = GC_generic_malloc(lb, k);
+ if(0 != op) obj_link(op) = 0;
+ *result = op;
+ return;
+ }
+ lw = BYTES_TO_WORDS(lb);
+ lg = BYTES_TO_GRANULES(lb);
+ if (GC_have_errors) GC_print_all_errors();
+ GC_INVOKE_FINALIZERS();
+ LOCK();
+ if (!GC_is_initialized) GC_init_inner();
+ /* Do our share of marking work */
+ if (GC_incremental && !GC_dont_gc) {
+ ENTER_GC();
+ GC_collect_a_little_inner(1);
+ EXIT_GC();
+ }
+ /* First see if we can reclaim a page of objects waiting to be */
+ /* reclaimed. */
+ {
+ struct hblk ** rlh = ok -> ok_reclaim_list;
+ struct hblk * hbp;
+ hdr * hhdr;
+
+ rlh += lg;
+ while ((hbp = *rlh) != 0) {
+ hhdr = HDR(hbp);
+ *rlh = hhdr -> hb_next;
+ GC_ASSERT(hhdr -> hb_sz == lb);
+ hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
+# ifdef PARALLEL_MARK
+ {
+ signed_word my_bytes_allocd_tmp = GC_bytes_allocd_tmp;
+
+ GC_ASSERT(my_bytes_allocd_tmp >= 0);
+ /* We only decrement it while holding the GC lock. */
+ /* Thus we can't accidentally adjust it down in more */
+ /* than one thread simultaneously. */
+ if (my_bytes_allocd_tmp != 0) {
+ (void)AO_fetch_and_add(
+ (volatile AO_t *)(&GC_bytes_allocd_tmp),
+ (AO_t)(-my_bytes_allocd_tmp));
+ GC_bytes_allocd += my_bytes_allocd_tmp;
+ }
+ }
+ GC_acquire_mark_lock();
+ ++ GC_fl_builder_count;
+ UNLOCK();
+ GC_release_mark_lock();
+# endif
+ op = GC_reclaim_generic(hbp, hhdr, lb,
+ ok -> ok_init, 0, &my_bytes_allocd);
+ if (op != 0) {
+ /* We also reclaimed memory, so we need to adjust */
+ /* that count. */
+ /* This should be atomic, so the results may be */
+ /* inaccurate. */
+ GC_bytes_found += my_bytes_allocd;
+# ifdef PARALLEL_MARK
+ *result = op;
+ (void)AO_fetch_and_add(
+ (volatile AO_t *)(&GC_bytes_allocd_tmp),
+ (AO_t)(my_bytes_allocd));
+ GC_acquire_mark_lock();
+ -- GC_fl_builder_count;
+ if (GC_fl_builder_count == 0) GC_notify_all_builder();
+ GC_release_mark_lock();
+ (void) GC_clear_stack(0);
+ return;
+# else
+ GC_bytes_allocd += my_bytes_allocd;
+ goto out;
+# endif
+ }
+# ifdef PARALLEL_MARK
+ GC_acquire_mark_lock();
+ -- GC_fl_builder_count;
+ if (GC_fl_builder_count == 0) GC_notify_all_builder();
+ GC_release_mark_lock();
+ LOCK();
+ /* GC lock is needed for reclaim list access. We */
+ /* must decrement fl_builder_count before reaquiring GC */
+ /* lock. Hopefully this path is rare. */
+# endif
+ }
+ }
+ /* Next try to use prefix of global free list if there is one. */
+ /* We don't refill it, but we need to use it up before allocating */
+ /* a new block ourselves. */
+ opp = &(GC_obj_kinds[k].ok_freelist[lg]);
+ if ( (op = *opp) != 0 ) {
+ *opp = 0;
+ my_bytes_allocd = 0;
+ for (p = op; p != 0; p = obj_link(p)) {
+ my_bytes_allocd += lb;
+ if (my_bytes_allocd >= HBLKSIZE) {
+ *opp = obj_link(p);
+ obj_link(p) = 0;
+ break;
+ }
+ }
+ GC_bytes_allocd += my_bytes_allocd;
+ goto out;
+ }
+ /* Next try to allocate a new block worth of objects of this size. */
+ {
+ struct hblk *h = GC_allochblk(lb, k, 0);
+ if (h != 0) {
+ if (IS_UNCOLLECTABLE(k)) GC_set_hdr_marks(HDR(h));
+ GC_bytes_allocd += HBLKSIZE - HBLKSIZE % lb;
+# ifdef PARALLEL_MARK
+ GC_acquire_mark_lock();
+ ++ GC_fl_builder_count;
+ UNLOCK();
+ GC_release_mark_lock();
+# endif
+
+ op = GC_build_fl(h, lw, ok -> ok_init, 0);
+# ifdef PARALLEL_MARK
+ *result = op;
+ GC_acquire_mark_lock();
+ -- GC_fl_builder_count;
+ if (GC_fl_builder_count == 0) GC_notify_all_builder();
+ GC_release_mark_lock();
+ (void) GC_clear_stack(0);
+ return;
+# else
+ goto out;
+# endif
+ }
+ }
+
+ /* As a last attempt, try allocating a single object. Note that */
+ /* this may trigger a collection or expand the heap. */
+ op = GC_generic_malloc_inner(lb, k);
+ if (0 != op) obj_link(op) = 0;
+
+ out:
+ *result = op;
+ UNLOCK();
+ (void) GC_clear_stack(0);
+}
+
+void * GC_malloc_many(size_t lb)
+{
+ void *result;
+ GC_generic_malloc_many(((lb + EXTRA_BYTES + GRANULE_BYTES-1)
+ & ~(GRANULE_BYTES-1)),
+ NORMAL, &result);
+ return result;
+}
+
+/* Note that the "atomic" version of this would be unsafe, since the */
+/* links would not be seen by the collector. */
+# endif
+
+/* Allocate lb bytes of pointerful, traced, but not collectable data */
+void * GC_malloc_uncollectable(size_t lb)
+{
+ void *op;
+ void **opp;
+ size_t lg;
+ DCL_LOCK_STATE;
+
+ if( SMALL_OBJ(lb) ) {
+ if (EXTRA_BYTES != 0 && lb != 0) lb--;
+ /* We don't need the extra byte, since this won't be */
+ /* collected anyway. */
+ lg = GC_size_map[lb];
+ opp = &(GC_uobjfreelist[lg]);
+ LOCK();
+ if( (op = *opp) != 0 ) {
+ /* See above comment on signals. */
+ *opp = obj_link(op);
+ obj_link(op) = 0;
+ GC_bytes_allocd += GRANULES_TO_BYTES(lg);
+ /* Mark bit ws already set on free list. It will be */
+ /* cleared only temporarily during a collection, as a */
+ /* result of the normal free list mark bit clearing. */
+ GC_non_gc_bytes += GRANULES_TO_BYTES(lg);
+ UNLOCK();
+ } else {
+ UNLOCK();
+ op = (ptr_t)GC_generic_malloc((word)lb, UNCOLLECTABLE);
+ /* For small objects, the free lists are completely marked. */
+ }
+ GC_ASSERT(0 == op || GC_is_marked(op));
+ return((void *) op);
+ } else {
+ hdr * hhdr;
+
+ op = (ptr_t)GC_generic_malloc((word)lb, UNCOLLECTABLE);
+ if (0 == op) return(0);
+
+ GC_ASSERT(((word)op & (HBLKSIZE - 1)) == 0); /* large block */
+ hhdr = HDR((struct hbklk *)op);
+ /* We don't need the lock here, since we have an undisguised */
+ /* pointer. We do need to hold the lock while we adjust */
+ /* mark bits. */
+ lb = hhdr -> hb_sz;
+ LOCK();
+ set_mark_bit_from_hdr(hhdr, 0); /* Only object. */
+ GC_ASSERT(hhdr -> hb_n_marks == 0);
+ hhdr -> hb_n_marks = 1;
+ UNLOCK();
+ return((void *) op);
+ }
+}
+
+/* Not well tested nor integrated. */
+/* Debug version is tricky and currently missing. */
+#include <limits.h>
+
+void * GC_memalign(size_t align, size_t lb)
+{
+ size_t new_lb;
+ size_t offset;
+ ptr_t result;
+
+ if (align <= GRANULE_BYTES) return GC_malloc(lb);
+ if (align >= HBLKSIZE/2 || lb >= HBLKSIZE/2) {
+ if (align > HBLKSIZE) return GC_oom_fn(LONG_MAX-1024) /* Fail */;
+ return GC_malloc(lb <= HBLKSIZE? HBLKSIZE : lb);
+ /* Will be HBLKSIZE aligned. */
+ }
+ /* We could also try to make sure that the real rounded-up object size */
+ /* is a multiple of align. That would be correct up to HBLKSIZE. */
+ new_lb = lb + align - 1;
+ result = GC_malloc(new_lb);
+ offset = (word)result % align;
+ if (offset != 0) {
+ offset = align - offset;
+ if (!GC_all_interior_pointers) {
+ if (offset >= VALID_OFFSET_SZ) return GC_malloc(HBLKSIZE);
+ GC_register_displacement(offset);
+ }
+ }
+ result = (void *) ((ptr_t)result + offset);
+ GC_ASSERT((word)result % align == 0);
+ return result;
+}
+
+# ifdef ATOMIC_UNCOLLECTABLE
+/* Allocate lb bytes of pointerfree, untraced, uncollectable data */
+/* This is normally roughly equivalent to the system malloc. */
+/* But it may be useful if malloc is redefined. */
+void * GC_malloc_atomic_uncollectable(size_t lb)
+{
+ void *op;
+ void **opp;
+ size_t lg;
+ DCL_LOCK_STATE;
+
+ if( SMALL_OBJ(lb) ) {
+ if (EXTRA_BYTES != 0 && lb != 0) lb--;
+ /* We don't need the extra byte, since this won't be */
+ /* collected anyway. */
+ lg = GC_size_map[lb];
+ opp = &(GC_auobjfreelist[lg]);
+ LOCK();
+ if( (op = *opp) != 0 ) {
+ /* See above comment on signals. */
+ *opp = obj_link(op);
+ obj_link(op) = 0;
+ GC_bytes_allocd += GRANULES_TO_BYTES(lg);
+ /* Mark bit was already set while object was on free list. */
+ GC_non_gc_bytes += GRANULES_TO_BYTES(lg);
+ UNLOCK();
+ } else {
+ UNLOCK();
+ op = (ptr_t)GC_generic_malloc(lb, AUNCOLLECTABLE);
+ }
+ GC_ASSERT(0 == op || GC_is_marked(op));
+ return((void *) op);
+ } else {
+ hdr * hhdr;
+
+ op = (ptr_t)GC_generic_malloc(lb, AUNCOLLECTABLE);
+ if (0 == op) return(0);
+
+ GC_ASSERT(((word)op & (HBLKSIZE - 1)) == 0);
+ hhdr = HDR((struct hbklk *)op);
+ lb = hhdr -> hb_sz;
+
+ LOCK();
+ set_mark_bit_from_hdr(hhdr, 0); /* Only object. */
+ GC_ASSERT(hhdr -> hb_n_marks == 0);
+ hhdr -> hb_n_marks = 1;
+ UNLOCK();
+ return((void *) op);
+ }
+}
+
+#endif /* ATOMIC_UNCOLLECTABLE */
diff --git a/tools/build/v2/engine/boehm_gc/mark.c b/tools/build/v2/engine/boehm_gc/mark.c
new file mode 100644
index 0000000000..3e5c46d1b0
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/mark.c
@@ -0,0 +1,1866 @@
+
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+
+# include <stdio.h>
+# include "private/gc_pmark.h"
+
+#if defined(MSWIN32) && defined(__GNUC__)
+# include <excpt.h>
+#endif
+
+/* We put this here to minimize the risk of inlining. */
+/*VARARGS*/
+#ifdef __WATCOMC__
+ void GC_noop(void *p, ...) {}
+#else
+ void GC_noop() {}
+#endif
+
+/* Single argument version, robust against whole program analysis. */
+void GC_noop1(word x)
+{
+ static volatile word sink;
+
+ sink = x;
+}
+
+/* mark_proc GC_mark_procs[MAX_MARK_PROCS] = {0} -- declared in gc_priv.h */
+
+unsigned GC_n_mark_procs = GC_RESERVED_MARK_PROCS;
+
+/* Initialize GC_obj_kinds properly and standard free lists properly. */
+/* This must be done statically since they may be accessed before */
+/* GC_init is called. */
+/* It's done here, since we need to deal with mark descriptors. */
+struct obj_kind GC_obj_kinds[MAXOBJKINDS] = {
+/* PTRFREE */ { &GC_aobjfreelist[0], 0 /* filled in dynamically */,
+ 0 | GC_DS_LENGTH, FALSE, FALSE },
+/* NORMAL */ { &GC_objfreelist[0], 0,
+ 0 | GC_DS_LENGTH, /* Adjusted in GC_init_inner for EXTRA_BYTES */
+ TRUE /* add length to descr */, TRUE },
+/* UNCOLLECTABLE */
+ { &GC_uobjfreelist[0], 0,
+ 0 | GC_DS_LENGTH, TRUE /* add length to descr */, TRUE },
+# ifdef ATOMIC_UNCOLLECTABLE
+ /* AUNCOLLECTABLE */
+ { &GC_auobjfreelist[0], 0,
+ 0 | GC_DS_LENGTH, FALSE /* add length to descr */, FALSE },
+# endif
+# ifdef STUBBORN_ALLOC
+/*STUBBORN*/ { &GC_sobjfreelist[0], 0,
+ 0 | GC_DS_LENGTH, TRUE /* add length to descr */, TRUE },
+# endif
+};
+
+# ifdef ATOMIC_UNCOLLECTABLE
+# ifdef STUBBORN_ALLOC
+ unsigned GC_n_kinds = 5;
+# else
+ unsigned GC_n_kinds = 4;
+# endif
+# else
+# ifdef STUBBORN_ALLOC
+ unsigned GC_n_kinds = 4;
+# else
+ unsigned GC_n_kinds = 3;
+# endif
+# endif
+
+
+# ifndef INITIAL_MARK_STACK_SIZE
+# define INITIAL_MARK_STACK_SIZE (1*HBLKSIZE)
+ /* INITIAL_MARK_STACK_SIZE * sizeof(mse) should be a */
+ /* multiple of HBLKSIZE. */
+ /* The incremental collector actually likes a larger */
+ /* size, since it want to push all marked dirty objs */
+ /* before marking anything new. Currently we let it */
+ /* grow dynamically. */
+# endif
+
+/*
+ * Limits of stack for GC_mark routine.
+ * All ranges between GC_mark_stack(incl.) and GC_mark_stack_top(incl.) still
+ * need to be marked from.
+ */
+
+word GC_n_rescuing_pages; /* Number of dirty pages we marked from */
+ /* excludes ptrfree pages, etc. */
+
+mse * GC_mark_stack;
+
+mse * GC_mark_stack_limit;
+
+size_t GC_mark_stack_size = 0;
+
+#ifdef PARALLEL_MARK
+# include "atomic_ops.h"
+
+ mse * volatile GC_mark_stack_top;
+ /* Updated only with mark lock held, but read asynchronously. */
+ volatile AO_t GC_first_nonempty;
+ /* Lowest entry on mark stack */
+ /* that may be nonempty. */
+ /* Updated only by initiating */
+ /* thread. */
+#else
+ mse * GC_mark_stack_top;
+#endif
+
+static struct hblk * scan_ptr;
+
+mark_state_t GC_mark_state = MS_NONE;
+
+GC_bool GC_mark_stack_too_small = FALSE;
+
+GC_bool GC_objects_are_marked = FALSE; /* Are there collectable marked */
+ /* objects in the heap? */
+
+/* Is a collection in progress? Note that this can return true in the */
+/* nonincremental case, if a collection has been abandoned and the */
+/* mark state is now MS_INVALID. */
+GC_bool GC_collection_in_progress(void)
+{
+ return(GC_mark_state != MS_NONE);
+}
+
+/* clear all mark bits in the header */
+void GC_clear_hdr_marks(hdr *hhdr)
+{
+ size_t last_bit = FINAL_MARK_BIT(hhdr -> hb_sz);
+
+# ifdef USE_MARK_BYTES
+ BZERO(hhdr -> hb_marks, MARK_BITS_SZ);
+ hhdr -> hb_marks[last_bit] = 1;
+# else
+ BZERO(hhdr -> hb_marks, MARK_BITS_SZ*sizeof(word));
+ set_mark_bit_from_hdr(hhdr, last_bit);
+# endif
+ hhdr -> hb_n_marks = 0;
+}
+
+/* Set all mark bits in the header. Used for uncollectable blocks. */
+void GC_set_hdr_marks(hdr *hhdr)
+{
+ unsigned i;
+ size_t sz = hhdr -> hb_sz;
+ size_t n_marks = FINAL_MARK_BIT(sz);
+
+# ifdef USE_MARK_BYTES
+ for (i = 0; i <= n_marks; i += MARK_BIT_OFFSET(sz)) {
+ hhdr -> hb_marks[i] = 1;
+ }
+# else
+ for (i = 0; i < divWORDSZ(n_marks + WORDSZ); ++i) {
+ hhdr -> hb_marks[i] = ONES;
+ }
+# endif
+# ifdef MARK_BIT_PER_OBJ
+ hhdr -> hb_n_marks = n_marks - 1;
+# else
+ hhdr -> hb_n_marks = HBLK_OBJS(sz);
+# endif
+}
+
+/*
+ * Clear all mark bits associated with block h.
+ */
+/*ARGSUSED*/
+static void clear_marks_for_block(struct hblk *h, word dummy)
+{
+ register hdr * hhdr = HDR(h);
+
+ if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) return;
+ /* Mark bit for these is cleared only once the object is */
+ /* explicitly deallocated. This either frees the block, or */
+ /* the bit is cleared once the object is on the free list. */
+ GC_clear_hdr_marks(hhdr);
+}
+
+/* Slow but general routines for setting/clearing/asking about mark bits */
+void GC_set_mark_bit(ptr_t p)
+{
+ struct hblk *h = HBLKPTR(p);
+ hdr * hhdr = HDR(h);
+ word bit_no = MARK_BIT_NO(p - (ptr_t)h, hhdr -> hb_sz);
+
+ if (!mark_bit_from_hdr(hhdr, bit_no)) {
+ set_mark_bit_from_hdr(hhdr, bit_no);
+ ++hhdr -> hb_n_marks;
+ }
+}
+
+void GC_clear_mark_bit(ptr_t p)
+{
+ struct hblk *h = HBLKPTR(p);
+ hdr * hhdr = HDR(h);
+ word bit_no = MARK_BIT_NO(p - (ptr_t)h, hhdr -> hb_sz);
+
+ if (mark_bit_from_hdr(hhdr, bit_no)) {
+ size_t n_marks;
+ clear_mark_bit_from_hdr(hhdr, bit_no);
+ n_marks = hhdr -> hb_n_marks - 1;
+# ifdef PARALLEL_MARK
+ if (n_marks != 0)
+ hhdr -> hb_n_marks = n_marks;
+ /* Don't decrement to zero. The counts are approximate due to */
+ /* concurrency issues, but we need to ensure that a count of */
+ /* zero implies an empty block. */
+# else
+ hhdr -> hb_n_marks = n_marks;
+# endif
+ }
+}
+
+GC_bool GC_is_marked(ptr_t p)
+{
+ struct hblk *h = HBLKPTR(p);
+ hdr * hhdr = HDR(h);
+ word bit_no = MARK_BIT_NO(p - (ptr_t)h, hhdr -> hb_sz);
+
+ return((GC_bool)mark_bit_from_hdr(hhdr, bit_no));
+}
+
+
+/*
+ * Clear mark bits in all allocated heap blocks. This invalidates
+ * the marker invariant, and sets GC_mark_state to reflect this.
+ * (This implicitly starts marking to reestablish the invariant.)
+ */
+void GC_clear_marks(void)
+{
+ GC_apply_to_all_blocks(clear_marks_for_block, (word)0);
+ GC_objects_are_marked = FALSE;
+ GC_mark_state = MS_INVALID;
+ scan_ptr = 0;
+}
+
+/* Initiate a garbage collection. Initiates a full collection if the */
+/* mark state is invalid. */
+/*ARGSUSED*/
+void GC_initiate_gc(void)
+{
+ if (GC_dirty_maintained) GC_read_dirty();
+# ifdef STUBBORN_ALLOC
+ GC_read_changed();
+# endif
+# ifdef CHECKSUMS
+ {
+ extern void GC_check_dirty();
+
+ if (GC_dirty_maintained) GC_check_dirty();
+ }
+# endif
+ GC_n_rescuing_pages = 0;
+ if (GC_mark_state == MS_NONE) {
+ GC_mark_state = MS_PUSH_RESCUERS;
+ } else if (GC_mark_state != MS_INVALID) {
+ ABORT("unexpected state");
+ } /* else this is really a full collection, and mark */
+ /* bits are invalid. */
+ scan_ptr = 0;
+}
+
+
+static void alloc_mark_stack(size_t);
+
+# if defined(MSWIN32) || defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)
+ /* Under rare conditions, we may end up marking from nonexistent memory. */
+ /* Hence we need to be prepared to recover by running GC_mark_some */
+ /* with a suitable handler in place. */
+# define WRAP_MARK_SOME
+# endif
+
+/* Perform a small amount of marking. */
+/* We try to touch roughly a page of memory. */
+/* Return TRUE if we just finished a mark phase. */
+/* Cold_gc_frame is an address inside a GC frame that */
+/* remains valid until all marking is complete. */
+/* A zero value indicates that it's OK to miss some */
+/* register values. */
+/* We hold the allocation lock. In the case of */
+/* incremental collection, the world may not be stopped.*/
+#ifdef WRAP_MARK_SOME
+ /* For win32, this is called after we establish a structured */
+ /* exception handler, in case Windows unmaps one of our root */
+ /* segments. See below. In either case, we acquire the */
+ /* allocator lock long before we get here. */
+ GC_bool GC_mark_some_inner(ptr_t cold_gc_frame)
+#else
+ GC_bool GC_mark_some(ptr_t cold_gc_frame)
+#endif
+{
+ switch(GC_mark_state) {
+ case MS_NONE:
+ return(FALSE);
+
+ case MS_PUSH_RESCUERS:
+ if (GC_mark_stack_top
+ >= GC_mark_stack_limit - INITIAL_MARK_STACK_SIZE/2) {
+ /* Go ahead and mark, even though that might cause us to */
+ /* see more marked dirty objects later on. Avoid this */
+ /* in the future. */
+ GC_mark_stack_too_small = TRUE;
+ MARK_FROM_MARK_STACK();
+ return(FALSE);
+ } else {
+ scan_ptr = GC_push_next_marked_dirty(scan_ptr);
+ if (scan_ptr == 0) {
+ if (GC_print_stats) {
+ GC_log_printf("Marked from %u dirty pages\n",
+ GC_n_rescuing_pages);
+ }
+ GC_push_roots(FALSE, cold_gc_frame);
+ GC_objects_are_marked = TRUE;
+ if (GC_mark_state != MS_INVALID) {
+ GC_mark_state = MS_ROOTS_PUSHED;
+ }
+ }
+ }
+ return(FALSE);
+
+ case MS_PUSH_UNCOLLECTABLE:
+ if (GC_mark_stack_top
+ >= GC_mark_stack + GC_mark_stack_size/4) {
+# ifdef PARALLEL_MARK
+ /* Avoid this, since we don't parallelize the marker */
+ /* here. */
+ if (GC_parallel) GC_mark_stack_too_small = TRUE;
+# endif
+ MARK_FROM_MARK_STACK();
+ return(FALSE);
+ } else {
+ scan_ptr = GC_push_next_marked_uncollectable(scan_ptr);
+ if (scan_ptr == 0) {
+ GC_push_roots(TRUE, cold_gc_frame);
+ GC_objects_are_marked = TRUE;
+ if (GC_mark_state != MS_INVALID) {
+ GC_mark_state = MS_ROOTS_PUSHED;
+ }
+ }
+ }
+ return(FALSE);
+
+ case MS_ROOTS_PUSHED:
+# ifdef PARALLEL_MARK
+ /* In the incremental GC case, this currently doesn't */
+ /* quite do the right thing, since it runs to */
+ /* completion. On the other hand, starting a */
+ /* parallel marker is expensive, so perhaps it is */
+ /* the right thing? */
+ /* Eventually, incremental marking should run */
+ /* asynchronously in multiple threads, without grabbing */
+ /* the allocation lock. */
+ if (GC_parallel) {
+ GC_do_parallel_mark();
+ GC_ASSERT(GC_mark_stack_top < (mse *)GC_first_nonempty);
+ GC_mark_stack_top = GC_mark_stack - 1;
+ if (GC_mark_stack_too_small) {
+ alloc_mark_stack(2*GC_mark_stack_size);
+ }
+ if (GC_mark_state == MS_ROOTS_PUSHED) {
+ GC_mark_state = MS_NONE;
+ return(TRUE);
+ } else {
+ return(FALSE);
+ }
+ }
+# endif
+ if (GC_mark_stack_top >= GC_mark_stack) {
+ MARK_FROM_MARK_STACK();
+ return(FALSE);
+ } else {
+ GC_mark_state = MS_NONE;
+ if (GC_mark_stack_too_small) {
+ alloc_mark_stack(2*GC_mark_stack_size);
+ }
+ return(TRUE);
+ }
+
+ case MS_INVALID:
+ case MS_PARTIALLY_INVALID:
+ if (!GC_objects_are_marked) {
+ GC_mark_state = MS_PUSH_UNCOLLECTABLE;
+ return(FALSE);
+ }
+ if (GC_mark_stack_top >= GC_mark_stack) {
+ MARK_FROM_MARK_STACK();
+ return(FALSE);
+ }
+ if (scan_ptr == 0 && GC_mark_state == MS_INVALID) {
+ /* About to start a heap scan for marked objects. */
+ /* Mark stack is empty. OK to reallocate. */
+ if (GC_mark_stack_too_small) {
+ alloc_mark_stack(2*GC_mark_stack_size);
+ }
+ GC_mark_state = MS_PARTIALLY_INVALID;
+ }
+ scan_ptr = GC_push_next_marked(scan_ptr);
+ if (scan_ptr == 0 && GC_mark_state == MS_PARTIALLY_INVALID) {
+ GC_push_roots(TRUE, cold_gc_frame);
+ GC_objects_are_marked = TRUE;
+ if (GC_mark_state != MS_INVALID) {
+ GC_mark_state = MS_ROOTS_PUSHED;
+ }
+ }
+ return(FALSE);
+ default:
+ ABORT("GC_mark_some: bad state");
+ return(FALSE);
+ }
+}
+
+
+#if defined(MSWIN32) && defined(__GNUC__)
+
+ typedef struct {
+ EXCEPTION_REGISTRATION ex_reg;
+ void *alt_path;
+ } ext_ex_regn;
+
+
+ static EXCEPTION_DISPOSITION mark_ex_handler(
+ struct _EXCEPTION_RECORD *ex_rec,
+ void *est_frame,
+ struct _CONTEXT *context,
+ void *disp_ctxt)
+ {
+ if (ex_rec->ExceptionCode == STATUS_ACCESS_VIOLATION) {
+ ext_ex_regn *xer = (ext_ex_regn *)est_frame;
+
+ /* Unwind from the inner function assuming the standard */
+ /* function prologue. */
+ /* Assumes code has not been compiled with */
+ /* -fomit-frame-pointer. */
+ context->Esp = context->Ebp;
+ context->Ebp = *((DWORD *)context->Esp);
+ context->Esp = context->Esp - 8;
+
+ /* Resume execution at the "real" handler within the */
+ /* wrapper function. */
+ context->Eip = (DWORD )(xer->alt_path);
+
+ return ExceptionContinueExecution;
+
+ } else {
+ return ExceptionContinueSearch;
+ }
+ }
+# endif /* __GNUC__ && MSWIN32 */
+
+#ifdef GC_WIN32_THREADS
+ extern GC_bool GC_started_thread_while_stopped(void);
+ /* In win32_threads.c. Did we invalidate mark phase with an */
+ /* unexpected thread start? */
+#endif
+
+# ifdef WRAP_MARK_SOME
+ GC_bool GC_mark_some(ptr_t cold_gc_frame)
+ {
+ GC_bool ret_val;
+
+# ifdef MSWIN32
+# ifndef __GNUC__
+ /* Windows 98 appears to asynchronously create and remove */
+ /* writable memory mappings, for reasons we haven't yet */
+ /* understood. Since we look for writable regions to */
+ /* determine the root set, we may try to mark from an */
+ /* address range that disappeared since we started the */
+ /* collection. Thus we have to recover from faults here. */
+ /* This code does not appear to be necessary for Windows */
+ /* 95/NT/2000. Note that this code should never generate */
+ /* an incremental GC write fault. */
+ /* It's conceivable that this is the same issue with */
+ /* terminating threads that we see with Linux and */
+ /* USE_PROC_FOR_LIBRARIES. */
+
+ __try {
+ ret_val = GC_mark_some_inner(cold_gc_frame);
+ } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
+ goto handle_ex;
+ }
+# ifdef GC_WIN32_THREADS
+ /* With DllMain-based thread tracking, a thread may have */
+ /* started while we were marking. This is logically equivalent */
+ /* to the exception case; our results are invalid and we have */
+ /* to start over. This cannot be prevented since we can't */
+ /* block in DllMain. */
+ if (GC_started_thread_while_stopped()) goto handle_ex;
+# endif
+ rm_handler:
+ return ret_val;
+
+# else /* __GNUC__ */
+
+ /* Manually install an exception handler since GCC does */
+ /* not yet support Structured Exception Handling (SEH) on */
+ /* Win32. */
+
+ ext_ex_regn er;
+
+ er.alt_path = &&handle_ex;
+ er.ex_reg.handler = mark_ex_handler;
+ asm volatile ("movl %%fs:0, %0" : "=r" (er.ex_reg.prev));
+ asm volatile ("movl %0, %%fs:0" : : "r" (&er));
+ ret_val = GC_mark_some_inner(cold_gc_frame);
+ /* Prevent GCC from considering the following code unreachable */
+ /* and thus eliminating it. */
+ if (er.alt_path == 0)
+ goto handle_ex;
+ rm_handler:
+ /* Uninstall the exception handler */
+ asm volatile ("mov %0, %%fs:0" : : "r" (er.ex_reg.prev));
+ return ret_val;
+
+# endif /* __GNUC__ */
+# else /* !MSWIN32 */
+ /* Here we are handling the case in which /proc is used for root */
+ /* finding, and we have threads. We may find a stack for a */
+ /* thread that is in the process of exiting, and disappears */
+ /* while we are marking it. This seems extremely difficult to */
+ /* avoid otherwise. */
+ if (GC_incremental)
+ WARN("Incremental GC incompatible with /proc roots\n", 0);
+ /* I'm not sure if this could still work ... */
+ GC_setup_temporary_fault_handler();
+ if(SETJMP(GC_jmp_buf) != 0) goto handle_ex;
+ ret_val = GC_mark_some_inner(cold_gc_frame);
+ rm_handler:
+ GC_reset_fault_handler();
+ return ret_val;
+
+# endif /* !MSWIN32 */
+
+handle_ex:
+ /* Exception handler starts here for all cases. */
+ if (GC_print_stats) {
+ GC_log_printf("Caught ACCESS_VIOLATION in marker. "
+ "Memory mapping disappeared.\n");
+ }
+
+ /* We have bad roots on the stack. Discard mark stack. */
+ /* Rescan from marked objects. Redetermine roots. */
+ GC_invalidate_mark_state();
+ scan_ptr = 0;
+
+ ret_val = FALSE;
+ goto rm_handler; // Back to platform-specific code.
+ }
+#endif /* WRAP_MARK_SOME */
+
+
+GC_bool GC_mark_stack_empty(void)
+{
+ return(GC_mark_stack_top < GC_mark_stack);
+}
+
+void GC_invalidate_mark_state(void)
+{
+ GC_mark_state = MS_INVALID;
+ GC_mark_stack_top = GC_mark_stack-1;
+}
+
+mse * GC_signal_mark_stack_overflow(mse *msp)
+{
+ GC_mark_state = MS_INVALID;
+ GC_mark_stack_too_small = TRUE;
+ if (GC_print_stats) {
+ GC_log_printf("Mark stack overflow; current size = %lu entries\n",
+ GC_mark_stack_size);
+ }
+ return(msp - GC_MARK_STACK_DISCARDS);
+}
+
+/*
+ * Mark objects pointed to by the regions described by
+ * mark stack entries between mark_stack and mark_stack_top,
+ * inclusive. Assumes the upper limit of a mark stack entry
+ * is never 0. A mark stack entry never has size 0.
+ * We try to traverse on the order of a hblk of memory before we return.
+ * Caller is responsible for calling this until the mark stack is empty.
+ * Note that this is the most performance critical routine in the
+ * collector. Hence it contains all sorts of ugly hacks to speed
+ * things up. In particular, we avoid procedure calls on the common
+ * path, we take advantage of peculiarities of the mark descriptor
+ * encoding, we optionally maintain a cache for the block address to
+ * header mapping, we prefetch when an object is "grayed", etc.
+ */
+mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, mse *mark_stack_limit)
+{
+ signed_word credit = HBLKSIZE; /* Remaining credit for marking work */
+ ptr_t current_p; /* Pointer to current candidate ptr. */
+ word current; /* Candidate pointer. */
+ ptr_t limit; /* (Incl) limit of current candidate */
+ /* range */
+ word descr;
+ ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
+ ptr_t least_ha = GC_least_plausible_heap_addr;
+ DECLARE_HDR_CACHE;
+
+# define SPLIT_RANGE_WORDS 128 /* Must be power of 2. */
+
+ GC_objects_are_marked = TRUE;
+ INIT_HDR_CACHE;
+# ifdef OS2 /* Use untweaked version to circumvent compiler problem */
+ while (mark_stack_top >= mark_stack && credit >= 0) {
+# else
+ while ((((ptr_t)mark_stack_top - (ptr_t)mark_stack) | credit)
+ >= 0) {
+# endif
+ current_p = mark_stack_top -> mse_start;
+ descr = mark_stack_top -> mse_descr;
+ retry:
+ /* current_p and descr describe the current object. */
+ /* *mark_stack_top is vacant. */
+ /* The following is 0 only for small objects described by a simple */
+ /* length descriptor. For many applications this is the common */
+ /* case, so we try to detect it quickly. */
+ if (descr & ((~(WORDS_TO_BYTES(SPLIT_RANGE_WORDS) - 1)) | GC_DS_TAGS)) {
+ word tag = descr & GC_DS_TAGS;
+
+ switch(tag) {
+ case GC_DS_LENGTH:
+ /* Large length. */
+ /* Process part of the range to avoid pushing too much on the */
+ /* stack. */
+ GC_ASSERT(descr < (word)GC_greatest_plausible_heap_addr
+ - (word)GC_least_plausible_heap_addr);
+# ifdef ENABLE_TRACE
+ if (GC_trace_addr >= current_p
+ && GC_trace_addr < current_p + descr) {
+ GC_log_printf("GC:%d Large section; start %p len %lu\n",
+ GC_gc_no, current_p, (unsigned long) descr);
+ }
+# endif /* ENABLE_TRACE */
+# ifdef PARALLEL_MARK
+# define SHARE_BYTES 2048
+ if (descr > SHARE_BYTES && GC_parallel
+ && mark_stack_top < mark_stack_limit - 1) {
+ int new_size = (descr/2) & ~(sizeof(word)-1);
+ mark_stack_top -> mse_start = current_p;
+ mark_stack_top -> mse_descr = new_size + sizeof(word);
+ /* makes sure we handle */
+ /* misaligned pointers. */
+ mark_stack_top++;
+# ifdef ENABLE_TRACE
+ if (GC_trace_addr >= current_p
+ && GC_trace_addr < current_p + descr) {
+ GC_log_printf("GC:%d splitting (parallel) %p at %p\n",
+ GC_gc_no, current_p, current_p + new_size);
+ }
+# endif /* ENABLE_TRACE */
+ current_p += new_size;
+ descr -= new_size;
+ goto retry;
+ }
+# endif /* PARALLEL_MARK */
+ mark_stack_top -> mse_start =
+ limit = current_p + WORDS_TO_BYTES(SPLIT_RANGE_WORDS-1);
+ mark_stack_top -> mse_descr =
+ descr - WORDS_TO_BYTES(SPLIT_RANGE_WORDS-1);
+# ifdef ENABLE_TRACE
+ if (GC_trace_addr >= current_p
+ && GC_trace_addr < current_p + descr) {
+ GC_log_printf("GC:%d splitting %p at %p\n",
+ GC_gc_no, current_p, limit);
+ }
+# endif /* ENABLE_TRACE */
+ /* Make sure that pointers overlapping the two ranges are */
+ /* considered. */
+ limit += sizeof(word) - ALIGNMENT;
+ break;
+ case GC_DS_BITMAP:
+ mark_stack_top--;
+# ifdef ENABLE_TRACE
+ if (GC_trace_addr >= current_p
+ && GC_trace_addr < current_p + WORDS_TO_BYTES(WORDSZ-2)) {
+ GC_log_printf("GC:%d Tracing from %p bitmap descr %lu\n",
+ GC_gc_no, current_p, (unsigned long) descr);
+ }
+# endif /* ENABLE_TRACE */
+ descr &= ~GC_DS_TAGS;
+ credit -= WORDS_TO_BYTES(WORDSZ/2); /* guess */
+ while (descr != 0) {
+ if ((signed_word)descr < 0) {
+ current = *(word *)current_p;
+ FIXUP_POINTER(current);
+ if ((ptr_t)current >= least_ha && (ptr_t)current < greatest_ha) {
+ PREFETCH((ptr_t)current);
+# ifdef ENABLE_TRACE
+ if (GC_trace_addr == current_p) {
+ GC_log_printf("GC:%d Considering(3) %p -> %p\n",
+ GC_gc_no, current_p, (ptr_t) current);
+ }
+# endif /* ENABLE_TRACE */
+ PUSH_CONTENTS((ptr_t)current, mark_stack_top,
+ mark_stack_limit, current_p, exit1);
+ }
+ }
+ descr <<= 1;
+ current_p += sizeof(word);
+ }
+ continue;
+ case GC_DS_PROC:
+ mark_stack_top--;
+# ifdef ENABLE_TRACE
+ if (GC_trace_addr >= current_p
+ && GC_base(current_p) != 0
+ && GC_base(current_p) == GC_base(GC_trace_addr)) {
+ GC_log_printf("GC:%d Tracing from %p proc descr %lu\n",
+ GC_gc_no, current_p, (unsigned long) descr);
+ }
+# endif /* ENABLE_TRACE */
+ credit -= GC_PROC_BYTES;
+ mark_stack_top =
+ (*PROC(descr))
+ ((word *)current_p, mark_stack_top,
+ mark_stack_limit, ENV(descr));
+ continue;
+ case GC_DS_PER_OBJECT:
+ if ((signed_word)descr >= 0) {
+ /* Descriptor is in the object. */
+ descr = *(word *)(current_p + descr - GC_DS_PER_OBJECT);
+ } else {
+ /* Descriptor is in type descriptor pointed to by first */
+ /* word in object. */
+ ptr_t type_descr = *(ptr_t *)current_p;
+ /* type_descr is either a valid pointer to the descriptor */
+ /* structure, or this object was on a free list. If it */
+ /* it was anything but the last object on the free list, */
+ /* we will misinterpret the next object on the free list as */
+ /* the type descriptor, and get a 0 GC descriptor, which */
+ /* is ideal. Unfortunately, we need to check for the last */
+ /* object case explicitly. */
+ if (0 == type_descr) {
+ /* Rarely executed. */
+ mark_stack_top--;
+ continue;
+ }
+ descr = *(word *)(type_descr
+ - (descr - (GC_DS_PER_OBJECT
+ - GC_INDIR_PER_OBJ_BIAS)));
+ }
+ if (0 == descr) {
+ /* Can happen either because we generated a 0 descriptor */
+ /* or we saw a pointer to a free object. */
+ mark_stack_top--;
+ continue;
+ }
+ goto retry;
+ }
+ } else /* Small object with length descriptor */ {
+ mark_stack_top--;
+ limit = current_p + (word)descr;
+ }
+# ifdef ENABLE_TRACE
+ if (GC_trace_addr >= current_p
+ && GC_trace_addr < limit) {
+ GC_log_printf("GC:%d Tracing from %p len %lu\n",
+ GC_gc_no, current_p, (unsigned long) descr);
+ }
+# endif /* ENABLE_TRACE */
+ /* The simple case in which we're scanning a range. */
+ GC_ASSERT(!((word)current_p & (ALIGNMENT-1)));
+ credit -= limit - current_p;
+ limit -= sizeof(word);
+ {
+# define PREF_DIST 4
+
+# ifndef SMALL_CONFIG
+ word deferred;
+
+ /* Try to prefetch the next pointer to be examined asap. */
+ /* Empirically, this also seems to help slightly without */
+ /* prefetches, at least on linux/X86. Presumably this loop */
+ /* ends up with less register pressure, and gcc thus ends up */
+ /* generating slightly better code. Overall gcc code quality */
+ /* for this loop is still not great. */
+ for(;;) {
+ PREFETCH(limit - PREF_DIST*CACHE_LINE_SIZE);
+ GC_ASSERT(limit >= current_p);
+ deferred = *(word *)limit;
+ FIXUP_POINTER(deferred);
+ limit -= ALIGNMENT;
+ if ((ptr_t)deferred >= least_ha && (ptr_t)deferred < greatest_ha) {
+ PREFETCH((ptr_t)deferred);
+ break;
+ }
+ if (current_p > limit) goto next_object;
+ /* Unroll once, so we don't do too many of the prefetches */
+ /* based on limit. */
+ deferred = *(word *)limit;
+ FIXUP_POINTER(deferred);
+ limit -= ALIGNMENT;
+ if ((ptr_t)deferred >= least_ha && (ptr_t)deferred < greatest_ha) {
+ PREFETCH((ptr_t)deferred);
+ break;
+ }
+ if (current_p > limit) goto next_object;
+ }
+# endif
+
+ while (current_p <= limit) {
+ /* Empirically, unrolling this loop doesn't help a lot. */
+ /* Since PUSH_CONTENTS expands to a lot of code, */
+ /* we don't. */
+ current = *(word *)current_p;
+ FIXUP_POINTER(current);
+ PREFETCH(current_p + PREF_DIST*CACHE_LINE_SIZE);
+ if ((ptr_t)current >= least_ha && (ptr_t)current < greatest_ha) {
+ /* Prefetch the contents of the object we just pushed. It's */
+ /* likely we will need them soon. */
+ PREFETCH((ptr_t)current);
+# ifdef ENABLE_TRACE
+ if (GC_trace_addr == current_p) {
+ GC_log_printf("GC:%d Considering(1) %p -> %p\n",
+ GC_gc_no, current_p, (ptr_t) current);
+ }
+# endif /* ENABLE_TRACE */
+ PUSH_CONTENTS((ptr_t)current, mark_stack_top,
+ mark_stack_limit, current_p, exit2);
+ }
+ current_p += ALIGNMENT;
+ }
+
+# ifndef SMALL_CONFIG
+ /* We still need to mark the entry we previously prefetched. */
+ /* We already know that it passes the preliminary pointer */
+ /* validity test. */
+# ifdef ENABLE_TRACE
+ if (GC_trace_addr == current_p) {
+ GC_log_printf("GC:%d Considering(2) %p -> %p\n",
+ GC_gc_no, current_p, (ptr_t) deferred);
+ }
+# endif /* ENABLE_TRACE */
+ PUSH_CONTENTS((ptr_t)deferred, mark_stack_top,
+ mark_stack_limit, current_p, exit4);
+ next_object:;
+# endif
+ }
+ }
+ return mark_stack_top;
+}
+
+#ifdef PARALLEL_MARK
+
+/* We assume we have an ANSI C Compiler. */
+GC_bool GC_help_wanted = FALSE;
+unsigned GC_helper_count = 0;
+unsigned GC_active_count = 0;
+word GC_mark_no = 0;
+
+#define LOCAL_MARK_STACK_SIZE HBLKSIZE
+ /* Under normal circumstances, this is big enough to guarantee */
+ /* We don't overflow half of it in a single call to */
+ /* GC_mark_from. */
+
+
+/* Steal mark stack entries starting at mse low into mark stack local */
+/* until we either steal mse high, or we have max entries. */
+/* Return a pointer to the top of the local mark stack. */
+/* *next is replaced by a pointer to the next unscanned mark stack */
+/* entry. */
+mse * GC_steal_mark_stack(mse * low, mse * high, mse * local,
+ unsigned max, mse **next)
+{
+ mse *p;
+ mse *top = local - 1;
+ unsigned i = 0;
+
+ GC_ASSERT(high >= low-1 && high - low + 1 <= GC_mark_stack_size);
+ for (p = low; p <= high && i <= max; ++p) {
+ word descr = AO_load((volatile AO_t *) &(p -> mse_descr));
+ if (descr != 0) {
+ /* Must be ordered after read of descr: */
+ AO_store_release_write((volatile AO_t *) &(p -> mse_descr), 0);
+ /* More than one thread may get this entry, but that's only */
+ /* a minor performance problem. */
+ ++top;
+ top -> mse_descr = descr;
+ top -> mse_start = p -> mse_start;
+ GC_ASSERT((top -> mse_descr & GC_DS_TAGS) != GC_DS_LENGTH ||
+ top -> mse_descr < (ptr_t)GC_greatest_plausible_heap_addr
+ - (ptr_t)GC_least_plausible_heap_addr);
+ /* If this is a big object, count it as */
+ /* size/256 + 1 objects. */
+ ++i;
+ if ((descr & GC_DS_TAGS) == GC_DS_LENGTH) i += (descr >> 8);
+ }
+ }
+ *next = p;
+ return top;
+}
+
+/* Copy back a local mark stack. */
+/* low and high are inclusive bounds. */
+void GC_return_mark_stack(mse * low, mse * high)
+{
+ mse * my_top;
+ mse * my_start;
+ size_t stack_size;
+
+ if (high < low) return;
+ stack_size = high - low + 1;
+ GC_acquire_mark_lock();
+ my_top = GC_mark_stack_top; /* Concurrent modification impossible. */
+ my_start = my_top + 1;
+ if (my_start - GC_mark_stack + stack_size > GC_mark_stack_size) {
+ if (GC_print_stats) {
+ GC_log_printf("No room to copy back mark stack.");
+ }
+ GC_mark_state = MS_INVALID;
+ GC_mark_stack_too_small = TRUE;
+ /* We drop the local mark stack. We'll fix things later. */
+ } else {
+ BCOPY(low, my_start, stack_size * sizeof(mse));
+ GC_ASSERT((mse *)AO_load((volatile AO_t *)(&GC_mark_stack_top))
+ == my_top);
+ AO_store_release_write((volatile AO_t *)(&GC_mark_stack_top),
+ (AO_t)(my_top + stack_size));
+ /* Ensures visibility of previously written stack contents. */
+ }
+ GC_release_mark_lock();
+ GC_notify_all_marker();
+}
+
+/* Mark from the local mark stack. */
+/* On return, the local mark stack is empty. */
+/* But this may be achieved by copying the */
+/* local mark stack back into the global one. */
+void GC_do_local_mark(mse *local_mark_stack, mse *local_top)
+{
+ unsigned n;
+# define N_LOCAL_ITERS 1
+
+# ifdef GC_ASSERTIONS
+ /* Make sure we don't hold mark lock. */
+ GC_acquire_mark_lock();
+ GC_release_mark_lock();
+# endif
+ for (;;) {
+ for (n = 0; n < N_LOCAL_ITERS; ++n) {
+ local_top = GC_mark_from(local_top, local_mark_stack,
+ local_mark_stack + LOCAL_MARK_STACK_SIZE);
+ if (local_top < local_mark_stack) return;
+ if (local_top - local_mark_stack >= LOCAL_MARK_STACK_SIZE/2) {
+ GC_return_mark_stack(local_mark_stack, local_top);
+ return;
+ }
+ }
+ if ((mse *)AO_load((volatile AO_t *)(&GC_mark_stack_top))
+ < (mse *)AO_load(&GC_first_nonempty)
+ && GC_active_count < GC_helper_count
+ && local_top > local_mark_stack + 1) {
+ /* Try to share the load, since the main stack is empty, */
+ /* and helper threads are waiting for a refill. */
+ /* The entries near the bottom of the stack are likely */
+ /* to require more work. Thus we return those, eventhough */
+ /* it's harder. */
+ mse * new_bottom = local_mark_stack
+ + (local_top - local_mark_stack)/2;
+ GC_ASSERT(new_bottom > local_mark_stack
+ && new_bottom < local_top);
+ GC_return_mark_stack(local_mark_stack, new_bottom - 1);
+ memmove(local_mark_stack, new_bottom,
+ (local_top - new_bottom + 1) * sizeof(mse));
+ local_top -= (new_bottom - local_mark_stack);
+ }
+ }
+}
+
+#define ENTRIES_TO_GET 5
+
+long GC_markers = 2; /* Normally changed by thread-library- */
+ /* -specific code. */
+
+/* Mark using the local mark stack until the global mark stack is empty */
+/* and there are no active workers. Update GC_first_nonempty to reflect */
+/* progress. */
+/* Caller does not hold mark lock. */
+/* Caller has already incremented GC_helper_count. We decrement it, */
+/* and maintain GC_active_count. */
+void GC_mark_local(mse *local_mark_stack, int id)
+{
+ mse * my_first_nonempty;
+
+ GC_acquire_mark_lock();
+ GC_active_count++;
+ my_first_nonempty = (mse *)AO_load(&GC_first_nonempty);
+ GC_ASSERT((mse *)AO_load(&GC_first_nonempty) >= GC_mark_stack &&
+ (mse *)AO_load(&GC_first_nonempty) <=
+ (mse *)AO_load((volatile AO_t *)(&GC_mark_stack_top)) + 1);
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf("Starting mark helper %lu\n", (unsigned long)id);
+ GC_release_mark_lock();
+ for (;;) {
+ size_t n_on_stack;
+ size_t n_to_get;
+ mse * my_top;
+ mse * local_top;
+ mse * global_first_nonempty = (mse *)AO_load(&GC_first_nonempty);
+
+ GC_ASSERT(my_first_nonempty >= GC_mark_stack &&
+ my_first_nonempty <=
+ (mse *)AO_load((volatile AO_t *)(&GC_mark_stack_top)) + 1);
+ GC_ASSERT(global_first_nonempty >= GC_mark_stack &&
+ global_first_nonempty <=
+ (mse *)AO_load((volatile AO_t *)(&GC_mark_stack_top)) + 1);
+ if (my_first_nonempty < global_first_nonempty) {
+ my_first_nonempty = global_first_nonempty;
+ } else if (global_first_nonempty < my_first_nonempty) {
+ AO_compare_and_swap(&GC_first_nonempty,
+ (AO_t) global_first_nonempty,
+ (AO_t) my_first_nonempty);
+ /* If this fails, we just go ahead, without updating */
+ /* GC_first_nonempty. */
+ }
+ /* Perhaps we should also update GC_first_nonempty, if it */
+ /* is less. But that would require using atomic updates. */
+ my_top = (mse *)AO_load_acquire((volatile AO_t *)(&GC_mark_stack_top));
+ n_on_stack = my_top - my_first_nonempty + 1;
+ if (0 == n_on_stack) {
+ GC_acquire_mark_lock();
+ my_top = GC_mark_stack_top;
+ /* Asynchronous modification impossible here, */
+ /* since we hold mark lock. */
+ n_on_stack = my_top - my_first_nonempty + 1;
+ if (0 == n_on_stack) {
+ GC_active_count--;
+ GC_ASSERT(GC_active_count <= GC_helper_count);
+ /* Other markers may redeposit objects */
+ /* on the stack. */
+ if (0 == GC_active_count) GC_notify_all_marker();
+ while (GC_active_count > 0
+ && (mse *)AO_load(&GC_first_nonempty)
+ > GC_mark_stack_top) {
+ /* We will be notified if either GC_active_count */
+ /* reaches zero, or if more objects are pushed on */
+ /* the global mark stack. */
+ GC_wait_marker();
+ }
+ if (GC_active_count == 0 &&
+ (mse *)AO_load(&GC_first_nonempty) > GC_mark_stack_top) {
+ GC_bool need_to_notify = FALSE;
+ /* The above conditions can't be falsified while we */
+ /* hold the mark lock, since neither */
+ /* GC_active_count nor GC_mark_stack_top can */
+ /* change. GC_first_nonempty can only be */
+ /* incremented asynchronously. Thus we know that */
+ /* both conditions actually held simultaneously. */
+ GC_helper_count--;
+ if (0 == GC_helper_count) need_to_notify = TRUE;
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf(
+ "Finished mark helper %lu\n", (unsigned long)id);
+ GC_release_mark_lock();
+ if (need_to_notify) GC_notify_all_marker();
+ return;
+ }
+ /* else there's something on the stack again, or */
+ /* another helper may push something. */
+ GC_active_count++;
+ GC_ASSERT(GC_active_count > 0);
+ GC_release_mark_lock();
+ continue;
+ } else {
+ GC_release_mark_lock();
+ }
+ }
+ n_to_get = ENTRIES_TO_GET;
+ if (n_on_stack < 2 * ENTRIES_TO_GET) n_to_get = 1;
+ local_top = GC_steal_mark_stack(my_first_nonempty, my_top,
+ local_mark_stack, n_to_get,
+ &my_first_nonempty);
+ GC_ASSERT(my_first_nonempty >= GC_mark_stack &&
+ my_first_nonempty <=
+ (mse *)AO_load((volatile AO_t *)(&GC_mark_stack_top)) + 1);
+ GC_do_local_mark(local_mark_stack, local_top);
+ }
+}
+
+/* Perform Parallel mark. */
+/* We hold the GC lock, not the mark lock. */
+/* Currently runs until the mark stack is */
+/* empty. */
+void GC_do_parallel_mark()
+{
+ mse local_mark_stack[LOCAL_MARK_STACK_SIZE];
+
+ GC_acquire_mark_lock();
+ GC_ASSERT(I_HOLD_LOCK());
+ /* This could be a GC_ASSERT, but it seems safer to keep it on */
+ /* all the time, especially since it's cheap. */
+ if (GC_help_wanted || GC_active_count != 0 || GC_helper_count != 0)
+ ABORT("Tried to start parallel mark in bad state");
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf("Starting marking for mark phase number %lu\n",
+ (unsigned long)GC_mark_no);
+ GC_first_nonempty = (AO_t)GC_mark_stack;
+ GC_active_count = 0;
+ GC_helper_count = 1;
+ GC_help_wanted = TRUE;
+ GC_release_mark_lock();
+ GC_notify_all_marker();
+ /* Wake up potential helpers. */
+ GC_mark_local(local_mark_stack, 0);
+ GC_acquire_mark_lock();
+ GC_help_wanted = FALSE;
+ /* Done; clean up. */
+ while (GC_helper_count > 0) GC_wait_marker();
+ /* GC_helper_count cannot be incremented while GC_help_wanted == FALSE */
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf(
+ "Finished marking for mark phase number %lu\n",
+ (unsigned long)GC_mark_no);
+ GC_mark_no++;
+ GC_release_mark_lock();
+ GC_notify_all_marker();
+}
+
+
+/* Try to help out the marker, if it's running. */
+/* We do not hold the GC lock, but the requestor does. */
+void GC_help_marker(word my_mark_no)
+{
+ mse local_mark_stack[LOCAL_MARK_STACK_SIZE];
+ unsigned my_id;
+
+ if (!GC_parallel) return;
+ GC_acquire_mark_lock();
+ while (GC_mark_no < my_mark_no
+ || (!GC_help_wanted && GC_mark_no == my_mark_no)) {
+ GC_wait_marker();
+ }
+ my_id = GC_helper_count;
+ if (GC_mark_no != my_mark_no || my_id >= GC_markers) {
+ /* Second test is useful only if original threads can also */
+ /* act as helpers. Under Linux they can't. */
+ GC_release_mark_lock();
+ return;
+ }
+ GC_helper_count = my_id + 1;
+ GC_release_mark_lock();
+ GC_mark_local(local_mark_stack, my_id);
+ /* GC_mark_local decrements GC_helper_count. */
+}
+
+#endif /* PARALLEL_MARK */
+
+/* Allocate or reallocate space for mark stack of size n entries. */
+/* May silently fail. */
+static void alloc_mark_stack(size_t n)
+{
+ mse * new_stack = (mse *)GC_scratch_alloc(n * sizeof(struct GC_ms_entry));
+# ifdef GWW_VDB
+ /* Don't recycle a stack segment obtained with the wrong flags. */
+ /* Win32 GetWriteWatch requires the right kind of memory. */
+ static GC_bool GC_incremental_at_stack_alloc = 0;
+ GC_bool recycle_old = (!GC_incremental || GC_incremental_at_stack_alloc);
+
+ GC_incremental_at_stack_alloc = GC_incremental;
+# else
+# define recycle_old 1
+# endif
+
+ GC_mark_stack_too_small = FALSE;
+ if (GC_mark_stack_size != 0) {
+ if (new_stack != 0) {
+ if (recycle_old) {
+ /* Recycle old space */
+ size_t page_offset = (word)GC_mark_stack & (GC_page_size - 1);
+ size_t size = GC_mark_stack_size * sizeof(struct GC_ms_entry);
+ size_t displ = 0;
+
+ if (0 != page_offset) displ = GC_page_size - page_offset;
+ size = (size - displ) & ~(GC_page_size - 1);
+ if (size > 0) {
+ GC_add_to_heap((struct hblk *)
+ ((word)GC_mark_stack + displ), (word)size);
+ }
+ }
+ GC_mark_stack = new_stack;
+ GC_mark_stack_size = n;
+ GC_mark_stack_limit = new_stack + n;
+ if (GC_print_stats) {
+ GC_log_printf("Grew mark stack to %lu frames\n",
+ (unsigned long) GC_mark_stack_size);
+ }
+ } else {
+ if (GC_print_stats) {
+ GC_log_printf("Failed to grow mark stack to %lu frames\n",
+ (unsigned long) n);
+ }
+ }
+ } else {
+ if (new_stack == 0) {
+ GC_err_printf("No space for mark stack\n");
+ EXIT();
+ }
+ GC_mark_stack = new_stack;
+ GC_mark_stack_size = n;
+ GC_mark_stack_limit = new_stack + n;
+ }
+ GC_mark_stack_top = GC_mark_stack-1;
+}
+
+void GC_mark_init()
+{
+ alloc_mark_stack(INITIAL_MARK_STACK_SIZE);
+}
+
+/*
+ * Push all locations between b and t onto the mark stack.
+ * b is the first location to be checked. t is one past the last
+ * location to be checked.
+ * Should only be used if there is no possibility of mark stack
+ * overflow.
+ */
+void GC_push_all(ptr_t bottom, ptr_t top)
+{
+ register word length;
+
+ bottom = (ptr_t)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
+ top = (ptr_t)(((word) top) & ~(ALIGNMENT-1));
+ if (top == 0 || bottom == top) return;
+ GC_mark_stack_top++;
+ if (GC_mark_stack_top >= GC_mark_stack_limit) {
+ ABORT("unexpected mark stack overflow");
+ }
+ length = top - bottom;
+# if GC_DS_TAGS > ALIGNMENT - 1
+ length += GC_DS_TAGS;
+ length &= ~GC_DS_TAGS;
+# endif
+ GC_mark_stack_top -> mse_start = bottom;
+ GC_mark_stack_top -> mse_descr = length;
+}
+
+/*
+ * Analogous to the above, but push only those pages h with dirty_fn(h) != 0.
+ * We use push_fn to actually push the block.
+ * Used both to selectively push dirty pages, or to push a block
+ * in piecemeal fashion, to allow for more marking concurrency.
+ * Will not overflow mark stack if push_fn pushes a small fixed number
+ * of entries. (This is invoked only if push_fn pushes a single entry,
+ * or if it marks each object before pushing it, thus ensuring progress
+ * in the event of a stack overflow.)
+ */
+void GC_push_selected(ptr_t bottom, ptr_t top,
+ int (*dirty_fn) (struct hblk *),
+ void (*push_fn) (ptr_t, ptr_t))
+{
+ struct hblk * h;
+
+ bottom = (ptr_t)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
+ top = (ptr_t)(((word) top) & ~(ALIGNMENT-1));
+
+ if (top == 0 || bottom == top) return;
+ h = HBLKPTR(bottom + HBLKSIZE);
+ if (top <= (ptr_t) h) {
+ if ((*dirty_fn)(h-1)) {
+ (*push_fn)(bottom, top);
+ }
+ return;
+ }
+ if ((*dirty_fn)(h-1)) {
+ (*push_fn)(bottom, (ptr_t)h);
+ }
+ while ((ptr_t)(h+1) <= top) {
+ if ((*dirty_fn)(h)) {
+ if ((word)(GC_mark_stack_top - GC_mark_stack)
+ > 3 * GC_mark_stack_size / 4) {
+ /* Danger of mark stack overflow */
+ (*push_fn)((ptr_t)h, top);
+ return;
+ } else {
+ (*push_fn)((ptr_t)h, (ptr_t)(h+1));
+ }
+ }
+ h++;
+ }
+ if ((ptr_t)h != top) {
+ if ((*dirty_fn)(h)) {
+ (*push_fn)((ptr_t)h, top);
+ }
+ }
+ if (GC_mark_stack_top >= GC_mark_stack_limit) {
+ ABORT("unexpected mark stack overflow");
+ }
+}
+
+# ifndef SMALL_CONFIG
+
+#ifdef PARALLEL_MARK
+ /* Break up root sections into page size chunks to better spread */
+ /* out work. */
+ GC_bool GC_true_func(struct hblk *h) { return TRUE; }
+# define GC_PUSH_ALL(b,t) GC_push_selected(b,t,GC_true_func,GC_push_all);
+#else
+# define GC_PUSH_ALL(b,t) GC_push_all(b,t);
+#endif
+
+
+void GC_push_conditional(ptr_t bottom, ptr_t top, GC_bool all)
+{
+ if (all) {
+ if (GC_dirty_maintained) {
+# ifdef PROC_VDB
+ /* Pages that were never dirtied cannot contain pointers */
+ GC_push_selected(bottom, top, GC_page_was_ever_dirty, GC_push_all);
+# else
+ GC_push_all(bottom, top);
+# endif
+ } else {
+ GC_push_all(bottom, top);
+ }
+ } else {
+ GC_push_selected(bottom, top, GC_page_was_dirty, GC_push_all);
+ }
+}
+#endif
+
+# if defined(MSWIN32) || defined(MSWINCE)
+ void __cdecl GC_push_one(word p)
+# else
+ void GC_push_one(word p)
+# endif
+{
+ GC_PUSH_ONE_STACK((ptr_t)p, MARKED_FROM_REGISTER);
+}
+
+struct GC_ms_entry *GC_mark_and_push(void *obj,
+ mse *mark_stack_ptr,
+ mse *mark_stack_limit,
+ void **src)
+{
+ hdr * hhdr;
+
+ PREFETCH(obj);
+ GET_HDR(obj, hhdr);
+ if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr),FALSE)) {
+ if (GC_all_interior_pointers) {
+ hhdr = GC_find_header(GC_base(obj));
+ if (hhdr == 0) {
+ GC_ADD_TO_BLACK_LIST_NORMAL(obj, src);
+ return mark_stack_ptr;
+ }
+ } else {
+ GC_ADD_TO_BLACK_LIST_NORMAL(obj, src);
+ return mark_stack_ptr;
+ }
+ }
+ if (EXPECT(HBLK_IS_FREE(hhdr),0)) {
+ GC_ADD_TO_BLACK_LIST_NORMAL(obj, src);
+ return mark_stack_ptr;
+ }
+
+ PUSH_CONTENTS_HDR(obj, mark_stack_ptr /* modified */, mark_stack_limit,
+ src, was_marked, hhdr, TRUE);
+ was_marked:
+ return mark_stack_ptr;
+}
+
+/* Mark and push (i.e. gray) a single object p onto the main */
+/* mark stack. Consider p to be valid if it is an interior */
+/* pointer. */
+/* The object p has passed a preliminary pointer validity */
+/* test, but we do not definitely know whether it is valid. */
+/* Mark bits are NOT atomically updated. Thus this must be the */
+/* only thread setting them. */
+# if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)
+ void GC_mark_and_push_stack(ptr_t p, ptr_t source)
+# else
+ void GC_mark_and_push_stack(ptr_t p)
+# define source 0
+# endif
+{
+ hdr * hhdr;
+ ptr_t r = p;
+
+ PREFETCH(p);
+ GET_HDR(p, hhdr);
+ if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr),FALSE)) {
+ if (hhdr != 0) {
+ r = GC_base(p);
+ hhdr = HDR(r);
+ }
+ if (hhdr == 0) {
+ GC_ADD_TO_BLACK_LIST_STACK(p, source);
+ return;
+ }
+ }
+ if (EXPECT(HBLK_IS_FREE(hhdr),0)) {
+ GC_ADD_TO_BLACK_LIST_NORMAL(p, src);
+ return;
+ }
+# if defined(MANUAL_VDB) && defined(THREADS)
+ /* Pointer is on the stack. We may have dirtied the object */
+ /* it points to, but not yet have called GC_dirty(); */
+ GC_dirty(p); /* Implicitly affects entire object. */
+# endif
+ PUSH_CONTENTS_HDR(r, GC_mark_stack_top, GC_mark_stack_limit,
+ source, mark_and_push_exit, hhdr, FALSE);
+ mark_and_push_exit: ;
+ /* We silently ignore pointers to near the end of a block, */
+ /* which is very mildly suboptimal. */
+ /* FIXME: We should probably add a header word to address */
+ /* this. */
+}
+
+# ifdef TRACE_BUF
+
+# define TRACE_ENTRIES 1000
+
+struct trace_entry {
+ char * kind;
+ word gc_no;
+ word bytes_allocd;
+ word arg1;
+ word arg2;
+} GC_trace_buf[TRACE_ENTRIES];
+
+int GC_trace_buf_ptr = 0;
+
+void GC_add_trace_entry(char *kind, word arg1, word arg2)
+{
+ GC_trace_buf[GC_trace_buf_ptr].kind = kind;
+ GC_trace_buf[GC_trace_buf_ptr].gc_no = GC_gc_no;
+ GC_trace_buf[GC_trace_buf_ptr].bytes_allocd = GC_bytes_allocd;
+ GC_trace_buf[GC_trace_buf_ptr].arg1 = arg1 ^ 0x80000000;
+ GC_trace_buf[GC_trace_buf_ptr].arg2 = arg2 ^ 0x80000000;
+ GC_trace_buf_ptr++;
+ if (GC_trace_buf_ptr >= TRACE_ENTRIES) GC_trace_buf_ptr = 0;
+}
+
+void GC_print_trace(word gc_no, GC_bool lock)
+{
+ int i;
+ struct trace_entry *p;
+
+ if (lock) LOCK();
+ for (i = GC_trace_buf_ptr-1; i != GC_trace_buf_ptr; i--) {
+ if (i < 0) i = TRACE_ENTRIES-1;
+ p = GC_trace_buf + i;
+ if (p -> gc_no < gc_no || p -> kind == 0) return;
+ printf("Trace:%s (gc:%d,bytes:%d) 0x%X, 0x%X\n",
+ p -> kind, p -> gc_no, p -> bytes_allocd,
+ (p -> arg1) ^ 0x80000000, (p -> arg2) ^ 0x80000000);
+ }
+ printf("Trace incomplete\n");
+ if (lock) UNLOCK();
+}
+
+# endif /* TRACE_BUF */
+
+/*
+ * A version of GC_push_all that treats all interior pointers as valid
+ * and scans the entire region immediately, in case the contents
+ * change.
+ */
+void GC_push_all_eager(ptr_t bottom, ptr_t top)
+{
+ word * b = (word *)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
+ word * t = (word *)(((word) top) & ~(ALIGNMENT-1));
+ register word *p;
+ register ptr_t q;
+ register word *lim;
+ register ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
+ register ptr_t least_ha = GC_least_plausible_heap_addr;
+# define GC_greatest_plausible_heap_addr greatest_ha
+# define GC_least_plausible_heap_addr least_ha
+
+ if (top == 0) return;
+ /* check all pointers in range and push if they appear */
+ /* to be valid. */
+ lim = t - 1 /* longword */;
+ for (p = b; p <= lim; p = (word *)(((ptr_t)p) + ALIGNMENT)) {
+ q = (ptr_t)(*p);
+ GC_PUSH_ONE_STACK((ptr_t)q, p);
+ }
+# undef GC_greatest_plausible_heap_addr
+# undef GC_least_plausible_heap_addr
+}
+
+#ifndef THREADS
+/*
+ * A version of GC_push_all that treats all interior pointers as valid
+ * and scans part of the area immediately, to make sure that saved
+ * register values are not lost.
+ * Cold_gc_frame delimits the stack section that must be scanned
+ * eagerly. A zero value indicates that no eager scanning is needed.
+ * We don't need to worry about the MANUAL_VDB case here, since this
+ * is only called in the single-threaded case. We assume that we
+ * cannot collect between an assignment and the corresponding
+ * GC_dirty() call.
+ */
+void GC_push_all_stack_partially_eager(ptr_t bottom, ptr_t top,
+ ptr_t cold_gc_frame)
+{
+ if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) {
+ /* Push the hot end of the stack eagerly, so that register values */
+ /* saved inside GC frames are marked before they disappear. */
+ /* The rest of the marking can be deferred until later. */
+ if (0 == cold_gc_frame) {
+ GC_push_all_stack(bottom, top);
+ return;
+ }
+ GC_ASSERT(bottom <= cold_gc_frame && cold_gc_frame <= top);
+# ifdef STACK_GROWS_DOWN
+ GC_push_all(cold_gc_frame - sizeof(ptr_t), top);
+ GC_push_all_eager(bottom, cold_gc_frame);
+# else /* STACK_GROWS_UP */
+ GC_push_all(bottom, cold_gc_frame + sizeof(ptr_t));
+ GC_push_all_eager(cold_gc_frame, top);
+# endif /* STACK_GROWS_UP */
+ } else {
+ GC_push_all_eager(bottom, top);
+ }
+# ifdef TRACE_BUF
+ GC_add_trace_entry("GC_push_all_stack", bottom, top);
+# endif
+}
+#endif /* !THREADS */
+
+void GC_push_all_stack(ptr_t bottom, ptr_t top)
+{
+# if defined(THREADS) && defined(MPROTECT_VDB)
+ GC_push_all_eager(bottom, top);
+# else
+ if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) {
+ GC_push_all(bottom, top);
+ } else {
+ GC_push_all_eager(bottom, top);
+ }
+# endif
+}
+
+#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) && \
+ defined(MARK_BIT_PER_GRANULE)
+# if GC_GRANULE_WORDS == 1
+# define USE_PUSH_MARKED_ACCELERATORS
+# define PUSH_GRANULE(q) \
+ { ptr_t qcontents = (ptr_t)((q)[0]); \
+ GC_PUSH_ONE_HEAP(qcontents, (q)); }
+# elif GC_GRANULE_WORDS == 2
+# define USE_PUSH_MARKED_ACCELERATORS
+# define PUSH_GRANULE(q) \
+ { ptr_t qcontents = (ptr_t)((q)[0]); \
+ GC_PUSH_ONE_HEAP(qcontents, (q)); \
+ qcontents = (ptr_t)((q)[1]); \
+ GC_PUSH_ONE_HEAP(qcontents, (q)+1); }
+# elif GC_GRANULE_WORDS == 4
+# define USE_PUSH_MARKED_ACCELERATORS
+# define PUSH_GRANULE(q) \
+ { ptr_t qcontents = (ptr_t)((q)[0]); \
+ GC_PUSH_ONE_HEAP(qcontents, (q)); \
+ qcontents = (ptr_t)((q)[1]); \
+ GC_PUSH_ONE_HEAP(qcontents, (q)+1); \
+ qcontents = (ptr_t)((q)[2]); \
+ GC_PUSH_ONE_HEAP(qcontents, (q)+2); \
+ qcontents = (ptr_t)((q)[3]); \
+ GC_PUSH_ONE_HEAP(qcontents, (q)+3); }
+# endif
+#endif
+
+#ifdef USE_PUSH_MARKED_ACCELERATORS
+/* Push all objects reachable from marked objects in the given block */
+/* containing objects of size 1 granule. */
+void GC_push_marked1(struct hblk *h, hdr *hhdr)
+{
+ word * mark_word_addr = &(hhdr->hb_marks[0]);
+ word *p;
+ word *plim;
+ word *q;
+ word mark_word;
+
+ /* Allow registers to be used for some frequently acccessed */
+ /* global variables. Otherwise aliasing issues are likely */
+ /* to prevent that. */
+ ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
+ ptr_t least_ha = GC_least_plausible_heap_addr;
+ mse * mark_stack_top = GC_mark_stack_top;
+ mse * mark_stack_limit = GC_mark_stack_limit;
+# define GC_mark_stack_top mark_stack_top
+# define GC_mark_stack_limit mark_stack_limit
+# define GC_greatest_plausible_heap_addr greatest_ha
+# define GC_least_plausible_heap_addr least_ha
+
+ p = (word *)(h->hb_body);
+ plim = (word *)(((word)h) + HBLKSIZE);
+
+ /* go through all words in block */
+ while( p < plim ) {
+ mark_word = *mark_word_addr++;
+ q = p;
+ while(mark_word != 0) {
+ if (mark_word & 1) {
+ PUSH_GRANULE(q);
+ }
+ q += GC_GRANULE_WORDS;
+ mark_word >>= 1;
+ }
+ p += WORDSZ*GC_GRANULE_WORDS;
+ }
+
+# undef GC_greatest_plausible_heap_addr
+# undef GC_least_plausible_heap_addr
+# undef GC_mark_stack_top
+# undef GC_mark_stack_limit
+
+ GC_mark_stack_top = mark_stack_top;
+}
+
+
+#ifndef UNALIGNED
+
+/* Push all objects reachable from marked objects in the given block */
+/* of size 2 (granules) objects. */
+void GC_push_marked2(struct hblk *h, hdr *hhdr)
+{
+ word * mark_word_addr = &(hhdr->hb_marks[0]);
+ word *p;
+ word *plim;
+ word *q;
+ word mark_word;
+
+ ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
+ ptr_t least_ha = GC_least_plausible_heap_addr;
+ mse * mark_stack_top = GC_mark_stack_top;
+ mse * mark_stack_limit = GC_mark_stack_limit;
+
+# define GC_mark_stack_top mark_stack_top
+# define GC_mark_stack_limit mark_stack_limit
+# define GC_greatest_plausible_heap_addr greatest_ha
+# define GC_least_plausible_heap_addr least_ha
+
+ p = (word *)(h->hb_body);
+ plim = (word *)(((word)h) + HBLKSIZE);
+
+ /* go through all words in block */
+ while( p < plim ) {
+ mark_word = *mark_word_addr++;
+ q = p;
+ while(mark_word != 0) {
+ if (mark_word & 1) {
+ PUSH_GRANULE(q);
+ PUSH_GRANULE(q + GC_GRANULE_WORDS);
+ }
+ q += 2 * GC_GRANULE_WORDS;
+ mark_word >>= 2;
+ }
+ p += WORDSZ*GC_GRANULE_WORDS;
+ }
+
+# undef GC_greatest_plausible_heap_addr
+# undef GC_least_plausible_heap_addr
+# undef GC_mark_stack_top
+# undef GC_mark_stack_limit
+
+ GC_mark_stack_top = mark_stack_top;
+}
+
+# if GC_GRANULE_WORDS < 4
+/* Push all objects reachable from marked objects in the given block */
+/* of size 4 (granules) objects. */
+/* There is a risk of mark stack overflow here. But we handle that. */
+/* And only unmarked objects get pushed, so it's not very likely. */
+void GC_push_marked4(struct hblk *h, hdr *hhdr)
+{
+ word * mark_word_addr = &(hhdr->hb_marks[0]);
+ word *p;
+ word *plim;
+ word *q;
+ word mark_word;
+
+ ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
+ ptr_t least_ha = GC_least_plausible_heap_addr;
+ mse * mark_stack_top = GC_mark_stack_top;
+ mse * mark_stack_limit = GC_mark_stack_limit;
+# define GC_mark_stack_top mark_stack_top
+# define GC_mark_stack_limit mark_stack_limit
+# define GC_greatest_plausible_heap_addr greatest_ha
+# define GC_least_plausible_heap_addr least_ha
+
+ p = (word *)(h->hb_body);
+ plim = (word *)(((word)h) + HBLKSIZE);
+
+ /* go through all words in block */
+ while( p < plim ) {
+ mark_word = *mark_word_addr++;
+ q = p;
+ while(mark_word != 0) {
+ if (mark_word & 1) {
+ PUSH_GRANULE(q);
+ PUSH_GRANULE(q + GC_GRANULE_WORDS);
+ PUSH_GRANULE(q + 2*GC_GRANULE_WORDS);
+ PUSH_GRANULE(q + 3*GC_GRANULE_WORDS);
+ }
+ q += 4 * GC_GRANULE_WORDS;
+ mark_word >>= 4;
+ }
+ p += WORDSZ*GC_GRANULE_WORDS;
+ }
+# undef GC_greatest_plausible_heap_addr
+# undef GC_least_plausible_heap_addr
+# undef GC_mark_stack_top
+# undef GC_mark_stack_limit
+ GC_mark_stack_top = mark_stack_top;
+}
+
+#endif /* GC_GRANULE_WORDS < 4 */
+
+#endif /* UNALIGNED */
+
+#endif /* USE_PUSH_MARKED_ACCELERATORS */
+
+/* Push all objects reachable from marked objects in the given block */
+void GC_push_marked(struct hblk *h, hdr *hhdr)
+{
+ size_t sz = hhdr -> hb_sz;
+ word descr = hhdr -> hb_descr;
+ ptr_t p;
+ word bit_no;
+ ptr_t lim;
+ mse * GC_mark_stack_top_reg;
+ mse * mark_stack_limit = GC_mark_stack_limit;
+
+ /* Some quick shortcuts: */
+ if ((0 | GC_DS_LENGTH) == descr) return;
+ if (GC_block_empty(hhdr)/* nothing marked */) return;
+ GC_n_rescuing_pages++;
+ GC_objects_are_marked = TRUE;
+ if (sz > MAXOBJBYTES) {
+ lim = h -> hb_body;
+ } else {
+ lim = (h + 1)->hb_body - sz;
+ }
+
+ switch(BYTES_TO_GRANULES(sz)) {
+# if defined(USE_PUSH_MARKED_ACCELERATORS)
+ case 1:
+ GC_push_marked1(h, hhdr);
+ break;
+# if !defined(UNALIGNED)
+ case 2:
+ GC_push_marked2(h, hhdr);
+ break;
+# if GC_GRANULE_WORDS < 4
+ case 4:
+ GC_push_marked4(h, hhdr);
+ break;
+# endif
+# endif
+# endif
+ default:
+ GC_mark_stack_top_reg = GC_mark_stack_top;
+ for (p = h -> hb_body, bit_no = 0; p <= lim;
+ p += sz, bit_no += MARK_BIT_OFFSET(sz)) {
+ if (mark_bit_from_hdr(hhdr, bit_no)) {
+ /* Mark from fields inside the object */
+ PUSH_OBJ(p, hhdr, GC_mark_stack_top_reg, mark_stack_limit);
+ }
+ }
+ GC_mark_stack_top = GC_mark_stack_top_reg;
+ }
+}
+
+#ifndef SMALL_CONFIG
+/* Test whether any page in the given block is dirty */
+GC_bool GC_block_was_dirty(struct hblk *h, hdr *hhdr)
+{
+ size_t sz = hhdr -> hb_sz;
+
+ if (sz <= MAXOBJBYTES) {
+ return(GC_page_was_dirty(h));
+ } else {
+ ptr_t p = (ptr_t)h;
+ while (p < (ptr_t)h + sz) {
+ if (GC_page_was_dirty((struct hblk *)p)) return(TRUE);
+ p += HBLKSIZE;
+ }
+ return(FALSE);
+ }
+}
+#endif /* SMALL_CONFIG */
+
+/* Similar to GC_push_next_marked, but return address of next block */
+struct hblk * GC_push_next_marked(struct hblk *h)
+{
+ hdr * hhdr = HDR(h);
+
+ if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr), FALSE)) {
+ h = GC_next_used_block(h);
+ if (h == 0) return(0);
+ hhdr = GC_find_header((ptr_t)h);
+ }
+ GC_push_marked(h, hhdr);
+ return(h + OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz));
+}
+
+#ifndef SMALL_CONFIG
+/* Identical to above, but mark only from dirty pages */
+struct hblk * GC_push_next_marked_dirty(struct hblk *h)
+{
+ hdr * hhdr = HDR(h);
+
+ if (!GC_dirty_maintained) { ABORT("dirty bits not set up"); }
+ for (;;) {
+ if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr), FALSE)) {
+ h = GC_next_used_block(h);
+ if (h == 0) return(0);
+ hhdr = GC_find_header((ptr_t)h);
+ }
+# ifdef STUBBORN_ALLOC
+ if (hhdr -> hb_obj_kind == STUBBORN) {
+ if (GC_page_was_changed(h) && GC_block_was_dirty(h, hhdr)) {
+ break;
+ }
+ } else {
+ if (GC_block_was_dirty(h, hhdr)) break;
+ }
+# else
+ if (GC_block_was_dirty(h, hhdr)) break;
+# endif
+ h += OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
+ hhdr = HDR(h);
+ }
+ GC_push_marked(h, hhdr);
+ return(h + OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz));
+}
+#endif
+
+/* Similar to above, but for uncollectable pages. Needed since we */
+/* do not clear marks for such pages, even for full collections. */
+struct hblk * GC_push_next_marked_uncollectable(struct hblk *h)
+{
+ hdr * hhdr = HDR(h);
+
+ for (;;) {
+ if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr), FALSE)) {
+ h = GC_next_used_block(h);
+ if (h == 0) return(0);
+ hhdr = GC_find_header((ptr_t)h);
+ }
+ if (hhdr -> hb_obj_kind == UNCOLLECTABLE) break;
+ h += OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
+ hhdr = HDR(h);
+ }
+ GC_push_marked(h, hhdr);
+ return(h + OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz));
+}
+
diff --git a/tools/build/v2/engine/boehm_gc/mark_rts.c b/tools/build/v2/engine/boehm_gc/mark_rts.c
new file mode 100644
index 0000000000..05ece1c2bf
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/mark_rts.c
@@ -0,0 +1,617 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+# include <stdio.h>
+# include "private/gc_priv.h"
+
+/* Data structure for list of root sets. */
+/* We keep a hash table, so that we can filter out duplicate additions. */
+/* Under Win32, we need to do a better job of filtering overlaps, so */
+/* we resort to sequential search, and pay the price. */
+/* This is really declared in gc_priv.h:
+struct roots {
+ ptr_t r_start;
+ ptr_t r_end;
+ # if !defined(MSWIN32) && !defined(MSWINCE)
+ struct roots * r_next;
+ # endif
+ GC_bool r_tmp;
+ -- Delete before registering new dynamic libraries
+};
+
+struct roots GC_static_roots[MAX_ROOT_SETS];
+*/
+
+int GC_no_dls = 0; /* Register dynamic library data segments. */
+
+static int n_root_sets = 0;
+
+ /* GC_static_roots[0..n_root_sets) contains the valid root sets. */
+
+# if !defined(NO_DEBUGGING)
+/* For debugging: */
+void GC_print_static_roots(void)
+{
+ register int i;
+ size_t total = 0;
+
+ for (i = 0; i < n_root_sets; i++) {
+ GC_printf("From %p to %p ",
+ GC_static_roots[i].r_start,
+ GC_static_roots[i].r_end);
+ if (GC_static_roots[i].r_tmp) {
+ GC_printf(" (temporary)\n");
+ } else {
+ GC_printf("\n");
+ }
+ total += GC_static_roots[i].r_end - GC_static_roots[i].r_start;
+ }
+ GC_printf("Total size: %ld\n", (unsigned long) total);
+ if (GC_root_size != total) {
+ GC_printf("GC_root_size incorrect: %ld!!\n",
+ (unsigned long) GC_root_size);
+ }
+}
+# endif /* NO_DEBUGGING */
+
+/* Primarily for debugging support: */
+/* Is the address p in one of the registered static */
+/* root sections? */
+GC_bool GC_is_static_root(ptr_t p)
+{
+ static int last_root_set = MAX_ROOT_SETS;
+ register int i;
+
+
+ if (last_root_set < n_root_sets
+ && p >= GC_static_roots[last_root_set].r_start
+ && p < GC_static_roots[last_root_set].r_end) return(TRUE);
+ for (i = 0; i < n_root_sets; i++) {
+ if (p >= GC_static_roots[i].r_start
+ && p < GC_static_roots[i].r_end) {
+ last_root_set = i;
+ return(TRUE);
+ }
+ }
+ return(FALSE);
+}
+
+#if !defined(MSWIN32) && !defined(MSWINCE)
+/*
+# define LOG_RT_SIZE 6
+# define RT_SIZE (1 << LOG_RT_SIZE) -- Power of 2, may be != MAX_ROOT_SETS
+
+ struct roots * GC_root_index[RT_SIZE];
+ -- Hash table header. Used only to check whether a range is
+ -- already present.
+ -- really defined in gc_priv.h
+*/
+
+static INLINE int rt_hash(ptr_t addr)
+{
+ word result = (word) addr;
+# if CPP_WORDSZ > 8*LOG_RT_SIZE
+ result ^= result >> 8*LOG_RT_SIZE;
+# endif
+# if CPP_WORDSZ > 4*LOG_RT_SIZE
+ result ^= result >> 4*LOG_RT_SIZE;
+# endif
+ result ^= result >> 2*LOG_RT_SIZE;
+ result ^= result >> LOG_RT_SIZE;
+ result &= (RT_SIZE-1);
+ return(result);
+}
+
+/* Is a range starting at b already in the table? If so return a */
+/* pointer to it, else NIL. */
+struct roots * GC_roots_present(ptr_t b)
+{
+ int h = rt_hash(b);
+ struct roots *p = GC_root_index[h];
+
+ while (p != 0) {
+ if (p -> r_start == (ptr_t)b) return(p);
+ p = p -> r_next;
+ }
+ return(FALSE);
+}
+
+/* Add the given root structure to the index. */
+static void add_roots_to_index(struct roots *p)
+{
+ int h = rt_hash(p -> r_start);
+
+ p -> r_next = GC_root_index[h];
+ GC_root_index[h] = p;
+}
+
+# else /* MSWIN32 || MSWINCE */
+
+# define add_roots_to_index(p)
+
+# endif
+
+
+
+
+word GC_root_size = 0;
+
+void GC_add_roots(void *b, void *e)
+{
+ DCL_LOCK_STATE;
+
+ if (!GC_is_initialized) GC_init();
+ LOCK();
+ GC_add_roots_inner((ptr_t)b, (ptr_t)e, FALSE);
+ UNLOCK();
+}
+
+
+/* Add [b,e) to the root set. Adding the same interval a second time */
+/* is a moderately fast noop, and hence benign. We do not handle */
+/* different but overlapping intervals efficiently. (We do handle */
+/* them correctly.) */
+/* Tmp specifies that the interval may be deleted before */
+/* reregistering dynamic libraries. */
+void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp)
+{
+ struct roots * old;
+
+# if defined(MSWIN32) || defined(MSWINCE)
+ /* Spend the time to ensure that there are no overlapping */
+ /* or adjacent intervals. */
+ /* This could be done faster with e.g. a */
+ /* balanced tree. But the execution time here is */
+ /* virtually guaranteed to be dominated by the time it */
+ /* takes to scan the roots. */
+ {
+ register int i;
+
+ for (i = 0; i < n_root_sets; i++) {
+ old = GC_static_roots + i;
+ if (b <= old -> r_end && e >= old -> r_start) {
+ if (b < old -> r_start) {
+ old -> r_start = b;
+ GC_root_size += (old -> r_start - b);
+ }
+ if (e > old -> r_end) {
+ old -> r_end = e;
+ GC_root_size += (e - old -> r_end);
+ }
+ old -> r_tmp &= tmp;
+ break;
+ }
+ }
+ if (i < n_root_sets) {
+ /* merge other overlapping intervals */
+ struct roots *other;
+
+ for (i++; i < n_root_sets; i++) {
+ other = GC_static_roots + i;
+ b = other -> r_start;
+ e = other -> r_end;
+ if (b <= old -> r_end && e >= old -> r_start) {
+ if (b < old -> r_start) {
+ old -> r_start = b;
+ GC_root_size += (old -> r_start - b);
+ }
+ if (e > old -> r_end) {
+ old -> r_end = e;
+ GC_root_size += (e - old -> r_end);
+ }
+ old -> r_tmp &= other -> r_tmp;
+ /* Delete this entry. */
+ GC_root_size -= (other -> r_end - other -> r_start);
+ other -> r_start = GC_static_roots[n_root_sets-1].r_start;
+ other -> r_end = GC_static_roots[n_root_sets-1].r_end;
+ n_root_sets--;
+ }
+ }
+ return;
+ }
+ }
+# else
+ old = GC_roots_present(b);
+ if (old != 0) {
+ if (e <= old -> r_end) /* already there */ return;
+ /* else extend */
+ GC_root_size += e - old -> r_end;
+ old -> r_end = e;
+ return;
+ }
+# endif
+ if (n_root_sets == MAX_ROOT_SETS) {
+ ABORT("Too many root sets\n");
+ }
+ GC_static_roots[n_root_sets].r_start = (ptr_t)b;
+ GC_static_roots[n_root_sets].r_end = (ptr_t)e;
+ GC_static_roots[n_root_sets].r_tmp = tmp;
+# if !defined(MSWIN32) && !defined(MSWINCE)
+ GC_static_roots[n_root_sets].r_next = 0;
+# endif
+ add_roots_to_index(GC_static_roots + n_root_sets);
+ GC_root_size += e - b;
+ n_root_sets++;
+}
+
+static GC_bool roots_were_cleared = FALSE;
+
+void GC_clear_roots (void)
+{
+ DCL_LOCK_STATE;
+
+ if (!GC_is_initialized) GC_init();
+ LOCK();
+ roots_were_cleared = TRUE;
+ n_root_sets = 0;
+ GC_root_size = 0;
+# if !defined(MSWIN32) && !defined(MSWINCE)
+ {
+ register int i;
+
+ for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0;
+ }
+# endif
+ UNLOCK();
+}
+
+/* Internal use only; lock held. */
+static void GC_remove_root_at_pos(int i)
+{
+ GC_root_size -= (GC_static_roots[i].r_end - GC_static_roots[i].r_start);
+ GC_static_roots[i].r_start = GC_static_roots[n_root_sets-1].r_start;
+ GC_static_roots[i].r_end = GC_static_roots[n_root_sets-1].r_end;
+ GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets-1].r_tmp;
+ n_root_sets--;
+}
+
+#if !defined(MSWIN32) && !defined(MSWINCE)
+static void GC_rebuild_root_index(void)
+{
+ int i;
+
+ for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0;
+ for (i = 0; i < n_root_sets; i++)
+ add_roots_to_index(GC_static_roots + i);
+}
+#endif
+
+/* Internal use only; lock held. */
+void GC_remove_tmp_roots(void)
+{
+ int i;
+
+ for (i = 0; i < n_root_sets; ) {
+ if (GC_static_roots[i].r_tmp) {
+ GC_remove_root_at_pos(i);
+ } else {
+ i++;
+ }
+ }
+ #if !defined(MSWIN32) && !defined(MSWINCE)
+ GC_rebuild_root_index();
+ #endif
+}
+
+#if !defined(MSWIN32) && !defined(MSWINCE)
+void GC_remove_roots(void *b, void *e)
+{
+ DCL_LOCK_STATE;
+
+ LOCK();
+ GC_remove_roots_inner((ptr_t)b, (ptr_t)e);
+ UNLOCK();
+}
+
+/* Should only be called when the lock is held */
+void GC_remove_roots_inner(ptr_t b, ptr_t e)
+{
+ int i;
+ for (i = 0; i < n_root_sets; ) {
+ if (GC_static_roots[i].r_start >= b
+ && GC_static_roots[i].r_end <= e) {
+ GC_remove_root_at_pos(i);
+ } else {
+ i++;
+ }
+ }
+ GC_rebuild_root_index();
+}
+#endif /* !defined(MSWIN32) && !defined(MSWINCE) */
+
+#if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION)
+/* Workaround for the OS mapping and unmapping behind our back: */
+/* Is the address p in one of the temporary static root sections? */
+GC_bool GC_is_tmp_root(ptr_t p)
+{
+ static int last_root_set = MAX_ROOT_SETS;
+ register int i;
+
+ if (last_root_set < n_root_sets
+ && p >= GC_static_roots[last_root_set].r_start
+ && p < GC_static_roots[last_root_set].r_end)
+ return GC_static_roots[last_root_set].r_tmp;
+ for (i = 0; i < n_root_sets; i++) {
+ if (p >= GC_static_roots[i].r_start
+ && p < GC_static_roots[i].r_end) {
+ last_root_set = i;
+ return GC_static_roots[i].r_tmp;
+ }
+ }
+ return(FALSE);
+}
+#endif /* MSWIN32 || _WIN32_WCE_EMULATION */
+
+ptr_t GC_approx_sp(void)
+{
+ volatile word dummy;
+
+ dummy = 42; /* Force stack to grow if necessary. Otherwise the */
+ /* later accesses might cause the kernel to think we're */
+ /* doing something wrong. */
+# ifdef _MSC_VER
+# pragma warning(disable:4172)
+# endif
+ return((ptr_t)(&dummy));
+# ifdef _MSC_VER
+# pragma warning(default:4172)
+# endif
+}
+
+/*
+ * Data structure for excluded static roots.
+ * Real declaration is in gc_priv.h.
+
+struct exclusion {
+ ptr_t e_start;
+ ptr_t e_end;
+};
+
+struct exclusion GC_excl_table[MAX_EXCLUSIONS];
+ -- Array of exclusions, ascending
+ -- address order.
+*/
+
+size_t GC_excl_table_entries = 0; /* Number of entries in use. */
+
+/* Return the first exclusion range that includes an address >= start_addr */
+/* Assumes the exclusion table contains at least one entry (namely the */
+/* GC data structures). */
+struct exclusion * GC_next_exclusion(ptr_t start_addr)
+{
+ size_t low = 0;
+ size_t high = GC_excl_table_entries - 1;
+ size_t mid;
+
+ while (high > low) {
+ mid = (low + high) >> 1;
+ /* low <= mid < high */
+ if ((word) GC_excl_table[mid].e_end <= (word) start_addr) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ if ((word) GC_excl_table[low].e_end <= (word) start_addr) return 0;
+ return GC_excl_table + low;
+}
+
+void GC_exclude_static_roots(void *start, void *finish)
+{
+ struct exclusion * next;
+ size_t next_index, i;
+
+ if (0 == GC_excl_table_entries) {
+ next = 0;
+ } else {
+ next = GC_next_exclusion(start);
+ }
+ if (0 != next) {
+ if ((word)(next -> e_start) < (word) finish) {
+ /* incomplete error check. */
+ ABORT("exclusion ranges overlap");
+ }
+ if ((word)(next -> e_start) == (word) finish) {
+ /* extend old range backwards */
+ next -> e_start = (ptr_t)start;
+ return;
+ }
+ next_index = next - GC_excl_table;
+ for (i = GC_excl_table_entries; i > next_index; --i) {
+ GC_excl_table[i] = GC_excl_table[i-1];
+ }
+ } else {
+ next_index = GC_excl_table_entries;
+ }
+ if (GC_excl_table_entries == MAX_EXCLUSIONS) ABORT("Too many exclusions");
+ GC_excl_table[next_index].e_start = (ptr_t)start;
+ GC_excl_table[next_index].e_end = (ptr_t)finish;
+ ++GC_excl_table_entries;
+}
+
+/* Invoke push_conditional on ranges that are not excluded. */
+void GC_push_conditional_with_exclusions(ptr_t bottom, ptr_t top, GC_bool all)
+{
+ struct exclusion * next;
+ ptr_t excl_start;
+
+ while (bottom < top) {
+ next = GC_next_exclusion(bottom);
+ if (0 == next || (excl_start = next -> e_start) >= top) {
+ GC_push_conditional(bottom, top, all);
+ return;
+ }
+ if (excl_start > bottom) GC_push_conditional(bottom, excl_start, all);
+ bottom = next -> e_end;
+ }
+}
+
+/*
+ * In the absence of threads, push the stack contents.
+ * In the presence of threads, push enough of the current stack
+ * to ensure that callee-save registers saved in collector frames have been
+ * seen.
+ * FIXME: Merge with per-thread stuff.
+ */
+void GC_push_current_stack(ptr_t cold_gc_frame, void * context)
+{
+# if defined(THREADS)
+ if (0 == cold_gc_frame) return;
+# ifdef STACK_GROWS_DOWN
+ GC_push_all_eager(GC_approx_sp(), cold_gc_frame);
+ /* For IA64, the register stack backing store is handled */
+ /* in the thread-specific code. */
+# else
+ GC_push_all_eager( cold_gc_frame, GC_approx_sp() );
+# endif
+# else
+# ifdef STACK_GROWS_DOWN
+ GC_push_all_stack_partially_eager( GC_approx_sp(), GC_stackbottom,
+ cold_gc_frame );
+# ifdef IA64
+ /* We also need to push the register stack backing store. */
+ /* This should really be done in the same way as the */
+ /* regular stack. For now we fudge it a bit. */
+ /* Note that the backing store grows up, so we can't use */
+ /* GC_push_all_stack_partially_eager. */
+ {
+ extern word GC_save_regs_ret_val;
+ /* Previously set to backing store pointer. */
+ ptr_t bsp = (ptr_t) GC_save_regs_ret_val;
+ ptr_t cold_gc_bs_pointer;
+ if (GC_all_interior_pointers) {
+ cold_gc_bs_pointer = bsp - 2048;
+ if (cold_gc_bs_pointer < BACKING_STORE_BASE) {
+ cold_gc_bs_pointer = BACKING_STORE_BASE;
+ } else {
+ GC_push_all_stack(BACKING_STORE_BASE, cold_gc_bs_pointer);
+ }
+ } else {
+ cold_gc_bs_pointer = BACKING_STORE_BASE;
+ }
+ GC_push_all_eager(cold_gc_bs_pointer, bsp);
+ /* All values should be sufficiently aligned that we */
+ /* dont have to worry about the boundary. */
+ }
+# endif
+# else
+ GC_push_all_stack_partially_eager( GC_stackbottom, GC_approx_sp(),
+ cold_gc_frame );
+# endif
+# endif /* !THREADS */
+}
+
+/*
+ * Push GC internal roots. Only called if there is some reason to believe
+ * these would not otherwise get registered.
+ */
+void GC_push_gc_structures(void)
+{
+ GC_push_finalizer_structures();
+# if defined(THREADS)
+ GC_push_thread_structures();
+# endif
+}
+
+#ifdef THREAD_LOCAL_ALLOC
+ void GC_mark_thread_local_free_lists(void);
+#endif
+
+void GC_cond_register_dynamic_libraries(void)
+{
+# if defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \
+ || defined(PCR)
+ GC_remove_tmp_roots();
+ if (!GC_no_dls) GC_register_dynamic_libraries();
+# else
+ GC_no_dls = TRUE;
+# endif
+}
+
+/*
+ * Call the mark routines (GC_tl_push for a single pointer, GC_push_conditional
+ * on groups of pointers) on every top level accessible pointer.
+ * If all is FALSE, arrange to push only possibly altered values.
+ * Cold_gc_frame is an address inside a GC frame that
+ * remains valid until all marking is complete.
+ * A zero value indicates that it's OK to miss some
+ * register values.
+ */
+void GC_push_roots(GC_bool all, ptr_t cold_gc_frame)
+{
+ int i;
+ unsigned kind;
+
+ /*
+ * Next push static data. This must happen early on, since it's
+ * not robust against mark stack overflow.
+ */
+ /* Reregister dynamic libraries, in case one got added. */
+ /* There is some argument for doing this as late as possible, */
+ /* especially on win32, where it can change asynchronously. */
+ /* In those cases, we do it here. But on other platforms, it's */
+ /* not safe with the world stopped, so we do it earlier. */
+# if !defined(REGISTER_LIBRARIES_EARLY)
+ GC_cond_register_dynamic_libraries();
+# endif
+
+ /* Mark everything in static data areas */
+ for (i = 0; i < n_root_sets; i++) {
+ GC_push_conditional_with_exclusions(
+ GC_static_roots[i].r_start,
+ GC_static_roots[i].r_end, all);
+ }
+
+ /* Mark all free list header blocks, if those were allocated from */
+ /* the garbage collected heap. This makes sure they don't */
+ /* disappear if we are not marking from static data. It also */
+ /* saves us the trouble of scanning them, and possibly that of */
+ /* marking the freelists. */
+ for (kind = 0; kind < GC_n_kinds; kind++) {
+ void *base = GC_base(GC_obj_kinds[kind].ok_freelist);
+ if (0 != base) {
+ GC_set_mark_bit(base);
+ }
+ }
+
+ /* Mark from GC internal roots if those might otherwise have */
+ /* been excluded. */
+ if (GC_no_dls || roots_were_cleared) {
+ GC_push_gc_structures();
+ }
+
+ /* Mark thread local free lists, even if their mark */
+ /* descriptor excludes the link field. */
+ /* If the world is not stopped, this is unsafe. It is */
+ /* also unnecessary, since we will do this again with the */
+ /* world stopped. */
+# if defined(THREAD_LOCAL_ALLOC)
+ if (GC_world_stopped) GC_mark_thread_local_free_lists();
+# endif
+
+ /*
+ * Now traverse stacks, and mark from register contents.
+ * These must be done last, since they can legitimately overflow
+ * the mark stack.
+ * This is usually done by saving the current context on the
+ * stack, and then just tracing from the stack.
+ */
+ GC_push_regs_and_stack(cold_gc_frame);
+
+ if (GC_push_other_roots != 0) (*GC_push_other_roots)();
+ /* In the threads case, this also pushes thread stacks. */
+ /* Note that without interior pointer recognition lots */
+ /* of stuff may have been pushed already, and this */
+ /* should be careful about mark stack overflows. */
+}
+
diff --git a/tools/build/v2/engine/boehm_gc/mips_sgi_mach_dep.s b/tools/build/v2/engine/boehm_gc/mips_sgi_mach_dep.s
new file mode 100644
index 0000000000..56390280a7
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/mips_sgi_mach_dep.s
@@ -0,0 +1,46 @@
+#include <sys/regdef.h>
+#include <sys/asm.h>
+/* This file must be preprocessed. But the SGI assembler always does */
+/* that. Furthermore, a generic preprocessor won't do, since some of */
+/* the SGI-supplied include files rely on behavior of the MIPS */
+/* assembler. Hence we treat and name this file as though it required */
+/* no preprocessing. */
+
+# define call_push(x) move $4,x; jal GC_push_one
+
+ .option pic2
+ .text
+/* Mark from machine registers that are saved by C compiler */
+# define FRAMESZ 32
+# define RAOFF FRAMESZ-SZREG
+# define GPOFF FRAMESZ-(2*SZREG)
+ NESTED(GC_push_regs, FRAMESZ, ra)
+ .mask 0x80000000,-SZREG # inform debugger of saved ra loc
+ move t0,gp
+ SETUP_GPX(t8)
+ PTR_SUBU sp,FRAMESZ
+# ifdef SETUP_GP64
+ SETUP_GP64(GPOFF, GC_push_regs)
+# endif
+ SAVE_GP(GPOFF)
+ REG_S ra,RAOFF(sp)
+# if (_MIPS_SIM == _MIPS_SIM_ABI32)
+ call_push($2)
+ call_push($3)
+# endif
+ call_push($16)
+ call_push($17)
+ call_push($18)
+ call_push($19)
+ call_push($20)
+ call_push($21)
+ call_push($22)
+ call_push($23)
+ call_push($30)
+ REG_L ra,RAOFF(sp)
+# ifdef RESTORE_GP64
+ RESTORE_GP64
+# endif
+ PTR_ADDU sp,FRAMESZ
+ j ra
+ .end GC_push_regs
diff --git a/tools/build/v2/engine/boehm_gc/mips_ultrix_mach_dep.s b/tools/build/v2/engine/boehm_gc/mips_ultrix_mach_dep.s
new file mode 100644
index 0000000000..178224e31c
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/mips_ultrix_mach_dep.s
@@ -0,0 +1,26 @@
+# define call_push(x) move $4,x; jal GC_push_one
+
+ .text
+ # Mark from machine registers that are saved by C compiler
+ .globl GC_push_regs
+ .ent GC_push_regs
+GC_push_regs:
+ subu $sp,8 ## Need to save only return address
+ sw $31,4($sp)
+ .mask 0x80000000,-4
+ .frame $sp,8,$31
+ call_push($2)
+ call_push($3)
+ call_push($16)
+ call_push($17)
+ call_push($18)
+ call_push($19)
+ call_push($20)
+ call_push($21)
+ call_push($22)
+ call_push($23)
+ call_push($30)
+ lw $31,4($sp)
+ addu $sp,8
+ j $31
+ .end GC_push_regs
diff --git a/tools/build/v2/engine/boehm_gc/misc.c b/tools/build/v2/engine/boehm_gc/misc.c
new file mode 100644
index 0000000000..37e509336a
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/misc.c
@@ -0,0 +1,1177 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, July 31, 1995 5:02 pm PDT */
+
+
+#include <stdio.h>
+#include <limits.h>
+#include <stdarg.h>
+#ifndef _WIN32_WCE
+#include <signal.h>
+#endif
+
+#define I_HIDE_POINTERS /* To make GC_call_with_alloc_lock visible */
+#include "private/gc_pmark.h"
+
+#ifdef GC_SOLARIS_THREADS
+# include <sys/syscall.h>
+#endif
+#if defined(MSWIN32) || defined(MSWINCE)
+# define WIN32_LEAN_AND_MEAN
+# define NOSERVICE
+# include <windows.h>
+# include <tchar.h>
+#endif
+
+#ifdef UNIX_LIKE
+# include <fcntl.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+
+ int GC_log; /* Forward decl, so we can set it. */
+#endif
+
+#ifdef NONSTOP
+# include <floss.h>
+#endif
+
+#if defined(THREADS) && defined(PCR)
+# include "il/PCR_IL.h"
+ PCR_Th_ML GC_allocate_ml;
+#endif
+/* For other platforms with threads, the lock and possibly */
+/* GC_lock_holder variables are defined in the thread support code. */
+
+#if defined(NOSYS) || defined(ECOS)
+#undef STACKBASE
+#endif
+
+/* Dont unnecessarily call GC_register_main_static_data() in case */
+/* dyn_load.c isn't linked in. */
+#ifdef DYNAMIC_LOADING
+# define GC_REGISTER_MAIN_STATIC_DATA() GC_register_main_static_data()
+#else
+# define GC_REGISTER_MAIN_STATIC_DATA() TRUE
+#endif
+
+GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */;
+
+
+GC_bool GC_debugging_started = FALSE;
+ /* defined here so we don't have to load debug_malloc.o */
+
+void (*GC_check_heap) (void) = (void (*) (void))0;
+void (*GC_print_all_smashed) (void) = (void (*) (void))0;
+
+void (*GC_start_call_back) (void) = (void (*) (void))0;
+
+ptr_t GC_stackbottom = 0;
+
+#ifdef IA64
+ ptr_t GC_register_stackbottom = 0;
+#endif
+
+GC_bool GC_dont_gc = 0;
+
+GC_bool GC_dont_precollect = 0;
+
+GC_bool GC_quiet = 0;
+
+#ifndef SMALL_CONFIG
+ GC_bool GC_print_stats = 0;
+#endif
+
+GC_bool GC_print_back_height = 0;
+
+#ifndef NO_DEBUGGING
+ GC_bool GC_dump_regularly = 0; /* Generate regular debugging dumps. */
+#endif
+
+#ifdef KEEP_BACK_PTRS
+ long GC_backtraces = 0; /* Number of random backtraces to */
+ /* generate for each GC. */
+#endif
+
+#ifdef FIND_LEAK
+ int GC_find_leak = 1;
+#else
+ int GC_find_leak = 0;
+#endif
+
+#ifdef ALL_INTERIOR_POINTERS
+ int GC_all_interior_pointers = 1;
+#else
+ int GC_all_interior_pointers = 0;
+#endif
+
+long GC_large_alloc_warn_interval = 5;
+ /* Interval between unsuppressed warnings. */
+
+long GC_large_alloc_warn_suppressed = 0;
+ /* Number of warnings suppressed so far. */
+
+/*ARGSUSED*/
+void * GC_default_oom_fn(size_t bytes_requested)
+{
+ return(0);
+}
+
+void * (*GC_oom_fn) (size_t bytes_requested) = GC_default_oom_fn;
+
+void * GC_project2(void *arg1, void *arg2)
+{
+ return arg2;
+}
+
+/* Set things up so that GC_size_map[i] >= granules(i), */
+/* but not too much bigger */
+/* and so that size_map contains relatively few distinct entries */
+/* This was originally stolen from Russ Atkinson's Cedar */
+/* quantization alogrithm (but we precompute it). */
+void GC_init_size_map(void)
+{
+ int i;
+
+ /* Map size 0 to something bigger. */
+ /* This avoids problems at lower levels. */
+ GC_size_map[0] = 1;
+ for (i = 1; i <= GRANULES_TO_BYTES(TINY_FREELISTS-1) - EXTRA_BYTES; i++) {
+ GC_size_map[i] = ROUNDED_UP_GRANULES(i);
+ GC_ASSERT(GC_size_map[i] < TINY_FREELISTS);
+ }
+ /* We leave the rest of the array to be filled in on demand. */
+}
+
+/* Fill in additional entries in GC_size_map, including the ith one */
+/* We assume the ith entry is currently 0. */
+/* Note that a filled in section of the array ending at n always */
+/* has length at least n/4. */
+void GC_extend_size_map(size_t i)
+{
+ size_t orig_granule_sz = ROUNDED_UP_GRANULES(i);
+ size_t granule_sz = orig_granule_sz;
+ size_t byte_sz = GRANULES_TO_BYTES(granule_sz);
+ /* The size we try to preserve. */
+ /* Close to i, unless this would */
+ /* introduce too many distinct sizes. */
+ size_t smaller_than_i = byte_sz - (byte_sz >> 3);
+ size_t much_smaller_than_i = byte_sz - (byte_sz >> 2);
+ size_t low_limit; /* The lowest indexed entry we */
+ /* initialize. */
+ size_t j;
+
+ if (GC_size_map[smaller_than_i] == 0) {
+ low_limit = much_smaller_than_i;
+ while (GC_size_map[low_limit] != 0) low_limit++;
+ } else {
+ low_limit = smaller_than_i + 1;
+ while (GC_size_map[low_limit] != 0) low_limit++;
+ granule_sz = ROUNDED_UP_GRANULES(low_limit);
+ granule_sz += granule_sz >> 3;
+ if (granule_sz < orig_granule_sz) granule_sz = orig_granule_sz;
+ }
+ /* For these larger sizes, we use an even number of granules. */
+ /* This makes it easier to, for example, construct a 16byte-aligned */
+ /* allocator even if GRANULE_BYTES is 8. */
+ granule_sz += 1;
+ granule_sz &= ~1;
+ if (granule_sz > MAXOBJGRANULES) {
+ granule_sz = MAXOBJGRANULES;
+ }
+ /* If we can fit the same number of larger objects in a block, */
+ /* do so. */
+ {
+ size_t number_of_objs = HBLK_GRANULES/granule_sz;
+ granule_sz = HBLK_GRANULES/number_of_objs;
+ granule_sz &= ~1;
+ }
+ byte_sz = GRANULES_TO_BYTES(granule_sz);
+ /* We may need one extra byte; */
+ /* don't always fill in GC_size_map[byte_sz] */
+ byte_sz -= EXTRA_BYTES;
+
+ for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = granule_sz;
+}
+
+
+/*
+ * The following is a gross hack to deal with a problem that can occur
+ * on machines that are sloppy about stack frame sizes, notably SPARC.
+ * Bogus pointers may be written to the stack and not cleared for
+ * a LONG time, because they always fall into holes in stack frames
+ * that are not written. We partially address this by clearing
+ * sections of the stack whenever we get control.
+ */
+word GC_stack_last_cleared = 0; /* GC_no when we last did this */
+# ifdef THREADS
+# define BIG_CLEAR_SIZE 2048 /* Clear this much now and then. */
+# define SMALL_CLEAR_SIZE 256 /* Clear this much every time. */
+# endif
+# define CLEAR_SIZE 213 /* Granularity for GC_clear_stack_inner */
+# define DEGRADE_RATE 50
+
+ptr_t GC_min_sp; /* Coolest stack pointer value from which we've */
+ /* already cleared the stack. */
+
+ptr_t GC_high_water;
+ /* "hottest" stack pointer value we have seen */
+ /* recently. Degrades over time. */
+
+word GC_bytes_allocd_at_reset;
+
+#if defined(ASM_CLEAR_CODE)
+ extern void *GC_clear_stack_inner(void *, ptr_t);
+#else
+/* Clear the stack up to about limit. Return arg. */
+/*ARGSUSED*/
+void * GC_clear_stack_inner(void *arg, ptr_t limit)
+{
+ word dummy[CLEAR_SIZE];
+
+ BZERO(dummy, CLEAR_SIZE*sizeof(word));
+ if ((ptr_t)(dummy) COOLER_THAN limit) {
+ (void) GC_clear_stack_inner(arg, limit);
+ }
+ /* Make sure the recursive call is not a tail call, and the bzero */
+ /* call is not recognized as dead code. */
+ GC_noop1((word)dummy);
+ return(arg);
+}
+#endif
+
+/* Clear some of the inaccessible part of the stack. Returns its */
+/* argument, so it can be used in a tail call position, hence clearing */
+/* another frame. */
+void * GC_clear_stack(void *arg)
+{
+ ptr_t sp = GC_approx_sp(); /* Hotter than actual sp */
+# ifdef THREADS
+ word dummy[SMALL_CLEAR_SIZE];
+ static unsigned random_no = 0;
+ /* Should be more random than it is ... */
+ /* Used to occasionally clear a bigger */
+ /* chunk. */
+# endif
+ ptr_t limit;
+
+# define SLOP 400
+ /* Extra bytes we clear every time. This clears our own */
+ /* activation record, and should cause more frequent */
+ /* clearing near the cold end of the stack, a good thing. */
+# define GC_SLOP 4000
+ /* We make GC_high_water this much hotter than we really saw */
+ /* saw it, to cover for GC noise etc. above our current frame. */
+# define CLEAR_THRESHOLD 100000
+ /* We restart the clearing process after this many bytes of */
+ /* allocation. Otherwise very heavily recursive programs */
+ /* with sparse stacks may result in heaps that grow almost */
+ /* without bounds. As the heap gets larger, collection */
+ /* frequency decreases, thus clearing frequency would decrease, */
+ /* thus more junk remains accessible, thus the heap gets */
+ /* larger ... */
+# ifdef THREADS
+ if (++random_no % 13 == 0) {
+ limit = sp;
+ MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word));
+ limit = (ptr_t)((word)limit & ~0xf);
+ /* Make it sufficiently aligned for assembly */
+ /* implementations of GC_clear_stack_inner. */
+ return GC_clear_stack_inner(arg, limit);
+ } else {
+ BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word));
+ return arg;
+ }
+# else
+ if (GC_gc_no > GC_stack_last_cleared) {
+ /* Start things over, so we clear the entire stack again */
+ if (GC_stack_last_cleared == 0) GC_high_water = (ptr_t)GC_stackbottom;
+ GC_min_sp = GC_high_water;
+ GC_stack_last_cleared = GC_gc_no;
+ GC_bytes_allocd_at_reset = GC_bytes_allocd;
+ }
+ /* Adjust GC_high_water */
+ MAKE_COOLER(GC_high_water, WORDS_TO_BYTES(DEGRADE_RATE) + GC_SLOP);
+ if (sp HOTTER_THAN GC_high_water) {
+ GC_high_water = sp;
+ }
+ MAKE_HOTTER(GC_high_water, GC_SLOP);
+ limit = GC_min_sp;
+ MAKE_HOTTER(limit, SLOP);
+ if (sp COOLER_THAN limit) {
+ limit = (ptr_t)((word)limit & ~0xf);
+ /* Make it sufficiently aligned for assembly */
+ /* implementations of GC_clear_stack_inner. */
+ GC_min_sp = sp;
+ return(GC_clear_stack_inner(arg, limit));
+ } else if (GC_bytes_allocd - GC_bytes_allocd_at_reset > CLEAR_THRESHOLD) {
+ /* Restart clearing process, but limit how much clearing we do. */
+ GC_min_sp = sp;
+ MAKE_HOTTER(GC_min_sp, CLEAR_THRESHOLD/4);
+ if (GC_min_sp HOTTER_THAN GC_high_water) GC_min_sp = GC_high_water;
+ GC_bytes_allocd_at_reset = GC_bytes_allocd;
+ }
+ return(arg);
+# endif
+}
+
+
+/* Return a pointer to the base address of p, given a pointer to a */
+/* an address within an object. Return 0 o.w. */
+void * GC_base(void * p)
+{
+ ptr_t r;
+ struct hblk *h;
+ bottom_index *bi;
+ hdr *candidate_hdr;
+ ptr_t limit;
+
+ r = p;
+ if (!GC_is_initialized) return 0;
+ h = HBLKPTR(r);
+ GET_BI(r, bi);
+ candidate_hdr = HDR_FROM_BI(bi, r);
+ if (candidate_hdr == 0) return(0);
+ /* If it's a pointer to the middle of a large object, move it */
+ /* to the beginning. */
+ while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) {
+ h = FORWARDED_ADDR(h,candidate_hdr);
+ r = (ptr_t)h;
+ candidate_hdr = HDR(h);
+ }
+ if (HBLK_IS_FREE(candidate_hdr)) return(0);
+ /* Make sure r points to the beginning of the object */
+ r = (ptr_t)((word)r & ~(WORDS_TO_BYTES(1) - 1));
+ {
+ size_t offset = HBLKDISPL(r);
+ signed_word sz = candidate_hdr -> hb_sz;
+ size_t obj_displ = offset % sz;
+
+ r -= obj_displ;
+ limit = r + sz;
+ if (limit > (ptr_t)(h + 1) && sz <= HBLKSIZE) {
+ return(0);
+ }
+ if ((ptr_t)p >= limit) return(0);
+ }
+ return((void *)r);
+}
+
+
+/* Return the size of an object, given a pointer to its base. */
+/* (For small obects this also happens to work from interior pointers, */
+/* but that shouldn't be relied upon.) */
+size_t GC_size(void * p)
+{
+ hdr * hhdr = HDR(p);
+
+ return hhdr -> hb_sz;
+}
+
+size_t GC_get_heap_size(void)
+{
+ return GC_heapsize;
+}
+
+size_t GC_get_free_bytes(void)
+{
+ return GC_large_free_bytes;
+}
+
+size_t GC_get_bytes_since_gc(void)
+{
+ return GC_bytes_allocd;
+}
+
+size_t GC_get_total_bytes(void)
+{
+ return GC_bytes_allocd+GC_bytes_allocd_before_gc;
+}
+
+GC_bool GC_is_initialized = FALSE;
+
+# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+ extern void GC_init_parallel(void);
+# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
+
+void GC_init(void)
+{
+ DCL_LOCK_STATE;
+
+#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
+ if (!GC_is_initialized) {
+ BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL;
+ HMODULE hK32 = GetModuleHandleA("kernel32.dll");
+ if (hK32)
+ pfn = (BOOL (WINAPI *) (LPCRITICAL_SECTION, DWORD))
+ GetProcAddress (hK32,
+ "InitializeCriticalSectionAndSpinCount");
+ if (pfn)
+ pfn(&GC_allocate_ml, 4000);
+ else
+ InitializeCriticalSection (&GC_allocate_ml);
+ }
+#endif /* MSWIN32 */
+
+ LOCK();
+ GC_init_inner();
+ UNLOCK();
+
+# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+ /* Make sure marker threads and started and thread local */
+ /* allocation is initialized, in case we didn't get */
+ /* called from GC_init_parallel(); */
+ {
+ GC_init_parallel();
+ }
+# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
+
+# if defined(DYNAMIC_LOADING) && defined(DARWIN)
+ {
+ /* This must be called WITHOUT the allocation lock held
+ and before any threads are created */
+ extern void GC_init_dyld();
+ GC_init_dyld();
+ }
+# endif
+}
+
+#if defined(MSWIN32) || defined(MSWINCE)
+ CRITICAL_SECTION GC_write_cs;
+#endif
+
+#ifdef MSWIN32
+ extern void GC_init_win32(void);
+#endif
+
+extern void GC_setpagesize();
+
+
+#ifdef MSWIN32
+extern GC_bool GC_no_win32_dlls;
+#else
+# define GC_no_win32_dlls FALSE
+#endif
+
+void GC_exit_check(void)
+{
+ GC_gcollect();
+}
+
+#ifdef SEARCH_FOR_DATA_START
+ extern void GC_init_linux_data_start(void);
+#endif
+
+#ifdef UNIX_LIKE
+
+extern void GC_set_and_save_fault_handler(void (*handler)(int));
+
+static void looping_handler(sig)
+int sig;
+{
+ GC_err_printf("Caught signal %d: looping in handler\n", sig);
+ for(;;);
+}
+
+static GC_bool installed_looping_handler = FALSE;
+
+static void maybe_install_looping_handler()
+{
+ /* Install looping handler before the write fault handler, so we */
+ /* handle write faults correctly. */
+ if (!installed_looping_handler && 0 != GETENV("GC_LOOP_ON_ABORT")) {
+ GC_set_and_save_fault_handler(looping_handler);
+ installed_looping_handler = TRUE;
+ }
+}
+
+#else /* !UNIX_LIKE */
+
+# define maybe_install_looping_handler()
+
+#endif
+
+void GC_init_inner()
+{
+# if !defined(THREADS) && defined(GC_ASSERTIONS)
+ word dummy;
+# endif
+ word initial_heap_sz = (word)MINHINCR;
+
+ if (GC_is_initialized) return;
+# if defined(MSWIN32) || defined(MSWINCE)
+ InitializeCriticalSection(&GC_write_cs);
+# endif
+# if (!defined(SMALL_CONFIG))
+ if (0 != GETENV("GC_PRINT_STATS")) {
+ GC_print_stats = 1;
+ }
+ if (0 != GETENV("GC_PRINT_VERBOSE_STATS")) {
+ GC_print_stats = VERBOSE;
+ }
+# if defined(UNIX_LIKE)
+ {
+ char * file_name = GETENV("GC_LOG_FILE");
+ if (0 != file_name) {
+ int log_d = open(file_name, O_CREAT|O_WRONLY|O_APPEND, 0666);
+ if (log_d < 0) {
+ GC_log_printf("Failed to open %s as log file\n", file_name);
+ } else {
+ GC_log = log_d;
+ }
+ }
+ }
+# endif
+# endif
+# ifndef NO_DEBUGGING
+ if (0 != GETENV("GC_DUMP_REGULARLY")) {
+ GC_dump_regularly = 1;
+ }
+# endif
+# ifdef KEEP_BACK_PTRS
+ {
+ char * backtraces_string = GETENV("GC_BACKTRACES");
+ if (0 != backtraces_string) {
+ GC_backtraces = atol(backtraces_string);
+ if (backtraces_string[0] == '\0') GC_backtraces = 1;
+ }
+ }
+# endif
+ if (0 != GETENV("GC_FIND_LEAK")) {
+ GC_find_leak = 1;
+ atexit(GC_exit_check);
+ }
+ if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) {
+ GC_all_interior_pointers = 1;
+ }
+ if (0 != GETENV("GC_DONT_GC")) {
+ GC_dont_gc = 1;
+ }
+ if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) {
+ GC_print_back_height = 1;
+ }
+ if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) {
+ GC_large_alloc_warn_interval = LONG_MAX;
+ }
+ {
+ char * addr_string = GETENV("GC_TRACE");
+ if (0 != addr_string) {
+# ifndef ENABLE_TRACE
+ WARN("Tracing not enabled: Ignoring GC_TRACE value\n", 0);
+# else
+# ifdef STRTOULL
+ long long addr = strtoull(addr_string, NULL, 16);
+# else
+ long addr = strtoul(addr_string, NULL, 16);
+# endif
+ if (addr < 0x1000)
+ WARN("Unlikely trace address: 0x%lx\n", (GC_word)addr);
+ GC_trace_addr = (ptr_t)addr;
+# endif
+ }
+ }
+ {
+ char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET");
+ if (0 != time_limit_string) {
+ long time_limit = atol(time_limit_string);
+ if (time_limit < 5) {
+ WARN("GC_PAUSE_TIME_TARGET environment variable value too small "
+ "or bad syntax: Ignoring\n", 0);
+ } else {
+ GC_time_limit = time_limit;
+ }
+ }
+ }
+ {
+ char * interval_string = GETENV("GC_LARGE_ALLOC_WARN_INTERVAL");
+ if (0 != interval_string) {
+ long interval = atol(interval_string);
+ if (interval <= 0) {
+ WARN("GC_LARGE_ALLOC_WARN_INTERVAL environment variable has "
+ "bad value: Ignoring\n", 0);
+ } else {
+ GC_large_alloc_warn_interval = interval;
+ }
+ }
+ }
+ maybe_install_looping_handler();
+ /* Adjust normal object descriptor for extra allocation. */
+ if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) {
+ GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH);
+ }
+ GC_setpagesize();
+ GC_exclude_static_roots(beginGC_arrays, endGC_arrays);
+ GC_exclude_static_roots(beginGC_obj_kinds, endGC_obj_kinds);
+# ifdef SEPARATE_GLOBALS
+ GC_exclude_static_roots(beginGC_objfreelist, endGC_objfreelist);
+ GC_exclude_static_roots(beginGC_aobjfreelist, endGC_aobjfreelist);
+# endif
+# ifdef MSWIN32
+ GC_init_win32();
+# endif
+# if defined(USE_PROC_FOR_LIBRARIES) && defined(GC_LINUX_THREADS)
+ WARN("USE_PROC_FOR_LIBRARIES + GC_LINUX_THREADS performs poorly.\n", 0);
+ /* If thread stacks are cached, they tend to be scanned in */
+ /* entirety as part of the root set. This wil grow them to */
+ /* maximum size, and is generally not desirable. */
+# endif
+# if defined(SEARCH_FOR_DATA_START)
+ GC_init_linux_data_start();
+# endif
+# if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
+ GC_init_netbsd_elf();
+# endif
+# if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \
+ || defined(GC_SOLARIS_THREADS)
+ if (GC_stackbottom == 0) {
+ GC_stackbottom = GC_get_main_stack_base();
+# if (defined(LINUX) || defined(HPUX)) && defined(IA64)
+ GC_register_stackbottom = GC_get_register_stack_base();
+# endif
+ } else {
+# if (defined(LINUX) || defined(HPUX)) && defined(IA64)
+ if (GC_register_stackbottom == 0) {
+ WARN("GC_register_stackbottom should be set with GC_stackbottom\n", 0);
+ /* The following may fail, since we may rely on */
+ /* alignment properties that may not hold with a user set */
+ /* GC_stackbottom. */
+ GC_register_stackbottom = GC_get_register_stack_base();
+ }
+# endif
+ }
+# endif
+ /* Ignore gcc -Wall warnings on the following. */
+ GC_STATIC_ASSERT(sizeof (ptr_t) == sizeof(word));
+ GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word));
+ GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE);
+# ifndef THREADS
+# ifdef STACK_GROWS_DOWN
+ GC_ASSERT((word)(&dummy) <= (word)GC_stackbottom);
+# else
+ GC_ASSERT((word)(&dummy) >= (word)GC_stackbottom);
+# endif
+# endif
+# if !defined(_AUX_SOURCE) || defined(__GNUC__)
+ GC_ASSERT((word)(-1) > (word)0);
+ /* word should be unsigned */
+# endif
+ GC_ASSERT((ptr_t)(word)(-1) > (ptr_t)0);
+ /* Ptr_t comparisons should behave as unsigned comparisons. */
+ GC_ASSERT((signed_word)(-1) < (signed_word)0);
+# if !defined(SMALL_CONFIG)
+ if (GC_incremental || 0 != GETENV("GC_ENABLE_INCREMENTAL")) {
+ /* This used to test for !GC_no_win32_dlls. Why? */
+ GC_setpagesize();
+ /* For GWW_MPROTECT on Win32, this needs to happen before any */
+ /* heap memory is allocated. */
+ GC_dirty_init();
+ GC_ASSERT(GC_bytes_allocd == 0)
+ GC_incremental = TRUE;
+ }
+# endif /* !SMALL_CONFIG */
+
+ /* Add initial guess of root sets. Do this first, since sbrk(0) */
+ /* might be used. */
+ if (GC_REGISTER_MAIN_STATIC_DATA()) GC_register_data_segments();
+ GC_init_headers();
+ GC_bl_init();
+ GC_mark_init();
+ {
+ char * sz_str = GETENV("GC_INITIAL_HEAP_SIZE");
+ if (sz_str != NULL) {
+ initial_heap_sz = atoi(sz_str);
+ if (initial_heap_sz <= MINHINCR * HBLKSIZE) {
+ WARN("Bad initial heap size %s - ignoring it.\n",
+ sz_str);
+ }
+ initial_heap_sz = divHBLKSZ(initial_heap_sz);
+ }
+ }
+ {
+ char * sz_str = GETENV("GC_MAXIMUM_HEAP_SIZE");
+ if (sz_str != NULL) {
+ word max_heap_sz = (word)atol(sz_str);
+ if (max_heap_sz < initial_heap_sz * HBLKSIZE) {
+ WARN("Bad maximum heap size %s - ignoring it.\n",
+ sz_str);
+ }
+ if (0 == GC_max_retries) GC_max_retries = 2;
+ GC_set_max_heap_size(max_heap_sz);
+ }
+ }
+ if (!GC_expand_hp_inner(initial_heap_sz)) {
+ GC_err_printf("Can't start up: not enough memory\n");
+ EXIT();
+ }
+ GC_initialize_offsets();
+ GC_register_displacement_inner(0L);
+# if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC)
+ if (!GC_all_interior_pointers) {
+ /* TLS ABI uses pointer-sized offsets for dtv. */
+ GC_register_displacement_inner(sizeof(void *));
+ }
+# endif
+ GC_init_size_map();
+# ifdef PCR
+ if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever)
+ != PCR_ERes_okay) {
+ ABORT("Can't lock load state\n");
+ } else if (PCR_IL_Unlock() != PCR_ERes_okay) {
+ ABORT("Can't unlock load state\n");
+ }
+ PCR_IL_Unlock();
+ GC_pcr_install();
+# endif
+ GC_is_initialized = TRUE;
+# if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
+ GC_thr_init();
+# endif
+ COND_DUMP;
+ /* Get black list set up and/or incremental GC started */
+ if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner();
+# ifdef STUBBORN_ALLOC
+ GC_stubborn_init();
+# endif
+# if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC)
+ {
+ extern void GC_init_lib_bounds(void);
+ GC_init_lib_bounds();
+ }
+# endif
+ /* Convince lint that some things are used */
+# ifdef LINT
+ {
+ extern char * GC_copyright[];
+ extern int GC_read();
+ extern void GC_register_finalizer_no_order();
+
+ GC_noop(GC_copyright, GC_find_header,
+ GC_push_one, GC_call_with_alloc_lock, GC_read,
+ GC_dont_expand,
+# ifndef NO_DEBUGGING
+ GC_dump,
+# endif
+ GC_register_finalizer_no_order);
+ }
+# endif
+}
+
+void GC_enable_incremental(void)
+{
+# if !defined(SMALL_CONFIG) && !defined(KEEP_BACK_PTRS)
+ /* If we are keeping back pointers, the GC itself dirties all */
+ /* pages on which objects have been marked, making */
+ /* incremental GC pointless. */
+ if (!GC_find_leak) {
+ DCL_LOCK_STATE;
+
+ LOCK();
+ if (GC_incremental) goto out;
+ GC_setpagesize();
+ /* if (GC_no_win32_dlls) goto out; Should be win32S test? */
+ maybe_install_looping_handler(); /* Before write fault handler! */
+ GC_incremental = TRUE;
+ if (!GC_is_initialized) {
+ GC_init_inner();
+ } else {
+ GC_dirty_init();
+ }
+ if (!GC_dirty_maintained) goto out;
+ if (GC_dont_gc) {
+ /* Can't easily do it. */
+ UNLOCK();
+ return;
+ }
+ if (GC_bytes_allocd > 0) {
+ /* There may be unmarked reachable objects */
+ GC_gcollect_inner();
+ } /* else we're OK in assuming everything's */
+ /* clean since nothing can point to an */
+ /* unmarked object. */
+ GC_read_dirty();
+out:
+ UNLOCK();
+ } else {
+ GC_init();
+ }
+# else
+ GC_init();
+# endif
+}
+
+
+#if defined(MSWIN32) || defined(MSWINCE)
+# if defined(_MSC_VER) && defined(_DEBUG)
+# include <crtdbg.h>
+# endif
+# ifdef OLD_WIN32_LOG_FILE
+# define LOG_FILE _T("gc.log")
+# endif
+
+ HANDLE GC_stdout = 0;
+
+ void GC_deinit()
+ {
+ if (GC_is_initialized) {
+ DeleteCriticalSection(&GC_write_cs);
+ }
+ }
+
+# ifndef THREADS
+# define GC_need_to_lock 0 /* Not defined without threads */
+# endif
+ int GC_write(const char *buf, size_t len)
+ {
+ BOOL tmp;
+ DWORD written;
+ if (len == 0)
+ return 0;
+ if (GC_need_to_lock) EnterCriticalSection(&GC_write_cs);
+ if (GC_stdout == INVALID_HANDLE_VALUE) {
+ if (GC_need_to_lock) LeaveCriticalSection(&GC_write_cs);
+ return -1;
+ } else if (GC_stdout == 0) {
+ char * file_name = GETENV("GC_LOG_FILE");
+ char logPath[_MAX_PATH + 5];
+
+ if (0 == file_name) {
+# ifdef OLD_WIN32_LOG_FILE
+ strcpy(logPath, LOG_FILE);
+# else
+ GetModuleFileName(NULL, logPath, _MAX_PATH);
+ strcat(logPath, ".log");
+# endif
+ file_name = logPath;
+ }
+ GC_stdout = CreateFile(logPath, GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
+ NULL);
+ if (GC_stdout == INVALID_HANDLE_VALUE)
+ ABORT("Open of log file failed");
+ }
+ tmp = WriteFile(GC_stdout, buf, (DWORD)len, &written, NULL);
+ if (!tmp)
+ DebugBreak();
+# if defined(_MSC_VER) && defined(_DEBUG)
+ _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, "%.*s", len, buf);
+# endif
+ if (GC_need_to_lock) LeaveCriticalSection(&GC_write_cs);
+ return tmp ? (int)written : -1;
+ }
+# undef GC_need_to_lock
+
+#endif
+
+#if defined(OS2) || defined(MACOS)
+FILE * GC_stdout = NULL;
+FILE * GC_stderr = NULL;
+FILE * GC_log = NULL;
+int GC_tmp; /* Should really be local ... */
+
+ void GC_set_files()
+ {
+ if (GC_stdout == NULL) {
+ GC_stdout = stdout;
+ }
+ if (GC_stderr == NULL) {
+ GC_stderr = stderr;
+ }
+ if (GC_log == NULL) {
+ GC_log = stderr;
+ }
+ }
+#endif
+
+#if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE)
+ int GC_stdout = 1;
+ int GC_stderr = 2;
+ int GC_log = 2;
+# if !defined(AMIGA)
+# include <unistd.h>
+# endif
+#endif
+
+#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \
+ && !defined(MACOS) && !defined(ECOS) && !defined(NOSYS)
+int GC_write(fd, buf, len)
+int fd;
+const char *buf;
+size_t len;
+{
+ register int bytes_written = 0;
+ register int result;
+
+ while (bytes_written < len) {
+# ifdef GC_SOLARIS_THREADS
+ result = syscall(SYS_write, fd, buf + bytes_written,
+ len - bytes_written);
+# else
+ result = write(fd, buf + bytes_written, len - bytes_written);
+# endif
+ if (-1 == result) return(result);
+ bytes_written += result;
+ }
+ return(bytes_written);
+}
+#endif /* UN*X */
+
+#ifdef ECOS
+int GC_write(fd, buf, len)
+{
+ _Jv_diag_write (buf, len);
+ return len;
+}
+#endif
+
+#ifdef NOSYS
+int GC_write(fd, buf, len)
+{
+ /* No writing. */
+ return len;
+}
+#endif
+
+
+#if defined(MSWIN32) || defined(MSWINCE)
+ /* FIXME: This is pretty ugly ... */
+# define WRITE(f, buf, len) GC_write(buf, len)
+#else
+# if defined(OS2) || defined(MACOS)
+# define WRITE(f, buf, len) (GC_set_files(), \
+ GC_tmp = fwrite((buf), 1, (len), (f)), \
+ fflush(f), GC_tmp)
+# else
+# define WRITE(f, buf, len) GC_write((f), (buf), (len))
+# endif
+#endif
+
+#define BUFSZ 1024
+#ifdef _MSC_VER
+# define vsnprintf _vsnprintf
+#endif
+/* A version of printf that is unlikely to call malloc, and is thus safer */
+/* to call from the collector in case malloc has been bound to GC_malloc. */
+/* Floating point arguments ans formats should be avoided, since fp */
+/* conversion is more likely to allocate. */
+/* Assumes that no more than BUFSZ-1 characters are written at once. */
+void GC_printf(const char *format, ...)
+{
+ va_list args;
+ char buf[BUFSZ+1];
+
+ va_start(args, format);
+ if (GC_quiet) return;
+ buf[BUFSZ] = 0x15;
+ (void) vsnprintf(buf, BUFSZ, format, args);
+ va_end(args);
+ if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack");
+ if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed");
+}
+
+void GC_err_printf(const char *format, ...)
+{
+ va_list args;
+ char buf[BUFSZ+1];
+
+ va_start(args, format);
+ buf[BUFSZ] = 0x15;
+ (void) vsnprintf(buf, BUFSZ, format, args);
+ va_end(args);
+ if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack");
+ if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed");
+}
+
+void GC_log_printf(const char *format, ...)
+{
+ va_list args;
+ char buf[BUFSZ+1];
+
+ va_start(args, format);
+ buf[BUFSZ] = 0x15;
+ (void) vsnprintf(buf, BUFSZ, format, args);
+ va_end(args);
+ if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack");
+ if (WRITE(GC_log, buf, strlen(buf)) < 0) ABORT("write to log failed");
+}
+
+void GC_err_puts(const char *s)
+{
+ if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");
+}
+
+#if defined(LINUX) && !defined(SMALL_CONFIG)
+void GC_err_write(buf, len)
+const char *buf;
+size_t len;
+{
+ if (WRITE(GC_stderr, buf, len) < 0) ABORT("write to stderr failed");
+}
+#endif
+
+void GC_default_warn_proc(char *msg, GC_word arg)
+{
+ GC_err_printf(msg, arg);
+}
+
+GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;
+
+GC_warn_proc GC_set_warn_proc(GC_warn_proc p)
+{
+ GC_warn_proc result;
+
+# ifdef GC_WIN32_THREADS
+ GC_ASSERT(GC_is_initialized);
+# endif
+ LOCK();
+ result = GC_current_warn_proc;
+ GC_current_warn_proc = p;
+ UNLOCK();
+ return(result);
+}
+
+GC_word GC_set_free_space_divisor (GC_word value)
+{
+ GC_word old = GC_free_space_divisor;
+ GC_free_space_divisor = value;
+ return old;
+}
+
+#ifndef PCR
+void GC_abort(const char *msg)
+{
+# if defined(MSWIN32)
+ (void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
+# else
+ GC_err_printf("%s\n", msg);
+# endif
+ if (GETENV("GC_LOOP_ON_ABORT") != NULL) {
+ /* In many cases it's easier to debug a running process. */
+ /* It's arguably nicer to sleep, but that makes it harder */
+ /* to look at the thread if the debugger doesn't know much */
+ /* about threads. */
+ for(;;) {}
+ }
+# if defined(MSWIN32) || defined(MSWINCE)
+ DebugBreak();
+# else
+ (void) abort();
+# endif
+}
+#endif
+
+void GC_enable()
+{
+ LOCK();
+ GC_dont_gc--;
+ UNLOCK();
+}
+
+void GC_disable()
+{
+ LOCK();
+ GC_dont_gc++;
+ UNLOCK();
+}
+
+/* Helper procedures for new kind creation. */
+void ** GC_new_free_list_inner()
+{
+ void *result = GC_INTERNAL_MALLOC((MAXOBJGRANULES+1)*sizeof(ptr_t),
+ PTRFREE);
+ if (result == 0) ABORT("Failed to allocate freelist for new kind");
+ BZERO(result, (MAXOBJGRANULES+1)*sizeof(ptr_t));
+ return result;
+}
+
+void ** GC_new_free_list()
+{
+ void *result;
+ LOCK();
+ result = GC_new_free_list_inner();
+ UNLOCK();
+ return result;
+}
+
+unsigned GC_new_kind_inner(void **fl, GC_word descr, int adjust, int clear)
+{
+ unsigned result = GC_n_kinds++;
+
+ if (GC_n_kinds > MAXOBJKINDS) ABORT("Too many kinds");
+ GC_obj_kinds[result].ok_freelist = fl;
+ GC_obj_kinds[result].ok_reclaim_list = 0;
+ GC_obj_kinds[result].ok_descriptor = descr;
+ GC_obj_kinds[result].ok_relocate_descr = adjust;
+ GC_obj_kinds[result].ok_init = clear;
+ return result;
+}
+
+unsigned GC_new_kind(void **fl, GC_word descr, int adjust, int clear)
+{
+ unsigned result;
+ LOCK();
+ result = GC_new_kind_inner(fl, descr, adjust, clear);
+ UNLOCK();
+ return result;
+}
+
+unsigned GC_new_proc_inner(GC_mark_proc proc)
+{
+ unsigned result = GC_n_mark_procs++;
+
+ if (GC_n_mark_procs > MAX_MARK_PROCS) ABORT("Too many mark procedures");
+ GC_mark_procs[result] = proc;
+ return result;
+}
+
+unsigned GC_new_proc(GC_mark_proc proc)
+{
+ unsigned result;
+ LOCK();
+ result = GC_new_proc_inner(proc);
+ UNLOCK();
+ return result;
+}
+
+void * GC_call_with_stack_base(GC_stack_base_func fn, void *arg)
+{
+ int dummy;
+ struct GC_stack_base base;
+
+ base.mem_base = (void *)&dummy;
+# ifdef IA64
+ base.reg_base = (void *)GC_save_regs_in_stack();
+ /* Unnecessarily flushes register stack, */
+ /* but that probably doesn't hurt. */
+# endif
+ return fn(&base, arg);
+}
+
+#if !defined(NO_DEBUGGING)
+
+void GC_dump()
+{
+ GC_printf("***Static roots:\n");
+ GC_print_static_roots();
+ GC_printf("\n***Heap sections:\n");
+ GC_print_heap_sects();
+ GC_printf("\n***Free blocks:\n");
+ GC_print_hblkfreelist();
+ GC_printf("\n***Blocks in use:\n");
+ GC_print_block_list();
+ GC_printf("\n***Finalization statistics:\n");
+ GC_print_finalization_stats();
+}
+
+#endif /* NO_DEBUGGING */
diff --git a/tools/build/v2/engine/boehm_gc/missing b/tools/build/v2/engine/boehm_gc/missing
new file mode 100755
index 0000000000..dd583709f5
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/missing
@@ -0,0 +1,336 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+case "$1" in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing 0.4 - GNU automake"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal*)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ fi
+
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ fi
+
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ fi
+
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ fi
+
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ fi
+
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1Help2man' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
+ test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ fi
+
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+ fi
+ if [ -f "$file" ]; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit 1
+ fi
+ ;;
+
+ makeinfo)
+ if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
+ # We have makeinfo, but it failed.
+ exit 1
+ fi
+
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ tar)
+ shift
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ fi
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar ${1+"$@"} && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar ${1+"$@"} && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case "$firstarg" in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" ${1+"$@"} && exit 0
+ ;;
+ esac
+ case "$firstarg" in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" ${1+"$@"} && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/tools/build/v2/engine/boehm_gc/mkinstalldirs b/tools/build/v2/engine/boehm_gc/mkinstalldirs
new file mode 100755
index 0000000000..82a561f435
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/mkinstalldirs
@@ -0,0 +1,101 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.1.1.1 2005/10/10 22:33:34 hboehm Exp $
+
+errstatus=0
+dirmode=""
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
+
+# process command line arguments
+while test $# -gt 0 ; do
+ case "${1}" in
+ -h | --help | --h* ) # -h for help
+ echo "${usage}" 1>&2; exit 0 ;;
+ -m ) # -m PERM arg
+ shift
+ test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; }
+ dirmode="${1}"
+ shift ;;
+ -- ) shift; break ;; # stop option processing
+ -* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option
+ * ) break ;; # first non-opt arg
+ esac
+done
+
+for file
+do
+ if test -d "$file"; then
+ shift
+ else
+ break
+ fi
+done
+
+case $# in
+0) exit 0 ;;
+esac
+
+case $dirmode in
+'')
+ if mkdir -p -- . 2>/dev/null; then
+ echo "mkdir -p -- $*"
+ exec mkdir -p -- "$@"
+ fi ;;
+*)
+ if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
+ echo "mkdir -m $dirmode -p -- $*"
+ exec mkdir -m "$dirmode" -p -- "$@"
+ fi ;;
+esac
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ else
+ if test ! -z "$dirmode"; then
+ echo "chmod $dirmode $pathcomp"
+
+ lasterr=""
+ chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+ if test ! -z "$lasterr"; then
+ errstatus=$lasterr
+ fi
+ fi
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 3
+# End:
+# mkinstalldirs ends here
diff --git a/tools/build/v2/engine/boehm_gc/msvc_dbg.c b/tools/build/v2/engine/boehm_gc/msvc_dbg.c
new file mode 100644
index 0000000000..b172025ba5
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/msvc_dbg.c
@@ -0,0 +1,348 @@
+/*
+ Copyright (c) 2004 Andrei Polushin
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+#ifndef _M_AMD64
+
+/* X86_64 is ccurrently missing some meachine-dependent code below. */
+
+#include "private/msvc_dbg.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#pragma pack(push, 8)
+#include <imagehlp.h>
+#pragma pack(pop)
+
+#pragma comment(lib, "dbghelp.lib")
+#pragma optimize("gy", off)
+
+#ifdef _WIN64
+ typedef ULONG_PTR ULONG_ADDR;
+#else
+ typedef ULONG ULONG_ADDR;
+#endif
+
+static HANDLE GetSymHandle()
+{
+ static HANDLE symHandle = NULL;
+ if (!symHandle) {
+ BOOL bRet = SymInitialize(symHandle = GetCurrentProcess(), NULL, FALSE);
+ if (bRet) {
+ DWORD dwOptions = SymGetOptions();
+ dwOptions &= ~SYMOPT_UNDNAME;
+ dwOptions |= SYMOPT_LOAD_LINES;
+ SymSetOptions(dwOptions);
+ }
+ }
+ return symHandle;
+}
+
+static void* CALLBACK FunctionTableAccess(HANDLE hProcess, ULONG_ADDR dwAddrBase)
+{
+ return SymFunctionTableAccess(hProcess, dwAddrBase);
+}
+
+static ULONG_ADDR CALLBACK GetModuleBase(HANDLE hProcess, ULONG_ADDR dwAddress)
+{
+ MEMORY_BASIC_INFORMATION memoryInfo;
+ ULONG_ADDR dwAddrBase = SymGetModuleBase(hProcess, dwAddress);
+ if (dwAddrBase) {
+ return dwAddrBase;
+ }
+ if (VirtualQueryEx(hProcess, (void*)(ULONG_PTR)dwAddress, &memoryInfo, sizeof(memoryInfo))) {
+ char filePath[_MAX_PATH];
+ char curDir[_MAX_PATH];
+ char exePath[_MAX_PATH];
+ DWORD size = GetModuleFileNameA((HINSTANCE)memoryInfo.AllocationBase, filePath, sizeof(filePath));
+
+ // Save and restore current directory around SymLoadModule, see KB article Q189780
+ GetCurrentDirectoryA(sizeof(curDir), curDir);
+ GetModuleFileNameA(NULL, exePath, sizeof(exePath));
+ strcat_s(exePath, sizeof(exePath), "\\..");
+ SetCurrentDirectoryA(exePath);
+#ifdef _DEBUG
+ GetCurrentDirectoryA(sizeof(exePath), exePath);
+#endif
+ SymLoadModule(hProcess, NULL, size ? filePath : NULL, NULL, (ULONG_ADDR)(ULONG_PTR)memoryInfo.AllocationBase, 0);
+ SetCurrentDirectoryA(curDir);
+ }
+ return (ULONG_ADDR)(ULONG_PTR)memoryInfo.AllocationBase;
+}
+
+static ULONG_ADDR CheckAddress(void* address)
+{
+ ULONG_ADDR dwAddress = (ULONG_ADDR)(ULONG_PTR)address;
+ GetModuleBase(GetSymHandle(), dwAddress);
+ return dwAddress;
+}
+
+size_t GetStackFrames(size_t skip, void* frames[], size_t maxFrames)
+{
+ HANDLE hProcess = GetSymHandle();
+ HANDLE hThread = GetCurrentThread();
+ CONTEXT context;
+ context.ContextFlags = CONTEXT_FULL;
+ if (!GetThreadContext(hThread, &context)) {
+ return 0;
+ }
+ // GetThreadContext might return invalid context for the current thread
+#if defined(_M_IX86)
+ __asm mov context.Ebp, ebp
+#endif
+ return GetStackFramesFromContext(hProcess, hThread, &context, skip + 1, frames, maxFrames);
+}
+
+size_t GetStackFramesFromContext(HANDLE hProcess, HANDLE hThread, CONTEXT* context, size_t skip, void* frames[], size_t maxFrames)
+{
+ size_t frameIndex;
+ DWORD machineType;
+ STACKFRAME stackFrame = { 0 };
+ stackFrame.AddrPC.Mode = AddrModeFlat;
+#if defined(_M_IX86)
+ machineType = IMAGE_FILE_MACHINE_I386;
+ stackFrame.AddrPC.Offset = context->Eip;
+ stackFrame.AddrStack.Mode = AddrModeFlat;
+ stackFrame.AddrStack.Offset = context->Esp;
+ stackFrame.AddrFrame.Mode = AddrModeFlat;
+ stackFrame.AddrFrame.Offset = context->Ebp;
+#elif defined(_M_MRX000)
+ machineType = IMAGE_FILE_MACHINE_R4000;
+ stackFrame.AddrPC.Offset = context->Fir;
+#elif defined(_M_ALPHA)
+ machineType = IMAGE_FILE_MACHINE_ALPHA;
+ stackFrame.AddrPC.Offset = (unsigned long)context->Fir;
+#elif defined(_M_PPC)
+ machineType = IMAGE_FILE_MACHINE_POWERPC;
+ stackFrame.AddrPC.Offset = context->Iar;
+#elif defined(_M_IA64)
+ machineType = IMAGE_FILE_MACHINE_IA64;
+ stackFrame.AddrPC.Offset = context->StIIP;
+#elif defined(_M_ALPHA64)
+ machineType = IMAGE_FILE_MACHINE_ALPHA64;
+ stackFrame.AddrPC.Offset = context->Fir;
+#else
+#error Unknown CPU
+#endif
+ for (frameIndex = 0; frameIndex < maxFrames; ) {
+ BOOL bRet = StackWalk(machineType, hProcess, hThread, &stackFrame, &context, NULL, FunctionTableAccess, GetModuleBase, NULL);
+ if (!bRet) {
+ break;
+ }
+ if (skip) {
+ skip--;
+ } else {
+ frames[frameIndex++] = (void*)(ULONG_PTR)stackFrame.AddrPC.Offset;
+ }
+ }
+ return frameIndex;
+}
+
+size_t GetModuleNameFromAddress(void* address, char* moduleName, size_t size)
+{
+ if (size) *moduleName = 0;
+ {
+ const char* sourceName;
+ IMAGEHLP_MODULE moduleInfo = { sizeof (moduleInfo) };
+ if (!SymGetModuleInfo(GetSymHandle(), CheckAddress(address), &moduleInfo)) {
+ return 0;
+ }
+ sourceName = strrchr(moduleInfo.ImageName, '\\');
+ if (sourceName) {
+ sourceName++;
+ } else {
+ sourceName = moduleInfo.ImageName;
+ }
+ if (size) {
+ strncpy(moduleName, sourceName, size)[size - 1] = 0;
+ }
+ return strlen(sourceName);
+ }
+}
+
+size_t GetModuleNameFromStack(size_t skip, char* moduleName, size_t size)
+{
+ void* address = NULL;
+ GetStackFrames(skip + 1, &address, 1);
+ if (address) {
+ return GetModuleNameFromAddress(address, moduleName, size);
+ }
+ return 0;
+}
+
+size_t GetSymbolNameFromAddress(void* address, char* symbolName, size_t size, size_t* offsetBytes)
+{
+ if (size) *symbolName = 0;
+ if (offsetBytes) *offsetBytes = 0;
+ __try {
+ ULONG_ADDR dwOffset = 0;
+ union {
+ IMAGEHLP_SYMBOL sym;
+ char symNameBuffer[sizeof(IMAGEHLP_SYMBOL) + MAX_SYM_NAME];
+ } u;
+ u.sym.SizeOfStruct = sizeof(u.sym);
+ u.sym.MaxNameLength = sizeof(u.symNameBuffer) - sizeof(u.sym);
+
+ if (!SymGetSymFromAddr(GetSymHandle(), CheckAddress(address), &dwOffset, &u.sym)) {
+ return 0;
+ } else {
+ const char* sourceName = u.sym.Name;
+ char undName[1024];
+ if (UnDecorateSymbolName(u.sym.Name, undName, sizeof(undName), UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS)) {
+ sourceName = undName;
+ } else if (SymUnDName(&u.sym, undName, sizeof(undName))) {
+ sourceName = undName;
+ }
+ if (offsetBytes) {
+ *offsetBytes = dwOffset;
+ }
+ if (size) {
+ strncpy(symbolName, sourceName, size)[size - 1] = 0;
+ }
+ return strlen(sourceName);
+ }
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+ SetLastError(GetExceptionCode());
+ }
+ return 0;
+}
+
+size_t GetSymbolNameFromStack(size_t skip, char* symbolName, size_t size, size_t* offsetBytes)
+{
+ void* address = NULL;
+ GetStackFrames(skip + 1, &address, 1);
+ if (address) {
+ return GetSymbolNameFromAddress(address, symbolName, size, offsetBytes);
+ }
+ return 0;
+}
+
+size_t GetFileLineFromAddress(void* address, char* fileName, size_t size, size_t* lineNumber, size_t* offsetBytes)
+{
+ if (size) *fileName = 0;
+ if (lineNumber) *lineNumber = 0;
+ if (offsetBytes) *offsetBytes = 0;
+ {
+ char* sourceName;
+ IMAGEHLP_LINE line = { sizeof (line) };
+ ULONG_PTR dwOffset = 0;
+ if (!SymGetLineFromAddr(GetSymHandle(), CheckAddress(address), &dwOffset, &line)) {
+ return 0;
+ }
+ if (lineNumber) {
+ *lineNumber = line.LineNumber;
+ }
+ if (offsetBytes) {
+ *offsetBytes = dwOffset;
+ }
+ sourceName = line.FileName;
+ // TODO: resolve relative filenames, found in 'source directories' registered with MSVC IDE.
+ if (size) {
+ strncpy(fileName, sourceName, size)[size - 1] = 0;
+ }
+ return strlen(sourceName);
+ }
+}
+
+size_t GetFileLineFromStack(size_t skip, char* fileName, size_t size, size_t* lineNumber, size_t* offsetBytes)
+{
+ void* address = NULL;
+ GetStackFrames(skip + 1, &address, 1);
+ if (address) {
+ return GetFileLineFromAddress(address, fileName, size, lineNumber, offsetBytes);
+ }
+ return 0;
+}
+
+size_t GetDescriptionFromAddress(void* address, const char* format, char* buffer, size_t size)
+{
+ char*const begin = buffer;
+ char*const end = buffer + size;
+ size_t line_number = 0;
+ char str[128];
+
+ if (size) {
+ *buffer = 0;
+ }
+ buffer += GetFileLineFromAddress(address, buffer, size, &line_number, NULL);
+ size = end < buffer ? 0 : end - buffer;
+
+ if (line_number) {
+ wsprintf(str, "(%d) : ", line_number);
+ if (size) {
+ strncpy(buffer, str, size)[size - 1] = 0;
+ }
+ buffer += strlen(str);
+ size = end < buffer ? 0 : end - buffer;
+ }
+
+ if (size) {
+ strncpy(buffer, "at ", size)[size - 1] = 0;
+ }
+ buffer += strlen("at ");
+ size = end < buffer ? 0 : end - buffer;
+
+ buffer += GetSymbolNameFromAddress(address, buffer, size, NULL);
+ size = end < buffer ? 0 : end - buffer;
+
+ if (size) {
+ strncpy(buffer, " in ", size)[size - 1] = 0;
+ }
+ buffer += strlen(" in ");
+ size = end < buffer ? 0 : end - buffer;
+
+ buffer += GetModuleNameFromAddress(address, buffer, size);
+ size = end < buffer ? 0 : end - buffer;
+
+ return buffer - begin;
+}
+
+size_t GetDescriptionFromStack(void*const frames[], size_t count, const char* format, char* description[], size_t size)
+{
+ char*const begin = (char*)description;
+ char*const end = begin + size;
+ char* buffer = begin + (count + 1) * sizeof(char*);
+ size_t i;
+ for (i = 0; i < count; ++i) {
+ if (description) description[i] = buffer;
+ size = end < buffer ? 0 : end - buffer;
+ buffer += 1 + GetDescriptionFromAddress(frames[i], NULL, buffer, size);
+ }
+ if (description) description[count] = NULL;
+ return buffer - begin;
+}
+
+/* Compatibility with <execinfo.h> */
+
+int backtrace(void* addresses[], int count)
+{
+ return GetStackFrames(1, addresses, count);
+}
+
+char** backtrace_symbols(void*const* addresses, int count)
+{
+ size_t size = GetDescriptionFromStack(addresses, count, NULL, NULL, 0);
+ char** symbols = (char**)malloc(size);
+ GetDescriptionFromStack(addresses, count, NULL, symbols, size);
+ return symbols;
+}
+
+#endif /* !_M_AMD64 */
diff --git a/tools/build/v2/engine/boehm_gc/new_hblk.c b/tools/build/v2/engine/boehm_gc/new_hblk.c
new file mode 100644
index 0000000000..5d5a56f2af
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/new_hblk.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ * This file contains the functions:
+ * ptr_t GC_build_flXXX(h, old_fl)
+ * void GC_new_hblk(size)
+ */
+/* Boehm, May 19, 1994 2:09 pm PDT */
+
+
+# include <stdio.h>
+# include "private/gc_priv.h"
+
+#ifndef SMALL_CONFIG
+/*
+ * Build a free list for size 2 (words) cleared objects inside hblk h.
+ * Set the last link to
+ * be ofl. Return a pointer tpo the first free list entry.
+ */
+ptr_t GC_build_fl_clear2(struct hblk *h, ptr_t ofl)
+{
+ word * p = (word *)(h -> hb_body);
+ word * lim = (word *)(h + 1);
+
+ p[0] = (word)ofl;
+ p[1] = 0;
+ p[2] = (word)p;
+ p[3] = 0;
+ p += 4;
+ for (; p < lim; p += 4) {
+ p[0] = (word)(p-2);
+ p[1] = 0;
+ p[2] = (word)p;
+ p[3] = 0;
+ };
+ return((ptr_t)(p-2));
+}
+
+/* The same for size 4 cleared objects */
+ptr_t GC_build_fl_clear4(struct hblk *h, ptr_t ofl)
+{
+ word * p = (word *)(h -> hb_body);
+ word * lim = (word *)(h + 1);
+
+ p[0] = (word)ofl;
+ p[1] = 0;
+ p[2] = 0;
+ p[3] = 0;
+ p += 4;
+ for (; p < lim; p += 4) {
+ PREFETCH_FOR_WRITE((ptr_t)(p+64));
+ p[0] = (word)(p-4);
+ p[1] = 0;
+ CLEAR_DOUBLE(p+2);
+ };
+ return((ptr_t)(p-4));
+}
+
+/* The same for size 2 uncleared objects */
+ptr_t GC_build_fl2(struct hblk *h, ptr_t ofl)
+{
+ word * p = (word *)(h -> hb_body);
+ word * lim = (word *)(h + 1);
+
+ p[0] = (word)ofl;
+ p[2] = (word)p;
+ p += 4;
+ for (; p < lim; p += 4) {
+ p[0] = (word)(p-2);
+ p[2] = (word)p;
+ };
+ return((ptr_t)(p-2));
+}
+
+/* The same for size 4 uncleared objects */
+ptr_t GC_build_fl4(struct hblk *h, ptr_t ofl)
+{
+ word * p = (word *)(h -> hb_body);
+ word * lim = (word *)(h + 1);
+
+ p[0] = (word)ofl;
+ p[4] = (word)p;
+ p += 8;
+ for (; p < lim; p += 8) {
+ PREFETCH_FOR_WRITE((ptr_t)(p+64));
+ p[0] = (word)(p-4);
+ p[4] = (word)p;
+ };
+ return((ptr_t)(p-4));
+}
+
+#endif /* !SMALL_CONFIG */
+
+
+/* Build a free list for objects of size sz inside heap block h. */
+/* Clear objects inside h if clear is set. Add list to the end of */
+/* the free list we build. Return the new free list. */
+/* This could be called without the main GC lock, if we ensure that */
+/* there is no concurrent collection which might reclaim objects that */
+/* we have not yet allocated. */
+ptr_t GC_build_fl(struct hblk *h, size_t sz, GC_bool clear, ptr_t list)
+{
+ word *p, *prev;
+ word *last_object; /* points to last object in new hblk */
+
+ /* Do a few prefetches here, just because its cheap. */
+ /* If we were more serious about it, these should go inside */
+ /* the loops. But write prefetches usually don't seem to */
+ /* matter much. */
+ PREFETCH_FOR_WRITE((ptr_t)h);
+ PREFETCH_FOR_WRITE((ptr_t)h + 128);
+ PREFETCH_FOR_WRITE((ptr_t)h + 256);
+ PREFETCH_FOR_WRITE((ptr_t)h + 378);
+ /* Handle small objects sizes more efficiently. For larger objects */
+ /* the difference is less significant. */
+# ifndef SMALL_CONFIG
+ switch (sz) {
+ case 2: if (clear) {
+ return GC_build_fl_clear2(h, list);
+ } else {
+ return GC_build_fl2(h, list);
+ }
+ case 4: if (clear) {
+ return GC_build_fl_clear4(h, list);
+ } else {
+ return GC_build_fl4(h, list);
+ }
+ default:
+ break;
+ }
+# endif /* !SMALL_CONFIG */
+
+ /* Clear the page if necessary. */
+ if (clear) BZERO(h, HBLKSIZE);
+
+ /* Add objects to free list */
+ p = (word *)(h -> hb_body) + sz; /* second object in *h */
+ prev = (word *)(h -> hb_body); /* One object behind p */
+ last_object = (word *)((char *)h + HBLKSIZE);
+ last_object -= sz;
+ /* Last place for last object to start */
+
+ /* make a list of all objects in *h with head as last object */
+ while (p <= last_object) {
+ /* current object's link points to last object */
+ obj_link(p) = (ptr_t)prev;
+ prev = p;
+ p += sz;
+ }
+ p -= sz; /* p now points to last object */
+
+ /*
+ * put p (which is now head of list of objects in *h) as first
+ * pointer in the appropriate free list for this size.
+ */
+ obj_link(h -> hb_body) = list;
+ return ((ptr_t)p);
+}
+
+
+/*
+ * Allocate a new heapblock for small objects of size gran granules.
+ * Add all of the heapblock's objects to the free list for objects
+ * of that size.
+ * Set all mark bits if objects are uncollectable.
+ * Will fail to do anything if we are out of memory.
+ */
+void GC_new_hblk(size_t gran, int kind)
+{
+ struct hblk *h; /* the new heap block */
+ GC_bool clear = GC_obj_kinds[kind].ok_init;
+
+ /* Ignore gcc "no effect" warning on the following: */
+ GC_STATIC_ASSERT((sizeof (struct hblk)) == HBLKSIZE);
+
+ if (GC_debugging_started) clear = TRUE;
+
+ /* Allocate a new heap block */
+ h = GC_allochblk(GRANULES_TO_BYTES(gran), kind, 0);
+ if (h == 0) return;
+
+ /* Mark all objects if appropriate. */
+ if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(HDR(h));
+
+ /* Build the free list */
+ GC_obj_kinds[kind].ok_freelist[gran] =
+ GC_build_fl(h, GRANULES_TO_WORDS(gran), clear,
+ GC_obj_kinds[kind].ok_freelist[gran]);
+}
+
diff --git a/tools/build/v2/engine/boehm_gc/obj_map.c b/tools/build/v2/engine/boehm_gc/obj_map.c
new file mode 100644
index 0000000000..c295c4033b
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/obj_map.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991, 1992 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* Routines for maintaining maps describing heap block
+ * layouts for various object sizes. Allows fast pointer validity checks
+ * and fast location of object start locations on machines (such as SPARC)
+ * with slow division.
+ */
+
+# include "private/gc_priv.h"
+
+/* Consider pointers that are offset bytes displaced from the beginning */
+/* of an object to be valid. */
+
+void GC_register_displacement(size_t offset)
+{
+ DCL_LOCK_STATE;
+
+ LOCK();
+ GC_register_displacement_inner(offset);
+ UNLOCK();
+}
+
+void GC_register_displacement_inner(size_t offset)
+{
+ if (offset >= VALID_OFFSET_SZ) {
+ ABORT("Bad argument to GC_register_displacement");
+ }
+ if (!GC_valid_offsets[offset]) {
+ GC_valid_offsets[offset] = TRUE;
+ GC_modws_valid_offsets[offset % sizeof(word)] = TRUE;
+ }
+}
+
+#ifdef MARK_BIT_PER_GRANULE
+/* Add a heap block map for objects of size granules to obj_map. */
+/* Return FALSE on failure. */
+/* A size of 0 granules is used for large objects. */
+GC_bool GC_add_map_entry(size_t granules)
+{
+ unsigned displ;
+ short * new_map;
+
+ if (granules > BYTES_TO_GRANULES(MAXOBJBYTES)) granules = 0;
+ if (GC_obj_map[granules] != 0) {
+ return(TRUE);
+ }
+ new_map = (short *)GC_scratch_alloc(MAP_LEN * sizeof(short));
+ if (new_map == 0) return(FALSE);
+ if (GC_print_stats)
+ GC_printf("Adding block map for size of %u granules (%u bytes)\n",
+ (unsigned)granules, (unsigned)(GRANULES_TO_BYTES(granules)));
+ if (granules == 0) {
+ for (displ = 0; displ < BYTES_TO_GRANULES(HBLKSIZE); displ++) {
+ new_map[displ] = 1; /* Nonzero to get us out of marker fast path. */
+ }
+ } else {
+ for (displ = 0; displ < BYTES_TO_GRANULES(HBLKSIZE); displ++) {
+ new_map[displ] = (short)(displ % granules);
+ }
+ }
+ GC_obj_map[granules] = new_map;
+ return(TRUE);
+}
+#endif
+
+static GC_bool offsets_initialized = FALSE;
+
+void GC_initialize_offsets(void)
+{
+ if (!offsets_initialized) {
+ int i;
+ if (GC_all_interior_pointers) {
+ for (i = 0; i < VALID_OFFSET_SZ; ++i) GC_valid_offsets[i] = TRUE;
+ }
+ offsets_initialized = TRUE;
+ }
+}
diff --git a/tools/build/v2/engine/boehm_gc/os_dep.c b/tools/build/v2/engine/boehm_gc/os_dep.c
new file mode 100644
index 0000000000..bb8fa08f61
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/os_dep.c
@@ -0,0 +1,4333 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+# include "private/gc_priv.h"
+# ifdef THREADS
+# include "atomic_ops.h"
+# endif
+
+# if defined(LINUX) && !defined(POWERPC)
+# include <linux/version.h>
+# if (LINUX_VERSION_CODE <= 0x10400)
+ /* Ugly hack to get struct sigcontext_struct definition. Required */
+ /* for some early 1.3.X releases. Will hopefully go away soon. */
+ /* in some later Linux releases, asm/sigcontext.h may have to */
+ /* be included instead. */
+# define __KERNEL__
+# include <asm/signal.h>
+# undef __KERNEL__
+# else
+ /* Kernels prior to 2.1.1 defined struct sigcontext_struct instead of */
+ /* struct sigcontext. libc6 (glibc2) uses "struct sigcontext" in */
+ /* prototypes, so we have to include the top-level sigcontext.h to */
+ /* make sure the former gets defined to be the latter if appropriate. */
+# include <features.h>
+# if 2 <= __GLIBC__
+# if 2 == __GLIBC__ && 0 == __GLIBC_MINOR__
+ /* glibc 2.1 no longer has sigcontext.h. But signal.h */
+ /* has the right declaration for glibc 2.1. */
+# include <sigcontext.h>
+# endif /* 0 == __GLIBC_MINOR__ */
+# else /* not 2 <= __GLIBC__ */
+ /* libc5 doesn't have <sigcontext.h>: go directly with the kernel */
+ /* one. Check LINUX_VERSION_CODE to see which we should reference. */
+# include <asm/sigcontext.h>
+# endif /* 2 <= __GLIBC__ */
+# endif
+# endif
+# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \
+ && !defined(MSWINCE)
+# include <sys/types.h>
+# if !defined(MSWIN32)
+# include <unistd.h>
+# endif
+# endif
+
+# include <stdio.h>
+# if defined(MSWINCE)
+# define SIGSEGV 0 /* value is irrelevant */
+# else
+# include <signal.h>
+# endif
+
+#ifdef UNIX_LIKE
+# include <fcntl.h>
+#endif
+
+#if defined(LINUX) || defined(LINUX_STACKBOTTOM)
+# include <ctype.h>
+#endif
+
+/* Blatantly OS dependent routines, except for those that are related */
+/* to dynamic loading. */
+
+#ifdef AMIGA
+# define GC_AMIGA_DEF
+# include "AmigaOS.c"
+# undef GC_AMIGA_DEF
+#endif
+
+#if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
+# define WIN32_LEAN_AND_MEAN
+# define NOSERVICE
+# include <windows.h>
+ /* It's not clear this is completely kosher under Cygwin. But it */
+ /* allows us to get a working GC_get_stack_base. */
+#endif
+
+#ifdef MACOS
+# include <Processes.h>
+#endif
+
+#ifdef IRIX5
+# include <sys/uio.h>
+# include <malloc.h> /* for locking */
+#endif
+
+#if defined(LINUX) || defined(FREEBSD) || defined(SOLARIS) || defined(IRIX5) \
+ || defined(USE_MMAP) || defined(USE_MUNMAP)
+# define MMAP_SUPPORTED
+#endif
+
+#if defined(MMAP_SUPPORTED) || defined(ADD_HEAP_GUARD_PAGES)
+# if defined(USE_MUNMAP) && !defined(USE_MMAP)
+ --> USE_MUNMAP requires USE_MMAP
+# endif
+# include <sys/types.h>
+# include <sys/mman.h>
+# include <sys/stat.h>
+# include <errno.h>
+#endif
+
+#ifdef DARWIN
+/* for get_etext and friends */
+#include <mach-o/getsect.h>
+#endif
+
+#ifdef DJGPP
+ /* Apparently necessary for djgpp 2.01. May cause problems with */
+ /* other versions. */
+ typedef long unsigned int caddr_t;
+#endif
+
+#ifdef PCR
+# include "il/PCR_IL.h"
+# include "th/PCR_ThCtl.h"
+# include "mm/PCR_MM.h"
+#endif
+
+#if !defined(NO_EXECUTE_PERMISSION)
+# define OPT_PROT_EXEC PROT_EXEC
+#else
+# define OPT_PROT_EXEC 0
+#endif
+
+#if defined(LINUX) && \
+ (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) || !defined(SMALL_CONFIG))
+# define NEED_PROC_MAPS
+#endif
+
+#ifdef NEED_PROC_MAPS
+/* We need to parse /proc/self/maps, either to find dynamic libraries, */
+/* and/or to find the register backing store base (IA64). Do it once */
+/* here. */
+
+#define READ read
+
+/* Repeatedly perform a read call until the buffer is filled or */
+/* we encounter EOF. */
+ssize_t GC_repeat_read(int fd, char *buf, size_t count)
+{
+ ssize_t num_read = 0;
+ ssize_t result;
+
+ while (num_read < count) {
+ result = READ(fd, buf + num_read, count - num_read);
+ if (result < 0) return result;
+ if (result == 0) break;
+ num_read += result;
+ }
+ return num_read;
+}
+
+/* Determine the length of a file by incrementally reading it into a */
+/* This would be sily to use on a file supporting lseek, but Linux */
+/* /proc files usually do not. */
+size_t GC_get_file_len(int f)
+{
+ size_t total = 0;
+ ssize_t result;
+# define GET_FILE_LEN_BUF_SZ 500
+ char buf[GET_FILE_LEN_BUF_SZ];
+
+ do {
+ result = read(f, buf, GET_FILE_LEN_BUF_SZ);
+ if (result == -1) return 0;
+ total += result;
+ } while (result > 0);
+ return total;
+}
+
+size_t GC_get_maps_len(void)
+{
+ int f = open("/proc/self/maps", O_RDONLY);
+ size_t result = GC_get_file_len(f);
+ close(f);
+ return result;
+}
+
+/*
+ * Copy the contents of /proc/self/maps to a buffer in our address space.
+ * Return the address of the buffer, or zero on failure.
+ * This code could be simplified if we could determine its size
+ * ahead of time.
+ */
+char * GC_get_maps(void)
+{
+ int f;
+ int result;
+ static char init_buf[1];
+ static char *maps_buf = init_buf;
+ static size_t maps_buf_sz = 1;
+ size_t maps_size, old_maps_size = 0;
+
+ /* The buffer is essentially static, so there must be a single client. */
+ GC_ASSERT(I_HOLD_LOCK());
+
+ /* Note that in the presence of threads, the maps file can */
+ /* essentially shrink asynchronously and unexpectedly as */
+ /* threads that we already think of as dead release their */
+ /* stacks. And there is no easy way to read the entire */
+ /* file atomically. This is arguably a misfeature of the */
+ /* /proc/.../maps interface. */
+
+ /* Since we dont believe the file can grow */
+ /* asynchronously, it should suffice to first determine */
+ /* the size (using lseek or read), and then to reread the */
+ /* file. If the size is inconsistent we have to retry. */
+ /* This only matters with threads enabled, and if we use */
+ /* this to locate roots (not the default). */
+
+ /* Determine the initial size of /proc/self/maps. */
+ /* Note that lseek doesn't work, at least as of 2.6.15. */
+# ifdef THREADS
+ maps_size = GC_get_maps_len();
+ if (0 == maps_size) return 0;
+# else
+ maps_size = 4000; /* Guess */
+# endif
+
+ /* Read /proc/self/maps, growing maps_buf as necessary. */
+ /* Note that we may not allocate conventionally, and */
+ /* thus can't use stdio. */
+ do {
+ while (maps_size >= maps_buf_sz) {
+ /* Grow only by powers of 2, since we leak "too small" buffers. */
+ while (maps_size >= maps_buf_sz) maps_buf_sz *= 2;
+ maps_buf = GC_scratch_alloc(maps_buf_sz);
+# ifdef THREADS
+ /* Recompute initial length, since we allocated. */
+ /* This can only happen a few times per program */
+ /* execution. */
+ maps_size = GC_get_maps_len();
+ if (0 == maps_size) return 0;
+# endif
+ if (maps_buf == 0) return 0;
+ }
+ GC_ASSERT(maps_buf_sz >= maps_size + 1);
+ f = open("/proc/self/maps", O_RDONLY);
+ if (-1 == f) return 0;
+# ifdef THREADS
+ old_maps_size = maps_size;
+# endif
+ maps_size = 0;
+ do {
+ result = GC_repeat_read(f, maps_buf, maps_buf_sz-1);
+ if (result <= 0) return 0;
+ maps_size += result;
+ } while (result == maps_buf_sz-1);
+ close(f);
+# ifdef THREADS
+ if (maps_size > old_maps_size) {
+ GC_err_printf("Old maps size = %d, new maps size = %d\n",
+ old_maps_size, maps_size);
+ ABORT("Unexpected asynchronous /proc/self/maps growth: "
+ "Unregistered thread?");
+ }
+# endif
+ } while (maps_size >= maps_buf_sz || maps_size < old_maps_size);
+ /* In the single-threaded case, the second clause is false. */
+ maps_buf[maps_size] = '\0';
+
+ /* Apply fn to result. */
+ return maps_buf;
+}
+
+//
+// GC_parse_map_entry parses an entry from /proc/self/maps so we can
+// locate all writable data segments that belong to shared libraries.
+// The format of one of these entries and the fields we care about
+// is as follows:
+// XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
+// ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
+// start end prot maj_dev
+//
+// Note that since about august 2003 kernels, the columns no longer have
+// fixed offsets on 64-bit kernels. Hence we no longer rely on fixed offsets
+// anywhere, which is safer anyway.
+//
+
+/*
+ * Assign various fields of the first line in buf_ptr to *start, *end,
+ * *prot, *maj_dev and *mapping_name. Mapping_name may be NULL.
+ * *prot and *mapping_name are assigned pointers into the original
+ * buffer.
+ */
+char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end,
+ char **prot, unsigned int *maj_dev,
+ char **mapping_name)
+{
+ char *start_start, *end_start, *maj_dev_start;
+ char *p;
+ char *endp;
+
+ if (buf_ptr == NULL || *buf_ptr == '\0') {
+ return NULL;
+ }
+
+ p = buf_ptr;
+ while (isspace(*p)) ++p;
+ start_start = p;
+ GC_ASSERT(isxdigit(*start_start));
+ *start = (ptr_t)strtoul(start_start, &endp, 16); p = endp;
+ GC_ASSERT(*p=='-');
+
+ ++p;
+ end_start = p;
+ GC_ASSERT(isxdigit(*end_start));
+ *end = (ptr_t)strtoul(end_start, &endp, 16); p = endp;
+ GC_ASSERT(isspace(*p));
+
+ while (isspace(*p)) ++p;
+ GC_ASSERT(*p == 'r' || *p == '-');
+ *prot = p;
+ /* Skip past protection field to offset field */
+ while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
+ GC_ASSERT(isxdigit(*p));
+ /* Skip past offset field, which we ignore */
+ while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
+ maj_dev_start = p;
+ GC_ASSERT(isxdigit(*maj_dev_start));
+ *maj_dev = strtoul(maj_dev_start, NULL, 16);
+
+ if (mapping_name == 0) {
+ while (*p && *p++ != '\n');
+ } else {
+ while (*p && *p != '\n' && *p != '/' && *p != '[') p++;
+ *mapping_name = p;
+ while (*p && *p++ != '\n');
+ }
+
+ return p;
+}
+
+/* Try to read the backing store base from /proc/self/maps. */
+/* Return the bounds of the writable mapping with a 0 major device, */
+/* which includes the address passed as data. */
+/* Return FALSE if there is no such mapping. */
+GC_bool GC_enclosing_mapping(ptr_t addr, ptr_t *startp, ptr_t *endp)
+{
+ char *prot;
+ ptr_t my_start, my_end;
+ unsigned int maj_dev;
+ char *maps = GC_get_maps();
+ char *buf_ptr = maps;
+
+ if (0 == maps) return(FALSE);
+ for (;;) {
+ buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
+ &prot, &maj_dev, 0);
+
+ if (buf_ptr == NULL) return FALSE;
+ if (prot[1] == 'w' && maj_dev == 0) {
+ if (my_end > addr && my_start <= addr) {
+ *startp = my_start;
+ *endp = my_end;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/* Find the text(code) mapping for the library whose name starts with nm. */
+GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp)
+{
+ size_t nm_len = strlen(nm);
+ char *prot;
+ char *map_path;
+ ptr_t my_start, my_end;
+ unsigned int maj_dev;
+ char *maps = GC_get_maps();
+ char *buf_ptr = maps;
+
+ if (0 == maps) return(FALSE);
+ for (;;) {
+ buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
+ &prot, &maj_dev, &map_path);
+
+ if (buf_ptr == NULL) return FALSE;
+ if (prot[0] == 'r' && prot[1] == '-' && prot[2] == 'x' &&
+ strncmp(nm, map_path, nm_len) == 0) {
+ *startp = my_start;
+ *endp = my_end;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+#ifdef IA64
+static ptr_t backing_store_base_from_proc(void)
+{
+ ptr_t my_start, my_end;
+ if (!GC_enclosing_mapping(GC_save_regs_in_stack(), &my_start, &my_end)) {
+ if (GC_print_stats) {
+ GC_log_printf("Failed to find backing store base from /proc\n");
+ }
+ return 0;
+ }
+ return my_start;
+}
+#endif
+
+#endif /* NEED_PROC_MAPS */
+
+#if defined(SEARCH_FOR_DATA_START)
+ /* The I386 case can be handled without a search. The Alpha case */
+ /* used to be handled differently as well, but the rules changed */
+ /* for recent Linux versions. This seems to be the easiest way to */
+ /* cover all versions. */
+
+# if defined(LINUX) || defined(HURD)
+ /* Some Linux distributions arrange to define __data_start. Some */
+ /* define data_start as a weak symbol. The latter is technically */
+ /* broken, since the user program may define data_start, in which */
+ /* case we lose. Nonetheless, we try both, prefering __data_start. */
+ /* We assume gcc-compatible pragmas. */
+# pragma weak __data_start
+ extern int __data_start[];
+# pragma weak data_start
+ extern int data_start[];
+# endif /* LINUX */
+ extern int _end[];
+
+ ptr_t GC_data_start;
+
+ void GC_init_linux_data_start()
+ {
+ extern ptr_t GC_find_limit(ptr_t, GC_bool);
+
+# if defined(LINUX) || defined(HURD)
+ /* Try the easy approaches first: */
+ if ((ptr_t)__data_start != 0) {
+ GC_data_start = (ptr_t)(__data_start);
+ return;
+ }
+ if ((ptr_t)data_start != 0) {
+ GC_data_start = (ptr_t)(data_start);
+ return;
+ }
+# endif /* LINUX */
+ GC_data_start = GC_find_limit((ptr_t)(_end), FALSE);
+ }
+#endif
+
+# ifdef ECOS
+
+# ifndef ECOS_GC_MEMORY_SIZE
+# define ECOS_GC_MEMORY_SIZE (448 * 1024)
+# endif /* ECOS_GC_MEMORY_SIZE */
+
+// FIXME: This is a simple way of allocating memory which is
+// compatible with ECOS early releases. Later releases use a more
+// sophisticated means of allocating memory than this simple static
+// allocator, but this method is at least bound to work.
+static char memory[ECOS_GC_MEMORY_SIZE];
+static char *brk = memory;
+
+static void *tiny_sbrk(ptrdiff_t increment)
+{
+ void *p = brk;
+
+ brk += increment;
+
+ if (brk > memory + sizeof memory)
+ {
+ brk -= increment;
+ return NULL;
+ }
+
+ return p;
+}
+#define sbrk tiny_sbrk
+# endif /* ECOS */
+
+#if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
+ ptr_t GC_data_start;
+
+ void GC_init_netbsd_elf(void)
+ {
+ extern ptr_t GC_find_limit(ptr_t, GC_bool);
+ extern char **environ;
+ /* This may need to be environ, without the underscore, for */
+ /* some versions. */
+ GC_data_start = GC_find_limit((ptr_t)&environ, FALSE);
+ }
+#endif
+
+# ifdef OS2
+
+# include <stddef.h>
+
+# if !defined(__IBMC__) && !defined(__WATCOMC__) /* e.g. EMX */
+
+struct exe_hdr {
+ unsigned short magic_number;
+ unsigned short padding[29];
+ long new_exe_offset;
+};
+
+#define E_MAGIC(x) (x).magic_number
+#define EMAGIC 0x5A4D
+#define E_LFANEW(x) (x).new_exe_offset
+
+struct e32_exe {
+ unsigned char magic_number[2];
+ unsigned char byte_order;
+ unsigned char word_order;
+ unsigned long exe_format_level;
+ unsigned short cpu;
+ unsigned short os;
+ unsigned long padding1[13];
+ unsigned long object_table_offset;
+ unsigned long object_count;
+ unsigned long padding2[31];
+};
+
+#define E32_MAGIC1(x) (x).magic_number[0]
+#define E32MAGIC1 'L'
+#define E32_MAGIC2(x) (x).magic_number[1]
+#define E32MAGIC2 'X'
+#define E32_BORDER(x) (x).byte_order
+#define E32LEBO 0
+#define E32_WORDER(x) (x).word_order
+#define E32LEWO 0
+#define E32_CPU(x) (x).cpu
+#define E32CPU286 1
+#define E32_OBJTAB(x) (x).object_table_offset
+#define E32_OBJCNT(x) (x).object_count
+
+struct o32_obj {
+ unsigned long size;
+ unsigned long base;
+ unsigned long flags;
+ unsigned long pagemap;
+ unsigned long mapsize;
+ unsigned long reserved;
+};
+
+#define O32_FLAGS(x) (x).flags
+#define OBJREAD 0x0001L
+#define OBJWRITE 0x0002L
+#define OBJINVALID 0x0080L
+#define O32_SIZE(x) (x).size
+#define O32_BASE(x) (x).base
+
+# else /* IBM's compiler */
+
+/* A kludge to get around what appears to be a header file bug */
+# ifndef WORD
+# define WORD unsigned short
+# endif
+# ifndef DWORD
+# define DWORD unsigned long
+# endif
+
+# define EXE386 1
+# include <newexe.h>
+# include <exe386.h>
+
+# endif /* __IBMC__ */
+
+# define INCL_DOSEXCEPTIONS
+# define INCL_DOSPROCESS
+# define INCL_DOSERRORS
+# define INCL_DOSMODULEMGR
+# define INCL_DOSMEMMGR
+# include <os2.h>
+
+
+/* Disable and enable signals during nontrivial allocations */
+
+void GC_disable_signals(void)
+{
+ ULONG nest;
+
+ DosEnterMustComplete(&nest);
+ if (nest != 1) ABORT("nested GC_disable_signals");
+}
+
+void GC_enable_signals(void)
+{
+ ULONG nest;
+
+ DosExitMustComplete(&nest);
+ if (nest != 0) ABORT("GC_enable_signals");
+}
+
+
+# else
+
+# if !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \
+ && !defined(MSWINCE) \
+ && !defined(MACOS) && !defined(DJGPP) && !defined(DOS4GW) \
+ && !defined(NOSYS) && !defined(ECOS)
+
+# if 0
+ /* Use the traditional BSD interface */
+# define SIGSET_T int
+# define SIG_DEL(set, signal) (set) &= ~(sigmask(signal))
+# define SIG_FILL(set) (set) = 0x7fffffff
+ /* Setting the leading bit appears to provoke a bug in some */
+ /* longjmp implementations. Most systems appear not to have */
+ /* a signal 32. */
+# define SIGSETMASK(old, new) (old) = sigsetmask(new)
+# endif
+
+ /* Use POSIX/SYSV interface */
+# define SIGSET_T sigset_t
+# define SIG_DEL(set, signal) sigdelset(&(set), (signal))
+# define SIG_FILL(set) sigfillset(&set)
+# define SIGSETMASK(old, new) sigprocmask(SIG_SETMASK, &(new), &(old))
+
+
+static GC_bool mask_initialized = FALSE;
+
+static SIGSET_T new_mask;
+
+static SIGSET_T old_mask;
+
+static SIGSET_T dummy;
+
+#if defined(GC_ASSERTIONS) && !defined(THREADS)
+# define CHECK_SIGNALS
+ int GC_sig_disabled = 0;
+#endif
+
+void GC_disable_signals(void)
+{
+ if (!mask_initialized) {
+ SIG_FILL(new_mask);
+
+ SIG_DEL(new_mask, SIGSEGV);
+ SIG_DEL(new_mask, SIGILL);
+ SIG_DEL(new_mask, SIGQUIT);
+# ifdef SIGBUS
+ SIG_DEL(new_mask, SIGBUS);
+# endif
+# ifdef SIGIOT
+ SIG_DEL(new_mask, SIGIOT);
+# endif
+# ifdef SIGEMT
+ SIG_DEL(new_mask, SIGEMT);
+# endif
+# ifdef SIGTRAP
+ SIG_DEL(new_mask, SIGTRAP);
+# endif
+ mask_initialized = TRUE;
+ }
+# ifdef CHECK_SIGNALS
+ if (GC_sig_disabled != 0) ABORT("Nested disables");
+ GC_sig_disabled++;
+# endif
+ SIGSETMASK(old_mask,new_mask);
+}
+
+void GC_enable_signals(void)
+{
+# ifdef CHECK_SIGNALS
+ if (GC_sig_disabled != 1) ABORT("Unmatched enable");
+ GC_sig_disabled--;
+# endif
+ SIGSETMASK(dummy,old_mask);
+}
+
+# endif /* !PCR */
+
+# endif /*!OS/2 */
+
+/* Ivan Demakov: simplest way (to me) */
+#if defined (DOS4GW)
+ void GC_disable_signals() { }
+ void GC_enable_signals() { }
+#endif
+
+/* Find the page size */
+word GC_page_size;
+
+# if defined(MSWIN32) || defined(MSWINCE)
+ void GC_setpagesize(void)
+ {
+ GetSystemInfo(&GC_sysinfo);
+ GC_page_size = GC_sysinfo.dwPageSize;
+ }
+
+# else
+# if defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(USE_MMAP)
+ void GC_setpagesize(void)
+ {
+ GC_page_size = GETPAGESIZE();
+ }
+# else
+ /* It's acceptable to fake it. */
+ void GC_setpagesize(void)
+ {
+ GC_page_size = HBLKSIZE;
+ }
+# endif
+# endif
+
+/*
+ * Find the base of the stack.
+ * Used only in single-threaded environment.
+ * With threads, GC_mark_roots needs to know how to do this.
+ * Called with allocator lock held.
+ */
+# if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
+# define is_writable(prot) ((prot) == PAGE_READWRITE \
+ || (prot) == PAGE_WRITECOPY \
+ || (prot) == PAGE_EXECUTE_READWRITE \
+ || (prot) == PAGE_EXECUTE_WRITECOPY)
+/* Return the number of bytes that are writable starting at p. */
+/* The pointer p is assumed to be page aligned. */
+/* If base is not 0, *base becomes the beginning of the */
+/* allocation region containing p. */
+word GC_get_writable_length(ptr_t p, ptr_t *base)
+{
+ MEMORY_BASIC_INFORMATION buf;
+ word result;
+ word protect;
+
+ result = VirtualQuery(p, &buf, sizeof(buf));
+ if (result != sizeof(buf)) ABORT("Weird VirtualQuery result");
+ if (base != 0) *base = (ptr_t)(buf.AllocationBase);
+ protect = (buf.Protect & ~(PAGE_GUARD | PAGE_NOCACHE));
+ if (!is_writable(protect)) {
+ return(0);
+ }
+ if (buf.State != MEM_COMMIT) return(0);
+ return(buf.RegionSize);
+}
+
+int GC_get_stack_base(struct GC_stack_base *sb)
+{
+ int dummy;
+ ptr_t sp = (ptr_t)(&dummy);
+ ptr_t trunc_sp = (ptr_t)((word)sp & ~(GC_page_size - 1));
+ word size = GC_get_writable_length(trunc_sp, 0);
+
+ sb -> mem_base = trunc_sp + size;
+ return GC_SUCCESS;
+}
+
+#define HAVE_GET_STACK_BASE
+
+/* This is always called from the main thread. */
+ptr_t GC_get_main_stack_base(void)
+{
+ struct GC_stack_base sb;
+
+ GC_get_stack_base(&sb);
+ return (ptr_t)sb.mem_base;
+}
+
+# endif /* MS Windows */
+
+# ifdef BEOS
+# include <kernel/OS.h>
+ptr_t GC_get_main_stack_base(void){
+ thread_info th;
+ get_thread_info(find_thread(NULL),&th);
+ return th.stack_end;
+}
+# endif /* BEOS */
+
+
+# ifdef OS2
+
+ptr_t GC_get_main_stack_base(void)
+{
+ PTIB ptib;
+ PPIB ppib;
+
+ if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
+ GC_err_printf("DosGetInfoBlocks failed\n");
+ ABORT("DosGetInfoBlocks failed\n");
+ }
+ return((ptr_t)(ptib -> tib_pstacklimit));
+}
+
+# endif /* OS2 */
+
+# ifdef AMIGA
+# define GC_AMIGA_SB
+# include "AmigaOS.c"
+# undef GC_AMIGA_SB
+# endif /* AMIGA */
+
+# if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE)
+
+ typedef void (*handler)(int);
+
+# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \
+ || defined(HURD) || defined(NETBSD)
+ static struct sigaction old_segv_act;
+# if defined(_sigargs) /* !Irix6.x */ || defined(HPUX) \
+ || defined(HURD) || defined(NETBSD)
+ static struct sigaction old_bus_act;
+# endif
+# else
+ static handler old_segv_handler, old_bus_handler;
+# endif
+
+ void GC_set_and_save_fault_handler(handler h)
+ {
+# if defined(SUNOS5SIGS) || defined(IRIX5) \
+ || defined(OSF1) || defined(HURD) || defined(NETBSD)
+ struct sigaction act;
+
+ act.sa_handler = h;
+# if 0 /* Was necessary for Solaris 2.3 and very temporary */
+ /* NetBSD bugs. */
+ act.sa_flags = SA_RESTART | SA_NODEFER;
+# else
+ act.sa_flags = SA_RESTART;
+# endif
+
+ (void) sigemptyset(&act.sa_mask);
+# ifdef GC_IRIX_THREADS
+ /* Older versions have a bug related to retrieving and */
+ /* and setting a handler at the same time. */
+ (void) sigaction(SIGSEGV, 0, &old_segv_act);
+ (void) sigaction(SIGSEGV, &act, 0);
+# else
+ (void) sigaction(SIGSEGV, &act, &old_segv_act);
+# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
+ || defined(HPUX) || defined(HURD) || defined(NETBSD)
+ /* Under Irix 5.x or HP/UX, we may get SIGBUS. */
+ /* Pthreads doesn't exist under Irix 5.x, so we */
+ /* don't have to worry in the threads case. */
+ (void) sigaction(SIGBUS, &act, &old_bus_act);
+# endif
+# endif /* GC_IRIX_THREADS */
+# else
+ old_segv_handler = signal(SIGSEGV, h);
+# ifdef SIGBUS
+ old_bus_handler = signal(SIGBUS, h);
+# endif
+# endif
+ }
+# endif /* NEED_FIND_LIMIT || UNIX_LIKE */
+
+# if defined(NEED_FIND_LIMIT) || \
+ defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)
+ /* Some tools to implement HEURISTIC2 */
+# define MIN_PAGE_SIZE 256 /* Smallest conceivable page size, bytes */
+
+ /*ARGSUSED*/
+ void GC_fault_handler(int sig)
+ {
+ LONGJMP(GC_jmp_buf, 1);
+ }
+
+ void GC_setup_temporary_fault_handler(void)
+ {
+ /* Handler is process-wide, so this should only happen in */
+ /* one thread at a time. */
+ GC_ASSERT(I_HOLD_LOCK());
+ GC_set_and_save_fault_handler(GC_fault_handler);
+ }
+
+ void GC_reset_fault_handler(void)
+ {
+# if defined(SUNOS5SIGS) || defined(IRIX5) \
+ || defined(OSF1) || defined(HURD) || defined(NETBSD)
+ (void) sigaction(SIGSEGV, &old_segv_act, 0);
+# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
+ || defined(HPUX) || defined(HURD) || defined(NETBSD)
+ (void) sigaction(SIGBUS, &old_bus_act, 0);
+# endif
+# else
+ (void) signal(SIGSEGV, old_segv_handler);
+# ifdef SIGBUS
+ (void) signal(SIGBUS, old_bus_handler);
+# endif
+# endif
+ }
+
+ /* Return the first nonaddressible location > p (up) or */
+ /* the smallest location q s.t. [q,p) is addressable (!up). */
+ /* We assume that p (up) or p-1 (!up) is addressable. */
+ /* Requires allocation lock. */
+ ptr_t GC_find_limit_with_bound(ptr_t p, GC_bool up, ptr_t bound)
+ {
+ static volatile ptr_t result;
+ /* Safer if static, since otherwise it may not be */
+ /* preserved across the longjmp. Can safely be */
+ /* static since it's only called with the */
+ /* allocation lock held. */
+
+ GC_ASSERT(I_HOLD_LOCK());
+ GC_setup_temporary_fault_handler();
+ if (SETJMP(GC_jmp_buf) == 0) {
+ result = (ptr_t)(((word)(p))
+ & ~(MIN_PAGE_SIZE-1));
+ for (;;) {
+ if (up) {
+ result += MIN_PAGE_SIZE;
+ if (result >= bound) return bound;
+ } else {
+ result -= MIN_PAGE_SIZE;
+ if (result <= bound) return bound;
+ }
+ GC_noop1((word)(*result));
+ }
+ }
+ GC_reset_fault_handler();
+ if (!up) {
+ result += MIN_PAGE_SIZE;
+ }
+ return(result);
+ }
+
+ ptr_t GC_find_limit(ptr_t p, GC_bool up)
+ {
+ if (up) {
+ return GC_find_limit_with_bound(p, up, (ptr_t)(word)(-1));
+ } else {
+ return GC_find_limit_with_bound(p, up, 0);
+ }
+ }
+# endif
+
+#if defined(ECOS) || defined(NOSYS)
+ ptr_t GC_get_main_stack_base(void)
+ {
+ return STACKBOTTOM;
+ }
+#endif
+
+#ifdef HPUX_STACKBOTTOM
+
+#include <sys/param.h>
+#include <sys/pstat.h>
+
+ ptr_t GC_get_register_stack_base(void)
+ {
+ struct pst_vm_status vm_status;
+
+ int i = 0;
+ while (pstat_getprocvm(&vm_status, sizeof(vm_status), 0, i++) == 1) {
+ if (vm_status.pst_type == PS_RSESTACK) {
+ return (ptr_t) vm_status.pst_vaddr;
+ }
+ }
+
+ /* old way to get the register stackbottom */
+ return (ptr_t)(((word)GC_stackbottom - BACKING_STORE_DISPLACEMENT - 1)
+ & ~(BACKING_STORE_ALIGNMENT - 1));
+ }
+
+#endif /* HPUX_STACK_BOTTOM */
+
+#ifdef LINUX_STACKBOTTOM
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+# define STAT_SKIP 27 /* Number of fields preceding startstack */
+ /* field in /proc/self/stat */
+
+#ifdef USE_LIBC_PRIVATES
+# pragma weak __libc_stack_end
+ extern ptr_t __libc_stack_end;
+#endif
+
+# ifdef IA64
+# ifdef USE_LIBC_PRIVATES
+# pragma weak __libc_ia64_register_backing_store_base
+ extern ptr_t __libc_ia64_register_backing_store_base;
+# endif
+
+ ptr_t GC_get_register_stack_base(void)
+ {
+ ptr_t result;
+
+# ifdef USE_LIBC_PRIVATES
+ if (0 != &__libc_ia64_register_backing_store_base
+ && 0 != __libc_ia64_register_backing_store_base) {
+ /* Glibc 2.2.4 has a bug such that for dynamically linked */
+ /* executables __libc_ia64_register_backing_store_base is */
+ /* defined but uninitialized during constructor calls. */
+ /* Hence we check for both nonzero address and value. */
+ return __libc_ia64_register_backing_store_base;
+ }
+# endif
+ result = backing_store_base_from_proc();
+ if (0 == result) {
+ result = GC_find_limit(GC_save_regs_in_stack(), FALSE);
+ /* Now seems to work better than constant displacement */
+ /* heuristic used in 6.X versions. The latter seems to */
+ /* fail for 2.6 kernels. */
+ }
+ return result;
+ }
+# endif
+
+ ptr_t GC_linux_stack_base(void)
+ {
+ /* We read the stack base value from /proc/self/stat. We do this */
+ /* using direct I/O system calls in order to avoid calling malloc */
+ /* in case REDIRECT_MALLOC is defined. */
+# define STAT_BUF_SIZE 4096
+# define STAT_READ read
+ /* Should probably call the real read, if read is wrapped. */
+ char stat_buf[STAT_BUF_SIZE];
+ int f;
+ char c;
+ word result = 0;
+ size_t i, buf_offset = 0;
+
+ /* First try the easy way. This should work for glibc 2.2 */
+ /* This fails in a prelinked ("prelink" command) executable */
+ /* since the correct value of __libc_stack_end never */
+ /* becomes visible to us. The second test works around */
+ /* this. */
+# ifdef USE_LIBC_PRIVATES
+ if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {
+# if defined(IA64)
+ /* Some versions of glibc set the address 16 bytes too */
+ /* low while the initialization code is running. */
+ if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) {
+ return __libc_stack_end + 0x10;
+ } /* Otherwise it's not safe to add 16 bytes and we fall */
+ /* back to using /proc. */
+# elif defined(SPARC)
+ /* Older versions of glibc for 64-bit Sparc do not set
+ * this variable correctly, it gets set to either zero
+ * or one.
+ */
+ if (__libc_stack_end != (ptr_t) (unsigned long)0x1)
+ return __libc_stack_end;
+# else
+ return __libc_stack_end;
+# endif
+ }
+# endif
+ f = open("/proc/self/stat", O_RDONLY);
+ if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {
+ ABORT("Couldn't read /proc/self/stat");
+ }
+ c = stat_buf[buf_offset++];
+ /* Skip the required number of fields. This number is hopefully */
+ /* constant across all Linux implementations. */
+ for (i = 0; i < STAT_SKIP; ++i) {
+ while (isspace(c)) c = stat_buf[buf_offset++];
+ while (!isspace(c)) c = stat_buf[buf_offset++];
+ }
+ while (isspace(c)) c = stat_buf[buf_offset++];
+ while (isdigit(c)) {
+ result *= 10;
+ result += c - '0';
+ c = stat_buf[buf_offset++];
+ }
+ close(f);
+ if (result < 0x10000000) ABORT("Absurd stack bottom value");
+ return (ptr_t)result;
+ }
+
+#endif /* LINUX_STACKBOTTOM */
+
+#ifdef FREEBSD_STACKBOTTOM
+
+/* This uses an undocumented sysctl call, but at least one expert */
+/* believes it will stay. */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+ ptr_t GC_freebsd_stack_base(void)
+ {
+ int nm[2] = {CTL_KERN, KERN_USRSTACK};
+ ptr_t base;
+ size_t len = sizeof(ptr_t);
+ int r = sysctl(nm, 2, &base, &len, NULL, 0);
+
+ if (r) ABORT("Error getting stack base");
+
+ return base;
+ }
+
+#endif /* FREEBSD_STACKBOTTOM */
+
+#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
+ && !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) \
+ && !defined(CYGWIN32)
+
+ptr_t GC_get_main_stack_base(void)
+{
+# if defined(HEURISTIC1) || defined(HEURISTIC2)
+ word dummy;
+# endif
+ ptr_t result;
+
+# define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)
+
+# ifdef STACKBOTTOM
+ return(STACKBOTTOM);
+# else
+# ifdef HEURISTIC1
+# ifdef STACK_GROWS_DOWN
+ result = (ptr_t)((((word)(&dummy))
+ + STACKBOTTOM_ALIGNMENT_M1)
+ & ~STACKBOTTOM_ALIGNMENT_M1);
+# else
+ result = (ptr_t)(((word)(&dummy))
+ & ~STACKBOTTOM_ALIGNMENT_M1);
+# endif
+# endif /* HEURISTIC1 */
+# ifdef LINUX_STACKBOTTOM
+ result = GC_linux_stack_base();
+# endif
+# ifdef FREEBSD_STACKBOTTOM
+ result = GC_freebsd_stack_base();
+# endif
+# ifdef HEURISTIC2
+# ifdef STACK_GROWS_DOWN
+ result = GC_find_limit((ptr_t)(&dummy), TRUE);
+# ifdef HEURISTIC2_LIMIT
+ if (result > HEURISTIC2_LIMIT
+ && (ptr_t)(&dummy) < HEURISTIC2_LIMIT) {
+ result = HEURISTIC2_LIMIT;
+ }
+# endif
+# else
+ result = GC_find_limit((ptr_t)(&dummy), FALSE);
+# ifdef HEURISTIC2_LIMIT
+ if (result < HEURISTIC2_LIMIT
+ && (ptr_t)(&dummy) > HEURISTIC2_LIMIT) {
+ result = HEURISTIC2_LIMIT;
+ }
+# endif
+# endif
+
+# endif /* HEURISTIC2 */
+# ifdef STACK_GROWS_DOWN
+ if (result == 0) result = (ptr_t)(signed_word)(-sizeof(ptr_t));
+# endif
+ return(result);
+# endif /* STACKBOTTOM */
+}
+
+# endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS */
+
+#if defined(GC_LINUX_THREADS) && !defined(HAVE_GET_STACK_BASE)
+
+#include <pthread.h>
+
+#ifdef IA64
+ ptr_t GC_greatest_stack_base_below(ptr_t bound);
+ /* From pthread_support.c */
+#endif
+
+int GC_get_stack_base(struct GC_stack_base *b)
+{
+ pthread_attr_t attr;
+ size_t size;
+
+ if (pthread_getattr_np(pthread_self(), &attr) != 0) {
+ WARN("pthread_getattr_np failed\n", 0);
+ return GC_UNIMPLEMENTED;
+ }
+ if (pthread_attr_getstack(&attr, &(b -> mem_base), &size) != 0) {
+ ABORT("pthread_attr_getstack failed");
+ }
+# ifdef STACK_GROWS_DOWN
+ b -> mem_base = (char *)(b -> mem_base) + size;
+# endif
+# ifdef IA64
+ /* We could try backing_store_base_from_proc, but that's safe */
+ /* only if no mappings are being asynchronously created. */
+ /* Subtracting the size from the stack base doesn't work for at */
+ /* least the main thread. */
+ LOCK();
+ {
+ ptr_t bsp = GC_save_regs_in_stack();
+ ptr_t next_stack = GC_greatest_stack_base_below(bsp);
+ if (0 == next_stack) {
+ b -> reg_base = GC_find_limit(bsp, FALSE);
+ } else {
+ /* Avoid walking backwards into preceding memory stack and */
+ /* growing it. */
+ b -> reg_base = GC_find_limit_with_bound(bsp, FALSE, next_stack);
+ }
+ }
+ UNLOCK();
+# endif
+ return GC_SUCCESS;
+}
+
+#define HAVE_GET_STACK_BASE
+
+#endif /* GC_LINUX_THREADS */
+
+#ifndef HAVE_GET_STACK_BASE
+/* Retrieve stack base. */
+/* Using the GC_find_limit version is risky. */
+/* On IA64, for example, there is no guard page between the */
+/* stack of one thread and the register backing store of the */
+/* next. Thus this is likely to identify way too large a */
+/* "stack" and thus at least result in disastrous performance. */
+/* FIXME - Implement better strategies here. */
+int GC_get_stack_base(struct GC_stack_base *b)
+{
+ int dummy;
+
+# ifdef NEED_FIND_LIMIT
+# ifdef STACK_GROWS_DOWN
+ b -> mem_base = GC_find_limit((ptr_t)(&dummy), TRUE);
+# ifdef IA64
+ b -> reg_base = GC_find_limit(GC_save_regs_in_stack(), FALSE);
+# endif
+# else
+ b -> mem_base = GC_find_limit(&dummy, FALSE);
+# endif
+ return GC_SUCCESS;
+# else
+ return GC_UNIMPLEMENTED;
+# endif
+}
+#endif
+
+/*
+ * Register static data segment(s) as roots.
+ * If more data segments are added later then they need to be registered
+ * add that point (as we do with SunOS dynamic loading),
+ * or GC_mark_roots needs to check for them (as we do with PCR).
+ * Called with allocator lock held.
+ */
+
+# ifdef OS2
+
+void GC_register_data_segments(void)
+{
+ PTIB ptib;
+ PPIB ppib;
+ HMODULE module_handle;
+# define PBUFSIZ 512
+ UCHAR path[PBUFSIZ];
+ FILE * myexefile;
+ struct exe_hdr hdrdos; /* MSDOS header. */
+ struct e32_exe hdr386; /* Real header for my executable */
+ struct o32_obj seg; /* Currrent segment */
+ int nsegs;
+
+
+ if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
+ GC_err_printf("DosGetInfoBlocks failed\n");
+ ABORT("DosGetInfoBlocks failed\n");
+ }
+ module_handle = ppib -> pib_hmte;
+ if (DosQueryModuleName(module_handle, PBUFSIZ, path) != NO_ERROR) {
+ GC_err_printf("DosQueryModuleName failed\n");
+ ABORT("DosGetInfoBlocks failed\n");
+ }
+ myexefile = fopen(path, "rb");
+ if (myexefile == 0) {
+ GC_err_puts("Couldn't open executable ");
+ GC_err_puts(path); GC_err_puts("\n");
+ ABORT("Failed to open executable\n");
+ }
+ if (fread((char *)(&hdrdos), 1, sizeof hdrdos, myexefile) < sizeof hdrdos) {
+ GC_err_puts("Couldn't read MSDOS header from ");
+ GC_err_puts(path); GC_err_puts("\n");
+ ABORT("Couldn't read MSDOS header");
+ }
+ if (E_MAGIC(hdrdos) != EMAGIC) {
+ GC_err_puts("Executable has wrong DOS magic number: ");
+ GC_err_puts(path); GC_err_puts("\n");
+ ABORT("Bad DOS magic number");
+ }
+ if (fseek(myexefile, E_LFANEW(hdrdos), SEEK_SET) != 0) {
+ GC_err_puts("Seek to new header failed in ");
+ GC_err_puts(path); GC_err_puts("\n");
+ ABORT("Bad DOS magic number");
+ }
+ if (fread((char *)(&hdr386), 1, sizeof hdr386, myexefile) < sizeof hdr386) {
+ GC_err_puts("Couldn't read MSDOS header from ");
+ GC_err_puts(path); GC_err_puts("\n");
+ ABORT("Couldn't read OS/2 header");
+ }
+ if (E32_MAGIC1(hdr386) != E32MAGIC1 || E32_MAGIC2(hdr386) != E32MAGIC2) {
+ GC_err_puts("Executable has wrong OS/2 magic number:");
+ GC_err_puts(path); GC_err_puts("\n");
+ ABORT("Bad OS/2 magic number");
+ }
+ if ( E32_BORDER(hdr386) != E32LEBO || E32_WORDER(hdr386) != E32LEWO) {
+ GC_err_puts("Executable %s has wrong byte order: ");
+ GC_err_puts(path); GC_err_puts("\n");
+ ABORT("Bad byte order");
+ }
+ if ( E32_CPU(hdr386) == E32CPU286) {
+ GC_err_puts("GC can't handle 80286 executables: ");
+ GC_err_puts(path); GC_err_puts("\n");
+ EXIT();
+ }
+ if (fseek(myexefile, E_LFANEW(hdrdos) + E32_OBJTAB(hdr386),
+ SEEK_SET) != 0) {
+ GC_err_puts("Seek to object table failed: ");
+ GC_err_puts(path); GC_err_puts("\n");
+ ABORT("Seek to object table failed");
+ }
+ for (nsegs = E32_OBJCNT(hdr386); nsegs > 0; nsegs--) {
+ int flags;
+ if (fread((char *)(&seg), 1, sizeof seg, myexefile) < sizeof seg) {
+ GC_err_puts("Couldn't read obj table entry from ");
+ GC_err_puts(path); GC_err_puts("\n");
+ ABORT("Couldn't read obj table entry");
+ }
+ flags = O32_FLAGS(seg);
+ if (!(flags & OBJWRITE)) continue;
+ if (!(flags & OBJREAD)) continue;
+ if (flags & OBJINVALID) {
+ GC_err_printf("Object with invalid pages?\n");
+ continue;
+ }
+ GC_add_roots_inner(O32_BASE(seg), O32_BASE(seg)+O32_SIZE(seg), FALSE);
+ }
+}
+
+# else /* !OS2 */
+
+# if defined(MSWIN32) || defined(MSWINCE)
+
+# ifdef MSWIN32
+ /* Unfortunately, we have to handle win32s very differently from NT, */
+ /* Since VirtualQuery has very different semantics. In particular, */
+ /* under win32s a VirtualQuery call on an unmapped page returns an */
+ /* invalid result. Under NT, GC_register_data_segments is a noop and */
+ /* all real work is done by GC_register_dynamic_libraries. Under */
+ /* win32s, we cannot find the data segments associated with dll's. */
+ /* We register the main data segment here. */
+ GC_bool GC_no_win32_dlls = FALSE;
+ /* This used to be set for gcc, to avoid dealing with */
+ /* the structured exception handling issues. But we now have */
+ /* assembly code to do that right. */
+
+# if defined(GWW_VDB)
+
+# ifndef _BASETSD_H_
+ typedef ULONG * PULONG_PTR;
+# endif
+ typedef UINT (WINAPI * GetWriteWatch_type)(
+ DWORD, PVOID, SIZE_T, PVOID*, PULONG_PTR, PULONG);
+ static GetWriteWatch_type GetWriteWatch_func;
+ static DWORD GetWriteWatch_alloc_flag;
+
+# define GC_GWW_AVAILABLE() (GetWriteWatch_func != NULL)
+
+ static void detect_GetWriteWatch(void)
+ {
+ static GC_bool done;
+ if (done)
+ return;
+
+ GetWriteWatch_func = (GetWriteWatch_type)
+ GetProcAddress(GetModuleHandle("kernel32.dll"), "GetWriteWatch");
+ if (GetWriteWatch_func != NULL) {
+ /* Also check whether VirtualAlloc accepts MEM_WRITE_WATCH, */
+ /* as some versions of kernel32.dll have one but not the */
+ /* other, making the feature completely broken. */
+ void * page = VirtualAlloc(NULL, GC_page_size,
+ MEM_WRITE_WATCH | MEM_RESERVE,
+ PAGE_READWRITE);
+ if (page != NULL) {
+ PVOID pages[16];
+ ULONG_PTR count = 16;
+ DWORD page_size;
+ /* Check that it actually works. In spite of some */
+ /* documentation it actually seems to exist on W2K. */
+ /* This test may be unnecessary, but ... */
+ if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
+ page, GC_page_size,
+ pages,
+ &count,
+ &page_size) != 0) {
+ /* GetWriteWatch always fails. */
+ GetWriteWatch_func = NULL;
+ } else {
+ GetWriteWatch_alloc_flag = MEM_WRITE_WATCH;
+ }
+ VirtualFree(page, GC_page_size, MEM_RELEASE);
+ } else {
+ /* GetWriteWatch will be useless. */
+ GetWriteWatch_func = NULL;
+ }
+ }
+ if (GC_print_stats) {
+ if (GetWriteWatch_func == NULL) {
+ GC_log_printf("Did not find a usable GetWriteWatch()\n");
+ } else {
+ GC_log_printf("Using GetWriteWatch()\n");
+ }
+ }
+ done = TRUE;
+ }
+
+# endif /* GWW_VDB */
+
+ GC_bool GC_wnt = FALSE;
+ /* This is a Windows NT derivative, i.e. NT, W2K, XP or later. */
+
+ void GC_init_win32(void)
+ {
+ /* Set GC_wnt. */
+ /* If we're running under win32s, assume that no DLLs will be loaded */
+ /* I doubt anyone still runs win32s, but ... */
+ DWORD v = GetVersion();
+ GC_wnt = !(v & 0x80000000);
+ GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3);
+ }
+
+ /* Return the smallest address a such that VirtualQuery */
+ /* returns correct results for all addresses between a and start. */
+ /* Assumes VirtualQuery returns correct information for start. */
+ ptr_t GC_least_described_address(ptr_t start)
+ {
+ MEMORY_BASIC_INFORMATION buf;
+ size_t result;
+ LPVOID limit;
+ ptr_t p;
+ LPVOID q;
+
+ limit = GC_sysinfo.lpMinimumApplicationAddress;
+ p = (ptr_t)((word)start & ~(GC_page_size - 1));
+ for (;;) {
+ q = (LPVOID)(p - GC_page_size);
+ if ((ptr_t)q > (ptr_t)p /* underflow */ || q < limit) break;
+ result = VirtualQuery(q, &buf, sizeof(buf));
+ if (result != sizeof(buf) || buf.AllocationBase == 0) break;
+ p = (ptr_t)(buf.AllocationBase);
+ }
+ return p;
+ }
+# endif
+
+# ifndef REDIRECT_MALLOC
+ /* We maintain a linked list of AllocationBase values that we know */
+ /* correspond to malloc heap sections. Currently this is only called */
+ /* during a GC. But there is some hope that for long running */
+ /* programs we will eventually see most heap sections. */
+
+ /* In the long run, it would be more reliable to occasionally walk */
+ /* the malloc heap with HeapWalk on the default heap. But that */
+ /* apparently works only for NT-based Windows. */
+
+ /* In the long run, a better data structure would also be nice ... */
+ struct GC_malloc_heap_list {
+ void * allocation_base;
+ struct GC_malloc_heap_list *next;
+ } *GC_malloc_heap_l = 0;
+
+ /* Is p the base of one of the malloc heap sections we already know */
+ /* about? */
+ GC_bool GC_is_malloc_heap_base(ptr_t p)
+ {
+ struct GC_malloc_heap_list *q = GC_malloc_heap_l;
+
+ while (0 != q) {
+ if (q -> allocation_base == p) return TRUE;
+ q = q -> next;
+ }
+ return FALSE;
+ }
+
+ void *GC_get_allocation_base(void *p)
+ {
+ MEMORY_BASIC_INFORMATION buf;
+ size_t result = VirtualQuery(p, &buf, sizeof(buf));
+ if (result != sizeof(buf)) {
+ ABORT("Weird VirtualQuery result");
+ }
+ return buf.AllocationBase;
+ }
+
+ size_t GC_max_root_size = 100000; /* Appr. largest root size. */
+
+ void GC_add_current_malloc_heap()
+ {
+ struct GC_malloc_heap_list *new_l =
+ malloc(sizeof(struct GC_malloc_heap_list));
+ void * candidate = GC_get_allocation_base(new_l);
+
+ if (new_l == 0) return;
+ if (GC_is_malloc_heap_base(candidate)) {
+ /* Try a little harder to find malloc heap. */
+ size_t req_size = 10000;
+ do {
+ void *p = malloc(req_size);
+ if (0 == p) { free(new_l); return; }
+ candidate = GC_get_allocation_base(p);
+ free(p);
+ req_size *= 2;
+ } while (GC_is_malloc_heap_base(candidate)
+ && req_size < GC_max_root_size/10 && req_size < 500000);
+ if (GC_is_malloc_heap_base(candidate)) {
+ free(new_l); return;
+ }
+ }
+ if (GC_print_stats)
+ GC_log_printf("Found new system malloc AllocationBase at %p\n",
+ candidate);
+ new_l -> allocation_base = candidate;
+ new_l -> next = GC_malloc_heap_l;
+ GC_malloc_heap_l = new_l;
+ }
+# endif /* REDIRECT_MALLOC */
+
+ /* Is p the start of either the malloc heap, or of one of our */
+ /* heap sections? */
+ GC_bool GC_is_heap_base (ptr_t p)
+ {
+
+ unsigned i;
+
+# ifndef REDIRECT_MALLOC
+ static word last_gc_no = (word)(-1);
+
+ if (last_gc_no != GC_gc_no) {
+ GC_add_current_malloc_heap();
+ last_gc_no = GC_gc_no;
+ }
+ if (GC_root_size > GC_max_root_size) GC_max_root_size = GC_root_size;
+ if (GC_is_malloc_heap_base(p)) return TRUE;
+# endif
+ for (i = 0; i < GC_n_heap_bases; i++) {
+ if (GC_heap_bases[i] == p) return TRUE;
+ }
+ return FALSE ;
+ }
+
+# ifdef MSWIN32
+ void GC_register_root_section(ptr_t static_root)
+ {
+ MEMORY_BASIC_INFORMATION buf;
+ size_t result;
+ DWORD protect;
+ LPVOID p;
+ char * base;
+ char * limit, * new_limit;
+
+ if (!GC_no_win32_dlls) return;
+ p = base = limit = GC_least_described_address(static_root);
+ while (p < GC_sysinfo.lpMaximumApplicationAddress) {
+ result = VirtualQuery(p, &buf, sizeof(buf));
+ if (result != sizeof(buf) || buf.AllocationBase == 0
+ || GC_is_heap_base(buf.AllocationBase)) break;
+ new_limit = (char *)p + buf.RegionSize;
+ protect = buf.Protect;
+ if (buf.State == MEM_COMMIT
+ && is_writable(protect)) {
+ if ((char *)p == limit) {
+ limit = new_limit;
+ } else {
+ if (base != limit) GC_add_roots_inner(base, limit, FALSE);
+ base = p;
+ limit = new_limit;
+ }
+ }
+ if (p > (LPVOID)new_limit /* overflow */) break;
+ p = (LPVOID)new_limit;
+ }
+ if (base != limit) GC_add_roots_inner(base, limit, FALSE);
+ }
+#endif
+
+ void GC_register_data_segments()
+ {
+# ifdef MSWIN32
+ static char dummy;
+ GC_register_root_section((ptr_t)(&dummy));
+# endif
+ }
+
+# else /* !OS2 && !Windows */
+
+# if (defined(SVR4) || defined(AUX) || defined(DGUX) \
+ || (defined(LINUX) && defined(SPARC))) && !defined(PCR)
+ptr_t GC_SysVGetDataStart(size_t max_page_size, ptr_t etext_addr)
+{
+ word text_end = ((word)(etext_addr) + sizeof(word) - 1)
+ & ~(sizeof(word) - 1);
+ /* etext rounded to word boundary */
+ word next_page = ((text_end + (word)max_page_size - 1)
+ & ~((word)max_page_size - 1));
+ word page_offset = (text_end & ((word)max_page_size - 1));
+ volatile char * result = (char *)(next_page + page_offset);
+ /* Note that this isnt equivalent to just adding */
+ /* max_page_size to &etext if &etext is at a page boundary */
+
+ GC_setup_temporary_fault_handler();
+ if (SETJMP(GC_jmp_buf) == 0) {
+ /* Try writing to the address. */
+ *result = *result;
+ GC_reset_fault_handler();
+ } else {
+ GC_reset_fault_handler();
+ /* We got here via a longjmp. The address is not readable. */
+ /* This is known to happen under Solaris 2.4 + gcc, which place */
+ /* string constants in the text segment, but after etext. */
+ /* Use plan B. Note that we now know there is a gap between */
+ /* text and data segments, so plan A bought us something. */
+ result = (char *)GC_find_limit((ptr_t)(DATAEND), FALSE);
+ }
+ return((ptr_t)result);
+}
+# endif
+
+# if defined(FREEBSD) && (defined(I386) || defined(X86_64) || defined(powerpc) || defined(__powerpc__)) && !defined(PCR)
+/* Its unclear whether this should be identical to the above, or */
+/* whether it should apply to non-X86 architectures. */
+/* For now we don't assume that there is always an empty page after */
+/* etext. But in some cases there actually seems to be slightly more. */
+/* This also deals with holes between read-only data and writable data. */
+ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr)
+{
+ word text_end = ((word)(etext_addr) + sizeof(word) - 1)
+ & ~(sizeof(word) - 1);
+ /* etext rounded to word boundary */
+ volatile word next_page = (text_end + (word)max_page_size - 1)
+ & ~((word)max_page_size - 1);
+ volatile ptr_t result = (ptr_t)text_end;
+ GC_setup_temporary_fault_handler();
+ if (SETJMP(GC_jmp_buf) == 0) {
+ /* Try reading at the address. */
+ /* This should happen before there is another thread. */
+ for (; next_page < (word)(DATAEND); next_page += (word)max_page_size)
+ *(volatile char *)next_page;
+ GC_reset_fault_handler();
+ } else {
+ GC_reset_fault_handler();
+ /* As above, we go to plan B */
+ result = GC_find_limit((ptr_t)(DATAEND), FALSE);
+ }
+ return(result);
+}
+
+# endif
+
+
+#ifdef AMIGA
+
+# define GC_AMIGA_DS
+# include "AmigaOS.c"
+# undef GC_AMIGA_DS
+
+#else /* !OS2 && !Windows && !AMIGA */
+
+void GC_register_data_segments(void)
+{
+# if !defined(PCR) && !defined(MACOS)
+# if defined(REDIRECT_MALLOC) && defined(GC_SOLARIS_THREADS)
+ /* As of Solaris 2.3, the Solaris threads implementation */
+ /* allocates the data structure for the initial thread with */
+ /* sbrk at process startup. It needs to be scanned, so that */
+ /* we don't lose some malloc allocated data structures */
+ /* hanging from it. We're on thin ice here ... */
+ extern caddr_t sbrk();
+
+ GC_add_roots_inner(DATASTART, (ptr_t)sbrk(0), FALSE);
+# else
+ GC_add_roots_inner(DATASTART, (ptr_t)(DATAEND), FALSE);
+# if defined(DATASTART2)
+ GC_add_roots_inner(DATASTART2, (ptr_t)(DATAEND2), FALSE);
+# endif
+# endif
+# endif
+# if defined(MACOS)
+ {
+# if defined(THINK_C)
+ extern void* GC_MacGetDataStart(void);
+ /* globals begin above stack and end at a5. */
+ GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
+ (ptr_t)LMGetCurrentA5(), FALSE);
+# else
+# if defined(__MWERKS__)
+# if !__POWERPC__
+ extern void* GC_MacGetDataStart(void);
+ /* MATTHEW: Function to handle Far Globals (CW Pro 3) */
+# if __option(far_data)
+ extern void* GC_MacGetDataEnd(void);
+# endif
+ /* globals begin above stack and end at a5. */
+ GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
+ (ptr_t)LMGetCurrentA5(), FALSE);
+ /* MATTHEW: Handle Far Globals */
+# if __option(far_data)
+ /* Far globals follow he QD globals: */
+ GC_add_roots_inner((ptr_t)LMGetCurrentA5(),
+ (ptr_t)GC_MacGetDataEnd(), FALSE);
+# endif
+# else
+ extern char __data_start__[], __data_end__[];
+ GC_add_roots_inner((ptr_t)&__data_start__,
+ (ptr_t)&__data_end__, FALSE);
+# endif /* __POWERPC__ */
+# endif /* __MWERKS__ */
+# endif /* !THINK_C */
+ }
+# endif /* MACOS */
+
+ /* Dynamic libraries are added at every collection, since they may */
+ /* change. */
+}
+
+# endif /* ! AMIGA */
+# endif /* ! MSWIN32 && ! MSWINCE*/
+# endif /* ! OS2 */
+
+/*
+ * Auxiliary routines for obtaining memory from OS.
+ */
+
+# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) \
+ && !defined(MSWIN32) && !defined(MSWINCE) \
+ && !defined(MACOS) && !defined(DOS4GW) && !defined(NONSTOP)
+
+# define SBRK_ARG_T ptrdiff_t
+
+#if defined(MMAP_SUPPORTED)
+
+#ifdef USE_MMAP_FIXED
+# define GC_MMAP_FLAGS MAP_FIXED | MAP_PRIVATE
+ /* Seems to yield better performance on Solaris 2, but can */
+ /* be unreliable if something is already mapped at the address. */
+#else
+# define GC_MMAP_FLAGS MAP_PRIVATE
+#endif
+
+#ifdef USE_MMAP_ANON
+# define zero_fd -1
+# if defined(MAP_ANONYMOUS)
+# define OPT_MAP_ANON MAP_ANONYMOUS
+# else
+# define OPT_MAP_ANON MAP_ANON
+# endif
+#else
+ static int zero_fd;
+# define OPT_MAP_ANON 0
+#endif
+
+#ifndef HEAP_START
+# define HEAP_START 0
+#endif
+
+ptr_t GC_unix_mmap_get_mem(word bytes)
+{
+ void *result;
+ static ptr_t last_addr = HEAP_START;
+
+# ifndef USE_MMAP_ANON
+ static GC_bool initialized = FALSE;
+
+ if (!initialized) {
+ zero_fd = open("/dev/zero", O_RDONLY);
+ fcntl(zero_fd, F_SETFD, FD_CLOEXEC);
+ initialized = TRUE;
+ }
+# endif
+
+ if (bytes & (GC_page_size -1)) ABORT("Bad GET_MEM arg");
+ result = mmap(last_addr, bytes, PROT_READ | PROT_WRITE | OPT_PROT_EXEC,
+ GC_MMAP_FLAGS | OPT_MAP_ANON, zero_fd, 0/* offset */);
+ if (result == MAP_FAILED) return(0);
+ last_addr = (ptr_t)result + bytes + GC_page_size - 1;
+ last_addr = (ptr_t)((word)last_addr & ~(GC_page_size - 1));
+# if !defined(LINUX)
+ if (last_addr == 0) {
+ /* Oops. We got the end of the address space. This isn't */
+ /* usable by arbitrary C code, since one-past-end pointers */
+ /* don't work, so we discard it and try again. */
+ munmap(result, (size_t)(-GC_page_size) - (size_t)result);
+ /* Leave last page mapped, so we can't repeat. */
+ return GC_unix_mmap_get_mem(bytes);
+ }
+# else
+ GC_ASSERT(last_addr != 0);
+# endif
+ return((ptr_t)result);
+}
+
+# endif /* MMAP_SUPPORTED */
+
+#if defined(USE_MMAP)
+
+ptr_t GC_unix_get_mem(word bytes)
+{
+ return GC_unix_mmap_get_mem(bytes);
+}
+
+#else /* Not USE_MMAP */
+
+ptr_t GC_unix_sbrk_get_mem(word bytes)
+{
+ ptr_t result;
+# ifdef IRIX5
+ /* Bare sbrk isn't thread safe. Play by malloc rules. */
+ /* The equivalent may be needed on other systems as well. */
+ __LOCK_MALLOC();
+# endif
+ {
+ ptr_t cur_brk = (ptr_t)sbrk(0);
+ SBRK_ARG_T lsbs = (word)cur_brk & (GC_page_size-1);
+
+ if ((SBRK_ARG_T)bytes < 0) {
+ result = 0; /* too big */
+ goto out;
+ }
+ if (lsbs != 0) {
+ if((ptr_t)sbrk(GC_page_size - lsbs) == (ptr_t)(-1)) {
+ result = 0;
+ goto out;
+ }
+ }
+# ifdef ADD_HEAP_GUARD_PAGES
+ /* This is useful for catching severe memory overwrite problems that */
+ /* span heap sections. It shouldn't otherwise be turned on. */
+ {
+ ptr_t guard = (ptr_t)sbrk((SBRK_ARG_T)GC_page_size);
+ if (mprotect(guard, GC_page_size, PROT_NONE) != 0)
+ ABORT("ADD_HEAP_GUARD_PAGES: mprotect failed");
+ }
+# endif /* ADD_HEAP_GUARD_PAGES */
+ result = (ptr_t)sbrk((SBRK_ARG_T)bytes);
+ if (result == (ptr_t)(-1)) result = 0;
+ }
+ out:
+# ifdef IRIX5
+ __UNLOCK_MALLOC();
+# endif
+ return(result);
+}
+
+#if defined(MMAP_SUPPORTED)
+
+/* By default, we try both sbrk and mmap, in that order. */
+ptr_t GC_unix_get_mem(word bytes)
+{
+ static GC_bool sbrk_failed = FALSE;
+ ptr_t result = 0;
+
+ if (!sbrk_failed) result = GC_unix_sbrk_get_mem(bytes);
+ if (0 == result) {
+ sbrk_failed = TRUE;
+ result = GC_unix_mmap_get_mem(bytes);
+ }
+ if (0 == result) {
+ /* Try sbrk again, in case sbrk memory became available. */
+ result = GC_unix_sbrk_get_mem(bytes);
+ }
+ return result;
+}
+
+#else /* !MMAP_SUPPORTED */
+
+ptr_t GC_unix_get_mem(word bytes)
+{
+ return GC_unix_sbrk_get_mem(bytes);
+}
+
+#endif
+
+#endif /* Not USE_MMAP */
+
+# endif /* UN*X */
+
+# ifdef OS2
+
+void * os2_alloc(size_t bytes)
+{
+ void * result;
+
+ if (DosAllocMem(&result, bytes, PAG_EXECUTE | PAG_READ |
+ PAG_WRITE | PAG_COMMIT)
+ != NO_ERROR) {
+ return(0);
+ }
+ if (result == 0) return(os2_alloc(bytes));
+ return(result);
+}
+
+# endif /* OS2 */
+
+
+# if defined(MSWIN32) || defined(MSWINCE)
+SYSTEM_INFO GC_sysinfo;
+# endif
+
+# ifdef MSWIN32
+
+# ifdef USE_GLOBAL_ALLOC
+# define GLOBAL_ALLOC_TEST 1
+# else
+# define GLOBAL_ALLOC_TEST GC_no_win32_dlls
+# endif
+
+word GC_n_heap_bases = 0;
+
+word GC_mem_top_down = 0; /* Change to MEM_TOP_DOWN for better 64-bit */
+ /* testing. Otherwise all addresses tend to */
+ /* end up in first 4GB, hiding bugs. */
+
+ptr_t GC_win32_get_mem(word bytes)
+{
+ ptr_t result;
+
+ if (GLOBAL_ALLOC_TEST) {
+ /* VirtualAlloc doesn't like PAGE_EXECUTE_READWRITE. */
+ /* There are also unconfirmed rumors of other */
+ /* problems, so we dodge the issue. */
+ result = (ptr_t) GlobalAlloc(0, bytes + HBLKSIZE);
+ result = (ptr_t)(((word)result + HBLKSIZE - 1) & ~(HBLKSIZE-1));
+ } else {
+ /* VirtualProtect only works on regions returned by a */
+ /* single VirtualAlloc call. Thus we allocate one */
+ /* extra page, which will prevent merging of blocks */
+ /* in separate regions, and eliminate any temptation */
+ /* to call VirtualProtect on a range spanning regions. */
+ /* This wastes a small amount of memory, and risks */
+ /* increased fragmentation. But better alternatives */
+ /* would require effort. */
+ /* Pass the MEM_WRITE_WATCH only if GetWriteWatch-based */
+ /* VDBs are enabled and the GetWriteWatch function is */
+ /* available. Otherwise we waste resources or possibly */
+ /* cause VirtualAlloc to fail (observed in Windows 2000 */
+ /* SP2). */
+ result = (ptr_t) VirtualAlloc(NULL, bytes + 1,
+# ifdef GWW_VDB
+ GetWriteWatch_alloc_flag |
+# endif
+ MEM_COMMIT | MEM_RESERVE
+ | GC_mem_top_down,
+ PAGE_EXECUTE_READWRITE);
+ }
+ if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
+ /* If I read the documentation correctly, this can */
+ /* only happen if HBLKSIZE > 64k or not a power of 2. */
+ if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
+ GC_heap_bases[GC_n_heap_bases++] = result;
+ return(result);
+}
+
+void GC_win32_free_heap(void)
+{
+ if (GC_no_win32_dlls) {
+ while (GC_n_heap_bases > 0) {
+ GlobalFree (GC_heap_bases[--GC_n_heap_bases]);
+ GC_heap_bases[GC_n_heap_bases] = 0;
+ }
+ }
+}
+# endif
+
+#ifdef AMIGA
+# define GC_AMIGA_AM
+# include "AmigaOS.c"
+# undef GC_AMIGA_AM
+#endif
+
+
+# ifdef MSWINCE
+word GC_n_heap_bases = 0;
+
+ptr_t GC_wince_get_mem(word bytes)
+{
+ ptr_t result;
+ word i;
+
+ /* Round up allocation size to multiple of page size */
+ bytes = (bytes + GC_page_size-1) & ~(GC_page_size-1);
+
+ /* Try to find reserved, uncommitted pages */
+ for (i = 0; i < GC_n_heap_bases; i++) {
+ if (((word)(-(signed_word)GC_heap_lengths[i])
+ & (GC_sysinfo.dwAllocationGranularity-1))
+ >= bytes) {
+ result = GC_heap_bases[i] + GC_heap_lengths[i];
+ break;
+ }
+ }
+
+ if (i == GC_n_heap_bases) {
+ /* Reserve more pages */
+ word res_bytes = (bytes + GC_sysinfo.dwAllocationGranularity-1)
+ & ~(GC_sysinfo.dwAllocationGranularity-1);
+ /* If we ever support MPROTECT_VDB here, we will probably need to */
+ /* ensure that res_bytes is strictly > bytes, so that VirtualProtect */
+ /* never spans regions. It seems to be OK for a VirtualFree */
+ /* argument to span regions, so we should be OK for now. */
+ result = (ptr_t) VirtualAlloc(NULL, res_bytes,
+ MEM_RESERVE | MEM_TOP_DOWN,
+ PAGE_EXECUTE_READWRITE);
+ if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
+ /* If I read the documentation correctly, this can */
+ /* only happen if HBLKSIZE > 64k or not a power of 2. */
+ if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
+ GC_heap_bases[GC_n_heap_bases] = result;
+ GC_heap_lengths[GC_n_heap_bases] = 0;
+ GC_n_heap_bases++;
+ }
+
+ /* Commit pages */
+ result = (ptr_t) VirtualAlloc(result, bytes,
+ MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE);
+ if (result != NULL) {
+ if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
+ GC_heap_lengths[i] += bytes;
+ }
+
+ return(result);
+}
+# endif
+
+#ifdef USE_MUNMAP
+
+/* For now, this only works on Win32/WinCE and some Unix-like */
+/* systems. If you have something else, don't define */
+/* USE_MUNMAP. */
+/* We assume ANSI C to support this feature. */
+
+#if !defined(MSWIN32) && !defined(MSWINCE)
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#endif
+
+/* Compute a page aligned starting address for the unmap */
+/* operation on a block of size bytes starting at start. */
+/* Return 0 if the block is too small to make this feasible. */
+ptr_t GC_unmap_start(ptr_t start, size_t bytes)
+{
+ ptr_t result = start;
+ /* Round start to next page boundary. */
+ result += GC_page_size - 1;
+ result = (ptr_t)((word)result & ~(GC_page_size - 1));
+ if (result + GC_page_size > start + bytes) return 0;
+ return result;
+}
+
+/* Compute end address for an unmap operation on the indicated */
+/* block. */
+ptr_t GC_unmap_end(ptr_t start, size_t bytes)
+{
+ ptr_t end_addr = start + bytes;
+ end_addr = (ptr_t)((word)end_addr & ~(GC_page_size - 1));
+ return end_addr;
+}
+
+/* Under Win32/WinCE we commit (map) and decommit (unmap) */
+/* memory using VirtualAlloc and VirtualFree. These functions */
+/* work on individual allocations of virtual memory, made */
+/* previously using VirtualAlloc with the MEM_RESERVE flag. */
+/* The ranges we need to (de)commit may span several of these */
+/* allocations; therefore we use VirtualQuery to check */
+/* allocation lengths, and split up the range as necessary. */
+
+/* We assume that GC_remap is called on exactly the same range */
+/* as a previous call to GC_unmap. It is safe to consistently */
+/* round the endpoints in both places. */
+void GC_unmap(ptr_t start, size_t bytes)
+{
+ ptr_t start_addr = GC_unmap_start(start, bytes);
+ ptr_t end_addr = GC_unmap_end(start, bytes);
+ word len = end_addr - start_addr;
+ if (0 == start_addr) return;
+# if defined(MSWIN32) || defined(MSWINCE)
+ while (len != 0) {
+ MEMORY_BASIC_INFORMATION mem_info;
+ GC_word free_len;
+ if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
+ != sizeof(mem_info))
+ ABORT("Weird VirtualQuery result");
+ free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
+ if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
+ ABORT("VirtualFree failed");
+ GC_unmapped_bytes += free_len;
+ start_addr += free_len;
+ len -= free_len;
+ }
+# else
+ /* We immediately remap it to prevent an intervening mmap from */
+ /* accidentally grabbing the same address space. */
+ {
+ void * result;
+ result = mmap(start_addr, len, PROT_NONE,
+ MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
+ zero_fd, 0/* offset */);
+ if (result != (void *)start_addr) ABORT("mmap(...PROT_NONE...) failed");
+ }
+ GC_unmapped_bytes += len;
+# endif
+}
+
+
+void GC_remap(ptr_t start, size_t bytes)
+{
+ ptr_t start_addr = GC_unmap_start(start, bytes);
+ ptr_t end_addr = GC_unmap_end(start, bytes);
+ word len = end_addr - start_addr;
+
+# if defined(MSWIN32) || defined(MSWINCE)
+ ptr_t result;
+
+ if (0 == start_addr) return;
+ while (len != 0) {
+ MEMORY_BASIC_INFORMATION mem_info;
+ GC_word alloc_len;
+ if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
+ != sizeof(mem_info))
+ ABORT("Weird VirtualQuery result");
+ alloc_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
+ result = VirtualAlloc(start_addr, alloc_len,
+ MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE);
+ if (result != start_addr) {
+ ABORT("VirtualAlloc remapping failed");
+ }
+ GC_unmapped_bytes -= alloc_len;
+ start_addr += alloc_len;
+ len -= alloc_len;
+ }
+# else
+ /* It was already remapped with PROT_NONE. */
+ int result;
+
+ if (0 == start_addr) return;
+ result = mprotect(start_addr, len,
+ PROT_READ | PROT_WRITE | OPT_PROT_EXEC);
+ if (result != 0) {
+ GC_err_printf(
+ "Mprotect failed at %p (length %ld) with errno %d\n",
+ start_addr, (unsigned long)len, errno);
+ ABORT("Mprotect remapping failed");
+ }
+ GC_unmapped_bytes -= len;
+# endif
+}
+
+/* Two adjacent blocks have already been unmapped and are about to */
+/* be merged. Unmap the whole block. This typically requires */
+/* that we unmap a small section in the middle that was not previously */
+/* unmapped due to alignment constraints. */
+void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2, size_t bytes2)
+{
+ ptr_t start1_addr = GC_unmap_start(start1, bytes1);
+ ptr_t end1_addr = GC_unmap_end(start1, bytes1);
+ ptr_t start2_addr = GC_unmap_start(start2, bytes2);
+ ptr_t end2_addr = GC_unmap_end(start2, bytes2);
+ ptr_t start_addr = end1_addr;
+ ptr_t end_addr = start2_addr;
+ size_t len;
+ GC_ASSERT(start1 + bytes1 == start2);
+ if (0 == start1_addr) start_addr = GC_unmap_start(start1, bytes1 + bytes2);
+ if (0 == start2_addr) end_addr = GC_unmap_end(start1, bytes1 + bytes2);
+ if (0 == start_addr) return;
+ len = end_addr - start_addr;
+# if defined(MSWIN32) || defined(MSWINCE)
+ while (len != 0) {
+ MEMORY_BASIC_INFORMATION mem_info;
+ GC_word free_len;
+ if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
+ != sizeof(mem_info))
+ ABORT("Weird VirtualQuery result");
+ free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
+ if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
+ ABORT("VirtualFree failed");
+ GC_unmapped_bytes += free_len;
+ start_addr += free_len;
+ len -= free_len;
+ }
+# else
+ if (len != 0 && munmap(start_addr, len) != 0) ABORT("munmap failed");
+ GC_unmapped_bytes += len;
+# endif
+}
+
+#endif /* USE_MUNMAP */
+
+/* Routine for pushing any additional roots. In THREADS */
+/* environment, this is also responsible for marking from */
+/* thread stacks. */
+#ifndef THREADS
+void (*GC_push_other_roots)(void) = 0;
+#else /* THREADS */
+
+# ifdef PCR
+PCR_ERes GC_push_thread_stack(PCR_Th_T *t, PCR_Any dummy)
+{
+ struct PCR_ThCtl_TInfoRep info;
+ PCR_ERes result;
+
+ info.ti_stkLow = info.ti_stkHi = 0;
+ result = PCR_ThCtl_GetInfo(t, &info);
+ GC_push_all_stack((ptr_t)(info.ti_stkLow), (ptr_t)(info.ti_stkHi));
+ return(result);
+}
+
+/* Push the contents of an old object. We treat this as stack */
+/* data only becasue that makes it robust against mark stack */
+/* overflow. */
+PCR_ERes GC_push_old_obj(void *p, size_t size, PCR_Any data)
+{
+ GC_push_all_stack((ptr_t)p, (ptr_t)p + size);
+ return(PCR_ERes_okay);
+}
+
+
+void GC_default_push_other_roots(void)
+{
+ /* Traverse data allocated by previous memory managers. */
+ {
+ extern struct PCR_MM_ProcsRep * GC_old_allocator;
+
+ if ((*(GC_old_allocator->mmp_enumerate))(PCR_Bool_false,
+ GC_push_old_obj, 0)
+ != PCR_ERes_okay) {
+ ABORT("Old object enumeration failed");
+ }
+ }
+ /* Traverse all thread stacks. */
+ if (PCR_ERes_IsErr(
+ PCR_ThCtl_ApplyToAllOtherThreads(GC_push_thread_stack,0))
+ || PCR_ERes_IsErr(GC_push_thread_stack(PCR_Th_CurrThread(), 0))) {
+ ABORT("Thread stack marking failed\n");
+ }
+}
+
+# endif /* PCR */
+
+
+# if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
+
+extern void GC_push_all_stacks(void);
+
+void GC_default_push_other_roots(void)
+{
+ GC_push_all_stacks();
+}
+
+# endif /* GC_WIN32_THREADS || GC_PTHREADS */
+
+void (*GC_push_other_roots)(void) = GC_default_push_other_roots;
+
+#endif /* THREADS */
+
+/*
+ * Routines for accessing dirty bits on virtual pages.
+ * There are six ways to maintain this information:
+ * DEFAULT_VDB: A simple dummy implementation that treats every page
+ * as possibly dirty. This makes incremental collection
+ * useless, but the implementation is still correct.
+ * MANUAL_VDB: Stacks and static data are always considered dirty.
+ * Heap pages are considered dirty if GC_dirty(p) has been
+ * called on some pointer p pointing to somewhere inside
+ * an object on that page. A GC_dirty() call on a large
+ * object directly dirties only a single page, but for
+ * MANUAL_VDB we are careful to treat an object with a dirty
+ * page as completely dirty.
+ * In order to avoid races, an object must be marked dirty
+ * after it is written, and a reference to the object
+ * must be kept on a stack or in a register in the interim.
+ * With threads enabled, an object directly reachable from the
+ * stack at the time of a collection is treated as dirty.
+ * In single-threaded mode, it suffices to ensure that no
+ * collection can take place between the pointer assignment
+ * and the GC_dirty() call.
+ * PCR_VDB: Use PPCRs virtual dirty bit facility.
+ * PROC_VDB: Use the /proc facility for reading dirty bits. Only
+ * works under some SVR4 variants. Even then, it may be
+ * too slow to be entirely satisfactory. Requires reading
+ * dirty bits for entire address space. Implementations tend
+ * to assume that the client is a (slow) debugger.
+ * MPROTECT_VDB:Protect pages and then catch the faults to keep track of
+ * dirtied pages. The implementation (and implementability)
+ * is highly system dependent. This usually fails when system
+ * calls write to a protected page. We prevent the read system
+ * call from doing so. It is the clients responsibility to
+ * make sure that other system calls are similarly protected
+ * or write only to the stack.
+ * GWW_VDB: Use the Win32 GetWriteWatch functions, if available, to
+ * read dirty bits. In case it is not available (because we
+ * are running on Windows 95, Windows 2000 or earlier),
+ * MPROTECT_VDB may be defined as a fallback strategy.
+ */
+GC_bool GC_dirty_maintained = FALSE;
+
+#if defined(PROC_VDB) || defined(GWW_VDB)
+
+/* Add all pages in pht2 to pht1 */
+void GC_or_pages(page_hash_table pht1, page_hash_table pht2)
+{
+ register int i;
+
+ for (i = 0; i < PHT_SIZE; i++) pht1[i] |= pht2[i];
+}
+
+#endif
+
+#ifdef GWW_VDB
+
+# define GC_GWW_BUF_LEN 1024
+ static PVOID gww_buf[GC_GWW_BUF_LEN];
+
+# ifdef MPROTECT_VDB
+ GC_bool GC_gww_dirty_init(void)
+ {
+ detect_GetWriteWatch();
+ return GC_GWW_AVAILABLE();
+ }
+# else
+ void GC_dirty_init(void)
+ {
+ detect_GetWriteWatch();
+ GC_dirty_maintained = GC_GWW_AVAILABLE();
+ }
+# endif
+
+# ifdef MPROTECT_VDB
+ static void GC_gww_read_dirty(void)
+# else
+ void GC_read_dirty(void)
+# endif
+ {
+ word i;
+
+ BZERO(GC_grungy_pages, sizeof(GC_grungy_pages));
+
+ for (i = 0; i != GC_n_heap_sects; ++i) {
+ ULONG_PTR count;
+
+ do {
+ PVOID * pages, * pages_end;
+ DWORD page_size;
+
+ pages = gww_buf;
+ count = GC_GWW_BUF_LEN;
+ /*
+ * GetWriteWatch is documented as returning non-zero when it fails,
+ * but the documentation doesn't explicitly say why it would fail or
+ * what its behaviour will be if it fails.
+ * It does appear to fail, at least on recent W2K instances, if
+ * the underlying memory was not allocated with the appropriate
+ * flag. This is common if GC_enable_incremental is called
+ * shortly after GC initialization. To avoid modifying the
+ * interface, we silently work around such a failure, it it only
+ * affects the initial (small) heap allocation.
+ * If there are more dirty
+ * pages than will fit in the buffer, this is not treated as a
+ * failure; we must check the page count in the loop condition.
+ * Since each partial call will reset the status of some
+ * pages, this should eventually terminate even in the overflow
+ * case.
+ */
+ if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
+ GC_heap_sects[i].hs_start,
+ GC_heap_sects[i].hs_bytes,
+ pages,
+ &count,
+ &page_size) != 0) {
+ static int warn_count = 0;
+ unsigned j;
+ struct hblk * start = (struct hblk *)GC_heap_sects[i].hs_start;
+ static struct hblk *last_warned = 0;
+ size_t nblocks = divHBLKSZ(GC_heap_sects[i].hs_bytes);
+
+ if ( i != 0 && last_warned != start && warn_count++ < 5) {
+ last_warned = start;
+ WARN(
+ "GC_gww_read_dirty unexpectedly failed at %ld: "
+ "Falling back to marking all pages dirty\n", start);
+ }
+ for (j = 0; j < nblocks; ++j) {
+ word hash = PHT_HASH(start + j);
+ set_pht_entry_from_index(GC_grungy_pages, hash);
+ }
+ count = 1; /* Done with this section. */
+ } else /* succeeded */{
+ pages_end = pages + count;
+ while (pages != pages_end) {
+ struct hblk * h = (struct hblk *) *pages++;
+ struct hblk * h_end = (struct hblk *) ((char *) h + page_size);
+ do
+ set_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
+ while (++h < h_end);
+ }
+ }
+ } while (count == GC_GWW_BUF_LEN);
+ }
+
+ GC_or_pages(GC_written_pages, GC_grungy_pages);
+ }
+
+# ifdef MPROTECT_VDB
+ static GC_bool GC_gww_page_was_dirty(struct hblk * h)
+# else
+ GC_bool GC_page_was_dirty(struct hblk * h)
+# endif
+ {
+ return HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
+ }
+
+# ifdef MPROTECT_VDB
+ static GC_bool GC_gww_page_was_ever_dirty(struct hblk * h)
+# else
+ GC_bool GC_page_was_ever_dirty(struct hblk * h)
+# endif
+ {
+ return HDR(h) == 0 || get_pht_entry_from_index(GC_written_pages, PHT_HASH(h));
+ }
+
+# ifndef MPROTECT_VDB
+ void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
+ {}
+# endif
+
+# endif /* GWW_VDB */
+
+# ifdef DEFAULT_VDB
+
+/* All of the following assume the allocation lock is held, and */
+/* signals are disabled. */
+
+/* The client asserts that unallocated pages in the heap are never */
+/* written. */
+
+/* Initialize virtual dirty bit implementation. */
+void GC_dirty_init(void)
+{
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf("Initializing DEFAULT_VDB...\n");
+ GC_dirty_maintained = TRUE;
+}
+
+/* Retrieve system dirty bits for heap to a local buffer. */
+/* Restore the systems notion of which pages are dirty. */
+void GC_read_dirty(void)
+{}
+
+/* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
+/* If the actual page size is different, this returns TRUE if any */
+/* of the pages overlapping h are dirty. This routine may err on the */
+/* side of labelling pages as dirty (and this implementation does). */
+/*ARGSUSED*/
+GC_bool GC_page_was_dirty(struct hblk *h)
+{
+ return(TRUE);
+}
+
+/*
+ * The following two routines are typically less crucial. They matter
+ * most with large dynamic libraries, or if we can't accurately identify
+ * stacks, e.g. under Solaris 2.X. Otherwise the following default
+ * versions are adequate.
+ */
+
+/* Could any valid GC heap pointer ever have been written to this page? */
+/*ARGSUSED*/
+GC_bool GC_page_was_ever_dirty(struct hblk *h)
+{
+ return(TRUE);
+}
+
+/* A call that: */
+/* I) hints that [h, h+nblocks) is about to be written. */
+/* II) guarantees that protection is removed. */
+/* (I) may speed up some dirty bit implementations. */
+/* (II) may be essential if we need to ensure that */
+/* pointer-free system call buffers in the heap are */
+/* not protected. */
+/*ARGSUSED*/
+void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
+{
+}
+
+# endif /* DEFAULT_VDB */
+
+# ifdef MANUAL_VDB
+
+/* Initialize virtual dirty bit implementation. */
+void GC_dirty_init(void)
+{
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf("Initializing MANUAL_VDB...\n");
+ /* GC_dirty_pages and GC_grungy_pages are already cleared. */
+ GC_dirty_maintained = TRUE;
+}
+
+/* Retrieve system dirty bits for heap to a local buffer. */
+/* Restore the systems notion of which pages are dirty. */
+void GC_read_dirty(void)
+{
+ BCOPY((word *)GC_dirty_pages, GC_grungy_pages,
+ (sizeof GC_dirty_pages));
+ BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
+}
+
+/* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
+/* If the actual page size is different, this returns TRUE if any */
+/* of the pages overlapping h are dirty. This routine may err on the */
+/* side of labelling pages as dirty (and this implementation does). */
+/*ARGSUSED*/
+GC_bool GC_page_was_dirty(struct hblk *h)
+{
+ register word index;
+
+ index = PHT_HASH(h);
+ return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index));
+}
+
+/* Could any valid GC heap pointer ever have been written to this page? */
+/*ARGSUSED*/
+GC_bool GC_page_was_ever_dirty(struct hblk *h)
+{
+ /* FIXME - implement me. */
+ return(TRUE);
+}
+
+/* Mark the page containing p as dirty. Logically, this dirties the */
+/* entire object. */
+void GC_dirty(ptr_t p)
+{
+ word index = PHT_HASH(p);
+ async_set_pht_entry_from_index(GC_dirty_pages, index);
+}
+
+/*ARGSUSED*/
+void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
+{
+}
+
+# endif /* MANUAL_VDB */
+
+
+# ifdef MPROTECT_VDB
+
+/*
+ * See DEFAULT_VDB for interface descriptions.
+ */
+
+/*
+ * This implementation maintains dirty bits itself by catching write
+ * faults and keeping track of them. We assume nobody else catches
+ * SIGBUS or SIGSEGV. We assume no write faults occur in system calls.
+ * This means that clients must ensure that system calls don't write
+ * to the write-protected heap. Probably the best way to do this is to
+ * ensure that system calls write at most to POINTERFREE objects in the
+ * heap, and do even that only if we are on a platform on which those
+ * are not protected. Another alternative is to wrap system calls
+ * (see example for read below), but the current implementation holds
+ * applications.
+ * We assume the page size is a multiple of HBLKSIZE.
+ * We prefer them to be the same. We avoid protecting POINTERFREE
+ * objects only if they are the same.
+ */
+
+# if !defined(MSWIN32) && !defined(MSWINCE) && !defined(DARWIN)
+
+# include <sys/mman.h>
+# include <signal.h>
+# include <sys/syscall.h>
+
+# define PROTECT(addr, len) \
+ if (mprotect((caddr_t)(addr), (size_t)(len), \
+ PROT_READ | OPT_PROT_EXEC) < 0) { \
+ ABORT("mprotect failed"); \
+ }
+# define UNPROTECT(addr, len) \
+ if (mprotect((caddr_t)(addr), (size_t)(len), \
+ PROT_WRITE | PROT_READ | OPT_PROT_EXEC ) < 0) { \
+ ABORT("un-mprotect failed"); \
+ }
+
+# else
+
+# ifdef DARWIN
+ /* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to
+ decrease the likelihood of some of the problems described below. */
+ #include <mach/vm_map.h>
+ static mach_port_t GC_task_self;
+ #define PROTECT(addr,len) \
+ if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
+ FALSE,VM_PROT_READ) != KERN_SUCCESS) { \
+ ABORT("vm_portect failed"); \
+ }
+ #define UNPROTECT(addr,len) \
+ if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
+ FALSE,VM_PROT_READ|VM_PROT_WRITE) != KERN_SUCCESS) { \
+ ABORT("vm_portect failed"); \
+ }
+# else
+
+# ifndef MSWINCE
+# include <signal.h>
+# endif
+
+ static DWORD protect_junk;
+# define PROTECT(addr, len) \
+ if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READ, \
+ &protect_junk)) { \
+ DWORD last_error = GetLastError(); \
+ GC_printf("Last error code: %lx\n", last_error); \
+ ABORT("VirtualProtect failed"); \
+ }
+# define UNPROTECT(addr, len) \
+ if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READWRITE, \
+ &protect_junk)) { \
+ ABORT("un-VirtualProtect failed"); \
+ }
+# endif /* !DARWIN */
+# endif /* MSWIN32 || MSWINCE || DARWIN */
+
+#if defined(MSWIN32)
+ typedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_HNDLR_PTR;
+# undef SIG_DFL
+# define SIG_DFL (LPTOP_LEVEL_EXCEPTION_FILTER) (-1)
+#elif defined(MSWINCE)
+ typedef LONG (WINAPI *SIG_HNDLR_PTR)(struct _EXCEPTION_POINTERS *);
+# undef SIG_DFL
+# define SIG_DFL (SIG_HNDLR_PTR) (-1)
+#elif defined(DARWIN)
+ typedef void (* SIG_HNDLR_PTR)();
+#else
+ typedef void (* SIG_HNDLR_PTR)(int, siginfo_t *, void *);
+ typedef void (* PLAIN_HNDLR_PTR)(int);
+#endif
+
+#if defined(__GLIBC__)
+# if __GLIBC__ < 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
+# error glibc too old?
+# endif
+#endif
+
+#ifndef DARWIN
+SIG_HNDLR_PTR GC_old_bus_handler;
+GC_bool GC_old_bus_handler_used_si;
+SIG_HNDLR_PTR GC_old_segv_handler;
+ /* Also old MSWIN32 ACCESS_VIOLATION filter */
+GC_bool GC_old_segv_handler_used_si;
+#endif /* !DARWIN */
+
+#if defined(THREADS)
+/* We need to lock around the bitmap update in the write fault handler */
+/* in order to avoid the risk of losing a bit. We do this with a */
+/* test-and-set spin lock if we know how to do that. Otherwise we */
+/* check whether we are already in the handler and use the dumb but */
+/* safe fallback algorithm of setting all bits in the word. */
+/* Contention should be very rare, so we do the minimum to handle it */
+/* correctly. */
+#ifdef AO_HAVE_test_and_set_acquire
+ static volatile AO_TS_t fault_handler_lock = 0;
+ void async_set_pht_entry_from_index(volatile page_hash_table db, size_t index) {
+ while (AO_test_and_set_acquire(&fault_handler_lock) == AO_TS_SET) {}
+ /* Could also revert to set_pht_entry_from_index_safe if initial */
+ /* GC_test_and_set fails. */
+ set_pht_entry_from_index(db, index);
+ AO_CLEAR(&fault_handler_lock);
+ }
+#else /* !AO_have_test_and_set_acquire */
+# error No test_and_set operation: Introduces a race.
+ /* THIS WOULD BE INCORRECT! */
+ /* The dirty bit vector may be temporarily wrong, */
+ /* just before we notice the conflict and correct it. We may end up */
+ /* looking at it while it's wrong. But this requires contention */
+ /* exactly when a GC is triggered, which seems far less likely to */
+ /* fail than the old code, which had no reported failures. Thus we */
+ /* leave it this way while we think of something better, or support */
+ /* GC_test_and_set on the remaining platforms. */
+ static volatile word currently_updating = 0;
+ void async_set_pht_entry_from_index(volatile page_hash_table db, size_t index) {
+ unsigned int update_dummy;
+ currently_updating = (word)(&update_dummy);
+ set_pht_entry_from_index(db, index);
+ /* If we get contention in the 10 or so instruction window here, */
+ /* and we get stopped by a GC between the two updates, we lose! */
+ if (currently_updating != (word)(&update_dummy)) {
+ set_pht_entry_from_index_safe(db, index);
+ /* We claim that if two threads concurrently try to update the */
+ /* dirty bit vector, the first one to execute UPDATE_START */
+ /* will see it changed when UPDATE_END is executed. (Note that */
+ /* &update_dummy must differ in two distinct threads.) It */
+ /* will then execute set_pht_entry_from_index_safe, thus */
+ /* returning us to a safe state, though not soon enough. */
+ }
+ }
+#endif /* !AO_HAVE_test_and_set_acquire */
+#else /* !THREADS */
+# define async_set_pht_entry_from_index(db, index) \
+ set_pht_entry_from_index(db, index)
+#endif /* !THREADS */
+
+#if !defined(DARWIN)
+# include <errno.h>
+# if defined(FREEBSD)
+# define SIG_OK TRUE
+# define CODE_OK (code == BUS_PAGE_FAULT)
+# elif defined(OSF1)
+# define SIG_OK (sig == SIGSEGV)
+# define CODE_OK (code == 2 /* experimentally determined */)
+# elif defined(IRIX5)
+# define SIG_OK (sig == SIGSEGV)
+# define CODE_OK (code == EACCES)
+# elif defined(HURD)
+# define SIG_OK (sig == SIGBUS || sig == SIGSEGV)
+# define CODE_OK TRUE
+# elif defined(LINUX)
+# define SIG_OK (sig == SIGSEGV)
+# define CODE_OK TRUE
+ /* Empirically c.trapno == 14, on IA32, but is that useful? */
+ /* Should probably consider alignment issues on other */
+ /* architectures. */
+# elif defined(HPUX)
+# define SIG_OK (sig == SIGSEGV || sig == SIGBUS)
+# define CODE_OK (si -> si_code == SEGV_ACCERR) \
+ || (si -> si_code == BUS_ADRERR) \
+ || (si -> si_code == BUS_UNKNOWN) \
+ || (si -> si_code == SEGV_UNKNOWN) \
+ || (si -> si_code == BUS_OBJERR)
+# elif defined(FREEBSD)
+# define SIG_OK (sig == SIGBUS)
+# define CODE_OK (si -> si_code == BUS_PAGE_FAULT)
+# elif defined(SUNOS5SIGS)
+# define SIG_OK (sig == SIGSEGV)
+# define CODE_OK (si -> si_code == SEGV_ACCERR)
+# elif defined(MSWIN32) || defined(MSWINCE)
+# define SIG_OK (exc_info -> ExceptionRecord -> ExceptionCode \
+ == STATUS_ACCESS_VIOLATION)
+# define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] \
+ == 1) /* Write fault */
+# endif
+
+# if defined(MSWIN32) || defined(MSWINCE)
+ LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info)
+# else
+# include <ucontext.h>
+ /*ARGSUSED*/
+ void GC_write_fault_handler(int sig, siginfo_t *si, void *raw_sc)
+# endif /* MSWIN32 || MSWINCE */
+{
+# if !defined(MSWIN32) && !defined(MSWINCE)
+ int code = si -> si_code; /* Ignore gcc unused var. warning. */
+ ucontext_t * scp = (ucontext_t *)raw_sc;
+ /* Ignore gcc unused var. warning. */
+ char *addr = si -> si_addr;
+# endif
+# if defined(MSWIN32) || defined(MSWINCE)
+ char * addr = (char *) (exc_info -> ExceptionRecord
+ -> ExceptionInformation[1]);
+# define sig SIGSEGV
+# endif
+ unsigned i;
+
+ if (SIG_OK && CODE_OK) {
+ register struct hblk * h =
+ (struct hblk *)((word)addr & ~(GC_page_size-1));
+ GC_bool in_allocd_block;
+
+# ifdef SUNOS5SIGS
+ /* Address is only within the correct physical page. */
+ in_allocd_block = FALSE;
+ for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
+ if (HDR(h+i) != 0) {
+ in_allocd_block = TRUE;
+ }
+ }
+# else
+ in_allocd_block = (HDR(addr) != 0);
+# endif
+ if (!in_allocd_block) {
+ /* FIXME - We should make sure that we invoke the */
+ /* old handler with the appropriate calling */
+ /* sequence, which often depends on SA_SIGINFO. */
+
+ /* Heap blocks now begin and end on page boundaries */
+ SIG_HNDLR_PTR old_handler;
+ GC_bool used_si;
+
+ if (sig == SIGSEGV) {
+ old_handler = GC_old_segv_handler;
+ used_si = GC_old_segv_handler_used_si;
+ } else {
+ old_handler = GC_old_bus_handler;
+ used_si = GC_old_bus_handler_used_si;
+ }
+ if (old_handler == (SIG_HNDLR_PTR)SIG_DFL) {
+# if !defined(MSWIN32) && !defined(MSWINCE)
+ GC_err_printf("Segfault at %p\n", addr);
+ ABORT("Unexpected bus error or segmentation fault");
+# else
+ return(EXCEPTION_CONTINUE_SEARCH);
+# endif
+ } else {
+ /*
+ * FIXME: This code should probably check if the
+ * old signal handler used the traditional style and
+ * if so call it using that style.
+ */
+# ifdef MSWIN32
+ return((*old_handler)(exc_info));
+# else
+ if (used_si)
+ ((SIG_HNDLR_PTR)old_handler) (sig, si, raw_sc);
+ else
+ /* FIXME: should pass nonstandard args as well. */
+ ((PLAIN_HNDLR_PTR)old_handler) (sig);
+ return;
+# endif
+ }
+ }
+ UNPROTECT(h, GC_page_size);
+ /* We need to make sure that no collection occurs between */
+ /* the UNPROTECT and the setting of the dirty bit. Otherwise */
+ /* a write by a third thread might go unnoticed. Reversing */
+ /* the order is just as bad, since we would end up unprotecting */
+ /* a page in a GC cycle during which it's not marked. */
+ /* Currently we do this by disabling the thread stopping */
+ /* signals while this handler is running. An alternative might */
+ /* be to record the fact that we're about to unprotect, or */
+ /* have just unprotected a page in the GC's thread structure, */
+ /* and then to have the thread stopping code set the dirty */
+ /* flag, if necessary. */
+ for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
+ size_t index = PHT_HASH(h+i);
+
+ async_set_pht_entry_from_index(GC_dirty_pages, index);
+ }
+ /* The write may not take place before dirty bits are read. */
+ /* But then we'll fault again ... */
+# if defined(MSWIN32) || defined(MSWINCE)
+ return(EXCEPTION_CONTINUE_EXECUTION);
+# else
+ return;
+# endif
+ }
+#if defined(MSWIN32) || defined(MSWINCE)
+ return EXCEPTION_CONTINUE_SEARCH;
+#else
+ GC_err_printf("Segfault at %p\n", addr);
+ ABORT("Unexpected bus error or segmentation fault");
+#endif
+}
+#endif /* !DARWIN */
+
+/*
+ * We hold the allocation lock. We expect block h to be written
+ * shortly. Ensure that all pages containing any part of the n hblks
+ * starting at h are no longer protected. If is_ptrfree is false,
+ * also ensure that they will subsequently appear to be dirty.
+ */
+void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
+{
+ struct hblk * h_trunc; /* Truncated to page boundary */
+ struct hblk * h_end; /* Page boundary following block end */
+ struct hblk * current;
+ GC_bool found_clean;
+
+# if defined(GWW_VDB)
+ if (GC_GWW_AVAILABLE()) return;
+# endif
+ if (!GC_dirty_maintained) return;
+ h_trunc = (struct hblk *)((word)h & ~(GC_page_size-1));
+ h_end = (struct hblk *)(((word)(h + nblocks) + GC_page_size-1)
+ & ~(GC_page_size-1));
+ found_clean = FALSE;
+ for (current = h_trunc; current < h_end; ++current) {
+ size_t index = PHT_HASH(current);
+
+ if (!is_ptrfree || current < h || current >= h + nblocks) {
+ async_set_pht_entry_from_index(GC_dirty_pages, index);
+ }
+ }
+ UNPROTECT(h_trunc, (ptr_t)h_end - (ptr_t)h_trunc);
+}
+
+#if !defined(DARWIN)
+void GC_dirty_init(void)
+{
+# if !defined(MSWIN32) && !defined(MSWINCE)
+ struct sigaction act, oldact;
+ act.sa_flags = SA_RESTART | SA_SIGINFO;
+ act.sa_sigaction = GC_write_fault_handler;
+ (void)sigemptyset(&act.sa_mask);
+# ifdef SIG_SUSPEND
+ /* Arrange to postpone SIG_SUSPEND while we're in a write fault */
+ /* handler. This effectively makes the handler atomic w.r.t. */
+ /* stopping the world for GC. */
+ (void)sigaddset(&act.sa_mask, SIG_SUSPEND);
+# endif /* SIG_SUSPEND */
+# endif
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf(
+ "Initializing mprotect virtual dirty bit implementation\n");
+ GC_dirty_maintained = TRUE;
+ if (GC_page_size % HBLKSIZE != 0) {
+ GC_err_printf("Page size not multiple of HBLKSIZE\n");
+ ABORT("Page size not multiple of HBLKSIZE");
+ }
+# if !defined(MSWIN32) && !defined(MSWINCE)
+# if defined(GC_IRIX_THREADS)
+ sigaction(SIGSEGV, 0, &oldact);
+ sigaction(SIGSEGV, &act, 0);
+# else
+ {
+ int res = sigaction(SIGSEGV, &act, &oldact);
+ if (res != 0) ABORT("Sigaction failed");
+ }
+# endif
+ if (oldact.sa_flags & SA_SIGINFO) {
+ GC_old_segv_handler = oldact.sa_sigaction;
+ GC_old_segv_handler_used_si = TRUE;
+ } else {
+ GC_old_segv_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
+ GC_old_segv_handler_used_si = FALSE;
+ }
+ if (GC_old_segv_handler == (SIG_HNDLR_PTR)SIG_IGN) {
+ GC_err_printf("Previously ignored segmentation violation!?");
+ GC_old_segv_handler = (SIG_HNDLR_PTR)SIG_DFL;
+ }
+ if (GC_old_segv_handler != (SIG_HNDLR_PTR)SIG_DFL) {
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf("Replaced other SIGSEGV handler\n");
+ }
+# endif /* ! MS windows */
+# if defined(HPUX) || defined(LINUX) || defined(HURD) \
+ || (defined(FREEBSD) && defined(SUNOS5SIGS))
+ sigaction(SIGBUS, &act, &oldact);
+ if (oldact.sa_flags & SA_SIGINFO) {
+ GC_old_bus_handler = oldact.sa_sigaction;
+ GC_old_bus_handler_used_si = TRUE;
+ } else {
+ GC_old_bus_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
+ GC_old_bus_handler_used_si = FALSE;
+ }
+ if (GC_old_bus_handler == (SIG_HNDLR_PTR)SIG_IGN) {
+ GC_err_printf("Previously ignored bus error!?");
+ GC_old_bus_handler = (SIG_HNDLR_PTR)SIG_DFL;
+ }
+ if (GC_old_bus_handler != (SIG_HNDLR_PTR)SIG_DFL) {
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf("Replaced other SIGBUS handler\n");
+ }
+# endif /* HPUX || LINUX || HURD || (FREEBSD && SUNOS5SIGS) */
+# if defined(MSWIN32)
+# if defined(GWW_VDB)
+ if (GC_gww_dirty_init())
+ return;
+# endif
+ GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);
+ if (GC_old_segv_handler != NULL) {
+ if (GC_print_stats)
+ GC_log_printf("Replaced other UnhandledExceptionFilter\n");
+ } else {
+ GC_old_segv_handler = SIG_DFL;
+ }
+# endif
+}
+#endif /* !DARWIN */
+
+int GC_incremental_protection_needs(void)
+{
+ if (GC_page_size == HBLKSIZE) {
+ return GC_PROTECTS_POINTER_HEAP;
+ } else {
+ return GC_PROTECTS_POINTER_HEAP | GC_PROTECTS_PTRFREE_HEAP;
+ }
+}
+
+#define HAVE_INCREMENTAL_PROTECTION_NEEDS
+
+#define IS_PTRFREE(hhdr) ((hhdr)->hb_descr == 0)
+
+#define PAGE_ALIGNED(x) !((word)(x) & (GC_page_size - 1))
+void GC_protect_heap(void)
+{
+ ptr_t start;
+ size_t len;
+ struct hblk * current;
+ struct hblk * current_start; /* Start of block to be protected. */
+ struct hblk * limit;
+ unsigned i;
+ GC_bool protect_all =
+ (0 != (GC_incremental_protection_needs() & GC_PROTECTS_PTRFREE_HEAP));
+ for (i = 0; i < GC_n_heap_sects; i++) {
+ start = GC_heap_sects[i].hs_start;
+ len = GC_heap_sects[i].hs_bytes;
+ if (protect_all) {
+ PROTECT(start, len);
+ } else {
+ GC_ASSERT(PAGE_ALIGNED(len))
+ GC_ASSERT(PAGE_ALIGNED(start))
+ current_start = current = (struct hblk *)start;
+ limit = (struct hblk *)(start + len);
+ while (current < limit) {
+ hdr * hhdr;
+ word nhblks;
+ GC_bool is_ptrfree;
+
+ GC_ASSERT(PAGE_ALIGNED(current));
+ GET_HDR(current, hhdr);
+ if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
+ /* This can happen only if we're at the beginning of a */
+ /* heap segment, and a block spans heap segments. */
+ /* We will handle that block as part of the preceding */
+ /* segment. */
+ GC_ASSERT(current_start == current);
+ current_start = ++current;
+ continue;
+ }
+ if (HBLK_IS_FREE(hhdr)) {
+ GC_ASSERT(PAGE_ALIGNED(hhdr -> hb_sz));
+ nhblks = divHBLKSZ(hhdr -> hb_sz);
+ is_ptrfree = TRUE; /* dirty on alloc */
+ } else {
+ nhblks = OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
+ is_ptrfree = IS_PTRFREE(hhdr);
+ }
+ if (is_ptrfree) {
+ if (current_start < current) {
+ PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
+ }
+ current_start = (current += nhblks);
+ } else {
+ current += nhblks;
+ }
+ }
+ if (current_start < current) {
+ PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
+ }
+ }
+ }
+}
+
+/* We assume that either the world is stopped or its OK to lose dirty */
+/* bits while this is happenning (as in GC_enable_incremental). */
+void GC_read_dirty(void)
+{
+# if defined(GWW_VDB)
+ if (GC_GWW_AVAILABLE()) {
+ GC_gww_read_dirty();
+ return;
+ }
+# endif
+ BCOPY((word *)GC_dirty_pages, GC_grungy_pages,
+ (sizeof GC_dirty_pages));
+ BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
+ GC_protect_heap();
+}
+
+GC_bool GC_page_was_dirty(struct hblk *h)
+{
+ register word index;
+
+# if defined(GWW_VDB)
+ if (GC_GWW_AVAILABLE())
+ return GC_gww_page_was_dirty(h);
+# endif
+
+ index = PHT_HASH(h);
+ return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index));
+}
+
+/*
+ * Acquiring the allocation lock here is dangerous, since this
+ * can be called from within GC_call_with_alloc_lock, and the cord
+ * package does so. On systems that allow nested lock acquisition, this
+ * happens to work.
+ * On other systems, SET_LOCK_HOLDER and friends must be suitably defined.
+ */
+
+static GC_bool syscall_acquired_lock = FALSE; /* Protected by GC lock. */
+
+#if 0
+void GC_begin_syscall(void)
+{
+ /* FIXME: Resurrecting this code would require fixing the */
+ /* test, which can spuriously return TRUE. */
+ if (!I_HOLD_LOCK()) {
+ LOCK();
+ syscall_acquired_lock = TRUE;
+ }
+}
+
+void GC_end_syscall(void)
+{
+ if (syscall_acquired_lock) {
+ syscall_acquired_lock = FALSE;
+ UNLOCK();
+ }
+}
+
+void GC_unprotect_range(ptr_t addr, word len)
+{
+ struct hblk * start_block;
+ struct hblk * end_block;
+ register struct hblk *h;
+ ptr_t obj_start;
+
+ if (!GC_dirty_maintained) return;
+ obj_start = GC_base(addr);
+ if (obj_start == 0) return;
+ if (GC_base(addr + len - 1) != obj_start) {
+ ABORT("GC_unprotect_range(range bigger than object)");
+ }
+ start_block = (struct hblk *)((word)addr & ~(GC_page_size - 1));
+ end_block = (struct hblk *)((word)(addr + len - 1) & ~(GC_page_size - 1));
+ end_block += GC_page_size/HBLKSIZE - 1;
+ for (h = start_block; h <= end_block; h++) {
+ register word index = PHT_HASH(h);
+
+ async_set_pht_entry_from_index(GC_dirty_pages, index);
+ }
+ UNPROTECT(start_block,
+ ((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE);
+}
+
+
+/* We no longer wrap read by default, since that was causing too many */
+/* problems. It is preferred that the client instead avoids writing */
+/* to the write-protected heap with a system call. */
+/* This still serves as sample code if you do want to wrap system calls.*/
+
+#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(GC_USE_LD_WRAP)
+/* Replacement for UNIX system call. */
+/* Other calls that write to the heap should be handled similarly. */
+/* Note that this doesn't work well for blocking reads: It will hold */
+/* the allocation lock for the entire duration of the call. Multithreaded */
+/* clients should really ensure that it won't block, either by setting */
+/* the descriptor nonblocking, or by calling select or poll first, to */
+/* make sure that input is available. */
+/* Another, preferred alternative is to ensure that system calls never */
+/* write to the protected heap (see above). */
+# include <unistd.h>
+# include <sys/uio.h>
+ssize_t read(int fd, void *buf, size_t nbyte)
+{
+ int result;
+
+ GC_begin_syscall();
+ GC_unprotect_range(buf, (word)nbyte);
+# if defined(IRIX5) || defined(GC_LINUX_THREADS)
+ /* Indirect system call may not always be easily available. */
+ /* We could call _read, but that would interfere with the */
+ /* libpthread interception of read. */
+ /* On Linux, we have to be careful with the linuxthreads */
+ /* read interception. */
+ {
+ struct iovec iov;
+
+ iov.iov_base = buf;
+ iov.iov_len = nbyte;
+ result = readv(fd, &iov, 1);
+ }
+# else
+# if defined(HURD)
+ result = __read(fd, buf, nbyte);
+# else
+ /* The two zero args at the end of this list are because one
+ IA-64 syscall() implementation actually requires six args
+ to be passed, even though they aren't always used. */
+ result = syscall(SYS_read, fd, buf, nbyte, 0, 0);
+# endif /* !HURD */
+# endif
+ GC_end_syscall();
+ return(result);
+}
+#endif /* !MSWIN32 && !MSWINCE && !GC_LINUX_THREADS */
+
+#if defined(GC_USE_LD_WRAP) && !defined(THREADS)
+ /* We use the GNU ld call wrapping facility. */
+ /* This requires that the linker be invoked with "--wrap read". */
+ /* This can be done by passing -Wl,"--wrap read" to gcc. */
+ /* I'm not sure that this actually wraps whatever version of read */
+ /* is called by stdio. That code also mentions __read. */
+# include <unistd.h>
+ ssize_t __wrap_read(int fd, void *buf, size_t nbyte)
+ {
+ int result;
+
+ GC_begin_syscall();
+ GC_unprotect_range(buf, (word)nbyte);
+ result = __real_read(fd, buf, nbyte);
+ GC_end_syscall();
+ return(result);
+ }
+
+ /* We should probably also do this for __read, or whatever stdio */
+ /* actually calls. */
+#endif
+
+#endif /* 0 */
+
+/*ARGSUSED*/
+GC_bool GC_page_was_ever_dirty(struct hblk *h)
+{
+# if defined(GWW_VDB)
+ if (GC_GWW_AVAILABLE())
+ return GC_gww_page_was_ever_dirty(h);
+# endif
+ return(TRUE);
+}
+
+# endif /* MPROTECT_VDB */
+
+# ifdef PROC_VDB
+
+/*
+ * See DEFAULT_VDB for interface descriptions.
+ */
+
+/*
+ * This implementaion assumes a Solaris 2.X like /proc pseudo-file-system
+ * from which we can read page modified bits. This facility is far from
+ * optimal (e.g. we would like to get the info for only some of the
+ * address space), but it avoids intercepting system calls.
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <sys/procfs.h>
+#include <sys/stat.h>
+
+#define INITIAL_BUF_SZ 16384
+word GC_proc_buf_size = INITIAL_BUF_SZ;
+char *GC_proc_buf;
+
+int GC_proc_fd;
+
+void GC_dirty_init(void)
+{
+ int fd;
+ char buf[30];
+
+ GC_dirty_maintained = TRUE;
+ if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) {
+ register int i;
+
+ for (i = 0; i < PHT_SIZE; i++) GC_written_pages[i] = (word)(-1);
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf(
+ "Allocated bytes:%lu:all pages may have been written\n",
+ (unsigned long)
+ (GC_bytes_allocd + GC_bytes_allocd_before_gc));
+ }
+ sprintf(buf, "/proc/%d", getpid());
+ fd = open(buf, O_RDONLY);
+ if (fd < 0) {
+ ABORT("/proc open failed");
+ }
+ GC_proc_fd = syscall(SYS_ioctl, fd, PIOCOPENPD, 0);
+ close(fd);
+ syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC);
+ if (GC_proc_fd < 0) {
+ ABORT("/proc ioctl failed");
+ }
+ GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size);
+}
+
+/* Ignore write hints. They don't help us here. */
+/*ARGSUSED*/
+void GC_remove_protection(h, nblocks, is_ptrfree)
+struct hblk *h;
+word nblocks;
+GC_bool is_ptrfree;
+{
+}
+
+# define READ(fd,buf,nbytes) read(fd, buf, nbytes)
+
+void GC_read_dirty(void)
+{
+ unsigned long ps, np;
+ int nmaps;
+ ptr_t vaddr;
+ struct prasmap * map;
+ char * bufp;
+ ptr_t current_addr, limit;
+ int i;
+
+ BZERO(GC_grungy_pages, (sizeof GC_grungy_pages));
+
+ bufp = GC_proc_buf;
+ if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
+ if (GC_print_stats)
+ GC_log_printf("/proc read failed: GC_proc_buf_size = %lu\n",
+ (unsigned long)GC_proc_buf_size);
+ {
+ /* Retry with larger buffer. */
+ word new_size = 2 * GC_proc_buf_size;
+ char * new_buf = GC_scratch_alloc(new_size);
+
+ if (new_buf != 0) {
+ GC_proc_buf = bufp = new_buf;
+ GC_proc_buf_size = new_size;
+ }
+ if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
+ WARN("Insufficient space for /proc read\n", 0);
+ /* Punt: */
+ memset(GC_grungy_pages, 0xff, sizeof (page_hash_table));
+ memset(GC_written_pages, 0xff, sizeof(page_hash_table));
+ return;
+ }
+ }
+ }
+ /* Copy dirty bits into GC_grungy_pages */
+ nmaps = ((struct prpageheader *)bufp) -> pr_nmap;
+ /* printf( "nmaps = %d, PG_REFERENCED = %d, PG_MODIFIED = %d\n",
+ nmaps, PG_REFERENCED, PG_MODIFIED); */
+ bufp = bufp + sizeof(struct prpageheader);
+ for (i = 0; i < nmaps; i++) {
+ map = (struct prasmap *)bufp;
+ vaddr = (ptr_t)(map -> pr_vaddr);
+ ps = map -> pr_pagesize;
+ np = map -> pr_npage;
+ /* printf("vaddr = 0x%X, ps = 0x%X, np = 0x%X\n", vaddr, ps, np); */
+ limit = vaddr + ps * np;
+ bufp += sizeof (struct prasmap);
+ for (current_addr = vaddr;
+ current_addr < limit; current_addr += ps){
+ if ((*bufp++) & PG_MODIFIED) {
+ register struct hblk * h = (struct hblk *) current_addr;
+
+ while ((ptr_t)h < current_addr + ps) {
+ register word index = PHT_HASH(h);
+
+ set_pht_entry_from_index(GC_grungy_pages, index);
+ h++;
+ }
+ }
+ }
+ bufp += sizeof(long) - 1;
+ bufp = (char *)((unsigned long)bufp & ~(sizeof(long)-1));
+ }
+ /* Update GC_written_pages. */
+ GC_or_pages(GC_written_pages, GC_grungy_pages);
+}
+
+#undef READ
+
+GC_bool GC_page_was_dirty(struct hblk *h)
+{
+ register word index = PHT_HASH(h);
+ register GC_bool result;
+
+ result = get_pht_entry_from_index(GC_grungy_pages, index);
+ return(result);
+}
+
+GC_bool GC_page_was_ever_dirty(struct hblk *h)
+{
+ register word index = PHT_HASH(h);
+ register GC_bool result;
+
+ result = get_pht_entry_from_index(GC_written_pages, index);
+ return(result);
+}
+
+# endif /* PROC_VDB */
+
+
+# ifdef PCR_VDB
+
+# include "vd/PCR_VD.h"
+
+# define NPAGES (32*1024) /* 128 MB */
+
+PCR_VD_DB GC_grungy_bits[NPAGES];
+
+ptr_t GC_vd_base; /* Address corresponding to GC_grungy_bits[0] */
+ /* HBLKSIZE aligned. */
+
+void GC_dirty_init(void)
+{
+ GC_dirty_maintained = TRUE;
+ /* For the time being, we assume the heap generally grows up */
+ GC_vd_base = GC_heap_sects[0].hs_start;
+ if (GC_vd_base == 0) {
+ ABORT("Bad initial heap segment");
+ }
+ if (PCR_VD_Start(HBLKSIZE, GC_vd_base, NPAGES*HBLKSIZE)
+ != PCR_ERes_okay) {
+ ABORT("dirty bit initialization failed");
+ }
+}
+
+void GC_read_dirty(void)
+{
+ /* lazily enable dirty bits on newly added heap sects */
+ {
+ static int onhs = 0;
+ int nhs = GC_n_heap_sects;
+ for( ; onhs < nhs; onhs++ ) {
+ PCR_VD_WriteProtectEnable(
+ GC_heap_sects[onhs].hs_start,
+ GC_heap_sects[onhs].hs_bytes );
+ }
+ }
+
+
+ if (PCR_VD_Clear(GC_vd_base, NPAGES*HBLKSIZE, GC_grungy_bits)
+ != PCR_ERes_okay) {
+ ABORT("dirty bit read failed");
+ }
+}
+
+GC_bool GC_page_was_dirty(struct hblk *h)
+{
+ if((ptr_t)h < GC_vd_base || (ptr_t)h >= GC_vd_base + NPAGES*HBLKSIZE) {
+ return(TRUE);
+ }
+ return(GC_grungy_bits[h - (struct hblk *)GC_vd_base] & PCR_VD_DB_dirtyBit);
+}
+
+/*ARGSUSED*/
+void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
+{
+ PCR_VD_WriteProtectDisable(h, nblocks*HBLKSIZE);
+ PCR_VD_WriteProtectEnable(h, nblocks*HBLKSIZE);
+}
+
+# endif /* PCR_VDB */
+
+#if defined(MPROTECT_VDB) && defined(DARWIN)
+/* The following sources were used as a *reference* for this exception handling
+ code:
+ 1. Apple's mach/xnu documentation
+ 2. Timothy J. Wood's "Mach Exception Handlers 101" post to the
+ omnigroup's macosx-dev list.
+ www.omnigroup.com/mailman/archive/macosx-dev/2000-June/014178.html
+ 3. macosx-nat.c from Apple's GDB source code.
+*/
+
+/* The bug that caused all this trouble should now be fixed. This should
+ eventually be removed if all goes well. */
+
+/* #define BROKEN_EXCEPTION_HANDLING */
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <mach/thread_status.h>
+#include <mach/exception.h>
+#include <mach/task.h>
+#include <pthread.h>
+
+extern void GC_darwin_register_mach_handler_thread(mach_port_t);
+
+/* These are not defined in any header, although they are documented */
+extern boolean_t
+exc_server(mach_msg_header_t *, mach_msg_header_t *);
+
+extern kern_return_t
+exception_raise(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
+ exception_data_t, mach_msg_type_number_t);
+
+extern kern_return_t
+exception_raise_state(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
+ exception_data_t, mach_msg_type_number_t,
+ thread_state_flavor_t*, thread_state_t,
+ mach_msg_type_number_t, thread_state_t,
+ mach_msg_type_number_t*);
+
+extern kern_return_t
+exception_raise_state_identity(mach_port_t, mach_port_t, mach_port_t,
+ exception_type_t, exception_data_t,
+ mach_msg_type_number_t, thread_state_flavor_t*,
+ thread_state_t, mach_msg_type_number_t,
+ thread_state_t, mach_msg_type_number_t*);
+
+
+#define MAX_EXCEPTION_PORTS 16
+
+static struct {
+ mach_msg_type_number_t count;
+ exception_mask_t masks[MAX_EXCEPTION_PORTS];
+ exception_handler_t ports[MAX_EXCEPTION_PORTS];
+ exception_behavior_t behaviors[MAX_EXCEPTION_PORTS];
+ thread_state_flavor_t flavors[MAX_EXCEPTION_PORTS];
+} GC_old_exc_ports;
+
+static struct {
+ mach_port_t exception;
+#if defined(THREADS)
+ mach_port_t reply;
+#endif
+} GC_ports;
+
+typedef struct {
+ mach_msg_header_t head;
+} GC_msg_t;
+
+typedef enum {
+ GC_MP_NORMAL, GC_MP_DISCARDING, GC_MP_STOPPED
+} GC_mprotect_state_t;
+
+/* FIXME: 1 and 2 seem to be safe to use in the msgh_id field,
+ but it isn't documented. Use the source and see if they
+ should be ok. */
+#define ID_STOP 1
+#define ID_RESUME 2
+
+/* These values are only used on the reply port */
+#define ID_ACK 3
+
+#if defined(THREADS)
+
+GC_mprotect_state_t GC_mprotect_state;
+
+/* The following should ONLY be called when the world is stopped */
+static void GC_mprotect_thread_notify(mach_msg_id_t id)
+{
+
+ struct {
+ GC_msg_t msg;
+ mach_msg_trailer_t trailer;
+ } buf;
+
+ mach_msg_return_t r;
+ /* remote, local */
+ buf.msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
+ buf.msg.head.msgh_size = sizeof(buf.msg);
+ buf.msg.head.msgh_remote_port = GC_ports.exception;
+ buf.msg.head.msgh_local_port = MACH_PORT_NULL;
+ buf.msg.head.msgh_id = id;
+
+ r = mach_msg(&buf.msg.head, MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_LARGE,
+ sizeof(buf.msg), sizeof(buf), GC_ports.reply,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if(r != MACH_MSG_SUCCESS)
+ ABORT("mach_msg failed in GC_mprotect_thread_notify");
+ if(buf.msg.head.msgh_id != ID_ACK)
+ ABORT("invalid ack in GC_mprotect_thread_notify");
+}
+
+/* Should only be called by the mprotect thread */
+static void GC_mprotect_thread_reply(void)
+{
+
+ GC_msg_t msg;
+ mach_msg_return_t r;
+ /* remote, local */
+ msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
+ msg.head.msgh_size = sizeof(msg);
+ msg.head.msgh_remote_port = GC_ports.reply;
+ msg.head.msgh_local_port = MACH_PORT_NULL;
+ msg.head.msgh_id = ID_ACK;
+
+ r = mach_msg(&msg.head, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if(r != MACH_MSG_SUCCESS)
+ ABORT("mach_msg failed in GC_mprotect_thread_reply");
+}
+
+void GC_mprotect_stop(void)
+{
+ GC_mprotect_thread_notify(ID_STOP);
+}
+void GC_mprotect_resume(void)
+{
+ GC_mprotect_thread_notify(ID_RESUME);
+}
+
+#else /* !THREADS */
+/* The compiler should optimize away any GC_mprotect_state computations */
+#define GC_mprotect_state GC_MP_NORMAL
+#endif
+
+static void *GC_mprotect_thread(void *arg)
+{
+ mach_msg_return_t r;
+ /* These two structures contain some private kernel data. We don't need to
+ access any of it so we don't bother defining a proper struct. The
+ correct definitions are in the xnu source code. */
+ struct {
+ mach_msg_header_t head;
+ char data[256];
+ } reply;
+ struct {
+ mach_msg_header_t head;
+ mach_msg_body_t msgh_body;
+ char data[1024];
+ } msg;
+
+ mach_msg_id_t id;
+
+ GC_darwin_register_mach_handler_thread(mach_thread_self());
+
+ for(;;) {
+ r = mach_msg(&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE |
+ (GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0),
+ 0, sizeof(msg), GC_ports.exception,
+ GC_mprotect_state == GC_MP_DISCARDING ? 0
+ : MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1;
+
+# if defined(THREADS)
+ if(GC_mprotect_state == GC_MP_DISCARDING) {
+ if(r == MACH_RCV_TIMED_OUT) {
+ GC_mprotect_state = GC_MP_STOPPED;
+ GC_mprotect_thread_reply();
+ continue;
+ }
+ if(r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME))
+ ABORT("out of order mprotect thread request");
+ }
+# endif /* THREADS */
+
+ if(r != MACH_MSG_SUCCESS) {
+ GC_err_printf("mach_msg failed with %d %s\n", (int)r,
+ mach_error_string(r));
+ ABORT("mach_msg failed");
+ }
+
+ switch(id) {
+# if defined(THREADS)
+ case ID_STOP:
+ if(GC_mprotect_state != GC_MP_NORMAL)
+ ABORT("Called mprotect_stop when state wasn't normal");
+ GC_mprotect_state = GC_MP_DISCARDING;
+ break;
+ case ID_RESUME:
+ if(GC_mprotect_state != GC_MP_STOPPED)
+ ABORT("Called mprotect_resume when state wasn't stopped");
+ GC_mprotect_state = GC_MP_NORMAL;
+ GC_mprotect_thread_reply();
+ break;
+# endif /* THREADS */
+ default:
+ /* Handle the message (calls catch_exception_raise) */
+ if(!exc_server(&msg.head, &reply.head))
+ ABORT("exc_server failed");
+ /* Send the reply */
+ r = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0,
+ MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+ if(r != MACH_MSG_SUCCESS) {
+ /* This will fail if the thread dies, but the thread */
+ /* shouldn't die... */
+# ifdef BROKEN_EXCEPTION_HANDLING
+ GC_err_printf("mach_msg failed with %d %s while sending"
+ "exc reply\n", (int)r,mach_error_string(r));
+# else
+ ABORT("mach_msg failed while sending exception reply");
+# endif
+ }
+ } /* switch */
+ } /* for(;;) */
+ /* NOT REACHED */
+ return NULL;
+}
+
+/* All this SIGBUS code shouldn't be necessary. All protection faults should
+ be going throught the mach exception handler. However, it seems a SIGBUS is
+ occasionally sent for some unknown reason. Even more odd, it seems to be
+ meaningless and safe to ignore. */
+#ifdef BROKEN_EXCEPTION_HANDLING
+
+static SIG_HNDLR_PTR GC_old_bus_handler;
+
+/* Updates to this aren't atomic, but the SIGBUSs seem pretty rare.
+ Even if this doesn't get updated property, it isn't really a problem */
+static int GC_sigbus_count;
+
+static void GC_darwin_sigbus(int num, siginfo_t *sip, void *context)
+{
+ if(num != SIGBUS)
+ ABORT("Got a non-sigbus signal in the sigbus handler");
+
+ /* Ugh... some seem safe to ignore, but too many in a row probably means
+ trouble. GC_sigbus_count is reset for each mach exception that is
+ handled */
+ if(GC_sigbus_count >= 8) {
+ ABORT("Got more than 8 SIGBUSs in a row!");
+ } else {
+ GC_sigbus_count++;
+ WARN("Ignoring SIGBUS.\n", 0);
+ }
+}
+#endif /* BROKEN_EXCEPTION_HANDLING */
+
+void GC_dirty_init(void)
+{
+ kern_return_t r;
+ mach_port_t me;
+ pthread_t thread;
+ pthread_attr_t attr;
+ exception_mask_t mask;
+
+ if (GC_print_stats == VERBOSE)
+ GC_log_printf("Inititalizing mach/darwin mprotect virtual dirty bit "
+ "implementation\n");
+# ifdef BROKEN_EXCEPTION_HANDLING
+ WARN("Enabling workarounds for various darwin "
+ "exception handling bugs.\n", 0);
+# endif
+ GC_dirty_maintained = TRUE;
+ if (GC_page_size % HBLKSIZE != 0) {
+ GC_err_printf("Page size not multiple of HBLKSIZE\n");
+ ABORT("Page size not multiple of HBLKSIZE");
+ }
+
+ GC_task_self = me = mach_task_self();
+
+ r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.exception);
+ if(r != KERN_SUCCESS)
+ ABORT("mach_port_allocate failed (exception port)");
+
+ r = mach_port_insert_right(me, GC_ports.exception, GC_ports.exception,
+ MACH_MSG_TYPE_MAKE_SEND);
+ if(r != KERN_SUCCESS)
+ ABORT("mach_port_insert_right failed (exception port)");
+
+# if defined(THREADS)
+ r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.reply);
+ if(r != KERN_SUCCESS)
+ ABORT("mach_port_allocate failed (reply port)");
+# endif
+
+ /* The exceptions we want to catch */
+ mask = EXC_MASK_BAD_ACCESS;
+
+ r = task_get_exception_ports(me, mask, GC_old_exc_ports.masks,
+ &GC_old_exc_ports.count, GC_old_exc_ports.ports,
+ GC_old_exc_ports.behaviors,
+ GC_old_exc_ports.flavors);
+ if(r != KERN_SUCCESS)
+ ABORT("task_get_exception_ports failed");
+
+ r = task_set_exception_ports(me, mask, GC_ports.exception, EXCEPTION_DEFAULT,
+ GC_MACH_THREAD_STATE);
+ if(r != KERN_SUCCESS)
+ ABORT("task_set_exception_ports failed");
+ if(pthread_attr_init(&attr) != 0)
+ ABORT("pthread_attr_init failed");
+ if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
+ ABORT("pthread_attr_setdetachedstate failed");
+
+# undef pthread_create
+ /* This will call the real pthread function, not our wrapper */
+ if(pthread_create(&thread, &attr, GC_mprotect_thread, NULL) != 0)
+ ABORT("pthread_create failed");
+ pthread_attr_destroy(&attr);
+
+ /* Setup the sigbus handler for ignoring the meaningless SIGBUSs */
+# ifdef BROKEN_EXCEPTION_HANDLING
+ {
+ struct sigaction sa, oldsa;
+ sa.sa_handler = (SIG_HNDLR_PTR)GC_darwin_sigbus;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART|SA_SIGINFO;
+ if(sigaction(SIGBUS, &sa, &oldsa) < 0)
+ ABORT("sigaction");
+ GC_old_bus_handler = (SIG_HNDLR_PTR)oldsa.sa_handler;
+ if (GC_old_bus_handler != SIG_DFL) {
+ if (GC_print_stats == VERBOSE)
+ GC_err_printf("Replaced other SIGBUS handler\n");
+ }
+ }
+# endif /* BROKEN_EXCEPTION_HANDLING */
+}
+
+/* The source code for Apple's GDB was used as a reference for the exception
+ forwarding code. This code is similar to be GDB code only because there is
+ only one way to do it. */
+static kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task,
+ exception_type_t exception,
+ exception_data_t data,
+ mach_msg_type_number_t data_count)
+{
+ unsigned int i;
+ kern_return_t r;
+ mach_port_t port;
+ exception_behavior_t behavior;
+ thread_state_flavor_t flavor;
+
+ thread_state_t thread_state = NULL;
+ mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
+
+ for(i=0; i < GC_old_exc_ports.count; i++)
+ if(GC_old_exc_ports.masks[i] & (1 << exception))
+ break;
+ if(i==GC_old_exc_ports.count)
+ ABORT("No handler for exception!");
+
+ port = GC_old_exc_ports.ports[i];
+ behavior = GC_old_exc_ports.behaviors[i];
+ flavor = GC_old_exc_ports.flavors[i];
+
+ if(behavior != EXCEPTION_DEFAULT) {
+ r = thread_get_state(thread, flavor, thread_state, &thread_state_count);
+ if(r != KERN_SUCCESS)
+ ABORT("thread_get_state failed in forward_exception");
+ }
+
+ switch(behavior) {
+ case EXCEPTION_DEFAULT:
+ r = exception_raise(port, thread, task, exception, data, data_count);
+ break;
+ case EXCEPTION_STATE:
+ r = exception_raise_state(port, thread, task, exception, data, data_count,
+ &flavor, thread_state, thread_state_count,
+ thread_state, &thread_state_count);
+ break;
+ case EXCEPTION_STATE_IDENTITY:
+ r = exception_raise_state_identity(port, thread, task, exception, data,
+ data_count, &flavor, thread_state,
+ thread_state_count, thread_state,
+ &thread_state_count);
+ break;
+ default:
+ r = KERN_FAILURE; /* make gcc happy */
+ ABORT("forward_exception: unknown behavior");
+ break;
+ }
+
+ if(behavior != EXCEPTION_DEFAULT) {
+ r = thread_set_state(thread, flavor, thread_state, thread_state_count);
+ if(r != KERN_SUCCESS)
+ ABORT("thread_set_state failed in forward_exception");
+ }
+
+ return r;
+}
+
+#define FWD() GC_forward_exception(thread, task, exception, code, code_count)
+
+/* This violates the namespace rules but there isn't anything that can be done
+ about it. The exception handling stuff is hard coded to call this */
+kern_return_t
+catch_exception_raise(mach_port_t exception_port, mach_port_t thread,
+ mach_port_t task, exception_type_t exception,
+ exception_data_t code, mach_msg_type_number_t code_count)
+{
+ kern_return_t r;
+ char *addr;
+ struct hblk *h;
+ unsigned int i;
+# if defined(POWERPC)
+# if CPP_WORDSZ == 32
+ thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
+ mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
+ ppc_exception_state_t exc_state;
+# else
+ thread_state_flavor_t flavor = PPC_EXCEPTION_STATE64;
+ mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT;
+ ppc_exception_state64_t exc_state;
+# endif
+# elif defined(I386) || defined(X86_64)
+# if CPP_WORDSZ == 32
+ thread_state_flavor_t flavor = x86_EXCEPTION_STATE32;
+ mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE32_COUNT;
+ x86_exception_state32_t exc_state;
+# else
+ thread_state_flavor_t flavor = x86_EXCEPTION_STATE64;
+ mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE64_COUNT;
+ x86_exception_state64_t exc_state;
+# endif
+# else
+# error FIXME for non-ppc/x86 darwin
+# endif
+
+
+ if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
+# ifdef DEBUG_EXCEPTION_HANDLING
+ /* We aren't interested, pass it on to the old handler */
+ GC_printf("Exception: 0x%x Code: 0x%x 0x%x in catch....\n", exception,
+ code_count > 0 ? code[0] : -1, code_count > 1 ? code[1] : -1);
+# endif
+ return FWD();
+ }
+
+ r = thread_get_state(thread, flavor, (natural_t*)&exc_state,
+ &exc_state_count);
+ if(r != KERN_SUCCESS) {
+ /* The thread is supposed to be suspended while the exception handler
+ is called. This shouldn't fail. */
+# ifdef BROKEN_EXCEPTION_HANDLING
+ GC_err_printf("thread_get_state failed in catch_exception_raise\n");
+ return KERN_SUCCESS;
+# else
+ ABORT("thread_get_state failed in catch_exception_raise");
+# endif
+ }
+
+ /* This is the address that caused the fault */
+# if defined(POWERPC)
+ addr = (char*) exc_state. THREAD_FLD(dar);
+# elif defined (I386) || defined (X86_64)
+ addr = (char*) exc_state. THREAD_FLD(faultvaddr);
+# else
+# error FIXME for non POWERPC/I386
+# endif
+
+ if((HDR(addr)) == 0) {
+ /* Ugh... just like the SIGBUS problem above, it seems we get a bogus
+ KERN_PROTECTION_FAILURE every once and a while. We wait till we get
+ a bunch in a row before doing anything about it. If a "real" fault
+ ever occurres it'll just keep faulting over and over and we'll hit
+ the limit pretty quickly. */
+# ifdef BROKEN_EXCEPTION_HANDLING
+ static char *last_fault;
+ static int last_fault_count;
+
+ if(addr != last_fault) {
+ last_fault = addr;
+ last_fault_count = 0;
+ }
+ if(++last_fault_count < 32) {
+ if(last_fault_count == 1)
+ WARN("Ignoring KERN_PROTECTION_FAILURE at %lx\n", (GC_word)addr);
+ return KERN_SUCCESS;
+ }
+
+ GC_err_printf("Unexpected KERN_PROTECTION_FAILURE at %p\n",addr);
+ /* Can't pass it along to the signal handler because that is
+ ignoring SIGBUS signals. We also shouldn't call ABORT here as
+ signals don't always work too well from the exception handler. */
+ GC_err_printf("Aborting\n");
+ exit(EXIT_FAILURE);
+# else /* BROKEN_EXCEPTION_HANDLING */
+ /* Pass it along to the next exception handler
+ (which should call SIGBUS/SIGSEGV) */
+ return FWD();
+# endif /* !BROKEN_EXCEPTION_HANDLING */
+ }
+
+# ifdef BROKEN_EXCEPTION_HANDLING
+ /* Reset the number of consecutive SIGBUSs */
+ GC_sigbus_count = 0;
+# endif
+
+ if(GC_mprotect_state == GC_MP_NORMAL) { /* common case */
+ h = (struct hblk*)((word)addr & ~(GC_page_size-1));
+ UNPROTECT(h, GC_page_size);
+ for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
+ register int index = PHT_HASH(h+i);
+ async_set_pht_entry_from_index(GC_dirty_pages, index);
+ }
+ } else if(GC_mprotect_state == GC_MP_DISCARDING) {
+ /* Lie to the thread for now. No sense UNPROTECT()ing the memory
+ when we're just going to PROTECT() it again later. The thread
+ will just fault again once it resumes */
+ } else {
+ /* Shouldn't happen, i don't think */
+ GC_printf("KERN_PROTECTION_FAILURE while world is stopped\n");
+ return FWD();
+ }
+ return KERN_SUCCESS;
+}
+#undef FWD
+
+/* These should never be called, but just in case... */
+kern_return_t
+catch_exception_raise_state(mach_port_name_t exception_port, int exception,
+ exception_data_t code,
+ mach_msg_type_number_t codeCnt, int flavor,
+ thread_state_t old_state, int old_stateCnt,
+ thread_state_t new_state, int new_stateCnt)
+{
+ ABORT("catch_exception_raise_state");
+ return(KERN_INVALID_ARGUMENT);
+}
+
+kern_return_t
+catch_exception_raise_state_identity(mach_port_name_t exception_port,
+ mach_port_t thread, mach_port_t task,
+ int exception, exception_data_t code,
+ mach_msg_type_number_t codeCnt, int flavor,
+ thread_state_t old_state, int old_stateCnt,
+ thread_state_t new_state, int new_stateCnt)
+{
+ ABORT("catch_exception_raise_state_identity");
+ return(KERN_INVALID_ARGUMENT);
+}
+
+
+#endif /* DARWIN && MPROTECT_VDB */
+
+# ifndef HAVE_INCREMENTAL_PROTECTION_NEEDS
+ int GC_incremental_protection_needs()
+ {
+ return GC_PROTECTS_NONE;
+ }
+# endif /* !HAVE_INCREMENTAL_PROTECTION_NEEDS */
+
+/*
+ * Call stack save code for debugging.
+ * Should probably be in mach_dep.c, but that requires reorganization.
+ */
+
+/* I suspect the following works for most X86 *nix variants, so */
+/* long as the frame pointer is explicitly stored. In the case of gcc, */
+/* compiler flags (e.g. -fomit-frame-pointer) determine whether it is. */
+#if defined(I386) && defined(LINUX) && defined(SAVE_CALL_CHAIN)
+# include <features.h>
+
+ struct frame {
+ struct frame *fr_savfp;
+ long fr_savpc;
+ long fr_arg[NARGS]; /* All the arguments go here. */
+ };
+#endif
+
+#if defined(SPARC)
+# if defined(LINUX)
+# include <features.h>
+
+ struct frame {
+ long fr_local[8];
+ long fr_arg[6];
+ struct frame *fr_savfp;
+ long fr_savpc;
+# ifndef __arch64__
+ char *fr_stret;
+# endif
+ long fr_argd[6];
+ long fr_argx[0];
+ };
+# elif defined (DRSNX)
+# include <sys/sparc/frame.h>
+# elif defined(OPENBSD)
+# include <frame.h>
+# elif defined(FREEBSD) || defined(NETBSD)
+# include <machine/frame.h>
+# else
+# include <sys/frame.h>
+# endif
+# if NARGS > 6
+# error We only know how to to get the first 6 arguments
+# endif
+#endif /* SPARC */
+
+#ifdef NEED_CALLINFO
+/* Fill in the pc and argument information for up to NFRAMES of my */
+/* callers. Ignore my frame and my callers frame. */
+
+#ifdef LINUX
+# include <unistd.h>
+#endif
+
+#endif /* NEED_CALLINFO */
+
+#if defined(GC_HAVE_BUILTIN_BACKTRACE)
+# ifdef _MSC_VER
+# include "private/msvc_dbg.h"
+# else
+# include <execinfo.h>
+# endif
+#endif
+
+#ifdef SAVE_CALL_CHAIN
+
+#if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \
+ && defined(GC_HAVE_BUILTIN_BACKTRACE)
+
+#ifdef REDIRECT_MALLOC
+ /* Deal with possible malloc calls in backtrace by omitting */
+ /* the infinitely recursing backtrace. */
+# ifdef THREADS
+ __thread /* If your compiler doesn't understand this */
+ /* you could use something like pthread_getspecific. */
+# endif
+ GC_in_save_callers = FALSE;
+#endif
+
+void GC_save_callers (struct callinfo info[NFRAMES])
+{
+ void * tmp_info[NFRAMES + 1];
+ int npcs, i;
+# define IGNORE_FRAMES 1
+
+ /* We retrieve NFRAMES+1 pc values, but discard the first, since it */
+ /* points to our own frame. */
+# ifdef REDIRECT_MALLOC
+ if (GC_in_save_callers) {
+ info[0].ci_pc = (word)(&GC_save_callers);
+ for (i = 1; i < NFRAMES; ++i) info[i].ci_pc = 0;
+ return;
+ }
+ GC_in_save_callers = TRUE;
+# endif
+ GC_ASSERT(sizeof(struct callinfo) == sizeof(void *));
+ npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES);
+ BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *));
+ for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0;
+# ifdef REDIRECT_MALLOC
+ GC_in_save_callers = FALSE;
+# endif
+}
+
+#else /* No builtin backtrace; do it ourselves */
+
+#if (defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD)) && defined(SPARC)
+# define FR_SAVFP fr_fp
+# define FR_SAVPC fr_pc
+#else
+# define FR_SAVFP fr_savfp
+# define FR_SAVPC fr_savpc
+#endif
+
+#if defined(SPARC) && (defined(__arch64__) || defined(__sparcv9))
+# define BIAS 2047
+#else
+# define BIAS 0
+#endif
+
+void GC_save_callers (struct callinfo info[NFRAMES])
+{
+ struct frame *frame;
+ struct frame *fp;
+ int nframes = 0;
+# ifdef I386
+ /* We assume this is turned on only with gcc as the compiler. */
+ asm("movl %%ebp,%0" : "=r"(frame));
+ fp = frame;
+# else
+ frame = (struct frame *) GC_save_regs_in_stack ();
+ fp = (struct frame *)((long) frame -> FR_SAVFP + BIAS);
+#endif
+
+ for (; (!(fp HOTTER_THAN frame) && !(GC_stackbottom HOTTER_THAN (ptr_t)fp)
+ && (nframes < NFRAMES));
+ fp = (struct frame *)((long) fp -> FR_SAVFP + BIAS), nframes++) {
+ register int i;
+
+ info[nframes].ci_pc = fp->FR_SAVPC;
+# if NARGS > 0
+ for (i = 0; i < NARGS; i++) {
+ info[nframes].ci_arg[i] = ~(fp->fr_arg[i]);
+ }
+# endif /* NARGS > 0 */
+ }
+ if (nframes < NFRAMES) info[nframes].ci_pc = 0;
+}
+
+#endif /* No builtin backtrace */
+
+#endif /* SAVE_CALL_CHAIN */
+
+#ifdef NEED_CALLINFO
+
+/* Print info to stderr. We do NOT hold the allocation lock */
+void GC_print_callers (struct callinfo info[NFRAMES])
+{
+ register int i;
+ static int reentry_count = 0;
+ GC_bool stop = FALSE;
+
+ /* FIXME: This should probably use a different lock, so that we */
+ /* become callable with or without the allocation lock. */
+ LOCK();
+ ++reentry_count;
+ UNLOCK();
+
+# if NFRAMES == 1
+ GC_err_printf("\tCaller at allocation:\n");
+# else
+ GC_err_printf("\tCall chain at allocation:\n");
+# endif
+ for (i = 0; i < NFRAMES && !stop ; i++) {
+ if (info[i].ci_pc == 0) break;
+# if NARGS > 0
+ {
+ int j;
+
+ GC_err_printf("\t\targs: ");
+ for (j = 0; j < NARGS; j++) {
+ if (j != 0) GC_err_printf(", ");
+ GC_err_printf("%d (0x%X)", ~(info[i].ci_arg[j]),
+ ~(info[i].ci_arg[j]));
+ }
+ GC_err_printf("\n");
+ }
+# endif
+ if (reentry_count > 1) {
+ /* We were called during an allocation during */
+ /* a previous GC_print_callers call; punt. */
+ GC_err_printf("\t\t##PC##= 0x%lx\n", info[i].ci_pc);
+ continue;
+ }
+ {
+# ifdef LINUX
+ FILE *pipe;
+# endif
+# if defined(GC_HAVE_BUILTIN_BACKTRACE) \
+ && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
+ char **sym_name =
+ backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
+ char *name = sym_name[0];
+# else
+ char buf[40];
+ char *name = buf;
+ sprintf(buf, "##PC##= 0x%lx", info[i].ci_pc);
+# endif
+# if defined(LINUX) && !defined(SMALL_CONFIG)
+ /* Try for a line number. */
+ {
+# define EXE_SZ 100
+ static char exe_name[EXE_SZ];
+# define CMD_SZ 200
+ char cmd_buf[CMD_SZ];
+# define RESULT_SZ 200
+ static char result_buf[RESULT_SZ];
+ size_t result_len;
+ char *old_preload;
+# define PRELOAD_SZ 200
+ char preload_buf[PRELOAD_SZ];
+ static GC_bool found_exe_name = FALSE;
+ static GC_bool will_fail = FALSE;
+ int ret_code;
+ /* Try to get it via a hairy and expensive scheme. */
+ /* First we get the name of the executable: */
+ if (will_fail) goto out;
+ if (!found_exe_name) {
+ ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
+ if (ret_code < 0 || ret_code >= EXE_SZ
+ || exe_name[0] != '/') {
+ will_fail = TRUE; /* Dont try again. */
+ goto out;
+ }
+ exe_name[ret_code] = '\0';
+ found_exe_name = TRUE;
+ }
+ /* Then we use popen to start addr2line -e <exe> <addr> */
+ /* There are faster ways to do this, but hopefully this */
+ /* isn't time critical. */
+ sprintf(cmd_buf, "/usr/bin/addr2line -f -e %s 0x%lx", exe_name,
+ (unsigned long)info[i].ci_pc);
+ old_preload = getenv ("LD_PRELOAD");
+ if (0 != old_preload) {
+ if (strlen (old_preload) >= PRELOAD_SZ) {
+ will_fail = TRUE;
+ goto out;
+ }
+ strcpy (preload_buf, old_preload);
+ unsetenv ("LD_PRELOAD");
+ }
+ pipe = popen(cmd_buf, "r");
+ if (0 != old_preload
+ && 0 != setenv ("LD_PRELOAD", preload_buf, 0)) {
+ WARN("Failed to reset LD_PRELOAD\n", 0);
+ }
+ if (pipe == NULL
+ || (result_len = fread(result_buf, 1, RESULT_SZ - 1, pipe))
+ == 0) {
+ if (pipe != NULL) pclose(pipe);
+ will_fail = TRUE;
+ goto out;
+ }
+ if (result_buf[result_len - 1] == '\n') --result_len;
+ result_buf[result_len] = 0;
+ if (result_buf[0] == '?'
+ || (result_buf[result_len-2] == ':'
+ && result_buf[result_len-1] == '0')) {
+ pclose(pipe);
+ goto out;
+ }
+ /* Get rid of embedded newline, if any. Test for "main" */
+ {
+ char * nl = strchr(result_buf, '\n');
+ if (nl != NULL && nl < result_buf + result_len) {
+ *nl = ':';
+ }
+ if (strncmp(result_buf, "main", nl - result_buf) == 0) {
+ stop = TRUE;
+ }
+ }
+ if (result_len < RESULT_SZ - 25) {
+ /* Add in hex address */
+ sprintf(result_buf + result_len, " [0x%lx]",
+ (unsigned long)info[i].ci_pc);
+ }
+ name = result_buf;
+ pclose(pipe);
+ out:;
+ }
+# endif /* LINUX */
+ GC_err_printf("\t\t%s\n", name);
+# if defined(GC_HAVE_BUILTIN_BACKTRACE) \
+ && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
+ free(sym_name); /* May call GC_free; that's OK */
+# endif
+ }
+ }
+ LOCK();
+ --reentry_count;
+ UNLOCK();
+}
+
+#endif /* NEED_CALLINFO */
+
+
+
+#if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
+
+/* Dump /proc/self/maps to GC_stderr, to enable looking up names for
+ addresses in FIND_LEAK output. */
+
+static word dump_maps(char *maps)
+{
+ GC_err_write(maps, strlen(maps));
+ return 1;
+}
+
+void GC_print_address_map(void)
+{
+ GC_err_printf("---------- Begin address map ----------\n");
+ dump_maps(GC_get_maps());
+ GC_err_printf("---------- End address map ----------\n");
+}
+
+#endif
+
+
diff --git a/tools/build/v2/engine/boehm_gc/pcr_interface.c b/tools/build/v2/engine/boehm_gc/pcr_interface.c
new file mode 100644
index 0000000000..77bddf80bd
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/pcr_interface.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+# include "private/gc_priv.h"
+
+# ifdef PCR
+/*
+ * Note that POSIX PCR requires an ANSI C compiler. Hence we are allowed
+ * to make the same assumption here.
+ * We wrap all of the allocator functions to avoid questions of
+ * compatibility between the prototyped and nonprototyped versions of the f
+ */
+# include "config/PCR_StdTypes.h"
+# include "mm/PCR_MM.h"
+# include <errno.h>
+
+# define MY_MAGIC 17L
+# define MY_DEBUGMAGIC 42L
+
+void * GC_AllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear )
+{
+ if (ptrFree) {
+ void * result = (void *)GC_malloc_atomic(size);
+ if (clear && result != 0) BZERO(result, size);
+ return(result);
+ } else {
+ return((void *)GC_malloc(size));
+ }
+}
+
+void * GC_DebugAllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear )
+{
+ if (ptrFree) {
+ void * result = (void *)GC_debug_malloc_atomic(size, __FILE__,
+ __LINE__);
+ if (clear && result != 0) BZERO(result, size);
+ return(result);
+ } else {
+ return((void *)GC_debug_malloc(size, __FILE__, __LINE__));
+ }
+}
+
+# define GC_ReallocProc GC_realloc
+void * GC_DebugReallocProc(void * old_object, size_t new_size_in_bytes)
+{
+ return(GC_debug_realloc(old_object, new_size_in_bytes, __FILE__, __LINE__));
+}
+
+# define GC_FreeProc GC_free
+# define GC_DebugFreeProc GC_debug_free
+
+typedef struct {
+ PCR_ERes (*ed_proc)(void *p, size_t size, PCR_Any data);
+ GC_bool ed_pointerfree;
+ PCR_ERes ed_fail_code;
+ PCR_Any ed_client_data;
+} enumerate_data;
+
+void GC_enumerate_block(struct hblk *h; enumerate_data * ed)
+{
+ register hdr * hhdr;
+ register int sz;
+ ptr_t p;
+ ptr_t lim;
+ word descr;
+# error This code was updated without testing.
+# error and its precursor was clearly broken.
+
+ hhdr = HDR(h);
+ descr = hhdr -> hb_descr;
+ sz = hhdr -> hb_sz;
+ if (descr != 0 && ed -> ed_pointerfree
+ || descr == 0 && !(ed -> ed_pointerfree)) return;
+ lim = (ptr_t)(h+1) - sz;
+ p = (ptr_t)h;
+ do {
+ if (PCR_ERes_IsErr(ed -> ed_fail_code)) return;
+ ed -> ed_fail_code =
+ (*(ed -> ed_proc))(p, sz, ed -> ed_client_data);
+ p+= sz;
+ } while (p <= lim);
+}
+
+struct PCR_MM_ProcsRep * GC_old_allocator = 0;
+
+PCR_ERes GC_EnumerateProc(
+ PCR_Bool ptrFree,
+ PCR_ERes (*proc)(void *p, size_t size, PCR_Any data),
+ PCR_Any data
+)
+{
+ enumerate_data ed;
+
+ ed.ed_proc = proc;
+ ed.ed_pointerfree = ptrFree;
+ ed.ed_fail_code = PCR_ERes_okay;
+ ed.ed_client_data = data;
+ GC_apply_to_all_blocks(GC_enumerate_block, &ed);
+ if (ed.ed_fail_code != PCR_ERes_okay) {
+ return(ed.ed_fail_code);
+ } else {
+ /* Also enumerate objects allocated by my predecessors */
+ return((*(GC_old_allocator->mmp_enumerate))(ptrFree, proc, data));
+ }
+}
+
+void GC_DummyFreeProc(void *p) {}
+
+void GC_DummyShutdownProc(void) {}
+
+struct PCR_MM_ProcsRep GC_Rep = {
+ MY_MAGIC,
+ GC_AllocProc,
+ GC_ReallocProc,
+ GC_DummyFreeProc, /* mmp_free */
+ GC_FreeProc, /* mmp_unsafeFree */
+ GC_EnumerateProc,
+ GC_DummyShutdownProc /* mmp_shutdown */
+};
+
+struct PCR_MM_ProcsRep GC_DebugRep = {
+ MY_DEBUGMAGIC,
+ GC_DebugAllocProc,
+ GC_DebugReallocProc,
+ GC_DummyFreeProc, /* mmp_free */
+ GC_DebugFreeProc, /* mmp_unsafeFree */
+ GC_EnumerateProc,
+ GC_DummyShutdownProc /* mmp_shutdown */
+};
+
+GC_bool GC_use_debug = 0;
+
+void GC_pcr_install()
+{
+ PCR_MM_Install((GC_use_debug? &GC_DebugRep : &GC_Rep), &GC_old_allocator);
+}
+
+PCR_ERes
+PCR_GC_Setup(void)
+{
+ return PCR_ERes_okay;
+}
+
+PCR_ERes
+PCR_GC_Run(void)
+{
+
+ if( !PCR_Base_TestPCRArg("-nogc") ) {
+ GC_quiet = ( PCR_Base_TestPCRArg("-gctrace") ? 0 : 1 );
+ GC_use_debug = (GC_bool)PCR_Base_TestPCRArg("-debug_alloc");
+ GC_init();
+ if( !PCR_Base_TestPCRArg("-nogc_incremental") ) {
+ /*
+ * awful hack to test whether VD is implemented ...
+ */
+ if( PCR_VD_Start( 0, NIL, 0) != PCR_ERes_FromErr(ENOSYS) ) {
+ GC_enable_incremental();
+ }
+ }
+ }
+ return PCR_ERes_okay;
+}
+
+void GC_push_thread_structures(void)
+{
+ /* PCR doesn't work unless static roots are pushed. Can't get here. */
+ ABORT("In GC_push_thread_structures()");
+}
+
+# endif
diff --git a/tools/build/v2/engine/boehm_gc/pthread_stop_world.c b/tools/build/v2/engine/boehm_gc/pthread_stop_world.c
new file mode 100644
index 0000000000..3a1524b96b
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/pthread_stop_world.c
@@ -0,0 +1,537 @@
+#include "private/pthread_support.h"
+
+#if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) && \
+ !defined(GC_DARWIN_THREADS)
+
+#include <signal.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <unistd.h>
+#include "atomic_ops.h"
+
+#if DEBUG_THREADS
+
+#ifndef NSIG
+# if defined(MAXSIG)
+# define NSIG (MAXSIG+1)
+# elif defined(_NSIG)
+# define NSIG _NSIG
+# elif defined(__SIGRTMAX)
+# define NSIG (__SIGRTMAX+1)
+# else
+ --> please fix it
+# endif
+#endif
+
+void GC_print_sig_mask()
+{
+ sigset_t blocked;
+ int i;
+
+ if (pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0)
+ ABORT("pthread_sigmask");
+ GC_printf("Blocked: ");
+ for (i = 1; i < NSIG; i++) {
+ if (sigismember(&blocked, i)) { GC_printf("%d ", i); }
+ }
+ GC_printf("\n");
+}
+
+#endif
+
+/* Remove the signals that we want to allow in thread stopping */
+/* handler from a set. */
+void GC_remove_allowed_signals(sigset_t *set)
+{
+ if (sigdelset(set, SIGINT) != 0
+ || sigdelset(set, SIGQUIT) != 0
+ || sigdelset(set, SIGABRT) != 0
+ || sigdelset(set, SIGTERM) != 0) {
+ ABORT("sigdelset() failed");
+ }
+
+# ifdef MPROTECT_VDB
+ /* Handlers write to the thread structure, which is in the heap, */
+ /* and hence can trigger a protection fault. */
+ if (sigdelset(set, SIGSEGV) != 0
+# ifdef SIGBUS
+ || sigdelset(set, SIGBUS) != 0
+# endif
+ ) {
+ ABORT("sigdelset() failed");
+ }
+# endif
+}
+
+static sigset_t suspend_handler_mask;
+
+volatile AO_t GC_stop_count;
+ /* Incremented at the beginning of GC_stop_world. */
+
+volatile AO_t GC_world_is_stopped = FALSE;
+ /* FALSE ==> it is safe for threads to restart, i.e. */
+ /* they will see another suspend signal before they */
+ /* are expected to stop (unless they have voluntarily */
+ /* stopped). */
+
+#ifdef GC_OSF1_THREADS
+ GC_bool GC_retry_signals = TRUE;
+#else
+ GC_bool GC_retry_signals = FALSE;
+#endif
+
+/*
+ * We use signals to stop threads during GC.
+ *
+ * Suspended threads wait in signal handler for SIG_THR_RESTART.
+ * That's more portable than semaphores or condition variables.
+ * (We do use sem_post from a signal handler, but that should be portable.)
+ *
+ * The thread suspension signal SIG_SUSPEND is now defined in gc_priv.h.
+ * Note that we can't just stop a thread; we need it to save its stack
+ * pointer(s) and acknowledge.
+ */
+
+#ifndef SIG_THR_RESTART
+# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || defined(GC_NETBSD_THREADS)
+# ifdef _SIGRTMIN
+# define SIG_THR_RESTART _SIGRTMIN + 5
+# else
+# define SIG_THR_RESTART SIGRTMIN + 5
+# endif
+# else
+# define SIG_THR_RESTART SIGXCPU
+# endif
+#endif
+
+sem_t GC_suspend_ack_sem;
+
+#ifdef GC_NETBSD_THREADS
+# define GC_NETBSD_THREADS_WORKAROUND
+ /* It seems to be necessary to wait until threads have restarted. */
+ /* But it is unclear why that is the case. */
+ sem_t GC_restart_ack_sem;
+#endif
+
+void GC_suspend_handler_inner(ptr_t sig_arg, void *context);
+
+#if defined(IA64) || defined(HP_PA) || defined(M68K)
+void GC_suspend_handler(int sig, siginfo_t *info, void *context)
+{
+ int old_errno = errno;
+ GC_with_callee_saves_pushed(GC_suspend_handler_inner, (ptr_t)(word)sig);
+ errno = old_errno;
+}
+#else
+/* We believe that in all other cases the full context is already */
+/* in the signal handler frame. */
+void GC_suspend_handler(int sig, siginfo_t *info, void *context)
+{
+ int old_errno = errno;
+ GC_suspend_handler_inner((ptr_t)(word)sig, context);
+ errno = old_errno;
+}
+#endif
+
+void GC_suspend_handler_inner(ptr_t sig_arg, void *context)
+{
+ int sig = (int)(word)sig_arg;
+ int dummy;
+ pthread_t my_thread = pthread_self();
+ GC_thread me;
+# ifdef PARALLEL_MARK
+ word my_mark_no = GC_mark_no;
+ /* Marker can't proceed until we acknowledge. Thus this is */
+ /* guaranteed to be the mark_no correspending to our */
+ /* suspension, i.e. the marker can't have incremented it yet. */
+# endif
+ AO_t my_stop_count = AO_load(&GC_stop_count);
+
+ if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler");
+
+# if DEBUG_THREADS
+ GC_printf("Suspending 0x%x\n", (unsigned)my_thread);
+# endif
+
+ me = GC_lookup_thread(my_thread);
+ /* The lookup here is safe, since I'm doing this on behalf */
+ /* of a thread which holds the allocation lock in order */
+ /* to stop the world. Thus concurrent modification of the */
+ /* data structure is impossible. */
+ if (me -> stop_info.last_stop_count == my_stop_count) {
+ /* Duplicate signal. OK if we are retrying. */
+ if (!GC_retry_signals) {
+ WARN("Duplicate suspend signal in thread %lx\n",
+ pthread_self());
+ }
+ return;
+ }
+# ifdef SPARC
+ me -> stop_info.stack_ptr = GC_save_regs_in_stack();
+# else
+ me -> stop_info.stack_ptr = (ptr_t)(&dummy);
+# endif
+# ifdef IA64
+ me -> backing_store_ptr = GC_save_regs_in_stack();
+# endif
+
+ /* Tell the thread that wants to stop the world that this */
+ /* thread has been stopped. Note that sem_post() is */
+ /* the only async-signal-safe primitive in LinuxThreads. */
+ sem_post(&GC_suspend_ack_sem);
+ me -> stop_info.last_stop_count = my_stop_count;
+
+ /* Wait until that thread tells us to restart by sending */
+ /* this thread a SIG_THR_RESTART signal. */
+ /* SIG_THR_RESTART should be masked at this point. Thus there */
+ /* is no race. */
+ /* We do not continue until we receive a SIG_THR_RESTART, */
+ /* but we do not take that as authoritative. (We may be */
+ /* accidentally restarted by one of the user signals we */
+ /* don't block.) After we receive the signal, we use a */
+ /* primitive and expensive mechanism to wait until it's */
+ /* really safe to proceed. Under normal circumstances, */
+ /* this code should not be executed. */
+ do {
+ sigsuspend (&suspend_handler_mask);
+ } while (AO_load_acquire(&GC_world_is_stopped)
+ && AO_load(&GC_stop_count) == my_stop_count);
+ /* If the RESTART signal gets lost, we can still lose. That should be */
+ /* less likely than losing the SUSPEND signal, since we don't do much */
+ /* between the sem_post and sigsuspend. */
+ /* We'd need more handshaking to work around that. */
+ /* Simply dropping the sigsuspend call should be safe, but is unlikely */
+ /* to be efficient. */
+
+# if DEBUG_THREADS
+ GC_printf("Continuing 0x%x\n", (unsigned)my_thread);
+# endif
+}
+
+void GC_restart_handler(int sig)
+{
+ pthread_t my_thread = pthread_self();
+ GC_thread me;
+
+ if (sig != SIG_THR_RESTART) ABORT("Bad signal in suspend_handler");
+
+# ifdef GC_NETBSD_THREADS_WORKAROUND
+ sem_post(&GC_restart_ack_sem);
+# endif
+
+ /*
+ ** Note: even if we don't do anything useful here,
+ ** it would still be necessary to have a signal handler,
+ ** rather than ignoring the signals, otherwise
+ ** the signals will not be delivered at all, and
+ ** will thus not interrupt the sigsuspend() above.
+ */
+
+# if DEBUG_THREADS
+ GC_printf("In GC_restart_handler for 0x%x\n", (unsigned)pthread_self());
+# endif
+}
+
+# ifdef IA64
+# define IF_IA64(x) x
+# else
+# define IF_IA64(x)
+# endif
+/* We hold allocation lock. Should do exactly the right thing if the */
+/* world is stopped. Should not fail if it isn't. */
+void GC_push_all_stacks()
+{
+ GC_bool found_me = FALSE;
+ size_t nthreads = 0;
+ int i;
+ GC_thread p;
+ ptr_t lo, hi;
+ /* On IA64, we also need to scan the register backing store. */
+ IF_IA64(ptr_t bs_lo; ptr_t bs_hi;)
+ pthread_t me = pthread_self();
+
+ if (!GC_thr_initialized) GC_thr_init();
+# if DEBUG_THREADS
+ GC_printf("Pushing stacks from thread 0x%x\n", (unsigned) me);
+# endif
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ for (p = GC_threads[i]; p != 0; p = p -> next) {
+ if (p -> flags & FINISHED) continue;
+ ++nthreads;
+ if (THREAD_EQUAL(p -> id, me)) {
+# ifdef SPARC
+ lo = (ptr_t)GC_save_regs_in_stack();
+# else
+ lo = GC_approx_sp();
+# endif
+ found_me = TRUE;
+ IF_IA64(bs_hi = (ptr_t)GC_save_regs_in_stack();)
+ } else {
+ lo = p -> stop_info.stack_ptr;
+ IF_IA64(bs_hi = p -> backing_store_ptr;)
+ }
+ if ((p -> flags & MAIN_THREAD) == 0) {
+ hi = p -> stack_end;
+ IF_IA64(bs_lo = p -> backing_store_end);
+ } else {
+ /* The original stack. */
+ hi = GC_stackbottom;
+ IF_IA64(bs_lo = BACKING_STORE_BASE;)
+ }
+# if DEBUG_THREADS
+ GC_printf("Stack for thread 0x%x = [%p,%p)\n",
+ (unsigned)(p -> id), lo, hi);
+# endif
+ if (0 == lo) ABORT("GC_push_all_stacks: sp not set!\n");
+# ifdef STACK_GROWS_UP
+ /* We got them backwards! */
+ GC_push_all_stack(hi, lo);
+# else
+ GC_push_all_stack(lo, hi);
+# endif
+# ifdef IA64
+# if DEBUG_THREADS
+ GC_printf("Reg stack for thread 0x%x = [%lx,%lx)\n",
+ (unsigned)p -> id, bs_lo, bs_hi);
+# endif
+ if (THREAD_EQUAL(p -> id, me)) {
+ /* FIXME: This may add an unbounded number of entries, */
+ /* and hence overflow the mark stack, which is bad. */
+ GC_push_all_eager(bs_lo, bs_hi);
+ } else {
+ GC_push_all_stack(bs_lo, bs_hi);
+ }
+# endif
+ }
+ }
+ if (GC_print_stats == VERBOSE) {
+ GC_log_printf("Pushed %d thread stacks\n", nthreads);
+ }
+ if (!found_me && !GC_in_thread_creation)
+ ABORT("Collecting from unknown thread.");
+}
+
+/* There seems to be a very rare thread stopping problem. To help us */
+/* debug that, we save the ids of the stopping thread. */
+pthread_t GC_stopping_thread;
+int GC_stopping_pid;
+
+/* We hold the allocation lock. Suspend all threads that might */
+/* still be running. Return the number of suspend signals that */
+/* were sent. */
+int GC_suspend_all()
+{
+ int n_live_threads = 0;
+ int i;
+ GC_thread p;
+ int result;
+ pthread_t my_thread = pthread_self();
+
+ GC_stopping_thread = my_thread; /* debugging only. */
+ GC_stopping_pid = getpid(); /* debugging only. */
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ for (p = GC_threads[i]; p != 0; p = p -> next) {
+ if (!THREAD_EQUAL(p -> id, my_thread)) {
+ if (p -> flags & FINISHED) continue;
+ if (p -> stop_info.last_stop_count == GC_stop_count) continue;
+ if (p -> thread_blocked) /* Will wait */ continue;
+ n_live_threads++;
+# if DEBUG_THREADS
+ GC_printf("Sending suspend signal to 0x%x\n",
+ (unsigned)(p -> id));
+# endif
+
+ result = pthread_kill(p -> id, SIG_SUSPEND);
+ switch(result) {
+ case ESRCH:
+ /* Not really there anymore. Possible? */
+ n_live_threads--;
+ break;
+ case 0:
+ break;
+ default:
+ ABORT("pthread_kill failed");
+ }
+ }
+ }
+ }
+ return n_live_threads;
+}
+
+void GC_stop_world()
+{
+ int i;
+ int n_live_threads;
+ int code;
+
+ GC_ASSERT(I_HOLD_LOCK());
+# if DEBUG_THREADS
+ GC_printf("Stopping the world from 0x%x\n", (unsigned)pthread_self());
+# endif
+
+ /* Make sure all free list construction has stopped before we start. */
+ /* No new construction can start, since free list construction is */
+ /* required to acquire and release the GC lock before it starts, */
+ /* and we have the lock. */
+# ifdef PARALLEL_MARK
+ GC_acquire_mark_lock();
+ GC_ASSERT(GC_fl_builder_count == 0);
+ /* We should have previously waited for it to become zero. */
+# endif /* PARALLEL_MARK */
+ AO_store(&GC_stop_count, GC_stop_count+1);
+ /* Only concurrent reads are possible. */
+ AO_store_release(&GC_world_is_stopped, TRUE);
+ n_live_threads = GC_suspend_all();
+
+ if (GC_retry_signals) {
+ unsigned long wait_usecs = 0; /* Total wait since retry. */
+# define WAIT_UNIT 3000
+# define RETRY_INTERVAL 100000
+ for (;;) {
+ int ack_count;
+
+ sem_getvalue(&GC_suspend_ack_sem, &ack_count);
+ if (ack_count == n_live_threads) break;
+ if (wait_usecs > RETRY_INTERVAL) {
+ int newly_sent = GC_suspend_all();
+
+ if (GC_print_stats) {
+ GC_log_printf("Resent %d signals after timeout\n",
+ newly_sent);
+ }
+ sem_getvalue(&GC_suspend_ack_sem, &ack_count);
+ if (newly_sent < n_live_threads - ack_count) {
+ WARN("Lost some threads during GC_stop_world?!\n",0);
+ n_live_threads = ack_count + newly_sent;
+ }
+ wait_usecs = 0;
+ }
+ usleep(WAIT_UNIT);
+ wait_usecs += WAIT_UNIT;
+ }
+ }
+ for (i = 0; i < n_live_threads; i++) {
+ retry:
+ if (0 != (code = sem_wait(&GC_suspend_ack_sem))) {
+ /* On Linux, sem_wait is documented to always return zero.*/
+ /* But the documentation appears to be incorrect. */
+ if (errno == EINTR) {
+ /* Seems to happen with some versions of gdb. */
+ goto retry;
+ }
+ ABORT("sem_wait for handler failed");
+ }
+ }
+# ifdef PARALLEL_MARK
+ GC_release_mark_lock();
+# endif
+ #if DEBUG_THREADS
+ GC_printf("World stopped from 0x%x\n", (unsigned)pthread_self());
+ #endif
+ GC_stopping_thread = 0; /* debugging only */
+}
+
+/* Caller holds allocation lock, and has held it continuously since */
+/* the world stopped. */
+void GC_start_world()
+{
+ pthread_t my_thread = pthread_self();
+ register int i;
+ register GC_thread p;
+ register int n_live_threads = 0;
+ register int result;
+# ifdef GC_NETBSD_THREADS_WORKAROUND
+ int code;
+# endif
+
+# if DEBUG_THREADS
+ GC_printf("World starting\n");
+# endif
+
+ AO_store(&GC_world_is_stopped, FALSE);
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ for (p = GC_threads[i]; p != 0; p = p -> next) {
+ if (!THREAD_EQUAL(p -> id, my_thread)) {
+ if (p -> flags & FINISHED) continue;
+ if (p -> thread_blocked) continue;
+ n_live_threads++;
+ #if DEBUG_THREADS
+ GC_printf("Sending restart signal to 0x%x\n",
+ (unsigned)(p -> id));
+ #endif
+
+ result = pthread_kill(p -> id, SIG_THR_RESTART);
+ switch(result) {
+ case ESRCH:
+ /* Not really there anymore. Possible? */
+ n_live_threads--;
+ break;
+ case 0:
+ break;
+ default:
+ ABORT("pthread_kill failed");
+ }
+ }
+ }
+ }
+# ifdef GC_NETBSD_THREADS_WORKAROUND
+ for (i = 0; i < n_live_threads; i++)
+ while (0 != (code = sem_wait(&GC_restart_ack_sem)))
+ if (errno != EINTR) {
+ GC_err_printf1("sem_wait() returned %ld\n",
+ (unsigned long)code);
+ ABORT("sem_wait() for restart handler failed");
+ }
+# endif
+# if DEBUG_THREADS
+ GC_printf("World started\n");
+# endif
+}
+
+void GC_stop_init() {
+ struct sigaction act;
+
+ if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0)
+ ABORT("sem_init failed");
+# ifdef GC_NETBSD_THREADS_WORKAROUND
+ if (sem_init(&GC_restart_ack_sem, 0, 0) != 0)
+ ABORT("sem_init failed");
+# endif
+
+ act.sa_flags = SA_RESTART | SA_SIGINFO;
+ if (sigfillset(&act.sa_mask) != 0) {
+ ABORT("sigfillset() failed");
+ }
+ GC_remove_allowed_signals(&act.sa_mask);
+ /* SIG_THR_RESTART is set in the resulting mask. */
+ /* It is unmasked by the handler when necessary. */
+ act.sa_sigaction = GC_suspend_handler;
+ if (sigaction(SIG_SUSPEND, &act, NULL) != 0) {
+ ABORT("Cannot set SIG_SUSPEND handler");
+ }
+
+ act.sa_flags &= ~ SA_SIGINFO;
+ act.sa_handler = GC_restart_handler;
+ if (sigaction(SIG_THR_RESTART, &act, NULL) != 0) {
+ ABORT("Cannot set SIG_THR_RESTART handler");
+ }
+
+ /* Inititialize suspend_handler_mask. It excludes SIG_THR_RESTART. */
+ if (sigfillset(&suspend_handler_mask) != 0) ABORT("sigfillset() failed");
+ GC_remove_allowed_signals(&suspend_handler_mask);
+ if (sigdelset(&suspend_handler_mask, SIG_THR_RESTART) != 0)
+ ABORT("sigdelset() failed");
+
+ /* Check for GC_RETRY_SIGNALS. */
+ if (0 != GETENV("GC_RETRY_SIGNALS")) {
+ GC_retry_signals = TRUE;
+ }
+ if (0 != GETENV("GC_NO_RETRY_SIGNALS")) {
+ GC_retry_signals = FALSE;
+ }
+ if (GC_print_stats && GC_retry_signals) {
+ GC_log_printf("Will retry suspend signal if necessary.\n");
+ }
+}
+
+#endif
diff --git a/tools/build/v2/engine/boehm_gc/pthread_support.c b/tools/build/v2/engine/boehm_gc/pthread_support.c
new file mode 100644
index 0000000000..955eea2daa
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/pthread_support.c
@@ -0,0 +1,1495 @@
+/*
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1998 by Fergus Henderson. All rights reserved.
+ * Copyright (c) 2000-2005 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/*
+ * Support code originally for LinuxThreads, the clone()-based kernel
+ * thread package for Linux which is included in libc6.
+ *
+ * This code no doubt makes some assumptions beyond what is
+ * guaranteed by the pthread standard, though it now does
+ * very little of that. It now also supports NPTL, and many
+ * other Posix thread implementations. We are trying to merge
+ * all flavors of pthread dupport code into this file.
+ */
+ /* DG/UX ix86 support <takis@xfree86.org> */
+/*
+ * Linux_threads.c now also includes some code to support HPUX and
+ * OSF1 (Compaq Tru64 Unix, really). The OSF1 support is based on Eric Benson's
+ * patch.
+ *
+ * Eric also suggested an alternate basis for a lock implementation in
+ * his code:
+ * + #elif defined(OSF1)
+ * + unsigned long GC_allocate_lock = 0;
+ * + msemaphore GC_allocate_semaphore;
+ * + # define GC_TRY_LOCK() \
+ * + ((msem_lock(&GC_allocate_semaphore, MSEM_IF_NOWAIT) == 0) \
+ * + ? (GC_allocate_lock = 1) \
+ * + : 0)
+ * + # define GC_LOCK_TAKEN GC_allocate_lock
+ */
+
+/*#define DEBUG_THREADS 1*/
+
+# include "private/pthread_support.h"
+
+# if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS)
+
+# if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
+# define _POSIX4A_DRAFT10_SOURCE 1
+# endif
+
+# if defined(GC_DGUX386_THREADS) && !defined(_USING_POSIX4A_DRAFT10)
+# define _USING_POSIX4A_DRAFT10 1
+# endif
+
+# include <stdlib.h>
+# include <pthread.h>
+# include <sched.h>
+# include <time.h>
+# include <errno.h>
+# include <unistd.h>
+# include <sys/mman.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <signal.h>
+
+# include "gc_inline.h"
+
+#if defined(GC_DARWIN_THREADS)
+# include "private/darwin_semaphore.h"
+#else
+# include <semaphore.h>
+#endif /* !GC_DARWIN_THREADS */
+
+#if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
+# include <sys/sysctl.h>
+#endif /* GC_DARWIN_THREADS */
+
+#if defined(GC_NETBSD_THREADS)
+# include <sys/param.h>
+# include <sys/sysctl.h>
+#endif /* GC_NETBSD_THREADS */
+
+/* Allocator lock definitions. */
+#if !defined(USE_SPIN_LOCK)
+ pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
+#endif
+unsigned long GC_lock_holder = NO_THREAD;
+ /* Used only for assertions, and to prevent */
+ /* recursive reentry in the system call wrapper. */
+
+#if defined(GC_DGUX386_THREADS)
+# include <sys/dg_sys_info.h>
+# include <sys/_int_psem.h>
+ /* sem_t is an uint in DG/UX */
+ typedef unsigned int sem_t;
+#endif /* GC_DGUX386_THREADS */
+
+#ifndef __GNUC__
+# define __inline__
+#endif
+
+/* Undefine macros used to redirect pthread primitives. */
+# undef pthread_create
+# if !defined(GC_DARWIN_THREADS)
+# undef pthread_sigmask
+# endif
+# undef pthread_join
+# undef pthread_detach
+# if defined(GC_OSF1_THREADS) && defined(_PTHREAD_USE_MANGLED_NAMES_) \
+ && !defined(_PTHREAD_USE_PTDNAM_)
+ /* Restore the original mangled names on Tru64 UNIX. */
+# define pthread_create __pthread_create
+# define pthread_join __pthread_join
+# define pthread_detach __pthread_detach
+# endif
+
+#ifdef GC_USE_LD_WRAP
+# define WRAP_FUNC(f) __wrap_##f
+# define REAL_FUNC(f) __real_##f
+#else
+# ifdef GC_USE_DLOPEN_WRAP
+# include <dlfcn.h>
+# define WRAP_FUNC(f) f
+# define REAL_FUNC(f) GC_real_##f
+ /* We define both GC_f and plain f to be the wrapped function. */
+ /* In that way plain calls work, as do calls from files that */
+ /* included gc.h, wich redefined f to GC_f. */
+ /* FIXME: Needs work for DARWIN and True64 (OSF1) */
+ typedef int (* GC_pthread_create_t)(pthread_t *, const pthread_attr_t *,
+ void * (*)(void *), void *);
+ static GC_pthread_create_t GC_real_pthread_create;
+ typedef int (* GC_pthread_sigmask_t)(int, const sigset_t *, sigset_t *);
+ static GC_pthread_sigmask_t GC_real_pthread_sigmask;
+ typedef int (* GC_pthread_join_t)(pthread_t, void **);
+ static GC_pthread_join_t GC_real_pthread_join;
+ typedef int (* GC_pthread_detach_t)(pthread_t);
+ static GC_pthread_detach_t GC_real_pthread_detach;
+# else
+# define WRAP_FUNC(f) GC_##f
+# if !defined(GC_DGUX386_THREADS)
+# define REAL_FUNC(f) f
+# else /* GC_DGUX386_THREADS */
+# define REAL_FUNC(f) __d10_##f
+# endif /* GC_DGUX386_THREADS */
+# endif
+#endif
+
+#if defined(GC_USE_DL_WRAP) || defined(GC_USE_DLOPEN_WRAP)
+/* Define GC_ functions as aliases for the plain ones, which will */
+/* be intercepted. This allows files which include gc.h, and hence */
+/* generate referemces to the GC_ symbols, to see the right symbols. */
+ int GC_pthread_create(pthread_t * t, const pthread_attr_t * a,
+ void * (* fn)(void *), void * arg) {
+ return pthread_create(t, a, fn, arg);
+ }
+ int GC_pthread_sigmask(int how, const sigset_t *mask, sigset_t *old) {
+ return pthread_sigmask(how, mask, old);
+ }
+ int GC_pthread_join(pthread_t t, void **res) {
+ return pthread_join(t, res);
+ }
+ int GC_pthread_detach(pthread_t t) {
+ return pthread_detach(t);
+ }
+#endif /* Linker-based interception. */
+
+#ifdef GC_USE_DLOPEN_WRAP
+ static GC_bool GC_syms_initialized = FALSE;
+
+ void GC_init_real_syms(void)
+ {
+ void *dl_handle;
+# define LIBPTHREAD_NAME "libpthread.so.0"
+# define LIBPTHREAD_NAME_LEN 16 /* incl. trailing 0 */
+ size_t len = LIBPTHREAD_NAME_LEN - 1;
+ char namebuf[LIBPTHREAD_NAME_LEN];
+ static char *libpthread_name = LIBPTHREAD_NAME;
+
+ if (GC_syms_initialized) return;
+# ifdef RTLD_NEXT
+ dl_handle = RTLD_NEXT;
+# else
+ dl_handle = dlopen(libpthread_name, RTLD_LAZY);
+ if (NULL == dl_handle) {
+ while (isdigit(libpthread_name[len-1])) --len;
+ if (libpthread_name[len-1] == '.') --len;
+ memcpy(namebuf, libpthread_name, len);
+ namebuf[len] = '\0';
+ dl_handle = dlopen(namebuf, RTLD_LAZY);
+ }
+ if (NULL == dl_handle) ABORT("Couldn't open libpthread\n");
+# endif
+ GC_real_pthread_create = (GC_pthread_create_t)
+ dlsym(dl_handle, "pthread_create");
+ GC_real_pthread_sigmask = (GC_pthread_sigmask_t)
+ dlsym(dl_handle, "pthread_sigmask");
+ GC_real_pthread_join = (GC_pthread_join_t)
+ dlsym(dl_handle, "pthread_join");
+ GC_real_pthread_detach = (GC_pthread_detach_t)
+ dlsym(dl_handle, "pthread_detach");
+ GC_syms_initialized = TRUE;
+ }
+
+# define INIT_REAL_SYMS() if (!GC_syms_initialized) GC_init_real_syms();
+#else
+# define INIT_REAL_SYMS()
+#endif
+
+void GC_thr_init(void);
+
+static GC_bool parallel_initialized = FALSE;
+
+GC_bool GC_need_to_lock = FALSE;
+
+void GC_init_parallel(void);
+
+long GC_nprocs = 1; /* Number of processors. We may not have */
+ /* access to all of them, but this is as good */
+ /* a guess as any ... */
+
+#ifdef THREAD_LOCAL_ALLOC
+/* We must explicitly mark ptrfree and gcj free lists, since the free */
+/* list links wouldn't otherwise be found. We also set them in the */
+/* normal free lists, since that involves touching less memory than if */
+/* we scanned them normally. */
+void GC_mark_thread_local_free_lists(void)
+{
+ int i;
+ GC_thread p;
+
+ for (i = 0; i < THREAD_TABLE_SZ; ++i) {
+ for (p = GC_threads[i]; 0 != p; p = p -> next) {
+ GC_mark_thread_local_fls_for(&(p->tlfs));
+ }
+ }
+}
+
+#if defined(GC_ASSERTIONS)
+ /* Check that all thread-local free-lists are completely marked. */
+ /* also check that thread-specific-data structures are marked. */
+ void GC_check_tls(void) {
+ int i;
+ GC_thread p;
+
+ for (i = 0; i < THREAD_TABLE_SZ; ++i) {
+ for (p = GC_threads[i]; 0 != p; p = p -> next) {
+ GC_check_tls_for(&(p->tlfs));
+ }
+ }
+# if defined(USE_CUSTOM_SPECIFIC)
+ if (GC_thread_key != 0)
+ GC_check_tsd_marks(GC_thread_key);
+# endif
+ }
+#endif /* GC_ASSERTIONS */
+
+#endif /* Thread_local_alloc */
+
+#ifdef PARALLEL_MARK
+
+# ifndef MAX_MARKERS
+# define MAX_MARKERS 16
+# endif
+
+static ptr_t marker_sp[MAX_MARKERS] = {0};
+#ifdef IA64
+ static ptr_t marker_bsp[MAX_MARKERS] = {0};
+#endif
+
+void * GC_mark_thread(void * id)
+{
+ word my_mark_no = 0;
+
+ marker_sp[(word)id] = GC_approx_sp();
+# ifdef IA64
+ marker_bsp[(word)id] = GC_save_regs_in_stack();
+# endif
+ for (;; ++my_mark_no) {
+ /* GC_mark_no is passed only to allow GC_help_marker to terminate */
+ /* promptly. This is important if it were called from the signal */
+ /* handler or from the GC lock acquisition code. Under Linux, it's */
+ /* not safe to call it from a signal handler, since it uses mutexes */
+ /* and condition variables. Since it is called only here, the */
+ /* argument is unnecessary. */
+ if (my_mark_no < GC_mark_no || my_mark_no > GC_mark_no + 2) {
+ /* resynchronize if we get far off, e.g. because GC_mark_no */
+ /* wrapped. */
+ my_mark_no = GC_mark_no;
+ }
+# ifdef DEBUG_THREADS
+ GC_printf("Starting mark helper for mark number %lu\n", my_mark_no);
+# endif
+ GC_help_marker(my_mark_no);
+ }
+}
+
+extern long GC_markers; /* Number of mark threads we would */
+ /* like to have. Includes the */
+ /* initiating thread. */
+
+pthread_t GC_mark_threads[MAX_MARKERS];
+
+#define PTHREAD_CREATE REAL_FUNC(pthread_create)
+
+static void start_mark_threads(void)
+{
+ unsigned i;
+ pthread_attr_t attr;
+
+ if (GC_markers > MAX_MARKERS) {
+ WARN("Limiting number of mark threads\n", 0);
+ GC_markers = MAX_MARKERS;
+ }
+ if (0 != pthread_attr_init(&attr)) ABORT("pthread_attr_init failed");
+
+ if (0 != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
+ ABORT("pthread_attr_setdetachstate failed");
+
+# if defined(HPUX) || defined(GC_DGUX386_THREADS)
+ /* Default stack size is usually too small: fix it. */
+ /* Otherwise marker threads or GC may run out of */
+ /* space. */
+# define MIN_STACK_SIZE (8*HBLKSIZE*sizeof(word))
+ {
+ size_t old_size;
+ int code;
+
+ if (pthread_attr_getstacksize(&attr, &old_size) != 0)
+ ABORT("pthread_attr_getstacksize failed\n");
+ if (old_size < MIN_STACK_SIZE) {
+ if (pthread_attr_setstacksize(&attr, MIN_STACK_SIZE) != 0)
+ ABORT("pthread_attr_setstacksize failed\n");
+ }
+ }
+# endif /* HPUX || GC_DGUX386_THREADS */
+ if (GC_print_stats) {
+ GC_log_printf("Starting %ld marker threads\n", GC_markers - 1);
+ }
+ for (i = 0; i < GC_markers - 1; ++i) {
+ if (0 != PTHREAD_CREATE(GC_mark_threads + i, &attr,
+ GC_mark_thread, (void *)(word)i)) {
+ WARN("Marker thread creation failed, errno = %ld.\n", errno);
+ }
+ }
+}
+
+#endif /* PARALLEL_MARK */
+
+GC_bool GC_thr_initialized = FALSE;
+
+volatile GC_thread GC_threads[THREAD_TABLE_SZ];
+
+void GC_push_thread_structures(void)
+{
+ GC_ASSERT(I_HOLD_LOCK());
+ GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads));
+# if defined(THREAD_LOCAL_ALLOC)
+ GC_push_all((ptr_t)(&GC_thread_key),
+ (ptr_t)(&GC_thread_key)+sizeof(&GC_thread_key));
+# endif
+}
+
+/* It may not be safe to allocate when we register the first thread. */
+static struct GC_Thread_Rep first_thread;
+
+/* Add a thread to GC_threads. We assume it wasn't already there. */
+/* Caller holds allocation lock. */
+GC_thread GC_new_thread(pthread_t id)
+{
+ int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ;
+ GC_thread result;
+ static GC_bool first_thread_used = FALSE;
+
+ GC_ASSERT(I_HOLD_LOCK());
+ if (!first_thread_used) {
+ result = &first_thread;
+ first_thread_used = TRUE;
+ } else {
+ result = (struct GC_Thread_Rep *)
+ GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL);
+ GC_ASSERT(result -> flags == 0);
+ }
+ if (result == 0) return(0);
+ result -> id = id;
+ result -> next = GC_threads[hv];
+ GC_threads[hv] = result;
+ GC_ASSERT(result -> flags == 0 && result -> thread_blocked == 0);
+ return(result);
+}
+
+/* Delete a thread from GC_threads. We assume it is there. */
+/* (The code intentionally traps if it wasn't.) */
+void GC_delete_thread(pthread_t id)
+{
+ int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ;
+ register GC_thread p = GC_threads[hv];
+ register GC_thread prev = 0;
+
+ GC_ASSERT(I_HOLD_LOCK());
+ while (!THREAD_EQUAL(p -> id, id)) {
+ prev = p;
+ p = p -> next;
+ }
+ if (prev == 0) {
+ GC_threads[hv] = p -> next;
+ } else {
+ prev -> next = p -> next;
+ }
+# ifdef GC_DARWIN_THREADS
+ mach_port_deallocate(mach_task_self(), p->stop_info.mach_thread);
+# endif
+ GC_INTERNAL_FREE(p);
+}
+
+/* If a thread has been joined, but we have not yet */
+/* been notified, then there may be more than one thread */
+/* in the table with the same pthread id. */
+/* This is OK, but we need a way to delete a specific one. */
+void GC_delete_gc_thread(GC_thread gc_id)
+{
+ pthread_t id = gc_id -> id;
+ int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ;
+ register GC_thread p = GC_threads[hv];
+ register GC_thread prev = 0;
+
+ GC_ASSERT(I_HOLD_LOCK());
+ while (p != gc_id) {
+ prev = p;
+ p = p -> next;
+ }
+ if (prev == 0) {
+ GC_threads[hv] = p -> next;
+ } else {
+ prev -> next = p -> next;
+ }
+# ifdef GC_DARWIN_THREADS
+ mach_port_deallocate(mach_task_self(), p->stop_info.mach_thread);
+# endif
+ GC_INTERNAL_FREE(p);
+}
+
+/* Return a GC_thread corresponding to a given pthread_t. */
+/* Returns 0 if it's not there. */
+/* Caller holds allocation lock or otherwise inhibits */
+/* updates. */
+/* If there is more than one thread with the given id we */
+/* return the most recent one. */
+GC_thread GC_lookup_thread(pthread_t id)
+{
+ int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ;
+ register GC_thread p = GC_threads[hv];
+
+ while (p != 0 && !THREAD_EQUAL(p -> id, id)) p = p -> next;
+ return(p);
+}
+
+#ifdef HANDLE_FORK
+/* Remove all entries from the GC_threads table, except the */
+/* one for the current thread. We need to do this in the child */
+/* process after a fork(), since only the current thread */
+/* survives in the child. */
+void GC_remove_all_threads_but_me(void)
+{
+ pthread_t self = pthread_self();
+ int hv;
+ GC_thread p, next, me;
+
+ for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) {
+ me = 0;
+ for (p = GC_threads[hv]; 0 != p; p = next) {
+ next = p -> next;
+ if (THREAD_EQUAL(p -> id, self)) {
+ me = p;
+ p -> next = 0;
+ } else {
+# ifdef THREAD_LOCAL_ALLOC
+ if (!(p -> flags & FINISHED)) {
+ GC_destroy_thread_local(&(p->tlfs));
+ }
+# endif /* THREAD_LOCAL_ALLOC */
+ if (p != &first_thread) GC_INTERNAL_FREE(p);
+ }
+ }
+ GC_threads[hv] = me;
+ }
+}
+#endif /* HANDLE_FORK */
+
+#ifdef USE_PROC_FOR_LIBRARIES
+GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi)
+{
+ int i;
+ GC_thread p;
+
+ GC_ASSERT(I_HOLD_LOCK());
+# ifdef PARALLEL_MARK
+ for (i = 0; i < GC_markers; ++i) {
+ if (marker_sp[i] > lo & marker_sp[i] < hi) return TRUE;
+# ifdef IA64
+ if (marker_bsp[i] > lo & marker_bsp[i] < hi) return TRUE;
+# endif
+ }
+# endif
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ for (p = GC_threads[i]; p != 0; p = p -> next) {
+ if (0 != p -> stack_end) {
+# ifdef STACK_GROWS_UP
+ if (p -> stack_end >= lo && p -> stack_end < hi) return TRUE;
+# else /* STACK_GROWS_DOWN */
+ if (p -> stack_end > lo && p -> stack_end <= hi) return TRUE;
+# endif
+ }
+ }
+ }
+ return FALSE;
+}
+#endif /* USE_PROC_FOR_LIBRARIES */
+
+#ifdef IA64
+/* Find the largest stack_base smaller than bound. May be used */
+/* to find the boundary between a register stack and adjacent */
+/* immediately preceding memory stack. */
+ptr_t GC_greatest_stack_base_below(ptr_t bound)
+{
+ int i;
+ GC_thread p;
+ ptr_t result = 0;
+
+ GC_ASSERT(I_HOLD_LOCK());
+# ifdef PARALLEL_MARK
+ for (i = 0; i < GC_markers; ++i) {
+ if (marker_sp[i] > result && marker_sp[i] < bound)
+ result = marker_sp[i];
+ }
+# endif
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ for (p = GC_threads[i]; p != 0; p = p -> next) {
+ if (p -> stack_end > result && p -> stack_end < bound) {
+ result = p -> stack_end;
+ }
+ }
+ }
+ return result;
+}
+#endif /* IA64 */
+
+#ifdef GC_LINUX_THREADS
+/* Return the number of processors, or i<= 0 if it can't be determined. */
+int GC_get_nprocs(void)
+{
+ /* Should be "return sysconf(_SC_NPROCESSORS_ONLN);" but that */
+ /* appears to be buggy in many cases. */
+ /* We look for lines "cpu<n>" in /proc/stat. */
+# define STAT_BUF_SIZE 4096
+# define STAT_READ read
+ /* If read is wrapped, this may need to be redefined to call */
+ /* the real one. */
+ char stat_buf[STAT_BUF_SIZE];
+ int f;
+ word result = 1;
+ /* Some old kernels only have a single "cpu nnnn ..." */
+ /* entry in /proc/stat. We identify those as */
+ /* uniprocessors. */
+ size_t i, len = 0;
+
+ f = open("/proc/stat", O_RDONLY);
+ if (f < 0 || (len = STAT_READ(f, stat_buf, STAT_BUF_SIZE)) < 100) {
+ WARN("Couldn't read /proc/stat\n", 0);
+ return -1;
+ }
+ for (i = 0; i < len - 100; ++i) {
+ if (stat_buf[i] == '\n' && stat_buf[i+1] == 'c'
+ && stat_buf[i+2] == 'p' && stat_buf[i+3] == 'u') {
+ int cpu_no = atoi(stat_buf + i + 4);
+ if (cpu_no >= result) result = cpu_no + 1;
+ }
+ }
+ close(f);
+ return result;
+}
+#endif /* GC_LINUX_THREADS */
+
+/* We hold the GC lock. Wait until an in-progress GC has finished. */
+/* Repeatedly RELEASES GC LOCK in order to wait. */
+/* If wait_for_all is true, then we exit with the GC lock held and no */
+/* collection in progress; otherwise we just wait for the current GC */
+/* to finish. */
+extern GC_bool GC_collection_in_progress(void);
+void GC_wait_for_gc_completion(GC_bool wait_for_all)
+{
+ GC_ASSERT(I_HOLD_LOCK());
+ if (GC_incremental && GC_collection_in_progress()) {
+ int old_gc_no = GC_gc_no;
+
+ /* Make sure that no part of our stack is still on the mark stack, */
+ /* since it's about to be unmapped. */
+ while (GC_incremental && GC_collection_in_progress()
+ && (wait_for_all || old_gc_no == GC_gc_no)) {
+ ENTER_GC();
+ GC_in_thread_creation = TRUE;
+ GC_collect_a_little_inner(1);
+ GC_in_thread_creation = FALSE;
+ EXIT_GC();
+ UNLOCK();
+ sched_yield();
+ LOCK();
+ }
+ }
+}
+
+#ifdef HANDLE_FORK
+/* Procedures called before and after a fork. The goal here is to make */
+/* it safe to call GC_malloc() in a forked child. It's unclear that is */
+/* attainable, since the single UNIX spec seems to imply that one */
+/* should only call async-signal-safe functions, and we probably can't */
+/* quite guarantee that. But we give it our best shot. (That same */
+/* spec also implies that it's not safe to call the system malloc */
+/* between fork() and exec(). Thus we're doing no worse than it. */
+
+/* Called before a fork() */
+void GC_fork_prepare_proc(void)
+{
+ /* Acquire all relevant locks, so that after releasing the locks */
+ /* the child will see a consistent state in which monitor */
+ /* invariants hold. Unfortunately, we can't acquire libc locks */
+ /* we might need, and there seems to be no guarantee that libc */
+ /* must install a suitable fork handler. */
+ /* Wait for an ongoing GC to finish, since we can't finish it in */
+ /* the (one remaining thread in) the child. */
+ LOCK();
+# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+ GC_wait_for_reclaim();
+# endif
+ GC_wait_for_gc_completion(TRUE);
+# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+ GC_acquire_mark_lock();
+# endif
+}
+
+/* Called in parent after a fork() */
+void GC_fork_parent_proc(void)
+{
+# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+ GC_release_mark_lock();
+# endif
+ UNLOCK();
+}
+
+/* Called in child after a fork() */
+void GC_fork_child_proc(void)
+{
+ /* Clean up the thread table, so that just our thread is left. */
+# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+ GC_release_mark_lock();
+# endif
+ GC_remove_all_threads_but_me();
+# ifdef PARALLEL_MARK
+ /* Turn off parallel marking in the child, since we are probably */
+ /* just going to exec, and we would have to restart mark threads. */
+ GC_markers = 1;
+ GC_parallel = FALSE;
+# endif /* PARALLEL_MARK */
+ UNLOCK();
+}
+#endif /* HANDLE_FORK */
+
+#if defined(GC_DGUX386_THREADS)
+/* Return the number of processors, or i<= 0 if it can't be determined. */
+int GC_get_nprocs(void)
+{
+ /* <takis@XFree86.Org> */
+ int numCpus;
+ struct dg_sys_info_pm_info pm_sysinfo;
+ int status =0;
+
+ status = dg_sys_info((long int *) &pm_sysinfo,
+ DG_SYS_INFO_PM_INFO_TYPE, DG_SYS_INFO_PM_CURRENT_VERSION);
+ if (status < 0)
+ /* set -1 for error */
+ numCpus = -1;
+ else
+ /* Active CPUs */
+ numCpus = pm_sysinfo.idle_vp_count;
+
+# ifdef DEBUG_THREADS
+ GC_printf("Number of active CPUs in this system: %d\n", numCpus);
+# endif
+ return(numCpus);
+}
+#endif /* GC_DGUX386_THREADS */
+
+#if defined(GC_NETBSD_THREADS)
+static int get_ncpu(void)
+{
+ int mib[] = {CTL_HW,HW_NCPU};
+ int res;
+ size_t len = sizeof(res);
+
+ sysctl(mib, sizeof(mib)/sizeof(int), &res, &len, NULL, 0);
+ return res;
+}
+#endif /* GC_NETBSD_THREADS */
+
+# if defined(GC_LINUX_THREADS) && defined(INCLUDE_LINUX_THREAD_DESCR)
+__thread int dummy_thread_local;
+# endif
+
+/* We hold the allocation lock. */
+void GC_thr_init(void)
+{
+# ifndef GC_DARWIN_THREADS
+ int dummy;
+# endif
+ GC_thread t;
+
+ if (GC_thr_initialized) return;
+ GC_thr_initialized = TRUE;
+
+# ifdef HANDLE_FORK
+ /* Prepare for a possible fork. */
+ pthread_atfork(GC_fork_prepare_proc, GC_fork_parent_proc,
+ GC_fork_child_proc);
+# endif /* HANDLE_FORK */
+# if defined(INCLUDE_LINUX_THREAD_DESCR)
+ /* Explicitly register the region including the address */
+ /* of a thread local variable. This should included thread */
+ /* locals for the main thread, except for those allocated */
+ /* in response to dlopen calls. */
+ {
+ ptr_t thread_local_addr = (ptr_t)(&dummy_thread_local);
+ ptr_t main_thread_start, main_thread_end;
+ if (!GC_enclosing_mapping(thread_local_addr, &main_thread_start,
+ &main_thread_end)) {
+ ABORT("Failed to find mapping for main thread thread locals");
+ }
+ GC_add_roots_inner(main_thread_start, main_thread_end, FALSE);
+ }
+# endif
+ /* Add the initial thread, so we can stop it. */
+ t = GC_new_thread(pthread_self());
+# ifdef GC_DARWIN_THREADS
+ t -> stop_info.mach_thread = mach_thread_self();
+# else
+ t -> stop_info.stack_ptr = (ptr_t)(&dummy);
+# endif
+ t -> flags = DETACHED | MAIN_THREAD;
+
+ GC_stop_init();
+
+ /* Set GC_nprocs. */
+ {
+ char * nprocs_string = GETENV("GC_NPROCS");
+ GC_nprocs = -1;
+ if (nprocs_string != NULL) GC_nprocs = atoi(nprocs_string);
+ }
+ if (GC_nprocs <= 0) {
+# if defined(GC_HPUX_THREADS)
+ GC_nprocs = pthread_num_processors_np();
+# endif
+# if defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS) \
+ || defined(GC_SOLARIS_THREADS)
+ GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);
+ if (GC_nprocs <= 0) GC_nprocs = 1;
+# endif
+# if defined(GC_IRIX_THREADS)
+ GC_nprocs = sysconf(_SC_NPROC_ONLN);
+ if (GC_nprocs <= 0) GC_nprocs = 1;
+# endif
+# if defined(GC_NETBSD_THREADS)
+ GC_nprocs = get_ncpu();
+# endif
+# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
+ int ncpus = 1;
+ size_t len = sizeof(ncpus);
+ sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);
+ GC_nprocs = ncpus;
+# endif
+# if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS)
+ GC_nprocs = GC_get_nprocs();
+# endif
+# if defined(GC_GNU_THREADS)
+ if (GC_nprocs <= 0) GC_nprocs = 1;
+# endif
+ }
+ if (GC_nprocs <= 0) {
+ WARN("GC_get_nprocs() returned %ld\n", GC_nprocs);
+ GC_nprocs = 2;
+# ifdef PARALLEL_MARK
+ GC_markers = 1;
+# endif
+ } else {
+# ifdef PARALLEL_MARK
+ {
+ char * markers_string = GETENV("GC_MARKERS");
+ if (markers_string != NULL) {
+ GC_markers = atoi(markers_string);
+ } else {
+ GC_markers = GC_nprocs;
+ }
+ }
+# endif
+ }
+# ifdef PARALLEL_MARK
+ if (GC_print_stats) {
+ GC_log_printf("Number of processors = %ld, "
+ "number of marker threads = %ld\n", GC_nprocs, GC_markers);
+ }
+ if (GC_markers == 1) {
+ GC_parallel = FALSE;
+ if (GC_print_stats) {
+ GC_log_printf(
+ "Single marker thread, turning off parallel marking\n");
+ }
+ } else {
+ GC_parallel = TRUE;
+ /* Disable true incremental collection, but generational is OK. */
+ GC_time_limit = GC_TIME_UNLIMITED;
+ }
+ /* If we are using a parallel marker, actually start helper threads. */
+ if (GC_parallel) start_mark_threads();
+# endif
+}
+
+
+/* Perform all initializations, including those that */
+/* may require allocation. */
+/* Called without allocation lock. */
+/* Must be called before a second thread is created. */
+/* Did we say it's called without the allocation lock? */
+void GC_init_parallel(void)
+{
+ if (parallel_initialized) return;
+ parallel_initialized = TRUE;
+
+ /* GC_init() calls us back, so set flag first. */
+ if (!GC_is_initialized) GC_init();
+ /* Initialize thread local free lists if used. */
+# if defined(THREAD_LOCAL_ALLOC)
+ LOCK();
+ GC_init_thread_local(&(GC_lookup_thread(pthread_self())->tlfs));
+ UNLOCK();
+# endif
+}
+
+
+#if !defined(GC_DARWIN_THREADS)
+int WRAP_FUNC(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset)
+{
+ sigset_t fudged_set;
+
+ INIT_REAL_SYMS();
+ if (set != NULL && (how == SIG_BLOCK || how == SIG_SETMASK)) {
+ fudged_set = *set;
+ sigdelset(&fudged_set, SIG_SUSPEND);
+ set = &fudged_set;
+ }
+ return(REAL_FUNC(pthread_sigmask)(how, set, oset));
+}
+#endif /* !GC_DARWIN_THREADS */
+
+/* Wrapper for functions that are likely to block for an appreciable */
+/* length of time. */
+
+struct blocking_data {
+ void (*fn)(void *);
+ void *arg;
+};
+
+static void GC_do_blocking_inner(ptr_t data, void * context) {
+ struct blocking_data * d = (struct blocking_data *) data;
+ GC_thread me;
+ LOCK();
+ me = GC_lookup_thread(pthread_self());
+ GC_ASSERT(!(me -> thread_blocked));
+# ifdef SPARC
+ me -> stop_info.stack_ptr = GC_save_regs_in_stack();
+# elif !defined(GC_DARWIN_THREADS)
+ me -> stop_info.stack_ptr = GC_approx_sp();
+# endif
+# ifdef IA64
+ me -> backing_store_ptr = GC_save_regs_in_stack();
+# endif
+ me -> thread_blocked = TRUE;
+ /* Save context here if we want to support precise stack marking */
+ UNLOCK();
+ (d -> fn)(d -> arg);
+ LOCK(); /* This will block if the world is stopped. */
+ me -> thread_blocked = FALSE;
+ UNLOCK();
+}
+
+void GC_do_blocking(void (*fn)(void *), void *arg) {
+ struct blocking_data my_data;
+
+ my_data.fn = fn;
+ my_data.arg = arg;
+ GC_with_callee_saves_pushed(GC_do_blocking_inner, (ptr_t)(&my_data));
+}
+
+struct start_info {
+ void *(*start_routine)(void *);
+ void *arg;
+ word flags;
+ sem_t registered; /* 1 ==> in our thread table, but */
+ /* parent hasn't yet noticed. */
+};
+
+int GC_unregister_my_thread(void)
+{
+ GC_thread me;
+
+ LOCK();
+ /* Wait for any GC that may be marking from our stack to */
+ /* complete before we remove this thread. */
+ GC_wait_for_gc_completion(FALSE);
+ me = GC_lookup_thread(pthread_self());
+# if defined(THREAD_LOCAL_ALLOC)
+ GC_destroy_thread_local(&(me->tlfs));
+# endif
+ if (me -> flags & DETACHED) {
+ GC_delete_thread(pthread_self());
+ } else {
+ me -> flags |= FINISHED;
+ }
+# if defined(THREAD_LOCAL_ALLOC)
+ GC_remove_specific(GC_thread_key);
+# endif
+ UNLOCK();
+ return GC_SUCCESS;
+}
+
+/* Called at thread exit. */
+/* Never called for main thread. That's OK, since it */
+/* results in at most a tiny one-time leak. And */
+/* linuxthreads doesn't reclaim the main threads */
+/* resources or id anyway. */
+void GC_thread_exit_proc(void *arg)
+{
+ GC_unregister_my_thread();
+}
+
+int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval)
+{
+ int result;
+ GC_thread thread_gc_id;
+
+ INIT_REAL_SYMS();
+ LOCK();
+ thread_gc_id = GC_lookup_thread(thread);
+ /* This is guaranteed to be the intended one, since the thread id */
+ /* cant have been recycled by pthreads. */
+ UNLOCK();
+ result = REAL_FUNC(pthread_join)(thread, retval);
+# if defined (GC_FREEBSD_THREADS)
+ /* On FreeBSD, the wrapped pthread_join() sometimes returns (what
+ appears to be) a spurious EINTR which caused the test and real code
+ to gratuitously fail. Having looked at system pthread library source
+ code, I see how this return code may be generated. In one path of
+ code, pthread_join() just returns the errno setting of the thread
+ being joined. This does not match the POSIX specification or the
+ local man pages thus I have taken the liberty to catch this one
+ spurious return value properly conditionalized on GC_FREEBSD_THREADS. */
+ if (result == EINTR) result = 0;
+# endif
+ if (result == 0) {
+ LOCK();
+ /* Here the pthread thread id may have been recycled. */
+ GC_delete_gc_thread(thread_gc_id);
+ UNLOCK();
+ }
+ return result;
+}
+
+int
+WRAP_FUNC(pthread_detach)(pthread_t thread)
+{
+ int result;
+ GC_thread thread_gc_id;
+
+ INIT_REAL_SYMS();
+ LOCK();
+ thread_gc_id = GC_lookup_thread(thread);
+ UNLOCK();
+ result = REAL_FUNC(pthread_detach)(thread);
+ if (result == 0) {
+ LOCK();
+ thread_gc_id -> flags |= DETACHED;
+ /* Here the pthread thread id may have been recycled. */
+ if (thread_gc_id -> flags & FINISHED) {
+ GC_delete_gc_thread(thread_gc_id);
+ }
+ UNLOCK();
+ }
+ return result;
+}
+
+GC_bool GC_in_thread_creation = FALSE; /* Protected by allocation lock. */
+
+GC_thread GC_register_my_thread_inner(struct GC_stack_base *sb,
+ pthread_t my_pthread)
+{
+ GC_thread me;
+
+ GC_in_thread_creation = TRUE; /* OK to collect from unknown thread. */
+ me = GC_new_thread(my_pthread);
+ GC_in_thread_creation = FALSE;
+# ifdef GC_DARWIN_THREADS
+ me -> stop_info.mach_thread = mach_thread_self();
+# else
+ me -> stop_info.stack_ptr = sb -> mem_base;
+# endif
+ me -> stack_end = sb -> mem_base;
+# ifdef IA64
+ me -> backing_store_end = sb -> reg_base;
+# endif /* IA64 */
+ return me;
+}
+
+int GC_register_my_thread(struct GC_stack_base *sb)
+{
+ pthread_t my_pthread = pthread_self();
+ GC_thread me;
+
+ LOCK();
+ me = GC_lookup_thread(my_pthread);
+ if (0 == me) {
+ me = GC_register_my_thread_inner(sb, my_pthread);
+ me -> flags |= DETACHED;
+ /* Treat as detached, since we do not need to worry about */
+ /* pointer results. */
+ UNLOCK();
+ return GC_SUCCESS;
+ } else {
+ UNLOCK();
+ return GC_DUPLICATE;
+ }
+}
+
+void * GC_inner_start_routine(struct GC_stack_base *sb, void * arg)
+{
+ struct start_info * si = arg;
+ void * result;
+ GC_thread me;
+ pthread_t my_pthread;
+ void *(*start)(void *);
+ void *start_arg;
+
+ my_pthread = pthread_self();
+# ifdef DEBUG_THREADS
+ GC_printf("Starting thread 0x%x\n", (unsigned)my_pthread);
+ GC_printf("pid = %ld\n", (long) getpid());
+ GC_printf("sp = 0x%lx\n", (long) &arg);
+# endif
+ LOCK();
+ me = GC_register_my_thread_inner(sb, my_pthread);
+ me -> flags = si -> flags;
+ UNLOCK();
+ start = si -> start_routine;
+# ifdef DEBUG_THREADS
+ GC_printf("start_routine = %p\n", (void *)start);
+# endif
+ start_arg = si -> arg;
+ sem_post(&(si -> registered)); /* Last action on si. */
+ /* OK to deallocate. */
+ pthread_cleanup_push(GC_thread_exit_proc, 0);
+# if defined(THREAD_LOCAL_ALLOC)
+ LOCK();
+ GC_init_thread_local(&(me->tlfs));
+ UNLOCK();
+# endif
+ result = (*start)(start_arg);
+# if DEBUG_THREADS
+ GC_printf("Finishing thread 0x%x\n", (unsigned)pthread_self());
+# endif
+ me -> status = result;
+ pthread_cleanup_pop(1);
+ /* Cleanup acquires lock, ensuring that we can't exit */
+ /* while a collection that thinks we're alive is trying to stop */
+ /* us. */
+ return(result);
+}
+
+void * GC_start_routine(void * arg)
+{
+# ifdef INCLUDE_LINUX_THREAD_DESCR
+ struct GC_stack_base sb;
+
+# ifdef REDIRECT_MALLOC
+ /* GC_get_stack_base may call pthread_getattr_np, which can */
+ /* unfortunately call realloc, which may allocate from an */
+ /* unregistered thread. This is unpleasant, since it might */
+ /* force heap growth. */
+ GC_disable();
+# endif
+ if (GC_get_stack_base(&sb) != GC_SUCCESS)
+ ABORT("Failed to get thread stack base.");
+# ifdef REDIRECT_MALLOC
+ GC_enable();
+# endif
+ return GC_inner_start_routine(&sb, arg);
+# else
+ return GC_call_with_stack_base(GC_inner_start_routine, arg);
+# endif
+}
+
+int
+WRAP_FUNC(pthread_create)(pthread_t *new_thread,
+ const pthread_attr_t *attr,
+ void *(*start_routine)(void *), void *arg)
+{
+ int result;
+ int detachstate;
+ word my_flags = 0;
+ struct start_info * si;
+ /* This is otherwise saved only in an area mmapped by the thread */
+ /* library, which isn't visible to the collector. */
+
+ /* We resist the temptation to muck with the stack size here, */
+ /* even if the default is unreasonably small. That's the client's */
+ /* responsibility. */
+
+ INIT_REAL_SYMS();
+ LOCK();
+ si = (struct start_info *)GC_INTERNAL_MALLOC(sizeof(struct start_info),
+ NORMAL);
+ UNLOCK();
+ if (!parallel_initialized) GC_init_parallel();
+ if (0 == si) return(ENOMEM);
+ sem_init(&(si -> registered), 0, 0);
+ si -> start_routine = start_routine;
+ si -> arg = arg;
+ LOCK();
+ if (!GC_thr_initialized) GC_thr_init();
+# ifdef GC_ASSERTIONS
+ {
+ size_t stack_size = 0;
+ if (NULL != attr) {
+ pthread_attr_getstacksize(attr, &stack_size);
+ }
+ if (0 == stack_size) {
+ pthread_attr_t my_attr;
+ pthread_attr_init(&my_attr);
+ pthread_attr_getstacksize(&my_attr, &stack_size);
+ }
+ /* On Solaris 10, with default attr initialization, */
+ /* stack_size remains 0. Fudge it. */
+ if (0 == stack_size) {
+# ifndef SOLARIS
+ WARN("Failed to get stack size for assertion checking\n", 0);
+# endif
+ stack_size = 1000000;
+ }
+# ifdef PARALLEL_MARK
+ GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word)));
+# else
+ /* FreeBSD-5.3/Alpha: default pthread stack is 64K, */
+ /* HBLKSIZE=8192, sizeof(word)=8 */
+ GC_ASSERT(stack_size >= 65536);
+# endif
+ /* Our threads may need to do some work for the GC. */
+ /* Ridiculously small threads won't work, and they */
+ /* probably wouldn't work anyway. */
+ }
+# endif
+ if (NULL == attr) {
+ detachstate = PTHREAD_CREATE_JOINABLE;
+ } else {
+ pthread_attr_getdetachstate(attr, &detachstate);
+ }
+ if (PTHREAD_CREATE_DETACHED == detachstate) my_flags |= DETACHED;
+ si -> flags = my_flags;
+ UNLOCK();
+# ifdef DEBUG_THREADS
+ GC_printf("About to start new thread from thread 0x%x\n",
+ (unsigned)pthread_self());
+# endif
+ GC_need_to_lock = TRUE;
+
+ result = REAL_FUNC(pthread_create)(new_thread, attr, GC_start_routine, si);
+
+# ifdef DEBUG_THREADS
+ GC_printf("Started thread 0x%x\n", (unsigned)(*new_thread));
+# endif
+ /* Wait until child has been added to the thread table. */
+ /* This also ensures that we hold onto si until the child is done */
+ /* with it. Thus it doesn't matter whether it is otherwise */
+ /* visible to the collector. */
+ if (0 == result) {
+ while (0 != sem_wait(&(si -> registered))) {
+ if (EINTR != errno) ABORT("sem_wait failed");
+ }
+ }
+ sem_destroy(&(si -> registered));
+ LOCK();
+ GC_INTERNAL_FREE(si);
+ UNLOCK();
+
+ return(result);
+}
+
+/* Spend a few cycles in a way that can't introduce contention with */
+/* othre threads. */
+void GC_pause(void)
+{
+ int i;
+# if !defined(__GNUC__) || defined(__INTEL_COMPILER)
+ volatile word dummy = 0;
+# endif
+
+ for (i = 0; i < 10; ++i) {
+# if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+ __asm__ __volatile__ (" " : : : "memory");
+# else
+ /* Something that's unlikely to be optimized away. */
+ GC_noop(++dummy);
+# endif
+ }
+}
+
+#define SPIN_MAX 128 /* Maximum number of calls to GC_pause before */
+ /* give up. */
+
+volatile GC_bool GC_collecting = 0;
+ /* A hint that we're in the collector and */
+ /* holding the allocation lock for an */
+ /* extended period. */
+
+#if !defined(USE_SPIN_LOCK) || defined(PARALLEL_MARK)
+/* If we don't want to use the below spinlock implementation, either */
+/* because we don't have a GC_test_and_set implementation, or because */
+/* we don't want to risk sleeping, we can still try spinning on */
+/* pthread_mutex_trylock for a while. This appears to be very */
+/* beneficial in many cases. */
+/* I suspect that under high contention this is nearly always better */
+/* than the spin lock. But it's a bit slower on a uniprocessor. */
+/* Hence we still default to the spin lock. */
+/* This is also used to acquire the mark lock for the parallel */
+/* marker. */
+
+/* Here we use a strict exponential backoff scheme. I don't know */
+/* whether that's better or worse than the above. We eventually */
+/* yield by calling pthread_mutex_lock(); it never makes sense to */
+/* explicitly sleep. */
+
+#define LOCK_STATS
+#ifdef LOCK_STATS
+ unsigned long GC_spin_count = 0;
+ unsigned long GC_block_count = 0;
+ unsigned long GC_unlocked_count = 0;
+#endif
+
+void GC_generic_lock(pthread_mutex_t * lock)
+{
+#ifndef NO_PTHREAD_TRYLOCK
+ unsigned pause_length = 1;
+ unsigned i;
+
+ if (0 == pthread_mutex_trylock(lock)) {
+# ifdef LOCK_STATS
+ ++GC_unlocked_count;
+# endif
+ return;
+ }
+ for (; pause_length <= SPIN_MAX; pause_length <<= 1) {
+ for (i = 0; i < pause_length; ++i) {
+ GC_pause();
+ }
+ switch(pthread_mutex_trylock(lock)) {
+ case 0:
+# ifdef LOCK_STATS
+ ++GC_spin_count;
+# endif
+ return;
+ case EBUSY:
+ break;
+ default:
+ ABORT("Unexpected error from pthread_mutex_trylock");
+ }
+ }
+#endif /* !NO_PTHREAD_TRYLOCK */
+# ifdef LOCK_STATS
+ ++GC_block_count;
+# endif
+ pthread_mutex_lock(lock);
+}
+
+#endif /* !USE_SPIN_LOCK || PARALLEL_MARK */
+
+#if defined(USE_SPIN_LOCK)
+
+/* Reasonably fast spin locks. Basically the same implementation */
+/* as STL alloc.h. This isn't really the right way to do this. */
+/* but until the POSIX scheduling mess gets straightened out ... */
+
+volatile AO_TS_t GC_allocate_lock = 0;
+
+
+void GC_lock(void)
+{
+# define low_spin_max 30 /* spin cycles if we suspect uniprocessor */
+# define high_spin_max SPIN_MAX /* spin cycles for multiprocessor */
+ static unsigned spin_max = low_spin_max;
+ unsigned my_spin_max;
+ static unsigned last_spins = 0;
+ unsigned my_last_spins;
+ int i;
+
+ if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_CLEAR) {
+ return;
+ }
+ my_spin_max = spin_max;
+ my_last_spins = last_spins;
+ for (i = 0; i < my_spin_max; i++) {
+ if (GC_collecting || GC_nprocs == 1) goto yield;
+ if (i < my_last_spins/2) {
+ GC_pause();
+ continue;
+ }
+ if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_CLEAR) {
+ /*
+ * got it!
+ * Spinning worked. Thus we're probably not being scheduled
+ * against the other process with which we were contending.
+ * Thus it makes sense to spin longer the next time.
+ */
+ last_spins = i;
+ spin_max = high_spin_max;
+ return;
+ }
+ }
+ /* We are probably being scheduled against the other process. Sleep. */
+ spin_max = low_spin_max;
+yield:
+ for (i = 0;; ++i) {
+ if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_CLEAR) {
+ return;
+ }
+# define SLEEP_THRESHOLD 12
+ /* Under Linux very short sleeps tend to wait until */
+ /* the current time quantum expires. On old Linux */
+ /* kernels nanosleep(<= 2ms) just spins under Linux. */
+ /* (Under 2.4, this happens only for real-time */
+ /* processes.) We want to minimize both behaviors */
+ /* here. */
+ if (i < SLEEP_THRESHOLD) {
+ sched_yield();
+ } else {
+ struct timespec ts;
+
+ if (i > 24) i = 24;
+ /* Don't wait for more than about 15msecs, even */
+ /* under extreme contention. */
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1 << i;
+ nanosleep(&ts, 0);
+ }
+ }
+}
+
+#else /* !USE_SPINLOCK */
+void GC_lock(void)
+{
+#ifndef NO_PTHREAD_TRYLOCK
+ if (1 == GC_nprocs || GC_collecting) {
+ pthread_mutex_lock(&GC_allocate_ml);
+ } else {
+ GC_generic_lock(&GC_allocate_ml);
+ }
+#else /* !NO_PTHREAD_TRYLOCK */
+ pthread_mutex_lock(&GC_allocate_ml);
+#endif /* !NO_PTHREAD_TRYLOCK */
+}
+
+#endif /* !USE_SPINLOCK */
+
+#if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+
+#ifdef GC_ASSERTIONS
+ unsigned long GC_mark_lock_holder = NO_THREAD;
+#endif
+
+#if 0
+ /* Ugly workaround for a linux threads bug in the final versions */
+ /* of glibc2.1. Pthread_mutex_trylock sets the mutex owner */
+ /* field even when it fails to acquire the mutex. This causes */
+ /* pthread_cond_wait to die. Remove for glibc2.2. */
+ /* According to the man page, we should use */
+ /* PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, but that isn't actually */
+ /* defined. */
+ static pthread_mutex_t mark_mutex =
+ {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, {0, 0}};
+#else
+ static pthread_mutex_t mark_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+static pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER;
+
+void GC_acquire_mark_lock(void)
+{
+/*
+ if (pthread_mutex_lock(&mark_mutex) != 0) {
+ ABORT("pthread_mutex_lock failed");
+ }
+*/
+ GC_generic_lock(&mark_mutex);
+# ifdef GC_ASSERTIONS
+ GC_mark_lock_holder = NUMERIC_THREAD_ID(pthread_self());
+# endif
+}
+
+void GC_release_mark_lock(void)
+{
+ GC_ASSERT(GC_mark_lock_holder == NUMERIC_THREAD_ID(pthread_self()));
+# ifdef GC_ASSERTIONS
+ GC_mark_lock_holder = NO_THREAD;
+# endif
+ if (pthread_mutex_unlock(&mark_mutex) != 0) {
+ ABORT("pthread_mutex_unlock failed");
+ }
+}
+
+/* Collector must wait for a freelist builders for 2 reasons: */
+/* 1) Mark bits may still be getting examined without lock. */
+/* 2) Partial free lists referenced only by locals may not be scanned */
+/* correctly, e.g. if they contain "pointer-free" objects, since the */
+/* free-list link may be ignored. */
+void GC_wait_builder(void)
+{
+ GC_ASSERT(GC_mark_lock_holder == NUMERIC_THREAD_ID(pthread_self()));
+# ifdef GC_ASSERTIONS
+ GC_mark_lock_holder = NO_THREAD;
+# endif
+ if (pthread_cond_wait(&builder_cv, &mark_mutex) != 0) {
+ ABORT("pthread_cond_wait failed");
+ }
+ GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
+# ifdef GC_ASSERTIONS
+ GC_mark_lock_holder = NUMERIC_THREAD_ID(pthread_self());
+# endif
+}
+
+void GC_wait_for_reclaim(void)
+{
+ GC_acquire_mark_lock();
+ while (GC_fl_builder_count > 0) {
+ GC_wait_builder();
+ }
+ GC_release_mark_lock();
+}
+
+void GC_notify_all_builder(void)
+{
+ GC_ASSERT(GC_mark_lock_holder == NUMERIC_THREAD_ID(pthread_self()));
+ if (pthread_cond_broadcast(&builder_cv) != 0) {
+ ABORT("pthread_cond_broadcast failed");
+ }
+}
+
+#endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
+
+#ifdef PARALLEL_MARK
+
+static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
+
+void GC_wait_marker(void)
+{
+ GC_ASSERT(GC_mark_lock_holder == NUMERIC_THREAD_ID(pthread_self()));
+# ifdef GC_ASSERTIONS
+ GC_mark_lock_holder = NO_THREAD;
+# endif
+ if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) {
+ ABORT("pthread_cond_wait failed");
+ }
+ GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
+# ifdef GC_ASSERTIONS
+ GC_mark_lock_holder = NUMERIC_THREAD_ID(pthread_self());
+# endif
+}
+
+void GC_notify_all_marker(void)
+{
+ if (pthread_cond_broadcast(&mark_cv) != 0) {
+ ABORT("pthread_cond_broadcast failed");
+ }
+}
+
+#endif /* PARALLEL_MARK */
+
+# endif /* GC_LINUX_THREADS and friends */
+
diff --git a/tools/build/v2/engine/boehm_gc/ptr_chck.c b/tools/build/v2/engine/boehm_gc/ptr_chck.c
new file mode 100644
index 0000000000..d04d2daf52
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/ptr_chck.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/*
+ * These are checking routines calls to which could be inserted by a
+ * preprocessor to validate C pointer arithmetic.
+ */
+
+#include "private/gc_pmark.h"
+
+void GC_default_same_obj_print_proc(void * p, void * q)
+{
+ GC_err_printf("%p and %p are not in the same object\n", p, q);
+ ABORT("GC_same_obj test failed");
+}
+
+void (*GC_same_obj_print_proc) (void *, void *)
+ = GC_default_same_obj_print_proc;
+
+/* Check that p and q point to the same object. Call */
+/* *GC_same_obj_print_proc if they don't. */
+/* Returns the first argument. (Return value may be hard */
+/* to use,due to typing issues. But if we had a suitable */
+/* preprocessor ...) */
+/* Succeeds if neither p nor q points to the heap. */
+/* We assume this is performance critical. (It shouldn't */
+/* be called by production code, but this can easily make */
+/* debugging intolerably slow.) */
+void * GC_same_obj(void *p, void *q)
+{
+ struct hblk *h;
+ hdr *hhdr;
+ ptr_t base, limit;
+ word sz;
+
+ if (!GC_is_initialized) GC_init();
+ hhdr = HDR((word)p);
+ if (hhdr == 0) {
+ if (divHBLKSZ((word)p) != divHBLKSZ((word)q)
+ && HDR((word)q) != 0) {
+ goto fail;
+ }
+ return(p);
+ }
+ /* If it's a pointer to the middle of a large object, move it */
+ /* to the beginning. */
+ if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
+ h = HBLKPTR(p) - (word)hhdr;
+ hhdr = HDR(h);
+ while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
+ h = FORWARDED_ADDR(h, hhdr);
+ hhdr = HDR(h);
+ }
+ limit = (ptr_t)h + hhdr -> hb_sz;
+ if ((ptr_t)p >= limit || (ptr_t)q >= limit || (ptr_t)q < (ptr_t)h ) {
+ goto fail;
+ }
+ return(p);
+ }
+ sz = hhdr -> hb_sz;
+ if (sz > MAXOBJBYTES) {
+ base = (ptr_t)HBLKPTR(p);
+ limit = base + sz;
+ if ((ptr_t)p >= limit) {
+ goto fail;
+ }
+ } else {
+ size_t offset;
+ size_t pdispl = HBLKDISPL(p);
+
+ offset = pdispl % sz;
+ if (HBLKPTR(p) != HBLKPTR(q)) goto fail;
+ /* W/o this check, we might miss an error if */
+ /* q points to the first object on a page, and */
+ /* points just before the page. */
+ base = (ptr_t)p - offset;
+ limit = base + sz;
+ }
+ /* [base, limit) delimits the object containing p, if any. */
+ /* If p is not inside a valid object, then either q is */
+ /* also outside any valid object, or it is outside */
+ /* [base, limit). */
+ if ((ptr_t)q >= limit || (ptr_t)q < base) {
+ goto fail;
+ }
+ return(p);
+fail:
+ (*GC_same_obj_print_proc)((ptr_t)p, (ptr_t)q);
+ return(p);
+}
+
+void GC_default_is_valid_displacement_print_proc (void *p)
+{
+ GC_err_printf("%p does not point to valid object displacement\n", p);
+ ABORT("GC_is_valid_displacement test failed");
+}
+
+void (*GC_is_valid_displacement_print_proc)(void *) =
+ GC_default_is_valid_displacement_print_proc;
+
+/* Check that if p is a pointer to a heap page, then it points to */
+/* a valid displacement within a heap object. */
+/* Uninteresting with GC_all_interior_pointers. */
+/* Always returns its argument. */
+/* Note that we don't lock, since nothing relevant about the header */
+/* should change while we have a valid object pointer to the block. */
+void * GC_is_valid_displacement(void *p)
+{
+ hdr *hhdr;
+ word pdispl;
+ word offset;
+ struct hblk *h;
+ word sz;
+
+ if (!GC_is_initialized) GC_init();
+ hhdr = HDR((word)p);
+ if (hhdr == 0) return(p);
+ h = HBLKPTR(p);
+ if (GC_all_interior_pointers) {
+ while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
+ h = FORWARDED_ADDR(h, hhdr);
+ hhdr = HDR(h);
+ }
+ }
+ if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
+ goto fail;
+ }
+ sz = hhdr -> hb_sz;
+ pdispl = HBLKDISPL(p);
+ offset = pdispl % sz;
+ if ((sz > MAXOBJBYTES && (ptr_t)p >= (ptr_t)h + sz)
+ || !GC_valid_offsets[offset]
+ || (ptr_t)p - offset + sz > (ptr_t)(h + 1)) {
+ goto fail;
+ }
+ return(p);
+fail:
+ (*GC_is_valid_displacement_print_proc)((ptr_t)p);
+ return(p);
+}
+
+void GC_default_is_visible_print_proc(void * p)
+{
+ GC_err_printf("%p is not a GC visible pointer location\n", p);
+ ABORT("GC_is_visible test failed");
+}
+
+void (*GC_is_visible_print_proc)(void * p) = GC_default_is_visible_print_proc;
+
+/* Could p be a stack address? */
+GC_bool GC_on_stack(ptr_t p)
+{
+# ifdef THREADS
+ return(TRUE);
+# else
+ int dummy;
+# ifdef STACK_GROWS_DOWN
+ if ((ptr_t)p >= (ptr_t)(&dummy) && (ptr_t)p < GC_stackbottom ) {
+ return(TRUE);
+ }
+# else
+ if ((ptr_t)p <= (ptr_t)(&dummy) && (ptr_t)p > GC_stackbottom ) {
+ return(TRUE);
+ }
+# endif
+ return(FALSE);
+# endif
+}
+
+/* Check that p is visible */
+/* to the collector as a possibly pointer containing location. */
+/* If it isn't invoke *GC_is_visible_print_proc. */
+/* Returns the argument in all cases. May erroneously succeed */
+/* in hard cases. (This is intended for debugging use with */
+/* untyped allocations. The idea is that it should be possible, though */
+/* slow, to add such a call to all indirect pointer stores.) */
+/* Currently useless for multithreaded worlds. */
+void * GC_is_visible(void *p)
+{
+ hdr *hhdr;
+
+ if ((word)p & (ALIGNMENT - 1)) goto fail;
+ if (!GC_is_initialized) GC_init();
+# ifdef THREADS
+ hhdr = HDR((word)p);
+ if (hhdr != 0 && GC_base(p) == 0) {
+ goto fail;
+ } else {
+ /* May be inside thread stack. We can't do much. */
+ return(p);
+ }
+# else
+ /* Check stack first: */
+ if (GC_on_stack(p)) return(p);
+ hhdr = HDR((word)p);
+ if (hhdr == 0) {
+ GC_bool result;
+
+ if (GC_is_static_root(p)) return(p);
+ /* Else do it again correctly: */
+# if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || \
+ defined(MSWINCE) || defined(PCR))
+ GC_register_dynamic_libraries();
+ result = GC_is_static_root(p);
+ if (result) return(p);
+# endif
+ goto fail;
+ } else {
+ /* p points to the heap. */
+ word descr;
+ ptr_t base = GC_base(p); /* Should be manually inlined? */
+
+ if (base == 0) goto fail;
+ if (HBLKPTR(base) != HBLKPTR(p)) hhdr = HDR((word)p);
+ descr = hhdr -> hb_descr;
+ retry:
+ switch(descr & GC_DS_TAGS) {
+ case GC_DS_LENGTH:
+ if ((word)((ptr_t)p - (ptr_t)base) > (word)descr) goto fail;
+ break;
+ case GC_DS_BITMAP:
+ if ((ptr_t)p - (ptr_t)base
+ >= WORDS_TO_BYTES(BITMAP_BITS)
+ || ((word)p & (sizeof(word) - 1))) goto fail;
+ if (!((1 << (WORDSZ - ((ptr_t)p - (ptr_t)base) - 1))
+ & descr)) goto fail;
+ break;
+ case GC_DS_PROC:
+ /* We could try to decipher this partially. */
+ /* For now we just punt. */
+ break;
+ case GC_DS_PER_OBJECT:
+ if ((signed_word)descr >= 0) {
+ descr = *(word *)((ptr_t)base + (descr & ~GC_DS_TAGS));
+ } else {
+ ptr_t type_descr = *(ptr_t *)base;
+ descr = *(word *)(type_descr
+ - (descr - (GC_DS_PER_OBJECT
+ - GC_INDIR_PER_OBJ_BIAS)));
+ }
+ goto retry;
+ }
+ return(p);
+ }
+# endif
+fail:
+ (*GC_is_visible_print_proc)((ptr_t)p);
+ return(p);
+}
+
+
+void * GC_pre_incr (void **p, size_t how_much)
+{
+ void * initial = *p;
+ void * result = GC_same_obj((void *)((word)initial + how_much), initial);
+
+ if (!GC_all_interior_pointers) {
+ (void) GC_is_valid_displacement(result);
+ }
+ return (*p = result);
+}
+
+void * GC_post_incr (void **p, size_t how_much)
+{
+ void * initial = *p;
+ void * result = GC_same_obj((void *)((word)initial + how_much), initial);
+
+ if (!GC_all_interior_pointers) {
+ (void) GC_is_valid_displacement(result);
+ }
+ *p = result;
+ return(initial);
+}
diff --git a/tools/build/v2/engine/boehm_gc/real_malloc.c b/tools/build/v2/engine/boehm_gc/real_malloc.c
new file mode 100644
index 0000000000..85befdcbaa
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/real_malloc.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, May 19, 1994 2:04 pm PDT */
+
+
+# ifdef PCR
+/*
+ * This definition should go in its own file that includes no other
+ * header files. Otherwise, we risk not getting the underlying system
+ * malloc.
+ */
+# define PCR_NO_RENAME
+# include <stdlib.h>
+
+void * real_malloc(size_t size)
+{
+ return(malloc(size));
+}
+#endif /* PCR */
+
diff --git a/tools/build/v2/engine/boehm_gc/reclaim.c b/tools/build/v2/engine/boehm_gc/reclaim.c
new file mode 100644
index 0000000000..cd50fa4811
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/reclaim.c
@@ -0,0 +1,608 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#include <stdio.h>
+#include "private/gc_priv.h"
+
+signed_word GC_bytes_found = 0;
+ /* Number of bytes of memory reclaimed */
+
+#if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+ word GC_fl_builder_count = 0;
+ /* Number of threads currently building free lists without */
+ /* holding GC lock. It is not safe to collect if this is */
+ /* nonzero. */
+#endif /* PARALLEL_MARK */
+
+/* We defer printing of leaked objects until we're done with the GC */
+/* cycle, since the routine for printing objects needs to run outside */
+/* the collector, e.g. without the allocation lock. */
+#define MAX_LEAKED 40
+ptr_t GC_leaked[MAX_LEAKED];
+unsigned GC_n_leaked = 0;
+
+GC_bool GC_have_errors = FALSE;
+
+void GC_add_leaked(ptr_t leaked)
+{
+ if (GC_n_leaked < MAX_LEAKED) {
+ GC_have_errors = TRUE;
+ GC_leaked[GC_n_leaked++] = leaked;
+ /* Make sure it's not reclaimed this cycle */
+ GC_set_mark_bit(leaked);
+ }
+}
+
+static GC_bool printing_errors = FALSE;
+/* Print all objects on the list after printing any smashed objs. */
+/* Clear both lists. */
+void GC_print_all_errors ()
+{
+ unsigned i;
+
+ LOCK();
+ if (printing_errors) {
+ UNLOCK();
+ return;
+ }
+ printing_errors = TRUE;
+ UNLOCK();
+ if (GC_debugging_started) GC_print_all_smashed();
+ for (i = 0; i < GC_n_leaked; ++i) {
+ ptr_t p = GC_leaked[i];
+ if (HDR(p) -> hb_obj_kind == PTRFREE) {
+ GC_err_printf("Leaked atomic object at ");
+ } else {
+ GC_err_printf("Leaked composite object at ");
+ }
+ GC_print_heap_obj(p);
+ GC_err_printf("\n");
+ GC_free(p);
+ GC_leaked[i] = 0;
+ }
+ GC_n_leaked = 0;
+ printing_errors = FALSE;
+}
+
+
+/*
+ * reclaim phase
+ *
+ */
+
+
+/*
+ * Test whether a block is completely empty, i.e. contains no marked
+ * objects. This does not require the block to be in physical
+ * memory.
+ */
+
+GC_bool GC_block_empty(hdr *hhdr)
+{
+ return (hhdr -> hb_n_marks == 0);
+}
+
+GC_bool GC_block_nearly_full(hdr *hhdr)
+{
+ return (hhdr -> hb_n_marks > 7 * HBLK_OBJS(hhdr -> hb_sz)/8);
+}
+
+/* FIXME: This should perhaps again be specialized for USE_MARK_BYTES */
+/* and USE_MARK_BITS cases. */
+
+/*
+ * Restore unmarked small objects in h of size sz to the object
+ * free list. Returns the new list.
+ * Clears unmarked objects. Sz is in bytes.
+ */
+/*ARGSUSED*/
+ptr_t GC_reclaim_clear(struct hblk *hbp, hdr *hhdr, size_t sz,
+ ptr_t list, signed_word *count)
+{
+ word bit_no = 0;
+ word *p, *q, *plim;
+ signed_word n_bytes_found = 0;
+
+ GC_ASSERT(hhdr == GC_find_header((ptr_t)hbp));
+ GC_ASSERT(sz == hhdr -> hb_sz);
+ GC_ASSERT((sz & (BYTES_PER_WORD-1)) == 0);
+ p = (word *)(hbp->hb_body);
+ plim = (word *)(hbp->hb_body + HBLKSIZE - sz);
+
+ /* go through all words in block */
+ while( p <= plim ) {
+ if( mark_bit_from_hdr(hhdr, bit_no) ) {
+ p = (word *)((ptr_t)p + sz);
+ } else {
+ n_bytes_found += sz;
+ /* object is available - put on list */
+ obj_link(p) = list;
+ list = ((ptr_t)p);
+ /* Clear object, advance p to next object in the process */
+ q = (word *)((ptr_t)p + sz);
+# ifdef USE_MARK_BYTES
+ GC_ASSERT(!(sz & 1)
+ && !((word)p & (2 * sizeof(word) - 1)));
+ p[1] = 0;
+ p += 2;
+ while (p < q) {
+ CLEAR_DOUBLE(p);
+ p += 2;
+ }
+# else
+ p++; /* Skip link field */
+ while (p < q) {
+ *p++ = 0;
+ }
+# endif
+ }
+ bit_no += MARK_BIT_OFFSET(sz);
+ }
+ *count += n_bytes_found;
+ return(list);
+}
+
+/* The same thing, but don't clear objects: */
+/*ARGSUSED*/
+ptr_t GC_reclaim_uninit(struct hblk *hbp, hdr *hhdr, size_t sz,
+ ptr_t list, signed_word *count)
+{
+ word bit_no = 0;
+ word *p, *plim;
+ signed_word n_bytes_found = 0;
+
+ GC_ASSERT(sz == hhdr -> hb_sz);
+ p = (word *)(hbp->hb_body);
+ plim = (word *)((ptr_t)hbp + HBLKSIZE - sz);
+
+ /* go through all words in block */
+ while( p <= plim ) {
+ if( !mark_bit_from_hdr(hhdr, bit_no) ) {
+ n_bytes_found += sz;
+ /* object is available - put on list */
+ obj_link(p) = list;
+ list = ((ptr_t)p);
+ }
+ p = (word *)((ptr_t)p + sz);
+ bit_no += MARK_BIT_OFFSET(sz);
+ }
+ *count += n_bytes_found;
+ return(list);
+}
+
+/* Don't really reclaim objects, just check for unmarked ones: */
+/*ARGSUSED*/
+void GC_reclaim_check(struct hblk *hbp, hdr *hhdr, word sz)
+{
+ word bit_no = 0;
+ ptr_t p, plim;
+
+ GC_ASSERT(sz == hhdr -> hb_sz);
+ p = hbp->hb_body;
+ plim = p + HBLKSIZE - sz;
+
+ /* go through all words in block */
+ while( p <= plim ) {
+ if( !mark_bit_from_hdr(hhdr, bit_no) ) {
+ GC_add_leaked(p);
+ }
+ p += sz;
+ bit_no += MARK_BIT_OFFSET(sz);
+ }
+}
+
+
+/*
+ * Generic procedure to rebuild a free list in hbp.
+ * Also called directly from GC_malloc_many.
+ * Sz is now in bytes.
+ */
+ptr_t GC_reclaim_generic(struct hblk * hbp, hdr *hhdr, size_t sz,
+ GC_bool init, ptr_t list, signed_word *count)
+{
+ ptr_t result = list;
+
+ GC_ASSERT(GC_find_header((ptr_t)hbp) == hhdr);
+ GC_remove_protection(hbp, 1, (hhdr)->hb_descr == 0 /* Pointer-free? */);
+ if (init) {
+ result = GC_reclaim_clear(hbp, hhdr, sz, list, count);
+ } else {
+ GC_ASSERT((hhdr)->hb_descr == 0 /* Pointer-free block */);
+ result = GC_reclaim_uninit(hbp, hhdr, sz, list, count);
+ }
+ if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) GC_set_hdr_marks(hhdr);
+ return result;
+}
+
+/*
+ * Restore unmarked small objects in the block pointed to by hbp
+ * to the appropriate object free list.
+ * If entirely empty blocks are to be completely deallocated, then
+ * caller should perform that check.
+ */
+void GC_reclaim_small_nonempty_block(struct hblk *hbp,
+ int report_if_found, signed_word *count)
+{
+ hdr *hhdr = HDR(hbp);
+ size_t sz = hhdr -> hb_sz;
+ int kind = hhdr -> hb_obj_kind;
+ struct obj_kind * ok = &GC_obj_kinds[kind];
+ void **flh = &(ok -> ok_freelist[BYTES_TO_GRANULES(sz)]);
+
+ hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
+
+ if (report_if_found) {
+ GC_reclaim_check(hbp, hhdr, sz);
+ } else {
+ *flh = GC_reclaim_generic(hbp, hhdr, sz,
+ (ok -> ok_init || GC_debugging_started),
+ *flh, &GC_bytes_found);
+ }
+}
+
+/*
+ * Restore an unmarked large object or an entirely empty blocks of small objects
+ * to the heap block free list.
+ * Otherwise enqueue the block for later processing
+ * by GC_reclaim_small_nonempty_block.
+ * If report_if_found is TRUE, then process any block immediately, and
+ * simply report free objects; do not actually reclaim them.
+ */
+void GC_reclaim_block(struct hblk *hbp, word report_if_found)
+{
+ hdr * hhdr = HDR(hbp);
+ size_t sz = hhdr -> hb_sz; /* size of objects in current block */
+ struct obj_kind * ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
+ struct hblk ** rlh;
+
+ if( sz > MAXOBJBYTES ) { /* 1 big object */
+ if( !mark_bit_from_hdr(hhdr, 0) ) {
+ if (report_if_found) {
+ GC_add_leaked((ptr_t)hbp);
+ } else {
+ size_t blocks = OBJ_SZ_TO_BLOCKS(sz);
+ if (blocks > 1) {
+ GC_large_allocd_bytes -= blocks * HBLKSIZE;
+ }
+ GC_bytes_found += sz;
+ GC_freehblk(hbp);
+ }
+ } else {
+ if (hhdr -> hb_descr != 0) {
+ GC_composite_in_use += sz;
+ } else {
+ GC_atomic_in_use += sz;
+ }
+ }
+ } else {
+ GC_bool empty = GC_block_empty(hhdr);
+# ifdef PARALLEL_MARK
+ /* Count can be low or one too high because we sometimes */
+ /* have to ignore decrements. Objects can also potentially */
+ /* be repeatedly marked by each marker. */
+ /* Here we assume two markers, but this is extremely */
+ /* unlikely to fail spuriously with more. And if it does, it */
+ /* should be looked at. */
+ GC_ASSERT(hhdr -> hb_n_marks <= 2 * (HBLKSIZE/sz + 1) + 16);
+# else
+ GC_ASSERT(sz * hhdr -> hb_n_marks <= HBLKSIZE);
+# endif
+ if (hhdr -> hb_descr != 0) {
+ GC_composite_in_use += sz * hhdr -> hb_n_marks;
+ } else {
+ GC_atomic_in_use += sz * hhdr -> hb_n_marks;
+ }
+ if (report_if_found) {
+ GC_reclaim_small_nonempty_block(hbp, (int)report_if_found,
+ &GC_bytes_found);
+ } else if (empty) {
+ GC_bytes_found += HBLKSIZE;
+ GC_freehblk(hbp);
+ } else if (TRUE != GC_block_nearly_full(hhdr)){
+ /* group of smaller objects, enqueue the real work */
+ rlh = &(ok -> ok_reclaim_list[BYTES_TO_GRANULES(sz)]);
+ hhdr -> hb_next = *rlh;
+ *rlh = hbp;
+ } /* else not worth salvaging. */
+ /* We used to do the nearly_full check later, but we */
+ /* already have the right cache context here. Also */
+ /* doing it here avoids some silly lock contention in */
+ /* GC_malloc_many. */
+ }
+}
+
+#if !defined(NO_DEBUGGING)
+/* Routines to gather and print heap block info */
+/* intended for debugging. Otherwise should be called */
+/* with lock. */
+
+struct Print_stats
+{
+ size_t number_of_blocks;
+ size_t total_bytes;
+};
+
+#ifdef USE_MARK_BYTES
+
+/* Return the number of set mark bits in the given header */
+int GC_n_set_marks(hdr *hhdr)
+{
+ int result = 0;
+ int i;
+ size_t sz = hhdr -> hb_sz;
+ int offset = MARK_BIT_OFFSET(sz);
+ int limit = FINAL_MARK_BIT(sz);
+
+ for (i = 0; i < limit; i += offset) {
+ result += hhdr -> hb_marks[i];
+ }
+ GC_ASSERT(hhdr -> hb_marks[limit]);
+ return(result);
+}
+
+#else
+
+/* Number of set bits in a word. Not performance critical. */
+static int set_bits(word n)
+{
+ word m = n;
+ int result = 0;
+
+ while (m > 0) {
+ if (m & 1) result++;
+ m >>= 1;
+ }
+ return(result);
+}
+
+/* Return the number of set mark bits in the given header */
+int GC_n_set_marks(hdr *hhdr)
+{
+ int result = 0;
+ int i;
+ int n_mark_words;
+# ifdef MARK_BIT_PER_OBJ
+ int n_objs = HBLK_OBJS(hhdr -> hb_sz);
+
+ if (0 == n_objs) n_objs = 1;
+ n_mark_words = divWORDSZ(n_objs + WORDSZ - 1);
+# else /* MARK_BIT_PER_GRANULE */
+ n_mark_words = MARK_BITS_SZ;
+# endif
+ for (i = 0; i < n_mark_words - 1; i++) {
+ result += set_bits(hhdr -> hb_marks[i]);
+ }
+# ifdef MARK_BIT_PER_OBJ
+ result += set_bits((hhdr -> hb_marks[n_mark_words - 1])
+ << (n_mark_words * WORDSZ - n_objs));
+# else
+ result += set_bits(hhdr -> hb_marks[n_mark_words - 1]);
+# endif
+ return(result - 1);
+}
+
+#endif /* !USE_MARK_BYTES */
+
+/*ARGSUSED*/
+void GC_print_block_descr(struct hblk *h, word /* struct PrintStats */ raw_ps)
+{
+ hdr * hhdr = HDR(h);
+ size_t bytes = hhdr -> hb_sz;
+ struct Print_stats *ps;
+ unsigned n_marks = GC_n_set_marks(hhdr);
+
+ if (hhdr -> hb_n_marks != n_marks) {
+ GC_printf("(%u:%u,%u!=%u)", hhdr -> hb_obj_kind,
+ bytes,
+ hhdr -> hb_n_marks, n_marks);
+ } else {
+ GC_printf("(%u:%u,%u)", hhdr -> hb_obj_kind,
+ bytes, n_marks);
+ }
+ bytes += HBLKSIZE-1;
+ bytes &= ~(HBLKSIZE-1);
+
+ ps = (struct Print_stats *)raw_ps;
+ ps->total_bytes += bytes;
+ ps->number_of_blocks++;
+}
+
+void GC_print_block_list()
+{
+ struct Print_stats pstats;
+
+ GC_printf("(kind(0=ptrfree,1=normal,2=unc.):size_in_bytes, #_marks_set)\n");
+ pstats.number_of_blocks = 0;
+ pstats.total_bytes = 0;
+ GC_apply_to_all_blocks(GC_print_block_descr, (word)&pstats);
+ GC_printf("\nblocks = %lu, bytes = %lu\n",
+ (unsigned long)pstats.number_of_blocks,
+ (unsigned long)pstats.total_bytes);
+}
+
+/* Currently for debugger use only: */
+void GC_print_free_list(int kind, size_t sz_in_granules)
+{
+ struct obj_kind * ok = &GC_obj_kinds[kind];
+ ptr_t flh = ok -> ok_freelist[sz_in_granules];
+ struct hblk *lastBlock = 0;
+ int n = 0;
+
+ while (flh){
+ struct hblk *block = HBLKPTR(flh);
+ if (block != lastBlock){
+ GC_printf("\nIn heap block at 0x%x:\n\t", block);
+ lastBlock = block;
+ }
+ GC_printf("%d: 0x%x;", ++n, flh);
+ flh = obj_link(flh);
+ }
+}
+
+#endif /* NO_DEBUGGING */
+
+/*
+ * Clear all obj_link pointers in the list of free objects *flp.
+ * Clear *flp.
+ * This must be done before dropping a list of free gcj-style objects,
+ * since may otherwise end up with dangling "descriptor" pointers.
+ * It may help for other pointer-containing objects.
+ */
+void GC_clear_fl_links(void **flp)
+{
+ void *next = *flp;
+
+ while (0 != next) {
+ *flp = 0;
+ flp = &(obj_link(next));
+ next = *flp;
+ }
+}
+
+/*
+ * Perform GC_reclaim_block on the entire heap, after first clearing
+ * small object free lists (if we are not just looking for leaks).
+ */
+void GC_start_reclaim(GC_bool report_if_found)
+{
+ unsigned kind;
+
+# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+ GC_ASSERT(0 == GC_fl_builder_count);
+# endif
+ /* Reset in use counters. GC_reclaim_block recomputes them. */
+ GC_composite_in_use = 0;
+ GC_atomic_in_use = 0;
+ /* Clear reclaim- and free-lists */
+ for (kind = 0; kind < GC_n_kinds; kind++) {
+ void **fop;
+ void **lim;
+ struct hblk ** rlp;
+ struct hblk ** rlim;
+ struct hblk ** rlist = GC_obj_kinds[kind].ok_reclaim_list;
+ GC_bool should_clobber = (GC_obj_kinds[kind].ok_descriptor != 0);
+
+ if (rlist == 0) continue; /* This kind not used. */
+ if (!report_if_found) {
+ lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJGRANULES+1]);
+ for( fop = GC_obj_kinds[kind].ok_freelist; fop < lim; fop++ ) {
+ if (*fop != 0) {
+ if (should_clobber) {
+ GC_clear_fl_links(fop);
+ } else {
+ *fop = 0;
+ }
+ }
+ }
+ } /* otherwise free list objects are marked, */
+ /* and its safe to leave them */
+ rlim = rlist + MAXOBJGRANULES+1;
+ for( rlp = rlist; rlp < rlim; rlp++ ) {
+ *rlp = 0;
+ }
+ }
+
+
+ /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */
+ /* or enqueue the block for later processing. */
+ GC_apply_to_all_blocks(GC_reclaim_block, (word)report_if_found);
+
+# ifdef EAGER_SWEEP
+ /* This is a very stupid thing to do. We make it possible anyway, */
+ /* so that you can convince yourself that it really is very stupid. */
+ GC_reclaim_all((GC_stop_func)0, FALSE);
+# endif
+# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+ GC_ASSERT(0 == GC_fl_builder_count);
+# endif
+
+}
+
+/*
+ * Sweep blocks of the indicated object size and kind until either the
+ * appropriate free list is nonempty, or there are no more blocks to
+ * sweep.
+ */
+void GC_continue_reclaim(size_t sz /* granules */, int kind)
+{
+ hdr * hhdr;
+ struct hblk * hbp;
+ struct obj_kind * ok = &(GC_obj_kinds[kind]);
+ struct hblk ** rlh = ok -> ok_reclaim_list;
+ void **flh = &(ok -> ok_freelist[sz]);
+
+ if (rlh == 0) return; /* No blocks of this kind. */
+ rlh += sz;
+ while ((hbp = *rlh) != 0) {
+ hhdr = HDR(hbp);
+ *rlh = hhdr -> hb_next;
+ GC_reclaim_small_nonempty_block(hbp, FALSE, &GC_bytes_found);
+ if (*flh != 0) break;
+ }
+}
+
+/*
+ * Reclaim all small blocks waiting to be reclaimed.
+ * Abort and return FALSE when/if (*stop_func)() returns TRUE.
+ * If this returns TRUE, then it's safe to restart the world
+ * with incorrectly cleared mark bits.
+ * If ignore_old is TRUE, then reclaim only blocks that have been
+ * recently reclaimed, and discard the rest.
+ * Stop_func may be 0.
+ */
+GC_bool GC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old)
+{
+ word sz;
+ unsigned kind;
+ hdr * hhdr;
+ struct hblk * hbp;
+ struct obj_kind * ok;
+ struct hblk ** rlp;
+ struct hblk ** rlh;
+ CLOCK_TYPE start_time;
+ CLOCK_TYPE done_time;
+
+ if (GC_print_stats == VERBOSE)
+ GET_TIME(start_time);
+
+ for (kind = 0; kind < GC_n_kinds; kind++) {
+ ok = &(GC_obj_kinds[kind]);
+ rlp = ok -> ok_reclaim_list;
+ if (rlp == 0) continue;
+ for (sz = 1; sz <= MAXOBJGRANULES; sz++) {
+ rlh = rlp + sz;
+ while ((hbp = *rlh) != 0) {
+ if (stop_func != (GC_stop_func)0 && (*stop_func)()) {
+ return(FALSE);
+ }
+ hhdr = HDR(hbp);
+ *rlh = hhdr -> hb_next;
+ if (!ignore_old || hhdr -> hb_last_reclaimed == GC_gc_no - 1) {
+ /* It's likely we'll need it this time, too */
+ /* It's been touched recently, so this */
+ /* shouldn't trigger paging. */
+ GC_reclaim_small_nonempty_block(hbp, FALSE, &GC_bytes_found);
+ }
+ }
+ }
+ }
+ if (GC_print_stats == VERBOSE) {
+ GET_TIME(done_time);
+ GC_log_printf("Disposing of reclaim lists took %lu msecs\n",
+ MS_TIME_DIFF(done_time,start_time));
+ }
+ return(TRUE);
+}
diff --git a/tools/build/v2/engine/boehm_gc/rs6000_mach_dep.s b/tools/build/v2/engine/boehm_gc/rs6000_mach_dep.s
new file mode 100644
index 0000000000..12bf9a84d5
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/rs6000_mach_dep.s
@@ -0,0 +1,114 @@
+ .set r0,0
+ .set r1,1
+ .set r2,2
+ .set r3,3
+ .set r4,4
+ .set r5,5
+ .set r6,6
+ .set r7,7
+ .set r8,8
+ .set r9,9
+ .set r10,10
+ .set r11,11
+ .set r12,12
+ .set r13,13
+ .set r14,14
+ .set r15,15
+ .set r16,16
+ .set r17,17
+ .set r18,18
+ .set r19,19
+ .set r20,20
+ .set r21,21
+ .set r22,22
+ .set r23,23
+ .set r24,24
+ .set r25,25
+ .set r26,26
+ .set r27,27
+ .set r28,28
+ .set r29,29
+ .set r30,30
+ .set r31,31
+
+ .extern .GC_push_one
+ # Mark from machine registers that are saved by C compiler
+ .globl .GC_push_regs
+.csect .text[PR]
+ .align 2
+ .globl GC_push_regs
+ .globl .GC_push_regs
+.csect GC_push_regs[DS]
+GC_push_regs:
+ .long .GC_push_regs, TOC[tc0], 0
+.csect .text[PR]
+.GC_push_regs:
+ stu r1,-64(r1) # reserve stack frame
+ mflr r0 # save link register
+ st r0,0x48(r1)
+ oril r3,r2,0x0 # mark from r2
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r13,0x0 # mark from r13-r31
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r14,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r15,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r16,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r17,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r18,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r19,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r20,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r21,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r22,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r23,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r24,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r25,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r26,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r27,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r28,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r29,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r30,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ oril r3,r31,0x0
+ bl .GC_push_one
+ cror 15,15,15
+ l r0,0x48(r1)
+ mtlr r0
+ ai r1,r1,64
+ br
+ .long 0
+ .byte 0,0,0,0,0,0,0,0
diff --git a/tools/build/v2/engine/boehm_gc/setjmp_t.c b/tools/build/v2/engine/boehm_gc/setjmp_t.c
new file mode 100644
index 0000000000..5a171df0cb
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/setjmp_t.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* Check whether setjmp actually saves registers in jmp_buf. */
+/* If it doesn't, the generic mark_regs code won't work. */
+/* Compilers vary as to whether they will put x in a */
+/* (callee-save) register without -O. The code is */
+/* contrived such that any decent compiler should put x in */
+/* a callee-save register with -O. Thus it is is */
+/* recommended that this be run optimized. (If the machine */
+/* has no callee-save registers, then the generic code is */
+/* safe, but this will not be noticed by this piece of */
+/* code.) This test appears to be far from perfect. */
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "private/gc_priv.h"
+
+#ifdef OS2
+/* GETPAGESIZE() is set to getpagesize() by default, but that */
+/* doesn't really exist, and the collector doesn't need it. */
+#define INCL_DOSFILEMGR
+#define INCL_DOSMISC
+#define INCL_DOSERRORS
+#include <os2.h>
+
+int
+getpagesize()
+{
+ ULONG result[1];
+
+ if (DosQuerySysInfo(QSV_PAGE_SIZE, QSV_PAGE_SIZE,
+ (void *)result, sizeof(ULONG)) != NO_ERROR) {
+ fprintf(stderr, "DosQuerySysInfo failed\n");
+ result[0] = 4096;
+ }
+ return((int)(result[0]));
+}
+#endif
+
+struct {char a_a; char * a_b;} a;
+
+int * nested_sp()
+{
+ int dummy;
+
+ return(&dummy);
+}
+
+int main()
+{
+ int dummy;
+ long ps = GETPAGESIZE();
+ jmp_buf b;
+ register int x = (int)strlen("a"); /* 1, slightly disguised */
+ static int y = 0;
+
+ printf("This appears to be a %s running %s\n", MACH_TYPE, OS_TYPE);
+ if (nested_sp() < &dummy) {
+ printf("Stack appears to grow down, which is the default.\n");
+ printf("A good guess for STACKBOTTOM on this machine is 0x%lx.\n",
+ ((unsigned long)(&dummy) + ps) & ~(ps-1));
+ } else {
+ printf("Stack appears to grow up.\n");
+ printf("Define STACK_GROWS_UP in gc_private.h\n");
+ printf("A good guess for STACKBOTTOM on this machine is 0x%lx.\n",
+ ((unsigned long)(&dummy) + ps) & ~(ps-1));
+ }
+ printf("Note that this may vary between machines of ostensibly\n");
+ printf("the same architecture (e.g. Sun 3/50s and 3/80s).\n");
+ printf("On many machines the value is not fixed.\n");
+ printf("A good guess for ALIGNMENT on this machine is %ld.\n",
+ (unsigned long)(&(a.a_b))-(unsigned long)(&a));
+
+ printf("The following is a very dubious test of one root marking"
+ " strategy.\n");
+ printf("Results may not be accurate/useful:\n");
+ /* Encourage the compiler to keep x in a callee-save register */
+ x = 2*x-1;
+ printf("");
+ x = 2*x-1;
+ setjmp(b);
+ if (y == 1) {
+ if (x == 2) {
+ printf("Setjmp-based generic mark_regs code probably wont work.\n");
+ printf("But we rarely try that anymore. If you have getcontect()\n");
+ printf("this probably doesn't matter.\n");
+ } else if (x == 1) {
+ printf("Setjmp-based register marking code may work.\n");
+ } else {
+ printf("Very strange setjmp implementation.\n");
+ }
+ }
+ y++;
+ x = 2;
+ if (y == 1) longjmp(b,1);
+ printf("Some GC internal configuration stuff: \n");
+ printf("\tWORDSZ = %d, ALIGNMENT = %d, GC_GRANULE_BYTES = %d\n",
+ WORDSZ, ALIGNMENT, GC_GRANULE_BYTES);
+ printf("\tUsing one mark ");
+# if defined(USE_MARK_BYTES)
+ printf("byte");
+# elif defined(USE_MARK_BITS)
+ printf("bit");
+# endif
+ printf(" per ");
+# if defined(MARK_BIT_PER_OBJ)
+ printf("object.\n");
+# elif defined(MARK_BIT_PER_GRANULE)
+ printf("granule.\n");
+# endif
+# ifdef THREAD_LOCAL_ALLOC
+ printf("Thread local allocation enabled.\n");
+# endif
+# ifdef PARALLEL_MARK
+ printf("Parallel marking enabled.\n");
+# endif
+ return(0);
+}
+
+int g(x)
+int x;
+{
+ return(x);
+}
diff --git a/tools/build/v2/engine/boehm_gc/sparc_mach_dep.S b/tools/build/v2/engine/boehm_gc/sparc_mach_dep.S
new file mode 100644
index 0000000000..e8ad6556f9
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/sparc_mach_dep.S
@@ -0,0 +1,70 @@
+! SPARCompiler 3.0 and later apparently no longer handles
+! asm outside functions. So we need a separate .s file
+! This is only set up for SunOS 5, not SunOS 4.
+! Assumes this is called before the stack contents are
+! examined.
+
+ .seg "text"
+ .globl GC_save_regs_in_stack
+ .globl GC_push_regs
+GC_save_regs_in_stack:
+#if defined(__arch64__) || defined(__sparcv9)
+ save %sp,-128,%sp
+ flushw
+ ret
+ restore %sp,2047+128,%o0
+#else /* 32 bit SPARC */
+ ta 0x3 ! ST_FLUSH_WINDOWS
+ mov %sp,%o0
+ retl
+ nop
+#endif /* 32 bit SPARC */
+.GC_save_regs_in_stack_end:
+ .size GC_save_regs_in_stack,.GC_save_regs_in_stack_end-GC_save_regs_in_stack
+
+
+! GC_clear_stack_inner(arg, limit) clears stack area up to limit and
+! returns arg. Stack clearing is crucial on SPARC, so we supply
+! an assembly version that s more careful. Assumes limit is hotter
+! than sp, and limit is 8 byte aligned.
+ .globl GC_clear_stack_inner
+GC_clear_stack_inner:
+#if defined(__arch64__) || defined(__sparcv9)
+ mov %sp,%o2 ! Save sp
+ add %sp,2047-8,%o3 ! p = sp+bias-8
+ add %o1,-2047-192,%sp ! Move sp out of the way,
+ ! so that traps still work.
+ ! Includes some extra words
+ ! so we can be sloppy below.
+loop:
+ stx %g0,[%o3] ! *(long *)p = 0
+ cmp %o3,%o1
+ bgu,pt %xcc, loop ! if (p > limit) goto loop
+ add %o3,-8,%o3 ! p -= 8 (delay slot)
+ retl
+ mov %o2,%sp ! Restore sp., delay slot
+#else /* 32 bit SPARC */
+ mov %sp,%o2 ! Save sp
+ add %sp,-8,%o3 ! p = sp-8
+ clr %g1 ! [g0,g1] = 0
+ add %o1,-0x60,%sp ! Move sp out of the way,
+ ! so that traps still work.
+ ! Includes some extra words
+ ! so we can be sloppy below.
+loop:
+ std %g0,[%o3] ! *(long long *)p = 0
+ cmp %o3,%o1
+ bgu loop ! if (p > limit) goto loop
+ add %o3,-8,%o3 ! p -= 8 (delay slot)
+ retl
+ mov %o2,%sp ! Restore sp., delay slot
+#endif /* 32 bit SPARC */
+.GC_clear_stack_inner_end:
+ .size GC_clear_stack_inner,.GC_clear_stack_inner_end-GC_clear_stack_inner
+
+
+
+
+
+
+
diff --git a/tools/build/v2/engine/boehm_gc/sparc_netbsd_mach_dep.s b/tools/build/v2/engine/boehm_gc/sparc_netbsd_mach_dep.s
new file mode 100644
index 0000000000..bc3f160373
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/sparc_netbsd_mach_dep.s
@@ -0,0 +1,34 @@
+! SPARCompiler 3.0 and later apparently no longer handles
+! asm outside functions. So we need a separate .s file
+! This is only set up for SunOS 4.
+! Assumes this is called before the stack contents are
+! examined.
+
+#include "machine/asm.h"
+
+ .seg "text"
+ .globl _C_LABEL(GC_save_regs_in_stack)
+ .globl _C_LABEL(GC_push_regs)
+_C_LABEL(GC_save_regs_in_stack):
+_C_LABEL(GC_push_regs):
+ ta 0x3 ! ST_FLUSH_WINDOWS
+ mov %sp,%o0
+ retl
+ nop
+
+ .globl _C_LABEL(GC_clear_stack_inner)
+_C_LABEL(GC_clear_stack_inner):
+ mov %sp,%o2 ! Save sp
+ add %sp,-8,%o3 ! p = sp-8
+ clr %g1 ! [g0,g1] = 0
+ add %o1,-0x60,%sp ! Move sp out of the way,
+ ! so that traps still work.
+ ! Includes some extra words
+ ! so we can be sloppy below.
+loop:
+ std %g0,[%o3] ! *(long long *)p = 0
+ cmp %o3,%o1
+ bgu loop ! if (p > limit) goto loop
+ add %o3,-8,%o3 ! p -= 8 (delay slot)
+ retl
+ mov %o2,%sp ! Restore sp., delay slot
diff --git a/tools/build/v2/engine/boehm_gc/sparc_sunos4_mach_dep.s b/tools/build/v2/engine/boehm_gc/sparc_sunos4_mach_dep.s
new file mode 100644
index 0000000000..41858073ef
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/sparc_sunos4_mach_dep.s
@@ -0,0 +1,38 @@
+! SPARCompiler 3.0 and later apparently no longer handles
+! asm outside functions. So we need a separate .s file
+! This is only set up for SunOS 4.
+! Assumes this is called before the stack contents are
+! examined.
+
+ .seg "text"
+ .globl _GC_save_regs_in_stack
+ .globl _GC_push_regs
+_GC_save_regs_in_stack:
+_GC_push_regs:
+ ta 0x3 ! ST_FLUSH_WINDOWS
+ mov %sp,%o0
+ retl
+ nop
+
+ .globl _GC_clear_stack_inner
+_GC_clear_stack_inner:
+ mov %sp,%o2 ! Save sp
+ add %sp,-8,%o3 ! p = sp-8
+ clr %g1 ! [g0,g1] = 0
+ add %o1,-0x60,%sp ! Move sp out of the way,
+ ! so that traps still work.
+ ! Includes some extra words
+ ! so we can be sloppy below.
+loop:
+ std %g0,[%o3] ! *(long long *)p = 0
+ cmp %o3,%o1
+ bgu loop ! if (p > limit) goto loop
+ add %o3,-8,%o3 ! p -= 8 (delay slot)
+ retl
+ mov %o2,%sp ! Restore sp., delay slot
+
+
+
+
+
+
diff --git a/tools/build/v2/engine/boehm_gc/specific.c b/tools/build/v2/engine/boehm_gc/specific.c
new file mode 100644
index 0000000000..b8ea49dd32
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/specific.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#include "private/gc_priv.h" /* For configuration, pthreads.h. */
+#include "private/thread_local_alloc.h"
+ /* To determine type of tsd impl. */
+ /* Includes private/specific.h */
+ /* if needed. */
+
+#if defined(USE_CUSTOM_SPECIFIC)
+
+#include "atomic_ops.h"
+
+static tse invalid_tse = {INVALID_QTID, 0, 0, INVALID_THREADID};
+ /* A thread-specific data entry which will never */
+ /* appear valid to a reader. Used to fill in empty */
+ /* cache entries to avoid a check for 0. */
+
+int PREFIXED(key_create) (tsd ** key_ptr, void (* destructor)(void *)) {
+ int i;
+ tsd * result = (tsd *)MALLOC_CLEAR(sizeof (tsd));
+
+ /* A quick alignment check, since we need atomic stores */
+ GC_ASSERT((unsigned long)(&invalid_tse.next) % sizeof(tse *) == 0);
+ if (0 == result) return ENOMEM;
+ pthread_mutex_init(&(result -> lock), NULL);
+ for (i = 0; i < TS_CACHE_SIZE; ++i) {
+ result -> cache[i] = &invalid_tse;
+ }
+# ifdef GC_ASSERTIONS
+ for (i = 0; i < TS_HASH_SIZE; ++i) {
+ GC_ASSERT(result -> hash[i] == 0);
+ }
+# endif
+ *key_ptr = result;
+ return 0;
+}
+
+int PREFIXED(setspecific) (tsd * key, void * value) {
+ pthread_t self = pthread_self();
+ int hash_val = HASH(self);
+ volatile tse * entry = (volatile tse *)MALLOC_CLEAR(sizeof (tse));
+
+ GC_ASSERT(self != INVALID_THREADID);
+ if (0 == entry) return ENOMEM;
+ pthread_mutex_lock(&(key -> lock));
+ /* Could easily check for an existing entry here. */
+ entry -> next = key -> hash[hash_val];
+ entry -> thread = self;
+ entry -> value = value;
+ GC_ASSERT(entry -> qtid == INVALID_QTID);
+ /* There can only be one writer at a time, but this needs to be */
+ /* atomic with respect to concurrent readers. */
+ AO_store_release((volatile AO_t *)(key -> hash + hash_val), (AO_t)entry);
+ pthread_mutex_unlock(&(key -> lock));
+ return 0;
+}
+
+/* Remove thread-specific data for this thread. Should be called on */
+/* thread exit. */
+void PREFIXED(remove_specific) (tsd * key) {
+ pthread_t self = pthread_self();
+ unsigned hash_val = HASH(self);
+ tse *entry;
+ tse **link = key -> hash + hash_val;
+
+ pthread_mutex_lock(&(key -> lock));
+ entry = *link;
+ while (entry != NULL && entry -> thread != self) {
+ link = &(entry -> next);
+ entry = *link;
+ }
+ /* Invalidate qtid field, since qtids may be reused, and a later */
+ /* cache lookup could otherwise find this entry. */
+ entry -> qtid = INVALID_QTID;
+ if (entry != NULL) {
+ *link = entry -> next;
+ /* Atomic! concurrent accesses still work. */
+ /* They must, since readers don't lock. */
+ /* We shouldn't need a volatile access here, */
+ /* since both this and the preceding write */
+ /* should become visible no later than */
+ /* the pthread_mutex_unlock() call. */
+ }
+ /* If we wanted to deallocate the entry, we'd first have to clear */
+ /* any cache entries pointing to it. That probably requires */
+ /* additional synchronization, since we can't prevent a concurrent */
+ /* cache lookup, which should still be examining deallocated memory.*/
+ /* This can only happen if the concurrent access is from another */
+ /* thread, and hence has missed the cache, but still... */
+
+ /* With GC, we're done, since the pointers from the cache will */
+ /* be overwritten, all local pointers to the entries will be */
+ /* dropped, and the entry will then be reclaimed. */
+ pthread_mutex_unlock(&(key -> lock));
+}
+
+/* Note that even the slow path doesn't lock. */
+void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid,
+ tse * volatile * cache_ptr) {
+ pthread_t self = pthread_self();
+ unsigned hash_val = HASH(self);
+ tse *entry = key -> hash[hash_val];
+
+ GC_ASSERT(qtid != INVALID_QTID);
+ while (entry != NULL && entry -> thread != self) {
+ entry = entry -> next;
+ }
+ if (entry == NULL) return NULL;
+ /* Set cache_entry. */
+ entry -> qtid = qtid;
+ /* It's safe to do this asynchronously. Either value */
+ /* is safe, though may produce spurious misses. */
+ /* We're replacing one qtid with another one for the */
+ /* same thread. */
+ *cache_ptr = entry;
+ /* Again this is safe since pointer assignments are */
+ /* presumed atomic, and either pointer is valid. */
+ return entry -> value;
+}
+
+#ifdef GC_ASSERTIONS
+
+/* Check that that all elements of the data structure associated */
+/* with key are marked. */
+void PREFIXED(check_tsd_marks) (tsd *key)
+{
+ int i;
+ tse *p;
+
+ if (!GC_is_marked(GC_base(key))) {
+ ABORT("Unmarked thread-specific-data table");
+ }
+ for (i = 0; i < TS_HASH_SIZE; ++i) {
+ for (p = key -> hash[i]; p != 0; p = p -> next) {
+ if (!GC_is_marked(GC_base(p))) {
+ GC_err_printf(
+ "Thread-specific-data entry at %p not marked\n",p);
+ ABORT("Unmarked tse");
+ }
+ }
+ }
+ for (i = 0; i < TS_CACHE_SIZE; ++i) {
+ p = key -> cache[i];
+ if (p != &invalid_tse && !GC_is_marked(GC_base(p))) {
+ GC_err_printf(
+ "Cached thread-specific-data entry at %p not marked\n",p);
+ ABORT("Unmarked cached tse");
+ }
+ }
+}
+
+#endif
+
+#endif /* USE_CUSTOM_SPECIFIC */
diff --git a/tools/build/v2/engine/boehm_gc/stubborn.c b/tools/build/v2/engine/boehm_gc/stubborn.c
new file mode 100644
index 0000000000..f4e0958399
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/stubborn.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* Boehm, July 31, 1995 5:02 pm PDT */
+
+
+#include "private/gc_priv.h"
+
+#if defined(MANUAL_VDB)
+/* Stubborn object (hard to change, nearly immutable) allocation. */
+/* This interface is deprecated. We mostly emulate it using */
+/* MANUAL_VDB. But that imposes the additional constraint that */
+/* written, but not yet GC_dirty()ed objects must be referenced */
+/* by a stack. */
+void * GC_malloc_stubborn(size_t lb)
+{
+ return(GC_malloc(lb));
+}
+
+/*ARGSUSED*/
+void GC_end_stubborn_change(void *p)
+{
+ GC_dirty(p);
+}
+
+/*ARGSUSED*/
+void GC_change_stubborn(void *p)
+{
+}
+
+#else /* !MANUAL_VDB */
+
+void * GC_malloc_stubborn(size_t lb)
+{
+ return(GC_malloc(lb));
+}
+
+/*ARGSUSED*/
+void GC_end_stubborn_change(void *p)
+{
+}
+
+/*ARGSUSED*/
+void GC_change_stubborn(void *p)
+{
+}
+
+#endif /* !MANUAL_VDB */
diff --git a/tools/build/v2/engine/boehm_gc/tests/leak_test.c b/tools/build/v2/engine/boehm_gc/tests/leak_test.c
new file mode 100644
index 0000000000..d6a60d47a7
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/tests/leak_test.c
@@ -0,0 +1,25 @@
+#include "leak_detector.h"
+
+main() {
+ int *p[10];
+ int i;
+ GC_find_leak = 1; /* for new collect versions not compiled */
+ /* with -DFIND_LEAK. */
+
+ GC_INIT(); /* Needed if thread-local allocation is enabled. */
+ /* FIXME: This is not ideal. */
+ for (i = 0; i < 10; ++i) {
+ p[i] = malloc(sizeof(int)+i);
+ }
+ CHECK_LEAKS();
+ for (i = 1; i < 10; ++i) {
+ free(p[i]);
+ }
+ for (i = 0; i < 9; ++i) {
+ p[i] = malloc(sizeof(int)+i);
+ }
+ CHECK_LEAKS();
+ CHECK_LEAKS();
+ CHECK_LEAKS();
+ return 0;
+}
diff --git a/tools/build/v2/engine/boehm_gc/tests/middle.c b/tools/build/v2/engine/boehm_gc/tests/middle.c
new file mode 100644
index 0000000000..ebb348c493
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/tests/middle.c
@@ -0,0 +1,26 @@
+/*
+ * Test at the boundary between small and large objects.
+ * Inspired by a test case from Zoltan Varga.
+ */
+#include <gc.h>
+#include <stdio.h>
+
+int main ()
+{
+ int i;
+
+ GC_all_interior_pointers = 0;
+ GC_INIT();
+
+ for (i = 0; i < 20000; ++i) {
+ GC_malloc_atomic (4096);
+ GC_malloc (4096);
+ }
+ for (i = 0; i < 20000; ++i) {
+ GC_malloc_atomic (2048);
+ GC_malloc (2048);
+ }
+ printf("Final heap size is %ld\n", GC_get_heap_size());
+ return 0;
+}
+
diff --git a/tools/build/v2/engine/boehm_gc/tests/test.c b/tools/build/v2/engine/boehm_gc/tests/test.c
new file mode 100644
index 0000000000..47cf99b596
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/tests/test.c
@@ -0,0 +1,1634 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+/* An incomplete test for the garbage collector. */
+/* Some more obscure entry points are not tested at all. */
+/* This must be compiled with the same flags used to build the */
+/* GC. It uses GC internals to allow more precise results */
+/* checking for some of the tests. */
+
+# undef GC_BUILD
+
+#if defined(DBG_HDRS_ALL) || defined(MAKE_BACK_GRAPH)
+# define GC_DEBUG
+#endif
+
+# if defined(mips) && defined(SYSTYPE_BSD43)
+ /* MIPS RISCOS 4 */
+# else
+# include <stdlib.h>
+# endif
+# include <stdio.h>
+# ifdef _WIN32_WCE
+# include <winbase.h>
+# define assert ASSERT
+# else
+# include <assert.h> /* Not normally used, but handy for debugging. */
+# endif
+# include "gc.h"
+# include "gc_typed.h"
+# include "private/gc_priv.h" /* For output, locking, MIN_WORDS, */
+ /* and some statistics, and gcconfig.h. */
+
+# if defined(MSWIN32) || defined(MSWINCE)
+# include <windows.h>
+# endif
+
+# ifdef PCR
+# include "th/PCR_ThCrSec.h"
+# include "th/PCR_Th.h"
+# define GC_printf printf
+# endif
+
+# if defined(GC_PTHREADS)
+# include <pthread.h>
+# endif
+
+# if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
+ static CRITICAL_SECTION incr_cs;
+# endif
+
+#ifdef __STDC__
+# include <stdarg.h>
+#endif
+
+
+/* Allocation Statistics */
+int stubborn_count = 0;
+int uncollectable_count = 0;
+int collectable_count = 0;
+int atomic_count = 0;
+int realloc_count = 0;
+
+#if defined(GC_AMIGA_FASTALLOC) && defined(AMIGA)
+
+ extern void GC_amiga_free_all_mem(void);
+ void Amiga_Fail(void){GC_amiga_free_all_mem();abort();}
+# define FAIL (void)Amiga_Fail()
+ void *GC_amiga_gctest_malloc_explicitly_typed(size_t lb, GC_descr d){
+ void *ret=GC_malloc_explicitly_typed(lb,d);
+ if(ret==NULL){
+ if(!GC_dont_gc){
+ GC_gcollect();
+ ret=GC_malloc_explicitly_typed(lb,d);
+ }
+ if(ret==NULL){
+ GC_printf("Out of memory, (typed allocations are not directly "
+ "supported with the GC_AMIGA_FASTALLOC option.)\n");
+ FAIL;
+ }
+ }
+ return ret;
+ }
+ void *GC_amiga_gctest_calloc_explicitly_typed(size_t a,size_t lb, GC_descr d){
+ void *ret=GC_calloc_explicitly_typed(a,lb,d);
+ if(ret==NULL){
+ if(!GC_dont_gc){
+ GC_gcollect();
+ ret=GC_calloc_explicitly_typed(a,lb,d);
+ }
+ if(ret==NULL){
+ GC_printf("Out of memory, (typed allocations are not directly "
+ "supported with the GC_AMIGA_FASTALLOC option.)\n");
+ FAIL;
+ }
+ }
+ return ret;
+ }
+# define GC_malloc_explicitly_typed(a,b) GC_amiga_gctest_malloc_explicitly_typed(a,b)
+# define GC_calloc_explicitly_typed(a,b,c) GC_amiga_gctest_calloc_explicitly_typed(a,b,c)
+
+#else /* !AMIGA_FASTALLOC */
+
+# ifdef PCR
+# define FAIL (void)abort()
+# else
+# ifdef MSWINCE
+# define FAIL DebugBreak()
+# else
+# define FAIL GC_abort("Test failed");
+# endif
+# endif
+
+#endif /* !AMIGA_FASTALLOC */
+
+/* AT_END may be defined to exercise the interior pointer test */
+/* if the collector is configured with ALL_INTERIOR_POINTERS. */
+/* As it stands, this test should succeed with either */
+/* configuration. In the FIND_LEAK configuration, it should */
+/* find lots of leaks, since we free almost nothing. */
+
+struct SEXPR {
+ struct SEXPR * sexpr_car;
+ struct SEXPR * sexpr_cdr;
+};
+
+
+typedef struct SEXPR * sexpr;
+
+# define INT_TO_SEXPR(x) ((sexpr)(GC_word)(x))
+# define SEXPR_TO_INT(x) ((int)(GC_word)(x))
+
+# undef nil
+# define nil (INT_TO_SEXPR(0))
+# define car(x) ((x) -> sexpr_car)
+# define cdr(x) ((x) -> sexpr_cdr)
+# define is_nil(x) ((x) == nil)
+
+
+int extra_count = 0; /* Amount of space wasted in cons node */
+
+/* Silly implementation of Lisp cons. Intentionally wastes lots of space */
+/* to test collector. */
+# ifdef VERY_SMALL_CONFIG
+# define cons small_cons
+# else
+sexpr cons (sexpr x, sexpr y)
+{
+ sexpr r;
+ int *p;
+ int my_extra = extra_count;
+
+ stubborn_count++;
+ r = (sexpr) GC_MALLOC_STUBBORN(sizeof(struct SEXPR) + my_extra);
+ if (r == 0) {
+ (void)GC_printf("Out of memory\n");
+ exit(1);
+ }
+ for (p = (int *)r;
+ ((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) {
+ if (*p) {
+ (void)GC_printf("Found nonzero at %p - allocator is broken\n", p);
+ FAIL;
+ }
+ *p = (int)((13 << 12) + ((p - (int *)r) & 0xfff));
+ }
+# ifdef AT_END
+ r = (sexpr)((char *)r + (my_extra & ~7));
+# endif
+ r -> sexpr_car = x;
+ r -> sexpr_cdr = y;
+ my_extra++;
+ if ( my_extra >= 5000 ) {
+ extra_count = 0;
+ } else {
+ extra_count = my_extra;
+ }
+ GC_END_STUBBORN_CHANGE((char *)r);
+ return(r);
+}
+# endif
+
+#ifdef GC_GCJ_SUPPORT
+
+#include "gc_mark.h"
+#include "gc_gcj.h"
+
+/* The following struct emulates the vtable in gcj. */
+/* This assumes the default value of MARK_DESCR_OFFSET. */
+struct fake_vtable {
+ void * dummy; /* class pointer in real gcj. */
+ size_t descr;
+};
+
+struct fake_vtable gcj_class_struct1 = { 0, sizeof(struct SEXPR)
+ + sizeof(struct fake_vtable *) };
+ /* length based descriptor. */
+struct fake_vtable gcj_class_struct2 =
+ { 0, (3l << (CPP_WORDSZ - 3)) | GC_DS_BITMAP};
+ /* Bitmap based descriptor. */
+
+struct GC_ms_entry * fake_gcj_mark_proc(word * addr,
+ struct GC_ms_entry *mark_stack_ptr,
+ struct GC_ms_entry *mark_stack_limit,
+ word env )
+{
+ sexpr x;
+ if (1 == env) {
+ /* Object allocated with debug allocator. */
+ addr = (word *)GC_USR_PTR_FROM_BASE(addr);
+ }
+ x = (sexpr)(addr + 1); /* Skip the vtable pointer. */
+ mark_stack_ptr = GC_MARK_AND_PUSH(
+ (void *)(x -> sexpr_cdr), mark_stack_ptr,
+ mark_stack_limit, (void * *)&(x -> sexpr_cdr));
+ mark_stack_ptr = GC_MARK_AND_PUSH(
+ (void *)(x -> sexpr_car), mark_stack_ptr,
+ mark_stack_limit, (void * *)&(x -> sexpr_car));
+ return(mark_stack_ptr);
+}
+
+#endif /* GC_GCJ_SUPPORT */
+
+
+sexpr small_cons (sexpr x, sexpr y)
+{
+ sexpr r;
+
+ collectable_count++;
+ r = (sexpr) GC_MALLOC(sizeof(struct SEXPR));
+ if (r == 0) {
+ (void)GC_printf("Out of memory\n");
+ exit(1);
+ }
+ r -> sexpr_car = x;
+ r -> sexpr_cdr = y;
+ return(r);
+}
+
+sexpr small_cons_uncollectable (sexpr x, sexpr y)
+{
+ sexpr r;
+
+ uncollectable_count++;
+ r = (sexpr) GC_MALLOC_UNCOLLECTABLE(sizeof(struct SEXPR));
+ if (r == 0) {
+ (void)GC_printf("Out of memory\n");
+ exit(1);
+ }
+ r -> sexpr_car = x;
+ r -> sexpr_cdr = (sexpr)(~(GC_word)y);
+ return(r);
+}
+
+#ifdef GC_GCJ_SUPPORT
+
+
+sexpr gcj_cons(sexpr x, sexpr y)
+{
+ GC_word * r;
+ sexpr result;
+ static int count = 0;
+
+ r = (GC_word *) GC_GCJ_MALLOC(sizeof(struct SEXPR)
+ + sizeof(struct fake_vtable*),
+ &gcj_class_struct2);
+ if (r == 0) {
+ (void)GC_printf("Out of memory\n");
+ exit(1);
+ }
+ result = (sexpr)(r + 1);
+ result -> sexpr_car = x;
+ result -> sexpr_cdr = y;
+ return(result);
+}
+#endif
+
+/* Return reverse(x) concatenated with y */
+sexpr reverse1(sexpr x, sexpr y)
+{
+ if (is_nil(x)) {
+ return(y);
+ } else {
+ return( reverse1(cdr(x), cons(car(x), y)) );
+ }
+}
+
+sexpr reverse(sexpr x)
+{
+# ifdef TEST_WITH_SYSTEM_MALLOC
+ malloc(100000);
+# endif
+ return( reverse1(x, nil) );
+}
+
+sexpr ints(int low, int up)
+{
+ if (low > up) {
+ return(nil);
+ } else {
+ return(small_cons(small_cons(INT_TO_SEXPR(low), nil), ints(low+1, up)));
+ }
+}
+
+#ifdef GC_GCJ_SUPPORT
+/* Return reverse(x) concatenated with y */
+sexpr gcj_reverse1(sexpr x, sexpr y)
+{
+ if (is_nil(x)) {
+ return(y);
+ } else {
+ return( gcj_reverse1(cdr(x), gcj_cons(car(x), y)) );
+ }
+}
+
+sexpr gcj_reverse(sexpr x)
+{
+ return( gcj_reverse1(x, nil) );
+}
+
+sexpr gcj_ints(int low, int up)
+{
+ if (low > up) {
+ return(nil);
+ } else {
+ return(gcj_cons(gcj_cons(INT_TO_SEXPR(low), nil), gcj_ints(low+1, up)));
+ }
+}
+#endif /* GC_GCJ_SUPPORT */
+
+/* To check uncollectable allocation we build lists with disguised cdr */
+/* pointers, and make sure they don't go away. */
+sexpr uncollectable_ints(int low, int up)
+{
+ if (low > up) {
+ return(nil);
+ } else {
+ return(small_cons_uncollectable(small_cons(INT_TO_SEXPR(low), nil),
+ uncollectable_ints(low+1, up)));
+ }
+}
+
+void check_ints(sexpr list, int low, int up)
+{
+ if (SEXPR_TO_INT(car(car(list))) != low) {
+ (void)GC_printf(
+ "List reversal produced incorrect list - collector is broken\n");
+ FAIL;
+ }
+ if (low == up) {
+ if (cdr(list) != nil) {
+ (void)GC_printf("List too long - collector is broken\n");
+ FAIL;
+ }
+ } else {
+ check_ints(cdr(list), low+1, up);
+ }
+}
+
+# define UNCOLLECTABLE_CDR(x) (sexpr)(~(GC_word)(cdr(x)))
+
+void check_uncollectable_ints(sexpr list, int low, int up)
+{
+ if (SEXPR_TO_INT(car(car(list))) != low) {
+ (void)GC_printf(
+ "Uncollectable list corrupted - collector is broken\n");
+ FAIL;
+ }
+ if (low == up) {
+ if (UNCOLLECTABLE_CDR(list) != nil) {
+ (void)GC_printf("Uncollectable list too long - collector is broken\n");
+ FAIL;
+ }
+ } else {
+ check_uncollectable_ints(UNCOLLECTABLE_CDR(list), low+1, up);
+ }
+}
+
+/* Not used, but useful for debugging: */
+void print_int_list(sexpr x)
+{
+ if (is_nil(x)) {
+ (void)GC_printf("NIL\n");
+ } else {
+ (void)GC_printf("(%d)", SEXPR_TO_INT(car(car(x))));
+ if (!is_nil(cdr(x))) {
+ (void)GC_printf(", ");
+ (void)print_int_list(cdr(x));
+ } else {
+ (void)GC_printf("\n");
+ }
+ }
+}
+
+/* ditto: */
+void check_marks_int_list(sexpr x)
+{
+ if (!GC_is_marked((ptr_t)x))
+ GC_printf("[unm:%p]", x);
+ else
+ GC_printf("[mkd:%p]", x);
+ if (is_nil(x)) {
+ (void)GC_printf("NIL\n");
+ } else {
+ if (!GC_is_marked((ptr_t)car(x))) GC_printf("[unm car:%p]", car(x));
+ (void)GC_printf("(%d)", SEXPR_TO_INT(car(car(x))));
+ if (!is_nil(cdr(x))) {
+ (void)GC_printf(", ");
+ (void)check_marks_int_list(cdr(x));
+ } else {
+ (void)GC_printf("\n");
+ }
+ }
+}
+
+/*
+ * A tiny list reversal test to check thread creation.
+ */
+#ifdef THREADS
+
+# if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
+ DWORD __stdcall tiny_reverse_test(void * arg)
+# else
+ void * tiny_reverse_test(void * arg)
+# endif
+{
+ int i;
+ for (i = 0; i < 5; ++i) {
+ check_ints(reverse(reverse(ints(1,10))), 1, 10);
+ }
+ return 0;
+}
+
+# if defined(GC_PTHREADS)
+ void fork_a_thread()
+ {
+ pthread_t t;
+ int code;
+ if ((code = pthread_create(&t, 0, tiny_reverse_test, 0)) != 0) {
+ (void)GC_printf("Small thread creation failed %d\n", code);
+ FAIL;
+ }
+ if ((code = pthread_join(t, 0)) != 0) {
+ (void)GC_printf("Small thread join failed %d\n", code);
+ FAIL;
+ }
+ }
+
+# elif defined(GC_WIN32_THREADS)
+ void fork_a_thread()
+ {
+ DWORD thread_id;
+ HANDLE h;
+ h = GC_CreateThread(NULL, 0, tiny_reverse_test, 0, 0, &thread_id);
+ if (h == (HANDLE)NULL) {
+ (void)GC_printf("Small thread creation failed %d\n",
+ GetLastError());
+ FAIL;
+ }
+ if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {
+ (void)GC_printf("Small thread wait failed %d\n",
+ GetLastError());
+ FAIL;
+ }
+ }
+
+# else
+
+# define fork_a_thread()
+
+# endif
+
+#else
+
+# define fork_a_thread()
+
+#endif
+
+/* Try to force a to be strangely aligned */
+struct {
+ char dummy;
+ sexpr aa;
+} A;
+#define a A.aa
+
+/*
+ * Repeatedly reverse lists built out of very different sized cons cells.
+ * Check that we didn't lose anything.
+ */
+void reverse_test()
+{
+ int i;
+ sexpr b;
+ sexpr c;
+ sexpr d;
+ sexpr e;
+ sexpr *f, *g, *h;
+# if defined(MSWIN32) || defined(MACOS)
+ /* Win32S only allows 128K stacks */
+# define BIG 1000
+# else
+# if defined PCR
+ /* PCR default stack is 100K. Stack frames are up to 120 bytes. */
+# define BIG 700
+# else
+# if defined MSWINCE
+ /* WinCE only allows 64K stacks */
+# define BIG 500
+# else
+# if defined(OSF1)
+ /* OSF has limited stack space by default, and large frames. */
+# define BIG 200
+# else
+# define BIG 4500
+# endif
+# endif
+# endif
+# endif
+
+ A.dummy = 17;
+ a = ints(1, 49);
+ b = ints(1, 50);
+ c = ints(1, BIG);
+ d = uncollectable_ints(1, 100);
+ e = uncollectable_ints(1, 1);
+ /* Check that realloc updates object descriptors correctly */
+ collectable_count++;
+ f = (sexpr *)GC_MALLOC(4 * sizeof(sexpr));
+ realloc_count++;
+ f = (sexpr *)GC_REALLOC((void *)f, 6 * sizeof(sexpr));
+ f[5] = ints(1,17);
+ collectable_count++;
+ g = (sexpr *)GC_MALLOC(513 * sizeof(sexpr));
+ realloc_count++;
+ g = (sexpr *)GC_REALLOC((void *)g, 800 * sizeof(sexpr));
+ g[799] = ints(1,18);
+ collectable_count++;
+ h = (sexpr *)GC_MALLOC(1025 * sizeof(sexpr));
+ realloc_count++;
+ h = (sexpr *)GC_REALLOC((void *)h, 2000 * sizeof(sexpr));
+# ifdef GC_GCJ_SUPPORT
+ h[1999] = gcj_ints(1,200);
+ for (i = 0; i < 51; ++i)
+ h[1999] = gcj_reverse(h[1999]);
+ /* Leave it as the reveresed list for now. */
+# else
+ h[1999] = ints(1,200);
+# endif
+ /* Try to force some collections and reuse of small list elements */
+ for (i = 0; i < 10; i++) {
+ (void)ints(1, BIG);
+ }
+ /* Superficially test interior pointer recognition on stack */
+ c = (sexpr)((char *)c + sizeof(char *));
+ d = (sexpr)((char *)d + sizeof(char *));
+
+# ifdef __STDC__
+ GC_FREE((void *)e);
+# else
+ GC_FREE((char *)e);
+# endif
+ check_ints(b,1,50);
+ check_ints(a,1,49);
+ for (i = 0; i < 50; i++) {
+ check_ints(b,1,50);
+ b = reverse(reverse(b));
+ }
+ check_ints(b,1,50);
+ check_ints(a,1,49);
+ for (i = 0; i < 60; i++) {
+ if (i % 10 == 0) fork_a_thread();
+ /* This maintains the invariant that a always points to a list of */
+ /* 49 integers. Thus this is thread safe without locks, */
+ /* assuming atomic pointer assignments. */
+ a = reverse(reverse(a));
+# if !defined(AT_END) && !defined(THREADS)
+ /* This is not thread safe, since realloc explicitly deallocates */
+ if (i & 1) {
+ a = (sexpr)GC_REALLOC((void *)a, 500);
+ } else {
+ a = (sexpr)GC_REALLOC((void *)a, 8200);
+ }
+# endif
+ }
+ check_ints(a,1,49);
+ check_ints(b,1,50);
+ c = (sexpr)((char *)c - sizeof(char *));
+ d = (sexpr)((char *)d - sizeof(char *));
+ check_ints(c,1,BIG);
+ check_uncollectable_ints(d, 1, 100);
+ check_ints(f[5], 1,17);
+ check_ints(g[799], 1,18);
+# ifdef GC_GCJ_SUPPORT
+ h[1999] = gcj_reverse(h[1999]);
+# endif
+ check_ints(h[1999], 1,200);
+# ifndef THREADS
+ a = 0;
+# endif
+ b = c = 0;
+}
+
+#undef a
+
+/*
+ * The rest of this builds balanced binary trees, checks that they don't
+ * disappear, and tests finalization.
+ */
+typedef struct treenode {
+ int level;
+ struct treenode * lchild;
+ struct treenode * rchild;
+} tn;
+
+int finalizable_count = 0;
+int finalized_count = 0;
+volatile int dropped_something = 0;
+
+# ifdef __STDC__
+ void finalizer(void * obj, void * client_data)
+# else
+ void finalizer(obj, client_data)
+ char * obj;
+ char * client_data;
+# endif
+{
+ tn * t = (tn *)obj;
+
+# ifdef PCR
+ PCR_ThCrSec_EnterSys();
+# endif
+# if defined(GC_PTHREADS)
+ static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&incr_lock);
+# elif defined(GC_WIN32_THREADS)
+ EnterCriticalSection(&incr_cs);
+# endif
+ if ((int)(GC_word)client_data != t -> level) {
+ (void)GC_printf("Wrong finalization data - collector is broken\n");
+ FAIL;
+ }
+ finalized_count++;
+ t -> level = -1; /* detect duplicate finalization immediately */
+# ifdef PCR
+ PCR_ThCrSec_ExitSys();
+# endif
+# if defined(GC_PTHREADS)
+ pthread_mutex_unlock(&incr_lock);
+# elif defined(GC_WIN32_THREADS)
+ LeaveCriticalSection(&incr_cs);
+# endif
+}
+
+size_t counter = 0;
+
+# define MAX_FINALIZED 8000
+
+# if !defined(MACOS)
+ GC_FAR GC_word live_indicators[MAX_FINALIZED] = {0};
+#else
+ /* Too big for THINK_C. have to allocate it dynamically. */
+ GC_word *live_indicators = 0;
+#endif
+
+int live_indicators_count = 0;
+
+tn * mktree(int n)
+{
+ tn * result = (tn *)GC_MALLOC(sizeof(tn));
+
+ collectable_count++;
+# if defined(MACOS)
+ /* get around static data limitations. */
+ if (!live_indicators)
+ live_indicators =
+ (GC_word*)NewPtrClear(MAX_FINALIZED * sizeof(GC_word));
+ if (!live_indicators) {
+ (void)GC_printf("Out of memory\n");
+ exit(1);
+ }
+# endif
+ if (n == 0) return(0);
+ if (result == 0) {
+ (void)GC_printf("Out of memory\n");
+ exit(1);
+ }
+ result -> level = n;
+ result -> lchild = mktree(n-1);
+ result -> rchild = mktree(n-1);
+ if (counter++ % 17 == 0 && n >= 2) {
+ tn * tmp = result -> lchild -> rchild;
+
+ result -> lchild -> rchild = result -> rchild -> lchild;
+ result -> rchild -> lchild = tmp;
+ }
+ if (counter++ % 119 == 0) {
+ int my_index;
+
+ {
+# ifdef PCR
+ PCR_ThCrSec_EnterSys();
+# endif
+# if defined(GC_PTHREADS)
+ static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&incr_lock);
+# elif defined(GC_WIN32_THREADS)
+ EnterCriticalSection(&incr_cs);
+# endif
+ /* Losing a count here causes erroneous report of failure. */
+ finalizable_count++;
+ my_index = live_indicators_count++;
+# ifdef PCR
+ PCR_ThCrSec_ExitSys();
+# endif
+# if defined(GC_PTHREADS)
+ pthread_mutex_unlock(&incr_lock);
+# elif defined(GC_WIN32_THREADS)
+ LeaveCriticalSection(&incr_cs);
+# endif
+ }
+
+ GC_REGISTER_FINALIZER((void *)result, finalizer, (void *)(GC_word)n,
+ (GC_finalization_proc *)0, (void * *)0);
+ if (my_index >= MAX_FINALIZED) {
+ GC_printf("live_indicators overflowed\n");
+ FAIL;
+ }
+ live_indicators[my_index] = 13;
+ if (GC_GENERAL_REGISTER_DISAPPEARING_LINK(
+ (void * *)(&(live_indicators[my_index])),
+ (void *)result) != 0) {
+ GC_printf("GC_general_register_disappearing_link failed\n");
+ FAIL;
+ }
+ if (GC_unregister_disappearing_link(
+ (void * *)
+ (&(live_indicators[my_index]))) == 0) {
+ GC_printf("GC_unregister_disappearing_link failed\n");
+ FAIL;
+ }
+ if (GC_GENERAL_REGISTER_DISAPPEARING_LINK(
+ (void * *)(&(live_indicators[my_index])),
+ (void *)result) != 0) {
+ GC_printf("GC_general_register_disappearing_link failed 2\n");
+ FAIL;
+ }
+ GC_reachable_here(result);
+ }
+ return(result);
+}
+
+void chktree(tn *t, int n)
+{
+ if (n == 0 && t != 0) {
+ (void)GC_printf("Clobbered a leaf - collector is broken\n");
+ FAIL;
+ }
+ if (n == 0) return;
+ if (t -> level != n) {
+ (void)GC_printf("Lost a node at level %d - collector is broken\n", n);
+ FAIL;
+ }
+ if (counter++ % 373 == 0) {
+ collectable_count++;
+ (void) GC_MALLOC(counter%5001);
+ }
+ chktree(t -> lchild, n-1);
+ if (counter++ % 73 == 0) {
+ collectable_count++;
+ (void) GC_MALLOC(counter%373);
+ }
+ chktree(t -> rchild, n-1);
+}
+
+
+#if defined(GC_PTHREADS)
+pthread_key_t fl_key;
+
+void * alloc8bytes()
+{
+# if defined(SMALL_CONFIG) || defined(GC_DEBUG)
+ collectable_count++;
+ return(GC_MALLOC(8));
+# else
+ void ** my_free_list_ptr;
+ void * my_free_list;
+
+ my_free_list_ptr = (void **)pthread_getspecific(fl_key);
+ if (my_free_list_ptr == 0) {
+ uncollectable_count++;
+ my_free_list_ptr = GC_NEW_UNCOLLECTABLE(void *);
+ if (pthread_setspecific(fl_key, my_free_list_ptr) != 0) {
+ (void)GC_printf("pthread_setspecific failed\n");
+ FAIL;
+ }
+ }
+ my_free_list = *my_free_list_ptr;
+ if (my_free_list == 0) {
+ my_free_list = GC_malloc_many(8);
+ if (my_free_list == 0) {
+ (void)GC_printf("alloc8bytes out of memory\n");
+ FAIL;
+ }
+ }
+ *my_free_list_ptr = GC_NEXT(my_free_list);
+ GC_NEXT(my_free_list) = 0;
+ collectable_count++;
+ return(my_free_list);
+# endif
+}
+
+#else
+# define alloc8bytes() GC_MALLOC_ATOMIC(8)
+#endif
+
+void alloc_small(int n)
+{
+ int i;
+
+ for (i = 0; i < n; i += 8) {
+ atomic_count++;
+ if (alloc8bytes() == 0) {
+ (void)GC_printf("Out of memory\n");
+ FAIL;
+ }
+ }
+}
+
+# if defined(THREADS) && defined(GC_DEBUG)
+# ifdef VERY_SMALL_CONFIG
+# define TREE_HEIGHT 12
+# else
+# define TREE_HEIGHT 15
+# endif
+# else
+# ifdef VERY_SMALL_CONFIG
+# define TREE_HEIGHT 13
+# else
+# define TREE_HEIGHT 16
+# endif
+# endif
+void tree_test()
+{
+ tn * root;
+ int i;
+
+ root = mktree(TREE_HEIGHT);
+# ifndef VERY_SMALL_CONFIG
+ alloc_small(5000000);
+# endif
+ chktree(root, TREE_HEIGHT);
+ if (finalized_count && ! dropped_something) {
+ (void)GC_printf("Premature finalization - collector is broken\n");
+ FAIL;
+ }
+ dropped_something = 1;
+ GC_noop(root); /* Root needs to remain live until */
+ /* dropped_something is set. */
+ root = mktree(TREE_HEIGHT);
+ chktree(root, TREE_HEIGHT);
+ for (i = TREE_HEIGHT; i >= 0; i--) {
+ root = mktree(i);
+ chktree(root, i);
+ }
+# ifndef VERY_SMALL_CONFIG
+ alloc_small(5000000);
+# endif
+}
+
+unsigned n_tests = 0;
+
+GC_word bm_huge[10] = {
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0x00ffffff,
+};
+
+/* A very simple test of explicitly typed allocation */
+void typed_test()
+{
+ GC_word * old, * new;
+ GC_word bm3 = 0x3;
+ GC_word bm2 = 0x2;
+ GC_word bm_large = 0xf7ff7fff;
+ GC_descr d1 = GC_make_descriptor(&bm3, 2);
+ GC_descr d2 = GC_make_descriptor(&bm2, 2);
+ GC_descr d3 = GC_make_descriptor(&bm_large, 32);
+ GC_descr d4 = GC_make_descriptor(bm_huge, 320);
+ GC_word * x = (GC_word *)GC_malloc_explicitly_typed(2000, d4);
+ int i;
+
+# ifndef LINT
+ (void)GC_make_descriptor(&bm_large, 32);
+# endif
+ collectable_count++;
+ old = 0;
+ for (i = 0; i < 4000; i++) {
+ collectable_count++;
+ new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d1);
+ if (0 != new[0] || 0 != new[1]) {
+ GC_printf("Bad initialization by GC_malloc_explicitly_typed\n");
+ FAIL;
+ }
+ new[0] = 17;
+ new[1] = (GC_word)old;
+ old = new;
+ collectable_count++;
+ new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d2);
+ new[0] = 17;
+ new[1] = (GC_word)old;
+ old = new;
+ collectable_count++;
+ new = (GC_word *) GC_malloc_explicitly_typed(33 * sizeof(GC_word), d3);
+ new[0] = 17;
+ new[1] = (GC_word)old;
+ old = new;
+ collectable_count++;
+ new = (GC_word *) GC_calloc_explicitly_typed(4, 2 * sizeof(GC_word),
+ d1);
+ new[0] = 17;
+ new[1] = (GC_word)old;
+ old = new;
+ collectable_count++;
+ if (i & 0xff) {
+ new = (GC_word *) GC_calloc_explicitly_typed(7, 3 * sizeof(GC_word),
+ d2);
+ } else {
+ new = (GC_word *) GC_calloc_explicitly_typed(1001,
+ 3 * sizeof(GC_word),
+ d2);
+ if (0 != new[0] || 0 != new[1]) {
+ GC_printf("Bad initialization by GC_malloc_explicitly_typed\n");
+ FAIL;
+ }
+ }
+ new[0] = 17;
+ new[1] = (GC_word)old;
+ old = new;
+ }
+ for (i = 0; i < 20000; i++) {
+ if (new[0] != 17) {
+ (void)GC_printf("typed alloc failed at %lu\n",
+ (unsigned long)i);
+ FAIL;
+ }
+ new[0] = 0;
+ old = new;
+ new = (GC_word *)(old[1]);
+ }
+ GC_gcollect();
+ GC_noop(x);
+}
+
+int fail_count = 0;
+
+#ifndef __STDC__
+/*ARGSUSED*/
+void fail_proc1(x)
+void * x;
+{
+ fail_count++;
+}
+
+#else
+
+/*ARGSUSED*/
+void fail_proc1(void * x)
+{
+ fail_count++;
+}
+
+static void uniq(void *p, ...) {
+ va_list a;
+ void *q[100];
+ int n = 0, i, j;
+ q[n++] = p;
+ va_start(a,p);
+ for (;(q[n] = va_arg(a,void *));n++) ;
+ va_end(a);
+ for (i=0; i<n; i++)
+ for (j=0; j<i; j++)
+ if (q[i] == q[j]) {
+ GC_printf(
+ "Apparently failed to mark from some function arguments.\n"
+ "Perhaps GC_push_regs was configured incorrectly?\n"
+ );
+ FAIL;
+ }
+}
+
+#endif /* __STDC__ */
+
+#ifdef THREADS
+# define TEST_FAIL_COUNT(n) 1
+#else
+# define TEST_FAIL_COUNT(n) (fail_count >= (n))
+#endif
+
+void run_one_test()
+{
+ char *x;
+# ifdef LINT
+ char *y = 0;
+# else
+ char *y = (char *)(size_t)fail_proc1;
+# endif
+ DCL_LOCK_STATE;
+
+# ifdef FIND_LEAK
+ (void)GC_printf(
+ "This test program is not designed for leak detection mode\n");
+ (void)GC_printf("Expect lots of problems.\n");
+# endif
+ GC_FREE(0);
+# ifndef DBG_HDRS_ALL
+ collectable_count += 3;
+ if ((GC_size(GC_malloc(7)) != 8 &&
+ GC_size(GC_malloc(7)) != MIN_WORDS * sizeof(GC_word))
+ || GC_size(GC_malloc(15)) != 16) {
+ (void)GC_printf("GC_size produced unexpected results\n");
+ FAIL;
+ }
+ collectable_count += 1;
+ if (GC_size(GC_malloc(0)) != MIN_WORDS * sizeof(GC_word)) {
+ (void)GC_printf("GC_malloc(0) failed: GC_size returns %ld\n",
+ (unsigned long)GC_size(GC_malloc(0)));
+ FAIL;
+ }
+ collectable_count += 1;
+ if (GC_size(GC_malloc_uncollectable(0)) != MIN_WORDS * sizeof(GC_word)) {
+ (void)GC_printf("GC_malloc_uncollectable(0) failed\n");
+ FAIL;
+ }
+ GC_is_valid_displacement_print_proc = fail_proc1;
+ GC_is_visible_print_proc = fail_proc1;
+ collectable_count += 1;
+ x = GC_malloc(16);
+ if (GC_base(x + 13) != x) {
+ (void)GC_printf("GC_base(heap ptr) produced incorrect result\n");
+ FAIL;
+ }
+# ifndef PCR
+ if (GC_base(y) != 0) {
+ (void)GC_printf("GC_base(fn_ptr) produced incorrect result\n");
+ FAIL;
+ }
+# endif
+ if (GC_same_obj(x+5, x) != x + 5) {
+ (void)GC_printf("GC_same_obj produced incorrect result\n");
+ FAIL;
+ }
+ if (GC_is_visible(y) != y || GC_is_visible(x) != x) {
+ (void)GC_printf("GC_is_visible produced incorrect result\n");
+ FAIL;
+ }
+ if (!TEST_FAIL_COUNT(1)) {
+# if!(defined(RS6000) || defined(POWERPC) || defined(IA64)) || defined(M68K)
+ /* ON RS6000s function pointers point to a descriptor in the */
+ /* data segment, so there should have been no failures. */
+ /* The same applies to IA64. Something similar seems to */
+ /* be going on with NetBSD/M68K. */
+ (void)GC_printf("GC_is_visible produced wrong failure indication\n");
+ FAIL;
+# endif
+ }
+ if (GC_is_valid_displacement(y) != y
+ || GC_is_valid_displacement(x) != x
+ || GC_is_valid_displacement(x + 3) != x + 3) {
+ (void)GC_printf(
+ "GC_is_valid_displacement produced incorrect result\n");
+ FAIL;
+ }
+# if defined(__STDC__) && !defined(MSWIN32) && !defined(MSWINCE)
+ /* Harder to test under Windows without a gc.h declaration. */
+ {
+ size_t i;
+ extern void *GC_memalign();
+
+ GC_malloc(17);
+ for (i = sizeof(GC_word); i < 512; i *= 2) {
+ GC_word result = (GC_word) GC_memalign(i, 17);
+ if (result % i != 0 || result == 0 || *(int *)result != 0) FAIL;
+ }
+ }
+# endif
+# ifndef ALL_INTERIOR_POINTERS
+# if defined(RS6000) || defined(POWERPC)
+ if (!TEST_FAIL_COUNT(1)) {
+# else
+ if (GC_all_interior_pointers && !TEST_FAIL_COUNT(1)
+ || !GC_all_interior_pointers && !TEST_FAIL_COUNT(2)) {
+# endif
+ (void)GC_printf("GC_is_valid_displacement produced wrong failure indication\n");
+ FAIL;
+ }
+# endif
+# endif /* DBG_HDRS_ALL */
+ /* Test floating point alignment */
+ collectable_count += 2;
+ *(double *)GC_MALLOC(sizeof(double)) = 1.0;
+ *(double *)GC_MALLOC(sizeof(double)) = 1.0;
+# ifdef GC_GCJ_SUPPORT
+ GC_REGISTER_DISPLACEMENT(sizeof(struct fake_vtable *));
+ GC_init_gcj_malloc(0, (void *)fake_gcj_mark_proc);
+# endif
+ /* Make sure that fn arguments are visible to the collector. */
+# ifdef __STDC__
+ uniq(
+ GC_malloc(12), GC_malloc(12), GC_malloc(12),
+ (GC_gcollect(),GC_malloc(12)),
+ GC_malloc(12), GC_malloc(12), GC_malloc(12),
+ (GC_gcollect(),GC_malloc(12)),
+ GC_malloc(12), GC_malloc(12), GC_malloc(12),
+ (GC_gcollect(),GC_malloc(12)),
+ GC_malloc(12), GC_malloc(12), GC_malloc(12),
+ (GC_gcollect(),GC_malloc(12)),
+ GC_malloc(12), GC_malloc(12), GC_malloc(12),
+ (GC_gcollect(),GC_malloc(12)),
+ (void *)0);
+# endif
+ /* GC_malloc(0) must return NULL or something we can deallocate. */
+ GC_free(GC_malloc(0));
+ GC_free(GC_malloc_atomic(0));
+ GC_free(GC_malloc(0));
+ GC_free(GC_malloc_atomic(0));
+ /* Repeated list reversal test. */
+ reverse_test();
+# ifdef PRINTSTATS
+ GC_printf("-------------Finished reverse_test\n");
+# endif
+# ifndef DBG_HDRS_ALL
+ typed_test();
+# ifdef PRINTSTATS
+ GC_printf("-------------Finished typed_test\n");
+# endif
+# endif /* DBG_HDRS_ALL */
+ tree_test();
+ LOCK();
+ n_tests++;
+ UNLOCK();
+# if defined(THREADS) && defined(HANDLE_FORK)
+ if (fork() == 0) {
+ GC_gcollect();
+ tiny_reverse_test(0);
+ GC_gcollect();
+ GC_printf("Finished a child process\n");
+ exit(0);
+ }
+# endif
+ /* GC_printf("Finished %x\n", pthread_self()); */
+}
+
+void check_heap_stats()
+{
+ size_t max_heap_sz;
+ int i;
+ int still_live;
+ int late_finalize_count = 0;
+
+# ifdef VERY_SMALL_CONFIG
+ /* these are something of a guess */
+ if (sizeof(char *) > 4) {
+ max_heap_sz = 4500000;
+ } else {
+ max_heap_sz = 2800000;
+ }
+# else
+ if (sizeof(char *) > 4) {
+ max_heap_sz = 19000000;
+ } else {
+ max_heap_sz = 11000000;
+ }
+# endif
+# ifdef GC_DEBUG
+ max_heap_sz *= 2;
+# ifdef SAVE_CALL_CHAIN
+ max_heap_sz *= 3;
+# ifdef SAVE_CALL_COUNT
+ max_heap_sz += max_heap_sz * SAVE_CALL_COUNT/4;
+# endif
+# endif
+# endif
+ /* Garbage collect repeatedly so that all inaccessible objects */
+ /* can be finalized. */
+ while (GC_collect_a_little()) { }
+ for (i = 0; i < 16; i++) {
+ GC_gcollect();
+ late_finalize_count += GC_invoke_finalizers();
+ }
+ (void)GC_printf("Completed %u tests\n", n_tests);
+ (void)GC_printf("Allocated %d collectable objects\n", collectable_count);
+ (void)GC_printf("Allocated %d uncollectable objects\n",
+ uncollectable_count);
+ (void)GC_printf("Allocated %d atomic objects\n", atomic_count);
+ (void)GC_printf("Allocated %d stubborn objects\n", stubborn_count);
+ (void)GC_printf("Finalized %d/%d objects - ",
+ finalized_count, finalizable_count);
+# ifdef FINALIZE_ON_DEMAND
+ if (finalized_count != late_finalize_count) {
+ (void)GC_printf("Demand finalization error\n");
+ FAIL;
+ }
+# endif
+ if (finalized_count > finalizable_count
+ || finalized_count < finalizable_count/2) {
+ (void)GC_printf("finalization is probably broken\n");
+ FAIL;
+ } else {
+ (void)GC_printf("finalization is probably ok\n");
+ }
+ still_live = 0;
+ for (i = 0; i < MAX_FINALIZED; i++) {
+ if (live_indicators[i] != 0) {
+ still_live++;
+ }
+ }
+ i = finalizable_count - finalized_count - still_live;
+ if (0 != i) {
+ GC_printf("%d disappearing links remain and %d more objects "
+ "were not finalized\n", still_live, i);
+ if (i > 10) {
+ GC_printf("\tVery suspicious!\n");
+ } else {
+ GC_printf("\tSlightly suspicious, but probably OK.\n");
+ }
+ }
+ (void)GC_printf("Total number of bytes allocated is %lu\n",
+ (unsigned long)
+ (GC_bytes_allocd + GC_bytes_allocd_before_gc));
+ (void)GC_printf("Final heap size is %lu bytes\n",
+ (unsigned long)GC_get_heap_size());
+ if (GC_bytes_allocd + GC_bytes_allocd_before_gc
+# ifdef VERY_SMALL_CONFIG
+ < 2700000*n_tests) {
+# else
+ < 33500000*n_tests) {
+# endif
+ (void)GC_printf("Incorrect execution - missed some allocations\n");
+ FAIL;
+ }
+ if (GC_get_heap_size() > max_heap_sz*n_tests) {
+ (void)GC_printf("Unexpected heap growth - collector may be broken\n");
+ FAIL;
+ }
+ (void)GC_printf("Collector appears to work\n");
+}
+
+#if defined(MACOS)
+void SetMinimumStack(long minSize)
+{
+ long newApplLimit;
+
+ if (minSize > LMGetDefltStack())
+ {
+ newApplLimit = (long) GetApplLimit()
+ - (minSize - LMGetDefltStack());
+ SetApplLimit((Ptr) newApplLimit);
+ MaxApplZone();
+ }
+}
+
+#define cMinStackSpace (512L * 1024L)
+
+#endif
+
+#ifdef __STDC__
+ void warn_proc(char *msg, GC_word p)
+#else
+ void warn_proc(msg, p)
+ char *msg;
+ GC_word p;
+#endif
+{
+ GC_printf(msg, (unsigned long)p);
+ /*FAIL;*/
+}
+
+
+#if !defined(PCR) \
+ && !defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) \
+ || defined(LINT)
+#if defined(MSWIN32) && !defined(__MINGW32__)
+ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPTSTR cmd, int n)
+#else
+ int main()
+#endif
+{
+# if defined(DJGPP)
+ int dummy;
+# endif
+ n_tests = 0;
+
+# if defined(DJGPP)
+ /* No good way to determine stack base from library; do it */
+ /* manually on this platform. */
+ GC_stackbottom = (void *)(&dummy);
+# endif
+# if defined(MACOS)
+ /* Make sure we have lots and lots of stack space. */
+ SetMinimumStack(cMinStackSpace);
+ /* Cheat and let stdio initialize toolbox for us. */
+ printf("Testing GC Macintosh port.\n");
+# endif
+ GC_INIT(); /* Only needed on a few platforms. */
+ (void) GC_set_warn_proc(warn_proc);
+# if (defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(GWW_VDB)) \
+ && !defined(MAKE_BACK_GRAPH) && !defined(NO_INCREMENTAL)
+ GC_enable_incremental();
+ (void) GC_printf("Switched to incremental mode\n");
+# if defined(MPROTECT_VDB)
+ (void)GC_printf("Emulating dirty bits with mprotect/signals\n");
+# else
+# ifdef PROC_VDB
+ (void)GC_printf("Reading dirty bits from /proc\n");
+# else
+ (void)GC_printf("Using DEFAULT_VDB dirty bit implementation\n");
+# endif
+# endif
+# endif
+ run_one_test();
+ check_heap_stats();
+# ifndef MSWINCE
+ (void)fflush(stdout);
+# endif
+# ifdef LINT
+ /* Entry points we should be testing, but aren't. */
+ /* Some can be tested by defining GC_DEBUG at the top of this file */
+ /* This is a bit SunOS4 specific. */
+ GC_noop(GC_expand_hp, GC_add_roots, GC_clear_roots,
+ GC_register_disappearing_link,
+ GC_register_finalizer_ignore_self,
+ GC_debug_register_displacement,
+ GC_print_obj, GC_debug_change_stubborn,
+ GC_debug_end_stubborn_change, GC_debug_malloc_uncollectable,
+ GC_debug_free, GC_debug_realloc, GC_generic_malloc_words_small,
+ GC_init, GC_make_closure, GC_debug_invoke_finalizer,
+ GC_page_was_ever_dirty, GC_is_fresh,
+ GC_malloc_ignore_off_page, GC_malloc_atomic_ignore_off_page,
+ GC_set_max_heap_size, GC_get_bytes_since_gc,
+ GC_get_total_bytes, GC_pre_incr, GC_post_incr);
+# endif
+# ifdef MSWIN32
+ GC_win32_free_heap();
+# endif
+ return(0);
+}
+# endif
+
+#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
+
+DWORD __stdcall thr_run_one_test(void *arg)
+{
+ run_one_test();
+ return 0;
+}
+
+#ifdef MSWINCE
+HANDLE win_created_h;
+HWND win_handle;
+
+LRESULT CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT ret = 0;
+ switch (uMsg) {
+ case WM_HIBERNATE:
+ GC_printf("Received WM_HIBERNATE, calling GC_gcollect\n");
+ GC_gcollect();
+ break;
+ case WM_CLOSE:
+ GC_printf("Received WM_CLOSE, closing window\n");
+ DestroyWindow(hwnd);
+ break;
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+ default:
+ ret = DefWindowProc(hwnd, uMsg, wParam, lParam);
+ break;
+ }
+ return ret;
+}
+
+DWORD __stdcall thr_window(void *arg)
+{
+ WNDCLASS win_class = {
+ CS_NOCLOSE,
+ window_proc,
+ 0,
+ 0,
+ GetModuleHandle(NULL),
+ NULL,
+ NULL,
+ (HBRUSH)(COLOR_APPWORKSPACE+1),
+ NULL,
+ L"GCtestWindow"
+ };
+ MSG msg;
+
+ if (!RegisterClass(&win_class))
+ FAIL;
+
+ win_handle = CreateWindowEx(
+ 0,
+ L"GCtestWindow",
+ L"GCtest",
+ 0,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL,
+ NULL,
+ GetModuleHandle(NULL),
+ NULL);
+
+ if (win_handle == NULL)
+ FAIL;
+
+ SetEvent(win_created_h);
+
+ ShowWindow(win_handle, SW_SHOW);
+ UpdateWindow(win_handle);
+
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ return 0;
+}
+#endif
+
+#define NTEST 2
+
+# ifdef MSWINCE
+int APIENTRY GC_WinMain(HINSTANCE instance, HINSTANCE prev, LPWSTR cmd, int n)
+# else
+int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int n)
+# endif
+{
+# if NTEST > 0
+ HANDLE h[NTEST];
+ int i;
+# endif
+# ifdef MSWINCE
+ HANDLE win_thr_h;
+# endif
+ DWORD thread_id;
+
+# ifdef GC_DLL
+ GC_use_DllMain(); /* Test with implicit thread registration if possible. */
+ GC_printf("Using DllMain to track threads\n");
+# endif
+ GC_INIT();
+# ifndef NO_INCREMENTAL
+ GC_enable_incremental();
+# endif
+ InitializeCriticalSection(&incr_cs);
+ (void) GC_set_warn_proc(warn_proc);
+# ifdef MSWINCE
+ win_created_h = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (win_created_h == (HANDLE)NULL) {
+ (void)GC_printf("Event creation failed %\n", GetLastError());
+ FAIL;
+ }
+ win_thr_h = GC_CreateThread(NULL, 0, thr_window, 0, 0, &thread_id);
+ if (win_thr_h == (HANDLE)NULL) {
+ (void)GC_printf("Thread creation failed %d\n", GetLastError());
+ FAIL;
+ }
+ if (WaitForSingleObject(win_created_h, INFINITE) != WAIT_OBJECT_0)
+ FAIL;
+ CloseHandle(win_created_h);
+# endif
+# if NTEST > 0
+ for (i = 0; i < NTEST; i++) {
+ h[i] = GC_CreateThread(NULL, 0, thr_run_one_test, 0, 0, &thread_id);
+ if (h[i] == (HANDLE)NULL) {
+ (void)GC_printf("Thread creation failed %d\n", GetLastError());
+ FAIL;
+ }
+ }
+# endif /* NTEST > 0 */
+ run_one_test();
+# if NTEST > 0
+ for (i = 0; i < NTEST; i++) {
+ if (WaitForSingleObject(h[i], INFINITE) != WAIT_OBJECT_0) {
+ (void)GC_printf("Thread wait failed %d\n", GetLastError());
+ FAIL;
+ }
+ }
+# endif /* NTEST > 0 */
+# ifdef MSWINCE
+ PostMessage(win_handle, WM_CLOSE, 0, 0);
+ if (WaitForSingleObject(win_thr_h, INFINITE) != WAIT_OBJECT_0)
+ FAIL;
+# endif
+ check_heap_stats();
+ return(0);
+}
+
+#endif /* GC_WIN32_THREADS */
+
+
+#ifdef PCR
+test()
+{
+ PCR_Th_T * th1;
+ PCR_Th_T * th2;
+ int code;
+
+ n_tests = 0;
+ /* GC_enable_incremental(); */
+ (void) GC_set_warn_proc(warn_proc);
+ th1 = PCR_Th_Fork(run_one_test, 0);
+ th2 = PCR_Th_Fork(run_one_test, 0);
+ run_one_test();
+ if (PCR_Th_T_Join(th1, &code, NIL, PCR_allSigsBlocked, PCR_waitForever)
+ != PCR_ERes_okay || code != 0) {
+ (void)GC_printf("Thread 1 failed\n");
+ }
+ if (PCR_Th_T_Join(th2, &code, NIL, PCR_allSigsBlocked, PCR_waitForever)
+ != PCR_ERes_okay || code != 0) {
+ (void)GC_printf("Thread 2 failed\n");
+ }
+ check_heap_stats();
+ return(0);
+}
+#endif
+
+#if defined(GC_PTHREADS)
+void * thr_run_one_test(void * arg)
+{
+ run_one_test();
+ return(0);
+}
+
+#ifdef GC_DEBUG
+# define GC_free GC_debug_free
+#endif
+
+int main()
+{
+ pthread_t th1;
+ pthread_t th2;
+ pthread_attr_t attr;
+ int code;
+# ifdef GC_IRIX_THREADS
+ /* Force a larger stack to be preallocated */
+ /* Since the initial cant always grow later. */
+ *((volatile char *)&code - 1024*1024) = 0; /* Require 1 Mb */
+# endif /* GC_IRIX_THREADS */
+# if defined(GC_HPUX_THREADS)
+ /* Default stack size is too small, especially with the 64 bit ABI */
+ /* Increase it. */
+ if (pthread_default_stacksize_np(1024*1024, 0) != 0) {
+ (void)GC_printf("pthread_default_stacksize_np failed.\n");
+ }
+# endif /* GC_HPUX_THREADS */
+# ifdef PTW32_STATIC_LIB
+ pthread_win32_process_attach_np ();
+ pthread_win32_thread_attach_np ();
+# endif
+ GC_INIT();
+
+ pthread_attr_init(&attr);
+# if defined(GC_IRIX_THREADS) || defined(GC_FREEBSD_THREADS) \
+ || defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)
+ pthread_attr_setstacksize(&attr, 1000000);
+# endif
+ n_tests = 0;
+# if (defined(MPROTECT_VDB)) \
+ && !defined(PARALLEL_MARK) &&!defined(REDIRECT_MALLOC) \
+ && !defined(MAKE_BACK_GRAPH) && !defined(USE_PROC_FOR_LIBRARIES) \
+ && !defined(NO_INCREMENTAL)
+ GC_enable_incremental();
+ (void) GC_printf("Switched to incremental mode\n");
+# if defined(MPROTECT_VDB)
+ (void)GC_printf("Emulating dirty bits with mprotect/signals\n");
+# else
+# ifdef PROC_VDB
+ (void)GC_printf("Reading dirty bits from /proc\n");
+# else
+ (void)GC_printf("Using DEFAULT_VDB dirty bit implementation\n");
+# endif
+# endif
+# endif
+ (void) GC_set_warn_proc(warn_proc);
+ if ((code = pthread_key_create(&fl_key, 0)) != 0) {
+ (void)GC_printf("Key creation failed %d\n", code);
+ FAIL;
+ }
+ if ((code = pthread_create(&th1, &attr, thr_run_one_test, 0)) != 0) {
+ (void)GC_printf("Thread 1 creation failed %d\n", code);
+ FAIL;
+ }
+ if ((code = pthread_create(&th2, &attr, thr_run_one_test, 0)) != 0) {
+ (void)GC_printf("Thread 2 creation failed %d\n", code);
+ FAIL;
+ }
+ run_one_test();
+ if ((code = pthread_join(th1, 0)) != 0) {
+ (void)GC_printf("Thread 1 failed %d\n", code);
+ FAIL;
+ }
+ if (pthread_join(th2, 0) != 0) {
+ (void)GC_printf("Thread 2 failed %d\n", code);
+ FAIL;
+ }
+ check_heap_stats();
+ (void)fflush(stdout);
+ pthread_attr_destroy(&attr);
+ GC_printf("Completed %d collections\n", GC_gc_no);
+# ifdef PTW32_STATIC_LIB
+ pthread_win32_thread_detach_np ();
+ pthread_win32_process_detach_np ();
+# endif
+ return(0);
+}
+#endif /* GC_PTHREADS */
diff --git a/tools/build/v2/engine/boehm_gc/tests/test_cpp.cc b/tools/build/v2/engine/boehm_gc/tests/test_cpp.cc
new file mode 100644
index 0000000000..9bf53de811
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/tests/test_cpp.cc
@@ -0,0 +1,292 @@
+/****************************************************************************
+Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+
+THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+
+Permission is hereby granted to use or copy this program for any
+purpose, provided the above notices are retained on all copies.
+Permission to modify the code and to distribute modified code is
+granted, provided the above notices are retained, and a notice that
+the code was modified is included with the above copyright notice.
+****************************************************************************
+Last modified on Mon Jul 10 21:06:03 PDT 1995 by ellis
+ modified on December 20, 1994 7:27 pm PST by boehm
+
+usage: test_cpp number-of-iterations
+
+This program tries to test the specific C++ functionality provided by
+gc_c++.h that isn't tested by the more general test routines of the
+collector.
+
+A recommended value for number-of-iterations is 10, which will take a
+few minutes to complete.
+
+***************************************************************************/
+
+#include "gc_cpp.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define USE_STD_ALLOCATOR
+#ifdef USE_STD_ALLOCATOR
+# include "gc_allocator.h"
+#elif __GNUC__
+# include "new_gc_alloc.h"
+#else
+# include "gc_alloc.h"
+#endif
+extern "C" {
+# include "private/gcconfig.h"
+ GC_API void GC_printf(const char *format, ...);
+ /* Use GC private output to reach the same log file. */
+ /* Don't include gc_priv.h, since that may include Windows system */
+ /* header files that don't take kindly to this context. */
+}
+#ifdef MSWIN32
+# include <windows.h>
+#endif
+#ifdef GC_NAME_CONFLICT
+# define USE_GC UseGC
+ struct foo * GC;
+#else
+# define USE_GC GC
+#endif
+
+
+#define my_assert( e ) \
+ if (! (e)) { \
+ GC_printf( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
+ __LINE__ ); \
+ exit( 1 ); }
+
+
+class A {public:
+ /* An uncollectable class. */
+
+ A( int iArg ): i( iArg ) {}
+ void Test( int iArg ) {
+ my_assert( i == iArg );}
+ int i;};
+
+
+class B: public gc, public A {public:
+ /* A collectable class. */
+
+ B( int j ): A( j ) {}
+ ~B() {
+ my_assert( deleting );}
+ static void Deleting( int on ) {
+ deleting = on;}
+ static int deleting;};
+
+int B::deleting = 0;
+
+
+class C: public gc_cleanup, public A {public:
+ /* A collectable class with cleanup and virtual multiple inheritance. */
+
+ C( int levelArg ): A( levelArg ), level( levelArg ) {
+ nAllocated++;
+ if (level > 0) {
+ left = new C( level - 1 );
+ right = new C( level - 1 );}
+ else {
+ left = right = 0;}}
+ ~C() {
+ this->A::Test( level );
+ nFreed++;
+ my_assert( level == 0 ?
+ left == 0 && right == 0 :
+ level == left->level + 1 && level == right->level + 1 );
+ left = right = 0;
+ level = -123456;}
+ static void Test() {
+ my_assert( nFreed <= nAllocated && nFreed >= .8 * nAllocated );}
+
+ static int nFreed;
+ static int nAllocated;
+ int level;
+ C* left;
+ C* right;};
+
+int C::nFreed = 0;
+int C::nAllocated = 0;
+
+
+class D: public gc {public:
+ /* A collectable class with a static member function to be used as
+ an explicit clean-up function supplied to ::new. */
+
+ D( int iArg ): i( iArg ) {
+ nAllocated++;}
+ static void CleanUp( void* obj, void* data ) {
+ D* self = (D*) obj;
+ nFreed++;
+ my_assert( self->i == (int) (GC_word) data );}
+ static void Test() {
+ my_assert( nFreed >= .8 * nAllocated );}
+
+ int i;
+ static int nFreed;
+ static int nAllocated;};
+
+int D::nFreed = 0;
+int D::nAllocated = 0;
+
+
+class E: public gc_cleanup {public:
+ /* A collectable class with clean-up for use by F. */
+
+ E() {
+ nAllocated++;}
+ ~E() {
+ nFreed++;}
+
+ static int nFreed;
+ static int nAllocated;};
+
+int E::nFreed = 0;
+int E::nAllocated = 0;
+
+
+class F: public E {public:
+ /* A collectable class with clean-up, a base with clean-up, and a
+ member with clean-up. */
+
+ F() {
+ nAllocated++;}
+ ~F() {
+ nFreed++;}
+ static void Test() {
+ my_assert( nFreed >= .8 * nAllocated );
+ my_assert( 2 * nFreed == E::nFreed );}
+
+ E e;
+ static int nFreed;
+ static int nAllocated;};
+
+int F::nFreed = 0;
+int F::nAllocated = 0;
+
+
+GC_word Disguise( void* p ) {
+ return ~ (GC_word) p;}
+
+void* Undisguise( GC_word i ) {
+ return (void*) ~ i;}
+
+
+#ifdef MSWIN32
+int APIENTRY WinMain(
+ HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow )
+{
+ int argc;
+ char* argv[ 3 ];
+
+ for (argc = 1; argc < sizeof( argv ) / sizeof( argv[ 0 ] ); argc++) {
+ argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" );
+ if (0 == argv[ argc ]) break;}
+
+#else
+# ifdef MACOS
+ int main() {
+# else
+ int main( int argc, char* argv[] ) {
+# endif
+#endif
+
+ GC_INIT();
+
+# if defined(MACOS) // MacOS
+ char* argv_[] = {"test_cpp", "10"}; // doesn't
+ argv = argv_; // have a
+ argc = sizeof(argv_)/sizeof(argv_[0]); // commandline
+# endif
+ int i, iters, n;
+# ifdef USE_STD_ALLOCATOR
+ int *x = gc_allocator<int>().allocate(1);
+ int **xptr = traceable_allocator<int *>().allocate(1);
+# else
+# ifdef __GNUC__
+ int *x = (int *)gc_alloc::allocate(sizeof(int));
+# else
+ int *x = (int *)alloc::allocate(sizeof(int));
+# endif
+# endif
+ *x = 29;
+# ifdef USE_STD_ALLOCATOR
+ *xptr = x;
+ x = 0;
+# endif
+ if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
+ GC_printf( "usage: test_cpp number-of-iterations\nAssuming 10 iters\n" );
+ n = 10;}
+
+ for (iters = 1; iters <= n; iters++) {
+ GC_printf( "Starting iteration %d\n", iters );
+
+ /* Allocate some uncollectable As and disguise their pointers.
+ Later we'll check to see if the objects are still there. We're
+ checking to make sure these objects really are uncollectable. */
+ GC_word as[ 1000 ];
+ GC_word bs[ 1000 ];
+ for (i = 0; i < 1000; i++) {
+ as[ i ] = Disguise( new (NoGC) A( i ) );
+ bs[ i ] = Disguise( new (NoGC) B( i ) );}
+
+ /* Allocate a fair number of finalizable Cs, Ds, and Fs.
+ Later we'll check to make sure they've gone away. */
+ for (i = 0; i < 1000; i++) {
+ C* c = new C( 2 );
+ C c1( 2 ); /* stack allocation should work too */
+ D* d = ::new (USE_GC, D::CleanUp, (void*)(GC_word)i) D( i );
+ F* f = new F;
+ if (0 == i % 10) delete c;}
+
+ /* Allocate a very large number of collectable As and Bs and
+ drop the references to them immediately, forcing many
+ collections. */
+ for (i = 0; i < 1000000; i++) {
+ A* a = new (USE_GC) A( i );
+ B* b = new B( i );
+ b = new (USE_GC) B( i );
+ if (0 == i % 10) {
+ B::Deleting( 1 );
+ delete b;
+ B::Deleting( 0 );}
+# ifdef FINALIZE_ON_DEMAND
+ GC_invoke_finalizers();
+# endif
+ }
+
+ /* Make sure the uncollectable As and Bs are still there. */
+ for (i = 0; i < 1000; i++) {
+ A* a = (A*) Undisguise( as[ i ] );
+ B* b = (B*) Undisguise( bs[ i ] );
+ a->Test( i );
+ delete a;
+ b->Test( i );
+ B::Deleting( 1 );
+ delete b;
+ B::Deleting( 0 );
+# ifdef FINALIZE_ON_DEMAND
+ GC_invoke_finalizers();
+# endif
+
+ }
+
+ /* Make sure most of the finalizable Cs, Ds, and Fs have
+ gone away. */
+ C::Test();
+ D::Test();
+ F::Test();}
+
+# ifdef USE_STD_ALLOCATOR
+ x = *xptr;
+# endif
+ my_assert (29 == x[0]);
+ GC_printf( "The test appears to have succeeded.\n" );
+ return( 0 );}
+
+
diff --git a/tools/build/v2/engine/boehm_gc/tests/tests.am b/tools/build/v2/engine/boehm_gc/tests/tests.am
new file mode 100644
index 0000000000..aedac1fa67
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/tests/tests.am
@@ -0,0 +1,57 @@
+#
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose, provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+
+
+## FIXME: trace_test don't works on macosx 10.3
+## gcc -g -O2 -o .libs/tracetest trace_test.o ../.libs/libgc.dylib -lpthread
+## ld: Undefined symbols:
+## _GC_generate_random_backtrace
+
+
+# Common libs to _LDADD for all tests.
+test_ldadd = $(top_builddir)/libgc.la $(EXTRA_TEST_LIBS)
+
+
+TESTS += gctest$(EXEEXT)
+check_PROGRAMS += gctest
+gctest_SOURCES = tests/test.c
+gctest_LDADD = $(test_ldadd)
+gctest_DEPENDENCIES = $(top_builddir)/libgc.la
+
+TESTS += leaktest$(EXEEXT)
+check_PROGRAMS += leaktest
+leaktest_SOURCES = tests/leak_test.c
+leaktest_LDADD = $(test_ldadd)
+
+TESTS += middletest$(EXEEXT)
+check_PROGRAMS += middletest
+middletest_SOURCES = tests/middle.c
+middletest_LDADD = $(test_ldadd)
+
+#TESTS += tracetest$(EXEEXT)
+#check_PROGRAMS += tracetest
+#tracetest_SOURCES = tests/trace_test.c
+#tracetest_LDADD = $(test_ldadd)
+
+if THREADS
+TESTS += threadleaktest$(EXEEXT)
+check_PROGRAMS += threadleaktest
+threadleaktest_SOURCES = tests/thread_leak_test.c
+threadleaktest_LDADD = $(test_ldadd)
+endif
+
+if CPLUSPLUS
+TESTS += test_cpp$(EXEEXT)
+check_PROGRAMS += test_cpp
+test_cpp_SOURCES = tests/test_cpp.cc
+test_cpp_LDADD = libgccpp.la $(test_ldadd)
+endif
+
diff --git a/tools/build/v2/engine/boehm_gc/tests/thread_leak_test.c b/tools/build/v2/engine/boehm_gc/tests/thread_leak_test.c
new file mode 100644
index 0000000000..f2c15e9671
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/tests/thread_leak_test.c
@@ -0,0 +1,45 @@
+#ifndef GC_THREADS
+# define GC_THREADS
+#endif /* GC_THREADS */
+#include "leak_detector.h"
+#include <pthread.h>
+#include <stdio.h>
+
+void * test(void * arg) {
+ int *p[10];
+ int i;
+ GC_find_leak = 1; /* for new collect versions not compiled */
+ /* with -DFIND_LEAK. */
+ for (i = 0; i < 10; ++i) {
+ p[i] = malloc(sizeof(int)+i);
+ }
+ CHECK_LEAKS();
+ for (i = 1; i < 10; ++i) {
+ free(p[i]);
+ }
+ return 0;
+}
+
+#define NTHREADS 5
+
+main() {
+ int i;
+ pthread_t t[NTHREADS];
+ int code;
+
+ GC_INIT();
+ for (i = 0; i < NTHREADS; ++i) {
+ if ((code = pthread_create(t + i, 0, test, 0)) != 0) {
+ printf("Thread creation failed %d\n", code);
+ }
+ }
+ for (i = 0; i < NTHREADS; ++i) {
+ if ((code = pthread_join(t[i], 0)) != 0) {
+ printf("Thread join failed %lu\n", code);
+ }
+ }
+ CHECK_LEAKS();
+ CHECK_LEAKS();
+ CHECK_LEAKS();
+ return 0;
+}
diff --git a/tools/build/v2/engine/boehm_gc/thread_local_alloc.c b/tools/build/v2/engine/boehm_gc/thread_local_alloc.c
new file mode 100644
index 0000000000..f747b35570
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/thread_local_alloc.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2000-2005 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+#include "private/gc_priv.h"
+
+# if defined(THREAD_LOCAL_ALLOC)
+
+#include "private/thread_local_alloc.h"
+#include "gc_inline.h"
+
+# include <stdlib.h>
+
+#if defined(USE_COMPILER_TLS)
+ __thread
+#elif defined(USE_WIN32_COMPILER_TLS)
+ __declspec(thread)
+#endif
+GC_key_t GC_thread_key;
+
+static GC_bool keys_initialized;
+
+/* Return a single nonempty freelist fl to the global one pointed to */
+/* by gfl. */
+
+static void return_single_freelist(void *fl, void **gfl)
+{
+ void *q, **qptr;
+
+ if (*gfl == 0) {
+ *gfl = fl;
+ } else {
+ GC_ASSERT(GC_size(fl) == GC_size(*gfl));
+ /* Concatenate: */
+ for (qptr = &(obj_link(fl)), q = *qptr;
+ (word)q >= HBLKSIZE; qptr = &(obj_link(q)), q = *qptr);
+ GC_ASSERT(0 == q);
+ *qptr = *gfl;
+ *gfl = fl;
+ }
+}
+
+/* Recover the contents of the freelist array fl into the global one gfl.*/
+/* We hold the allocator lock. */
+static void return_freelists(void **fl, void **gfl)
+{
+ int i;
+
+ for (i = 1; i < TINY_FREELISTS; ++i) {
+ if ((word)(fl[i]) >= HBLKSIZE) {
+ return_single_freelist(fl[i], gfl+i);
+ }
+ /* Clear fl[i], since the thread structure may hang around. */
+ /* Do it in a way that is likely to trap if we access it. */
+ fl[i] = (ptr_t)HBLKSIZE;
+ }
+ /* The 0 granule freelist really contains 1 granule objects. */
+# ifdef GC_GCJ_SUPPORT
+ if (fl[0] == ERROR_FL) return;
+# endif
+ if ((word)(fl[0]) >= HBLKSIZE) {
+ return_single_freelist(fl[0], gfl+1);
+ }
+}
+
+/* Each thread structure must be initialized. */
+/* This call must be made from the new thread. */
+/* Caller holds allocation lock. */
+void GC_init_thread_local(GC_tlfs p)
+{
+ int i;
+
+ if (!keys_initialized) {
+ if (0 != GC_key_create(&GC_thread_key, 0)) {
+ ABORT("Failed to create key for local allocator");
+ }
+ keys_initialized = TRUE;
+ }
+ if (0 != GC_setspecific(GC_thread_key, p)) {
+ ABORT("Failed to set thread specific allocation pointers");
+ }
+ for (i = 1; i < TINY_FREELISTS; ++i) {
+ p -> ptrfree_freelists[i] = (void *)1;
+ p -> normal_freelists[i] = (void *)1;
+# ifdef GC_GCJ_SUPPORT
+ p -> gcj_freelists[i] = (void *)1;
+# endif
+ }
+ /* Set up the size 0 free lists. */
+ /* We now handle most of them like regular free lists, to ensure */
+ /* That explicit deallocation works. However, allocation of a */
+ /* size 0 "gcj" object is always an error. */
+ p -> ptrfree_freelists[0] = (void *)1;
+ p -> normal_freelists[0] = (void *)1;
+# ifdef GC_GCJ_SUPPORT
+ p -> gcj_freelists[0] = ERROR_FL;
+# endif
+}
+
+#ifdef GC_GCJ_SUPPORT
+ extern void ** GC_gcjobjfreelist;
+#endif
+
+/* We hold the allocator lock. */
+void GC_destroy_thread_local(GC_tlfs p)
+{
+ /* We currently only do this from the thread itself or from */
+ /* the fork handler for a child process. */
+# ifndef HANDLE_FORK
+ GC_ASSERT(GC_getspecific(GC_thread_key) == (void *)p);
+# endif
+ return_freelists(p -> ptrfree_freelists, GC_aobjfreelist);
+ return_freelists(p -> normal_freelists, GC_objfreelist);
+# ifdef GC_GCJ_SUPPORT
+ return_freelists(p -> gcj_freelists, GC_gcjobjfreelist);
+# endif
+}
+
+#if defined(GC_ASSERTIONS) && defined(GC_PTHREADS) && !defined(CYGWIN32) \
+ && !defined(GC_WIN32_PTHREADS)
+# include <pthread.h>
+ extern char * GC_lookup_thread(pthread_t id);
+#endif
+
+#if defined(GC_ASSERTIONS) && defined(GC_WIN32_THREADS)
+ extern char * GC_lookup_thread(int id);
+#endif
+
+void * GC_malloc(size_t bytes)
+{
+ size_t granules = ROUNDED_UP_GRANULES(bytes);
+ void *tsd;
+ void *result;
+ void **tiny_fl;
+
+# if defined(REDIRECT_MALLOC) && !defined(USE_PTHREAD_SPECIFIC)
+ GC_key_t k = GC_thread_key;
+ if (EXPECT(0 == k, 0)) {
+ /* We haven't yet run GC_init_parallel. That means */
+ /* we also aren't locking, so this is fairly cheap. */
+ return GC_core_malloc(bytes);
+ }
+ tsd = GC_getspecific(k);
+# else
+ GC_ASSERT(GC_is_initialized);
+ tsd = GC_getspecific(GC_thread_key);
+# endif
+# if defined(REDIRECT_MALLOC) && defined(USE_PTHREAD_SPECIFIC)
+ if (EXPECT(NULL == tsd, 0)) {
+ return GC_core_malloc(bytes);
+ }
+# endif
+# ifdef GC_ASSERTIONS
+ /* We can't check tsd correctly, since we don't have access to */
+ /* the right declarations. But we can check that it's close. */
+ LOCK();
+ {
+# if defined(GC_WIN32_THREADS)
+ char * me = (char *)GC_lookup_thread_inner(GetCurrentThreadId());
+# else
+ char * me = GC_lookup_thread(pthread_self());
+# endif
+ GC_ASSERT((char *)tsd > me && (char *)tsd < me + 1000);
+ }
+ UNLOCK();
+# endif
+ tiny_fl = ((GC_tlfs)tsd) -> normal_freelists;
+ GC_FAST_MALLOC_GRANS(result, granules, tiny_fl, DIRECT_GRANULES,
+ NORMAL, GC_core_malloc(bytes), obj_link(result)=0);
+ return result;
+}
+
+void * GC_malloc_atomic(size_t bytes)
+{
+ size_t granules = ROUNDED_UP_GRANULES(bytes);
+ void *result;
+ void **tiny_fl;
+
+ GC_ASSERT(GC_is_initialized);
+ tiny_fl = ((GC_tlfs)GC_getspecific(GC_thread_key))
+ -> ptrfree_freelists;
+ GC_FAST_MALLOC_GRANS(result, bytes, tiny_fl, DIRECT_GRANULES,
+ PTRFREE, GC_core_malloc_atomic(bytes), 0/* no init */);
+ return result;
+}
+
+#ifdef GC_GCJ_SUPPORT
+
+#include "include/gc_gcj.h"
+
+#ifdef GC_ASSERTIONS
+ extern GC_bool GC_gcj_malloc_initialized;
+#endif
+
+extern int GC_gcj_kind;
+
+/* Gcj-style allocation without locks is extremely tricky. The */
+/* fundamental issue is that we may end up marking a free list, which */
+/* has freelist links instead of "vtable" pointers. That is usually */
+/* OK, since the next object on the free list will be cleared, and */
+/* will thus be interpreted as containg a zero descriptor. That's fine */
+/* if the object has not yet been initialized. But there are */
+/* interesting potential races. */
+/* In the case of incremental collection, this seems hopeless, since */
+/* the marker may run asynchronously, and may pick up the pointer to */
+/* the next freelist entry (which it thinks is a vtable pointer), get */
+/* suspended for a while, and then see an allocated object instead */
+/* of the vtable. This made be avoidable with either a handshake with */
+/* the collector or, probably more easily, by moving the free list */
+/* links to the second word of each object. The latter isn't a */
+/* universal win, since on architecture like Itanium, nonzero offsets */
+/* are not necessarily free. And there may be cache fill order issues. */
+/* For now, we punt with incremental GC. This probably means that */
+/* incremental GC should be enabled before we fork a second thread. */
+void * GC_gcj_malloc(size_t bytes,
+ void * ptr_to_struct_containing_descr)
+{
+ if (GC_EXPECT(GC_incremental, 0)) {
+ return GC_core_gcj_malloc(bytes, ptr_to_struct_containing_descr);
+ } else {
+ size_t granules = ROUNDED_UP_GRANULES(bytes);
+ void *result;
+ void **tiny_fl = ((GC_tlfs)GC_getspecific(GC_thread_key))
+ -> gcj_freelists;
+ GC_ASSERT(GC_gcj_malloc_initialized);
+ GC_FAST_MALLOC_GRANS(result, bytes, tiny_fl, DIRECT_GRANULES,
+ GC_gcj_kind,
+ GC_core_gcj_malloc(bytes,
+ ptr_to_struct_containing_descr),
+ {AO_compiler_barrier();
+ *(void **)result = ptr_to_struct_containing_descr;});
+ /* This forces the initialization of the "method ptr". */
+ /* This is necessary to ensure some very subtle properties */
+ /* required if a GC is run in the middle of such an allocation. */
+ /* Here we implicitly also assume atomicity for the free list. */
+ /* and method pointer assignments. */
+ /* We must update the freelist before we store the pointer. */
+ /* Otherwise a GC at this point would see a corrupted */
+ /* free list. */
+ /* A real memory barrier is not needed, since the */
+ /* action of stopping this thread will cause prior writes */
+ /* to complete. */
+ /* We assert that any concurrent marker will stop us. */
+ /* Thus it is impossible for a mark procedure to see the */
+ /* allocation of the next object, but to see this object */
+ /* still containing a free list pointer. Otherwise the */
+ /* marker, by misinterpreting the freelist link as a vtable */
+ /* pointer, might find a random "mark descriptor" in the next */
+ /* object. */
+ return result;
+ }
+}
+
+#endif /* GC_GCJ_SUPPORT */
+
+/* The thread support layer must arrange to mark thread-local */
+/* free lists explicitly, since the link field is often */
+/* invisible to the marker. It knows hoe to find all threads; */
+/* we take care of an individual thread freelist structure. */
+void GC_mark_thread_local_fls_for(GC_tlfs p)
+{
+ ptr_t q;
+ int j;
+
+ for (j = 1; j < TINY_FREELISTS; ++j) {
+ q = p -> ptrfree_freelists[j];
+ if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
+ q = p -> normal_freelists[j];
+ if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
+# ifdef GC_GCJ_SUPPORT
+ q = p -> gcj_freelists[j];
+ if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
+# endif /* GC_GCJ_SUPPORT */
+ }
+}
+
+#if defined(GC_ASSERTIONS)
+ /* Check that all thread-local free-lists in p are completely marked. */
+ void GC_check_tls_for(GC_tlfs p)
+ {
+ ptr_t q;
+ int j;
+
+ for (j = 1; j < TINY_FREELISTS; ++j) {
+ q = p -> ptrfree_freelists[j];
+ if ((word)q > HBLKSIZE) GC_check_fl_marks(q);
+ q = p -> normal_freelists[j];
+ if ((word)q > HBLKSIZE) GC_check_fl_marks(q);
+# ifdef GC_GCJ_SUPPORT
+ q = p -> gcj_freelists[j];
+ if ((word)q > HBLKSIZE) GC_check_fl_marks(q);
+# endif /* GC_GCJ_SUPPORT */
+ }
+ }
+#endif /* GC_ASSERTIONS */
+
+# else /* !THREAD_LOCAL_ALLOC */
+
+# define GC_destroy_thread_local(t)
+
+# endif /* !THREAD_LOCAL_ALLOC */
+
diff --git a/tools/build/v2/engine/boehm_gc/threadlibs.c b/tools/build/v2/engine/boehm_gc/threadlibs.c
new file mode 100644
index 0000000000..f2ab58250f
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/threadlibs.c
@@ -0,0 +1,63 @@
+# include "gc_config_macros.h"
+# include "private/gcconfig.h"
+# include <stdio.h>
+
+int main()
+{
+# if defined(GC_USE_LD_WRAP)
+ printf("-Wl,--wrap -Wl,dlopen "
+ "-Wl,--wrap -Wl,pthread_create -Wl,--wrap -Wl,pthread_join "
+ "-Wl,--wrap -Wl,pthread_detach "
+ "-Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,sleep\n");
+# endif
+# if defined(GC_LINUX_THREADS) || defined(GC_IRIX_THREADS) \
+ || defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS) \
+ || defined(GC_GNU_THREADS)
+# ifdef GC_USE_DLOPEN_WRAP
+ printf("-ldl ");
+# endif
+ printf("-lpthread\n");
+# endif
+# if defined(GC_FREEBSD_THREADS)
+# ifdef GC_USE_DLOPEN_WRAP
+ printf("-ldl ");
+# endif
+# if (__FREEBSD_version >= 500000)
+ printf("-lpthread\n");
+# else
+ printf("-pthread\n");
+# endif
+# endif
+# if defined(GC_NETBSD_THREADS)
+ printf("-lpthread -lrt\n");
+# endif
+
+# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
+ printf("-lpthread -lrt\n");
+# endif
+# if defined(GC_SOLARIS_THREADS)
+ printf("-lthread -lposix4\n");
+ /* Is this right for recent versions? */
+# endif
+# if defined(GC_WIN32_THREADS) && defined(CYGWIN32)
+ printf("-lpthread\n");
+# endif
+# if defined(GC_WIN32_PTHREADS)
+# ifdef PTW32_STATIC_LIB
+ /* assume suffix s for static version of the win32 pthread library */
+ printf("-lpthreadGC2s -lws2_32\n");
+# else
+ printf("-lpthreadGC2\n");
+# endif
+# endif
+# if defined(GC_OSF1_THREADS)
+ printf("-pthread -lrt"); /* DOB: must be -pthread, not -lpthread */
+# endif
+ /* You need GCC 3.0.3 to build this one! */
+ /* DG/UX native gcc doesnt know what "-pthread" is */
+# if defined(GC_DGUX386_THREADS)
+ printf("-ldl -pthread\n");
+# endif
+ return 0;
+}
+
diff --git a/tools/build/v2/engine/boehm_gc/typd_mlc.c b/tools/build/v2/engine/boehm_gc/typd_mlc.c
new file mode 100644
index 0000000000..c46616323d
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/typd_mlc.c
@@ -0,0 +1,722 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * opyright (c) 1999-2000 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+
+/*
+ * Some simple primitives for allocation with explicit type information.
+ * Simple objects are allocated such that they contain a GC_descr at the
+ * end (in the last allocated word). This descriptor may be a procedure
+ * which then examines an extended descriptor passed as its environment.
+ *
+ * Arrays are treated as simple objects if they have sufficiently simple
+ * structure. Otherwise they are allocated from an array kind that supplies
+ * a special mark procedure. These arrays contain a pointer to a
+ * complex_descriptor as their last word.
+ * This is done because the environment field is too small, and the collector
+ * must trace the complex_descriptor.
+ *
+ * Note that descriptors inside objects may appear cleared, if we encounter a
+ * false refrence to an object on a free list. In the GC_descr case, this
+ * is OK, since a 0 descriptor corresponds to examining no fields.
+ * In the complex_descriptor case, we explicitly check for that case.
+ *
+ * MAJOR PARTS OF THIS CODE HAVE NOT BEEN TESTED AT ALL and are not testable,
+ * since they are not accessible through the current interface.
+ */
+
+#include "private/gc_pmark.h"
+#include "gc_typed.h"
+
+# define TYPD_EXTRA_BYTES (sizeof(word) - EXTRA_BYTES)
+
+GC_bool GC_explicit_typing_initialized = FALSE;
+
+int GC_explicit_kind; /* Object kind for objects with indirect */
+ /* (possibly extended) descriptors. */
+
+int GC_array_kind; /* Object kind for objects with complex */
+ /* descriptors and GC_array_mark_proc. */
+
+/* Extended descriptors. GC_typed_mark_proc understands these. */
+/* These are used for simple objects that are larger than what */
+/* can be described by a BITMAP_BITS sized bitmap. */
+typedef struct {
+ word ed_bitmap; /* lsb corresponds to first word. */
+ GC_bool ed_continued; /* next entry is continuation. */
+} ext_descr;
+
+/* Array descriptors. GC_array_mark_proc understands these. */
+/* We may eventually need to add provisions for headers and */
+/* trailers. Hence we provide for tree structured descriptors, */
+/* though we don't really use them currently. */
+typedef union ComplexDescriptor {
+ struct LeafDescriptor { /* Describes simple array */
+ word ld_tag;
+# define LEAF_TAG 1
+ size_t ld_size; /* bytes per element */
+ /* multiple of ALIGNMENT */
+ size_t ld_nelements; /* Number of elements. */
+ GC_descr ld_descriptor; /* A simple length, bitmap, */
+ /* or procedure descriptor. */
+ } ld;
+ struct ComplexArrayDescriptor {
+ word ad_tag;
+# define ARRAY_TAG 2
+ size_t ad_nelements;
+ union ComplexDescriptor * ad_element_descr;
+ } ad;
+ struct SequenceDescriptor {
+ word sd_tag;
+# define SEQUENCE_TAG 3
+ union ComplexDescriptor * sd_first;
+ union ComplexDescriptor * sd_second;
+ } sd;
+} complex_descriptor;
+#define TAG ld.ld_tag
+
+ext_descr * GC_ext_descriptors; /* Points to array of extended */
+ /* descriptors. */
+
+size_t GC_ed_size = 0; /* Current size of above arrays. */
+# define ED_INITIAL_SIZE 100;
+
+size_t GC_avail_descr = 0; /* Next available slot. */
+
+int GC_typed_mark_proc_index; /* Indices of my mark */
+int GC_array_mark_proc_index; /* procedures. */
+
+/* Add a multiword bitmap to GC_ext_descriptors arrays. Return */
+/* starting index. */
+/* Returns -1 on failure. */
+/* Caller does not hold allocation lock. */
+signed_word GC_add_ext_descriptor(GC_bitmap bm, word nbits)
+{
+ size_t nwords = divWORDSZ(nbits + WORDSZ-1);
+ signed_word result;
+ size_t i;
+ word last_part;
+ size_t extra_bits;
+ DCL_LOCK_STATE;
+
+ LOCK();
+ while (GC_avail_descr + nwords >= GC_ed_size) {
+ ext_descr * new;
+ size_t new_size;
+ word ed_size = GC_ed_size;
+
+ UNLOCK();
+ if (ed_size == 0) {
+ new_size = ED_INITIAL_SIZE;
+ } else {
+ new_size = 2 * ed_size;
+ if (new_size > MAX_ENV) return(-1);
+ }
+ new = (ext_descr *) GC_malloc_atomic(new_size * sizeof(ext_descr));
+ if (new == 0) return(-1);
+ LOCK();
+ if (ed_size == GC_ed_size) {
+ if (GC_avail_descr != 0) {
+ BCOPY(GC_ext_descriptors, new,
+ GC_avail_descr * sizeof(ext_descr));
+ }
+ GC_ed_size = new_size;
+ GC_ext_descriptors = new;
+ } /* else another thread already resized it in the meantime */
+ }
+ result = GC_avail_descr;
+ for (i = 0; i < nwords-1; i++) {
+ GC_ext_descriptors[result + i].ed_bitmap = bm[i];
+ GC_ext_descriptors[result + i].ed_continued = TRUE;
+ }
+ last_part = bm[i];
+ /* Clear irrelevant bits. */
+ extra_bits = nwords * WORDSZ - nbits;
+ last_part <<= extra_bits;
+ last_part >>= extra_bits;
+ GC_ext_descriptors[result + i].ed_bitmap = last_part;
+ GC_ext_descriptors[result + i].ed_continued = FALSE;
+ GC_avail_descr += nwords;
+ UNLOCK();
+ return(result);
+}
+
+/* Table of bitmap descriptors for n word long all pointer objects. */
+GC_descr GC_bm_table[WORDSZ/2];
+
+/* Return a descriptor for the concatenation of 2 nwords long objects, */
+/* each of which is described by descriptor. */
+/* The result is known to be short enough to fit into a bitmap */
+/* descriptor. */
+/* Descriptor is a GC_DS_LENGTH or GC_DS_BITMAP descriptor. */
+GC_descr GC_double_descr(GC_descr descriptor, word nwords)
+{
+ if ((descriptor & GC_DS_TAGS) == GC_DS_LENGTH) {
+ descriptor = GC_bm_table[BYTES_TO_WORDS((word)descriptor)];
+ };
+ descriptor |= (descriptor & ~GC_DS_TAGS) >> nwords;
+ return(descriptor);
+}
+
+complex_descriptor * GC_make_sequence_descriptor();
+
+/* Build a descriptor for an array with nelements elements, */
+/* each of which can be described by a simple descriptor. */
+/* We try to optimize some common cases. */
+/* If the result is COMPLEX, then a complex_descr* is returned */
+/* in *complex_d. */
+/* If the result is LEAF, then we built a LeafDescriptor in */
+/* the structure pointed to by leaf. */
+/* The tag in the leaf structure is not set. */
+/* If the result is SIMPLE, then a GC_descr */
+/* is returned in *simple_d. */
+/* If the result is NO_MEM, then */
+/* we failed to allocate the descriptor. */
+/* The implementation knows that GC_DS_LENGTH is 0. */
+/* *leaf, *complex_d, and *simple_d may be used as temporaries */
+/* during the construction. */
+# define COMPLEX 2
+# define LEAF 1
+# define SIMPLE 0
+# define NO_MEM (-1)
+int GC_make_array_descriptor(size_t nelements, size_t size, GC_descr descriptor,
+ GC_descr *simple_d,
+ complex_descriptor **complex_d,
+ struct LeafDescriptor * leaf)
+{
+# define OPT_THRESHOLD 50
+ /* For larger arrays, we try to combine descriptors of adjacent */
+ /* descriptors to speed up marking, and to reduce the amount */
+ /* of space needed on the mark stack. */
+ if ((descriptor & GC_DS_TAGS) == GC_DS_LENGTH) {
+ if (descriptor == (GC_descr)size) {
+ *simple_d = nelements * descriptor;
+ return(SIMPLE);
+ } else if ((word)descriptor == 0) {
+ *simple_d = (GC_descr)0;
+ return(SIMPLE);
+ }
+ }
+ if (nelements <= OPT_THRESHOLD) {
+ if (nelements <= 1) {
+ if (nelements == 1) {
+ *simple_d = descriptor;
+ return(SIMPLE);
+ } else {
+ *simple_d = (GC_descr)0;
+ return(SIMPLE);
+ }
+ }
+ } else if (size <= BITMAP_BITS/2
+ && (descriptor & GC_DS_TAGS) != GC_DS_PROC
+ && (size & (sizeof(word)-1)) == 0) {
+ int result =
+ GC_make_array_descriptor(nelements/2, 2*size,
+ GC_double_descr(descriptor,
+ BYTES_TO_WORDS(size)),
+ simple_d, complex_d, leaf);
+ if ((nelements & 1) == 0) {
+ return(result);
+ } else {
+ struct LeafDescriptor * one_element =
+ (struct LeafDescriptor *)
+ GC_malloc_atomic(sizeof(struct LeafDescriptor));
+
+ if (result == NO_MEM || one_element == 0) return(NO_MEM);
+ one_element -> ld_tag = LEAF_TAG;
+ one_element -> ld_size = size;
+ one_element -> ld_nelements = 1;
+ one_element -> ld_descriptor = descriptor;
+ switch(result) {
+ case SIMPLE:
+ {
+ struct LeafDescriptor * beginning =
+ (struct LeafDescriptor *)
+ GC_malloc_atomic(sizeof(struct LeafDescriptor));
+ if (beginning == 0) return(NO_MEM);
+ beginning -> ld_tag = LEAF_TAG;
+ beginning -> ld_size = size;
+ beginning -> ld_nelements = 1;
+ beginning -> ld_descriptor = *simple_d;
+ *complex_d = GC_make_sequence_descriptor(
+ (complex_descriptor *)beginning,
+ (complex_descriptor *)one_element);
+ break;
+ }
+ case LEAF:
+ {
+ struct LeafDescriptor * beginning =
+ (struct LeafDescriptor *)
+ GC_malloc_atomic(sizeof(struct LeafDescriptor));
+ if (beginning == 0) return(NO_MEM);
+ beginning -> ld_tag = LEAF_TAG;
+ beginning -> ld_size = leaf -> ld_size;
+ beginning -> ld_nelements = leaf -> ld_nelements;
+ beginning -> ld_descriptor = leaf -> ld_descriptor;
+ *complex_d = GC_make_sequence_descriptor(
+ (complex_descriptor *)beginning,
+ (complex_descriptor *)one_element);
+ break;
+ }
+ case COMPLEX:
+ *complex_d = GC_make_sequence_descriptor(
+ *complex_d,
+ (complex_descriptor *)one_element);
+ break;
+ }
+ return(COMPLEX);
+ }
+ }
+ {
+ leaf -> ld_size = size;
+ leaf -> ld_nelements = nelements;
+ leaf -> ld_descriptor = descriptor;
+ return(LEAF);
+ }
+}
+
+complex_descriptor * GC_make_sequence_descriptor(complex_descriptor *first,
+ complex_descriptor *second)
+{
+ struct SequenceDescriptor * result =
+ (struct SequenceDescriptor *)
+ GC_malloc(sizeof(struct SequenceDescriptor));
+ /* Can't result in overly conservative marking, since tags are */
+ /* very small integers. Probably faster than maintaining type */
+ /* info. */
+ if (result != 0) {
+ result -> sd_tag = SEQUENCE_TAG;
+ result -> sd_first = first;
+ result -> sd_second = second;
+ }
+ return((complex_descriptor *)result);
+}
+
+#ifdef UNDEFINED
+complex_descriptor * GC_make_complex_array_descriptor(word nelements,
+ complex_descriptor *descr)
+{
+ struct ComplexArrayDescriptor * result =
+ (struct ComplexArrayDescriptor *)
+ GC_malloc(sizeof(struct ComplexArrayDescriptor));
+
+ if (result != 0) {
+ result -> ad_tag = ARRAY_TAG;
+ result -> ad_nelements = nelements;
+ result -> ad_element_descr = descr;
+ }
+ return((complex_descriptor *)result);
+}
+#endif
+
+ptr_t * GC_eobjfreelist;
+
+ptr_t * GC_arobjfreelist;
+
+mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr,
+ mse * mark_stack_limit, word env);
+
+mse * GC_array_mark_proc(word * addr, mse * mark_stack_ptr,
+ mse * mark_stack_limit, word env);
+
+/* Caller does not hold allocation lock. */
+void GC_init_explicit_typing(void)
+{
+ register int i;
+ DCL_LOCK_STATE;
+
+
+ /* Ignore gcc "no effect" warning. */
+ GC_STATIC_ASSERT(sizeof(struct LeafDescriptor) % sizeof(word) == 0);
+ LOCK();
+ if (GC_explicit_typing_initialized) {
+ UNLOCK();
+ return;
+ }
+ GC_explicit_typing_initialized = TRUE;
+ /* Set up object kind with simple indirect descriptor. */
+ GC_eobjfreelist = (ptr_t *)GC_new_free_list_inner();
+ GC_explicit_kind = GC_new_kind_inner(
+ (void **)GC_eobjfreelist,
+ (((word)WORDS_TO_BYTES(-1)) | GC_DS_PER_OBJECT),
+ TRUE, TRUE);
+ /* Descriptors are in the last word of the object. */
+ GC_typed_mark_proc_index = GC_new_proc_inner(GC_typed_mark_proc);
+ /* Set up object kind with array descriptor. */
+ GC_arobjfreelist = (ptr_t *)GC_new_free_list_inner();
+ GC_array_mark_proc_index = GC_new_proc_inner(GC_array_mark_proc);
+ GC_array_kind = GC_new_kind_inner(
+ (void **)GC_arobjfreelist,
+ GC_MAKE_PROC(GC_array_mark_proc_index, 0),
+ FALSE, TRUE);
+ for (i = 0; i < WORDSZ/2; i++) {
+ GC_descr d = (((word)(-1)) >> (WORDSZ - i)) << (WORDSZ - i);
+ d |= GC_DS_BITMAP;
+ GC_bm_table[i] = d;
+ }
+ UNLOCK();
+}
+
+mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr,
+ mse * mark_stack_limit, word env)
+{
+ word bm = GC_ext_descriptors[env].ed_bitmap;
+ word * current_p = addr;
+ word current;
+ ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
+ ptr_t least_ha = GC_least_plausible_heap_addr;
+ DECLARE_HDR_CACHE;
+
+ INIT_HDR_CACHE;
+ for (; bm != 0; bm >>= 1, current_p++) {
+ if (bm & 1) {
+ current = *current_p;
+ FIXUP_POINTER(current);
+ if ((ptr_t)current >= least_ha && (ptr_t)current <= greatest_ha) {
+ PUSH_CONTENTS((ptr_t)current, mark_stack_ptr,
+ mark_stack_limit, current_p, exit1);
+ }
+ }
+ }
+ if (GC_ext_descriptors[env].ed_continued) {
+ /* Push an entry with the rest of the descriptor back onto the */
+ /* stack. Thus we never do too much work at once. Note that */
+ /* we also can't overflow the mark stack unless we actually */
+ /* mark something. */
+ mark_stack_ptr++;
+ if (mark_stack_ptr >= mark_stack_limit) {
+ mark_stack_ptr = GC_signal_mark_stack_overflow(mark_stack_ptr);
+ }
+ mark_stack_ptr -> mse_start = (ptr_t)(addr + WORDSZ);
+ mark_stack_ptr -> mse_descr =
+ GC_MAKE_PROC(GC_typed_mark_proc_index, env+1);
+ }
+ return(mark_stack_ptr);
+}
+
+/* Return the size of the object described by d. It would be faster to */
+/* store this directly, or to compute it as part of */
+/* GC_push_complex_descriptor, but hopefully it doesn't matter. */
+word GC_descr_obj_size(complex_descriptor *d)
+{
+ switch(d -> TAG) {
+ case LEAF_TAG:
+ return(d -> ld.ld_nelements * d -> ld.ld_size);
+ case ARRAY_TAG:
+ return(d -> ad.ad_nelements
+ * GC_descr_obj_size(d -> ad.ad_element_descr));
+ case SEQUENCE_TAG:
+ return(GC_descr_obj_size(d -> sd.sd_first)
+ + GC_descr_obj_size(d -> sd.sd_second));
+ default:
+ ABORT("Bad complex descriptor");
+ /*NOTREACHED*/ return 0; /*NOTREACHED*/
+ }
+}
+
+/* Push descriptors for the object at addr with complex descriptor d */
+/* onto the mark stack. Return 0 if the mark stack overflowed. */
+mse * GC_push_complex_descriptor(word *addr, complex_descriptor *d,
+ mse *msp, mse *msl)
+{
+ register ptr_t current = (ptr_t) addr;
+ register word nelements;
+ register word sz;
+ register word i;
+
+ switch(d -> TAG) {
+ case LEAF_TAG:
+ {
+ register GC_descr descr = d -> ld.ld_descriptor;
+
+ nelements = d -> ld.ld_nelements;
+ if (msl - msp <= (ptrdiff_t)nelements) return(0);
+ sz = d -> ld.ld_size;
+ for (i = 0; i < nelements; i++) {
+ msp++;
+ msp -> mse_start = current;
+ msp -> mse_descr = descr;
+ current += sz;
+ }
+ return(msp);
+ }
+ case ARRAY_TAG:
+ {
+ register complex_descriptor *descr = d -> ad.ad_element_descr;
+
+ nelements = d -> ad.ad_nelements;
+ sz = GC_descr_obj_size(descr);
+ for (i = 0; i < nelements; i++) {
+ msp = GC_push_complex_descriptor((word *)current, descr,
+ msp, msl);
+ if (msp == 0) return(0);
+ current += sz;
+ }
+ return(msp);
+ }
+ case SEQUENCE_TAG:
+ {
+ sz = GC_descr_obj_size(d -> sd.sd_first);
+ msp = GC_push_complex_descriptor((word *)current, d -> sd.sd_first,
+ msp, msl);
+ if (msp == 0) return(0);
+ current += sz;
+ msp = GC_push_complex_descriptor((word *)current, d -> sd.sd_second,
+ msp, msl);
+ return(msp);
+ }
+ default:
+ ABORT("Bad complex descriptor");
+ /*NOTREACHED*/ return 0; /*NOTREACHED*/
+ }
+}
+
+/*ARGSUSED*/
+mse * GC_array_mark_proc(word * addr, mse * mark_stack_ptr,
+ mse * mark_stack_limit, word env)
+{
+ hdr * hhdr = HDR(addr);
+ size_t sz = hhdr -> hb_sz;
+ size_t nwords = BYTES_TO_WORDS(sz);
+ complex_descriptor * descr = (complex_descriptor *)(addr[nwords-1]);
+ mse * orig_mark_stack_ptr = mark_stack_ptr;
+ mse * new_mark_stack_ptr;
+
+ if (descr == 0) {
+ /* Found a reference to a free list entry. Ignore it. */
+ return(orig_mark_stack_ptr);
+ }
+ /* In use counts were already updated when array descriptor was */
+ /* pushed. Here we only replace it by subobject descriptors, so */
+ /* no update is necessary. */
+ new_mark_stack_ptr = GC_push_complex_descriptor(addr, descr,
+ mark_stack_ptr,
+ mark_stack_limit-1);
+ if (new_mark_stack_ptr == 0) {
+ /* Doesn't fit. Conservatively push the whole array as a unit */
+ /* and request a mark stack expansion. */
+ /* This cannot cause a mark stack overflow, since it replaces */
+ /* the original array entry. */
+ GC_mark_stack_too_small = TRUE;
+ new_mark_stack_ptr = orig_mark_stack_ptr + 1;
+ new_mark_stack_ptr -> mse_start = (ptr_t)addr;
+ new_mark_stack_ptr -> mse_descr = sz | GC_DS_LENGTH;
+ } else {
+ /* Push descriptor itself */
+ new_mark_stack_ptr++;
+ new_mark_stack_ptr -> mse_start = (ptr_t)(addr + nwords - 1);
+ new_mark_stack_ptr -> mse_descr = sizeof(word) | GC_DS_LENGTH;
+ }
+ return new_mark_stack_ptr;
+}
+
+GC_descr GC_make_descriptor(GC_bitmap bm, size_t len)
+{
+ signed_word last_set_bit = len - 1;
+ GC_descr result;
+ signed_word i;
+# define HIGH_BIT (((word)1) << (WORDSZ - 1))
+
+ if (!GC_explicit_typing_initialized) GC_init_explicit_typing();
+ while (last_set_bit >= 0 && !GC_get_bit(bm, last_set_bit)) last_set_bit --;
+ if (last_set_bit < 0) return(0 /* no pointers */);
+# if ALIGNMENT == CPP_WORDSZ/8
+ {
+ register GC_bool all_bits_set = TRUE;
+ for (i = 0; i < last_set_bit; i++) {
+ if (!GC_get_bit(bm, i)) {
+ all_bits_set = FALSE;
+ break;
+ }
+ }
+ if (all_bits_set) {
+ /* An initial section contains all pointers. Use length descriptor. */
+ return (WORDS_TO_BYTES(last_set_bit+1) | GC_DS_LENGTH);
+ }
+ }
+# endif
+ if (last_set_bit < BITMAP_BITS) {
+ /* Hopefully the common case. */
+ /* Build bitmap descriptor (with bits reversed) */
+ result = HIGH_BIT;
+ for (i = last_set_bit - 1; i >= 0; i--) {
+ result >>= 1;
+ if (GC_get_bit(bm, i)) result |= HIGH_BIT;
+ }
+ result |= GC_DS_BITMAP;
+ return(result);
+ } else {
+ signed_word index;
+
+ index = GC_add_ext_descriptor(bm, (word)last_set_bit+1);
+ if (index == -1) return(WORDS_TO_BYTES(last_set_bit+1) | GC_DS_LENGTH);
+ /* Out of memory: use conservative */
+ /* approximation. */
+ result = GC_MAKE_PROC(GC_typed_mark_proc_index, (word)index);
+ return result;
+ }
+}
+
+/* ptr_t GC_clear_stack(); */
+
+#define GENERAL_MALLOC(lb,k) \
+ (void *)GC_clear_stack(GC_generic_malloc((word)lb, k))
+
+#define GENERAL_MALLOC_IOP(lb,k) \
+ (void *)GC_clear_stack(GC_generic_malloc_ignore_off_page(lb, k))
+
+void * GC_malloc_explicitly_typed(size_t lb, GC_descr d)
+{
+ ptr_t op;
+ ptr_t * opp;
+ size_t lg;
+ DCL_LOCK_STATE;
+
+ lb += TYPD_EXTRA_BYTES;
+ if(SMALL_OBJ(lb)) {
+ lg = GC_size_map[lb];
+ opp = &(GC_eobjfreelist[lg]);
+ LOCK();
+ if( (op = *opp) == 0 ) {
+ UNLOCK();
+ op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind);
+ if (0 == op) return 0;
+ lg = GC_size_map[lb]; /* May have been uninitialized. */
+ } else {
+ *opp = obj_link(op);
+ obj_link(op) = 0;
+ GC_bytes_allocd += GRANULES_TO_BYTES(lg);
+ UNLOCK();
+ }
+ } else {
+ op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind);
+ if (op != NULL)
+ lg = BYTES_TO_GRANULES(GC_size(op));
+ }
+ if (op != NULL)
+ ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d;
+ return((void *) op);
+}
+
+void * GC_malloc_explicitly_typed_ignore_off_page(size_t lb, GC_descr d)
+{
+ptr_t op;
+ptr_t * opp;
+size_t lg;
+DCL_LOCK_STATE;
+
+ lb += TYPD_EXTRA_BYTES;
+ if( SMALL_OBJ(lb) ) {
+ lg = GC_size_map[lb];
+ opp = &(GC_eobjfreelist[lg]);
+ LOCK();
+ if( (op = *opp) == 0 ) {
+ UNLOCK();
+ op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind);
+ lg = GC_size_map[lb]; /* May have been uninitialized. */
+ } else {
+ *opp = obj_link(op);
+ obj_link(op) = 0;
+ GC_bytes_allocd += GRANULES_TO_BYTES(lg);
+ UNLOCK();
+ }
+ } else {
+ op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind);
+ if (op != NULL)
+ lg = BYTES_TO_WORDS(GC_size(op));
+ }
+ if (op != NULL)
+ ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d;
+ return((void *) op);
+}
+
+void * GC_calloc_explicitly_typed(size_t n, size_t lb, GC_descr d)
+{
+ptr_t op;
+ptr_t * opp;
+size_t lg;
+GC_descr simple_descr;
+complex_descriptor *complex_descr;
+register int descr_type;
+struct LeafDescriptor leaf;
+DCL_LOCK_STATE;
+
+ descr_type = GC_make_array_descriptor((word)n, (word)lb, d,
+ &simple_descr, &complex_descr, &leaf);
+ switch(descr_type) {
+ case NO_MEM: return(0);
+ case SIMPLE: return(GC_malloc_explicitly_typed(n*lb, simple_descr));
+ case LEAF:
+ lb *= n;
+ lb += sizeof(struct LeafDescriptor) + TYPD_EXTRA_BYTES;
+ break;
+ case COMPLEX:
+ lb *= n;
+ lb += TYPD_EXTRA_BYTES;
+ break;
+ }
+ if( SMALL_OBJ(lb) ) {
+ lg = GC_size_map[lb];
+ opp = &(GC_arobjfreelist[lg]);
+ LOCK();
+ if( (op = *opp) == 0 ) {
+ UNLOCK();
+ op = (ptr_t)GENERAL_MALLOC((word)lb, GC_array_kind);
+ if (0 == op) return(0);
+ lg = GC_size_map[lb]; /* May have been uninitialized. */
+ } else {
+ *opp = obj_link(op);
+ obj_link(op) = 0;
+ GC_bytes_allocd += GRANULES_TO_BYTES(lg);
+ UNLOCK();
+ }
+ } else {
+ op = (ptr_t)GENERAL_MALLOC((word)lb, GC_array_kind);
+ if (0 == op) return(0);
+ lg = BYTES_TO_GRANULES(GC_size(op));
+ }
+ if (descr_type == LEAF) {
+ /* Set up the descriptor inside the object itself. */
+ volatile struct LeafDescriptor * lp =
+ (struct LeafDescriptor *)
+ ((word *)op
+ + GRANULES_TO_WORDS(lg)
+ - (BYTES_TO_WORDS(sizeof(struct LeafDescriptor)) + 1));
+
+ lp -> ld_tag = LEAF_TAG;
+ lp -> ld_size = leaf.ld_size;
+ lp -> ld_nelements = leaf.ld_nelements;
+ lp -> ld_descriptor = leaf.ld_descriptor;
+ ((volatile word *)op)[GRANULES_TO_WORDS(lg) - 1] = (word)lp;
+ } else {
+ extern unsigned GC_finalization_failures;
+ unsigned ff = GC_finalization_failures;
+ size_t lw = GRANULES_TO_WORDS(lg);
+
+ ((word *)op)[lw - 1] = (word)complex_descr;
+ /* Make sure the descriptor is cleared once there is any danger */
+ /* it may have been collected. */
+ (void)
+ GC_general_register_disappearing_link((void * *)
+ ((word *)op+lw-1),
+ (void *) op);
+ if (ff != GC_finalization_failures) {
+ /* Couldn't register it due to lack of memory. Punt. */
+ /* This will probably fail too, but gives the recovery code */
+ /* a chance. */
+ return(GC_malloc(n*lb));
+ }
+ }
+ return((void *) op);
+}
diff --git a/tools/build/v2/engine/boehm_gc/version.h b/tools/build/v2/engine/boehm_gc/version.h
new file mode 100644
index 0000000000..112dec30ea
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/version.h
@@ -0,0 +1,30 @@
+/* The version here should match that in configure/configure.ac */
+/* Eventually this one may become unnecessary. For now we need */
+/* it to keep the old-style build process working. */
+#define GC_TMP_VERSION_MAJOR 7
+#define GC_TMP_VERSION_MINOR 0
+#define GC_TMP_ALPHA_VERSION GC_NOT_ALPHA
+
+#ifndef GC_NOT_ALPHA
+# define GC_NOT_ALPHA 0xff
+#endif
+
+#if defined(GC_VERSION_MAJOR)
+# if GC_TMP_VERSION_MAJOR != GC_VERSION_MAJOR || \
+ GC_TMP_VERSION_MINOR != GC_VERSION_MINOR || \
+ defined(GC_ALPHA_VERSION) != (GC_TMP_ALPHA_VERSION != GC_NOT_ALPHA) || \
+ defined(GC_ALPHA_VERSION) && GC_TMP_ALPHA_VERSION != GC_ALPHA_VERSION
+# error Inconsistent version info. Check README, version.h, and configure.ac.
+# endif
+#else
+# define GC_VERSION_MAJOR GC_TMP_VERSION_MAJOR
+# define GC_VERSION_MINOR GC_TMP_VERSION_MINOR
+# define GC_ALPHA_VERSION GC_TMP_ALPHA_VERSION
+#endif
+
+
+#ifndef GC_NO_VERSION_VAR
+
+unsigned GC_version = ((GC_VERSION_MAJOR << 16) | (GC_VERSION_MINOR << 8) | GC_TMP_ALPHA_VERSION);
+
+#endif /* GC_NO_VERSION_VAR */
diff --git a/tools/build/v2/engine/boehm_gc/win32_threads.c b/tools/build/v2/engine/boehm_gc/win32_threads.c
new file mode 100644
index 0000000000..ac57971900
--- /dev/null
+++ b/tools/build/v2/engine/boehm_gc/win32_threads.c
@@ -0,0 +1,1570 @@
+#include "private/gc_priv.h"
+
+#if defined(GC_WIN32_THREADS)
+
+#include <windows.h>
+
+#ifdef THREAD_LOCAL_ALLOC
+# include "private/thread_local_alloc.h"
+#endif /* THREAD_LOCAL_ALLOC */
+
+/* Allocation lock declarations. */
+#if !defined(USE_PTHREAD_LOCKS)
+# if defined(GC_DLL)
+ __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml;
+# else
+ CRITICAL_SECTION GC_allocate_ml;
+# endif
+ DWORD GC_lock_holder = NO_THREAD;
+ /* Thread id for current holder of allocation lock */
+#else
+ pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
+ unsigned long GC_lock_holder = NO_THREAD;
+#endif
+
+#ifdef GC_PTHREADS
+# include <errno.h>
+
+/* GC_DLL should not normally be defined, especially since we often do turn */
+/* on THREAD_LOCAL_ALLOC, which is currently incompatible. */
+/* It might be possible to get GC_DLL and DllMain-based thread registration */
+/* to work with Cygwin, but if you try you are on your own. */
+#ifdef GC_DLL
+# error GC_DLL untested with Cygwin
+#endif
+
+ /* Cygwin-specific forward decls */
+# undef pthread_create
+# undef pthread_sigmask
+# undef pthread_join
+# undef pthread_detach
+# undef dlopen
+
+# ifdef DEBUG_THREADS
+# ifdef CYGWIN32
+# define DEBUG_CYGWIN_THREADS 1
+# define DEBUG_WIN32_PTHREADS 0
+# else
+# define DEBUG_WIN32_PTHREADS 1
+# define DEBUG_CYGWIN_THREADS 0
+# endif
+# else
+# define DEBUG_CYGWIN_THREADS 0
+# define DEBUG_WIN32_PTHREADS 0
+# endif
+
+ void * GC_pthread_start(void * arg);
+ void GC_thread_exit_proc(void *arg);
+
+# include <pthread.h>
+
+#else
+
+# ifdef DEBUG_THREADS
+# define DEBUG_WIN32_THREADS 1
+# else
+# define DEBUG_WIN32_THREADS 0
+# endif
+
+# undef CreateThread
+# undef ExitThread
+# undef _beginthreadex
+# undef _endthreadex
+# undef _beginthread
+# ifdef DEBUG_THREADS
+# define DEBUG_WIN32_THREADS 1
+# else
+# define DEBUG_WIN32_THREADS 0
+# endif
+
+# include <process.h> /* For _beginthreadex, _endthreadex */
+
+#endif
+
+#if defined(GC_DLL) && !defined(MSWINCE)
+ static GC_bool GC_win32_dll_threads = FALSE;
+ /* This code operates in two distinct modes, depending on */
+ /* the setting of GC_win32_dll_threads. If */
+ /* GC_win32_dll_threads is set, all threads in the process */
+ /* are implicitly registered with the GC by DllMain. */
+ /* No explicit registration is required, and attempts at */
+ /* explicit registration are ignored. This mode is */
+ /* very different from the Posix operation of the collector. */
+ /* In this mode access to the thread table is lock-free. */
+ /* Hence there is a static limit on the number of threads. */
+
+ /* If GC_win32_dll_threads is FALSE, or the collector is */
+ /* built without GC_DLL defined, things operate in a way */
+ /* that is very similar to Posix platforms, and new threads */
+ /* must be registered with the collector, e.g. by using */
+ /* preprocessor-based interception of the thread primitives. */
+ /* In this case, we use a real data structure for the thread */
+ /* table. Note that there is no equivalent of linker-based */
+ /* call interception, since we don't have ELF-like */
+ /* facilities. The Windows analog appears to be "API */
+ /* hooking", which really seems to be a standard way to */
+ /* do minor binary rewriting (?). I'd prefer not to have */
+ /* the basic collector rely on such facilities, but an */
+ /* optional package that intercepts thread calls this way */
+ /* would probably be nice. */
+
+ /* GC_win32_dll_threads must be set at initialization time, */
+ /* i.e. before any collector or thread calls. We make it a */
+ /* "dynamic" option only to avoid multiple library versions. */
+#else
+# define GC_win32_dll_threads FALSE
+#endif
+
+/* We have two versions of the thread table. Which one */
+/* we us depends on whether or not GC_win32_dll_threads */
+/* is set. Note that before initialization, we don't */
+/* add any entries to either table, even if DllMain is */
+/* called. The main thread will be added on */
+/* initialization. */
+
+/* The type of the first argument to InterlockedExchange. */
+/* Documented to be LONG volatile *, but at least gcc likes */
+/* this better. */
+typedef LONG * IE_t;
+
+GC_bool GC_thr_initialized = FALSE;
+
+GC_bool GC_need_to_lock = FALSE;
+
+static GC_bool parallel_initialized = FALSE;
+
+void GC_init_parallel(void);
+
+#ifdef GC_DLL
+ /* Turn on GC_win32_dll_threads */
+ GC_API void GC_use_DllMain(void)
+ {
+# ifdef THREAD_LOCAL_ALLOC
+ ABORT("Cannot use thread local allocation with DllMain-based "
+ "thread registration.");
+ /* Thread-local allocation really wants to lock at thread */
+ /* entry and exit. */
+# endif
+ GC_ASSERT(!parallel_initialized);
+ GC_win32_dll_threads = TRUE;
+ }
+#else
+ GC_API void GC_use_DllMain(void)
+ {
+ ABORT("GC not configured as DLL");
+ }
+#endif
+
+DWORD GC_main_thread = 0;
+
+struct GC_Thread_Rep {
+ union {
+ AO_t tm_in_use; /* Updated without lock. */
+ /* We assert that unused */
+ /* entries have invalid ids of */
+ /* zero and zero stack fields. */
+ /* Used only with GC_win32_dll_threads. */
+ struct GC_Thread_Rep * tm_next;
+ /* Hash table link without */
+ /* GC_win32_dll_threads. */
+ /* More recently allocated threads */
+ /* with a given pthread id come */
+ /* first. (All but the first are */
+ /* guaranteed to be dead, but we may */
+ /* not yet have registered the join.) */
+ } table_management;
+# define in_use table_management.tm_in_use
+# define next table_management.tm_next
+ DWORD id;
+ HANDLE handle;
+ ptr_t stack_base; /* The cold end of the stack. */
+ /* 0 ==> entry not valid. */
+ /* !in_use ==> stack_base == 0 */
+ GC_bool suspended;
+
+# ifdef GC_PTHREADS
+ void *status; /* hold exit value until join in case it's a pointer */
+ pthread_t pthread_id;
+ short flags; /* Protected by GC lock. */
+# define FINISHED 1 /* Thread has exited. */
+# define DETACHED 2 /* Thread is intended to be detached. */
+# define KNOWN_FINISHED(t) (((t) -> flags) & FINISHED)
+# else
+# define KNOWN_FINISHED(t) 0
+# endif
+# ifdef THREAD_LOCAL_ALLOC
+ struct thread_local_freelists tlfs;
+# endif
+};
+
+typedef struct GC_Thread_Rep * GC_thread;
+typedef volatile struct GC_Thread_Rep * GC_vthread;
+
+/*
+ * We assumed that volatile ==> memory ordering, at least among
+ * volatiles. This code should consistently use atomic_ops.
+ */
+
+volatile GC_bool GC_please_stop = FALSE;
+
+/*
+ * We track thread attachments while the world is supposed to be stopped.
+ * Unfortunately, we can't stop them from starting, since blocking in
+ * DllMain seems to cause the world to deadlock. Thus we have to recover
+ * If we notice this in the middle of marking.
+ */
+
+AO_t GC_attached_thread = FALSE;
+/* Return TRUE if an thread was attached since we last asked or */
+/* since GC_attached_thread was explicitly reset. */
+GC_bool GC_started_thread_while_stopped(void)
+{
+ AO_t result;
+
+ if (GC_win32_dll_threads) {
+ AO_nop_full(); /* Prior heap reads need to complete earlier. */
+ result = AO_load(&GC_attached_thread);
+ if (result) {
+ AO_store(&GC_attached_thread, FALSE);
+ }
+ return ((GC_bool)result);
+ } else {
+ return FALSE;
+ }
+}
+
+/* Thread table used if GC_win32_dll_threads is set. */
+/* This is a fixed size array. */
+/* Since we use runtime conditionals, both versions */
+/* are always defined. */
+# ifndef MAX_THREADS
+# define MAX_THREADS 512
+# endif
+ /* Things may get quite slow for large numbers of threads, */
+ /* since we look them up with sequential search. */
+
+ volatile struct GC_Thread_Rep dll_thread_table[MAX_THREADS];
+
+ volatile LONG GC_max_thread_index = 0;
+ /* Largest index in dll_thread_table */
+ /* that was ever used. */
+
+/* And now the version used if GC_win32_dll_threads is not set. */
+/* This is a chained hash table, with much of the code borrowed */
+/* From the Posix implementation. */
+# define THREAD_TABLE_SZ 256 /* Must be power of 2 */
+ GC_thread GC_threads[THREAD_TABLE_SZ];
+
+
+/* Add a thread to GC_threads. We assume it wasn't already there. */
+/* Caller holds allocation lock. */
+/* Unlike the pthreads version, the id field is set by the caller. */
+GC_thread GC_new_thread(DWORD id)
+{
+ word hv = ((word)id) % THREAD_TABLE_SZ;
+ GC_thread result;
+ /* It may not be safe to allocate when we register the first thread. */
+ static struct GC_Thread_Rep first_thread;
+ static GC_bool first_thread_used = FALSE;
+
+ GC_ASSERT(I_HOLD_LOCK());
+ if (!first_thread_used) {
+ result = &first_thread;
+ first_thread_used = TRUE;
+ } else {
+ GC_ASSERT(!GC_win32_dll_threads);
+ result = (struct GC_Thread_Rep *)
+ GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL);
+# ifdef GC_PTHREADS
+ /* result can be NULL -> segfault */
+ GC_ASSERT(result -> flags == 0);
+# endif
+ }
+ if (result == 0) return(0);
+ /* result -> id = id; Done by caller. */
+ result -> next = GC_threads[hv];
+ GC_threads[hv] = result;
+# ifdef GC_PTHREADS
+ GC_ASSERT(result -> flags == 0 /* && result -> thread_blocked == 0 */);
+# endif
+ return(result);
+}
+
+extern LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info);
+
+#if defined(GWW_VDB) && defined(MPROTECT_VDB)
+ extern GC_bool GC_gww_dirty_init(void);
+ /* Defined in os_dep.c. Returns TRUE if GetWriteWatch is available. */
+ /* may be called repeatedly. */
+#endif
+
+GC_bool GC_in_thread_creation = FALSE; /* Protected by allocation lock. */
+
+/*
+ * This may be called from DllMain, and hence operates under unusual
+ * constraints. In particular, it must be lock-free if GC_win32_dll_threads
+ * is set. Always called from the thread being added.
+ * If GC_win32_dll_threads is not set, we already hold the allocation lock,
+ * except possibly during single-threaded start-up code.
+ */
+static GC_thread GC_register_my_thread_inner(struct GC_stack_base *sb,
+ DWORD thread_id)
+{
+ GC_vthread me;
+
+ /* The following should be a noop according to the win32 */
+ /* documentation. There is empirical evidence that it */
+ /* isn't. - HB */
+# if defined(MPROTECT_VDB)
+# if defined(GWW_VDB)
+ if (GC_incremental && !GC_gww_dirty_init())
+ SetUnhandledExceptionFilter(GC_write_fault_handler);
+# else
+ if (GC_incremental) SetUnhandledExceptionFilter(GC_write_fault_handler);
+# endif
+# endif
+
+ if (GC_win32_dll_threads) {
+ int i;
+ /* It appears to be unsafe to acquire a lock here, since this */
+ /* code is apparently not preeemptible on some systems. */
+ /* (This is based on complaints, not on Microsoft's official */
+ /* documentation, which says this should perform "only simple */
+ /* initialization tasks".) */
+ /* Hence we make do with nonblocking synchronization. */
+ /* It has been claimed that DllMain is really only executed with */
+ /* a particular system lock held, and thus careful use of locking */
+ /* around code that doesn't call back into the system libraries */
+ /* might be OK. But this hasn't been tested across all win32 */
+ /* variants. */
+ /* cast away volatile qualifier */
+ for (i = 0; InterlockedExchange((IE_t)&dll_thread_table[i].in_use,1) != 0;
+ i++) {
+ /* Compare-and-swap would make this cleaner, but that's not */
+ /* supported before Windows 98 and NT 4.0. In Windows 2000, */
+ /* InterlockedExchange is supposed to be replaced by */
+ /* InterlockedExchangePointer, but that's not really what I */
+ /* want here. */
+ /* FIXME: We should eventually declare Win95 dead and use AO_ */
+ /* primitives here. */
+ if (i == MAX_THREADS - 1)
+ ABORT("too many threads");
+ }
+ /* Update GC_max_thread_index if necessary. The following is safe, */
+ /* and unlike CompareExchange-based solutions seems to work on all */
+ /* Windows95 and later platforms. */
+ /* Unfortunately, GC_max_thread_index may be temporarily out of */
+ /* bounds, so readers have to compensate. */
+ while (i > GC_max_thread_index) {
+ InterlockedIncrement((IE_t)&GC_max_thread_index);
+ }
+ if (GC_max_thread_index >= MAX_THREADS) {
+ /* We overshot due to simultaneous increments. */
+ /* Setting it to MAX_THREADS-1 is always safe. */
+ GC_max_thread_index = MAX_THREADS - 1;
+ }
+ me = dll_thread_table + i;
+ } else /* Not using DllMain */ {
+ GC_ASSERT(I_HOLD_LOCK());
+ GC_in_thread_creation = TRUE; /* OK to collect from unknown thread. */
+ me = GC_new_thread(thread_id);
+ GC_in_thread_creation = FALSE;
+ }
+# ifdef GC_PTHREADS
+ /* me can be NULL -> segfault */
+ me -> pthread_id = pthread_self();
+# endif
+
+ if (!DuplicateHandle(GetCurrentProcess(),
+ GetCurrentThread(),
+ GetCurrentProcess(),
+ (HANDLE*)&(me -> handle),
+ 0,
+ 0,
+ DUPLICATE_SAME_ACCESS)) {
+ DWORD last_error = GetLastError();
+ GC_err_printf("Last error code: %d\n", last_error);
+ ABORT("DuplicateHandle failed");
+ }
+ me -> stack_base = sb -> mem_base;
+ /* Up until this point, GC_push_all_stacks considers this thread */
+ /* invalid. */
+ /* Up until this point, this entry is viewed as reserved but invalid */
+ /* by GC_delete_thread. */
+ me -> id = thread_id;
+# if defined(THREAD_LOCAL_ALLOC)
+ GC_init_thread_local((GC_tlfs)(&(me->tlfs)));
+# endif
+ if (me -> stack_base == NULL)
+ ABORT("Bad stack base in GC_register_my_thread_inner");
+ if (GC_win32_dll_threads) {
+ if (GC_please_stop) {
+ AO_store(&GC_attached_thread, TRUE);
+ AO_nop_full(); // Later updates must become visible after this.
+ }
+ /* We'd like to wait here, but can't, since waiting in DllMain */
+ /* provokes deadlocks. */
+ /* Thus we force marking to be restarted instead. */
+ } else {
+ GC_ASSERT(!GC_please_stop);
+ /* Otherwise both we and the thread stopping code would be */
+ /* holding the allocation lock. */
+ }
+ return (GC_thread)(me);
+}
+
+/*
+ * GC_max_thread_index may temporarily be larger than MAX_THREADS.
+ * To avoid subscript errors, we check on access.
+ */
+#ifdef __GNUC__
+__inline__
+#endif
+LONG GC_get_max_thread_index()
+{
+ LONG my_max = GC_max_thread_index;
+
+ if (my_max >= MAX_THREADS) return MAX_THREADS-1;
+ return my_max;
+}
+
+/* Return the GC_thread corresponding to a thread id. May be called */
+/* without a lock, but should be called in contexts in which the */
+/* requested thread cannot be asynchronously deleted, e.g. from the */
+/* thread itself. */
+/* This version assumes that either GC_win32_dll_threads is set, or */
+/* we hold the allocator lock. */
+/* Also used (for assertion checking only) from thread_local_alloc.c. */
+GC_thread GC_lookup_thread_inner(DWORD thread_id) {
+ if (GC_win32_dll_threads) {
+ int i;
+ LONG my_max = GC_get_max_thread_index();
+ for (i = 0;
+ i <= my_max &&
+ (!AO_load_acquire(&(dll_thread_table[i].in_use))
+ || dll_thread_table[i].id != thread_id);
+ /* Must still be in_use, since nobody else can store our thread_id. */
+ i++) {}
+ if (i > my_max) {
+ return 0;
+ } else {
+ return (GC_thread)(dll_thread_table + i);
+ }
+ } else {
+ word hv = ((word)thread_id) % THREAD_TABLE_SZ;
+ register GC_thread p = GC_threads[hv];
+
+ GC_ASSERT(I_HOLD_LOCK());
+ while (p != 0 && p -> id != thread_id) p = p -> next;
+ return(p);
+ }
+}
+
+/* A version of the above that acquires the lock if necessary. Note */
+/* that the identically named function for pthreads is different, and */
+/* just assumes we hold the lock. */
+/* Also used (for assertion checking only) from thread_local_alloc.c. */
+static GC_thread GC_lookup_thread(DWORD thread_id)
+{
+ if (GC_win32_dll_threads) {
+ return GC_lookup_thread_inner(thread_id);
+ } else {
+ GC_thread result;
+ LOCK();
+ result = GC_lookup_thread_inner(thread_id);
+ UNLOCK();
+ return result;
+ }
+}
+
+/* If a thread has been joined, but we have not yet */
+/* been notified, then there may be more than one thread */
+/* in the table with the same win32 id. */
+/* This is OK, but we need a way to delete a specific one. */
+/* Assumes we hold the allocation lock unless */
+/* GC_win32_dll_threads is set. */
+/* If GC_win32_dll_threads is set it should be called from the */
+/* thread being deleted. */
+void GC_delete_gc_thread(GC_vthread gc_id)
+{
+ if (GC_win32_dll_threads) {
+ /* This is intended to be lock-free. */
+ /* It is either called synchronously from the thread being deleted, */
+ /* or by the joining thread. */
+ /* In this branch asynchronosu changes to *gc_id are possible. */
+ CloseHandle(gc_id->handle);
+ gc_id -> stack_base = 0;
+ gc_id -> id = 0;
+# ifdef CYGWIN32
+ gc_id -> pthread_id = 0;
+# endif /* CYGWIN32 */
+# ifdef GC_WIN32_PTHREADS
+ gc_id -> pthread_id.p = NULL;
+# endif /* GC_WIN32_PTHREADS */
+ AO_store_release(&(gc_id->in_use), FALSE);
+ } else {
+ /* Cast away volatile qualifier, since we have lock. */
+ GC_thread gc_nvid = (GC_thread)gc_id;
+ DWORD id = gc_nvid -> id;
+ word hv = ((word)id) % THREAD_TABLE_SZ;
+ register GC_thread p = GC_threads[hv];
+ register GC_thread prev = 0;
+
+ GC_ASSERT(I_HOLD_LOCK());
+ while (p != gc_nvid) {
+ prev = p;
+ p = p -> next;
+ }
+ if (prev == 0) {
+ GC_threads[hv] = p -> next;
+ } else {
+ prev -> next = p -> next;
+ }
+ GC_INTERNAL_FREE(p);
+ }
+}
+
+/* Delete a thread from GC_threads. We assume it is there. */
+/* (The code intentionally traps if it wasn't.) */
+/* Assumes we hold the allocation lock unless */
+/* GC_win32_dll_threads is set. */
+/* If GC_win32_dll_threads is set it should be called from the */
+/* thread being deleted. */
+void GC_delete_thread(DWORD id)
+{
+ if (GC_win32_dll_threads) {
+ GC_thread t = GC_lookup_thread_inner(id);
+
+ if (0 == t) {
+ WARN("Removing nonexistent thread %ld\n", (GC_word)id);
+ } else {
+ GC_delete_gc_thread(t);
+ }
+ } else {
+ word hv = ((word)id) % THREAD_TABLE_SZ;
+ register GC_thread p = GC_threads[hv];
+ register GC_thread prev = 0;
+
+ GC_ASSERT(I_HOLD_LOCK());
+ while (p -> id != id) {
+ prev = p;
+ p = p -> next;
+ }
+ if (prev == 0) {
+ GC_threads[hv] = p -> next;
+ } else {
+ prev -> next = p -> next;
+ }
+ GC_INTERNAL_FREE(p);
+ }
+}
+
+int GC_register_my_thread(struct GC_stack_base *sb) {
+ DWORD t = GetCurrentThreadId();
+
+ if (0 == GC_lookup_thread(t)) {
+ /* We lock here, since we want to wait for an ongoing GC. */
+ LOCK();
+ GC_register_my_thread_inner(sb, t);
+ UNLOCK();
+ return GC_SUCCESS;
+ } else {
+ return GC_DUPLICATE;
+ }
+}
+
+int GC_unregister_my_thread(void)
+{
+ DWORD t = GetCurrentThreadId();
+
+# if defined(THREAD_LOCAL_ALLOC)
+ LOCK();
+ {
+ GC_thread me = GC_lookup_thread_inner(t);
+ GC_destroy_thread_local(&(me->tlfs));
+ }
+ UNLOCK();
+# endif
+ if (GC_win32_dll_threads) {
+ /* Should we just ignore this? */
+ GC_delete_thread(t);
+ } else {
+ LOCK();
+ GC_delete_thread(t);
+ UNLOCK();
+ }
+ return GC_SUCCESS;
+}
+
+
+#ifdef GC_PTHREADS
+
+/* A quick-and-dirty cache of the mapping between pthread_t */
+/* and win32 thread id. */
+#define PTHREAD_MAP_SIZE 512
+DWORD GC_pthread_map_cache[PTHREAD_MAP_SIZE];
+#define HASH(pthread_id) ((NUMERIC_THREAD_ID(pthread_id) >> 5) % PTHREAD_MAP_SIZE)
+ /* It appears pthread_t is really a pointer type ... */
+#define SET_PTHREAD_MAP_CACHE(pthread_id, win32_id) \
+ GC_pthread_map_cache[HASH(pthread_id)] = (win32_id);
+#define GET_PTHREAD_MAP_CACHE(pthread_id) \
+ GC_pthread_map_cache[HASH(pthread_id)]
+
+/* Return a GC_thread corresponding to a given pthread_t. */
+/* Returns 0 if it's not there. */
+/* We assume that this is only called for pthread ids that */
+/* have not yet terminated or are still joinable, and */
+/* cannot be concurrently terminated. */
+/* Assumes we do NOT hold the allocation lock. */
+static GC_thread GC_lookup_pthread(pthread_t id)
+{
+ if (GC_win32_dll_threads) {
+ int i;
+ LONG my_max = GC_get_max_thread_index();
+
+ for (i = 0;
+ i <= my_max &&
+ (!AO_load_acquire(&(dll_thread_table[i].in_use))
+ || THREAD_EQUAL(dll_thread_table[i].pthread_id, id));
+ /* Must still be in_use, since nobody else can store our thread_id. */
+ i++);
+ if (i > my_max) return 0;
+ return (GC_thread)(dll_thread_table + i);
+ } else {
+ /* We first try the cache. If that fails, we use a very slow */
+ /* approach. */
+ int hv_guess = GET_PTHREAD_MAP_CACHE(id) % THREAD_TABLE_SZ;
+ int hv;
+ GC_thread p;
+
+ LOCK();
+ for (p = GC_threads[hv_guess]; 0 != p; p = p -> next) {
+ if (THREAD_EQUAL(p -> pthread_id, id))
+ goto foundit;
+ }
+ for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) {
+ for (p = GC_threads[hv]; 0 != p; p = p -> next) {
+ if (THREAD_EQUAL(p -> pthread_id, id))
+ goto foundit;
+ }
+ }
+ p = 0;
+ foundit:
+ UNLOCK();
+ return p;
+ }
+}
+
+#endif /* GC_PTHREADS */
+
+void GC_push_thread_structures(void)
+{
+ GC_ASSERT(I_HOLD_LOCK());
+ if (GC_win32_dll_threads) {
+ /* Unlike the other threads implementations, the thread table here */
+ /* contains no pointers to the collectable heap. Thus we have */
+ /* no private structures we need to preserve. */
+# ifdef GC_PTHREADS
+ { int i; /* pthreads may keep a pointer in the thread exit value */
+ LONG my_max = GC_get_max_thread_index();
+
+ for (i = 0; i <= my_max; i++)
+ if (dll_thread_table[i].in_use)
+ GC_push_all((ptr_t)&(dll_thread_table[i].status),
+ (ptr_t)(&(dll_thread_table[i].status)+1));
+ }
+# endif
+ } else {
+ GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads));
+ }
+# if defined(THREAD_LOCAL_ALLOC)
+ GC_push_all((ptr_t)(&GC_thread_key),
+ (ptr_t)(&GC_thread_key)+sizeof(&GC_thread_key));
+ /* Just in case we ever use our own TLS implementation. */
+# endif
+}
+
+/* Suspend the given thread, if it's still active. */
+void GC_suspend(GC_thread t)
+{
+# ifdef MSWINCE
+ /* SuspendThread will fail if thread is running kernel code */
+ while (SuspendThread(t -> handle) == (DWORD)-1)
+ Sleep(10);
+# else
+ /* Apparently the Windows 95 GetOpenFileName call creates */
+ /* a thread that does not properly get cleaned up, and */
+ /* SuspendThread on its descriptor may provoke a crash. */
+ /* This reduces the probability of that event, though it still */
+ /* appears there's a race here. */
+ DWORD exitCode;
+ if (GetExitCodeThread(t -> handle, &exitCode) &&
+ exitCode != STILL_ACTIVE) {
+ t -> stack_base = 0; /* prevent stack from being pushed */
+# ifndef GC_PTHREADS
+ /* this breaks pthread_join on Cygwin, which is guaranteed to */
+ /* only see user pthreads */
+ AO_store(&(t -> in_use), FALSE);
+ CloseHandle(t -> handle);
+# endif
+ return;
+ }
+ if (SuspendThread(t -> handle) == (DWORD)-1)
+ ABORT("SuspendThread failed");
+# endif
+ t -> suspended = TRUE;
+}
+
+/* Defined in misc.c */
+#ifndef CYGWIN32
+ extern CRITICAL_SECTION GC_write_cs;
+#endif
+
+void GC_stop_world(void)
+{
+ DWORD thread_id = GetCurrentThreadId();
+ int i;
+
+ if (!GC_thr_initialized) ABORT("GC_stop_world() called before GC_thr_init()");
+ GC_ASSERT(I_HOLD_LOCK());
+
+ GC_please_stop = TRUE;
+# ifndef CYGWIN32
+ EnterCriticalSection(&GC_write_cs);
+# endif
+ if (GC_win32_dll_threads) {
+ /* Any threads being created during this loop will end up setting */
+ /* GC_attached_thread when they start. This will force marking to */
+ /* restart. */
+ /* This is not ideal, but hopefully correct. */
+ GC_attached_thread = FALSE;
+ for (i = 0; i <= GC_get_max_thread_index(); i++) {
+ GC_vthread t = dll_thread_table + i;
+ if (t -> stack_base != 0
+ && t -> id != thread_id) {
+ GC_suspend((GC_thread)t);
+ }
+ }
+ } else {
+ GC_thread t;
+ int i;
+
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ for (t = GC_threads[i]; t != 0; t = t -> next) {
+ if (t -> stack_base != 0
+ && !KNOWN_FINISHED(t)
+ && t -> id != thread_id) {
+ GC_suspend(t);
+ }
+ }
+ }
+ }
+# ifndef CYGWIN32
+ LeaveCriticalSection(&GC_write_cs);
+# endif
+}
+
+void GC_start_world(void)
+{
+ DWORD thread_id = GetCurrentThreadId();
+ int i;
+ LONG my_max = GC_get_max_thread_index();
+
+ GC_ASSERT(I_HOLD_LOCK());
+ if (GC_win32_dll_threads) {
+ for (i = 0; i <= my_max; i++) {
+ GC_thread t = (GC_thread)(dll_thread_table + i);
+ if (t -> stack_base != 0 && t -> suspended
+ && t -> id != thread_id) {
+ if (ResumeThread(t -> handle) == (DWORD)-1)
+ ABORT("ResumeThread failed");
+ t -> suspended = FALSE;
+ }
+ }
+ } else {
+ GC_thread t;
+ int i;
+
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ for (t = GC_threads[i]; t != 0; t = t -> next) {
+ if (t -> stack_base != 0 && t -> suspended
+ && t -> id != thread_id) {
+ if (ResumeThread(t -> handle) == (DWORD)-1)
+ ABORT("ResumeThread failed");
+ t -> suspended = FALSE;
+ }
+ }
+ }
+ }
+ GC_please_stop = FALSE;
+}
+
+# ifdef MSWINCE
+ /* The VirtualQuery calls below won't work properly on WinCE, but */
+ /* since each stack is restricted to an aligned 64K region of */
+ /* virtual memory we can just take the next lowest multiple of 64K. */
+# define GC_get_stack_min(s) \
+ ((ptr_t)(((DWORD)(s) - 1) & 0xFFFF0000))
+# else
+ static ptr_t GC_get_stack_min(ptr_t s)
+ {
+ ptr_t bottom;
+ MEMORY_BASIC_INFORMATION info;
+ VirtualQuery(s, &info, sizeof(info));
+ do {
+ bottom = info.BaseAddress;
+ VirtualQuery(bottom - 1, &info, sizeof(info));
+ } while ((info.Protect & PAGE_READWRITE)
+ && !(info.Protect & PAGE_GUARD));
+ return(bottom);
+ }
+# endif
+
+void GC_push_stack_for(GC_thread thread)
+{
+ int dummy;
+ ptr_t sp, stack_min;
+ DWORD me = GetCurrentThreadId();
+
+ if (thread -> stack_base) {
+ if (thread -> id == me) {
+ sp = (ptr_t) &dummy;
+ } else {
+ CONTEXT context;
+ context.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL;
+ if (!GetThreadContext(thread -> handle, &context))
+ ABORT("GetThreadContext failed");
+
+ /* Push all registers that might point into the heap. Frame */
+ /* pointer registers are included in case client code was */
+ /* compiled with the 'omit frame pointer' optimisation. */
+# define PUSH1(reg) GC_push_one((word)context.reg)
+# define PUSH2(r1,r2) PUSH1(r1), PUSH1(r2)
+# define PUSH4(r1,r2,r3,r4) PUSH2(r1,r2), PUSH2(r3,r4)
+# if defined(I386)
+ PUSH4(Edi,Esi,Ebx,Edx), PUSH2(Ecx,Eax), PUSH1(Ebp);
+ sp = (ptr_t)context.Esp;
+# elif defined(X86_64)
+ PUSH4(Rax,Rcx,Rdx,Rbx); PUSH2(Rbp, Rsi); PUSH1(Rdi);
+ PUSH4(R8, R9, R10, R11); PUSH4(R12, R13, R14, R15);
+ sp = (ptr_t)context.Rsp;
+# elif defined(ARM32)
+ PUSH4(R0,R1,R2,R3),PUSH4(R4,R5,R6,R7),PUSH4(R8,R9,R10,R11),PUSH1(R12);
+ sp = (ptr_t)context.Sp;
+# elif defined(SHx)
+ PUSH4(R0,R1,R2,R3), PUSH4(R4,R5,R6,R7), PUSH4(R8,R9,R10,R11);
+ PUSH2(R12,R13), PUSH1(R14);
+ sp = (ptr_t)context.R15;
+# elif defined(MIPS)
+ PUSH4(IntAt,IntV0,IntV1,IntA0), PUSH4(IntA1,IntA2,IntA3,IntT0);
+ PUSH4(IntT1,IntT2,IntT3,IntT4), PUSH4(IntT5,IntT6,IntT7,IntS0);
+ PUSH4(IntS1,IntS2,IntS3,IntS4), PUSH4(IntS5,IntS6,IntS7,IntT8);
+ PUSH4(IntT9,IntK0,IntK1,IntS8);
+ sp = (ptr_t)context.IntSp;
+# elif defined(PPC)
+ PUSH4(Gpr0, Gpr3, Gpr4, Gpr5), PUSH4(Gpr6, Gpr7, Gpr8, Gpr9);
+ PUSH4(Gpr10,Gpr11,Gpr12,Gpr14), PUSH4(Gpr15,Gpr16,Gpr17,Gpr18);
+ PUSH4(Gpr19,Gpr20,Gpr21,Gpr22), PUSH4(Gpr23,Gpr24,Gpr25,Gpr26);
+ PUSH4(Gpr27,Gpr28,Gpr29,Gpr30), PUSH1(Gpr31);
+ sp = (ptr_t)context.Gpr1;
+# elif defined(ALPHA)
+ PUSH4(IntV0,IntT0,IntT1,IntT2), PUSH4(IntT3,IntT4,IntT5,IntT6);
+ PUSH4(IntT7,IntS0,IntS1,IntS2), PUSH4(IntS3,IntS4,IntS5,IntFp);
+ PUSH4(IntA0,IntA1,IntA2,IntA3), PUSH4(IntA4,IntA5,IntT8,IntT9);
+ PUSH4(IntT10,IntT11,IntT12,IntAt);
+ sp = (ptr_t)context.IntSp;
+# else
+# error "architecture is not supported"
+# endif
+ } /* ! current thread */
+
+ stack_min = GC_get_stack_min(thread->stack_base);
+
+ if (sp >= stack_min && sp < thread->stack_base) {
+# if DEBUG_WIN32_PTHREADS || DEBUG_WIN32_THREADS \
+ || DEBUG_CYGWIN_THREADS
+ GC_printf("Pushing thread from %p to %p for 0x%x from 0x%x\n",
+ sp, thread -> stack_base, thread -> id, me);
+# endif
+ GC_push_all_stack(sp, thread->stack_base);
+ } else {
+ WARN("Thread stack pointer 0x%lx out of range, pushing everything\n",
+ (unsigned long)(size_t)sp);
+ GC_push_all_stack(stack_min, thread->stack_base);
+ }
+ } /* thread looks live */
+}
+
+void GC_push_all_stacks(void)
+{
+ DWORD me = GetCurrentThreadId();
+ GC_bool found_me = FALSE;
+ size_t nthreads = 0;
+
+ if (GC_win32_dll_threads) {
+ int i;
+ LONG my_max = GC_get_max_thread_index();
+
+ for (i = 0; i <= my_max; i++) {
+ GC_thread t = (GC_thread)(dll_thread_table + i);
+ if (t -> in_use) {
+ ++nthreads;
+ GC_push_stack_for(t);
+ if (t -> id == me) found_me = TRUE;
+ }
+ }
+ } else {
+ GC_thread t;
+ int i;
+
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ for (t = GC_threads[i]; t != 0; t = t -> next) {
+ ++nthreads;
+ if (!KNOWN_FINISHED(t)) GC_push_stack_for(t);
+ if (t -> id == me) found_me = TRUE;
+ }
+ }
+ }
+ if (GC_print_stats == VERBOSE) {
+ GC_log_printf("Pushed %d thread stacks ", nthreads);
+ if (GC_win32_dll_threads) {
+ GC_log_printf("based on DllMain thread tracking\n");
+ } else {
+ GC_log_printf("\n");
+ }
+ }
+ if (!found_me && !GC_in_thread_creation)
+ ABORT("Collecting from unknown thread.");
+}
+
+void GC_get_next_stack(char *start, char **lo, char **hi)
+{
+ int i;
+# define ADDR_LIMIT (char *)(-1L)
+ char * current_min = ADDR_LIMIT;
+
+ if (GC_win32_dll_threads) {
+ LONG my_max = GC_get_max_thread_index();
+
+ for (i = 0; i <= my_max; i++) {
+ ptr_t s = (ptr_t)(dll_thread_table[i].stack_base);
+
+ if (0 != s && s > start && s < current_min) {
+ current_min = s;
+ }
+ }
+ } else {
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ GC_thread t;
+
+ for (t = GC_threads[i]; t != 0; t = t -> next) {
+ ptr_t s = (ptr_t)(t -> stack_base);
+
+ if (0 != s && s > start && s < current_min) {
+ current_min = s;
+ }
+ }
+ }
+ }
+ *hi = current_min;
+ if (current_min == ADDR_LIMIT) {
+ *lo = ADDR_LIMIT;
+ return;
+ }
+ *lo = GC_get_stack_min(current_min);
+ if (*lo < start) *lo = start;
+}
+
+#ifndef GC_PTHREADS
+
+/* We have no DllMain to take care of new threads. Thus we */
+/* must properly intercept thread creation. */
+
+typedef struct {
+ LPTHREAD_START_ROUTINE start;
+ LPVOID param;
+} thread_args;
+
+static DWORD WINAPI thread_start(LPVOID arg);
+
+void * GC_win32_start_inner(struct GC_stack_base *sb, LPVOID arg)
+{
+ void * ret;
+ thread_args *args = (thread_args *)arg;
+
+# if DEBUG_WIN32_THREADS
+ GC_printf("thread 0x%x starting...\n", GetCurrentThreadId());
+# endif
+
+ GC_register_my_thread(sb); /* This waits for an in-progress GC. */
+
+ /* Clear the thread entry even if we exit with an exception. */
+ /* This is probably pointless, since an uncaught exception is */
+ /* supposed to result in the process being killed. */
+#ifndef __GNUC__
+ __try {
+#endif /* __GNUC__ */
+ ret = (void *)(size_t)args->start (args->param);
+#ifndef __GNUC__
+ } __finally {
+#endif /* __GNUC__ */
+ GC_unregister_my_thread();
+ GC_free(args);
+#ifndef __GNUC__
+ }
+#endif /* __GNUC__ */
+
+# if DEBUG_WIN32_THREADS
+ GC_printf("thread 0x%x returned from start routine.\n",
+ GetCurrentThreadId());
+# endif
+ return ret;
+}
+
+DWORD WINAPI GC_win32_start(LPVOID arg)
+{
+ return (DWORD)(size_t)GC_call_with_stack_base(GC_win32_start_inner, arg);
+}
+
+GC_API HANDLE WINAPI GC_CreateThread(
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId )
+{
+ HANDLE thread_h = NULL;
+
+ thread_args *args;
+
+ if (!parallel_initialized) GC_init_parallel();
+ /* make sure GC is initialized (i.e. main thread is attached,
+ tls initialized) */
+
+# if DEBUG_WIN32_THREADS
+ GC_printf("About to create a thread from 0x%x\n", GetCurrentThreadId());
+# endif
+ if (GC_win32_dll_threads) {
+ return CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress,
+ lpParameter, dwCreationFlags, lpThreadId);
+ } else {
+ args = GC_malloc_uncollectable(sizeof(thread_args));
+ /* Handed off to and deallocated by child thread. */
+ if (0 == args) {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+
+ /* set up thread arguments */
+ args -> start = lpStartAddress;
+ args -> param = lpParameter;
+
+ GC_need_to_lock = TRUE;
+ thread_h = CreateThread(lpThreadAttributes,
+ dwStackSize, GC_win32_start,
+ args, dwCreationFlags,
+ lpThreadId);
+ if( thread_h == 0 ) GC_free( args );
+ return thread_h;
+ }
+}
+
+void WINAPI GC_ExitThread(DWORD dwExitCode)
+{
+ GC_unregister_my_thread();
+ ExitThread(dwExitCode);
+}
+
+uintptr_t GC_beginthreadex(
+ void *security, unsigned stack_size,
+ unsigned ( __stdcall *start_address )( void * ),
+ void *arglist, unsigned initflag, unsigned *thrdaddr)
+{
+ uintptr_t thread_h = -1L;
+
+ thread_args *args;
+
+ if (!parallel_initialized) GC_init_parallel();
+ /* make sure GC is initialized (i.e. main thread is attached,
+ tls initialized) */
+# if DEBUG_WIN32_THREADS
+ GC_printf("About to create a thread from 0x%x\n", GetCurrentThreadId());
+# endif
+
+ if (GC_win32_dll_threads) {
+ return _beginthreadex(security, stack_size, start_address,
+ arglist, initflag, thrdaddr);
+ } else {
+ args = GC_malloc_uncollectable(sizeof(thread_args));
+ /* Handed off to and deallocated by child thread. */
+ if (0 == args) {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return (uintptr_t)(-1);
+ }
+
+ /* set up thread arguments */
+ args -> start = (LPTHREAD_START_ROUTINE)start_address;
+ args -> param = arglist;
+
+ GC_need_to_lock = TRUE;
+ thread_h = _beginthreadex(security, stack_size,
+ (unsigned (__stdcall *) (void *))GC_win32_start,
+ args, initflag, thrdaddr);
+ if( thread_h == 0 ) GC_free( args );
+ return thread_h;
+ }
+}
+
+void GC_endthreadex(unsigned retval)
+{
+ GC_unregister_my_thread();
+ _endthreadex(retval);
+}
+
+#endif /* !GC_PTHREADS */
+
+#ifdef MSWINCE
+
+typedef struct {
+ HINSTANCE hInstance;
+ HINSTANCE hPrevInstance;
+ LPWSTR lpCmdLine;
+ int nShowCmd;
+} main_thread_args;
+
+DWORD WINAPI main_thread_start(LPVOID arg);
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPWSTR lpCmdLine, int nShowCmd)
+{
+ DWORD exit_code = 1;
+
+ main_thread_args args = {
+ hInstance, hPrevInstance, lpCmdLine, nShowCmd
+ };
+ HANDLE thread_h;
+ DWORD thread_id;
+
+ /* initialize everything */
+ GC_init();
+
+ /* start the main thread */
+ thread_h = GC_CreateThread(
+ NULL, 0, main_thread_start, &args, 0, &thread_id);
+
+ if (thread_h != NULL)
+ {
+ WaitForSingleObject (thread_h, INFINITE);
+ GetExitCodeThread (thread_h, &exit_code);
+ CloseHandle (thread_h);
+ }
+
+ GC_deinit();
+ DeleteCriticalSection(&GC_allocate_ml);
+
+ return (int) exit_code;
+}
+
+DWORD WINAPI main_thread_start(LPVOID arg)
+{
+ main_thread_args * args = (main_thread_args *) arg;
+
+ return (DWORD) GC_WinMain (args->hInstance, args->hPrevInstance,
+ args->lpCmdLine, args->nShowCmd);
+}
+
+# else /* !MSWINCE */
+
+/* Called by GC_init() - we hold the allocation lock. */
+void GC_thr_init(void) {
+ struct GC_stack_base sb;
+ int sb_result;
+
+ GC_ASSERT(I_HOLD_LOCK());
+ if (GC_thr_initialized) return;
+ GC_main_thread = GetCurrentThreadId();
+ GC_thr_initialized = TRUE;
+
+ /* Add the initial thread, so we can stop it. */
+ sb_result = GC_get_stack_base(&sb);
+ GC_ASSERT(sb_result == GC_SUCCESS);
+ GC_register_my_thread(&sb);
+}
+
+#ifdef GC_PTHREADS
+
+struct start_info {
+ void *(*start_routine)(void *);
+ void *arg;
+ GC_bool detached;
+};
+
+int GC_pthread_join(pthread_t pthread_id, void **retval) {
+ int result;
+ int i;
+ GC_thread joinee;
+
+# if DEBUG_CYGWIN_THREADS
+ GC_printf("thread 0x%x(0x%x) is joining thread 0x%x.\n",
+ (int)pthread_self(), GetCurrentThreadId(), (int)pthread_id);
+# endif
+# if DEBUG_WIN32_PTHREADS
+ GC_printf("thread 0x%x(0x%x) is joining thread 0x%x.\n",
+ (int)(pthread_self()).p, GetCurrentThreadId(), pthread_id.p);
+# endif
+
+ if (!parallel_initialized) GC_init_parallel();
+ /* Thread being joined might not have registered itself yet. */
+ /* After the join,thread id may have been recycled. */
+ /* FIXME: It would be better if this worked more like */
+ /* pthread_support.c. */
+
+ #ifndef GC_WIN32_PTHREADS
+ while ((joinee = GC_lookup_pthread(pthread_id)) == 0) Sleep(10);
+ #endif
+
+ result = pthread_join(pthread_id, retval);
+
+ #ifdef GC_WIN32_PTHREADS
+ /* win32_pthreads id are unique */
+ joinee = GC_lookup_pthread(pthread_id);
+ #endif
+
+ if (!GC_win32_dll_threads) {
+ LOCK();
+ GC_delete_gc_thread(joinee);
+ UNLOCK();
+ } /* otherwise dllmain handles it. */
+
+# if DEBUG_CYGWIN_THREADS
+ GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x.\n",
+ (int)pthread_self(), GetCurrentThreadId(), (int)pthread_id);
+# endif
+# if DEBUG_WIN32_PTHREADS
+ GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x.\n",
+ (int)(pthread_self()).p, GetCurrentThreadId(), pthread_id.p);
+# endif
+
+ return result;
+}
+
+/* Cygwin-pthreads calls CreateThread internally, but it's not
+ * easily interceptible by us..
+ * so intercept pthread_create instead
+ */
+int
+GC_pthread_create(pthread_t *new_thread,
+ const pthread_attr_t *attr,
+ void *(*start_routine)(void *), void *arg) {
+ int result;
+ struct start_info * si;
+
+ if (!parallel_initialized) GC_init_parallel();
+ /* make sure GC is initialized (i.e. main thread is attached) */
+ if (GC_win32_dll_threads) {
+ return pthread_create(new_thread, attr, start_routine, arg);
+ }
+
+ /* This is otherwise saved only in an area mmapped by the thread */
+ /* library, which isn't visible to the collector. */
+ si = GC_malloc_uncollectable(sizeof(struct start_info));
+ if (0 == si) return(EAGAIN);
+
+ si -> start_routine = start_routine;
+ si -> arg = arg;
+ if (attr != 0 &&
+ pthread_attr_getdetachstate(attr, &si->detached)
+ == PTHREAD_CREATE_DETACHED) {
+ si->detached = TRUE;
+ }
+
+# if DEBUG_CYGWIN_THREADS
+ GC_printf("About to create a thread from 0x%x(0x%x)\n",
+ (int)pthread_self(), GetCurrentThreadId);
+# endif
+# if DEBUG_WIN32_PTHREADS
+ GC_printf("About to create a thread from 0x%x(0x%x)\n",
+ (int)(pthread_self()).p, GetCurrentThreadId());
+# endif
+ GC_need_to_lock = TRUE;
+ result = pthread_create(new_thread, attr, GC_pthread_start, si);
+
+ if (result) { /* failure */
+ GC_free(si);
+ }
+
+ return(result);
+}
+
+void * GC_pthread_start_inner(struct GC_stack_base *sb, void * arg)
+{
+ struct start_info * si = arg;
+ void * result;
+ void *(*start)(void *);
+ void *start_arg;
+ DWORD thread_id = GetCurrentThreadId();
+ pthread_t pthread_id = pthread_self();
+ GC_thread me;
+ GC_bool detached;
+ int i;
+
+# if DEBUG_CYGWIN_THREADS
+ GC_printf("thread 0x%x(0x%x) starting...\n",(int)pthread_id,
+ thread_id);
+# endif
+# if DEBUG_WIN32_PTHREADS
+ GC_printf("thread 0x%x(0x%x) starting...\n",(int) pthread_id.p,
+ thread_id);
+# endif
+
+ GC_ASSERT(!GC_win32_dll_threads);
+ /* If a GC occurs before the thread is registered, that GC will */
+ /* ignore this thread. That's fine, since it will block trying to */
+ /* acquire the allocation lock, and won't yet hold interesting */
+ /* pointers. */
+ LOCK();
+ /* We register the thread here instead of in the parent, so that */
+ /* we don't need to hold the allocation lock during pthread_create. */
+ me = GC_register_my_thread_inner(sb, thread_id);
+ SET_PTHREAD_MAP_CACHE(pthread_id, thread_id);
+ UNLOCK();
+
+ start = si -> start_routine;
+ start_arg = si -> arg;
+ if (si-> detached) me -> flags |= DETACHED;
+ me -> pthread_id = pthread_id;
+
+ GC_free(si); /* was allocated uncollectable */
+
+ pthread_cleanup_push(GC_thread_exit_proc, (void *)me);
+ result = (*start)(start_arg);
+ me -> status = result;
+ pthread_cleanup_pop(1);
+
+# if DEBUG_CYGWIN_THREADS
+ GC_printf("thread 0x%x(0x%x) returned from start routine.\n",
+ (int)pthread_self(),GetCurrentThreadId());
+# endif
+# if DEBUG_WIN32_PTHREADS
+ GC_printf("thread 0x%x(0x%x) returned from start routine.\n",
+ (int)(pthread_self()).p, GetCurrentThreadId());
+# endif
+
+ return(result);
+}
+
+void * GC_pthread_start(void * arg)
+{
+ return GC_call_with_stack_base(GC_pthread_start_inner, arg);
+}
+
+void GC_thread_exit_proc(void *arg)
+{
+ GC_thread me = (GC_thread)arg;
+ int i;
+
+ GC_ASSERT(!GC_win32_dll_threads);
+# if DEBUG_CYGWIN_THREADS
+ GC_printf("thread 0x%x(0x%x) called pthread_exit().\n",
+ (int)pthread_self(),GetCurrentThreadId());
+# endif
+# if DEBUG_WIN32_PTHREADS
+ GC_printf("thread 0x%x(0x%x) called pthread_exit().\n",
+ (int)(pthread_self()).p,GetCurrentThreadId());
+# endif
+
+ LOCK();
+# if defined(THREAD_LOCAL_ALLOC)
+ GC_destroy_thread_local(&(me->tlfs));
+# endif
+ if (me -> flags & DETACHED) {
+ GC_delete_thread(GetCurrentThreadId());
+ } else {
+ /* deallocate it as part of join */
+ me -> flags |= FINISHED;
+ }
+ UNLOCK();
+}
+
+#ifndef GC_WIN32_PTHREADS
+/* win32 pthread does not support sigmask */
+/* nothing required here... */
+int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) {
+ if (!parallel_initialized) GC_init_parallel();
+ return pthread_sigmask(how, set, oset);
+}
+#endif
+
+int GC_pthread_detach(pthread_t thread)
+{
+ int result;
+ GC_thread thread_gc_id;
+
+ if (!parallel_initialized) GC_init_parallel();
+ LOCK();
+ thread_gc_id = GC_lookup_pthread(thread);
+ UNLOCK();
+ result = pthread_detach(thread);
+ if (result == 0) {
+ LOCK();
+ thread_gc_id -> flags |= DETACHED;
+ /* Here the pthread thread id may have been recycled. */
+ if (thread_gc_id -> flags & FINISHED) {
+ GC_delete_gc_thread(thread_gc_id);
+ }
+ UNLOCK();
+ }
+ return result;
+}
+
+#else /* !GC_PTHREADS */
+
+/*
+ * We avoid acquiring locks here, since this doesn't seem to be preemptable.
+ * This may run with an uninitialized collector, in which case we don't do much.
+ * This implies that no threads other than the main one should be created
+ * with an uninitialized collector. (The alternative of initializing
+ * the collector here seems dangerous, since DllMain is limited in what it
+ * can do.)
+ */
+#ifdef GC_DLL
+GC_API BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
+{
+ struct GC_stack_base sb;
+ DWORD thread_id;
+ int sb_result;
+ static int entry_count = 0;
+
+ if (parallel_initialized && !GC_win32_dll_threads) return TRUE;
+
+ switch (reason) {
+ case DLL_THREAD_ATTACH:
+ GC_ASSERT(entry_count == 0 || parallel_initialized);
+ ++entry_count; /* and fall through: */
+ case DLL_PROCESS_ATTACH:
+ /* This may run with the collector uninitialized. */
+ thread_id = GetCurrentThreadId();
+ if (parallel_initialized && GC_main_thread != thread_id) {
+ /* Don't lock here. */
+ sb_result = GC_get_stack_base(&sb);
+ GC_ASSERT(sb_result == GC_SUCCESS);
+# ifdef THREAD_LOCAL_ALLOC
+ ABORT("Cannot initialize thread local cache from DllMain");
+# endif
+ GC_register_my_thread_inner(&sb, thread_id);
+ } /* o.w. we already did it during GC_thr_init(), called by GC_init() */
+ break;
+
+ case DLL_THREAD_DETACH:
+ /* We are hopefully running in the context of the exiting thread. */
+ GC_ASSERT(parallel_initialized);
+ if (!GC_win32_dll_threads) return TRUE;
+ GC_delete_thread(GetCurrentThreadId());
+ break;
+
+ case DLL_PROCESS_DETACH:
+ {
+ int i;
+
+ if (!GC_win32_dll_threads) return TRUE;
+ for (i = 0; i <= GC_get_max_thread_index(); ++i)
+ {
+ if (AO_load(&(dll_thread_table[i].in_use)))
+ GC_delete_gc_thread(dll_thread_table + i);
+ }
+
+ GC_deinit();
+ DeleteCriticalSection(&GC_allocate_ml);
+ }
+ break;
+
+ }
+ return TRUE;
+}
+#endif /* GC_DLL */
+#endif /* !GC_PTHREADS */
+
+# endif /* !MSWINCE */
+
+/* Perform all initializations, including those that */
+/* may require allocation. */
+/* Called without allocation lock. */
+/* Must be called before a second thread is created. */
+void GC_init_parallel(void)
+{
+ if (parallel_initialized) return;
+ parallel_initialized = TRUE;
+ /* GC_init() calls us back, so set flag first. */
+
+ if (!GC_is_initialized) GC_init();
+ if (GC_win32_dll_threads) {
+ GC_need_to_lock = TRUE;
+ /* Cannot intercept thread creation. Hence we don't know if other */
+ /* threads exist. However, client is not allowed to create other */
+ /* threads before collector initialization. Thus it's OK not to */
+ /* lock before this. */
+ }
+ /* Initialize thread local free lists if used. */
+# if defined(THREAD_LOCAL_ALLOC)
+ LOCK();
+ GC_init_thread_local(&(GC_lookup_thread(GetCurrentThreadId())->tlfs));
+ UNLOCK();
+# endif
+}
+
+#if defined(USE_PTHREAD_LOCKS)
+ /* Support for pthread locking code. */
+ /* Pthread_mutex_try_lock may not win here, */
+ /* due to builtinsupport for spinning first? */
+
+volatile GC_bool GC_collecting = 0;
+ /* A hint that we're in the collector and */
+ /* holding the allocation lock for an */
+ /* extended period. */
+
+void GC_lock(void)
+{
+ pthread_mutex_lock(&GC_allocate_ml);
+}
+#endif /* USE_PTHREAD ... */
+
+# if defined(THREAD_LOCAL_ALLOC)
+
+/* Add thread-local allocation support. Microsoft uses __declspec(thread) */
+
+/* We must explicitly mark ptrfree and gcj free lists, since the free */
+/* list links wouldn't otherwise be found. We also set them in the */
+/* normal free lists, since that involves touching less memory than if */
+/* we scanned them normally. */
+void GC_mark_thread_local_free_lists(void)
+{
+ int i;
+ GC_thread p;
+
+ for (i = 0; i < THREAD_TABLE_SZ; ++i) {
+ for (p = GC_threads[i]; 0 != p; p = p -> next) {
+ GC_mark_thread_local_fls_for(&(p->tlfs));
+ }
+ }
+}
+
+#if defined(GC_ASSERTIONS)
+ /* Check that all thread-local free-lists are completely marked. */
+ /* also check that thread-specific-data structures are marked. */
+ void GC_check_tls(void) {
+ int i;
+ GC_thread p;
+
+ for (i = 0; i < THREAD_TABLE_SZ; ++i) {
+ for (p = GC_threads[i]; 0 != p; p = p -> next) {
+ GC_check_tls_for(&(p->tlfs));
+ }
+ }
+# if defined(USE_CUSTOM_SPECIFIC)
+ if (GC_thread_key != 0)
+ GC_check_tsd_marks(GC_thread_key);
+# endif
+ }
+#endif /* GC_ASSERTIONS */
+
+#endif /* THREAD_LOCAL_ALLOC ... */
+
+#endif /* GC_WIN32_THREADS */
diff --git a/tools/build/v2/engine/boost-jam.spec b/tools/build/v2/engine/boost-jam.spec
new file mode 100644
index 0000000000..bc572fc96e
--- /dev/null
+++ b/tools/build/v2/engine/boost-jam.spec
@@ -0,0 +1,64 @@
+Name: boost-jam
+Version: 3.1.19
+Summary: Build tool
+Release: 1
+Source: %{name}-%{version}.tgz
+
+License: Boost Software License, Version 1.0
+Group: Development/Tools
+URL: http://www.boost.org
+Packager: Rene Rivera <grafik@redshift-software.com>
+BuildRoot: /var/tmp/%{name}-%{version}.root
+
+%description
+Boost Jam is a build tool based on FTJam, which in turn is based on
+Perforce Jam. It contains significant improvements made to facilitate
+its use in the Boost Build System, but should be backward compatible
+with Perforce Jam.
+
+Authors:
+ Perforce Jam : Cristopher Seiwald
+ FT Jam : David Turner
+ Boost Jam : David Abrahams
+
+Copyright:
+ /+\
+ +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ \+/
+ License is hereby granted to use this software and distribute it
+ freely, as long as this copyright notice is retained and modifications
+ are clearly marked.
+ ALL WARRANTIES ARE HEREBY DISCLAIMED.
+
+Also:
+ Copyright 2001-2006 David Abrahams.
+ Copyright 2002-2006 Rene Rivera.
+ Copyright 2003-2006 Vladimir Prus.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+%prep
+%setup -n %{name}-%{version}
+
+%build
+LOCATE_TARGET=bin ./build.sh $BOOST_JAM_TOOLSET
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT%{_bindir}
+mkdir -p $RPM_BUILD_ROOT%{_docdir}/%{name}-%{version}
+install -m 755 bin/bjam $RPM_BUILD_ROOT%{_bindir}/bjam-%{version}
+ln -sf bjam-%{version} $RPM_BUILD_ROOT%{_bindir}/bjam
+cp -R *.html *.png *.css LICENSE*.txt images jam $RPM_BUILD_ROOT%{_docdir}/%{name}-%{version}
+
+find $RPM_BUILD_ROOT -name CVS -type d -exec rm -r {} \;
+
+%files
+%defattr(-,root,root)
+%attr(755,root,root) /usr/bin/*
+%doc %{_docdir}/%{name}-%{version}
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
diff --git a/tools/build/v2/engine/boost-no-inspect b/tools/build/v2/engine/boost-no-inspect
new file mode 100644
index 0000000000..8a06f3a707
--- /dev/null
+++ b/tools/build/v2/engine/boost-no-inspect
@@ -0,0 +1 @@
+this really out of our hands, so tell inspect to ignore directory \ No newline at end of file
diff --git a/tools/build/v2/engine/build.bat b/tools/build/v2/engine/build.bat
new file mode 100644
index 0000000000..f927b7697c
--- /dev/null
+++ b/tools/build/v2/engine/build.bat
@@ -0,0 +1,532 @@
+@ECHO OFF
+
+REM ~ Copyright 2002-2007 Rene Rivera.
+REM ~ Distributed under the Boost Software License, Version 1.0.
+REM ~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+setlocal
+goto Start
+
+
+:Set_Error
+color 00
+goto :eof
+
+
+:Clear_Error
+ver >nul
+goto :eof
+
+
+:Error_Print
+REM Output an error message and set the errorlevel to indicate failure.
+setlocal
+ECHO ###
+ECHO ### %1
+ECHO ###
+ECHO ### You can specify the toolset as the argument, i.e.:
+ECHO ### .\build.bat msvc
+ECHO ###
+ECHO ### Toolsets supported by this script are: borland, como, gcc, gcc-nocygwin,
+ECHO ### intel-win32, metrowerks, mingw, msvc, vc7, vc8, vc9, vc10
+ECHO ###
+call :Set_Error
+endlocal
+goto :eof
+
+
+:Test_Path
+REM Tests for the given file(executable) presence in the directories in the PATH
+REM environment variable. Additionaly sets FOUND_PATH to the path of the
+REM found file.
+call :Clear_Error
+setlocal
+set test=%~$PATH:1
+endlocal
+if not errorlevel 1 set FOUND_PATH=%~dp$PATH:1
+goto :eof
+
+
+:Test_Option
+REM Tests whether the given string is in the form of an option: "--*"
+call :Clear_Error
+setlocal
+set test=%1
+if not defined test (
+ call :Set_Error
+ goto Test_Option_End
+)
+set test=###%test%###
+set test=%test:"###=%
+set test=%test:###"=%
+set test=%test:###=%
+if not "-" == "%test:~1,1%" call :Set_Error
+:Test_Option_End
+endlocal
+goto :eof
+
+
+:Test_Empty
+REM Tests whether the given string is not empty
+call :Clear_Error
+setlocal
+set test=%1
+if not defined test (
+ call :Clear_Error
+ goto Test_Empty_End
+)
+set test=###%test%###
+set test=%test:"###=%
+set test=%test:###"=%
+set test=%test:###=%
+if not "" == "%test%" call :Set_Error
+:Test_Empty_End
+endlocal
+goto :eof
+
+
+:Call_If_Exists
+if EXIST %1 call %*
+goto :eof
+
+
+:Guess_Toolset
+REM Try and guess the toolset to bootstrap the build with...
+REM Sets BOOST_JAM_TOOLSET to the first found toolset.
+REM May also set BOOST_JAM_TOOLSET_ROOT to the
+REM location of the found toolset.
+
+call :Clear_Error
+call :Test_Empty %ProgramFiles%
+if not errorlevel 1 set ProgramFiles=C:\Program Files
+
+call :Clear_Error
+if NOT "_%VS100COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET=vc10"
+ set "BOOST_JAM_TOOLSET_ROOT=%VS100COMNTOOLS%..\..\VC\"
+ goto :eof)
+call :Clear_Error
+if EXIST "%ProgramFiles%\Microsoft Visual Studio 10.0\VC\VCVARSALL.BAT" (
+ set "BOOST_JAM_TOOLSET=vc10"
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio 10.0\VC\"
+ goto :eof)
+call :Clear_Error
+if NOT "_%VS90COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET=vc9"
+ set "BOOST_JAM_TOOLSET_ROOT=%VS90COMNTOOLS%..\..\VC\"
+ goto :eof)
+call :Clear_Error
+if EXIST "%ProgramFiles%\Microsoft Visual Studio 9.0\VC\VCVARSALL.BAT" (
+ set "BOOST_JAM_TOOLSET=vc9"
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio 9.0\VC\"
+ goto :eof)
+call :Clear_Error
+if NOT "_%VS80COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET=vc8"
+ set "BOOST_JAM_TOOLSET_ROOT=%VS80COMNTOOLS%..\..\VC\"
+ goto :eof)
+call :Clear_Error
+if EXIST "%ProgramFiles%\Microsoft Visual Studio 8\VC\VCVARSALL.BAT" (
+ set "BOOST_JAM_TOOLSET=vc8"
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio 8\VC\"
+ goto :eof)
+call :Clear_Error
+if NOT "_%VS71COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET=vc7"
+ set "BOOST_JAM_TOOLSET_ROOT=%VS71COMNTOOLS%\..\..\VC7\"
+ goto :eof)
+call :Clear_Error
+if NOT "_%VCINSTALLDIR%_" == "__" (
+ REM %VCINSTALLDIR% is also set for VC9 (and probably VC8)
+ set "BOOST_JAM_TOOLSET=vc7"
+ set "BOOST_JAM_TOOLSET_ROOT=%VCINSTALLDIR%\VC7\"
+ goto :eof)
+call :Clear_Error
+if EXIST "%ProgramFiles%\Microsoft Visual Studio .NET 2003\VC7\bin\VCVARS32.BAT" (
+ set "BOOST_JAM_TOOLSET=vc7"
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio .NET 2003\VC7\"
+ goto :eof)
+call :Clear_Error
+if EXIST "%ProgramFiles%\Microsoft Visual Studio .NET\VC7\bin\VCVARS32.BAT" (
+ set "BOOST_JAM_TOOLSET=vc7"
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio .NET\VC7\"
+ goto :eof)
+call :Clear_Error
+if NOT "_%MSVCDir%_" == "__" (
+ set "BOOST_JAM_TOOLSET=msvc"
+ set "BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\"
+ goto :eof)
+call :Clear_Error
+if EXIST "%ProgramFiles%\Microsoft Visual Studio\VC98\bin\VCVARS32.BAT" (
+ set "BOOST_JAM_TOOLSET=msvc"
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio\VC98\"
+ goto :eof)
+call :Clear_Error
+if EXIST "%ProgramFiles%\Microsoft Visual C++\VC98\bin\VCVARS32.BAT" (
+ set "BOOST_JAM_TOOLSET=msvc"
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual C++\VC98\"
+ goto :eof)
+call :Clear_Error
+call :Test_Path cl.exe
+if not errorlevel 1 (
+ set "BOOST_JAM_TOOLSET=msvc"
+ set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\"
+ goto :eof)
+call :Clear_Error
+call :Test_Path vcvars32.bat
+if not errorlevel 1 (
+ set "BOOST_JAM_TOOLSET=msvc"
+ call "%FOUND_PATH%VCVARS32.BAT"
+ set "BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\"
+ goto :eof)
+call :Clear_Error
+if EXIST "C:\Borland\BCC55\Bin\bcc32.exe" (
+ set "BOOST_JAM_TOOLSET=borland"
+ set "BOOST_JAM_TOOLSET_ROOT=C:\Borland\BCC55\"
+ goto :eof)
+call :Clear_Error
+call :Test_Path bcc32.exe
+if not errorlevel 1 (
+ set "BOOST_JAM_TOOLSET=borland"
+ set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\"
+ goto :eof)
+call :Clear_Error
+call :Test_Path icl.exe
+if not errorlevel 1 (
+ set "BOOST_JAM_TOOLSET=intel-win32"
+ set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\"
+ goto :eof)
+call :Clear_Error
+if EXIST "C:\MinGW\bin\gcc.exe" (
+ set "BOOST_JAM_TOOLSET=mingw"
+ set "BOOST_JAM_TOOLSET_ROOT=C:\MinGW\"
+ goto :eof)
+call :Clear_Error
+if NOT "_%CWFolder%_" == "__" (
+ set "BOOST_JAM_TOOLSET=metrowerks"
+ set "BOOST_JAM_TOOLSET_ROOT=%CWFolder%\"
+ goto :eof )
+call :Clear_Error
+call :Test_Path mwcc.exe
+if not errorlevel 1 (
+ set "BOOST_JAM_TOOLSET=metrowerks"
+ set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\..\"
+ goto :eof)
+call :Clear_Error
+call :Error_Print "Could not find a suitable toolset."
+goto :eof
+
+
+:Guess_Yacc
+REM Tries to find bison or yacc in common places so we can build the grammar.
+call :Clear_Error
+call :Test_Path yacc.exe
+if not errorlevel 1 (
+ set "YACC=yacc -d"
+ goto :eof)
+call :Clear_Error
+call :Test_Path bison.exe
+if not errorlevel 1 (
+ set "YACC=bison -d --yacc"
+ goto :eof)
+call :Clear_Error
+if EXIST "C:\Program Files\GnuWin32\bin\bison.exe" (
+ set "YACC=C:\Program Files\GnuWin32\bin\bison.exe" -d --yacc
+ goto :eof)
+call :Clear_Error
+call :Error_Print "Could not find Yacc to build the Jam grammar."
+goto :eof
+
+
+:Start
+set BOOST_JAM_TOOLSET=
+set BOOST_JAM_ARGS=
+
+REM If no arguments guess the toolset;
+REM or if first argument is an option guess the toolset;
+REM otherwise the argument is the toolset to use.
+call :Clear_Error
+call :Test_Empty %1
+if not errorlevel 1 (
+ call :Guess_Toolset
+ if not errorlevel 1 ( goto Setup_Toolset ) else ( goto Finish )
+)
+
+call :Clear_Error
+call :Test_Option %1
+if not errorlevel 1 (
+ call :Guess_Toolset
+ if not errorlevel 1 ( goto Setup_Toolset ) else ( goto Finish )
+)
+
+call :Clear_Error
+set BOOST_JAM_TOOLSET=%1
+shift
+goto Setup_Toolset
+
+
+:Setup_Toolset
+REM Setup the toolset command and options. This bit of code
+REM needs to be flexible enough to handle both when
+REM the toolset was guessed at and found, or when the toolset
+REM was indicated in the command arguments.
+REM NOTE: The strange multiple "if ?? == _toolset_" tests are that way
+REM because in BAT variables are subsituted only once during a single
+REM command. A complete "if ... ( commands ) else ( commands )"
+REM is a single command, even though it's in multiple lines here.
+:Setup_Args
+call :Clear_Error
+call :Test_Empty %1
+if not errorlevel 1 goto Config_Toolset
+call :Clear_Error
+call :Test_Option %1
+if errorlevel 1 (
+ set BOOST_JAM_ARGS=%BOOST_JAM_ARGS% %1
+ shift
+ goto Setup_Args
+)
+:Config_Toolset
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_metrowerks_" goto Skip_METROWERKS
+if NOT "_%CWFolder%_" == "__" (
+ set "BOOST_JAM_TOOLSET_ROOT=%CWFolder%\"
+ )
+set "PATH=%BOOST_JAM_TOOLSET_ROOT%Other Metrowerks Tools\Command Line Tools;%PATH%"
+set "BOOST_JAM_CC=mwcc -runtime ss -cwd include -DNT -lkernel32.lib -ladvapi32.lib -luser32.lib"
+set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
+set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
+set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
+set "_known_=1"
+:Skip_METROWERKS
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_msvc_" goto Skip_MSVC
+if NOT "_%MSVCDir%_" == "__" (
+ set "BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\"
+ )
+call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%bin\VCVARS32.BAT"
+if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
+ )
+set "BOOST_JAM_CC=cl /nologo /GZ /Zi /MLd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG kernel32.lib advapi32.lib user32.lib"
+set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
+set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
+set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
+set "_known_=1"
+:Skip_MSVC
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc7_" goto Skip_VC7
+if NOT "_%VS71COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET_ROOT=%VS71COMNTOOLS%..\..\VC7\"
+ )
+if "_%VCINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%bin\VCVARS32.BAT"
+if NOT "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ if "_%VCINSTALLDIR%_" == "__" (
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
+ ) )
+set "BOOST_JAM_CC=cl /nologo /GZ /Zi /MLd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG kernel32.lib advapi32.lib user32.lib"
+set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
+set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
+set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
+set "_known_=1"
+:Skip_VC7
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc8_" goto Skip_VC8
+if NOT "_%VS80COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET_ROOT=%VS80COMNTOOLS%..\..\VC\"
+ )
+if "_%VCINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%VCVARSALL.BAT" %BOOST_JAM_ARGS%
+if NOT "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ if "_%VCINSTALLDIR%_" == "__" (
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
+ ) )
+set "BOOST_JAM_CC=cl /nologo /RTC1 /Zi /MTd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG -wd4996 kernel32.lib advapi32.lib user32.lib"
+set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
+set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
+set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
+set "_known_=1"
+:Skip_VC8
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc9_" goto Skip_VC9
+if NOT "_%VS90COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET_ROOT=%VS90COMNTOOLS%..\..\VC\"
+ )
+if "_%VCINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%VCVARSALL.BAT" %BOOST_JAM_ARGS%
+if NOT "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ if "_%VCINSTALLDIR%_" == "__" (
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
+ ) )
+set "BOOST_JAM_CC=cl /nologo /RTC1 /Zi /MTd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG -wd4996 kernel32.lib advapi32.lib user32.lib"
+set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
+set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
+set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
+set "_known_=1"
+:Skip_VC9
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc10_" goto Skip_VC10
+if NOT "_%VS100COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET_ROOT=%VS100COMNTOOLS%..\..\VC\"
+ )
+if "_%VCINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%VCVARSALL.BAT" %BOOST_JAM_ARGS%
+if NOT "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ if "_%VCINSTALLDIR%_" == "__" (
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
+ ) )
+set "BOOST_JAM_CC=cl /nologo /RTC1 /Zi /MTd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG -wd4996 kernel32.lib advapi32.lib user32.lib"
+set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
+set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
+set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
+set "_known_=1"
+:Skip_VC10
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_borland_" goto Skip_BORLAND
+if "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ call :Test_Path bcc32.exe )
+if "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ if not errorlevel 1 (
+ set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\"
+ ) )
+if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%Bin;%PATH%"
+ )
+set "BOOST_JAM_CC=bcc32 -WC -w- -q -I%BOOST_JAM_TOOLSET_ROOT%Include -L%BOOST_JAM_TOOLSET_ROOT%Lib /DNT -nbootstrap"
+set "BOOST_JAM_OPT_JAM=-ejam0"
+set "BOOST_JAM_OPT_MKJAMBASE=-emkjambasejam0"
+set "BOOST_JAM_OPT_YYACC=-eyyacc0"
+set "_known_=1"
+:Skip_BORLAND
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_como_" goto Skip_COMO
+set "BOOST_JAM_CC=como -DNT"
+set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
+set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
+set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
+set "_known_=1"
+:Skip_COMO
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_gcc_" goto Skip_GCC
+set "BOOST_JAM_CC=gcc -DNT"
+set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
+set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
+set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
+set "_known_=1"
+:Skip_GCC
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_gcc-nocygwin_" goto Skip_GCC_NOCYGWIN
+set "BOOST_JAM_CC=gcc -DNT -mno-cygwin"
+set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
+set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
+set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
+set "_known_=1"
+:Skip_GCC_NOCYGWIN
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_intel-win32_" goto Skip_INTEL_WIN32
+set "BOOST_JAM_CC=icl -DNT /nologo kernel32.lib advapi32.lib user32.lib"
+set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
+set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
+set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
+set "_known_=1"
+:Skip_INTEL_WIN32
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_mingw_" goto Skip_MINGW
+if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
+ )
+set "BOOST_JAM_CC=gcc -DNT"
+set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
+set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
+set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
+set "_known_=1"
+:Skip_MINGW
+call :Clear_Error
+if "_%_known_%_" == "__" (
+ call :Error_Print "Unknown toolset: %BOOST_JAM_TOOLSET%"
+)
+if errorlevel 1 goto Finish
+
+echo ###
+echo ### Using '%BOOST_JAM_TOOLSET%' toolset.
+echo ###
+
+set YYACC_SOURCES=yyacc.c
+set MKJAMBASE_SOURCES=mkjambase.c
+set BJAM_SOURCES=
+set BJAM_SOURCES=%BJAM_SOURCES% command.c compile.c debug.c execnt.c expand.c filent.c glob.c hash.c
+set BJAM_SOURCES=%BJAM_SOURCES% hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c
+set BJAM_SOURCES=%BJAM_SOURCES% newstr.c option.c output.c parse.c pathunix.c regexp.c
+set BJAM_SOURCES=%BJAM_SOURCES% rules.c scan.c search.c subst.c timestamp.c variable.c modules.c
+set BJAM_SOURCES=%BJAM_SOURCES% strings.c filesys.c builtins.c md5.c pwd.c class.c w32_getreg.c native.c
+set BJAM_SOURCES=%BJAM_SOURCES% modules/set.c modules/path.c modules/regex.c
+set BJAM_SOURCES=%BJAM_SOURCES% modules/property-set.c modules/sequence.c modules/order.c
+
+set BJAM_UPDATE=
+:Check_Update
+call :Test_Empty %1
+if not errorlevel 1 goto Check_Update_End
+call :Clear_Error
+setlocal
+set test=%1
+set test=###%test%###
+set test=%test:"###=%
+set test=%test:###"=%
+set test=%test:###=%
+if "%test%" == "--update" set BJAM_UPDATE=update
+endlocal
+shift
+if not "_%BJAM_UPDATE%_" == "_update_" goto Check_Update
+:Check_Update_End
+if "_%BJAM_UPDATE%_" == "_update_" (
+ if not exist ".\bootstrap\jam0.exe" (
+ set BJAM_UPDATE=
+ )
+)
+
+@echo ON
+@if "_%BJAM_UPDATE%_" == "_update_" goto Skip_Bootstrap
+if exist bootstrap rd /S /Q bootstrap
+md bootstrap
+@if not exist jamgram.y goto Bootstrap_GrammarPrep
+@if not exist jamgramtab.h goto Bootstrap_GrammarPrep
+@goto Skip_GrammarPrep
+:Bootstrap_GrammarPrep
+%BOOST_JAM_CC% %BOOST_JAM_OPT_YYACC% %YYACC_SOURCES%
+@if not exist ".\bootstrap\yyacc0.exe" goto Skip_GrammarPrep
+.\bootstrap\yyacc0 jamgram.y jamgramtab.h jamgram.yy
+:Skip_GrammarPrep
+@if not exist jamgram.c goto Bootstrap_GrammarBuild
+@if not exist jamgram.h goto Bootstrap_GrammarBuild
+@goto Skip_GrammarBuild
+:Bootstrap_GrammarBuild
+@echo OFF
+if "_%YACC%_" == "__" (
+ call :Guess_Yacc
+)
+if errorlevel 1 goto Finish
+@echo ON
+%YACC% jamgram.y
+@if errorlevel 1 goto Finish
+del /f jamgram.c
+rename y.tab.c jamgram.c
+del /f jamgram.h
+rename y.tab.h jamgram.h
+:Skip_GrammarBuild
+@echo ON
+@if exist jambase.c goto Skip_Jambase
+%BOOST_JAM_CC% %BOOST_JAM_OPT_MKJAMBASE% %MKJAMBASE_SOURCES%
+@if not exist ".\bootstrap\mkjambase0.exe" goto Skip_Jambase
+.\bootstrap\mkjambase0 jambase.c Jambase
+:Skip_Jambase
+%BOOST_JAM_CC% %BOOST_JAM_OPT_JAM% %BJAM_SOURCES%
+:Skip_Bootstrap
+@if not exist ".\bootstrap\jam0.exe" goto Skip_Jam
+@if "_%BJAM_UPDATE%_" == "_update_" goto Skip_Clean
+.\bootstrap\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " clean
+:Skip_Clean
+@set args=%*
+@echo OFF
+:Set_Args
+setlocal
+call :Test_Empty %args%
+if not errorlevel 1 goto Set_Args_End
+set test=###%args:~0,2%###
+set test=%test:"###=%
+set test=%test:###"=%
+set test=%test:###=%
+set test=%test:~0,1%
+if "-" == "%test%" goto Set_Args_End
+endlocal
+set args=%args:~1%
+goto Set_Args
+:Set_Args_End
+@echo ON
+.\bootstrap\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " %args%
+:Skip_Jam
+
+:Finish
diff --git a/tools/build/v2/engine/build.jam b/tools/build/v2/engine/build.jam
new file mode 100644
index 0000000000..266b07a17d
--- /dev/null
+++ b/tools/build/v2/engine/build.jam
@@ -0,0 +1,1070 @@
+#~ Copyright 2002-2007 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Clean env vars of any "extra" empty values.
+for local v in ARGV CC CFLAGS LIBS
+{
+ local values ;
+ for local x in $($(v))
+ {
+ if $(x) != ""
+ {
+ values += $(x) ;
+ }
+ }
+ $(v) = $(values) ;
+}
+
+# Platform related specifics.
+if $(OS) = NT { rule .path { return "$(<:J=\\)" ; } ./ = "/" ; }
+else if $(OS) = OS2 { rule .path { return "$(<:J=\\)" ; } ./ = "/" ; }
+else if $(OS) = VMS { rule .path { return "[.$(<:J=/)]" ; } }
+else if $(OS) = MAC { rule .path { return ":$(<:J=\:)" ; } }
+else { rule .path { return "$(<:J=/)" ; } }
+if $(OS) = VMS { . = "_" ; }
+else { . = "." ; }
+./ ?= "" ;
+
+# Info about what we are building.
+_VERSION_ = 3 1 19 ;
+NAME = boost-jam ;
+VERSION = $(_VERSION_:J=$(.)) ;
+RELEASE = 1 ;
+LICENSE = LICENSE_1_0 ;
+
+# Generate development debug binaries?
+if --debug in $(ARGV)
+{
+ debug = true ;
+}
+
+if --profile in $(ARGV)
+{
+ profile = true ;
+}
+
+# Attempt to generate and/or build the grammar?
+if --grammar in $(ARGV)
+{
+ grammar = true ;
+}
+
+# Do we need to add a default build type argument?
+if ! ( --release in $(ARGV) ) &&
+ ! ( --debug in $(ARGV) ) &&
+ ! ( --profile in $(ARGV) )
+{
+ ARGV += --release ;
+}
+
+# Enable, and configure, Python hooks.
+with-python = ;
+python-location = [ MATCH --with-python=(.*) : $(ARGV) ] ;
+if $(python-location)
+{
+ with-python = true ;
+}
+if $(with-python)
+{
+ if $(OS) = NT
+ {
+ --python-include = [ .path $(python-location) include ] ;
+ --python-lib = ;
+ for local v in 26 25 24 23 22
+ {
+ --python-lib ?=
+ [ GLOB [ .path $(python-location) libs ] : "python$(v).lib" ]
+ [ GLOB $(python-location) [ .path $(python-location) libs ]
+ $(Path) $(PATH) $(path) : "python$(v).dll" ]
+ ;
+ if ! $(--python-lib[2])
+ {
+ --python-lib = ;
+ }
+ }
+ --python-lib = $(--python-lib[1]) ;
+ }
+ else if $(OS) = MACOSX
+ {
+ --python-include = [ .path $(python-location) Headers ] ;
+ --python-lib = $(python-location) Python ;
+ }
+ else
+ {
+ --python-include = ;
+ --python-lib = ;
+ for local v in 2.6 2.5 2.4 2.3 2.2
+ {
+ local inc = [ GLOB [ .path $(python-location) include ] : python$(v) ] ;
+ local lib = [ GLOB [ .path $(python-location) lib ] : libpython$(v)* ] ;
+ if $(inc) && $(lib)
+ {
+ --python-include ?= $(inc) ;
+ --python-lib ?= $(lib[1]:D) python$(v) ;
+ }
+ }
+ }
+}
+
+# Boehm GC?
+if --gc in $(ARGV)
+{
+ --boehm-gc = true ;
+}
+if $(--boehm-gc)
+{
+ --extra-include += [ .path [ PWD ] "boehm_gc" "include" ] ;
+}
+
+# Duma?
+if --duma in $(ARGV)
+{
+ --duma = true ;
+}
+if $(--duma)
+{
+ --extra-include += [ .path [ PWD ] "duma" ] ;
+}
+
+# An explicit root for the toolset? (trim spaces)
+toolset-root = [ MATCH --toolset-root=(.*) : $(ARGV) ] ;
+{
+ local t = [ MATCH "[ ]*(.*)" : $(toolset-root:J=" ") ] ;
+ toolset-root = ;
+ while $(t)
+ {
+ t = [ MATCH "([^ ]+)([ ]*)(.*)" : $(t) ] ;
+ toolset-root += $(t[1]) ;
+ if $(t[3]) { toolset-root += $(t[2]) ; }
+ t = $(t[3]) ;
+ }
+ toolset-root = $(toolset-root:J="") ;
+}
+
+# Configure the implemented toolsets. These are minimal
+# commands and options to compile the full Jam. When
+# adding new toolsets make sure to add them to the
+# "known" list also.
+
+rule toolset ( name command .type ? : opt.out + : opt.define * : flags * : linklibs * )
+{
+ .type ?= "" ;
+ tool.$(name)$(.type).cc ?= $(command) ;
+ tool.$(name)$(.type).opt.out ?= $(opt.out) ;
+ tool.$(name)$(.type).opt.define ?= $(opt.define) ;
+ tool.$(name)$(.type).flags ?= $(flags) ;
+ tool.$(name)$(.type).linklibs ?= $(linklibs) ;
+ if ! $(name) in $(toolsets) { toolsets += $(name) ; }
+}
+
+rule if-os ( os + : yes-opt * : no-opt * )
+ { if $(os) in $(OS) { return $(yes-opt) ; } else { return $(no-opt) ; } }
+
+rule opt ( type : yes-opt * : no-opt * )
+ { if $(type) in $(ARGV) { return $(yes-opt) ; } else { return $(no-opt) ; } }
+
+## HP-UX aCC compiler
+toolset acc cc : "-o " : -D
+ : -Ae
+ [ opt --release : -s -O3 ]
+ [ opt --debug : -g -pg ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Borland C++ 5.5.x
+toolset borland bcc32 : -e -n : /D
+ : -WC -w- -q "-I$(toolset-root)Include" "-L$(toolset-root)Lib"
+ [ opt --release : -O2 -vi -w-inl ]
+ [ opt --debug : -v -Od -vi- ]
+ -I$(--python-include) -I$(--extra-include)
+ : $(--python-lib[1]) ;
+## Generic Unix cc
+if ! $(CC) { CC = cc ; }
+toolset cc $(CC) : "-o " : -D
+ : $(CFLAGS)
+ [ opt --release : -s -O ]
+ [ opt --debug : -g ]
+ -I$(--python-include) -I$(--extra-include)
+ : $(LIBS) -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Comeau C/C++ 4.x
+toolset como como : "-o " : -D
+ : --c
+ [ opt --release : --inlining ]
+ [ opt --debug : --no_inlining ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Clang Linux 2.8+
+toolset clang clang : "-o " : -D
+ : -Wno-unused -Wno-format
+ [ opt --release : -Os ]
+ [ opt --debug : -g -O0 -fno-inline ]
+ [ opt --profile : -finline-functions -g ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## MacOSX Darwin, using GCC 2.9.x, 3.x
+toolset darwin cc : "-o " : -D
+ :
+ [ opt --release : -Wl,-x -O3 -finline-functions ]
+ [ opt --debug : -g -O0 -fno-inline -pg ]
+ [ opt --profile : -Wl,-x -O3 -finline-functions -g -pg ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## GCC 2.x, 3.x, 4.x
+toolset gcc gcc : "-o " : -D
+ : -pedantic -fno-strict-aliasing
+ [ opt --release : [ opt --symbols : -g : -s ] -O3 ]
+ [ opt --debug : -g -O0 -fno-inline ]
+ -I$(--python-include) -I$(--extra-include) -Wno-long-long
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## GCC 2.x, 3.x on CYGWIN but without cygwin1.dll
+toolset gcc-nocygwin gcc : "-o " : -D
+ : -s -O3 -mno-cygwin
+ [ opt --release : -finline-functions ]
+ [ opt --debug : -s -O3 -fno-inline -pg ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Intel C/C++ for Darwin
+toolset intel-darwin icc : "-o " : -D
+ :
+ [ opt --release : -O3 ]
+ [ opt --debug : -g -O0 -p ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Intel C/C++ for Linux
+toolset intel-linux icc : "-o " : -D
+ :
+ [ opt --release : -Xlinker -s -O3 ]
+ [ opt --debug : -g -O0 -p ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Intel C/C++ for Win32
+toolset intel-win32 icl : /Fe : -D
+ : /nologo
+ [ opt --release : /MT /O2 /Ob2 /Gy /GF /GA /GB ]
+ [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 ]
+ -I$(--python-include) -I$(--extra-include)
+ : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
+## KCC ?
+toolset kcc KCC : "-o " : -D
+ :
+ [ opt --release : -s +K2 ]
+ [ opt --debug : -g +K0 ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Borland Kylix
+toolset kylix bc++ : -o : -D
+ : -tC -q
+ [ opt --release : -O2 -vi -w-inl ]
+ [ opt --debug : -v -Od -vi- ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Metrowerks CodeWarrior 8.x
+{
+ # Even though CW can compile all files at once, it crashes if it tries in the bjam case.
+ local mwcc = ; if $(OS) = NT { mwcc = mwcc ; } else { mwcc = mwc$(OSPLAT:L) ; }
+ mwcc ?= mwcc ;
+ toolset metrowerks $(mwcc) : "-o " : -D
+ : -c -lang c -subsystem console -cwd include
+ [ opt --release : -runtime ss -opt full -inline all ]
+ [ opt --debug : -runtime ssd -opt none -inline off ]
+ -I$(--python-include) -I$(--extra-include) ;
+ toolset metrowerks $(mwcc) .link : "-o " :
+ : -subsystem console -lkernel32.lib -ladvapi32.lib -luser32.lib
+ [ opt --release : -runtime ss ]
+ [ opt --debug : -runtime ssd ]
+ : $(--python-lib[1]) ;
+}
+## MINGW GCC
+toolset mingw gcc : "-o " : -D
+ :
+ [ opt --release : -s -O3 -finline-functions ]
+ [ opt --debug : -g -O0 -fno-inline -pg ]
+ -I$(--python-include) -I$(--extra-include)
+ : $(--python-lib[2]) ;
+## MIPS Pro
+toolset mipspro cc : "-o " : -D
+ :
+ [ opt --release : -s -O3 -g0 -INLINE:none ]
+ [ opt --debug : -g -O0 -INLINE ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Microsoft Visual Studio C++ 6.x
+toolset msvc cl : /Fe /Fe /Fd /Fo : -D
+ : /nologo
+ [ opt --release : /ML /O2 /Ob2 /Gy /GF /GA /GB ]
+ [ opt --debug : /MLd /DEBUG /Z7 /Od /Ob0 ]
+ -I$(--python-include) -I$(--extra-include)
+ : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
+## QNX 6.x GCC 3.x/2.95.3
+toolset qcc qcc : "-o " : -D
+ : -Wc,-pedantic -Wc,-fno-strict-aliasing
+ [ opt --release : [ opt --symbols : -g ] -O3 -Wc,-finline-functions ]
+ [ opt --debug : -g -O0 -Wc,-fno-inline ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Qlogic Pathscale 2.4
+toolset pathscale pathcc : "-o " : -D
+ :
+ [ opt --release : -s -Ofast -O3 ]
+ [ opt --debug : -g ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Portland Group Pgi 6.2
+toolset pgi pgcc : "-o " : -D
+ :
+ [ opt --release : -s -O3 ]
+ [ opt --debug : -g ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Sun Workshop 6 C++
+toolset sun cc : "-o " : -D
+ :
+ [ opt --release : -s -fast -xO4 ]
+ [ opt --debug : -g ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Sun Workshop 6 C++ (old alias)
+toolset sunpro cc : "-o " : -D
+ :
+ [ opt --release : -s -fast -xO4 ]
+ [ opt --debug : -g ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## Compaq Alpha CXX
+toolset tru64cxx cc : "-o " : -D
+ :
+ [ opt --release : -s -O5 -inline speed ]
+ [ opt --debug : -g -O0 -pg ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
+## IBM VisualAge C++
+toolset vacpp xlc : "-o " : -D
+ :
+ [ opt --release : -s -O3 -qstrict -qinline ]
+ [ opt --debug : -g -qNOOPTimize -qnoinline -pg ]
+ -I$(--python-include) -I$(--extra-include)
+ : -L$(--python-lib[1]) -l$(--python-lib[2]) [ if-os AIX : -bmaxdata:0x40000000 ] ;
+## Microsoft Visual C++ .NET 7.x
+toolset vc7 cl : /Fe /Fe /Fd /Fo : -D
+ : /nologo
+ [ opt --release : /ML /O2 /Ob2 /Gy /GF /GA /GB ]
+ [ opt --debug : /MLd /DEBUG /Z7 /Od /Ob0 ]
+ -I$(--python-include) -I$(--extra-include)
+ : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
+## Microsoft Visual C++ 2005
+toolset vc8 cl : /Fe /Fe /Fd /Fo : -D
+ : /nologo
+ [ opt --release : /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
+ [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
+ -I$(--python-include) -I$(--extra-include)
+ : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
+## Microsoft Visual C++ 2008
+toolset vc9 cl : /Fe /Fe /Fd /Fo : -D
+ : /nologo
+ [ opt --release : /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
+ [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
+ -I$(--python-include) -I$(--extra-include)
+ : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
+## Microsoft Visual C++ 2010
+toolset vc10 cl : /Fe /Fe /Fd /Fo : -D
+ : /nologo
+ [ opt --release : /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
+ [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
+ -I$(--python-include) -I$(--extra-include)
+ : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
+## VMS/OpenVMS DEC C
+toolset vmsdecc cc : /OBJECT= : "/DEFINES=(" "," ")"
+ : /STANDARD=VAXC /PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES
+ [ opt --release : /OPTIMIZE /NODEBUG ]
+ [ opt --debug : /NOOPTIMIZE /DEBUG ]
+ ;
+toolset vmsdecc link .link : /EXECUTABLE= :
+ : /NOMAP
+ [ opt --release : /NODEBUG ]
+ [ opt --debug : /DEBUG ]
+ ;
+
+# First set the build commands and options according to the
+# preset toolset.
+toolset = [ MATCH --toolset=(.*) : $(ARGV) ] ;
+if ! $(toolset)
+{
+ # For some reason, the following test does not catch empty toolset.
+ ECHO "###" ;
+ ECHO "###" No toolset specified. Please use --toolset option. ;
+ ECHO "###" ;
+ ECHO "###" Known toolsets are: $(toolsets:J=", ") ;
+ EXIT "###" ;
+}
+if ! $(toolset) in $(toolsets)
+{
+ ECHO "###" ;
+ ECHO "###" Unknown toolset: $(toolset) ;
+ ECHO "###" ;
+ ECHO "###" Known toolsets are: $(toolsets:J=", ") ;
+ EXIT "###" ;
+}
+--cc = $(tool.$(toolset).cc) ;
+if $(tool.$(toolset).opt.out[2])
+{
+ if $(tool.$(toolset).opt.out[1]) = $(tool.$(toolset).opt.out[2])
+ {
+ --out = $(tool.$(toolset).opt.out[1]) ;
+ --dir = $(tool.$(toolset).opt.out[3-]) ;
+ }
+ else
+ {
+ --bin = $(tool.$(toolset).opt.out[1]) ;
+ --dir = $(tool.$(toolset).opt.out[2-]) ;
+ }
+}
+else
+{
+ --out = $(tool.$(toolset).opt.out) ;
+}
+--def = $(tool.$(toolset).opt.define) ;
+--flags = $(tool.$(toolset).flags) ;
+--defs = $(tool.$(toolset).defines) ;
+--libs = $(tool.$(toolset).linklibs) ;
+if $(tool.$(toolset).link.cc)
+{
+ --link = $(tool.$(toolset).link.cc) ;
+ if $(tool.$(toolset).link.opt.out[2])
+ {
+ if $(tool.$(toolset).link.opt.out[1]) = $(tool.$(toolset).link.opt.out[2])
+ {
+ --link-out = $(tool.$(toolset).link.opt.out[1]) ;
+ --link-dir = $(tool.$(toolset).link.opt.out[3-]) ;
+ }
+ else
+ {
+ --link-bin = $(tool.$(toolset).link.opt.out[1]) ;
+ --link-dir = $(tool.$(toolset).link.opt.out[2-]) ;
+ }
+ }
+ else
+ {
+ --link-out = $(tool.$(toolset).link.opt.out) ;
+ }
+ --link-def = $(tool.$(toolset).link.opt.define) ;
+ --link-flags = $(tool.$(toolset).link.flags) ;
+ --link-defs = $(tool.$(toolset).link.defines) ;
+ --link-libs = $(tool.$(toolset).link.linklibs) ;
+}
+
+# Put executables in platform-specific subdirectory.
+locate-target = $(LOCATE_TARGET) ;
+if $(OS) = VMS
+{
+ locate-target ?= bin$(.)vms ;
+ platform = vms ;
+}
+else if $(OS) = MAC
+{
+ locate-target ?= bin$(.)$(OS:L)$(OSPLAT:L) ;
+ platform = $(OS:L)$(OSPLAT:L) ;
+}
+else if $(OSPLAT)
+{
+ locate-target ?= bin$(.)$(OS:L)$(OSPLAT:L) ;
+ platform = $(OS:L)$(OSPLAT:L) ;
+}
+else
+{
+ locate-target ?= bin$(.)$(OS:L) ;
+ platform = $(OS:L) ;
+}
+if $(debug)
+{
+ locate-target = [ .path $(locate-target)$(.)debug ] ;
+}
+if $(profile)
+{
+ locate-target = [ .path $(locate-target)$(.)profile ] ;
+}
+else
+{
+ locate-target = [ .path $(locate-target) ] ;
+}
+
+if --show-locate-target in $(ARGV)
+{
+ ECHO $(locate-target) ;
+}
+
+# We have some different files for UNIX, VMS, and NT.
+jam.source =
+ command.c compile.c debug.c expand.c glob.c
+ hash.c hcache.c headers.c hdrmacro.c
+ jam.c jambase.c jamgram.c
+ lists.c make.c make1.c mem.c newstr.c
+ option.c output.c parse.c regexp.c rules.c
+ scan.c search.c subst.c w32_getreg.c
+ timestamp.c variable.c modules.c strings.c filesys.c
+ builtins.c pwd.c class.c native.c md5.c modules/set.c
+ modules/path.c modules/regex.c modules/property-set.c
+ modules/sequence.c modules/order.c
+ ;
+if $(OS) = NT
+{
+ jam.source += execnt.c filent.c pathunix.c ;
+}
+else if $(OS) = OS2
+{
+ jam.source += execunix.c fileos2.c pathunix.c ;
+}
+else if $(OS) = VMS
+{
+ jam.source += execvms.c filevms.c pathvms.c ;
+}
+else if $(OS) = MAC
+{
+ jam.source += execmac.c filemac.c pathmac.c ;
+}
+else
+{
+ jam.source += execunix.c fileunix.c pathunix.c ;
+}
+
+# Debug assertions, or not.
+if ! $(debug) || --noassert in $(ARGV)
+{
+ --defs += NDEBUG ;
+}
+
+# Enable some optional features.
+--defs += OPT_HEADER_CACHE_EXT ;
+--defs += OPT_GRAPH_DEBUG_EXT ;
+--defs += OPT_SEMAPHORE ;
+--defs += OPT_AT_FILES ;
+--defs += OPT_DEBUG_PROFILE ;
+
+# Bug fixes
+--defs += OPT_FIX_TARGET_VARIABLES_EXT ;
+#~ --defs += OPT_NO_EXTERNAL_VARIABLE_SPLIT ;
+
+# Improvements
+--defs += OPT_IMPROVED_PATIENCE_EXT ;
+
+# Use Boehm GC memory allocator?
+if $(--boehm-gc)
+{
+ --defs += OPT_BOEHM_GC ;
+ if $(debug)
+ {
+ --defs += GC_DEBUG ;
+ }
+}
+
+if $(--duma)
+{
+ --defs += OPT_DUMA ;
+}
+
+if ( $(OS) = NT ) && ! NT in $(--defs)
+{
+ --defs += NT ;
+}
+if $(OS) = VMS
+{
+ --defs += VMS ;
+}
+--defs += YYSTACKSIZE=5000 ;
+
+if $(with-python)
+{
+ --defs += HAVE_PYTHON ;
+}
+
+if $(debug)
+{
+ --defs += BJAM_NEWSTR_NO_ALLOCATE ;
+}
+
+
+# The basic symbolic targets...
+NOTFILE all clean dist ;
+ALWAYS clean ;
+
+# Utility rules and actions...
+rule .clean
+{
+ [DELETE] clean : $(<) ;
+}
+if $(OS) = NT { actions piecemeal together existing [DELETE] {
+ del /F /Q "$(>)"
+} }
+if $(UNIX) = true { actions piecemeal together existing [DELETE] {
+ rm -f "$(>)"
+} }
+if $(OS) = VMS { actions piecemeal together existing [DELETE] {
+ DELETE $(>[--2]:J=";*, ") $(>[-1]);*
+} }
+if $(OS) = NT {
+ --chmod+w = "attrib -r " ;
+}
+if $(UNIX) = true {
+ --chmod+w = "chmod +w " ;
+}
+if $(OS) = VMS {
+ --chmod+w = "SET FILE/PROT=(S:RWED) " ;
+}
+
+rule .mkdir
+{
+ NOUPDATE $(<) ;
+ if $(<:P) { DEPENDS $(<) : $(<:P) ; .mkdir $(<:P) ; }
+ if ! $(md<$(<)>) { [MKDIR] $(<) ; md<$(<)> = - ; }
+}
+if $(OS) = NT { actions [MKDIR] {
+ md "$(<)"
+} }
+if $(UNIX) = true { actions [MKDIR] {
+ mkdir "$(<)"
+} }
+if $(OS) = VMS { actions [MKDIR] {
+ CREATE/DIR $(<J=", ")
+} }
+
+rule .exe
+{
+ local exe = $(<) ;
+ if $(OS) = NT || ( $(UNIX) = true && $(OS) = CYGWIN ) || $(OS) = VMS { exe = $(exe:S=.exe) ; }
+ LOCATE on $(exe) = $(locate-target) ;
+ DEPENDS all : $(exe) ;
+ .mkdir $(locate-target) ;
+ if $(--link)
+ {
+ local objs = ;
+ for local s in $(>)
+ {
+ # Translate any subdir elements into a simple file name.
+ local o = [ MATCH "([^/]+)[/]?(.+)" : $(s) ] ;
+ o = $(o:J=_) ;
+ o = $(o:S=.o) ;
+ objs += $(o) ;
+ LOCATE on $(o) = $(locate-target) ;
+ DEPENDS $(exe) : $(o) ;
+ DEPENDS $(o) : $(s) ;
+ DEPENDS $(o) : $(locate-target) ;
+ [COMPILE] $(o) : $(s) ;
+ .clean $(o) ;
+ }
+ DEPENDS $(exe) : $(objs) ;
+ DEPENDS $(exe) : $(locate-target) ;
+ [COMPILE.LINK] $(exe) : $(objs) ;
+ .clean $(exe) ;
+ }
+ else
+ {
+ DEPENDS $(exe) : $(>) ;
+ DEPENDS $(exe) : $(locate-target) ;
+ [COMPILE] $(exe) : $(>) ;
+ .clean $(exe) ;
+ }
+ return $(exe) ;
+}
+if ! $(--def[2]) { actions [COMPILE] {
+ "$(--cc)" "$(--bin)$(<:D=)" "$(--dir)$(<:D)$(./)" $(--out)$(<) "$(--def)$(--defs)" "$(--flags)" "$(--libs)" "$(>)"
+} }
+else { actions [COMPILE] {
+ "$(--cc)" "$(--bin)$(<:D=)" "$(--dir)$(<:D)$(./)" $(--out)$(<) "$(--def[1])$(--defs:J=$(--def[2]))$(--def[3])" "$(--flags)" "$(--libs)" "$(>)"
+} }
+if $(OS) = VMS { actions [COMPILE.LINK] {
+ "$(--link)" $(--link-bin)$(<:D=) $(--link-dir)$(<:D)$(./) $(--link-out)$(<) $(--link-def)$(--link-defs) $(--link-flags) "$(--link-libs)" $(>J=", ")
+} }
+else { actions [COMPILE.LINK] {
+ "$(--link)" "$(--link-bin)$(<:D=)" "$(--link-dir)$(<:D)$(./)" "$(--link-out)$(<)" "$(--link-def)$(--link-defs)" "$(--link-flags)" "$(--link-libs)" "$(>)"
+} }
+
+rule .link
+{
+ DEPENDS all : $(<) ;
+ DEPENDS $(<) : $(>) ;
+ [LINK] $(<) : $(>) ;
+ .clean $(<) ;
+}
+if $(OS) = NT { actions [LINK] {
+ copy "$(>)" "$(<)"
+} }
+if $(UNIX) = true { actions [LINK] {
+ ln -fs "$(>)" "$(<)"
+} }
+if $(OS) = VMS { actions [LINK] {
+ COPY/REPLACE $(>) $(<)
+} }
+
+rule .copy
+{
+ DEPENDS all : $(<) ;
+ DEPENDS $(<) : $(>) ;
+ [COPY] $(<) : $(>) ;
+ .clean $(<) ;
+}
+
+# Will be redefined later.
+actions [COPY]
+{
+}
+
+
+rule .move
+{
+ DEPENDS $(<) : $(>) ;
+ [MOVE] $(<) : $(>) ;
+}
+if $(OS) = NT { actions [MOVE] {
+ del /f "$(<)"
+ rename "$(>)" "$(<)"
+} }
+if $(UNIX) = true { actions [MOVE] {
+ mv -f "$(>)" "$(<)"
+} }
+if $(OS) = VMS { actions [MOVE] {
+ RENAME "$(>)" "$(<)"
+} }
+
+# Generate the grammar tokens table, and the real yacc grammar.
+rule .yyacc
+{
+ local exe = [ .exe yyacc : yyacc.c ] ;
+ NOUPDATE $(exe) ;
+ DEPENDS $(<) : $(exe) $(>) ;
+ LEAVES $(<) ;
+ yyacc.exe on $(<) = $(exe:R=$(locate-target)) ;
+ [YYACC] $(<) : $(>) ;
+}
+actions [YYACC] {
+ $(--chmod+w)$(<[1])
+ $(--chmod+w)$(<[2])
+ "$(yyacc.exe)" "$(<)" "$(>)"
+}
+if $(grammar)
+{
+ .yyacc jamgram.y jamgramtab.h : jamgram.yy ;
+}
+else if $(debug)
+{
+ .exe yyacc : yyacc.c ;
+}
+
+# How to build the grammar.
+if $(OS) = NT
+{
+ SUFEXE = .exe ;
+ # try some other likely spellings...
+ PATH ?= $(Path) ;
+ PATH ?= $(path) ;
+}
+SUFEXE ?= "" ;
+
+yacc ?= [ GLOB $(PATH) : yacc$(SUFEXE) ] ;
+yacc ?= [ GLOB $(PATH) : bison$(SUFEXE) ] ;
+yacc ?= [ GLOB "$(ProgramFiles:J= )\\GnuWin32\\bin" "C:\\Program Files\\GnuWin32\\bin" : bison$(SUFEXE) ] ;
+yacc = $(yacc[1]) ;
+switch $(yacc:D=:S=)
+{
+ case bison : yacc += -d --yacc ;
+ case yacc : yacc += -d ;
+}
+if $(debug) && $(yacc)
+{
+ yacc += -t -v ;
+}
+yacc += $(YACCFLAGS) ;
+
+rule .yacc
+{
+ DEPENDS $(<) : $(>) ;
+ LEAVES $(<) ;
+ [YACC] $(<) : $(>) ;
+}
+if $(OS) = NT { actions [YACC] {
+ "$(yacc)" "$(>)"
+ if not errorlevel 1 (
+ del /f "$(<[1])"
+ rename y.tab$(<[1]:S) "$(<[1])"
+ del /f $(<[2])
+ rename y.tab$(<[2]:S) "$(<[2])"
+ ) else set _error_ =
+} }
+if $(UNIX) = true { actions [YACC] {
+ if ` "$(yacc)" "$(>)" ` ; then
+ mv -f y.tab$(<[1]:S) "$(<[1])"
+ mv -f y.tab$(<[2]:S) "$(<[2])"
+ else
+ exit 1
+ fi
+} }
+if $(OS) = VMS { actions [YACC] {
+ IF "$(yacc)" $(>)
+ THEN
+ RENAME y_tab$(<[1]:S) $(<[1])
+ RENAME y_tab$(<[2]:S) $(<[2])
+ ENDIF
+} }
+if $(grammar) && ! $(yacc)
+{
+ EXIT "Could not find the 'yacc' tool, and therefore can not build the grammar." ;
+}
+if $(grammar) && $(yacc)
+{
+ .yacc jamgram.c jamgram.h : jamgram.y ;
+}
+
+# How to build the compiled in jambase.
+rule .mkjambase
+{
+ local exe = [ .exe mkjambase : mkjambase.c ] ;
+ DEPENDS $(<) : $(exe) $(>) ;
+ LEAVES $(<) ;
+ mkjambase.exe on $(<) = $(exe:R=$(locate-target)) ;
+ [MKJAMBASE] $(<) : $(>) ;
+}
+actions [MKJAMBASE] {
+ $(--chmod+w)$(<)
+ $(mkjambase.exe) "$(<)" "$(>)"
+}
+if $(debug)
+{
+ .mkjambase jambase.c : Jambase ;
+}
+
+# How to build Jam.
+rule .jam
+{
+ $(>).exe = [ .exe $(>) : $(jam.source) ] ;
+ DEPENDS all : $($(>).exe) ;
+
+ # Make a copy under the old name.
+ $(<).exe = $(<:S=$($(>).exe:S)) ;
+ LOCATE on $($(<).exe) = $(locate-target) ;
+ .copy $($(<).exe) : $($(>).exe) ;
+ DEPENDS all : $($(<).exe) ;
+}
+.jam bjam : b2 ;
+
+
+# Scan sources for header dependencies.
+# WARNING: Yes those are *REAL TABS* below. DO NOT CHANGE,
+# under any circumstances, to spaces!! And the tabs
+# indenting this are so that if someone is in the mood to
+# replace tabs they hit this comment, and hopefully notice
+# their error.
+rule .scan
+{
+ HDRRULE on $(<:D=) = .hdr.scan ;
+ HDRSCAN on $(<:D=) = "^[ ]*#[ ]*include[ ]*([<\"][^\">]*[\">]).*$" ;
+}
+rule .hdr.scan
+{
+ local hdrs = [ GLOB . : $(>:D=) ] ;
+ INCLUDES $(<:D=) : $(hdrs:D=) ;
+ HDRRULE on $(>:D=) = .hdr.scan ;
+ HDRSCAN on $(>:D=) = "^[ ]*#[ ]*include[ ]*([<\"][^\">]*[\">]).*$" ;
+}
+.scan [ GLOB . : *.c ] ;
+
+# Distribution making from here on out. Assumes that
+# the docs are already built as html at ../doc/html. If
+# they aren't, then the docs are not included in the dist
+# archive.
+dist.license =
+ [ GLOB . : $(LICENSE).txt ]
+ ;
+dist.license = $(dist.license:D=)
+ [ GLOB [ .path .. .. .. ] : $(LICENSE).txt ]
+ [ GLOB [ .path .. boost ] : $(LICENSE).txt ] ;
+dist.docs =
+ [ GLOB . : *.png *.css *.html ]
+ ;
+dist.docs = $(dist.docs:D=)
+ [ GLOB [ .path images ] : *.png ]
+ [ GLOB [ .path jam ] : *.html ]
+ ;
+dist.source =
+ [ GLOB . : *.c *.h ]
+ ;
+dist.source = $(dist.source:D=)
+ $(dist.license[1])
+ $(dist.docs)
+ build.jam build.bat build.sh build_vms.com
+ Jambase
+ jamgram.y jamgram.yy
+ [ .path modules set.c ]
+ [ .path modules path.c ]
+ [ .path modules regex.c ]
+ [ .path modules property-set.c ]
+ [ .path modules sequence.c ]
+ [ .path modules order.c ]
+ [ GLOB [ .path boehm_gc ] : * ]
+ [ GLOB [ .path boehm_gc include ] : * ]
+ [ GLOB [ .path boehm_gc include private ] : * ]
+ [ GLOB [ .path boehm_gc cord ] : * ]
+ [ GLOB [ .path boehm_gc Mac_files ] : * ]
+ [ GLOB [ .path boehm_gc tests ] : * ]
+ [ GLOB [ .path boehm_gc doc ] : * ]
+ ;
+dist.bin =
+ bjam
+ ;
+dist.bin =
+ $(dist.license[1])
+ $(dist.bin:S=$(bjam.exe:S))
+ ;
+
+if $(OS) = NT
+{
+ zip ?= [ GLOB "$(ProgramFiles:J= )\\7-ZIP" "C:\\Program Files\\7-ZIP" : "7z.exe" ] ;
+ zip ?= [ GLOB "$(ProgramFiles:J= )\\7-ZIP" "C:\\Program Files\\7-ZIP" : "7zn.exe" ] ;
+ zip ?= [ GLOB $(PATH) : zip.exe ] ;
+ zip ?= zip ;
+ zip = $(zip[1]) ;
+ switch $(zip:D=:S=)
+ {
+ case 7z* : zip += a -r -tzip -mx=9 ;
+ case zip : zip += -9r ;
+ }
+ actions piecemeal [PACK] {
+ "$(zip)" "$(<)" "$(>)"
+ }
+ actions piecemeal [ZIP] {
+ "$(zip)" "$(<)" "$(>)"
+ }
+ actions piecemeal [COPY] {
+ copy /Y "$(>)" "$(<)" >NUL:
+ }
+}
+if $(UNIX) = true
+{
+ tar ?= [ GLOB $(PATH) : star bsdtar tar ] ;
+ tar = $(tar[1]) ;
+ switch $(tar:D=:S=)
+ {
+ case star : tar += -c artype=pax -D -d -to-stdout ;
+ case * : tar += -c -f - ;
+ }
+ actions [PACK] {
+ "$(tar)" "$(>)" | gzip -c9 > "$(<)"
+ }
+ #~ actions [PACK] {
+ #~ tar cf "$(<:S=.tar)" "$(>)"
+ #~ }
+ actions [ZIP] {
+ gzip -c9 "$(>)" > "$(<)"
+ }
+ actions [COPY] {
+ cp -Rpf "$(>)" "$(<)"
+ }
+}
+
+# The single binary, compressed.
+rule .binary
+{
+ local zip = ;
+ if $(OS) = NT { zip = $($(<).exe:S=.zip) ; }
+ if $(UNIX) = true { zip = $($(<).exe:S=.tgz) ; }
+ zip = $(zip:S=)-$(VERSION)-$(RELEASE)-$(platform)$(zip:S) ;
+ DEPENDS $(zip) : $($(<).exe) ;
+ DEPENDS dist : $(zip) ;
+ #~ LOCATE on $(zip) = $(locate-target) ;
+ if $(OS) = NT { [ZIP] $(zip) : $($(<).exe) ; }
+ if $(UNIX) = true { [PACK] $(zip) : $($(<).exe) ; }
+ .clean $(zip) ;
+}
+
+# Package some file.
+rule .package ( dst-dir : src-files + )
+{
+ local dst-files ;
+ local src-files-actual ;
+ for local src-path in $(src-files)
+ {
+ if ! [ GLOB $(src-path:P) : $(src-path:B) ] || [ CHECK_IF_FILE $(src-path) ]
+ {
+ local src-subdir = $(src-path:D) ;
+ local src-file = $(src-path) ;
+ while $(src-subdir:D) { src-subdir = $(src-subdir:D) ; }
+ if $(src-subdir) = ".."
+ {
+ src-file = $(src-file:D=) ;
+ }
+ dst-files += $(src-file:R=$(dst-dir)) ;
+ src-files-actual += $(src-path) ;
+ }
+ }
+
+ local pack = ;
+ if $(OS) = NT { pack = $(dst-dir).zip ; }
+ if $(UNIX) = true { pack = $(dst-dir).tgz ; }
+
+ DEPENDS dist : $(pack) ;
+ DEPENDS $(pack) : $(dst-files) ;
+
+ local dst-files-queue = $(dst-files) ;
+ for local src-path in $(src-files-actual)
+ {
+ local dst-file = $(dst-files-queue[1]) ;
+ dst-files-queue = $(dst-files-queue[2-]) ;
+ DEPENDS $(dst-file) : $(src-path) $(dst-file:D) ;
+ .mkdir $(dst-file:D) ;
+
+ [COPY] $(dst-file) : $(src-path) ;
+ .clean $(dst-file) ;
+ }
+
+ [PACK] $(pack) : $(dst-files) ;
+ .clean $(pack) ;
+}
+
+# RPM distro file.
+rpm-tool = [ GLOB $(PATH) : "rpmbuild" ] ;
+rpm-tool ?= [ GLOB $(PATH) : "rpm" ] ;
+rpm-tool = $(rpm-tool[1]) ;
+rule .rpm ( name : source )
+{
+ local rpm-arch = ;
+ switch $(OSPLAT)
+ {
+ case X86 : rpm-arch ?= i386 ;
+ case PPC : rpm-arch ?= ppc ;
+ case AXP : rpm-arch ?= alpha ;
+ # no guaranty for these:
+ case IA64 : rpm-arch ?= ia64 ;
+ case ARM : rpm-arch ?= arm ;
+ case SPARC : rpm-arch ?= sparc ;
+ case * : rpm-arch ?= other ;
+ }
+ local target = $(name)-rpm ;
+ NOTFILE $(target) ;
+ DEPENDS dist : $(target) ;
+ DEPENDS $(target) : $(name).$(rpm-arch).rpm $(name).src.rpm ;
+ DEPENDS $(name).$(rpm-arch).rpm : $(source) ;
+ DEPENDS $(name).src.rpm : $(name).$(rpm-arch).rpm ;
+ docs on $(target) = $(dist.docs:J=" ") ;
+ arch on $(target) = $(rpm-arch) ;
+ if $(rpm-arch) = ppc { target-opt on $(target) = --target= ; }
+ else { target-opt on $(target) = "--target " ; }
+ [RPM] $(target) : $(source) ;
+ .clean $(name).$(rpm-arch).rpm $(name).src.rpm ;
+}
+actions [RPM] {
+ set -e
+ export BOOST_JAM_TOOLSET="$(toolset)"
+ $(rpm-tool) -ta $(target-opt)$(arch) $(>) | tee rpm.out
+ cp `grep -e '^Wrote:' rpm.out | sed 's/^Wrote: //'` .
+ rm -f rpm.out
+}
+
+# The distribution targets. Don't bother with the targets if
+# distribution build not requested.
+if dist in $(ARGV)
+{
+ #~ .binary bjam ;
+ .package $(NAME)-$(VERSION) : $(dist.source) ;
+ .package $(NAME)-$(VERSION)-$(RELEASE)-$(platform) : $(dist.bin) ;
+ if $(rpm-tool)
+ {
+ #~ .rpm $(NAME)-$(VERSION)-$(RELEASE) : $(NAME)-$(VERSION).tgz ;
+ }
+}
diff --git a/tools/build/v2/engine/build.sh b/tools/build/v2/engine/build.sh
new file mode 100755
index 0000000000..f1fb806d3c
--- /dev/null
+++ b/tools/build/v2/engine/build.sh
@@ -0,0 +1,303 @@
+#!/bin/sh
+
+#~ Copyright 2002-2005 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Reset the toolset.
+BOOST_JAM_TOOLSET=
+
+# Run a command, and echo before doing so. Also checks the exit
+# status and quits if there was an error.
+echo_run ()
+{
+ echo "$@"
+ $@
+ r=$?
+ if test $r -ne 0 ; then
+ exit $r
+ fi
+}
+
+# Print an error message, and exit with a status of 1.
+error_exit ()
+{
+ echo "###"
+ echo "###" "$@"
+ echo "###"
+ echo "### You can specify the toolset as the argument, i.e.:"
+ echo "### ./build.sh gcc"
+ echo "###"
+ echo "### Toolsets supported by this script are:"
+ echo "### acc, como, darwin, gcc, intel-darwin, intel-linux, kcc, kylix,"
+ echo "### mipspro, mingw(msys), pathscale, pgi, qcc, sun, sunpro, tru64cxx, vacpp"
+ echo "###"
+ echo "### A special toolset; cc, is available which is used as a fallback"
+ echo "### when a more specific toolset is not found and the cc command is"
+ echo "### detected. The 'cc' toolset will use the CC, CFLAGS, and LIBS"
+ echo "### envrironment variables, if present."
+ echo "###"
+ exit 1
+}
+
+# Check that a command is in the PATH.
+test_path ()
+{
+ if `command -v command 1>/dev/null 2>/dev/null`; then
+ command -v $1 1>/dev/null 2>/dev/null
+ else
+ hash $1 1>/dev/null 2>/dev/null
+ fi
+}
+
+# Check that the OS name, as returned by "uname", is as given.
+test_uname ()
+{
+ if test_path uname; then
+ test `uname` = $*
+ fi
+}
+
+# Try and guess the toolset to bootstrap the build with...
+Guess_Toolset ()
+{
+ if test -r /mingw/bin/gcc ; then
+ BOOST_JAM_TOOLSET=mingw
+ BOOST_JAM_TOOLSET_ROOT=/mingw/
+ elif test_uname Darwin ; then BOOST_JAM_TOOLSET=darwin
+ elif test_uname IRIX ; then BOOST_JAM_TOOLSET=mipspro
+ elif test_uname IRIX64 ; then BOOST_JAM_TOOLSET=mipspro
+ elif test_uname OSF1 ; then BOOST_JAM_TOOLSET=tru64cxx
+ elif test_uname QNX && test_path qcc ; then BOOST_JAM_TOOLSET=qcc
+ elif test_path gcc ; then BOOST_JAM_TOOLSET=gcc
+ elif test_path icc ; then BOOST_JAM_TOOLSET=intel-linux
+ elif test -r /opt/intel/cc/9.0/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET=intel-linux
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/cc/9.0
+ elif test -r /opt/intel_cc_80/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET=intel-linux
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel_cc_80
+ elif test -r /opt/intel/compiler70/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET=intel-linux
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler70/ia32/
+ elif test -r /opt/intel/compiler60/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET=intel-linux
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler60/ia32/
+ elif test -r /opt/intel/compiler50/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET=intel-linux
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler50/ia32/
+ elif test_path pgcc ; then BOOST_JAM_TOOLSET=pgi
+ elif test_path pathcc ; then BOOST_JAM_TOOLSET=pathscale
+ elif test_path xlc ; then BOOST_JAM_TOOLSET=vacpp
+ elif test_path como ; then BOOST_JAM_TOOLSET=como
+ elif test_path KCC ; then BOOST_JAM_TOOLSET=kcc
+ elif test_path bc++ ; then BOOST_JAM_TOOLSET=kylix
+ elif test_path aCC ; then BOOST_JAM_TOOLSET=acc
+ elif test_uname HP-UX ; then BOOST_JAM_TOOLSET=acc
+ elif test -r /opt/SUNWspro/bin/cc ; then
+ BOOST_JAM_TOOLSET=sunpro
+ BOOST_JAM_TOOLSET_ROOT=/opt/SUNWspro/
+ # Test for "cc" as the default fallback.
+ elif test_path $CC ; then BOOST_JAM_TOOLSET=cc
+ elif test_path cc ; then
+ BOOST_JAM_TOOLSET=cc
+ CC=cc
+ fi
+ if test "$BOOST_JAM_TOOLSET" = "" ; then
+ error_exit "Could not find a suitable toolset."
+ fi
+}
+
+# The one option we support in the invocation
+# is the name of the toolset to force building
+# with.
+case "$1" in
+ --guess-toolset) Guess_Toolset ; echo "$BOOST_JAM_TOOLSET" ; exit 1 ;;
+ -*) Guess_Toolset ;;
+ ?*) BOOST_JAM_TOOLSET=$1 ; shift ;;
+ *) Guess_Toolset ;;
+esac
+BOOST_JAM_OPT_JAM="-o bootstrap/jam0"
+BOOST_JAM_OPT_MKJAMBASE="-o bootstrap/mkjambase0"
+BOOST_JAM_OPT_YYACC="-o bootstrap/yyacc0"
+case $BOOST_JAM_TOOLSET in
+ mingw)
+ if test -r ${BOOST_JAM_TOOLSET_ROOT}bin/gcc ; then
+ export PATH=${BOOST_JAM_TOOLSET_ROOT}bin:$PATH
+ fi
+ BOOST_JAM_CC="gcc -DNT"
+ ;;
+
+ gcc)
+ BOOST_JAM_CC=gcc
+ ;;
+
+ darwin)
+ BOOST_JAM_CC=cc
+ ;;
+
+ intel-darwin)
+ BOOST_JAM_CC=icc
+ ;;
+
+ intel-linux)
+ if test -r /opt/intel/cc/9.0/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/cc/9.0/
+ elif test -r /opt/intel_cc_80/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel_cc_80/
+ elif test -r /opt/intel/compiler70/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler70/ia32/
+ elif test -r /opt/intel/compiler60/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler60/ia32/
+ elif test -r /opt/intel/compiler50/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler50/ia32/
+ fi
+ if test -r ${BOOST_JAM_TOOLSET_ROOT}bin/iccvars.sh ; then
+ # iccvars doesn't change LD_RUN_PATH. We adjust LD_RUN_PATH
+ # here in order not to have to rely on ld.so.conf knowing the
+ # icc library directory. We do this before running iccvars.sh
+ # in order to allow a user to add modifications to LD_RUN_PATH
+ # in iccvars.sh.
+ if test -z "${LD_RUN_PATH}"; then
+ LD_RUN_PATH="${BOOST_JAM_TOOLSET_ROOT}lib"
+ else
+ LD_RUN_PATH="${BOOST_JAM_TOOLSET_ROOT}lib:${LD_RUN_PATH}"
+ fi
+ export LD_RUN_PATH
+ . ${BOOST_JAM_TOOLSET_ROOT}bin/iccvars.sh
+ fi
+ BOOST_JAM_CC=icc
+ ;;
+
+ vacpp)
+ BOOST_JAM_CC=xlc
+ ;;
+
+ como)
+ BOOST_JAM_CC="como --c"
+ ;;
+
+ kcc)
+ BOOST_JAM_CC=KCC
+ ;;
+
+ kylix)
+ BOOST_JAM_CC=bc++
+ ;;
+
+ mipspro)
+ BOOST_JAM_CC=cc
+ ;;
+
+ pathscale)
+ BOOST_JAM_CC=pathcc
+ ;;
+
+ pgi)
+ BOOST_JAM_CC=pgcc
+ ;;
+
+ sun*)
+ if test -z "${BOOST_JAM_TOOLSET_ROOT}" -a -r /opt/SUNWspro/bin/cc ; then
+ BOOST_JAM_TOOLSET_ROOT=/opt/SUNWspro/
+ fi
+ if test -r "${BOOST_JAM_TOOLSET_ROOT}bin/cc" ; then
+ PATH=${BOOST_JAM_TOOLSET_ROOT}bin:${PATH}
+ export PATH
+ fi
+ BOOST_JAM_CC=cc
+ ;;
+
+ clang*)
+ BOOST_JAM_CC="clang -Wno-unused -Wno-format"
+ BOOST_JAM_TOOLSET=clang
+ ;;
+
+ tru64cxx)
+ BOOST_JAM_CC=cc
+ ;;
+
+ acc)
+ BOOST_JAM_CC="cc -Ae"
+ ;;
+
+ cc)
+ if test -z "$CC" ; then CC=cc ; fi
+ BOOST_JAM_CC=$CC
+ BOOST_JAM_OPT_JAM="$BOOST_JAM_OPT_JAM $CFLAGS $LIBS"
+ BOOST_JAM_OPT_MKJAMBASE="$BOOST_JAM_OPT_MKJAMBASE $CFLAGS $LIBS"
+ BOOST_JAM_OPT_YYACC="$BOOST_JAM_OPT_YYACC $CFLAGS $LIBS"
+ ;;
+
+ qcc)
+ BOOST_JAM_CC=qcc
+ ;;
+
+ *)
+ error_exit "Unknown toolset: $BOOST_JAM_TOOLSET"
+ ;;
+esac
+
+echo "###"
+echo "### Using '$BOOST_JAM_TOOLSET' toolset."
+echo "###"
+
+YYACC_SOURCES="yyacc.c"
+MKJAMBASE_SOURCES="mkjambase.c"
+BJAM_SOURCES="\
+ command.c compile.c debug.c expand.c glob.c hash.c\
+ hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c\
+ newstr.c option.c output.c parse.c pathunix.c pathvms.c regexp.c\
+ rules.c scan.c search.c subst.c timestamp.c variable.c modules.c\
+ strings.c filesys.c builtins.c pwd.c class.c native.c md5.c w32_getreg.c\
+ modules/set.c modules/path.c modules/regex.c modules/property-set.c\
+ modules/sequence.c modules/order.c"
+case $BOOST_JAM_TOOLSET in
+ mingw)
+ BJAM_SOURCES="${BJAM_SOURCES} execnt.c filent.c"
+ ;;
+
+ *)
+ BJAM_SOURCES="${BJAM_SOURCES} execunix.c fileunix.c"
+ ;;
+esac
+
+BJAM_UPDATE=
+if test "$1" = "--update" -o "$2" = "--update" -o "$3" = "--update" -o "$4" = "--update" ; then
+ BJAM_UPDATE="update"
+fi
+if test "${BJAM_UPDATE}" = "update" -a ! -x "./bootstrap/jam0" ; then
+ BJAM_UPDATE=
+fi
+
+if test "${BJAM_UPDATE}" != "update" ; then
+ echo_run rm -rf bootstrap
+ echo_run mkdir bootstrap
+ if test ! -r jamgram.y -o ! -r jamgramtab.h ; then
+ echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_YYACC} ${YYACC_SOURCES}
+ if test -x "./bootstrap/yyacc0" ; then
+ echo_run ./bootstrap/yyacc0 jamgram.y jamgramtab.h jamgram.yy
+ fi
+ fi
+ if test ! -r jamgram.c -o ! -r jamgram.h ; then
+ if test_path yacc ; then YACC="yacc -d"
+ elif test_path bison ; then YACC="bison -y -d --yacc"
+ fi
+ echo_run $YACC jamgram.y
+ mv -f y.tab.c jamgram.c
+ mv -f y.tab.h jamgram.h
+ fi
+ if test ! -r jambase.c ; then
+ echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_MKJAMBASE} ${MKJAMBASE_SOURCES}
+ if test -x "./bootstrap/mkjambase0" ; then
+ echo_run ./bootstrap/mkjambase0 jambase.c Jambase
+ fi
+ fi
+ echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_JAM} ${BJAM_SOURCES}
+fi
+if test -x "./bootstrap/jam0" ; then
+ if test "${BJAM_UPDATE}" != "update" ; then
+ echo_run ./bootstrap/jam0 -f build.jam --toolset=$BOOST_JAM_TOOLSET "--toolset-root=$BOOST_JAM_TOOLSET_ROOT" clean
+ fi
+ echo_run ./bootstrap/jam0 -f build.jam --toolset=$BOOST_JAM_TOOLSET "--toolset-root=$BOOST_JAM_TOOLSET_ROOT" "$@"
+fi
diff --git a/tools/build/v2/engine/build_vms.com b/tools/build/v2/engine/build_vms.com
new file mode 100644
index 0000000000..965b634247
--- /dev/null
+++ b/tools/build/v2/engine/build_vms.com
@@ -0,0 +1,105 @@
+$ ! Copyright 2002-2003 Rene Rivera, Johan Nilsson.
+$ ! Distributed under the Boost Software License, Version 1.0.
+$ ! (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+$ !
+$ ! bootstrap build script for Jam
+$ !
+$ SAY :== WRITE SYS$OUTPUT
+$ !
+$ ON WARNING THEN CONTINUE
+$ !
+$ IF "" .NES. F$SEARCH("[.bootstrap_vms]*.*")
+$ THEN
+$ SAY "Cleaning previous boostrap files..."
+$ !
+$ SET FILE/PROTECTION=(S:RWED) [.bootstrap_vms]*.*;*
+$ DELETE [.bootstrap_vms]*.*;*
+$ ENDIF
+$ !
+$ IF "" .NES. F$SEARCH("bootstrap_vms.dir")
+$ THEN
+$ SAY "Removing previous boostrap directory..."
+$ !
+$ SET FILE/PROT=(S:RWED) bootstrap_vms.dir
+$ DELETE bootstrap_vms.dir;
+$ ENDIF
+$ !
+$ SAY "Creating boostrap directory..."
+$ !
+$ CREATE/DIR [.bootstrap_vms]
+$ !
+$ SAY "Building bootstrap jam..."
+$ !
+$ CC_FLAGS = "/DEFINE=VMS /STANDARD=VAXC /PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES "
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]builtins.obj builtins.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]command.obj command.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]compile.obj compile.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]execvms.obj execvms.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]expand.obj expand.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]filesys.obj filesys.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]filevms.obj filevms.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]glob.obj glob.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]hash.obj hash.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]hdrmacro.obj hdrmacro.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]headers.obj headers.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]jam.obj jam.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]jambase.obj jambase.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]jamgram.obj jamgram.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]lists.obj lists.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]make.obj make.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]make1.obj make1.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]modules.obj modules.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]newstr.obj newstr.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]option.obj option.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]parse.obj parse.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]pathvms.obj pathvms.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]pwd.obj pwd.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]regexp.obj regexp.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]rules.obj rules.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]scan.obj scan.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]search.obj search.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]strings.obj strings.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]subst.obj subst.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]timestamp.obj timestamp.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]variable.obj variable.c
+$ link -
+ /EXECUTABLE=[.bootstrap_vms]jam0.exe -
+ [.bootstrap_vms]builtins.obj, -
+ [.bootstrap_vms]command.obj, -
+ [.bootstrap_vms]compile.obj, -
+ [.bootstrap_vms]execvms.obj, -
+ [.bootstrap_vms]expand.obj, -
+ [.bootstrap_vms]filesys.obj, -
+ [.bootstrap_vms]filevms.obj, -
+ [.bootstrap_vms]glob.obj, -
+ [.bootstrap_vms]hash.obj, -
+ [.bootstrap_vms]hdrmacro.obj, -
+ [.bootstrap_vms]headers.obj, -
+ [.bootstrap_vms]jam.obj, -
+ [.bootstrap_vms]jambase.obj, -
+ [.bootstrap_vms]jamgram.obj, -
+ [.bootstrap_vms]lists.obj, -
+ [.bootstrap_vms]make.obj, -
+ [.bootstrap_vms]make1.obj, -
+ [.bootstrap_vms]modules.obj, -
+ [.bootstrap_vms]newstr.obj, -
+ [.bootstrap_vms]option.obj, -
+ [.bootstrap_vms]parse.obj, -
+ [.bootstrap_vms]pathvms.obj, -
+ [.bootstrap_vms]pwd.obj, -
+ [.bootstrap_vms]regexp.obj, -
+ [.bootstrap_vms]rules.obj, -
+ [.bootstrap_vms]scan.obj, -
+ [.bootstrap_vms]search.obj, -
+ [.bootstrap_vms]strings.obj, -
+ [.bootstrap_vms]subst.obj, -
+ [.bootstrap_vms]timestamp.obj, -
+ [.bootstrap_vms]variable.obj
+$ !
+$ SAY "Cleaning any previous build..."
+$ !
+$ MCR [.bootstrap_vms]jam0.exe -f build.jam --toolset=vmsdecc clean
+$ !
+$ SAY "Building Boost.Jam..."
+$ !
+$ MCR [.bootstrap_vms]jam0.exe -f build.jam --toolset=vmsdecc
diff --git a/tools/build/v2/engine/builtins.c b/tools/build/v2/engine/builtins.c
new file mode 100644
index 0000000000..b28a484ec4
--- /dev/null
+++ b/tools/build/v2/engine/builtins.c
@@ -0,0 +1,2310 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+#include "jam.h"
+
+#include "lists.h"
+#include "parse.h"
+#include "builtins.h"
+#include "rules.h"
+#include "filesys.h"
+#include "newstr.h"
+#include "regexp.h"
+#include "frames.h"
+#include "hash.h"
+#include "strings.h"
+#include "pwd.h"
+#include "pathsys.h"
+#include "make.h"
+#include "hdrmacro.h"
+#include "compile.h"
+#include "native.h"
+#include "variable.h"
+#include "timestamp.h"
+#include "md5.h"
+#include <ctype.h>
+
+#if defined(USE_EXECUNIX)
+# include <sys/types.h>
+# include <sys/wait.h>
+#else
+/*
+ NT does not have wait() and associated macros, it uses the return value
+ of system() instead. Status code group are documented at
+ http://msdn.microsoft.com/en-gb/library/ff565436.aspx
+*/
+# define WIFEXITED(w) (((w) & 0XFFFFFF00) == 0)
+# define WEXITSTATUS(w)(w)
+#endif
+
+/*
+ * builtins.c - builtin jam rules
+ *
+ * External routines:
+ *
+ * load_builtin() - define builtin rules
+ *
+ * Internal routines:
+ *
+ * builtin_depends() - DEPENDS/INCLUDES rule.
+ * builtin_echo() - ECHO rule.
+ * builtin_exit() - EXIT rule.
+ * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule.
+ * builtin_glob() - GLOB rule.
+ * builtin_match() - MATCH rule.
+ *
+ * 01/10/01 (seiwald) - split from compile.c
+ */
+
+
+/*
+ * compile_builtin() - define builtin rules
+ */
+
+#define P0 (PARSE *)0
+#define C0 (char *)0
+
+#if defined( OS_NT ) || defined( OS_CYGWIN )
+ LIST * builtin_system_registry ( PARSE *, FRAME * );
+ LIST * builtin_system_registry_names( PARSE *, FRAME * );
+#endif
+
+int glob( char * s, char * c );
+
+void backtrace ( FRAME * );
+void backtrace_line ( FRAME * );
+void print_source_line( PARSE * );
+
+
+RULE * bind_builtin( char * name, LIST * (* f)( PARSE *, FRAME * ), int flags, char * * args )
+{
+ argument_list* arg_list = 0;
+
+ if ( args )
+ {
+ arg_list = args_new();
+ lol_build( arg_list->data, args );
+ }
+
+ return new_rule_body( root_module(), name, arg_list,
+ parse_make( f, P0, P0, P0, C0, C0, flags ), 1 );
+}
+
+
+RULE * duplicate_rule( char * name, RULE * other )
+{
+ return import_rule( other, root_module(), name );
+}
+
+
+void load_builtins()
+{
+ duplicate_rule( "Always",
+ bind_builtin( "ALWAYS",
+ builtin_flags, T_FLAG_TOUCHED, 0 ) );
+
+ duplicate_rule( "Depends",
+ bind_builtin( "DEPENDS",
+ builtin_depends, 0, 0 ) );
+
+ duplicate_rule( "echo",
+ duplicate_rule( "Echo",
+ bind_builtin( "ECHO",
+ builtin_echo, 0, 0 ) ) );
+
+ {
+ char * args[] = { "message", "*", ":", "result-value", "?", 0 };
+ duplicate_rule( "exit",
+ duplicate_rule( "Exit",
+ bind_builtin( "EXIT",
+ builtin_exit, 0, args ) ) );
+ }
+
+ {
+ char * args[] = { "directories", "*", ":", "patterns", "*", ":", "case-insensitive", "?", 0 };
+ duplicate_rule( "Glob",
+ bind_builtin( "GLOB", builtin_glob, 0, args ) );
+ }
+
+ {
+ char * args[] = { "patterns", "*", 0 };
+ bind_builtin( "GLOB-RECURSIVELY",
+ builtin_glob_recursive, 0, args );
+ }
+
+ duplicate_rule( "Includes",
+ bind_builtin( "INCLUDES",
+ builtin_depends, 1, 0 ) );
+
+ {
+ char * args[] = { "targets", "*", ":", "targets-to-rebuild", "*", 0 };
+ bind_builtin( "REBUILDS",
+ builtin_rebuilds, 0, args );
+ }
+
+ duplicate_rule( "Leaves",
+ bind_builtin( "LEAVES",
+ builtin_flags, T_FLAG_LEAVES, 0 ) );
+
+ duplicate_rule( "Match",
+ bind_builtin( "MATCH",
+ builtin_match, 0, 0 ) );
+
+ {
+ char * args[] = { "string", ":", "delimiters" };
+ bind_builtin( "SPLIT_BY_CHARACTERS",
+ builtin_split_by_characters, 0, 0 );
+ }
+
+ duplicate_rule( "NoCare",
+ bind_builtin( "NOCARE",
+ builtin_flags, T_FLAG_NOCARE, 0 ) );
+
+ duplicate_rule( "NOTIME",
+ duplicate_rule( "NotFile",
+ bind_builtin( "NOTFILE",
+ builtin_flags, T_FLAG_NOTFILE, 0 ) ) );
+
+ duplicate_rule( "NoUpdate",
+ bind_builtin( "NOUPDATE",
+ builtin_flags, T_FLAG_NOUPDATE, 0 ) );
+
+ duplicate_rule( "Temporary",
+ bind_builtin( "TEMPORARY",
+ builtin_flags, T_FLAG_TEMP, 0 ) );
+
+ bind_builtin( "ISFILE",
+ builtin_flags, T_FLAG_ISFILE, 0 );
+
+ duplicate_rule( "HdrMacro",
+ bind_builtin( "HDRMACRO",
+ builtin_hdrmacro, 0, 0 ) );
+
+ /* FAIL_EXPECTED is used to indicate that the result of a target build
+ * action should be inverted (ok <=> fail) this can be useful when
+ * performing test runs from Jamfiles.
+ */
+ bind_builtin( "FAIL_EXPECTED",
+ builtin_flags, T_FLAG_FAIL_EXPECTED, 0 );
+
+ bind_builtin( "RMOLD",
+ builtin_flags, T_FLAG_RMOLD, 0 );
+
+ {
+ char * args[] = { "targets", "*", 0 };
+ bind_builtin( "UPDATE",
+ builtin_update, 0, args );
+ }
+
+ {
+ char * args[] = { "targets", "*",
+ ":", "log", "?",
+ ":", "ignore-minus-n", "?",
+ ":", "ignore-minus-q", "?", 0 };
+ bind_builtin( "UPDATE_NOW",
+ builtin_update_now, 0, args );
+ }
+
+ {
+ char * args[] = { "string", "pattern", "replacements", "+", 0 };
+ duplicate_rule( "subst",
+ bind_builtin( "SUBST",
+ builtin_subst, 0, args ) );
+ }
+
+ {
+ char * args[] = { "module", "?", 0 };
+ bind_builtin( "RULENAMES",
+ builtin_rulenames, 0, args );
+ }
+
+
+ {
+ char * args[] = { "module", "?", 0 };
+ bind_builtin( "VARNAMES",
+ builtin_varnames, 0, args );
+ }
+
+ {
+ char * args[] = { "module", "?", 0 };
+ bind_builtin( "DELETE_MODULE",
+ builtin_delete_module, 0, args );
+ }
+
+ {
+ char * args[] = { "source_module", "?",
+ ":", "source_rules", "*",
+ ":", "target_module", "?",
+ ":", "target_rules", "*",
+ ":", "localize", "?", 0 };
+ bind_builtin( "IMPORT",
+ builtin_import, 0, args );
+ }
+
+ {
+ char * args[] = { "module", "?", ":", "rules", "*", 0 };
+ bind_builtin( "EXPORT",
+ builtin_export, 0, args );
+ }
+
+ {
+ char * args[] = { "levels", "?", 0 };
+ bind_builtin( "CALLER_MODULE",
+ builtin_caller_module, 0, args );
+ }
+
+ {
+ char * args[] = { "levels", "?", 0 };
+ bind_builtin( "BACKTRACE",
+ builtin_backtrace, 0, args );
+ }
+
+ {
+ char * args[] = { 0 };
+ bind_builtin( "PWD",
+ builtin_pwd, 0, args );
+ }
+
+ {
+ char * args[] = { "target", "*", ":", "path", "*", 0 };
+ bind_builtin( "SEARCH_FOR_TARGET",
+ builtin_search_for_target, 0, args );
+ }
+
+ {
+ char * args[] = { "modules_to_import", "+", ":", "target_module", "?", 0 };
+ bind_builtin( "IMPORT_MODULE",
+ builtin_import_module, 0, args );
+ }
+
+ {
+ char * args[] = { "module", "?", 0 };
+ bind_builtin( "IMPORTED_MODULES",
+ builtin_imported_modules, 0, args );
+ }
+
+ {
+ char * args[] = { "instance_module", ":", "class_module", 0 };
+ bind_builtin( "INSTANCE",
+ builtin_instance, 0, args );
+ }
+
+ {
+ char * args[] = { "sequence", "*", 0 };
+ bind_builtin( "SORT",
+ builtin_sort, 0, args );
+ }
+
+ {
+ char * args[] = { "path_parts", "*", 0 };
+ bind_builtin( "NORMALIZE_PATH",
+ builtin_normalize_path, 0, args );
+ }
+
+ {
+ char * args[] = { "args", "*", 0 };
+ bind_builtin( "CALC",
+ builtin_calc, 0, args );
+ }
+
+ {
+ char * args[] = { "module", ":", "rule", 0 };
+ bind_builtin( "NATIVE_RULE",
+ builtin_native_rule, 0, args );
+ }
+
+ {
+ char * args[] = { "module", ":", "rule", ":", "version", 0 };
+ bind_builtin( "HAS_NATIVE_RULE",
+ builtin_has_native_rule, 0, args );
+ }
+
+ {
+ char * args[] = { "module", "*", 0 };
+ bind_builtin( "USER_MODULE",
+ builtin_user_module, 0, args );
+ }
+
+ {
+ char * args[] = { 0 };
+ bind_builtin( "NEAREST_USER_LOCATION",
+ builtin_nearest_user_location, 0, args );
+ }
+
+ {
+ char * args[] = { "file", 0 };
+ bind_builtin( "CHECK_IF_FILE",
+ builtin_check_if_file, 0, args );
+ }
+
+#ifdef HAVE_PYTHON
+ {
+ char * args[] = { "python-module", ":", "function", ":",
+ "jam-module", ":", "rule-name", 0 };
+ bind_builtin( "PYTHON_IMPORT_RULE",
+ builtin_python_import_rule, 0, args );
+ }
+#endif
+
+# if defined( OS_NT ) || defined( OS_CYGWIN )
+ {
+ char * args[] = { "key_path", ":", "data", "?", 0 };
+ bind_builtin( "W32_GETREG",
+ builtin_system_registry, 0, args );
+ }
+
+ {
+ char * args[] = { "key_path", ":", "result-type", 0 };
+ bind_builtin( "W32_GETREGNAMES",
+ builtin_system_registry_names, 0, args );
+ }
+# endif
+
+ {
+ char * args[] = { "command", ":", "*", 0 };
+ duplicate_rule( "SHELL",
+ bind_builtin( "COMMAND",
+ builtin_shell, 0, args ) );
+ }
+
+ {
+ char * args[] = { "string", 0 };
+ bind_builtin( "MD5",
+ builtin_md5, 0, args ) ;
+ }
+
+ {
+ char * args[] = { "name", ":", "mode", 0 };
+ bind_builtin( "FILE_OPEN",
+ builtin_file_open, 0, args );
+ }
+
+ {
+ char * args[] = { "string", ":", "width", 0 };
+ bind_builtin( "PAD",
+ builtin_pad, 0, args );
+ }
+
+ {
+ char * args[] = { "targets", "*", 0 };
+ bind_builtin( "PRECIOUS",
+ builtin_precious, 0, args );
+ }
+
+ {
+ char * args [] = { 0 };
+ bind_builtin( "SELF_PATH", builtin_self_path, 0, args );
+ }
+
+ {
+ char * args [] = { "path", 0 };
+ bind_builtin( "MAKEDIR", builtin_makedir, 0, args );
+ }
+
+ /* Initialize builtin modules. */
+ init_set();
+ init_path();
+ init_regex();
+ init_property_set();
+ init_sequence();
+ init_order();
+}
+
+
+/*
+ * builtin_calc() - CALC rule.
+ *
+ * The CALC rule performs simple mathematical operations on two arguments.
+ */
+
+LIST * builtin_calc( PARSE * parse, FRAME * frame )
+{
+ LIST * arg = lol_get( frame->args, 0 );
+
+ LIST * result = 0;
+ long lhs_value;
+ long rhs_value;
+ long result_value;
+ char buffer [ 16 ];
+ char const * lhs;
+ char const * op;
+ char const * rhs;
+
+ if ( arg == 0 ) return L0;
+ lhs = arg->string;
+
+ arg = list_next( arg );
+ if ( arg == 0 ) return L0;
+ op = arg->string;
+
+ arg = list_next( arg );
+ if ( arg == 0 ) return L0;
+ rhs = arg->string;
+
+ lhs_value = atoi( lhs );
+ rhs_value = atoi( rhs );
+
+ if ( strcmp( "+", op ) == 0 )
+ {
+ result_value = lhs_value + rhs_value;
+ }
+ else if ( strcmp( "-", op ) == 0 )
+ {
+ result_value = lhs_value - rhs_value;
+ }
+ else
+ {
+ return L0;
+ }
+
+ sprintf( buffer, "%ld", result_value );
+ result = list_new( result, newstr( buffer ) );
+ return result;
+}
+
+
+/*
+ * builtin_depends() - DEPENDS/INCLUDES rule.
+ *
+ * The DEPENDS/INCLUDES builtin rule appends each of the listed sources on the
+ * dependency/includes list of each of the listed targets. It binds both the
+ * targets and sources as TARGETs.
+ */
+
+LIST * builtin_depends( PARSE * parse, FRAME * frame )
+{
+ LIST * targets = lol_get( frame->args, 0 );
+ LIST * sources = lol_get( frame->args, 1 );
+ LIST * l;
+
+ for ( l = targets; l; l = list_next( l ) )
+ {
+ TARGET * t = bindtarget( l->string );
+
+ /* If doing INCLUDES, switch to the TARGET's include */
+ /* TARGET, creating it if needed. The internal include */
+ /* TARGET shares the name of its parent. */
+
+ if ( parse->num )
+ {
+ if ( !t->includes )
+ {
+ t->includes = copytarget( t );
+ t->includes->original_target = t;
+ }
+ t = t->includes;
+ }
+
+ t->depends = targetlist( t->depends, sources );
+ }
+
+ /* Enter reverse links */
+ for ( l = sources; l; l = list_next( l ) )
+ {
+ TARGET * s = bindtarget( l->string );
+ s->dependants = targetlist( s->dependants, targets );
+ }
+
+ return L0;
+}
+
+
+/*
+ * builtin_rebuilds() - REBUILDS rule.
+ *
+ * The REBUILDS builtin rule appends each of the listed rebuild-targets in its
+ * 2nd argument on the rebuilds list of each of the listed targets in its first
+ * argument.
+ */
+
+LIST * builtin_rebuilds( PARSE * parse, FRAME * frame )
+{
+ LIST * targets = lol_get( frame->args, 0 );
+ LIST * rebuilds = lol_get( frame->args, 1 );
+ LIST * l;
+
+ for ( l = targets; l; l = list_next( l ) )
+ {
+ TARGET * t = bindtarget( l->string );
+ t->rebuilds = targetlist( t->rebuilds, rebuilds );
+ }
+
+ return L0;
+}
+
+
+/*
+ * builtin_echo() - ECHO rule.
+ *
+ * The ECHO builtin rule echoes the targets to the user. No other actions are
+ * taken.
+ */
+
+LIST * builtin_echo( PARSE * parse, FRAME * frame )
+{
+ list_print( lol_get( frame->args, 0 ) );
+ printf( "\n" );
+ fflush( stdout );
+ return L0;
+}
+
+
+/*
+ * builtin_exit() - EXIT rule.
+ *
+ * The EXIT builtin rule echoes the targets to the user and exits the program
+ * with a failure status.
+ */
+
+LIST * builtin_exit( PARSE * parse, FRAME * frame )
+{
+ list_print( lol_get( frame->args, 0 ) );
+ printf( "\n" );
+ if ( lol_get( frame->args, 1 ) )
+ {
+ exit( atoi( lol_get( frame->args, 1 )->string ) );
+ }
+ else
+ {
+ exit( EXITBAD ); /* yeech */
+ }
+ return L0;
+}
+
+
+/*
+ * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule.
+ *
+ * Builtin_flags() marks the target with the appropriate flag, for use by make0().
+ * It binds each target as a TARGET.
+ */
+
+LIST * builtin_flags( PARSE * parse, FRAME * frame )
+{
+ LIST * l = lol_get( frame->args, 0 );
+ for ( ; l; l = list_next( l ) )
+ bindtarget( l->string )->flags |= parse->num;
+ return L0;
+}
+
+
+/*
+ * builtin_globbing() - GLOB rule.
+ */
+
+struct globbing
+{
+ LIST * patterns;
+ LIST * results;
+ LIST * case_insensitive;
+};
+
+
+static void downcase_inplace( char * p )
+{
+ for ( ; *p; ++p )
+ *p = tolower( *p );
+}
+
+
+static void builtin_glob_back
+(
+ void * closure,
+ char * file,
+ int status,
+ time_t time
+)
+{
+ PROFILE_ENTER( BUILTIN_GLOB_BACK );
+
+ struct globbing * globbing = (struct globbing *)closure;
+ LIST * l;
+ PATHNAME f;
+ string buf[ 1 ];
+
+ /* Null out directory for matching. We wish we had file_dirscan() pass up a
+ * PATHNAME.
+ */
+ path_parse( file, &f );
+ f.f_dir.len = 0;
+
+ /* For globbing, we unconditionally ignore current and parent directory
+ * items. Since they items always exist, there is no reason why caller of
+ * GLOB would want to see them. We could also change file_dirscan(), but
+ * then paths with embedded "." and ".." would not work anywhere.
+ */
+ if ( !strcmp( f.f_base.ptr, "." ) || !strcmp( f.f_base.ptr, ".." ) )
+ {
+ PROFILE_EXIT( BUILTIN_GLOB_BACK );
+ return;
+ }
+
+ string_new( buf );
+ path_build( &f, buf, 0 );
+
+ if ( globbing->case_insensitive )
+ downcase_inplace( buf->value );
+
+ for ( l = globbing->patterns; l; l = l->next )
+ {
+ if ( !glob( l->string, buf->value ) )
+ {
+ globbing->results = list_new( globbing->results, newstr( file ) );
+ break;
+ }
+ }
+
+ string_free( buf );
+
+ PROFILE_EXIT( BUILTIN_GLOB_BACK );
+}
+
+
+static LIST * downcase_list( LIST * in )
+{
+ LIST * result = 0;
+
+ string s[ 1 ];
+ string_new( s );
+
+ while ( in )
+ {
+ string_copy( s, in->string );
+ downcase_inplace( s->value );
+ result = list_append( result, list_new( 0, newstr( s->value ) ) );
+ in = in->next;
+ }
+
+ string_free( s );
+ return result;
+}
+
+
+LIST * builtin_glob( PARSE * parse, FRAME * frame )
+{
+ LIST * l = lol_get( frame->args, 0 );
+ LIST * r = lol_get( frame->args, 1 );
+
+ struct globbing globbing;
+
+ globbing.results = L0;
+ globbing.patterns = r;
+
+ globbing.case_insensitive
+# if defined( OS_NT ) || defined( OS_CYGWIN )
+ = l; /* Always case-insensitive if any files can be found. */
+# else
+ = lol_get( frame->args, 2 );
+# endif
+
+ if ( globbing.case_insensitive )
+ globbing.patterns = downcase_list( r );
+
+ for ( ; l; l = list_next( l ) )
+ file_dirscan( l->string, builtin_glob_back, &globbing );
+
+ if ( globbing.case_insensitive )
+ list_free( globbing.patterns );
+
+ return globbing.results;
+}
+
+
+static int has_wildcards( char const * str )
+{
+ size_t const index = strcspn( str, "[]*?" );
+ return str[ index ] == '\0' ? 0 : 1;
+}
+
+
+/*
+ * If 'file' exists, append 'file' to 'list'. Returns 'list'.
+ */
+
+static LIST * append_if_exists( LIST * list, char * file )
+{
+ time_t time;
+ timestamp( file, &time );
+ return time > 0
+ ? list_new( list, newstr( file ) )
+ : list;
+}
+
+
+LIST * glob1( char * dirname, char * pattern )
+{
+ LIST * plist = list_new( L0, pattern );
+ struct globbing globbing;
+
+ globbing.results = L0;
+ globbing.patterns = plist;
+
+ globbing.case_insensitive
+# if defined( OS_NT ) || defined( OS_CYGWIN )
+ = plist; /* always case-insensitive if any files can be found */
+# else
+ = L0;
+# endif
+
+ if ( globbing.case_insensitive )
+ globbing.patterns = downcase_list( plist );
+
+ file_dirscan( dirname, builtin_glob_back, &globbing );
+
+ if ( globbing.case_insensitive )
+ list_free( globbing.patterns );
+
+ list_free( plist );
+
+ return globbing.results;
+}
+
+
+LIST * glob_recursive( char * pattern )
+{
+ LIST * result = L0;
+
+ /* Check if there's metacharacters in pattern */
+ if ( !has_wildcards( pattern ) )
+ {
+ /* No metacharacters. Check if the path exists. */
+ result = append_if_exists(result, pattern);
+ }
+ else
+ {
+ /* Have metacharacters in the pattern. Split into dir/name. */
+ PATHNAME path[ 1 ];
+ path_parse( pattern, path );
+
+ if ( path->f_dir.ptr )
+ {
+ LIST * dirs = L0;
+ string dirname[ 1 ];
+ string basename[ 1 ];
+ string_new( dirname );
+ string_new( basename );
+
+ string_append_range( dirname, path->f_dir.ptr,
+ path->f_dir.ptr + path->f_dir.len );
+
+ path->f_grist.ptr = 0;
+ path->f_grist.len = 0;
+ path->f_dir.ptr = 0;
+ path->f_dir.len = 0;
+ path_build( path, basename, 0 );
+
+ dirs = has_wildcards( dirname->value )
+ ? glob_recursive( dirname->value )
+ : list_new( dirs, dirname->value );
+
+ if ( has_wildcards( basename->value ) )
+ {
+ for ( ; dirs; dirs = dirs->next )
+ result = list_append( result, glob1( dirs->string,
+ basename->value ) );
+ }
+ else
+ {
+ string file_string[ 1 ];
+ string_new( file_string );
+
+ /* No wildcard in basename. */
+ for ( ; dirs; dirs = dirs->next )
+ {
+ path->f_dir.ptr = dirs->string;
+ path->f_dir.len = strlen( dirs->string );
+ path_build( path, file_string, 0 );
+
+ result = append_if_exists( result, file_string->value );
+
+ string_truncate( file_string, 0 );
+ }
+
+ string_free( file_string );
+ }
+
+ string_free( dirname );
+ string_free( basename );
+ }
+ else
+ {
+ /** No directory, just a pattern. */
+ result = list_append( result, glob1( ".", pattern ) );
+ }
+ }
+
+ return result;
+}
+
+
+LIST * builtin_glob_recursive( PARSE * parse, FRAME * frame )
+{
+ LIST * result = L0;
+ LIST * l = lol_get( frame->args, 0 );
+ for ( ; l; l = l->next )
+ result = list_append( result, glob_recursive( l->string ) );
+ return result;
+}
+
+
+/*
+ * builtin_match() - MATCH rule, regexp matching.
+ */
+
+LIST * builtin_match( PARSE * parse, FRAME * frame )
+{
+ LIST * l;
+ LIST * r;
+ LIST * result = 0;
+
+ string buf[ 1 ];
+ string_new( buf );
+
+ /* For each pattern */
+
+ for ( l = lol_get( frame->args, 0 ); l; l = l->next )
+ {
+ /* Result is cached and intentionally never freed. */
+ regexp * re = regex_compile( l->string );
+
+ /* For each string to match against. */
+ for ( r = lol_get( frame->args, 1 ); r; r = r->next )
+ {
+ if ( regexec( re, r->string ) )
+ {
+ int i;
+ int top;
+
+ /* Find highest parameter */
+
+ for ( top = NSUBEXP; top-- > 1; )
+ if ( re->startp[ top ] )
+ break;
+
+ /* And add all parameters up to highest onto list. */
+ /* Must have parameters to have results! */
+ for ( i = 1; i <= top; ++i )
+ {
+ string_append_range( buf, re->startp[ i ], re->endp[ i ] );
+ result = list_new( result, newstr( buf->value ) );
+ string_truncate( buf, 0 );
+ }
+ }
+ }
+ }
+
+ string_free( buf );
+ return result;
+}
+
+LIST * builtin_split_by_characters( PARSE * parse, FRAME * frame )
+{
+ LIST * l1 = lol_get( frame->args, 0 );
+ LIST * l2 = lol_get( frame->args, 1 );
+
+ LIST * result = 0;
+
+ char* s = strdup (l1->string);
+ char* delimiters = l2->string;
+ char* t;
+
+ t = strtok (s, delimiters);
+ while (t)
+ {
+ result = list_new(result, newstr(t));
+ t = strtok (NULL, delimiters);
+ }
+
+ free (s);
+
+ return result;
+}
+
+LIST * builtin_hdrmacro( PARSE * parse, FRAME * frame )
+{
+ LIST * l = lol_get( frame->args, 0 );
+
+ for ( ; l; l = list_next( l ) )
+ {
+ TARGET * t = bindtarget( l->string );
+
+ /* Scan file for header filename macro definitions. */
+ if ( DEBUG_HEADER )
+ printf( "scanning '%s' for header file macro definitions\n",
+ l->string );
+
+ macro_headers( t );
+ }
+
+ return L0;
+}
+
+
+/*
+ * builtin_rulenames() - RULENAMES ( MODULE ? ).
+ *
+ * Returns a list of the non-local rule names in the given MODULE. If MODULE is
+ * not supplied, returns the list of rule names in the global module.
+ */
+
+static void add_rule_name( void * r_, void * result_ )
+{
+ RULE * r = (RULE *)r_;
+ LIST * * result = (LIST * *)result_;
+ if ( r->exported )
+ *result = list_new( *result, copystr( r->name ) );
+}
+
+
+LIST * builtin_rulenames( PARSE * parse, FRAME * frame )
+{
+ LIST * arg0 = lol_get( frame->args, 0 );
+ LIST * result = L0;
+ module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
+
+ if ( source_module->rules )
+ hashenumerate( source_module->rules, add_rule_name, &result );
+ return result;
+}
+
+
+/*
+ * builtin_varnames() - VARNAMES ( MODULE ? ).
+ *
+ * Returns a list of the variable names in the given MODULE. If MODULE is not
+ * supplied, returns the list of variable names in the global module.
+ */
+
+/* helper function for builtin_varnames(), below. Used with hashenumerate, will
+ * prepend the key of each element to the list
+ */
+static void add_hash_key( void * np, void * result_ )
+{
+ LIST * * result = (LIST * *)result_;
+ *result = list_new( *result, copystr( *(char * *)np ) );
+}
+
+
+static struct hash * get_running_module_vars()
+{
+ struct hash * dummy;
+ struct hash * vars = NULL;
+ /* Get the global variables pointer (that of the currently running module).
+ */
+ var_hash_swap( &vars );
+ dummy = vars;
+ /* Put the global variables pointer in its right place. */
+ var_hash_swap( &dummy );
+ return vars;
+}
+
+
+LIST * builtin_varnames( PARSE * parse, FRAME * frame )
+{
+ LIST * arg0 = lol_get( frame->args, 0 );
+ LIST * result = L0;
+ module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
+
+ /* The running module _always_ has its 'variables' member set to NULL due to
+ * the way enter_module() and var_hash_swap() work.
+ */
+ struct hash * vars = source_module == frame->module
+ ? get_running_module_vars()
+ : source_module->variables;
+
+ if ( vars )
+ hashenumerate( vars, add_hash_key, &result );
+ return result;
+}
+
+
+/*
+ * builtin_delete_module() - MODULE ?.
+ *
+ * Clears all rules and variables from the given module.
+ */
+
+LIST * builtin_delete_module( PARSE * parse, FRAME * frame )
+{
+ LIST * arg0 = lol_get( frame->args, 0 );
+ LIST * result = L0;
+ module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
+ delete_module( source_module );
+ return result;
+}
+
+
+static void unknown_rule( FRAME * frame, char * key, char * module_name, char * rule_name )
+{
+ backtrace_line( frame->prev );
+ printf( "%s error: rule \"%s\" unknown in module \"%s\"\n", key, rule_name, module_name );
+ backtrace( frame->prev );
+ exit( 1 );
+}
+
+
+/*
+ * builtin_import() - IMPORT
+ * (
+ * SOURCE_MODULE ? :
+ * SOURCE_RULES * :
+ * TARGET_MODULE ? :
+ * TARGET_RULES * :
+ * LOCALIZE ?
+ * )
+ *
+ * The IMPORT rule imports rules from the SOURCE_MODULE into the TARGET_MODULE
+ * as local rules. If either SOURCE_MODULE or TARGET_MODULE is not supplied, it
+ * refers to the global module. SOURCE_RULES specifies which rules from the
+ * SOURCE_MODULE to import; TARGET_RULES specifies the names to give those rules
+ * in TARGET_MODULE. If SOURCE_RULES contains a name which doesn't correspond to
+ * a rule in SOURCE_MODULE, or if it contains a different number of items than
+ * TARGET_RULES, an error is issued. If LOCALIZE is specified, the rules will be
+ * executed in TARGET_MODULE, with corresponding access to its module local
+ * variables.
+ */
+
+LIST * builtin_import( PARSE * parse, FRAME * frame )
+{
+ LIST * source_module_list = lol_get( frame->args, 0 );
+ LIST * source_rules = lol_get( frame->args, 1 );
+ LIST * target_module_list = lol_get( frame->args, 2 );
+ LIST * target_rules = lol_get( frame->args, 3 );
+ LIST * localize = lol_get( frame->args, 4 );
+
+ module_t * target_module =
+ bindmodule( target_module_list ? target_module_list->string : 0 );
+ module_t * source_module =
+ bindmodule( source_module_list ? source_module_list->string : 0 );
+
+ LIST * source_name;
+ LIST * target_name;
+
+ for ( source_name = source_rules, target_name = target_rules;
+ source_name && target_name;
+ source_name = list_next( source_name ),
+ target_name = list_next( target_name ) )
+ {
+ RULE r_;
+ RULE * r = &r_;
+ RULE * imported;
+ r_.name = source_name->string;
+
+ if ( !source_module->rules ||
+ !hashcheck( source_module->rules, (HASHDATA * *)&r ) )
+ unknown_rule( frame, "IMPORT", source_module->name, r_.name );
+
+ imported = import_rule( r, target_module, target_name->string );
+ if ( localize )
+ imported->module = target_module;
+ /* This rule is really part of some other module. Just refer to it here,
+ * but do not let it out.
+ */
+ imported->exported = 0;
+ }
+
+ if ( source_name || target_name )
+ {
+ backtrace_line( frame->prev );
+ printf( "import error: length of source and target rule name lists don't match!\n" );
+ printf( " source: " );
+ list_print( source_rules );
+ printf( "\n target: " );
+ list_print( target_rules );
+ printf( "\n" );
+ backtrace( frame->prev );
+ exit( 1 );
+ }
+
+ return L0;
+}
+
+
+/*
+ * builtin_export() - EXPORT ( MODULE ? : RULES * ).
+ *
+ * The EXPORT rule marks RULES from the SOURCE_MODULE as non-local (and thus
+ * exportable). If an element of RULES does not name a rule in MODULE, an error
+ * is issued.
+ */
+
+LIST * builtin_export( PARSE * parse, FRAME * frame )
+{
+ LIST * module_list = lol_get( frame->args, 0 );
+ LIST * rules = lol_get( frame->args, 1 );
+ module_t * m = bindmodule( module_list ? module_list->string : 0 );
+
+ for ( ; rules; rules = list_next( rules ) )
+ {
+ RULE r_;
+ RULE * r = &r_;
+ r_.name = rules->string;
+
+ if ( !m->rules || !hashcheck( m->rules, (HASHDATA * *)&r ) )
+ unknown_rule( frame, "EXPORT", m->name, r_.name );
+
+ r->exported = 1;
+ }
+ return L0;
+}
+
+
+/*
+ * get_source_line() - Retrieve the file and line number that should be
+ * indicated for a given procedure in debug output or an error backtrace.
+ */
+
+static void get_source_line( PARSE * procedure, char * * file, int * line )
+{
+ if ( procedure )
+ {
+ char * f = procedure->file;
+ int l = procedure->line;
+ if ( !strcmp( f, "+" ) )
+ {
+ f = "jambase.c";
+ l += 3;
+ }
+ *file = f;
+ *line = l;
+ }
+ else
+ {
+ *file = "(builtin)";
+ *line = -1;
+ }
+}
+
+
+void print_source_line( PARSE * p )
+{
+ char * file;
+ int line;
+
+ get_source_line( p, &file, &line );
+ if ( line < 0 )
+ printf( "(builtin):" );
+ else
+ printf( "%s:%d:", file, line );
+}
+
+
+/*
+ * backtrace_line() - print a single line of error backtrace for the given
+ * frame.
+ */
+
+void backtrace_line( FRAME * frame )
+{
+ if ( frame == 0 )
+ {
+ printf( "(no frame):" );
+ }
+ else
+ {
+ print_source_line( frame->procedure );
+ printf( " in %s\n", frame->rulename );
+ }
+}
+
+
+/*
+ * backtrace() - Print the entire backtrace from the given frame to the Jambase
+ * which invoked it.
+ */
+
+void backtrace( FRAME * frame )
+{
+ if ( !frame ) return;
+ while ( ( frame = frame->prev ) )
+ backtrace_line( frame );
+}
+
+
+/*
+ * builtin_backtrace() - A Jam version of the backtrace function, taking no
+ * arguments and returning a list of quadruples: FILENAME LINE MODULE. RULENAME
+ * describing each frame. Note that the module-name is always followed by a
+ * period.
+ */
+
+LIST * builtin_backtrace( PARSE * parse, FRAME * frame )
+{
+ LIST * levels_arg = lol_get( frame->args, 0 );
+ int levels = levels_arg ? atoi( levels_arg->string ) : ( (unsigned int)(-1) >> 1 ) ;
+
+ LIST * result = L0;
+ for ( ; ( frame = frame->prev ) && levels ; --levels )
+ {
+ char * file;
+ int line;
+ char buf[32];
+ get_source_line( frame->procedure, &file, &line );
+ sprintf( buf, "%d", line );
+ result = list_new( result, newstr( file ) );
+ result = list_new( result, newstr( buf ) );
+ result = list_new( result, newstr( frame->module->name ) );
+ result = list_new( result, newstr( frame->rulename ) );
+ }
+ return result;
+}
+
+
+/*
+ * builtin_caller_module() - CALLER_MODULE ( levels ? )
+ *
+ * If levels is not supplied, returns the name of the module of the rule which
+ * called the one calling this one. If levels is supplied, it is interpreted as
+ * an integer specifying a number of additional levels of call stack to traverse
+ * in order to locate the module in question. If no such module exists, returns
+ * the empty list. Also returns the empty list when the module in question is
+ * the global module. This rule is needed for implementing module import
+ * behavior.
+ */
+
+LIST * builtin_caller_module( PARSE * parse, FRAME * frame )
+{
+ LIST * levels_arg = lol_get( frame->args, 0 );
+ int levels = levels_arg ? atoi( levels_arg->string ) : 0 ;
+
+ int i;
+ for ( i = 0; ( i < levels + 2 ) && frame->prev; ++i )
+ frame = frame->prev;
+
+ if ( frame->module == root_module() )
+ return L0;
+
+ {
+ LIST * result;
+ string name;
+ string_copy( &name, frame->module->name );
+ string_pop_back( &name );
+ result = list_new( L0, newstr(name.value) );
+ string_free( &name );
+ return result;
+ }
+}
+
+
+/*
+ * Return the current working directory.
+ *
+ * Usage: pwd = [ PWD ] ;
+ */
+
+LIST * builtin_pwd( PARSE * parse, FRAME * frame )
+{
+ return pwd();
+}
+
+
+/*
+ * Adds targets to the list of target that jam will attempt to update.
+ */
+
+LIST * builtin_update( PARSE * parse, FRAME * frame )
+{
+ LIST * result = list_copy( L0, targets_to_update() );
+ LIST * arg1 = lol_get( frame->args, 0 );
+ clear_targets_to_update();
+ for ( ; arg1; arg1 = list_next( arg1 ) )
+ mark_target_for_updating( newstr( arg1->string ) );
+ return result;
+}
+
+extern int anyhow;
+int last_update_now_status;
+
+/* Takes a list of target names as first argument, and immediately
+ updates them.
+ Second parameter, if specified, if the descriptor (converted to a string)
+ of a log file where all build output is redirected.
+ Third parameter, if non-empty, specifies that the -n option should have
+ no effect -- that is, all out-of-date targets should be rebuild.
+*/
+LIST * builtin_update_now( PARSE * parse, FRAME * frame )
+{
+ LIST * targets = lol_get( frame->args, 0 );
+ LIST * log = lol_get( frame->args, 1 );
+ LIST * force = lol_get (frame->args, 2);
+ LIST * continue_ = lol_get(frame->args, 3);
+ int status = 0;
+ int original_stdout;
+ int original_stderr;
+ int n;
+ int targets_count;
+ const char** targets2;
+ int i;
+ int original_noexec;
+ int original_quitquick;
+
+
+ if (log)
+ {
+ int fd = atoi(log->string);
+ /* Redirect stdout and stderr, temporary, to the log file. */
+ original_stdout = dup (0);
+ original_stderr = dup (1);
+ dup2 (fd, 0);
+ dup2 (fd, 1);
+ }
+
+ if (force)
+ {
+ original_noexec = globs.noexec;
+ globs.noexec = 0;
+ original_quitquick = globs.quitquick;
+ globs.quitquick = 0;
+ }
+
+ if (continue_)
+ {
+ original_quitquick = globs.quitquick;
+ globs.quitquick = 0;
+ }
+
+ targets_count = list_length( targets );
+ targets2 = (const char * *)BJAM_MALLOC( targets_count * sizeof( char * ) );
+ for (i = 0 ; targets; targets = list_next( targets ) )
+ targets2[ i++ ] = targets->string;
+ status |= make( targets_count, targets2, anyhow);
+ free( targets );
+
+ if (force)
+ {
+ globs.noexec = original_noexec;
+ globs.quitquick = original_quitquick;
+ }
+
+ if (continue_)
+ {
+ globs.quitquick = original_quitquick;
+ }
+
+ if (log)
+ {
+ /* Flush whatever stdio might have buffered, while descriptions
+ 0 and 1 still refer to the log file. */
+ fflush (stdout);
+ fflush (stderr);
+ dup2 (original_stdout, 0);
+ dup2 (original_stderr, 1);
+ close (original_stdout);
+ close (original_stderr);
+ }
+
+ last_update_now_status = status;
+
+ if (status == 0)
+ return list_new (L0, newstr ("ok"));
+ else
+ return L0;
+}
+
+LIST * builtin_search_for_target( PARSE * parse, FRAME * frame )
+{
+ LIST * arg1 = lol_get( frame->args, 0 );
+ LIST * arg2 = lol_get( frame->args, 1 );
+ TARGET * t = search_for_target( arg1->string, arg2 );
+ return list_new( L0, t->name );
+}
+
+
+LIST * builtin_import_module( PARSE * parse, FRAME * frame )
+{
+ LIST * arg1 = lol_get( frame->args, 0 );
+ LIST * arg2 = lol_get( frame->args, 1 );
+ module_t * m = arg2 ? bindmodule( arg2->string ) : root_module();
+ import_module( arg1, m );
+ return L0;
+}
+
+
+LIST * builtin_imported_modules( PARSE * parse, FRAME * frame )
+{
+ LIST * arg0 = lol_get( frame->args, 0 );
+ return imported_modules( bindmodule( arg0 ? arg0->string : 0 ) );
+}
+
+
+LIST * builtin_instance( PARSE * parse, FRAME * frame )
+{
+ LIST * arg1 = lol_get( frame->args, 0 );
+ LIST * arg2 = lol_get( frame->args, 1 );
+ module_t * const instance = bindmodule( arg1->string );
+ module_t * const class_module = bindmodule( arg2->string );
+ instance->class_module = class_module;
+ return L0;
+}
+
+
+LIST * builtin_sort( PARSE * parse, FRAME * frame )
+{
+ LIST * arg1 = lol_get( frame->args, 0 );
+ return list_sort( arg1 );
+}
+
+
+LIST * builtin_normalize_path( PARSE * parse, FRAME * frame )
+{
+ LIST * arg = lol_get( frame->args, 0 );
+
+ /* First, we iterate over all '/'-separated elements, starting from the end
+ * of string. If we see a '..', we remove a previous path elements. If we
+ * see '.', we remove it. The removal is done by overwriting data using '\1'
+ * in the string. After the whole string has been processed, we do a second
+ * pass, removing all the entered '\1' characters.
+ */
+
+ string in[ 1 ];
+ string out[ 1 ];
+ /* Last character of the part of string still to be processed. */
+ char * end;
+ /* Working pointer. */
+ char * current;
+ /* Number of '..' elements seen and not processed yet. */
+ int dotdots = 0;
+ int rooted = 0;
+ char * result = 0;
+
+ /* Make a copy of input: we should not change it. Prepend a '/' before it as
+ * a guard for the algorithm later on and remember whether it was originally
+ * rooted or not.
+ */
+ string_new( in );
+ string_push_back( in, '/' );
+ for ( ; arg; arg = list_next( arg ) )
+ {
+ if ( arg->string[ 0 ] != '\0' )
+ {
+ if ( in->size == 1 )
+ rooted = ( ( arg->string[ 0 ] == '/' ) ||
+ ( arg->string[ 0 ] == '\\' ) );
+ else
+ string_append( in, "/" );
+ string_append( in, arg->string );
+ }
+ }
+
+ /* Convert \ into /. On Windows, paths using / and \ are equivalent, and we
+ * want this function to obtain a canonic representation.
+ */
+ for ( current = in->value, end = in->value + in->size;
+ current < end; ++current )
+ if ( *current == '\\' )
+ *current = '/';
+
+ /* Now we remove any extra path elements by overwriting them with '\1'
+ * characters and cound how many more unused '..' path elements there are
+ * remaining. Note that each remaining path element with always starts with
+ * a '/' character.
+ */
+ for ( end = in->value + in->size - 1; end >= in->value; )
+ {
+ /* Set 'current' to the next occurence of '/', which always exists. */
+ for ( current = end; *current != '/'; --current );
+
+ if ( current == end )
+ {
+ /* Found a trailing or duplicate '/'. Remove it. */
+ *current = '\1';
+ }
+ else if ( ( end - current == 1 ) && ( *(current + 1) == '.' ) )
+ {
+ /* Found '/.'. Remove them all. */
+ *current = '\1';
+ *(current + 1) = '\1';
+ }
+ else if ( ( end - current == 2 ) && ( *(current + 1) == '.' ) && ( *(current + 2) == '.' ) )
+ {
+ /* Found '/..'. Remove them all. */
+ *current = '\1';
+ *(current + 1) = '\1';
+ *(current + 2) = '\1';
+ ++dotdots;
+ }
+ else if ( dotdots )
+ {
+ memset( current, '\1', end - current + 1 );
+ --dotdots;
+ }
+ end = current - 1;
+ }
+
+ string_new( out );
+
+ /* Now we know that we need to add exactly dotdots '..' path elements to the
+ * front and that our string is either empty or has a '/' as its first
+ * significant character. If we have any dotdots remaining then the passed
+ * path must not have been rooted or else it is invalid we return an empty
+ * list.
+ */
+ if ( dotdots )
+ {
+ if ( rooted ) return L0;
+ do
+ string_append( out, "/.." );
+ while ( --dotdots );
+ }
+
+ /* Now we actually remove all the path characters marked for removal. */
+ for ( current = in->value; *current; ++current )
+ if ( *current != '\1' )
+ string_push_back( out, *current );
+
+ /* Here we know that our string contains no '\1' characters and is either
+ * empty or has a '/' as its initial character. If the original path was not
+ * rooted and we have a non-empty path we need to drop the initial '/'. If
+ * the original path was rooted and we have an empty path we need to add
+ * back the '/'.
+ */
+ result = newstr( out->size ? out->value + !rooted : ( rooted ? "/" : "." ) );
+
+ string_free( out );
+ string_free( in );
+
+ return list_new( 0, result );
+}
+
+
+LIST * builtin_native_rule( PARSE * parse, FRAME * frame )
+{
+ LIST * module_name = lol_get( frame->args, 0 );
+ LIST * rule_name = lol_get( frame->args, 1 );
+
+ module_t * module = bindmodule( module_name->string );
+
+ native_rule_t n;
+ native_rule_t * np = &n;
+ n.name = rule_name->string;
+ if ( module->native_rules && hashcheck( module->native_rules, (HASHDATA * *)&np ) )
+ {
+ new_rule_body( module, np->name, np->arguments, np->procedure, 1 );
+ }
+ else
+ {
+ backtrace_line( frame->prev );
+ printf( "error: no native rule \"%s\" defined in module \"%s\"\n",
+ n.name, module->name );
+ backtrace( frame->prev );
+ exit( 1 );
+ }
+ return L0;
+}
+
+
+LIST * builtin_has_native_rule( PARSE * parse, FRAME * frame )
+{
+ LIST * module_name = lol_get( frame->args, 0 );
+ LIST * rule_name = lol_get( frame->args, 1 );
+ LIST * version = lol_get( frame->args, 2 );
+
+ module_t * module = bindmodule( module_name->string );
+
+ native_rule_t n;
+ native_rule_t * np = &n;
+ n.name = rule_name->string;
+ if ( module->native_rules && hashcheck( module->native_rules, (HASHDATA * *)&np ) )
+ {
+ int expected_version = atoi( version->string );
+ if ( np->version == expected_version )
+ return list_new( 0, newstr( "true" ) );
+ }
+ return L0;
+}
+
+
+LIST * builtin_user_module( PARSE * parse, FRAME * frame )
+{
+ LIST * module_name = lol_get( frame->args, 0 );
+ for ( ; module_name; module_name = module_name->next )
+ {
+ module_t * m = bindmodule( module_name->string );
+ m->user_module = 1;
+ }
+ return L0;
+}
+
+
+LIST * builtin_nearest_user_location( PARSE * parse, FRAME * frame )
+{
+ FRAME * nearest_user_frame =
+ frame->module->user_module ? frame : frame->prev_user;
+ if ( !nearest_user_frame )
+ return L0;
+
+ {
+ LIST * result = 0;
+ char * file;
+ int line;
+ char buf[32];
+
+ get_source_line( nearest_user_frame->procedure, &file, &line );
+ sprintf( buf, "%d", line );
+ result = list_new( result, newstr( file ) );
+ result = list_new( result, newstr( buf ) );
+ return result;
+ }
+}
+
+
+LIST * builtin_check_if_file( PARSE * parse, FRAME * frame )
+{
+ LIST * name = lol_get( frame->args, 0 );
+ return file_is_file( name->string ) == 1
+ ? list_new( 0, newstr( "true" ) )
+ : L0 ;
+}
+
+
+LIST * builtin_md5( PARSE * parse, FRAME * frame )
+{
+ LIST * l = lol_get( frame->args, 0 );
+ char* s = l->string;
+
+ md5_state_t state;
+ md5_byte_t digest[16];
+ char hex_output[16*2 + 1];
+
+ int di;
+
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)s, strlen(s));
+ md5_finish(&state, digest);
+
+ for (di = 0; di < 16; ++di)
+ sprintf(hex_output + di * 2, "%02x", digest[di]);
+
+ return list_new (0, newstr(hex_output));
+}
+
+LIST *builtin_file_open( PARSE *parse, FRAME *frame )
+{
+ char* name = lol_get(frame->args, 0)->string;
+ char* mode = lol_get(frame->args, 1)->string;
+ int fd;
+ char buffer[sizeof("4294967295")];
+
+ if (strcmp(mode, "w") == 0)
+ {
+ fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ }
+ else
+ {
+ fd = open(name, O_RDONLY);
+ }
+
+ if (fd != -1)
+ {
+ sprintf(buffer, "%d", fd);
+ return list_new(L0, newstr(buffer));
+ }
+ else
+ {
+ return L0;
+ }
+}
+
+LIST *builtin_pad( PARSE *parse, FRAME *frame )
+{
+ char *string = lol_get(frame->args, 0)->string;
+ char *width_s = lol_get(frame->args, 1)->string;
+
+ int current = strlen (string);
+ int desired = atoi(width_s);
+ if (current >= desired)
+ return list_new (L0, string);
+ else
+ {
+ char *buffer = malloc (desired + 1);
+ int i;
+ LIST *result;
+
+ strcpy (buffer, string);
+ for (i = current; i < desired; ++i)
+ buffer[i] = ' ';
+ buffer[desired] = '\0';
+ result = list_new (L0, newstr (buffer));
+ free (buffer);
+ return result;
+ }
+}
+
+LIST *builtin_precious( PARSE *parse, FRAME *frame )
+{
+ LIST* targets = lol_get(frame->args, 0);
+
+ for ( ; targets; targets = list_next( targets ) )
+ {
+ TARGET* t = bindtarget (targets->string);
+ t->flags |= T_FLAG_PRECIOUS;
+ }
+
+ return L0;
+}
+
+LIST *builtin_self_path( PARSE *parse, FRAME *frame )
+{
+ extern char *saved_argv0;
+ char *p = executable_path (saved_argv0);
+ if (p)
+ {
+ LIST* result = list_new (0, newstr (p));
+ free(p);
+ return result;
+ }
+ else
+ {
+ return L0;
+ }
+}
+
+LIST *builtin_makedir( PARSE *parse, FRAME *frame )
+{
+ LIST *path = lol_get(frame->args, 0);
+
+ if (file_mkdir(path->string) == 0)
+ {
+ LIST *result = list_new (0, newstr(path->string));
+ return result;
+ }
+ else
+ {
+ return L0;
+ }
+}
+
+#ifdef HAVE_PYTHON
+
+LIST * builtin_python_import_rule( PARSE * parse, FRAME * frame )
+{
+ static int first_time = 1;
+ char * python_module = lol_get( frame->args, 0 )->string;
+ char * python_function = lol_get( frame->args, 1 )->string;
+ char * jam_module = lol_get( frame->args, 2 )->string;
+ char * jam_rule = lol_get( frame->args, 3 )->string;
+
+ PyObject * pName;
+ PyObject * pModule;
+ PyObject * pDict;
+ PyObject * pFunc;
+
+ if ( first_time )
+ {
+ /* At the first invocation, we add the value of the global
+ * EXTRA_PYTHONPATH to the sys.path Python variable.
+ */
+ LIST * extra = 0;
+ module_t * outer_module = frame->module;
+
+ first_time = 0;
+
+ if ( outer_module != root_module() )
+ {
+ exit_module( outer_module );
+ enter_module( root_module() );
+ }
+
+ extra = var_get( "EXTRA_PYTHONPATH" );
+
+ if ( outer_module != root_module() )
+ {
+ exit_module( root_module() );
+ enter_module( outer_module );
+ }
+
+ for ( ; extra; extra = extra->next )
+ {
+ string buf[ 1 ];
+ string_new( buf );
+ string_append( buf, "import sys\nsys.path.append(\"" );
+ string_append( buf, extra->string );
+ string_append( buf, "\")\n" );
+ PyRun_SimpleString( buf->value );
+ string_free( buf );
+ }
+ }
+
+ pName = PyString_FromString( python_module );
+ pModule = PyImport_Import( pName );
+ Py_DECREF( pName );
+
+ if ( pModule != NULL )
+ {
+ pDict = PyModule_GetDict( pModule );
+ pFunc = PyDict_GetItemString( pDict, python_function );
+
+ if ( pFunc && PyCallable_Check( pFunc ) )
+ {
+ module_t * m = bindmodule( jam_module );
+ RULE * r = bindrule( jam_rule, m );
+
+ /* Make pFunc owned. */
+ Py_INCREF( pFunc );
+
+ r->python_function = pFunc;
+ }
+ else
+ {
+ if ( PyErr_Occurred() )
+ PyErr_Print();
+ fprintf( stderr, "Cannot find function \"%s\"\n", python_function );
+ }
+ Py_DECREF( pModule );
+ }
+ else
+ {
+ PyErr_Print();
+ fprintf( stderr, "Failed to load \"%s\"\n", python_module );
+ }
+ return L0;
+
+}
+
+#endif
+
+void lol_build( LOL * lol, char * * elements )
+{
+ LIST * l = L0;
+ lol_init( lol );
+
+ while ( elements && *elements )
+ {
+ if ( !strcmp( *elements, ":" ) )
+ {
+ lol_add( lol, l );
+ l = L0 ;
+ }
+ else
+ {
+ l = list_new( l, newstr( *elements ) );
+ }
+ ++elements;
+ }
+
+ if ( l != L0 )
+ lol_add( lol, l );
+}
+
+
+#ifdef HAVE_PYTHON
+
+/*
+ * Calls the bjam rule specified by name passed in 'args'. The name is looked up
+ * in the context of bjam's 'python_interface' module. Returns the list of
+ * string retured by the rule.
+ */
+
+PyObject* bjam_call( PyObject * self, PyObject * args )
+{
+ FRAME inner[ 1 ];
+ LIST * result;
+ PARSE * p;
+ char * rulename;
+
+ /* Build up the list of arg lists. */
+ frame_init( inner );
+ inner->prev = 0;
+ inner->prev_user = 0;
+ inner->module = bindmodule( "python_interface" );
+ inner->procedure = 0;
+
+ /* Extract the rule name and arguments from 'args'. */
+
+ /* PyTuple_GetItem returns borrowed reference. */
+ rulename = PyString_AsString( PyTuple_GetItem( args, 0 ) );
+ {
+ int i = 1;
+ int size = PyTuple_Size( args );
+ for ( ; i < size; ++i )
+ {
+ PyObject * a = PyTuple_GetItem( args, i );
+ if ( PyString_Check( a ) )
+ {
+ lol_add( inner->args, list_new( 0, newstr(
+ PyString_AsString( a ) ) ) );
+ }
+ else if ( PySequence_Check( a ) )
+ {
+ LIST * l = 0;
+ int s = PySequence_Size( a );
+ int i = 0;
+ for ( ; i < s; ++i )
+ {
+ /* PySequence_GetItem returns new reference. */
+ PyObject * e = PySequence_GetItem( a, i );
+ char * s = PyString_AsString( e );
+ if ( !s )
+ {
+ printf( "Invalid parameter type passed from Python\n" );
+ exit( 1 );
+ }
+ l = list_new( l, newstr( s ) );
+ Py_DECREF( e );
+ }
+ lol_add( inner->args, l );
+ }
+ }
+ }
+
+ result = evaluate_rule( rulename, inner );
+
+ frame_free( inner );
+
+ /* Convert the bjam list into a Python list result. */
+ {
+ PyObject * pyResult = PyList_New( list_length( result ) );
+ int i = 0;
+ while ( result )
+ {
+ PyList_SetItem( pyResult, i, PyString_FromString( result->string ) );
+ result = list_next( result );
+ i += 1;
+ }
+ list_free( result );
+ return pyResult;
+ }
+}
+
+
+/*
+ * Accepts four arguments:
+ * - module name
+ * - rule name,
+ * - Python callable.
+ * - (optional) bjam language function signature.
+ * Creates a bjam rule with the specified name in the specified module, which will
+ * invoke the Python callable.
+ */
+
+PyObject * bjam_import_rule( PyObject * self, PyObject * args )
+{
+ char * module;
+ char * rule;
+ PyObject * func;
+ PyObject * bjam_signature = NULL;
+ module_t * m;
+ RULE * r;
+
+ if ( !PyArg_ParseTuple( args, "ssO|O:import_rule",
+ &module, &rule, &func, &bjam_signature ) )
+ return NULL;
+
+ if ( !PyCallable_Check( func ) )
+ {
+ PyErr_SetString( PyExc_RuntimeError,
+ "Non-callable object passed to bjam.import_rule" );
+ return NULL;
+ }
+
+ m = bindmodule( *module ? module : 0 );
+ r = bindrule( rule, m );
+
+ /* Make pFunc owned. */
+ Py_INCREF( func );
+
+ r->python_function = func;
+ r->arguments = 0;
+
+ if (bjam_signature)
+ {
+ argument_list * arg_list = args_new();
+ Py_ssize_t i;
+
+ Py_ssize_t s = PySequence_Size (bjam_signature);
+ for (i = 0; i < s; ++i)
+ {
+ PyObject* v = PySequence_GetItem (bjam_signature, i);
+ lol_add(arg_list->data, list_from_python (v));
+ Py_DECREF(v);
+ }
+ r->arguments = arg_list;
+ }
+
+ Py_INCREF( Py_None );
+ return Py_None;
+}
+
+
+/*
+ * Accepts four arguments:
+ * - an action name
+ * - an action body
+ * - a list of variable that will be bound inside the action
+ * - integer flags.
+ * Defines an action on bjam side.
+ */
+
+PyObject * bjam_define_action( PyObject * self, PyObject * args )
+{
+ char * name;
+ char * body;
+ module_t * m;
+ PyObject * bindlist_python;
+ int flags;
+ LIST * bindlist = L0;
+ int n;
+ int i;
+
+ if ( !PyArg_ParseTuple( args, "ssO!i:define_action", &name, &body,
+ &PyList_Type, &bindlist_python, &flags ) )
+ return NULL;
+
+ n = PyList_Size( bindlist_python );
+ for ( i = 0; i < n; ++i )
+ {
+ PyObject * next = PyList_GetItem( bindlist_python, i );
+ if ( !PyString_Check( next ) )
+ {
+ PyErr_SetString( PyExc_RuntimeError,
+ "bind list has non-string type" );
+ return NULL;
+ }
+ bindlist = list_new( bindlist, PyString_AsString( next ) );
+ }
+
+ new_rule_actions( root_module(), name, newstr( body ), bindlist, flags );
+
+ Py_INCREF( Py_None );
+ return Py_None;
+}
+
+
+/*
+ * Returns the value of a variable in root Jam module.
+ */
+
+PyObject * bjam_variable( PyObject * self, PyObject * args )
+{
+ char * name;
+ LIST * value;
+ PyObject * result;
+ int i;
+
+ if ( !PyArg_ParseTuple( args, "s", &name ) )
+ return NULL;
+
+ enter_module( root_module() );
+ value = var_get( name );
+ exit_module( root_module() );
+
+ result = PyList_New( list_length( value ) );
+ for ( i = 0; value; value = list_next( value ), ++i )
+ PyList_SetItem( result, i, PyString_FromString( value->string ) );
+
+ return result;
+}
+
+
+PyObject * bjam_backtrace( PyObject * self, PyObject * args )
+{
+ PyObject * result = PyList_New( 0 );
+ struct frame * f = frame_before_python_call;
+
+ for ( ; f = f->prev; )
+ {
+ PyObject * tuple = PyTuple_New( 4 );
+ char * file;
+ int line;
+ char buf[ 32 ];
+
+ get_source_line( f->procedure, &file, &line );
+ sprintf( buf, "%d", line );
+
+ /* PyTuple_SetItem steals reference. */
+ PyTuple_SetItem( tuple, 0, PyString_FromString( file ) );
+ PyTuple_SetItem( tuple, 1, PyString_FromString( buf ) );
+ PyTuple_SetItem( tuple, 2, PyString_FromString( f->module->name ) );
+ PyTuple_SetItem( tuple, 3, PyString_FromString( f->rulename ) );
+
+ PyList_Append( result, tuple );
+ Py_DECREF( tuple );
+ }
+ return result;
+}
+
+PyObject * bjam_caller( PyObject * self, PyObject * args )
+{
+ PyObject *result = PyString_FromString(
+ frame_before_python_call->prev->module->name);
+ return result;
+}
+
+#endif /* #ifdef HAVE_PYTHON */
+
+
+#ifdef HAVE_POPEN
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+ #define popen windows_popen_wrapper
+ #define pclose _pclose
+
+ /*
+ * This wrapper is a workaround for a funny _popen() feature on Windows
+ * where it eats external quotes in some cases. The bug seems to be related
+ * to the quote stripping functionality used by the Windows cmd.exe
+ * interpreter when its /S is not specified.
+ *
+ * Cleaned up quote from the cmd.exe help screen as displayed on Windows XP
+ * SP3:
+ *
+ * 1. If all of the following conditions are met, then quote characters on
+ * the command line are preserved:
+ *
+ * - no /S switch
+ * - exactly two quote characters
+ * - no special characters between the two quote characters, where
+ * special is one of: &<>()@^|
+ * - there are one or more whitespace characters between the two quote
+ * characters
+ * - the string between the two quote characters is the name of an
+ * executable file.
+ *
+ * 2. Otherwise, old behavior is to see if the first character is a quote
+ * character and if so, strip the leading character and remove the last
+ * quote character on the command line, preserving any text after the
+ * last quote character.
+ *
+ * This causes some commands containing quotes not to be executed correctly.
+ * For example:
+ *
+ * "\Long folder name\aaa.exe" --name="Jurko" --no-surname
+ *
+ * would get its outermost quotes stripped and would be executed as:
+ *
+ * \Long folder name\aaa.exe" --name="Jurko --no-surname
+ *
+ * which would report an error about '\Long' not being a valid command.
+ *
+ * cmd.exe help seems to indicate it would be enough to add an extra space
+ * character in front of the command to avoid this but this does not work,
+ * most likely due to the shell first stripping all leading whitespace
+ * characters from the command.
+ *
+ * Solution implemented here is to quote the whole command in case it
+ * contains any quote characters. Note thought this will not work correctly
+ * should Windows ever 'fix' this feature.
+ * (03.06.2008.) (Jurko)
+ */
+ static FILE * windows_popen_wrapper( char * command, char * mode )
+ {
+ int extra_command_quotes_needed = ( strchr( command, '"' ) != 0 );
+ string quoted_command;
+ FILE * result;
+
+ if ( extra_command_quotes_needed )
+ {
+ string_new( &quoted_command );
+ string_append( &quoted_command, "\"" );
+ string_append( &quoted_command, command );
+ string_append( &quoted_command, "\"" );
+ command = quoted_command.value;
+ }
+
+ result = _popen( command, "r" );
+
+ if ( extra_command_quotes_needed )
+ string_free( &quoted_command );
+
+ return result;
+ }
+#endif
+
+
+static char * rtrim(char *s)
+{
+ char *p = s;
+ while(*p) ++p;
+ for(--p; p >= s && isspace(*p); *p-- = 0);
+ return s;
+}
+
+LIST * builtin_shell( PARSE * parse, FRAME * frame )
+{
+ LIST * command = lol_get( frame->args, 0 );
+ LIST * result = 0;
+ string s;
+ int ret;
+ char buffer[ 1024 ];
+ FILE * p = NULL;
+ int exit_status = -1;
+ int exit_status_opt = 0;
+ int no_output_opt = 0;
+ int strip_eol_opt = 0;
+
+ /* Process the variable args options. */
+ {
+ int a = 1;
+ LIST * arg = lol_get( frame->args, a );
+ while ( arg )
+ {
+ if ( strcmp( "exit-status", arg->string ) == 0 )
+ {
+ exit_status_opt = 1;
+ }
+ else if ( strcmp( "no-output", arg->string ) == 0 )
+ {
+ no_output_opt = 1;
+ }
+ else if ( strcmp("strip-eol", arg->string) == 0 )
+ {
+ strip_eol_opt = 1;
+ }
+ arg = lol_get( frame->args, ++a );
+ }
+ }
+
+ /* The following fflush() call seems to be indicated as a workaround for a
+ * popen() bug on POSIX implementations related to synhronizing input
+ * stream positions for the called and the calling process.
+ */
+ fflush( NULL );
+
+ p = popen( command->string, "r" );
+ if ( p == NULL )
+ return L0;
+
+ string_new( &s );
+
+ while ( ( ret = fread( buffer, sizeof( char ), sizeof( buffer ) - 1, p ) ) > 0 )
+ {
+ buffer[ret] = 0;
+ if ( !no_output_opt )
+ {
+ if ( strip_eol_opt )
+ rtrim(buffer);
+ string_append( &s, buffer );
+ }
+ }
+
+ exit_status = pclose( p );
+
+ /* The command output is returned first. */
+ result = list_new( L0, newstr( s.value ) );
+ string_free( &s );
+
+ /* The command exit result next. */
+ if ( exit_status_opt )
+ {
+ if ( WIFEXITED(exit_status) )
+ exit_status = WEXITSTATUS(exit_status);
+ else
+ exit_status = -1;
+ sprintf( buffer, "%d", exit_status );
+ result = list_new( result, newstr( buffer ) );
+ }
+
+ return result;
+}
+
+#else /* #ifdef HAVE_POPEN */
+
+LIST * builtin_shell( PARSE * parse, FRAME * frame )
+{
+ return L0;
+}
+
+#endif /* #ifdef HAVE_POPEN */
diff --git a/tools/build/v2/engine/builtins.h b/tools/build/v2/engine/builtins.h
new file mode 100644
index 0000000000..5fed07c968
--- /dev/null
+++ b/tools/build/v2/engine/builtins.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+#ifndef JAM_BUILTINS_H
+# define JAM_BUILTINS_H
+
+# include "frames.h"
+
+/*
+ * builtins.h - compile parsed jam statements
+ */
+
+void load_builtins();
+void init_set();
+void init_path();
+void init_regex();
+void init_property_set();
+void init_sequence();
+void init_order();
+
+LIST *builtin_calc( PARSE *parse, FRAME *args );
+LIST *builtin_depends( PARSE *parse, FRAME *args );
+LIST *builtin_rebuilds( PARSE *parse, FRAME *args );
+LIST *builtin_echo( PARSE *parse, FRAME *args );
+LIST *builtin_exit( PARSE *parse, FRAME *args );
+LIST *builtin_flags( PARSE *parse, FRAME *args );
+LIST *builtin_glob( PARSE *parse, FRAME *args );
+LIST *builtin_glob_recursive( PARSE *parse, FRAME *frame );
+LIST *builtin_subst( PARSE *parse, FRAME *args );
+LIST *builtin_match( PARSE *parse, FRAME *args );
+LIST *builtin_split_by_characters( PARSE *parse, FRAME *args );
+LIST *builtin_hdrmacro( PARSE *parse, FRAME *args );
+LIST *builtin_rulenames( PARSE *parse, FRAME *args );
+LIST *builtin_varnames( PARSE *parse, FRAME *args );
+LIST *builtin_delete_module( PARSE *parse, FRAME *args );
+LIST *builtin_import( PARSE *parse, FRAME *args );
+LIST *builtin_export( PARSE *parse, FRAME *args );
+LIST *builtin_caller_module( PARSE *parse, FRAME *args );
+LIST *builtin_backtrace( PARSE *parse, FRAME *args );
+LIST *builtin_pwd( PARSE *parse, FRAME *args );
+LIST *builtin_update( PARSE *parse, FRAME *args );
+LIST *builtin_update_now( PARSE *parse, FRAME *args );
+LIST *builtin_search_for_target( PARSE *parse, FRAME *args );
+LIST *builtin_import_module( PARSE *parse, FRAME *args );
+LIST *builtin_imported_modules( PARSE *parse, FRAME *frame );
+LIST *builtin_instance( PARSE *parse, FRAME *frame );
+LIST *builtin_sort( PARSE *parse, FRAME *frame );
+LIST *builtin_normalize_path( PARSE *parse, FRAME *frame );
+LIST *builtin_native_rule( PARSE *parse, FRAME *frame );
+LIST *builtin_has_native_rule( PARSE *parse, FRAME *frame );
+LIST *builtin_user_module( PARSE *parse, FRAME *frame );
+LIST *builtin_nearest_user_location( PARSE *parse, FRAME *frame );
+LIST *builtin_check_if_file( PARSE *parse, FRAME *frame );
+LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame );
+LIST *builtin_shell( PARSE *parse, FRAME *frame );
+LIST *builtin_md5( PARSE *parse, FRAME *frame );
+LIST *builtin_file_open( PARSE *parse, FRAME *frame );
+LIST *builtin_pad( PARSE *parse, FRAME *frame );
+LIST *builtin_precious( PARSE *parse, FRAME *frame );
+LIST *builtin_self_path( PARSE *parse, FRAME *frame );
+LIST *builtin_makedir( PARSE *parse, FRAME *frame );
+
+void backtrace( FRAME *frame );
+extern int last_update_now_status;
+
+#endif
diff --git a/tools/build/v2/engine/bump_version.py b/tools/build/v2/engine/bump_version.py
new file mode 100644
index 0000000000..9423c4c774
--- /dev/null
+++ b/tools/build/v2/engine/bump_version.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+
+# This script is used to bump version of bjam. It takes a single argument, e.g
+#
+# ./bump_version.py 3.1.9
+#
+# and updates all necessary files. For the time being, it's assumes presense
+# of 'perl' executable and Debian-specific 'dch' executable.
+#
+
+
+import os
+import os.path
+import re
+import string
+import sys
+
+srcdir = os.path.abspath(os.path.dirname(__file__ ))
+docdir = os.path.abspath(os.path.join(srcdir,"..","doc"))
+
+def edit(file,replacements):
+ print " '%s'..." %(file)
+ text = open(file,'r').read()
+ while len(replacements) > 0:
+ #~ print " '%s' ==> '%s'" % (replacements[0],replacements[1])
+ text = re.compile(replacements[0],re.M).subn(replacements[1],text)[0]
+ replacements = replacements[2:]
+ #~ print text
+ open(file,'w').write(text)
+
+def make_edits(version):
+ edit(os.path.join(srcdir,"boost-jam.spec"), [
+ '^Version:.*$','Version: %s' % string.join(version, "."),
+ ])
+
+ edit(os.path.join(srcdir,"build.jam"), [
+ '^_VERSION_ = .* ;$','_VERSION_ = %s %s %s ;' % (version[0], version[1], version[2]),
+ ])
+
+ edit(os.path.join(docdir,"bjam.qbk"), [
+ '\[version.*\]','[version: %s]' % string.join(version, '.'),
+ '\[def :version:.*\]','[def :version: %s]' % string.join(version, '.'),
+ ])
+
+ edit(os.path.join(srcdir,"patchlevel.h"), [
+ '^#define VERSION_MAJOR .*$',
+ '#define VERSION_MAJOR %s' % (version[0]),
+ '^#define VERSION_MINOR .*$',
+ '#define VERSION_MINOR %s' % (version[1]),
+ '^#define VERSION_PATCH .*$',
+ '#define VERSION_PATCH %s' % (version[2]),
+ '^#define VERSION_MAJOR_SYM .*$',
+ '#define VERSION_MAJOR_SYM "0%s"' % (version[0]),
+ '^#define VERSION_MINOR_SYM .*$',
+ '#define VERSION_MINOR_SYM "%s"' % (version[1]),
+ '^#define VERSION_PATCH_SYM .*$',
+ '#define VERSION_PATCH_SYM "%s"' % (version[2]),
+ '^#define VERSION .*$',
+ '#define VERSION "%s"' % string.join(version, '.'),
+ '^#define JAMVERSYM .*$',
+ '#define JAMVERSYM "JAMVERSION=%s.%s"' % (version[0],version[1]),
+ ])
+
+def main():
+
+ if len(sys.argv) < 2:
+ print "Expect new version as argument"
+ sys.exit(1)
+
+ version = string.split(sys.argv[1], ".")
+ print "Setting version to", version
+ make_edits(version)
+
+if __name__ == '__main__':
+ main()
+
+#~ Copyright 2006 Rene Rivera.
+#~ Copyright 2005-2006 Vladimir Prus.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
diff --git a/tools/build/v2/engine/class.c b/tools/build/v2/engine/class.c
new file mode 100644
index 0000000000..ff4ec56807
--- /dev/null
+++ b/tools/build/v2/engine/class.c
@@ -0,0 +1,141 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#include "class.h"
+#include "strings.h"
+#include "variable.h"
+#include "frames.h"
+#include "rules.h"
+#include "newstr.h"
+
+#include "hash.h"
+
+
+static struct hash * classes = 0;
+
+
+static void check_defined( LIST * class_names )
+{
+ for ( ; class_names; class_names = class_names->next )
+ {
+ char * * p = &class_names->string;
+ if ( !hashcheck( classes, (HASHDATA * *)&p ) )
+ {
+ printf( "Class %s is not defined\n", class_names->string );
+ abort();
+ }
+ }
+}
+
+
+static char * class_module_name( char * declared_name )
+{
+ string name[ 1 ];
+ char * result;
+
+ string_new( name );
+ string_append( name, "class@" );
+ string_append( name, declared_name );
+
+ result = newstr( name->value );
+ string_free( name );
+
+ return result;
+}
+
+
+struct import_base_data
+{
+ char * base_name;
+ module_t * base_module;
+ module_t * class_module;
+};
+
+
+static void import_base_rule( void * r_, void * d_ )
+{
+ RULE * r = (RULE *)r_;
+ RULE * ir1;
+ RULE * ir2;
+ struct import_base_data * d = (struct import_base_data *)d_;
+ string qualified_name[ 1 ];
+
+ string_new ( qualified_name );
+ string_append ( qualified_name, d->base_name );
+ string_push_back( qualified_name, '.' );
+ string_append ( qualified_name, r->name );
+
+ ir1 = import_rule( r, d->class_module, r->name );
+ ir2 = import_rule( r, d->class_module, qualified_name->value );
+
+ /* Copy 'exported' flag. */
+ ir1->exported = ir2->exported = r->exported;
+
+ /* If we are importing a class method, localize it. */
+ if ( ( r->module == d->base_module ) || ( r->module->class_module &&
+ ( r->module->class_module == d->base_module ) ) )
+ ir1->module = ir2->module = d->class_module;
+
+ string_free( qualified_name );
+}
+
+
+/*
+ * For each exported rule 'n', declared in class module for base, imports that
+ * rule in 'class' as 'n' and as 'base.n'. Imported rules are localized and
+ * marked as exported.
+ */
+
+static void import_base_rules( module_t * class, char * base )
+{
+ module_t * base_module = bindmodule( class_module_name( base ) );
+ struct import_base_data d;
+ d.base_name = base;
+ d.base_module = base_module;
+ d.class_module = class;
+
+ if ( base_module->rules )
+ hashenumerate( base_module->rules, import_base_rule, &d );
+
+ import_module( imported_modules( base_module ), class );
+}
+
+
+char * make_class_module( LIST * xname, LIST * bases, FRAME * frame )
+{
+ char * name = class_module_name( xname->string );
+ char * * pp = &xname->string;
+ module_t * class_module = 0;
+ module_t * outer_module = frame->module;
+
+ if ( !classes )
+ classes = hashinit( sizeof( char * ), "classes" );
+
+ if ( hashcheck( classes, (HASHDATA * *)&pp ) )
+ {
+ printf( "Class %s already defined\n", xname->string );
+ abort();
+ }
+ else
+ {
+ hashenter( classes, (HASHDATA * *)&pp );
+ }
+ check_defined( bases );
+
+ class_module = bindmodule( name );
+
+ exit_module( outer_module );
+ enter_module( class_module );
+
+ var_set( "__name__", xname, VAR_SET );
+ var_set( "__bases__", bases, VAR_SET );
+
+ exit_module( class_module );
+ enter_module( outer_module );
+
+ for ( ; bases; bases = bases->next )
+ import_base_rules( class_module, bases->string );
+
+ return name;
+}
diff --git a/tools/build/v2/engine/class.h b/tools/build/v2/engine/class.h
new file mode 100644
index 0000000000..f7faeff62e
--- /dev/null
+++ b/tools/build/v2/engine/class.h
@@ -0,0 +1,13 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#ifndef CLASS_H_VP_2003_08_01
+#define CLASS_H_VP_2003_08_01
+
+#include "lists.h"
+#include "frames.h"
+
+char* make_class_module(LIST* xname, LIST* bases, FRAME* frame);
+
+#endif
diff --git a/tools/build/v2/engine/command.c b/tools/build/v2/engine/command.c
new file mode 100644
index 0000000000..d2ea068149
--- /dev/null
+++ b/tools/build/v2/engine/command.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * command.c - maintain lists of commands
+ */
+
+#include "jam.h"
+
+#include "lists.h"
+#include "parse.h"
+#include "variable.h"
+#include "rules.h"
+
+#include "command.h"
+#include <limits.h>
+#include <string.h>
+
+
+/*
+ * cmd_new() - return a new CMD or 0 if too many args
+ */
+
+CMD * cmd_new( RULE * rule, LIST * targets, LIST * sources, LIST * shell )
+{
+ CMD * cmd = (CMD *)BJAM_MALLOC( sizeof( CMD ) );
+ /* Lift line-length limitation entirely when JAMSHELL is just "%". */
+ int no_limit = ( shell && !strcmp(shell->string,"%") && !list_next(shell) );
+ int max_line = MAXLINE;
+ int allocated = -1;
+
+ cmd->rule = rule;
+ cmd->shell = shell;
+ cmd->next = 0;
+
+ lol_init( &cmd->args );
+ lol_add( &cmd->args, targets );
+ lol_add( &cmd->args, sources );
+ cmd->buf = 0;
+
+ do
+ {
+ BJAM_FREE( cmd->buf ); /* free any buffer from previous iteration */
+
+ cmd->buf = (char*)BJAM_MALLOC_ATOMIC( max_line + 1 );
+
+ if ( cmd->buf == 0 )
+ break;
+
+ allocated = var_string( rule->actions->command, cmd->buf, max_line, &cmd->args );
+
+ max_line = max_line * 2;
+ }
+ while ( ( allocated < 0 ) && ( max_line < INT_MAX / 2 ) );
+
+ if ( !no_limit )
+ {
+ /* Bail if the result will not fit in MAXLINE. */
+ char * s = cmd->buf;
+ while ( *s )
+ {
+ size_t l = strcspn( s, "\n" );
+
+ if ( l > MAXLINE )
+ {
+ /* We do not free targets/sources/shell if bailing. */
+ cmd_free( cmd );
+ return 0;
+ }
+
+ s += l;
+ if ( *s )
+ ++s;
+ }
+ }
+
+ return cmd;
+}
+
+
+/*
+ * cmd_free() - free a CMD
+ */
+
+void cmd_free( CMD * cmd )
+{
+ lol_free( &cmd->args );
+ list_free( cmd->shell );
+ BJAM_FREE( cmd->buf );
+ BJAM_FREE( (char *)cmd );
+}
diff --git a/tools/build/v2/engine/command.h b/tools/build/v2/engine/command.h
new file mode 100644
index 0000000000..ddd38e6897
--- /dev/null
+++ b/tools/build/v2/engine/command.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 1994 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * command.h - the CMD structure and routines to manipulate them
+ *
+ * Both ACTION and CMD contain a rule, targets, and sources. An
+ * ACTION describes a rule to be applied to the given targets and
+ * sources; a CMD is what actually gets executed by the shell. The
+ * differences are due to:
+ *
+ * ACTIONS must be combined if 'actions together' is given.
+ * ACTIONS must be split if 'actions piecemeal' is given.
+ * ACTIONS must have current sources omitted for 'actions updated'.
+ *
+ * The CMD datatype holds a single command that is to be executed
+ * against a target, and they can chain together to represent the
+ * full collection of commands used to update a target.
+ *
+ * Structures:
+ *
+ * CMD - an action, ready to be formatted into a buffer and executed.
+ *
+ * External routines:
+ *
+ * cmd_new() - return a new CMD or 0 if too many args.
+ * cmd_free() - delete CMD and its parts.
+ * cmd_next() - walk the CMD chain.
+ */
+
+
+/*
+ * CMD - an action, ready to be formatted into a buffer and executed.
+ */
+
+typedef struct _cmd CMD;
+
+struct _cmd
+{
+ CMD * next;
+ CMD * tail; /* valid on in head */
+ RULE * rule; /* rule->actions contains shell script */
+ LIST * shell; /* $(SHELL) value */
+ LOL args; /* LISTs for $(<), $(>) */
+ char * buf; /* actual commands */
+};
+
+CMD * cmd_new
+(
+ RULE * rule, /* rule (referenced) */
+ LIST * targets, /* $(<) (freed) */
+ LIST * sources, /* $(>) (freed) */
+ LIST * shell /* $(SHELL) (freed) */
+);
+
+void cmd_free( CMD * );
+
+#define cmd_next( c ) ( ( c )->next )
diff --git a/tools/build/v2/engine/compile.c b/tools/build/v2/engine/compile.c
new file mode 100644
index 0000000000..2c049aae59
--- /dev/null
+++ b/tools/build/v2/engine/compile.c
@@ -0,0 +1,1424 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+
+# include "lists.h"
+# include "parse.h"
+# include "compile.h"
+# include "variable.h"
+# include "expand.h"
+# include "rules.h"
+# include "newstr.h"
+# include "make.h"
+# include "search.h"
+# include "hdrmacro.h"
+# include "hash.h"
+# include "modules.h"
+# include "strings.h"
+# include "builtins.h"
+# include "class.h"
+
+# include <assert.h>
+# include <string.h>
+# include <stdarg.h>
+
+/*
+ * compile.c - compile parsed jam statements
+ *
+ * External routines:
+ *
+ * compile_append() - append list results of two statements
+ * compile_eval() - evaluate if to determine which leg to compile
+ * compile_foreach() - compile the "for x in y" statement
+ * compile_if() - compile 'if' rule
+ * compile_while() - compile 'while' rule
+ * compile_include() - support for 'include' - call include() on file
+ * compile_list() - expand and return a list
+ * compile_local() - declare (and set) local variables
+ * compile_null() - do nothing -- a stub for parsing
+ * compile_on() - run rule under influence of on-target variables
+ * compile_rule() - compile a single user defined rule
+ * compile_rules() - compile a chain of rules
+ * compile_set() - compile the "set variable" statement
+ * compile_setcomp() - support for `rule` - save parse tree
+ * compile_setexec() - support for `actions` - save execution string
+ * compile_settings() - compile the "on =" (set variable on exec) statement
+ * compile_switch() - compile 'switch' rule
+ *
+ * Internal routines:
+ *
+ * debug_compile() - printf with indent to show rule expansion.
+ * evaluate_rule() - execute a rule invocation
+ *
+ * builtin_depends() - DEPENDS/INCLUDES rule
+ * builtin_echo() - ECHO rule
+ * builtin_exit() - EXIT rule
+ * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule
+ *
+ * 02/03/94 (seiwald) - Changed trace output to read "setting" instead of
+ * the awkward sounding "settings".
+ * 04/12/94 (seiwald) - Combined build_depends() with build_includes().
+ * 04/12/94 (seiwald) - actionlist() now just appends a single action.
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 05/13/94 (seiwald) - include files are now bound as targets, and thus
+ * can make use of $(SEARCH)
+ * 06/01/94 (seiwald) - new 'actions existing' does existing sources
+ * 08/23/94 (seiwald) - Support for '+=' (append to variable)
+ * 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
+ * 01/22/95 (seiwald) - Exit rule.
+ * 02/02/95 (seiwald) - Always rule; LEAVES rule.
+ * 02/14/95 (seiwald) - NoUpdate rule.
+ * 09/11/00 (seiwald) - new evaluate_rule() for headers().
+ * 09/11/00 (seiwald) - compile_xxx() now return LIST *.
+ * New compile_append() and compile_list() in
+ * support of building lists here, rather than
+ * in jamgram.yy.
+ * 01/10/00 (seiwald) - built-ins split out to builtin.c.
+ */
+
+static void debug_compile( int which, char *s, FRAME* frame );
+int glob( char *s, char *c );
+/* Internal functions from builtins.c */
+void backtrace( FRAME *frame );
+void backtrace_line( FRAME *frame );
+void print_source_line( PARSE* p );
+
+struct frame * frame_before_python_call;
+
+void frame_init( FRAME* frame )
+{
+ frame->prev = 0;
+ frame->prev_user = 0;
+ lol_init(frame->args);
+ frame->module = root_module();
+ frame->rulename = "module scope";
+ frame->procedure = 0;
+}
+
+
+void frame_free( FRAME* frame )
+{
+ lol_free( frame->args );
+}
+
+
+/*
+ * compile_append() - append list results of two statements
+ *
+ * parse->left more compile_append() by left-recursion
+ * parse->right single rule
+ */
+
+LIST * compile_append( PARSE * parse, FRAME * frame )
+{
+ /* Append right to left. */
+ return list_append(
+ parse_evaluate( parse->left, frame ),
+ parse_evaluate( parse->right, frame ) );
+}
+
+
+/*
+ * compile_eval() - evaluate if to determine which leg to compile
+ *
+ * Returns:
+ * list if expression true - compile 'then' clause
+ * L0 if expression false - compile 'else' clause
+ */
+
+static int lcmp( LIST * t, LIST * s )
+{
+ int status = 0;
+
+ while ( !status && ( t || s ) )
+ {
+ char *st = t ? t->string : "";
+ char *ss = s ? s->string : "";
+
+ status = strcmp( st, ss );
+
+ t = t ? list_next( t ) : t;
+ s = s ? list_next( s ) : s;
+ }
+
+ return status;
+}
+
+LIST * compile_eval( PARSE * parse, FRAME * frame )
+{
+ LIST * ll;
+ LIST * lr;
+ LIST * s;
+ LIST * t;
+ int status = 0;
+
+ /* Short circuit lr eval for &&, ||, and 'in'. */
+
+ ll = parse_evaluate( parse->left, frame );
+ lr = 0;
+
+ switch ( parse->num )
+ {
+ case EXPR_AND:
+ case EXPR_IN : if ( ll ) goto eval; break;
+ case EXPR_OR : if ( !ll ) goto eval; break;
+ default: eval: lr = parse_evaluate( parse->right, frame );
+ }
+
+ /* Now eval. */
+ switch ( parse->num )
+ {
+ case EXPR_NOT: if ( !ll ) status = 1; break;
+ case EXPR_AND: if ( ll && lr ) status = 1; break;
+ case EXPR_OR : if ( ll || lr ) status = 1; break;
+
+ case EXPR_IN:
+ /* "a in b": make sure each of ll is equal to something in lr. */
+ for ( t = ll; t; t = list_next( t ) )
+ {
+ for ( s = lr; s; s = list_next( s ) )
+ if ( !strcmp( t->string, s->string ) )
+ break;
+ if ( !s ) break;
+ }
+ /* No more ll? Success. */
+ if ( !t ) status = 1;
+ break;
+
+ case EXPR_EXISTS: if ( lcmp( ll, L0 ) != 0 ) status = 1; break;
+ case EXPR_EQUALS: if ( lcmp( ll, lr ) == 0 ) status = 1; break;
+ case EXPR_NOTEQ : if ( lcmp( ll, lr ) != 0 ) status = 1; break;
+ case EXPR_LESS : if ( lcmp( ll, lr ) < 0 ) status = 1; break;
+ case EXPR_LESSEQ: if ( lcmp( ll, lr ) <= 0 ) status = 1; break;
+ case EXPR_MORE : if ( lcmp( ll, lr ) > 0 ) status = 1; break;
+ case EXPR_MOREEQ: if ( lcmp( ll, lr ) >= 0 ) status = 1; break;
+ }
+
+ if ( DEBUG_IF )
+ {
+ debug_compile( 0, "if", frame );
+ list_print( ll );
+ printf( "(%d) ", status );
+ list_print( lr );
+ printf( "\n" );
+ }
+
+ /* Find something to return. */
+ /* In odd circumstances (like "" = "") */
+ /* we'll have to return a new string. */
+
+ if ( !status ) t = 0;
+ else if ( ll ) t = ll, ll = 0;
+ else if ( lr ) t = lr, lr = 0;
+ else t = list_new( L0, newstr( "1" ) );
+
+ if ( ll ) list_free( ll );
+ if ( lr ) list_free( lr );
+ return t;
+}
+
+
+/*
+ * compile_foreach() - compile the "for x in y" statement
+ *
+ * Compile_foreach() resets the given variable name to each specified
+ * value, executing the commands enclosed in braces for each iteration.
+ *
+ * parse->string index variable
+ * parse->left variable values
+ * parse->right rule to compile
+ */
+
+LIST * compile_foreach( PARSE * parse, FRAME * frame )
+{
+ LIST * nv = parse_evaluate( parse->left, frame );
+ LIST * l;
+ SETTINGS * s = 0;
+
+ if ( parse->num )
+ {
+ s = addsettings( s, VAR_SET, parse->string, L0 );
+ pushsettings( s );
+ }
+
+ /* Call var_set to reset $(parse->string) for each val. */
+
+ for ( l = nv; l; l = list_next( l ) )
+ {
+ LIST * val = list_new( L0, copystr( l->string ) );
+ var_set( parse->string, val, VAR_SET );
+ list_free( parse_evaluate( parse->right, frame ) );
+ }
+
+ if ( parse->num )
+ {
+ popsettings( s );
+ freesettings( s );
+ }
+
+ list_free( nv );
+
+ return L0;
+}
+
+/*
+ * compile_if() - compile 'if' rule
+ *
+ * parse->left condition tree
+ * parse->right then tree
+ * parse->third else tree
+ */
+
+LIST * compile_if( PARSE * p, FRAME * frame )
+{
+ LIST * l = parse_evaluate( p->left, frame );
+ if ( l )
+ {
+ list_free( l );
+ return parse_evaluate( p->right, frame );
+ }
+ return parse_evaluate( p->third, frame );
+}
+
+
+LIST * compile_while( PARSE * p, FRAME * frame )
+{
+ LIST * r = 0;
+ LIST * l;
+ while ( ( l = parse_evaluate( p->left, frame ) ) )
+ {
+ list_free( l );
+ if ( r ) list_free( r );
+ r = parse_evaluate( p->right, frame );
+ }
+ return r;
+}
+
+
+/*
+ * compile_include() - support for 'include' - call include() on file
+ *
+ * parse->left list of files to include (can only do 1)
+ */
+
+LIST * compile_include( PARSE * parse, FRAME * frame )
+{
+ LIST * nt = parse_evaluate( parse->left, frame );
+
+ if ( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "include", frame);
+ list_print( nt );
+ printf( "\n" );
+ }
+
+ if ( nt )
+ {
+ TARGET * t = bindtarget( nt->string );
+
+ /* DWA 2001/10/22 - Perforce Jam cleared the arguments here, which
+ * prevents an included file from being treated as part of the body of a
+ * rule. I did not see any reason to do that, so I lifted the
+ * restriction.
+ */
+
+ /* Bind the include file under the influence of */
+ /* "on-target" variables. Though they are targets, */
+ /* include files are not built with make(). */
+
+ pushsettings( t->settings );
+ /* We don't expect that file to be included is generated by some
+ action. Therefore, pass 0 as third argument.
+ If the name resolves to directory, let it error out. */
+ t->boundname = search( t->name, &t->time, 0, 0 );
+ popsettings( t->settings );
+
+ parse_file( t->boundname, frame );
+ }
+
+ list_free( nt );
+
+ return L0;
+}
+
+static LIST* evaluate_in_module ( char* module_name, PARSE * p, FRAME* frame)
+{
+ LIST* result;
+
+ module_t* outer_module = frame->module;
+ frame->module = module_name ? bindmodule( module_name ) : root_module();
+
+ if ( outer_module != frame->module )
+ {
+ exit_module( outer_module );
+ enter_module( frame->module );
+ }
+
+ result = parse_evaluate( p, frame );
+
+ if ( outer_module != frame->module )
+ {
+ exit_module( frame->module );
+ enter_module( outer_module );
+ frame->module = outer_module;
+ }
+
+ return result;
+}
+
+
+LIST * compile_module( PARSE * p, FRAME * frame )
+{
+ /* Here we are entering a module declaration block. */
+ LIST * module_name = parse_evaluate( p->left, frame );
+ LIST * result = evaluate_in_module( module_name ? module_name->string : 0,
+ p->right, frame );
+ list_free( module_name );
+ return result;
+}
+
+
+LIST * compile_class( PARSE * p, FRAME * frame )
+{
+ /** Todo: check for empty class name.
+ Check for class redeclaration. */
+
+ char * class_module = 0;
+
+ LIST * name = parse_evaluate( p->left->right, frame );
+ LIST * bases = 0;
+
+ if ( p->left->left )
+ bases = parse_evaluate( p->left->left->right, frame );
+
+ class_module = make_class_module( name, bases, frame );
+ evaluate_in_module( class_module, p->right, frame );
+
+ return L0;
+}
+
+
+/*
+ * compile_list() - expand and return a list.
+ *
+ * parse->string - character string to expand.
+ */
+
+LIST * compile_list( PARSE * parse, FRAME * frame )
+{
+ /* s is a copyable string */
+ char * s = parse->string;
+ return var_expand( L0, s, s + strlen( s ), frame->args, 1 );
+}
+
+
+/*
+ * compile_local() - declare (and set) local variables.
+ *
+ * parse->left list of variables
+ * parse->right list of values
+ * parse->third rules to execute
+ */
+
+LIST * compile_local( PARSE * parse, FRAME * frame )
+{
+ LIST * l;
+ SETTINGS * s = 0;
+ LIST * nt = parse_evaluate( parse->left, frame );
+ LIST * ns = parse_evaluate( parse->right, frame );
+ LIST * result;
+
+ if ( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "local", frame );
+ list_print( nt );
+ printf( " = " );
+ list_print( ns );
+ printf( "\n" );
+ }
+
+ /* Initial value is ns. */
+ for ( l = nt; l; l = list_next( l ) )
+ s = addsettings( s, VAR_SET, l->string, list_copy( (LIST *)0, ns ) );
+
+ list_free( ns );
+ list_free( nt );
+
+ /* Note that callees of the current context get this "local" variable,
+ * making it not so much local as layered.
+ */
+
+ pushsettings( s );
+ result = parse_evaluate( parse->third, frame );
+ popsettings( s );
+
+ freesettings( s );
+
+ return result;
+}
+
+
+/*
+ * compile_null() - do nothing -- a stub for parsing.
+ */
+
+LIST * compile_null( PARSE * parse, FRAME * frame )
+{
+ return L0;
+}
+
+
+/*
+ * compile_on() - run rule under influence of on-target variables
+ *
+ * parse->left list of files to include (can only do 1).
+ * parse->right rule to run.
+ *
+ * EXPERIMENTAL!
+ */
+
+LIST * compile_on( PARSE * parse, FRAME * frame )
+{
+ LIST * nt = parse_evaluate( parse->left, frame );
+ LIST * result = 0;
+
+ if ( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "on", frame );
+ list_print( nt );
+ printf( "\n" );
+ }
+
+ if ( nt )
+ {
+ TARGET * t = bindtarget( nt->string );
+ pushsettings( t->settings );
+ result = parse_evaluate( parse->right, frame );
+ popsettings( t->settings );
+ }
+
+ list_free( nt );
+
+ return result;
+}
+
+
+/*
+ * compile_rule() - compile a single user defined rule.
+ *
+ * parse->string name of user defined rule.
+ * parse->left parameters (list of lists) to rule, recursing left.
+ *
+ * Wrapped around evaluate_rule() so that headers() can share it.
+ */
+
+LIST * compile_rule( PARSE * parse, FRAME * frame )
+{
+ FRAME inner[ 1 ];
+ LIST * result;
+ PARSE * p;
+
+ /* Build up the list of arg lists. */
+ frame_init( inner );
+ inner->prev = frame;
+ inner->prev_user = frame->module->user_module ? frame : frame->prev_user;
+ inner->module = frame->module; /* This gets fixed up in evaluate_rule(), below. */
+ inner->procedure = parse;
+ /* Special-case LOL of length 1 where the first list is totally empty.
+ This is created when calling functions with no parameters, due to
+ the way jam grammar is written. This is OK when one jam function
+ calls another, but really not good when Jam function calls Python. */
+ if ( parse->left->left == NULL && parse->left->right->func == compile_null)
+ ;
+ else
+ for ( p = parse->left; p; p = p->left )
+ lol_add( inner->args, parse_evaluate( p->right, frame ) );
+
+ /* And invoke the rule. */
+ result = evaluate_rule( parse->string, inner );
+ frame_free( inner );
+ return result;
+}
+
+
+static void argument_error( char * message, RULE * rule, FRAME * frame, LIST* arg )
+{
+ LOL * actual = frame->args;
+ assert( frame->procedure != 0 );
+ backtrace_line( frame->prev );
+ printf( "*** argument error\n* rule %s ( ", frame->rulename );
+ lol_print( rule->arguments->data );
+ printf( " )\n* called with: ( " );
+ lol_print( actual );
+ printf( " )\n* %s %s\n", message, arg ? arg->string : "" );
+ print_source_line( rule->procedure );
+ printf( "see definition of rule '%s' being called\n", rule->name );
+ backtrace( frame->prev );
+ exit( 1 );
+}
+
+
+/* Define delimiters for type check elements in argument lists (and return type
+ * specifications, eventually).
+ */
+# define TYPE_OPEN_DELIM '['
+# define TYPE_CLOSE_DELIM ']'
+
+/*
+ * is_type_name() - true iff the given string represents a type check
+ * specification.
+ */
+
+static int is_type_name( char * s )
+{
+ return ( s[ 0 ] == TYPE_OPEN_DELIM ) &&
+ ( s[ strlen( s ) - 1 ] == TYPE_CLOSE_DELIM );
+}
+
+
+/*
+ * arg_modifier - if the next element of formal is a single character, return
+ * that; return 0 otherwise. Used to extract "*+?" modifiers * from argument
+ * lists.
+ */
+
+static char arg_modifier( LIST * formal )
+{
+ if ( formal->next )
+ {
+ char * next = formal->next->string;
+ if ( next && ( next[ 0 ] != 0 ) && ( next[ 1 ] == 0 ) )
+ return next[ 0 ];
+ }
+ return 0;
+}
+
+
+/*
+ * type_check() - checks that each element of values satisfies the requirements
+ * of type_name.
+ *
+ * caller - the frame of the rule calling the rule whose arguments are
+ * being checked
+ *
+ * called - the rule being called
+ *
+ * arg_name - a list element containing the name of the argument being
+ * checked
+ */
+
+static void type_check
+(
+ char * type_name,
+ LIST * values,
+ FRAME * caller,
+ RULE * called,
+ LIST * arg_name
+)
+{
+ static module_t * typecheck = 0;
+
+ /* If nothing to check, bail now. */
+ if ( !values || !type_name )
+ return;
+
+ if ( !typecheck )
+ typecheck = bindmodule( ".typecheck" );
+
+ /* If the checking rule can not be found, also bail. */
+ {
+ RULE checker_, *checker = &checker_;
+
+ checker->name = type_name;
+ if ( !typecheck->rules || !hashcheck( typecheck->rules, (HASHDATA * *)&checker ) )
+ return;
+ }
+
+ exit_module( caller->module );
+
+ while ( values != 0 )
+ {
+ LIST *error;
+ FRAME frame[1];
+ frame_init( frame );
+ frame->module = typecheck;
+ frame->prev = caller;
+ frame->prev_user = caller->module->user_module ? caller : caller->prev_user;
+
+ enter_module( typecheck );
+ /* Prepare the argument list */
+ lol_add( frame->args, list_new( L0, values->string ) );
+ error = evaluate_rule( type_name, frame );
+
+ exit_module( typecheck );
+
+ if ( error )
+ argument_error( error->string, called, caller, arg_name );
+
+ frame_free( frame );
+ values = values->next;
+ }
+
+ enter_module( caller->module );
+}
+
+/*
+ * collect_arguments() - local argument checking and collection
+ */
+static SETTINGS *
+collect_arguments( RULE* rule, FRAME* frame )
+{
+ SETTINGS *locals = 0;
+
+ LOL * all_actual = frame->args;
+ LOL * all_formal = rule->arguments ? rule->arguments->data : 0;
+ if ( all_formal ) /* Nothing to set; nothing to check */
+ {
+ int max = all_formal->count > all_actual->count
+ ? all_formal->count
+ : all_actual->count;
+
+ int n;
+ for ( n = 0; n < max ; ++n )
+ {
+ LIST *actual = lol_get( all_actual, n );
+ char *type_name = 0;
+
+ LIST *formal;
+ for ( formal = lol_get( all_formal, n ); formal; formal = formal->next )
+ {
+ char* name = formal->string;
+
+ if ( is_type_name(name) )
+ {
+ if ( type_name )
+ argument_error( "missing argument name before type name:", rule, frame, formal );
+
+ if ( !formal->next )
+ argument_error( "missing argument name after type name:", rule, frame, formal );
+
+ type_name = formal->string;
+ }
+ else
+ {
+ LIST* value = 0;
+ char modifier;
+ LIST* arg_name = formal; /* hold the argument name for type checking */
+ int multiple = 0;
+
+ /* Stop now if a variable number of arguments are specified */
+ if ( name[0] == '*' && name[1] == 0 )
+ return locals;
+
+ modifier = arg_modifier( formal );
+
+ if ( !actual && modifier != '?' && modifier != '*' )
+ argument_error( "missing argument", rule, frame, formal );
+
+ switch ( modifier )
+ {
+ case '+':
+ case '*':
+ value = list_copy( 0, actual );
+ multiple = 1;
+ actual = 0;
+ /* skip an extra element for the modifier */
+ formal = formal->next;
+ break;
+ case '?':
+ /* skip an extra element for the modifier */
+ formal = formal->next;
+ /* fall through */
+ default:
+ if ( actual ) /* in case actual is missing */
+ {
+ value = list_new( 0, actual->string );
+ actual = actual->next;
+ }
+ }
+
+ locals = addsettings(locals, VAR_SET, name, value);
+ locals->multiple = multiple;
+ type_check( type_name, value, frame, rule, arg_name );
+ type_name = 0;
+ }
+ }
+
+ if ( actual )
+ {
+ argument_error( "extra argument", rule, frame, actual );
+ }
+ }
+ }
+ return locals;
+}
+
+RULE *
+enter_rule( char *rulename, module_t *target_module );
+
+#ifdef HAVE_PYTHON
+
+static int python_instance_number = 0;
+
+
+/* Given a Python object, return a string to use in Jam
+ code instead of said object.
+ If the object is string, use the string value
+ If the object implemenets __jam_repr__ method, use that.
+ Otherwise return 0.
+
+ The result value is newstr-ed. */
+char *python_to_string(PyObject* value)
+{
+ if (PyString_Check(value))
+ {
+ return newstr(PyString_AsString(value));
+ }
+ else
+ {
+ /* See if this is an instance that defines special __jam_repr__
+ method. */
+ if (PyInstance_Check(value)
+ && PyObject_HasAttrString(value, "__jam_repr__"))
+ {
+ PyObject* repr = PyObject_GetAttrString(value, "__jam_repr__");
+ if (repr)
+ {
+ PyObject* arguments2 = PyTuple_New(0);
+ PyObject* value2 = PyObject_Call(repr, arguments2, 0);
+ Py_DECREF(repr);
+ Py_DECREF(arguments2);
+ if (PyString_Check(value2))
+ {
+ return newstr(PyString_AsString(value2));
+ }
+ Py_DECREF(value2);
+ }
+ }
+ return 0;
+ }
+}
+
+static LIST*
+call_python_function(RULE* r, FRAME* frame)
+{
+ LIST * result = 0;
+ PyObject * arguments = 0;
+ PyObject * kw = NULL;
+ int i ;
+ PyObject * py_result;
+
+ if (r->arguments)
+ {
+ SETTINGS * args;
+
+ arguments = PyTuple_New(0);
+ kw = PyDict_New();
+
+ for (args = collect_arguments(r, frame); args; args = args->next)
+ {
+ PyObject *key = PyString_FromString(args->symbol);
+ PyObject *value = 0;
+ if (args->multiple)
+ value = list_to_python(args->value);
+ else {
+ if (args->value)
+ value = PyString_FromString(args->value->string);
+ }
+
+ if (value)
+ PyDict_SetItem(kw, key, value);
+ Py_DECREF(key);
+ Py_XDECREF(value);
+ }
+ }
+ else
+ {
+ arguments = PyTuple_New( frame->args->count );
+ for ( i = 0; i < frame->args->count; ++i )
+ {
+ PyObject * arg = PyList_New(0);
+ LIST* l = lol_get( frame->args, i);
+
+ for ( ; l; l = l->next )
+ {
+ PyObject * v = PyString_FromString(l->string);
+ PyList_Append( arg, v );
+ Py_DECREF(v);
+ }
+ /* Steals reference to 'arg' */
+ PyTuple_SetItem( arguments, i, arg );
+ }
+ }
+
+ frame_before_python_call = frame;
+ py_result = PyObject_Call( r->python_function, arguments, kw );
+ Py_DECREF(arguments);
+ Py_XDECREF(kw);
+ if ( py_result != NULL )
+ {
+ if ( PyList_Check( py_result ) )
+ {
+ int size = PyList_Size( py_result );
+ int i;
+ for ( i = 0; i < size; ++i )
+ {
+ PyObject * item = PyList_GetItem( py_result, i );
+ char *s = python_to_string (item);
+ if (!s) {
+ fprintf( stderr, "Non-string object returned by Python call.\n" );
+ } else {
+ result = list_new (result, s);
+ }
+ }
+ }
+ else if ( py_result == Py_None )
+ {
+ result = L0;
+ }
+ else
+ {
+ char *s = python_to_string(py_result);
+ if (s)
+ result = list_new(0, s);
+ else
+ /* We have tried all we could. Return empty list. There are
+ cases, e.g. feature.feature function that should return
+ value for the benefit of Python code and which also can be
+ called by Jam code, where no sensible value can be
+ returned. We cannot even emit a warning, since there will
+ be a pile of them. */
+ result = L0;
+ }
+
+ Py_DECREF( py_result );
+ }
+ else
+ {
+ PyErr_Print();
+ fprintf(stderr,"Call failed\n");
+ }
+
+ return result;
+}
+
+
+module_t * python_module()
+{
+ static module_t * python = 0;
+ if ( !python )
+ python = bindmodule("__python__");
+ return python;
+}
+
+#endif
+
+
+/*
+ * evaluate_rule() - execute a rule invocation.
+ */
+
+LIST *
+evaluate_rule(
+ char * rulename,
+ FRAME * frame )
+{
+ LIST * result = L0;
+ RULE * rule;
+ profile_frame prof[1];
+ module_t * prev_module = frame->module;
+
+ LIST * l;
+ {
+ LOL arg_context_, * arg_context = &arg_context_;
+ if ( !frame->prev )
+ lol_init(arg_context);
+ else
+ arg_context = frame->prev->args;
+ l = var_expand( L0, rulename, rulename+strlen(rulename), arg_context, 0 );
+ }
+
+ if ( !l )
+ {
+ backtrace_line( frame->prev );
+ printf( "warning: rulename %s expands to empty string\n", rulename );
+ backtrace( frame->prev );
+ return result;
+ }
+
+ rulename = l->string;
+ rule = bindrule( l->string, frame->module );
+
+#ifdef HAVE_PYTHON
+ if ( rule->python_function )
+ {
+ /* The below messing with modules is due to the way modules are
+ * implemented in Jam. Suppose we are in module M1 now. The global
+ * variable map actually holds 'M1' variables, and M1->variables hold
+ * global variables.
+ *
+ * If we call Python right away, Python calls back Jam and then Jam
+ * does 'module M1 { }' then Jam will try to swap the current global
+ * variables with M1->variables. The result will be that global
+ * variables map will hold global variables, and any variable settings
+ * we do will go to the global module, not M1.
+ *
+ * By restoring basic state, where the global variable map holds global
+ * variable, we make sure any future 'module M1' entry will work OK.
+ */
+
+ LIST * result;
+ module_t * m = python_module();
+
+ frame->module = m;
+
+ exit_module( prev_module );
+ enter_module( m );
+
+ result = call_python_function( rule, frame );
+
+ exit_module( m );
+ enter_module ( prev_module );
+
+ return result;
+ }
+#endif
+
+ /* Drop the rule name. */
+ l = list_pop_front( l );
+
+ /* Tack the rest of the expansion onto the front of the first argument. */
+ frame->args->list[0] = list_append( l, lol_get( frame->args, 0 ) );
+
+ if ( DEBUG_COMPILE )
+ {
+ /* Try hard to indicate in which module the rule is going to execute. */
+ if ( rule->module != frame->module
+ && rule->procedure != 0 && strcmp( rulename, rule->procedure->rulename ) )
+ {
+ char buf[256] = "";
+ strncat( buf, rule->module->name, sizeof( buf ) - 1 );
+ strncat( buf, rule->name, sizeof( buf ) - 1 );
+ debug_compile( 1, buf, frame );
+ }
+ else
+ {
+ debug_compile( 1, rulename, frame );
+ }
+
+ lol_print( frame->args );
+ printf( "\n" );
+ }
+
+ if ( rule->procedure && rule->module != prev_module )
+ {
+ /* Propagate current module to nested rule invocations. */
+ frame->module = rule->module;
+
+ /* Swap variables. */
+ exit_module( prev_module );
+ enter_module( rule->module );
+ }
+
+ /* Record current rule name in frame. */
+ if ( rule->procedure )
+ {
+ frame->rulename = rulename;
+ /* And enter record profile info. */
+ if ( DEBUG_PROFILE )
+ profile_enter( rule->procedure->rulename, prof );
+ }
+
+ /* Check traditional targets $(<) and sources $(>). */
+ if ( !rule->actions && !rule->procedure )
+ {
+ backtrace_line( frame->prev );
+ printf( "rule %s unknown in module %s\n", rule->name, frame->module->name );
+ backtrace( frame->prev );
+ exit( 1 );
+ }
+
+ /* If this rule will be executed for updating the targets then construct the
+ * action for make().
+ */
+ if ( rule->actions )
+ {
+ TARGETS * t;
+ ACTION * action;
+
+ /* The action is associated with this instance of this rule. */
+ action = (ACTION *)BJAM_MALLOC( sizeof( ACTION ) );
+ memset( (char *)action, '\0', sizeof( *action ) );
+
+ action->rule = rule;
+ action->targets = targetlist( (TARGETS *)0, lol_get( frame->args, 0 ) );
+ action->sources = targetlist( (TARGETS *)0, lol_get( frame->args, 1 ) );
+
+ /* If we have a group of targets all being built using the same action
+ * then we must not allow any of them to be used as sources unless they
+ * had all already been built in the first place or their joined action
+ * has had a chance to finish its work and build all of them anew.
+ *
+ * Without this it might be possible, in case of a multi-process build,
+ * for their action, triggered by buiding one of the targets, to still
+ * be running when another target in the group reports as done in order
+ * to avoid triggering the same action again and gets used prematurely.
+ *
+ * As a quick-fix to achieve this effect we make all the targets list
+ * each other as 'included targets'. More precisely, we mark the first
+ * listed target as including all the other targets in the list and vice
+ * versa. This makes anyone depending on any of those targets implicitly
+ * depend on all of them, thus making sure none of those targets can be
+ * used as sources until all of them have been built. Note that direct
+ * dependencies could not have been used due to the 'circular
+ * dependency' issue.
+ *
+ * TODO: Although the current implementation solves the problem of one
+ * of the targets getting used before its action completes its work it
+ * also forces the action to run whenever any of the targets in the
+ * group is not up to date even though some of them might not actually
+ * be used by the targets being built. We should see how we can
+ * correctly recognize such cases and use that to avoid running the
+ * action if possible and not rebuild targets not actually depending on
+ * targets that are not up to date.
+ *
+ * TODO: Using the 'include' feature might have side-effects due to
+ * interaction with the actual 'inclusion scanning' system. This should
+ * be checked.
+ */
+ if ( action->targets )
+ {
+ TARGET * t0 = action->targets->target;
+ for ( t = action->targets->next; t; t = t->next )
+ {
+ target_include( t->target, t0 );
+ target_include( t0, t->target );
+ }
+ }
+
+ /* Append this action to the actions of each target. */
+ for ( t = action->targets; t; t = t->next )
+ t->target->actions = actionlist( t->target->actions, action );
+ }
+
+ /* Now recursively compile any parse tree associated with this rule.
+ * parse_refer()/parse_free() call pair added to ensure rule not freed
+ * during use.
+ */
+ if ( rule->procedure )
+ {
+ SETTINGS * local_args = collect_arguments( rule, frame );
+ PARSE * parse = rule->procedure;
+ parse_refer( parse );
+
+ pushsettings( local_args );
+ result = parse_evaluate( parse, frame );
+ popsettings( local_args );
+ freesettings( local_args );
+
+ parse_free( parse );
+ }
+
+ if ( frame->module != prev_module )
+ {
+ exit_module( frame->module );
+ enter_module( prev_module );
+ }
+
+ if ( DEBUG_PROFILE && rule->procedure )
+ profile_exit( prof );
+
+ if ( DEBUG_COMPILE )
+ debug_compile( -1, 0, frame);
+
+ return result;
+}
+
+
+/*
+ * Call the given rule with the specified parameters. The parameters should be
+ * of type LIST* and end with a NULL pointer. This differs from 'evaluate_rule'
+ * in that frame for the called rule is prepared inside 'call_rule'.
+ *
+ * This function is useful when a builtin rule (in C) wants to call another rule
+ * which might be implemented in Jam.
+ */
+
+LIST * call_rule( char * rulename, FRAME * caller_frame, ... )
+{
+ va_list va;
+ LIST * result;
+
+ FRAME inner[1];
+ frame_init( inner );
+ inner->prev = caller_frame;
+ inner->prev_user = caller_frame->module->user_module ?
+ caller_frame : caller_frame->prev_user;
+ inner->module = caller_frame->module;
+ inner->procedure = 0;
+
+ va_start( va, caller_frame );
+ for ( ; ; )
+ {
+ LIST * l = va_arg( va, LIST* );
+ if ( !l )
+ break;
+ lol_add( inner->args, l );
+ }
+ va_end( va );
+
+ result = evaluate_rule( rulename, inner );
+
+ frame_free( inner );
+
+ return result;
+}
+
+
+/*
+ * compile_rules() - compile a chain of rules
+ *
+ * parse->left single rule
+ * parse->right more compile_rules() by right-recursion
+ */
+
+LIST * compile_rules( PARSE * parse, FRAME * frame )
+{
+ /* Ignore result from first statement; return the 2nd. */
+ /* Optimize recursion on the right by looping. */
+ do list_free( parse_evaluate( parse->left, frame ) );
+ while ( ( parse = parse->right )->func == compile_rules );
+ return parse_evaluate( parse, frame );
+}
+
+
+/*
+ * assign_var_mode() - convert ASSIGN_XXX compilation flag into corresponding
+ * VAR_XXX variable set flag.
+ */
+
+static int assign_var_mode( int parsenum, char const * * tracetext )
+{
+ char const * trace;
+ int setflag;
+ switch ( parsenum )
+ {
+ case ASSIGN_SET : setflag = VAR_SET ; trace = "=" ; break;
+ case ASSIGN_APPEND : setflag = VAR_APPEND ; trace = "+="; break;
+ case ASSIGN_DEFAULT: setflag = VAR_DEFAULT; trace = "?="; break;
+ default: setflag = VAR_SET ; trace = "" ; break;
+ }
+ if ( tracetext )
+ *tracetext = trace ;
+ return setflag;
+}
+
+/*
+ * compile_set() - compile the "set variable" statement
+ *
+ * parse->left variable names
+ * parse->right variable values
+ * parse->num ASSIGN_SET/APPEND/DEFAULT
+ */
+
+LIST * compile_set( PARSE * parse, FRAME * frame )
+{
+ LIST * nt = parse_evaluate( parse->left, frame );
+ LIST * ns = parse_evaluate( parse->right, frame );
+ LIST * l;
+ char const * trace;
+ int setflag = assign_var_mode( parse->num, &trace );
+
+ if ( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "set", frame );
+ list_print( nt );
+ printf( " %s ", trace );
+ list_print( ns );
+ printf( "\n" );
+ }
+
+ /* Call var_set to set variable. var_set keeps ns, so need to copy it. */
+ for ( l = nt; l; l = list_next( l ) )
+ var_set( l->string, list_copy( L0, ns ), setflag );
+ list_free( nt );
+ return ns;
+}
+
+
+/*
+ * compile_setcomp() - support for `rule` - save parse tree.
+ *
+ * parse->string rule name
+ * parse->left rules for rule
+ * parse->right optional list-of-lists describing arguments
+ */
+
+LIST * compile_setcomp( PARSE * parse, FRAME * frame )
+{
+ argument_list * arg_list = 0;
+
+ /* Create new LOL describing argument requirements if supplied. */
+ if ( parse->right )
+ {
+ PARSE * p;
+ arg_list = args_new();
+ for ( p = parse->right; p; p = p->left )
+ lol_add( arg_list->data, parse_evaluate( p->right, frame ) );
+ }
+
+ new_rule_body( frame->module, parse->string, arg_list, parse->left, !parse->num );
+ return L0;
+}
+
+
+/*
+ * compile_setexec() - support for `actions` - save execution string.
+ *
+ * parse->string rule name
+ * parse->string1 OS command string
+ * parse->num flags
+ * parse->left `bind` variables
+ *
+ * Note that the parse flags (as defined in compile.h) are transferred directly
+ * to the rule flags (as defined in rules.h).
+ */
+
+LIST * compile_setexec( PARSE * parse, FRAME * frame )
+{
+ LIST * bindlist = parse_evaluate( parse->left, frame );
+ new_rule_actions( frame->module, parse->string, parse->string1, bindlist, parse->num );
+ return L0;
+}
+
+
+/*
+ * compile_settings() - compile the "on =" (set variable on exec) statement.
+ *
+ * parse->left variable names
+ * parse->right target name
+ * parse->third variable value
+ * parse->num ASSIGN_SET/APPEND
+ */
+
+LIST * compile_settings( PARSE * parse, FRAME * frame )
+{
+ LIST * nt = parse_evaluate( parse->left, frame );
+ LIST * ns = parse_evaluate( parse->third, frame );
+ LIST * targets = parse_evaluate( parse->right, frame );
+ LIST * ts;
+ char const * trace;
+ int setflag = assign_var_mode( parse->num, &trace );
+
+ if ( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "set", frame );
+ list_print( nt );
+ printf( " on " );
+ list_print( targets );
+ printf( " %s ", trace );
+ list_print( ns );
+ printf( "\n" );
+ }
+
+ /* Call addsettings() to save variable setting. addsettings() keeps ns, so
+ * need to copy it. Pass append flag to addsettings().
+ */
+ for ( ts = targets; ts; ts = list_next( ts ) )
+ {
+ TARGET * t = bindtarget( ts->string );
+ LIST * l;
+
+ for ( l = nt; l; l = list_next( l ) )
+ t->settings = addsettings( t->settings, setflag, l->string,
+ list_copy( (LIST *)0, ns ) );
+ }
+
+ list_free( nt );
+ list_free( targets );
+ return ns;
+}
+
+
+/*
+ * compile_switch() - compile 'switch' rule.
+ *
+ * parse->left switch value (only 1st used)
+ * parse->right cases
+ *
+ * cases->left 1st case
+ * cases->right next cases
+ *
+ * case->string argument to match
+ * case->left parse tree to execute
+ */
+
+LIST * compile_switch( PARSE * parse, FRAME * frame )
+{
+ LIST * nt = parse_evaluate( parse->left, frame );
+ LIST * result = 0;
+
+ if ( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "switch", frame );
+ list_print( nt );
+ printf( "\n" );
+ }
+
+ /* Step through cases. */
+ for ( parse = parse->right; parse; parse = parse->right )
+ {
+ if ( !glob( parse->left->string, nt ? nt->string : "" ) )
+ {
+ /* Get & exec parse tree for this case. */
+ parse = parse->left->left;
+ result = parse_evaluate( parse, frame );
+ break;
+ }
+ }
+
+ list_free( nt );
+ return result;
+}
+
+
+/*
+ * debug_compile() - printf with indent to show rule expansion.
+ */
+
+static void debug_compile( int which, char * s, FRAME * frame )
+{
+ static int level = 0;
+ static char indent[36] = ">>>>|>>>>|>>>>|>>>>|>>>>|>>>>|>>>>|";
+
+ if ( which >= 0 )
+ {
+ int i;
+
+ print_source_line( frame->procedure );
+
+ i = ( level + 1 ) * 2;
+ while ( i > 35 )
+ {
+ fputs( indent, stdout );
+ i -= 35;
+ }
+
+ printf( "%*.*s ", i, i, indent );
+ }
+
+ if ( s )
+ printf( "%s ", s );
+
+ level += which;
+}
diff --git a/tools/build/v2/engine/compile.h b/tools/build/v2/engine/compile.h
new file mode 100644
index 0000000000..7d5191f0e1
--- /dev/null
+++ b/tools/build/v2/engine/compile.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef COMPILE_DWA20011022_H
+# define COMPILE_DWA20011022_H
+
+# include "frames.h"
+# include "parse.h"
+# include "regexp.h"
+
+/*
+ * compile.h - compile parsed jam statements
+ */
+
+void compile_builtins();
+
+LIST *compile_append( PARSE *parse, FRAME *frame );
+LIST *compile_foreach( PARSE *parse, FRAME *frame );
+LIST *compile_if( PARSE *parse, FRAME *frame );
+LIST *compile_eval( PARSE *parse, FRAME *args );
+LIST *compile_include( PARSE *parse, FRAME *frame );
+LIST *compile_list( PARSE *parse, FRAME *frame );
+LIST *compile_local( PARSE *parse, FRAME *frame );
+LIST *compile_module( PARSE *parse, FRAME *frame );
+LIST *compile_class( PARSE *parse, FRAME *frame );
+LIST *compile_null( PARSE *parse, FRAME *frame );
+LIST *compile_on( PARSE *parse, FRAME *frame );
+LIST *compile_rule( PARSE *parse, FRAME *frame );
+LIST *compile_rules( PARSE *parse, FRAME *frame );
+LIST *compile_set( PARSE *parse, FRAME *frame );
+LIST *compile_setcomp( PARSE *parse, FRAME *frame );
+LIST *compile_setexec( PARSE *parse, FRAME *frame );
+LIST *compile_settings( PARSE *parse, FRAME *frame );
+LIST *compile_switch( PARSE *parse, FRAME *frame );
+LIST *compile_while( PARSE *parse, FRAME *frame );
+
+LIST *evaluate_rule( char *rulename, FRAME *frame );
+LIST *call_rule( char *rulename, FRAME* caller_frame, ...);
+
+regexp* regex_compile( const char* pattern );
+
+/* Flags for compile_set(), etc */
+
+# define ASSIGN_SET 0x00 /* = assign variable */
+# define ASSIGN_APPEND 0x01 /* += append variable */
+# define ASSIGN_DEFAULT 0x02 /* set only if unset */
+
+/* Flags for compile_setexec() */
+
+# define EXEC_UPDATED 0x01 /* executes updated */
+# define EXEC_TOGETHER 0x02 /* executes together */
+# define EXEC_IGNORE 0x04 /* executes ignore */
+# define EXEC_QUIETLY 0x08 /* executes quietly */
+# define EXEC_PIECEMEAL 0x10 /* executes piecemeal */
+# define EXEC_EXISTING 0x20 /* executes existing */
+
+/* Conditions for compile_if() */
+
+# define EXPR_NOT 0 /* ! cond */
+# define EXPR_AND 1 /* cond && cond */
+# define EXPR_OR 2 /* cond || cond */
+
+# define EXPR_EXISTS 3 /* arg */
+# define EXPR_EQUALS 4 /* arg = arg */
+# define EXPR_NOTEQ 5 /* arg != arg */
+# define EXPR_LESS 6 /* arg < arg */
+# define EXPR_LESSEQ 7 /* arg <= arg */
+# define EXPR_MORE 8 /* arg > arg */
+# define EXPR_MOREEQ 9 /* arg >= arg */
+# define EXPR_IN 10 /* arg in arg */
+
+#endif
+
diff --git a/tools/build/v2/engine/debian/changelog b/tools/build/v2/engine/debian/changelog
new file mode 100644
index 0000000000..29084289cc
--- /dev/null
+++ b/tools/build/v2/engine/debian/changelog
@@ -0,0 +1,72 @@
+bjam (3.1.12-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Rene Rivera <grafik@redshift-software.com> Sat, 01 Oct 2005 00:00:00 +0000
+
+bjam (3.1.11-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Rene Rivera <grafik@redshift-software.com> Sat, 30 Apr 2005 00:00:00 +0000
+
+bjam (3.1.10-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Rene Rivera <grafik@redshift-software.com> Tue, 1 Jun 2004 05:42:35 +0000
+
+bjam (3.1.9-2) unstable; urgency=low
+
+ * Use default value of BOOST_BUILD_PATH is not is set in environment.
+
+ -- Vladimir Prus <ghost@zigzag.lvk.cs.msu.su> Wed, 17 Dec 2003 16:44:35 +0300
+
+bjam (3.1.9-1) unstable; urgency=low
+
+ * Implement NATIVE_FILE builtin and several native rules.
+
+ -- Vladimir Prus <ghost@zigzag.lvk.cs.msu.su> Thu, 11 Dec 2003 13:15:26 +0300
+
+bjam (3.1.8-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Vladimir Prus <ghost@zigzag.lvk.cs.msu.su> Tue, 4 Nov 2003 20:50:43 +0300
+
+bjam (3.1.7-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Vladimir Prus <ghost@zigzag.lvk.cs.msu.su> Thu, 11 Sep 2003 10:45:44 +0400
+
+bjam (3.1.6-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Vladimir Prus <ghost@zigzag.lvk.cs.msu.su> Tue, 1 Jul 2003 09:12:18 +0400
+
+bjam (3.1.5-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Vladimir Prus <ghost@zigzag.lvk.cs.msu.su> Mon, 19 May 2003 14:05:13 +0400
+
+bjam (3.1.3-2) unstable; urgency=low
+
+ * Changed Debian package to be similar to Jam's package.
+
+ -- Vladimir Prus <ghost@cs.msu.su> Thu, 10 Oct 2002 18:43:26 +0400
+
+bjam (3.1.3-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Vladimir Prus <ghost@zigzag.lvk.cs.msu.su> Fri, 4 Oct 2002 18:16:54 +0400
+
+bjam (3.1.2-1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- Vladimir Prus <ghost@cs.msu.su> Wed, 14 Aug 2002 14:08:00 +0400
+
diff --git a/tools/build/v2/engine/debian/control b/tools/build/v2/engine/debian/control
new file mode 100644
index 0000000000..c7f151932e
--- /dev/null
+++ b/tools/build/v2/engine/debian/control
@@ -0,0 +1,16 @@
+Source: bjam
+Section: devel
+Priority: optional
+Maintainer: Vladimir Prus <ghost@cs.msu.su>
+Build-Depends: debhelper (>> 3.0.0), docbook-to-man, bison
+Standards-Version: 3.5.2
+
+Package: bjam
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: Build tool
+ Boost.Jam is a portable build tool with its own interpreted language, which
+ allows to implement rather complex logic in a readable way and without
+ resorting to external programs. It is a descendant of Jam/MR tool modified to
+ suit the needs of Boost.Build. In particular, modules and rule parameters
+ were added, as well as several new builtins.
diff --git a/tools/build/v2/engine/debian/copyright b/tools/build/v2/engine/debian/copyright
new file mode 100644
index 0000000000..f72e4e3a96
--- /dev/null
+++ b/tools/build/v2/engine/debian/copyright
@@ -0,0 +1,25 @@
+This package was debianized by Vladimir Prus <ghost@cs.msu.su> on
+Wed, 17 July 2002, 19:27:00 +0400.
+
+Copyright:
+
+ /+\
+ +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ \+/
+
+ This is Release 2.4 of Jam/MR, a make-like program.
+
+ License is hereby granted to use this software and distribute it
+ freely, as long as this copyright notice is retained and modifications
+ are clearly marked.
+
+ ALL WARRANTIES ARE HEREBY DISCLAIMED.
+
+Some portions are also:
+
+ Copyright 2001-2006 David Abrahams.
+ Copyright 2002-2006 Rene Rivera.
+ Copyright 2003-2006 Vladimir Prus.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
diff --git a/tools/build/v2/engine/debian/jam.man.sgml b/tools/build/v2/engine/debian/jam.man.sgml
new file mode 100644
index 0000000000..ee21d4d830
--- /dev/null
+++ b/tools/build/v2/engine/debian/jam.man.sgml
@@ -0,0 +1,236 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
+
+<!-- Process this file with docbook-to-man to generate an nroff manual
+ page: `docbook-to-man manpage.sgml > manpage.1'. You may view
+ the manual page with: `docbook-to-man manpage.sgml | nroff -man |
+ less'. A typical entry in a Makefile or Makefile.am is:
+
+manpage.1: manpage.sgml
+ docbook-to-man $< > $@
+ -->
+
+ <!ENTITY dhfirstname "<firstname>Yann</firstname>">
+ <!ENTITY dhsurname "<surname>Dirson</surname>">
+ <!-- Please adjust the date whenever revising the manpage. -->
+ <!ENTITY dhdate "<date>mai 23, 2001</date>">
+ <!ENTITY dhemail "<email>dirson@debian.org</email>">
+ <!ENTITY dhusername "Yann Dirson">
+ <!ENTITY dhpackage "jam">
+
+ <!ENTITY debian "<productname>Debian GNU/Linux</productname>">
+ <!ENTITY gnu "<acronym>GNU</acronym>">
+]>
+
+<refentry>
+ <refentryinfo>
+ <address>
+ &dhemail;
+ </address>
+ <author>
+ &dhfirstname;
+ &dhsurname;
+ </author>
+ <copyright>
+ <year>2001</year>
+ <holder>&dhusername;</holder>
+ </copyright>
+ &dhdate;
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>JAM</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>Jam/MR</refname>
+ <refpurpose>Make(1) Redux</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>jam</command>
+
+ <arg><option>-a</option></arg>
+ <arg><option>-n</option></arg>
+ <arg><option>-v</option></arg>
+
+ <arg><option>-d <replaceable/debug/</option></arg>
+ <arg><option>-f <replaceable/jambase/</option></arg>
+ <arg><option>-j <replaceable/jobs/</option></arg>
+ <arg><option>-o <replaceable/actionsfile/</option></arg>
+ <arg><option>-s <replaceable/var/=<replaceable/value/</option></arg>
+ <arg><option>-t <replaceable/target/</option></arg>
+
+ <arg repeat><option><replaceable/target/</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para>Jam is a program construction tool, like make(1).</para>
+
+ <para>Jam recursively builds target files from source files, using
+ dependency information and updating actions expressed in the
+ Jambase file, which is written in jam's own interpreted language.
+ The default Jambase is compiled into jam and provides a
+ boilerplate for common use, relying on a user-provide file
+ "Jamfile" to enumerate actual targets and sources.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><option/-a/</term>
+ <listitem>
+ <para>Build all targets anyway, even if they are up-to-date.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-d <replaceable/n/</option></term>
+ <listitem>
+ <para>Enable cummulative debugging levels from 1 to
+ <replaceable/n/. Interesting values are:
+
+ <glosslist>
+ <glossentry><glossterm/1/ <glossdef><simpara/Show
+ actions (the default)/</glossdef></glossentry>
+
+ <glossentry><glossterm/2/ <glossdef><simpara/Show
+ "quiet" actions and display all action
+ text/</glossdef></glossentry>
+
+ <glossentry><glossterm/3/ <glossdef><simpara>Show
+ dependency analysis, and target/source
+ timestamps/paths</simpara></glossdef></glossentry>
+
+ <glossentry><glossterm/4/ <glossdef><simpara/Show shell
+ arguments/</glossdef></glossentry>
+
+ <glossentry><glossterm/5/ <glossdef><simpara/Show rule
+ invocations and variable
+ expansions/</glossdef></glossentry>
+
+ <glossentry><glossterm/6/ <glossdef><simpara>Show
+ directory/header file/archive
+ scans</simpara></glossdef></glossentry>
+
+ <glossentry><glossterm/7/ <glossdef><simpara/Show
+ variable settings/</glossdef></glossentry>
+
+ <glossentry><glossterm/8/ <glossdef><simpara/Show
+ variable fetches/</glossdef></glossentry>
+
+ <glossentry><glossterm/9/ <glossdef><simpara/Show
+ variable manipulation, scanner
+ tokens/</glossdef></glossentry>
+ </glosslist>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-d +<replaceable/n/</option></term>
+ <listitem>
+ <para>Enable debugging level <replaceable/n/.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option/-d 0/</term>
+ <listitem>
+ <para>Turn off all debugging levels. Only errors are not
+ suppressed.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-f <replaceable/jambase/</option></term>
+ <listitem>
+ <para>Read <replaceable/jambase/ instead of using the
+ built-in Jambase. Only one <option/-f/ flag is permitted,
+ but the <replaceable/jambase/ may explicitly include other
+ files.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-j <replaceable/n/</option></term>
+ <listitem>
+ <para>Run up to <replaceable/n/ shell commands concurrently
+ (UNIX and NT only). The default is 1.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option/-n/</term>
+ <listitem>
+ <para>Don't actually execute the updating actions, but do
+ everything else. This changes the debug level default to
+ <option/-d2/.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-o <replaceable/file/</option></term>
+ <listitem>
+ <para>Write the updating actions to the specified file
+ instead of running them (or outputting them, as on the
+ Mac).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-s <replaceable/var/=<replaceable/value/</option></term>
+ <listitem>
+ <para>Set the variable <replaceable/var/ to
+ <replaceable/value/, overriding both internal variables and
+ variables imported from the environment. </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-t <replaceable/target/</option></term>
+ <listitem>
+ <para>Rebuild <replaceable/target/ and everything that
+ depends on it, even if it is up-to-date.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option/-v/</term>
+ <listitem>
+ <para>Print the version of jam and exit.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+
+ <para>Jam is documented fully in HTML pages available on Debian
+ systems from
+ <filename>/usr/share/doc/jam/Jam.html</filename>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+
+ <para>This manual page was created by &dhusername; &dhemail; from
+ the <filename/Jam.html/ documentation, for the &debian; system
+ (but may be used by others).</para>
+ </refsect1>
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+sgml-omittag:t
+sgml-shorttag:t
+End:
+-->
diff --git a/tools/build/v2/engine/debian/rules b/tools/build/v2/engine/debian/rules
new file mode 100755
index 0000000000..756052a3b3
--- /dev/null
+++ b/tools/build/v2/engine/debian/rules
@@ -0,0 +1,73 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 to 1999 by Joey Hess.
+# GNU copyright 2001 by Yann Dirson.
+
+# This is the debian/rules file for packages jam and ftjam
+# It should be usable with both packages without any change
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# This is the debhelper compatability version to use.
+export DH_COMPAT=3
+
+topdir=$(shell pwd)
+
+jam=bjam
+binname=bjam
+
+build: build-stamp
+build-stamp: debian/jam.1
+ dh_testdir
+
+ ./build.sh
+
+ touch build-stamp
+
+%.1: %.man.sgml
+ /usr/bin/docbook-to-man $< > $@
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp
+ rm -rf bin.*
+ rm -f jam0 debian/jam.1
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ install -d ${topdir}/debian/${jam}/usr/bin
+ install -m755 bin.linuxx86/bjam ${topdir}/debian/${jam}/usr/bin/
+ install -d ${topdir}/debian/${jam}/usr/share/man/man1/
+ install -m644 debian/jam.1 ${topdir}/debian/${jam}/usr/share/man/man1/${binname}.1
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installdocs README RELNOTES Jambase *.html
+# dh_installemacsen
+# dh_undocumented
+ dh_installchangelogs
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/tools/build/v2/engine/debug.c b/tools/build/v2/engine/debug.c
new file mode 100644
index 0000000000..7290555a74
--- /dev/null
+++ b/tools/build/v2/engine/debug.c
@@ -0,0 +1,132 @@
+/*
+ Copyright Rene Rivera 2005.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "jam.h"
+
+#include "hash.h"
+
+#include <time.h>
+#include <assert.h>
+
+
+static profile_frame * profile_stack = 0;
+static struct hash * profile_hash = 0;
+static profile_info profile_other = { "[OTHER]", 0, 0, 0, 0, 0 };
+static profile_info profile_total = { "[TOTAL]", 0, 0, 0, 0, 0 };
+
+
+profile_frame * profile_init( char * rulename, profile_frame * frame )
+{
+ if ( DEBUG_PROFILE ) profile_enter( rulename, frame );
+ return frame;
+}
+
+
+void profile_enter( char * rulename, profile_frame * frame )
+{
+ if ( DEBUG_PROFILE )
+ {
+ clock_t start = clock();
+ profile_info info;
+ profile_info * p = &info;
+
+ if ( !rulename ) p = &profile_other;
+
+ if ( !profile_hash && rulename )
+ profile_hash = hashinit( sizeof( profile_info ), "profile" );
+
+ info.name = rulename;
+
+ if ( rulename && hashenter( profile_hash, (HASHDATA * *)&p ) )
+ p->cumulative = p->net = p->num_entries = p->stack_count = p->memory = 0;
+
+ ++p->num_entries;
+ ++p->stack_count;
+
+ frame->info = p;
+
+ frame->caller = profile_stack;
+ profile_stack = frame;
+
+ frame->entry_time = clock();
+ frame->overhead = 0;
+ frame->subrules = 0;
+
+ /* caller pays for the time it takes to play with the hash table */
+ if ( frame->caller )
+ frame->caller->overhead += frame->entry_time - start;
+ }
+}
+
+
+void profile_memory( long mem )
+{
+ if ( DEBUG_PROFILE )
+ if ( profile_stack && profile_stack->info )
+ profile_stack->info->memory += mem;
+}
+
+
+void profile_exit( profile_frame * frame )
+{
+ if ( DEBUG_PROFILE )
+ {
+ /* Cumulative time for this call. */
+ clock_t t = clock() - frame->entry_time - frame->overhead;
+ /* If this rule is already present on the stack, don't add the time for
+ * this instance.
+ */
+ if ( frame->info->stack_count == 1 )
+ frame->info->cumulative += t;
+ /* Net time does not depend on presense of the same rule in call stack.
+ */
+ frame->info->net += t - frame->subrules;
+
+ if ( frame->caller )
+ {
+ /* Caller's cumulative time must account for this overhead. */
+ frame->caller->overhead += frame->overhead;
+ frame->caller->subrules += t;
+ }
+ /* Pop this stack frame. */
+ --frame->info->stack_count;
+ profile_stack = frame->caller;
+ }
+}
+
+
+static void dump_profile_entry( void * p_, void * ignored )
+{
+ profile_info * p = (profile_info *)p_;
+ unsigned long mem_each = ( p->memory / ( p->num_entries ? p->num_entries : 1 ) );
+ double cumulative = p->cumulative;
+ double net = p->net;
+ double q = p->net;
+ q /= ( p->num_entries ? p->num_entries : 1 );
+ cumulative /= CLOCKS_PER_SEC;
+ net /= CLOCKS_PER_SEC;
+ q /= CLOCKS_PER_SEC;
+ if ( !ignored )
+ {
+ profile_total.cumulative += p->net;
+ profile_total.memory += p->memory;
+ }
+ printf( "%10ld %12.6f %12.6f %12.8f %10ld %10ld %s\n", p->num_entries,
+ cumulative, net, q, p->memory, mem_each, p->name );
+}
+
+
+void profile_dump()
+{
+ if ( profile_hash )
+ {
+ printf( "%10s %12s %12s %12s %10s %10s %s\n", "--count--", "--gross--",
+ "--net--", "--each--", "--mem--", "--each--", "--name--" );
+ hashenumerate( profile_hash, dump_profile_entry, 0 );
+ dump_profile_entry( &profile_other, 0 );
+ dump_profile_entry( &profile_total, (void *)1 );
+ }
+}
diff --git a/tools/build/v2/engine/debug.h b/tools/build/v2/engine/debug.h
new file mode 100644
index 0000000000..115a88735b
--- /dev/null
+++ b/tools/build/v2/engine/debug.h
@@ -0,0 +1,54 @@
+/*
+ Copyright Rene Rivera 2005.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BJAM_DEBUG_H
+#define BJAM_DEBUG_H
+
+#include "jam.h"
+#include <time.h>
+
+
+struct profile_info
+{
+ /* name of rule being called */
+ char* name;
+ /* cumulative time spent in rule */
+ clock_t cumulative;
+ /* time spent in rule proper */
+ clock_t net;
+ /* number of time rule was entered */
+ unsigned long num_entries;
+ /* number of the times this function is present in stack */
+ unsigned long stack_count;
+ /* bytes of memory allocated by the call */
+ unsigned long memory;
+};
+typedef struct profile_info profile_info;
+
+struct profile_frame
+{
+ /* permanent storage where data accumulates */
+ profile_info* info;
+ /* overhead for profiling in this call */
+ clock_t overhead;
+ /* time of last entry to rule */
+ clock_t entry_time;
+ /* stack frame of caller */
+ struct profile_frame* caller;
+ /* time spent in subrules */
+ clock_t subrules;
+};
+typedef struct profile_frame profile_frame;
+
+profile_frame * profile_init( char * rulename, profile_frame * frame );
+void profile_enter( char* rulename, profile_frame * frame );
+void profile_memory( long mem );
+void profile_exit( profile_frame * frame );
+void profile_dump();
+
+#define PROFILE_ENTER( scope ) profile_frame PROF_ ## scope, *PROF_ ## scope ## _p = profile_init( #scope, &PROF_ ## scope )
+#define PROFILE_EXIT( scope ) profile_exit( PROF_ ## scope ## _p )
+
+#endif
diff --git a/tools/build/v2/engine/execcmd.h b/tools/build/v2/engine/execcmd.h
new file mode 100644
index 0000000000..67f2b839c6
--- /dev/null
+++ b/tools/build/v2/engine/execcmd.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * execcmd.h - execute a shell script.
+ *
+ * Defines the interface to be implemented in platform specific implementation
+ * modules.
+ *
+ * 05/04/94 (seiwald) - async multiprocess interface
+ */
+
+#ifndef EXECCMD_H
+#define EXECCMD_H
+
+#include <time.h>
+
+typedef struct timing_info
+{
+ double system;
+ double user;
+ time_t start;
+ time_t end;
+} timing_info;
+
+void exec_cmd
+(
+ char * string,
+ void (* func)( void * closure, int status, timing_info *, char *, char * ),
+ void * closure,
+ LIST * shell,
+ char * action,
+ char * target
+);
+
+int exec_wait();
+
+#define EXEC_CMD_OK 0
+#define EXEC_CMD_FAIL 1
+#define EXEC_CMD_INTR 2
+
+#endif
diff --git a/tools/build/v2/engine/execmac.c b/tools/build/v2/engine/execmac.c
new file mode 100644
index 0000000000..2ddddedd15
--- /dev/null
+++ b/tools/build/v2/engine/execmac.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+#include "jam.h"
+#include "lists.h"
+#include "execcmd.h"
+#include <errno.h>
+
+#ifdef OS_MAC
+
+/*
+ * execunix.c - execute a shell script on UNIX
+ *
+ * If $(JAMSHELL) is defined, uses that to formulate execvp().
+ * The default is:
+ *
+ * /bin/sh -c %
+ *
+ * Each word must be an individual element in a jam variable value.
+ *
+ * In $(JAMSHELL), % expands to the command string and ! expands to
+ * the slot number (starting at 1) for multiprocess (-j) invocations.
+ * If $(JAMSHELL) doesn't include a %, it is tacked on as the last
+ * argument.
+ *
+ * Don't just set JAMSHELL to /bin/sh - it won't work!
+ *
+ * External routines:
+ * exec_cmd() - launch an async command execution.
+ * exec_wait() - wait and drive at most one execution completion.
+ *
+ * Internal routines:
+ * onintr() - bump intr to note command interruption.
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 05/04/94 (seiwald) - async multiprocess interface
+ * 01/22/95 (seiwald) - $(JAMSHELL) support
+ */
+
+
+/*
+ * exec_cmd() - launch an async command execution.
+ */
+
+void exec_cmd
+(
+ char * string,
+ void (* func)( void * closure, int status, timing_info *, char *, char * ),
+ void * closure,
+ LIST * shell
+)
+{
+ printf( "%s", string );
+ (*func)( closure, EXEC_CMD_OK );
+}
+
+/*
+ * exec_wait() - wait and drive at most one execution completion.
+ */
+
+int exec_wait()
+{
+ return 0;
+}
+
+#endif /* OS_MAC */
diff --git a/tools/build/v2/engine/execnt.c b/tools/build/v2/engine/execnt.c
new file mode 100644
index 0000000000..7642045180
--- /dev/null
+++ b/tools/build/v2/engine/execnt.c
@@ -0,0 +1,1296 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Copyright 2007 Rene Rivera.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include "jam.h"
+#include "lists.h"
+#include "execcmd.h"
+#include "pathsys.h"
+#include "string.h"
+#include "output.h"
+#include <errno.h>
+#include <assert.h>
+#include <ctype.h>
+#include <time.h>
+#include <math.h>
+
+#ifdef USE_EXECNT
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <process.h>
+#include <tlhelp32.h>
+
+/*
+ * execnt.c - execute a shell command on Windows NT
+ *
+ * If $(JAMSHELL) is defined, uses that to formulate execvp()/spawnvp().
+ * The default is:
+ *
+ * /bin/sh -c % [ on UNIX/AmigaOS ]
+ * cmd.exe /c % [ on Windows NT ]
+ *
+ * Each word must be an individual element in a jam variable value.
+ *
+ * In $(JAMSHELL), % expands to the command string and ! expands to
+ * the slot number (starting at 1) for multiprocess (-j) invocations.
+ * If $(JAMSHELL) doesn't include a %, it is tacked on as the last
+ * argument.
+ *
+ * Don't just set JAMSHELL to /bin/sh or cmd.exe - it won't work!
+ *
+ * External routines:
+ * exec_cmd() - launch an async command execution.
+ * exec_wait() - wait and drive at most one execution completion.
+ *
+ * Internal routines:
+ * onintr() - bump intr to note command interruption.
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 05/04/94 (seiwald) - async multiprocess interface
+ * 01/22/95 (seiwald) - $(JAMSHELL) support
+ * 06/02/97 (gsar) - full async multiprocess support for Win32
+ */
+
+/* get the maximum command line length according to the OS */
+int maxline();
+
+/* delete and argv list */
+static void free_argv(char**);
+/* Convert a command string into arguments for spawnvp. */
+static char** string_to_args(const char*);
+/* bump intr to note command interruption */
+static void onintr(int);
+/* If the command is suitable for execution via spawnvp */
+long can_spawn(char*);
+/* Add two 64-bit unsigned numbers, h1l1 and h2l2 */
+static FILETIME add_64(
+ unsigned long h1, unsigned long l1,
+ unsigned long h2, unsigned long l2);
+static FILETIME add_FILETIME(FILETIME t1, FILETIME t2);
+static FILETIME negate_FILETIME(FILETIME t);
+/* Convert a FILETIME to a number of seconds */
+static double filetime_seconds(FILETIME t);
+/* record the timing info for the process */
+static void record_times(HANDLE, timing_info*);
+/* calc the current running time of an *active* process */
+static double running_time(HANDLE);
+/* */
+DWORD get_process_id(HANDLE);
+/* terminate the given process, after terminating all its children */
+static void kill_process_tree(DWORD, HANDLE);
+/* waits for a command to complete or for the given timeout, whichever is first */
+static int try_wait(int timeoutMillis);
+/* reads any pending output for running commands */
+static void read_output();
+/* checks if a command ran out of time, and kills it */
+static int try_kill_one();
+/* */
+static double creation_time(HANDLE);
+/* Recursive check if first process is parent (directly or indirectly) of
+the second one. */
+static int is_parent_child(DWORD, DWORD);
+/* */
+static void close_alert(HANDLE);
+/* close any alerts hanging around */
+static void close_alerts();
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+static int intr = 0;
+static int cmdsrunning = 0;
+static void (* istat)( int );
+
+
+/* The list of commands we run. */
+static struct
+{
+ string action; /* buffer to hold action */
+ string target; /* buffer to hold target */
+ string command; /* buffer to hold command being invoked */
+
+ /* Temporary batch file used to execute the action when needed. */
+ char * tempfile_bat;
+
+ /* Pipes for communicating with the child process. Parent reads from (0),
+ * child writes to (1).
+ */
+ HANDLE pipe_out[ 2 ];
+ HANDLE pipe_err[ 2 ];
+
+ string buffer_out; /* buffer to hold stdout, if any */
+ string buffer_err; /* buffer to hold stderr, if any */
+
+ PROCESS_INFORMATION pi; /* running process information */
+ DWORD exit_code; /* executed command's exit code */
+ int exit_reason; /* reason why a command completed */
+
+ /* Function called when the command completes. */
+ void (* func)( void * closure, int status, timing_info *, char *, char * );
+
+ /* Opaque data passed back to the 'func' callback called when the command
+ * completes.
+ */
+ void * closure;
+}
+cmdtab[ MAXJOBS ] = { { 0 } };
+
+
+/*
+ * Execution unit tests.
+ */
+
+void execnt_unit_test()
+{
+#if !defined( NDEBUG )
+ /* vc6 preprocessor is broken, so assert with these strings gets confused.
+ * Use a table instead.
+ */
+ typedef struct test { char * command; int result; } test;
+ test tests[] = {
+ { "x", 0 },
+ { "x\n ", 0 },
+ { "x\ny", 1 },
+ { "x\n\n y", 1 },
+ { "echo x > foo.bar", 1 },
+ { "echo x < foo.bar", 1 },
+ { "echo x \">\" foo.bar", 0 },
+ { "echo x \"<\" foo.bar", 0 },
+ { "echo x \\\">\\\" foo.bar", 1 },
+ { "echo x \\\"<\\\" foo.bar", 1 } };
+ int i;
+ for ( i = 0; i < sizeof( tests ) / sizeof( *tests ); ++i )
+ assert( !can_spawn( tests[ i ].command ) == tests[ i ].result );
+
+ {
+ char * long_command = BJAM_MALLOC_ATOMIC( MAXLINE + 10 );
+ assert( long_command != 0 );
+ memset( long_command, 'x', MAXLINE + 9 );
+ long_command[ MAXLINE + 9 ] = 0;
+ assert( can_spawn( long_command ) == MAXLINE + 9 );
+ BJAM_FREE( long_command );
+ }
+
+ {
+ /* Work around vc6 bug; it doesn't like escaped string
+ * literals inside assert
+ */
+ char * * argv = string_to_args(" \"g++\" -c -I\"Foobar\"" );
+ char const expected[] = "-c -I\"Foobar\"";
+
+ assert( !strcmp( argv[ 0 ], "g++" ) );
+ assert( !strcmp( argv[ 1 ], expected ) );
+ free_argv( argv );
+ }
+#endif
+}
+
+
+/*
+ * exec_cmd() - launch an async command execution.
+ */
+
+void exec_cmd
+(
+ char * command,
+ void (* func)( void * closure, int status, timing_info *, char * invoked_command, char * command_output ),
+ void * closure,
+ LIST * shell,
+ char * action,
+ char * target
+)
+{
+ int slot;
+ int raw_cmd = 0 ;
+ char * argv_static[ MAXARGC + 1 ]; /* +1 for NULL */
+ char * * argv = argv_static;
+ char * p;
+ char * command_orig = command;
+
+ /* Check to see if we need to hack around the line-length limitation. Look
+ * for a JAMSHELL setting of "%", indicating that the command should be
+ * invoked directly.
+ */
+ if ( shell && !strcmp( shell->string, "%" ) && !list_next( shell ) )
+ {
+ raw_cmd = 1;
+ shell = 0;
+ }
+
+ /* Find a slot in the running commands table for this one. */
+ for ( slot = 0; slot < MAXJOBS; ++slot )
+ if ( !cmdtab[ slot ].pi.hProcess )
+ break;
+ if ( slot == MAXJOBS )
+ {
+ printf( "no slots for child!\n" );
+ exit( EXITBAD );
+ }
+
+ /* Compute the name of a temp batch file, for possible use. */
+ if ( !cmdtab[ slot ].tempfile_bat )
+ {
+ char const * tempdir = path_tmpdir();
+ DWORD procID = GetCurrentProcessId();
+
+ /* SVA - allocate 64 bytes extra just to be safe. */
+ cmdtab[ slot ].tempfile_bat = BJAM_MALLOC_ATOMIC( strlen( tempdir ) + 64 );
+
+ sprintf( cmdtab[ slot ].tempfile_bat, "%s\\jam%d-%02d.bat",
+ tempdir, procID, slot );
+ }
+
+ /* Trim leading, -ending- white space */
+ while ( *( command + 1 ) && isspace( *command ) )
+ ++command;
+
+ /* Write to .BAT file unless the line would be too long and it meets the
+ * other spawnability criteria.
+ */
+ if ( raw_cmd && ( can_spawn( command ) >= MAXLINE ) )
+ {
+ if ( DEBUG_EXECCMD )
+ printf("Executing raw command directly\n");
+ }
+ else
+ {
+ FILE * f = 0;
+ int tries = 0;
+ raw_cmd = 0;
+
+ /* Write command to bat file. For some reason this open can fail
+ * intermitently. But doing some retries works. Most likely this is due
+ * to a previously existing file of the same name that happens to be
+ * opened by an active virus scanner. Pointed out and fixed by Bronek
+ * Kozicki.
+ */
+ for ( ; !f && ( tries < 4 ); ++tries )
+ {
+ f = fopen( cmdtab[ slot ].tempfile_bat, "w" );
+ if ( !f && ( tries < 4 ) ) Sleep( 250 );
+ }
+ if ( !f )
+ {
+ printf( "failed to write command file!\n" );
+ exit( EXITBAD );
+ }
+ fputs( command, f );
+ fclose( f );
+
+ command = cmdtab[ slot ].tempfile_bat;
+
+ if ( DEBUG_EXECCMD )
+ {
+ if ( shell )
+ printf( "using user-specified shell: %s", shell->string );
+ else
+ printf( "Executing through .bat file\n" );
+ }
+ }
+
+ /* Formulate argv; If shell was defined, be prepared for % and ! subs.
+ * Otherwise, use stock cmd.exe.
+ */
+ if ( shell )
+ {
+ int i;
+ char jobno[ 4 ];
+ int gotpercent = 0;
+
+ sprintf( jobno, "%d", slot + 1 );
+
+ for ( i = 0; shell && ( i < MAXARGC ); ++i, shell = list_next( shell ) )
+ {
+ switch ( shell->string[ 0 ] )
+ {
+ case '%': argv[ i ] = command; ++gotpercent; break;
+ case '!': argv[ i ] = jobno; break;
+ default : argv[ i ] = shell->string;
+ }
+ if ( DEBUG_EXECCMD )
+ printf( "argv[%d] = '%s'\n", i, argv[ i ] );
+ }
+
+ if ( !gotpercent )
+ argv[ i++ ] = command;
+
+ argv[ i ] = 0;
+ }
+ else if ( raw_cmd )
+ {
+ argv = string_to_args( command );
+ }
+ else
+ {
+ argv[ 0 ] = "cmd.exe";
+ argv[ 1 ] = "/Q/C"; /* anything more is non-portable */
+ argv[ 2 ] = command;
+ argv[ 3 ] = 0;
+ }
+
+ /* Catch interrupts whenever commands are running. */
+ if ( !cmdsrunning++ )
+ istat = signal( SIGINT, onintr );
+
+ /* Start the command. */
+ {
+ SECURITY_ATTRIBUTES sa
+ = { sizeof( SECURITY_ATTRIBUTES ), 0, 0 };
+ SECURITY_DESCRIPTOR sd;
+ STARTUPINFO si
+ = { sizeof( STARTUPINFO ), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ string cmd;
+
+ /* Init the security data. */
+ InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION );
+ SetSecurityDescriptorDacl( &sd, TRUE, NULL, FALSE );
+ sa.lpSecurityDescriptor = &sd;
+ sa.bInheritHandle = TRUE;
+
+ /* Create the stdout, which is also the merged out + err, pipe. */
+ if ( !CreatePipe( &cmdtab[ slot ].pipe_out[ 0 ],
+ &cmdtab[ slot ].pipe_out[ 1 ], &sa, 0 ) )
+ {
+ perror( "CreatePipe" );
+ exit( EXITBAD );
+ }
+
+ /* Create the stdout, which is also the merged out+err, pipe. */
+ if ( globs.pipe_action == 2 )
+ {
+ if ( !CreatePipe( &cmdtab[ slot ].pipe_err[ 0 ],
+ &cmdtab[ slot ].pipe_err[ 1 ], &sa, 0 ) )
+ {
+ perror( "CreatePipe" );
+ exit( EXITBAD );
+ }
+ }
+
+ /* Set handle inheritance off for the pipe ends the parent reads from. */
+ SetHandleInformation( cmdtab[ slot ].pipe_out[ 0 ], HANDLE_FLAG_INHERIT, 0 );
+ if ( globs.pipe_action == 2 )
+ SetHandleInformation( cmdtab[ slot ].pipe_err[ 0 ], HANDLE_FLAG_INHERIT, 0 );
+
+ /* Hide the child window, if any. */
+ si.dwFlags |= STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+
+ /* Set the child outputs to the pipes. */
+ si.dwFlags |= STARTF_USESTDHANDLES;
+ si.hStdOutput = cmdtab[ slot ].pipe_out[ 1 ];
+ if ( globs.pipe_action == 2 )
+ {
+ /* Pipe stderr to the action error output. */
+ si.hStdError = cmdtab[ slot ].pipe_err[ 1 ];
+ }
+ else if ( globs.pipe_action == 1 )
+ {
+ /* Pipe stderr to the console error output. */
+ si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
+ }
+ else
+ {
+ /* Pipe stderr to the action merged output. */
+ si.hStdError = cmdtab[ slot ].pipe_out[ 1 ];
+ }
+
+ /* Let the child inherit stdin, as some commands assume it's available. */
+ si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+
+ /* Save the operation for exec_wait() to find. */
+ cmdtab[ slot ].func = func;
+ cmdtab[ slot ].closure = closure;
+ if ( action && target )
+ {
+ string_copy( &cmdtab[ slot ].action, action );
+ string_copy( &cmdtab[ slot ].target, target );
+ }
+ else
+ {
+ string_free( &cmdtab[ slot ].action );
+ string_new ( &cmdtab[ slot ].action );
+ string_free( &cmdtab[ slot ].target );
+ string_new ( &cmdtab[ slot ].target );
+ }
+ string_copy( &cmdtab[ slot ].command, command_orig );
+
+ /* Put together the command we run. */
+ {
+ char * * argp = argv;
+ string_new( &cmd );
+ string_copy( &cmd, *(argp++) );
+ while ( *argp )
+ {
+ string_push_back( &cmd, ' ' );
+ string_append( &cmd, *(argp++) );
+ }
+ }
+
+ /* Create output buffers. */
+ string_new( &cmdtab[ slot ].buffer_out );
+ string_new( &cmdtab[ slot ].buffer_err );
+
+ /* Run the command by creating a sub-process for it. */
+ if (
+ ! CreateProcess(
+ NULL , /* application name */
+ cmd.value , /* command line */
+ NULL , /* process attributes */
+ NULL , /* thread attributes */
+ TRUE , /* inherit handles */
+ CREATE_NEW_PROCESS_GROUP, /* create flags */
+ NULL , /* env vars, null inherits env */
+ NULL , /* current dir, null is our */
+ /* current dir */
+ &si , /* startup info */
+ &cmdtab[ slot ].pi /* child process info, if created */
+ )
+ )
+ {
+ perror( "CreateProcess" );
+ exit( EXITBAD );
+ }
+
+ /* Clean up temporary stuff. */
+ string_free( &cmd );
+ }
+
+ /* Wait until we are under the limit of concurrent commands. Do not trust
+ * globs.jobs alone.
+ */
+ while ( ( cmdsrunning >= MAXJOBS ) || ( cmdsrunning >= globs.jobs ) )
+ if ( !exec_wait() )
+ break;
+
+ if ( argv != argv_static )
+ free_argv( argv );
+}
+
+
+/*
+ * exec_wait()
+ * * wait and drive at most one execution completion.
+ * * waits for one command to complete, while processing the i/o for all
+ * ongoing commands.
+ *
+ * Returns 0 if called when there were no more commands being executed or 1
+ * otherwise.
+ */
+
+int exec_wait()
+{
+ int i = -1;
+
+ /* Handle naive make1() which does not know if cmds are running. */
+ if ( !cmdsrunning )
+ return 0;
+
+ /* Wait for a command to complete, while snarfing up any output. */
+ do
+ {
+ /* Check for a complete command, briefly. */
+ i = try_wait(500);
+ /* Read in the output of all running commands. */
+ read_output();
+ /* Close out pending debug style dialogs. */
+ close_alerts();
+ /* Check if a command ran out of time. */
+ if ( i < 0 ) i = try_kill_one();
+ }
+ while ( i < 0 );
+
+ /* We have a command... process it. */
+ --cmdsrunning;
+ {
+ timing_info time;
+ int rstat;
+
+ /* The time data for the command. */
+ record_times( cmdtab[ i ].pi.hProcess, &time );
+
+ /* Clear the temp file. */
+ if ( cmdtab[ i ].tempfile_bat )
+ {
+ unlink( cmdtab[ i ].tempfile_bat );
+ BJAM_FREE( cmdtab[ i ].tempfile_bat );
+ cmdtab[ i ].tempfile_bat = NULL;
+ }
+
+ /* Find out the process exit code. */
+ GetExitCodeProcess( cmdtab[ i ].pi.hProcess, &cmdtab[ i ].exit_code );
+
+ /* The dispossition of the command. */
+ if ( intr )
+ rstat = EXEC_CMD_INTR;
+ else if ( cmdtab[ i ].exit_code != 0 )
+ rstat = EXEC_CMD_FAIL;
+ else
+ rstat = EXEC_CMD_OK;
+
+ /* Output the action block. */
+ out_action(
+ cmdtab[ i ].action.size > 0 ? cmdtab[ i ].action.value : 0,
+ cmdtab[ i ].target.size > 0 ? cmdtab[ i ].target.value : 0,
+ cmdtab[ i ].command.size > 0 ? cmdtab[ i ].command.value : 0,
+ cmdtab[ i ].buffer_out.size > 0 ? cmdtab[ i ].buffer_out.value : 0,
+ cmdtab[ i ].buffer_err.size > 0 ? cmdtab[ i ].buffer_err.value : 0,
+ cmdtab[ i ].exit_reason );
+
+ /* Call the callback, may call back to jam rule land. Assume -p0 in
+ * effect so only pass buffer containing merged output.
+ */
+ (*cmdtab[ i ].func)(
+ cmdtab[ i ].closure,
+ rstat,
+ &time,
+ cmdtab[ i ].command.value,
+ cmdtab[ i ].buffer_out.value );
+
+ /* Clean up the command data, process, etc. */
+ string_free( &cmdtab[ i ].action ); string_new( &cmdtab[ i ].action );
+ string_free( &cmdtab[ i ].target ); string_new( &cmdtab[ i ].target );
+ string_free( &cmdtab[ i ].command ); string_new( &cmdtab[ i ].command );
+ if ( cmdtab[ i ].pi.hProcess ) { CloseHandle( cmdtab[ i ].pi.hProcess ); cmdtab[ i ].pi.hProcess = 0; }
+ if ( cmdtab[ i ].pi.hThread ) { CloseHandle( cmdtab[ i ].pi.hThread ); cmdtab[ i ].pi.hThread = 0; }
+ if ( cmdtab[ i ].pipe_out[ 0 ] ) { CloseHandle( cmdtab[ i ].pipe_out[ 0 ] ); cmdtab[ i ].pipe_out[ 0 ] = 0; }
+ if ( cmdtab[ i ].pipe_out[ 1 ] ) { CloseHandle( cmdtab[ i ].pipe_out[ 1 ] ); cmdtab[ i ].pipe_out[ 1 ] = 0; }
+ if ( cmdtab[ i ].pipe_err[ 0 ] ) { CloseHandle( cmdtab[ i ].pipe_err[ 0 ] ); cmdtab[ i ].pipe_err[ 0 ] = 0; }
+ if ( cmdtab[ i ].pipe_err[ 1 ] ) { CloseHandle( cmdtab[ i ].pipe_err[ 1 ] ); cmdtab[ i ].pipe_err[ 1 ] = 0; }
+ string_free( &cmdtab[ i ].buffer_out ); string_new( &cmdtab[ i ].buffer_out );
+ string_free( &cmdtab[ i ].buffer_err ); string_new( &cmdtab[ i ].buffer_err );
+ cmdtab[ i ].exit_code = 0;
+ cmdtab[ i ].exit_reason = EXIT_OK;
+ }
+
+ return 1;
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+static void free_argv( char * * args )
+{
+ BJAM_FREE( args[ 0 ] );
+ BJAM_FREE( args );
+}
+
+
+/*
+ * For more details on Windows cmd.exe shell command-line length limitations see
+ * the following MSDN article:
+ * http://support.microsoft.com/default.aspx?scid=kb;en-us;830473
+ */
+
+int maxline()
+{
+ OSVERSIONINFO os_info;
+ os_info.dwOSVersionInfoSize = sizeof( os_info );
+ GetVersionEx( &os_info );
+
+ if ( os_info.dwMajorVersion >= 5 ) return 8191; /* XP > */
+ if ( os_info.dwMajorVersion == 4 ) return 2047; /* NT 4.x */
+ return 996; /* NT 3.5.1 */
+}
+
+
+/*
+ * Convert a command string into arguments for spawnvp(). The original code,
+ * inherited from ftjam, tried to break up every argument on the command-line,
+ * dealing with quotes, but that is really a waste of time on Win32, at least.
+ * It turns out that all you need to do is get the raw path to the executable in
+ * the first argument to spawnvp(), and you can pass all the rest of the
+ * command-line arguments to spawnvp() in one, un-processed string.
+ *
+ * New strategy: break the string in at most one place.
+ */
+
+static char * * string_to_args( char const * string )
+{
+ int src_len;
+ int in_quote;
+ char * line;
+ char const * src;
+ char * dst;
+ char * * argv;
+
+ /* Drop leading and trailing whitespace if any. */
+ while ( isspace( *string ) )
+ ++string;
+
+ src_len = strlen( string );
+ while ( ( src_len > 0 ) && isspace( string[ src_len - 1 ] ) )
+ --src_len;
+
+ /* Copy the input string into a buffer we can modify. */
+ line = (char *)BJAM_MALLOC_ATOMIC( src_len + 1 );
+ if ( !line )
+ return 0;
+
+ /* Allocate the argv array.
+ * element 0: stores the path to the executable
+ * element 1: stores the command-line arguments to the executable
+ * element 2: NULL terminator
+ */
+ argv = (char * *)BJAM_MALLOC( 3 * sizeof( char * ) );
+ if ( !argv )
+ {
+ BJAM_FREE( line );
+ return 0;
+ }
+
+ /* Strip quotes from the first command-line argument and find where it ends.
+ * Quotes are illegal in Win32 pathnames, so we do not need to worry about
+ * preserving escaped quotes here. Spaces can not be escaped in Win32, only
+ * enclosed in quotes, so removing backslash escapes is also a non-issue.
+ */
+ in_quote = 0;
+ for ( src = string, dst = line ; *src; ++src )
+ {
+ if ( *src == '"' )
+ in_quote = !in_quote;
+ else if ( !in_quote && isspace( *src ) )
+ break;
+ else
+ *dst++ = *src;
+ }
+ *dst++ = 0;
+ argv[ 0 ] = line;
+
+ /* Skip whitespace in src. */
+ while ( isspace( *src ) )
+ ++src;
+
+ argv[ 1 ] = dst;
+
+ /* Copy the rest of the arguments verbatim. */
+ src_len -= src - string;
+
+ /* Use strncat() because it appends a trailing nul. */
+ *dst = 0;
+ strncat( dst, src, src_len );
+
+ argv[ 2 ] = 0;
+
+ return argv;
+}
+
+
+static void onintr( int disp )
+{
+ ++intr;
+ printf( "...interrupted\n" );
+}
+
+
+/*
+ * can_spawn() - If the command is suitable for execution via spawnvp(), return
+ * a number >= the number of characters it would occupy on the command-line.
+ * Otherwise, return zero.
+ */
+
+long can_spawn( char * command )
+{
+ char * p;
+ char inquote = 0;
+
+ /* Move to the first non-whitespace. */
+ command += strspn( command, " \t" );
+
+ p = command;
+
+ /* Look for newlines and unquoted i/o redirection. */
+ do
+ {
+ p += strcspn( p, "'\n\"<>|" );
+
+ switch ( *p )
+ {
+ case '\n':
+ /* Skip over any following spaces. */
+ while ( isspace( *p ) )
+ ++p;
+ /* Must use a .bat file if there is anything significant following
+ * the newline.
+ */
+ if ( *p )
+ return 0;
+ break;
+
+ case '"':
+ case '\'':
+ if ( ( p > command ) && ( p[ -1 ] != '\\' ) )
+ {
+ if ( inquote == *p )
+ inquote = 0;
+ else if ( inquote == 0 )
+ inquote = *p;
+ }
+ ++p;
+ break;
+
+ case '<':
+ case '>':
+ case '|':
+ if ( !inquote )
+ return 0;
+ ++p;
+ break;
+ }
+ }
+ while ( *p );
+
+ /* Return the number of characters the command will occupy. */
+ return p - command;
+}
+
+
+/* 64-bit arithmetic helpers. */
+
+/* Compute the carry bit from the addition of two 32-bit unsigned numbers. */
+#define add_carry_bit( a, b ) ( (((a) | (b)) >> 31) & (~((a) + (b)) >> 31) & 0x1 )
+
+/* Compute the high 32 bits of the addition of two 64-bit unsigned numbers, h1l1 and h2l2. */
+#define add_64_hi( h1, l1, h2, l2 ) ((h1) + (h2) + add_carry_bit(l1, l2))
+
+
+/*
+ * Add two 64-bit unsigned numbers, h1l1 and h2l2.
+ */
+
+static FILETIME add_64
+(
+ unsigned long h1, unsigned long l1,
+ unsigned long h2, unsigned long l2
+)
+{
+ FILETIME result;
+ result.dwLowDateTime = l1 + l2;
+ result.dwHighDateTime = add_64_hi( h1, l1, h2, l2 );
+ return result;
+}
+
+
+static FILETIME add_FILETIME( FILETIME t1, FILETIME t2 )
+{
+ return add_64( t1.dwHighDateTime, t1.dwLowDateTime, t2.dwHighDateTime,
+ t2.dwLowDateTime );
+}
+
+
+static FILETIME negate_FILETIME( FILETIME t )
+{
+ /* 2s complement negation */
+ return add_64( ~t.dwHighDateTime, ~t.dwLowDateTime, 0, 1 );
+}
+
+
+/*
+ * Convert a FILETIME to a number of seconds.
+ */
+
+static double filetime_seconds( FILETIME t )
+{
+ return t.dwHighDateTime * ( (double)( 1UL << 31 ) * 2.0 * 1.0e-7 ) + t.dwLowDateTime * 1.0e-7;
+}
+
+
+/*
+ * What should be a simple conversion, turns out to be horribly complicated by
+ * the defficiencies of MSVC and the Win32 API.
+ */
+
+static time_t filetime_dt( FILETIME t_utc )
+{
+ static int calc_time_diff = 1;
+ static double time_diff;
+ if ( calc_time_diff )
+ {
+ struct tm t0_;
+ FILETIME f0_local;
+ FILETIME f0_;
+ SYSTEMTIME s0_;
+ GetSystemTime( &s0_ );
+ t0_.tm_year = s0_.wYear-1900;
+ t0_.tm_mon = s0_.wMonth-1;
+ t0_.tm_wday = s0_.wDayOfWeek;
+ t0_.tm_mday = s0_.wDay;
+ t0_.tm_hour = s0_.wHour;
+ t0_.tm_min = s0_.wMinute;
+ t0_.tm_sec = s0_.wSecond;
+ t0_.tm_isdst = 0;
+ SystemTimeToFileTime( &s0_, &f0_local );
+ LocalFileTimeToFileTime( &f0_local, &f0_ );
+ time_diff = filetime_seconds( f0_ ) - (double)mktime( &t0_ );
+ calc_time_diff = 0;
+ }
+ return ceil( filetime_seconds( t_utc ) - time_diff );
+}
+
+
+static void record_times( HANDLE process, timing_info * time )
+{
+ FILETIME creation;
+ FILETIME exit;
+ FILETIME kernel;
+ FILETIME user;
+ if ( GetProcessTimes( process, &creation, &exit, &kernel, &user ) )
+ {
+ time->system = filetime_seconds( kernel );
+ time->user = filetime_seconds( user );
+ time->start = filetime_dt ( creation );
+ time->end = filetime_dt ( exit );
+ }
+}
+
+
+#define IO_BUFFER_SIZE ( 16 * 1024 )
+
+static char ioBuffer[ IO_BUFFER_SIZE + 1 ];
+
+
+static void read_pipe
+(
+ HANDLE in, /* the pipe to read from */
+ string * out
+)
+{
+ DWORD bytesInBuffer = 0;
+ DWORD bytesAvailable = 0;
+
+ do
+ {
+ /* check if we have any data to read */
+ if ( !PeekNamedPipe( in, ioBuffer, IO_BUFFER_SIZE, &bytesInBuffer, &bytesAvailable, NULL ) )
+ bytesAvailable = 0;
+
+ /* read in the available data */
+ if ( bytesAvailable > 0 )
+ {
+ /* we only read in the available bytes, to avoid blocking */
+ if ( ReadFile( in, ioBuffer,
+ bytesAvailable <= IO_BUFFER_SIZE ? bytesAvailable : IO_BUFFER_SIZE,
+ &bytesInBuffer, NULL ) )
+ {
+ if ( bytesInBuffer > 0 )
+ {
+ /* Clean up some illegal chars. */
+ int i;
+ for ( i = 0; i < bytesInBuffer; ++i )
+ {
+ if ( ( (unsigned char)ioBuffer[ i ] < 1 ) )
+ ioBuffer[ i ] = '?';
+ }
+ /* Null, terminate. */
+ ioBuffer[ bytesInBuffer ] = '\0';
+ /* Append to the output. */
+ string_append( out, ioBuffer );
+ /* Subtract what we read in. */
+ bytesAvailable -= bytesInBuffer;
+ }
+ else
+ {
+ /* Likely read a error, bail out. */
+ bytesAvailable = 0;
+ }
+ }
+ else
+ {
+ /* Definitely read a error, bail out. */
+ bytesAvailable = 0;
+ }
+ }
+ }
+ while ( bytesAvailable > 0 );
+}
+
+
+static void read_output()
+{
+ int i;
+ for ( i = 0; i < globs.jobs && i < MAXJOBS; ++i )
+ {
+ /* Read stdout data. */
+ if ( cmdtab[ i ].pipe_out[ 0 ] )
+ read_pipe( cmdtab[ i ].pipe_out[ 0 ], & cmdtab[ i ].buffer_out );
+ /* Read stderr data. */
+ if ( cmdtab[ i ].pipe_err[ 0 ] )
+ read_pipe( cmdtab[ i ].pipe_err[ 0 ], & cmdtab[ i ].buffer_err );
+ }
+}
+
+
+/*
+ * Waits for a single child process command to complete, or the timeout,
+ * whichever comes first. Returns the index of the completed command in the
+ * cmdtab array, or -1.
+ */
+
+static int try_wait( int timeoutMillis )
+{
+ int i;
+ int num_active;
+ int wait_api_result;
+ HANDLE active_handles[ MAXJOBS ];
+ int active_procs[ MAXJOBS ];
+
+ /* Prepare a list of all active processes to wait for. */
+ for ( num_active = 0, i = 0; i < globs.jobs; ++i )
+ {
+ if ( cmdtab[ i ].pi.hProcess )
+ {
+ active_handles[ num_active ] = cmdtab[ i ].pi.hProcess;
+ active_procs[ num_active ] = i;
+ ++num_active;
+ }
+ }
+
+ /* Wait for a child to complete, or for our timeout window to expire. */
+ wait_api_result = WaitForMultipleObjects( num_active, active_handles,
+ FALSE, timeoutMillis );
+ if ( ( WAIT_OBJECT_0 <= wait_api_result ) &&
+ ( wait_api_result < WAIT_OBJECT_0 + num_active ) )
+ {
+ /* Rerminated process detected - return its index. */
+ return active_procs[ wait_api_result - WAIT_OBJECT_0 ];
+ }
+
+ /* Timeout. */
+ return -1;
+}
+
+
+static int try_kill_one()
+{
+ /* Only need to check if a timeout was specified with the -l option. */
+ if ( globs.timeout > 0 )
+ {
+ int i;
+ for ( i = 0; i < globs.jobs; ++i )
+ {
+ double t = running_time( cmdtab[ i ].pi.hProcess );
+ if ( t > (double)globs.timeout )
+ {
+ /* The job may have left an alert dialog around, try and get rid
+ * of it before killing
+ */
+ close_alert( cmdtab[ i ].pi.hProcess );
+ /* We have a "runaway" job, kill it. */
+ kill_process_tree( 0, cmdtab[ i ].pi.hProcess );
+ /* And return it marked as a timeout. */
+ cmdtab[ i ].exit_reason = EXIT_TIMEOUT;
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+
+static void close_alerts()
+{
+ /* We only attempt this every 5 seconds, or so, because it is not a cheap
+ * operation, and we will catch the alerts eventually. This check uses
+ * floats as some compilers define CLOCKS_PER_SEC as a float or double.
+ */
+ if ( ( (float)clock() / (float)( CLOCKS_PER_SEC * 5 ) ) < ( 1.0 / 5.0 ) )
+ {
+ int i;
+ for ( i = 0; i < globs.jobs; ++i )
+ close_alert( cmdtab[ i ].pi.hProcess );
+ }
+}
+
+
+/*
+ * Calc the current running time of an *active* process.
+ */
+
+static double running_time( HANDLE process )
+{
+ FILETIME creation;
+ FILETIME exit;
+ FILETIME kernel;
+ FILETIME user;
+ FILETIME current;
+ if ( GetProcessTimes( process, &creation, &exit, &kernel, &user ) )
+ {
+ /* Compute the elapsed time. */
+ GetSystemTimeAsFileTime( &current );
+ return filetime_seconds( add_FILETIME( current,
+ negate_FILETIME( creation ) ) );
+ }
+ return 0.0;
+}
+
+
+/* It is just stupidly silly that one has to do this. */
+typedef struct PROCESS_BASIC_INFORMATION__
+{
+ LONG ExitStatus;
+ PVOID PebBaseAddress;
+ ULONG AffinityMask;
+ LONG BasePriority;
+ ULONG UniqueProcessId;
+ ULONG InheritedFromUniqueProcessId;
+} PROCESS_BASIC_INFORMATION_;
+typedef LONG (__stdcall * NtQueryInformationProcess__)(
+ HANDLE ProcessHandle,
+ LONG ProcessInformationClass,
+ PVOID ProcessInformation,
+ ULONG ProcessInformationLength,
+ PULONG ReturnLength);
+static NtQueryInformationProcess__ NtQueryInformationProcess_ = NULL;
+static HMODULE NTDLL_ = NULL;
+DWORD get_process_id( HANDLE process )
+{
+ PROCESS_BASIC_INFORMATION_ pinfo;
+ if ( !NtQueryInformationProcess_ )
+ {
+ if ( ! NTDLL_ )
+ NTDLL_ = GetModuleHandleA( "ntdll" );
+ if ( NTDLL_ )
+ NtQueryInformationProcess_
+ = (NtQueryInformationProcess__)GetProcAddress( NTDLL_, "NtQueryInformationProcess" );
+ }
+ if ( NtQueryInformationProcess_ )
+ {
+ LONG r = (*NtQueryInformationProcess_)( process,
+ /* ProcessBasicInformation == */ 0, &pinfo,
+ sizeof( PROCESS_BASIC_INFORMATION_ ), NULL );
+ return pinfo.UniqueProcessId;
+ }
+ return 0;
+}
+
+
+/*
+ * Not really optimal, or efficient, but it is easier this way, and it is not
+ * like we are going to be killing thousands, or even tens of processes.
+ */
+
+static void kill_process_tree( DWORD pid, HANDLE process )
+{
+ HANDLE process_snapshot_h = INVALID_HANDLE_VALUE;
+ if ( !pid )
+ pid = get_process_id( process );
+ process_snapshot_h = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
+
+ if ( INVALID_HANDLE_VALUE != process_snapshot_h )
+ {
+ BOOL ok = TRUE;
+ PROCESSENTRY32 pinfo;
+ pinfo.dwSize = sizeof( PROCESSENTRY32 );
+ for (
+ ok = Process32First( process_snapshot_h, &pinfo );
+ ok == TRUE;
+ ok = Process32Next( process_snapshot_h, &pinfo ) )
+ {
+ if ( pinfo.th32ParentProcessID == pid )
+ {
+ /* Found a child, recurse to kill it and anything else below it.
+ */
+ HANDLE ph = OpenProcess( PROCESS_ALL_ACCESS, FALSE,
+ pinfo.th32ProcessID );
+ if ( NULL != ph )
+ {
+ kill_process_tree( pinfo.th32ProcessID, ph );
+ CloseHandle( ph );
+ }
+ }
+ }
+ CloseHandle( process_snapshot_h );
+ }
+ /* Now that the children are all dead, kill the root. */
+ TerminateProcess( process, -2 );
+}
+
+
+static double creation_time( HANDLE process )
+{
+ FILETIME creation;
+ FILETIME exit;
+ FILETIME kernel;
+ FILETIME user;
+ FILETIME current;
+ return GetProcessTimes( process, &creation, &exit, &kernel, &user )
+ ? filetime_seconds( creation )
+ : 0.0;
+}
+
+
+/*
+ * Recursive check if first process is parent (directly or indirectly) of the
+ * second one. Both processes are passed as process ids, not handles. Special
+ * return value 2 means that the second process is smss.exe and its parent
+ * process is System (first argument is ignored).
+ */
+
+static int is_parent_child( DWORD parent, DWORD child )
+{
+ HANDLE process_snapshot_h = INVALID_HANDLE_VALUE;
+
+ if ( !child )
+ return 0;
+ if ( parent == child )
+ return 1;
+
+ process_snapshot_h = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
+ if ( INVALID_HANDLE_VALUE != process_snapshot_h )
+ {
+ BOOL ok = TRUE;
+ PROCESSENTRY32 pinfo;
+ pinfo.dwSize = sizeof( PROCESSENTRY32 );
+ for (
+ ok = Process32First( process_snapshot_h, &pinfo );
+ ok == TRUE;
+ ok = Process32Next( process_snapshot_h, &pinfo ) )
+ {
+ if ( pinfo.th32ProcessID == child )
+ {
+ /* Unfortunately, process ids are not really unique. There might
+ * be spurious "parent and child" relationship match between two
+ * non-related processes if real parent process of a given
+ * process has exited (while child process kept running as an
+ * "orphan") and the process id of such parent process has been
+ * reused by internals of the operating system when creating
+ * another process.
+ *
+ * Thus additional check is needed - process creation time. This
+ * check may fail (i.e. return 0) for system processes due to
+ * insufficient privileges, and that is OK.
+ */
+ double tchild = 0.0;
+ double tparent = 0.0;
+ HANDLE hchild = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pinfo.th32ProcessID );
+ CloseHandle( process_snapshot_h );
+
+ /* csrss.exe may display message box like following:
+ * xyz.exe - Unable To Locate Component
+ * This application has failed to start because
+ * boost_foo-bar.dll was not found. Re-installing the
+ * application may fix the problem
+ * This actually happens when starting test process that depends
+ * on a dynamic library which failed to build. We want to
+ * automatically close these message boxes even though csrss.exe
+ * is not our child process. We may depend on the fact that (in
+ * all current versions of Windows) csrss.exe is directly child
+ * of the smss.exe process, which in turn is directly child of
+ * the System process, which always has process id == 4. This
+ * check must be performed before comparison of process creation
+ * times.
+ */
+ if ( !stricmp( pinfo.szExeFile, "csrss.exe" ) &&
+ ( is_parent_child( parent, pinfo.th32ParentProcessID ) == 2 ) )
+ return 1;
+ if ( !stricmp( pinfo.szExeFile, "smss.exe" ) &&
+ ( pinfo.th32ParentProcessID == 4 ) )
+ return 2;
+
+ if ( hchild )
+ {
+ HANDLE hparent = OpenProcess( PROCESS_QUERY_INFORMATION,
+ FALSE, pinfo.th32ParentProcessID );
+ if ( hparent )
+ {
+ tchild = creation_time( hchild );
+ tparent = creation_time( hparent );
+ CloseHandle( hparent );
+ }
+ CloseHandle( hchild );
+ }
+
+ /* Return 0 if one of the following is true:
+ * 1. we failed to read process creation time
+ * 2. child was created before alleged parent
+ */
+ if ( ( tchild == 0.0 ) || ( tparent == 0.0 ) ||
+ ( tchild < tparent ) )
+ return 0;
+
+ return is_parent_child( parent, pinfo.th32ParentProcessID ) & 1;
+ }
+ }
+
+ CloseHandle( process_snapshot_h );
+ }
+
+ return 0;
+}
+
+typedef struct PROCESS_HANDLE_ID { HANDLE h; DWORD pid; } PROCESS_HANDLE_ID;
+
+
+/*
+ * This function is called by the operating system for each topmost window.
+ */
+
+BOOL CALLBACK close_alert_window_enum( HWND hwnd, LPARAM lParam )
+{
+ char buf[ 7 ] = { 0 };
+ PROCESS_HANDLE_ID p = *( (PROCESS_HANDLE_ID *)lParam );
+ DWORD pid = 0;
+ DWORD tid = 0;
+
+ /* We want to find and close any window that:
+ * 1. is visible and
+ * 2. is a dialog and
+ * 3. is displayed by any of our child processes
+ */
+ if ( !IsWindowVisible( hwnd ) )
+ return TRUE;
+
+ if ( !GetClassNameA( hwnd, buf, sizeof( buf ) ) )
+ return TRUE; /* Failed to read class name; presume it is not a dialog. */
+
+ if ( strcmp( buf, "#32770" ) )
+ return TRUE; /* Not a dialog */
+
+ /* GetWindowThreadProcessId() returns 0 on error, otherwise thread id of
+ * window message pump thread.
+ */
+ tid = GetWindowThreadProcessId( hwnd, &pid );
+
+ if ( tid && is_parent_child( p.pid, pid ) )
+ {
+ /* Ask really nice. */
+ PostMessageA( hwnd, WM_CLOSE, 0, 0 );
+ /* Now wait and see if it worked. If not, insist. */
+ if ( WaitForSingleObject( p.h, 200 ) == WAIT_TIMEOUT )
+ {
+ PostThreadMessageA( tid, WM_QUIT, 0, 0 );
+ WaitForSingleObject( p.h, 300 );
+ }
+
+ /* Done, we do not want to check any other window now. */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static void close_alert( HANDLE process )
+{
+ DWORD pid = get_process_id( process );
+ /* If process already exited or we just can not get its process id, do not
+ * go any further.
+ */
+ if ( pid )
+ {
+ PROCESS_HANDLE_ID p;
+ p.h = process;
+ p.pid = pid;
+ EnumWindows( &close_alert_window_enum, (LPARAM)&p );
+ }
+}
+
+#endif /* USE_EXECNT */
diff --git a/tools/build/v2/engine/execunix.c b/tools/build/v2/engine/execunix.c
new file mode 100644
index 0000000000..ef9dba0037
--- /dev/null
+++ b/tools/build/v2/engine/execunix.c
@@ -0,0 +1,569 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ * Copyright 2007 Noel Belcourt.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+#include "jam.h"
+#include "lists.h"
+#include "execcmd.h"
+#include "output.h"
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h> /* needed for vfork(), _exit() prototypes */
+#include <sys/resource.h>
+#include <sys/times.h>
+#include <sys/wait.h>
+
+#if defined(sun) || defined(__sun) || defined(linux)
+ #include <wait.h>
+#endif
+
+#ifdef USE_EXECUNIX
+
+#include <sys/times.h>
+
+#if defined(__APPLE__)
+ #define NO_VFORK
+#endif
+
+#ifdef NO_VFORK
+ #define vfork() fork()
+#endif
+
+
+/*
+ * execunix.c - execute a shell script on UNIX/WinNT/OS2/AmigaOS
+ *
+ * If $(JAMSHELL) is defined, uses that to formulate execvp()/spawnvp().
+ * The default is:
+ *
+ * /bin/sh -c % [ on UNIX/AmigaOS ]
+ * cmd.exe /c % [ on OS2/WinNT ]
+ *
+ * Each word must be an individual element in a jam variable value.
+ *
+ * In $(JAMSHELL), % expands to the command string and ! expands to the slot
+ * number (starting at 1) for multiprocess (-j) invocations. If $(JAMSHELL) does
+ * not include a %, it is tacked on as the last argument.
+ *
+ * Do not just set JAMSHELL to /bin/sh or cmd.exe - it will not work!
+ *
+ * External routines:
+ * exec_cmd() - launch an async command execution.
+ * exec_wait() - wait and drive at most one execution completion.
+ *
+ * Internal routines:
+ * onintr() - bump intr to note command interruption.
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 05/04/94 (seiwald) - async multiprocess interface
+ * 01/22/95 (seiwald) - $(JAMSHELL) support
+ * 06/02/97 (gsar) - full async multiprocess support for Win32
+ */
+
+static clock_t tps = 0;
+static struct timeval tv;
+static int select_timeout = 0;
+static int intr = 0;
+static int cmdsrunning = 0;
+static struct tms old_time;
+
+#define OUT 0
+#define ERR 1
+
+static struct
+{
+ int pid; /* on win32, a real process handle */
+ int fd[2]; /* file descriptors for stdout and stderr */
+ FILE *stream[2]; /* child's stdout (0) and stderr (1) file stream */
+ clock_t start_time; /* start time of child process */
+ int exit_reason; /* termination status */
+ int action_length; /* length of action string */
+ int target_length; /* length of target string */
+ char *action; /* buffer to hold action and target invoked */
+ char *target; /* buffer to hold action and target invoked */
+ char *command; /* buffer to hold command being invoked */
+ char *buffer[2]; /* buffer to hold stdout and stderr, if any */
+ void (*func)( void *closure, int status, timing_info*, char *, char * );
+ void *closure;
+ time_t start_dt; /* start of command timestamp */
+} cmdtab[ MAXJOBS ] = {{0}};
+
+/*
+ * onintr() - bump intr to note command interruption
+ */
+
+void onintr( int disp )
+{
+ ++intr;
+ printf( "...interrupted\n" );
+}
+
+
+/*
+ * exec_cmd() - launch an async command execution.
+ */
+
+void exec_cmd
+(
+ char * string,
+ void (*func)( void *closure, int status, timing_info*, char *, char * ),
+ void * closure,
+ LIST * shell,
+ char * action,
+ char * target
+)
+{
+ static int initialized = 0;
+ int out[2];
+ int err[2];
+ int slot;
+ int len;
+ char * argv[ MAXARGC + 1 ]; /* +1 for NULL */
+
+ /* Find a slot in the running commands table for this one. */
+ for ( slot = 0; slot < MAXJOBS; ++slot )
+ if ( !cmdtab[ slot ].pid )
+ break;
+
+ if ( slot == MAXJOBS )
+ {
+ printf( "no slots for child!\n" );
+ exit( EXITBAD );
+ }
+
+ /* Forumulate argv. If shell was defined, be prepared for % and ! subs.
+ * Otherwise, use stock /bin/sh on unix or cmd.exe on NT.
+ */
+ if ( shell )
+ {
+ int i;
+ char jobno[4];
+ int gotpercent = 0;
+
+ sprintf( jobno, "%d", slot + 1 );
+
+ for ( i = 0; shell && i < MAXARGC; ++i, shell = list_next( shell ) )
+ {
+ switch ( shell->string[0] )
+ {
+ case '%': argv[ i ] = string; ++gotpercent; break;
+ case '!': argv[ i ] = jobno; break;
+ default : argv[ i ] = shell->string;
+ }
+ if ( DEBUG_EXECCMD )
+ printf( "argv[%d] = '%s'\n", i, argv[ i ] );
+ }
+
+ if ( !gotpercent )
+ argv[ i++ ] = string;
+
+ argv[ i ] = 0;
+ }
+ else
+ {
+ argv[ 0 ] = "/bin/sh";
+ argv[ 1 ] = "-c";
+ argv[ 2 ] = string;
+ argv[ 3 ] = 0;
+ }
+
+ /* Increment jobs running. */
+ ++cmdsrunning;
+
+ /* Save off actual command string. */
+ cmdtab[ slot ].command = BJAM_MALLOC_ATOMIC( strlen( string ) + 1 );
+ strcpy( cmdtab[ slot ].command, string );
+
+ /* Initialize only once. */
+ if ( !initialized )
+ {
+ times( &old_time );
+ initialized = 1;
+ }
+
+ /* Create pipes from child to parent. */
+ {
+ if ( pipe( out ) < 0 )
+ exit( EXITBAD );
+
+ if ( pipe( err ) < 0 )
+ exit( EXITBAD );
+ }
+
+ /* Start the command */
+
+ cmdtab[ slot ].start_dt = time(0);
+
+ if ( 0 < globs.timeout )
+ {
+ /*
+ * Handle hung processes by manually tracking elapsed time and signal
+ * process when time limit expires.
+ */
+ struct tms buf;
+ cmdtab[ slot ].start_time = times( &buf );
+
+ /* Make a global, only do this once. */
+ if ( tps == 0 ) tps = sysconf( _SC_CLK_TCK );
+ }
+
+ if ( ( cmdtab[ slot ].pid = vfork() ) == 0 )
+ {
+ int pid = getpid();
+
+ close( out[0] );
+ close( err[0] );
+
+ dup2( out[1], STDOUT_FILENO );
+
+ if ( globs.pipe_action == 0 )
+ dup2( out[1], STDERR_FILENO );
+ else
+ dup2( err[1], STDERR_FILENO );
+
+ close( out[1] );
+ close( err[1] );
+
+ /* Make this process a process group leader so that when we kill it, all
+ * child processes of this process are terminated as well. We use
+ * killpg(pid, SIGKILL) to kill the process group leader and all its
+ * children.
+ */
+ if ( 0 < globs.timeout )
+ {
+ struct rlimit r_limit;
+ r_limit.rlim_cur = globs.timeout;
+ r_limit.rlim_max = globs.timeout;
+ setrlimit( RLIMIT_CPU, &r_limit );
+ }
+ setpgid( pid,pid );
+ execvp( argv[0], argv );
+ perror( "execvp" );
+ _exit( 127 );
+ }
+ else if ( cmdtab[ slot ].pid == -1 )
+ {
+ perror( "vfork" );
+ exit( EXITBAD );
+ }
+
+ setpgid( cmdtab[ slot ].pid, cmdtab[ slot ].pid );
+
+ /* close write end of pipes */
+ close( out[1] );
+ close( err[1] );
+
+ /* set both file descriptors to non-blocking */
+ fcntl(out[0], F_SETFL, O_NONBLOCK);
+ fcntl(err[0], F_SETFL, O_NONBLOCK);
+
+ /* child writes stdout to out[1], parent reads from out[0] */
+ cmdtab[ slot ].fd[ OUT ] = out[0];
+ cmdtab[ slot ].stream[ OUT ] = fdopen( cmdtab[ slot ].fd[ OUT ], "rb" );
+ if ( cmdtab[ slot ].stream[ OUT ] == NULL )
+ {
+ perror( "fdopen" );
+ exit( EXITBAD );
+ }
+
+ /* child writes stderr to err[1], parent reads from err[0] */
+ if (globs.pipe_action == 0)
+ {
+ close(err[0]);
+ }
+ else
+ {
+ cmdtab[ slot ].fd[ ERR ] = err[0];
+ cmdtab[ slot ].stream[ ERR ] = fdopen( cmdtab[ slot ].fd[ ERR ], "rb" );
+ if ( cmdtab[ slot ].stream[ ERR ] == NULL )
+ {
+ perror( "fdopen" );
+ exit( EXITBAD );
+ }
+ }
+
+ /* Ensure enough room for rule and target name. */
+ if ( action && target )
+ {
+ len = strlen( action ) + 1;
+ if ( cmdtab[ slot ].action_length < len )
+ {
+ BJAM_FREE( cmdtab[ slot ].action );
+ cmdtab[ slot ].action = BJAM_MALLOC_ATOMIC( len );
+ cmdtab[ slot ].action_length = len;
+ }
+ strcpy( cmdtab[ slot ].action, action );
+ len = strlen( target ) + 1;
+ if ( cmdtab[ slot ].target_length < len )
+ {
+ BJAM_FREE( cmdtab[ slot ].target );
+ cmdtab[ slot ].target = BJAM_MALLOC_ATOMIC( len );
+ cmdtab[ slot ].target_length = len;
+ }
+ strcpy( cmdtab[ slot ].target, target );
+ }
+ else
+ {
+ BJAM_FREE( cmdtab[ slot ].action );
+ BJAM_FREE( cmdtab[ slot ].target );
+ cmdtab[ slot ].action = 0;
+ cmdtab[ slot ].target = 0;
+ cmdtab[ slot ].action_length = 0;
+ cmdtab[ slot ].target_length = 0;
+ }
+
+ /* Save the operation for exec_wait() to find. */
+ cmdtab[ slot ].func = func;
+ cmdtab[ slot ].closure = closure;
+
+ /* Wait until we are under the limit of concurrent commands. Do not trust
+ * globs.jobs alone.
+ */
+ while ( ( cmdsrunning >= MAXJOBS ) || ( cmdsrunning >= globs.jobs ) )
+ if ( !exec_wait() )
+ break;
+}
+
+
+/* Returns 1 if file is closed, 0 if descriptor is still live.
+ *
+ * i is index into cmdtab
+ *
+ * s (stream) indexes:
+ * - cmdtab[ i ].stream[ s ]
+ * - cmdtab[ i ].buffer[ s ]
+ * - cmdtab[ i ].fd [ s ]
+ */
+
+int read_descriptor( int i, int s )
+{
+ int ret;
+ int len;
+ char buffer[BUFSIZ];
+
+ while ( 0 < ( ret = fread( buffer, sizeof(char), BUFSIZ-1, cmdtab[ i ].stream[ s ] ) ) )
+ {
+ buffer[ret] = 0;
+ if ( !cmdtab[ i ].buffer[ s ] )
+ {
+ /* Never been allocated. */
+ cmdtab[ i ].buffer[ s ] = (char*)BJAM_MALLOC_ATOMIC( ret + 1 );
+ memcpy( cmdtab[ i ].buffer[ s ], buffer, ret + 1 );
+ }
+ else
+ {
+ /* Previously allocated. */
+ char * tmp = cmdtab[ i ].buffer[ s ];
+ len = strlen( tmp );
+ cmdtab[ i ].buffer[ s ] = (char*)BJAM_MALLOC_ATOMIC( len + ret + 1 );
+ memcpy( cmdtab[ i ].buffer[ s ], tmp, len );
+ memcpy( cmdtab[ i ].buffer[ s ] + len, buffer, ret + 1 );
+ BJAM_FREE( tmp );
+ }
+ }
+
+ return feof(cmdtab[ i ].stream[ s ]);
+}
+
+
+void close_streams( int i, int s )
+{
+ /* Close the stream and pipe descriptor. */
+ fclose(cmdtab[ i ].stream[ s ]);
+ cmdtab[ i ].stream[ s ] = 0;
+
+ close(cmdtab[ i ].fd[ s ]);
+ cmdtab[ i ].fd[ s ] = 0;
+}
+
+
+void populate_file_descriptors( int * fmax, fd_set * fds)
+{
+ int i, fd_max = 0;
+ struct tms buf;
+ clock_t current = times( &buf );
+ select_timeout = globs.timeout;
+
+ /* Compute max read file descriptor for use in select. */
+ FD_ZERO(fds);
+ for ( i = 0; i < globs.jobs; ++i )
+ {
+ if ( 0 < cmdtab[ i ].fd[ OUT ] )
+ {
+ fd_max = fd_max < cmdtab[ i ].fd[ OUT ] ? cmdtab[ i ].fd[ OUT ] : fd_max;
+ FD_SET(cmdtab[ i ].fd[ OUT ], fds);
+ }
+ if ( globs.pipe_action != 0 )
+ {
+ if (0 < cmdtab[ i ].fd[ ERR ])
+ {
+ fd_max = fd_max < cmdtab[ i ].fd[ ERR ] ? cmdtab[ i ].fd[ ERR ] : fd_max;
+ FD_SET(cmdtab[ i ].fd[ ERR ], fds);
+ }
+ }
+
+ if (globs.timeout && cmdtab[ i ].pid) {
+ clock_t consumed = (current - cmdtab[ i ].start_time) / tps;
+ clock_t process_timesout = globs.timeout - consumed;
+ if (0 < process_timesout && process_timesout < select_timeout) {
+ select_timeout = process_timesout;
+ }
+ if ( globs.timeout <= consumed )
+ {
+ killpg( cmdtab[ i ].pid, SIGKILL );
+ cmdtab[ i ].exit_reason = EXIT_TIMEOUT;
+ }
+ }
+ }
+ *fmax = fd_max;
+}
+
+
+/*
+ * exec_wait() - wait and drive at most one execution completion.
+ */
+
+int exec_wait()
+{
+ int i;
+ int ret;
+ int fd_max;
+ int pid;
+ int status;
+ int finished;
+ int rstat;
+ timing_info time_info;
+ fd_set fds;
+ struct tms new_time;
+
+ /* Handle naive make1() which does not know if commands are running. */
+ if ( !cmdsrunning )
+ return 0;
+
+ /* Process children that signaled. */
+ finished = 0;
+ while ( !finished && cmdsrunning )
+ {
+ /* Compute max read file descriptor for use in select(). */
+ populate_file_descriptors( &fd_max, &fds );
+
+ if ( 0 < globs.timeout )
+ {
+ /* Force select() to timeout so we can terminate expired processes.
+ */
+ tv.tv_sec = select_timeout;
+ tv.tv_usec = 0;
+
+ /* select() will wait until: i/o on a descriptor, a signal, or we
+ * time out.
+ */
+ ret = select( fd_max + 1, &fds, 0, 0, &tv );
+ }
+ else
+ {
+ /* select() will wait until i/o on a descriptor or a signal. */
+ ret = select( fd_max + 1, &fds, 0, 0, 0 );
+ }
+
+ if ( 0 < ret )
+ {
+ for ( i = 0; i < globs.jobs; ++i )
+ {
+ int out = 0;
+ int err = 0;
+ if ( FD_ISSET( cmdtab[ i ].fd[ OUT ], &fds ) )
+ out = read_descriptor( i, OUT );
+
+ if ( ( globs.pipe_action != 0 ) &&
+ ( FD_ISSET( cmdtab[ i ].fd[ ERR ], &fds ) ) )
+ err = read_descriptor( i, ERR );
+
+ /* If feof on either descriptor, then we are done. */
+ if ( out || err )
+ {
+ /* Close the stream and pipe descriptors. */
+ close_streams( i, OUT );
+ if ( globs.pipe_action != 0 )
+ close_streams( i, ERR );
+
+ /* Reap the child and release resources. */
+ pid = waitpid( cmdtab[ i ].pid, &status, 0 );
+
+ if ( pid == cmdtab[ i ].pid )
+ {
+ finished = 1;
+ pid = 0;
+ cmdtab[ i ].pid = 0;
+
+ /* Set reason for exit if not timed out. */
+ if ( WIFEXITED( status ) )
+ {
+ cmdtab[ i ].exit_reason = 0 == WEXITSTATUS( status )
+ ? EXIT_OK
+ : EXIT_FAIL;
+ }
+
+ /* Print out the rule and target name. */
+ out_action( cmdtab[ i ].action, cmdtab[ i ].target,
+ cmdtab[ i ].command, cmdtab[ i ].buffer[ OUT ],
+ cmdtab[ i ].buffer[ ERR ], cmdtab[ i ].exit_reason
+ );
+
+ times( &new_time );
+
+ time_info.system = (double)( new_time.tms_cstime - old_time.tms_cstime ) / CLOCKS_PER_SEC;
+ time_info.user = (double)( new_time.tms_cutime - old_time.tms_cutime ) / CLOCKS_PER_SEC;
+ time_info.start = cmdtab[ i ].start_dt;
+ time_info.end = time( 0 );
+
+ old_time = new_time;
+
+ /* Drive the completion. */
+ --cmdsrunning;
+
+ if ( intr )
+ rstat = EXEC_CMD_INTR;
+ else if ( status != 0 )
+ rstat = EXEC_CMD_FAIL;
+ else
+ rstat = EXEC_CMD_OK;
+
+ /* Assume -p0 in effect so only pass buffer[ 0 ]
+ * containing merged output.
+ */
+ (*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat,
+ &time_info, cmdtab[ i ].command,
+ cmdtab[ i ].buffer[ 0 ] );
+
+ BJAM_FREE( cmdtab[ i ].buffer[ OUT ] );
+ cmdtab[ i ].buffer[ OUT ] = 0;
+
+ BJAM_FREE( cmdtab[ i ].buffer[ ERR ] );
+ cmdtab[ i ].buffer[ ERR ] = 0;
+
+ BJAM_FREE( cmdtab[ i ].command );
+ cmdtab[ i ].command = 0;
+
+ cmdtab[ i ].func = 0;
+ cmdtab[ i ].closure = 0;
+ cmdtab[ i ].start_time = 0;
+ }
+ else
+ {
+ printf( "unknown pid %d with errno = %d\n", pid, errno );
+ exit( EXITBAD );
+ }
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+# endif /* USE_EXECUNIX */
diff --git a/tools/build/v2/engine/execvms.c b/tools/build/v2/engine/execvms.c
new file mode 100644
index 0000000000..729917d356
--- /dev/null
+++ b/tools/build/v2/engine/execvms.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+#include "jam.h"
+#include "lists.h"
+#include "execcmd.h"
+
+#ifdef OS_VMS
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <iodef.h>
+#include <ssdef.h>
+#include <descrip.h>
+#include <dvidef.h>
+#include <clidef.h>
+
+/*
+ * execvms.c - execute a shell script, ala VMS.
+ *
+ * The approach is this:
+ *
+ * If the command is a single line, and shorter than WRTLEN (what we believe to
+ * be the maximum line length), we just system() it.
+ *
+ * If the command is multi-line, or longer than WRTLEN, we write the command
+ * block to a temp file, splitting long lines (using "-" at the end of the line
+ * to indicate contiuation), and then source that temp file. We use special
+ * logic to make sure we do not continue in the middle of a quoted string.
+ *
+ * 05/04/94 (seiwald) - async multiprocess interface; noop on VMS
+ * 12/20/96 (seiwald) - rewritten to handle multi-line commands well
+ * 01/14/96 (seiwald) - do not put -'s between "'s
+ */
+
+#define WRTLEN 240
+
+#define MIN( a, b ) ((a) < (b) ? (a) : (b))
+
+/* 1 for the @ and 4 for the .com */
+
+char tempnambuf[ L_tmpnam + 1 + 4 ] = { 0 };
+
+
+void exec_cmd
+(
+ char * string,
+ void (* func)( void * closure, int status, timing_info *, char *, char * ),
+ void * closure,
+ LIST * shell,
+ char * rule_name,
+ char * target
+)
+{
+ char * s;
+ char * e;
+ cahr * p;
+ int rstat = EXEC_CMD_OK;
+ int status;
+
+ /* See if string is more than one line discounting leading/trailing white
+ * space.
+ */
+ for ( s = string; *s && isspace( *s ); ++s );
+
+ e = p = strchr( s, '\n' );
+
+ while ( p && isspace( *p ) )
+ ++p;
+
+ /* If multi line or long, write to com file. Otherwise, exec directly. */
+ if ( ( p && *p ) || ( e - s > WRTLEN ) )
+ {
+ FILE * f;
+
+ /* Create temp file invocation "@sys$scratch:tempfile.com". */
+ if ( !*tempnambuf )
+ {
+ tempnambuf[0] = '@';
+ (void)tmpnam( tempnambuf + 1 );
+ strcat( tempnambuf, ".com" );
+ }
+
+ /* Open tempfile. */
+ if ( !( f = fopen( tempnambuf + 1, "w" ) ) )
+ {
+ printf( "can't open command file\n" );
+ (*func)( closure, EXEC_CMD_FAIL );
+ return;
+ }
+
+ /* For each line of the string. */
+ while ( *string )
+ {
+ char * s = strchr( string, '\n' );
+ int len = s ? s + 1 - string : strlen( string );
+
+ fputc( '$', f );
+
+ /* For each chunk of a line that needs to be split. */
+ while ( len > 0 )
+ {
+ char * q = string;
+ char * qe = string + MIN( len, WRTLEN );
+ char * qq = q;
+ int quote = 0;
+
+ /* Look for matching "s. */
+ for ( ; q < qe; ++q )
+ if ( ( *q == '"' ) && ( quote = !quote ) )
+ qq = q;
+
+ /* Back up to opening quote, if in one. */
+ if ( quote )
+ q = qq;
+
+ fwrite( string, ( q - string ), 1, f );
+
+ len -= ( q - string );
+ string = q;
+
+ if ( len )
+ {
+ fputc( '-', f );
+ fputc( '\n', f );
+ }
+ }
+ }
+
+ fclose( f );
+
+ status = system( tempnambuf ) & 0x07;
+
+ unlink( tempnambuf + 1 );
+ }
+ else
+ {
+ /* Execute single line command. Strip trailing newline before execing.
+ */
+ if ( e ) *e = 0;
+ status = system( s ) & 0x07;
+ }
+
+ /* Fail for error or fatal error. OK on OK, warning or info exit. */
+ if ( ( status == 2 ) || ( status == 4 ) )
+ rstat = EXEC_CMD_FAIL;
+
+ (*func)( closure, rstat );
+}
+
+
+int exec_wait()
+{
+ return 0;
+}
+
+# endif /* VMS */
diff --git a/tools/build/v2/engine/expand.c b/tools/build/v2/engine/expand.c
new file mode 100644
index 0000000000..d8e58827c6
--- /dev/null
+++ b/tools/build/v2/engine/expand.c
@@ -0,0 +1,733 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "variable.h"
+# include "expand.h"
+# include "pathsys.h"
+# include "newstr.h"
+# include <assert.h>
+# include <stdlib.h>
+# include <limits.h>
+
+# ifdef OS_CYGWIN
+# include <sys/cygwin.h>
+# include <windows.h>
+# endif
+
+/*
+ * expand.c - expand a buffer, given variable values
+ *
+ * External routines:
+ *
+ * var_expand() - variable-expand input string into list of strings
+ *
+ * Internal routines:
+ *
+ * var_edit_parse() - parse : modifiers into PATHNAME structure.
+ * var_edit_file() - copy input target name to output, modifying filename.
+ * var_edit_shift() - do upshift/downshift mods.
+ *
+ * 01/25/94 (seiwald) - $(X)$(UNDEF) was expanding like plain $(X)
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 01/11/01 (seiwald) - added support for :E=emptyvalue, :J=joinval
+ */
+
+typedef struct
+{
+ PATHNAME f; /* :GDBSMR -- pieces */
+ char parent; /* :P -- go to parent directory */
+ char filemods; /* one of the above applied */
+ char downshift; /* :L -- downshift result */
+ char upshift; /* :U -- upshift result */
+ char to_slashes; /* :T -- convert "\" to "/" */
+ char to_windows; /* :W -- convert cygwin to native paths */
+ PATHPART empty; /* :E -- default for empties */
+ PATHPART join; /* :J -- join list with char */
+} VAR_EDITS ;
+
+static void var_edit_parse( char * mods, VAR_EDITS * edits );
+static void var_edit_file ( char * in, string * out, VAR_EDITS * edits );
+static void var_edit_shift( string * out, VAR_EDITS * edits );
+
+#define MAGIC_COLON '\001'
+#define MAGIC_LEFT '\002'
+#define MAGIC_RIGHT '\003'
+
+
+/*
+ * var_expand() - variable-expand input string into list of strings.
+ *
+ * Would just copy input to output, performing variable expansion, except that
+ * since variables can contain multiple values the result of variable expansion
+ * may contain multiple values (a list). Properly performs "product" operations
+ * that occur in "$(var1)xxx$(var2)" or even "$($(var2))".
+ *
+ * Returns a newly created list.
+ */
+
+LIST * var_expand( LIST * l, char * in, char * end, LOL * lol, int cancopyin )
+{
+ char out_buf[ MAXSYM ];
+ string buf[ 1 ];
+ string out1[ 1 ]; /* temporary buffer */
+ size_t prefix_length;
+ char * out;
+ char * inp = in;
+ char * ov; /* for temp copy of variable in outbuf */
+ int depth;
+
+ if ( DEBUG_VAREXP )
+ printf( "expand '%.*s'\n", end - in, in );
+
+ /* This gets a lot of cases: $(<) and $(>). */
+ if
+ (
+ ( in[ 0 ] == '$' ) &&
+ ( in[ 1 ] == '(' ) &&
+ ( in[ 3 ] == ')' ) &&
+ ( in[ 4 ] == '\0' )
+ )
+ {
+ switch ( in[ 2 ] )
+ {
+ case '<': return list_copy( l, lol_get( lol, 0 ) );
+ case '>': return list_copy( l, lol_get( lol, 1 ) );
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return list_copy( l, lol_get( lol, in[ 2 ] - '1' ) );
+ }
+ }
+ else if ( in[0] == '$' && in[1] == '(' && in[2] == '1' && in[4] == ')' &&
+ in[5] == '\0') {
+
+ switch( in[3] )
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return list_copy( l, lol_get( lol, in[3]-'0'+10-1 ) );
+ }
+ }
+
+ /* Expand @() files, to single item plus accompanying file. */
+ if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) && ( *( end - 1 ) == ')' ) )
+ {
+ /* We try the expansion until it fits within the propective output
+ * buffer.
+ */
+ char * at_buf = 0;
+ int at_size = MAXJPATH;
+ int at_len = 0;
+ do
+ {
+ BJAM_FREE( at_buf );
+ at_buf = (char *)BJAM_MALLOC_ATOMIC( at_size + 1 );
+ at_len = var_string( in, at_buf, at_size, lol );
+ at_size *= 2;
+ }
+ while ( ( at_len < 0 ) && ( at_size < INT_MAX / 2 ) );
+ /* Return the result as a single item list. */
+ if ( at_len > 0 )
+ {
+ LIST * r;
+ string_copy( buf, at_buf );
+ r = list_new( l, newstr( buf->value ) );
+ string_free( buf );
+ BJAM_FREE( at_buf );
+ return r;
+ }
+ BJAM_FREE( at_buf );
+ }
+
+ /* Just try simple copy of in to out. */
+ while ( in < end )
+ if ( ( *in++ == '$' ) && ( *in == '(' ) )
+ goto expand;
+
+ /* No variables expanded - just add copy of input string to list. */
+
+ /* 'cancopyin' is an optimization: if the input was already a list item, we
+ * can use copystr() to put it on the new list. Otherwise, we use the slower
+ * newstr().
+ */
+ if ( cancopyin )
+ return list_new( l, copystr( inp ) );
+
+ {
+ LIST * r;
+ string_new( buf );
+ string_append_range( buf, inp, end );
+ r = list_new( l, newstr( buf->value ) );
+ string_free( buf );
+ return r;
+ }
+
+expand:
+ string_new( buf );
+ string_append_range( buf, inp, in - 1 ); /* Copy the part before '$'. */
+ /*
+ * Input so far (ignore blanks):
+ *
+ * stuff-in-outbuf $(variable) remainder
+ * ^ ^
+ * in end
+ * Output so far:
+ *
+ * stuff-in-outbuf $
+ * ^ ^
+ * out_buf out
+ *
+ *
+ * We just copied the $ of $(...), so back up one on the output. We now find
+ * the matching close paren, copying the variable and modifiers between the
+ * $( and ) temporarily into out_buf, so that we can replace :'s with
+ * MAGIC_COLON. This is necessary to avoid being confused by modifier values
+ * that are variables containing :'s. Ugly.
+ */
+
+ depth = 1;
+ inp = ++in; /* Skip over the '('. */
+
+ while ( ( in < end ) && depth )
+ {
+ switch ( *in++ )
+ {
+ case '(': ++depth; break;
+ case ')': --depth; break;
+ }
+ }
+
+ /*
+ * Input so far (ignore blanks):
+ *
+ * stuff-in-outbuf $(variable) remainder
+ * ^ ^ ^
+ * inp in end
+ */
+ prefix_length = buf->size;
+ string_append_range( buf, inp, in - 1 );
+
+ out = buf->value + prefix_length;
+ for ( ov = out; ov < buf->value + buf->size; ++ov )
+ {
+ switch ( *ov )
+ {
+ case ':': *ov = MAGIC_COLON; break;
+ case '[': *ov = MAGIC_LEFT ; break;
+ case ']': *ov = MAGIC_RIGHT; break;
+ }
+ }
+
+ /*
+ * Input so far (ignore blanks):
+ *
+ * stuff-in-outbuf $(variable) remainder
+ * ^ ^
+ * in end
+ * Output so far:
+ *
+ * stuff-in-outbuf variable
+ * ^ ^ ^
+ * out_buf out ov
+ *
+ * Later we will overwrite 'variable' in out_buf, but we will be done with
+ * it by then. 'variable' may be a multi-element list, so may each value for
+ * '$(variable element)', and so may 'remainder'. Thus we produce a product
+ * of three lists.
+ */
+ {
+ LIST * variables = 0;
+ LIST * remainder = 0;
+ LIST * vars;
+
+ /* Recursively expand variable name & rest of input. */
+ if ( out < ov ) variables = var_expand( L0, out, ov, lol, 0 );
+ if ( in < end ) remainder = var_expand( L0, in, end, lol, 0 );
+
+ /* Now produce the result chain. */
+
+ /* For each variable name. */
+ for ( vars = variables; vars; vars = list_next( vars ) )
+ {
+ LIST * value = 0;
+ LIST * evalue = 0;
+ char * colon;
+ char * bracket;
+ string variable[1];
+ char * varname;
+ int sub1 = 0;
+ int sub2 = -1;
+ VAR_EDITS edits;
+
+ /* Look for a : modifier in the variable name. Must copy into
+ * varname so we can modify it.
+ */
+ string_copy( variable, vars->string );
+ varname = variable->value;
+
+ if ( ( colon = strchr( varname, MAGIC_COLON ) ) )
+ {
+ string_truncate( variable, colon - varname );
+ var_edit_parse( colon + 1, &edits );
+ }
+
+ /* Look for [x-y] subscripting. sub1 and sub2 are x and y. */
+ if ( ( bracket = strchr( varname, MAGIC_LEFT ) ) )
+ {
+ /* Make all syntax errors in [] subscripting result in the same
+ * behavior: silenty return an empty expansion (by setting sub2
+ * = 0). Brute force parsing; May get moved into yacc someday.
+ */
+
+ char * s = bracket + 1;
+
+ string_truncate( variable, bracket - varname );
+
+ do /* so we can use "break" */
+ {
+ /* Allow negative indexes. */
+ if ( !isdigit( *s ) && ( *s != '-' ) )
+ {
+ sub2 = 0;
+ break;
+ }
+ sub1 = atoi( s );
+
+ /* Skip over the first symbol, which is either a digit or dash. */
+ ++s;
+ while ( isdigit( *s ) ) ++s;
+
+ if ( *s == MAGIC_RIGHT )
+ {
+ sub2 = sub1;
+ break;
+ }
+
+ if ( *s != '-' )
+ {
+ sub2 = 0;
+ break;
+ }
+
+ ++s;
+
+ if ( *s == MAGIC_RIGHT )
+ {
+ sub2 = -1;
+ break;
+ }
+
+ if ( !isdigit( *s ) && ( *s != '-' ) )
+ {
+ sub2 = 0;
+ break;
+ }
+
+ /* First, compute the index of the last element. */
+ sub2 = atoi( s );
+ while ( isdigit( *++s ) );
+
+ if ( *s != MAGIC_RIGHT )
+ sub2 = 0;
+
+ } while ( 0 );
+
+ /* Anything but the end of the string, or the colon introducing
+ * a modifier is a syntax error.
+ */
+ ++s;
+ if ( *s && ( *s != MAGIC_COLON ) )
+ sub2 = 0;
+
+ *bracket = '\0';
+ }
+
+ /* Get variable value, with special handling for $(<), $(>), $(n).
+ */
+ if ( !varname[1] )
+ {
+ if ( varname[0] == '<' )
+ value = lol_get( lol, 0 );
+ else if ( varname[0] == '>' )
+ value = lol_get( lol, 1 );
+ else if ( ( varname[0] >= '1' ) && ( varname[0] <= '9' ) )
+ value = lol_get( lol, varname[0] - '1' );
+ else if( varname[0] == '1' && varname[1] >= '0' &&
+ varname[1] <= '9' && !varname[2] )
+ value = lol_get( lol, varname[1] - '0' + 10 - 1 );
+ }
+
+ if ( !value )
+ value = var_get( varname );
+
+ /* Handle negitive indexes: part two. */
+ {
+ int length = list_length( value );
+
+ if ( sub1 < 0 )
+ sub1 = length + sub1;
+ else
+ sub1 -= 1;
+
+ if ( sub2 < 0 )
+ sub2 = length + 1 + sub2 - sub1;
+ else
+ sub2 -= sub1;
+ /* The "sub2 < 0" test handles the semantic error of sub2 <
+ * sub1.
+ */
+ if ( sub2 < 0 )
+ sub2 = 0;
+ }
+
+ /* The fast path: $(x) - just copy the variable value. This is only
+ * an optimization.
+ */
+ if ( ( out == out_buf ) && !bracket && !colon && ( in == end ) )
+ {
+ string_free( variable );
+ l = list_copy( l, value );
+ continue;
+ }
+
+ /* Handle start subscript. */
+ while ( ( sub1 > 0 ) && value )
+ --sub1, value = list_next( value );
+
+ /* Empty w/ :E=default?. */
+ if ( !value && colon && edits.empty.ptr )
+ evalue = value = list_new( L0, newstr( edits.empty.ptr ) );
+
+ /* For each variable value. */
+ string_new( out1 );
+ for ( ; value; value = list_next( value ) )
+ {
+ LIST * rem;
+ size_t postfix_start;
+
+ /* Handle end subscript (length actually). */
+
+ if ( sub2 >= 0 && --sub2 < 0 )
+ break;
+
+ string_truncate( buf, prefix_length );
+
+ /* Apply : mods, if present */
+
+ if ( colon && edits.filemods )
+ var_edit_file( value->string, out1, &edits );
+ else
+ string_append( out1, value->string );
+
+ if ( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) )
+ var_edit_shift( out1, &edits );
+
+ /* Handle :J=joinval */
+ /* If we have more values for this var, just keep appending them
+ * (using the join value) rather than creating separate LIST
+ * elements.
+ */
+ if ( colon && edits.join.ptr &&
+ ( list_next( value ) || list_next( vars ) ) )
+ {
+ string_append( out1, edits.join.ptr );
+ continue;
+ }
+
+ string_append( buf, out1->value );
+ string_free( out1 );
+ string_new( out1 );
+
+ /* If no remainder, append result to output chain. */
+ if ( in == end )
+ {
+ l = list_new( l, newstr( buf->value ) );
+ continue;
+ }
+
+ /* For each remainder, append the complete string to the output
+ * chain. Remember the end of the variable expansion so we can
+ * just tack on each instance of 'remainder'.
+ */
+ postfix_start = buf->size;
+ for ( rem = remainder; rem; rem = list_next( rem ) )
+ {
+ string_truncate( buf, postfix_start );
+ string_append( buf, rem->string );
+ l = list_new( l, newstr( buf->value ) );
+ }
+ }
+ string_free( out1 );
+
+ /* Toss used empty. */
+ if ( evalue )
+ list_free( evalue );
+
+ string_free( variable );
+ }
+
+ /* variables & remainder were gifts from var_expand and must be freed. */
+ if ( variables ) list_free( variables );
+ if ( remainder ) list_free( remainder );
+
+ if ( DEBUG_VAREXP )
+ {
+ printf( "expanded to " );
+ list_print( l );
+ printf( "\n" );
+ }
+
+ string_free( buf );
+ return l;
+ }
+}
+
+
+/*
+ * var_edit_parse() - parse : modifiers into PATHNAME structure
+ *
+ * The : modifiers in a $(varname:modifier) currently support replacing or
+ * omitting elements of a filename, and so they are parsed into a PATHNAME
+ * structure (which contains pointers into the original string).
+ *
+ * Modifiers of the form "X=value" replace the component X with the given value.
+ * Modifiers without the "=value" cause everything but the component X to be
+ * omitted. X is one of:
+ *
+ * G <grist>
+ * D directory name
+ * B base name
+ * S .suffix
+ * M (member)
+ * R root directory - prepended to whole path
+ *
+ * This routine sets:
+ *
+ * f->f_xxx.ptr = 0
+ * f->f_xxx.len = 0
+ * -> leave the original component xxx
+ *
+ * f->f_xxx.ptr = string
+ * f->f_xxx.len = strlen( string )
+ * -> replace component xxx with string
+ *
+ * f->f_xxx.ptr = ""
+ * f->f_xxx.len = 0
+ * -> omit component xxx
+ *
+ * var_edit_file() below and path_build() obligingly follow this convention.
+ */
+
+static void var_edit_parse( char * mods, VAR_EDITS * edits )
+{
+ int havezeroed = 0;
+ memset( (char *)edits, 0, sizeof( *edits ) );
+
+ while ( *mods )
+ {
+ char * p;
+ PATHPART * fp;
+
+ switch ( *mods++ )
+ {
+ case 'L': edits->downshift = 1; continue;
+ case 'U': edits->upshift = 1; continue;
+ case 'P': edits->parent = edits->filemods = 1; continue;
+ case 'E': fp = &edits->empty; goto strval;
+ case 'J': fp = &edits->join; goto strval;
+ case 'G': fp = &edits->f.f_grist; goto fileval;
+ case 'R': fp = &edits->f.f_root; goto fileval;
+ case 'D': fp = &edits->f.f_dir; goto fileval;
+ case 'B': fp = &edits->f.f_base; goto fileval;
+ case 'S': fp = &edits->f.f_suffix; goto fileval;
+ case 'M': fp = &edits->f.f_member; goto fileval;
+ case 'T': edits->to_slashes = 1; continue;
+ case 'W': edits->to_windows = 1; continue;
+ default:
+ return; /* Should complain, but so what... */
+ }
+
+ fileval:
+ /* Handle :CHARS, where each char (without a following =) selects a
+ * particular file path element. On the first such char, we deselect all
+ * others (by setting ptr = "", len = 0) and for each char we select
+ * that element (by setting ptr = 0).
+ */
+ edits->filemods = 1;
+
+ if ( *mods != '=' )
+ {
+ if ( !havezeroed++ )
+ {
+ int i;
+ for ( i = 0; i < 6; ++i )
+ {
+ edits->f.part[ i ].len = 0;
+ edits->f.part[ i ].ptr = "";
+ }
+ }
+
+ fp->ptr = 0;
+ continue;
+ }
+
+ strval:
+ /* Handle :X=value, or :X */
+ if ( *mods != '=' )
+ {
+ fp->ptr = "";
+ fp->len = 0;
+ }
+ else if ( ( p = strchr( mods, MAGIC_COLON ) ) )
+ {
+ *p = 0;
+ fp->ptr = ++mods;
+ fp->len = p - mods;
+ mods = p + 1;
+ }
+ else
+ {
+ fp->ptr = ++mods;
+ fp->len = strlen( mods );
+ mods += fp->len;
+ }
+ }
+}
+
+
+/*
+ * var_edit_file() - copy input target name to output, modifying filename.
+ */
+
+static void var_edit_file( char * in, string * out, VAR_EDITS * edits )
+{
+ PATHNAME pathname;
+
+ /* Parse apart original filename, putting parts into "pathname". */
+ path_parse( in, &pathname );
+
+ /* Replace any pathname with edits->f */
+ if ( edits->f.f_grist .ptr ) pathname.f_grist = edits->f.f_grist;
+ if ( edits->f.f_root .ptr ) pathname.f_root = edits->f.f_root;
+ if ( edits->f.f_dir .ptr ) pathname.f_dir = edits->f.f_dir;
+ if ( edits->f.f_base .ptr ) pathname.f_base = edits->f.f_base;
+ if ( edits->f.f_suffix.ptr ) pathname.f_suffix = edits->f.f_suffix;
+ if ( edits->f.f_member.ptr ) pathname.f_member = edits->f.f_member;
+
+ /* If requested, modify pathname to point to parent. */
+ if ( edits->parent )
+ path_parent( &pathname );
+
+ /* Put filename back together. */
+ path_build( &pathname, out, 0 );
+}
+
+
+/*
+ * var_edit_shift() - do upshift/downshift mods.
+ */
+
+static void var_edit_shift( string * out, VAR_EDITS * edits )
+{
+ /* Handle upshifting, downshifting and slash translation now. */
+ char * p;
+ for ( p = out->value; *p; ++p)
+ {
+ if ( edits->upshift )
+ *p = toupper( *p );
+ else if ( edits->downshift )
+ *p = tolower( *p );
+ if ( edits->to_slashes && ( *p == '\\' ) )
+ *p = '/';
+# ifdef OS_CYGWIN
+ if ( edits->to_windows )
+ {
+ char result[ MAX_PATH + 1 ];
+ cygwin_conv_to_win32_path( out->value, result );
+ assert( strlen( result ) <= MAX_PATH );
+ string_free( out );
+ string_copy( out, result );
+ }
+# endif
+ }
+ out->size = p - out->value;
+}
+
+
+#ifndef NDEBUG
+void var_expand_unit_test()
+{
+ LOL lol[ 1 ];
+ LIST * l;
+ LIST * l2;
+ LIST * expected = list_new( list_new( L0, newstr( "axb" ) ), newstr( "ayb" ) );
+ LIST * e2;
+ char axyb[] = "a$(xy)b";
+ char azb[] = "a$($(z))b";
+ char path[] = "$(p:W)";
+
+# ifdef OS_CYGWIN
+ char cygpath[ 256 ];
+ cygwin_conv_to_posix_path( "c:\\foo\\bar", cygpath );
+# else
+ char cygpath[] = "/cygdrive/c/foo/bar";
+# endif
+
+ lol_init(lol);
+ var_set( "xy", list_new( list_new( L0, newstr( "x" ) ), newstr( "y" ) ), VAR_SET );
+ var_set( "z", list_new( L0, newstr( "xy" ) ), VAR_SET );
+ var_set( "p", list_new( L0, newstr( cygpath ) ), VAR_SET );
+
+ l = var_expand( 0, axyb, axyb + sizeof( axyb ) - 1, lol, 0 );
+ for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next( l2 ), e2 = list_next( e2 ) )
+ assert( !strcmp( e2->string, l2->string ) );
+ assert( l2 == 0 );
+ assert( e2 == 0 );
+ list_free( l );
+
+ l = var_expand( 0, azb, azb + sizeof( azb ) - 1, lol, 0 );
+ for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next( l2 ), e2 = list_next( e2 ) )
+ assert( !strcmp( e2->string, l2->string ) );
+ assert( l2 == 0 );
+ assert( e2 == 0 );
+ list_free( l );
+
+ l = var_expand( 0, path, path + sizeof( path ) - 1, lol, 0 );
+ assert( l != 0 );
+ assert( list_next( l ) == 0 );
+# ifdef OS_CYGWIN
+ /* On some installations of cygwin the drive letter is expanded to other
+ * case. This has been reported to be the case if cygwin has been installed
+ * to C:\ as opposed to C:\cygwin. Since case of the drive letter will not
+ * matter, we allow for both.
+ */
+ assert( !strcmp( l->string, "c:\\foo\\bar" ) ||
+ !strcmp( l->string, "C:\\foo\\bar" ) );
+# else
+ assert( !strcmp( l->string, cygpath ) );
+# endif
+ list_free( l );
+ list_free( expected );
+ lol_free( lol );
+}
+#endif
diff --git a/tools/build/v2/engine/expand.h b/tools/build/v2/engine/expand.h
new file mode 100644
index 0000000000..cc25d19090
--- /dev/null
+++ b/tools/build/v2/engine/expand.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * expand.h - expand a buffer, given variable values
+ */
+
+#include "lists.h"
+
+LIST *var_expand( LIST *l, char *in, char *end, LOL *lol, int cancopyin );
+void var_expand_unit_test();
diff --git a/tools/build/v2/engine/filemac.c b/tools/build/v2/engine/filemac.c
new file mode 100644
index 0000000000..e69aa648f3
--- /dev/null
+++ b/tools/build/v2/engine/filemac.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "filesys.h"
+# include "pathsys.h"
+
+# ifdef OS_MAC
+
+#include <Files.h>
+#include <Folders.h>
+
+# include <:sys:stat.h>
+
+/*
+ * filemac.c - manipulate file names and scan directories on macintosh
+ *
+ * External routines:
+ *
+ * file_dirscan() - scan a directory for files
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_archscan() - scan an archive for files
+ *
+ * File_dirscan() and file_archscan() call back a caller provided function
+ * for each file found. A flag to this callback function lets file_dirscan()
+ * and file_archscan() indicate that a timestamp is being provided with the
+ * file. If file_dirscan() or file_archscan() do not provide the file's
+ * timestamp, interested parties may later call file_time().
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 12/19/94 (mikem) - solaris string table insanity support
+ * 02/14/95 (seiwald) - parse and build /xxx properly
+ * 05/03/96 (seiwald) - split into pathunix.c
+ * 11/21/96 (peterk) - BEOS does not have Unix-style archives
+ */
+
+
+void CopyC2PStr( char const * cstr, StringPtr pstr )
+{
+ int len;
+ for ( len = 0; *cstr && ( len < 255 ); pstr[ ++len ] = *cstr++ );
+ pstr[ 0 ] = len;
+}
+
+
+/*
+ * file_dirscan() - scan a directory for files.
+ */
+
+void file_dirscan( char * dir, scanback func, void * closure )
+{
+ PATHNAME f;
+ string filename[ 1 ];
+ unsigned char fullPath[ 512 ];
+
+ FSSpec spec;
+ WDPBRec vol;
+ Str63 volName;
+ CInfoPBRec lastInfo;
+ int index = 1;
+
+ /* First enter directory itself. */
+
+ memset( (char *)&f, '\0', sizeof( f ) );
+
+ f.f_dir.ptr = dir;
+ f.f_dir.len = strlen(dir);
+
+ if ( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", dir );
+
+ /* Special case ":" - enter it */
+
+ if ( ( f.f_dir.len == 1 ) && ( f.f_dir.ptr[0] == ':' ) )
+ (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
+
+ /* Now enter contents of directory */
+
+ vol.ioNamePtr = volName;
+
+ if ( PBHGetVolSync( &vol ) )
+ return;
+
+ CopyC2PStr( dir, fullPath );
+
+ if ( FSMakeFSSpec( vol.ioWDVRefNum, vol.ioWDDirID, fullPath, &spec ) )
+ return;
+
+ lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
+ lastInfo.dirInfo.ioDrDirID = spec.parID;
+ lastInfo.dirInfo.ioNamePtr = spec.name;
+ lastInfo.dirInfo.ioFDirIndex = 0;
+ lastInfo.dirInfo.ioACUser = 0;
+
+ if ( PBGetCatInfoSync( &lastInfo ) )
+ return;
+
+ if ( !( lastInfo.dirInfo.ioFlAttrib & 0x10 ) )
+ return;
+
+ /* ioDrDirID must be reset each time. */
+ spec.parID = lastInfo.dirInfo.ioDrDirID;
+
+ string_new( filename );
+ for ( ; ; )
+ {
+ lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
+ lastInfo.dirInfo.ioDrDirID = spec.parID;
+ lastInfo.dirInfo.ioNamePtr = fullPath;
+ lastInfo.dirInfo.ioFDirIndex = index++;
+
+ if ( PBGetCatInfoSync( &lastInfo ) )
+ return;
+
+ f.f_base.ptr = (char *)fullPath + 1;
+ f.f_base.len = *fullPath;
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename, 0 );
+ (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
+ }
+ string_free( filename );
+}
+
+
+/*
+ * file_time() - get timestamp of file, if not done by file_dirscan().
+ */
+
+int file_time( char * filename, time_t * time )
+{
+ struct stat statbuf;
+
+ if ( stat( filename, &statbuf ) < 0 )
+ return -1;
+
+ *time = statbuf.st_mtime;
+
+ return 0;
+}
+
+
+int file_is_file( char * filename )
+{
+ struct stat statbuf;
+ if ( stat( filename, &statbuf ) < 0 )
+ return -1;
+ return S_ISREG( statbuf.st_mode ) ? 1 : 0;
+}
+
+int file_mkdir(char *pathname)
+{
+ return mkdir(pathname, 0766);
+}
+
+
+/*
+ * file_archscan() - scan an archive for files.
+ */
+
+void file_archscan( char * archive, scanback func, void * closure )
+{
+}
+
+
+# endif /* macintosh */
diff --git a/tools/build/v2/engine/filent.c b/tools/build/v2/engine/filent.c
new file mode 100644
index 0000000000..ab18957677
--- /dev/null
+++ b/tools/build/v2/engine/filent.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Copyright 2005 Rene Rivera.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+
+# include "filesys.h"
+# include "pathsys.h"
+# include "strings.h"
+# include "newstr.h"
+
+# ifdef OS_NT
+
+# ifdef __BORLANDC__
+# if __BORLANDC__ < 0x550
+# include <dir.h>
+# include <dos.h>
+# endif
+# undef FILENAME /* cpp namespace collision */
+# define _finddata_t ffblk
+# endif
+
+# include <io.h>
+# include <sys/stat.h>
+# include <ctype.h>
+# include <direct.h>
+
+/*
+ * filent.c - scan directories and archives on NT
+ *
+ * External routines:
+ *
+ * file_dirscan() - scan a directory for files
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_archscan() - scan an archive for files
+ *
+ * File_dirscan() and file_archscan() call back a caller provided function
+ * for each file found. A flag to this callback function lets file_dirscan()
+ * and file_archscan() indicate that a timestamp is being provided with the
+ * file. If file_dirscan() or file_archscan() do not provide the file's
+ * timestamp, interested parties may later call file_time().
+ *
+ * 07/10/95 (taylor) Findfirst() returns the first file on NT.
+ * 05/03/96 (seiwald) split apart into pathnt.c
+ */
+
+/*
+ * file_dirscan() - scan a directory for files
+ */
+
+void file_dirscan( char * dir, scanback func, void * closure )
+{
+ PROFILE_ENTER( FILE_DIRSCAN );
+
+ file_info_t * d = 0;
+
+ dir = short_path_to_long_path( dir );
+
+ /* First enter directory itself */
+
+ d = file_query( dir );
+
+ if ( !d || !d->is_dir )
+ {
+ PROFILE_EXIT( FILE_DIRSCAN );
+ return;
+ }
+
+ if ( !d->files )
+ {
+ PATHNAME f;
+ string filespec[ 1 ];
+ string filename[ 1 ];
+ long handle;
+ int ret;
+ struct _finddata_t finfo[ 1 ];
+ LIST * files = L0;
+ int d_length = strlen( d->name );
+
+ memset( (char *)&f, '\0', sizeof( f ) );
+
+ f.f_dir.ptr = d->name;
+ f.f_dir.len = d_length;
+
+ /* Now enter contents of directory */
+
+ /* Prepare file search specification for the findfirst() API. */
+ if ( d_length == 0 )
+ string_copy( filespec, ".\\*" );
+ else
+ {
+ /*
+ * We can not simply assume the given folder name will never include
+ * its trailing path separator or otherwise we would not support the
+ * Windows root folder specified without its drive letter, i.e. '\'.
+ */
+ char trailingChar = d->name[ d_length - 1 ] ;
+ string_copy( filespec, d->name );
+ if ( ( trailingChar != '\\' ) && ( trailingChar != '/' ) )
+ string_append( filespec, "\\" );
+ string_append( filespec, "*" );
+ }
+
+ if ( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", dir );
+
+ #if defined(__BORLANDC__) && __BORLANDC__ < 0x550
+ if ( ret = findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
+ {
+ string_free( filespec );
+ PROFILE_EXIT( FILE_DIRSCAN );
+ return;
+ }
+
+ string_new ( filename );
+ while ( !ret )
+ {
+ file_info_t * ff = 0;
+
+ f.f_base.ptr = finfo->ff_name;
+ f.f_base.len = strlen( finfo->ff_name );
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename );
+
+ files = list_new( files, newstr(filename->value) );
+ ff = file_info( filename->value );
+ ff->is_file = finfo->ff_attrib & FA_DIREC ? 0 : 1;
+ ff->is_dir = finfo->ff_attrib & FA_DIREC ? 1 : 0;
+ ff->size = finfo->ff_fsize;
+ ff->time = (finfo->ff_ftime << 16) | finfo->ff_ftime;
+
+ ret = findnext( finfo );
+ }
+ # else
+ handle = _findfirst( filespec->value, finfo );
+
+ if ( ret = ( handle < 0L ) )
+ {
+ string_free( filespec );
+ PROFILE_EXIT( FILE_DIRSCAN );
+ return;
+ }
+
+ string_new( filename );
+ while ( !ret )
+ {
+ file_info_t * ff = 0;
+
+ f.f_base.ptr = finfo->name;
+ f.f_base.len = strlen( finfo->name );
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename, 0 );
+
+ files = list_new( files, newstr( filename->value ) );
+ ff = file_info( filename->value );
+ ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1;
+ ff->is_dir = finfo->attrib & _A_SUBDIR ? 1 : 0;
+ ff->size = finfo->size;
+ ff->time = finfo->time_write;
+
+ ret = _findnext( handle, finfo );
+ }
+
+ _findclose( handle );
+ # endif
+ string_free( filename );
+ string_free( filespec );
+
+ d->files = files;
+ }
+
+ /* Special case \ or d:\ : enter it */
+ {
+ unsigned long len = strlen(d->name);
+ if ( len == 1 && d->name[0] == '\\' )
+ (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
+ else if ( len == 3 && d->name[1] == ':' ) {
+ (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
+ /* We've just entered 3-letter drive name spelling (with trailing
+ slash), into the hash table. Now enter two-letter variant,
+ without trailing slash, so that if we try to check whether
+ "c:" exists, we hit it.
+
+ Jam core has workarounds for that. Given:
+ x = c:\whatever\foo ;
+ p = $(x:D) ;
+ p2 = $(p:D) ;
+ There will be no trailing slash in $(p), but there will be one
+ in $(p2). But, that seems rather fragile.
+ */
+ d->name[2] = 0;
+ (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
+ }
+ }
+
+ /* Now enter contents of directory */
+ if ( d->files )
+ {
+ LIST * files = d->files;
+ while ( files )
+ {
+ file_info_t * ff = file_info( files->string );
+ (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
+ files = list_next( files );
+ }
+ }
+
+ PROFILE_EXIT( FILE_DIRSCAN );
+}
+
+file_info_t * file_query( char * filename )
+{
+ file_info_t * ff = file_info( filename );
+ if ( ! ff->time )
+ {
+ struct stat statbuf;
+
+ if ( stat( *filename ? filename : ".", &statbuf ) < 0 )
+ return 0;
+
+ ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
+ ff->is_dir = statbuf.st_mode & S_IFDIR ? 1 : 0;
+ ff->size = statbuf.st_size;
+ ff->time = statbuf.st_mtime ? statbuf.st_mtime : 1;
+ }
+ return ff;
+}
+
+/*
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ */
+
+int
+file_time(
+ char *filename,
+ time_t *time )
+{
+ file_info_t * ff = file_query( filename );
+ if ( !ff ) return -1;
+ *time = ff->time;
+ return 0;
+}
+
+int file_is_file(char* filename)
+{
+ file_info_t * ff = file_query( filename );
+ if ( !ff ) return -1;
+ return ff->is_file;
+}
+
+int file_mkdir(char *pathname)
+{
+ return _mkdir(pathname);
+}
+
+/*
+ * file_archscan() - scan an archive for files
+ */
+
+/* Straight from SunOS */
+
+#define ARMAG "!<arch>\n"
+#define SARMAG 8
+
+#define ARFMAG "`\n"
+
+struct ar_hdr {
+ char ar_name[16];
+ char ar_date[12];
+ char ar_uid[6];
+ char ar_gid[6];
+ char ar_mode[8];
+ char ar_size[10];
+ char ar_fmag[2];
+};
+
+# define SARFMAG 2
+# define SARHDR sizeof( struct ar_hdr )
+
+void
+file_archscan(
+ char *archive,
+ scanback func,
+ void *closure )
+{
+ struct ar_hdr ar_hdr;
+ char *string_table = 0;
+ char buf[ MAXJPATH ];
+ long offset;
+ int fd;
+
+ if ( ( fd = open( archive, O_RDONLY | O_BINARY, 0 ) ) < 0 )
+ return;
+
+ if ( read( fd, buf, SARMAG ) != SARMAG ||
+ strncmp( ARMAG, buf, SARMAG ) )
+ {
+ close( fd );
+ return;
+ }
+
+ offset = SARMAG;
+
+ if ( DEBUG_BINDSCAN )
+ printf( "scan archive %s\n", archive );
+
+ while ( ( read( fd, &ar_hdr, SARHDR ) == SARHDR ) &&
+ !memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG ) )
+ {
+ long lar_date;
+ long lar_size;
+ char *name = 0;
+ char *endname;
+ char *c;
+
+ sscanf( ar_hdr.ar_date, "%ld", &lar_date );
+ sscanf( ar_hdr.ar_size, "%ld", &lar_size );
+
+ lar_size = ( lar_size + 1 ) & ~1;
+
+ if (ar_hdr.ar_name[0] == '/' && ar_hdr.ar_name[1] == '/' )
+ {
+ /* this is the "string table" entry of the symbol table,
+ ** which holds strings of filenames that are longer than
+ ** 15 characters (ie. don't fit into a ar_name
+ */
+
+ string_table = BJAM_MALLOC_ATOMIC(lar_size+1);
+ if (read(fd, string_table, lar_size) != lar_size)
+ printf("error reading string table\n");
+ string_table[lar_size] = '\0';
+ offset += SARHDR + lar_size;
+ continue;
+ }
+ else if (ar_hdr.ar_name[0] == '/' && ar_hdr.ar_name[1] != ' ')
+ {
+ /* Long filenames are recognized by "/nnnn" where nnnn is
+ ** the offset of the string in the string table represented
+ ** in ASCII decimals.
+ */
+
+ name = string_table + atoi( ar_hdr.ar_name + 1 );
+ for ( endname = name; *endname && *endname != '\n'; ++endname) {}
+ }
+ else
+ {
+ /* normal name */
+ name = ar_hdr.ar_name;
+ endname = name + sizeof( ar_hdr.ar_name );
+ }
+
+ /* strip trailing white-space, slashes, and backslashes */
+
+ while ( endname-- > name )
+ if ( !isspace(*endname) && ( *endname != '\\' ) && ( *endname != '/' ) )
+ break;
+ *++endname = 0;
+
+ /* strip leading directory names, an NT specialty */
+
+ if ( c = strrchr( name, '/' ) )
+ name = c + 1;
+ if ( c = strrchr( name, '\\' ) )
+ name = c + 1;
+
+ sprintf( buf, "%s(%.*s)", archive, endname - name, name );
+ (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+
+ offset += SARHDR + lar_size;
+ lseek( fd, offset, 0 );
+ }
+
+ close( fd );
+}
+
+# endif /* NT */
diff --git a/tools/build/v2/engine/fileos2.c b/tools/build/v2/engine/fileos2.c
new file mode 100644
index 0000000000..af2373ea83
--- /dev/null
+++ b/tools/build/v2/engine/fileos2.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "filesys.h"
+# include "pathsys.h"
+
+/* note that we use "fileunix.c" when compiling with EMX on OS/2 */
+# if defined(OS_OS2) && !defined(__EMX__)
+
+# include <io.h>
+# include <dos.h>
+
+/*
+ * fileos2.c - scan directories and archives on NT
+ *
+ * External routines:
+ *
+ * file_dirscan() - scan a directory for files
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_archscan() - scan an archive for files
+ *
+ * File_dirscan() and file_archscan() call back a caller provided function
+ * for each file found. A flag to this callback function lets file_dirscan()
+ * and file_archscan() indicate that a timestamp is being provided with the
+ * file. If file_dirscan() or file_archscan() do not provide the file's
+ * timestamp, interested parties may later call file_time().
+ *
+ * 07/10/95 (taylor) Findfirst() returns the first file on NT.
+ * 05/03/96 (seiwald) split apart into pathnt.c
+ * 09/22/00 (seiwald) handle \ and c:\ specially: don't add extra /
+ */
+
+/*
+ * file_dirscan() - scan a directory for files
+ */
+
+void
+file_dirscan(
+ char *dir,
+ scanback func,
+ void *closure )
+{
+ PATHNAME f;
+ string filespec[1];
+ long handle;
+ int ret;
+ struct _find_t finfo[1];
+
+ /* First enter directory itself */
+
+ memset( (char *)&f, '\0', sizeof( f ) );
+
+ f.f_dir.ptr = dir;
+ f.f_dir.len = strlen(dir);
+
+ dir = *dir ? dir : ".";
+
+ /* Special case \ or d:\ : enter it */
+ string_copy( filespec, dir );
+
+ if ( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
+ (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
+ else if ( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
+ (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
+ else
+ string_push_back( filespec, '/' );
+
+ string_push_back( filespec, '*' );
+
+ /* Now enter contents of directory */
+
+ if ( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", filespec->value );
+
+ /* Time info in dos find_t is not very useful. It consists */
+ /* of a separate date and time, and putting them together is */
+ /* not easy. So we leave that to a later stat() call. */
+
+ if ( !_dos_findfirst( filespec->value, _A_NORMAL|_A_RDONLY|_A_SUBDIR, finfo ) )
+ {
+ string filename[1];
+ string_new( filename );
+ do
+ {
+ f.f_base.ptr = finfo->name;
+ f.f_base.len = strlen( finfo->name );
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename, 0 );
+ (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
+ }
+ while ( !_dos_findnext( finfo ) );
+ string_free( filename );
+ }
+}
+
+/*
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ */
+
+int
+file_time(
+ char *filename,
+ time_t *time )
+{
+ /* This is called on OS2, not NT. */
+ /* NT fills in the time in the dirscan. */
+
+ struct stat statbuf;
+
+ if ( stat( filename, &statbuf ) < 0 )
+ return -1;
+
+ *time = statbuf.st_mtime;
+
+ return 0;
+}
+
+void
+file_archscan(
+ char *archive,
+ scanback func,
+ void *closure )
+{
+}
+
+# endif /* OS2 && !__EMX__ */
+
diff --git a/tools/build/v2/engine/filesys.c b/tools/build/v2/engine/filesys.c
new file mode 100644
index 0000000000..eb62ed4060
--- /dev/null
+++ b/tools/build/v2/engine/filesys.c
@@ -0,0 +1,83 @@
+# include "jam.h"
+# include "pathsys.h"
+# include "strings.h"
+# include "newstr.h"
+# include "filesys.h"
+# include "lists.h"
+
+void file_build1( PATHNAME * f, string * file )
+{
+ if ( DEBUG_SEARCH )
+ {
+ printf("build file: ");
+ if ( f->f_root.len )
+ printf( "root = '%.*s' ", f->f_root.len, f->f_root.ptr );
+ if ( f->f_dir.len )
+ printf( "dir = '%.*s' ", f->f_dir.len, f->f_dir.ptr );
+ if ( f->f_base.len )
+ printf( "base = '%.*s' ", f->f_base.len, f->f_base.ptr );
+ printf( "\n" );
+ }
+
+ /* Start with the grist. If the current grist isn't */
+ /* surrounded by <>'s, add them. */
+
+ if ( f->f_grist.len )
+ {
+ if ( f->f_grist.ptr[0] != '<' )
+ string_push_back( file, '<' );
+ string_append_range(
+ file, f->f_grist.ptr, f->f_grist.ptr + f->f_grist.len );
+ if ( file->value[file->size - 1] != '>' )
+ string_push_back( file, '>' );
+ }
+}
+
+static struct hash * filecache_hash = 0;
+static file_info_t filecache_finfo;
+
+file_info_t * file_info(char * filename)
+{
+ file_info_t *finfo = &filecache_finfo;
+
+ if ( !filecache_hash )
+ filecache_hash = hashinit( sizeof( file_info_t ), "file_info" );
+
+ finfo->name = filename;
+ finfo->is_file = 0;
+ finfo->is_dir = 0;
+ finfo->size = 0;
+ finfo->time = 0;
+ finfo->files = 0;
+ if ( hashenter( filecache_hash, (HASHDATA**)&finfo ) )
+ {
+ /* printf( "file_info: %s\n", filename ); */
+ finfo->name = newstr( finfo->name );
+ }
+
+ return finfo;
+}
+
+static LIST * files_to_remove = L0;
+
+static void remove_files_atexit(void)
+{
+ /* we do pop front in case this exit function is called
+ more than once */
+ while ( files_to_remove )
+ {
+ remove( files_to_remove->string );
+ files_to_remove = list_pop_front( files_to_remove );
+ }
+}
+
+void file_done()
+{
+ remove_files_atexit();
+ hashdone( filecache_hash );
+}
+
+void file_remove_atexit( const char * path )
+{
+ files_to_remove = list_new( files_to_remove, newstr((char*)path) );
+}
diff --git a/tools/build/v2/engine/filesys.h b/tools/build/v2/engine/filesys.h
new file mode 100644
index 0000000000..efc081d120
--- /dev/null
+++ b/tools/build/v2/engine/filesys.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * filesys.h - OS specific file routines
+ */
+
+#ifndef FILESYS_DWA20011025_H
+# define FILESYS_DWA20011025_H
+
+# include "pathsys.h"
+#include "hash.h"
+#include "lists.h"
+
+typedef void (*scanback)( void *closure, char *file, int found, time_t t );
+
+void file_dirscan( char *dir, scanback func, void *closure );
+void file_archscan( char *arch, scanback func, void *closure );
+
+int file_time( char *filename, time_t *time );
+
+void file_build1(PATHNAME *f, string* file) ;
+int file_is_file(char* filename);
+int file_mkdir(char *pathname);
+
+typedef struct file_info_t file_info_t ;
+struct file_info_t
+{
+ char * name;
+ short is_file;
+ short is_dir;
+ unsigned long size;
+ time_t time;
+ LIST * files;
+};
+
+
+/* Creates a pointer to information about file 'filename', creating it as
+ * necessary. If created, the structure will be default initialized.
+ */
+file_info_t * file_info( char * filename );
+
+/* Returns information about a file, queries the OS if needed. */
+file_info_t * file_query( char * filename );
+
+void file_done();
+
+/* Marks a path/file to be removed when jam exits. */
+void file_remove_atexit( const char * path );
+
+#endif
diff --git a/tools/build/v2/engine/fileunix.c b/tools/build/v2/engine/fileunix.c
new file mode 100644
index 0000000000..680c3f5394
--- /dev/null
+++ b/tools/build/v2/engine/fileunix.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Copyright 2005 Rene Rivera.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "filesys.h"
+# include "strings.h"
+# include "pathsys.h"
+# include "newstr.h"
+# include <stdio.h>
+# include <sys/stat.h>
+
+#if defined(sun) || defined(__sun) || defined(linux)
+# include <unistd.h> /* needed for read and close prototype */
+#endif
+
+# ifdef USE_FILEUNIX
+
+#if defined(sun) || defined(__sun)
+# include <unistd.h> /* needed for read and close prototype */
+#endif
+
+# if defined( OS_SEQUENT ) || \
+ defined( OS_DGUX ) || \
+ defined( OS_SCO ) || \
+ defined( OS_ISC )
+# define PORTAR 1
+# endif
+
+# ifdef __EMX__
+# include <sys/types.h>
+# include <sys/stat.h>
+# endif
+
+# if defined( OS_RHAPSODY ) || \
+ defined( OS_MACOSX ) || \
+ defined( OS_NEXT )
+/* need unistd for rhapsody's proper lseek */
+# include <sys/dir.h>
+# include <unistd.h>
+# define STRUCT_DIRENT struct direct
+# else
+# include <dirent.h>
+# define STRUCT_DIRENT struct dirent
+# endif
+
+# ifdef OS_COHERENT
+# include <arcoff.h>
+# define HAVE_AR
+# endif
+
+# if defined( OS_MVS ) || \
+ defined( OS_INTERIX )
+
+#define ARMAG "!<arch>\n"
+#define SARMAG 8
+#define ARFMAG "`\n"
+
+struct ar_hdr /* archive file member header - printable ascii */
+{
+ char ar_name[16]; /* file member name - `/' terminated */
+ char ar_date[12]; /* file member date - decimal */
+ char ar_uid[6]; /* file member user id - decimal */
+ char ar_gid[6]; /* file member group id - decimal */
+ char ar_mode[8]; /* file member mode - octal */
+ char ar_size[10]; /* file member size - decimal */
+ char ar_fmag[2]; /* ARFMAG - string to end header */
+};
+
+# define HAVE_AR
+# endif
+
+# if defined( OS_QNX ) || \
+ defined( OS_BEOS ) || \
+ defined( OS_MPEIX )
+# define NO_AR
+# define HAVE_AR
+# endif
+
+# ifndef HAVE_AR
+
+# ifdef OS_AIX
+/* Define those for AIX to get the definitions for both the small and the
+ * big variant of the archive file format. */
+# define __AR_SMALL__
+# define __AR_BIG__
+# endif
+
+# include <ar.h>
+# endif
+
+/*
+ * fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS
+ *
+ * External routines:
+ *
+ * file_dirscan() - scan a directory for files
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_archscan() - scan an archive for files
+ *
+ * File_dirscan() and file_archscan() call back a caller provided function
+ * for each file found. A flag to this callback function lets file_dirscan()
+ * and file_archscan() indicate that a timestamp is being provided with the
+ * file. If file_dirscan() or file_archscan() do not provide the file's
+ * timestamp, interested parties may later call file_time().
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 12/19/94 (mikem) - solaris string table insanity support
+ * 02/14/95 (seiwald) - parse and build /xxx properly
+ * 05/03/96 (seiwald) - split into pathunix.c
+ * 11/21/96 (peterk) - BEOS does not have Unix-style archives
+ */
+
+
+/*
+ * file_dirscan() - scan a directory for files.
+ */
+
+void file_dirscan( char * dir, scanback func, void * closure )
+{
+ PROFILE_ENTER( FILE_DIRSCAN );
+
+ file_info_t * d = 0;
+
+ d = file_query( dir );
+
+ if ( !d || !d->is_dir )
+ {
+ PROFILE_EXIT( FILE_DIRSCAN );
+ return;
+ }
+
+ if ( ! d->files )
+ {
+ LIST* files = L0;
+ PATHNAME f;
+ DIR *dd;
+ STRUCT_DIRENT *dirent;
+ string filename[1];
+
+ /* First enter directory itself */
+
+ memset( (char *)&f, '\0', sizeof( f ) );
+
+ f.f_dir.ptr = dir;
+ f.f_dir.len = strlen(dir);
+
+ dir = *dir ? dir : ".";
+
+ /* Now enter contents of directory. */
+
+ if ( !( dd = opendir( dir ) ) )
+ {
+ PROFILE_EXIT( FILE_DIRSCAN );
+ return;
+ }
+
+ if ( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", dir );
+
+ string_new( filename );
+ while ( ( dirent = readdir( dd ) ) )
+ {
+ # ifdef old_sinix
+ /* Broken structure definition on sinix. */
+ f.f_base.ptr = dirent->d_name - 2;
+ # else
+ f.f_base.ptr = dirent->d_name;
+ # endif
+ f.f_base.len = strlen( f.f_base.ptr );
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename, 0 );
+
+ files = list_new( files, newstr(filename->value) );
+ file_query( filename->value );
+ }
+ string_free( filename );
+
+ closedir( dd );
+
+ d->files = files;
+ }
+
+ /* Special case / : enter it */
+ {
+ unsigned long len = strlen(d->name);
+ if ( ( len == 1 ) && ( d->name[0] == '/' ) )
+ (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
+ }
+
+ /* Now enter contents of directory */
+ if ( d->files )
+ {
+ LIST * files = d->files;
+ while ( files )
+ {
+ file_info_t * ff = file_info( files->string );
+ (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
+ files = list_next( files );
+ }
+ }
+
+ PROFILE_EXIT( FILE_DIRSCAN );
+}
+
+
+file_info_t * file_query( char * filename )
+{
+ file_info_t * ff = file_info( filename );
+ if ( ! ff->time )
+ {
+ struct stat statbuf;
+
+ if ( stat( *filename ? filename : ".", &statbuf ) < 0 )
+ return 0;
+
+ ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
+ ff->is_dir = statbuf.st_mode & S_IFDIR ? 1 : 0;
+ ff->size = statbuf.st_size;
+ ff->time = statbuf.st_mtime ? statbuf.st_mtime : 1;
+ }
+ return ff;
+}
+
+/*
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ */
+
+int
+file_time(
+ char *filename,
+ time_t *time )
+{
+ file_info_t * ff = file_query( filename );
+ if ( !ff ) return -1;
+ *time = ff->time;
+ return 0;
+}
+
+int file_is_file(char* filename)
+{
+ file_info_t * ff = file_query( filename );
+ if ( !ff ) return -1;
+ return ff->is_file;
+}
+
+int file_mkdir(char* pathname)
+{
+ return mkdir(pathname, 0766);
+}
+
+/*
+ * file_archscan() - scan an archive for files
+ */
+
+# ifndef AIAMAG /* God-fearing UNIX */
+
+# define SARFMAG 2
+# define SARHDR sizeof( struct ar_hdr )
+
+void
+file_archscan(
+ char *archive,
+ scanback func,
+ void *closure )
+{
+# ifndef NO_AR
+ struct ar_hdr ar_hdr;
+ char buf[ MAXJPATH ];
+ long offset;
+ char *string_table = 0;
+ int fd;
+
+ if ( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
+ return;
+
+ if ( read( fd, buf, SARMAG ) != SARMAG ||
+ strncmp( ARMAG, buf, SARMAG ) )
+ {
+ close( fd );
+ return;
+ }
+
+ offset = SARMAG;
+
+ if ( DEBUG_BINDSCAN )
+ printf( "scan archive %s\n", archive );
+
+ while ( ( read( fd, &ar_hdr, SARHDR ) == SARHDR )
+ && !( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )
+#ifdef ARFZMAG
+ /* OSF also has a compressed format */
+ && memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )
+#endif
+ ) )
+ {
+ char lar_name_[257];
+ char * lar_name = lar_name_ + 1;
+ long lar_date;
+ long lar_size;
+ long lar_offset;
+ char * c;
+ char * src;
+ char * dest;
+
+ strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
+
+ sscanf( ar_hdr.ar_date, "%ld", &lar_date );
+ sscanf( ar_hdr.ar_size, "%ld", &lar_size );
+
+ if (ar_hdr.ar_name[0] == '/')
+ {
+ if (ar_hdr.ar_name[1] == '/')
+ {
+ /* this is the "string table" entry of the symbol table,
+ ** which holds strings of filenames that are longer than
+ ** 15 characters (ie. don't fit into a ar_name
+ */
+
+ string_table = (char *)BJAM_MALLOC_ATOMIC(lar_size);
+ lseek(fd, offset + SARHDR, 0);
+ if (read(fd, string_table, lar_size) != lar_size)
+ printf("error reading string table\n");
+ }
+ else if (string_table && ar_hdr.ar_name[1] != ' ')
+ {
+ /* Long filenames are recognized by "/nnnn" where nnnn is
+ ** the offset of the string in the string table represented
+ ** in ASCII decimals.
+ */
+ dest = lar_name;
+ lar_offset = atoi(lar_name + 1);
+ src = &string_table[lar_offset];
+ while (*src != '/')
+ *dest++ = *src++;
+ *dest = '/';
+ }
+ }
+
+ c = lar_name - 1;
+ while ( ( *++c != ' ' ) && ( *c != '/' ) ) ;
+ *c = '\0';
+
+ if ( DEBUG_BINDSCAN )
+ printf( "archive name %s found\n", lar_name );
+
+ sprintf( buf, "%s(%s)", archive, lar_name );
+
+ (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+
+ offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
+ lseek( fd, offset, 0 );
+ }
+
+ if (string_table)
+ BJAM_FREE(string_table);
+
+ close( fd );
+
+# endif /* NO_AR */
+
+}
+
+# else /* AIAMAG - RS6000 AIX */
+
+static void file_archscan_small(
+ int fd, char const *archive, scanback func, void *closure)
+{
+ struct fl_hdr fl_hdr;
+
+ struct {
+ struct ar_hdr hdr;
+ char pad[ 256 ];
+ } ar_hdr ;
+
+ char buf[ MAXJPATH ];
+ long offset;
+
+ if ( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ)
+ return;
+
+ sscanf( fl_hdr.fl_fstmoff, "%ld", &offset );
+
+ if ( DEBUG_BINDSCAN )
+ printf( "scan archive %s\n", archive );
+
+ while ( ( offset > 0 )
+ && ( lseek( fd, offset, 0 ) >= 0 )
+ && ( read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) ) )
+ {
+ long lar_date;
+ int lar_namlen;
+
+ sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
+ sscanf( ar_hdr.hdr.ar_date , "%ld", &lar_date );
+ sscanf( ar_hdr.hdr.ar_nxtmem, "%ld", &offset );
+
+ if ( !lar_namlen )
+ continue;
+
+ ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
+
+ sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
+
+ (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ }
+}
+
+/* Check for OS version which supports the big variant. */
+#ifdef AR_HSZ_BIG
+
+static void file_archscan_big(
+ int fd, char const *archive, scanback func, void *closure)
+{
+ struct fl_hdr_big fl_hdr;
+
+ struct {
+ struct ar_hdr_big hdr;
+ char pad[ 256 ];
+ } ar_hdr ;
+
+ char buf[ MAXJPATH ];
+ long long offset;
+
+ if ( read( fd, (char *)&fl_hdr, FL_HSZ_BIG) != FL_HSZ_BIG)
+ return;
+
+ sscanf( fl_hdr.fl_fstmoff, "%lld", &offset );
+
+ if ( DEBUG_BINDSCAN )
+ printf( "scan archive %s\n", archive );
+
+ while ( ( offset > 0 )
+ && ( lseek( fd, offset, 0 ) >= 0 )
+ && ( read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) ) )
+ {
+ long lar_date;
+ int lar_namlen;
+
+ sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
+ sscanf( ar_hdr.hdr.ar_date , "%ld" , &lar_date );
+ sscanf( ar_hdr.hdr.ar_nxtmem, "%lld", &offset );
+
+ if ( !lar_namlen )
+ continue;
+
+ ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
+
+ sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
+
+ (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ }
+
+}
+
+#endif /* AR_HSZ_BIG */
+
+void file_archscan(char *archive, scanback func, void *closure)
+{
+ int fd;
+ char fl_magic[SAIAMAG];
+
+ if (( fd = open(archive, O_RDONLY, 0)) < 0)
+ return;
+
+ if (read( fd, fl_magic, SAIAMAG) != SAIAMAG
+ || lseek(fd, 0, SEEK_SET) == -1)
+ {
+ close(fd);
+ return;
+ }
+
+ if (strncmp(AIAMAG, fl_magic, SAIAMAG) == 0)
+ {
+ /* read small variant */
+ file_archscan_small(fd, archive, func, closure);
+ }
+#ifdef AR_HSZ_BIG
+ else if (strncmp(AIAMAGBIG, fl_magic, SAIAMAG) == 0)
+ {
+ /* read big variant */
+ file_archscan_big(fd, archive, func, closure);
+ }
+#endif
+
+ close( fd );
+}
+
+# endif /* AIAMAG - RS6000 AIX */
+
+# endif /* USE_FILEUNIX */
diff --git a/tools/build/v2/engine/filevms.c b/tools/build/v2/engine/filevms.c
new file mode 100644
index 0000000000..d2ab2047f0
--- /dev/null
+++ b/tools/build/v2/engine/filevms.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "filesys.h"
+# include "pathsys.h"
+
+# ifdef OS_VMS
+
+/*
+ * filevms.c - scan directories and libaries on VMS
+ *
+ * External routines:
+ *
+ * file_dirscan() - scan a directory for files
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_archscan() - scan an archive for files
+ *
+ * File_dirscan() and file_archscan() call back a caller provided function
+ * for each file found. A flag to this callback function lets file_dirscan()
+ * and file_archscan() indicate that a timestamp is being provided with the
+ * file. If file_dirscan() or file_archscan() do not provide the file's
+ * timestamp, interested parties may later call file_time().
+ *
+ * 02/09/95 (seiwald) - bungled R=[xxx] - was using directory length!
+ * 05/03/96 (seiwald) - split into pathvms.c
+ */
+
+# include <rms.h>
+# include <iodef.h>
+# include <ssdef.h>
+# include <string.h>
+# include <stdlib.h>
+# include <stdio.h>
+# include <descrip.h>
+
+#include <lbrdef.h>
+#include <credef.h>
+#include <mhddef.h>
+#include <lhidef.h>
+#include <lib$routines.h>
+#include <starlet.h>
+
+/* Supply missing prototypes for lbr$-routines*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int lbr$set_module(
+ void **,
+ unsigned long *,
+ struct dsc$descriptor_s *,
+ unsigned short *,
+ void * );
+
+int lbr$open( void **,
+ struct dsc$descriptor_s *,
+ void *,
+ void *,
+ void *,
+ void *,
+ void * );
+
+int lbr$ini_control(
+ void **,
+ unsigned long *,
+ unsigned long *,
+ void * );
+
+int lbr$get_index(
+ void **,
+ unsigned long *,
+ int (*func)( struct dsc$descriptor_s *, unsigned long *),
+ void * );
+
+int lbr$close(
+ void ** );
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+static void
+file_cvttime(
+ unsigned int *curtime,
+ time_t *unixtime )
+{
+ static const size_t divisor = 10000000;
+ static unsigned int bastim[2] = { 0x4BEB4000, 0x007C9567 }; /* 1/1/1970 */
+ int delta[2], remainder;
+
+ lib$subx( curtime, bastim, delta );
+ lib$ediv( &divisor, delta, unixtime, &remainder );
+}
+
+# define DEFAULT_FILE_SPECIFICATION "[]*.*;0"
+
+# define min( a,b ) ((a)<(b)?(a):(b))
+
+void
+file_dirscan(
+ char *dir,
+ scanback func,
+ void *closure )
+{
+
+ struct FAB xfab;
+ struct NAM xnam;
+ struct XABDAT xab;
+ char esa[256];
+ char filename[256];
+ string filename2[1];
+ char dirname[256];
+ register int status;
+ PATHNAME f;
+
+ memset( (char *)&f, '\0', sizeof( f ) );
+
+ f.f_root.ptr = dir;
+ f.f_root.len = strlen( dir );
+
+ /* get the input file specification
+ */
+ xnam = cc$rms_nam;
+ xnam.nam$l_esa = esa;
+ xnam.nam$b_ess = sizeof( esa ) - 1;
+ xnam.nam$l_rsa = filename;
+ xnam.nam$b_rss = min( sizeof( filename ) - 1, NAM$C_MAXRSS );
+
+ xab = cc$rms_xabdat; /* initialize extended attributes */
+ xab.xab$b_cod = XAB$C_DAT; /* ask for date */
+ xab.xab$l_nxt = NULL; /* terminate XAB chain */
+
+ xfab = cc$rms_fab;
+ xfab.fab$l_dna = DEFAULT_FILE_SPECIFICATION;
+ xfab.fab$b_dns = sizeof( DEFAULT_FILE_SPECIFICATION ) - 1;
+ xfab.fab$l_fop = FAB$M_NAM;
+ xfab.fab$l_fna = dir; /* address of file name */
+ xfab.fab$b_fns = strlen( dir ); /* length of file name */
+ xfab.fab$l_nam = &xnam; /* address of NAB block */
+ xfab.fab$l_xab = (char *)&xab; /* address of XAB block */
+
+
+ status = sys$parse( &xfab );
+
+ if ( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", dir );
+
+ if ( !( status & 1 ) )
+ return;
+
+
+
+ /* Add bogus directory for [000000] */
+
+ if ( !strcmp( dir, "[000000]" ) )
+ {
+ (*func)( closure, "[000000]", 1 /* time valid */, 1 /* old but true */ );
+ }
+
+ /* Add bogus directory for [] */
+
+ if ( !strcmp( dir, "[]" ) )
+ {
+ (*func)( closure, "[]", 1 /* time valid */, 1 /* old but true */ );
+ (*func)( closure, "[-]", 1 /* time valid */, 1 /* old but true */ );
+ }
+
+ string_new( filename2 );
+ while ( (status = sys$search( &xfab )) & 1 )
+ {
+ char *s;
+ time_t time;
+
+ /* "I think that might work" - eml */
+
+ sys$open( &xfab );
+ sys$close( &xfab );
+
+ file_cvttime( (unsigned int *)&xab.xab$q_rdt, &time );
+
+ filename[xnam.nam$b_rsl] = '\0';
+
+ /* What we do with the name depends on the suffix: */
+ /* .dir is a directory */
+ /* .xxx is a file with a suffix */
+ /* . is no suffix at all */
+
+ if ( xnam.nam$b_type == 4 && !strncmp( xnam.nam$l_type, ".DIR", 4 ) )
+ {
+ /* directory */
+ sprintf( dirname, "[.%.*s]", xnam.nam$b_name, xnam.nam$l_name );
+ f.f_dir.ptr = dirname;
+ f.f_dir.len = strlen( dirname );
+ f.f_base.ptr = 0;
+ f.f_base.len = 0;
+ f.f_suffix.ptr = 0;
+ f.f_suffix.len = 0;
+ }
+ else
+ {
+ /* normal file with a suffix */
+ f.f_dir.ptr = 0;
+ f.f_dir.len = 0;
+ f.f_base.ptr = xnam.nam$l_name;
+ f.f_base.len = xnam.nam$b_name;
+ f.f_suffix.ptr = xnam.nam$l_type;
+ f.f_suffix.len = xnam.nam$b_type;
+ }
+
+ string_truncate( filename2, 0 );
+ path_build( &f, filename2, 0 );
+
+ /*
+ if ( DEBUG_SEARCH )
+ printf("root '%s' base %.*s suf %.*s = %s\n",
+ dir,
+ xnam.nam$b_name, xnam.nam$l_name,
+ xnam.nam$b_type, xnam.nam$l_type,
+ filename2 );
+ */
+
+ (*func)( closure, filename2->value, 1 /* time valid */, time );
+ }
+ string_free( filename2 );
+}
+
+int
+file_time(
+ char *filename,
+ time_t *time )
+{
+ /* This should never be called, as all files are */
+ /* timestampped in file_dirscan() and file_archscan() */
+ return -1;
+}
+
+static char *VMS_archive = 0;
+static scanback VMS_func;
+static void *VMS_closure;
+static void *context;
+
+static int
+file_archmember(
+ struct dsc$descriptor_s *module,
+ unsigned long *rfa )
+{
+ static struct dsc$descriptor_s bufdsc =
+ {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
+
+ struct mhddef *mhd;
+ char filename[128];
+ char buf[ MAXJPATH ];
+
+ int status;
+ time_t library_date;
+
+ register int i;
+ register char *p;
+
+ bufdsc.dsc$a_pointer = filename;
+ bufdsc.dsc$w_length = sizeof( filename );
+ status = lbr$set_module( &context, rfa, &bufdsc,
+ &bufdsc.dsc$w_length, NULL );
+
+ if ( !(status & 1) )
+ return ( 1 );
+
+ mhd = (struct mhddef *)filename;
+
+ file_cvttime( &mhd->mhd$l_datim, &library_date );
+
+ for ( i = 0, p = module->dsc$a_pointer; i < module->dsc$w_length; ++i, ++p )
+ filename[ i ] = *p;
+
+ filename[ i ] = '\0';
+
+ sprintf( buf, "%s(%s.obj)", VMS_archive, filename );
+
+ (*VMS_func)( VMS_closure, buf, 1 /* time valid */, (time_t)library_date );
+
+ return ( 1 );
+}
+
+
+void file_archscan( char * archive, scanback func, void * closure )
+{
+ static struct dsc$descriptor_s library =
+ {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
+
+ unsigned long lfunc = LBR$C_READ;
+ unsigned long typ = LBR$C_TYP_UNK;
+ unsigned long index = 1;
+
+ register int status;
+
+ VMS_archive = archive;
+ VMS_func = func;
+ VMS_closure = closure;
+
+ status = lbr$ini_control( &context, &lfunc, &typ, NULL );
+ if ( !( status & 1 ) )
+ return;
+
+ library.dsc$a_pointer = archive;
+ library.dsc$w_length = strlen( archive );
+
+ status = lbr$open( &context, &library, NULL, NULL, NULL, NULL, NULL );
+ if ( !( status & 1 ) )
+ return;
+
+ (void) lbr$get_index( &context, &index, file_archmember, NULL );
+
+ (void) lbr$close( &context );
+}
+
+# endif /* VMS */
diff --git a/tools/build/v2/engine/frames.c b/tools/build/v2/engine/frames.c
new file mode 100644
index 0000000000..84889f09e7
--- /dev/null
+++ b/tools/build/v2/engine/frames.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "frames.h"
+# include "lists.h"
+
+void frame_init( FRAME* frame )
+{
+ frame->prev = 0;
+ lol_init(frame->args);
+ frame->module = root_module();
+ frame->rulename = "module scope";
+ frame->procedure = 0;
+}
+
+void frame_free( FRAME* frame )
+{
+ lol_free( frame->args );
+}
diff --git a/tools/build/v2/engine/frames.h b/tools/build/v2/engine/frames.h
new file mode 100644
index 0000000000..693d77fa0a
--- /dev/null
+++ b/tools/build/v2/engine/frames.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef FRAMES_DWA20011021_H
+#define FRAMES_DWA20011021_H
+
+#include "lists.h"
+#include "modules.h"
+
+typedef struct _PARSE PARSE;
+typedef struct frame FRAME;
+
+struct frame
+{
+ FRAME * prev;
+ /* The nearest enclosing frame for which module->user_module is true. */
+ FRAME * prev_user;
+ LOL args[ 1 ];
+ module_t * module;
+ PARSE * procedure;
+ char * rulename;
+};
+
+
+/* When call into Python is in progress, this variable points to the bjam frame
+ * that was current at the moment of call. When the call completes, the variable
+ * is not defined. Further, if Jam calls Python which calls Jam and so on, this
+ * variable only keeps the most recent Jam frame.
+ */
+extern struct frame * frame_before_python_call;
+
+void frame_init( FRAME * ); /* implemented in compile.c */
+void frame_free( FRAME * ); /* implemented in compile.c */
+
+#endif
diff --git a/tools/build/v2/engine/glob.c b/tools/build/v2/engine/glob.c
new file mode 100644
index 0000000000..527d6c8088
--- /dev/null
+++ b/tools/build/v2/engine/glob.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright 1994 Christopher Seiwald. All rights reserved.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * glob.c - match a string against a simple pattern
+ *
+ * Understands the following patterns:
+ *
+ * * any number of characters
+ * ? any single character
+ * [a-z] any single character in the range a-z
+ * [^a-z] any single character not in the range a-z
+ * \x match x
+ *
+ * External functions:
+ *
+ * glob() - match a string against a simple pattern
+ *
+ * Internal functions:
+ *
+ * globchars() - build a bitlist to check for character group match
+ */
+
+# include "jam.h"
+
+# define CHECK_BIT( tab, bit ) ( tab[ (bit)/8 ] & (1<<( (bit)%8 )) )
+# define BITLISTSIZE 16 /* bytes used for [chars] in compiled expr */
+
+static void globchars( char * s, char * e, char * b );
+
+
+/*
+ * glob() - match a string against a simple pattern.
+ */
+
+int glob( char * c, char * s )
+{
+ char bitlist[ BITLISTSIZE ];
+ char * here;
+
+ for ( ; ; )
+ switch ( *c++ )
+ {
+ case '\0':
+ return *s ? -1 : 0;
+
+ case '?':
+ if ( !*s++ )
+ return 1;
+ break;
+
+ case '[':
+ /* Scan for matching ]. */
+
+ here = c;
+ do if ( !*c++ ) return 1;
+ while ( ( here == c ) || ( *c != ']' ) );
+ ++c;
+
+ /* Build character class bitlist. */
+
+ globchars( here, c, bitlist );
+
+ if ( !CHECK_BIT( bitlist, *(unsigned char *)s ) )
+ return 1;
+ ++s;
+ break;
+
+ case '*':
+ here = s;
+
+ while ( *s )
+ ++s;
+
+ /* Try to match the rest of the pattern in a recursive */
+ /* call. If the match fails we'll back up chars, retrying. */
+
+ while ( s != here )
+ {
+ int r;
+
+ /* A fast path for the last token in a pattern. */
+ r = *c ? glob( c, s ) : *s ? -1 : 0;
+
+ if ( !r )
+ return 0;
+ if ( r < 0 )
+ return 1;
+ --s;
+ }
+ break;
+
+ case '\\':
+ /* Force literal match of next char. */
+ if ( !*c || ( *s++ != *c++ ) )
+ return 1;
+ break;
+
+ default:
+ if ( *s++ != c[ -1 ] )
+ return 1;
+ break;
+ }
+}
+
+
+/*
+ * globchars() - build a bitlist to check for character group match.
+ */
+
+static void globchars( char * s, char * e, char * b )
+{
+ int neg = 0;
+
+ memset( b, '\0', BITLISTSIZE );
+
+ if ( *s == '^' )
+ {
+ ++neg;
+ ++s;
+ }
+
+ while ( s < e )
+ {
+ int c;
+
+ if ( ( s + 2 < e ) && ( s[1] == '-' ) )
+ {
+ for ( c = s[0]; c <= s[2]; ++c )
+ b[ c/8 ] |= ( 1 << ( c % 8 ) );
+ s += 3;
+ }
+ else
+ {
+ c = *s++;
+ b[ c/8 ] |= ( 1 << ( c % 8 ) );
+ }
+ }
+
+ if ( neg )
+ {
+ int i;
+ for ( i = 0; i < BITLISTSIZE; ++i )
+ b[ i ] ^= 0377;
+ }
+
+ /* Do not include \0 in either $[chars] or $[^chars]. */
+ b[0] &= 0376;
+}
diff --git a/tools/build/v2/engine/hash.c b/tools/build/v2/engine/hash.c
new file mode 100644
index 0000000000..fbd1a8993d
--- /dev/null
+++ b/tools/build/v2/engine/hash.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "hash.h"
+# include "compile.h"
+# include <assert.h>
+
+/*
+ * hash.c - simple in-memory hashing routines
+ *
+ * External routines:
+ *
+ * hashinit() - initialize a hash table, returning a handle
+ * hashitem() - find a record in the table, and optionally enter a new one
+ * hashdone() - free a hash table, given its handle
+ *
+ * Internal routines:
+ *
+ * hashrehash() - resize and rebuild hp->tab, the hash table
+ *
+ * 4/29/93 - ensure ITEM's are aligned
+ */
+
+/* */
+#define HASH_DEBUG_PROFILE 1
+/* */
+
+char *hashsccssid="@(#)hash.c 1.14 () 6/20/88";
+
+/* Header attached to all data items entered into a hash table. */
+
+struct hashhdr
+{
+ struct item * next;
+ unsigned int keyval; /* for quick comparisons */
+};
+
+/* This structure overlays the one handed to hashenter(). Its actual size is
+ * given to hashinit().
+ */
+
+struct hashdata
+{
+ char * key;
+ /* rest of user data */
+};
+
+typedef struct item
+{
+ struct hashhdr hdr;
+ struct hashdata data;
+} ITEM ;
+
+# define MAX_LISTS 32
+
+struct hash
+{
+ /*
+ * the hash table, just an array of item pointers
+ */
+ struct {
+ int nel;
+ ITEM **base;
+ } tab;
+
+ int bloat; /* tab.nel / items.nel */
+ int inel; /* initial number of elements */
+
+ /*
+ * the array of records, maintained by these routines
+ * essentially a microallocator
+ */
+ struct {
+ int more; /* how many more ITEMs fit in lists[ list ] */
+ ITEM *free; /* free list of items */
+ char *next; /* where to put more ITEMs in lists[ list ] */
+ int datalen; /* length of records in this hash table */
+ int size; /* sizeof( ITEM ) + aligned datalen */
+ int nel; /* total ITEMs held by all lists[] */
+ int list; /* index into lists[] */
+
+ struct {
+ int nel; /* total ITEMs held by this list */
+ char *base; /* base of ITEMs array */
+ } lists[ MAX_LISTS ];
+ } items;
+
+ char * name; /* just for hashstats() */
+};
+
+static void hashrehash( struct hash *hp );
+static void hashstat( struct hash *hp );
+static void * hash_mem_alloc(size_t datalen, size_t size);
+static void hash_mem_free(size_t datalen, void * data);
+#ifdef OPT_BOEHM_GC
+static void hash_mem_finalizer(char * key, struct hash * hp);
+#endif
+
+static unsigned int jenkins_one_at_a_time_hash(const unsigned char *key)
+{
+ unsigned int hash = 0;
+
+ while ( *key )
+ {
+ hash += *key++;
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+
+ return hash;
+}
+
+/*
+static unsigned int knuth_hash(const unsigned char *key)
+{
+ unsigned int keyval = *key;
+ while ( *key )
+ keyval = keyval * 2147059363 + *key++;
+ return keyval;
+}
+*/
+
+static unsigned int hash_keyval( const char * key_ )
+{
+ /*
+ return knuth_hash((const unsigned char *)key_);
+ */
+ return jenkins_one_at_a_time_hash((const unsigned char *)key_);
+}
+
+#define hash_bucket(hp,keyval) ((hp)->tab.base + ( (keyval) % (hp)->tab.nel ))
+
+/* Find the hash item for the given data. Returns pointer to the
+ item and if given a pointer to the item before the found item.
+ If it's the first item in a bucket, there is no previous item,
+ and zero is returned for the previous item instead.
+*/
+static ITEM * hash_search(
+ struct hash *hp,
+ unsigned int keyval,
+ const char * keydata,
+ ITEM * * previous )
+{
+ ITEM * i = *hash_bucket(hp,keyval);
+ ITEM * p = 0;
+
+ for ( ; i; i = i->hdr.next )
+ {
+ if ( ( keyval == i->hdr.keyval ) &&
+ !strcmp( i->data.key, keydata ) )
+ {
+ if (previous)
+ {
+ *previous = p;
+ }
+ return i;
+ }
+ p = i;
+ }
+
+ return 0;
+}
+
+/*
+ * hash_free() - remove the given item from the table if it's there.
+ * Returns 1 if found, 0 otherwise.
+ *
+ * NOTE: 2nd argument is HASHDATA*, not HASHDATA** as elsewhere.
+ */
+int
+hash_free(
+ register struct hash *hp,
+ HASHDATA *data)
+{
+ ITEM * i = 0;
+ ITEM * prev = 0;
+ unsigned int keyval = hash_keyval(data->key);
+
+ i = hash_search( hp, keyval, data->key, &prev );
+ if (i)
+ {
+ /* mark it free so we skip it during enumeration */
+ i->data.key = 0;
+ /* unlink the record from the hash chain */
+ if (prev) prev->hdr.next = i->hdr.next;
+ else *hash_bucket(hp,keyval) = i->hdr.next;
+ /* link it into the freelist */
+ i->hdr.next = hp->items.free;
+ hp->items.free = i;
+ /* we have another item */
+ hp->items.more++;
+
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * hashitem() - find a record in the table, and optionally enter a new one
+ */
+
+int
+hashitem(
+ register struct hash *hp,
+ HASHDATA **data,
+ int enter )
+{
+ register ITEM *i;
+ char *b = (*data)->key;
+ unsigned int keyval = hash_keyval(b);
+
+ #ifdef HASH_DEBUG_PROFILE
+ profile_frame prof[1];
+ if ( DEBUG_PROFILE )
+ profile_enter( 0, prof );
+ #endif
+
+ if ( enter && !hp->items.more )
+ hashrehash( hp );
+
+ if ( !enter && !hp->items.nel )
+ {
+ #ifdef HASH_DEBUG_PROFILE
+ if ( DEBUG_PROFILE )
+ profile_exit( prof );
+ #endif
+ return 0;
+ }
+
+ i = hash_search( hp, keyval, (*data)->key, 0 );
+ if (i)
+ {
+ *data = &i->data;
+ #ifdef HASH_DEBUG_PROFILE
+ if ( DEBUG_PROFILE ) profile_exit( prof );
+ #endif
+ return !0;
+ }
+
+ if ( enter )
+ {
+ ITEM * * base = hash_bucket(hp,keyval);
+
+ /* try to grab one from the free list */
+ if ( hp->items.free )
+ {
+ i = hp->items.free;
+ hp->items.free = i->hdr.next;
+ assert( i->data.key == 0 );
+ }
+ else
+ {
+ i = (ITEM *)hp->items.next;
+ hp->items.next += hp->items.size;
+ }
+ hp->items.more--;
+ memcpy( (char *)&i->data, (char *)*data, hp->items.datalen );
+ i->hdr.keyval = keyval;
+ i->hdr.next = *base;
+ *base = i;
+ *data = &i->data;
+ #ifdef OPT_BOEHM_GC
+ if (sizeof(HASHDATA) == hp->items.datalen)
+ {
+ GC_REGISTER_FINALIZER(i->data.key,&hash_mem_finalizer,hp,0,0);
+ }
+ #endif
+ }
+
+ #ifdef HASH_DEBUG_PROFILE
+ if ( DEBUG_PROFILE )
+ profile_exit( prof );
+ #endif
+ return 0;
+}
+
+/*
+ * hashrehash() - resize and rebuild hp->tab, the hash table
+ */
+
+static void hashrehash( register struct hash *hp )
+{
+ int i = ++hp->items.list;
+ hp->items.more = i ? 2 * hp->items.nel : hp->inel;
+ hp->items.next = (char *)hash_mem_alloc( hp->items.datalen, hp->items.more * hp->items.size );
+ hp->items.free = 0;
+
+ hp->items.lists[i].nel = hp->items.more;
+ hp->items.lists[i].base = hp->items.next;
+ hp->items.nel += hp->items.more;
+
+ if ( hp->tab.base )
+ hash_mem_free( hp->items.datalen, (char *)hp->tab.base );
+
+ hp->tab.nel = hp->items.nel * hp->bloat;
+ hp->tab.base = (ITEM **)hash_mem_alloc( hp->items.datalen, hp->tab.nel * sizeof(ITEM **) );
+
+ memset( (char *)hp->tab.base, '\0', hp->tab.nel * sizeof( ITEM * ) );
+
+ for ( i = 0; i < hp->items.list; ++i )
+ {
+ int nel = hp->items.lists[i].nel;
+ char *next = hp->items.lists[i].base;
+
+ for ( ; nel--; next += hp->items.size )
+ {
+ register ITEM *i = (ITEM *)next;
+ ITEM **ip = hp->tab.base + i->hdr.keyval % hp->tab.nel;
+ /* code currently assumes rehashing only when there are no free items */
+ assert( i->data.key != 0 );
+
+ i->hdr.next = *ip;
+ *ip = i;
+ }
+ }
+}
+
+void hashenumerate( struct hash * hp, void (* f)( void *, void * ), void * data )
+{
+ int i;
+ for ( i = 0; i <= hp->items.list; ++i )
+ {
+ char * next = hp->items.lists[i].base;
+ int nel = hp->items.lists[i].nel;
+ if ( i == hp->items.list )
+ nel -= hp->items.more;
+
+ for ( ; nel--; next += hp->items.size )
+ {
+ ITEM * i = (ITEM *)next;
+ if ( i->data.key != 0 ) /* DO not enumerate freed items. */
+ f( &i->data, data );
+ }
+ }
+}
+
+/* --- */
+
+# define ALIGNED(x) ( ( x + sizeof( ITEM ) - 1 ) & ~( sizeof( ITEM ) - 1 ) )
+
+/*
+ * hashinit() - initialize a hash table, returning a handle
+ */
+
+struct hash *
+hashinit(
+ int datalen,
+ char *name )
+{
+ struct hash *hp = (struct hash *)hash_mem_alloc( datalen, sizeof( *hp ) );
+
+ hp->bloat = 3;
+ hp->tab.nel = 0;
+ hp->tab.base = (ITEM **)0;
+ hp->items.more = 0;
+ hp->items.free = 0;
+ hp->items.datalen = datalen;
+ hp->items.size = sizeof( struct hashhdr ) + ALIGNED( datalen );
+ hp->items.list = -1;
+ hp->items.nel = 0;
+ hp->inel = 11 /* 47 */;
+ hp->name = name;
+
+ return hp;
+}
+
+/*
+ * hashdone() - free a hash table, given its handle
+ */
+
+void
+hashdone( struct hash *hp )
+{
+ int i;
+
+ if ( !hp )
+ return;
+
+ if ( DEBUG_MEM || DEBUG_PROFILE )
+ hashstat( hp );
+
+ if ( hp->tab.base )
+ hash_mem_free( hp->items.datalen, (char *)hp->tab.base );
+ for ( i = 0; i <= hp->items.list; ++i )
+ hash_mem_free( hp->items.datalen, hp->items.lists[i].base );
+ hash_mem_free( hp->items.datalen, (char *)hp );
+}
+
+static void * hash_mem_alloc(size_t datalen, size_t size)
+{
+ if (sizeof(HASHDATA) == datalen)
+ {
+ return BJAM_MALLOC_RAW(size);
+ }
+ else
+ {
+ return BJAM_MALLOC(size);
+ }
+}
+
+static void hash_mem_free(size_t datalen, void * data)
+{
+ if (sizeof(HASHDATA) == datalen)
+ {
+ BJAM_FREE_RAW(data);
+ }
+ else
+ {
+ BJAM_FREE(data);
+ }
+}
+
+#ifdef OPT_BOEHM_GC
+static void hash_mem_finalizer(char * key, struct hash * hp)
+{
+ HASHDATA d;
+ d.key = key;
+ hash_free(hp,&d);
+}
+#endif
+
+
+/* ---- */
+
+static void hashstat( struct hash * hp )
+{
+ ITEM * * tab = hp->tab.base;
+ int nel = hp->tab.nel;
+ int count = 0;
+ int sets = 0;
+ int run = ( tab[ nel - 1 ] != (ITEM *)0 );
+ int i;
+ int here;
+
+ for ( i = nel; i > 0; --i )
+ {
+ if ( ( here = ( *tab++ != (ITEM *)0 ) ) )
+ count++;
+ if ( here && !run )
+ sets++;
+ run = here;
+ }
+
+ printf( "%s table: %d+%d+%d (%dK+%luK) items+table+hash, %f density\n",
+ hp->name,
+ count,
+ hp->items.nel,
+ hp->tab.nel,
+ hp->items.nel * hp->items.size / 1024,
+ (long unsigned)hp->tab.nel * sizeof( ITEM ** ) / 1024,
+ (float)count / (float)sets );
+}
diff --git a/tools/build/v2/engine/hash.h b/tools/build/v2/engine/hash.h
new file mode 100644
index 0000000000..7195b4146f
--- /dev/null
+++ b/tools/build/v2/engine/hash.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * hash.h - simple in-memory hashing routines
+ */
+
+#ifndef BOOST_JAM_HASH_H
+#define BOOST_JAM_HASH_H
+
+typedef struct hashdata HASHDATA;
+
+struct hash * hashinit ( int datalen, char * name );
+int hashitem ( struct hash * hp, HASHDATA * * data, int enter );
+void hashdone ( struct hash * hp );
+void hashenumerate( struct hash * hp, void (* f)( void *, void * ), void * data );
+int hash_free ( struct hash * hp, HASHDATA * data);
+
+#define hashenter( hp, data ) ( !hashitem( hp, data, !0 ) )
+#define hashcheck( hp, data ) hashitem( hp, data, 0 )
+
+#endif
diff --git a/tools/build/v2/engine/hcache.c b/tools/build/v2/engine/hcache.c
new file mode 100644
index 0000000000..70bb798cc9
--- /dev/null
+++ b/tools/build/v2/engine/hcache.c
@@ -0,0 +1,434 @@
+/*
+ * This file has been donated to Jam.
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "parse.h"
+# include "rules.h"
+# include "regexp.h"
+# include "headers.h"
+# include "newstr.h"
+# include "hash.h"
+# include "hcache.h"
+# include "variable.h"
+# include "search.h"
+
+#ifdef OPT_HEADER_CACHE_EXT
+
+/*
+ * Craig W. McPheeters, Alias|Wavefront.
+ *
+ * hcache.c hcache.h - handle cacheing of #includes in source files.
+ *
+ * Create a cache of files scanned for headers. When starting jam, look for the
+ * cache file and load it if present. When finished the binding phase, create a
+ * new header cache. The cache contains files, their timestamps and the header
+ * files found in their scan. During the binding phase of jam, look in the
+ * header cache first for the headers contained in a file. If the cache is
+ * present and valid, use its contents. This results in dramatic speedups with
+ * large projects (eg. 3min -> 1min startup for one project.)
+ *
+ * External routines:
+ * hcache_init() - read and parse the local .jamdeps file.
+ * hcache_done() - write a new .jamdeps file.
+ * hcache() - return list of headers on target. Use cache or do a scan.
+ *
+ * The dependency file format is an ASCII file with 1 line per target. Each line
+ * has the following fields:
+ * @boundname@ timestamp @file@ @file@ @file@ ... \n
+ */
+
+typedef struct hcachedata HCACHEDATA ;
+
+struct hcachedata
+{
+ char * boundname;
+ time_t time;
+ LIST * includes;
+ LIST * hdrscan; /* the HDRSCAN value for this target */
+ int age; /* if too old, we'll remove it from cache */
+ HCACHEDATA * next;
+};
+
+
+static struct hash * hcachehash = 0;
+static HCACHEDATA * hcachelist = 0;
+
+static int queries = 0;
+static int hits = 0;
+
+#define CACHE_FILE_VERSION "version 4"
+#define CACHE_RECORD_HEADER "header"
+#define CACHE_RECORD_END "end"
+
+
+/*
+ * Return the name of the header cache file. May return NULL.
+ *
+ * The user sets this by setting the HCACHEFILE variable in a Jamfile. We cache
+ * the result so the user can not change the cache file during header scanning.
+ */
+
+static char * cache_name( void )
+{
+ static char * name = 0;
+ if ( !name )
+ {
+ LIST * hcachevar = var_get( "HCACHEFILE" );
+
+ if ( hcachevar )
+ {
+ TARGET * t = bindtarget( hcachevar->string );
+
+ pushsettings( t->settings );
+ /* Do not expect the cache file to be generated, so pass 0 as the
+ * third argument to search. Expect the location to be specified via
+ * LOCATE, so pass 0 as the fourth arugment.
+ */
+ t->boundname = search( t->name, &t->time, 0, 0 );
+ popsettings( t->settings );
+
+ if ( hcachevar )
+ name = copystr( t->boundname );
+ }
+ }
+ return name;
+}
+
+
+/*
+ * Return the maximum age a cache entry can have before it is purged ftom the
+ * cache.
+ */
+
+static int cache_maxage( void )
+{
+ int age = 100;
+ LIST * var = var_get( "HCACHEMAXAGE" );
+ if ( var )
+ {
+ age = atoi( var->string );
+ if ( age < 0 )
+ age = 0;
+ }
+ return age;
+}
+
+
+/*
+ * Read a netstring. The caveat is that the string can not contain ASCII 0. The
+ * returned value is as returned by newstr(), so it need not be freed.
+ */
+
+char * read_netstring( FILE * f )
+{
+ unsigned long len;
+ static char * buf = NULL;
+ static unsigned long buf_len = 0;
+
+ if ( fscanf( f, " %9lu", &len ) != 1 )
+ return NULL;
+ if ( fgetc( f ) != (int)'\t' )
+ return NULL;
+
+ if ( len > 1024 * 64 )
+ return NULL; /* sanity check */
+
+ if ( len > buf_len )
+ {
+ unsigned long new_len = buf_len * 2;
+ if ( new_len < len )
+ new_len = len;
+ buf = (char *)BJAM_REALLOC( buf, new_len + 1 );
+ if ( buf )
+ buf_len = new_len;
+ }
+
+ if ( !buf )
+ return NULL;
+
+ if ( fread( buf, 1, len, f ) != len )
+ return NULL;
+ if ( fgetc( f ) != (int)'\n' )
+ return NULL;
+
+ buf[ len ] = 0;
+ return newstr( buf );
+}
+
+
+/*
+ * Write a netstring.
+ */
+
+void write_netstring( FILE * f, char const * s )
+{
+ if ( !s )
+ s = "";
+ fprintf( f, "%lu\t%s\n", (long unsigned)strlen( s ), s );
+}
+
+
+void hcache_init()
+{
+ HCACHEDATA cachedata;
+ HCACHEDATA * c;
+ FILE * f;
+ char * version;
+ int header_count = 0;
+ char * hcachename;
+
+ hcachehash = hashinit( sizeof( HCACHEDATA ), "hcache" );
+
+ if ( !( hcachename = cache_name() ) )
+ return;
+
+ if ( !( f = fopen( hcachename, "rb" ) ) )
+ return;
+
+ version = read_netstring( f );
+ if ( !version || strcmp( version, CACHE_FILE_VERSION ) )
+ {
+ fclose( f );
+ return;
+ }
+
+ while ( 1 )
+ {
+ char * record_type;
+ char * time_str;
+ char * age_str;
+ char * includes_count_str;
+ char * hdrscan_count_str;
+ int i;
+ int count;
+ LIST * l;
+
+ record_type = read_netstring( f );
+ if ( !record_type )
+ {
+ fprintf( stderr, "invalid %s\n", hcachename );
+ goto bail;
+ }
+ if ( !strcmp( record_type, CACHE_RECORD_END ) )
+ break;
+ if ( strcmp( record_type, CACHE_RECORD_HEADER ) )
+ {
+ fprintf( stderr, "invalid %s with record separator <%s>\n",
+ hcachename, record_type ? record_type : "<null>" );
+ goto bail;
+ }
+
+ c = &cachedata;
+
+ c->boundname = read_netstring( f );
+ time_str = read_netstring( f );
+ age_str = read_netstring( f );
+ includes_count_str = read_netstring( f );
+
+ if ( !c->boundname || !time_str || !age_str || !includes_count_str )
+ {
+ fprintf( stderr, "invalid %s\n", hcachename );
+ goto bail;
+ }
+
+ c->time = atoi( time_str );
+ c->age = atoi( age_str ) + 1;
+
+ count = atoi( includes_count_str );
+ for ( l = 0, i = 0; i < count; ++i )
+ {
+ char * s = read_netstring( f );
+ if ( !s )
+ {
+ fprintf( stderr, "invalid %s\n", hcachename );
+ goto bail;
+ }
+ l = list_new( l, s );
+ }
+ c->includes = l;
+
+ hdrscan_count_str = read_netstring( f );
+ if ( !includes_count_str )
+ {
+ list_free( c->includes );
+ fprintf( stderr, "invalid %s\n", hcachename );
+ goto bail;
+ }
+
+ count = atoi( hdrscan_count_str );
+ for ( l = 0, i = 0; i < count; ++i )
+ {
+ char * s = read_netstring( f );
+ if ( !s )
+ {
+ fprintf( stderr, "invalid %s\n", hcachename );
+ goto bail;
+ }
+ l = list_new( l, s );
+ }
+ c->hdrscan = l;
+
+ if ( !hashenter( hcachehash, (HASHDATA * *)&c ) )
+ {
+ fprintf( stderr, "can't insert header cache item, bailing on %s\n",
+ hcachename );
+ goto bail;
+ }
+
+ c->next = hcachelist;
+ hcachelist = c;
+
+ ++header_count;
+ }
+
+ if ( DEBUG_HEADER )
+ printf( "hcache read from file %s\n", hcachename );
+
+ bail:
+ fclose( f );
+}
+
+
+void hcache_done()
+{
+ FILE * f;
+ HCACHEDATA * c;
+ int header_count = 0;
+ char * hcachename;
+ int maxage;
+
+ if ( !hcachehash )
+ return;
+
+ if ( !( hcachename = cache_name() ) )
+ return;
+
+ if ( !( f = fopen( hcachename, "wb" ) ) )
+ return;
+
+ maxage = cache_maxage();
+
+ /* Print out the version. */
+ write_netstring( f, CACHE_FILE_VERSION );
+
+ c = hcachelist;
+ for ( c = hcachelist; c; c = c->next )
+ {
+ LIST * l;
+ char time_str[ 30 ];
+ char age_str[ 30 ];
+ char includes_count_str[ 30 ];
+ char hdrscan_count_str[ 30 ];
+
+ if ( maxage == 0 )
+ c->age = 0;
+ else if ( c->age > maxage )
+ continue;
+
+ sprintf( includes_count_str, "%lu", (long unsigned) list_length( c->includes ) );
+ sprintf( hdrscan_count_str, "%lu", (long unsigned) list_length( c->hdrscan ) );
+ sprintf( time_str, "%lu", (long unsigned) c->time );
+ sprintf( age_str, "%lu", (long unsigned) c->age );
+
+ write_netstring( f, CACHE_RECORD_HEADER );
+ write_netstring( f, c->boundname );
+ write_netstring( f, time_str );
+ write_netstring( f, age_str );
+ write_netstring( f, includes_count_str );
+ for ( l = c->includes; l; l = list_next( l ) )
+ write_netstring( f, l->string );
+ write_netstring( f, hdrscan_count_str );
+ for ( l = c->hdrscan; l; l = list_next( l ) )
+ write_netstring( f, l->string );
+ fputs( "\n", f );
+ ++header_count;
+ }
+ write_netstring( f, CACHE_RECORD_END );
+
+ if ( DEBUG_HEADER )
+ printf( "hcache written to %s. %d dependencies, %.0f%% hit rate\n",
+ hcachename, header_count, queries ? 100.0 * hits / queries : 0 );
+
+ fclose ( f );
+}
+
+
+LIST * hcache( TARGET * t, int rec, regexp * re[], LIST * hdrscan )
+{
+ HCACHEDATA cachedata;
+ HCACHEDATA * c = &cachedata;
+
+ LIST * l = 0;
+
+ ++queries;
+
+ c->boundname = t->boundname;
+
+ if (hashcheck (hcachehash, (HASHDATA **) &c))
+ {
+ if (c->time == t->time)
+ {
+ LIST *l1 = hdrscan, *l2 = c->hdrscan;
+ while (l1 && l2) {
+ if (l1->string != l2->string) {
+ l1 = NULL;
+ } else {
+ l1 = list_next(l1);
+ l2 = list_next(l2);
+ }
+ }
+ if (l1 || l2) {
+ if (DEBUG_HEADER)
+ printf("HDRSCAN out of date in cache for %s\n",
+ t->boundname);
+
+ printf("HDRSCAN out of date for %s\n", t->boundname);
+ printf(" real : ");
+ list_print(hdrscan);
+ printf("\n cached: ");
+ list_print(c->hdrscan);
+ printf("\n");
+
+ list_free(c->includes);
+ list_free(c->hdrscan);
+ c->includes = 0;
+ c->hdrscan = 0;
+ } else {
+ if (DEBUG_HEADER)
+ printf ("using header cache for %s\n", t->boundname);
+ c->age = 0;
+ ++hits;
+ l = list_copy (0, c->includes);
+ return l;
+ }
+ } else {
+ if (DEBUG_HEADER)
+ printf ("header cache out of date for %s\n", t->boundname);
+ list_free (c->includes);
+ list_free(c->hdrscan);
+ c->includes = 0;
+ c->hdrscan = 0;
+ }
+ } else {
+ if (hashenter (hcachehash, (HASHDATA **)&c)) {
+ c->boundname = newstr (c->boundname);
+ c->next = hcachelist;
+ hcachelist = c;
+ }
+ }
+
+ /* 'c' points at the cache entry. Its out of date. */
+
+ l = headers1 (0, t->boundname, rec, re);
+
+ c->time = t->time;
+ c->age = 0;
+ c->includes = list_copy (0, l);
+ c->hdrscan = list_copy(0, hdrscan);
+
+ return l;
+}
+
+#endif
diff --git a/tools/build/v2/engine/hcache.h b/tools/build/v2/engine/hcache.h
new file mode 100644
index 0000000000..c316e3bcad
--- /dev/null
+++ b/tools/build/v2/engine/hcache.h
@@ -0,0 +1,18 @@
+/*
+ * This file is not part of Jam
+ */
+
+/*
+ * hcache.h - handle #includes in source files
+ */
+#ifndef HCACHE_H
+# define HCACHE_H
+
+# include "regexp.h"
+# include "lists.h"
+
+void hcache_init(void);
+void hcache_done(void);
+LIST *hcache(TARGET *t, int rec, regexp *re[], LIST *hdrscan);
+
+#endif
diff --git a/tools/build/v2/engine/hdrmacro.c b/tools/build/v2/engine/hdrmacro.c
new file mode 100644
index 0000000000..43031d48ff
--- /dev/null
+++ b/tools/build/v2/engine/hdrmacro.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "parse.h"
+# include "compile.h"
+# include "rules.h"
+# include "variable.h"
+# include "regexp.h"
+# include "hdrmacro.h"
+# include "hash.h"
+# include "newstr.h"
+# include "strings.h"
+
+/*
+ * hdrmacro.c - handle header files that define macros used in
+ * #include statements.
+ *
+ * we look for lines like "#define MACRO <....>" or '#define MACRO " "'
+ * in the target file. When found, we
+ *
+ * we then phony up a rule invocation like:
+ *
+ * $(HDRRULE) <target> : <resolved included files> ;
+ *
+ * External routines:
+ * headers1() - scan a target for "#include MACRO" lines and try
+ * to resolve them when needed
+ *
+ * Internal routines:
+ * headers1() - using regexp, scan a file and build include LIST
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 09/10/00 (seiwald) - replaced call to compile_rule with evaluate_rule,
+ * so that headers() doesn't have to mock up a parse structure
+ * just to invoke a rule.
+ */
+
+/* this type is used to store a dictionary of file header macros */
+typedef struct header_macro
+{
+ char * symbol;
+ char * filename; /* we could maybe use a LIST here ?? */
+} HEADER_MACRO;
+
+static struct hash * header_macros_hash = 0;
+
+
+/*
+ * headers() - scan a target for include files and call HDRRULE
+ */
+
+# define MAXINC 10
+
+void
+macro_headers( TARGET *t )
+{
+ static regexp *re = 0;
+ FILE *f;
+ char buf[ 1024 ];
+
+ if ( DEBUG_HEADER )
+ printf( "macro header scan for %s\n", t->name );
+
+ /* this regexp is used to detect lines of the form */
+ /* "#define MACRO <....>" or "#define MACRO "....." */
+ /* in the header macro files.. */
+ if ( re == 0 )
+ {
+ re = regex_compile(
+ "^[ ]*#[ ]*define[ ]*([A-Za-z][A-Za-z0-9_]*)[ ]*"
+ "[<\"]([^\">]*)[\">].*$" );
+ }
+
+ if ( !( f = fopen( t->boundname, "r" ) ) )
+ return;
+
+ while ( fgets( buf, sizeof( buf ), f ) )
+ {
+ HEADER_MACRO var;
+ HEADER_MACRO *v = &var;
+
+ if ( regexec( re, buf ) && re->startp[1] )
+ {
+ /* we detected a line that looks like "#define MACRO filename */
+ re->endp[1][0] = '\0';
+ re->endp[2][0] = '\0';
+
+ if ( DEBUG_HEADER )
+ printf( "macro '%s' used to define filename '%s' in '%s'\n",
+ re->startp[1], re->startp[2], t->boundname );
+
+ /* add macro definition to hash table */
+ if ( !header_macros_hash )
+ header_macros_hash = hashinit( sizeof( HEADER_MACRO ), "hdrmacros" );
+
+ v->symbol = re->startp[1];
+ v->filename = 0;
+ if ( hashenter( header_macros_hash, (HASHDATA **)&v ) )
+ {
+ v->symbol = newstr( re->startp[1] ); /* never freed */
+ v->filename = newstr( re->startp[2] ); /* never freed */
+ }
+ /* XXXX: FOR NOW, WE IGNORE MULTIPLE MACRO DEFINITIONS !! */
+ /* WE MIGHT AS WELL USE A LIST TO STORE THEM.. */
+ }
+ }
+
+ fclose( f );
+}
+
+
+char * macro_header_get( const char * macro_name )
+{
+ HEADER_MACRO var;
+ HEADER_MACRO * v = &var;
+
+ v->symbol = (char* )macro_name;
+
+ if ( header_macros_hash && hashcheck( header_macros_hash, (HASHDATA **)&v ) )
+ {
+ if ( DEBUG_HEADER )
+ printf( "### macro '%s' evaluated to '%s'\n", macro_name, v->filename );
+ return v->filename;
+ }
+ return 0;
+}
diff --git a/tools/build/v2/engine/hdrmacro.h b/tools/build/v2/engine/hdrmacro.h
new file mode 100644
index 0000000000..08cc111600
--- /dev/null
+++ b/tools/build/v2/engine/hdrmacro.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * hdrmacro.h - parses header files for #define MACRO <filename> or
+ * #define MACRO "filename" definitions
+ */
+
+void macro_headers( TARGET *t );
+
+char* macro_header_get( const char* macro_name );
diff --git a/tools/build/v2/engine/headers.c b/tools/build/v2/engine/headers.c
new file mode 100644
index 0000000000..b9d8f6370d
--- /dev/null
+++ b/tools/build/v2/engine/headers.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "parse.h"
+# include "compile.h"
+# include "rules.h"
+# include "variable.h"
+# include "regexp.h"
+# include "headers.h"
+# include "hdrmacro.h"
+# include "newstr.h"
+
+#ifdef OPT_HEADER_CACHE_EXT
+# include "hcache.h"
+#endif
+
+/*
+ * headers.c - handle #includes in source files
+ *
+ * Using regular expressions provided as the variable $(HDRSCAN),
+ * headers() searches a file for #include files and phonies up a
+ * rule invocation:
+ *
+ * $(HDRRULE) <target> : <include files> ;
+ *
+ * External routines:
+ * headers() - scan a target for include files and call HDRRULE
+ *
+ * Internal routines:
+ * headers1() - using regexp, scan a file and build include LIST
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 09/10/00 (seiwald) - replaced call to compile_rule with evaluate_rule,
+ * so that headers() doesn't have to mock up a parse structure
+ * just to invoke a rule.
+ */
+
+#ifndef OPT_HEADER_CACHE_EXT
+static LIST *headers1( LIST *l, char *file, int rec, regexp *re[]);
+#endif
+
+/*
+ * headers() - scan a target for include files and call HDRRULE
+ */
+
+# define MAXINC 10
+
+void
+headers( TARGET *t )
+{
+ LIST * hdrscan;
+ LIST * hdrrule;
+ #ifndef OPT_HEADER_CACHE_EXT
+ LIST * headlist = 0;
+ #endif
+ regexp * re[ MAXINC ];
+ int rec = 0;
+
+ if ( !( hdrscan = var_get( "HDRSCAN" ) ) ||
+ !( hdrrule = var_get( "HDRRULE" ) ) )
+ return;
+
+ if ( DEBUG_HEADER )
+ printf( "header scan %s\n", t->name );
+
+ /* Compile all regular expressions in HDRSCAN */
+ while ( ( rec < MAXINC ) && hdrscan )
+ {
+ re[ rec++ ] = regex_compile( hdrscan->string );
+ hdrscan = list_next( hdrscan );
+ }
+
+ /* Doctor up call to HDRRULE rule */
+ /* Call headers1() to get LIST of included files. */
+ {
+ FRAME frame[1];
+ frame_init( frame );
+ lol_add( frame->args, list_new( L0, t->name ) );
+#ifdef OPT_HEADER_CACHE_EXT
+ lol_add( frame->args, hcache( t, rec, re, hdrscan ) );
+#else
+ lol_add( frame->args, headers1( headlist, t->boundname, rec, re ) );
+#endif
+
+ if ( lol_get( frame->args, 1 ) )
+ {
+ /* The third argument to HDRRULE is the bound name of
+ * $(<) */
+ lol_add( frame->args, list_new( L0, t->boundname ) );
+
+ list_free( evaluate_rule( hdrrule->string, frame ) );
+ }
+
+ /* Clean up. */
+ frame_free( frame );
+ }
+}
+
+
+/*
+ * headers1() - using regexp, scan a file and build include LIST.
+ */
+
+#ifdef OPT_HEADER_CACHE_EXT
+LIST *
+#else
+static LIST *
+#endif
+headers1(
+ LIST * l,
+ char * file,
+ int rec,
+ regexp * re[] )
+{
+ FILE * f;
+ char buf[ 1024 ];
+ int i;
+ static regexp * re_macros = 0;
+
+#ifdef OPT_IMPROVED_PATIENCE_EXT
+ static int count = 0;
+ ++count;
+ if ( ((count == 100) || !( count % 1000 )) && DEBUG_MAKE )
+ printf("...patience...\n");
+#endif
+
+ /* the following regexp is used to detect cases where a */
+ /* file is included through a line line "#include MACRO" */
+ if ( re_macros == 0 )
+ re_macros = regex_compile(
+ "^[ ]*#[ ]*include[ ]*([A-Za-z][A-Za-z0-9_]*).*$" );
+
+ if ( !( f = fopen( file, "r" ) ) )
+ return l;
+
+ while ( fgets( buf, sizeof( buf ), f ) )
+ {
+ int size = strlen( buf );
+ /* Remove trailing \r and \n, if any. */
+ while ( ( size > 0 ) &&
+ ( buf[ size - 1 ] == '\n' ) &&
+ ( buf[ size - 1 ] == '\r' ) )
+ {
+ buf[ size - 1 ] = '\0';
+ --size;
+ }
+
+ for ( i = 0; i < rec; ++i )
+ if ( regexec( re[i], buf ) && re[i]->startp[1] )
+ {
+ re[i]->endp[1][0] = '\0';
+
+ if ( DEBUG_HEADER )
+ printf( "header found: %s\n", re[i]->startp[1] );
+
+ l = list_new( l, newstr( re[i]->startp[1] ) );
+ }
+
+ /* special treatment for #include MACRO */
+ if ( regexec( re_macros, buf ) && re_macros->startp[1] )
+ {
+ char* header_filename;
+
+ re_macros->endp[1][0] = '\0';
+
+ if ( DEBUG_HEADER )
+ printf( "macro header found: %s", re_macros->startp[1] );
+
+ header_filename = macro_header_get( re_macros->startp[1] );
+ if ( header_filename )
+ {
+ if ( DEBUG_HEADER )
+ printf( " resolved to '%s'\n", header_filename );
+ l = list_new( l, newstr( header_filename ) );
+ }
+ else
+ {
+ if ( DEBUG_HEADER )
+ printf( " ignored !!\n" );
+ }
+ }
+ }
+
+ fclose( f );
+
+ return l;
+}
+
+
+void regerror( char * s )
+{
+ printf( "re error %s\n", s );
+}
diff --git a/tools/build/v2/engine/headers.h b/tools/build/v2/engine/headers.h
new file mode 100644
index 0000000000..624475fe7d
--- /dev/null
+++ b/tools/build/v2/engine/headers.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * headers.h - handle #includes in source files
+ */
+
+void headers( TARGET *t );
+
+#ifdef OPT_HEADER_CACHE_EXT
+struct regexp;
+LIST *headers1( LIST *l, char *file, int rec, struct regexp *re[] );
+#endif
diff --git a/tools/build/v2/engine/jam.c b/tools/build/v2/engine/jam.c
new file mode 100644
index 0000000000..e11d082bca
--- /dev/null
+++ b/tools/build/v2/engine/jam.c
@@ -0,0 +1,632 @@
+/*
+ * /+\
+ * +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ * \+/
+ *
+ * This file is part of jam.
+ *
+ * License is hereby granted to use this software and distribute it
+ * freely, as long as this copyright notice is retained and modifications
+ * are clearly marked.
+ *
+ * ALL WARRANTIES ARE HEREBY DISCLAIMED.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * jam.c - make redux
+ *
+ * See Jam.html for usage information.
+ *
+ * These comments document the code.
+ *
+ * The top half of the code is structured such:
+ *
+ * jam
+ * / | \
+ * +---+ | \
+ * / | \
+ * jamgram option \
+ * / | \ \
+ * / | \ \
+ * / | \ |
+ * scan | compile make
+ * | | / | \ / | \
+ * | | / | \ / | \
+ * | | / | \ / | \
+ * jambase parse | rules search make1
+ * | | | \
+ * | | | \
+ * | | | \
+ * builtins timestamp command execute
+ * |
+ * |
+ * |
+ * filesys
+ *
+ *
+ * The support routines are called by all of the above, but themselves
+ * are layered thus:
+ *
+ * variable|expand
+ * / | | |
+ * / | | |
+ * / | | |
+ * lists | | pathsys
+ * \ | |
+ * \ | |
+ * \ | |
+ * newstr |
+ * \ |
+ * \ |
+ * \ |
+ * hash
+ *
+ * Roughly, the modules are:
+ *
+ * builtins.c - jam's built-in rules
+ * command.c - maintain lists of commands
+ * compile.c - compile parsed jam statements
+ * execunix.c - execute a shell script on UNIX
+ * execvms.c - execute a shell script, ala VMS
+ * expand.c - expand a buffer, given variable values
+ * file*.c - scan directories and archives on *
+ * hash.c - simple in-memory hashing routines
+ * hdrmacro.c - handle header file parsing for filename macro definitions
+ * headers.c - handle #includes in source files
+ * jambase.c - compilable copy of Jambase
+ * jamgram.y - jam grammar
+ * lists.c - maintain lists of strings
+ * make.c - bring a target up to date, once rules are in place
+ * make1.c - execute command to bring targets up to date
+ * newstr.c - string manipulation routines
+ * option.c - command line option processing
+ * parse.c - make and destroy parse trees as driven by the parser
+ * path*.c - manipulate file names on *
+ * hash.c - simple in-memory hashing routines
+ * regexp.c - Henry Spencer's regexp
+ * rules.c - access to RULEs, TARGETs, and ACTIONs
+ * scan.c - the jam yacc scanner
+ * search.c - find a target along $(SEARCH) or $(LOCATE)
+ * timestamp.c - get the timestamp of a file or archive member
+ * variable.c - handle jam multi-element variables
+ *
+ * 05/04/94 (seiwald) - async multiprocess (-j) support
+ * 02/08/95 (seiwald) - -n implies -d2.
+ * 02/22/95 (seiwald) - -v for version info.
+ * 09/11/00 (seiwald) - PATCHLEVEL folded into VERSION.
+ * 01/10/01 (seiwald) - pathsys.h split from filesys.h
+ */
+
+
+#include "jam.h"
+#include "option.h"
+#include "patchlevel.h"
+
+/* These get various function declarations. */
+#include "lists.h"
+#include "parse.h"
+#include "variable.h"
+#include "compile.h"
+#include "builtins.h"
+#include "rules.h"
+#include "newstr.h"
+#include "scan.h"
+#include "timestamp.h"
+#include "make.h"
+#include "strings.h"
+#include "expand.h"
+#include "filesys.h"
+#include "output.h"
+
+/* Macintosh is "special" */
+#ifdef OS_MAC
+ #include <QuickDraw.h>
+#endif
+
+/* And UNIX for this. */
+#ifdef unix
+ #include <sys/utsname.h>
+ #include <signal.h>
+#endif
+
+struct globs globs =
+{
+ 0, /* noexec */
+ 1, /* jobs */
+ 0, /* quitquick */
+ 0, /* newestfirst */
+ 0, /* pipes action stdout and stderr merged to action output */
+#ifdef OS_MAC
+ { 0, 0 }, /* debug - suppress tracing output */
+#else
+ { 0, 1 }, /* debug ... */
+#endif
+ 0, /* output commands, not run them */
+ 0 /* action timeout */
+};
+
+/* Symbols to be defined as true for use in Jambase. */
+static char * othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, 0 };
+
+
+/* Known for sure:
+ * mac needs arg_enviro
+ * OS2 needs extern environ
+ */
+
+#ifdef OS_MAC
+ #define use_environ arg_environ
+ #ifdef MPW
+ QDGlobals qd;
+ #endif
+#endif
+
+/* on Win32-LCC */
+#if defined( OS_NT ) && defined( __LCC__ )
+ #define use_environ _environ
+#endif
+
+# if defined( __MWERKS__)
+ #define use_environ _environ
+ extern char * * _environ;
+#endif
+
+#ifndef use_environ
+ #define use_environ environ
+ #if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT )
+ extern char **environ;
+ #endif
+#endif
+
+#if YYDEBUG != 0
+ extern int yydebug;
+#endif
+
+#ifndef NDEBUG
+static void run_unit_tests()
+{
+#if defined( USE_EXECNT )
+ extern void execnt_unit_test();
+ execnt_unit_test();
+#endif
+ string_unit_test();
+ var_expand_unit_test();
+}
+#endif
+
+int anyhow = 0;
+
+#ifdef HAVE_PYTHON
+ extern PyObject * bjam_call ( PyObject * self, PyObject * args );
+ extern PyObject * bjam_import_rule ( PyObject * self, PyObject * args );
+ extern PyObject * bjam_define_action( PyObject * self, PyObject * args );
+ extern PyObject * bjam_variable ( PyObject * self, PyObject * args );
+ extern PyObject * bjam_backtrace ( PyObject * self, PyObject * args );
+ extern PyObject * bjam_caller ( PyObject * self, PyObject * args );
+#endif
+
+char *saved_argv0;
+
+int main( int argc, char * * argv, char * * arg_environ )
+{
+ int n;
+ char * s;
+ struct bjam_option optv[N_OPTS];
+ char const * all = "all";
+ int status;
+ int arg_c = argc;
+ char * * arg_v = argv;
+ char const * progname = argv[0];
+
+ saved_argv0 = argv[0];
+
+ BJAM_MEM_INIT();
+
+# ifdef OS_MAC
+ InitGraf(&qd.thePort);
+# endif
+
+ --argc;
+ ++argv;
+
+ if ( getoptions( argc, argv, "-:l:d:j:p:f:gs:t:ano:qv", optv ) < 0 )
+ {
+ printf( "\nusage: %s [ options ] targets...\n\n", progname );
+
+ printf( "-a Build all targets, even if they are current.\n" );
+ printf( "-dx Set the debug level to x (0-9).\n" );
+ printf( "-fx Read x instead of Jambase.\n" );
+ /* printf( "-g Build from newest sources first.\n" ); */
+ printf( "-jx Run up to x shell commands concurrently.\n" );
+ printf( "-lx Limit actions to x number of seconds after which they are stopped.\n" );
+ printf( "-n Don't actually execute the updating actions.\n" );
+ printf( "-ox Write the updating actions to file x.\n" );
+ printf( "-px x=0, pipes action stdout and stderr merged into action output.\n" );
+ printf( "-q Quit quickly as soon as a target fails.\n" );
+ printf( "-sx=y Set variable x=y, overriding environment.\n" );
+ printf( "-tx Rebuild x, even if it is up-to-date.\n" );
+ printf( "-v Print the version of jam and exit.\n" );
+ printf( "--x Option is ignored.\n\n" );
+
+ exit( EXITBAD );
+ }
+
+ /* Version info. */
+ if ( ( s = getoptval( optv, 'v', 0 ) ) )
+ {
+ printf( "Boost.Jam " );
+ printf( "Version %s. %s.\n", VERSION, OSMINOR );
+ printf( " Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. \n" );
+ printf( " Copyright 2001 David Turner.\n" );
+ printf( " Copyright 2001-2004 David Abrahams.\n" );
+ printf( " Copyright 2002-2008 Rene Rivera.\n" );
+ printf( " Copyright 2003-2008 Vladimir Prus.\n" );
+
+ return EXITOK;
+ }
+
+ /* Pick up interesting options. */
+ if ( ( s = getoptval( optv, 'n', 0 ) ) )
+ globs.noexec++, globs.debug[2] = 1;
+
+ if ( ( s = getoptval( optv, 'p', 0 ) ) )
+ {
+ /* Undocumented -p3 (acts like both -p1 -p2) means separate pipe action
+ * stdout and stderr.
+ */
+ globs.pipe_action = atoi( s );
+ if ( ( 3 < globs.pipe_action ) || ( globs.pipe_action < 0 ) )
+ {
+ printf(
+ "Invalid pipe descriptor '%d', valid values are -p[0..3].\n",
+ globs.pipe_action );
+ exit( EXITBAD );
+ }
+ }
+
+ if ( ( s = getoptval( optv, 'q', 0 ) ) )
+ globs.quitquick = 1;
+
+ if ( ( s = getoptval( optv, 'a', 0 ) ) )
+ anyhow++;
+
+ if ( ( s = getoptval( optv, 'j', 0 ) ) )
+ {
+ globs.jobs = atoi( s );
+ if (globs.jobs == 0)
+ {
+ printf("Invalid value for the '-j' option.\n");
+ exit(EXITBAD);
+ }
+ }
+
+ if ( ( s = getoptval( optv, 'g', 0 ) ) )
+ globs.newestfirst = 1;
+
+ if ( ( s = getoptval( optv, 'l', 0 ) ) )
+ globs.timeout = atoi( s );
+
+ /* Turn on/off debugging */
+ for ( n = 0; ( s = getoptval( optv, 'd', n ) ); ++n )
+ {
+ int i;
+
+ /* First -d, turn off defaults. */
+ if ( !n )
+ for ( i = 0; i < DEBUG_MAX; ++i )
+ globs.debug[i] = 0;
+
+ i = atoi( s );
+
+ if ( ( i < 0 ) || ( i >= DEBUG_MAX ) )
+ {
+ printf( "Invalid debug level '%s'.\n", s );
+ continue;
+ }
+
+ /* n turns on levels 1-n. */
+ /* +n turns on level n. */
+ if ( *s == '+' )
+ globs.debug[i] = 1;
+ else while ( i )
+ globs.debug[i--] = 1;
+ }
+
+ {
+ PROFILE_ENTER( MAIN );
+
+#ifdef HAVE_PYTHON
+ {
+ PROFILE_ENTER( MAIN_PYTHON );
+ Py_Initialize();
+ {
+ static PyMethodDef BjamMethods[] = {
+ {"call", bjam_call, METH_VARARGS,
+ "Call the specified bjam rule."},
+ {"import_rule", bjam_import_rule, METH_VARARGS,
+ "Imports Python callable to bjam."},
+ {"define_action", bjam_define_action, METH_VARARGS,
+ "Defines a command line action."},
+ {"variable", bjam_variable, METH_VARARGS,
+ "Obtains a variable from bjam's global module."},
+ {"backtrace", bjam_backtrace, METH_VARARGS,
+ "Returns bjam backtrace from the last call into Python."},
+ {"caller", bjam_caller, METH_VARARGS,
+ "Returns the module from which the last call into Python is made."},
+ {NULL, NULL, 0, NULL}
+ };
+
+ Py_InitModule( "bjam", BjamMethods );
+ }
+ PROFILE_EXIT( MAIN_PYTHON );
+ }
+#endif
+
+#ifndef NDEBUG
+ run_unit_tests();
+#endif
+#if YYDEBUG != 0
+ if ( DEBUG_PARSE )
+ yydebug = 1;
+#endif
+
+ /* Set JAMDATE. */
+ var_set( "JAMDATE", list_new( L0, outf_time(time(0)) ), VAR_SET );
+
+ /* Set JAM_VERSION. */
+ var_set( "JAM_VERSION",
+ list_new( list_new( list_new( L0,
+ newstr( VERSION_MAJOR_SYM ) ),
+ newstr( VERSION_MINOR_SYM ) ),
+ newstr( VERSION_PATCH_SYM ) ),
+ VAR_SET );
+
+ /* Set JAMUNAME. */
+#ifdef unix
+ {
+ struct utsname u;
+
+ if ( uname( &u ) >= 0 )
+ {
+ var_set( "JAMUNAME",
+ list_new(
+ list_new(
+ list_new(
+ list_new(
+ list_new( L0,
+ newstr( u.sysname ) ),
+ newstr( u.nodename ) ),
+ newstr( u.release ) ),
+ newstr( u.version ) ),
+ newstr( u.machine ) ), VAR_SET );
+ }
+ }
+#endif /* unix */
+
+ /* Load up environment variables. */
+
+ /* First into the global module, with splitting, for backward
+ * compatibility.
+ */
+ var_defines( use_environ, 1 );
+
+ /* Then into .ENVIRON, without splitting. */
+ enter_module( bindmodule(".ENVIRON") );
+ var_defines( use_environ, 0 );
+ exit_module( bindmodule(".ENVIRON") );
+
+ /*
+ * Jam defined variables OS & OSPLAT. We load them after environment, so
+ * that setting OS in environment does not change Jam's notion of the
+ * current platform.
+ */
+ var_defines( othersyms, 1 );
+
+ /* Load up variables set on command line. */
+ for ( n = 0; ( s = getoptval( optv, 's', n ) ); ++n )
+ {
+ char *symv[2];
+ symv[ 0 ] = s;
+ symv[ 1 ] = 0;
+ var_defines( symv, 1 );
+ enter_module( bindmodule(".ENVIRON") );
+ var_defines( symv, 0 );
+ exit_module( bindmodule(".ENVIRON") );
+ }
+
+ /* Set the ARGV to reflect the complete list of arguments of invocation.
+ */
+ for ( n = 0; n < arg_c; ++n )
+ var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND );
+
+ /* Initialize built-in rules. */
+ load_builtins();
+
+ /* Add the targets in the command line to the update list. */
+ for ( n = 1; n < arg_c; ++n )
+ {
+ if ( arg_v[ n ][ 0 ] == '-' )
+ {
+ char * f = "-:l:d:j:f:gs:t:ano:qv";
+ for ( ; *f; ++f ) if ( *f == arg_v[ n ][ 1 ] ) break;
+ if ( ( f[ 1 ] == ':' ) && ( arg_v[ n ][ 2 ] == '\0' ) ) ++n;
+ }
+ else
+ {
+ mark_target_for_updating( arg_v[ n ] );
+ }
+ }
+
+ if (!targets_to_update())
+ mark_target_for_updating("all");
+
+ /* Parse ruleset. */
+ {
+ FRAME frame[ 1 ];
+ frame_init( frame );
+ for ( n = 0; ( s = getoptval( optv, 'f', n ) ); ++n )
+ parse_file( s, frame );
+
+ if ( !n )
+ parse_file( "+", frame );
+ }
+
+ status = yyanyerrors();
+
+ /* Manually touch -t targets. */
+ for ( n = 0; ( s = getoptval( optv, 't', n ) ); ++n )
+ touch_target( s );
+
+ /* If an output file is specified, set globs.cmdout to that. */
+ if ( ( s = getoptval( optv, 'o', 0 ) ) )
+ {
+ if ( !( globs.cmdout = fopen( s, "w" ) ) )
+ {
+ printf( "Failed to write to '%s'\n", s );
+ exit( EXITBAD );
+ }
+ ++globs.noexec;
+ }
+
+ /* The build system may set the PARALLELISM variable to override -j
+ options. */
+ {
+ LIST *p = L0;
+ p = var_get ("PARALLELISM");
+ if (p)
+ {
+ int j = atoi (p->string);
+ if (j == -1)
+ {
+ printf( "Invalid value of PARALLELISM: %s\n", p->string);
+ }
+ else
+ {
+ globs.jobs = j;
+ }
+ }
+ }
+
+ /* KEEP_GOING overrides -q option. */
+ {
+ LIST *p = L0;
+ p = var_get ("KEEP_GOING");
+ if (p)
+ {
+ int v = atoi (p->string);
+ if (v == 0)
+ globs.quitquick = 1;
+ else
+ globs.quitquick = 0;
+ }
+ }
+
+ /* Now make target. */
+ {
+ PROFILE_ENTER( MAIN_MAKE );
+
+ LIST * targets = targets_to_update();
+ if (targets)
+ {
+ int targets_count = list_length( targets );
+ const char * * targets2 = (const char * *)
+ BJAM_MALLOC( targets_count * sizeof( char * ) );
+ int n = 0;
+ for ( ; targets; targets = list_next( targets ) )
+ targets2[ n++ ] = targets->string;
+ status |= make( targets_count, targets2, anyhow );
+ free( targets );
+ }
+ else
+ {
+ status = last_update_now_status;
+ }
+
+ PROFILE_EXIT( MAIN_MAKE );
+ }
+
+ PROFILE_EXIT( MAIN );
+ }
+
+ if ( DEBUG_PROFILE )
+ profile_dump();
+
+ /* Widely scattered cleanup. */
+ var_done();
+ file_done();
+ rules_done();
+ stamps_done();
+ str_done();
+
+ /* Close cmdout. */
+ if ( globs.cmdout )
+ fclose( globs.cmdout );
+
+#ifdef HAVE_PYTHON
+ Py_Finalize();
+#endif
+
+ BJAM_MEM_CLOSE();
+
+ return status ? EXITBAD : EXITOK;
+}
+
+#if defined(_WIN32)
+#include <windows.h>
+char *executable_path(char *argv0) {
+ char buf[1024];
+ DWORD ret = GetModuleFileName(NULL, buf, sizeof(buf));
+ if (ret == 0 || ret == sizeof(buf)) return NULL;
+ return strdup (buf);
+}
+#elif defined(__APPLE__) /* Not tested */
+#include <mach-o/dyld.h>
+char *executable_path(char *argv0) {
+ char buf[1024];
+ uint32_t size = sizeof(buf);
+ int ret = _NSGetExecutablePath(buf, &size);
+ if (ret != 0) return NULL;
+ return strdup(buf);
+}
+#elif defined(sun) || defined(__sun) /* Not tested */
+#include <stdlib.h>
+
+char *executable_path(char *argv0) {
+ return strdup(getexecname());
+}
+#elif defined(__FreeBSD__)
+#include <sys/sysctl.h>
+char *executable_path(char *argv0) {
+ int mib[4];
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PATHNAME;
+ mib[3] = -1;
+ char buf[1024];
+ size_t size = sizeof(buf);
+ sysctl(mib, 4, buf, &size, NULL, 0);
+ if (size == 0 || size == sizeof(buf)) return NULL;
+ return strndup(buf, size);
+}
+#elif defined(__linux__)
+#include <unistd.h>
+char *executable_path(char *argv0) {
+ char buf[1024];
+ ssize_t ret = readlink("/proc/self/exe", buf, sizeof(buf));
+ if (ret == 0 || ret == sizeof(buf)) return NULL;
+ return strndup(buf, ret);
+}
+#else
+char *executable_path(char *argv0) {
+ /* If argv0 is absolute path, assume it's the right absolute path. */
+ if (argv0[0] == "/")
+ return strdup(argv0);
+ return NULL;
+}
+#endif
diff --git a/tools/build/v2/engine/jam.h b/tools/build/v2/engine/jam.h
new file mode 100644
index 0000000000..73a7a04c58
--- /dev/null
+++ b/tools/build/v2/engine/jam.h
@@ -0,0 +1,579 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * jam.h - includes and globals for jam
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 04/21/94 (seiwald) - DGUX is __DGUX__, not just __DGUX.
+ * 05/04/94 (seiwald) - new globs.jobs (-j jobs)
+ * 11/01/94 (wingerd) - let us define path of Jambase at compile time.
+ * 12/30/94 (wingerd) - changed command buffer size for NT (MS-DOS shell).
+ * 02/22/95 (seiwald) - Jambase now in /usr/local/lib.
+ * 04/30/95 (seiwald) - FreeBSD added. Live Free or Die.
+ * 05/10/95 (seiwald) - SPLITPATH character set up here.
+ * 08/20/95 (seiwald) - added LINUX.
+ * 08/21/95 (seiwald) - added NCR.
+ * 10/23/95 (seiwald) - added SCO.
+ * 01/03/96 (seiwald) - SINIX (nixdorf) added.
+ * 03/13/96 (seiwald) - Jambase now compiled in; remove JAMBASE variable.
+ * 04/29/96 (seiwald) - AIX now has 31 and 42 OSVERs.
+ * 11/21/96 (peterk) - added BeOS with MW CW mwcc
+ * 12/21/96 (seiwald) - OSPLAT now defined for NT.
+ * 07/19/99 (sickel) - Mac OS X Server and Client support added
+ * 02/18/00 (belmonte)- Support for Cygwin.
+ * 09/12/00 (seiwald) - OSSYMS split to OSMAJOR/OSMINOR/OSPLAT
+ * 12/29/00 (seiwald) - OSVER dropped.
+ */
+
+#ifndef JAM_H_VP_2003_08_01
+#define JAM_H_VP_2003_08_01
+
+#ifdef HAVE_PYTHON
+#include <Python.h>
+#endif
+
+/* Assume popen support is available unless known otherwise. */
+#define HAVE_POPEN 1
+
+/*
+ * VMS, OPENVMS
+ */
+
+#ifdef VMS
+
+#include <types.h>
+#include <file.h>
+#include <stat.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <unixlib.h>
+
+#define OSMINOR "OS=VMS"
+#define OSMAJOR "VMS=true"
+#define OS_VMS
+#define MAXLINE 1024 /* longest 'together' actions */
+#define SPLITPATH ','
+#define EXITOK 1
+#define EXITBAD 0
+#define DOWNSHIFT_PATHS
+
+/* This may be inaccurate. */
+#ifndef __DECC
+#define OSPLAT "OSPLAT=VAX"
+#endif
+
+#endif
+
+/*
+ * Windows NT
+ */
+
+#ifdef NT
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <malloc.h>
+#ifndef __MWERKS__
+ #include <memory.h>
+#endif
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+
+#define OSMAJOR "NT=true"
+#define OSMINOR "OS=NT"
+#define OS_NT
+#define SPLITPATH ';'
+/* Windows NT 3.51 only allows 996 chars per line, but we deal with the problem
+ * in "execnt.c".
+ */
+#define MAXLINE (maxline()) /* longest 'together' actions */
+#define USE_EXECNT
+#define USE_PATHUNIX
+#define PATH_DELIM '\\'
+#define DOWNSHIFT_PATHS
+
+/* AS400 cross-compile from NT. */
+
+#ifdef AS400
+ #undef OSMINOR
+ #undef OSMAJOR
+ #define OSMAJOR "AS400=true"
+ #define OSMINOR "OS=AS400"
+ #define OS_AS400
+#endif
+
+/* Metrowerks Standard Library on Windows. */
+
+#ifdef __MSL__
+ #undef HAVE_POPEN
+#endif
+
+# endif
+
+/*
+ * Windows MingW32
+ */
+
+#ifdef MINGW
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <memory.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+
+#define OSMAJOR "MINGW=true"
+#define OSMINOR "OS=MINGW"
+#define OS_NT
+#define SPLITPATH ';'
+#define MAXLINE 996 /* longest 'together' actions */
+#define USE_EXECUNIX
+#define USE_PATHUNIX
+#define PATH_DELIM '\\'
+#define DOWNSHIFT_PATHS
+
+#endif
+
+/*
+ * OS2
+ */
+
+#ifdef __OS2__
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+
+#define OSMAJOR "OS2=true"
+#define OSMINOR "OS=OS2"
+#define OS_OS2
+#define SPLITPATH ';'
+#define MAXLINE 996 /* longest 'together' actions */
+#define USE_EXECUNIX
+#define USE_PATHUNIX
+#define PATH_DELIM '\\'
+#define DOWNSHIFT_PATHS
+
+#ifdef __EMX__
+ #define USE_FILEUNIX
+#endif
+
+#endif
+
+/*
+ * Macintosh MPW
+ */
+
+#ifdef macintosh
+
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define OSMAJOR "MAC=true"
+#define OSMINOR "OS=MAC"
+#define OS_MAC
+#define SPLITPATH ','
+
+#endif
+
+/*
+ * God fearing UNIX.
+ */
+
+#ifndef OSMINOR
+
+#define OSMAJOR "UNIX=true"
+#define USE_EXECUNIX
+#define USE_FILEUNIX
+#define USE_PATHUNIX
+#define PATH_DELIM '/'
+
+#ifdef _AIX
+ #define unix
+ #define MAXLINE 23552 /* 24k - 1k, longest 'together' actions */
+ #define OSMINOR "OS=AIX"
+ #define OS_AIX
+ #define NO_VFORK
+#endif
+#ifdef AMIGA
+ #define OSMINOR "OS=AMIGA"
+ #define OS_AMIGA
+#endif
+#ifdef __BEOS__
+ #define unix
+ #define OSMINOR "OS=BEOS"
+ #define OS_BEOS
+ #define NO_VFORK
+#endif
+#ifdef __bsdi__
+ #define OSMINOR "OS=BSDI"
+ #define OS_BSDI
+#endif
+#if defined (COHERENT) && defined (_I386)
+ #define OSMINOR "OS=COHERENT"
+ #define OS_COHERENT
+ #define NO_VFORK
+#endif
+#if defined(__cygwin__) || defined(__CYGWIN__)
+ #define OSMINOR "OS=CYGWIN"
+ #define OS_CYGWIN
+#endif
+#if defined(__FreeBSD__) && !defined(__DragonFly__)
+ #define OSMINOR "OS=FREEBSD"
+ #define OS_FREEBSD
+#endif
+#ifdef __DragonFly__
+ #define OSMINOR "OS=DRAGONFLYBSD"
+ #define OS_DRAGONFLYBSD
+#endif
+#ifdef __DGUX__
+ #define OSMINOR "OS=DGUX"
+ #define OS_DGUX
+#endif
+#ifdef __hpux
+ #define OSMINOR "OS=HPUX"
+ #define OS_HPUX
+#endif
+#ifdef __OPENNT
+ #define unix
+ #define OSMINOR "OS=INTERIX"
+ #define OS_INTERIX
+ #define NO_VFORK
+#endif
+#ifdef __sgi
+ #define OSMINOR "OS=IRIX"
+ #define OS_IRIX
+ #define NO_VFORK
+#endif
+#ifdef __ISC
+ #define OSMINOR "OS=ISC"
+ #define OS_ISC
+ #define NO_VFORK
+#endif
+#ifdef linux
+ #define OSMINOR "OS=LINUX"
+ #define OS_LINUX
+#endif
+#ifdef __Lynx__
+ #define OSMINOR "OS=LYNX"
+ #define OS_LYNX
+ #define NO_VFORK
+ #define unix
+#endif
+#ifdef __MACHTEN__
+ #define OSMINOR "OS=MACHTEN"
+ #define OS_MACHTEN
+#endif
+#ifdef mpeix
+ #define unix
+ #define OSMINOR "OS=MPEIX"
+ #define OS_MPEIX
+ #define NO_VFORK
+#endif
+#ifdef __MVS__
+ #define unix
+ #define OSMINOR "OS=MVS"
+ #define OS_MVS
+#endif
+#ifdef _ATT4
+ #define OSMINOR "OS=NCR"
+ #define OS_NCR
+#endif
+#ifdef __NetBSD__
+ #define unix
+ #define OSMINOR "OS=NETBSD"
+ #define OS_NETBSD
+ #define NO_VFORK
+#endif
+#ifdef __QNX__
+ #define unix
+ #ifdef __QNXNTO__
+ #define OSMINOR "OS=QNXNTO"
+ #define OS_QNXNTO
+ #else
+ #define OSMINOR "OS=QNX"
+ #define OS_QNX
+ #define NO_VFORK
+ #define MAXLINE 996
+ #endif
+#endif
+#ifdef NeXT
+ #ifdef __APPLE__
+ #define OSMINOR "OS=RHAPSODY"
+ #define OS_RHAPSODY
+ #else
+ #define OSMINOR "OS=NEXT"
+ #define OS_NEXT
+ #endif
+#endif
+#ifdef __APPLE__
+ #define unix
+ #define OSMINOR "OS=MACOSX"
+ #define OS_MACOSX
+#endif
+#ifdef __osf__
+ #ifndef unix
+ #define unix
+ #endif
+ #define OSMINOR "OS=OSF"
+ #define OS_OSF
+#endif
+#ifdef _SEQUENT_
+ #define OSMINOR "OS=PTX"
+ #define OS_PTX
+#endif
+#ifdef M_XENIX
+ #define OSMINOR "OS=SCO"
+ #define OS_SCO
+ #define NO_VFORK
+#endif
+#ifdef sinix
+ #define unix
+ #define OSMINOR "OS=SINIX"
+ #define OS_SINIX
+#endif
+#ifdef sun
+ #if defined(__svr4__) || defined(__SVR4)
+ #define OSMINOR "OS=SOLARIS"
+ #define OS_SOLARIS
+ #else
+ #define OSMINOR "OS=SUNOS"
+ #define OS_SUNOS
+ #endif
+#endif
+#ifdef ultrix
+ #define OSMINOR "OS=ULTRIX"
+ #define OS_ULTRIX
+#endif
+#ifdef _UNICOS
+ #define OSMINOR "OS=UNICOS"
+ #define OS_UNICOS
+#endif
+#if defined(__USLC__) && !defined(M_XENIX)
+ #define OSMINOR "OS=UNIXWARE"
+ #define OS_UNIXWARE
+#endif
+#ifdef __OpenBSD__
+ #define OSMINOR "OS=OPENBSD"
+ #define OS_OPENBSD
+ #define unix
+#endif
+#if defined (__FreeBSD_kernel__) && !defined(__FreeBSD__)
+ #define OSMINOR "OS=KFREEBSD"
+ #define OS_KFREEBSD
+#endif
+#ifndef OSMINOR
+ #define OSMINOR "OS=UNKNOWN"
+#endif
+
+/* All the UNIX includes */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef OS_MPEIX
+ #include <sys/file.h>
+#endif
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#ifndef OS_QNX
+ #include <memory.h>
+#endif
+
+#ifndef OS_ULTRIX
+ #include <stdlib.h>
+#endif
+
+#if !defined( OS_BSDI ) && \
+ !defined( OS_FREEBSD ) && \
+ !defined( OS_DRAGONFLYBSD ) && \
+ !defined( OS_NEXT ) && \
+ !defined( OS_MACHTEN ) && \
+ !defined( OS_MACOSX ) && \
+ !defined( OS_RHAPSODY ) && \
+ !defined( OS_MVS ) && \
+ !defined( OS_OPENBSD )
+ #include <malloc.h>
+#endif
+
+#endif
+
+/*
+ * OSPLAT definitions - suppressed when it is a one-of-a-kind.
+ */
+
+#if defined( _M_PPC ) || \
+ defined( PPC ) || \
+ defined( ppc ) || \
+ defined( __powerpc__ ) || \
+ defined( __ppc__ )
+ #define OSPLAT "OSPLAT=PPC"
+#endif
+
+#if defined( _ALPHA_ ) || \
+ defined( __alpha__ )
+ #define OSPLAT "OSPLAT=AXP"
+#endif
+
+#if defined( _i386_ ) || \
+ defined( __i386__ ) || \
+ defined( __i386 ) || \
+ defined( _M_IX86 )
+ #define OSPLAT "OSPLAT=X86"
+#endif
+
+#if defined( __ia64__ ) || \
+ defined( __IA64__ ) || \
+ defined( __ia64 )
+ #define OSPLAT "OSPLAT=IA64"
+#endif
+
+#if defined( __x86_64__ ) || \
+ defined( __amd64__ ) || \
+ defined( _M_AMD64 )
+ #define OSPLAT "OSPLAT=X86_64"
+#endif
+
+
+#if defined( __sparc__ ) || \
+ defined( __sparc )
+ #define OSPLAT "OSPLAT=SPARC"
+#endif
+
+#ifdef __mips__
+ #define OSPLAT "OSPLAT=MIPS"
+#endif
+
+#ifdef __arm__
+ #define OSPLAT "OSPLAT=ARM"
+#endif
+
+#ifdef __s390__
+ #define OSPLAT "OSPLAT=390"
+#endif
+
+#ifdef __hppa
+ #define OSPLAT "OSPLAT=PARISC"
+#endif
+
+#ifndef OSPLAT
+ #define OSPLAT ""
+#endif
+
+/*
+ * Jam implementation misc.
+ */
+
+#ifndef MAXLINE
+ #define MAXLINE 102400 /* longest 'together' actions' */
+#endif
+
+#ifndef EXITOK
+ #define EXITOK 0
+ #define EXITBAD 1
+#endif
+
+#ifndef SPLITPATH
+ #define SPLITPATH ':'
+#endif
+
+/* You probably do not need to muck with these. */
+
+#define MAXSYM 1024 /* longest symbol in the environment */
+#define MAXJPATH 1024 /* longest filename */
+
+#define MAXJOBS 64 /* silently enforced -j limit */
+#define MAXARGC 32 /* words in $(JAMSHELL) */
+
+/* Jam private definitions below. */
+
+#define DEBUG_MAX 14
+
+
+struct globs
+{
+ int noexec;
+ int jobs;
+ int quitquick;
+ int newestfirst; /* build newest sources first */
+ int pipe_action;
+ char debug[ DEBUG_MAX ];
+ FILE * cmdout; /* print cmds, not run them */
+ long timeout; /* number of seconds to limit actions to,
+ * default 0 for no limit.
+ */
+ int dart; /* output build and test results formatted for Dart */
+};
+
+extern struct globs globs;
+
+#define DEBUG_MAKE ( globs.debug[ 1 ] ) /* show actions when executed */
+#define DEBUG_MAKEQ ( globs.debug[ 2 ] ) /* show even quiet actions */
+#define DEBUG_EXEC ( globs.debug[ 2 ] ) /* show text of actons */
+#define DEBUG_MAKEPROG ( globs.debug[ 3 ] ) /* show progress of make0 */
+#define DEBUG_BIND ( globs.debug[ 3 ] ) /* show when files bound */
+
+#define DEBUG_EXECCMD ( globs.debug[ 4 ] ) /* show execcmds()'s work */
+
+#define DEBUG_COMPILE ( globs.debug[ 5 ] ) /* show rule invocations */
+
+#define DEBUG_HEADER ( globs.debug[ 6 ] ) /* show result of header scan */
+#define DEBUG_BINDSCAN ( globs.debug[ 6 ] ) /* show result of dir scan */
+#define DEBUG_SEARCH ( globs.debug[ 6 ] ) /* show attempts at binding */
+
+#define DEBUG_VARSET ( globs.debug[ 7 ] ) /* show variable settings */
+#define DEBUG_VARGET ( globs.debug[ 8 ] ) /* show variable fetches */
+#define DEBUG_VAREXP ( globs.debug[ 8 ] ) /* show variable expansions */
+#define DEBUG_IF ( globs.debug[ 8 ] ) /* show 'if' calculations */
+#define DEBUG_LISTS ( globs.debug[ 9 ] ) /* show list manipulation */
+#define DEBUG_SCAN ( globs.debug[ 9 ] ) /* show scanner tokens */
+#define DEBUG_MEM ( globs.debug[ 9 ] ) /* show memory use */
+
+#define DEBUG_PROFILE ( globs.debug[ 10 ] ) /* dump rule execution times */
+#define DEBUG_PARSE ( globs.debug[ 11 ] ) /* debug parsing */
+#define DEBUG_GRAPH ( globs.debug[ 12 ] ) /* debug dependencies */
+#define DEBUG_FATE ( globs.debug[ 13 ] ) /* show changes to fate in make0() */
+
+/* Everyone gets the memory definitions. */
+#include "mem.h"
+
+/* They also get the profile functions. */
+#include "debug.h"
+
+#endif
diff --git a/tools/build/v2/engine/jambase.c b/tools/build/v2/engine/jambase.c
new file mode 100644
index 0000000000..b15282bc32
--- /dev/null
+++ b/tools/build/v2/engine/jambase.c
@@ -0,0 +1,1691 @@
+/* Generated by mkjambase from Jambase */
+char *jambase[] = {
+/* Jambase */
+"if $(NT)\n",
+"{\n",
+"SLASH ?= \\\\ ;\n",
+"}\n",
+"SLASH ?= / ;\n",
+"rule find-to-root ( dir : patterns + )\n",
+"{\n",
+"local globs = [ GLOB $(dir) : $(patterns) ] ;\n",
+"while ! $(globs) && $(dir:P) != $(dir)\n",
+"{\n",
+"dir = $(dir:P) ;\n",
+"globs = [ GLOB $(dir) : $(patterns) ] ;\n",
+"}\n",
+"return $(globs) ;\n",
+"}\n",
+".boost-build-file = ;\n",
+".bootstrap-file = ;\n",
+"BOOST_BUILD_PATH.user-value = $(BOOST_BUILD_PATH) ;\n",
+"if ! $(BOOST_BUILD_PATH) && $(UNIX)\n",
+"{\n",
+"BOOST_BUILD_PATH = /usr/share/boost-build ;\n",
+"}\n",
+"rule _poke ( module-name ? : variables + : value * )\n",
+"{\n",
+"module $(<)\n",
+"{\n",
+"$(>) = $(3) ;\n",
+"}\n",
+"}\n",
+"rule boost-build ( dir ? )\n",
+"{\n",
+"if $(.bootstrap-file)\n",
+"{\n",
+"ECHO \"Error: Illegal attempt to re-bootstrap the build system by invoking\" ;\n",
+"ECHO ;\n",
+"ECHO \" 'boost-build\" $(dir) \";'\" ;\n",
+"ECHO ;\n",
+"EXIT \"Please consult the documentation at 'http://www.boost.org'.\" ;\n",
+"}\n",
+"BOOST_BUILD_PATH = $(dir:R=$(.boost-build-file:D)) $(BOOST_BUILD_PATH) ;\n",
+"_poke .ENVIRON : BOOST_BUILD_PATH : $(BOOST_BUILD_PATH) ;\n",
+"local bootstrap-file = [ GLOB $(BOOST_BUILD_PATH) : bootstrap.jam ] ;\n",
+".bootstrap-file = $(bootstrap-file[1]) ;\n",
+"if ! $(.bootstrap-file)\n",
+"{\n",
+"ECHO \"Unable to load Boost.Build: could not find build system.\" ;\n",
+"ECHO --------------------------------------------------------- ;\n",
+"ECHO \"$(.boost-build-file) attempted to load the build system by invoking\" ;\n",
+"ECHO ;\n",
+"ECHO \" 'boost-build\" $(dir) \";'\" ;\n",
+"ECHO ;\n",
+"ECHO \"but we were unable to find \\\"bootstrap.jam\\\" in the specified directory\" ;\n",
+"ECHO \"or in BOOST_BUILD_PATH (searching \"$(BOOST_BUILD_PATH:J=\", \")\").\" ;\n",
+"ECHO ;\n",
+"EXIT \"Please consult the documentation at 'http://www.boost.org'.\" ;\n",
+"}\n",
+"if [ MATCH .*(--debug-configuration).* : $(ARGV) ]\n",
+"{\n",
+"ECHO \"notice: loading Boost.Build from\"\n",
+"[ NORMALIZE_PATH $(.bootstrap-file:D) ] ;\n",
+"}\n",
+"include $(.bootstrap-file) ;\n",
+"}\n",
+"if [ MATCH .*(b2).* : $(ARGV[1]:BL) ] \n",
+"|| [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]\n",
+"|| $(BOOST_ROOT) # A temporary measure so Jam works with Boost.Build v1.\n",
+"{\n",
+"local search-path = $(BOOST_BUILD_PATH) $(BOOST_ROOT) ;\n",
+"local self = [ SELF_PATH ] ;\n",
+"local boost-build-relative = ../../share/boost-build ;\n",
+"local self-based-path = [ NORMALIZE_PATH $(boost-build-relative:R=$(self)) ] ;\n",
+"local boost-build-files =\n",
+"[ find-to-root [ PWD ] : boost-build.jam ]\n",
+"[ GLOB $(self-based-path) : boost-build.jam ]\n",
+"[ GLOB $(search-path) : boost-build.jam ] ;\n",
+".boost-build-file = $(boost-build-files[1]) ;\n",
+"if ! $(.boost-build-file)\n",
+"{\n",
+"ECHO \"Unable to load Boost.Build: could not find \\\"boost-build.jam\\\"\" ;\n",
+"ECHO --------------------------------------------------------------- ;\n",
+"if ! [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]\n",
+"{\n",
+"ECHO \"BOOST_ROOT must be set, either in the environment, or \" ;\n",
+"ECHO \"on the command-line with -sBOOST_ROOT=..., to the root\" ;\n",
+"ECHO \"of the boost installation.\" ;\n",
+"ECHO ;\n",
+"}\n",
+"ECHO \"Attempted search from\" [ PWD ] \"up to the root\" ;\n",
+"ECHO \"at\" $(self-based-path) ;\n",
+"ECHO \"and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: \"$(search-path:J=\", \")\".\" ;\n",
+"EXIT \"Please consult the documentation at 'http://www.boost.org'.\" ;\n",
+"}\n",
+"if [ MATCH .*(--debug-configuration).* : $(ARGV) ]\n",
+"{\n",
+"ECHO \"notice: found boost-build.jam at\"\n",
+"[ NORMALIZE_PATH $(.boost-build-file) ] ;\n",
+"}\n",
+"include $(.boost-build-file) ;\n",
+"if ! $(.bootstrap-file)\n",
+"{\n",
+"ECHO \"Unable to load Boost.Build\" ;\n",
+"ECHO -------------------------- ;\n",
+"ECHO \"\\\"$(.boost-build-file)\\\" was found by searching from\" [ PWD ] \"up to the root\" ;\n",
+"ECHO \"and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: \"$(search-path:J=\", \")\".\" ;\n",
+"ECHO ;\n",
+"ECHO \"However, it failed to call the \\\"boost-build\\\" rule to indicate\" ;\n",
+"ECHO \"the location of the build system.\" ;\n",
+"ECHO ;\n",
+"EXIT \"Please consult the documentation at 'http://www.boost.org'.\" ;\n",
+"}\n",
+"}\n",
+"else\n",
+"{\n",
+"if $(NT)\n",
+"{\n",
+"local SUPPORTED_TOOLSETS = \"BORLANDC\" \"VC7\" \"VISUALC\" \"VISUALC16\" \"INTELC\" \"WATCOM\"\n",
+"\"MINGW\" \"LCC\" ;\n",
+"TOOLSET = \"\" ;\n",
+"if $(JAM_TOOLSET)\n",
+"{\n",
+"local t ;\n",
+"for t in $(SUPPORTED_TOOLSETS)\n",
+"{\n",
+"$(t) = $($(t):J=\" \") ; # reconstitute paths with spaces in them\n",
+"if $(t) = $(JAM_TOOLSET) { TOOLSET = $(t) ; }\n",
+"}\n",
+"if ! $(TOOLSET)\n",
+"{\n",
+"ECHO \"The JAM_TOOLSET environment variable is defined but its value\" ;\n",
+"ECHO \"is invalid, please use one of the following:\" ;\n",
+"ECHO ;\n",
+"for t in $(SUPPORTED_TOOLSETS) { ECHO \" \" $(t) ; }\n",
+"EXIT ;\n",
+"}\n",
+"}\n",
+"if ! $(TOOLSET)\n",
+"{\n",
+"if $(BCCROOT)\n",
+"{\n",
+"TOOLSET = BORLANDC ;\n",
+"BORLANDC = $(BCCROOT:J=\" \") ;\n",
+"}\n",
+"else if $(MSVC)\n",
+"{\n",
+"TOOLSET = VISUALC16 ;\n",
+"VISUALC16 = $(MSVC:J=\" \") ;\n",
+"}\n",
+"else if $(MSVCNT)\n",
+"{\n",
+"TOOLSET = VISUALC ;\n",
+"VISUALC = $(MSVCNT:J=\" \") ;\n",
+"}\n",
+"else if $(MSVCDir)\n",
+"{\n",
+"TOOLSET = VISUALC ;\n",
+"VISUALC = $(MSVCDir:J=\" \") ;\n",
+"}\n",
+"else if $(MINGW)\n",
+"{\n",
+"TOOLSET = MINGW ;\n",
+"}\n",
+"else\n",
+"{\n",
+"ECHO \"Jam cannot be run because, either:\" ;\n",
+"ECHO \" a. You didn't set BOOST_ROOT to indicate the root of your\" ;\n",
+"ECHO \" Boost installation.\" ;\n",
+"ECHO \" b. You are trying to use stock Jam but didn't indicate which\" ;\n",
+"ECHO \" compilation toolset to use. To do so, follow these simple\" ;\n",
+"ECHO \" instructions:\" ;\n",
+"ECHO ;\n",
+"ECHO \" - define one of the following environment variable, with the\" ;\n",
+"ECHO \" appropriate value according to this list:\" ;\n",
+"ECHO ;\n",
+"ECHO \" Variable Toolset Description\" ;\n",
+"ECHO ;\n",
+"ECHO \" BORLANDC Borland C++ BC++ install path\" ;\n",
+"ECHO \" VISUALC Microsoft Visual C++ VC++ install path\" ;\n",
+"ECHO \" VISUALC16 Microsoft Visual C++ 16 bit VC++ 16 bit install\" ;\n",
+"ECHO \" INTELC Intel C/C++ IC++ install path\" ;\n",
+"ECHO \" WATCOM Watcom C/C++ Watcom install path\" ;\n",
+"ECHO \" MINGW MinGW (gcc) MinGW install path\" ;\n",
+"ECHO \" LCC Win32-LCC LCC-Win32 install path\" ;\n",
+"ECHO ;\n",
+"ECHO \" - define the JAM_TOOLSET environment variable with the *name*\" ;\n",
+"ECHO \" of the toolset variable you want to use.\" ;\n",
+"ECHO ;\n",
+"ECHO \" e.g.: set VISUALC=C:\\\\Visual6\" ;\n",
+"ECHO \" set JAM_TOOLSET=VISUALC\" ;\n",
+"EXIT ;\n",
+"}\n",
+"}\n",
+"CP ?= copy ;\n",
+"RM ?= del /f/q ;\n",
+"SLASH ?= \\\\ ;\n",
+"SUFLIB ?= .lib ;\n",
+"SUFOBJ ?= .obj ;\n",
+"SUFEXE ?= .exe ;\n",
+"if $(TOOLSET) = BORLANDC\n",
+"{\n",
+"ECHO \"Compiler is Borland C++\" ;\n",
+"AR ?= tlib /C /P64 ;\n",
+"CC ?= bcc32 ;\n",
+"CCFLAGS ?= -q -y -d -v -w-par -w-ccc -w-rch -w-pro -w-aus ;\n",
+"C++ ?= bcc32 ;\n",
+"C++FLAGS ?= -q -y -d -v -w-par -w-ccc -w-rch -w-pro -w-aus -P ;\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= $(CCFLAGS) ;\n",
+"STDLIBPATH ?= $(BORLANDC)\\\\lib ;\n",
+"STDHDRS ?= $(BORLANDC)\\\\include ;\n",
+"NOARSCAN ?= true ;\n",
+"}\n",
+"else if $(TOOLSET) = VISUALC16\n",
+"{\n",
+"ECHO \"Compiler is Microsoft Visual C++ 16 bit\" ;\n",
+"AR ?= lib /nologo ;\n",
+"CC ?= cl /nologo ;\n",
+"CCFLAGS ?= /D \\\"WIN\\\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= $(CCFLAGS) ;\n",
+"LINKLIBS ?=\n",
+"\\\"$(VISUALC16)\\\\lib\\\\mlibce.lib\\\"\n",
+"\\\"$(VISUALC16)\\\\lib\\\\oldnames.lib\\\"\n",
+";\n",
+"LINKLIBS ?= ;\n",
+"NOARSCAN ?= true ;\n",
+"OPTIM ?= \"\" ;\n",
+"STDHDRS ?= $(VISUALC16)\\\\include ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = VISUALC\n",
+"{\n",
+"ECHO \"Compiler is Microsoft Visual C++\" ;\n",
+"AR ?= lib ;\n",
+"AS ?= masm386 ;\n",
+"CC ?= cl /nologo ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= link /nologo ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= \\\"$(VISUALC)\\\\lib\\\\advapi32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\lib\\\\gdi32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\lib\\\\user32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\lib\\\\kernel32.lib\\\" ;\n",
+"OPTIM ?= \"\" ;\n",
+"STDHDRS ?= $(VISUALC)\\\\include ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = VC7\n",
+"{\n",
+"ECHO \"Compiler is Microsoft Visual C++ .NET\" ;\n",
+"AR ?= lib ;\n",
+"AS ?= masm386 ;\n",
+"CC ?= cl /nologo ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= link /nologo ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= \\\"$(VISUALC)\\\\PlatformSDK\\\\lib\\\\advapi32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\PlatformSDK\\\\lib\\\\gdi32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\PlatformSDK\\\\lib\\\\user32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\PlatformSDK\\\\lib\\\\kernel32.lib\\\" ;\n",
+"OPTIM ?= \"\" ;\n",
+"STDHDRS ?= \\\"$(VISUALC)\\\\include\\\"\n",
+"\\\"$(VISUALC)\\\\PlatformSDK\\\\include\\\" ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = INTELC\n",
+"{\n",
+"ECHO \"Compiler is Intel C/C++\" ;\n",
+"if ! $(VISUALC)\n",
+"{\n",
+"ECHO \"As a special exception, when using the Intel C++ compiler, you need\" ;\n",
+"ECHO \"to define the VISUALC environment variable to indicate the location\" ;\n",
+"ECHO \"of your Visual C++ installation. Aborting..\" ;\n",
+"EXIT ;\n",
+"}\n",
+"AR ?= lib ;\n",
+"AS ?= masm386 ;\n",
+"CC ?= icl /nologo ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= link /nologo ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= $(VISUALC)\\\\lib\\\\advapi32.lib\n",
+"$(VISUALC)\\\\lib\\\\kernel32.lib\n",
+";\n",
+"OPTIM ?= \"\" ;\n",
+"STDHDRS ?= $(INTELC)\\include $(VISUALC)\\\\include ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = WATCOM\n",
+"{\n",
+"ECHO \"Compiler is Watcom C/C++\" ;\n",
+"AR ?= wlib ;\n",
+"CC ?= wcc386 ;\n",
+"CCFLAGS ?= /zq /DWIN32 /I$(WATCOM)\\\\h ; # zq=quiet\n",
+"C++ ?= wpp386 ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"CP ?= copy ;\n",
+"DOT ?= . ;\n",
+"DOTDOT ?= .. ;\n",
+"LINK ?= wcl386 ;\n",
+"LINKFLAGS ?= /zq ; # zq=quiet\n",
+"LINKLIBS ?= ;\n",
+"MV ?= move ;\n",
+"NOARSCAN ?= true ;\n",
+"OPTIM ?= ;\n",
+"RM ?= del /f ;\n",
+"SLASH ?= \\\\ ;\n",
+"STDHDRS ?= $(WATCOM)\\\\h $(WATCOM)\\\\h\\\\nt ;\n",
+"SUFEXE ?= .exe ;\n",
+"SUFLIB ?= .lib ;\n",
+"SUFOBJ ?= .obj ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = MINGW\n",
+"{\n",
+"ECHO \"Compiler is GCC with Mingw\" ;\n",
+"AR ?= ar -ru ;\n",
+"CC ?= gcc ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= \"\" ;\n",
+"OPTIM ?= ;\n",
+"SUFOBJ = .o ;\n",
+"SUFLIB = .a ;\n",
+"SLASH = / ;\n",
+"}\n",
+"else if $(TOOLSET) = LCC\n",
+"{\n",
+"ECHO \"Compiler is Win32-LCC\" ;\n",
+"AR ?= lcclib ;\n",
+"CC ?= lcc ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= lcclnk ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= \"\" ;\n",
+"OPTIM ?= ;\n",
+"NOARSCAN = true ;\n",
+"}\n",
+"else\n",
+"{\n",
+"EXIT On NT, set BCCROOT, MSVCNT, MINGW or MSVC to the root of the\n",
+"Borland or Microsoft directories. ;\n",
+"}\n",
+"}\n",
+"else if $(OS2)\n",
+"{\n",
+"local SUPPORTED_TOOLSETS = \"EMX\" \"WATCOM\" ;\n",
+"TOOLSET = \"\" ;\n",
+"if $(JAM_TOOLSET)\n",
+"{\n",
+"local t ;\n",
+"for t in $(SUPPORTED_TOOLSETS)\n",
+"{\n",
+"$(t) = $($(t):J=\" \") ; # reconstitute paths with spaces in them\n",
+"if $(t) = $(JAM_TOOLSET) { TOOLSET = $(t) ; }\n",
+"}\n",
+"if ! $(TOOLSET)\n",
+"{\n",
+"ECHO \"The JAM_TOOLSET environment variable is defined but its value\" ;\n",
+"ECHO \"is invalid, please use one of the following:\" ;\n",
+"ECHO ;\n",
+"for t in $(SUPPORTED_TOOLSETS) { ECHO \" \" $(t) ; }\n",
+"EXIT ;\n",
+"}\n",
+"}\n",
+"if ! $(TOOLSET)\n",
+"{\n",
+"if $(watcom)\n",
+"{\n",
+"WATCOM = $(watcom:J=\" \") ;\n",
+"TOOLSET = WATCOM ;\n",
+"}\n",
+"else\n",
+"{\n",
+"ECHO \"Jam cannot be run because you didn't indicate which compilation toolset\" ;\n",
+"ECHO \"to use. To do so, follow these simple instructions:\" ;\n",
+"ECHO ;\n",
+"ECHO \" - define one of the following environment variable, with the\" ;\n",
+"ECHO \" appropriate value according to this list:\" ;\n",
+"ECHO ;\n",
+"ECHO \" Variable Toolset Description\" ;\n",
+"ECHO ;\n",
+"ECHO \" WATCOM Watcom C/C++ Watcom install path\" ;\n",
+"ECHO \" EMX EMX (gcc) EMX install path\" ;\n",
+"ECHO \" VISUALAGE IBM Visual Age C/C++ VisualAge install path\" ;\n",
+"ECHO ;\n",
+"ECHO \" - define the JAM_TOOLSET environment variable with the *name*\" ;\n",
+"ECHO \" of the toolset variable you want to use.\" ;\n",
+"ECHO ;\n",
+"ECHO \" e.g.: set WATCOM=C:\\WATCOM\" ;\n",
+"ECHO \" set JAM_TOOLSET=WATCOM\" ;\n",
+"ECHO ;\n",
+"EXIT ;\n",
+"}\n",
+"}\n",
+"RM = del /f ;\n",
+"CP = copy ;\n",
+"MV ?= move ;\n",
+"DOT ?= . ;\n",
+"DOTDOT ?= .. ;\n",
+"SUFLIB ?= .lib ;\n",
+"SUFOBJ ?= .obj ;\n",
+"SUFEXE ?= .exe ;\n",
+"if $(TOOLSET) = WATCOM\n",
+"{\n",
+"AR ?= wlib ;\n",
+"BINDIR ?= \\\\os2\\\\apps ;\n",
+"CC ?= wcc386 ;\n",
+"CCFLAGS ?= /zq /DOS2 /I$(WATCOM)\\\\h ; # zq=quiet\n",
+"C++ ?= wpp386 ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= wcl386 ;\n",
+"LINKFLAGS ?= /zq ; # zq=quiet\n",
+"LINKLIBS ?= ;\n",
+"NOARSCAN ?= true ;\n",
+"OPTIM ?= ;\n",
+"SLASH ?= \\\\ ;\n",
+"STDHDRS ?= $(WATCOM)\\\\h ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = EMX\n",
+"{\n",
+"ECHO \"Compiler is GCC-EMX\" ;\n",
+"AR ?= ar -ru ;\n",
+"CC ?= gcc ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= \"\" ;\n",
+"OPTIM ?= ;\n",
+"SUFOBJ = .o ;\n",
+"SUFLIB = .a ;\n",
+"UNDEFFLAG ?= \"-U\" ;\n",
+"SLASH = / ;\n",
+"}\n",
+"else\n",
+"{\n",
+"EXIT \"Sorry, but the $(JAM_TOOLSET) toolset isn't supported for now\" ;\n",
+"}\n",
+"}\n",
+"else if $(VMS)\n",
+"{\n",
+"C++ ?= cxx ;\n",
+"C++FLAGS ?= ;\n",
+"CC ?= cc ;\n",
+"CCFLAGS ?= ;\n",
+"CHMOD ?= set file/prot= ;\n",
+"CP ?= copy/replace ;\n",
+"CRELIB ?= true ;\n",
+"DOT ?= [] ;\n",
+"DOTDOT ?= [-] ;\n",
+"EXEMODE ?= (w:e) ;\n",
+"FILEMODE ?= (w:r) ;\n",
+"HDRS ?= ;\n",
+"LINK ?= link ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= ;\n",
+"MKDIR ?= create/dir ;\n",
+"MV ?= rename ;\n",
+"OPTIM ?= \"\" ;\n",
+"RM ?= delete ;\n",
+"RUNVMS ?= mcr ;\n",
+"SHELLMODE ?= (w:er) ;\n",
+"SLASH ?= . ;\n",
+"STDHDRS ?= decc$library_include ;\n",
+"SUFEXE ?= .exe ;\n",
+"SUFLIB ?= .olb ;\n",
+"SUFOBJ ?= .obj ;\n",
+"switch $(OS)\n",
+"{\n",
+"case OPENVMS : CCFLAGS ?= /stand=vaxc ;\n",
+"case VMS : LINKLIBS ?= sys$library:vaxcrtl.olb/lib ;\n",
+"}\n",
+"}\n",
+"else if $(MAC)\n",
+"{\n",
+"local OPT ;\n",
+"CW ?= \"{CW}\" ;\n",
+"MACHDRS ?=\n",
+"\"$(UMACHDRS):Universal:Interfaces:CIncludes\"\n",
+"\"$(CW):MSL:MSL_C:MSL_Common:Include\"\n",
+"\"$(CW):MSL:MSL_C:MSL_MacOS:Include\" ;\n",
+"MACLIBS ?=\n",
+"\"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Interfacelib\"\n",
+"\"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Mathlib\" ;\n",
+"MPWLIBS ?=\n",
+"\"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib\"\n",
+"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW.Lib\" ;\n",
+"MPWNLLIBS ?=\n",
+"\"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib\"\n",
+"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW(NL).Lib\" ;\n",
+"SIOUXHDRS ?= ;\n",
+"SIOUXLIBS ?=\n",
+"\"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL RuntimePPC.lib\"\n",
+"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL SIOUX.PPC.Lib\"\n",
+"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC.Lib\" ;\n",
+"C++ ?= mwcppc ;\n",
+"C++FLAGS ?= -w off -nomapcr ;\n",
+"CC ?= mwcppc ;\n",
+"CCFLAGS ?= -w off -nomapcr ;\n",
+"CP ?= duplicate -y ;\n",
+"DOT ?= \":\" ;\n",
+"DOTDOT ?= \"::\" ;\n",
+"HDRS ?= $(MACHDRS) $(MPWHDRS) ;\n",
+"LINK ?= mwlinkppc ;\n",
+"LINKFLAGS ?= -mpwtool -warn ;\n",
+"LINKLIBS ?= $(MACLIBS) $(MPWLIBS) ;\n",
+"MKDIR ?= newfolder ;\n",
+"MV ?= rename -y ;\n",
+"NOARSCAN ?= true ;\n",
+"OPTIM ?= ;\n",
+"RM ?= delete -y ;\n",
+"SLASH ?= \":\" ;\n",
+"STDHDRS ?= ;\n",
+"SUFLIB ?= .lib ;\n",
+"SUFOBJ ?= .o ;\n",
+"}\n",
+"else if $(OS) = BEOS && $(METROWERKS)\n",
+"{\n",
+"AR ?= mwld -xml -o ;\n",
+"BINDIR ?= /boot/apps ;\n",
+"CC ?= mwcc ;\n",
+"CCFLAGS ?= -nosyspath ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= -nosyspath ;\n",
+"FORTRAN ?= \"\" ;\n",
+"LIBDIR ?= /boot/develop/libraries ;\n",
+"LINK ?= mwld ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"MANDIR ?= /boot/documentation/\"Shell Tools\"/HTML ;\n",
+"NOARSCAN ?= true ;\n",
+"STDHDRS ?= /boot/develop/headers/posix ;\n",
+"}\n",
+"else if $(OS) = BEOS\n",
+"{\n",
+"BINDIR ?= /boot/apps ;\n",
+"CC ?= gcc ;\n",
+"C++ ?= $(CC) ;\n",
+"FORTRAN ?= \"\" ;\n",
+"LIBDIR ?= /boot/develop/libraries ;\n",
+"LINK ?= gcc ;\n",
+"LINKLIBS ?= -lnet ;\n",
+"NOARSCAN ?= true ;\n",
+"STDHDRS ?= /boot/develop/headers/posix ;\n",
+"}\n",
+"else if $(UNIX)\n",
+"{\n",
+"switch $(OS)\n",
+"{\n",
+"case AIX :\n",
+"LINKLIBS ?= -lbsd ;\n",
+"case AMIGA :\n",
+"CC ?= gcc ;\n",
+"YACC ?= \"bison -y\" ;\n",
+"case CYGWIN :\n",
+"CC ?= gcc ;\n",
+"CCFLAGS += -D__cygwin__ ;\n",
+"LEX ?= flex ;\n",
+"RANLIB ?= \"\" ;\n",
+"SUFEXE ?= .exe ;\n",
+"YACC ?= \"bison -y\" ;\n",
+"case DGUX :\n",
+"RANLIB ?= \"\" ;\n",
+"RELOCATE ?= true ;\n",
+"case HPUX :\n",
+"YACC = ;\n",
+"CFLAGS += -Ae ;\n",
+"CCFLAGS += -Ae ;\n",
+"RANLIB ?= \"\" ;\n",
+"case INTERIX :\n",
+"CC ?= gcc ;\n",
+"RANLIB ?= \"\" ;\n",
+"case IRIX :\n",
+"RANLIB ?= \"\" ;\n",
+"case MPEIX :\n",
+"CC ?= gcc ;\n",
+"C++ ?= gcc ;\n",
+"CCFLAGS += -D_POSIX_SOURCE ;\n",
+"HDRS += /usr/include ;\n",
+"RANLIB ?= \"\" ;\n",
+"NOARSCAN ?= true ;\n",
+"NOARUPDATE ?= true ;\n",
+"case MVS :\n",
+"RANLIB ?= \"\" ;\n",
+"case NEXT :\n",
+"AR ?= libtool -o ;\n",
+"RANLIB ?= \"\" ;\n",
+"case MACOSX :\n",
+"AR ?= libtool -o ;\n",
+"C++ ?= c++ ;\n",
+"MANDIR ?= /usr/local/share/man ;\n",
+"RANLIB ?= \"\" ;\n",
+"case NCR :\n",
+"RANLIB ?= \"\" ;\n",
+"case PTX :\n",
+"RANLIB ?= \"\" ;\n",
+"case QNX :\n",
+"AR ?= wlib ;\n",
+"CC ?= cc ;\n",
+"CCFLAGS ?= -Q ; # quiet\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= -Q ; # quiet\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= -Q ; # quiet\n",
+"NOARSCAN ?= true ;\n",
+"RANLIB ?= \"\" ;\n",
+"case SCO :\n",
+"RANLIB ?= \"\" ;\n",
+"RELOCATE ?= true ;\n",
+"case SINIX :\n",
+"RANLIB ?= \"\" ;\n",
+"case SOLARIS :\n",
+"RANLIB ?= \"\" ;\n",
+"AR ?= \"/usr/ccs/bin/ar ru\" ;\n",
+"case UNICOS :\n",
+"NOARSCAN ?= true ;\n",
+"OPTIM ?= -O0 ;\n",
+"case UNIXWARE :\n",
+"RANLIB ?= \"\" ;\n",
+"RELOCATE ?= true ;\n",
+"}\n",
+"CCFLAGS ?= ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"CHMOD ?= chmod ;\n",
+"CHGRP ?= chgrp ;\n",
+"CHOWN ?= chown ;\n",
+"LEX ?= lex ;\n",
+"LINKFLAGS ?= $(CCFLAGS) ;\n",
+"LINKLIBS ?= ;\n",
+"OPTIM ?= -O ;\n",
+"RANLIB ?= ranlib ;\n",
+"YACC ?= yacc ;\n",
+"YACCFILES ?= y.tab ;\n",
+"YACCFLAGS ?= -d ;\n",
+"}\n",
+"AR ?= ar ru ;\n",
+"AS ?= as ;\n",
+"ASFLAGS ?= ;\n",
+"AWK ?= awk ;\n",
+"BINDIR ?= /usr/local/bin ;\n",
+"C++ ?= cc ;\n",
+"C++FLAGS ?= ;\n",
+"CC ?= cc ;\n",
+"CCFLAGS ?= ;\n",
+"CP ?= cp -f ;\n",
+"CRELIB ?= ;\n",
+"DOT ?= . ;\n",
+"DOTDOT ?= .. ;\n",
+"EXEMODE ?= 711 ;\n",
+"FILEMODE ?= 644 ;\n",
+"FORTRAN ?= f77 ;\n",
+"FORTRANFLAGS ?= ;\n",
+"HDRS ?= ;\n",
+"INSTALLGRIST ?= installed ;\n",
+"JAMFILE ?= Jamfile ;\n",
+"JAMRULES ?= Jamrules ;\n",
+"LEX ?= ;\n",
+"LIBDIR ?= /usr/local/lib ;\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= ;\n",
+"LINKLIBS ?= ;\n",
+"LN ?= ln ;\n",
+"MANDIR ?= /usr/local/man ;\n",
+"MKDIR ?= mkdir ;\n",
+"MV ?= mv -f ;\n",
+"OPTIM ?= ;\n",
+"RCP ?= rcp ;\n",
+"RM ?= rm -f ;\n",
+"RSH ?= rsh ;\n",
+"SED ?= sed ;\n",
+"SHELLHEADER ?= \"#!/bin/sh\" ;\n",
+"SHELLMODE ?= 755 ;\n",
+"SLASH ?= / ;\n",
+"STDHDRS ?= /usr/include ;\n",
+"SUFEXE ?= \"\" ;\n",
+"SUFLIB ?= .a ;\n",
+"SUFOBJ ?= .o ;\n",
+"UNDEFFLAG ?= \"-u _\" ;\n",
+"YACC ?= ;\n",
+"YACCFILES ?= ;\n",
+"YACCFLAGS ?= ;\n",
+"HDRPATTERN =\n",
+"\"^[ ]*#[ ]*include[ ]*[<\\\"]([^\\\">]*)[\\\">].*$\" ;\n",
+"OSFULL = $(OS)$(OSVER)$(OSPLAT) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ;\n",
+"DEPENDS all : shell files lib exe obj ;\n",
+"DEPENDS all shell files lib exe obj : first ;\n",
+"NOTFILE all first shell files lib exe obj dirs clean uninstall ;\n",
+"ALWAYS clean uninstall ;\n",
+"rule As\n",
+"{\n",
+"DEPENDS $(<) : $(>) ;\n",
+"ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;\n",
+"}\n",
+"rule Bulk\n",
+"{\n",
+"local i ;\n",
+"for i in $(>)\n",
+"{\n",
+"File $(i:D=$(<)) : $(i) ;\n",
+"}\n",
+"}\n",
+"rule Cc\n",
+"{\n",
+"local _h ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) ;\n",
+"if $(RELOCATE)\n",
+"{\n",
+"CcMv $(<) : $(>) ;\n",
+"}\n",
+"_h = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;\n",
+"if $(VMS) && $(_h)\n",
+"{\n",
+"SLASHINC on $(<) = \"/inc=(\" $(_h[1]) ,$(_h[2-]) \")\" ;\n",
+"}\n",
+"else if $(MAC) && $(_h)\n",
+"{\n",
+"local _i _j ;\n",
+"_j = $(_h[1]) ;\n",
+"for _i in $(_h[2-])\n",
+"{\n",
+"_j = $(_j),$(_i) ;\n",
+"}\n",
+"MACINC on $(<) = \\\"$(_j)\\\" ;\n",
+"}\n",
+"}\n",
+"rule C++\n",
+"{\n",
+"local _h ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"C++FLAGS on $(<) += $(C++FLAGS) $(SUBDIRC++FLAGS) ;\n",
+"if $(RELOCATE)\n",
+"{\n",
+"CcMv $(<) : $(>) ;\n",
+"}\n",
+"_h = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;\n",
+"if $(VMS) && $(_h)\n",
+"{\n",
+"SLASHINC on $(<) = \"/inc=(\" $(_h[1]) ,$(_h[2-]) \")\" ;\n",
+"}\n",
+"else if $(MAC) && $(_h)\n",
+"{\n",
+"local _i _j ;\n",
+"_j = $(_h[1]) ;\n",
+"for _i in $(_h[2-])\n",
+"{\n",
+"_j = $(_j),$(_i) ;\n",
+"}\n",
+"MACINC on $(<) = \\\"$(_j)\\\" ;\n",
+"}\n",
+"}\n",
+"rule Chmod\n",
+"{\n",
+"if $(CHMOD) { Chmod1 $(<) ; }\n",
+"}\n",
+"rule File\n",
+"{\n",
+"DEPENDS files : $(<) ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"MODE on $(<) = $(FILEMODE) ;\n",
+"Chmod $(<) ;\n",
+"}\n",
+"rule Fortran\n",
+"{\n",
+"DEPENDS $(<) : $(>) ;\n",
+"}\n",
+"rule GenFile\n",
+"{\n",
+"local _t = [ FGristSourceFiles $(<) ] ;\n",
+"local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;\n",
+"Depends $(_t) : $(_s) $(>[2-]) ;\n",
+"GenFile1 $(_t) : $(_s) $(>[2-]) ;\n",
+"Clean clean : $(_t) ;\n",
+"}\n",
+"rule GenFile1\n",
+"{\n",
+"MakeLocate $(<) : $(LOCATE_SOURCE) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"}\n",
+"rule HardLink\n",
+"{\n",
+"DEPENDS files : $(<) ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"}\n",
+"rule HdrMacroFile\n",
+"{\n",
+"HDRMACRO $(<) ;\n",
+"}\n",
+"rule HdrRule\n",
+"{\n",
+"local s ;\n",
+"if $(HDRGRIST)\n",
+"{\n",
+"s = $(>:G=$(HDRGRIST)) ;\n",
+"} else {\n",
+"s = $(>) ;\n",
+"}\n",
+"INCLUDES $(<) : $(s) ;\n",
+"SEARCH on $(s) = $(HDRSEARCH) ;\n",
+"NOCARE $(s) ;\n",
+"HDRSEARCH on $(s) = $(HDRSEARCH) ;\n",
+"HDRSCAN on $(s) = $(HDRSCAN) ;\n",
+"HDRRULE on $(s) = $(HDRRULE) ;\n",
+"HDRGRIST on $(s) = $(HDRGRIST) ;\n",
+"}\n",
+"rule InstallInto\n",
+"{\n",
+"local i t ;\n",
+"t = $(>:G=$(INSTALLGRIST)) ;\n",
+"Depends install : $(t) ;\n",
+"Clean uninstall : $(t) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"MakeLocate $(t) : $(<) ;\n",
+"for i in $(>)\n",
+"{\n",
+"local tt = $(i:G=$(INSTALLGRIST)) ;\n",
+"Depends $(tt) : $(i) ;\n",
+"Install $(tt) : $(i) ;\n",
+"Chmod $(tt) ;\n",
+"if $(OWNER) && $(CHOWN)\n",
+"{\n",
+"Chown $(tt) ;\n",
+"OWNER on $(tt) = $(OWNER) ;\n",
+"}\n",
+"if $(GROUP) && $(CHGRP)\n",
+"{\n",
+"Chgrp $(tt) ;\n",
+"GROUP on $(tt) = $(GROUP) ;\n",
+"}\n",
+"}\n",
+"}\n",
+"rule InstallBin\n",
+"{\n",
+"local _t = [ FAppendSuffix $(>) : $(SUFEXE) ] ;\n",
+"InstallInto $(<) : $(_t) ;\n",
+"MODE on $(_t:G=installed) = $(EXEMODE) ;\n",
+"}\n",
+"rule InstallFile\n",
+"{\n",
+"InstallInto $(<) : $(>) ;\n",
+"MODE on $(>:G=installed) = $(FILEMODE) ;\n",
+"}\n",
+"rule InstallLib\n",
+"{\n",
+"InstallInto $(<) : $(>) ;\n",
+"MODE on $(>:G=installed) = $(FILEMODE) ;\n",
+"}\n",
+"rule InstallMan\n",
+"{\n",
+"local i s d ;\n",
+"for i in $(>)\n",
+"{\n",
+"switch $(i:S)\n",
+"{\n",
+"case .1 : s = 1 ; case .2 : s = 2 ; case .3 : s = 3 ;\n",
+"case .4 : s = 4 ; case .5 : s = 5 ; case .6 : s = 6 ;\n",
+"case .7 : s = 7 ; case .8 : s = 8 ; case .l : s = l ;\n",
+"case .n : s = n ; case .man : s = 1 ;\n",
+"}\n",
+"d = man$(s) ;\n",
+"InstallInto $(d:R=$(<)) : $(i) ;\n",
+"}\n",
+"MODE on $(>:G=installed) = $(FILEMODE) ;\n",
+"}\n",
+"rule InstallShell\n",
+"{\n",
+"InstallInto $(<) : $(>) ;\n",
+"MODE on $(>:G=installed) = $(SHELLMODE) ;\n",
+"}\n",
+"rule Lex\n",
+"{\n",
+"LexMv $(<) : $(>) ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"MakeLocate $(<) : $(LOCATE_SOURCE) ;\n",
+"Clean clean : $(<) ;\n",
+"}\n",
+"rule Library\n",
+"{\n",
+"LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ;\n",
+"Objects $(>) ;\n",
+"}\n",
+"rule LibraryFromObjects\n",
+"{\n",
+"local _i _l _s ;\n",
+"_s = [ FGristFiles $(>) ] ;\n",
+"_l = $(<:S=$(SUFLIB)) ;\n",
+"if $(KEEPOBJS)\n",
+"{\n",
+"DEPENDS obj : $(_s) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"DEPENDS lib : $(_l) ;\n",
+"}\n",
+"if ! $(_l:D)\n",
+"{\n",
+"MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ;\n",
+"}\n",
+"if $(NOARSCAN)\n",
+"{\n",
+"DEPENDS $(_l) : $(_s) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"DEPENDS $(_l) : $(_l)($(_s:BS)) ;\n",
+"for _i in $(_s)\n",
+"{\n",
+"DEPENDS $(_l)($(_i:BS)) : $(_i) ;\n",
+"}\n",
+"}\n",
+"Clean clean : $(_l) ;\n",
+"if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; }\n",
+"Archive $(_l) : $(_s) ;\n",
+"if $(RANLIB) { Ranlib $(_l) ; }\n",
+"if ! ( $(NOARSCAN) || $(KEEPOBJS) ) { RmTemps $(_l) : $(_s) ; }\n",
+"}\n",
+"rule Link\n",
+"{\n",
+"MODE on $(<) = $(EXEMODE) ;\n",
+"Chmod $(<) ;\n",
+"}\n",
+"rule LinkLibraries\n",
+"{\n",
+"local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;\n",
+"DEPENDS $(_t) : $(>:S=$(SUFLIB)) ;\n",
+"NEEDLIBS on $(_t) += $(>:S=$(SUFLIB)) ;\n",
+"}\n",
+"rule Main\n",
+"{\n",
+"MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;\n",
+"Objects $(>) ;\n",
+"}\n",
+"rule MainFromObjects\n",
+"{\n",
+"local _s _t ;\n",
+"_s = [ FGristFiles $(>) ] ;\n",
+"_t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;\n",
+"if $(_t) != $(<)\n",
+"{\n",
+"DEPENDS $(<) : $(_t) ;\n",
+"NOTFILE $(<) ;\n",
+"}\n",
+"DEPENDS exe : $(_t) ;\n",
+"DEPENDS $(_t) : $(_s) ;\n",
+"MakeLocate $(_t) : $(LOCATE_TARGET) ;\n",
+"Clean clean : $(_t) ;\n",
+"Link $(_t) : $(_s) ;\n",
+"}\n",
+"rule MakeLocate\n",
+"{\n",
+"if $(>)\n",
+"{\n",
+"LOCATE on $(<) = $(>) ;\n",
+"Depends $(<) : $(>[1]) ;\n",
+"MkDir $(>[1]) ;\n",
+"}\n",
+"}\n",
+"rule MkDir\n",
+"{\n",
+"NOUPDATE $(<) ;\n",
+"if $(<) != $(DOT) && ! $($(<)-mkdir)\n",
+"{\n",
+"local s ;\n",
+"$(<)-mkdir = true ;\n",
+"MkDir1 $(<) ;\n",
+"Depends dirs : $(<) ;\n",
+"s = $(<:P) ;\n",
+"if $(NT)\n",
+"{\n",
+"switch $(s)\n",
+"{\n",
+"case *: : s = ;\n",
+"case *:\\\\ : s = ;\n",
+"}\n",
+"}\n",
+"if $(s) && $(s) != $(<)\n",
+"{\n",
+"Depends $(<) : $(s) ;\n",
+"MkDir $(s) ;\n",
+"}\n",
+"else if $(s)\n",
+"{\n",
+"NOTFILE $(s) ;\n",
+"}\n",
+"}\n",
+"}\n",
+"rule Object\n",
+"{\n",
+"local h ;\n",
+"Clean clean : $(<) ;\n",
+"MakeLocate $(<) : $(LOCATE_TARGET) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"HDRS on $(<) = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;\n",
+"if $(SEARCH_SOURCE)\n",
+"{\n",
+"h = $(SEARCH_SOURCE) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"h = \"\" ;\n",
+"}\n",
+"HDRRULE on $(>) = HdrRule ;\n",
+"HDRSCAN on $(>) = $(HDRPATTERN) ;\n",
+"HDRSEARCH on $(>) = $(HDRS) $(SUBDIRHDRS) $(h) $(STDHDRS) ;\n",
+"HDRGRIST on $(>) = $(HDRGRIST) ;\n",
+"switch $(>:S)\n",
+"{\n",
+"case .asm : As $(<) : $(>) ;\n",
+"case .c : Cc $(<) : $(>) ;\n",
+"case .C : C++ $(<) : $(>) ;\n",
+"case .cc : C++ $(<) : $(>) ;\n",
+"case .cpp : C++ $(<) : $(>) ;\n",
+"case .f : Fortran $(<) : $(>) ;\n",
+"case .l : Cc $(<) : $(<:S=.c) ;\n",
+"Lex $(<:S=.c) : $(>) ;\n",
+"case .s : As $(<) : $(>) ;\n",
+"case .y : Cc $(<) : $(<:S=.c) ;\n",
+"Yacc $(<:S=.c) : $(>) ;\n",
+"case * : UserObject $(<) : $(>) ;\n",
+"}\n",
+"}\n",
+"rule ObjectCcFlags\n",
+"{\n",
+"CCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;\n",
+"}\n",
+"rule ObjectC++Flags\n",
+"{\n",
+"C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;\n",
+"}\n",
+"rule ObjectHdrs\n",
+"{\n",
+"HDRS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;\n",
+"}\n",
+"rule Objects\n",
+"{\n",
+"local _i ;\n",
+"for _i in [ FGristFiles $(<) ]\n",
+"{\n",
+"Object $(_i:S=$(SUFOBJ)) : $(_i) ;\n",
+"DEPENDS obj : $(_i:S=$(SUFOBJ)) ;\n",
+"}\n",
+"}\n",
+"rule RmTemps\n",
+"{\n",
+"TEMPORARY $(>) ;\n",
+"}\n",
+"rule Setuid\n",
+"{\n",
+"MODE on [ FAppendSuffix $(<) : $(SUFEXE) ] = 4711 ;\n",
+"}\n",
+"rule Shell\n",
+"{\n",
+"DEPENDS shell : $(<) ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"MODE on $(<) = $(SHELLMODE) ;\n",
+"Clean clean : $(<) ;\n",
+"Chmod $(<) ;\n",
+"}\n",
+"rule SubDir\n",
+"{\n",
+"local _r _s ;\n",
+"if ! $($(<[1]))\n",
+"{\n",
+"if ! $(<[1])\n",
+"{\n",
+"EXIT SubDir syntax error ;\n",
+"}\n",
+"$(<[1]) = [ FSubDir $(<[2-]) ] ;\n",
+"}\n",
+"if ! $($(<[1])-included)\n",
+"{\n",
+"$(<[1])-included = TRUE ;\n",
+"_r = $($(<[1])RULES) ;\n",
+"if ! $(_r)\n",
+"{\n",
+"_r = $(JAMRULES:R=$($(<[1]))) ;\n",
+"}\n",
+"include $(_r) ;\n",
+"}\n",
+"_s = [ FDirName $(<[2-]) ] ;\n",
+"SUBDIR = $(_s:R=$($(<[1]))) ;\n",
+"SUBDIR_TOKENS = $(<[2-]) ;\n",
+"SEARCH_SOURCE = $(SUBDIR) ;\n",
+"LOCATE_SOURCE = $(ALL_LOCATE_TARGET) $(SUBDIR) ;\n",
+"LOCATE_TARGET = $(ALL_LOCATE_TARGET) $(SUBDIR) ;\n",
+"SOURCE_GRIST = [ FGrist $(<[2-]) ] ;\n",
+"SUBDIRCCFLAGS = ;\n",
+"SUBDIRC++FLAGS = ;\n",
+"SUBDIRHDRS = ;\n",
+"}\n",
+"rule SubDirCcFlags\n",
+"{\n",
+"SUBDIRCCFLAGS += $(<) ;\n",
+"}\n",
+"rule SubDirC++Flags\n",
+"{\n",
+"SUBDIRC++FLAGS += $(<) ;\n",
+"}\n",
+"rule SubDirHdrs\n",
+"{\n",
+"SUBDIRHDRS += $(<) ;\n",
+"}\n",
+"rule SubInclude\n",
+"{\n",
+"local _s ;\n",
+"if ! $($(<[1]))\n",
+"{\n",
+"EXIT Top level of source tree has not been set with $(<[1]) ;\n",
+"}\n",
+"_s = [ FDirName $(<[2-]) ] ;\n",
+"include $(JAMFILE:D=$(_s):R=$($(<[1]))) ;\n",
+"}\n",
+"rule Undefines\n",
+"{\n",
+"UNDEFS on [ FAppendSuffix $(<) : $(SUFEXE) ] += $(UNDEFFLAG)$(>) ;\n",
+"}\n",
+"rule UserObject\n",
+"{\n",
+"EXIT \"Unknown suffix on\" $(>) \"- see UserObject rule in Jamfile(5).\" ;\n",
+"}\n",
+"rule Yacc\n",
+"{\n",
+"local _h ;\n",
+"_h = $(<:BS=.h) ;\n",
+"MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ;\n",
+"if $(YACC)\n",
+"{\n",
+"DEPENDS $(<) $(_h) : $(>) ;\n",
+"Yacc1 $(<) $(_h) : $(>) ;\n",
+"YaccMv $(<) $(_h) : $(>) ;\n",
+"Clean clean : $(<) $(_h) ;\n",
+"}\n",
+"INCLUDES $(<) : $(_h) ;\n",
+"}\n",
+"rule FGrist\n",
+"{\n",
+"local _g _i ;\n",
+"_g = $(<[1]) ;\n",
+"for _i in $(<[2-])\n",
+"{\n",
+"_g = $(_g)!$(_i) ;\n",
+"}\n",
+"return $(_g) ;\n",
+"}\n",
+"rule FGristFiles\n",
+"{\n",
+"if ! $(SOURCE_GRIST)\n",
+"{\n",
+"return $(<) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"return $(<:G=$(SOURCE_GRIST)) ;\n",
+"}\n",
+"}\n",
+"rule FGristSourceFiles\n",
+"{\n",
+"if ! $(SOURCE_GRIST)\n",
+"{\n",
+"return $(<) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"local _i _o ;\n",
+"for _i in $(<)\n",
+"{\n",
+"switch $(_i)\n",
+"{\n",
+"case *.h : _o += $(_i) ;\n",
+"case * : _o += $(_i:G=$(SOURCE_GRIST)) ;\n",
+"}\n",
+"}\n",
+"return $(_o) ;\n",
+"}\n",
+"}\n",
+"rule FConcat\n",
+"{\n",
+"local _t _r ;\n",
+"$(_r) = $(<[1]) ;\n",
+"for _t in $(<[2-])\n",
+"{\n",
+"$(_r) = $(_r)$(_t) ;\n",
+"}\n",
+"return $(_r) ;\n",
+"}\n",
+"rule FSubDir\n",
+"{\n",
+"local _i _d ;\n",
+"if ! $(<[1])\n",
+"{\n",
+"_d = $(DOT) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"_d = $(DOTDOT) ;\n",
+"for _i in $(<[2-])\n",
+"{\n",
+"_d = $(_d:R=$(DOTDOT)) ;\n",
+"}\n",
+"}\n",
+"return $(_d) ;\n",
+"}\n",
+"rule FDirName\n",
+"{\n",
+"local _s _i ;\n",
+"if ! $(<)\n",
+"{\n",
+"_s = $(DOT) ;\n",
+"}\n",
+"else if $(VMS)\n",
+"{\n",
+"switch $(<[1])\n",
+"{\n",
+"case *:* : _s = $(<[1]) ;\n",
+"case \\\\[*\\\\] : _s = $(<[1]) ;\n",
+"case * : _s = [.$(<[1])] ;\n",
+"}\n",
+"for _i in [.$(<[2-])]\n",
+"{\n",
+"_s = $(_i:R=$(_s)) ;\n",
+"}\n",
+"}\n",
+"else if $(MAC)\n",
+"{\n",
+"_s = $(DOT) ;\n",
+"for _i in $(<)\n",
+"{\n",
+"_s = $(_i:R=$(_s)) ;\n",
+"}\n",
+"}\n",
+"else\n",
+"{\n",
+"_s = $(<[1]) ;\n",
+"for _i in $(<[2-])\n",
+"{\n",
+"_s = $(_i:R=$(_s)) ;\n",
+"}\n",
+"}\n",
+"return $(_s) ;\n",
+"}\n",
+"rule _makeCommon\n",
+"{\n",
+"if $($(<)[1]) && $($(<)[1]) = $($(>)[1])\n",
+"{\n",
+"$(<) = $($(<)[2-]) ;\n",
+"$(>) = $($(>)[2-]) ;\n",
+"_makeCommon $(<) : $(>) ;\n",
+"}\n",
+"}\n",
+"rule FRelPath\n",
+"{\n",
+"local _l _r ;\n",
+"_l = $(<) ;\n",
+"_r = $(>) ;\n",
+"_makeCommon _l : _r ;\n",
+"_l = [ FSubDir $(_l) ] ;\n",
+"_r = [ FDirName $(_r) ] ;\n",
+"if $(_r) = $(DOT) {\n",
+"return $(_l) ;\n",
+"} else {\n",
+"return $(_r:R=$(_l)) ;\n",
+"}\n",
+"}\n",
+"rule FAppendSuffix\n",
+"{\n",
+"if $(>)\n",
+"{\n",
+"local _i _o ;\n",
+"for _i in $(<)\n",
+"{\n",
+"if $(_i:S)\n",
+"{\n",
+"_o += $(_i) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"_o += $(_i:S=$(>)) ;\n",
+"}\n",
+"}\n",
+"return $(_o) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"return $(<) ;\n",
+"}\n",
+"}\n",
+"rule unmakeDir\n",
+"{\n",
+"if $(>[1]:D) && $(>[1]:D) != $(>[1]) && $(>[1]:D) != \\\\\\\\\n",
+"{\n",
+"unmakeDir $(<) : $(>[1]:D) $(>[1]:BS) $(>[2-]) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"$(<) = $(>) ;\n",
+"}\n",
+"}\n",
+"rule FConvertToSlashes\n",
+"{\n",
+"local _d, _s, _i ;\n",
+"unmakeDir _d : $(<) ;\n",
+"_s = $(_d[1]) ;\n",
+"for _i in $(_d[2-])\n",
+"{\n",
+"_s = $(_s)/$(_i) ;\n",
+"}\n",
+"return $(_s) ;\n",
+"}\n",
+"actions updated together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) $(>)\n",
+"}\n",
+"actions As\n",
+"{\n",
+"$(AS) $(ASFLAGS) -I$(HDRS) -o $(<) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)\n",
+"}\n",
+"actions Chgrp\n",
+"{\n",
+"$(CHGRP) $(GROUP) $(<)\n",
+"}\n",
+"actions Chmod1\n",
+"{\n",
+"$(CHMOD) $(MODE) $(<)\n",
+"}\n",
+"actions Chown\n",
+"{\n",
+"$(CHOWN) $(OWNER) $(<)\n",
+"}\n",
+"actions piecemeal together existing Clean\n",
+"{\n",
+"$(RM) $(>)\n",
+"}\n",
+"actions File\n",
+"{\n",
+"$(CP) $(>) $(<)\n",
+"}\n",
+"actions GenFile1\n",
+"{\n",
+"$(>[1]) $(<) $(>[2-])\n",
+"}\n",
+"actions Fortran\n",
+"{\n",
+"$(FORTRAN) $(FORTRANFLAGS) -o $(<) $(>)\n",
+"}\n",
+"actions HardLink\n",
+"{\n",
+"$(RM) $(<) && $(LN) $(>) $(<)\n",
+"}\n",
+"actions Install\n",
+"{\n",
+"$(CP) $(>) $(<)\n",
+"}\n",
+"actions Lex\n",
+"{\n",
+"$(LEX) $(>)\n",
+"}\n",
+"actions LexMv\n",
+"{\n",
+"$(MV) lex.yy.c $(<)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
+"}\n",
+"actions MkDir1\n",
+"{\n",
+"$(MKDIR) $(<)\n",
+"}\n",
+"actions together Ranlib\n",
+"{\n",
+"$(RANLIB) $(<)\n",
+"}\n",
+"actions quietly updated piecemeal together RmTemps\n",
+"{\n",
+"$(RM) $(>)\n",
+"}\n",
+"actions Shell\n",
+"{\n",
+"$(AWK) '\n",
+"NR == 1 { print \"$(SHELLHEADER)\" }\n",
+"NR == 1 && /^[#:]/ { next }\n",
+"/^##/ { next }\n",
+"{ print }\n",
+"' < $(>) > $(<)\n",
+"}\n",
+"actions Yacc1\n",
+"{\n",
+"$(YACC) $(YACCFLAGS) $(>)\n",
+"}\n",
+"actions YaccMv\n",
+"{\n",
+"$(MV) $(YACCFILES).c $(<[1])\n",
+"$(MV) $(YACCFILES).h $(<[2])\n",
+"}\n",
+"if $(RELOCATE)\n",
+"{\n",
+"actions C++\n",
+"{\n",
+"$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) $(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) $(>)\n",
+"}\n",
+"actions ignore CcMv\n",
+"{\n",
+"[ $(<) != $(>:BS=$(SUFOBJ)) ] && $(MV) $(>:BS=$(SUFOBJ)) $(<)\n",
+"}\n",
+"}\n",
+"if $(NOARUPDATE)\n",
+"{\n",
+"actions Archive\n",
+"{\n",
+"$(AR) $(<) $(>)\n",
+"}\n",
+"}\n",
+"if $(NT)\n",
+"{\n",
+"if $(TOOLSET) = VISUALC || $(TOOLSET) = VC7 || $(TOOLSET) = INTELC\n",
+"{\n",
+"actions updated together piecemeal Archive\n",
+"{\n",
+"if exist $(<) set _$(<:B)_=$(<)\n",
+"$(AR) /out:$(<) %_$(<:B)_% $(>)\n",
+"}\n",
+"actions As\n",
+"{\n",
+"$(AS) /Ml /p /v /w2 $(>) $(<) ,nul,nul;\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) /c $(CCFLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) /c $(C++FLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) /Tp$(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = VISUALC16\n",
+"{\n",
+"actions updated together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) -+$(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) /c $(CCFLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) /c $(C++FLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /Tp$(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = BORLANDC\n",
+"{\n",
+"actions updated together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) -+$(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) -e$(<) $(LINKFLAGS) $(UNDEFS) -L$(LINKLIBS) $(NEEDLIBS) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = MINGW\n",
+"{\n",
+"actions together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) $(>:T)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = WATCOM\n",
+"{\n",
+"actions together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) +-$(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) $(CCFLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) $(C++FLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
+"}\n",
+"actions Shell\n",
+"{\n",
+"$(CP) $(>) $(<)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = LCC\n",
+"{\n",
+"actions together piecemeal Archive\n",
+"{\n",
+"$(AR) /out:$(<) $(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) $(CCFLAGS) $(OPTIM) -Fo$(<) -I$(HDRS) $(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
+"}\n",
+"actions Shell\n",
+"{\n",
+"$(CP) $(>) $(<)\n",
+"}\n",
+"}\n",
+"}\n",
+"else if $(OS2)\n",
+"{\n",
+"if $(TOOLSET) = WATCOM\n",
+"{\n",
+"actions together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) +-$(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) $(CCFLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) $(C++FLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
+"}\n",
+"actions Shell\n",
+"{\n",
+"$(CP) $(>) $(<)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = EMX\n",
+"{\n",
+"actions together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) $(>:T)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"}\n",
+"}\n",
+"else if $(VMS)\n",
+"{\n",
+"actions updated together piecemeal Archive\n",
+"{\n",
+"lib/replace $(<) $(>[1]) ,$(>[2-])\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC)/obj=$(<) $(CCFLAGS) $(OPTIM) $(SLASHINC) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++)/obj=$(<) $(C++FLAGS) $(OPTIM) $(SLASHINC) $(>)\n",
+"}\n",
+"actions piecemeal together existing Clean\n",
+"{\n",
+"$(RM) $(>[1]);* ,$(>[2-]);*\n",
+"}\n",
+"actions together quietly CreLib\n",
+"{\n",
+"if f$search(\"$(<)\") .eqs. \"\" then lib/create $(<)\n",
+"}\n",
+"actions GenFile1\n",
+"{\n",
+"mcr $(>[1]) $(<) $(>[2-])\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK)/exe=$(<) $(LINKFLAGS) $(>[1]) ,$(>[2-]) ,$(NEEDLIBS)/lib ,$(LINKLIBS)\n",
+"}\n",
+"actions quietly updated piecemeal together RmTemps\n",
+"{\n",
+"$(RM) $(>[1]);* ,$(>[2-]);*\n",
+"}\n",
+"actions Shell\n",
+"{\n",
+"$(CP) $(>) $(<)\n",
+"}\n",
+"}\n",
+"else if $(MAC)\n",
+"{\n",
+"actions together Archive\n",
+"{\n",
+"$(LINK) -library -o $(<) $(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"set -e MWCincludes $(MACINC)\n",
+"$(CC) -o $(<) $(CCFLAGS) $(OPTIM) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"set -e MWCincludes $(MACINC)\n",
+"$(CC) -o $(<) $(C++FLAGS) $(OPTIM) $(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) -o $(<) $(LINKFLAGS) $(>) $(NEEDLIBS) \"$(LINKLIBS)\"\n",
+"}\n",
+"}\n",
+"rule BULK { Bulk $(<) : $(>) ; }\n",
+"rule FILE { File $(<) : $(>) ; }\n",
+"rule HDRRULE { HdrRule $(<) : $(>) ; }\n",
+"rule INSTALL { Install $(<) : $(>) ; }\n",
+"rule LIBRARY { Library $(<) : $(>) ; }\n",
+"rule LIBS { LinkLibraries $(<) : $(>) ; }\n",
+"rule LINK { Link $(<) : $(>) ; }\n",
+"rule MAIN { Main $(<) : $(>) ; }\n",
+"rule SETUID { Setuid $(<) ; }\n",
+"rule SHELL { Shell $(<) : $(>) ; }\n",
+"rule UNDEFINES { Undefines $(<) : $(>) ; }\n",
+"rule INSTALLBIN { InstallBin $(BINDIR) : $(<) ; }\n",
+"rule INSTALLLIB { InstallLib $(LIBDIR) : $(<) ; }\n",
+"rule INSTALLMAN { InstallMan $(MANDIR) : $(<) ; }\n",
+"rule addDirName { $(<) += [ FDirName $(>) ] ; }\n",
+"rule makeDirName { $(<) = [ FDirName $(>) ] ; }\n",
+"rule makeGristedName { $(<) = [ FGristSourceFiles $(>) ] ; }\n",
+"rule makeRelPath { $(<[1]) = [ FRelPath $(<[2-]) : $(>) ] ; }\n",
+"rule makeSuffixed { $(<[1]) = [ FAppendSuffix $(>) : $(<[2]) ] ; }\n",
+"{\n",
+"if $(JAMFILE) { include $(JAMFILE) ; }\n",
+"}\n",
+"}\n",
+0 };
diff --git a/tools/build/v2/engine/jambase.h b/tools/build/v2/engine/jambase.h
new file mode 100644
index 0000000000..c05ec79225
--- /dev/null
+++ b/tools/build/v2/engine/jambase.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * jambase.h - declaration for the internal jambase
+ *
+ * The file Jambase is turned into a C array of strings in jambase.c
+ * so that it can be built in to the executable. This is the
+ * declaration for that array.
+ */
+
+extern char *jambase[];
diff --git a/tools/build/v2/engine/jamgram.c b/tools/build/v2/engine/jamgram.c
new file mode 100644
index 0000000000..b1fa0835df
--- /dev/null
+++ b/tools/build/v2/engine/jamgram.c
@@ -0,0 +1,1830 @@
+/* A Bison parser, made by GNU Bison 1.875. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Written by Richard Stallman by simplifying the original so called
+ ``semantic'' parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ _BANG_t = 258,
+ _BANG_EQUALS_t = 259,
+ _AMPER_t = 260,
+ _AMPERAMPER_t = 261,
+ _LPAREN_t = 262,
+ _RPAREN_t = 263,
+ _PLUS_EQUALS_t = 264,
+ _COLON_t = 265,
+ _SEMIC_t = 266,
+ _LANGLE_t = 267,
+ _LANGLE_EQUALS_t = 268,
+ _EQUALS_t = 269,
+ _RANGLE_t = 270,
+ _RANGLE_EQUALS_t = 271,
+ _QUESTION_EQUALS_t = 272,
+ _LBRACKET_t = 273,
+ _RBRACKET_t = 274,
+ ACTIONS_t = 275,
+ BIND_t = 276,
+ CASE_t = 277,
+ CLASS_t = 278,
+ DEFAULT_t = 279,
+ ELSE_t = 280,
+ EXISTING_t = 281,
+ FOR_t = 282,
+ IF_t = 283,
+ IGNORE_t = 284,
+ IN_t = 285,
+ INCLUDE_t = 286,
+ LOCAL_t = 287,
+ MODULE_t = 288,
+ ON_t = 289,
+ PIECEMEAL_t = 290,
+ QUIETLY_t = 291,
+ RETURN_t = 292,
+ RULE_t = 293,
+ SWITCH_t = 294,
+ TOGETHER_t = 295,
+ UPDATED_t = 296,
+ WHILE_t = 297,
+ _LBRACE_t = 298,
+ _BAR_t = 299,
+ _BARBAR_t = 300,
+ _RBRACE_t = 301,
+ ARG = 302,
+ STRING = 303
+ };
+#endif
+#define _BANG_t 258
+#define _BANG_EQUALS_t 259
+#define _AMPER_t 260
+#define _AMPERAMPER_t 261
+#define _LPAREN_t 262
+#define _RPAREN_t 263
+#define _PLUS_EQUALS_t 264
+#define _COLON_t 265
+#define _SEMIC_t 266
+#define _LANGLE_t 267
+#define _LANGLE_EQUALS_t 268
+#define _EQUALS_t 269
+#define _RANGLE_t 270
+#define _RANGLE_EQUALS_t 271
+#define _QUESTION_EQUALS_t 272
+#define _LBRACKET_t 273
+#define _RBRACKET_t 274
+#define ACTIONS_t 275
+#define BIND_t 276
+#define CASE_t 277
+#define CLASS_t 278
+#define DEFAULT_t 279
+#define ELSE_t 280
+#define EXISTING_t 281
+#define FOR_t 282
+#define IF_t 283
+#define IGNORE_t 284
+#define IN_t 285
+#define INCLUDE_t 286
+#define LOCAL_t 287
+#define MODULE_t 288
+#define ON_t 289
+#define PIECEMEAL_t 290
+#define QUIETLY_t 291
+#define RETURN_t 292
+#define RULE_t 293
+#define SWITCH_t 294
+#define TOGETHER_t 295
+#define UPDATED_t 296
+#define WHILE_t 297
+#define _LBRACE_t 298
+#define _BAR_t 299
+#define _BARBAR_t 300
+#define _RBRACE_t 301
+#define ARG 302
+#define STRING 303
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 96 "jamgram.y"
+
+#include "jam.h"
+
+#include "lists.h"
+#include "parse.h"
+#include "scan.h"
+#include "compile.h"
+#include "newstr.h"
+#include "rules.h"
+
+# define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
+
+# define F0 (LIST *(*)(PARSE *, FRAME *))0
+# define P0 (PARSE *)0
+# define S0 (char *)0
+
+# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
+# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
+# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
+# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
+# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 )
+# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 )
+# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
+# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
+# define pclass( l,r ) parse_make( compile_class,l,r,P0,S0,S0,0 )
+# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
+# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
+# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
+# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
+# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
+# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a )
+# define psetc( s,p,a,l ) parse_make( compile_setcomp,p,a,P0,s,S0,l )
+# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f )
+# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
+# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
+
+# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
+# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
+
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+typedef int YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 214 of yacc.c. */
+#line 223 "y.tab.c"
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# if YYSTACK_USE_ALLOCA
+# define YYSTACK_ALLOC alloca
+# else
+# ifndef YYSTACK_USE_ALLOCA
+# if defined (alloca) || defined (_ALLOCA_H)
+# define YYSTACK_ALLOC alloca
+# else
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+# define YYSTACK_ALLOC malloc
+# define YYSTACK_FREE free
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+ && (! defined (__cplusplus) \
+ || (YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ short yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (short) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ register YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+ typedef signed char yysigned_char;
+#else
+ typedef short yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 43
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 261
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 49
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 24
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 75
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 159
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 303
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const unsigned char yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const unsigned char yyprhs[] =
+{
+ 0, 0, 3, 4, 6, 8, 10, 12, 15, 21,
+ 22, 25, 27, 31, 32, 34, 35, 39, 43, 47,
+ 52, 59, 63, 72, 78, 84, 90, 96, 102, 110,
+ 116, 120, 121, 122, 132, 134, 136, 138, 141, 143,
+ 147, 151, 155, 159, 163, 167, 171, 175, 179, 183,
+ 187, 190, 194, 195, 198, 203, 205, 209, 211, 212,
+ 215, 217, 218, 223, 226, 231, 236, 237, 240, 242,
+ 244, 246, 248, 250, 252, 253
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yysigned_char yyrhs[] =
+{
+ 50, 0, -1, -1, 52, -1, 53, -1, 52, -1,
+ 57, -1, 57, 52, -1, 32, 65, 54, 11, 51,
+ -1, -1, 14, 65, -1, 53, -1, 7, 64, 8,
+ -1, -1, 32, -1, -1, 43, 51, 46, -1, 31,
+ 65, 11, -1, 47, 64, 11, -1, 67, 60, 65,
+ 11, -1, 67, 34, 65, 60, 65, 11, -1, 37,
+ 65, 11, -1, 27, 56, 47, 30, 65, 43, 51,
+ 46, -1, 39, 65, 43, 62, 46, -1, 28, 61,
+ 43, 51, 46, -1, 33, 65, 43, 51, 46, -1,
+ 23, 64, 43, 51, 46, -1, 42, 61, 43, 51,
+ 46, -1, 28, 61, 43, 51, 46, 25, 57, -1,
+ 56, 38, 47, 55, 57, -1, 34, 67, 57, -1,
+ -1, -1, 20, 70, 47, 72, 43, 58, 48, 59,
+ 46, -1, 14, -1, 9, -1, 17, -1, 24, 14,
+ -1, 67, -1, 61, 14, 61, -1, 61, 4, 61,
+ -1, 61, 12, 61, -1, 61, 13, 61, -1, 61,
+ 15, 61, -1, 61, 16, 61, -1, 61, 5, 61,
+ -1, 61, 6, 61, -1, 61, 44, 61, -1, 61,
+ 45, 61, -1, 67, 30, 65, -1, 3, 61, -1,
+ 7, 61, 8, -1, -1, 63, 62, -1, 22, 47,
+ 10, 51, -1, 65, -1, 65, 10, 64, -1, 66,
+ -1, -1, 66, 67, -1, 47, -1, -1, 18, 68,
+ 69, 19, -1, 67, 64, -1, 34, 67, 67, 64,
+ -1, 34, 67, 37, 65, -1, -1, 70, 71, -1,
+ 41, -1, 40, -1, 29, -1, 36, -1, 35, -1,
+ 26, -1, -1, 21, 65, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const unsigned short yyrline[] =
+{
+ 0, 139, 139, 141, 152, 154, 158, 160, 162, 167,
+ 170, 172, 176, 179, 182, 185, 188, 190, 192, 194,
+ 196, 198, 200, 202, 204, 206, 208, 210, 212, 214,
+ 216, 219, 221, 218, 230, 232, 234, 236, 243, 245,
+ 247, 249, 251, 253, 255, 257, 259, 261, 263, 265,
+ 267, 269, 281, 282, 286, 295, 297, 307, 312, 313,
+ 317, 319, 319, 328, 330, 332, 343, 344, 348, 350,
+ 352, 354, 356, 358, 368, 369
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "_BANG_t", "_BANG_EQUALS_t", "_AMPER_t",
+ "_AMPERAMPER_t", "_LPAREN_t", "_RPAREN_t", "_PLUS_EQUALS_t", "_COLON_t",
+ "_SEMIC_t", "_LANGLE_t", "_LANGLE_EQUALS_t", "_EQUALS_t", "_RANGLE_t",
+ "_RANGLE_EQUALS_t", "_QUESTION_EQUALS_t", "_LBRACKET_t", "_RBRACKET_t",
+ "ACTIONS_t", "BIND_t", "CASE_t", "CLASS_t", "DEFAULT_t", "ELSE_t",
+ "EXISTING_t", "FOR_t", "IF_t", "IGNORE_t", "IN_t", "INCLUDE_t",
+ "LOCAL_t", "MODULE_t", "ON_t", "PIECEMEAL_t", "QUIETLY_t", "RETURN_t",
+ "RULE_t", "SWITCH_t", "TOGETHER_t", "UPDATED_t", "WHILE_t", "_LBRACE_t",
+ "_BAR_t", "_BARBAR_t", "_RBRACE_t", "ARG", "STRING", "$accept", "run",
+ "block", "rules", "null", "assign_list_opt", "arglist_opt", "local_opt",
+ "rule", "@1", "@2", "assign", "expr", "cases", "case", "lol", "list",
+ "listp", "arg", "@3", "func", "eflags", "eflag", "bindlist", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const unsigned short yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const unsigned char yyr1[] =
+{
+ 0, 49, 50, 50, 51, 51, 52, 52, 52, 53,
+ 54, 54, 55, 55, 56, 56, 57, 57, 57, 57,
+ 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+ 57, 58, 59, 57, 60, 60, 60, 60, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 62, 62, 63, 64, 64, 65, 66, 66,
+ 67, 68, 67, 69, 69, 69, 70, 70, 71, 71,
+ 71, 71, 71, 71, 72, 72
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const unsigned char yyr2[] =
+{
+ 0, 2, 0, 1, 1, 1, 1, 2, 5, 0,
+ 2, 1, 3, 0, 1, 0, 3, 3, 3, 4,
+ 6, 3, 8, 5, 5, 5, 5, 5, 7, 5,
+ 3, 0, 0, 9, 1, 1, 1, 2, 1, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 3, 0, 2, 4, 1, 3, 1, 0, 2,
+ 1, 0, 4, 2, 4, 4, 0, 2, 1, 1,
+ 1, 1, 1, 1, 0, 2
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const unsigned char yydefact[] =
+{
+ 2, 61, 66, 58, 15, 0, 58, 58, 58, 0,
+ 58, 58, 0, 9, 60, 0, 3, 0, 6, 0,
+ 0, 0, 0, 55, 57, 14, 0, 0, 0, 60,
+ 0, 38, 0, 9, 0, 15, 0, 0, 0, 0,
+ 5, 4, 0, 1, 0, 7, 35, 34, 36, 0,
+ 58, 58, 0, 58, 0, 73, 70, 72, 71, 69,
+ 68, 74, 67, 9, 58, 59, 0, 50, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,
+ 58, 17, 58, 11, 0, 9, 30, 21, 52, 9,
+ 16, 18, 13, 37, 0, 0, 0, 63, 62, 58,
+ 0, 0, 56, 58, 51, 40, 45, 46, 41, 42,
+ 39, 43, 44, 0, 47, 48, 49, 10, 9, 0,
+ 0, 0, 52, 0, 58, 15, 58, 19, 58, 58,
+ 75, 31, 26, 0, 24, 8, 25, 0, 23, 53,
+ 27, 0, 29, 0, 65, 64, 0, 9, 15, 9,
+ 12, 20, 32, 0, 28, 54, 0, 22, 33
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const short yydefgoto[] =
+{
+ -1, 15, 39, 40, 41, 84, 125, 17, 18, 146,
+ 156, 51, 30, 121, 122, 22, 23, 24, 31, 20,
+ 54, 21, 62, 100
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -48
+static const short yypact[] =
+{
+ 179, -48, -48, -48, -15, 7, -48, -16, -48, 3,
+ -48, -48, 7, 179, 1, 27, -48, -9, 179, 19,
+ -3, 33, -11, 24, 3, -48, -10, 7, 7, -48,
+ 138, 9, 30, 35, 13, 205, 53, 22, 151, 20,
+ -48, -48, 56, -48, 23, -48, -48, -48, -48, 61,
+ -48, -48, 3, -48, 62, -48, -48, -48, -48, -48,
+ -48, 58, -48, 179, -48, -48, 52, -48, 164, 7,
+ 7, 7, 7, 7, 7, 7, 7, 179, 7, 7,
+ -48, -48, -48, -48, 72, 179, -48, -48, 68, 179,
+ -48, -48, 85, -48, 77, 73, 8, -48, -48, -48,
+ 50, 57, -48, -48, -48, 45, 93, 93, -48, -48,
+ 45, -48, -48, 64, 245, 245, -48, -48, 179, 66,
+ 67, 69, 68, 71, -48, 205, -48, -48, -48, -48,
+ -48, -48, -48, 70, 79, -48, -48, 109, -48, -48,
+ -48, 112, -48, 115, -48, -48, 75, 179, 205, 179,
+ -48, -48, -48, 81, -48, -48, 82, -48, -48
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const short yypgoto[] =
+{
+ -48, -48, -47, 5, 104, -48, -48, 136, -27, -48,
+ -48, 47, 60, 36, -48, -13, -4, -48, 0, -48,
+ -48, -48, -48, -48
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -59
+static const short yytable[] =
+{
+ 19, 42, 32, 33, 34, 16, 36, 37, 86, 35,
+ 27, -58, -58, 19, 28, 1, 101, 25, 19, -58,
+ 53, 1, -14, 45, 65, 1, 1, 43, 46, 44,
+ 113, 52, 63, 47, 64, 19, 48, 66, 119, 80,
+ 97, 81, 123, 49, 29, 128, 94, 95, -58, 82,
+ 29, 102, 96, 50, 29, 29, 85, 72, 73, 55,
+ 75, 76, 56, 19, 87, 88, 90, 91, 57, 58,
+ 92, 135, 38, 59, 60, 93, 116, 19, 117, 99,
+ 61, 98, 103, 118, 127, 19, 46, 67, 68, 19,
+ 120, 47, 124, 131, 48, 130, 129, 69, 142, 133,
+ 153, 49, 155, 132, 148, 72, 73, 74, 75, 76,
+ 134, 141, 136, 147, 137, 138, 145, 140, 19, 149,
+ 150, 154, 143, 152, 144, 19, 151, 157, 158, 105,
+ 106, 107, 108, 109, 110, 111, 112, 83, 114, 115,
+ 26, 126, 69, 70, 71, 0, 0, 19, 19, 19,
+ 72, 73, 74, 75, 76, 69, 70, 71, 139, 0,
+ 0, 0, 0, 72, 73, 74, 75, 76, 69, 70,
+ 71, 0, 104, 0, 0, 0, 72, 73, 74, 75,
+ 76, 77, 78, 79, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 89, 78, 79, 1, 0, 2,
+ 0, 0, 3, 0, 0, 0, 4, 5, 78, 79,
+ 6, 7, 8, 9, 0, 0, 10, -15, 11, 0,
+ 0, 12, 13, 1, 0, 2, 14, 0, 3, 0,
+ 0, 0, 4, 5, 0, 0, 6, 25, 8, 9,
+ 0, 0, 10, 0, 11, 0, 0, 12, 13, 69,
+ 70, 71, 14, 0, 0, 0, 0, 72, 73, 74,
+ 75, 76
+};
+
+static const short yycheck[] =
+{
+ 0, 14, 6, 7, 8, 0, 10, 11, 35, 9,
+ 3, 10, 11, 13, 7, 18, 63, 32, 18, 18,
+ 20, 18, 38, 18, 24, 18, 18, 0, 9, 38,
+ 77, 34, 43, 14, 10, 35, 17, 47, 85, 30,
+ 53, 11, 89, 24, 47, 37, 50, 51, 47, 14,
+ 47, 64, 52, 34, 47, 47, 43, 12, 13, 26,
+ 15, 16, 29, 63, 11, 43, 46, 11, 35, 36,
+ 47, 118, 12, 40, 41, 14, 80, 77, 82, 21,
+ 47, 19, 30, 11, 11, 85, 9, 27, 28, 89,
+ 22, 14, 7, 43, 17, 99, 96, 4, 125, 103,
+ 147, 24, 149, 46, 25, 12, 13, 14, 15, 16,
+ 46, 124, 46, 43, 47, 46, 129, 46, 118, 10,
+ 8, 148, 126, 48, 128, 125, 11, 46, 46, 69,
+ 70, 71, 72, 73, 74, 75, 76, 33, 78, 79,
+ 4, 94, 4, 5, 6, -1, -1, 147, 148, 149,
+ 12, 13, 14, 15, 16, 4, 5, 6, 122, -1,
+ -1, -1, -1, 12, 13, 14, 15, 16, 4, 5,
+ 6, -1, 8, -1, -1, -1, 12, 13, 14, 15,
+ 16, 43, 44, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 43, 44, 45, 18, -1, 20,
+ -1, -1, 23, -1, -1, -1, 27, 28, 44, 45,
+ 31, 32, 33, 34, -1, -1, 37, 38, 39, -1,
+ -1, 42, 43, 18, -1, 20, 47, -1, 23, -1,
+ -1, -1, 27, 28, -1, -1, 31, 32, 33, 34,
+ -1, -1, 37, -1, 39, -1, -1, 42, 43, 4,
+ 5, 6, 47, -1, -1, -1, -1, 12, 13, 14,
+ 15, 16
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const unsigned char yystos[] =
+{
+ 0, 18, 20, 23, 27, 28, 31, 32, 33, 34,
+ 37, 39, 42, 43, 47, 50, 52, 56, 57, 67,
+ 68, 70, 64, 65, 66, 32, 56, 3, 7, 47,
+ 61, 67, 65, 65, 65, 67, 65, 65, 61, 51,
+ 52, 53, 64, 0, 38, 52, 9, 14, 17, 24,
+ 34, 60, 34, 67, 69, 26, 29, 35, 36, 40,
+ 41, 47, 71, 43, 10, 67, 47, 61, 61, 4,
+ 5, 6, 12, 13, 14, 15, 16, 43, 44, 45,
+ 30, 11, 14, 53, 54, 43, 57, 11, 43, 43,
+ 46, 11, 47, 14, 65, 65, 67, 64, 19, 21,
+ 72, 51, 64, 30, 8, 61, 61, 61, 61, 61,
+ 61, 61, 61, 51, 61, 61, 65, 65, 11, 51,
+ 22, 62, 63, 51, 7, 55, 60, 11, 37, 67,
+ 65, 43, 46, 65, 46, 51, 46, 47, 46, 62,
+ 46, 64, 57, 65, 65, 64, 58, 43, 25, 10,
+ 8, 11, 48, 51, 57, 51, 59, 46, 46
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrlab1
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror ("syntax error: cannot back up");\
+ YYERROR; \
+ } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+ are run). */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ Current.first_line = Rhs[1].first_line; \
+ Current.first_column = Rhs[1].first_column; \
+ Current.last_line = Rhs[N].last_line; \
+ Current.last_column = Rhs[N].last_column;
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+# define YYDSYMPRINT(Args) \
+do { \
+ if (yydebug) \
+ yysymprint Args; \
+} while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yysymprint (stderr, \
+ Token, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (cinluded). |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short *bottom, short *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ short *bottom;
+ short *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (/* Nothing. */; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+ int yyrule;
+#endif
+{
+ int yyi;
+ unsigned int yylineno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+ yyrule - 1, yylineno);
+ /* Print the symbols being reduced, and their result. */
+ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (Rule); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined (__GLIBC__) && defined (_STRING_H)
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+# if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+# else
+yystrlen (yystr)
+ const char *yystr;
+# endif
+{
+ register const char *yys = yystr;
+
+ while (*yys++ != '\0')
+ continue;
+
+ return yys - yystr - 1;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+# if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+# else
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+# endif
+{
+ register char *yyd = yydest;
+ register const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ if (yytype < YYNTOKENS)
+ {
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ }
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+ YYFPRINTF (yyoutput, ")");
+}
+
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yytype, yyvaluep)
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+ register int yystate;
+ register int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ short yyssa[YYINITDEPTH];
+ short *yyss = yyssa;
+ register short *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK (yyvsp--, yyssp--)
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* When reducing, the number of symbols on the RHS of the reduced
+ rule. */
+ int yylen;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks.
+ */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow ("parser stack overflow",
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyoverflowlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyoverflowlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ short *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyoverflowlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 3:
+#line 142 "jamgram.y"
+ { parse_save( yyvsp[0].parse ); }
+ break;
+
+ case 4:
+#line 153 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; }
+ break;
+
+ case 5:
+#line 155 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; }
+ break;
+
+ case 6:
+#line 159 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; }
+ break;
+
+ case 7:
+#line 161 "jamgram.y"
+ { yyval.parse = prules( yyvsp[-1].parse, yyvsp[0].parse ); }
+ break;
+
+ case 8:
+#line 163 "jamgram.y"
+ { yyval.parse = plocal( yyvsp[-3].parse, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 9:
+#line 167 "jamgram.y"
+ { yyval.parse = pnull(); }
+ break;
+
+ case 10:
+#line 171 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; yyval.number = ASSIGN_SET; }
+ break;
+
+ case 11:
+#line 173 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; yyval.number = ASSIGN_APPEND; }
+ break;
+
+ case 12:
+#line 177 "jamgram.y"
+ { yyval.parse = yyvsp[-1].parse; }
+ break;
+
+ case 13:
+#line 179 "jamgram.y"
+ { yyval.parse = P0; }
+ break;
+
+ case 14:
+#line 183 "jamgram.y"
+ { yyval.number = 1; }
+ break;
+
+ case 15:
+#line 185 "jamgram.y"
+ { yyval.number = 0; }
+ break;
+
+ case 16:
+#line 189 "jamgram.y"
+ { yyval.parse = yyvsp[-1].parse; }
+ break;
+
+ case 17:
+#line 191 "jamgram.y"
+ { yyval.parse = pincl( yyvsp[-1].parse ); }
+ break;
+
+ case 18:
+#line 193 "jamgram.y"
+ { yyval.parse = prule( yyvsp[-2].string, yyvsp[-1].parse ); }
+ break;
+
+ case 19:
+#line 195 "jamgram.y"
+ { yyval.parse = pset( yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-2].number ); }
+ break;
+
+ case 20:
+#line 197 "jamgram.y"
+ { yyval.parse = pset1( yyvsp[-5].parse, yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-2].number ); }
+ break;
+
+ case 21:
+#line 199 "jamgram.y"
+ { yyval.parse = yyvsp[-1].parse; }
+ break;
+
+ case 22:
+#line 201 "jamgram.y"
+ { yyval.parse = pfor( yyvsp[-5].string, yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-6].number ); }
+ break;
+
+ case 23:
+#line 203 "jamgram.y"
+ { yyval.parse = pswitch( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ break;
+
+ case 24:
+#line 205 "jamgram.y"
+ { yyval.parse = pif( yyvsp[-3].parse, yyvsp[-1].parse, pnull() ); }
+ break;
+
+ case 25:
+#line 207 "jamgram.y"
+ { yyval.parse = pmodule( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ break;
+
+ case 26:
+#line 209 "jamgram.y"
+ { yyval.parse = pclass( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ break;
+
+ case 27:
+#line 211 "jamgram.y"
+ { yyval.parse = pwhile( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ break;
+
+ case 28:
+#line 213 "jamgram.y"
+ { yyval.parse = pif( yyvsp[-5].parse, yyvsp[-3].parse, yyvsp[0].parse ); }
+ break;
+
+ case 29:
+#line 215 "jamgram.y"
+ { yyval.parse = psetc( yyvsp[-2].string, yyvsp[0].parse, yyvsp[-1].parse, yyvsp[-4].number ); }
+ break;
+
+ case 30:
+#line 217 "jamgram.y"
+ { yyval.parse = pon( yyvsp[-1].parse, yyvsp[0].parse ); }
+ break;
+
+ case 31:
+#line 219 "jamgram.y"
+ { yymode( SCAN_STRING ); }
+ break;
+
+ case 32:
+#line 221 "jamgram.y"
+ { yymode( SCAN_NORMAL ); }
+ break;
+
+ case 33:
+#line 223 "jamgram.y"
+ { yyval.parse = psete( yyvsp[-6].string,yyvsp[-5].parse,yyvsp[-2].string,yyvsp[-7].number ); }
+ break;
+
+ case 34:
+#line 231 "jamgram.y"
+ { yyval.number = ASSIGN_SET; }
+ break;
+
+ case 35:
+#line 233 "jamgram.y"
+ { yyval.number = ASSIGN_APPEND; }
+ break;
+
+ case 36:
+#line 235 "jamgram.y"
+ { yyval.number = ASSIGN_DEFAULT; }
+ break;
+
+ case 37:
+#line 237 "jamgram.y"
+ { yyval.number = ASSIGN_DEFAULT; }
+ break;
+
+ case 38:
+#line 244 "jamgram.y"
+ { yyval.parse = peval( EXPR_EXISTS, yyvsp[0].parse, pnull() ); }
+ break;
+
+ case 39:
+#line 246 "jamgram.y"
+ { yyval.parse = peval( EXPR_EQUALS, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 40:
+#line 248 "jamgram.y"
+ { yyval.parse = peval( EXPR_NOTEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 41:
+#line 250 "jamgram.y"
+ { yyval.parse = peval( EXPR_LESS, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 42:
+#line 252 "jamgram.y"
+ { yyval.parse = peval( EXPR_LESSEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 43:
+#line 254 "jamgram.y"
+ { yyval.parse = peval( EXPR_MORE, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 44:
+#line 256 "jamgram.y"
+ { yyval.parse = peval( EXPR_MOREEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 45:
+#line 258 "jamgram.y"
+ { yyval.parse = peval( EXPR_AND, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 46:
+#line 260 "jamgram.y"
+ { yyval.parse = peval( EXPR_AND, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 47:
+#line 262 "jamgram.y"
+ { yyval.parse = peval( EXPR_OR, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 48:
+#line 264 "jamgram.y"
+ { yyval.parse = peval( EXPR_OR, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 49:
+#line 266 "jamgram.y"
+ { yyval.parse = peval( EXPR_IN, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 50:
+#line 268 "jamgram.y"
+ { yyval.parse = peval( EXPR_NOT, yyvsp[0].parse, pnull() ); }
+ break;
+
+ case 51:
+#line 270 "jamgram.y"
+ { yyval.parse = yyvsp[-1].parse; }
+ break;
+
+ case 52:
+#line 281 "jamgram.y"
+ { yyval.parse = P0; }
+ break;
+
+ case 53:
+#line 283 "jamgram.y"
+ { yyval.parse = pnode( yyvsp[-1].parse, yyvsp[0].parse ); }
+ break;
+
+ case 54:
+#line 287 "jamgram.y"
+ { yyval.parse = psnode( yyvsp[-2].string, yyvsp[0].parse ); }
+ break;
+
+ case 55:
+#line 296 "jamgram.y"
+ { yyval.parse = pnode( P0, yyvsp[0].parse ); }
+ break;
+
+ case 56:
+#line 298 "jamgram.y"
+ { yyval.parse = pnode( yyvsp[0].parse, yyvsp[-2].parse ); }
+ break;
+
+ case 57:
+#line 308 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; yymode( SCAN_NORMAL ); }
+ break;
+
+ case 58:
+#line 312 "jamgram.y"
+ { yyval.parse = pnull(); yymode( SCAN_PUNCT ); }
+ break;
+
+ case 59:
+#line 314 "jamgram.y"
+ { yyval.parse = pappend( yyvsp[-1].parse, yyvsp[0].parse ); }
+ break;
+
+ case 60:
+#line 318 "jamgram.y"
+ { yyval.parse = plist( yyvsp[0].string ); }
+ break;
+
+ case 61:
+#line 319 "jamgram.y"
+ { yymode( SCAN_NORMAL ); }
+ break;
+
+ case 62:
+#line 320 "jamgram.y"
+ { yyval.parse = yyvsp[-1].parse; }
+ break;
+
+ case 63:
+#line 329 "jamgram.y"
+ { yyval.parse = prule( yyvsp[-1].string, yyvsp[0].parse ); }
+ break;
+
+ case 64:
+#line 331 "jamgram.y"
+ { yyval.parse = pon( yyvsp[-2].parse, prule( yyvsp[-1].string, yyvsp[0].parse ) ); }
+ break;
+
+ case 65:
+#line 333 "jamgram.y"
+ { yyval.parse = pon( yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 66:
+#line 343 "jamgram.y"
+ { yyval.number = 0; }
+ break;
+
+ case 67:
+#line 345 "jamgram.y"
+ { yyval.number = yyvsp[-1].number | yyvsp[0].number; }
+ break;
+
+ case 68:
+#line 349 "jamgram.y"
+ { yyval.number = EXEC_UPDATED; }
+ break;
+
+ case 69:
+#line 351 "jamgram.y"
+ { yyval.number = EXEC_TOGETHER; }
+ break;
+
+ case 70:
+#line 353 "jamgram.y"
+ { yyval.number = EXEC_IGNORE; }
+ break;
+
+ case 71:
+#line 355 "jamgram.y"
+ { yyval.number = EXEC_QUIETLY; }
+ break;
+
+ case 72:
+#line 357 "jamgram.y"
+ { yyval.number = EXEC_PIECEMEAL; }
+ break;
+
+ case 73:
+#line 359 "jamgram.y"
+ { yyval.number = EXEC_EXISTING; }
+ break;
+
+ case 74:
+#line 368 "jamgram.y"
+ { yyval.parse = pnull(); }
+ break;
+
+ case 75:
+#line 370 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; }
+ break;
+
+
+ }
+
+/* Line 991 of yacc.c. */
+#line 1621 "y.tab.c"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+
+
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (YYPACT_NINF < yyn && yyn < YYLAST)
+ {
+ YYSIZE_T yysize = 0;
+ int yytype = YYTRANSLATE (yychar);
+ char *yymsg;
+ int yyx, yycount;
+
+ yycount = 0;
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ for (yyx = yyn < 0 ? -yyn : 0;
+ yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+ yysize += yystrlen ("syntax error, unexpected ") + 1;
+ yysize += yystrlen (yytname[yytype]);
+ yymsg = (char *) YYSTACK_ALLOC (yysize);
+ if (yymsg != 0)
+ {
+ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+ yyp = yystpcpy (yyp, yytname[yytype]);
+
+ if (yycount < 5)
+ {
+ yycount = 0;
+ for (yyx = yyn < 0 ? -yyn : 0;
+ yyx < (int) (sizeof (yytname) / sizeof (char *));
+ yyx++)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ const char *yyq = ! yycount ? ", expecting " : " or ";
+ yyp = yystpcpy (yyp, yyq);
+ yyp = yystpcpy (yyp, yytname[yyx]);
+ yycount++;
+ }
+ }
+ yyerror (yymsg);
+ YYSTACK_FREE (yymsg);
+ }
+ else
+ yyerror ("syntax error; also virtual memory exhausted");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror ("syntax error");
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ {
+ /* Pop the error token. */
+ YYPOPSTACK;
+ /* Pop the rest of the stack. */
+ while (yyss < yyssp)
+ {
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[*yyssp], yyvsp);
+ YYPOPSTACK;
+ }
+ YYABORT;
+ }
+
+ YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+ yydestruct (yytoken, &yylval);
+ yychar = YYEMPTY;
+
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab2;
+
+
+/*----------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action. |
+`----------------------------------------------------*/
+yyerrlab1:
+
+ /* Suppress GCC warning that yyerrlab1 is unused when no action
+ invokes YYERROR. */
+#if defined (__GNUC_MINOR__) && 2093 <= (__GNUC__ * 1000 + __GNUC_MINOR__)
+ __attribute__ ((__unused__))
+#endif
+
+
+ goto yyerrlab2;
+
+
+/*---------------------------------------------------------------.
+| yyerrlab2 -- pop states until the error token can be shifted. |
+`---------------------------------------------------------------*/
+yyerrlab2:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[yystate], yyvsp);
+ yyvsp--;
+ yystate = *--yyssp;
+
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ YYDPRINTF ((stderr, "Shifting error token, "));
+
+ *++yyvsp = yylval;
+
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here. |
+`----------------------------------------------*/
+yyoverflowlab:
+ yyerror ("parser stack overflow");
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+ return yyresult;
+}
+
+
+
diff --git a/tools/build/v2/engine/jamgram.h b/tools/build/v2/engine/jamgram.h
new file mode 100644
index 0000000000..3cb7656417
--- /dev/null
+++ b/tools/build/v2/engine/jamgram.h
@@ -0,0 +1,140 @@
+/* A Bison parser, made by GNU Bison 1.875. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ _BANG_t = 258,
+ _BANG_EQUALS_t = 259,
+ _AMPER_t = 260,
+ _AMPERAMPER_t = 261,
+ _LPAREN_t = 262,
+ _RPAREN_t = 263,
+ _PLUS_EQUALS_t = 264,
+ _COLON_t = 265,
+ _SEMIC_t = 266,
+ _LANGLE_t = 267,
+ _LANGLE_EQUALS_t = 268,
+ _EQUALS_t = 269,
+ _RANGLE_t = 270,
+ _RANGLE_EQUALS_t = 271,
+ _QUESTION_EQUALS_t = 272,
+ _LBRACKET_t = 273,
+ _RBRACKET_t = 274,
+ ACTIONS_t = 275,
+ BIND_t = 276,
+ CASE_t = 277,
+ CLASS_t = 278,
+ DEFAULT_t = 279,
+ ELSE_t = 280,
+ EXISTING_t = 281,
+ FOR_t = 282,
+ IF_t = 283,
+ IGNORE_t = 284,
+ IN_t = 285,
+ INCLUDE_t = 286,
+ LOCAL_t = 287,
+ MODULE_t = 288,
+ ON_t = 289,
+ PIECEMEAL_t = 290,
+ QUIETLY_t = 291,
+ RETURN_t = 292,
+ RULE_t = 293,
+ SWITCH_t = 294,
+ TOGETHER_t = 295,
+ UPDATED_t = 296,
+ WHILE_t = 297,
+ _LBRACE_t = 298,
+ _BAR_t = 299,
+ _BARBAR_t = 300,
+ _RBRACE_t = 301,
+ ARG = 302,
+ STRING = 303
+ };
+#endif
+#define _BANG_t 258
+#define _BANG_EQUALS_t 259
+#define _AMPER_t 260
+#define _AMPERAMPER_t 261
+#define _LPAREN_t 262
+#define _RPAREN_t 263
+#define _PLUS_EQUALS_t 264
+#define _COLON_t 265
+#define _SEMIC_t 266
+#define _LANGLE_t 267
+#define _LANGLE_EQUALS_t 268
+#define _EQUALS_t 269
+#define _RANGLE_t 270
+#define _RANGLE_EQUALS_t 271
+#define _QUESTION_EQUALS_t 272
+#define _LBRACKET_t 273
+#define _RBRACKET_t 274
+#define ACTIONS_t 275
+#define BIND_t 276
+#define CASE_t 277
+#define CLASS_t 278
+#define DEFAULT_t 279
+#define ELSE_t 280
+#define EXISTING_t 281
+#define FOR_t 282
+#define IF_t 283
+#define IGNORE_t 284
+#define IN_t 285
+#define INCLUDE_t 286
+#define LOCAL_t 287
+#define MODULE_t 288
+#define ON_t 289
+#define PIECEMEAL_t 290
+#define QUIETLY_t 291
+#define RETURN_t 292
+#define RULE_t 293
+#define SWITCH_t 294
+#define TOGETHER_t 295
+#define UPDATED_t 296
+#define WHILE_t 297
+#define _LBRACE_t 298
+#define _BAR_t 299
+#define _BARBAR_t 300
+#define _RBRACE_t 301
+#define ARG 302
+#define STRING 303
+
+
+
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+typedef int YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
+
+
diff --git a/tools/build/v2/engine/jamgram.y b/tools/build/v2/engine/jamgram.y
new file mode 100644
index 0000000000..c26b1e1b6b
--- /dev/null
+++ b/tools/build/v2/engine/jamgram.y
@@ -0,0 +1,371 @@
+%token _BANG_t
+%token _BANG_EQUALS_t
+%token _AMPER_t
+%token _AMPERAMPER_t
+%token _LPAREN_t
+%token _RPAREN_t
+%token _PLUS_EQUALS_t
+%token _COLON_t
+%token _SEMIC_t
+%token _LANGLE_t
+%token _LANGLE_EQUALS_t
+%token _EQUALS_t
+%token _RANGLE_t
+%token _RANGLE_EQUALS_t
+%token _QUESTION_EQUALS_t
+%token _LBRACKET_t
+%token _RBRACKET_t
+%token ACTIONS_t
+%token BIND_t
+%token CASE_t
+%token CLASS_t
+%token DEFAULT_t
+%token ELSE_t
+%token EXISTING_t
+%token FOR_t
+%token IF_t
+%token IGNORE_t
+%token IN_t
+%token INCLUDE_t
+%token LOCAL_t
+%token MODULE_t
+%token ON_t
+%token PIECEMEAL_t
+%token QUIETLY_t
+%token RETURN_t
+%token RULE_t
+%token SWITCH_t
+%token TOGETHER_t
+%token UPDATED_t
+%token WHILE_t
+%token _LBRACE_t
+%token _BAR_t
+%token _BARBAR_t
+%token _RBRACE_t
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * jamgram.yy - jam grammar
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 06/01/94 (seiwald) - new 'actions existing' does existing sources
+ * 08/23/94 (seiwald) - Support for '+=' (append to variable)
+ * 08/31/94 (seiwald) - Allow ?= as alias for "default =".
+ * 09/15/94 (seiwald) - if conditionals take only single arguments, so
+ * that 'if foo == bar' gives syntax error (use =).
+ * 02/11/95 (seiwald) - when scanning arguments to rules, only treat
+ * punctuation keywords as keywords. All arg lists
+ * are terminated with punctuation keywords.
+ *
+ * 09/11/00 (seiwald) - Support for function calls:
+ *
+ * Rules now return lists (LIST *), rather than void.
+ *
+ * New "[ rule ]" syntax evals rule into a LIST.
+ *
+ * Lists are now generated by compile_list() and
+ * compile_append(), and any other rule that indirectly
+ * makes a list, rather than being built directly here,
+ * so that lists values can contain rule evaluations.
+ *
+ * New 'return' rule sets the return value, though
+ * other statements also may have return values.
+ *
+ * 'run' production split from 'block' production so
+ * that empty blocks can be handled separately.
+ */
+
+%token ARG STRING
+
+%left _BARBAR_t _BAR_t
+%left _AMPERAMPER_t _AMPER_t
+%left _EQUALS_t _BANG_EQUALS_t IN_t
+%left _LANGLE_t _LANGLE_EQUALS_t _RANGLE_t _RANGLE_EQUALS_t
+%left _BANG_t
+
+%{
+#include "jam.h"
+
+#include "lists.h"
+#include "parse.h"
+#include "scan.h"
+#include "compile.h"
+#include "newstr.h"
+#include "rules.h"
+
+# define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
+
+# define F0 (LIST *(*)(PARSE *, FRAME *))0
+# define P0 (PARSE *)0
+# define S0 (char *)0
+
+# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
+# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
+# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
+# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
+# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 )
+# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 )
+# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
+# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
+# define pclass( l,r ) parse_make( compile_class,l,r,P0,S0,S0,0 )
+# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
+# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
+# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
+# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
+# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
+# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a )
+# define psetc( s,p,a,l ) parse_make( compile_setcomp,p,a,P0,s,S0,l )
+# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f )
+# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
+# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
+
+# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
+# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
+
+%}
+
+%%
+
+run : /* empty */
+ /* do nothing */
+ | rules
+ { parse_save( $1.parse ); }
+ ;
+
+/*
+ * block - zero or more rules
+ * rules - one or more rules
+ * rule - any one of jam's rules
+ * right-recursive so rules execute in order.
+ */
+
+block : null
+ { $$.parse = $1.parse; }
+ | rules
+ { $$.parse = $1.parse; }
+ ;
+
+rules : rule
+ { $$.parse = $1.parse; }
+ | rule rules
+ { $$.parse = prules( $1.parse, $2.parse ); }
+ | LOCAL_t list assign_list_opt _SEMIC_t block
+ { $$.parse = plocal( $2.parse, $3.parse, $5.parse ); }
+ ;
+
+null : /* empty */
+ { $$.parse = pnull(); }
+ ;
+
+assign_list_opt : _EQUALS_t list
+ { $$.parse = $2.parse; $$.number = ASSIGN_SET; }
+ | null
+ { $$.parse = $1.parse; $$.number = ASSIGN_APPEND; }
+ ;
+
+arglist_opt : _LPAREN_t lol _RPAREN_t
+ { $$.parse = $2.parse; }
+ |
+ { $$.parse = P0; }
+ ;
+
+local_opt : LOCAL_t
+ { $$.number = 1; }
+ | /* empty */
+ { $$.number = 0; }
+ ;
+
+rule : _LBRACE_t block _RBRACE_t
+ { $$.parse = $2.parse; }
+ | INCLUDE_t list _SEMIC_t
+ { $$.parse = pincl( $2.parse ); }
+ | ARG lol _SEMIC_t
+ { $$.parse = prule( $1.string, $2.parse ); }
+ | arg assign list _SEMIC_t
+ { $$.parse = pset( $1.parse, $3.parse, $2.number ); }
+ | arg ON_t list assign list _SEMIC_t
+ { $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); }
+ | RETURN_t list _SEMIC_t
+ { $$.parse = $2.parse; }
+ | FOR_t local_opt ARG IN_t list _LBRACE_t block _RBRACE_t
+ { $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); }
+ | SWITCH_t list _LBRACE_t cases _RBRACE_t
+ { $$.parse = pswitch( $2.parse, $4.parse ); }
+ | IF_t expr _LBRACE_t block _RBRACE_t
+ { $$.parse = pif( $2.parse, $4.parse, pnull() ); }
+ | MODULE_t list _LBRACE_t block _RBRACE_t
+ { $$.parse = pmodule( $2.parse, $4.parse ); }
+ | CLASS_t lol _LBRACE_t block _RBRACE_t
+ { $$.parse = pclass( $2.parse, $4.parse ); }
+ | WHILE_t expr _LBRACE_t block _RBRACE_t
+ { $$.parse = pwhile( $2.parse, $4.parse ); }
+ | IF_t expr _LBRACE_t block _RBRACE_t ELSE_t rule
+ { $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
+ | local_opt RULE_t ARG arglist_opt rule
+ { $$.parse = psetc( $3.string, $5.parse, $4.parse, $1.number ); }
+ | ON_t arg rule
+ { $$.parse = pon( $2.parse, $3.parse ); }
+ | ACTIONS_t eflags ARG bindlist _LBRACE_t
+ { yymode( SCAN_STRING ); }
+ STRING
+ { yymode( SCAN_NORMAL ); }
+ _RBRACE_t
+ { $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
+ ;
+
+/*
+ * assign - = or +=
+ */
+
+assign : _EQUALS_t
+ { $$.number = ASSIGN_SET; }
+ | _PLUS_EQUALS_t
+ { $$.number = ASSIGN_APPEND; }
+ | _QUESTION_EQUALS_t
+ { $$.number = ASSIGN_DEFAULT; }
+ | DEFAULT_t _EQUALS_t
+ { $$.number = ASSIGN_DEFAULT; }
+ ;
+
+/*
+ * expr - an expression for if
+ */
+expr : arg
+ { $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
+ | expr _EQUALS_t expr
+ { $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
+ | expr _BANG_EQUALS_t expr
+ { $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
+ | expr _LANGLE_t expr
+ { $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
+ | expr _LANGLE_EQUALS_t expr
+ { $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
+ | expr _RANGLE_t expr
+ { $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
+ | expr _RANGLE_EQUALS_t expr
+ { $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
+ | expr _AMPER_t expr
+ { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
+ | expr _AMPERAMPER_t expr
+ { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
+ | expr _BAR_t expr
+ { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
+ | expr _BARBAR_t expr
+ { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
+ | arg IN_t list
+ { $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); }
+ | _BANG_t expr
+ { $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); }
+ | _LPAREN_t expr _RPAREN_t
+ { $$.parse = $2.parse; }
+ ;
+
+
+/*
+ * cases - action elements inside a 'switch'
+ * case - a single action element inside a 'switch'
+ * right-recursive rule so cases can be examined in order.
+ */
+
+cases : /* empty */
+ { $$.parse = P0; }
+ | case cases
+ { $$.parse = pnode( $1.parse, $2.parse ); }
+ ;
+
+case : CASE_t ARG _COLON_t block
+ { $$.parse = psnode( $2.string, $4.parse ); }
+ ;
+
+/*
+ * lol - list of lists
+ * right-recursive rule so that lists can be added in order.
+ */
+
+lol : list
+ { $$.parse = pnode( P0, $1.parse ); }
+ | list _COLON_t lol
+ { $$.parse = pnode( $3.parse, $1.parse ); }
+ ;
+
+/*
+ * list - zero or more args in a LIST
+ * listp - list (in puncutation only mode)
+ * arg - one ARG or function call
+ */
+
+list : listp
+ { $$.parse = $1.parse; yymode( SCAN_NORMAL ); }
+ ;
+
+listp : /* empty */
+ { $$.parse = pnull(); yymode( SCAN_PUNCT ); }
+ | listp arg
+ { $$.parse = pappend( $1.parse, $2.parse ); }
+ ;
+
+arg : ARG
+ { $$.parse = plist( $1.string ); }
+ | _LBRACKET_t { yymode( SCAN_NORMAL ); } func _RBRACKET_t
+ { $$.parse = $3.parse; }
+ ;
+
+/*
+ * func - a function call (inside [])
+ * This needs to be split cleanly out of 'rule'
+ */
+
+func : arg lol
+ { $$.parse = prule( $1.string, $2.parse ); }
+ | ON_t arg arg lol
+ { $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
+ | ON_t arg RETURN_t list
+ { $$.parse = pon( $2.parse, $4.parse ); }
+ ;
+
+
+/*
+ * eflags - zero or more modifiers to 'executes'
+ * eflag - a single modifier to 'executes'
+ */
+
+eflags : /* empty */
+ { $$.number = 0; }
+ | eflags eflag
+ { $$.number = $1.number | $2.number; }
+ ;
+
+eflag : UPDATED_t
+ { $$.number = EXEC_UPDATED; }
+ | TOGETHER_t
+ { $$.number = EXEC_TOGETHER; }
+ | IGNORE_t
+ { $$.number = EXEC_IGNORE; }
+ | QUIETLY_t
+ { $$.number = EXEC_QUIETLY; }
+ | PIECEMEAL_t
+ { $$.number = EXEC_PIECEMEAL; }
+ | EXISTING_t
+ { $$.number = EXEC_EXISTING; }
+ ;
+
+
+/*
+ * bindlist - list of variable to bind for an action
+ */
+
+bindlist : /* empty */
+ { $$.parse = pnull(); }
+ | BIND_t list
+ { $$.parse = $2.parse; }
+ ;
diff --git a/tools/build/v2/engine/jamgram.yy b/tools/build/v2/engine/jamgram.yy
new file mode 100644
index 0000000000..1524348710
--- /dev/null
+++ b/tools/build/v2/engine/jamgram.yy
@@ -0,0 +1,329 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * jamgram.yy - jam grammar
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 06/01/94 (seiwald) - new 'actions existing' does existing sources
+ * 08/23/94 (seiwald) - Support for '+=' (append to variable)
+ * 08/31/94 (seiwald) - Allow ?= as alias for "default =".
+ * 09/15/94 (seiwald) - if conditionals take only single arguments, so
+ * that 'if foo == bar' gives syntax error (use =).
+ * 02/11/95 (seiwald) - when scanning arguments to rules, only treat
+ * punctuation keywords as keywords. All arg lists
+ * are terminated with punctuation keywords.
+ *
+ * 09/11/00 (seiwald) - Support for function calls:
+ *
+ * Rules now return lists (LIST *), rather than void.
+ *
+ * New "[ rule ]" syntax evals rule into a LIST.
+ *
+ * Lists are now generated by compile_list() and
+ * compile_append(), and any other rule that indirectly
+ * makes a list, rather than being built directly here,
+ * so that lists values can contain rule evaluations.
+ *
+ * New 'return' rule sets the return value, though
+ * other statements also may have return values.
+ *
+ * 'run' production split from 'block' production so
+ * that empty blocks can be handled separately.
+ */
+
+%token ARG STRING
+
+%left `||` `|`
+%left `&&` `&`
+%left `=` `!=` `in`
+%left `<` `<=` `>` `>=`
+%left `!`
+
+%{
+#include "jam.h"
+
+#include "lists.h"
+#include "parse.h"
+#include "scan.h"
+#include "compile.h"
+#include "newstr.h"
+#include "rules.h"
+
+# define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
+
+# define F0 (LIST *(*)(PARSE *, FRAME *))0
+# define P0 (PARSE *)0
+# define S0 (char *)0
+
+# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
+# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
+# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
+# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
+# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 )
+# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 )
+# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
+# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
+# define pclass( l,r ) parse_make( compile_class,l,r,P0,S0,S0,0 )
+# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
+# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
+# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
+# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
+# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
+# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a )
+# define psetc( s,p,a,l ) parse_make( compile_setcomp,p,a,P0,s,S0,l )
+# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f )
+# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
+# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
+
+# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
+# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
+
+%}
+
+%%
+
+run : /* empty */
+ /* do nothing */
+ | rules
+ { parse_save( $1.parse ); }
+ ;
+
+/*
+ * block - zero or more rules
+ * rules - one or more rules
+ * rule - any one of jam's rules
+ * right-recursive so rules execute in order.
+ */
+
+block : null
+ { $$.parse = $1.parse; }
+ | rules
+ { $$.parse = $1.parse; }
+ ;
+
+rules : rule
+ { $$.parse = $1.parse; }
+ | rule rules
+ { $$.parse = prules( $1.parse, $2.parse ); }
+ | `local` list assign_list_opt `;` block
+ { $$.parse = plocal( $2.parse, $3.parse, $5.parse ); }
+ ;
+
+null : /* empty */
+ { $$.parse = pnull(); }
+ ;
+
+assign_list_opt : `=` list
+ { $$.parse = $2.parse; $$.number = ASSIGN_SET; }
+ | null
+ { $$.parse = $1.parse; $$.number = ASSIGN_APPEND; }
+ ;
+
+arglist_opt : `(` lol `)`
+ { $$.parse = $2.parse; }
+ |
+ { $$.parse = P0; }
+ ;
+
+local_opt : `local`
+ { $$.number = 1; }
+ | /* empty */
+ { $$.number = 0; }
+ ;
+
+rule : `{` block `}`
+ { $$.parse = $2.parse; }
+ | `include` list `;`
+ { $$.parse = pincl( $2.parse ); }
+ | ARG lol `;`
+ { $$.parse = prule( $1.string, $2.parse ); }
+ | arg assign list `;`
+ { $$.parse = pset( $1.parse, $3.parse, $2.number ); }
+ | arg `on` list assign list `;`
+ { $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); }
+ | `return` list `;`
+ { $$.parse = $2.parse; }
+ | `for` local_opt ARG `in` list `{` block `}`
+ { $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); }
+ | `switch` list `{` cases `}`
+ { $$.parse = pswitch( $2.parse, $4.parse ); }
+ | `if` expr `{` block `}`
+ { $$.parse = pif( $2.parse, $4.parse, pnull() ); }
+ | `module` list `{` block `}`
+ { $$.parse = pmodule( $2.parse, $4.parse ); }
+ | `class` lol `{` block `}`
+ { $$.parse = pclass( $2.parse, $4.parse ); }
+ | `while` expr `{` block `}`
+ { $$.parse = pwhile( $2.parse, $4.parse ); }
+ | `if` expr `{` block `}` `else` rule
+ { $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
+ | local_opt `rule` ARG arglist_opt rule
+ { $$.parse = psetc( $3.string, $5.parse, $4.parse, $1.number ); }
+ | `on` arg rule
+ { $$.parse = pon( $2.parse, $3.parse ); }
+ | `actions` eflags ARG bindlist `{`
+ { yymode( SCAN_STRING ); }
+ STRING
+ { yymode( SCAN_NORMAL ); }
+ `}`
+ { $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
+ ;
+
+/*
+ * assign - = or +=
+ */
+
+assign : `=`
+ { $$.number = ASSIGN_SET; }
+ | `+=`
+ { $$.number = ASSIGN_APPEND; }
+ | `?=`
+ { $$.number = ASSIGN_DEFAULT; }
+ | `default` `=`
+ { $$.number = ASSIGN_DEFAULT; }
+ ;
+
+/*
+ * expr - an expression for if
+ */
+expr : arg
+ { $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
+ | expr `=` expr
+ { $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
+ | expr `!=` expr
+ { $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
+ | expr `<` expr
+ { $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
+ | expr `<=` expr
+ { $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
+ | expr `>` expr
+ { $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
+ | expr `>=` expr
+ { $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
+ | expr `&` expr
+ { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
+ | expr `&&` expr
+ { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
+ | expr `|` expr
+ { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
+ | expr `||` expr
+ { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
+ | arg `in` list
+ { $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); }
+ | `!` expr
+ { $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); }
+ | `(` expr `)`
+ { $$.parse = $2.parse; }
+ ;
+
+
+/*
+ * cases - action elements inside a 'switch'
+ * case - a single action element inside a 'switch'
+ * right-recursive rule so cases can be examined in order.
+ */
+
+cases : /* empty */
+ { $$.parse = P0; }
+ | case cases
+ { $$.parse = pnode( $1.parse, $2.parse ); }
+ ;
+
+case : `case` ARG `:` block
+ { $$.parse = psnode( $2.string, $4.parse ); }
+ ;
+
+/*
+ * lol - list of lists
+ * right-recursive rule so that lists can be added in order.
+ */
+
+lol : list
+ { $$.parse = pnode( P0, $1.parse ); }
+ | list `:` lol
+ { $$.parse = pnode( $3.parse, $1.parse ); }
+ ;
+
+/*
+ * list - zero or more args in a LIST
+ * listp - list (in puncutation only mode)
+ * arg - one ARG or function call
+ */
+
+list : listp
+ { $$.parse = $1.parse; yymode( SCAN_NORMAL ); }
+ ;
+
+listp : /* empty */
+ { $$.parse = pnull(); yymode( SCAN_PUNCT ); }
+ | listp arg
+ { $$.parse = pappend( $1.parse, $2.parse ); }
+ ;
+
+arg : ARG
+ { $$.parse = plist( $1.string ); }
+ | `[` { yymode( SCAN_NORMAL ); } func `]`
+ { $$.parse = $3.parse; }
+ ;
+
+/*
+ * func - a function call (inside [])
+ * This needs to be split cleanly out of 'rule'
+ */
+
+func : arg lol
+ { $$.parse = prule( $1.string, $2.parse ); }
+ | `on` arg arg lol
+ { $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
+ | `on` arg `return` list
+ { $$.parse = pon( $2.parse, $4.parse ); }
+ ;
+
+
+/*
+ * eflags - zero or more modifiers to 'executes'
+ * eflag - a single modifier to 'executes'
+ */
+
+eflags : /* empty */
+ { $$.number = 0; }
+ | eflags eflag
+ { $$.number = $1.number | $2.number; }
+ ;
+
+eflag : `updated`
+ { $$.number = EXEC_UPDATED; }
+ | `together`
+ { $$.number = EXEC_TOGETHER; }
+ | `ignore`
+ { $$.number = EXEC_IGNORE; }
+ | `quietly`
+ { $$.number = EXEC_QUIETLY; }
+ | `piecemeal`
+ { $$.number = EXEC_PIECEMEAL; }
+ | `existing`
+ { $$.number = EXEC_EXISTING; }
+ ;
+
+
+/*
+ * bindlist - list of variable to bind for an action
+ */
+
+bindlist : /* empty */
+ { $$.parse = pnull(); }
+ | `bind` list
+ { $$.parse = $2.parse; }
+ ;
+
+
diff --git a/tools/build/v2/engine/jamgramtab.h b/tools/build/v2/engine/jamgramtab.h
new file mode 100644
index 0000000000..a0fd43f6aa
--- /dev/null
+++ b/tools/build/v2/engine/jamgramtab.h
@@ -0,0 +1,44 @@
+ { "!", _BANG_t },
+ { "!=", _BANG_EQUALS_t },
+ { "&", _AMPER_t },
+ { "&&", _AMPERAMPER_t },
+ { "(", _LPAREN_t },
+ { ")", _RPAREN_t },
+ { "+=", _PLUS_EQUALS_t },
+ { ":", _COLON_t },
+ { ";", _SEMIC_t },
+ { "<", _LANGLE_t },
+ { "<=", _LANGLE_EQUALS_t },
+ { "=", _EQUALS_t },
+ { ">", _RANGLE_t },
+ { ">=", _RANGLE_EQUALS_t },
+ { "?=", _QUESTION_EQUALS_t },
+ { "[", _LBRACKET_t },
+ { "]", _RBRACKET_t },
+ { "actions", ACTIONS_t },
+ { "bind", BIND_t },
+ { "case", CASE_t },
+ { "class", CLASS_t },
+ { "default", DEFAULT_t },
+ { "else", ELSE_t },
+ { "existing", EXISTING_t },
+ { "for", FOR_t },
+ { "if", IF_t },
+ { "ignore", IGNORE_t },
+ { "in", IN_t },
+ { "include", INCLUDE_t },
+ { "local", LOCAL_t },
+ { "module", MODULE_t },
+ { "on", ON_t },
+ { "piecemeal", PIECEMEAL_t },
+ { "quietly", QUIETLY_t },
+ { "return", RETURN_t },
+ { "rule", RULE_t },
+ { "switch", SWITCH_t },
+ { "together", TOGETHER_t },
+ { "updated", UPDATED_t },
+ { "while", WHILE_t },
+ { "{", _LBRACE_t },
+ { "|", _BAR_t },
+ { "||", _BARBAR_t },
+ { "}", _RBRACE_t },
diff --git a/tools/build/v2/engine/lists.c b/tools/build/v2/engine/lists.c
new file mode 100644
index 0000000000..ebabb63e90
--- /dev/null
+++ b/tools/build/v2/engine/lists.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "newstr.h"
+# include "lists.h"
+
+/*
+ * lists.c - maintain lists of strings
+ *
+ * This implementation essentially uses a singly linked list, but
+ * guarantees that the head element of every list has a valid pointer
+ * to the tail of the list, so the new elements can efficiently and
+ * properly be appended to the end of a list.
+ *
+ * To avoid massive allocation, list_free() just tacks the whole freed
+ * chain onto freelist and list_new() looks on freelist first for an
+ * available list struct. list_free() does not free the strings in the
+ * chain: it lazily lets list_new() do so.
+ *
+ * 08/23/94 (seiwald) - new list_append()
+ * 09/07/00 (seiwald) - documented lol_*() functions
+ */
+
+static LIST *freelist = 0; /* junkpile for list_free() */
+
+/*
+ * list_append() - append a list onto another one, returning total
+ */
+
+LIST * list_append( LIST * l, LIST * nl )
+{
+ if ( !nl )
+ {
+ /* Just return l */
+ }
+ else if ( !l )
+ {
+ l = nl;
+ }
+ else
+ {
+ /* Graft two non-empty lists. */
+ l->tail->next = nl;
+ l->tail = nl->tail;
+ }
+
+ return l;
+}
+
+/*
+ * list_new() - tack a string onto the end of a list of strings
+ */
+
+LIST * list_new( LIST * head, char * string )
+{
+ LIST * l;
+
+ if ( DEBUG_LISTS )
+ printf( "list > %s <\n", string );
+
+ /* Get list struct from freelist, if one available. */
+ /* Otherwise allocate. */
+ /* If from freelist, must free string first */
+
+ if ( freelist )
+ {
+ l = freelist;
+ freestr( l->string );
+ freelist = freelist->next;
+ }
+ else
+ {
+ l = (LIST *)BJAM_MALLOC( sizeof( LIST ) );
+ }
+
+ /* If first on chain, head points here. */
+ /* If adding to chain, tack us on. */
+ /* Tail must point to this new, last element. */
+
+ if ( !head ) head = l;
+ else head->tail->next = l;
+ head->tail = l;
+ l->next = 0;
+
+ l->string = string;
+
+ return head;
+}
+
+
+/*
+ * list_copy() - copy a whole list of strings (nl) onto end of another (l).
+ */
+
+LIST * list_copy( LIST * l, LIST * nl )
+{
+ for ( ; nl; nl = list_next( nl ) )
+ l = list_new( l, copystr( nl->string ) );
+ return l;
+}
+
+
+/*
+ * list_sublist() - copy a subset of a list of strings.
+ */
+
+LIST * list_sublist( LIST * l, int start, int count )
+{
+ LIST * nl = 0;
+ for ( ; l && start--; l = list_next( l ) );
+ for ( ; l && count--; l = list_next( l ) )
+ nl = list_new( nl, copystr( l->string ) );
+ return nl;
+}
+
+
+static int str_ptr_compare( void const * va, void const * vb )
+{
+ char * a = *( (char * *)va );
+ char * b = *( (char * *)vb );
+ return strcmp(a, b);
+}
+
+
+LIST * list_sort( LIST * l )
+{
+ int len;
+ int ii;
+ char * * strings;
+ LIST * listp;
+ LIST * result = 0;
+
+ if ( !l )
+ return L0;
+
+ len = list_length( l );
+ strings = (char * *)BJAM_MALLOC( len * sizeof(char*) );
+
+ listp = l;
+ for ( ii = 0; ii < len; ++ii )
+ {
+ strings[ ii ] = listp->string;
+ listp = listp->next;
+ }
+
+ qsort( strings, len, sizeof( char * ), str_ptr_compare );
+
+ for ( ii = 0; ii < len; ++ii )
+ result = list_append( result, list_new( 0, strings[ ii ] ) );
+
+ BJAM_FREE( strings );
+
+ return result;
+}
+
+
+/*
+ * list_free() - free a list of strings
+ */
+
+void list_free( LIST * head )
+{
+ /* Just tack onto freelist. */
+ if ( head )
+ {
+ head->tail->next = freelist;
+ freelist = head;
+ }
+}
+
+
+/*
+ * list_pop_front() - remove the front element from a list of strings
+ */
+
+LIST * list_pop_front( LIST * l )
+{
+ LIST * result = l->next;
+ if ( result )
+ {
+ result->tail = l->tail;
+ l->next = L0;
+ l->tail = l;
+ }
+ list_free( l );
+ return result;
+}
+
+
+/*
+ * list_print() - print a list of strings to stdout
+ */
+
+void list_print( LIST * l )
+{
+ LIST * p = 0;
+ for ( ; l; p = l, l = list_next( l ) )
+ if ( p )
+ printf( "%s ", p->string );
+ if ( p )
+ printf( "%s", p->string );
+}
+
+
+/*
+ * list_length() - return the number of items in the list
+ */
+
+int list_length( LIST * l )
+{
+ int n = 0;
+ for ( ; l; l = list_next( l ), ++n );
+ return n;
+}
+
+
+int list_in( LIST * l, char * value )
+{
+ for ( ; l; l = l->next )
+ if ( strcmp( l->string, value ) == 0 )
+ return 1;
+ return 0;
+}
+
+
+LIST * list_unique( LIST * sorted_list )
+{
+ LIST * result = 0;
+ LIST * last_added = 0;
+
+ for ( ; sorted_list; sorted_list = sorted_list->next )
+ {
+ if ( !last_added || strcmp( sorted_list->string, last_added->string ) != 0 )
+ {
+ result = list_new( result, sorted_list->string );
+ last_added = sorted_list;
+ }
+ }
+ return result;
+}
+
+
+/*
+ * lol_init() - initialize a LOL (list of lists).
+ */
+
+void lol_init( LOL * lol )
+{
+ lol->count = 0;
+}
+
+
+/*
+ * lol_add() - append a LIST onto an LOL.
+ */
+
+void lol_add( LOL * lol, LIST * l )
+{
+ if ( lol->count < LOL_MAX )
+ lol->list[ lol->count++ ] = l;
+}
+
+
+/*
+ * lol_free() - free the LOL and its LISTs.
+ */
+
+void lol_free( LOL * lol )
+{
+ int i;
+ for ( i = 0; i < lol->count; ++i )
+ list_free( lol->list[ i ] );
+ lol->count = 0;
+}
+
+
+/*
+ * lol_get() - return one of the LISTs in the LOL.
+ */
+
+LIST * lol_get( LOL * lol, int i )
+{
+ return i < lol->count ? lol->list[ i ] : 0;
+}
+
+
+/*
+ * lol_print() - debug print LISTS separated by ":".
+ */
+
+void lol_print( LOL * lol )
+{
+ int i;
+
+ for ( i = 0; i < lol->count; ++i )
+ {
+ if ( i )
+ printf( " : " );
+ list_print( lol->list[ i ] );
+ }
+}
+
+#ifdef HAVE_PYTHON
+
+PyObject *list_to_python(LIST *l)
+{
+ PyObject *result = PyList_New(0);
+
+ for (; l; l = l->next)
+ {
+ PyObject* s = PyString_FromString(l->string);
+ PyList_Append(result, s);
+ Py_DECREF(s);
+ }
+
+ return result;
+}
+
+LIST *list_from_python(PyObject *l)
+{
+ LIST * result = 0;
+
+ Py_ssize_t i, n;
+ n = PySequence_Size(l);
+ for (i = 0; i < n; ++i)
+ {
+ PyObject *v = PySequence_GetItem(l, i);
+ result = list_new (result, newstr (PyString_AsString(v)));
+ Py_DECREF(v);
+ }
+
+ return result;
+}
+
+#endif
diff --git a/tools/build/v2/engine/lists.h b/tools/build/v2/engine/lists.h
new file mode 100644
index 0000000000..1dc598274d
--- /dev/null
+++ b/tools/build/v2/engine/lists.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * lists.h - the LIST structure and routines to manipulate them
+ *
+ * The whole of jam relies on lists of strings as a datatype. This
+ * module, in conjunction with newstr.c, handles these relatively
+ * efficiently.
+ *
+ * Structures defined:
+ *
+ * LIST - list of strings
+ * LOL - list of LISTs
+ *
+ * External routines:
+ *
+ * list_append() - append a list onto another one, returning total
+ * list_new() - tack a string onto the end of a list of strings
+ * list_copy() - copy a whole list of strings
+ * list_sublist() - copy a subset of a list of strings
+ * list_free() - free a list of strings
+ * list_print() - print a list of strings to stdout
+ * list_length() - return the number of items in the list
+ *
+ * lol_init() - initialize a LOL (list of lists)
+ * lol_add() - append a LIST onto an LOL
+ * lol_free() - free the LOL and its LISTs
+ * lol_get() - return one of the LISTs in the LOL
+ * lol_print() - debug print LISTS separated by ":"
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 08/23/94 (seiwald) - new list_append()
+ */
+
+#ifndef LISTS_DWA20011022_H
+# define LISTS_DWA20011022_H
+
+#ifdef HAVE_PYTHON
+#include <Python.h>
+#endif
+
+/*
+ * LIST - list of strings
+ */
+
+typedef struct _list LIST;
+
+struct _list {
+ LIST *next;
+ LIST *tail; /* only valid in head node */
+ char *string; /* private copy */
+};
+
+/*
+ * LOL - list of LISTs
+ */
+
+typedef struct _lol LOL;
+
+# define LOL_MAX 19
+
+struct _lol {
+ int count;
+ LIST *list[ LOL_MAX ];
+};
+
+LIST * list_append( LIST *l, LIST *nl );
+LIST * list_copy( LIST *l, LIST *nl );
+void list_free( LIST *head );
+LIST * list_new( LIST *head, char *string );
+void list_print( LIST *l );
+int list_length( LIST *l );
+LIST * list_sublist( LIST *l, int start, int count );
+LIST * list_pop_front( LIST *l );
+LIST * list_sort( LIST *l);
+LIST * list_unique( LIST *sorted_list);
+int list_in(LIST* l, char* value);
+
+# define list_next( l ) ((l)->next)
+
+# define L0 ((LIST *)0)
+
+void lol_add( LOL *lol, LIST *l );
+void lol_init( LOL *lol );
+void lol_free( LOL *lol );
+LIST * lol_get( LOL *lol, int i );
+void lol_print( LOL *lol );
+void lol_build( LOL* lol, char** elements );
+
+#ifdef HAVE_PYTHON
+
+PyObject *list_to_python(LIST *l);
+LIST *list_from_python(PyObject *l);
+
+#endif
+
+#endif
+
diff --git a/tools/build/v2/engine/make.c b/tools/build/v2/engine/make.c
new file mode 100644
index 0000000000..c871f0be2d
--- /dev/null
+++ b/tools/build/v2/engine/make.c
@@ -0,0 +1,814 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * make.c - bring a target up to date, once rules are in place.
+ *
+ * This modules controls the execution of rules to bring a target and its
+ * dependencies up to date. It is invoked after the targets, rules, et. al.
+ * described in rules.h are created by the interpreting jam files.
+ *
+ * This file contains the main make() entry point and the first pass make0().
+ * The second pass, make1(), which actually does the command execution, is in
+ * make1.c.
+ *
+ * External routines:
+ * make() - make a target, given its name
+ *
+ * Internal routines:
+ * make0() - bind and scan everything to make a TARGET
+ * make0sort() - reorder TARGETS chain by their time (newest to oldest)
+ *
+ * 12/26/93 (seiwald) - allow NOTIME targets to be expanded via $(<), $(>).
+ * 01/04/94 (seiwald) - print all targets, bounded, when tracing commands.
+ * 04/08/94 (seiwald) - progress report now reflects only targets with actions.
+ * 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET.
+ * 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
+ * 12/20/94 (seiwald) - make0() headers after determining fate of target, so
+ * that headers are not seen as being dependent on
+ * themselves.
+ * 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets.
+ * 02/02/95 (seiwald) - propagate leaf source time for new LEAVES rule.
+ * 02/14/95 (seiwald) - NOUPDATE rule means don't update existing target.
+ * 08/22/95 (seiwald) - NOUPDATE targets immune to anyhow (-a) flag.
+ * 09/06/00 (seiwald) - NOCARE affects targets with sources/actions.
+ * 03/02/01 (seiwald) - reverse NOCARE change.
+ * 03/14/02 (seiwald) - TEMPORARY targets no longer take on parents age.
+ * 03/16/02 (seiwald) - support for -g (reorder builds by source time).
+ */
+
+#include "jam.h"
+
+#include "lists.h"
+#include "parse.h"
+#include "variable.h"
+#include "rules.h"
+
+#ifdef OPT_HEADER_CACHE_EXT
+ #include "hcache.h"
+#endif
+
+#include "search.h"
+#include "newstr.h"
+#include "make.h"
+#include "headers.h"
+#include "command.h"
+#include <assert.h>
+
+#ifndef max
+ #define max( a,b ) ((a)>(b)?(a):(b))
+#endif
+
+static TARGETS * make0sort( TARGETS * c );
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+ static void dependGraphOutput( TARGET * t, int depth );
+#endif
+
+static const char * target_fate[] =
+{
+ "init", /* T_FATE_INIT */
+ "making", /* T_FATE_MAKING */
+ "stable", /* T_FATE_STABLE */
+ "newer", /* T_FATE_NEWER */
+ "temp", /* T_FATE_ISTMP */
+ "touched", /* T_FATE_TOUCHED */
+ "rebuild", /* T_FATE_REBUILD */
+ "missing", /* T_FATE_MISSING */
+ "needtmp", /* T_FATE_NEEDTMP */
+ "old", /* T_FATE_OUTDATED */
+ "update", /* T_FATE_UPDATE */
+ "nofind", /* T_FATE_CANTFIND */
+ "nomake" /* T_FATE_CANTMAKE */
+};
+
+static const char * target_bind[] =
+{
+ "unbound",
+ "missing",
+ "parents",
+ "exists",
+};
+
+# define spaces(x) ( " " + ( x > 20 ? 0 : 20-x ) )
+
+
+/*
+ * make() - make a target, given its name.
+ */
+
+int make( int n_targets, char const * * targets, int anyhow )
+{
+ int i;
+ COUNTS counts[ 1 ];
+ int status = 0; /* 1 if anything fails */
+
+#ifdef OPT_HEADER_CACHE_EXT
+ hcache_init();
+#endif
+
+ memset( (char *)counts, 0, sizeof( *counts ) );
+
+ /* First bind all targets with LOCATE_TARGET setting. This is needed to
+ * correctly handle dependencies to generated headers.
+ */
+ bind_explicitly_located_targets();
+
+ {
+ PROFILE_ENTER( MAKE_MAKE0 );
+ for ( i = 0; i < n_targets; ++i )
+ make0( bindtarget( targets[ i ] ), 0, 0, counts, anyhow );
+ PROFILE_EXIT( MAKE_MAKE0 );
+ }
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+ if ( DEBUG_GRAPH )
+ for ( i = 0; i < n_targets; ++i )
+ dependGraphOutput( bindtarget( targets[ i ] ), 0 );
+#endif
+
+ if ( DEBUG_MAKE )
+ {
+ if ( counts->targets )
+ printf( "...found %d target%s...\n", counts->targets,
+ counts->targets > 1 ? "s" : "" );
+ if ( counts->temp )
+ printf( "...using %d temp target%s...\n", counts->temp,
+ counts->temp > 1 ? "s" : "" );
+ if ( counts->updating )
+ printf( "...updating %d target%s...\n", counts->updating,
+ counts->updating > 1 ? "s" : "" );
+ if ( counts->cantfind )
+ printf( "...can't find %d target%s...\n", counts->cantfind,
+ counts->cantfind > 1 ? "s" : "" );
+ if ( counts->cantmake )
+ printf( "...can't make %d target%s...\n", counts->cantmake,
+ counts->cantmake > 1 ? "s" : "" );
+ }
+
+#ifdef OPT_HEADER_CACHE_EXT
+ hcache_done();
+#endif
+
+ status = counts->cantfind || counts->cantmake;
+
+ {
+ PROFILE_ENTER( MAKE_MAKE1 );
+ for ( i = 0; i < n_targets; ++i )
+ status |= make1( bindtarget( targets[ i ] ) );
+ PROFILE_EXIT( MAKE_MAKE1 );
+ }
+
+ return status;
+}
+
+
+/* Force any dependants of t that have already at least begun being visited by
+ * make0() to be updated.
+ */
+
+static void update_dependants( TARGET * t )
+{
+ TARGETS * q;
+
+ for ( q = t->dependants; q; q = q->next )
+ {
+ TARGET * p = q->target;
+ char fate0 = p->fate;
+
+ /* If we have already at least begun visiting it and we are not already
+ * rebuilding it for other reasons.
+ */
+ if ( ( fate0 != T_FATE_INIT ) && ( fate0 < T_FATE_BUILD ) )
+ {
+ p->fate = T_FATE_UPDATE;
+
+ if ( DEBUG_FATE )
+ {
+ printf( "fate change %s from %s to %s (as dependant of %s)\n",
+ p->name, target_fate[ (int) fate0 ], target_fate[ (int) p->fate ], t->name );
+ }
+
+ /* If we are done visiting it, go back and make sure its dependants
+ * get rebuilt.
+ */
+ if ( fate0 > T_FATE_MAKING )
+ update_dependants( p );
+ }
+ }
+}
+
+
+/*
+ * Make sure that all of t's rebuilds get rebuilt.
+ */
+
+static void force_rebuilds( TARGET * t )
+{
+ TARGETS * d;
+ for ( d = t->rebuilds; d; d = d->next )
+ {
+ TARGET * r = d->target;
+
+ /* If it is not already being rebuilt for other reasons. */
+ if ( r->fate < T_FATE_BUILD )
+ {
+ if ( DEBUG_FATE )
+ printf( "fate change %s from %s to %s (by rebuild)\n",
+ r->name, target_fate[ (int) r->fate ], target_fate[ T_FATE_REBUILD ] );
+
+ /* Force rebuild it. */
+ r->fate = T_FATE_REBUILD;
+
+ /* And make sure its dependants are updated too. */
+ update_dependants( r );
+ }
+ }
+}
+
+
+/*
+ * make0() - bind and scan everything to make a TARGET.
+ *
+ * Recursively binds a target, searches for #included headers, calls itself on
+ * those headers and any dependencies.
+ */
+
+void make0
+(
+ TARGET * t,
+ TARGET * p, /* parent */
+ int depth, /* for display purposes */
+ COUNTS * counts, /* for reporting */
+ int anyhow
+) /* forcibly touch all (real) targets */
+{
+ TARGETS * c;
+ TARGET * ptime = t;
+ time_t last;
+ time_t leaf;
+ time_t hlast;
+ int fate;
+ char const * flag = "";
+ SETTINGS * s;
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+ int savedFate, oldTimeStamp;
+#endif
+
+ if ( DEBUG_MAKEPROG )
+ printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
+
+ /*
+ * Step 1: initialize
+ */
+
+ if ( DEBUG_MAKEPROG )
+ printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
+
+ t->fate = T_FATE_MAKING;
+
+ /*
+ * Step 2: under the influence of "on target" variables,
+ * bind the target and search for headers.
+ */
+
+ /* Step 2a: set "on target" variables. */
+ s = copysettings( t->settings );
+ pushsettings( s );
+
+ /* Step 2b: find and timestamp the target file (if it is a file). */
+ if ( ( t->binding == T_BIND_UNBOUND ) && !( t->flags & T_FLAG_NOTFILE ) )
+ {
+ char * another_target;
+ t->boundname = search( t->name, &t->time, &another_target,
+ t->flags & T_FLAG_ISFILE );
+ /* If it was detected that this target refers to an already existing and
+ * bound one, we add an include dependency, so that every target
+ * depending on us will depend on that other target as well.
+ */
+ if ( another_target )
+ target_include( t, bindtarget( another_target ) );
+
+ t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
+ }
+
+ /* INTERNAL, NOTFILE header nodes have the time of their parents. */
+ if ( p && ( t->flags & T_FLAG_INTERNAL ) )
+ ptime = p;
+
+ /* If temp file does not exist but parent does, use parent. */
+ if ( p && ( t->flags & T_FLAG_TEMP ) &&
+ ( t->binding == T_BIND_MISSING ) &&
+ ( p->binding != T_BIND_MISSING ) )
+ {
+ t->binding = T_BIND_PARENTS;
+ ptime = p;
+ }
+
+#ifdef OPT_SEMAPHORE
+ {
+ LIST * var = var_get( "JAM_SEMAPHORE" );
+ if ( var )
+ {
+ TARGET * semaphore = bindtarget( var->string );
+ semaphore->progress = T_MAKE_SEMAPHORE;
+ t->semaphore = semaphore;
+ }
+ }
+#endif
+
+ /* Step 2c: If its a file, search for headers. */
+ if ( t->binding == T_BIND_EXISTS )
+ headers( t );
+
+ /* Step 2d: reset "on target" variables. */
+ popsettings( s );
+ freesettings( s );
+
+ /*
+ * Pause for a little progress reporting .
+ */
+
+ if ( DEBUG_BIND )
+ {
+ if ( strcmp( t->name, t->boundname ) )
+ printf( "bind\t--\t%s%s: %s\n",
+ spaces( depth ), t->name, t->boundname );
+
+ switch ( t->binding )
+ {
+ case T_BIND_UNBOUND:
+ case T_BIND_MISSING:
+ case T_BIND_PARENTS:
+ printf( "time\t--\t%s%s: %s\n",
+ spaces( depth ), t->name, target_bind[ (int) t->binding ] );
+ break;
+
+ case T_BIND_EXISTS:
+ printf( "time\t--\t%s%s: %s",
+ spaces( depth ), t->name, ctime( &t->time ) );
+ break;
+ }
+ }
+
+ /*
+ * Step 3: recursively make0() dependencies & headers.
+ */
+
+ /* Step 3a: recursively make0() dependencies. */
+ for ( c = t->depends; c; c = c->next )
+ {
+ int internal = t->flags & T_FLAG_INTERNAL;
+
+ /* Warn about circular deps, except for includes, which include each
+ * other alot.
+ */
+ if ( c->target->fate == T_FATE_INIT )
+ make0( c->target, ptime, depth + 1, counts, anyhow );
+ else if ( c->target->fate == T_FATE_MAKING && !internal )
+ printf( "warning: %s depends on itself\n", c->target->name );
+ }
+
+ /* Step 3b: recursively make0() internal includes node. */
+ if ( t->includes )
+ make0( t->includes, p, depth + 1, counts, anyhow );
+
+ /* Step 3c: add dependencies' includes to our direct dependencies. */
+ {
+ TARGETS * incs = 0;
+ for ( c = t->depends; c; c = c->next )
+ if ( c->target->includes )
+ incs = targetentry( incs, c->target->includes );
+ t->depends = targetchain( t->depends, incs );
+ }
+
+ /*
+ * Step 4: compute time & fate
+ */
+
+ /* Step 4a: pick up dependencies' time and fate */
+ last = 0;
+ leaf = 0;
+ fate = T_FATE_STABLE;
+ for ( c = t->depends; c; c = c->next )
+ {
+ /* If LEAVES has been applied, we only heed the timestamps of the leaf
+ * source nodes.
+ */
+ leaf = max( leaf, c->target->leaf );
+
+ if ( t->flags & T_FLAG_LEAVES )
+ {
+ last = leaf;
+ continue;
+ }
+
+ last = max( last, c->target->time );
+ fate = max( fate, c->target->fate );
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+ if ( DEBUG_FATE )
+ if ( fate < c->target->fate )
+ printf( "fate change %s from %s to %s by dependency %s\n",
+ t->name, target_fate[(int) fate], target_fate[(int) c->target->fate],
+ c->target->name );
+#endif
+ }
+
+ /* Step 4b: pick up included headers time */
+
+ /*
+ * If a header is newer than a temp source that includes it,
+ * the temp source will need building.
+ */
+
+ hlast = t->includes ? t->includes->time : 0;
+
+ /* Step 4c: handle NOUPDATE oddity.
+ *
+ * If a NOUPDATE file exists, mark it as having eternally old dependencies.
+ * Do not inherit our fate from our dependencies. Decide fate based only on
+ * other flags and our binding (done later).
+ */
+ if ( t->flags & T_FLAG_NOUPDATE )
+ {
+#ifdef OPT_GRAPH_DEBUG_EXT
+ if ( DEBUG_FATE )
+ if ( fate != T_FATE_STABLE )
+ printf( "fate change %s back to stable, NOUPDATE.\n", t->name
+ );
+#endif
+
+ last = 0;
+ t->time = 0;
+
+ /* Do not inherit our fate from our dependencies. Decide fate based only
+ * upon other flags and our binding (done later).
+ */
+ fate = T_FATE_STABLE;
+ }
+
+ /* Step 4d: determine fate: rebuild target or what? */
+
+ /*
+ In English:
+ If can not find or make child, can not make target.
+ If children changed, make target.
+ If target missing, make it.
+ If children newer, make target.
+ If temp's children newer than parent, make temp.
+ If temp's headers newer than parent, make temp.
+ If deliberately touched, make it.
+ If up-to-date temp file present, use it.
+ If target newer than non-notfile parent, mark target newer.
+ Otherwise, stable!
+
+ Note this block runs from least to most stable:
+ as we make it further down the list, the target's
+ fate is getting stabler.
+ */
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+ savedFate = fate;
+ oldTimeStamp = 0;
+#endif
+
+ if ( fate >= T_FATE_BROKEN )
+ {
+ fate = T_FATE_CANTMAKE;
+ }
+ else if ( fate >= T_FATE_SPOIL )
+ {
+ fate = T_FATE_UPDATE;
+ }
+ else if ( t->binding == T_BIND_MISSING )
+ {
+ fate = T_FATE_MISSING;
+ }
+ else if ( ( t->binding == T_BIND_EXISTS ) && ( last > t->time ) )
+ {
+#ifdef OPT_GRAPH_DEBUG_EXT
+ oldTimeStamp = 1;
+#endif
+ fate = T_FATE_OUTDATED;
+ }
+ else if ( ( t->binding == T_BIND_PARENTS ) && ( last > p->time ) )
+ {
+#ifdef OPT_GRAPH_DEBUG_EXT
+ oldTimeStamp = 1;
+#endif
+ fate = T_FATE_NEEDTMP;
+ }
+ else if ( ( t->binding == T_BIND_PARENTS ) && ( hlast > p->time ) )
+ {
+ fate = T_FATE_NEEDTMP;
+ }
+ else if ( t->flags & T_FLAG_TOUCHED )
+ {
+ fate = T_FATE_TOUCHED;
+ }
+ else if ( anyhow && !( t->flags & T_FLAG_NOUPDATE ) )
+ {
+ fate = T_FATE_TOUCHED;
+ }
+ else if ( ( t->binding == T_BIND_EXISTS ) && ( t->flags & T_FLAG_TEMP ) )
+ {
+ fate = T_FATE_ISTMP;
+ }
+ else if ( ( t->binding == T_BIND_EXISTS ) && p &&
+ ( p->binding != T_BIND_UNBOUND ) && ( t->time > p->time ) )
+ {
+#ifdef OPT_GRAPH_DEBUG_EXT
+ oldTimeStamp = 1;
+#endif
+ fate = T_FATE_NEWER;
+ }
+ else
+ {
+ fate = T_FATE_STABLE;
+ }
+#ifdef OPT_GRAPH_DEBUG_EXT
+ if ( DEBUG_FATE && ( fate != savedFate ) )
+ {
+ if ( savedFate == T_FATE_STABLE )
+ printf( "fate change %s set to %s%s\n", t->name,
+ target_fate[ fate ], oldTimeStamp ? " (by timestamp)" : "" );
+ else
+ printf( "fate change %s from %s to %s%s\n", t->name,
+ target_fate[ savedFate ], target_fate[ fate ],
+ oldTimeStamp ? " (by timestamp)" : "" );
+ }
+#endif
+
+ /* Step 4e: handle missing files */
+ /* If it is missing and there are no actions to create it, boom. */
+ /* If we can not make a target we do not care about it, okay. */
+ /* We could insist that there are updating actions for all missing */
+ /* files, but if they have dependencies we just pretend it is a NOTFILE. */
+
+ if ( ( fate == T_FATE_MISSING ) && !t->actions && !t->depends )
+ {
+ if ( t->flags & T_FLAG_NOCARE )
+ {
+#ifdef OPT_GRAPH_DEBUG_EXT
+ if ( DEBUG_FATE )
+ printf( "fate change %s to STABLE from %s, "
+ "no actions, no dependencies and do not care\n",
+ t->name, target_fate[ fate ] );
+#endif
+ fate = T_FATE_STABLE;
+ }
+ else
+ {
+ printf( "don't know how to make %s\n", t->name );
+ fate = T_FATE_CANTFIND;
+ }
+ }
+
+ /* Step 4f: propagate dependencies' time & fate. */
+ /* Set leaf time to be our time only if this is a leaf. */
+
+ t->time = max( t->time, last );
+ t->leaf = leaf ? leaf : t->time ;
+ /* This target's fate may have been updated by virtue of following some
+ * target's rebuilds list, so only allow it to be increased to the fate we
+ * have calculated. Otherwise, grab its new fate.
+ */
+ if ( fate > t->fate )
+ t->fate = fate;
+ else
+ fate = t->fate;
+
+ /* Step 4g: if this target needs to be built, force rebuild everything in
+ * this target's rebuilds list.
+ */
+ if ( ( fate >= T_FATE_BUILD ) && ( fate < T_FATE_BROKEN ) )
+ force_rebuilds( t );
+
+ /*
+ * Step 5: sort dependencies by their update time.
+ */
+
+ if ( globs.newestfirst )
+ t->depends = make0sort( t->depends );
+
+ /*
+ * Step 6: a little harmless tabulating for tracing purposes
+ */
+
+ /* Do not count or report interal includes nodes. */
+ if ( t->flags & T_FLAG_INTERNAL )
+ return;
+
+ if ( counts )
+ {
+#ifdef OPT_IMPROVED_PATIENCE_EXT
+ ++counts->targets;
+#else
+ if ( !( ++counts->targets % 1000 ) && DEBUG_MAKE )
+ printf( "...patience...\n" );
+#endif
+
+ if ( fate == T_FATE_ISTMP )
+ ++counts->temp;
+ else if ( fate == T_FATE_CANTFIND )
+ ++counts->cantfind;
+ else if ( ( fate == T_FATE_CANTMAKE ) && t->actions )
+ ++counts->cantmake;
+ else if ( ( fate >= T_FATE_BUILD ) && ( fate < T_FATE_BROKEN ) &&
+ t->actions )
+ ++counts->updating;
+ }
+
+ if ( !( t->flags & T_FLAG_NOTFILE ) && ( fate >= T_FATE_SPOIL ) )
+ flag = "+";
+ else if ( ( t->binding == T_BIND_EXISTS ) && p && ( t->time > p->time ) )
+ flag = "*";
+
+ if ( DEBUG_MAKEPROG )
+ printf( "made%s\t%s\t%s%s\n", flag, target_fate[ (int) t->fate ],
+ spaces( depth ), t->name );
+}
+
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+
+static const char * target_name( TARGET * t )
+{
+ static char buf[ 1000 ];
+ if ( t->flags & T_FLAG_INTERNAL )
+ {
+ sprintf( buf, "%s (internal node)", t->name );
+ return buf;
+ }
+ return t->name;
+}
+
+
+/*
+ * dependGraphOutput() - output the DG after make0 has run.
+ */
+
+static void dependGraphOutput( TARGET * t, int depth )
+{
+ TARGETS * c;
+
+ if ( ( t->flags & T_FLAG_VISITED ) || !t->name || !t->boundname )
+ return;
+
+ t->flags |= T_FLAG_VISITED;
+
+ switch ( t->fate )
+ {
+ case T_FATE_TOUCHED:
+ case T_FATE_MISSING:
+ case T_FATE_OUTDATED:
+ case T_FATE_UPDATE:
+ printf( "->%s%2d Name: %s\n", spaces( depth ), depth, target_name( t ) );
+ break;
+ default:
+ printf( " %s%2d Name: %s\n", spaces( depth ), depth, target_name( t ) );
+ break;
+ }
+
+ if ( strcmp( t->name, t->boundname ) )
+ printf( " %s Loc: %s\n", spaces( depth ), t->boundname );
+
+ switch ( t->fate )
+ {
+ case T_FATE_STABLE:
+ printf( " %s : Stable\n", spaces( depth ) );
+ break;
+ case T_FATE_NEWER:
+ printf( " %s : Newer\n", spaces( depth ) );
+ break;
+ case T_FATE_ISTMP:
+ printf( " %s : Up to date temp file\n", spaces( depth ) );
+ break;
+ case T_FATE_NEEDTMP:
+ printf( " %s : Temporary file, to be updated\n", spaces( depth ) );
+ break;
+ case T_FATE_TOUCHED:
+ printf( " %s : Been touched, updating it\n", spaces( depth ) );
+ break;
+ case T_FATE_MISSING:
+ printf( " %s : Missing, creating it\n", spaces( depth ) );
+ break;
+ case T_FATE_OUTDATED:
+ printf( " %s : Outdated, updating it\n", spaces( depth ) );
+ break;
+ case T_FATE_REBUILD:
+ printf( " %s : Rebuild, updating it\n", spaces( depth ) );
+ break;
+ case T_FATE_UPDATE:
+ printf( " %s : Updating it\n", spaces( depth ) );
+ break;
+ case T_FATE_CANTFIND:
+ printf( " %s : Can not find it\n", spaces( depth ) );
+ break;
+ case T_FATE_CANTMAKE:
+ printf( " %s : Can make it\n", spaces( depth ) );
+ break;
+ }
+
+ if ( t->flags & ~T_FLAG_VISITED )
+ {
+ printf( " %s : ", spaces( depth ) );
+ if ( t->flags & T_FLAG_TEMP ) printf( "TEMPORARY " );
+ if ( t->flags & T_FLAG_NOCARE ) printf( "NOCARE " );
+ if ( t->flags & T_FLAG_NOTFILE ) printf( "NOTFILE " );
+ if ( t->flags & T_FLAG_TOUCHED ) printf( "TOUCHED " );
+ if ( t->flags & T_FLAG_LEAVES ) printf( "LEAVES " );
+ if ( t->flags & T_FLAG_NOUPDATE ) printf( "NOUPDATE " );
+ printf( "\n" );
+ }
+
+ for ( c = t->depends; c; c = c->next )
+ {
+ printf( " %s : Depends on %s (%s)", spaces( depth ),
+ target_name( c->target ), target_fate[ (int) c->target->fate ] );
+ if ( c->target->time == t->time )
+ printf( " (max time)");
+ printf( "\n" );
+ }
+
+ for ( c = t->depends; c; c = c->next )
+ dependGraphOutput( c->target, depth + 1 );
+}
+#endif
+
+
+/*
+ * make0sort() - reorder TARGETS chain by their time (newest to oldest).
+ *
+ * We walk chain, taking each item and inserting it on the sorted result, with
+ * newest items at the front. This involves updating each of the TARGETS'
+ * c->next and c->tail. Note that we make c->tail a valid prev pointer for every
+ * entry. Normally, it is only valid at the head, where prev == tail. Note also
+ * that while tail is a loop, next ends at the end of the chain.
+ */
+
+static TARGETS * make0sort( TARGETS * chain )
+{
+ PROFILE_ENTER( MAKE_MAKE0SORT );
+
+ TARGETS * result = 0;
+
+ /* Walk the current target list. */
+ while ( chain )
+ {
+ TARGETS * c = chain;
+ TARGETS * s = result;
+
+ chain = chain->next;
+
+ /* Find point s in result for c. */
+ while ( s && ( s->target->time > c->target->time ) )
+ s = s->next;
+
+ /* Insert c in front of s (might be 0). Do not even think of deciphering
+ * this.
+ */
+ c->next = s; /* good even if s = 0 */
+ if ( result == s ) result = c; /* new head of chain? */
+ if ( !s ) s = result; /* wrap to ensure a next */
+ if ( result != c ) s->tail->next = c; /* not head? be prev's next */
+ c->tail = s->tail; /* take on next's prev */
+ s->tail = c; /* make next's prev us */
+ }
+
+ PROFILE_EXIT( MAKE_MAKE0SORT );
+ return result;
+}
+
+
+static LIST * targets_to_update_ = 0;
+
+
+void mark_target_for_updating( char * target )
+{
+ targets_to_update_ = list_new( targets_to_update_, target );
+}
+
+
+LIST * targets_to_update()
+{
+ return targets_to_update_;
+}
+
+
+void clear_targets_to_update()
+{
+ list_free( targets_to_update_ );
+ targets_to_update_ = 0;
+}
diff --git a/tools/build/v2/engine/make.h b/tools/build/v2/engine/make.h
new file mode 100644
index 0000000000..b372263e19
--- /dev/null
+++ b/tools/build/v2/engine/make.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * make.h - bring a target up to date, once rules are in place
+ */
+
+#include "lists.h"
+
+int make( int n_targets, const char **targets, int anyhow );
+int make1( TARGET *t );
+
+typedef struct {
+ int temp;
+ int updating;
+ int cantfind;
+ int cantmake;
+ int targets;
+ int made;
+} COUNTS ;
+
+
+void make0( TARGET *t, TARGET *p, int depth,
+ COUNTS *counts, int anyhow );
+
+
+/*
+ * Specifies that the target should be updated.
+ */
+void mark_target_for_updating(char *target);
+/*
+ * Returns the list of all the target previously passed to 'mark_target_for_updating'.
+ */
+LIST *targets_to_update();
+/*
+ * Cleasr/unmarks all targets that are currently marked for update.
+ */
+void clear_targets_to_update();
diff --git a/tools/build/v2/engine/make1.c b/tools/build/v2/engine/make1.c
new file mode 100644
index 0000000000..8001f33390
--- /dev/null
+++ b/tools/build/v2/engine/make1.c
@@ -0,0 +1,1145 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * make1.c - execute command to bring targets up to date
+ *
+ * This module contains make1(), the entry point called by make() to
+ * recursively decend the dependency graph executing update actions as
+ * marked by make0().
+ *
+ * External routines:
+ *
+ * make1() - execute commands to update a TARGET and all of its dependencies.
+ *
+ * Internal routines, the recursive/asynchronous command executors:
+ *
+ * make1a() - recursively traverse dependency target tree, calling make1b().
+ * make1atail() - started processing all dependencies so go on to make1b().
+ * make1b() - when dependencies are up to date, build target with make1c().
+ * make1c() - launch target's next command, call parents' make1b() if none.
+ * make1d() - handle command execution completion and call back make1c().
+ *
+ * Internal support routines:
+ *
+ * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc.
+ * make1list() - turn a list of targets into a LIST, for $(<) and $(>).
+ * make1settings() - for vars that get bound values, build up replacement lists.
+ * make1bind() - bind targets that weren't bound in dependency analysis.
+ *
+ * 04/16/94 (seiwald) - Split from make.c.
+ * 04/21/94 (seiwald) - Handle empty "updated" actions.
+ * 05/04/94 (seiwald) - async multiprocess (-j) support.
+ * 06/01/94 (seiwald) - new 'actions existing' does existing sources.
+ * 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
+ * 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets.
+ * 01/22/94 (seiwald) - pass per-target JAMSHELL down to exec_cmd().
+ * 02/28/95 (seiwald) - Handle empty "existing" actions.
+ * 03/10/95 (seiwald) - Fancy counts.
+ */
+
+#include "jam.h"
+
+#include "lists.h"
+#include "parse.h"
+#include "assert.h"
+#include "variable.h"
+#include "rules.h"
+#include "headers.h"
+
+#include "search.h"
+#include "newstr.h"
+#include "make.h"
+#include "command.h"
+#include "execcmd.h"
+#include "compile.h"
+#include "output.h"
+
+#include <stdlib.h>
+
+#if ! defined(NT) || defined(__GNUC__)
+ #include <unistd.h> /* for unlink */
+#endif
+
+static CMD * make1cmds ( TARGET * );
+static LIST * make1list ( LIST *, TARGETS *, int flags );
+static SETTINGS * make1settings( LIST * vars );
+static void make1bind ( TARGET * );
+
+/* Ugly static - it is too hard to carry it through the callbacks. */
+
+static struct
+{
+ int failed;
+ int skipped;
+ int total;
+ int made;
+} counts[ 1 ] ;
+
+/* Target state - remove recursive calls by just keeping track of state target
+ * is in.
+ */
+typedef struct _state
+{
+ struct _state * prev; /* previous state on stack */
+ TARGET * t; /* current target */
+ TARGET * parent; /* parent argument necessary for make1a() */
+#define T_STATE_MAKE1A 0 /* make1a() should be called */
+#define T_STATE_MAKE1ATAIL 1 /* make1atail() should be called */
+#define T_STATE_MAKE1B 2 /* make1b() should be called */
+#define T_STATE_MAKE1C 3 /* make1c() should be called */
+#define T_STATE_MAKE1D 4 /* make1d() should be called */
+ int curstate; /* current state */
+ int status;
+} state;
+
+static void make1a ( state * );
+static void make1atail ( state * );
+static void make1b ( state * );
+static void make1c ( state * );
+static void make1d ( state * );
+static void make_closure( void * closure, int status, timing_info *, char *, char * );
+
+typedef struct _stack
+{
+ state * stack;
+} stack;
+
+static stack state_stack = { NULL };
+
+static state * state_freelist = NULL;
+
+
+static state * alloc_state()
+{
+ if ( state_freelist != NULL )
+ {
+ state * pState = state_freelist;
+ state_freelist = pState->prev;
+ memset( pState, 0, sizeof( state ) );
+ return pState;
+ }
+
+ return (state *)BJAM_MALLOC( sizeof( state ) );
+}
+
+
+static void free_state( state * pState )
+{
+ pState->prev = state_freelist;
+ state_freelist = pState;
+}
+
+
+static void clear_state_freelist()
+{
+ while ( state_freelist != NULL )
+ {
+ state * pState = state_freelist;
+ state_freelist = state_freelist->prev;
+ BJAM_FREE( pState );
+ }
+}
+
+
+static state * current_state( stack * pStack )
+{
+ return pStack->stack;
+}
+
+
+static void pop_state( stack * pStack )
+{
+ if ( pStack->stack != NULL )
+ {
+ state * pState = pStack->stack->prev;
+ free_state( pStack->stack );
+ pStack->stack = pState;
+ }
+}
+
+
+static state * push_state( stack * pStack, TARGET * t, TARGET * parent, int curstate )
+{
+ state * pState = alloc_state();
+
+ pState->t = t;
+ pState->parent = parent;
+ pState->prev = pStack->stack;
+ pState->curstate = curstate;
+
+ pStack->stack = pState;
+
+ return pStack->stack;
+}
+
+
+/*
+ * Pushes a stack onto another stack, effectively reversing the order.
+ */
+
+static void push_stack_on_stack( stack * pDest, stack * pSrc )
+{
+ while ( pSrc->stack != NULL )
+ {
+ state * pState = pSrc->stack;
+ pSrc->stack = pSrc->stack->prev;
+ pState->prev = pDest->stack;
+ pDest->stack = pState;
+ }
+}
+
+
+/*
+ * make1() - execute commands to update a TARGET and all of its dependencies.
+ */
+
+static int intr = 0;
+
+int make1( TARGET * t )
+{
+ state * pState;
+
+ memset( (char *)counts, 0, sizeof( *counts ) );
+
+ /* Recursively make the target and its dependencies. */
+ push_state( &state_stack, t, NULL, T_STATE_MAKE1A );
+
+ do
+ {
+ while ( ( pState = current_state( &state_stack ) ) != NULL )
+ {
+ if ( intr )
+ pop_state( &state_stack );
+
+ switch ( pState->curstate )
+ {
+ case T_STATE_MAKE1A : make1a ( pState ); break;
+ case T_STATE_MAKE1ATAIL: make1atail( pState ); break;
+ case T_STATE_MAKE1B : make1b ( pState ); break;
+ case T_STATE_MAKE1C : make1c ( pState ); break;
+ case T_STATE_MAKE1D : make1d ( pState ); break;
+ }
+ }
+ }
+ /* Wait for any outstanding commands to finish running. */
+ while ( exec_wait() );
+
+ clear_state_freelist();
+
+ /* Talk about it. */
+ if ( counts->failed )
+ printf( "...failed updating %d target%s...\n", counts->failed,
+ counts->failed > 1 ? "s" : "" );
+ if ( DEBUG_MAKE && counts->skipped )
+ printf( "...skipped %d target%s...\n", counts->skipped,
+ counts->skipped > 1 ? "s" : "" );
+ if ( DEBUG_MAKE && counts->made )
+ printf( "...updated %d target%s...\n", counts->made,
+ counts->made > 1 ? "s" : "" );
+
+ return counts->total != counts->made;
+}
+
+
+/*
+ * make1a() - recursively traverse target tree, calling make1b().
+ *
+ * Called to start processing a specified target. Does nothing if the target is
+ * already being processed or otherwise starts processing all of its
+ * dependencies. Once all of its dependencies have started being processed goes
+ * on and calls make1b() (actually does that indirectly via a helper
+ * make1atail() state).
+ */
+
+static void make1a( state * pState )
+{
+ TARGET * t = pState->t;
+ TARGETS * c;
+
+ /* If the parent is the first to try to build this target or this target is
+ * in the make1c() quagmire, arrange for the parent to be notified when this
+ * target is built.
+ */
+ if ( pState->parent )
+ switch ( pState->t->progress )
+ {
+ case T_MAKE_INIT:
+ case T_MAKE_ACTIVE:
+ case T_MAKE_RUNNING:
+ pState->t->parents = targetentry( pState->t->parents,
+ pState->parent );
+ ++pState->parent->asynccnt;
+ }
+
+ /* If this target is already being processed then do nothing. There is no
+ * need to start processing the same target all over again.
+ */
+ if ( pState->t->progress != T_MAKE_INIT )
+ {
+ pop_state( &state_stack );
+ return;
+ }
+
+ /* Asynccnt counts the dependencies preventing this target from proceeding
+ * to make1b() for actual building. We start off with a count of 1 to
+ * prevent anything from happening until we can notify all dependencies that
+ * they are needed. This 1 is accounted for when we call make1b() ourselves,
+ * below. Without this if a a dependency gets built before we finish
+ * processing all of our other dependencies our build might be triggerred
+ * prematurely.
+ */
+ pState->t->asynccnt = 1;
+
+ /* Add header nodes created during the building process. */
+ {
+ TARGETS * inc = 0;
+ for ( c = t->depends; c; c = c->next )
+ if ( c->target->rescanned && c->target->includes )
+ inc = targetentry( inc, c->target->includes );
+ t->depends = targetchain( t->depends, inc );
+ }
+
+ /* Guard against circular dependencies. */
+ pState->t->progress = T_MAKE_ONSTACK;
+
+ {
+ stack temp_stack = { NULL };
+ for ( c = t->depends; c && !intr; c = c->next )
+ push_state( &temp_stack, c->target, pState->t, T_STATE_MAKE1A );
+
+ /* Using stacks reverses the order of execution. Reverse it back. */
+ push_stack_on_stack( &state_stack, &temp_stack );
+ }
+
+ pState->curstate = T_STATE_MAKE1ATAIL;
+}
+
+
+/*
+ * make1atail() - started processing all dependencies so go on to make1b().
+ */
+
+static void make1atail( state * pState )
+{
+ pState->t->progress = T_MAKE_ACTIVE;
+ /* Now that all of our dependencies have bumped up our asynccnt we can
+ * remove our own internal bump added to prevent this target from being
+ * built before all of its dependencies start getting processed.
+ */
+ pState->curstate = T_STATE_MAKE1B;
+}
+
+
+/*
+ * make1b() - when dependencies are up to date, build target with make1c().
+ *
+ * Called after all dependencies have started being processed and after each of
+ * them finishes its processing. The target actually goes on to getting built in
+ * make1c() only after all of its dependencies have finished their processing.
+ */
+
+static void make1b( state * pState )
+{
+ TARGET * t = pState->t;
+ TARGETS * c;
+ TARGET * failed = 0;
+ char * failed_name = "dependencies";
+
+ /* If any dependencies are still outstanding, wait until they call make1b()
+ * to signal their completion.
+ */
+ if ( --pState->t->asynccnt )
+ {
+ pop_state( &state_stack );
+ return;
+ }
+
+ /* Try to aquire a semaphore. If it is locked, wait until the target that
+ * locked it is built and signal completition.
+ */
+#ifdef OPT_SEMAPHORE
+ if ( t->semaphore && t->semaphore->asynccnt )
+ {
+ /* Append 't' to the list of targets waiting on semaphore. */
+ t->semaphore->parents = targetentry( t->semaphore->parents, t );
+ t->asynccnt++;
+
+ if ( DEBUG_EXECCMD )
+ printf( "SEM: %s is busy, delaying launch of %s\n",
+ t->semaphore->name, t->name );
+ pop_state( &state_stack );
+ return;
+ }
+#endif
+
+ /* Now ready to build target 't', if dependencies built OK. */
+
+ /* Collect status from dependencies. */
+ for ( c = t->depends; c; c = c->next )
+ if ( c->target->status > t->status && !( c->target->flags & T_FLAG_NOCARE ) )
+ {
+ failed = c->target;
+ pState->t->status = c->target->status;
+ }
+ /* If an internal header node failed to build, we want to output the target
+ * that it failed on.
+ */
+ if ( failed )
+ {
+ failed_name = failed->flags & T_FLAG_INTERNAL
+ ? failed->failed
+ : failed->name;
+ }
+ t->failed = failed_name;
+
+ /* If actions for building any of the dependencies have failed, bail.
+ * Otherwise, execute all actions to make the current target.
+ */
+ if ( ( pState->t->status == EXEC_CMD_FAIL ) && pState->t->actions )
+ {
+ ++counts->skipped;
+ if ( ( pState->t->flags & ( T_FLAG_RMOLD | T_FLAG_NOTFILE ) ) == T_FLAG_RMOLD )
+ {
+ if ( !unlink( pState->t->boundname ) )
+ printf( "...removing outdated %s\n", pState->t->boundname );
+ }
+ else
+ printf( "...skipped %s for lack of %s...\n", pState->t->name, failed_name );
+ }
+
+ if ( pState->t->status == EXEC_CMD_OK )
+ switch ( pState->t->fate )
+ {
+ /* These are handled by the default case below now
+ case T_FATE_INIT:
+ case T_FATE_MAKING:
+ */
+
+ case T_FATE_STABLE:
+ case T_FATE_NEWER:
+ break;
+
+ case T_FATE_CANTFIND:
+ case T_FATE_CANTMAKE:
+ pState->t->status = EXEC_CMD_FAIL;
+ break;
+
+ case T_FATE_ISTMP:
+ if ( DEBUG_MAKE )
+ printf( "...using %s...\n", pState->t->name );
+ break;
+
+ case T_FATE_TOUCHED:
+ case T_FATE_MISSING:
+ case T_FATE_NEEDTMP:
+ case T_FATE_OUTDATED:
+ case T_FATE_UPDATE:
+ case T_FATE_REBUILD:
+ /* Prepare commands for executing actions scheduled for this target
+ * and then schedule transfer to make1c() state to proceed with
+ * executing the prepared commands. Commands have their embedded
+ * variables automatically expanded, including making use of any "on
+ * target" variables.
+ */
+ if ( pState->t->actions )
+ {
+ ++counts->total;
+ if ( DEBUG_MAKE && !( counts->total % 100 ) )
+ printf( "...on %dth target...\n", counts->total );
+
+ pState->t->cmds = (char *)make1cmds( pState->t );
+ /* Set the target's "progress" so that make1c() counts it among
+ * its successes/failures.
+ */
+ pState->t->progress = T_MAKE_RUNNING;
+ }
+ break;
+
+ /* All possible fates should have been accounted for by now. */
+ default:
+ printf( "ERROR: %s has bad fate %d", pState->t->name,
+ pState->t->fate );
+ abort();
+ }
+
+ /* Call make1c() to begin the execution of the chain of commands needed to
+ * build the target. If we are not going to build the target (due of
+ * dependency failures or no commands needing to be run) the chain will be
+ * empty and make1c() will directly signal the target's completion.
+ */
+
+#ifdef OPT_SEMAPHORE
+ /* If there is a semaphore, indicate that it is in use. */
+ if ( pState->t->semaphore )
+ {
+ ++pState->t->semaphore->asynccnt;
+ if ( DEBUG_EXECCMD )
+ printf( "SEM: %s now used by %s\n", pState->t->semaphore->name,
+ pState->t->name );
+ }
+#endif
+
+ pState->curstate = T_STATE_MAKE1C;
+}
+
+
+/*
+ * make1c() - launch target's next command, call parents' make1b() if none.
+ *
+ * If there are (more) commands to run to build this target (and we have not hit
+ * an error running earlier comands) we launch the command using exec_cmd(). If
+ * there are no more commands to run, we collect the status from all the actions
+ * and report our completion to all the parents.
+ */
+
+static void make1c( state * pState )
+{
+ CMD * cmd = (CMD *)pState->t->cmds;
+
+ if ( cmd && ( pState->t->status == EXEC_CMD_OK ) )
+ {
+ char * rule_name = 0;
+ char * target = 0;
+
+ if ( DEBUG_MAKEQ ||
+ ( !( cmd->rule->actions->flags & RULE_QUIETLY ) && DEBUG_MAKE ) )
+ {
+ rule_name = cmd->rule->name;
+ target = lol_get( &cmd->args, 0 )->string;
+ if ( globs.noexec )
+ out_action( rule_name, target, cmd->buf, "", "", EXIT_OK );
+ }
+
+ if ( globs.noexec )
+ {
+ pState->curstate = T_STATE_MAKE1D;
+ pState->status = EXEC_CMD_OK;
+ }
+ else
+ {
+ /* Pop state first because exec_cmd() could push state. */
+ pop_state( &state_stack );
+ exec_cmd( cmd->buf, make_closure, pState->t, cmd->shell, rule_name,
+ target );
+ }
+ }
+ else
+ {
+ TARGETS * c;
+ ACTIONS * actions;
+
+ /* Collect status from actions, and distribute it as well. */
+ for ( actions = pState->t->actions; actions; actions = actions->next )
+ if ( actions->action->status > pState->t->status )
+ pState->t->status = actions->action->status;
+ for ( actions = pState->t->actions; actions; actions = actions->next )
+ if ( pState->t->status > actions->action->status )
+ actions->action->status = pState->t->status;
+
+ /* Tally success/failure for those we tried to update. */
+ if ( pState->t->progress == T_MAKE_RUNNING )
+ switch ( pState->t->status )
+ {
+ case EXEC_CMD_OK : ++counts->made ; break;
+ case EXEC_CMD_FAIL: ++counts->failed; break;
+ }
+
+ /* Tell parents their dependency has been built. */
+ {
+ stack temp_stack = { NULL };
+ TARGET * t = pState->t;
+ TARGET * additional_includes = NULL;
+
+ t->progress = T_MAKE_DONE;
+
+ /* Target has been updated so rescan it for dependencies. */
+ if ( ( t->fate >= T_FATE_MISSING ) &&
+ ( t->status == EXEC_CMD_OK ) &&
+ !t->rescanned )
+ {
+ TARGET * target_to_rescan = t;
+ SETTINGS * s;
+
+ target_to_rescan->rescanned = 1;
+
+ if ( target_to_rescan->flags & T_FLAG_INTERNAL )
+ target_to_rescan = t->original_target;
+
+ /* Clean current includes. */
+ target_to_rescan->includes = 0;
+
+ s = copysettings( target_to_rescan->settings );
+ pushsettings( s );
+ headers( target_to_rescan );
+ popsettings( s );
+ freesettings( s );
+
+ if ( target_to_rescan->includes )
+ {
+ target_to_rescan->includes->rescanned = 1;
+ /* Tricky. The parents have already been processed, but they
+ * have not seen the internal node, because it was just
+ * created. We need to make the calls to make1a() that would
+ * have been made by the parents here, and also make sure
+ * all unprocessed parents will pick up the includes. We
+ * must make sure processing of the additional make1a()
+ * invocations is done before make1b() which means this
+ * target is built, otherwise the parent would be considered
+ * built before this make1a() processing has even started.
+ */
+ make0( target_to_rescan->includes, target_to_rescan->parents->target, 0, 0, 0 );
+ for ( c = target_to_rescan->parents; c; c = c->next )
+ c->target->depends = targetentry( c->target->depends,
+ target_to_rescan->includes );
+ /* Will be processed below. */
+ additional_includes = target_to_rescan->includes;
+ }
+ }
+
+ if ( additional_includes )
+ for ( c = t->parents; c; c = c->next )
+ push_state( &temp_stack, additional_includes, c->target, T_STATE_MAKE1A );
+
+ for ( c = t->parents; c; c = c->next )
+ push_state( &temp_stack, c->target, NULL, T_STATE_MAKE1B );
+
+#ifdef OPT_SEMAPHORE
+ /* If there is a semaphore, it is now free. */
+ if ( t->semaphore )
+ {
+ assert( t->semaphore->asynccnt == 1 );
+ --t->semaphore->asynccnt;
+
+ if ( DEBUG_EXECCMD )
+ printf( "SEM: %s is now free\n", t->semaphore->name );
+
+ /* If anything is waiting, notify the next target. There is no
+ * point in notifying waiting targets, since they will be
+ * notified again.
+ */
+ if ( t->semaphore->parents )
+ {
+ TARGETS * first = t->semaphore->parents;
+ if ( first->next )
+ first->next->tail = first->tail;
+ t->semaphore->parents = first->next;
+
+ if ( DEBUG_EXECCMD )
+ printf( "SEM: placing %s on stack\n", first->target->name );
+ push_state( &temp_stack, first->target, NULL, T_STATE_MAKE1B );
+ BJAM_FREE( first );
+ }
+ }
+#endif
+
+ /* Must pop state before pushing any more. */
+ pop_state( &state_stack );
+
+ /* Using stacks reverses the order of execution. Reverse it back. */
+ push_stack_on_stack( &state_stack, &temp_stack );
+ }
+ }
+}
+
+
+/*
+ * call_timing_rule() - Look up the __TIMING_RULE__ variable on the given
+ * target, and if non-empty, invoke the rule it names, passing the given
+ * timing_info.
+ */
+
+static void call_timing_rule( TARGET * target, timing_info * time )
+{
+ LIST * timing_rule;
+
+ pushsettings( target->settings );
+ timing_rule = var_get( "__TIMING_RULE__" );
+ popsettings( target->settings );
+
+ if ( timing_rule )
+ {
+ /* rule timing-rule ( args * : target : start end user system ) */
+
+ /* Prepare the argument list. */
+ FRAME frame[ 1 ];
+ frame_init( frame );
+
+ /* args * :: $(__TIMING_RULE__[2-]) */
+ lol_add( frame->args, list_copy( L0, timing_rule->next ) );
+
+ /* target :: the name of the target */
+ lol_add( frame->args, list_new( L0, target->name ) );
+
+ /* start end user system :: info about the action command */
+ lol_add( frame->args, list_new( list_new( list_new( list_new( L0,
+ outf_time ( time->start ) ),
+ outf_time ( time->end ) ),
+ outf_double( time->user ) ),
+ outf_double( time->system ) ) );
+
+ /* Call the rule. */
+ evaluate_rule( timing_rule->string, frame );
+
+ /* Clean up. */
+ frame_free( frame );
+ }
+}
+
+
+/*
+ * call_action_rule() - Look up the __ACTION_RULE__ variable on the given
+ * target, and if non-empty, invoke the rule it names, passing the given info,
+ * timing_info, executed command and command output.
+ */
+
+static void call_action_rule
+(
+ TARGET * target,
+ int status,
+ timing_info * time,
+ char * executed_command,
+ char * command_output
+)
+{
+ LIST * action_rule;
+
+ pushsettings( target->settings );
+ action_rule = var_get( "__ACTION_RULE__" );
+ popsettings( target->settings );
+
+ if ( action_rule )
+ {
+ /* rule action-rule (
+ args * :
+ target :
+ command status start end user system :
+ output ? ) */
+
+ /* Prepare the argument list. */
+ FRAME frame[ 1 ];
+ frame_init( frame );
+
+ /* args * :: $(__ACTION_RULE__[2-]) */
+ lol_add( frame->args, list_copy( L0, action_rule->next ) );
+
+ /* target :: the name of the target */
+ lol_add( frame->args, list_new( L0, target->name ) );
+
+ /* command status start end user system :: info about the action command */
+ lol_add( frame->args,
+ list_new( list_new( list_new( list_new( list_new( list_new( L0,
+ newstr( executed_command ) ),
+ outf_int( status ) ),
+ outf_time( time->start ) ),
+ outf_time( time->end ) ),
+ outf_double( time->user ) ),
+ outf_double( time->system ) ) );
+
+ /* output ? :: the output of the action command */
+ if ( command_output )
+ lol_add( frame->args, list_new( L0, newstr( command_output ) ) );
+ else
+ lol_add( frame->args, L0 );
+
+ /* Call the rule. */
+ evaluate_rule( action_rule->string, frame );
+
+ /* Clean up. */
+ frame_free( frame );
+ }
+}
+
+
+/*
+ * make_closure() - internal function passed as a notification callback for when
+ * commands finish getting executed by the OS.
+ */
+
+static void make_closure
+(
+ void * closure,
+ int status,
+ timing_info * time,
+ char * executed_command,
+ char * command_output
+)
+{
+ TARGET * built = (TARGET *)closure;
+
+ call_timing_rule( built, time );
+ if ( DEBUG_EXECCMD )
+ printf( "%f sec system; %f sec user\n", time->system, time->user );
+
+ call_action_rule( built, status, time, executed_command, command_output );
+
+ push_state( &state_stack, built, NULL, T_STATE_MAKE1D )->status = status;
+}
+
+
+/*
+ * make1d() - handle command execution completion and call back make1c().
+ *
+ * exec_cmd() has completed and now all we need to do is fiddle with the status
+ * and call back to make1c() so it can run the next command scheduled for
+ * building this target or close up the target's build process in case there are
+ * no more commands scheduled for it. On interrupts, we bail heavily.
+ */
+
+static void make1d( state * pState )
+{
+ TARGET * t = pState->t;
+ CMD * cmd = (CMD *)t->cmds;
+ int status = pState->status;
+
+ if ( t->flags & T_FLAG_FAIL_EXPECTED )
+ {
+ /* Invert execution result when FAIL_EXPECTED has been applied. */
+ switch ( status )
+ {
+ case EXEC_CMD_FAIL: status = EXEC_CMD_OK ; break;
+ case EXEC_CMD_OK: status = EXEC_CMD_FAIL; break;
+ }
+ }
+
+ if ( ( status == EXEC_CMD_FAIL ) &&
+ ( cmd->rule->actions->flags & RULE_IGNORE ) )
+ status = EXEC_CMD_OK;
+
+ /* On interrupt, set intr so _everything_ fails. */
+ if ( status == EXEC_CMD_INTR )
+ ++intr;
+
+ /* Print command text on failure. */
+ if ( ( status == EXEC_CMD_FAIL ) && DEBUG_MAKE )
+ {
+ if ( !DEBUG_EXEC )
+ printf( "%s\n", cmd->buf );
+
+ printf( "...failed %s ", cmd->rule->name );
+ list_print( lol_get( &cmd->args, 0 ) );
+ printf( "...\n" );
+ }
+
+ /* Treat failed commands as interrupts in case we were asked to stop the
+ * build in case of any errors.
+ */
+ if ( ( status == EXEC_CMD_FAIL ) && globs.quitquick )
+ ++intr;
+
+ /* If the command was interrupted or failed and the target is not
+ * "precious", remove the targets.
+ */
+ if (status != EXEC_CMD_OK)
+ {
+ LIST * targets = lol_get( &cmd->args, 0 );
+ for ( ; targets; targets = list_next( targets ) )
+ {
+ int need_unlink = 1;
+ TARGET* t = bindtarget ( targets->string );
+ if (t->flags & T_FLAG_PRECIOUS)
+ {
+ need_unlink = 0;
+ }
+ if (need_unlink && !unlink( targets->string ) )
+ printf( "...removing %s\n", targets->string );
+ }
+ }
+
+ /* Free this command and call make1c() to move onto the next one scheduled
+ * for building this same target.
+ */
+ t->status = status;
+ t->cmds = (char *)cmd_next( cmd );
+ cmd_free( cmd );
+ pState->curstate = T_STATE_MAKE1C;
+}
+
+
+/*
+ * swap_settings() - replace the settings from the current module and target
+ * with those from the new module and target
+ */
+
+static void swap_settings
+(
+ module_t * * current_module,
+ TARGET * * current_target,
+ module_t * new_module,
+ TARGET * new_target
+)
+{
+ if ( new_module == root_module() )
+ new_module = 0;
+
+ if ( ( new_target == *current_target ) && ( new_module == *current_module ) )
+ return;
+
+ if ( *current_target )
+ popsettings( (*current_target)->settings );
+
+ if ( new_module != *current_module )
+ {
+ if ( *current_module )
+ exit_module( *current_module );
+
+ *current_module = new_module;
+
+ if ( new_module )
+ enter_module( new_module );
+ }
+
+ *current_target = new_target;
+ if ( new_target )
+ pushsettings( new_target->settings );
+}
+
+
+/*
+ * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc.
+ *
+ * Essentially copies a chain of ACTIONs to a chain of CMDs, grouping
+ * RULE_TOGETHER actions, splitting RULE_PIECEMEAL actions, and handling
+ * RULE_NEWSRCS actions. The result is a chain of CMDs which can be expanded by
+ * var_string() and executed using exec_cmd().
+ */
+
+static CMD * make1cmds( TARGET * t )
+{
+ CMD * cmds = 0;
+ LIST * shell = 0;
+ module_t * settings_module = 0;
+ TARGET * settings_target = 0;
+ ACTIONS * a0;
+
+ /* Step through actions. Actions may be shared with other targets or grouped
+ * using RULE_TOGETHER, so actions already seen are skipped.
+ */
+ for ( a0 = t->actions ; a0; a0 = a0->next )
+ {
+ RULE * rule = a0->action->rule;
+ rule_actions * actions = rule->actions;
+ SETTINGS * boundvars;
+ LIST * nt;
+ LIST * ns;
+ ACTIONS * a1;
+ int start;
+ int chunk;
+ int length;
+
+ /* Only do rules with commands to execute. If this action has already
+ * been executed, use saved status.
+ */
+ if ( !actions || a0->action->running )
+ continue;
+
+ a0->action->running = 1;
+
+ /* Make LISTS of targets and sources. If `execute together` has been
+ * specified for this rule, tack on sources from each instance of this
+ * rule for this target.
+ */
+ nt = make1list( L0, a0->action->targets, 0 );
+ ns = make1list( L0, a0->action->sources, actions->flags );
+ if ( actions->flags & RULE_TOGETHER )
+ for ( a1 = a0->next; a1; a1 = a1->next )
+ if ( a1->action->rule == rule && !a1->action->running )
+ {
+ ns = make1list( ns, a1->action->sources, actions->flags );
+ a1->action->running = 1;
+ }
+
+ /* If doing only updated (or existing) sources, but none have been
+ * updated (or exist), skip this action.
+ */
+ if ( !ns && ( actions->flags & ( RULE_NEWSRCS | RULE_EXISTING ) ) )
+ {
+ list_free( nt );
+ continue;
+ }
+
+ swap_settings( &settings_module, &settings_target, rule->module, t );
+ if ( !shell )
+ shell = var_get( "JAMSHELL" ); /* shell is per-target */
+
+ /* If we had 'actions xxx bind vars' we bind the vars now. */
+ boundvars = make1settings( actions->bindlist );
+ pushsettings( boundvars );
+
+ /*
+ * Build command, starting with all source args.
+ *
+ * If cmd_new returns 0, it is because the resulting command length is
+ * > MAXLINE. In this case, we will slowly reduce the number of source
+ * arguments presented until it does fit. This only applies to actions
+ * that allow PIECEMEAL commands.
+ *
+ * While reducing slowly takes a bit of compute time to get things just
+ * right, it is worth it to get as close to MAXLINE as possible, because
+ * launching the commands we are executing is likely to be much more
+ * compute intensive.
+ *
+ * Note we loop through at least once, for sourceless actions.
+ */
+
+ start = 0;
+ chunk = length = list_length( ns );
+
+ do
+ {
+ /* Build cmd: cmd_new consumes its lists. */
+ CMD * cmd = cmd_new( rule,
+ list_copy( L0, nt ),
+ list_sublist( ns, start, chunk ),
+ list_copy( L0, shell ) );
+
+ if ( cmd )
+ {
+ /* It fit: chain it up. */
+ if ( !cmds ) cmds = cmd;
+ else cmds->tail->next = cmd;
+ cmds->tail = cmd;
+ start += chunk;
+ }
+ else if ( ( actions->flags & RULE_PIECEMEAL ) && ( chunk > 1 ) )
+ {
+ /* Reduce chunk size slowly. */
+ chunk = chunk * 9 / 10;
+ }
+ else
+ {
+ /* Too long and not splittable. */
+ printf( "%s actions too long (max %d):\n", rule->name, MAXLINE
+ );
+
+ /* Tell the user what didn't fit. */
+ cmd = cmd_new( rule, list_copy( L0, nt ),
+ list_sublist( ns, start, chunk ),
+ list_new( L0, newstr( "%" ) ) );
+ fputs( cmd->buf, stdout );
+ exit( EXITBAD );
+ }
+ }
+ while ( start < length );
+
+ /* These were always copied when used. */
+ list_free( nt );
+ list_free( ns );
+
+ /* Free the variables whose values were bound by 'actions xxx bind
+ * vars'.
+ */
+ popsettings( boundvars );
+ freesettings( boundvars );
+ }
+
+ swap_settings( &settings_module, &settings_target, 0, 0 );
+ return cmds;
+}
+
+
+/*
+ * make1list() - turn a list of targets into a LIST, for $(<) and $(>).
+ */
+
+static LIST * make1list( LIST * l, TARGETS * targets, int flags )
+{
+ for ( ; targets; targets = targets->next )
+ {
+ TARGET * t = targets->target;
+
+ if ( t->binding == T_BIND_UNBOUND )
+ make1bind( t );
+
+ if ( ( flags & RULE_EXISTING ) && ( flags & RULE_NEWSRCS ) )
+ {
+ if ( ( t->binding != T_BIND_EXISTS ) && ( t->fate <= T_FATE_STABLE ) )
+ continue;
+ }
+ else
+ {
+ if ( ( flags & RULE_EXISTING ) && ( t->binding != T_BIND_EXISTS ) )
+ continue;
+
+ if ( ( flags & RULE_NEWSRCS ) && ( t->fate <= T_FATE_STABLE ) )
+ continue;
+ }
+
+ /* Prohibit duplicates for RULE_TOGETHER. */
+ if ( flags & RULE_TOGETHER )
+ {
+ LIST * m;
+ for ( m = l; m; m = m->next )
+ if ( !strcmp( m->string, t->boundname ) )
+ break;
+ if ( m )
+ continue;
+ }
+
+ /* Build new list. */
+ l = list_new( l, copystr( t->boundname ) );
+ }
+
+ return l;
+}
+
+
+/*
+ * make1settings() - for vars that get bound values, build up replacement lists.
+ */
+
+static SETTINGS * make1settings( LIST * vars )
+{
+ SETTINGS * settings = 0;
+
+ for ( ; vars; vars = list_next( vars ) )
+ {
+ LIST * l = var_get( vars->string );
+ LIST * nl = 0;
+
+ for ( ; l; l = list_next( l ) )
+ {
+ TARGET * t = bindtarget( l->string );
+
+ /* Make sure the target is bound. */
+ if ( t->binding == T_BIND_UNBOUND )
+ make1bind( t );
+
+ /* Build a new list. */
+ nl = list_new( nl, copystr( t->boundname ) );
+ }
+
+ /* Add to settings chain. */
+ settings = addsettings( settings, VAR_SET, vars->string, nl );
+ }
+
+ return settings;
+}
+
+
+/*
+ * make1bind() - bind targets that were not bound during dependency analysis
+ *
+ * Spot the kludge! If a target is not in the dependency tree, it did not get
+ * bound by make0(), so we have to do it here. Ugly.
+ */
+
+static void make1bind( TARGET * t )
+{
+ if ( t->flags & T_FLAG_NOTFILE )
+ return;
+
+ pushsettings( t->settings );
+ t->boundname = search( t->name, &t->time, 0, ( t->flags & T_FLAG_ISFILE ) );
+ t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
+ popsettings( t->settings );
+}
diff --git a/tools/build/v2/engine/md5.c b/tools/build/v2/engine/md5.c
new file mode 100644
index 0000000000..c35d96c5ef
--- /dev/null
+++ b/tools/build/v2/engine/md5.c
@@ -0,0 +1,381 @@
+/*
+ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+ either statically or dynamically; added missing #include <string.h>
+ in library.
+ 2002-03-11 lpd Corrected argument list for main(), and added int return
+ type, in test program and T value program.
+ 2002-02-21 lpd Added missing #include <stdio.h> in test program.
+ 2000-07-03 lpd Patched to eliminate warnings about "constant is
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+#include "md5.h"
+#include <string.h>
+
+#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+# define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3 0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6 0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9 0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13 0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16 0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19 0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22 0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25 0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28 0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31 0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35 0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38 0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41 0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44 0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47 0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50 0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53 0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57 0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60 0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63 0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+#if BYTE_ORDER > 0
+ /* Define storage only for big-endian CPUs. */
+ md5_word_t X[16];
+#else
+ /* Define storage for little-endian or both types of CPUs. */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+#endif
+
+ {
+#if BYTE_ORDER == 0
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0 /* little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+#endif
+#if BYTE_ORDER == 0
+ else /* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0 /* big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
+
+# if BYTE_ORDER == 0
+ X = xbuf; /* (dynamic only) */
+# else
+# define xbuf X /* (static only) */
+# endif
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+#endif
+ }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
+#undef SET
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
+#undef SET
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+ static const md5_byte_t pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/tools/build/v2/engine/md5.h b/tools/build/v2/engine/md5.h
new file mode 100644
index 0000000000..698c995d8f
--- /dev/null
+++ b/tools/build/v2/engine/md5.h
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.h is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Removed support for non-ANSI compilers; removed
+ references to Ghostscript; clarified derivation from RFC 1321;
+ now handles byte order either statically or dynamically.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+ added conditionalization for C++ compilation from Martin
+ Purschke <purschke@bnl.gov>.
+ 1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
diff --git a/tools/build/v2/engine/mem.c b/tools/build/v2/engine/mem.c
new file mode 100644
index 0000000000..6a11fb38a5
--- /dev/null
+++ b/tools/build/v2/engine/mem.c
@@ -0,0 +1,75 @@
+/*
+Copyright Rene Rivera 2006.
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "jam.h"
+
+#ifdef OPT_BOEHM_GC
+
+ /* Compile the Boehm GC as one big chunk of code. It's much easier
+ this way, than trying to make radical changes to the bjam build
+ scripts. */
+
+ #define ATOMIC_UNCOLLECTABLE
+ #define NO_EXECUTE_PERMISSION
+ #define ALL_INTERIOR_POINTERS
+
+ #define LARGE_CONFIG
+ /*
+ #define NO_SIGNALS
+ #define SILENT
+ */
+ #ifndef GC_DEBUG
+ #define NO_DEBUGGING
+ #endif
+
+ #ifdef __GLIBC__
+ #define __USE_GNU
+ #endif
+
+ #include "boehm_gc/reclaim.c"
+ #include "boehm_gc/allchblk.c"
+ #include "boehm_gc/misc.c"
+ #include "boehm_gc/alloc.c"
+ #include "boehm_gc/mach_dep.c"
+ #include "boehm_gc/os_dep.c"
+ #include "boehm_gc/mark_rts.c"
+ #include "boehm_gc/headers.c"
+ #include "boehm_gc/mark.c"
+ #include "boehm_gc/obj_map.c"
+ #include "boehm_gc/pcr_interface.c"
+ #include "boehm_gc/blacklst.c"
+ #include "boehm_gc/new_hblk.c"
+ #include "boehm_gc/real_malloc.c"
+ #include "boehm_gc/dyn_load.c"
+ #include "boehm_gc/dbg_mlc.c"
+ #include "boehm_gc/malloc.c"
+ #include "boehm_gc/stubborn.c"
+ #include "boehm_gc/checksums.c"
+ #include "boehm_gc/pthread_support.c"
+ #include "boehm_gc/pthread_stop_world.c"
+ #include "boehm_gc/darwin_stop_world.c"
+ #include "boehm_gc/typd_mlc.c"
+ #include "boehm_gc/ptr_chck.c"
+ #include "boehm_gc/mallocx.c"
+ #include "boehm_gc/gcj_mlc.c"
+ #include "boehm_gc/specific.c"
+ #include "boehm_gc/gc_dlopen.c"
+ #include "boehm_gc/backgraph.c"
+ #include "boehm_gc/win32_threads.c"
+
+ /* Needs to be last. */
+ #include "boehm_gc/finalize.c"
+
+#elif defined(OPT_DUMA)
+
+ #ifdef OS_NT
+ #define WIN32
+ #endif
+ #include "duma/duma.c"
+ #include "duma/print.c"
+
+#endif
diff --git a/tools/build/v2/engine/mem.h b/tools/build/v2/engine/mem.h
new file mode 100644
index 0000000000..71b2fb4be2
--- /dev/null
+++ b/tools/build/v2/engine/mem.h
@@ -0,0 +1,134 @@
+/*
+Copyright Rene Rivera 2006.
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BJAM_MEM_H
+#define BJAM_MEM_H
+
+
+#ifdef OPT_BOEHM_GC
+
+ /* Use Boehm GC memory allocator. */
+ #include <gc.h>
+ #define bjam_malloc_x(s) memset(GC_malloc(s),0,s)
+ #define bjam_malloc_atomic_x(s) memset(GC_malloc_atomic(s),0,s)
+ #define bjam_calloc_x(n,s) memset(GC_malloc((n)*(s)),0,(n)*(s))
+ #define bjam_calloc_atomic_x(n,s) memset(GC_malloc_atomic((n)*(s)),0,(n)*(s))
+ #define bjam_realloc_x(p,s) GC_realloc(p,s)
+ #define bjam_free_x(p) GC_free(p)
+ #define bjam_mem_init_x() GC_init(); GC_enable_incremental()
+
+ #define bjam_malloc_raw_x(s) malloc(s)
+ #define bjam_calloc_raw_x(n,s) calloc(n,s)
+ #define bjam_realloc_raw_x(p,s) realloc(p,s)
+ #define bjam_free_raw_x(p) free(p)
+
+ #ifndef BJAM_NEWSTR_NO_ALLOCATE
+ #define BJAM_NEWSTR_NO_ALLOCATE
+ #endif
+
+#elif defined(OPT_DUMA)
+
+ /* Use Duma memory debugging library. */
+ #include <stdlib.h>
+ #define _DUMA_CONFIG_H_
+ #define DUMA_NO_GLOBAL_MALLOC_FREE
+ #define DUMA_EXPLICIT_INIT
+ #define DUMA_NO_THREAD_SAFETY
+ #define DUMA_NO_CPP_SUPPORT
+ /* #define DUMA_NO_LEAKDETECTION */
+ /* #define DUMA_USE_FRAMENO */
+ /* #define DUMA_PREFER_ATEXIT */
+ /* #define DUMA_OLD_DEL_MACRO */
+ /* #define DUMA_NO_HANG_MSG */
+ #define DUMA_PAGE_SIZE 4096
+ #define DUMA_MIN_ALIGNMENT 1
+ /* #define DUMA_GNU_INIT_ATTR 0 */
+ typedef unsigned int DUMA_ADDR;
+ typedef unsigned int DUMA_SIZE;
+ #include <duma.h>
+ #define bjam_malloc_x(s) malloc(s)
+ #define bjam_calloc_x(n,s) calloc(n,s)
+ #define bjam_realloc_x(p,s) realloc(p,s)
+ #define bjam_free_x(p) free(p)
+
+ #ifndef BJAM_NEWSTR_NO_ALLOCATE
+ #define BJAM_NEWSTR_NO_ALLOCATE
+ #endif
+
+#else
+
+ /* Standard C memory allocation. */
+ #define bjam_malloc_x(s) malloc(s)
+ #define bjam_calloc_x(n,s) calloc(n,s)
+ #define bjam_realloc_x(p,s) realloc(p,s)
+ #define bjam_free_x(p) free(p)
+
+#endif
+
+#ifndef bjam_malloc_atomic_x
+ #define bjam_malloc_atomic_x(s) bjam_malloc_x(s)
+#endif
+#ifndef bjam_calloc_atomic_x
+ #define bjam_calloc_atomic_x(n,s) bjam_calloc_x(n,s)
+#endif
+#ifndef bjam_mem_init_x
+ #define bjam_mem_init_x()
+#endif
+#ifndef bjam_mem_close_x
+ #define bjam_mem_close_x()
+#endif
+#ifndef bjam_malloc_raw_x
+ #define bjam_malloc_raw_x(s) bjam_malloc_x(s)
+#endif
+#ifndef bjam_calloc_raw_x
+ #define bjam_calloc_raw_x(n,s) bjam_calloc_x(n,s)
+#endif
+#ifndef bjam_realloc_raw_x
+ #define bjam_realloc_raw_x(p,s) bjam_realloc_x(p,s)
+#endif
+#ifndef bjam_free_raw_x
+ #define bjam_free_raw_x(p) bjam_free_x(p)
+#endif
+
+#ifdef OPT_DEBUG_PROFILE
+
+ /* Profile tracing of memory allocations. */
+ #define BJAM_MALLOC(s) (profile_memory(s), bjam_malloc_x(s))
+ #define BJAM_MALLOC_ATOMIC(s) (profile_memory(s), bjam_malloc_atomic_x(s))
+ #define BJAM_CALLOC(n,s) (profile_memory(n*s), bjam_calloc_x(n,s))
+ #define BJAM_CALLOC_ATOMIC(n,s) (profile_memory(n*s), bjam_calloc_atomic_x(n,s))
+ #define BJAM_REALLOC(p,s) (profile_memory(s), bjam_realloc_x(p,s))
+ #define BJAM_FREE(p) bjam_free_x(p)
+ #define BJAM_MEM_INIT() bjam_mem_init_x()
+ #define BJAM_MEM_CLOSE() bjam_mem_close_x()
+
+ #define BJAM_MALLOC_RAW(s) (profile_memory(s), bjam_malloc_raw_x(s))
+ #define BJAM_CALLOC_RAW(n,s) (profile_memory(n*s), bjam_calloc_raw_x(n,s))
+ #define BJAM_REALLOC_RAW(p,s) (profile_memory(s), bjam_realloc_raw_x(p,s))
+ #define BJAM_FREE_RAW(p) bjam_free_raw_x(p)
+
+#else
+
+ /* No mem tracing. */
+ #define BJAM_MALLOC(s) bjam_malloc_x(s)
+ #define BJAM_MALLOC_ATOMIC(s) bjam_malloc_atomic_x(s)
+ #define BJAM_CALLOC(n,s) bjam_calloc_x(n,s)
+ #define BJAM_CALLOC_ATOMIC(n,s) bjam_calloc_atomic_x(n,s)
+ #define BJAM_REALLOC(p,s) bjam_realloc_x(p,s)
+ #define BJAM_FREE(p) bjam_free_x(p)
+ #define BJAM_MEM_INIT() bjam_mem_init_x()
+ #define BJAM_MEM_CLOSE() bjam_mem_close_x()
+
+ #define BJAM_MALLOC_RAW(s) bjam_malloc_raw_x(s)
+ #define BJAM_CALLOC_RAW(n,s) bjam_calloc_raw_x(n,s)
+ #define BJAM_REALLOC_RAW(p,s) bjam_realloc_raw_x(p,s)
+ #define BJAM_FREE_RAW(p) bjam_free_raw_x(p)
+
+#endif
+
+
+#endif
diff --git a/tools/build/v2/engine/mkjambase.c b/tools/build/v2/engine/mkjambase.c
new file mode 100644
index 0000000000..cdf5998200
--- /dev/null
+++ b/tools/build/v2/engine/mkjambase.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * mkjambase.c - turn Jambase into a big C structure
+ *
+ * Usage: mkjambase jambase.c Jambase ...
+ *
+ * Results look like this:
+ *
+ * char *jambase[] = {
+ * "...\n",
+ * ...
+ * 0 };
+ *
+ * Handles \'s and "'s specially; knows to delete blank and comment lines.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+
+int main( int argc, char * * argv, char * * envp )
+{
+ char buf[ 1024 ];
+ FILE * fin;
+ FILE * fout;
+ char * p;
+ int doDotC = 0;
+
+ if ( argc < 3 )
+ {
+ fprintf( stderr, "usage: %s jambase.c Jambase ...\n", argv[ 0 ] );
+ return -1;
+ }
+
+ if ( !( fout = fopen( argv[1], "w" ) ) )
+ {
+ perror( argv[ 1 ] );
+ return -1;
+ }
+
+ /* If the file ends in .c generate a C source file. */
+ if ( ( p = strrchr( argv[1], '.' ) ) && !strcmp( p, ".c" ) )
+ doDotC++;
+
+ /* Now process the files. */
+
+ argc -= 2;
+ argv += 2;
+
+ if ( doDotC )
+ {
+ fprintf( fout, "/* Generated by mkjambase from Jambase */\n" );
+ fprintf( fout, "char *jambase[] = {\n" );
+ }
+
+ for ( ; argc--; ++argv )
+ {
+ if ( !( fin = fopen( *argv, "r" ) ) )
+ {
+ perror( *argv );
+ return -1;
+ }
+
+ if ( doDotC )
+ fprintf( fout, "/* %s */\n", *argv );
+ else
+ fprintf( fout, "### %s ###\n", *argv );
+
+ while ( fgets( buf, sizeof( buf ), fin ) )
+ {
+ if ( doDotC )
+ {
+ char * p = buf;
+
+ /* Strip leading whitespace. */
+ while ( ( *p == ' ' ) || ( *p == '\t' ) || ( *p == '\n' ) )
+ ++p;
+
+ /* Drop comments and empty lines. */
+ if ( ( *p == '#' ) || !*p )
+ continue;
+
+ /* Copy. */
+ putc( '"', fout );
+ for ( ; *p && ( *p != '\n' ); ++p )
+ switch ( *p )
+ {
+ case '\\': putc( '\\', fout ); putc( '\\', fout ); break;
+ case '"' : putc( '\\', fout ); putc( '"' , fout ); break;
+ case '\r': break;
+ default: putc( *p, fout ); break;
+ }
+
+ fprintf( fout, "\\n\",\n" );
+ }
+ else
+ {
+ fprintf( fout, "%s", buf );
+ }
+ }
+
+ fclose( fin );
+ }
+
+ if ( doDotC )
+ fprintf( fout, "0 };\n" );
+
+ fclose( fout );
+
+ return 0;
+}
diff --git a/tools/build/v2/engine/modules.c b/tools/build/v2/engine/modules.c
new file mode 100644
index 0000000000..7295259415
--- /dev/null
+++ b/tools/build/v2/engine/modules.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+#include "jam.h"
+
+#include "modules.h"
+#include "string.h"
+#include "hash.h"
+#include "newstr.h"
+#include "lists.h"
+#include "parse.h"
+#include "rules.h"
+#include "variable.h"
+#include "strings.h"
+#include <assert.h>
+
+static struct hash * module_hash = 0;
+
+
+static char * new_module_str( module_t * m, char * suffix )
+{
+ char * result;
+ string s;
+ string_copy( &s, m->name );
+ string_append( &s, suffix );
+ result = newstr( s.value );
+ string_free( &s );
+ return result;
+}
+
+
+module_t * bindmodule( char * name )
+{
+ PROFILE_ENTER( BINDMODULE );
+
+ string s;
+ module_t m_;
+ module_t * m = &m_;
+
+ if ( !module_hash )
+ module_hash = hashinit( sizeof( module_t ), "modules" );
+
+ string_new( &s );
+ if ( name )
+ {
+ string_append( &s, name );
+ string_push_back( &s, '.' );
+ }
+
+ m->name = s.value;
+
+ if ( hashenter( module_hash, (HASHDATA * *)&m ) )
+ {
+ m->name = newstr( m->name );
+ m->variables = 0;
+ m->rules = 0;
+ m->imported_modules = 0;
+ m->class_module = 0;
+ m->native_rules = 0;
+ m->user_module = 0;
+ }
+ string_free( &s );
+
+ PROFILE_EXIT( BINDMODULE );
+
+ return m;
+}
+
+/*
+ * demand_rules() - Get the module's "rules" hash on demand.
+ */
+struct hash * demand_rules( module_t * m )
+{
+ if ( !m->rules )
+ m->rules = hashinit( sizeof( RULE ), new_module_str( m, "rules" ) );
+ return m->rules;
+}
+
+
+/*
+ * delete_module() - wipe out the module's rules and variables.
+ */
+
+static void delete_rule_( void * xrule, void * data )
+{
+ rule_free( (RULE *)xrule );
+}
+
+
+void delete_module( module_t * m )
+{
+ /* Clear out all the rules. */
+ if ( m->rules )
+ {
+ hashenumerate( m->rules, delete_rule_, (void *)0 );
+ hashdone( m->rules );
+ m->rules = 0;
+ }
+
+ if ( m->variables )
+ {
+ var_hash_swap( &m->variables );
+ var_done();
+ var_hash_swap( &m->variables );
+ m->variables = 0;
+ }
+}
+
+
+module_t * root_module()
+{
+ static module_t * root = 0;
+ if ( !root )
+ root = bindmodule( 0 );
+ return root;
+}
+
+void enter_module( module_t * m )
+{
+ var_hash_swap( &m->variables );
+}
+
+
+void exit_module( module_t * m )
+{
+ var_hash_swap( &m->variables );
+}
+
+
+void import_module( LIST * module_names, module_t * target_module )
+{
+ PROFILE_ENTER( IMPORT_MODULE );
+
+ struct hash * h;
+
+ if ( !target_module->imported_modules )
+ target_module->imported_modules = hashinit( sizeof( char * ), "imported" );
+ h = target_module->imported_modules;
+
+ for ( ; module_names; module_names = module_names->next )
+ {
+ char * s = module_names->string;
+ char * * ss = &s;
+ hashenter( h, (HASHDATA * *)&ss );
+ }
+
+ PROFILE_EXIT( IMPORT_MODULE );
+}
+
+
+static void add_module_name( void * r_, void * result_ )
+{
+ char * * r = (char * *)r_;
+ LIST * * result = (LIST * *)result_;
+
+ *result = list_new( *result, copystr( *r ) );
+}
+
+
+LIST * imported_modules( module_t * module )
+{
+ LIST * result = L0;
+ if ( module->imported_modules )
+ hashenumerate( module->imported_modules, add_module_name, &result );
+ return result;
+}
diff --git a/tools/build/v2/engine/modules.h b/tools/build/v2/engine/modules.h
new file mode 100644
index 0000000000..60053a239f
--- /dev/null
+++ b/tools/build/v2/engine/modules.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef MODULES_DWA10182001_H
+# define MODULES_DWA10182001_H
+
+#include "lists.h"
+
+struct module_t
+{
+ char* name;
+ struct hash* rules;
+ struct hash* variables;
+ struct hash* imported_modules;
+ struct module_t* class_module;
+ struct hash* native_rules;
+ int user_module;
+};
+
+typedef struct module_t module_t ; /* MSVC debugger gets confused unless this is provided */
+
+module_t* bindmodule( char* name );
+module_t* root_module();
+void enter_module( module_t* );
+void exit_module( module_t* );
+void delete_module( module_t* );
+
+void import_module(LIST* module_names, module_t* target_module);
+LIST* imported_modules(module_t* module);
+
+struct hash* demand_rules( module_t* );
+
+
+#endif
+
diff --git a/tools/build/v2/engine/modules/order.c b/tools/build/v2/engine/modules/order.c
new file mode 100644
index 0000000000..d77943a79c
--- /dev/null
+++ b/tools/build/v2/engine/modules/order.c
@@ -0,0 +1,144 @@
+/* Copyright Vladimir Prus 2004. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#include "../native.h"
+#include "../lists.h"
+#include "../strings.h"
+#include "../newstr.h"
+#include "../variable.h"
+
+
+/* Use quite klugy approach: when we add order dependency from 'a' to 'b',
+ just append 'b' to of value of variable 'a'.
+*/
+LIST *add_pair( PARSE *parse, FRAME *frame )
+{
+ LIST* arg = lol_get( frame->args, 0 );
+
+ var_set(arg->string, list_copy(0, arg->next), VAR_APPEND);
+
+ return L0;
+}
+
+/** Given a list and a value, returns position of that value in
+ the list, or -1 if not found.
+*/
+int list_index(LIST* list, const char* value)
+{
+ int result = 0;
+ for(; list; list = list->next, ++result) {
+ if (strcmp(list->string, value) == 0)
+ return result;
+ }
+ return -1;
+}
+
+enum colors { white, gray, black };
+
+/* Main routite of topological sort. Calls itself recursively on all
+ adjacent vertices which were not yet visited. After that, 'current_vertex'
+ is added to '*result_ptr'.
+*/
+void do_ts(int** graph, int current_vertex, int* colors, int** result_ptr)
+{
+ int i;
+
+ colors[current_vertex] = gray;
+ for(i = 0; graph[current_vertex][i] != -1; ++i) {
+ int adjacent_vertex = graph[current_vertex][i];
+
+ if (colors[adjacent_vertex] == white)
+ do_ts(graph, adjacent_vertex, colors, result_ptr);
+ /* The vertex is either black, in which case we don't have to do
+ anything, a gray, in which case we have a loop. If we have a loop,
+ it's not clear what useful diagnostic we can emit, so we emit
+ nothing. */
+ }
+ colors[current_vertex] = black;
+ **result_ptr = current_vertex;
+ (*result_ptr)++;
+}
+
+void topological_sort(int** graph, int num_vertices, int* result)
+{
+ int i;
+ int* colors = (int*)BJAM_CALLOC(num_vertices, sizeof(int));
+ for (i = 0; i < num_vertices; ++i)
+ colors[i] = white;
+
+ for(i = 0; i < num_vertices; ++i)
+ if (colors[i] == white)
+ do_ts(graph, i, colors, &result);
+
+ BJAM_FREE(colors);
+}
+
+LIST *order( PARSE *parse, FRAME *frame )
+{
+ LIST* arg = lol_get( frame->args, 0 );
+ LIST* tmp;
+ LIST* result = 0;
+ int src;
+
+ /* We need to create a graph of order dependencies between
+ the passed objects. We assume that there are no duplicates
+ passed to 'add_pair'.
+ */
+ int length = list_length(arg);
+ int** graph = (int**)BJAM_CALLOC(length, sizeof(int*));
+ int* order = (int*)BJAM_MALLOC((length+1)*sizeof(int));
+
+ for(tmp = arg, src = 0; tmp; tmp = tmp->next, ++src) {
+ /* For all object this one depend upon, add elements
+ to 'graph' */
+ LIST* dependencies = var_get(tmp->string);
+ int index = 0;
+
+ graph[src] = (int*)BJAM_CALLOC(list_length(dependencies)+1, sizeof(int));
+ for(; dependencies; dependencies = dependencies->next) {
+ int dst = list_index(arg, dependencies->string);
+ if (dst != -1)
+ graph[src][index++] = dst;
+ }
+ graph[src][index] = -1;
+ }
+
+ topological_sort(graph, length, order);
+
+ {
+ int index = length-1;
+ for(; index >= 0; --index) {
+ int i;
+ tmp = arg;
+ for (i = 0; i < order[index]; ++i, tmp = tmp->next);
+ result = list_new(result, tmp->string);
+ }
+ }
+
+ /* Clean up */
+ {
+ int i;
+ for(i = 0; i < length; ++i)
+ BJAM_FREE(graph[i]);
+ BJAM_FREE(graph);
+ BJAM_FREE(order);
+ }
+
+ return result;
+}
+
+void init_order()
+{
+ {
+ char* args[] = { "first", "second", 0 };
+ declare_native_rule("class@order", "add-pair", args, add_pair, 1);
+ }
+
+ {
+ char* args[] = { "objects", "*", 0 };
+ declare_native_rule("class@order", "order", args, order, 1);
+ }
+
+
+}
diff --git a/tools/build/v2/engine/modules/path.c b/tools/build/v2/engine/modules/path.c
new file mode 100644
index 0000000000..f5d0962246
--- /dev/null
+++ b/tools/build/v2/engine/modules/path.c
@@ -0,0 +1,32 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#include "../native.h"
+#include "../timestamp.h"
+#include "../newstr.h"
+
+LIST *path_exists( PARSE *parse, FRAME *frame )
+{
+ LIST* l = lol_get( frame->args, 0 );
+
+ time_t time;
+ timestamp(l->string, &time);
+ if (time != 0)
+ {
+ return list_new(0, newstr("true"));
+ }
+ else
+ {
+ return L0;
+ }
+}
+
+void init_path()
+{
+ {
+ char* args[] = { "location", 0 };
+ declare_native_rule("path", "exists", args, path_exists, 1);
+ }
+
+}
diff --git a/tools/build/v2/engine/modules/property-set.c b/tools/build/v2/engine/modules/property-set.c
new file mode 100644
index 0000000000..2b0fb5d97b
--- /dev/null
+++ b/tools/build/v2/engine/modules/property-set.c
@@ -0,0 +1,110 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#include "../native.h"
+#include "../timestamp.h"
+#include "../newstr.h"
+#include "../strings.h"
+#include "../lists.h"
+#include "../variable.h"
+#include "../compile.h"
+
+LIST* get_grist(char* f)
+{
+ char* end = strchr(f, '>');
+ string s[1];
+ LIST* result;
+
+ string_new(s);
+
+ string_append_range(s, f, end+1);
+ result = list_new(0, newstr(s->value));
+
+ string_free(s);
+ return result;
+}
+
+/*
+rule create ( raw-properties * )
+{
+ raw-properties = [ sequence.unique
+ [ sequence.insertion-sort $(raw-properties) ] ] ;
+
+ local key = $(raw-properties:J=-:E=) ;
+
+ if ! $(.ps.$(key))
+ {
+ .ps.$(key) = [ new property-set $(raw-properties) ] ;
+ }
+ return $(.ps.$(key)) ;
+}
+*/
+
+LIST *property_set_create( PARSE *parse, FRAME *frame )
+{
+ LIST* properties = lol_get( frame->args, 0 );
+ LIST* sorted = 0;
+#if 0
+ LIST* order_sensitive = 0;
+#endif
+ LIST* unique;
+ LIST* tmp;
+ LIST* val;
+ string var[1];
+
+#if 0
+ /* Sort all properties which are not order sensitive */
+ for(tmp = properties; tmp; tmp = tmp->next) {
+ LIST* g = get_grist(tmp->string);
+ LIST* att = call_rule("feature.attributes", frame, g, 0);
+ if (list_in(att, "order-sensitive")) {
+ order_sensitive = list_new( order_sensitive, tmp->string);
+ } else {
+ sorted = list_new( sorted, tmp->string);
+ }
+ list_free(att);
+ }
+
+ sorted = list_sort(sorted);
+ sorted = list_append(sorted, order_sensitive);
+ unique = list_unique(sorted);
+#endif
+ sorted = list_sort(properties);
+ unique = list_unique(sorted);
+
+ string_new(var);
+ string_append(var, ".ps.");
+
+ for(tmp = unique; tmp; tmp = tmp->next) {
+ string_append(var, tmp->string);
+ string_push_back(var, '-');
+ }
+ val = var_get(var->value);
+ if (val == 0)
+ {
+ val = call_rule("new", frame,
+ list_append(list_new(0, "property-set"), unique), 0);
+
+ var_set(newstr(var->value), list_copy(0, val), VAR_SET);
+ }
+ else
+ {
+ val = list_copy(0, val);
+ }
+
+ string_free(var);
+ /* The 'unique' variable is freed in 'call_rule'. */
+ list_free(sorted);
+
+ return val;
+
+}
+
+void init_property_set()
+{
+ {
+ char* args[] = { "raw-properties", "*", 0 };
+ declare_native_rule("property-set", "create", args, property_set_create, 1);
+ }
+}
diff --git a/tools/build/v2/engine/modules/readme.txt b/tools/build/v2/engine/modules/readme.txt
new file mode 100644
index 0000000000..2edf6e17f8
--- /dev/null
+++ b/tools/build/v2/engine/modules/readme.txt
@@ -0,0 +1,3 @@
+
+This directory constains sources which declare native
+rules for Boost.Build modules. \ No newline at end of file
diff --git a/tools/build/v2/engine/modules/regex.c b/tools/build/v2/engine/modules/regex.c
new file mode 100644
index 0000000000..d048ba1de4
--- /dev/null
+++ b/tools/build/v2/engine/modules/regex.c
@@ -0,0 +1,96 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#include "../native.h"
+#include "../timestamp.h"
+#include "../newstr.h"
+#include "../strings.h"
+#include "../regexp.h"
+#include "../compile.h"
+
+/*
+rule transform ( list * : pattern : indices * )
+{
+ indices ?= 1 ;
+ local result ;
+ for local e in $(list)
+ {
+ local m = [ MATCH $(pattern) : $(e) ] ;
+ if $(m)
+ {
+ result += $(m[$(indices)]) ;
+ }
+ }
+ return $(result) ;
+}
+*/
+LIST *regex_transform( PARSE *parse, FRAME *frame )
+{
+ LIST* l = lol_get( frame->args, 0 );
+ LIST* pattern = lol_get( frame->args, 1 );
+ LIST* indices_list = lol_get(frame->args, 2);
+ int* indices = 0;
+ int size;
+ int* p;
+ LIST* result = 0;
+
+ string buf[1];
+ string_new(buf);
+
+ if (indices_list)
+ {
+ size = list_length(indices_list);
+ indices = (int*)BJAM_MALLOC(size*sizeof(int));
+ for(p = indices; indices_list; indices_list = indices_list->next)
+ {
+ *p++ = atoi(indices_list->string);
+ }
+ }
+ else
+ {
+ size = 1;
+ indices = (int*)BJAM_MALLOC(sizeof(int));
+ *indices = 1;
+ }
+
+ {
+ /* Result is cached and intentionally never freed */
+ regexp *re = regex_compile( pattern->string );
+
+ for(; l; l = l->next)
+ {
+ if( regexec( re, l->string ) )
+ {
+ int i = 0;
+ for(; i < size; ++i)
+ {
+ int index = indices[i];
+ /* Skip empty submatches. Not sure it's right in all cases,
+ but surely is right for the case for which this routine
+ is optimized -- header scanning.
+ */
+ if (re->startp[index] != re->endp[index])
+ {
+ string_append_range( buf, re->startp[index], re->endp[index] );
+ result = list_new( result, newstr( buf->value ) );
+ string_truncate( buf, 0 );
+ }
+ }
+ }
+ }
+ string_free( buf );
+ }
+
+ BJAM_FREE(indices);
+
+ return result;
+}
+
+void init_regex()
+{
+ {
+ char* args[] = { "list", "*", ":", "pattern", ":", "indices", "*", 0 };
+ declare_native_rule("regex", "transform", args, regex_transform, 2);
+ }
+}
diff --git a/tools/build/v2/engine/modules/sequence.c b/tools/build/v2/engine/modules/sequence.c
new file mode 100644
index 0000000000..bda80d94c4
--- /dev/null
+++ b/tools/build/v2/engine/modules/sequence.c
@@ -0,0 +1,42 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#include "../native.h"
+
+# ifndef max
+# define max( a,b ) ((a)>(b)?(a):(b))
+# endif
+
+
+LIST *sequence_select_highest_ranked( PARSE *parse, FRAME *frame )
+{
+ /* Returns all of 'elements' for which corresponding element in parallel */
+ /* list 'rank' is equal to the maximum value in 'rank'. */
+
+ LIST* elements = lol_get( frame->args, 0 );
+ LIST* rank = lol_get( frame->args, 1 );
+
+ LIST* result = 0;
+ LIST* tmp;
+ int highest_rank = -1;
+
+ for (tmp = rank; tmp; tmp = tmp->next)
+ highest_rank = max(highest_rank, atoi(tmp->string));
+
+ for (; rank; rank = rank->next, elements = elements->next)
+ if (atoi(rank->string) == highest_rank)
+ result = list_new(result, elements->string);
+
+ return result;
+}
+
+void init_sequence()
+{
+ {
+ char* args[] = { "elements", "*", ":", "rank", "*", 0 };
+ declare_native_rule("sequence", "select-highest-ranked", args,
+ sequence_select_highest_ranked, 1);
+ }
+
+}
diff --git a/tools/build/v2/engine/modules/set.c b/tools/build/v2/engine/modules/set.c
new file mode 100644
index 0000000000..f8219403c5
--- /dev/null
+++ b/tools/build/v2/engine/modules/set.c
@@ -0,0 +1,41 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#include "../native.h"
+
+/*
+ local result = ;
+ local element ;
+ for element in $(B)
+ {
+ if ! ( $(element) in $(A) )
+ {
+ result += $(element) ;
+ }
+ }
+ return $(result) ;
+*/
+LIST *set_difference( PARSE *parse, FRAME *frame )
+{
+
+ LIST* b = lol_get( frame->args, 0 );
+ LIST* a = lol_get( frame->args, 1 );
+
+ LIST* result = 0;
+ for(; b; b = b->next)
+ {
+ if (!list_in(a, b->string))
+ result = list_new(result, b->string);
+ }
+ return result;
+}
+
+void init_set()
+{
+ {
+ char* args[] = { "B", "*", ":", "A", "*", 0 };
+ declare_native_rule("set", "difference", args, set_difference, 1);
+ }
+
+}
diff --git a/tools/build/v2/engine/native.c b/tools/build/v2/engine/native.c
new file mode 100644
index 0000000000..4c2899595e
--- /dev/null
+++ b/tools/build/v2/engine/native.c
@@ -0,0 +1,36 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#include "native.h"
+#include "hash.h"
+
+# define P0 (PARSE *)0
+# define C0 (char *)0
+
+
+void declare_native_rule(char* module, char* rule, char** args,
+ LIST*(*f)(PARSE*, FRAME*), int version)
+{
+ module_t* m = bindmodule(module);
+ if (m->native_rules == 0) {
+ m->native_rules = hashinit( sizeof( native_rule_t ), "native rules");
+ }
+
+ {
+ native_rule_t n, *np = &n;
+ n.name = rule;
+ if (args)
+ {
+ n.arguments = args_new();
+ lol_build( n.arguments->data, args );
+ }
+ else
+ {
+ n.arguments = 0;
+ }
+ n.procedure = parse_make( f, P0, P0, P0, C0, C0, 0 );
+ n.version = version;
+ hashenter(m->native_rules, (HASHDATA**)&np);
+ }
+}
diff --git a/tools/build/v2/engine/native.h b/tools/build/v2/engine/native.h
new file mode 100644
index 0000000000..3fc710b9c6
--- /dev/null
+++ b/tools/build/v2/engine/native.h
@@ -0,0 +1,34 @@
+/* Copyright David Abrahams 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#ifndef NATIVE_H_VP_2003_12_09
+#define NATIVE_H_VP_2003_12_09
+
+#include "rules.h"
+
+struct native_rule_t
+{
+ char* name;
+ argument_list* arguments;
+ PARSE* procedure;
+ /* Version of the interface that the native rule provides.
+ It's possible that we want to change the set parameter
+ for existing native rule. In that case, version number
+ should be incremented so that Boost.Build can check for
+ version it relies on.
+
+ Versions are numbered from 1.
+ */
+ int version;
+};
+
+/* MSVC debugger gets confused unless this is provided */
+typedef struct native_rule_t native_rule_t ;
+
+void declare_native_rule(char* module, char* rule, char** args,
+ LIST*(*f)(PARSE*, FRAME*), int version);
+
+
+
+#endif
diff --git a/tools/build/v2/engine/newstr.c b/tools/build/v2/engine/newstr.c
new file mode 100644
index 0000000000..6a229eb216
--- /dev/null
+++ b/tools/build/v2/engine/newstr.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "newstr.h"
+# include "hash.h"
+# include "compile.h"
+# include <stddef.h>
+# include <stdlib.h>
+
+/*
+ * newstr.c - string manipulation routines
+ *
+ * To minimize string copying, string creation, copying, and freeing
+ * is done through newstr.
+ *
+ * External functions:
+ *
+ * newstr() - return a dynamically allocated copy of a string
+ * copystr() - return a copy of a string previously returned by newstr()
+ * freestr() - free a string returned by newstr() or copystr()
+ * str_done() - free string tables
+ *
+ * Once a string is passed to newstr(), the returned string is readonly.
+ *
+ * This implementation builds a hash table of all strings, so that multiple
+ * calls of newstr() on the same string allocate memory for the string once.
+ * Strings are never actually freed.
+ */
+
+typedef char * STRING;
+
+static struct hash * strhash = 0;
+static int strtotal = 0;
+static int strcount_in = 0;
+static int strcount_out = 0;
+
+
+/*
+ * Immortal string allocator implementation speeds string allocation and cuts
+ * down on internal fragmentation.
+ */
+
+# define STRING_BLOCK 4096
+typedef struct strblock
+{
+ struct strblock * next;
+ char data[STRING_BLOCK];
+} strblock;
+
+static strblock * strblock_chain = 0;
+
+/* Storage remaining in the current strblock */
+static char * storage_start = 0;
+static char * storage_finish = 0;
+
+
+/*
+ * allocate() - Allocate n bytes of immortal string storage.
+ */
+
+static char * allocate( size_t const n )
+{
+#ifdef BJAM_NEWSTR_NO_ALLOCATE
+ return (char*)BJAM_MALLOC_ATOMIC(n);
+#else
+ /* See if we can grab storage from an existing block. */
+ size_t remaining = storage_finish - storage_start;
+ if ( remaining >= n )
+ {
+ char * result = storage_start;
+ storage_start += n;
+ return result;
+ }
+ else /* Must allocate a new block. */
+ {
+ strblock * new_block;
+ size_t nalloc = n;
+ if ( nalloc < STRING_BLOCK )
+ nalloc = STRING_BLOCK;
+
+ /* Allocate a new block and link into the chain. */
+ new_block = (strblock *)BJAM_MALLOC( offsetof( strblock, data[0] ) + nalloc * sizeof( new_block->data[0] ) );
+ if ( new_block == 0 )
+ return 0;
+ new_block->next = strblock_chain;
+ strblock_chain = new_block;
+
+ /* Take future allocations out of the larger remaining space. */
+ if ( remaining < nalloc - n )
+ {
+ storage_start = new_block->data + n;
+ storage_finish = new_block->data + nalloc;
+ }
+ return new_block->data;
+ }
+#endif
+}
+
+
+/*
+ * newstr() - return a dynamically allocated copy of a string.
+ */
+
+char * newstr( char * string )
+{
+ STRING str;
+ STRING * s = &str;
+
+ if ( !strhash )
+ strhash = hashinit( sizeof( STRING ), "strings" );
+
+ *s = string;
+
+ if ( hashenter( strhash, (HASHDATA **)&s ) )
+ {
+ int l = strlen( string );
+ char * m = (char *)allocate( l + 1 );
+
+ strtotal += l + 1;
+ memcpy( m, string, l + 1 );
+ *s = m;
+ }
+
+ strcount_in += 1;
+ return *s;
+}
+
+
+/*
+ * copystr() - return a copy of a string previously returned by newstr()
+ */
+
+char * copystr( char * s )
+{
+ strcount_in += 1;
+ return s;
+}
+
+
+/*
+ * freestr() - free a string returned by newstr() or copystr()
+ */
+
+void freestr( char * s )
+{
+ strcount_out += 1;
+}
+
+
+/*
+ * str_done() - free string tables.
+ */
+
+void str_done()
+{
+ /* Reclaim string blocks. */
+ while ( strblock_chain != 0 )
+ {
+ strblock * n = strblock_chain->next;
+ BJAM_FREE(strblock_chain);
+ strblock_chain = n;
+ }
+
+ hashdone( strhash );
+
+ if ( DEBUG_MEM )
+ printf( "%dK in strings\n", strtotal / 1024 );
+
+ /* printf( "--- %d strings of %d dangling\n", strcount_in-strcount_out, strcount_in ); */
+}
diff --git a/tools/build/v2/engine/newstr.h b/tools/build/v2/engine/newstr.h
new file mode 100644
index 0000000000..84a4d7b6da
--- /dev/null
+++ b/tools/build/v2/engine/newstr.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * newstr.h - string manipulation routines
+ */
+
+char * copystr ( char * );
+void freestr ( char * );
+char * newstr ( char * );
+void str_done();
diff --git a/tools/build/v2/engine/option.c b/tools/build/v2/engine/option.c
new file mode 100644
index 0000000000..d25e5e8ad1
--- /dev/null
+++ b/tools/build/v2/engine/option.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "option.h"
+
+/*
+ * option.c - command line option processing
+ *
+ * {o >o
+ * \<>) "Process command line options as defined in <option.h>.
+ * Return the number of argv[] elements used up by options,
+ * or -1 if an invalid option flag was given or an argument
+ * was supplied for an option that does not require one."
+ */
+
+int getoptions( int argc, char * * argv, char * opts, bjam_option * optv )
+{
+ int i;
+ int optc = N_OPTS;
+
+ memset( (char *)optv, '\0', sizeof( *optv ) * N_OPTS );
+
+ for ( i = 0; i < argc; ++i )
+ {
+ char *arg;
+
+ if ( ( argv[ i ][ 0 ] != '-' ) ||
+ ( ( argv[ i ][ 1 ] != '-' ) && !isalpha( argv[ i ][ 1 ] ) ) )
+ continue;
+
+ if ( !optc-- )
+ {
+ printf( "too many options (%d max)\n", N_OPTS );
+ return -1;
+ }
+
+ for ( arg = &argv[ i ][ 1 ]; *arg; ++arg )
+ {
+ char * f;
+
+ for ( f = opts; *f; ++f )
+ if ( *f == *arg )
+ break;
+
+ if ( !*f )
+ {
+ printf( "Invalid option: -%c\n", *arg );
+ return -1;
+ }
+
+ optv->flag = *f;
+
+ if ( f[ 1 ] != ':' )
+ {
+ optv++->val = "true";
+ }
+ else if ( arg[ 1 ] )
+ {
+ optv++->val = &arg[1];
+ break;
+ }
+ else if ( ++i < argc )
+ {
+ optv++->val = argv[ i ];
+ break;
+ }
+ else
+ {
+ printf( "option: -%c needs argument\n", *f );
+ return -1;
+ }
+ }
+ }
+
+ return i;
+}
+
+
+/*
+ * Name: getoptval() - find an option given its character.
+ */
+
+char * getoptval( bjam_option * optv, char opt, int subopt )
+{
+ int i;
+ for ( i = 0; i < N_OPTS; ++i, ++optv )
+ if ( ( optv->flag == opt ) && !subopt-- )
+ return optv->val;
+ return 0;
+}
diff --git a/tools/build/v2/engine/option.h b/tools/build/v2/engine/option.h
new file mode 100644
index 0000000000..99ef620da5
--- /dev/null
+++ b/tools/build/v2/engine/option.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * option.h - command line option processing
+ *
+ * {o >o
+ * \ -) "Command line option."
+ */
+
+typedef struct bjam_option
+{
+ char flag; /* filled in by getoption() */
+ char *val; /* set to random address if true */
+} bjam_option;
+
+# define N_OPTS 256
+
+int getoptions( int argc, char **argv, char *opts, bjam_option *optv );
+char * getoptval( bjam_option *optv, char opt, int subopt );
diff --git a/tools/build/v2/engine/output.c b/tools/build/v2/engine/output.c
new file mode 100644
index 0000000000..483c6ca9e6
--- /dev/null
+++ b/tools/build/v2/engine/output.c
@@ -0,0 +1,125 @@
+/*
+ Copyright 2007 Rene Rivera
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "jam.h"
+#include "output.h"
+#include "newstr.h"
+#include <stdio.h>
+
+#define bjam_out (stdout)
+#define bjam_err (stderr)
+
+static void out_
+(
+ char const * data,
+ FILE * io
+)
+{
+ while ( *data )
+ {
+ size_t len = strcspn(data,"\r");
+ data += fwrite(data,1,len,io);
+ if ( *data == '\r' ) ++data;
+ }
+}
+
+
+void out_action
+(
+ char const * action,
+ char const * target,
+ char const * command,
+ char const * out_data,
+ char const * err_data,
+ int exit_reason
+)
+{
+ /* Print out the action+target line, if the action is quite the action
+ * should be null.
+ */
+ if ( action )
+ {
+ fprintf( bjam_out, "%s %s\n", action, target );
+ }
+
+ /* Print out the command executed if given -d+2. */
+ if ( DEBUG_EXEC )
+ {
+ fputs( command, bjam_out );
+ fputc( '\n', bjam_out );
+ }
+
+ /* Print out the command executed to the command stream. */
+ if ( globs.cmdout )
+ {
+ fputs( command, globs.cmdout );
+ }
+
+ switch ( exit_reason )
+ {
+ case EXIT_OK:
+ break;
+ case EXIT_FAIL:
+ break;
+ case EXIT_TIMEOUT:
+ {
+ /* Process expired, make user aware with explicit message. */
+ if ( action )
+ {
+ /* But only output for non-quietly actions. */
+ fprintf( bjam_out, "%ld second time limit exceeded\n", globs.timeout );
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ /* Print out the command output, if requested, or if the program failed. */
+ if ( action || exit_reason != EXIT_OK)
+ {
+ /* But only output for non-quietly actions. */
+ if ( ( 0 != out_data ) &&
+ ( ( globs.pipe_action & 1 /* STDOUT_FILENO */ ) ||
+ ( globs.pipe_action == 0 ) ) )
+ {
+ out_( out_data, bjam_out );
+ }
+ if ( ( 0 != err_data ) &&
+ ( globs.pipe_action & 2 /* STDERR_FILENO */ ) )
+ {
+ out_( err_data, bjam_err );
+ }
+ }
+
+ fflush( bjam_out );
+ fflush( bjam_err );
+ fflush( globs.cmdout );
+}
+
+
+char * outf_int( int value )
+{
+ char buffer[50];
+ sprintf( buffer, "%i", value );
+ return newstr( buffer );
+}
+
+
+char * outf_double( double value )
+{
+ char buffer[50];
+ sprintf( buffer, "%f", value );
+ return newstr( buffer );
+}
+
+
+char * outf_time( time_t value )
+{
+ char buffer[50];
+ strftime( buffer, 49, "%Y-%m-%d %H:%M:%SZ", gmtime( &value ) );
+ return newstr( buffer );
+}
diff --git a/tools/build/v2/engine/output.h b/tools/build/v2/engine/output.h
new file mode 100644
index 0000000000..9e9876cfc5
--- /dev/null
+++ b/tools/build/v2/engine/output.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2007 Rene Rivera
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BJAM_OUTPUT_H
+#define BJAM_OUTPUT_H
+
+#include <time.h>
+
+#define EXIT_OK 0
+#define EXIT_FAIL 1
+#define EXIT_TIMEOUT 2
+
+void out_action(
+ const char * action,
+ const char * target,
+ const char * command,
+ const char * out_data,
+ const char * err_data,
+ int exit_reason
+ );
+
+char * outf_int( int value );
+char * outf_double( double value );
+char * outf_time( time_t value );
+
+#endif
diff --git a/tools/build/v2/engine/parse.c b/tools/build/v2/engine/parse.c
new file mode 100644
index 0000000000..9114fa057a
--- /dev/null
+++ b/tools/build/v2/engine/parse.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include "jam.h"
+#include "lists.h"
+#include "parse.h"
+#include "scan.h"
+#include "newstr.h"
+#include "modules.h"
+#include "frames.h"
+
+/*
+ * parse.c - make and destroy parse trees as driven by the parser
+ *
+ * 09/07/00 (seiwald) - ref count on PARSE to avoid freeing when used,
+ * as per Matt Armstrong.
+ * 09/11/00 (seiwald) - structure reworked to reflect that (*func)()
+ * returns a LIST *.
+ */
+
+static PARSE * yypsave;
+
+void parse_file( char * f, FRAME * frame )
+{
+ /* Suspend scan of current file and push this new file in the stream. */
+ yyfparse( f );
+
+ /* Now parse each block of rules and execute it. Execute it outside of the
+ * parser so that recursive calls to yyrun() work (no recursive yyparse's).
+ */
+
+ for ( ; ; )
+ {
+ PARSE * p;
+
+ /* Filled by yyparse() calling parse_save(). */
+ yypsave = 0;
+
+ /* If parse error or empty parse, outta here. */
+ if ( yyparse() || !( p = yypsave ) )
+ break;
+
+ /* Run the parse tree. */
+ parse_evaluate( p, frame );
+ parse_free( p );
+ }
+}
+
+
+void parse_save( PARSE * p )
+{
+ yypsave = p;
+}
+
+
+PARSE * parse_make(
+ LIST * (* func)( PARSE *, FRAME * ),
+ PARSE * left,
+ PARSE * right,
+ PARSE * third,
+ char * string,
+ char * string1,
+ int num )
+{
+ PARSE * p = (PARSE *)BJAM_MALLOC( sizeof( PARSE ) );
+
+ p->func = func;
+ p->left = left;
+ p->right = right;
+ p->third = third;
+ p->string = string;
+ p->string1 = string1;
+ p->num = num;
+ p->refs = 1;
+ p->rulename = 0;
+
+ if ( left )
+ {
+ p->file = left->file;
+ p->line = left->line;
+ }
+ else
+ {
+ yyinput_stream( &p->file, &p->line );
+ }
+
+ return p;
+}
+
+
+void parse_refer( PARSE * p )
+{
+ ++p->refs;
+}
+
+
+void parse_free( PARSE * p )
+{
+ if ( --p->refs )
+ return;
+
+ if ( p->string )
+ freestr( p->string );
+ if ( p->string1 )
+ freestr( p->string1 );
+ if ( p->left )
+ parse_free( p->left );
+ if ( p->right )
+ parse_free( p->right );
+ if ( p->third )
+ parse_free( p->third );
+ if ( p->rulename )
+ freestr( p->rulename );
+
+ BJAM_FREE( (char *)p );
+}
+
+
+LIST * parse_evaluate( PARSE * p, FRAME * frame )
+{
+ frame->procedure = p;
+ return (*p->func)( p, frame );
+}
diff --git a/tools/build/v2/engine/parse.h b/tools/build/v2/engine/parse.h
new file mode 100644
index 0000000000..e324972f7b
--- /dev/null
+++ b/tools/build/v2/engine/parse.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PARSE_DWA20011020_H
+#define PARSE_DWA20011020_H
+
+#include "frames.h"
+#include "modules.h"
+#include "lists.h"
+
+/*
+ * parse.h - make and destroy parse trees as driven by the parser.
+ */
+
+/*
+ * Parse tree node.
+ */
+
+struct _PARSE {
+ LIST * (* func)( PARSE *, FRAME * );
+ PARSE * left;
+ PARSE * right;
+ PARSE * third;
+ char * string;
+ char * string1;
+ int num;
+ int refs;
+/* module * module; */
+ char * rulename;
+ char * file;
+ int line;
+};
+
+void parse_file( char *, FRAME * );
+void parse_save( PARSE * );
+
+PARSE * parse_make(
+ LIST * (* func)( PARSE *, FRAME * ),
+ PARSE * left,
+ PARSE * right,
+ PARSE * third,
+ char * string,
+ char * string1,
+ int num );
+
+void parse_refer ( PARSE * );
+void parse_free ( PARSE * );
+LIST * parse_evaluate( PARSE *, FRAME * );
+
+#endif
diff --git a/tools/build/v2/engine/patchlevel.h b/tools/build/v2/engine/patchlevel.h
new file mode 100644
index 0000000000..699efd84ba
--- /dev/null
+++ b/tools/build/v2/engine/patchlevel.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* Keep JAMVERSYM in sync with VERSION. */
+/* It can be accessed as $(JAMVERSION) in the Jamfile. */
+
+#define VERSION_MAJOR 2011
+#define VERSION_MINOR 04
+#define VERSION_PATCH 0
+#define VERSION_MAJOR_SYM "2011"
+#define VERSION_MINOR_SYM "04"
+#define VERSION_PATCH_SYM "00"
+#define VERSION "2011.4"
+#define JAMVERSYM "JAMVERSION=2011.4"
diff --git a/tools/build/v2/engine/pathmac.c b/tools/build/v2/engine/pathmac.c
new file mode 100644
index 0000000000..e2c250e338
--- /dev/null
+++ b/tools/build/v2/engine/pathmac.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "pathsys.h"
+
+# ifdef OS_MAC
+
+# define DELIM ':'
+
+/*
+ * pathunix.c - manipulate file names on UNIX, NT, OS2
+ *
+ * External routines:
+ *
+ * path_parse() - split a file name into dir/base/suffix/member
+ * path_build() - build a filename given dir/base/suffix/member
+ * path_parent() - make a PATHNAME point to its parent dir
+ *
+ * File_parse() and path_build() just manipuate a string and a structure;
+ * they do not make system calls.
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 12/26/93 (seiwald) - handle dir/.suffix properly in path_build()
+ * 12/19/94 (mikem) - solaris string table insanity support
+ * 12/21/94 (wingerd) Use backslashes for pathnames - the NT way.
+ * 02/14/95 (seiwald) - parse and build /xxx properly
+ * 02/23/95 (wingerd) Compilers on NT can handle "/" in pathnames, so we
+ * should expect hdr searches to come up with strings
+ * like "thing/thing.h". So we need to test for "/" as
+ * well as "\" when parsing pathnames.
+ * 03/16/95 (seiwald) - fixed accursed typo on line 69.
+ * 05/03/96 (seiwald) - split from filent.c, fileunix.c
+ * 12/20/96 (seiwald) - when looking for the rightmost . in a file name,
+ * don't include the archive member name.
+ * 01/10/01 (seiwald) - path_parse now strips the trailing : from the
+ * directory name, unless the directory name is all
+ * :'s, so that $(d:P) works.
+ */
+
+/*
+ * path_parse() - split a file name into dir/base/suffix/member
+ */
+
+void
+path_parse(
+ char *file,
+ PATHNAME *f )
+{
+ char *p, *q;
+ char *end;
+
+ memset( (char *)f, 0, sizeof( *f ) );
+
+ /* Look for <grist> */
+
+ if ( file[0] == '<' && ( p = strchr( file, '>' ) ) )
+ {
+ f->f_grist.ptr = file;
+ f->f_grist.len = p - file;
+ file = p + 1;
+ }
+
+ /* Look for dir: */
+
+ if ( p = strrchr( file, DELIM ) )
+ {
+ f->f_dir.ptr = file;
+ f->f_dir.len = p - file;
+ file = p + 1;
+
+ /* All :'s? Include last : as part of directory name */
+
+ while ( ( p > f->f_dir.ptr ) && ( *--p == DELIM ) );
+
+ if ( p == f->f_dir.ptr )
+ ++f->f_dir.len;
+ }
+
+ end = file + strlen( file );
+
+ /* Look for (member). */
+
+ if ( ( p = strchr( file, '(' ) ) && ( end[-1] == ')' ) )
+ {
+ f->f_member.ptr = p + 1;
+ f->f_member.len = end - p - 2;
+ end = p;
+ }
+
+ /* Look for .suffix */
+ /* This would be memrchr() */
+
+ p = 0;
+ q = file;
+
+ while ( q = memchr( q, '.', end - q ) )
+ p = q++;
+
+ if ( p )
+ {
+ f->f_suffix.ptr = p;
+ f->f_suffix.len = end - p;
+ end = p;
+ }
+
+ /* Leaves base */
+
+ f->f_base.ptr = file;
+ f->f_base.len = end - file;
+}
+
+/*
+ * path_build() - build a filename given dir/base/suffix/member.
+ */
+
+# define DIR_EMPTY 0 /* "" */
+# define DIR_DOT 1 /* : */
+# define DIR_DOTDOT 2 /* :: */
+# define DIR_ABS 3 /* dira:dirb: */
+# define DIR_REL 4 /* :dira:dirb: */
+
+# define G_DIR 0 /* take dir */
+# define G_ROOT 1 /* take root */
+# define G_CAT 2 /* prepend root to dir */
+# define G_DTDR 3 /* :: of rel dir */
+# define G_DDDD 4 /* make it ::: (../..) */
+# define G_MT 5 /* leave it empty */
+
+char grid[5][5] = {
+/* EMPTY DOT DOTDOT ABS REL */
+/* EMPTY */ { G_MT, G_DIR, G_DIR, G_DIR, G_DIR },
+/* DOT */ { G_ROOT, G_DIR, G_DIR, G_DIR, G_DIR },
+/* DOTDOT */ { G_ROOT, G_ROOT, G_DDDD, G_DIR, G_DTDR },
+/* ABS */ { G_ROOT, G_ROOT, G_ROOT, G_DIR, G_CAT },
+/* REL */ { G_ROOT, G_ROOT, G_ROOT, G_DIR, G_CAT }
+};
+
+static int file_flags( char * ptr, int len )
+{
+ if ( !len )
+ return DIR_EMPTY;
+ if ( ( len == 1 ) && ( ptr[0] == DELIM ) )
+ return DIR_DOT;
+ if ( ( len == 2 ) && ( ptr[0] == DELIM ) && ( ptr[1] == DELIM ) )
+ return DIR_DOTDOT;
+ if ( ptr[0] == DELIM )
+ return DIR_REL;
+ return DIR_ABS;
+}
+
+
+void path_build( PATHNAME * f, string * file, int binding )
+{
+ int dflag;
+ int rflag;
+ int act;
+
+ file_build1( f, file );
+
+ /* Combine root & directory, according to the grid. */
+
+ dflag = file_flags( f->f_dir.ptr, f->f_dir.len );
+ rflag = file_flags( f->f_root.ptr, f->f_root.len );
+
+ switch ( act = grid[ rflag ][ dflag ] )
+ {
+ case G_DTDR:
+ {
+ /* :: of rel dir */
+ string_push_back( file, DELIM );
+ }
+ /* fall through */
+
+ case G_DIR:
+ /* take dir */
+ string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
+ break;
+
+ case G_ROOT:
+ /* take root */
+ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
+ break;
+
+ case G_CAT:
+ /* prepend root to dir */
+ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
+ if ( file->value[ file->size - 1 ] == DELIM )
+ string_pop_back( file );
+ string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
+ break;
+
+ case G_DDDD:
+ /* make it ::: (../..) */
+ string_append( file, ":::" );
+ break;
+ }
+
+ /* Put : between dir and file (if none already). */
+
+ if ( ( act != G_MT ) &&
+ ( file->value[ file->size - 1 ] != DELIM ) &&
+ ( f->f_base.len || f->f_suffix.len ) )
+ {
+ string_push_back( file, DELIM );
+ }
+
+ if ( f->f_base.len )
+ string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
+
+ if ( f->f_suffix.len )
+ string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
+
+ if ( f->f_member.len )
+ {
+ string_push_back( file, '(' );
+ string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
+ string_push_back( file, ')' );
+ }
+
+ if ( DEBUG_SEARCH )
+ printf( " -> '%s'\n", file->value );
+}
+
+
+/*
+ * path_parent() - make a PATHNAME point to its parent dir
+ */
+
+void path_parent( PATHNAME * f )
+{
+ /* Just set everything else to nothing. */
+
+ f->f_base.ptr =
+ f->f_suffix.ptr =
+ f->f_member.ptr = "";
+
+ f->f_base.len =
+ f->f_suffix.len =
+ f->f_member.len = 0;
+}
+
+# endif /* OS_MAC */
diff --git a/tools/build/v2/engine/pathsys.h b/tools/build/v2/engine/pathsys.h
new file mode 100644
index 0000000000..737758105f
--- /dev/null
+++ b/tools/build/v2/engine/pathsys.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * pathsys.h - PATHNAME struct
+ */
+
+/*
+ * PATHNAME - a name of a file, broken into <grist>dir/base/suffix(member)
+ *
+ * <grist> is salt to distinguish between targets that otherwise would
+ * have the same name: it never appears in the bound name of a target.
+ * (member) is an archive member name: the syntax is arbitrary, but must
+ * agree in path_parse(), path_build() and the Jambase.
+ *
+ * On VMS, we keep track of whether the original path was a directory
+ * (without a file), so that $(VAR:D) can climb to the parent.
+ */
+
+#ifndef PATHSYS_VP_20020211_H
+# define PATHSYS_VP_20020211_H
+
+#include "strings.h"
+
+typedef struct _pathname PATHNAME;
+typedef struct _pathpart PATHPART;
+
+struct _pathpart
+{
+ char * ptr;
+ int len;
+};
+
+struct _pathname
+{
+ PATHPART part[6];
+#ifdef OS_VMS
+ int parent;
+#endif
+
+#define f_grist part[0]
+#define f_root part[1]
+#define f_dir part[2]
+#define f_base part[3]
+#define f_suffix part[4]
+#define f_member part[5]
+};
+
+void path_build( PATHNAME * f, string * file, int binding );
+void path_build1( PATHNAME * f, string * file );
+
+void path_parse( char * file, PATHNAME * f );
+void path_parent( PATHNAME * f );
+
+#ifdef NT
+
+/** Returns newstr-allocated string with long equivivalent of 'short_name'.
+ If none exists -- i.e. 'short_path' is already long path, it's returned
+ unaltered. */
+char * short_path_to_long_path( char * short_path );
+
+#endif
+
+#ifdef USE_PATHUNIX
+/** Returns a static pointer to the system dependent path to the temporary
+ directory. NOTE: *without* a trailing path separator.
+*/
+const char * path_tmpdir( void );
+
+/** Returns a new temporary name.
+*/
+const char * path_tmpnam( void );
+
+/** Returns a new temporary path.
+*/
+const char * path_tmpfile( void );
+#endif
+
+/** Give the first argument to 'main', return a full path to
+ our executable. Returns null in the unlikely case it
+ cannot be determined. Caller is responsible for freeing
+ the string.
+
+ Implemented in jam.c
+*/
+char * executable_path (char *argv0);
+
+#endif
diff --git a/tools/build/v2/engine/pathunix.c b/tools/build/v2/engine/pathunix.c
new file mode 100644
index 0000000000..2daad14b72
--- /dev/null
+++ b/tools/build/v2/engine/pathunix.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Copyright 2005 Rene Rivera.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "pathsys.h"
+# include "strings.h"
+# include "newstr.h"
+# include "filesys.h"
+# include <time.h>
+# include <stdlib.h>
+# ifndef OS_NT
+# include <unistd.h>
+# endif
+
+# ifdef USE_PATHUNIX
+
+/*
+ * pathunix.c - manipulate file names on UNIX, NT, OS2, AmigaOS
+ *
+ * External routines:
+ *
+ * path_parse() - split a file name into dir/base/suffix/member
+ * path_build() - build a filename given dir/base/suffix/member
+ * path_parent() - make a PATHNAME point to its parent dir
+ *
+ * File_parse() and path_build() just manipuate a string and a structure;
+ * they do not make system calls.
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 12/26/93 (seiwald) - handle dir/.suffix properly in path_build()
+ * 12/19/94 (mikem) - solaris string table insanity support
+ * 12/21/94 (wingerd) Use backslashes for pathnames - the NT way.
+ * 02/14/95 (seiwald) - parse and build /xxx properly
+ * 02/23/95 (wingerd) Compilers on NT can handle "/" in pathnames, so we
+ * should expect hdr searches to come up with strings
+ * like "thing/thing.h". So we need to test for "/" as
+ * well as "\" when parsing pathnames.
+ * 03/16/95 (seiwald) - fixed accursed typo on line 69.
+ * 05/03/96 (seiwald) - split from filent.c, fileunix.c
+ * 12/20/96 (seiwald) - when looking for the rightmost . in a file name,
+ * don't include the archive member name.
+ * 01/13/01 (seiwald) - turn on \ handling on UNIX, on by accident
+ */
+
+/*
+ * path_parse() - split a file name into dir/base/suffix/member
+ */
+
+void path_parse( char * file, PATHNAME * f )
+{
+ char * p;
+ char * q;
+ char * end;
+
+ memset( (char *)f, 0, sizeof( *f ) );
+
+ /* Look for <grist> */
+
+ if ( ( file[0] == '<' ) && ( p = strchr( file, '>' ) ) )
+ {
+ f->f_grist.ptr = file;
+ f->f_grist.len = p - file;
+ file = p + 1;
+ }
+
+ /* Look for dir/ */
+
+ p = strrchr( file, '/' );
+
+# if PATH_DELIM == '\\'
+ /* On NT, look for dir\ as well */
+ {
+ char *p1 = strrchr( file, '\\' );
+ p = p1 > p ? p1 : p;
+ }
+# endif
+
+ if ( p )
+ {
+ f->f_dir.ptr = file;
+ f->f_dir.len = p - file;
+
+ /* Special case for / - dirname is /, not "" */
+
+ if ( !f->f_dir.len )
+ f->f_dir.len = 1;
+
+# if PATH_DELIM == '\\'
+ /* Special case for D:/ - dirname is D:/, not "D:" */
+
+ if ( f->f_dir.len == 2 && file[1] == ':' )
+ f->f_dir.len = 3;
+# endif
+
+ file = p + 1;
+ }
+
+ end = file + strlen( file );
+
+ /* Look for (member) */
+
+ if ( ( p = strchr( file, '(' ) ) && ( end[ -1 ] == ')' ) )
+ {
+ f->f_member.ptr = p + 1;
+ f->f_member.len = end - p - 2;
+ end = p;
+ }
+
+ /* Look for .suffix */
+ /* This would be memrchr() */
+
+ p = 0;
+ q = file;
+
+ while ( ( q = (char *)memchr( q, '.', end - q ) ) )
+ p = q++;
+
+ if ( p )
+ {
+ f->f_suffix.ptr = p;
+ f->f_suffix.len = end - p;
+ end = p;
+ }
+
+ /* Leaves base */
+
+ f->f_base.ptr = file;
+ f->f_base.len = end - file;
+}
+
+/*
+ * path_delims - the string of legal path delimiters
+ */
+static char path_delims[] = {
+ PATH_DELIM,
+# if PATH_DELIM == '\\'
+ '/',
+# endif
+ 0
+};
+
+/*
+ * is_path_delim() - true iff c is a path delimiter
+ */
+static int is_path_delim( char c )
+{
+ char* p = strchr( path_delims, c );
+ return p && *p;
+}
+
+/*
+ * as_path_delim() - convert c to a path delimiter if it isn't one
+ * already
+ */
+static char as_path_delim( char c )
+{
+ return is_path_delim( c ) ? c : PATH_DELIM;
+}
+
+/*
+ * path_build() - build a filename given dir/base/suffix/member
+ *
+ * To avoid changing slash direction on NT when reconstituting paths,
+ * instead of unconditionally appending PATH_DELIM we check the
+ * past-the-end character of the previous path element. If it is in
+ * path_delims, we append that, and only append PATH_DELIM as a last
+ * resort. This heuristic is based on the fact that PATHNAME objects
+ * are usually the result of calling path_parse, which leaves the
+ * original slashes in the past-the-end position. Correctness depends
+ * on the assumption that all strings are zero terminated, so a
+ * past-the-end character will always be available.
+ *
+ * As an attendant patch, we had to ensure that backslashes are used
+ * explicitly in timestamp.c
+ */
+
+void
+path_build(
+ PATHNAME *f,
+ string *file,
+ int binding )
+{
+ file_build1( f, file );
+
+ /* Don't prepend root if it's . or directory is rooted */
+# if PATH_DELIM == '/'
+
+ if ( f->f_root.len
+ && !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' )
+ && !( f->f_dir.len && f->f_dir.ptr[0] == '/' ) )
+
+# else /* unix */
+
+ if ( f->f_root.len
+ && !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' )
+ && !( f->f_dir.len && f->f_dir.ptr[0] == '/' )
+ && !( f->f_dir.len && f->f_dir.ptr[0] == '\\' )
+ && !( f->f_dir.len && f->f_dir.ptr[1] == ':' ) )
+
+# endif /* unix */
+
+ {
+ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
+ /* If 'root' already ends with path delimeter,
+ don't add yet another one. */
+ if ( ! is_path_delim( f->f_root.ptr[f->f_root.len-1] ) )
+ string_push_back( file, as_path_delim( f->f_root.ptr[f->f_root.len] ) );
+ }
+
+ if ( f->f_dir.len )
+ string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
+
+ /* UNIX: Put / between dir and file */
+ /* NT: Put \ between dir and file */
+
+ if ( f->f_dir.len && ( f->f_base.len || f->f_suffix.len ) )
+ {
+ /* UNIX: Special case for dir \ : don't add another \ */
+ /* NT: Special case for dir / : don't add another / */
+
+# if PATH_DELIM == '\\'
+ if ( !( f->f_dir.len == 3 && f->f_dir.ptr[1] == ':' ) )
+# endif
+ if ( !( f->f_dir.len == 1 && is_path_delim( f->f_dir.ptr[0] ) ) )
+ string_push_back( file, as_path_delim( f->f_dir.ptr[f->f_dir.len] ) );
+ }
+
+ if ( f->f_base.len )
+ {
+ string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
+ }
+
+ if ( f->f_suffix.len )
+ {
+ string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
+ }
+
+ if ( f->f_member.len )
+ {
+ string_push_back( file, '(' );
+ string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
+ string_push_back( file, ')' );
+ }
+}
+
+/*
+ * path_parent() - make a PATHNAME point to its parent dir
+ */
+
+void
+path_parent( PATHNAME *f )
+{
+ /* just set everything else to nothing */
+
+ f->f_base.ptr =
+ f->f_suffix.ptr =
+ f->f_member.ptr = "";
+
+ f->f_base.len =
+ f->f_suffix.len =
+ f->f_member.len = 0;
+}
+
+#ifdef NT
+#include <windows.h>
+#include <tchar.h>
+
+/* The definition of this in winnt.h is not ANSI-C compatible. */
+#undef INVALID_FILE_ATTRIBUTES
+#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+
+
+DWORD ShortPathToLongPath(LPCTSTR lpszShortPath,LPTSTR lpszLongPath,DWORD
+ cchBuffer)
+{
+ LONG i=0;
+ TCHAR path[_MAX_PATH]={0};
+ TCHAR ret[_MAX_PATH]={0};
+ LONG pos=0, prev_pos=0;
+ LONG len=_tcslen(lpszShortPath);
+
+ /* Is the string valid? */
+ if (!lpszShortPath) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ /* Is the path valid? */
+ if (GetFileAttributes(lpszShortPath)==INVALID_FILE_ATTRIBUTES)
+ return 0;
+
+ /* Convert "/" to "\" */
+ for (i=0;i<len;++i) {
+ if (lpszShortPath[i]==_T('/'))
+ path[i]=_T('\\');
+ else
+ path[i]=lpszShortPath[i];
+ }
+
+ /* UNC path? */
+ if (path[0]==_T('\\') && path[1]==_T('\\')) {
+ pos=2;
+ for (i=0;i<2;++i) {
+ while (path[pos]!=_T('\\') && path[pos]!=_T('\0'))
+ ++pos;
+ ++pos;
+ }
+ _tcsncpy(ret,path,pos-1);
+ } /* Drive letter? */
+ else if (path[1]==_T(':')) {
+ if (path[2]==_T('\\'))
+ pos=3;
+ if (len==3) {
+ if (cchBuffer>3)
+ _tcscpy(lpszLongPath,lpszShortPath);
+ return len;
+ }
+ _tcsncpy(ret,path,2);
+ }
+
+ /* Expand the path for each subpath, and strip trailing backslashes */
+ for (prev_pos = pos-1;pos<=len;++pos) {
+ if (path[pos]==_T('\\') || (path[pos]==_T('\0') &&
+ path[pos-1]!=_T('\\'))) {
+ WIN32_FIND_DATA fd;
+ HANDLE hf=0;
+ TCHAR c=path[pos];
+ char* new_element;
+ path[pos]=_T('\0');
+
+ /* the path[prev_pos+1]... path[pos] range is the part of
+ path we're handling right now. We need to find long
+ name for that element and add it. */
+ new_element = path + prev_pos + 1;
+
+ /* First add separator, but only if there's something in result already. */
+ if (ret[0] != _T('\0'))
+ {
+ _tcscat(ret,_T("\\"));
+ }
+
+ /* If it's ".." element, we need to append it, not
+ the name in parent that FindFirstFile will return.
+ Same goes for "." */
+
+ if (new_element[0] == _T('.') && new_element[1] == _T('\0') ||
+ new_element[0] == _T('.') && new_element[1] == _T('.')
+ && new_element[2] == _T('\0'))
+ {
+ _tcscat(ret, new_element);
+ }
+ else
+ {
+ hf=FindFirstFile(path, &fd);
+ if (hf==INVALID_HANDLE_VALUE)
+ return 0;
+
+ _tcscat(ret,fd.cFileName);
+ FindClose(hf);
+ }
+
+ path[pos]=c;
+
+ prev_pos = pos;
+ }
+ }
+
+ len=_tcslen(ret)+1;
+ if (cchBuffer>=len)
+ _tcscpy(lpszLongPath,ret);
+
+ return len;
+}
+
+char* short_path_to_long_path(char* short_path)
+{
+ char buffer2[_MAX_PATH];
+ int ret = ShortPathToLongPath(short_path, buffer2, _MAX_PATH);
+
+ if (ret)
+ return newstr(buffer2);
+ else
+ return newstr(short_path);
+}
+
+#endif
+
+static string path_tmpdir_buffer[1];
+static const char * path_tmpdir_result = 0;
+
+const char * path_tmpdir()
+{
+ if (!path_tmpdir_result)
+ {
+ # ifdef OS_NT
+ DWORD pathLength = 0;
+ pathLength = GetTempPath(pathLength,NULL);
+ string_new(path_tmpdir_buffer);
+ string_reserve(path_tmpdir_buffer,pathLength);
+ pathLength = GetTempPathA(pathLength,path_tmpdir_buffer[0].value);
+ path_tmpdir_buffer[0].value[pathLength-1] = '\0';
+ path_tmpdir_buffer[0].size = pathLength-1;
+ # else
+ const char * t = getenv("TMPDIR");
+ if (!t)
+ {
+ t = "/tmp";
+ }
+ string_new(path_tmpdir_buffer);
+ string_append(path_tmpdir_buffer,t);
+ # endif
+ path_tmpdir_result = path_tmpdir_buffer[0].value;
+ }
+ return path_tmpdir_result;
+}
+
+const char * path_tmpnam(void)
+{
+ char name_buffer[64];
+ # ifdef OS_NT
+ unsigned long c0 = GetCurrentProcessId();
+ # else
+ unsigned long c0 = getpid();
+ # endif
+ static unsigned long c1 = 0;
+ if (0 == c1) c1 = time(0)&0xffff;
+ c1 += 1;
+ sprintf(name_buffer,"jam%lx%lx.000",c0,c1);
+ return newstr(name_buffer);
+}
+
+const char * path_tmpfile(void)
+{
+ const char * result = 0;
+
+ string file_path;
+ string_copy(&file_path,path_tmpdir());
+ string_push_back(&file_path,PATH_DELIM);
+ string_append(&file_path,path_tmpnam());
+ result = newstr(file_path.value);
+ string_free(&file_path);
+
+ return result;
+}
+
+
+# endif /* unix, NT, OS/2, AmigaOS */
diff --git a/tools/build/v2/engine/pathvms.c b/tools/build/v2/engine/pathvms.c
new file mode 100644
index 0000000000..975fe5a579
--- /dev/null
+++ b/tools/build/v2/engine/pathvms.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "pathsys.h"
+
+# ifdef OS_VMS
+
+# define DEBUG
+
+/*
+ * pathvms.c - manipulate file names on VMS
+ *
+ * External routines:
+ *
+ * path_parse() - split a file name into dir/base/suffix/member
+ * path_build() - build a filename given dir/base/suffix/member
+ * path_parent() - make a PATHNAME point to its parent dir
+ *
+ * File_parse() and path_build() just manipuate a string and a structure;
+ * they do not make system calls.
+ *
+ * WARNING! This file contains voodoo logic, as black magic is
+ * necessary for wrangling with VMS file name. Woe be to people
+ * who mess with this code.
+ *
+ * 02/09/95 (seiwald) - bungled R=[xxx] - was using directory length!
+ * 05/03/96 (seiwald) - split from filevms.c
+ */
+
+/*
+ * path_parse() - split a file name into dir/base/suffix/member.
+ */
+
+void path_parse( char * file, PATHNAME * f )
+{
+ char * p;
+ char * q;
+ char * end;
+
+ memset( (char *)f, 0, sizeof( *f ) );
+
+ /* Look for <grist> */
+
+ if ( ( file[0] == '<' ) && ( p = strchr( file, '>' ) ) )
+ {
+ f->f_grist.ptr = file;
+ f->f_grist.len = p - file;
+ file = p + 1;
+ }
+
+ /* Look for dev:[dir] or dev: */
+
+ if ( ( p = strchr( file, ']' ) ) || ( p = strchr( file, ':' ) ) )
+ {
+ f->f_dir.ptr = file;
+ f->f_dir.len = p + 1 - file;
+ file = p + 1;
+ }
+
+ end = file + strlen( file );
+
+ /* Look for (member). */
+
+ if ( ( p = strchr( file, '(' ) ) && ( end[ -1 ] == ')' ) )
+ {
+ f->f_member.ptr = p + 1;
+ f->f_member.len = end - p - 2;
+ end = p;
+ }
+
+ /* Look for .suffix */
+ /* This would be memrchr(). */
+
+ p = 0;
+ q = file;
+
+ while ( q = (char *)memchr( q, '.', end - q ) )
+ p = q++;
+
+ if ( p )
+ {
+ f->f_suffix.ptr = p;
+ f->f_suffix.len = end - p;
+ end = p;
+ }
+
+ /* Leaves base. */
+ f->f_base.ptr = file;
+ f->f_base.len = end - file;
+
+ /* Is this a directory without a file spec? */
+ f->parent = 0;
+}
+
+/*
+ * dir mods result
+ * --- --- ------
+ * Rerooting:
+ *
+ * (none) :R=dev: dev:
+ * devd: :R=dev: devd:
+ * devd:[dir] :R=dev: devd:[dir]
+ * [.dir] :R=dev: dev:[dir] questionable
+ * [dir] :R=dev: dev:[dir]
+ *
+ * (none) :R=[rdir] [rdir] questionable
+ * devd: :R=[rdir] devd:
+ * devd:[dir] :R=[rdir] devd:[dir]
+ * [.dir] :R=[rdir] [rdir.dir] questionable
+ * [dir] :R=[rdir] [rdir]
+ *
+ * (none) :R=dev:[root] dev:[root]
+ * devd: :R=dev:[root] devd:
+ * devd:[dir] :R=dev:[root] devd:[dir]
+ * [.dir] :R=dev:[root] dev:[root.dir]
+ * [dir] :R=dev:[root] [dir]
+ *
+ * Climbing to parent:
+ *
+ */
+
+# define DIR_EMPTY 0 /* empty string */
+# define DIR_DEV 1 /* dev: */
+# define DIR_DEVDIR 2 /* dev:[dir] */
+# define DIR_DOTDIR 3 /* [.dir] */
+# define DIR_DASHDIR 4 /* [-] or [-.dir] */
+# define DIR_ABSDIR 5 /* [dir] */
+# define DIR_ROOT 6 /* [000000] or dev:[000000] */
+
+# define G_DIR 0 /* take just dir */
+# define G_ROOT 1 /* take just root */
+# define G_VAD 2 /* root's dev: + [abs] */
+# define G_DRD 3 /* root's dev:[dir] + [.rel] */
+# define G_VRD 4 /* root's dev: + [.rel] made [abs] */
+# define G_DDD 5 /* root's dev:[dir] + . + [dir] */
+
+static int grid[7][7] = {
+
+/* root/dir EMPTY DEV DEVDIR DOTDIR DASH, ABSDIR ROOT */
+/* EMPTY */ G_DIR, G_DIR, G_DIR, G_DIR, G_DIR, G_DIR, G_DIR,
+/* DEV */ G_ROOT, G_DIR, G_DIR, G_VRD, G_VAD, G_VAD, G_VAD,
+/* DEVDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_VAD, G_VAD, G_VAD,
+/* DOTDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DIR, G_DIR, G_DIR,
+/* DASHDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DDD, G_DIR, G_DIR,
+/* ABSDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DIR, G_DIR, G_DIR,
+/* ROOT */ G_ROOT, G_DIR, G_DIR, G_VRD, G_DIR, G_DIR, G_DIR,
+
+};
+
+struct dirinf
+{
+ int flags;
+
+ struct
+ {
+ char * ptr;
+ int len;
+ } dev, dir;
+};
+
+static char * strnchr( char * buf, int c, int len )
+{
+ while ( len-- )
+ if ( *buf && ( *buf++ == c ) )
+ return buf - 1;
+ return 0;
+}
+
+
+static void dir_flags( char * buf, int len, struct dirinf * i )
+{
+ char * p;
+
+ if ( !buf || !len )
+ {
+ i->flags = DIR_EMPTY;
+ i->dev.ptr =
+ i->dir.ptr = 0;
+ i->dev.len =
+ i->dir.len = 0;
+ }
+ else if ( p = strnchr( buf, ':', len ) )
+ {
+ i->dev.ptr = buf;
+ i->dev.len = p + 1 - buf;
+ i->dir.ptr = buf + i->dev.len;
+ i->dir.len = len - i->dev.len;
+ i->flags = i->dir.len && *i->dir.ptr == '[' ? DIR_DEVDIR : DIR_DEV;
+ }
+ else
+ {
+ i->dev.ptr = buf;
+ i->dev.len = 0;
+ i->dir.ptr = buf;
+ i->dir.len = len;
+
+ if ( ( *buf == '[' ) && ( buf[1] == ']' ) )
+ i->flags = DIR_EMPTY;
+ else if ( ( *buf == '[' ) && ( buf[1] == '.' ) )
+ i->flags = DIR_DOTDIR;
+ else if ( ( *buf == '[' ) && ( buf[1] == '-' ) )
+ i->flags = DIR_DASHDIR;
+ else
+ i->flags = DIR_ABSDIR;
+ }
+
+ /* But if its rooted in any way. */
+
+ if ( ( i->dir.len == 8 ) && !strncmp( i->dir.ptr, "[000000]", 8 ) )
+ i->flags = DIR_ROOT;
+}
+
+
+/*
+ * path_build() - build a filename given dir/base/suffix/member
+ */
+
+void path_build( PATHNAME * f, string * file, int binding )
+{
+ struct dirinf root;
+ struct dirinf dir;
+ int g;
+
+ file_build1( f, file );
+
+ /* Get info on root and dir for combining. */
+ dir_flags( f->f_root.ptr, f->f_root.len, &root );
+ dir_flags( f->f_dir.ptr, f->f_dir.len, &dir );
+
+ /* Combine. */
+ switch ( g = grid[ root.flags ][ dir.flags ] )
+ {
+ case G_DIR:
+ /* take dir */
+ string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
+ break;
+
+ case G_ROOT:
+ /* take root */
+ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
+ break;
+
+ case G_VAD:
+ /* root's dev + abs directory */
+ string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len );
+ string_append_range( file, dir.dir.ptr, dir.dir.ptr + dir.dir.len );
+ break;
+
+ case G_DRD:
+ case G_DDD:
+ /* root's dev:[dir] + rel directory */
+ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
+
+ /* sanity checks: root ends with ] */
+
+ if ( file->value[file->size - 1] == ']' )
+ string_pop_back( file );
+
+ /* Add . if separating two -'s */
+
+ if ( g == G_DDD )
+ string_push_back( file, '.' );
+
+ /* skip [ of dir */
+ string_append_range( file, dir.dir.ptr + 1, dir.dir.ptr + 1 + dir.dir.len - 1 );
+ break;
+
+ case G_VRD:
+ /* root's dev + rel directory made abs */
+ string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len );
+ string_push_back( file, '[' );
+ /* skip [. of rel dir */
+ string_append_range( file, dir.dir.ptr + 2, dir.dir.ptr + 2 + dir.dir.len - 2 );
+ break;
+ }
+
+# ifdef DEBUG
+ if ( DEBUG_SEARCH && ( root.flags || dir.flags ) )
+ printf( "%d x %d = %d (%s)\n", root.flags, dir.flags,
+ grid[ root.flags ][ dir.flags ], file->value );
+# endif
+
+ /*
+ * Now do the special :P modifier when no file was present.
+ * (none) (none)
+ * [dir1.dir2] [dir1]
+ * [dir] [000000]
+ * [.dir] (none)
+ * [] []
+ */
+
+ if ( ( file->value[ file->size - 1 ] == ']' ) && f->parent )
+ {
+ char * p = file->value + file->size;
+ while ( p-- > file->value )
+ {
+ if ( *p == '.' )
+ {
+ /* If we've truncated everything and left with '[',
+ return empty string. */
+ if ( p == file->value + 1 )
+ string_truncate( file, 0 );
+ else
+ {
+ string_truncate( file, p - file->value );
+ string_push_back( file, ']' );
+ }
+ break;
+ }
+
+ if ( *p == '-' )
+ {
+ /* handle .- or - */
+ if ( ( p > file->value ) && ( p[ -1 ] == '.' ) )
+ --p;
+
+ *p++ = ']';
+ break;
+ }
+
+ if ( *p == '[' )
+ {
+ if ( p[ 1 ] == ']' )
+ {
+ /* CONSIDER: I don't see any use of this code. We immediately
+ break, and 'p' is a local variable. */
+ p += 2;
+ }
+ else
+ {
+ string_truncate( file, p - file->value );
+ string_append( file, "[000000]" );
+ }
+ break;
+ }
+ }
+ }
+
+ /* Now copy the file pieces. */
+ if ( f->f_base.len )
+ {
+ string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
+ }
+
+ /* If there is no suffix, we append a "." onto all generated names. This
+ * keeps VMS from appending its own (wrong) idea of what the suffix should
+ * be.
+ */
+ if ( f->f_suffix.len )
+ string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
+ else if ( binding && f->f_base.len )
+ string_push_back( file, '.' );
+
+ if ( f->f_member.len )
+ {
+ string_push_back( file, '(' );
+ string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
+ string_push_back( file, ')' );
+ }
+
+# ifdef DEBUG
+ if ( DEBUG_SEARCH )
+ printf( "built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n",
+ f->f_root.len, f->f_root.ptr,
+ f->f_dir.len, f->f_dir.ptr,
+ f->f_base.len, f->f_base.ptr,
+ f->f_suffix.len, f->f_suffix.ptr,
+ f->f_member.len, f->f_member.ptr,
+ file->value );
+# endif
+}
+
+
+/*
+ * path_parent() - make a PATHNAME point to its parent dir
+ */
+
+void path_parent( PATHNAME * f )
+{
+ if ( f->f_base.len )
+ {
+ f->f_base.ptr =
+ f->f_suffix.ptr =
+ f->f_member.ptr = "";
+
+ f->f_base.len =
+ f->f_suffix.len =
+ f->f_member.len = 0;
+ }
+ else
+ {
+ f->parent = 1;
+ }
+}
+
+# endif /* VMS */
diff --git a/tools/build/v2/engine/pwd.c b/tools/build/v2/engine/pwd.c
new file mode 100644
index 0000000000..90c8eb175d
--- /dev/null
+++ b/tools/build/v2/engine/pwd.c
@@ -0,0 +1,66 @@
+/* Copyright Vladimir Prus 2002, Rene Rivera 2005. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#include "jam.h"
+#include "lists.h"
+#include "newstr.h"
+#include "pathsys.h"
+#include "mem.h"
+
+#include <limits.h>
+#include <errno.h>
+
+/* MinGW on windows declares PATH_MAX in limits.h */
+#if defined(NT) && ! defined(__GNUC__)
+#include <direct.h>
+#define PATH_MAX _MAX_PATH
+#else
+#include <unistd.h>
+#if defined(__COMO__)
+ #include <linux/limits.h>
+#endif
+#endif
+
+#ifndef PATH_MAX
+ #define PATH_MAX 1024
+#endif
+
+/* The current directory can't change in bjam, so optimize this to cache
+** the result.
+*/
+static char * pwd_result = NULL;
+
+
+LIST*
+pwd(void)
+{
+ if (!pwd_result)
+ {
+ int buffer_size = PATH_MAX;
+ char * result_buffer = 0;
+ do
+ {
+ char * buffer = BJAM_MALLOC_RAW(buffer_size);
+ result_buffer = getcwd(buffer,buffer_size);
+ if (result_buffer)
+ {
+ #ifdef NT
+ pwd_result = short_path_to_long_path(result_buffer);
+ #else
+ pwd_result = newstr(result_buffer);
+ #endif
+ }
+ buffer_size *= 2;
+ BJAM_FREE_RAW(buffer);
+ }
+ while (!pwd_result && errno == ERANGE);
+
+ if (!pwd_result)
+ {
+ perror("can not get current directory");
+ return L0;
+ }
+ }
+ return list_new(L0, pwd_result);
+}
diff --git a/tools/build/v2/engine/pwd.h b/tools/build/v2/engine/pwd.h
new file mode 100644
index 0000000000..37cb531e4f
--- /dev/null
+++ b/tools/build/v2/engine/pwd.h
@@ -0,0 +1,10 @@
+/* Copyright Vladimir Prus 2002. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#ifndef PWD_H
+#define PWD_H
+
+LIST* pwd(void);
+
+#endif
diff --git a/tools/build/v2/engine/regexp.c b/tools/build/v2/engine/regexp.c
new file mode 100644
index 0000000000..30197a2feb
--- /dev/null
+++ b/tools/build/v2/engine/regexp.c
@@ -0,0 +1,1328 @@
+/*
+ * regcomp and regexec -- regsub and regerror are elsewhere
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore,
+ *** hoptoad!gnu, on 27 Dec 1986, to add \n as an alternative to |
+ *** to assist in implementing egrep.
+ *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore,
+ *** hoptoad!gnu, on 27 Dec 1986, to add \< and \> for word-matching
+ *** as in BSD grep and ex.
+ *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore,
+ *** hoptoad!gnu, on 28 Dec 1986, to optimize characters quoted with \.
+ *** THIS IS AN ALTERED VERSION. It was altered by James A. Woods,
+ *** ames!jaw, on 19 June 1987, to quash a regcomp() redundancy.
+ *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald
+ *** seiwald@vix.com, on 28 August 1993, for use in jam. Regmagic.h
+ *** was moved into regexp.h, and the include of regexp.h now uses "'s
+ *** to avoid conflicting with the system regexp.h. Const, bless its
+ *** soul, was removed so it can compile everywhere. The declaration
+ *** of strchr() was in conflict on AIX, so it was removed (as it is
+ *** happily defined in string.h).
+ *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald
+ *** seiwald@perforce.com, on 20 January 2000, to use function prototypes.
+ *
+ * Beware that some of this code is subtly aware of the way operator precedence
+ * is structured in regular expressions. Serious changes in regular-expression
+ * syntax might require a total rethink.
+ */
+
+
+#include "jam.h"
+#include "regexp.h"
+#include <stdio.h>
+#include <ctype.h>
+#ifndef ultrix
+ #include <stdlib.h>
+#endif
+#include <string.h>
+
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases. They are:
+ :
+ * regstart char that must begin a match; '\0' if none obvious.
+ * reganch is the match anchored (at beginning-of-line only)?
+ * regmust string (pointer into program) that match must include, or NULL.
+ * regmlen length of regmust string.
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot. Regmust permits fast rejection of
+ * lines that cannot possibly match. The regmust tests are costly enough that
+ * regcomp() supplies a regmust only if the r.e. contains something potentially
+ * expensive (at present, the only such thing detected is * or + at the start of
+ * the r.e., which can involve a lot of backup). Regmlen is supplied because the
+ * test in regexec() needs it and regcomp() is computing it anyway.
+ */
+
+/*
+ * Structure for regexp "program". This is essentially a linear encoding of a
+ * nondeterministic finite-state machine (aka syntax charts or "railroad normal
+ * form" in parsing technology). Each node is an opcode plus a "next" pointer,
+ * possibly plus an operand. "Next" pointers of all nodes except BRANCH
+ * implement concatenation; a "next" pointer with a BRANCH on both ends of it is
+ * connecting two alternatives. [Here we have one of the subtle syntax
+ * dependencies: an individual BRANCH, as opposed to a collection of them, is
+ * never concatenated with anything because of operator precedence.] The operand
+ * of some types of node is a literal string; for others, it is a node leading
+ * into a sub-FSM. In particular, the operand of a BRANCH node is the first node
+ * of the branch. [NB this is *not* a tree structure: the tail of the branch
+ * connects to the thing following the set of BRANCHes.] The opcodes are:
+ */
+
+/* definition number opnd? meaning */
+#define END 0 /* no End of program. */
+#define BOL 1 /* no Match "" at beginning of line. */
+#define EOL 2 /* no Match "" at end of line. */
+#define ANY 3 /* no Match any one character. */
+#define ANYOF 4 /* str Match any character in this string. */
+#define ANYBUT 5 /* str Match any character not in this string. */
+#define BRANCH 6 /* node Match this alternative, or the next... */
+#define BACK 7 /* no Match "", "next" ptr points backward. */
+#define EXACTLY 8 /* str Match this string. */
+#define NOTHING 9 /* no Match empty string. */
+#define STAR 10 /* node Match this (simple) thing 0 or more times. */
+#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
+#define WORDA 12 /* no Match "" at wordchar, where prev is nonword */
+#define WORDZ 13 /* no Match "" at nonwordchar, where prev is word */
+#define OPEN 20 /* no Mark this point in input as start of #n. */
+ /* OPEN+1 is number 1, etc. */
+#define CLOSE 30 /* no Analogous to OPEN. */
+
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH The set of branches constituting a single choice are hooked
+ * together with their "next" pointers, since precedence prevents
+ * anything being concatenated to any individual branch. The
+ * "next" pointer of the last BRANCH in a choice points to the
+ * thing following the whole choice. This is also where the
+ * final "next" pointer of each individual branch points; each
+ * branch starts with the operand node of a BRANCH node.
+ *
+ * BACK Normal "next" pointers all implicitly point forward; BACK
+ * exists to make loop structures possible.
+ *
+ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
+ * BRANCH structures using BACK. Simple cases (one character
+ * per match) are implemented with STAR and PLUS for speed
+ * and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE ...are numbered at compile time.
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first. The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node. (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define OP(p) (*(p))
+#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+#define OPERAND(p) ((p) + 3)
+
+/*
+ * See regmagic.h for one further detail of program structure.
+ */
+
+
+/*
+ * Utility definitions.
+ */
+#ifndef CHARBITS
+#define UCHARAT(p) ((int)*(unsigned char *)(p))
+#else
+#define UCHARAT(p) ((int)*(p)&CHARBITS)
+#endif
+
+#define FAIL(m) { regerror(m); return(NULL); }
+#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
+
+/*
+ * Flags to be passed up and down.
+ */
+#define HASWIDTH 01 /* Known never to match null string. */
+#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
+#define SPSTART 04 /* Starts with * or +. */
+#define WORST 0 /* Worst case. */
+
+/*
+ * Global work variables for regcomp().
+ */
+static char *regparse; /* Input-scan pointer. */
+static int regnpar; /* () count. */
+static char regdummy;
+static char *regcode; /* Code-emit pointer; &regdummy = don't. */
+static long regsize; /* Code size. */
+
+/*
+ * Forward declarations for regcomp()'s friends.
+ */
+#ifndef STATIC
+#define STATIC static
+#endif
+STATIC char *reg( int paren, int *flagp );
+STATIC char *regbranch( int *flagp );
+STATIC char *regpiece( int *flagp );
+STATIC char *regatom( int *flagp );
+STATIC char *regnode( int op );
+STATIC char *regnext( register char *p );
+STATIC void regc( int b );
+STATIC void reginsert( char op, char *opnd );
+STATIC void regtail( char *p, char *val );
+STATIC void regoptail( char *p, char *val );
+#ifdef STRCSPN
+STATIC int strcspn();
+#endif
+
+/*
+ - regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code. So we cheat: we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it. (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+regexp *
+regcomp( char *exp )
+{
+ register regexp *r;
+ register char *scan;
+ register char *longest;
+ register unsigned len;
+ int flags;
+
+ if (exp == NULL)
+ FAIL("NULL argument");
+
+ /* First pass: determine size, legality. */
+#ifdef notdef
+ if (exp[0] == '.' && exp[1] == '*') exp += 2; /* aid grep */
+#endif
+ regparse = (char *)exp;
+ regnpar = 1;
+ regsize = 0L;
+ regcode = &regdummy;
+ regc(MAGIC);
+ if (reg(0, &flags) == NULL)
+ return(NULL);
+
+ /* Small enough for pointer-storage convention? */
+ if (regsize >= 32767L) /* Probably could be 65535L. */
+ FAIL("regexp too big");
+
+ /* Allocate space. */
+ r = (regexp *)BJAM_MALLOC(sizeof(regexp) + (unsigned)regsize);
+ if (r == NULL)
+ FAIL("out of space");
+
+ /* Second pass: emit code. */
+ regparse = (char *)exp;
+ regnpar = 1;
+ regcode = r->program;
+ regc(MAGIC);
+ if (reg(0, &flags) == NULL)
+ return(NULL);
+
+ /* Dig out information for optimizations. */
+ r->regstart = '\0'; /* Worst-case defaults. */
+ r->reganch = 0;
+ r->regmust = NULL;
+ r->regmlen = 0;
+ scan = r->program+1; /* First BRANCH. */
+ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */
+ scan = OPERAND(scan);
+
+ /* Starting-point info. */
+ if (OP(scan) == EXACTLY)
+ r->regstart = *OPERAND(scan);
+ else if (OP(scan) == BOL)
+ r->reganch++;
+
+ /*
+ * If there's something expensive in the r.e., find the
+ * longest literal string that must appear and make it the
+ * regmust. Resolve ties in favor of later strings, since
+ * the regstart check works with the beginning of the r.e.
+ * and avoiding duplication strengthens checking. Not a
+ * strong reason, but sufficient in the absence of others.
+ */
+ if (flags&SPSTART) {
+ longest = NULL;
+ len = 0;
+ for (; scan != NULL; scan = regnext(scan))
+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+ longest = OPERAND(scan);
+ len = strlen(OPERAND(scan));
+ }
+ r->regmust = longest;
+ r->regmlen = len;
+ }
+ }
+
+ return(r);
+}
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+static char *
+reg(
+ int paren, /* Parenthesized? */
+ int *flagp )
+{
+ register char *ret;
+ register char *br;
+ register char *ender;
+ register int parno = 0;
+ int flags;
+
+ *flagp = HASWIDTH; /* Tentatively. */
+
+ /* Make an OPEN node, if parenthesized. */
+ if (paren) {
+ if (regnpar >= NSUBEXP)
+ FAIL("too many ()");
+ parno = regnpar;
+ regnpar++;
+ ret = regnode(OPEN+parno);
+ } else
+ ret = NULL;
+
+ /* Pick up the branches, linking them together. */
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ if (ret != NULL)
+ regtail(ret, br); /* OPEN -> first. */
+ else
+ ret = br;
+ if (!(flags&HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags&SPSTART;
+ while (*regparse == '|' || *regparse == '\n') {
+ regparse++;
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ regtail(ret, br); /* BRANCH -> BRANCH. */
+ if (!(flags&HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags&SPSTART;
+ }
+
+ /* Make a closing node, and hook it on the end. */
+ ender = regnode((paren) ? CLOSE+parno : END);
+ regtail(ret, ender);
+
+ /* Hook the tails of the branches to the closing node. */
+ for (br = ret; br != NULL; br = regnext(br))
+ regoptail(br, ender);
+
+ /* Check for proper termination. */
+ if (paren && *regparse++ != ')') {
+ FAIL("unmatched ()");
+ } else if (!paren && *regparse != '\0') {
+ if (*regparse == ')') {
+ FAIL("unmatched ()");
+ } else
+ FAIL("junk on end"); /* "Can't happen". */
+ /* NOTREACHED */
+ }
+
+ return(ret);
+}
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+static char *
+regbranch( int *flagp )
+{
+ register char *ret;
+ register char *chain;
+ register char *latest;
+ int flags;
+
+ *flagp = WORST; /* Tentatively. */
+
+ ret = regnode(BRANCH);
+ chain = NULL;
+ while (*regparse != '\0' && *regparse != ')' &&
+ *regparse != '\n' && *regparse != '|') {
+ latest = regpiece(&flags);
+ if (latest == NULL)
+ return(NULL);
+ *flagp |= flags&HASWIDTH;
+ if (chain == NULL) /* First piece. */
+ *flagp |= flags&SPSTART;
+ else
+ regtail(chain, latest);
+ chain = latest;
+ }
+ if (chain == NULL) /* Loop ran zero times. */
+ (void) regnode(NOTHING);
+
+ return(ret);
+}
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized: they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+static char *
+regpiece( int *flagp )
+{
+ register char *ret;
+ register char op;
+ register char *next;
+ int flags;
+
+ ret = regatom(&flags);
+ if (ret == NULL)
+ return(NULL);
+
+ op = *regparse;
+ if (!ISMULT(op)) {
+ *flagp = flags;
+ return(ret);
+ }
+
+ if (!(flags&HASWIDTH) && op != '?')
+ FAIL("*+ operand could be empty");
+ *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+
+ if (op == '*' && (flags&SIMPLE))
+ reginsert(STAR, ret);
+ else if (op == '*') {
+ /* Emit x* as (x&|), where & means "self". */
+ reginsert(BRANCH, ret); /* Either x */
+ regoptail(ret, regnode(BACK)); /* and loop */
+ regoptail(ret, ret); /* back */
+ regtail(ret, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ } else if (op == '+' && (flags&SIMPLE))
+ reginsert(PLUS, ret);
+ else if (op == '+') {
+ /* Emit x+ as x(&|), where & means "self". */
+ next = regnode(BRANCH); /* Either */
+ regtail(ret, next);
+ regtail(regnode(BACK), ret); /* loop back */
+ regtail(next, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ } else if (op == '?') {
+ /* Emit x? as (x|) */
+ reginsert(BRANCH, ret); /* Either x */
+ regtail(ret, regnode(BRANCH)); /* or */
+ next = regnode(NOTHING); /* null. */
+ regtail(ret, next);
+ regoptail(ret, next);
+ }
+ regparse++;
+ if (ISMULT(*regparse))
+ FAIL("nested *?+");
+
+ return(ret);
+}
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization: gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run. Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+static char *
+regatom( int *flagp )
+{
+ register char *ret;
+ int flags;
+
+ *flagp = WORST; /* Tentatively. */
+
+ switch (*regparse++) {
+ /* FIXME: these chars only have meaning at beg/end of pat? */
+ case '^':
+ ret = regnode(BOL);
+ break;
+ case '$':
+ ret = regnode(EOL);
+ break;
+ case '.':
+ ret = regnode(ANY);
+ *flagp |= HASWIDTH|SIMPLE;
+ break;
+ case '[': {
+ register int classr;
+ register int classend;
+
+ if (*regparse == '^') { /* Complement of range. */
+ ret = regnode(ANYBUT);
+ regparse++;
+ } else
+ ret = regnode(ANYOF);
+ if (*regparse == ']' || *regparse == '-')
+ regc(*regparse++);
+ while (*regparse != '\0' && *regparse != ']') {
+ if (*regparse == '-') {
+ regparse++;
+ if (*regparse == ']' || *regparse == '\0')
+ regc('-');
+ else {
+ classr = UCHARAT(regparse-2)+1;
+ classend = UCHARAT(regparse);
+ if (classr > classend+1)
+ FAIL("invalid [] range");
+ for (; classr <= classend; classr++)
+ regc(classr);
+ regparse++;
+ }
+ } else
+ regc(*regparse++);
+ }
+ regc('\0');
+ if (*regparse != ']')
+ FAIL("unmatched []");
+ regparse++;
+ *flagp |= HASWIDTH|SIMPLE;
+ }
+ break;
+ case '(':
+ ret = reg(1, &flags);
+ if (ret == NULL)
+ return(NULL);
+ *flagp |= flags&(HASWIDTH|SPSTART);
+ break;
+ case '\0':
+ case '|':
+ case '\n':
+ case ')':
+ FAIL("internal urp"); /* Supposed to be caught earlier. */
+ break;
+ case '?':
+ case '+':
+ case '*':
+ FAIL("?+* follows nothing");
+ break;
+ case '\\':
+ switch (*regparse++) {
+ case '\0':
+ FAIL("trailing \\");
+ break;
+ case '<':
+ ret = regnode(WORDA);
+ break;
+ case '>':
+ ret = regnode(WORDZ);
+ break;
+ /* FIXME: Someday handle \1, \2, ... */
+ default:
+ /* Handle general quoted chars in exact-match routine */
+ goto de_fault;
+ }
+ break;
+ de_fault:
+ default:
+ /*
+ * Encode a string of characters to be matched exactly.
+ *
+ * This is a bit tricky due to quoted chars and due to
+ * '*', '+', and '?' taking the SINGLE char previous
+ * as their operand.
+ *
+ * On entry, the char at regparse[-1] is going to go
+ * into the string, no matter what it is. (It could be
+ * following a \ if we are entered from the '\' case.)
+ *
+ * Basic idea is to pick up a good char in ch and
+ * examine the next char. If it's *+? then we twiddle.
+ * If it's \ then we frozzle. If it's other magic char
+ * we push ch and terminate the string. If none of the
+ * above, we push ch on the string and go around again.
+ *
+ * regprev is used to remember where "the current char"
+ * starts in the string, if due to a *+? we need to back
+ * up and put the current char in a separate, 1-char, string.
+ * When regprev is NULL, ch is the only char in the
+ * string; this is used in *+? handling, and in setting
+ * flags |= SIMPLE at the end.
+ */
+ {
+ char *regprev;
+ register char ch;
+
+ regparse--; /* Look at cur char */
+ ret = regnode(EXACTLY);
+ for ( regprev = 0 ; ; ) {
+ ch = *regparse++; /* Get current char */
+ switch (*regparse) { /* look at next one */
+
+ default:
+ regc(ch); /* Add cur to string */
+ break;
+
+ case '.': case '[': case '(':
+ case ')': case '|': case '\n':
+ case '$': case '^':
+ case '\0':
+ /* FIXME, $ and ^ should not always be magic */
+ magic:
+ regc(ch); /* dump cur char */
+ goto done; /* and we are done */
+
+ case '?': case '+': case '*':
+ if (!regprev) /* If just ch in str, */
+ goto magic; /* use it */
+ /* End mult-char string one early */
+ regparse = regprev; /* Back up parse */
+ goto done;
+
+ case '\\':
+ regc(ch); /* Cur char OK */
+ switch (regparse[1]){ /* Look after \ */
+ case '\0':
+ case '<':
+ case '>':
+ /* FIXME: Someday handle \1, \2, ... */
+ goto done; /* Not quoted */
+ default:
+ /* Backup point is \, scan * point is after it. */
+ regprev = regparse;
+ regparse++;
+ continue; /* NOT break; */
+ }
+ }
+ regprev = regparse; /* Set backup point */
+ }
+ done:
+ regc('\0');
+ *flagp |= HASWIDTH;
+ if (!regprev) /* One char? */
+ *flagp |= SIMPLE;
+ }
+ break;
+ }
+
+ return(ret);
+}
+
+/*
+ - regnode - emit a node
+ */
+static char * /* Location. */
+regnode( int op )
+{
+ register char *ret;
+ register char *ptr;
+
+ ret = regcode;
+ if (ret == &regdummy) {
+ regsize += 3;
+ return(ret);
+ }
+
+ ptr = ret;
+ *ptr++ = op;
+ *ptr++ = '\0'; /* Null "next" pointer. */
+ *ptr++ = '\0';
+ regcode = ptr;
+
+ return(ret);
+}
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+static void
+regc( int b )
+{
+ if (regcode != &regdummy)
+ *regcode++ = b;
+ else
+ regsize++;
+}
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+static void
+reginsert(
+ char op,
+ char *opnd )
+{
+ register char *src;
+ register char *dst;
+ register char *place;
+
+ if (regcode == &regdummy) {
+ regsize += 3;
+ return;
+ }
+
+ src = regcode;
+ regcode += 3;
+ dst = regcode;
+ while (src > opnd)
+ *--dst = *--src;
+
+ place = opnd; /* Op node, where operand used to be. */
+ *place++ = op;
+ *place++ = '\0';
+ *place++ = '\0';
+}
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+static void
+regtail(
+ char *p,
+ char *val )
+{
+ register char *scan;
+ register char *temp;
+ register int offset;
+
+ if (p == &regdummy)
+ return;
+
+ /* Find last node. */
+ scan = p;
+ for (;;) {
+ temp = regnext(scan);
+ if (temp == NULL)
+ break;
+ scan = temp;
+ }
+
+ if (OP(scan) == BACK)
+ offset = scan - val;
+ else
+ offset = val - scan;
+ *(scan+1) = (offset>>8)&0377;
+ *(scan+2) = offset&0377;
+}
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+
+static void
+regoptail(
+ char *p,
+ char *val )
+{
+ /* "Operandless" and "op != BRANCH" are synonymous in practice. */
+ if (p == NULL || p == &regdummy || OP(p) != BRANCH)
+ return;
+ regtail(OPERAND(p), val);
+}
+
+/*
+ * regexec and friends
+ */
+
+/*
+ * Global work variables for regexec().
+ */
+static char *reginput; /* String-input pointer. */
+static char *regbol; /* Beginning of input, for ^ check. */
+static char **regstartp; /* Pointer to startp array. */
+static char **regendp; /* Ditto for endp. */
+
+/*
+ * Forwards.
+ */
+STATIC int regtry( regexp *prog, char *string );
+STATIC int regmatch( char *prog );
+STATIC int regrepeat( char *p );
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump();
+STATIC char *regprop();
+#endif
+
+/*
+ - regexec - match a regexp against a string
+ */
+int
+regexec(
+ register regexp *prog,
+ register char *string )
+{
+ register char *s;
+
+ /* Be paranoid... */
+ if (prog == NULL || string == NULL) {
+ regerror("NULL parameter");
+ return(0);
+ }
+
+ /* Check validity of program. */
+ if (UCHARAT(prog->program) != MAGIC) {
+ regerror("corrupted program");
+ return(0);
+ }
+
+ /* If there is a "must appear" string, look for it. */
+ if ( prog->regmust != NULL )
+ {
+ s = (char *)string;
+ while ( ( s = strchr( s, prog->regmust[ 0 ] ) ) != NULL )
+ {
+ if ( !strncmp( s, prog->regmust, prog->regmlen ) )
+ break; /* Found it. */
+ ++s;
+ }
+ if ( s == NULL ) /* Not present. */
+ return 0;
+ }
+
+ /* Mark beginning of line for ^ . */
+ regbol = (char *)string;
+
+ /* Simplest case: anchored match need be tried only once. */
+ if ( prog->reganch )
+ return regtry( prog, string );
+
+ /* Messy cases: unanchored match. */
+ s = (char *)string;
+ if (prog->regstart != '\0')
+ /* We know what char it must start with. */
+ while ((s = strchr(s, prog->regstart)) != NULL) {
+ if (regtry(prog, s))
+ return(1);
+ s++;
+ }
+ else
+ /* We do not -- general case. */
+ do {
+ if ( regtry( prog, s ) )
+ return( 1 );
+ } while ( *s++ != '\0' );
+
+ /* Failure. */
+ return 0;
+}
+
+
+/*
+ * regtry() - try match at specific point.
+ */
+
+static int /* 0 failure, 1 success */
+regtry(
+ regexp *prog,
+ char *string )
+{
+ register int i;
+ register char * * sp;
+ register char * * ep;
+
+ reginput = string;
+ regstartp = prog->startp;
+ regendp = prog->endp;
+
+ sp = prog->startp;
+ ep = prog->endp;
+ for ( i = NSUBEXP; i > 0; --i )
+ {
+ *sp++ = NULL;
+ *ep++ = NULL;
+ }
+ if ( regmatch( prog->program + 1 ) )
+ {
+ prog->startp[ 0 ] = string;
+ prog->endp[ 0 ] = reginput;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+/*
+ * regmatch() - main matching routine.
+ *
+ * Conceptually the strategy is simple: check to see whether the current node
+ * matches, call self recursively to see whether the rest matches, and then act
+ * accordingly. In practice we make some effort to avoid recursion, in
+ * particular by going through "ordinary" nodes (that do not need to know
+ * whether the rest of the match failed) by a loop instead of by recursion.
+ */
+
+static int /* 0 failure, 1 success */
+regmatch( char * prog )
+{
+ char * scan; /* Current node. */
+ char * next; /* Next node. */
+
+ scan = prog;
+#ifdef DEBUG
+ if (scan != NULL && regnarrate)
+ fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+ while (scan != NULL) {
+#ifdef DEBUG
+ if (regnarrate)
+ fprintf(stderr, "%s...\n", regprop(scan));
+#endif
+ next = regnext(scan);
+
+ switch (OP(scan)) {
+ case BOL:
+ if (reginput != regbol)
+ return(0);
+ break;
+ case EOL:
+ if (*reginput != '\0')
+ return(0);
+ break;
+ case WORDA:
+ /* Must be looking at a letter, digit, or _ */
+ if ((!isalnum(*reginput)) && *reginput != '_')
+ return(0);
+ /* Prev must be BOL or nonword */
+ if (reginput > regbol &&
+ (isalnum(reginput[-1]) || reginput[-1] == '_'))
+ return(0);
+ break;
+ case WORDZ:
+ /* Must be looking at non letter, digit, or _ */
+ if (isalnum(*reginput) || *reginput == '_')
+ return(0);
+ /* We don't care what the previous char was */
+ break;
+ case ANY:
+ if (*reginput == '\0')
+ return(0);
+ reginput++;
+ break;
+ case EXACTLY: {
+ register int len;
+ register char *opnd;
+
+ opnd = OPERAND(scan);
+ /* Inline the first character, for speed. */
+ if (*opnd != *reginput)
+ return(0);
+ len = strlen(opnd);
+ if (len > 1 && strncmp(opnd, reginput, len) != 0)
+ return(0);
+ reginput += len;
+ }
+ break;
+ case ANYOF:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
+ return(0);
+ reginput++;
+ break;
+ case ANYBUT:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
+ return(0);
+ reginput++;
+ break;
+ case NOTHING:
+ break;
+ case BACK:
+ break;
+ case OPEN+1:
+ case OPEN+2:
+ case OPEN+3:
+ case OPEN+4:
+ case OPEN+5:
+ case OPEN+6:
+ case OPEN+7:
+ case OPEN+8:
+ case OPEN+9: {
+ register int no;
+ register char *save;
+
+ no = OP(scan) - OPEN;
+ save = reginput;
+
+ if (regmatch(next)) {
+ /*
+ * Don't set startp if some later
+ * invocation of the same parentheses
+ * already has.
+ */
+ if (regstartp[no] == NULL)
+ regstartp[no] = save;
+ return(1);
+ } else
+ return(0);
+ }
+ break;
+ case CLOSE+1:
+ case CLOSE+2:
+ case CLOSE+3:
+ case CLOSE+4:
+ case CLOSE+5:
+ case CLOSE+6:
+ case CLOSE+7:
+ case CLOSE+8:
+ case CLOSE+9: {
+ register int no;
+ register char *save;
+
+ no = OP(scan) - CLOSE;
+ save = reginput;
+
+ if (regmatch(next)) {
+ /*
+ * Don't set endp if some later
+ * invocation of the same parentheses
+ * already has.
+ */
+ if (regendp[no] == NULL)
+ regendp[no] = save;
+ return(1);
+ } else
+ return(0);
+ }
+ break;
+ case BRANCH: {
+ register char *save;
+
+ if (OP(next) != BRANCH) /* No choice. */
+ next = OPERAND(scan); /* Avoid recursion. */
+ else {
+ do {
+ save = reginput;
+ if (regmatch(OPERAND(scan)))
+ return(1);
+ reginput = save;
+ scan = regnext(scan);
+ } while (scan != NULL && OP(scan) == BRANCH);
+ return(0);
+ /* NOTREACHED */
+ }
+ }
+ break;
+ case STAR:
+ case PLUS: {
+ register char nextch;
+ register int no;
+ register char *save;
+ register int min;
+
+ /*
+ * Lookahead to avoid useless match attempts
+ * when we know what character comes next.
+ */
+ nextch = '\0';
+ if (OP(next) == EXACTLY)
+ nextch = *OPERAND(next);
+ min = (OP(scan) == STAR) ? 0 : 1;
+ save = reginput;
+ no = regrepeat(OPERAND(scan));
+ while (no >= min) {
+ /* If it could work, try it. */
+ if (nextch == '\0' || *reginput == nextch)
+ if (regmatch(next))
+ return(1);
+ /* Couldn't or didn't -- back up. */
+ no--;
+ reginput = save + no;
+ }
+ return(0);
+ }
+ break;
+ case END:
+ return(1); /* Success! */
+ break;
+ default:
+ regerror("memory corruption");
+ return(0);
+ break;
+ }
+
+ scan = next;
+ }
+
+ /*
+ * We get here only if there's trouble -- normally "case END" is
+ * the terminating point.
+ */
+ regerror("corrupted pointers");
+ return(0);
+}
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+static int
+regrepeat( char *p )
+{
+ register int count = 0;
+ register char *scan;
+ register char *opnd;
+
+ scan = reginput;
+ opnd = OPERAND(p);
+ switch (OP(p)) {
+ case ANY:
+ count = strlen(scan);
+ scan += count;
+ break;
+ case EXACTLY:
+ while (*opnd == *scan) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYOF:
+ while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYBUT:
+ while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
+ count++;
+ scan++;
+ }
+ break;
+ default: /* Oh dear. Called inappropriately. */
+ regerror("internal foulup");
+ count = 0; /* Best compromise. */
+ break;
+ }
+ reginput = scan;
+
+ return(count);
+}
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+static char *
+regnext( register char *p )
+{
+ register int offset;
+
+ if (p == &regdummy)
+ return(NULL);
+
+ offset = NEXT(p);
+ if (offset == 0)
+ return(NULL);
+
+ if (OP(p) == BACK)
+ return(p-offset);
+ else
+ return(p+offset);
+}
+
+#ifdef DEBUG
+
+STATIC char *regprop();
+
+/*
+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+void
+regdump( regexp *r )
+{
+ register char *s;
+ register char op = EXACTLY; /* Arbitrary non-END op. */
+ register char *next;
+
+
+ s = r->program + 1;
+ while (op != END) { /* While that wasn't END last time... */
+ op = OP(s);
+ printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */
+ next = regnext(s);
+ if (next == NULL) /* Next ptr. */
+ printf("(0)");
+ else
+ printf("(%d)", (s-r->program)+(next-s));
+ s += 3;
+ if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+ /* Literal string, where present. */
+ while (*s != '\0') {
+ putchar(*s);
+ s++;
+ }
+ s++;
+ }
+ putchar('\n');
+ }
+
+ /* Header fields of interest. */
+ if (r->regstart != '\0')
+ printf("start `%c' ", r->regstart);
+ if (r->reganch)
+ printf("anchored ");
+ if (r->regmust != NULL)
+ printf("must have \"%s\"", r->regmust);
+ printf("\n");
+}
+
+/*
+ - regprop - printable representation of opcode
+ */
+static char *
+regprop( char *op )
+{
+ register char *p;
+ static char buf[50];
+
+ (void) strcpy(buf, ":");
+
+ switch (OP(op)) {
+ case BOL:
+ p = "BOL";
+ break;
+ case EOL:
+ p = "EOL";
+ break;
+ case ANY:
+ p = "ANY";
+ break;
+ case ANYOF:
+ p = "ANYOF";
+ break;
+ case ANYBUT:
+ p = "ANYBUT";
+ break;
+ case BRANCH:
+ p = "BRANCH";
+ break;
+ case EXACTLY:
+ p = "EXACTLY";
+ break;
+ case NOTHING:
+ p = "NOTHING";
+ break;
+ case BACK:
+ p = "BACK";
+ break;
+ case END:
+ p = "END";
+ break;
+ case OPEN+1:
+ case OPEN+2:
+ case OPEN+3:
+ case OPEN+4:
+ case OPEN+5:
+ case OPEN+6:
+ case OPEN+7:
+ case OPEN+8:
+ case OPEN+9:
+ sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
+ p = NULL;
+ break;
+ case CLOSE+1:
+ case CLOSE+2:
+ case CLOSE+3:
+ case CLOSE+4:
+ case CLOSE+5:
+ case CLOSE+6:
+ case CLOSE+7:
+ case CLOSE+8:
+ case CLOSE+9:
+ sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
+ p = NULL;
+ break;
+ case STAR:
+ p = "STAR";
+ break;
+ case PLUS:
+ p = "PLUS";
+ break;
+ case WORDA:
+ p = "WORDA";
+ break;
+ case WORDZ:
+ p = "WORDZ";
+ break;
+ default:
+ regerror("corrupted opcode");
+ break;
+ }
+ if (p != NULL)
+ (void) strcat(buf, p);
+ return(buf);
+}
+#endif
+
+/*
+ * The following is provided for those people who do not have strcspn() in
+ * their C libraries. They should get off their butts and do something
+ * about it; at least one public-domain implementation of those (highly
+ * useful) string routines has been published on Usenet.
+ */
+#ifdef STRCSPN
+/*
+ * strcspn - find length of initial segment of s1 consisting entirely
+ * of characters not from s2
+ */
+
+static int
+strcspn(
+ char *s1,
+ char *s2 )
+{
+ register char *scan1;
+ register char *scan2;
+ register int count;
+
+ count = 0;
+ for (scan1 = s1; *scan1 != '\0'; scan1++) {
+ for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */
+ if (*scan1 == *scan2++)
+ return(count);
+ count++;
+ }
+ return(count);
+}
+#endif
diff --git a/tools/build/v2/engine/regexp.h b/tools/build/v2/engine/regexp.h
new file mode 100644
index 0000000000..9d4604f60a
--- /dev/null
+++ b/tools/build/v2/engine/regexp.h
@@ -0,0 +1,32 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+#ifndef REGEXP_DWA20011023_H
+# define REGEXP_DWA20011023_H
+
+#define NSUBEXP 10
+typedef struct regexp {
+ char *startp[NSUBEXP];
+ char *endp[NSUBEXP];
+ char regstart; /* Internal use only. */
+ char reganch; /* Internal use only. */
+ char *regmust; /* Internal use only. */
+ int regmlen; /* Internal use only. */
+ char program[1]; /* Unwarranted chumminess with compiler. */
+} regexp;
+
+regexp *regcomp( char *exp );
+int regexec( regexp *prog, char *string );
+void regerror( char *s );
+
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define MAGIC 0234
+
+#endif
+
diff --git a/tools/build/v2/engine/rules.c b/tools/build/v2/engine/rules.c
new file mode 100644
index 0000000000..a0be1d3400
--- /dev/null
+++ b/tools/build/v2/engine/rules.c
@@ -0,0 +1,810 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "parse.h"
+# include "variable.h"
+# include "rules.h"
+# include "newstr.h"
+# include "hash.h"
+# include "modules.h"
+# include "search.h"
+# include "lists.h"
+# include "pathsys.h"
+# include "timestamp.h"
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * rules.c - access to RULEs, TARGETs, and ACTIONs
+ *
+ * External routines:
+ *
+ * bindrule() - return pointer to RULE, creating it if necessary.
+ * bindtarget() - return pointer to TARGET, creating it if necessary.
+ * touch_target() - mark a target to simulate being new.
+ * targetlist() - turn list of target names into a TARGET chain.
+ * targetentry() - add a TARGET to a chain of TARGETS.
+ * actionlist() - append to an ACTION chain.
+ * addsettings() - add a deferred "set" command to a target.
+ * pushsettings() - set all target specific variables.
+ * popsettings() - reset target specific variables to their pre-push values.
+ * freesettings() - delete a settings list.
+ * rules_done() - free RULE and TARGET tables.
+ *
+ * 04/12/94 (seiwald) - actionlist() now just appends a single action.
+ * 08/23/94 (seiwald) - Support for '+=' (append to variable)
+ */
+
+static void set_rule_actions( RULE *, rule_actions * );
+static void set_rule_body ( RULE *, argument_list *, PARSE * procedure );
+
+static struct hash * targethash = 0;
+
+struct _located_target
+{
+ char * file_name;
+ TARGET * target;
+};
+typedef struct _located_target LOCATED_TARGET ;
+
+static struct hash * located_targets = 0;
+
+
+/*
+ * target_include() - adds the 'included' TARGET to the list of targets included
+ * by the 'including' TARGET. Such targets are modeled as dependencies of the
+ * internal include node belonging to the 'including' TARGET.
+ */
+
+void target_include( TARGET * including, TARGET * included )
+{
+ TARGET * internal;
+ if ( !including->includes )
+ {
+ including->includes = copytarget( including );
+ including->includes->original_target = including;
+ }
+ internal = including->includes;
+ internal->depends = targetentry( internal->depends, included );
+}
+
+
+/*
+ * enter_rule() - return pointer to RULE, creating it if necessary in
+ * target_module.
+ */
+
+static RULE * enter_rule( char * rulename, module_t * target_module )
+{
+ RULE rule;
+ RULE * r = &rule;
+
+ r->name = rulename;
+
+ if ( hashenter( demand_rules( target_module ), (HASHDATA * *)&r ) )
+ {
+ r->name = newstr( rulename ); /* never freed */
+ r->procedure = (PARSE *)0;
+ r->module = 0;
+ r->actions = 0;
+ r->arguments = 0;
+ r->exported = 0;
+ r->module = target_module;
+#ifdef HAVE_PYTHON
+ r->python_function = 0;
+#endif
+ }
+ return r;
+}
+
+
+/*
+ * define_rule() - return pointer to RULE, creating it if necessary in
+ * target_module. Prepare it to accept a body or action originating in
+ * src_module.
+ */
+
+static RULE * define_rule
+(
+ module_t * src_module,
+ char * rulename,
+ module_t * target_module
+)
+{
+ RULE * r = enter_rule( rulename, target_module );
+ if ( r->module != src_module ) /* if the rule was imported from elsewhere, clear it now */
+ {
+ set_rule_body( r, 0, 0 );
+ set_rule_actions( r, 0 );
+ r->module = src_module; /* r will be executed in the source module */
+ }
+ return r;
+}
+
+
+void rule_free( RULE * r )
+{
+ freestr( r->name );
+ r->name = "";
+ parse_free( r->procedure );
+ r->procedure = 0;
+ if ( r->arguments )
+ args_free( r->arguments );
+ r->arguments = 0;
+ if ( r->actions )
+ actions_free( r->actions );
+ r->actions = 0;
+}
+
+
+/*
+ * bindtarget() - return pointer to TARGET, creating it if necessary.
+ */
+
+TARGET * bindtarget( char const * target_name )
+{
+ TARGET target;
+ TARGET * t = &target;
+
+ if ( !targethash )
+ targethash = hashinit( sizeof( TARGET ), "targets" );
+
+ /* Perforce added const everywhere. No time to merge that change. */
+#ifdef NT
+ target_name = short_path_to_long_path( (char *)target_name );
+#endif
+ t->name = (char *)target_name;
+
+ if ( hashenter( targethash, (HASHDATA * *)&t ) )
+ {
+ memset( (char *)t, '\0', sizeof( *t ) );
+ t->name = newstr( (char *)target_name ); /* never freed */
+ t->boundname = t->name; /* default for T_FLAG_NOTFILE */
+ }
+
+ return t;
+}
+
+
+static void bind_explicitly_located_target( void * xtarget, void * data )
+{
+ TARGET * t = (TARGET *)xtarget;
+ if ( !( t->flags & T_FLAG_NOTFILE ) )
+ {
+ /* Check if there's a setting for LOCATE */
+ SETTINGS * s = t->settings;
+ for ( ; s ; s = s->next )
+ {
+ if ( strcmp( s->symbol, "LOCATE" ) == 0 )
+ {
+ pushsettings( t->settings );
+ /* We are binding a target with explicit LOCATE. So third
+ * argument is of no use: nothing will be returned through it.
+ */
+ t->boundname = search( t->name, &t->time, 0, 0 );
+ popsettings( t->settings );
+ break;
+ }
+ }
+ }
+}
+
+
+void bind_explicitly_located_targets()
+{
+ if ( targethash )
+ hashenumerate( targethash, bind_explicitly_located_target, (void *)0 );
+}
+
+
+/* TODO: It is probably not a good idea to use functions in other modules like
+ this. */
+void call_bind_rule( char * target, char * boundname );
+
+
+TARGET * search_for_target ( char * name, LIST * search_path )
+{
+ PATHNAME f[1];
+ string buf[1];
+ LOCATED_TARGET lt;
+ LOCATED_TARGET * lta = &lt;
+ time_t time;
+ int found = 0;
+ TARGET * result;
+
+ string_new( buf );
+
+ path_parse( name, f );
+
+ f->f_grist.ptr = 0;
+ f->f_grist.len = 0;
+
+ while ( search_path )
+ {
+ f->f_root.ptr = search_path->string;
+ f->f_root.len = strlen( search_path->string );
+
+ string_truncate( buf, 0 );
+ path_build( f, buf, 1 );
+
+ lt.file_name = buf->value ;
+
+ if ( !located_targets )
+ located_targets = hashinit( sizeof(LOCATED_TARGET),
+ "located targets" );
+
+ if ( hashcheck( located_targets, (HASHDATA * *)&lta ) )
+ {
+ return lta->target;
+ }
+
+ timestamp( buf->value, &time );
+ if ( time )
+ {
+ found = 1;
+ break;
+ }
+
+ search_path = list_next( search_path );
+ }
+
+ if ( !found )
+ {
+ f->f_root.ptr = 0;
+ f->f_root.len = 0;
+
+ string_truncate( buf, 0 );
+ path_build( f, buf, 1 );
+
+ timestamp( buf->value, &time );
+ }
+
+ result = bindtarget( name );
+ result->boundname = newstr( buf->value );
+ result->time = time;
+ result->binding = time ? T_BIND_EXISTS : T_BIND_MISSING;
+
+ call_bind_rule( result->name, result->boundname );
+
+ string_free( buf );
+
+ return result;
+}
+
+
+/*
+ * copytarget() - make a new target with the old target's name.
+ *
+ * Not entered into hash table -- for internal nodes.
+ */
+
+TARGET * copytarget( const TARGET * ot )
+{
+ TARGET * t = (TARGET *)BJAM_MALLOC( sizeof( *t ) );
+ memset( (char *)t, '\0', sizeof( *t ) );
+ t->name = copystr( ot->name );
+ t->boundname = t->name;
+
+ t->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL;
+
+ return t;
+}
+
+
+/*
+ * touch_target() - mark a target to simulate being new.
+ */
+
+void touch_target( char * t )
+{
+ bindtarget( t )->flags |= T_FLAG_TOUCHED;
+}
+
+
+/*
+ * targetlist() - turn list of target names into a TARGET chain.
+ *
+ * Inputs:
+ * chain existing TARGETS to append to
+ * targets list of target names
+ */
+
+TARGETS * targetlist( TARGETS * chain, LIST * target_names )
+{
+ for ( ; target_names; target_names = list_next( target_names ) )
+ chain = targetentry( chain, bindtarget( target_names->string ) );
+ return chain;
+}
+
+
+/*
+ * targetentry() - add a TARGET to a chain of TARGETS.
+ *
+ * Inputs:
+ * chain existing TARGETS to append to
+ * target new target to append
+ */
+
+TARGETS * targetentry( TARGETS * chain, TARGET * target )
+{
+ TARGETS * c = (TARGETS *)BJAM_MALLOC( sizeof( TARGETS ) );
+ c->target = target;
+
+ if ( !chain ) chain = c;
+ else chain->tail->next = c;
+ chain->tail = c;
+ c->next = 0;
+
+ return chain;
+}
+
+
+/*
+ * targetchain() - append two TARGET chains.
+ *
+ * Inputs:
+ * chain exisitng TARGETS to append to
+ * target new target to append
+ */
+
+TARGETS * targetchain( TARGETS * chain, TARGETS * targets )
+{
+ if ( !targets ) return chain;
+ if ( !chain ) return targets;
+
+ chain->tail->next = targets;
+ chain->tail = targets->tail;
+
+ return chain;
+}
+
+/*
+ * actionlist() - append to an ACTION chain.
+ */
+
+ACTIONS * actionlist( ACTIONS * chain, ACTION * action )
+{
+ ACTIONS * actions = (ACTIONS *)BJAM_MALLOC( sizeof( ACTIONS ) );
+
+ actions->action = action;
+
+ if ( !chain ) chain = actions;
+ else chain->tail->next = actions;
+ chain->tail = actions;
+ actions->next = 0;
+
+ return chain;
+}
+
+static SETTINGS * settings_freelist;
+
+
+/*
+ * addsettings() - add a deferred "set" command to a target.
+ *
+ * Adds a variable setting (varname=list) onto a chain of settings for a
+ * particular target. 'flag' controls the relationship between new and old
+ * values in the same way as in var_set() function (see variable.c). Returns
+ * the head of the settings chain.
+ */
+
+SETTINGS * addsettings( SETTINGS * head, int flag, char * symbol, LIST * value )
+{
+ SETTINGS * v;
+
+ /* Look for previous settings. */
+ for ( v = head; v; v = v->next )
+ if ( !strcmp( v->symbol, symbol ) )
+ break;
+
+ /* If not previously set, alloc a new. */
+ /* If appending, do so. */
+ /* Else free old and set new. */
+ if ( !v )
+ {
+ v = settings_freelist;
+
+ if ( v )
+ settings_freelist = v->next;
+ else
+ v = (SETTINGS *)BJAM_MALLOC( sizeof( *v ) );
+
+ v->symbol = newstr( symbol );
+ v->value = value;
+ v->next = head;
+ v->multiple = 0;
+ head = v;
+ }
+ else if ( flag == VAR_APPEND )
+ {
+ v->value = list_append( v->value, value );
+ }
+ else if ( flag != VAR_DEFAULT )
+ {
+ list_free( v->value );
+ v->value = value;
+ }
+ else
+ list_free( value );
+
+ /* Return (new) head of list. */
+ return head;
+}
+
+
+/*
+ * pushsettings() - set all target specific variables.
+ */
+
+void pushsettings( SETTINGS * v )
+{
+ for ( ; v; v = v->next )
+ v->value = var_swap( v->symbol, v->value );
+}
+
+
+/*
+ * popsettings() - reset target specific variables to their pre-push values.
+ */
+
+void popsettings( SETTINGS * v )
+{
+ pushsettings( v ); /* just swap again */
+}
+
+
+/*
+ * copysettings() - duplicate a settings list, returning the new copy.
+ */
+
+SETTINGS * copysettings( SETTINGS * head )
+{
+ SETTINGS * copy = 0;
+ SETTINGS * v;
+ for ( v = head; v; v = v->next )
+ copy = addsettings( copy, VAR_SET, v->symbol, list_copy( 0, v->value ) );
+ return copy;
+}
+
+
+/*
+ * freetargets() - delete a targets list.
+ */
+
+void freetargets( TARGETS * chain )
+{
+ while ( chain )
+ {
+ TARGETS * n = chain->next;
+ BJAM_FREE( chain );
+ chain = n;
+ }
+}
+
+
+/*
+ * freeactions() - delete an action list.
+ */
+
+void freeactions( ACTIONS * chain )
+{
+ while ( chain )
+ {
+ ACTIONS * n = chain->next;
+ BJAM_FREE( chain );
+ chain = n;
+ }
+}
+
+
+/*
+ * freesettings() - delete a settings list.
+ */
+
+void freesettings( SETTINGS * v )
+{
+ while ( v )
+ {
+ SETTINGS * n = v->next;
+ freestr( v->symbol );
+ list_free( v->value );
+ v->next = settings_freelist;
+ settings_freelist = v;
+ v = n;
+ }
+}
+
+
+static void freetarget( void * xt, void * data )
+{
+ TARGET * t = (TARGET *)xt;
+ if ( t->settings ) freesettings( t->settings );
+ if ( t->depends ) freetargets ( t->depends );
+ if ( t->includes ) freetarget ( t->includes, (void *)0 );
+ if ( t->actions ) freeactions ( t->actions );
+}
+
+
+/*
+ * rules_done() - free RULE and TARGET tables.
+ */
+
+void rules_done()
+{
+ hashenumerate( targethash, freetarget, 0 );
+ hashdone( targethash );
+ while ( settings_freelist )
+ {
+ SETTINGS * n = settings_freelist->next;
+ BJAM_FREE( settings_freelist );
+ settings_freelist = n;
+ }
+}
+
+
+/*
+ * args_new() - make a new reference-counted argument list.
+ */
+
+argument_list * args_new()
+{
+ argument_list * r = (argument_list *)BJAM_MALLOC( sizeof(argument_list) );
+ r->reference_count = 0;
+ lol_init( r->data );
+ return r;
+}
+
+
+/*
+ * args_refer() - add a new reference to the given argument list.
+ */
+
+void args_refer( argument_list * a )
+{
+ ++a->reference_count;
+}
+
+
+/*
+ * args_free() - release a reference to the given argument list.
+ */
+
+void args_free( argument_list * a )
+{
+ if ( --a->reference_count <= 0 )
+ {
+ lol_free( a->data );
+ BJAM_FREE( a );
+ }
+}
+
+
+/*
+ * actions_refer() - add a new reference to the given actions.
+ */
+
+void actions_refer( rule_actions * a )
+{
+ ++a->reference_count;
+}
+
+
+/*
+ * actions_free() - release a reference to the given actions.
+ */
+
+void actions_free( rule_actions * a )
+{
+ if ( --a->reference_count <= 0 )
+ {
+ freestr( a->command );
+ list_free( a->bindlist );
+ BJAM_FREE( a );
+ }
+}
+
+
+/*
+ * set_rule_body() - set the argument list and procedure of the given rule.
+ */
+
+static void set_rule_body( RULE * rule, argument_list * args, PARSE * procedure )
+{
+ if ( args )
+ args_refer( args );
+ if ( rule->arguments )
+ args_free( rule->arguments );
+ rule->arguments = args;
+
+ if ( procedure )
+ parse_refer( procedure );
+ if ( rule->procedure )
+ parse_free( rule->procedure );
+ rule->procedure = procedure;
+}
+
+
+/*
+ * global_name() - given a rule, return the name for a corresponding rule in the
+ * global module.
+ */
+
+static char * global_rule_name( RULE * r )
+{
+ if ( r->module == root_module() )
+ return r->name;
+
+ {
+ char name[4096] = "";
+ strncat( name, r->module->name, sizeof( name ) - 1 );
+ strncat( name, r->name, sizeof( name ) - 1 );
+ return newstr( name);
+ }
+}
+
+
+/*
+ * global_rule() - given a rule, produce the corresponding entry in the global
+ * module.
+ */
+
+static RULE * global_rule( RULE * r )
+{
+ if ( r->module == root_module() )
+ return r;
+
+ {
+ char * name = global_rule_name( r );
+ RULE * result = define_rule( r->module, name, root_module() );
+ freestr( name );
+ return result;
+ }
+}
+
+
+/*
+ * new_rule_body() - make a new rule named rulename in the given module, with
+ * the given argument list and procedure. If exported is true, the rule is
+ * exported to the global module as modulename.rulename.
+ */
+
+RULE * new_rule_body( module_t * m, char * rulename, argument_list * args, PARSE * procedure, int exported )
+{
+ RULE * local = define_rule( m, rulename, m );
+ local->exported = exported;
+ set_rule_body( local, args, procedure );
+
+ /* Mark the procedure with the global rule name, regardless of whether the
+ * rule is exported. That gives us something reasonably identifiable that we
+ * can use, e.g. in profiling output. Only do this once, since this could be
+ * called multiple times with the same procedure.
+ */
+ if ( procedure->rulename == 0 )
+ procedure->rulename = global_rule_name( local );
+
+ return local;
+}
+
+
+static void set_rule_actions( RULE * rule, rule_actions * actions )
+{
+ if ( actions )
+ actions_refer( actions );
+ if ( rule->actions )
+ actions_free( rule->actions );
+ rule->actions = actions;
+}
+
+
+static rule_actions * actions_new( char * command, LIST * bindlist, int flags )
+{
+ rule_actions * result = (rule_actions *)BJAM_MALLOC( sizeof( rule_actions ) );
+ result->command = copystr( command );
+ result->bindlist = bindlist;
+ result->flags = flags;
+ result->reference_count = 0;
+ return result;
+}
+
+
+RULE * new_rule_actions( module_t * m, char * rulename, char * command, LIST * bindlist, int flags )
+{
+ RULE * local = define_rule( m, rulename, m );
+ RULE * global = global_rule( local );
+ set_rule_actions( local, actions_new( command, bindlist, flags ) );
+ set_rule_actions( global, local->actions );
+ return local;
+}
+
+
+/*
+ * Looks for a rule in the specified module, and returns it, if found. First
+ * checks if the rule is present in the module's rule table. Second, if name of
+ * the rule is in the form name1.name2 and name1 is in the list of imported
+ * modules, look in module 'name1' for rule 'name2'.
+ */
+
+RULE * lookup_rule( char * rulename, module_t * m, int local_only )
+{
+ RULE rule;
+ RULE * r = &rule;
+ RULE * result = 0;
+ module_t * original_module = m;
+
+ r->name = rulename;
+
+ if ( m->class_module )
+ m = m->class_module;
+
+ if ( m->rules && hashcheck( m->rules, (HASHDATA * *)&r ) )
+ result = r;
+ else if ( !local_only && m->imported_modules )
+ {
+ /* Try splitting the name into module and rule. */
+ char *p = strchr( r->name, '.' ) ;
+ if ( p )
+ {
+ *p = '\0';
+ /* Now, r->name keeps the module name, and p+1 keeps the rule name.
+ */
+ if ( hashcheck( m->imported_modules, (HASHDATA * *)&r ) )
+ result = lookup_rule( p + 1, bindmodule( rulename ), 1 );
+ *p = '.';
+ }
+ }
+
+ if ( result )
+ {
+ if ( local_only && !result->exported )
+ result = 0;
+ else
+ {
+ /* Lookup started in class module. We have found a rule in class
+ * module, which is marked for execution in that module, or in some
+ * instances. Mark it for execution in the instance where we started
+ * the lookup.
+ */
+ int execute_in_class = ( result->module == m );
+ int execute_in_some_instance = ( result->module->class_module &&
+ ( result->module->class_module == m ) );
+ if ( ( original_module != m ) &&
+ ( execute_in_class || execute_in_some_instance ) )
+ result->module = original_module;
+ }
+ }
+
+ return result;
+}
+
+
+RULE * bindrule( char * rulename, module_t * m )
+{
+ RULE * result = lookup_rule( rulename, m, 0 );
+ if ( !result )
+ result = lookup_rule( rulename, root_module(), 0 );
+ /* We have only one caller, 'evaluate_rule', which will complain about
+ * calling an undefined rule. We could issue the error here, but we do not
+ * have the necessary information, such as frame.
+ */
+ if ( !result )
+ result = enter_rule( rulename, m );
+ return result;
+}
+
+
+RULE * import_rule( RULE * source, module_t * m, char * name )
+{
+ RULE * dest = define_rule( source->module, name, m );
+ set_rule_body( dest, source->arguments, source->procedure );
+ set_rule_actions( dest, source->actions );
+ return dest;
+}
diff --git a/tools/build/v2/engine/rules.h b/tools/build/v2/engine/rules.h
new file mode 100644
index 0000000000..806a1469c0
--- /dev/null
+++ b/tools/build/v2/engine/rules.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef RULES_DWA_20011020_H
+#define RULES_DWA_20011020_H
+
+#include "modules.h"
+#include "jam.h"
+#include "parse.h"
+
+
+/*
+ * rules.h - targets, rules, and related information
+ *
+ * This file describes the structures holding the targets, rules, and
+ * related information accumulated by interpreting the statements
+ * of the jam files.
+ *
+ * The following are defined:
+ *
+ * RULE - a generic jam rule, the product of RULE and ACTIONS.
+ * ACTIONS - a chain of ACTIONs.
+ * ACTION - a RULE instance with targets and sources.
+ * SETTINGS - variables to set when executing a TARGET's ACTIONS.
+ * TARGETS - a chain of TARGETs.
+ * TARGET - an entity (e.g. a file) that can be built.
+ *
+ * 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET.
+ * 04/12/94 (seiwald) - actionlist() now just appends a single action.
+ * 06/01/94 (seiwald) - new 'actions existing' does existing sources
+ * 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
+ * 01/19/95 (seiwald) - split DONTKNOW into CANTFIND/CANTMAKE.
+ * 02/02/95 (seiwald) - new LEAVES modifier on targets.
+ * 02/14/95 (seiwald) - new NOUPDATE modifier on targets.
+ */
+
+typedef struct _rule RULE;
+typedef struct _target TARGET;
+typedef struct _targets TARGETS;
+typedef struct _action ACTION;
+typedef struct _actions ACTIONS;
+typedef struct _settings SETTINGS ;
+
+/* RULE - a generic jam rule, the product of RULE and ACTIONS. */
+
+/* A rule's argument list. */
+struct argument_list
+{
+ int reference_count;
+ LOL data[1];
+};
+
+/* Build actions corresponding to a rule. */
+struct rule_actions
+{
+ int reference_count;
+ char * command; /* command string from ACTIONS */
+ LIST * bindlist;
+ int flags; /* modifiers on ACTIONS */
+
+#define RULE_NEWSRCS 0x01 /* $(>) is updated sources only */
+#define RULE_TOGETHER 0x02 /* combine actions on single target */
+#define RULE_IGNORE 0x04 /* ignore return status of executes */
+#define RULE_QUIETLY 0x08 /* do not mention it unless verbose */
+#define RULE_PIECEMEAL 0x10 /* split exec so each $(>) is small */
+#define RULE_EXISTING 0x20 /* $(>) is pre-exisitng sources only */
+};
+
+typedef struct rule_actions rule_actions;
+typedef struct argument_list argument_list;
+
+struct _rule
+{
+ char * name;
+ PARSE * procedure; /* parse tree from RULE */
+ argument_list * arguments; /* argument checking info, or NULL for unchecked
+ */
+ rule_actions * actions; /* build actions, or NULL for no actions */
+ module_t * module; /* module in which this rule is executed */
+ int exported; /* nonzero if this rule is supposed to appear in
+ * the global module and be automatically
+ * imported into other modules
+ */
+#ifdef HAVE_PYTHON
+ PyObject * python_function;
+#endif
+};
+
+/* ACTIONS - a chain of ACTIONs. */
+struct _actions
+{
+ ACTIONS * next;
+ ACTIONS * tail; /* valid only for head */
+ ACTION * action;
+};
+
+/* ACTION - a RULE instance with targets and sources. */
+struct _action
+{
+ RULE * rule;
+ TARGETS * targets;
+ TARGETS * sources; /* aka $(>) */
+ char running; /* has been started */
+ char status; /* see TARGET status */
+};
+
+/* SETTINGS - variables to set when executing a TARGET's ACTIONS. */
+struct _settings
+{
+ SETTINGS * next;
+ char * symbol; /* symbol name for var_set() */
+ LIST * value; /* symbol value for var_set() */
+ int multiple;
+};
+
+/* TARGETS - a chain of TARGETs. */
+struct _targets
+{
+ TARGETS * next;
+ TARGETS * tail; /* valid only for head */
+ TARGET * target;
+};
+
+/* TARGET - an entity (e.g. a file) that can be built. */
+struct _target
+{
+ char * name;
+ char * boundname; /* if search() relocates target */
+ ACTIONS * actions; /* rules to execute, if any */
+ SETTINGS * settings; /* variables to define */
+
+ short flags; /* status info */
+
+#define T_FLAG_TEMP 0x0001 /* TEMPORARY applied */
+#define T_FLAG_NOCARE 0x0002 /* NOCARE applied */
+#define T_FLAG_NOTFILE 0x0004 /* NOTFILE applied */
+#define T_FLAG_TOUCHED 0x0008 /* ALWAYS applied or -t target */
+#define T_FLAG_LEAVES 0x0010 /* LEAVES applied */
+#define T_FLAG_NOUPDATE 0x0020 /* NOUPDATE applied */
+#define T_FLAG_VISITED 0x0040 /* CWM: Used in debugging */
+
+/* This flag has been added to support a new built-in rule named "RMBAD". It is
+ * used to force removal of outdated targets whose dependencies fail to build.
+ */
+#define T_FLAG_RMOLD 0x0080 /* RMBAD applied */
+
+/* This flag was added to support a new built-in rule named "FAIL_EXPECTED" used
+ * to indicate that the result of running a given action should be inverted,
+ * i.e. ok <=> fail. This is useful for launching certain test runs from a
+ * Jamfile.
+ */
+#define T_FLAG_FAIL_EXPECTED 0x0100 /* FAIL_EXPECTED applied */
+
+#define T_FLAG_INTERNAL 0x0200 /* internal INCLUDES node */
+
+/* Indicates that the target must be a file. This prevents matching non-files,
+ * like directories, when a target is searched.
+ */
+#define T_FLAG_ISFILE 0x0400
+
+#define T_FLAG_PRECIOUS 0x0800
+
+ char binding; /* how target relates to a real file or
+ * folder
+ */
+
+#define T_BIND_UNBOUND 0 /* a disembodied name */
+#define T_BIND_MISSING 1 /* could not find real file */
+#define T_BIND_PARENTS 2 /* using parent's timestamp */
+#define T_BIND_EXISTS 3 /* real file, timestamp valid */
+
+ TARGETS * depends; /* dependencies */
+ TARGETS * dependants; /* the inverse of dependencies */
+ TARGETS * rebuilds; /* targets that should be force-rebuilt
+ * whenever this one is
+ */
+ TARGET * includes; /* internal includes node */
+ TARGET * original_target; /* original_target->includes = this */
+ char rescanned;
+
+ time_t time; /* update time */
+ time_t leaf; /* update time of leaf sources */
+
+ char fate; /* make0()'s diagnosis */
+
+#define T_FATE_INIT 0 /* nothing done to target */
+#define T_FATE_MAKING 1 /* make0(target) on stack */
+
+#define T_FATE_STABLE 2 /* target did not need updating */
+#define T_FATE_NEWER 3 /* target newer than parent */
+
+#define T_FATE_SPOIL 4 /* >= SPOIL rebuilds parents */
+#define T_FATE_ISTMP 4 /* unneeded temp target oddly present */
+
+#define T_FATE_BUILD 5 /* >= BUILD rebuilds target */
+#define T_FATE_TOUCHED 5 /* manually touched with -t */
+#define T_FATE_REBUILD 6
+#define T_FATE_MISSING 7 /* is missing, needs updating */
+#define T_FATE_NEEDTMP 8 /* missing temp that must be rebuild */
+#define T_FATE_OUTDATED 9 /* is out of date, needs updating */
+#define T_FATE_UPDATE 10 /* deps updated, needs updating */
+
+#define T_FATE_BROKEN 11 /* >= BROKEN ruins parents */
+#define T_FATE_CANTFIND 11 /* no rules to make missing target */
+#define T_FATE_CANTMAKE 12 /* can not find dependencies */
+
+ char progress; /* tracks make1() progress */
+
+#define T_MAKE_INIT 0 /* make1(target) not yet called */
+#define T_MAKE_ONSTACK 1 /* make1(target) on stack */
+#define T_MAKE_ACTIVE 2 /* make1(target) in make1b() */
+#define T_MAKE_RUNNING 3 /* make1(target) running commands */
+#define T_MAKE_DONE 4 /* make1(target) done */
+
+#ifdef OPT_SEMAPHORE
+ #define T_MAKE_SEMAPHORE 5 /* Special target type for semaphores */
+#endif
+
+#ifdef OPT_SEMAPHORE
+ TARGET * semaphore; /* used in serialization */
+#endif
+
+ char status; /* exec_cmd() result */
+
+ int asynccnt; /* child deps outstanding */
+ TARGETS * parents; /* used by make1() for completion */
+ char * cmds; /* type-punned command list */
+
+ char * failed;
+};
+
+
+/* Action related functions. */
+ACTIONS * actionlist ( ACTIONS *, ACTION * );
+void freeactions ( ACTIONS * );
+SETTINGS * addsettings ( SETTINGS *, int flag, char * symbol, LIST * value );
+void pushsettings ( SETTINGS * );
+void popsettings ( SETTINGS * );
+SETTINGS * copysettings ( SETTINGS * );
+void freesettings ( SETTINGS * );
+void actions_refer( rule_actions * );
+void actions_free ( rule_actions * );
+
+/* Argument list related functions. */
+void args_free ( argument_list * );
+argument_list * args_new ();
+void args_refer( argument_list * );
+
+/* Rule related functions. */
+RULE * bindrule ( char * rulename, module_t * );
+RULE * import_rule ( RULE * source, module_t *, char * name );
+RULE * new_rule_body ( module_t *, char * rulename, argument_list *, PARSE * procedure, int exprt );
+RULE * new_rule_actions( module_t *, char * rulename, char * command, LIST * bindlist, int flags );
+void rule_free ( RULE * );
+
+/* Target related functions. */
+void bind_explicitly_located_targets();
+TARGET * bindtarget ( char const * target_name );
+TARGET * copytarget ( TARGET const * t );
+void freetargets ( TARGETS * );
+TARGET * search_for_target ( char * name, LIST * search_path );
+TARGETS * targetchain ( TARGETS * chain, TARGETS * );
+TARGETS * targetentry ( TARGETS * chain, TARGET * );
+void target_include ( TARGET * including, TARGET * included );
+TARGETS * targetlist ( TARGETS * chain, LIST * target_names );
+void touch_target ( char * t );
+
+/* Final module cleanup. */
+void rules_done();
+
+#endif
diff --git a/tools/build/v2/engine/scan.c b/tools/build/v2/engine/scan.c
new file mode 100644
index 0000000000..11c44c0e21
--- /dev/null
+++ b/tools/build/v2/engine/scan.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+#include "jam.h"
+#include "lists.h"
+#include "parse.h"
+#include "scan.h"
+#include "jamgram.h"
+#include "jambase.h"
+#include "newstr.h"
+
+/*
+ * scan.c - the jam yacc scanner
+ *
+ * 12/26/93 (seiwald) - bump buf in yylex to 10240 - yuk.
+ * 09/16/94 (seiwald) - check for overflows, unmatched {}'s, etc.
+ * Also handle tokens abutting EOF by remembering
+ * to return EOF now matter how many times yylex()
+ * reinvokes yyline().
+ * 02/11/95 (seiwald) - honor only punctuation keywords if SCAN_PUNCT.
+ * 07/27/95 (seiwald) - Include jamgram.h after scan.h, so that YYSTYPE is
+ * defined before Linux's yacc tries to redefine it.
+ */
+
+struct keyword
+{
+ char * word;
+ int type;
+} keywords[] =
+{
+#include "jamgramtab.h"
+ { 0, 0 }
+};
+
+struct include
+{
+ struct include * next; /* next serial include file */
+ char * string; /* pointer into current line */
+ char * * strings; /* for yyfparse() -- text to parse */
+ FILE * file; /* for yyfparse() -- file being read */
+ char * fname; /* for yyfparse() -- file name */
+ int line; /* line counter for error messages */
+ char buf[ 512 ]; /* for yyfparse() -- line buffer */
+};
+
+static struct include * incp = 0; /* current file; head of chain */
+
+static int scanmode = SCAN_NORMAL;
+static int anyerrors = 0;
+
+
+static char * symdump( YYSTYPE * );
+
+#define BIGGEST_TOKEN 10240 /* no single token can be larger */
+
+
+/*
+ * Set parser mode: normal, string, or keyword.
+ */
+
+void yymode( int n )
+{
+ scanmode = n;
+}
+
+
+void yyerror( char * s )
+{
+ /* We use yylval instead of incp to access the error location information as
+ * the incp pointer will already be reset to 0 in case the error occurred at
+ * EOF.
+ *
+ * The two may differ only if we get an error while reading a lexical token
+ * spanning muliple lines, e.g. a multi-line string literal or action body,
+ * in which case yylval location information will hold the information about
+ * where this token started while incp will hold the information about where
+ * reading it broke.
+ *
+ * TODO: Test the theory about when yylval and incp location information are
+ * the same and when they differ.
+ */
+ printf( "%s:%d: %s at %s\n", yylval.file, yylval.line, s, symdump( &yylval ) );
+ ++anyerrors;
+}
+
+
+int yyanyerrors()
+{
+ return anyerrors != 0;
+}
+
+
+void yyfparse( char * s )
+{
+ struct include * i = (struct include *)BJAM_MALLOC( sizeof( *i ) );
+
+ /* Push this onto the incp chain. */
+ i->string = "";
+ i->strings = 0;
+ i->file = 0;
+ i->fname = copystr( s );
+ i->line = 0;
+ i->next = incp;
+ incp = i;
+
+ /* If the filename is "+", it means use the internal jambase. */
+ if ( !strcmp( s, "+" ) )
+ i->strings = jambase;
+}
+
+
+/*
+ * yyline() - read new line and return first character.
+ *
+ * Fabricates a continuous stream of characters across include files, returning
+ * EOF at the bitter end.
+ */
+
+int yyline()
+{
+ struct include * i = incp;
+
+ if ( !incp )
+ return EOF;
+
+ /* Once we start reading from the input stream, we reset the include
+ * insertion point so that the next include file becomes the head of the
+ * list.
+ */
+
+ /* If there is more data in this line, return it. */
+ if ( *i->string )
+ return *i->string++;
+
+ /* If we are reading from an internal string list, go to the next string. */
+ if ( i->strings )
+ {
+ if ( *i->strings )
+ {
+ ++i->line;
+ i->string = *(i->strings++);
+ return *i->string++;
+ }
+ }
+ else
+ {
+ /* If necessary, open the file. */
+ if ( !i->file )
+ {
+ FILE * f = stdin;
+ if ( strcmp( i->fname, "-" ) && !( f = fopen( i->fname, "r" ) ) )
+ perror( i->fname );
+ i->file = f;
+ }
+
+ /* If there is another line in this file, start it. */
+ if ( i->file && fgets( i->buf, sizeof( i->buf ), i->file ) )
+ {
+ ++i->line;
+ i->string = i->buf;
+ return *i->string++;
+ }
+ }
+
+ /* This include is done. Free it up and return EOF so yyparse() returns to
+ * parse_file().
+ */
+
+ incp = i->next;
+
+ /* Close file, free name. */
+ if ( i->file && ( i->file != stdin ) )
+ fclose( i->file );
+ freestr( i->fname );
+ BJAM_FREE( (char *)i );
+
+ return EOF;
+}
+
+
+/*
+ * yylex() - set yylval to current token; return its type.
+ *
+ * Macros to move things along:
+ *
+ * yychar() - return and advance character; invalid after EOF.
+ * yyprev() - back up one character; invalid before yychar().
+ *
+ * yychar() returns a continuous stream of characters, until it hits the EOF of
+ * the current include file.
+ */
+
+#define yychar() ( *incp->string ? *incp->string++ : yyline() )
+#define yyprev() ( incp->string-- )
+
+int yylex()
+{
+ int c;
+ char buf[ BIGGEST_TOKEN ];
+ char * b = buf;
+
+ if ( !incp )
+ goto eof;
+
+ /* Get first character (whitespace or of token). */
+ c = yychar();
+
+ if ( scanmode == SCAN_STRING )
+ {
+ /* If scanning for a string (action's {}'s), look for the closing brace.
+ * We handle matching braces, if they match.
+ */
+
+ int nest = 1;
+
+ while ( ( c != EOF ) && ( b < buf + sizeof( buf ) ) )
+ {
+ if ( c == '{' )
+ ++nest;
+
+ if ( ( c == '}' ) && !--nest )
+ break;
+
+ *b++ = c;
+
+ c = yychar();
+
+ /* Turn trailing "\r\n" sequences into plain "\n" for Cygwin. */
+ if ( ( c == '\n' ) && ( b[ -1 ] == '\r' ) )
+ --b;
+ }
+
+ /* We ate the ending brace -- regurgitate it. */
+ if ( c != EOF )
+ yyprev();
+
+ /* Check for obvious errors. */
+ if ( b == buf + sizeof( buf ) )
+ {
+ yyerror( "action block too big" );
+ goto eof;
+ }
+
+ if ( nest )
+ {
+ yyerror( "unmatched {} in action block" );
+ goto eof;
+ }
+
+ *b = 0;
+ yylval.type = STRING;
+ yylval.string = newstr( buf );
+ yylval.file = incp->fname;
+ yylval.line = incp->line;
+ }
+ else
+ {
+ char * b = buf;
+ struct keyword * k;
+ int inquote = 0;
+ int notkeyword;
+
+ /* Eat white space. */
+ for ( ;; )
+ {
+ /* Skip past white space. */
+ while ( ( c != EOF ) && isspace( c ) )
+ c = yychar();
+
+ /* Not a comment? */
+ if ( c != '#' )
+ break;
+
+ /* Swallow up comment line. */
+ while ( ( ( c = yychar() ) != EOF ) && ( c != '\n' ) ) ;
+ }
+
+ /* c now points to the first character of a token. */
+ if ( c == EOF )
+ goto eof;
+
+ yylval.file = incp->fname;
+ yylval.line = incp->line;
+
+ /* While scanning the word, disqualify it for (expensive) keyword lookup
+ * when we can: $anything, "anything", \anything
+ */
+ notkeyword = c == '$';
+
+ /* Look for white space to delimit word. "'s get stripped but preserve
+ * white space. \ protects next character.
+ */
+ while
+ (
+ ( c != EOF ) &&
+ ( b < buf + sizeof( buf ) ) &&
+ ( inquote || !isspace( c ) )
+ )
+ {
+ if ( c == '"' )
+ {
+ /* begin or end " */
+ inquote = !inquote;
+ notkeyword = 1;
+ }
+ else if ( c != '\\' )
+ {
+ /* normal char */
+ *b++ = c;
+ }
+ else if ( ( c = yychar() ) != EOF )
+ {
+ /* \c */
+ if (c == 'n')
+ c = '\n';
+ else if (c == 'r')
+ c = '\r';
+ else if (c == 't')
+ c = '\t';
+ *b++ = c;
+ notkeyword = 1;
+ }
+ else
+ {
+ /* \EOF */
+ break;
+ }
+
+ c = yychar();
+ }
+
+ /* Check obvious errors. */
+ if ( b == buf + sizeof( buf ) )
+ {
+ yyerror( "string too big" );
+ goto eof;
+ }
+
+ if ( inquote )
+ {
+ yyerror( "unmatched \" in string" );
+ goto eof;
+ }
+
+ /* We looked ahead a character - back up. */
+ if ( c != EOF )
+ yyprev();
+
+ /* Scan token table. Do not scan if it is obviously not a keyword or if
+ * it is an alphabetic when were looking for punctuation.
+ */
+
+ *b = 0;
+ yylval.type = ARG;
+
+ if ( !notkeyword && !( isalpha( *buf ) && ( scanmode == SCAN_PUNCT ) ) )
+ for ( k = keywords; k->word; ++k )
+ if ( ( *buf == *k->word ) && !strcmp( k->word, buf ) )
+ {
+ yylval.type = k->type;
+ yylval.string = k->word; /* used by symdump */
+ break;
+ }
+
+ if ( yylval.type == ARG )
+ yylval.string = newstr( buf );
+ }
+
+ if ( DEBUG_SCAN )
+ printf( "scan %s\n", symdump( &yylval ) );
+
+ return yylval.type;
+
+eof:
+ /* We do not reset yylval.file & yylval.line here so unexpected EOF error
+ * messages would include correct error location information.
+ */
+ yylval.type = EOF;
+ return yylval.type;
+}
+
+
+static char * symdump( YYSTYPE * s )
+{
+ static char buf[ BIGGEST_TOKEN + 20 ];
+ switch ( s->type )
+ {
+ case EOF : sprintf( buf, "EOF" ); break;
+ case 0 : sprintf( buf, "unknown symbol %s", s->string ); break;
+ case ARG : sprintf( buf, "argument %s" , s->string ); break;
+ case STRING: sprintf( buf, "string \"%s\"" , s->string ); break;
+ default : sprintf( buf, "keyword %s" , s->string ); break;
+ }
+ return buf;
+}
+
+
+/*
+ * Get information about the current file and line, for those epsilon
+ * transitions that produce a parse.
+ */
+
+void yyinput_stream( char * * name, int * line )
+{
+ if ( incp )
+ {
+ *name = incp->fname;
+ *line = incp->line;
+ }
+ else
+ {
+ *name = "(builtin)";
+ *line = -1;
+ }
+}
diff --git a/tools/build/v2/engine/scan.h b/tools/build/v2/engine/scan.h
new file mode 100644
index 0000000000..3fad1c24cf
--- /dev/null
+++ b/tools/build/v2/engine/scan.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * scan.h - the jam yacc scanner
+ *
+ * External functions:
+ *
+ * yyerror( char *s ) - print a parsing error message.
+ * yyfparse( char *s ) - scan include file s.
+ * yylex() - parse the next token, returning its type.
+ * yymode() - adjust lexicon of scanner.
+ * yyparse() - declaration for yacc parser.
+ * yyanyerrors() - indicate if any parsing errors occured.
+ *
+ * The yymode() function is for the parser to adjust the lexicon of the scanner.
+ * Aside from normal keyword scanning, there is a mode to handle action strings
+ * (look only for the closing }) and a mode to ignore most keywords when looking
+ * for a punctuation keyword. This allows non-punctuation keywords to be used in
+ * lists without quoting.
+ */
+
+/*
+ * YYSTYPE - value of a lexical token
+ */
+
+#define YYSTYPE YYSYMBOL
+
+typedef struct _YYSTYPE
+{
+ int type;
+ char * string;
+ PARSE * parse;
+ LIST * list;
+ int number;
+ char * file;
+ int line;
+} YYSTYPE;
+
+extern YYSTYPE yylval;
+
+void yymode( int n );
+void yyerror( char * s );
+int yyanyerrors();
+void yyfparse( char * s );
+int yyline();
+int yylex();
+int yyparse();
+void yyinput_stream( char * * name, int * line );
+
+# define SCAN_NORMAL 0 /* normal parsing */
+# define SCAN_STRING 1 /* look only for matching } */
+# define SCAN_PUNCT 2 /* only punctuation keywords */
diff --git a/tools/build/v2/engine/search.c b/tools/build/v2/engine/search.c
new file mode 100644
index 0000000000..6c23d97a14
--- /dev/null
+++ b/tools/build/v2/engine/search.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include "jam.h"
+#include "lists.h"
+#include "search.h"
+#include "timestamp.h"
+#include "pathsys.h"
+#include "variable.h"
+#include "newstr.h"
+#include "compile.h"
+#include "strings.h"
+#include "hash.h"
+#include "filesys.h"
+#include <string.h>
+
+
+typedef struct _binding
+{
+ char * binding;
+ char * target;
+} BINDING;
+
+static struct hash *explicit_bindings = 0;
+
+
+void call_bind_rule
+(
+ char * target_,
+ char * boundname_
+)
+{
+ LIST * bind_rule = var_get( "BINDRULE" );
+ if ( bind_rule )
+ {
+ /* No guarantee that the target is an allocated string, so be on the
+ * safe side.
+ */
+ char * target = copystr( target_ );
+
+ /* Likewise, do not rely on implementation details of newstr.c: allocate
+ * a copy of boundname.
+ */
+ char * boundname = copystr( boundname_ );
+ if ( boundname && target )
+ {
+ /* Prepare the argument list. */
+ FRAME frame[1];
+ frame_init( frame );
+
+ /* First argument is the target name. */
+ lol_add( frame->args, list_new( L0, target ) );
+
+ lol_add( frame->args, list_new( L0, boundname ) );
+ if ( lol_get( frame->args, 1 ) )
+ evaluate_rule( bind_rule->string, frame );
+
+ /* Clean up */
+ frame_free( frame );
+ }
+ else
+ {
+ if ( boundname )
+ freestr( boundname );
+ if ( target )
+ freestr( target );
+ }
+ }
+}
+
+/*
+ * search.c - find a target along $(SEARCH) or $(LOCATE)
+ * First, check if LOCATE is set. If so, use it to determine
+ * the location of target and return, regardless of whether anything
+ * exists on that location.
+ *
+ * Second, examine all directories in SEARCH. If there's file already
+ * or there's another target with the same name which was placed
+ * to this location via LOCATE setting, stop and return the location.
+ * In case of previous target, return it's name via the third argument.
+ *
+ * This bevahiour allow to handle dependency on generated files. If
+ * caller does not expect that target is generated, 0 can be passed as
+ * the third argument.
+ */
+
+char *
+search(
+ char *target,
+ time_t *time,
+ char **another_target,
+ int file
+)
+{
+ PATHNAME f[1];
+ LIST *varlist;
+ string buf[1];
+ int found = 0;
+ /* Will be set to 1 if target location is specified via LOCATE. */
+ int explicitly_located = 0;
+ char *boundname = 0;
+
+ if ( another_target )
+ *another_target = 0;
+
+ if (! explicit_bindings )
+ explicit_bindings = hashinit( sizeof(BINDING),
+ "explicitly specified locations");
+
+ string_new( buf );
+ /* Parse the filename */
+
+ path_parse( target, f );
+
+ f->f_grist.ptr = 0;
+ f->f_grist.len = 0;
+
+ if ( ( varlist = var_get( "LOCATE" ) ) )
+ {
+ f->f_root.ptr = varlist->string;
+ f->f_root.len = strlen( varlist->string );
+
+ path_build( f, buf, 1 );
+
+ if ( DEBUG_SEARCH )
+ printf( "locate %s: %s\n", target, buf->value );
+
+ explicitly_located = 1;
+
+ timestamp( buf->value, time );
+ found = 1;
+ }
+ else if ( ( varlist = var_get( "SEARCH" ) ) )
+ {
+ while ( varlist )
+ {
+ BINDING b, *ba = &b;
+ file_info_t *ff;
+
+ f->f_root.ptr = varlist->string;
+ f->f_root.len = strlen( varlist->string );
+
+ string_truncate( buf, 0 );
+ path_build( f, buf, 1 );
+
+ if ( DEBUG_SEARCH )
+ printf( "search %s: %s\n", target, buf->value );
+
+ ff = file_query(buf->value);
+ timestamp( buf->value, time );
+
+ b.binding = buf->value;
+
+ if ( hashcheck( explicit_bindings, (HASHDATA**)&ba ) )
+ {
+ if ( DEBUG_SEARCH )
+ printf(" search %s: found explicitly located target %s\n",
+ target, ba->target);
+ if ( another_target )
+ *another_target = ba->target;
+ found = 1;
+ break;
+ }
+ else if ( ff && ff->time )
+ {
+ if ( !file || ff->is_file )
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ varlist = list_next( varlist );
+ }
+ }
+
+ if ( !found )
+ {
+ /* Look for the obvious */
+ /* This is a questionable move. Should we look in the */
+ /* obvious place if SEARCH is set? */
+
+ f->f_root.ptr = 0;
+ f->f_root.len = 0;
+
+ string_truncate( buf, 0 );
+ path_build( f, buf, 1 );
+
+ if ( DEBUG_SEARCH )
+ printf( "search %s: %s\n", target, buf->value );
+
+ timestamp( buf->value, time );
+ }
+
+ boundname = newstr( buf->value );
+ string_free( buf );
+
+ if ( explicitly_located )
+ {
+ BINDING b;
+ BINDING * ba = &b;
+ b.binding = boundname;
+ b.target = target;
+ /* CONSIDER: we probably should issue a warning is another file
+ is explicitly bound to the same location. This might break
+ compatibility, though. */
+ hashenter( explicit_bindings, (HASHDATA * *)&ba );
+ }
+
+ /* prepare a call to BINDRULE if the variable is set */
+ call_bind_rule( target, boundname );
+
+ return boundname;
+}
diff --git a/tools/build/v2/engine/search.h b/tools/build/v2/engine/search.h
new file mode 100644
index 0000000000..c364cac03b
--- /dev/null
+++ b/tools/build/v2/engine/search.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * search.h - find a target along $(SEARCH) or $(LOCATE)
+ */
+
+char *search( char *target, time_t *time, char **another_target, int file );
diff --git a/tools/build/v2/engine/strings.c b/tools/build/v2/engine/strings.c
new file mode 100644
index 0000000000..8956123779
--- /dev/null
+++ b/tools/build/v2/engine/strings.c
@@ -0,0 +1,201 @@
+/* Copyright David Abrahams 2004. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+#include "jam.h"
+#include "strings.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+
+
+#ifndef NDEBUG
+# define JAM_STRING_MAGIC ((char)0xcf)
+# define JAM_STRING_MAGIC_SIZE 4
+static void assert_invariants( string* self )
+{
+ int i;
+
+ if ( self->value == 0 )
+ {
+ assert( self->size == 0 );
+ assert( self->capacity == 0 );
+ assert( self->opt[0] == 0 );
+ return;
+ }
+
+ assert( self->size < self->capacity );
+ assert( ( self->capacity <= sizeof(self->opt) ) == ( self->value == self->opt ) );
+ assert( strlen( self->value ) == self->size );
+
+ for (i = 0; i < 4; ++i)
+ {
+ assert( self->magic[i] == JAM_STRING_MAGIC );
+ assert( self->value[self->capacity + i] == JAM_STRING_MAGIC );
+ }
+}
+#else
+# define JAM_STRING_MAGIC_SIZE 0
+# define assert_invariants(x) do {} while (0)
+#endif
+
+void string_new( string* s )
+{
+ s->value = s->opt;
+ s->size = 0;
+ s->capacity = sizeof(s->opt);
+ s->opt[0] = 0;
+#ifndef NDEBUG
+ memset(s->magic, JAM_STRING_MAGIC, sizeof(s->magic));
+#endif
+ assert_invariants( s );
+}
+
+void string_free( string* s )
+{
+ assert_invariants( s );
+ if ( s->value != s->opt )
+ BJAM_FREE( s->value );
+ string_new( s );
+}
+
+static void string_reserve_internal( string* self, size_t capacity )
+{
+ if ( self->value == self->opt )
+ {
+ self->value = (char*)BJAM_MALLOC_ATOMIC( capacity + JAM_STRING_MAGIC_SIZE );
+ self->value[0] = 0;
+ strncat( self->value, self->opt, sizeof(self->opt) );
+ assert( strlen( self->value ) <= self->capacity ); /* This is a regression test */
+ }
+ else
+ {
+ self->value = (char*)BJAM_REALLOC( self->value, capacity + JAM_STRING_MAGIC_SIZE );
+ }
+#ifndef NDEBUG
+ memcpy( self->value + capacity, self->magic, JAM_STRING_MAGIC_SIZE );
+#endif
+ self->capacity = capacity;
+}
+
+void string_reserve( string* self, size_t capacity )
+{
+ assert_invariants( self );
+ if ( capacity <= self->capacity )
+ return;
+ string_reserve_internal( self, capacity );
+ assert_invariants( self );
+}
+
+static void extend_full( string* self, char const* start, char const* finish )
+{
+ size_t new_size = self->capacity + ( finish - start );
+ size_t new_capacity = self->capacity;
+ size_t old_size = self->capacity;
+ while ( new_capacity < new_size + 1)
+ new_capacity <<= 1;
+ string_reserve_internal( self, new_capacity );
+ memcpy( self->value + old_size, start, new_size - old_size );
+ self->value[new_size] = 0;
+ self->size = new_size;
+}
+
+void string_append( string* self, char const* rhs )
+{
+ char* p = self->value + self->size;
+ char* end = self->value + self->capacity;
+ assert_invariants( self );
+
+ while ( *rhs && p != end)
+ *p++ = *rhs++;
+
+ if ( p != end )
+ {
+ *p = 0;
+ self->size = p - self->value;
+ }
+ else
+ {
+ extend_full( self, rhs, rhs + strlen(rhs) );
+ }
+ assert_invariants( self );
+}
+
+void string_append_range( string* self, char const* start, char const* finish )
+{
+ char* p = self->value + self->size;
+ char* end = self->value + self->capacity;
+ assert_invariants( self );
+
+ while ( p != end && start != finish )
+ *p++ = *start++;
+
+ if ( p != end )
+ {
+ *p = 0;
+ self->size = p - self->value;
+ }
+ else
+ {
+ extend_full( self, start, finish );
+ }
+ assert_invariants( self );
+}
+
+void string_copy( string* s, char const* rhs )
+{
+ string_new( s );
+ string_append( s, rhs );
+}
+
+void string_truncate( string* self, size_t n )
+{
+ assert_invariants( self );
+ assert( n <= self->capacity );
+ self->value[self->size = n] = 0;
+ assert_invariants( self );
+}
+
+void string_pop_back( string* self )
+{
+ string_truncate( self, self->size - 1 );
+}
+
+void string_push_back( string* self, char x )
+{
+ string_append_range( self, &x, &x + 1 );
+}
+
+char string_back( string* self )
+{
+ assert_invariants( self );
+ return self->value[self->size - 1];
+}
+
+#ifndef NDEBUG
+void string_unit_test()
+{
+ string s[1];
+ int i;
+ char buffer[sizeof(s->opt) * 2 + 2];
+ int limit = sizeof(buffer) > 254 ? 254 : sizeof(buffer);
+
+ string_new(s);
+
+ for (i = 0; i < limit; ++i)
+ {
+ string_push_back( s, (char)(i + 1) );
+ };
+
+ for (i = 0; i < limit; ++i)
+ {
+ assert( i < s->size );
+ assert( s->value[i] == (char)(i + 1));
+ }
+
+ string_free(s);
+
+}
+#endif
+
diff --git a/tools/build/v2/engine/strings.h b/tools/build/v2/engine/strings.h
new file mode 100644
index 0000000000..33c77bd7f8
--- /dev/null
+++ b/tools/build/v2/engine/strings.h
@@ -0,0 +1,34 @@
+#ifndef STRINGS_DWA20011024_H
+# define STRINGS_DWA20011024_H
+
+/* Copyright David Abrahams 2004. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
+# include <stddef.h>
+
+typedef struct string
+{
+ char* value;
+ unsigned long size;
+ unsigned long capacity;
+ char opt[32];
+#ifndef NDEBUG
+ char magic[4];
+#endif
+} string;
+
+void string_new( string* );
+void string_copy( string*, char const* );
+void string_free( string* );
+void string_append( string*, char const* );
+void string_append_range( string*, char const*, char const* );
+void string_push_back( string* s, char x );
+void string_reserve( string*, size_t );
+void string_truncate( string*, size_t );
+void string_pop_back( string* );
+char string_back( string* );
+void string_unit_test();
+
+#endif
+
diff --git a/tools/build/v2/engine/subst.c b/tools/build/v2/engine/subst.c
new file mode 100644
index 0000000000..75524ecc12
--- /dev/null
+++ b/tools/build/v2/engine/subst.c
@@ -0,0 +1,94 @@
+#include <stddef.h>
+#include "jam.h"
+#include "regexp.h"
+#include "hash.h"
+
+#include "newstr.h"
+#include "lists.h"
+#include "parse.h"
+#include "compile.h"
+#include "frames.h"
+
+struct regex_entry
+{
+ const char* pattern;
+ regexp* regex;
+};
+typedef struct regex_entry regex_entry;
+
+static struct hash* regex_hash;
+
+regexp* regex_compile( const char* pattern )
+{
+ regex_entry entry, *e = &entry;
+ entry.pattern = pattern;
+
+ if ( !regex_hash )
+ regex_hash = hashinit(sizeof(regex_entry), "regex");
+
+ if ( hashenter( regex_hash, (HASHDATA **)&e ) )
+ e->regex = regcomp( (char*)pattern );
+
+ return e->regex;
+}
+
+LIST*
+builtin_subst(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST* result = L0;
+ LIST* arg1 = lol_get( frame->args, 0 );
+
+ if ( arg1 && list_next(arg1) && list_next(list_next(arg1)) )
+ {
+
+ const char* source = arg1->string;
+ const char* pattern = list_next(arg1)->string;
+ regexp* repat = regex_compile( pattern );
+
+ if ( regexec( repat, (char*)source) )
+ {
+ LIST* subst = list_next(arg1);
+
+ while ((subst = list_next(subst)) != L0)
+ {
+# define BUFLEN 4096
+ char buf[BUFLEN + 1];
+ const char* in = subst->string;
+ char* out = buf;
+
+ for ( in = subst->string; *in && out < buf + BUFLEN; ++in )
+ {
+ if ( *in == '\\' || *in == '$' )
+ {
+ ++in;
+ if ( *in == 0 )
+ {
+ break;
+ }
+ else if ( *in >= '0' && *in <= '9' )
+ {
+ unsigned n = *in - '0';
+ const size_t srclen = repat->endp[n] - repat->startp[n];
+ const size_t remaining = buf + BUFLEN - out;
+ const size_t len = srclen < remaining ? srclen : remaining;
+ memcpy( out, repat->startp[n], len );
+ out += len;
+ continue;
+ }
+ /* fall through and copy the next character */
+ }
+ *out++ = *in;
+ }
+ *out = 0;
+
+ result = list_new( result, newstr( buf ) );
+#undef BUFLEN
+ }
+ }
+ }
+
+ return result;
+}
+
diff --git a/tools/build/v2/engine/timestamp.c b/tools/build/v2/engine/timestamp.c
new file mode 100644
index 0000000000..8a59c8c0e0
--- /dev/null
+++ b/tools/build/v2/engine/timestamp.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+
+# include "hash.h"
+# include "filesys.h"
+# include "pathsys.h"
+# include "timestamp.h"
+# include "newstr.h"
+# include "strings.h"
+
+/*
+ * timestamp.c - get the timestamp of a file or archive member
+ *
+ * 09/22/00 (seiwald) - downshift names on OS2, too
+ */
+
+/*
+ * BINDING - all known files
+ */
+
+typedef struct _binding BINDING;
+
+struct _binding {
+ char *name;
+ short flags;
+
+# define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
+
+ short progress;
+
+# define BIND_INIT 0 /* never seen */
+# define BIND_NOENTRY 1 /* timestamp requested but file never found */
+# define BIND_SPOTTED 2 /* file found but not timed yet */
+# define BIND_MISSING 3 /* file found but can't get timestamp */
+# define BIND_FOUND 4 /* file found and time stamped */
+
+ time_t time; /* update time - 0 if not exist */
+};
+
+static struct hash * bindhash = 0;
+static void time_enter( void *, char *, int, time_t );
+
+static char * time_progress[] =
+{
+ "INIT",
+ "NOENTRY",
+ "SPOTTED",
+ "MISSING",
+ "FOUND"
+};
+
+
+/*
+ * timestamp() - return timestamp on a file, if present.
+ */
+
+void timestamp( char * target, time_t * time )
+{
+ PROFILE_ENTER( timestamp );
+
+ PATHNAME f1;
+ PATHNAME f2;
+ BINDING binding;
+ BINDING * b = &binding;
+ string buf[ 1 ];
+#ifdef DOWNSHIFT_PATHS
+ string path;
+ char * p;
+#endif
+
+#ifdef DOWNSHIFT_PATHS
+ string_copy( &path, target );
+ p = path.value;
+
+ do
+ {
+ *p = tolower( *p );
+#ifdef NT
+ /* On NT, we must use backslashes or the file will not be found. */
+ if ( *p == '/' )
+ *p = PATH_DELIM;
+#endif
+ }
+ while ( *p++ );
+
+ target = path.value;
+#endif /* #ifdef DOWNSHIFT_PATHS */
+ string_new( buf );
+
+ if ( !bindhash )
+ bindhash = hashinit( sizeof( BINDING ), "bindings" );
+
+ /* Quick path - is it there? */
+ b->name = target;
+ b->time = b->flags = 0;
+ b->progress = BIND_INIT;
+
+ if ( hashenter( bindhash, (HASHDATA * *)&b ) )
+ b->name = newstr( target ); /* never freed */
+
+ if ( b->progress != BIND_INIT )
+ goto afterscanning;
+
+ b->progress = BIND_NOENTRY;
+
+ /* Not found - have to scan for it. */
+ path_parse( target, &f1 );
+
+ /* Scan directory if not already done so. */
+ {
+ BINDING binding;
+ BINDING * b = &binding;
+
+ f2 = f1;
+ f2.f_grist.len = 0;
+ path_parent( &f2 );
+ path_build( &f2, buf, 0 );
+
+ b->name = buf->value;
+ b->time = b->flags = 0;
+ b->progress = BIND_INIT;
+
+ if ( hashenter( bindhash, (HASHDATA * *)&b ) )
+ b->name = newstr( buf->value ); /* never freed */
+
+ if ( !( b->flags & BIND_SCANNED ) )
+ {
+ file_dirscan( buf->value, time_enter, bindhash );
+ b->flags |= BIND_SCANNED;
+ }
+ }
+
+ /* Scan archive if not already done so. */
+ if ( f1.f_member.len )
+ {
+ BINDING binding;
+ BINDING * b = &binding;
+
+ f2 = f1;
+ f2.f_grist.len = 0;
+ f2.f_member.len = 0;
+ string_truncate( buf, 0 );
+ path_build( &f2, buf, 0 );
+
+ b->name = buf->value;
+ b->time = b->flags = 0;
+ b->progress = BIND_INIT;
+
+ if ( hashenter( bindhash, (HASHDATA * *)&b ) )
+ b->name = newstr( buf->value ); /* never freed */
+
+ if ( !( b->flags & BIND_SCANNED ) )
+ {
+ file_archscan( buf->value, time_enter, bindhash );
+ b->flags |= BIND_SCANNED;
+ }
+ }
+
+ afterscanning:
+
+ if ( b->progress == BIND_SPOTTED )
+ {
+ b->progress = file_time( b->name, &b->time ) < 0
+ ? BIND_MISSING
+ : BIND_FOUND;
+ }
+
+ *time = b->progress == BIND_FOUND ? b->time : 0;
+ string_free( buf );
+#ifdef DOWNSHIFT_PATHS
+ string_free( &path );
+#endif
+
+ PROFILE_EXIT( timestamp );
+}
+
+
+static void time_enter( void * closure, char * target, int found, time_t time )
+{
+ BINDING binding;
+ BINDING * b = &binding;
+ struct hash * bindhash = (struct hash *)closure;
+
+#ifdef DOWNSHIFT_PATHS
+ char path[ MAXJPATH ];
+ char * p = path;
+
+ do *p++ = tolower( *target );
+ while ( *target++ );
+
+ target = path;
+#endif
+
+ b->name = target;
+ b->flags = 0;
+
+ if ( hashenter( bindhash, (HASHDATA * *)&b ) )
+ b->name = newstr( target ); /* never freed */
+
+ b->time = time;
+ b->progress = found ? BIND_FOUND : BIND_SPOTTED;
+
+ if ( DEBUG_BINDSCAN )
+ printf( "time ( %s ) : %s\n", target, time_progress[ b->progress ] );
+}
+
+
+/*
+ * stamps_done() - free timestamp tables.
+ */
+
+void stamps_done()
+{
+ hashdone( bindhash );
+}
diff --git a/tools/build/v2/engine/timestamp.h b/tools/build/v2/engine/timestamp.h
new file mode 100644
index 0000000000..f575276393
--- /dev/null
+++ b/tools/build/v2/engine/timestamp.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * timestamp.h - get the timestamp of a file or archive member
+ */
+
+void timestamp( char * target, time_t * time );
+void stamps_done();
diff --git a/tools/build/v2/engine/variable.c b/tools/build/v2/engine/variable.c
new file mode 100644
index 0000000000..795f345846
--- /dev/null
+++ b/tools/build/v2/engine/variable.c
@@ -0,0 +1,631 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Copyright 2005 Reece H. Dunn.
+ * Copyright 2005 Rene Rivera.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include "jam.h"
+#include "lists.h"
+#include "parse.h"
+#include "variable.h"
+#include "expand.h"
+#include "hash.h"
+#include "filesys.h"
+#include "newstr.h"
+#include "strings.h"
+#include "pathsys.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * variable.c - handle Jam multi-element variables.
+ *
+ * External routines:
+ *
+ * var_defines() - load a bunch of variable=value settings.
+ * var_string() - expand a string with variables in it.
+ * var_get() - get value of a user defined symbol.
+ * var_set() - set a variable in jam's user defined symbol table.
+ * var_swap() - swap a variable's value with the given one.
+ * var_done() - free variable tables.
+ *
+ * Internal routines:
+ *
+ * var_enter() - make new var symbol table entry, returning var ptr.
+ * var_dump() - dump a variable to stdout.
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 08/23/94 (seiwald) - Support for '+=' (append to variable)
+ * 01/22/95 (seiwald) - split environment variables at blanks or :'s
+ * 05/10/95 (seiwald) - split path variables at SPLITPATH (not :)
+ * 09/11/00 (seiwald) - defunct var_list() removed
+ */
+
+static struct hash *varhash = 0;
+
+/*
+ * VARIABLE - a user defined multi-value variable
+ */
+
+typedef struct _variable VARIABLE ;
+
+struct _variable
+{
+ char * symbol;
+ LIST * value;
+};
+
+static VARIABLE * var_enter( char * symbol );
+static void var_dump( char * symbol, LIST * value, char * what );
+
+
+/*
+ * var_hash_swap() - swap all variable settings with those passed
+ *
+ * Used to implement separate settings spaces for modules
+ */
+
+void var_hash_swap( struct hash * * new_vars )
+{
+ struct hash * old = varhash;
+ varhash = *new_vars;
+ *new_vars = old;
+}
+
+
+/*
+ * var_defines() - load a bunch of variable=value settings
+ *
+ * If preprocess is false, take the value verbatim.
+ *
+ * Otherwise, if the variable value is enclosed in quotes, strip the
+ * quotes.
+ *
+ * Otherwise, if variable name ends in PATH, split value at :'s.
+ *
+ * Otherwise, split the value at blanks.
+ */
+
+void var_defines( char * const * e, int preprocess )
+{
+ string buf[1];
+
+ string_new( buf );
+
+ for ( ; *e; ++e )
+ {
+ char * val;
+
+# ifdef OS_MAC
+ /* On the mac (MPW), the var=val is actually var\0val */
+ /* Think different. */
+
+ if ( ( val = strchr( *e, '=' ) ) || ( val = *e + strlen( *e ) ) )
+# else
+ if ( ( val = strchr( *e, '=' ) ) )
+# endif
+ {
+ LIST * l = L0;
+ char * pp;
+ char * p;
+# ifdef OPT_NO_EXTERNAL_VARIABLE_SPLIT
+ char split = '\0';
+# else
+ # ifdef OS_MAC
+ char split = ',';
+ # else
+ char split = ' ';
+ # endif
+# endif
+ size_t len = strlen( val + 1 );
+
+ int quoted = ( val[1] == '"' ) && ( val[len] == '"' ) &&
+ ( len > 1 );
+
+ if ( quoted && preprocess )
+ {
+ string_append_range( buf, val + 2, val + len );
+ l = list_new( l, newstr( buf->value ) );
+ string_truncate( buf, 0 );
+ }
+ else
+ {
+ /* Split *PATH at :'s, not spaces. */
+ if ( val - 4 >= *e )
+ {
+ if ( !strncmp( val - 4, "PATH", 4 ) ||
+ !strncmp( val - 4, "Path", 4 ) ||
+ !strncmp( val - 4, "path", 4 ) )
+ split = SPLITPATH;
+ }
+
+ /* Do the split. */
+ for
+ (
+ pp = val + 1;
+ preprocess && ( ( p = strchr( pp, split ) ) != 0 );
+ pp = p + 1
+ )
+ {
+ string_append_range( buf, pp, p );
+ l = list_new( l, newstr( buf->value ) );
+ string_truncate( buf, 0 );
+ }
+
+ l = list_new( l, newstr( pp ) );
+ }
+
+ /* Get name. */
+ string_append_range( buf, *e, val );
+ var_set( buf->value, l, VAR_SET );
+ string_truncate( buf, 0 );
+ }
+ }
+ string_free( buf );
+}
+
+
+/*
+ * var_string() - expand a string with variables in it
+ *
+ * Copies in to out; doesn't modify targets & sources.
+ */
+
+int var_string( char * in, char * out, int outsize, LOL * lol )
+{
+ char * out0 = out;
+ char * oute = out + outsize - 1;
+
+ while ( *in )
+ {
+ char * lastword;
+ int dollar = 0;
+
+ /* Copy white space. */
+ while ( isspace( *in ) )
+ {
+ if ( out >= oute )
+ return -1;
+ *out++ = *in++;
+ }
+
+ lastword = out;
+
+ /* Copy non-white space, watching for variables. */
+ while ( *in && !isspace( *in ) )
+ {
+ if ( out >= oute )
+ return -1;
+
+ if ( ( in[ 0 ] == '$' ) && ( in[ 1 ] == '(' ) )
+ {
+ ++dollar;
+ *out++ = *in++;
+ }
+ #ifdef OPT_AT_FILES
+ else if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) )
+ {
+ int depth = 1;
+ char * ine = in + 2;
+ char * split = 0;
+
+ /* Scan the content of the response file @() section. */
+ while ( *ine && ( depth > 0 ) )
+ {
+ switch ( *ine )
+ {
+ case '(': ++depth; break;
+ case ')': --depth; break;
+ case ':':
+ if ( ( depth == 1 ) && ( ine[ 1 ] == 'E' ) && ( ine[ 2 ] == '=' ) )
+ split = ine;
+ break;
+ }
+ ++ine;
+ }
+
+ if ( !split )
+ {
+ /* the @() reference doesn't match the @(foo:E=bar) format.
+ hence we leave it alone by copying directly to output. */
+ int l = 0;
+ if ( out + 2 >= oute ) return -1;
+ *( out++ ) = '@';
+ *( out++ ) = '(';
+ l = var_string( in + 2, out, oute - out, lol );
+ if ( l < 0 ) return -1;
+ out += l;
+ if ( out + 1 >= oute ) return -1;
+ *( out++ ) = ')';
+ }
+ else if ( depth == 0 )
+ {
+ string file_name_v;
+ int file_name_l = 0;
+ const char * file_name_s = 0;
+
+ /* Expand the temporary file name var inline. */
+ #if 0
+ string_copy( &file_name_v, "$(" );
+ string_append_range( &file_name_v, in + 2, split );
+ string_push_back( &file_name_v, ')' );
+ #else
+ string_new( &file_name_v );
+ string_append_range( &file_name_v, in + 2, split );
+ #endif
+ file_name_l = var_string( file_name_v.value, out, oute - out + 1, lol );
+ string_free( &file_name_v );
+ if ( file_name_l < 0 ) return -1;
+ file_name_s = out;
+
+ /* For stdout/stderr we will create a temp file and generate
+ * a command that outputs the content as needed.
+ */
+ if ( ( strcmp( "STDOUT", out ) == 0 ) ||
+ ( strcmp( "STDERR", out ) == 0 ) )
+ {
+ int err_redir = strcmp( "STDERR", out ) == 0;
+ out[ 0 ] = '\0';
+ file_name_s = path_tmpfile();
+ file_name_l = strlen(file_name_s);
+ #ifdef OS_NT
+ if ( ( out + 7 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute )
+ return -1;
+ sprintf( out,"type \"%s\"%s", file_name_s,
+ err_redir ? " 1>&2" : "" );
+ #else
+ if ( ( out + 6 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute )
+ return -1;
+ sprintf( out,"cat \"%s\"%s", file_name_s,
+ err_redir ? " 1>&2" : "" );
+ #endif
+ /* We also make sure that the temp files created by this
+ * get nuked eventually.
+ */
+ file_remove_atexit( file_name_s );
+ }
+
+ /* Expand the file value into the file reference. */
+ var_string_to_file( split + 3, ine - split - 4, file_name_s,
+ lol );
+
+ /* Continue on with the expansion. */
+ out += strlen( out );
+ }
+
+ /* And continue with the parsing just past the @() reference. */
+ in = ine;
+ }
+ #endif
+ else
+ {
+ *out++ = *in++;
+ }
+ }
+
+ /* Add zero to 'out' so that 'lastword' is correctly zero-terminated. */
+ if ( out >= oute )
+ return -1;
+ /* Do not increment, intentionally. */
+ *out = '\0';
+
+ /* If a variable encountered, expand it and and embed the
+ * space-separated members of the list in the output.
+ */
+ if ( dollar )
+ {
+ LIST * l = var_expand( L0, lastword, out, lol, 0 );
+
+ out = lastword;
+
+ while ( l )
+ {
+ int so = strlen( l->string );
+
+ if ( out + so >= oute )
+ return -1;
+
+ strcpy( out, l->string );
+ out += so;
+ l = list_next( l );
+ if ( l ) *out++ = ' ';
+ }
+
+ list_free( l );
+ }
+ }
+
+ if ( out >= oute )
+ return -1;
+
+ *out++ = '\0';
+
+ return out - out0;
+}
+
+
+void var_string_to_file( const char * in, int insize, const char * out, LOL * lol )
+{
+ char const * ine = in + insize;
+ FILE * out_file = 0;
+ int out_debug = DEBUG_EXEC ? 1 : 0;
+ if ( globs.noexec )
+ {
+ /* out_debug = 1; */
+ }
+ else if ( strcmp( out, "STDOUT" ) == 0 )
+ {
+ out_file = stdout;
+ }
+ else if ( strcmp( out, "STDERR" ) == 0 )
+ {
+ out_file = stderr;
+ }
+ else
+ {
+ /* Handle "path to file" filenames. */
+ string out_name;
+ if ( ( out[ 0 ] == '"' ) && ( out[ strlen( out ) - 1 ] == '"' ) )
+ {
+ string_copy( &out_name, out + 1 );
+ string_truncate( &out_name, out_name.size - 1 );
+ }
+ else
+ {
+ string_copy( &out_name,out );
+ }
+ out_file = fopen( out_name.value, "w" );
+ if ( !out_file )
+ {
+ printf( "failed to write output file '%s'!\n", out_name.value );
+ exit( EXITBAD );
+ }
+ string_free( &out_name );
+ }
+
+ if ( out_debug ) printf( "\nfile %s\n", out );
+
+ while ( *in && ( in < ine ) )
+ {
+ int dollar = 0;
+ const char * output_0 = in;
+ const char * output_1 = in;
+
+ /* Copy white space. */
+ while ( ( output_1 < ine ) && isspace( *output_1 ) )
+ ++output_1;
+
+ if ( output_0 < output_1 )
+ {
+ if ( out_file ) fwrite( output_0, output_1 - output_0, 1, out_file );
+ if ( out_debug ) fwrite( output_0, output_1 - output_0, 1, stdout );
+ }
+ output_0 = output_1;
+
+ /* Copy non-white space, watching for variables. */
+ while ( ( output_1 < ine ) && *output_1 && !isspace( *output_1 ) )
+ {
+ if ( ( output_1[ 0 ] == '$' ) && ( output_1[ 1 ] == '(' ) )
+ ++dollar;
+ ++output_1;
+ }
+
+ /* If a variable encountered, expand it and embed the space-separated
+ * members of the list in the output.
+ */
+ if ( dollar )
+ {
+ LIST * l = var_expand( L0, (char *)output_0, (char *)output_1, lol, 0 );
+
+ while ( l )
+ {
+ if ( out_file ) fputs( l->string, out_file );
+ if ( out_debug ) puts( l->string );
+ l = list_next( l );
+ if ( l )
+ {
+ if ( out_file ) fputc( ' ', out_file );
+ if ( out_debug ) fputc( ' ', stdout );
+ }
+ }
+
+ list_free( l );
+ }
+ else if ( output_0 < output_1 )
+ {
+ if ( out_file )
+ {
+ const char * output_n = output_0;
+ while ( output_n < output_1 )
+ {
+ output_n += fwrite( output_n, 1, output_1-output_n, out_file );
+ }
+ }
+ if ( out_debug )
+ {
+ const char * output_n = output_0;
+ while ( output_n < output_1 )
+ {
+ output_n += fwrite( output_n, 1, output_1-output_n, stdout );
+ }
+ }
+ }
+
+ in = output_1;
+ }
+
+ if ( out_file && ( out_file != stdout ) && ( out_file != stderr ) )
+ {
+ fflush( out_file );
+ fclose( out_file );
+ }
+
+ if ( out_debug ) fputc( '\n', stdout );
+}
+
+
+/*
+ * var_get() - get value of a user defined symbol.
+ *
+ * Returns NULL if symbol unset.
+ */
+
+LIST * var_get( char * symbol )
+{
+ LIST * result = 0;
+#ifdef OPT_AT_FILES
+ /* Some "fixed" variables... */
+ if ( strcmp( "TMPDIR", symbol ) == 0 )
+ {
+ result = list_new( L0, newstr( (char *)path_tmpdir() ) );
+ }
+ else if ( strcmp( "TMPNAME", symbol ) == 0 )
+ {
+ result = list_new( L0, newstr( (char *)path_tmpnam() ) );
+ }
+ else if ( strcmp( "TMPFILE", symbol ) == 0 )
+ {
+ result = list_new( L0, newstr( (char *)path_tmpfile() ) );
+ }
+ else if ( strcmp( "STDOUT", symbol ) == 0 )
+ {
+ result = list_new( L0, newstr( "STDOUT" ) );
+ }
+ else if ( strcmp( "STDERR", symbol ) == 0 )
+ {
+ result = list_new( L0, newstr( "STDERR" ) );
+ }
+ else
+#endif
+ {
+ VARIABLE var;
+ VARIABLE * v = &var;
+
+ v->symbol = symbol;
+
+ if ( varhash && hashcheck( varhash, (HASHDATA * *)&v ) )
+ {
+ if ( DEBUG_VARGET )
+ var_dump( v->symbol, v->value, "get" );
+ result = v->value;
+ }
+ }
+ return result;
+}
+
+
+/*
+ * var_set() - set a variable in Jam's user defined symbol table.
+ *
+ * 'flag' controls the relationship between new and old values of the variable:
+ * SET replaces the old with the new; APPEND appends the new to the old; DEFAULT
+ * only uses the new if the variable was previously unset.
+ *
+ * Copies symbol. Takes ownership of value.
+ */
+
+void var_set( char * symbol, LIST * value, int flag )
+{
+ VARIABLE * v = var_enter( symbol );
+
+ if ( DEBUG_VARSET )
+ var_dump( symbol, value, "set" );
+
+ switch ( flag )
+ {
+ case VAR_SET:
+ /* Replace value */
+ list_free( v->value );
+ v->value = value;
+ break;
+
+ case VAR_APPEND:
+ /* Append value */
+ v->value = list_append( v->value, value );
+ break;
+
+ case VAR_DEFAULT:
+ /* Set only if unset */
+ if ( !v->value )
+ v->value = value;
+ else
+ list_free( value );
+ break;
+ }
+}
+
+
+/*
+ * var_swap() - swap a variable's value with the given one.
+ */
+
+LIST * var_swap( char * symbol, LIST * value )
+{
+ VARIABLE * v = var_enter( symbol );
+ LIST * oldvalue = v->value;
+ if ( DEBUG_VARSET )
+ var_dump( symbol, value, "set" );
+ v->value = value;
+ return oldvalue;
+}
+
+
+/*
+ * var_enter() - make new var symbol table entry, returning var ptr.
+ */
+
+static VARIABLE * var_enter( char * symbol )
+{
+ VARIABLE var;
+ VARIABLE * v = &var;
+
+ if ( !varhash )
+ varhash = hashinit( sizeof( VARIABLE ), "variables" );
+
+ v->symbol = symbol;
+ v->value = 0;
+
+ if ( hashenter( varhash, (HASHDATA * *)&v ) )
+ v->symbol = newstr( symbol ); /* never freed */
+
+ return v;
+}
+
+
+/*
+ * var_dump() - dump a variable to stdout.
+ */
+
+static void var_dump( char * symbol, LIST * value, char * what )
+{
+ printf( "%s %s = ", what, symbol );
+ list_print( value );
+ printf( "\n" );
+}
+
+
+/*
+ * var_done() - free variable tables.
+ */
+
+static void delete_var_( void * xvar, void * data )
+{
+ VARIABLE * v = (VARIABLE *)xvar;
+ freestr( v->symbol );
+ list_free( v-> value );
+}
+
+
+void var_done()
+{
+ hashenumerate( varhash, delete_var_, (void *)0 );
+ hashdone( varhash );
+}
diff --git a/tools/build/v2/engine/variable.h b/tools/build/v2/engine/variable.h
new file mode 100644
index 0000000000..5c49e3ca55
--- /dev/null
+++ b/tools/build/v2/engine/variable.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * variable.h - handle jam multi-element variables
+ */
+
+struct hash;
+
+void var_defines( char* const *e, int preprocess );
+int var_string( char *in, char *out, int outsize, LOL *lol );
+LIST * var_get( char *symbol );
+void var_set( char *symbol, LIST *value, int flag );
+LIST * var_swap( char *symbol, LIST *value );
+void var_done();
+void var_hash_swap( struct hash** );
+
+/** Expands the "in" expression directly into the "out" file.
+ The file can be one of: a path, STDOUT, or STDERR to send
+ the output to a file overwriting previous content, to
+ the console, or to the error output respectively.
+*/
+void var_string_to_file( const char * in, int insize, const char * out, LOL * lol );
+
+/*
+ * Defines for var_set().
+ */
+
+# define VAR_SET 0 /* override previous value */
+# define VAR_APPEND 1 /* append to previous value */
+# define VAR_DEFAULT 2 /* set only if no previous value */
+
diff --git a/tools/build/v2/engine/w32_getreg.c b/tools/build/v2/engine/w32_getreg.c
new file mode 100644
index 0000000000..5a06f43e92
--- /dev/null
+++ b/tools/build/v2/engine/w32_getreg.c
@@ -0,0 +1,207 @@
+/*
+Copyright Paul Lin 2003. Copyright 2006 Bojan Resnik.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+# include "jam.h"
+
+# if defined( OS_NT ) || defined( OS_CYGWIN )
+
+# include "lists.h"
+# include "newstr.h"
+# include "parse.h"
+# include "frames.h"
+# include "strings.h"
+
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+# define MAX_REGISTRY_DATA_LENGTH 4096
+# define MAX_REGISTRY_KEYNAME_LENGTH 256
+# define MAX_REGISTRY_VALUENAME_LENGTH 16384
+
+typedef struct
+{
+ LPCSTR name;
+ HKEY value;
+} KeyMap;
+
+static const KeyMap dlRootKeys[] = {
+ { "HKLM", HKEY_LOCAL_MACHINE },
+ { "HKCU", HKEY_CURRENT_USER },
+ { "HKCR", HKEY_CLASSES_ROOT },
+ { "HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE },
+ { "HKEY_CURRENT_USER", HKEY_CURRENT_USER },
+ { "HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT },
+ { 0, 0 }
+};
+
+static HKEY get_key(char const** path)
+{
+ const KeyMap *p;
+
+ for (p = dlRootKeys; p->name; ++p)
+ {
+ int n = strlen(p->name);
+ if (!strncmp(*path,p->name,n))
+ {
+ if ((*path)[n] == '\\' || (*path)[n] == 0)
+ {
+ *path += n + 1;
+ break;
+ }
+ }
+ }
+
+ return p->value;
+}
+
+LIST*
+builtin_system_registry(
+ PARSE *parse,
+ FRAME *frame )
+{
+ char const* path = lol_get(frame->args, 0)->string;
+ LIST* result = L0;
+ HKEY key = get_key(&path);
+
+ if (
+ key != 0
+ && ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key)
+ )
+ {
+ DWORD type;
+ BYTE data[MAX_REGISTRY_DATA_LENGTH];
+ DWORD len = sizeof(data);
+ LIST const* const field = lol_get(frame->args, 1);
+
+ if ( ERROR_SUCCESS ==
+ RegQueryValueEx(key, field ? field->string : 0, 0, &type, data, &len) )
+ {
+ switch (type)
+ {
+
+ case REG_EXPAND_SZ:
+ {
+ long len;
+ string expanded[1];
+ string_new(expanded);
+
+ while (
+ (len = ExpandEnvironmentStrings(
+ (LPCSTR)data, expanded->value, expanded->capacity))
+ > expanded->capacity
+ )
+ string_reserve(expanded, len);
+
+ expanded->size = len - 1;
+
+ result = list_new( result, newstr(expanded->value) );
+ string_free( expanded );
+ }
+ break;
+
+ case REG_MULTI_SZ:
+ {
+ char* s;
+
+ for (s = (char*)data; *s; s += strlen(s) + 1)
+ result = list_new( result, newstr(s) );
+
+ }
+ break;
+
+ case REG_DWORD:
+ {
+ char buf[100];
+ sprintf( buf, "%u", *(PDWORD)data );
+ result = list_new( result, newstr(buf) );
+ }
+ break;
+
+ case REG_SZ:
+ result = list_new( result, newstr((char*)data) );
+ break;
+ }
+ }
+ RegCloseKey(key);
+ }
+ return result;
+}
+
+static LIST* get_subkey_names(HKEY key, char const* path)
+{
+ LIST* result = 0;
+
+ if ( ERROR_SUCCESS ==
+ RegOpenKeyEx(key, path, 0, KEY_ENUMERATE_SUB_KEYS, &key)
+ )
+ {
+ char name[MAX_REGISTRY_KEYNAME_LENGTH];
+ DWORD name_size = sizeof(name);
+ DWORD index;
+ FILETIME last_write_time;
+
+ for ( index = 0;
+ ERROR_SUCCESS == RegEnumKeyEx(
+ key, index, name, &name_size, 0, 0, 0, &last_write_time);
+ ++index,
+ name_size = sizeof(name)
+ )
+ {
+ name[name_size] = 0;
+ result = list_append(result, list_new(0, newstr(name)));
+ }
+
+ RegCloseKey(key);
+ }
+
+ return result;
+}
+
+static LIST* get_value_names(HKEY key, char const* path)
+{
+ LIST* result = 0;
+
+ if ( ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key) )
+ {
+ char name[MAX_REGISTRY_VALUENAME_LENGTH];
+ DWORD name_size = sizeof(name);
+ DWORD index;
+
+ for ( index = 0;
+ ERROR_SUCCESS == RegEnumValue(
+ key, index, name, &name_size, 0, 0, 0, 0);
+ ++index,
+ name_size = sizeof(name)
+ )
+ {
+ name[name_size] = 0;
+ result = list_append(result, list_new(0, newstr(name)));
+ }
+
+ RegCloseKey(key);
+ }
+
+ return result;
+}
+
+LIST*
+builtin_system_registry_names(
+ PARSE *parse,
+ FRAME *frame )
+{
+ char const* path = lol_get(frame->args, 0)->string;
+ char const* result_type = lol_get(frame->args, 1)->string;
+
+ HKEY key = get_key(&path);
+
+ if ( !strcmp(result_type, "subkeys") )
+ return get_subkey_names(key, path);
+ if ( !strcmp(result_type, "values") )
+ return get_value_names(key, path);
+ return 0;
+}
+
+# endif
diff --git a/tools/build/v2/engine/yyacc.c b/tools/build/v2/engine/yyacc.c
new file mode 100644
index 0000000000..b5efc96b55
--- /dev/null
+++ b/tools/build/v2/engine/yyacc.c
@@ -0,0 +1,268 @@
+/* Copyright 2002 Rene Rivera.
+** Distributed under the Boost Software License, Version 1.0.
+** (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+/*
+# yyacc - yacc wrapper
+#
+# Allows tokens to be written as `literal` and then automatically
+# substituted with #defined tokens.
+#
+# Usage:
+# yyacc file.y filetab.h file.yy
+#
+# inputs:
+# file.yy yacc grammar with ` literals
+#
+# outputs:
+# file.y yacc grammar
+# filetab.h array of string <-> token mappings
+#
+# 3-13-93
+# Documented and p moved in sed command (for some reason,
+# s/x/y/p doesn't work).
+# 10-12-93
+# Take basename as second argument.
+# 12-31-96
+# reversed order of args to be compatible with GenFile rule
+# 11-20-2002
+# Reimplemented as a C program for portability. (Rene Rivera)
+*/
+
+void print_usage();
+char * copy_string(char * s, int l);
+char * tokenize_string(char * s);
+int cmp_literal(const void * a, const void * b);
+
+typedef struct
+{
+ char * string;
+ char * token;
+} literal;
+
+int main(int argc, char ** argv)
+{
+ int result = 0;
+ if (argc != 4)
+ {
+ print_usage();
+ result = 1;
+ }
+ else
+ {
+ FILE * token_output_f = 0;
+ FILE * grammar_output_f = 0;
+ FILE * grammar_source_f = 0;
+
+ grammar_source_f = fopen(argv[3],"r");
+ if (grammar_source_f == 0) { result = 1; }
+ if (result == 0)
+ {
+ literal literals[1024];
+ int t = 0;
+ char l[2048];
+ while (1)
+ {
+ if (fgets(l,2048,grammar_source_f) != 0)
+ {
+ char * c = l;
+ while (1)
+ {
+ char * c1 = strchr(c,'`');
+ if (c1 != 0)
+ {
+ char * c2 = strchr(c1+1,'`');
+ if (c2 != 0)
+ {
+ literals[t].string = copy_string(c1+1,c2-c1-1);
+ literals[t].token = tokenize_string(literals[t].string);
+ t += 1;
+ c = c2+1;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ literals[t].string = 0;
+ literals[t].token = 0;
+ qsort(literals,t,sizeof(literal),cmp_literal);
+ {
+ int p = 1;
+ int i = 1;
+ while (literals[i].string != 0)
+ {
+ if (strcmp(literals[p-1].string,literals[i].string) != 0)
+ {
+ literals[p] = literals[i];
+ p += 1;
+ }
+ i += 1;
+ }
+ literals[p].string = 0;
+ literals[p].token = 0;
+ t = p;
+ }
+ token_output_f = fopen(argv[2],"w");
+ if (token_output_f != 0)
+ {
+ int i = 0;
+ while (literals[i].string != 0)
+ {
+ fprintf(token_output_f," { \"%s\", %s },\n",literals[i].string,literals[i].token);
+ i += 1;
+ }
+ fclose(token_output_f);
+ }
+ else
+ result = 1;
+ if (result == 0)
+ {
+ grammar_output_f = fopen(argv[1],"w");
+ if (grammar_output_f != 0)
+ {
+ int i = 0;
+ while (literals[i].string != 0)
+ {
+ fprintf(grammar_output_f,"%%token %s\n",literals[i].token);
+ i += 1;
+ }
+ rewind(grammar_source_f);
+ while (1)
+ {
+ if (fgets(l,2048,grammar_source_f) != 0)
+ {
+ char * c = l;
+ while (1)
+ {
+ char * c1 = strchr(c,'`');
+ if (c1 != 0)
+ {
+ char * c2 = strchr(c1+1,'`');
+ if (c2 != 0)
+ {
+ literal key;
+ literal * replacement = 0;
+ key.string = copy_string(c1+1,c2-c1-1);
+ key.token = 0;
+ replacement = (literal*)bsearch(
+ &key,literals,t,sizeof(literal),cmp_literal);
+ *c1 = 0;
+ fprintf(grammar_output_f,"%s%s",c,replacement->token);
+ c = c2+1;
+ }
+ else
+ {
+ fprintf(grammar_output_f,"%s",c);
+ break;
+ }
+ }
+ else
+ {
+ fprintf(grammar_output_f,"%s",c);
+ break;
+ }
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ fclose(grammar_output_f);
+ }
+ else
+ result = 1;
+ }
+ }
+ if (result != 0)
+ {
+ perror("yyacc");
+ }
+ }
+ return result;
+}
+
+static char * usage[] = {
+ "yyacc <grammar output.y> <token table output.h> <grammar source.yy>",
+ 0 };
+
+void print_usage()
+{
+ char ** u;
+ for (u = usage; *u != 0; ++u)
+ {
+ fputs(*u,stderr); putc('\n',stderr);
+ }
+}
+
+char * copy_string(char * s, int l)
+{
+ char * result = (char*)malloc(l+1);
+ strncpy(result,s,l);
+ result[l] = 0;
+ return result;
+}
+
+char * tokenize_string(char * s)
+{
+ char * result;
+ char * literal = s;
+ int l;
+ int c;
+
+ if (strcmp(s,":") == 0) literal = "_colon";
+ else if (strcmp(s,"!") == 0) literal = "_bang";
+ else if (strcmp(s,"!=") == 0) literal = "_bang_equals";
+ else if (strcmp(s,"&&") == 0) literal = "_amperamper";
+ else if (strcmp(s,"&") == 0) literal = "_amper";
+ else if (strcmp(s,"+") == 0) literal = "_plus";
+ else if (strcmp(s,"+=") == 0) literal = "_plus_equals";
+ else if (strcmp(s,"||") == 0) literal = "_barbar";
+ else if (strcmp(s,"|") == 0) literal = "_bar";
+ else if (strcmp(s,";") == 0) literal = "_semic";
+ else if (strcmp(s,"-") == 0) literal = "_minus";
+ else if (strcmp(s,"<") == 0) literal = "_langle";
+ else if (strcmp(s,"<=") == 0) literal = "_langle_equals";
+ else if (strcmp(s,">") == 0) literal = "_rangle";
+ else if (strcmp(s,">=") == 0) literal = "_rangle_equals";
+ else if (strcmp(s,".") == 0) literal = "_period";
+ else if (strcmp(s,"?") == 0) literal = "_question";
+ else if (strcmp(s,"?=") == 0) literal = "_question_equals";
+ else if (strcmp(s,"=") == 0) literal = "_equals";
+ else if (strcmp(s,",") == 0) literal = "_comma";
+ else if (strcmp(s,"[") == 0) literal = "_lbracket";
+ else if (strcmp(s,"]") == 0) literal = "_rbracket";
+ else if (strcmp(s,"{") == 0) literal = "_lbrace";
+ else if (strcmp(s,"}") == 0) literal = "_rbrace";
+ else if (strcmp(s,"(") == 0) literal = "_lparen";
+ else if (strcmp(s,")") == 0) literal = "_rparen";
+ l = strlen(literal)+2;
+ result = (char*)malloc(l+1);
+ for (c = 0; literal[c] != 0; ++c)
+ {
+ result[c] = toupper(literal[c]);
+ }
+ result[l-2] = '_';
+ result[l-1] = 't';
+ result[l] = 0;
+ return result;
+}
+
+int cmp_literal(const void * a, const void * b)
+{
+ return strcmp(((const literal *)a)->string,((const literal *)b)->string);
+}
diff --git a/tools/build/v2/example/boost-build.jam b/tools/build/v2/example/boost-build.jam
new file mode 100644
index 0000000000..efcc231fe2
--- /dev/null
+++ b/tools/build/v2/example/boost-build.jam
@@ -0,0 +1,6 @@
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+boost-build ../kernel ;
diff --git a/tools/build/v2/example/built_tool/Jamroot.jam b/tools/build/v2/example/built_tool/Jamroot.jam
new file mode 100644
index 0000000000..c458650e8c
--- /dev/null
+++ b/tools/build/v2/example/built_tool/Jamroot.jam
@@ -0,0 +1,8 @@
+
+import feature ;
+
+feature.feature tblgen : : dependency free ;
+
+project built_tool ;
+
+build-project core ; \ No newline at end of file
diff --git a/tools/build/v2/example/built_tool/core/Jamfile.jam b/tools/build/v2/example/built_tool/core/Jamfile.jam
new file mode 100644
index 0000000000..2d96f7182b
--- /dev/null
+++ b/tools/build/v2/example/built_tool/core/Jamfile.jam
@@ -0,0 +1,30 @@
+
+import toolset ;
+
+project : requirements <tblgen>../tblgen//tblgen ;
+
+
+# Create a.c using a custom action defined below.
+make a.c : a.td : @tblgen ;
+
+# Use a.c in executable.
+exe core : core.cpp a.c ;
+
+# The action has to invoke the tool built in other
+# parts of the project. The <tblgen> feature is used
+# to specify the location of the tool, and the flags
+# statement below make the full path to the tool
+# available inside the action.
+toolset.flags tblgen COMMAND <tblgen> ;
+
+# We generally want a.c to be rebuilt when the tool changes.
+rule tblgen ( targets * : sources * : properties * )
+{
+ DEPENDS $(targets) : [ on $(targets) return $(COMMAND) ] ;
+}
+
+# The action that invokes the tool
+actions tblgen bind COMMAND
+{
+ $(COMMAND:E=tblgen) > $(<)
+}
diff --git a/tools/build/v2/example/built_tool/core/a.td b/tools/build/v2/example/built_tool/core/a.td
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/example/built_tool/core/a.td
diff --git a/tools/build/v2/example/built_tool/core/core.cpp b/tools/build/v2/example/built_tool/core/core.cpp
new file mode 100644
index 0000000000..31a133726c
--- /dev/null
+++ b/tools/build/v2/example/built_tool/core/core.cpp
@@ -0,0 +1,5 @@
+
+int main()
+{
+ return 0;
+}
diff --git a/tools/build/v2/example/built_tool/readme.txt b/tools/build/v2/example/built_tool/readme.txt
new file mode 100644
index 0000000000..bbb9f9b3a7
--- /dev/null
+++ b/tools/build/v2/example/built_tool/readme.txt
@@ -0,0 +1,5 @@
+
+This example shows how to build an executable and then use it
+for generating other targets. The 'tblgen' subdirectory builds
+a tool, while the 'core' subdirectory uses that tool. Refer
+to core/Jamfile.jam for detailed comments. \ No newline at end of file
diff --git a/tools/build/v2/example/built_tool/tblgen/Jamfile.jam b/tools/build/v2/example/built_tool/tblgen/Jamfile.jam
new file mode 100644
index 0000000000..af4906278f
--- /dev/null
+++ b/tools/build/v2/example/built_tool/tblgen/Jamfile.jam
@@ -0,0 +1,4 @@
+
+project : requirements -<tblgen>tblgen//tblgen ;
+
+exe tblgen : tblgen.cpp ; \ No newline at end of file
diff --git a/tools/build/v2/example/built_tool/tblgen/tblgen.cpp b/tools/build/v2/example/built_tool/tblgen/tblgen.cpp
new file mode 100644
index 0000000000..fbd0581334
--- /dev/null
+++ b/tools/build/v2/example/built_tool/tblgen/tblgen.cpp
@@ -0,0 +1,9 @@
+
+#include <iostream>
+
+int main()
+{
+ std::cout << "int foo;\n";
+ return 0;
+}
+
diff --git a/tools/build/v2/example/customization/class.verbatim b/tools/build/v2/example/customization/class.verbatim
new file mode 100644
index 0000000000..5c0d7b803c
--- /dev/null
+++ b/tools/build/v2/example/customization/class.verbatim
@@ -0,0 +1,7 @@
+class_template
+
+class %class_name% {
+public:
+ %class_name%() {}
+ ~%class_name%() {}
+}; \ No newline at end of file
diff --git a/tools/build/v2/example/customization/codegen.cpp b/tools/build/v2/example/customization/codegen.cpp
new file mode 100644
index 0000000000..6cdb45e4de
--- /dev/null
+++ b/tools/build/v2/example/customization/codegen.cpp
@@ -0,0 +1,36 @@
+// (C) Copyright Vladimir Prus, 2003
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Please see 'usage.verbatim' file for usage notes.
+
+#include <iostream>
+#include <string>
+#include <cstring>
+using std::cout;
+using std::string;
+using std::strlen;
+
+extern const char class_template[];
+extern const char usage[];
+
+int main(int ac, char* av[])
+{
+ if (av[1]) {
+
+ string class_name = av[1];
+ string s = class_template;
+
+ string::size_type n;
+ while((n = s.find("%class_name%")) != string::npos) {
+ s.replace(n, strlen("%class_name%"), class_name);
+ }
+ std::cout << "Output is:\n";
+ std::cout << s << "\n";
+ return 0;
+ } else {
+ std::cout << usage << "\n";
+ return 1;
+ }
+}
diff --git a/tools/build/v2/example/customization/inline_file.py b/tools/build/v2/example/customization/inline_file.py
new file mode 100755
index 0000000000..a48c5fc9d9
--- /dev/null
+++ b/tools/build/v2/example/customization/inline_file.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import sys
+from string import strip
+
+def quote_line(line):
+
+ result = ""
+
+ for i in line:
+ if (i == '\\'):
+ result = result + '\\\\'
+ elif (i == '\"'):
+ result = result + '\\\"'
+ elif (i != '\r' and i != '\n'):
+ result = result + i;
+
+ return '\"' + result + '\\n\"'
+
+def quote_file(file):
+ result = ""
+
+ for i in file.readlines():
+ result = result + quote_line(i) + "\n"
+
+ return result
+
+if len(sys.argv) < 3:
+ print "Usage: inline_file.py output_c_file file_to_include"
+else:
+ output_c_file = sys.argv[1]
+ out_file = open(output_c_file, "w");
+
+ file_to_include = sys.argv[2]
+
+ in_file = open(file_to_include, "r");
+ variable_name = strip(in_file.readline())
+ out_file.write("extern const char %s[] = {\n%s};\n\n" % (variable_name, quote_file(in_file)))
+ in_file.close()
+ out_file.close()
diff --git a/tools/build/v2/example/customization/jamroot.jam b/tools/build/v2/example/customization/jamroot.jam
new file mode 100644
index 0000000000..5e986d91c2
--- /dev/null
+++ b/tools/build/v2/example/customization/jamroot.jam
@@ -0,0 +1,9 @@
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import verbatim ;
+
+exe codegen : codegen.cpp class.verbatim usage.verbatim
+ t1.verbatim ;
+
diff --git a/tools/build/v2/example/customization/readme.txt b/tools/build/v2/example/customization/readme.txt
new file mode 100644
index 0000000000..7ee04f1a24
--- /dev/null
+++ b/tools/build/v2/example/customization/readme.txt
@@ -0,0 +1,11 @@
+Copyright 2003 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+This example show how to add a new target type and a new tool support to
+Boost.Build. Please refer to extender manual for a complete description of this
+example.
+
+Note that this example requires Python. If cygwin Python on Windows is to be
+used, please go to "verbatim.jam" and follow instructions there.
diff --git a/tools/build/v2/example/customization/t1.verbatim b/tools/build/v2/example/customization/t1.verbatim
new file mode 100644
index 0000000000..144540f29b
--- /dev/null
+++ b/tools/build/v2/example/customization/t1.verbatim
@@ -0,0 +1,2 @@
+t1
+//###include "t2.verbatim" \ No newline at end of file
diff --git a/tools/build/v2/example/customization/t2.verbatim b/tools/build/v2/example/customization/t2.verbatim
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/example/customization/t2.verbatim
diff --git a/tools/build/v2/example/customization/usage.verbatim b/tools/build/v2/example/customization/usage.verbatim
new file mode 100644
index 0000000000..0fc4b4a377
--- /dev/null
+++ b/tools/build/v2/example/customization/usage.verbatim
@@ -0,0 +1,5 @@
+usage
+Usage: codegen class_name
+
+This program takes a template of C++ code and replaces of all occurrences of
+%class_name% with the passed 'class_name' parameter. \ No newline at end of file
diff --git a/tools/build/v2/example/customization/verbatim.jam b/tools/build/v2/example/customization/verbatim.jam
new file mode 100644
index 0000000000..931fdce336
--- /dev/null
+++ b/tools/build/v2/example/customization/verbatim.jam
@@ -0,0 +1,51 @@
+# Copyright 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This file shows some of the primary customization mechanisms in Boost.Build V2
+# and should serve as a basic for your own customization.
+# Each part has a comment describing its purpose, and you can pick the parts
+# which are relevant to your case, remove everything else, and then change names
+# and actions to taste.
+
+# Declare a new target type. This allows Boost.Build to do something sensible
+# when targets with the .verbatim extension are found in sources.
+import type ;
+type.register VERBATIM : verbatim ;
+
+# Declare a dependency scanner for the new target type. The
+# 'inline-file.py' script does not handle includes, so this is
+# only for illustraction.
+import scanner ;
+# First, define a new class, derived from 'common-scanner',
+# that class has all the interesting logic, and we only need
+# to override the 'pattern' method which return regular
+# expression to use when scanning.
+class verbatim-scanner : common-scanner
+{
+ rule pattern ( )
+ {
+ return "//###include[ ]*\"([^\"]*)\"" ;
+ }
+}
+
+# Register the scanner class. The 'include' is
+# the property which specifies the search path
+# for includes.
+scanner.register verbatim-scanner : include ;
+# Assign the scanner class to the target type.
+# Now, all .verbatim sources will be scanned.
+# To test this, build the project, touch the
+# t2.verbatim file and build again.
+type.set-scanner VERBATIM : verbatim-scanner ;
+
+import generators ;
+generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
+
+# Note: To use Cygwin Python on Windows change the following line
+# to "python inline_file.py $(<) $(>)"
+# Also, make sure that "python" in in PATH.
+actions inline-file
+{
+ "./inline_file.py" $(<) $(>)
+}
diff --git a/tools/build/v2/example/customization/verbatim.py b/tools/build/v2/example/customization/verbatim.py
new file mode 100644
index 0000000000..be285976c1
--- /dev/null
+++ b/tools/build/v2/example/customization/verbatim.py
@@ -0,0 +1,47 @@
+# Copyright 2010 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This file is only used with Python port of Boost.Build
+
+# This file shows some of the primary customization mechanisms in Boost.Build V2
+# and should serve as a basic for your own customization.
+# Each part has a comment describing its purpose, and you can pick the parts
+# which are relevant to your case, remove everything else, and then change names
+# and actions to taste.
+
+# Declare a new target type. This allows Boost.Build to do something sensible
+# when targets with the .verbatim extension are found in sources.
+import b2.build.type as type
+type.register("VERBATIM", ["verbatim"])
+
+# Declare a dependency scanner for the new target type. The
+# 'inline-file.py' script does not handle includes, so this is
+# only for illustraction.
+import b2.build.scanner as scanner;
+# First, define a new class, derived from 'common-scanner',
+# that class has all the interesting logic, and we only need
+# to override the 'pattern' method which return regular
+# expression to use when scanning.
+class VerbatimScanner(scanner.CommonScanner):
+
+ def pattern(self):
+ return "//###include[ ]*\"([^\"]*)\""
+
+scanner.register(VerbatimScanner, ["include"])
+type.set_scanner("VERBATIM", VerbatimScanner)
+
+import b2.build.generators as generators
+
+generators.register_standard("verbatim.inline-file",
+ ["VERBATIM"], ["CPP"])
+
+from b2.manager import get_manager
+
+get_manager().engine().register_action("verbatim.inline-file",
+"""
+./inline_file.py $(<) $(>)
+""")
+
+
+
diff --git a/tools/build/v2/example/generate/REAME.txt b/tools/build/v2/example/generate/REAME.txt
new file mode 100644
index 0000000000..fc2b207723
--- /dev/null
+++ b/tools/build/v2/example/generate/REAME.txt
@@ -0,0 +1,11 @@
+# Copyright 2007 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+This example shows the 'generate' rule, that allows you to construct target
+using any arbitrary set of transformation and commands.
+
+The rule is similar to 'make' and 'notfile', but unlike those, you can operate
+in terms of Boost.Build 'virtual targets', which is more flexible.
+
+Please consult the docs for more explanations.
diff --git a/tools/build/v2/example/generate/a.cpp b/tools/build/v2/example/generate/a.cpp
new file mode 100644
index 0000000000..364975671d
--- /dev/null
+++ b/tools/build/v2/example/generate/a.cpp
@@ -0,0 +1,10 @@
+
+int main()
+{
+}
+
+/*
+Copyright 2007 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
diff --git a/tools/build/v2/example/generate/gen.jam b/tools/build/v2/example/generate/gen.jam
new file mode 100644
index 0000000000..73232aab5e
--- /dev/null
+++ b/tools/build/v2/example/generate/gen.jam
@@ -0,0 +1,26 @@
+
+import "class" : new ;
+import common ;
+
+rule generate-example ( project name : property-set : sources * )
+{
+ local result ;
+ for local s in $(sources)
+ {
+ #local source-name = [ $(s).name ] ;
+ #local source-action = [ $(s).action ] ;
+ #local source-properties = [ $(source-action).properties ] ;
+
+ # Create a new action, that takes the source target and runs the
+ # 'common.copy' command on it.
+ local a = [ new non-scanning-action $(s) : common.copy : $(property-set)
+ ] ;
+
+ # Create a target to represent the action result. Uses the target name
+ # passed here via the 'name' parameter and the same type and project as
+ # the source.
+ result += [ new file-target $(name) : [ $(s).type ] : $(project) : $(a)
+ ] ;
+ }
+ return $(result) ;
+} \ No newline at end of file
diff --git a/tools/build/v2/example/generate/gen.py b/tools/build/v2/example/generate/gen.py
new file mode 100644
index 0000000000..09ee15b43a
--- /dev/null
+++ b/tools/build/v2/example/generate/gen.py
@@ -0,0 +1,16 @@
+
+from b2.build.virtual_target import NonScanningAction, FileTarget
+
+def generate_example(project, name, ps, sources):
+
+ result = []
+ for s in sources:
+
+ a = NonScanningAction([s], "common.copy", ps)
+
+ # Create a target to represent the action result. Uses the target name
+ # passed here via the 'name' parameter and the same type and project as
+ # the source.
+ result.append(FileTarget(name, s.type(), project, a))
+
+ return result
diff --git a/tools/build/v2/example/generate/jamroot.jam b/tools/build/v2/example/generate/jamroot.jam
new file mode 100644
index 0000000000..c48f2207bf
--- /dev/null
+++ b/tools/build/v2/example/generate/jamroot.jam
@@ -0,0 +1,9 @@
+# Copyright 2007 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import generate ;
+
+import gen ;
+
+generate a2 : a.cpp : <generating-rule>@gen.generate-example ;
diff --git a/tools/build/v2/example/generator/README.txt b/tools/build/v2/example/generator/README.txt
new file mode 100644
index 0000000000..f26a856a58
--- /dev/null
+++ b/tools/build/v2/example/generator/README.txt
@@ -0,0 +1,6 @@
+# Copyright 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+This example shows how to declare a new generator class. It is necessary when
+generator's logic is more complex that just running a single tool.
diff --git a/tools/build/v2/example/generator/foo.gci b/tools/build/v2/example/generator/foo.gci
new file mode 100644
index 0000000000..2ccc45c6c5
--- /dev/null
+++ b/tools/build/v2/example/generator/foo.gci
@@ -0,0 +1,10 @@
+
+int main()
+{
+ return 0;
+}
+/*
+Copyright 2006 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
diff --git a/tools/build/v2/example/generator/jamroot.jam b/tools/build/v2/example/generator/jamroot.jam
new file mode 100644
index 0000000000..9703134dba
--- /dev/null
+++ b/tools/build/v2/example/generator/jamroot.jam
@@ -0,0 +1,6 @@
+# Copyright 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import soap ;
+exe foo : foo.gci : <server>on ;
diff --git a/tools/build/v2/example/generator/soap.jam b/tools/build/v2/example/generator/soap.jam
new file mode 100644
index 0000000000..d28bfdecc5
--- /dev/null
+++ b/tools/build/v2/example/generator/soap.jam
@@ -0,0 +1,77 @@
+# Copyright 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This is example of a fictional code generator tool.
+# It accepts a single input of type '.gci' and produces
+# either one or two outputs of type .cpp, depending
+# on the value of the feature <server-mode>
+#
+# This example is loosely based on gSOAP code generator.
+
+import type ;
+import generators ;
+import feature ;
+import common ;
+import "class" : new ;
+
+type.register GCI : gci ;
+
+feature.feature server : off on : incidental ;
+
+class soap-generator : generator
+{
+ import "class" : new ;
+
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * )
+ {
+ if ! $(sources[2])
+ {
+ # Accept only single source.
+ local t = [ $(sources[1]).type ] ;
+ if $(t) = GCI
+ {
+ # The type is correct.
+
+ # If no output name is specified, guess it from sources.
+ if ! $(name)
+ {
+ name = [ generator.determine-output-name $(sources) ] ;
+ }
+
+ # Produce one output, using just copy.
+ local a = [ new action $(sources[1])
+ : common.copy : $(property-set) ] ;
+ local t = [ new file-target $(name) : CPP : $(project)
+ : $(a) ] ;
+
+ # If in server mode, create another output -- an
+ # empty file. If this were a real SOAP generator, we
+ # might have created a single action, and two targets
+ # both using that action.
+ local t2 ;
+ if [ $(property-set).get <server> ] = "on"
+ {
+ local a = [ new action : soap.touch : $(property-set) ] ;
+ t2 = [ new file-target $(name)_server : CPP : $(project)
+ : $(a) ] ;
+ }
+ return [ virtual-target.register $(t) ]
+ [ virtual-target.register $(t2) ] ;
+ }
+ }
+ }
+}
+
+generators.register [ new soap-generator soap.soap : GCI : CPP ] ;
+
+TOUCH = [ common.file-touch-command ] ;
+actions touch
+{
+ $(TOUCH) $(<)
+}
diff --git a/tools/build/v2/example/gettext/jamfile.jam b/tools/build/v2/example/gettext/jamfile.jam
new file mode 100644
index 0000000000..d5096df305
--- /dev/null
+++ b/tools/build/v2/example/gettext/jamfile.jam
@@ -0,0 +1,26 @@
+# Copyright 2003, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+# Declare a main target.
+exe main : main.cpp ;
+
+# Declare an action for updating translations
+# After changing main.cpp, invocation of
+#
+# bjam update-russian
+#
+# will update translations in russian.po
+gettext.update update-russian : russian.po main ;
+
+# Compiled message catalog.
+gettext.catalog russian : russian.po ;
+
+# A stage rule which installs message catalog to the
+# location gettext expects.
+stage messages-russian : russian
+ : <location>messages/ru_RU.KOI8-R/LC_MESSAGES
+ <name>main.mo
+ ;
+
diff --git a/tools/build/v2/example/gettext/jamroot.jam b/tools/build/v2/example/gettext/jamroot.jam
new file mode 100644
index 0000000000..862f8930c7
--- /dev/null
+++ b/tools/build/v2/example/gettext/jamroot.jam
@@ -0,0 +1,6 @@
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+using gettext ;
diff --git a/tools/build/v2/example/gettext/main.cpp b/tools/build/v2/example/gettext/main.cpp
new file mode 100644
index 0000000000..6888e1abae
--- /dev/null
+++ b/tools/build/v2/example/gettext/main.cpp
@@ -0,0 +1,28 @@
+// Copyright Vladimir Prus 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#include <locale.h>
+#include <libintl.h>
+#define i18n(s) gettext(s)
+
+#include <iostream>
+using namespace std;
+
+int main()
+{
+ // Specify that translations are stored in directory
+ // "messages".
+ bindtextdomain("main", "messages");
+ textdomain("main");
+
+ // Switch to russian locale.
+ setlocale(LC_MESSAGES, "ru_RU.KOI8-R");
+
+ // Output localized message.
+ std::cout << i18n("hello") << "\n";
+
+ return 0;
+}
diff --git a/tools/build/v2/example/gettext/readme.txt b/tools/build/v2/example/gettext/readme.txt
new file mode 100644
index 0000000000..9c8fee6fd9
--- /dev/null
+++ b/tools/build/v2/example/gettext/readme.txt
@@ -0,0 +1,24 @@
+Copyright 2003 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+This example shows how it is possible to use GNU gettext utilities with
+Boost.Build.
+
+A simple translation file is compiled and installed as message catalog for
+russian. The main application explicitly switches to russian locale and outputs
+the translation of "hello".
+
+To test:
+
+ bjam
+ bin/gcc/debug/main
+
+To test even more:
+
+ - add more localized strings to "main.cpp"
+ - run "bjam update-russian"
+ - edit "russian.po"
+ - run bjam
+ - run "main"
diff --git a/tools/build/v2/example/gettext/russian.po b/tools/build/v2/example/gettext/russian.po
new file mode 100644
index 0000000000..daa7121c3d
--- /dev/null
+++ b/tools/build/v2/example/gettext/russian.po
@@ -0,0 +1,21 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-07-01 15:45+0400\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: main.cpp:16
+msgid "hello"
+msgstr "international hello"
diff --git a/tools/build/v2/example/hello/hello.cpp b/tools/build/v2/example/hello/hello.cpp
new file mode 100644
index 0000000000..6808022897
--- /dev/null
+++ b/tools/build/v2/example/hello/hello.cpp
@@ -0,0 +1,16 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include <iostream>
+
+int main()
+{
+ std::cout << "Hello!\n";
+ return 1;
+}
diff --git a/tools/build/v2/example/hello/jamroot.jam b/tools/build/v2/example/hello/jamroot.jam
new file mode 100644
index 0000000000..672ec02e90
--- /dev/null
+++ b/tools/build/v2/example/hello/jamroot.jam
@@ -0,0 +1 @@
+exe hello : hello.cpp ;
diff --git a/tools/build/v2/example/hello/readme.txt b/tools/build/v2/example/hello/readme.txt
new file mode 100644
index 0000000000..f416be675a
--- /dev/null
+++ b/tools/build/v2/example/hello/readme.txt
@@ -0,0 +1,7 @@
+Copyright 2008 Jurko Gospodnetic
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+This example shows a very basic Boost Build project set up so it compiles a
+single executable from a single source file.
diff --git a/tools/build/v2/example/libraries/app/app.cpp b/tools/build/v2/example/libraries/app/app.cpp
new file mode 100644
index 0000000000..f62c1c35db
--- /dev/null
+++ b/tools/build/v2/example/libraries/app/app.cpp
@@ -0,0 +1,15 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include <lib1.h>
+
+int main()
+{
+ foo();
+}
diff --git a/tools/build/v2/example/libraries/app/jamfile.jam b/tools/build/v2/example/libraries/app/jamfile.jam
new file mode 100644
index 0000000000..ed2054e130
--- /dev/null
+++ b/tools/build/v2/example/libraries/app/jamfile.jam
@@ -0,0 +1,9 @@
+# Copyright 2002, 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+# Declare a executable file, which uses a library. Note that
+# includes that for library will be automatically used
+# when compiling 'app.cpp'
+exe app : app.cpp /library-example/foo//bar ;
diff --git a/tools/build/v2/example/libraries/jamroot.jam b/tools/build/v2/example/libraries/jamroot.jam
new file mode 100644
index 0000000000..5e0dc48148
--- /dev/null
+++ b/tools/build/v2/example/libraries/jamroot.jam
@@ -0,0 +1,4 @@
+
+use-project /library-example/foo : util/foo ;
+
+build-project app ;
diff --git a/tools/build/v2/example/libraries/util/foo/bar.cpp b/tools/build/v2/example/libraries/util/foo/bar.cpp
new file mode 100644
index 0000000000..e6339ee9bb
--- /dev/null
+++ b/tools/build/v2/example/libraries/util/foo/bar.cpp
@@ -0,0 +1,13 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {}
diff --git a/tools/build/v2/example/libraries/util/foo/include/lib1.h b/tools/build/v2/example/libraries/util/foo/include/lib1.h
new file mode 100644
index 0000000000..50f5e19d20
--- /dev/null
+++ b/tools/build/v2/example/libraries/util/foo/include/lib1.h
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+void foo();
diff --git a/tools/build/v2/example/libraries/util/foo/jamfile.jam b/tools/build/v2/example/libraries/util/foo/jamfile.jam
new file mode 100644
index 0000000000..7b6359ea4e
--- /dev/null
+++ b/tools/build/v2/example/libraries/util/foo/jamfile.jam
@@ -0,0 +1,9 @@
+# Copyright 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project
+ : usage-requirements <include>include ;
+
+lib bar : bar.cpp ;
diff --git a/tools/build/v2/example/make/foo.py b/tools/build/v2/example/make/foo.py
new file mode 100644
index 0000000000..e4c0b824a0
--- /dev/null
+++ b/tools/build/v2/example/make/foo.py
@@ -0,0 +1,2 @@
+import sys
+open(sys.argv[2], "w").write(open(sys.argv[1]).read())
diff --git a/tools/build/v2/example/make/jamroot.jam b/tools/build/v2/example/make/jamroot.jam
new file mode 100644
index 0000000000..7bb98e3537
--- /dev/null
+++ b/tools/build/v2/example/make/jamroot.jam
@@ -0,0 +1,13 @@
+import feature ;
+import toolset ;
+
+path-constant HERE : . ;
+make main.cpp : main_cpp.pro : @do-something ;
+
+feature.feature example.python.interpreter : : free ;
+
+toolset.flags do-something PYTHON : <example.python.interpreter> ;
+actions do-something
+{
+ "$(PYTHON:E=python)" "$(HERE)/foo.py" "$(>)" "$(<)"
+}
diff --git a/tools/build/v2/example/make/main_cpp.pro b/tools/build/v2/example/make/main_cpp.pro
new file mode 100644
index 0000000000..237c8ce181
--- /dev/null
+++ b/tools/build/v2/example/make/main_cpp.pro
@@ -0,0 +1 @@
+int main() {}
diff --git a/tools/build/v2/example/make/readme.txt b/tools/build/v2/example/make/readme.txt
new file mode 100644
index 0000000000..333c55a716
--- /dev/null
+++ b/tools/build/v2/example/make/readme.txt
@@ -0,0 +1,7 @@
+Copyright 2002, 2005 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+Example of using custom command to create one file from another, using the
+built-in 'make' rule.
diff --git a/tools/build/v2/example/pch/include/pch.hpp b/tools/build/v2/example/pch/include/pch.hpp
new file mode 100644
index 0000000000..8f05cc43d9
--- /dev/null
+++ b/tools/build/v2/example/pch/include/pch.hpp
@@ -0,0 +1,19 @@
+/* Copyright 2006 Vladimir Prus
+
+ Distributed under the Boost Software License, Version 1.0. (See
+ accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifdef BOOST_BUILD_PCH_ENABLED
+
+#ifdef FOO2
+int bar();
+#endif
+
+class TestClass {
+public:
+ TestClass(int, int) {}
+};
+
+#endif
diff --git a/tools/build/v2/example/pch/jamroot.jam b/tools/build/v2/example/pch/jamroot.jam
new file mode 100644
index 0000000000..115164aaef
--- /dev/null
+++ b/tools/build/v2/example/pch/jamroot.jam
@@ -0,0 +1,29 @@
+# Copyright 2006 Ilya Sokolov
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# pch ##########################################################################
+
+import pch ;
+
+cpp-pch pch
+ : # sources
+ include/pch.hpp
+ : # requirements
+ <include>include
+ ;
+explicit pch ;
+
+# exe ##########################################################################
+
+exe hello_world
+ : # sources
+ pch
+ source/hello_world.cpp
+ : # requirements
+ <include>include
+ : # default build
+ : # usage requirements
+ ;
diff --git a/tools/build/v2/example/pch/source/hello_world.cpp b/tools/build/v2/example/pch/source/hello_world.cpp
new file mode 100644
index 0000000000..f618056a0b
--- /dev/null
+++ b/tools/build/v2/example/pch/source/hello_world.cpp
@@ -0,0 +1,15 @@
+/* Copyright 2006 Ilya Sokolov
+ Copyright 2006 Vladimir Prus
+
+ Distributed under the Boost Software License, Version 1.0. (See
+ accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include <pch.hpp>
+
+int main()
+{
+ TestClass c(1, 2);
+ return 0;
+}
diff --git a/tools/build/v2/example/python_modules/jamroot.jam b/tools/build/v2/example/python_modules/jamroot.jam
new file mode 100644
index 0000000000..c53e75d58b
--- /dev/null
+++ b/tools/build/v2/example/python_modules/jamroot.jam
@@ -0,0 +1,8 @@
+# Copyright 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import python_helpers ;
+
+ECHO "test1:" [ python_helpers.test1 ] ;
+ECHO "test2:" [ python_helpers.test2 1234 : 5678 ] ;
diff --git a/tools/build/v2/example/python_modules/python_helpers.jam b/tools/build/v2/example/python_modules/python_helpers.jam
new file mode 100644
index 0000000000..5a79aeebf2
--- /dev/null
+++ b/tools/build/v2/example/python_modules/python_helpers.jam
@@ -0,0 +1,15 @@
+# Copyright 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import modules ;
+local here = [ modules.binding $(__name__) ] ;
+here = $(here:D) ;
+modules.poke : EXTRA_PYTHONPATH : $(here) ;
+
+# Import the Python rules to Boost.Build
+PYTHON_IMPORT_RULE python_helpers : test1 : python_helpers : test1 ;
+PYTHON_IMPORT_RULE python_helpers : test2 : python_helpers : test2 ;
+
+# Make the new rules accessible to everybody who imports us.
+EXPORT python_helpers : test1 test2 ;
diff --git a/tools/build/v2/example/python_modules/python_helpers.py b/tools/build/v2/example/python_modules/python_helpers.py
new file mode 100644
index 0000000000..8148f57c35
--- /dev/null
+++ b/tools/build/v2/example/python_modules/python_helpers.py
@@ -0,0 +1,18 @@
+# Copyright 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Declare a couple of functions called from Boost.Build
+#
+# Each function will receive as many arguments as there ":"-separated
+# arguments in bjam call. Each argument is a list of strings.
+# As a special exception (aka bug), if no arguments are passed in bjam,
+# Python function will be passed a single empty list.
+#
+# All Python functions must return a list of strings, which may be empty.
+
+def test1(l):
+ return ["foo", "bar"]
+
+def test2(l, l2):
+ return [l[0], l2[0]] \ No newline at end of file
diff --git a/tools/build/v2/example/python_modules/readme.txt b/tools/build/v2/example/python_modules/readme.txt
new file mode 100644
index 0000000000..0fe6ee55e6
--- /dev/null
+++ b/tools/build/v2/example/python_modules/readme.txt
@@ -0,0 +1,16 @@
+Copyright 2006 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+This example shows how you can use Python modules from Boost.Build.
+
+In order to do this, you need to build bjam with Python support, by running:
+
+ ./build.sh --with-python=/usr
+
+in the jam/src directory (replace /usr with the root of your Python
+installation).
+
+The integration between Python and bjam is very basic now, but enough to be
+useful.
diff --git a/tools/build/v2/example/qt/README.txt b/tools/build/v2/example/qt/README.txt
new file mode 100644
index 0000000000..d187c31c36
--- /dev/null
+++ b/tools/build/v2/example/qt/README.txt
@@ -0,0 +1,20 @@
+Copyright 2005 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+This directory contains Boost.Build examples for the Qt library
+(http://www.trolltech.com/products/qt/index.html).
+
+The current examples are:
+ 1. Basic setup -- application with several sources and moccable header.
+ 2. Using of .ui source file.
+ 3. Running .cpp files via the moc tool.
+
+For convenience, there are examples both for 3.* and 4.* version of Qt, they are
+mostly identical and differ only in source code.
+
+All examples assumes that you just installed Boost.Build and that QTDIR
+environment variables is set (typical values can be /usr/share/qt3 and
+/usr/share/qt4). After adding "using qt ..." to your user-config.jam, you would
+have to remove "using qt ; " statements from example Jamroot files.
diff --git a/tools/build/v2/example/qt/qt3/hello/canvas.cpp b/tools/build/v2/example/qt/qt3/hello/canvas.cpp
new file mode 100644
index 0000000000..c6d23c9d47
--- /dev/null
+++ b/tools/build/v2/example/qt/qt3/hello/canvas.cpp
@@ -0,0 +1,73 @@
+// Copyright Vladimir Prus 2004.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "canvas.h"
+
+#include <qlabel.h>
+#include <qcanvas.h>
+#include <qlayout.h>
+
+Canvas::Canvas(QWidget* parent)
+: QWidget(parent)
+{
+ m_pen = QPen(QColor(255, 128, 128));
+ m_brushes = new QBrush[2];
+ m_brushes[0] = QBrush(QColor(255, 0, 0));
+ m_brushes[1] = QBrush(QColor(0, 255, 0));
+ m_current_brush = 0;
+
+ m_canvas = new QCanvas(this);
+ m_canvas->resize(4*1600, 600);
+
+ redraw();
+
+ QVBoxLayout* l = new QVBoxLayout(this);
+
+ m_canvas_view = new QCanvasView(m_canvas, this);
+ l->addWidget(m_canvas_view);
+ m_canvas_view->resize(rect().size());
+ m_canvas_view->show();
+}
+
+Canvas::~Canvas()
+{
+ delete m_brushes;
+}
+
+void Canvas::redraw()
+{
+ QCanvasItemList l = m_canvas->allItems();
+ for(QCanvasItemList::iterator i = l.begin(),
+ e = l.end(); i != e; ++i)
+ {
+ delete *i;
+ }
+
+ unsigned count = 0;
+ for (unsigned x = 10; x < 4*1600; x += 20)
+ for (unsigned y = 10; y < 600; y += 20) {
+ QCanvasRectangle* r = new QCanvasRectangle(x, y, 10, 10, m_canvas);
+ r->setPen(m_pen);
+ r->setBrush(m_brushes[m_current_brush]);
+ r->show();
+ ++count;
+ QCanvasText* t = new QCanvasText("D", m_canvas);
+ t->move(x, y);
+ t->show();
+ ++count;
+ }
+
+ (new QCanvasText(QString::number(count), m_canvas))->show();
+ m_canvas->setAllChanged();
+
+}
+
+void Canvas::change_color()
+{
+ m_current_brush = (m_current_brush + 1)%2;
+ redraw();
+ m_canvas->update();
+}
+
diff --git a/tools/build/v2/example/qt/qt3/hello/canvas.h b/tools/build/v2/example/qt/qt3/hello/canvas.h
new file mode 100644
index 0000000000..f9f9502679
--- /dev/null
+++ b/tools/build/v2/example/qt/qt3/hello/canvas.h
@@ -0,0 +1,35 @@
+// Copyright Vladimir Prus 2004.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef CANVAS_VP_2004_08_31
+#define CANVAS_VP_2004_08_31
+
+#include <qmainwindow.h>
+#include <qpen.h>
+#include <qbrush.h>
+
+class Canvas : public QWidget
+{
+ Q_OBJECT
+public:
+ Canvas(QWidget* parent);
+
+ virtual ~Canvas();
+
+public slots:
+ void change_color();
+
+private:
+ void redraw();
+ class QCanvas* m_canvas;
+ class QCanvasView* m_canvas_view;
+ class QPen m_pen;
+ class QBrush* m_brushes;
+ int m_current_brush;
+};
+
+#endif
+
diff --git a/tools/build/v2/example/qt/qt3/hello/jamroot.jam b/tools/build/v2/example/qt/qt3/hello/jamroot.jam
new file mode 100644
index 0000000000..03be582e50
--- /dev/null
+++ b/tools/build/v2/example/qt/qt3/hello/jamroot.jam
@@ -0,0 +1,13 @@
+# Copyright Vladimir Prus 2004.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+using qt ;
+
+project
+ # built MT version, unless asked otherwise.
+ : default-build <threading>multi
+ ;
+
+exe canvas : main.cpp canvas.cpp canvas.h : <library>/qt//qt ; \ No newline at end of file
diff --git a/tools/build/v2/example/qt/qt3/hello/main.cpp b/tools/build/v2/example/qt/qt3/hello/main.cpp
new file mode 100644
index 0000000000..8f1ffc2fba
--- /dev/null
+++ b/tools/build/v2/example/qt/qt3/hello/main.cpp
@@ -0,0 +1,36 @@
+// Copyright Vladimir Prus 2004.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "canvas.h"
+#include <qapplication.h>
+#include <qvbox.h>
+#include <qpushbutton.h>
+
+class Window : public QMainWindow
+{
+public:
+ Window()
+ {
+ setCaption("QCanvas test");
+ QVBox* vb = new QVBox(this);
+ setCentralWidget(vb);
+
+ Canvas* c = new Canvas(vb);
+ QPushButton* b = new QPushButton("Change color", vb);
+ connect(b, SIGNAL(clicked()), c, SLOT(change_color()));
+ }
+};
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ Window *w = new Window();
+
+ app.setMainWidget(w);
+ w->show();
+
+ return app.exec();
+}
+
diff --git a/tools/build/v2/example/qt/qt3/moccable-cpp/jamroot.jam b/tools/build/v2/example/qt/qt3/moccable-cpp/jamroot.jam
new file mode 100644
index 0000000000..85778da208
--- /dev/null
+++ b/tools/build/v2/example/qt/qt3/moccable-cpp/jamroot.jam
@@ -0,0 +1,11 @@
+
+using qt ;
+import cast ;
+
+project
+ : default-build <threading>multi
+ ;
+
+exe main : main.cpp [ cast _ moccable-cpp : main.cpp ]
+ /qt//qt
+ ;
diff --git a/tools/build/v2/example/qt/qt3/moccable-cpp/main.cpp b/tools/build/v2/example/qt/qt3/moccable-cpp/main.cpp
new file mode 100644
index 0000000000..ed36f74698
--- /dev/null
+++ b/tools/build/v2/example/qt/qt3/moccable-cpp/main.cpp
@@ -0,0 +1,41 @@
+// Copyright Vladimir Prus 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#include <qwidget.h>
+#include <qpushbutton.h>
+#include <qapplication.h>
+
+#include <iostream>
+
+class My_widget : public QWidget
+{
+ Q_OBJECT
+public:
+ My_widget() : QWidget()
+ {
+ QPushButton* b = new QPushButton("Push me", this);
+
+ connect(b, SIGNAL(clicked()), this, SLOT(theSlot()));
+ }
+
+private slots:
+ void theSlot()
+ {
+ std::cout << "Clicked\n";
+ }
+
+};
+
+int main(int ac, char* av[])
+{
+ QApplication app(ac, av);
+ My_widget mw;
+ mw.show();
+ app.setMainWidget(&mw);
+ app.exec();
+}
+
+#include "main.moc"
diff --git a/tools/build/v2/example/qt/qt3/uic/hello_world_widget.ui b/tools/build/v2/example/qt/qt3/uic/hello_world_widget.ui
new file mode 100644
index 0000000000..26cc734871
--- /dev/null
+++ b/tools/build/v2/example/qt/qt3/uic/hello_world_widget.ui
@@ -0,0 +1,58 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>HelloWorldWidget</class>
+<comment>
+<!--
+ Copyright Felix E. Klee, 2003
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt
+ or copy at http://www.boost.org/LICENSE_1_0.txt)
+-->
+</comment>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>HelloWorldWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>124</width>
+ <height>63</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Hello World!</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Hello World!</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>OkButton</cstring>
+ </property>
+ <property name="text">
+ <string>OK</string>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/tools/build/v2/example/qt/qt3/uic/jamroot.jam b/tools/build/v2/example/qt/qt3/uic/jamroot.jam
new file mode 100644
index 0000000000..d0b8062940
--- /dev/null
+++ b/tools/build/v2/example/qt/qt3/uic/jamroot.jam
@@ -0,0 +1,15 @@
+# Copyright Felix E. Klee, 2003
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# Tell that QT should be used. QTDIR will give installation
+# prefix.
+using qt ;
+
+project
+ : default-build <threading>multi
+ ;
+
+exe hello : main.cpp hello_world_widget.ui : <library>/qt//qt ;
+
diff --git a/tools/build/v2/example/qt/qt3/uic/main.cpp b/tools/build/v2/example/qt/qt3/uic/main.cpp
new file mode 100644
index 0000000000..f2a08b5faa
--- /dev/null
+++ b/tools/build/v2/example/qt/qt3/uic/main.cpp
@@ -0,0 +1,18 @@
+// Copyright Felix E. Klee, 2003
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "hello_world_widget.h"
+#include <qapplication.h>
+
+#include <qpushbutton.h>
+
+int main(int argc, char **argv) {
+ QApplication a(argc, argv);
+ HelloWorldWidget w;
+ QObject::connect(static_cast<QObject*>(w.OkButton), SIGNAL(clicked()), &w, SLOT(close()));
+ a.setMainWidget(&w);
+ w.show();
+ return a.exec();
+}
diff --git a/tools/build/v2/example/qt/qt4/hello/arrow.cpp b/tools/build/v2/example/qt/qt4/hello/arrow.cpp
new file mode 100644
index 0000000000..e821b16909
--- /dev/null
+++ b/tools/build/v2/example/qt/qt4/hello/arrow.cpp
@@ -0,0 +1,158 @@
+// Copyright Vladimir Prus 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "arrow.h"
+
+#include <QtGui/qapplication.h>
+
+#include <QtGui/qwidget.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qpainterpath.h>
+
+#include <stdlib.h>
+#include <math.h>
+
+Arrow_widget::Arrow_widget(QWidget* parent) : QWidget(parent), color_(0)
+{
+ QPalette pal = palette();
+ pal.setBrush(backgroundRole(), QBrush(Qt::white));
+ setPalette(pal);
+}
+
+void Arrow_widget::slotChangeColor()
+{
+ color_ = (color_ + 1) % 3;
+ update();
+}
+
+void
+Arrow_widget::draw_arrow(int x1, int y1, int x2, int y2, QPainter& painter)
+{
+ // The length of the from the tip of the arrow to the point
+ // where line starts.
+ const int arrowhead_length = 16;
+
+ QPainterPath arrow;
+ arrow.moveTo(x1, y1);
+
+ // Determine the angle of the straight line.
+ double a1 = (x2-x1);
+ double a2 = (y2-y1);
+ double b1 = 1;
+ double b2 = 0;
+
+ double straight_length = sqrt(a1*a1 + a2*a2);
+
+ double dot_product = a1*b1 + a2*b2;
+ double cosine = dot_product/
+ (sqrt(pow(a1, 2) + pow(a2, 2))*sqrt(b1 + b2));
+ double angle = acos(cosine);
+ if (y1 < y2)
+ {
+ angle = -angle;
+ }
+ double straight_angle = angle*180/M_PI;
+
+ double limit = 10;
+
+ double angle_to_vertical;
+ if (fabs(straight_angle) < 90)
+ angle_to_vertical = fabs(straight_angle);
+ else if (straight_angle > 0)
+ angle_to_vertical = 180-straight_angle;
+ else
+ angle_to_vertical = 180-(-straight_angle);
+
+ double angle_delta = 0;
+ if (angle_to_vertical > limit)
+ angle_delta = 30 * (angle_to_vertical - limit)/90;
+ double start_angle = straight_angle > 0
+ ? straight_angle - angle_delta :
+ straight_angle + angle_delta;
+
+
+ QMatrix m1;
+ m1.translate(x1, y1);
+ m1.rotate(-start_angle);
+
+ double end_angle = straight_angle > 0
+ ? (straight_angle + 180 + angle_delta) :
+ (straight_angle + 180 - angle_delta);
+
+ QMatrix m2;
+ m2.reset();
+ m2.translate(x2, y2);
+ m2.rotate(-end_angle);
+
+ arrow.cubicTo(m1.map(QPointF(straight_length/2, 0)),
+ m2.map(QPointF(straight_length/2, 0)),
+ m2.map(QPointF(arrowhead_length, 0)));
+
+ painter.save();
+ painter.setBrush(Qt::NoBrush);
+ painter.drawPath(arrow);
+ painter.restore();
+
+ painter.save();
+ painter.translate(x2, y2);
+
+ painter.rotate(-90);
+ painter.rotate(-end_angle);
+ painter.rotate(180);
+
+ QPolygon arrowhead(4);
+ arrowhead.setPoint(0, 0, 0);
+ arrowhead.setPoint(1, arrowhead_length/3, -arrowhead_length*5/4);
+ arrowhead.setPoint(2, 0, -arrowhead_length);
+ arrowhead.setPoint(3, -arrowhead_length/3, -arrowhead_length*5/4);
+
+ painter.drawPolygon(arrowhead);
+
+ painter.restore();
+
+}
+
+
+void Arrow_widget::paintEvent(QPaintEvent*)
+{
+ QPainter p(this);
+
+ p.setRenderHint(QPainter::Antialiasing);
+
+ int base_x = 550;
+ int base_y = 200;
+
+ if (color_ == 0)
+ p.setBrush(Qt::black);
+ else if (color_ == 1)
+ p.setBrush(Qt::green);
+ else if (color_ == 2)
+ p.setBrush(Qt::yellow);
+ else
+ p.setBrush(Qt::black);
+
+ for (int x_step = 0; x_step < 6; ++x_step)
+ {
+ for (int y_step = 1; y_step <= 3; ++y_step)
+ {
+ draw_arrow(base_x, base_y, base_x+x_step*100,
+ base_y - y_step*50, p);
+
+ draw_arrow(base_x, base_y, base_x+x_step*100,
+ base_y + y_step*50, p);
+
+ draw_arrow(base_x, base_y, base_x-x_step*100,
+ base_y + y_step*50, p);
+
+ draw_arrow(base_x, base_y, base_x-x_step*100,
+ base_y - y_step*50, p);
+ }
+ }
+
+ draw_arrow(50, 400, 1000, 450, p);
+ draw_arrow(1000, 400, 50, 450, p);
+
+}
+
diff --git a/tools/build/v2/example/qt/qt4/hello/arrow.h b/tools/build/v2/example/qt/qt4/hello/arrow.h
new file mode 100644
index 0000000000..d7743864f3
--- /dev/null
+++ b/tools/build/v2/example/qt/qt4/hello/arrow.h
@@ -0,0 +1,30 @@
+// Copyright Vladimir Prus 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <QtGui/qapplication.h>
+
+#include <QtGui/qwidget.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qpainterpath.h>
+
+#include <stdlib.h>
+#include <math.h>
+
+class Arrow_widget : public QWidget
+{
+ Q_OBJECT
+public:
+ Arrow_widget(QWidget* parent = 0);
+
+public slots:
+ void slotChangeColor();
+
+private:
+ void draw_arrow(int x1, int y1, int x2, int y2, QPainter& painter);
+ void paintEvent(QPaintEvent*);
+
+private:
+ int color_;
+};
diff --git a/tools/build/v2/example/qt/qt4/hello/jamroot.jam b/tools/build/v2/example/qt/qt4/hello/jamroot.jam
new file mode 100644
index 0000000000..83952f17b2
--- /dev/null
+++ b/tools/build/v2/example/qt/qt4/hello/jamroot.jam
@@ -0,0 +1,14 @@
+
+import qt4 ;
+
+if ! [ qt4.initialized ]
+{
+ ECHO "Warning: Qt4 not initialized in user-config.jam" ;
+ ECHO "Assuming /space/p2/ghost/build/Qt4 as location." ;
+ ECHO "This is very likely won't work for you. " ;
+ using qt4 : /space/p2/ghost/build/Qt4 ;
+}
+
+project : requirements <threading>multi ;
+
+exe arrow : main.cpp arrow.cpp arrow.h /qt//QtGui ; \ No newline at end of file
diff --git a/tools/build/v2/example/qt/qt4/hello/main.cpp b/tools/build/v2/example/qt/qt4/hello/main.cpp
new file mode 100644
index 0000000000..df27444bdd
--- /dev/null
+++ b/tools/build/v2/example/qt/qt4/hello/main.cpp
@@ -0,0 +1,27 @@
+// Copyright Vladimir Prus 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "arrow.h"
+
+#include <QApplication>
+#include <QTimer>
+
+int main(int ac, char* av[])
+{
+ QApplication app(ac, av);
+ Arrow_widget* w = new Arrow_widget;
+ w->resize(1100, 480);
+
+ QTimer timer;
+ QObject::connect(&timer, SIGNAL(timeout()),
+ w, SLOT(slotChangeColor()));
+
+ timer.start(2000);
+
+ w->show();
+ app.exec();
+ return 0;
+}
+
diff --git a/tools/build/v2/example/qt/qt4/moccable-cpp/jamroot.jam b/tools/build/v2/example/qt/qt4/moccable-cpp/jamroot.jam
new file mode 100644
index 0000000000..d07b9c7d3b
--- /dev/null
+++ b/tools/build/v2/example/qt/qt4/moccable-cpp/jamroot.jam
@@ -0,0 +1,18 @@
+
+import qt4 ;
+if ! [ qt4.initialized ]
+{
+ ECHO "Warning: Qt4 not initialized in user-config.jam" ;
+ ECHO "Assuming /space/p2/ghost/build/Qt4 as location." ;
+ ECHO "This is very likely won't work for you. " ;
+ using qt4 : /space/p2/ghost/build/Qt4 ;
+}
+
+import cast ;
+exe main : main.cpp
+ [ cast _ moccable-cpp : main.cpp ]
+ /qt//QtGui
+ : <threading>multi
+ ;
+
+
diff --git a/tools/build/v2/example/qt/qt4/moccable-cpp/main.cpp b/tools/build/v2/example/qt/qt4/moccable-cpp/main.cpp
new file mode 100644
index 0000000000..ffc96cc3e6
--- /dev/null
+++ b/tools/build/v2/example/qt/qt4/moccable-cpp/main.cpp
@@ -0,0 +1,39 @@
+// Copyright Vladimir Prus 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <qwidget.h>
+#include <qpushbutton.h>
+#include <qapplication.h>
+
+#include <iostream>
+
+class My_widget : public QWidget
+{
+ Q_OBJECT
+public:
+ My_widget() : QWidget()
+ {
+ QPushButton* b = new QPushButton("Push me", this);
+
+ connect(b, SIGNAL(clicked()), this, SLOT(theSlot()));
+ }
+
+private slots:
+ void theSlot()
+ {
+ std::cout << "Clicked\n";
+ }
+
+};
+
+int main(int ac, char* av[])
+{
+ QApplication app(ac, av);
+ My_widget mw;
+ mw.show();
+ app.exec();
+}
+
+#include "main.moc"
diff --git a/tools/build/v2/example/qt/qt4/uic/hello_world_widget.ui b/tools/build/v2/example/qt/qt4/uic/hello_world_widget.ui
new file mode 100644
index 0000000000..67060b336e
--- /dev/null
+++ b/tools/build/v2/example/qt/qt4/uic/hello_world_widget.ui
@@ -0,0 +1,55 @@
+<ui version="4.0" >
+ <author></author>
+ <comment>
+<!--
+ Copyright Felix E. Klee, 2003
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt
+ or copy at http://www.boost.org/LICENSE_1_0.txt)
+-->
+ </comment>
+ <exportmacro></exportmacro>
+ <class>HelloWorldWidget</class>
+ <widget class="QWidget" name="HelloWorldWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>124</width>
+ <height>63</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Hello World!</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="TextLabel2" >
+ <property name="text" >
+ <string>Hello World!</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="OkButton" >
+ <property name="text" >
+ <string>OK</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/build/v2/example/qt/qt4/uic/jamroot.jam b/tools/build/v2/example/qt/qt4/uic/jamroot.jam
new file mode 100644
index 0000000000..40675a72eb
--- /dev/null
+++ b/tools/build/v2/example/qt/qt4/uic/jamroot.jam
@@ -0,0 +1,18 @@
+# Copyright Felix E. Klee, 2003
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import qt4 ;
+if ! [ qt4.initialized ]
+{
+ ECHO "Warning: Qt4 not initialized in user-config.jam" ;
+ ECHO "Assuming /space/p2/ghost/build/Qt4 as location." ;
+ ECHO "This is very likely won't work for you. " ;
+ using qt4 : /space/p2/ghost/build/Qt4 ;
+}
+
+project : requirements <threading>multi
+ ;
+
+exe hello : main.cpp hello_world_widget.ui : <library>/qt//QtGui ;
diff --git a/tools/build/v2/example/qt/qt4/uic/main.cpp b/tools/build/v2/example/qt/qt4/uic/main.cpp
new file mode 100644
index 0000000000..fc72fd5e6b
--- /dev/null
+++ b/tools/build/v2/example/qt/qt4/uic/main.cpp
@@ -0,0 +1,23 @@
+// Copyright Felix E. Klee, 2003
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "ui_hello_world_widget.h"
+#include <qapplication.h>
+#include <qwidget.h>
+
+#include <qpushbutton.h>
+
+int main(int argc, char **argv) {
+ QApplication a(argc, argv);
+
+ QWidget w;
+ Ui::HelloWorldWidget wm;
+ wm.setupUi(&w);
+
+ QObject::connect(wm.OkButton, SIGNAL(clicked()), &w, SLOT(close()));
+
+ w.show();
+ return a.exec();
+}
diff --git a/tools/build/v2/example/variant/a.cpp b/tools/build/v2/example/variant/a.cpp
new file mode 100644
index 0000000000..42b69f3358
--- /dev/null
+++ b/tools/build/v2/example/variant/a.cpp
@@ -0,0 +1,7 @@
+// Copyright Vladimir Prus 2004.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+void l();
+int main() { l(); return 0; }
diff --git a/tools/build/v2/example/variant/jamfile.jam b/tools/build/v2/example/variant/jamfile.jam
new file mode 100644
index 0000000000..9f8c580be0
--- /dev/null
+++ b/tools/build/v2/example/variant/jamfile.jam
@@ -0,0 +1,11 @@
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+# By default, build the project with the two variants we have defined in
+# jamroot.jam.
+
+project : default-build crazy super_release ;
+
+exe a : a.cpp libs//l ;
diff --git a/tools/build/v2/example/variant/jamroot.jam b/tools/build/v2/example/variant/jamroot.jam
new file mode 100644
index 0000000000..e19476ccc0
--- /dev/null
+++ b/tools/build/v2/example/variant/jamroot.jam
@@ -0,0 +1,14 @@
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+# Define a build variant which is just combination
+# of four properties.
+variant crazy : <optimization>speed <inlining>off
+ <debug-symbols>on <profiling>on ;
+
+# Define a built variant inherited from 'release'.
+# It defines one new property and get all properties
+# from parent variant.
+variant super_release : release : <define>USE_ASM ;
diff --git a/tools/build/v2/example/variant/libs/jamfile.jam b/tools/build/v2/example/variant/libs/jamfile.jam
new file mode 100644
index 0000000000..4366b76246
--- /dev/null
+++ b/tools/build/v2/example/variant/libs/jamfile.jam
@@ -0,0 +1,6 @@
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+lib l : l.cpp ;
diff --git a/tools/build/v2/example/variant/libs/l.cpp b/tools/build/v2/example/variant/libs/l.cpp
new file mode 100644
index 0000000000..26cb4b1e63
--- /dev/null
+++ b/tools/build/v2/example/variant/libs/l.cpp
@@ -0,0 +1,9 @@
+// Copyright Vladimir Prus 2002-2004.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void l() {}
diff --git a/tools/build/v2/example/variant/readme.txt b/tools/build/v2/example/variant/readme.txt
new file mode 100644
index 0000000000..5ab1b938a9
--- /dev/null
+++ b/tools/build/v2/example/variant/readme.txt
@@ -0,0 +1,11 @@
+Copyright 2004 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+This example shows how user can create his own build variants. Two variants are
+defined: "crazy", which is just a random combination of properties, and
+"super-release", which is inherited from "release", and differs by a single
+define.
+
+See the jamroot.jam for the definitions.
diff --git a/tools/build/v2/example/versioned/hello.cpp b/tools/build/v2/example/versioned/hello.cpp
new file mode 100644
index 0000000000..11fef734b3
--- /dev/null
+++ b/tools/build/v2/example/versioned/hello.cpp
@@ -0,0 +1,12 @@
+// Copyright Rene Rivera, 2003
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+int main()
+{
+ std::cout << "Hello there!\n";
+ return 1;
+}
diff --git a/tools/build/v2/example/versioned/jamfile.jam b/tools/build/v2/example/versioned/jamfile.jam
new file mode 100644
index 0000000000..913cdf4d78
--- /dev/null
+++ b/tools/build/v2/example/versioned/jamfile.jam
@@ -0,0 +1,9 @@
+# Copyright 2003 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+#~ exe hello : hello.cpp : <version>1.0 ;
+lib hello : hello.cpp : <version>1.0 ;
+
+symlink hello_debug hello_release : hello/<variant>debug hello/<variant>release ;
+symlink links/hello_release : hello/<variant>release ;
diff --git a/tools/build/v2/example/versioned/jamroot.jam b/tools/build/v2/example/versioned/jamroot.jam
new file mode 100644
index 0000000000..981d3eb508
--- /dev/null
+++ b/tools/build/v2/example/versioned/jamroot.jam
@@ -0,0 +1,8 @@
+# Copyright 2003 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+import gcc ;
+import toolset ;
+import modifiers ;
diff --git a/tools/build/v2/exceptions.py b/tools/build/v2/exceptions.py
new file mode 100644
index 0000000000..5750abfe3f
--- /dev/null
+++ b/tools/build/v2/exceptions.py
@@ -0,0 +1,44 @@
+# Copyright Pedro Ferreira 2005. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# TODO: add more exception types?
+
+class BaseException (Exception):
+ def __init__ (self, message = ''): Exception.__init__ (self, message)
+
+class UserError (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
+
+class FeatureConflict (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
+
+class InvalidSource (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
+
+class InvalidFeature (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
+
+class InvalidProperty (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
+
+class InvalidValue (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
+
+class InvalidAttribute (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
+
+class AlreadyDefined (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
+
+class IllegalOperation (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
+
+class Recursion (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
+
+class NoBestMatchingAlternative (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
+
+class NoAction (BaseException):
+ def __init__ (self, message = ''): BaseException.__init__ (self, message)
diff --git a/tools/build/v2/hacking.txt b/tools/build/v2/hacking.txt
new file mode 100644
index 0000000000..2acc253370
--- /dev/null
+++ b/tools/build/v2/hacking.txt
@@ -0,0 +1,154 @@
+Copyright 2003, 2006 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+ ----------------------------------
+ Boost.Build contributor guidelines
+ ----------------------------------
+
+Boost.Build is an open-source project. This means that we welcome and appreciate
+all contributions --- be it ideas, bug reports, or patches. This document
+contains guidelines which helps to assure that development goes on smoothly, and
+changes are made quickly.
+
+The guidelines are not mandatory, and you can decide for yourself which one to
+follow. But note, that 10 mins that you spare writing a comment, for example,
+might lead to significally longer delay for everyone.
+
+Before contributing, make sure you are subscribed to our mailing list
+
+ boost-build@lists.boost.org
+
+Additional resources include
+
+ - The issue tracker
+ http://zigzag.cs.msu.su/boost.build
+
+ - commits mailing list:
+ boost-build@lists.sourceforge.net
+ http://sourceforge.net/mailarchive/forum.php?forum_id=9097
+
+
+BUGS and PATCHES
+
+Both bugs and patches can be send to our mailing list.
+
+When reporting a bug, please try to provide the following information.
+
+ - What you did. A minimal reproducible testcase is very much appreciated.
+ Shell script with some annotations is much better than verbose description
+ of the problem. A regression test is the best (see test/test_system.html).
+ - What you got.
+ - What you expected.
+ - What version of Boost.Build and Boost.Jam did you use. If possible,
+ please try to test with the CVS HEAD state.
+
+When submitting a patch, please:
+
+ - make a single patch for a single logical change
+ - follow the policies and coding conventions below,
+ - send patches in unified diff format,
+ (using either "cvs diff -u" or "diff -u")
+ - provide a log message together with the patch
+ - put the patch and the log message as attachment to your email.
+
+The purpose of log message serves to communicate what was changed, and *why*.
+Without a good log message, you might spend a lot of time later, wondering where
+a strange piece of code came from and why it was necessary.
+
+The good log message mentions each changed file and each rule/method, saying
+what happend to it, and why. Consider, the following log message
+
+ Better direct request handling.
+
+ * new/build-request.jam
+ (directly-requested-properties-adjuster): Redo.
+
+ * new/targets.jam
+ (main-target.generate-really): Adjust properties here.
+
+ * new/virtual-target.jam
+ (register-actual-name): New rule.
+ (virtual-target.actualize-no-scanner): Call the above, to detected bugs,
+ where two virtual target correspond to one Jam target name.
+
+The log messages for the last two files are good. They tell what was changed.
+The change to the first file is clearly undercommented.
+
+It's OK to use terse log messages for uninteresting changes, like ones induced
+by interface changes elsewhere.
+
+
+POLICIES.
+
+1. Testing.
+
+All serious changes must be tested. New rules must be tested by the module where
+they are declared. Test system (test/test_system.html) should be used to verify
+user-observable behaviour.
+
+2. Documentation.
+
+It turns out that it's hard to have too much comments, but it's easy to have too
+little. Please prepend each rule with a comment saying what the rule does and
+what arguments mean. Stop for a minute and consider if the comment makes sense
+for anybody else, and completely describes what the rules does. Generic phrases
+like "adjusts properties" are really not enough.
+
+When applicable, make changes to the user documentation as well.
+
+
+CODING CONVENTIONS.
+
+ 1. All names of rules and variables are lowercase with "-" to separate
+ words.
+
+ rule call-me-ishmael ( ) ...
+
+ 2. Names with dots in them are "intended globals". Ordinary globals use a
+ dot prefix:
+
+ .foobar
+ $(.foobar)
+
+ 3. Pseudofunctions or associations are <parameter>.<property>:
+
+ $(argument).name = hello ;
+ $($(argument).name)
+
+ 4. Class attribute names are prefixed with "self.":
+
+ self.x
+ $(self.x)
+
+ 5. Builtin rules are called via their ALL_UPPERCASE_NAMES:
+
+ DEPENDS $(target) : $(sources) ;
+
+ 6. Opening and closing braces go on separate lines:
+
+ if $(a)
+ {
+ #
+ }
+ else
+ {
+ #
+ }
+
+HTML DOCUMENTATION.
+
+ Please pass HTML files though HTML Tidy (http://tidy.sf.net) before
+ comitting. This has to important purposes:
+ - detecting bad HTML
+ - converting files to uniform indentation style, which inverses effect of
+ different editors and makes differences between revisions much smaller and
+ easy for review.
+
+ Alas, the way Tidy indents HTML differs between version. Please use the
+ version available at
+
+ http://tidy.sourceforge.net/src/old/tidy_src_020411.tgz
+
+ and "-i -wrap 78" command line parameters.
diff --git a/tools/build/v2/index.html b/tools/build/v2/index.html
new file mode 100644
index 0000000000..63df93fecb
--- /dev/null
+++ b/tools/build/v2/index.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<!-- Copyright 2004 Aleksey Gurtovoy -->
+<!-- Copyright 2004, 2005, 2006 Vladimir Prus -->
+<!-- Distributed under the Boost Software License, Version 1.0. -->
+<!-- (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) -->
+
+<html>
+ <head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st April 2002), see www.w3.org">
+ <meta name="generator" content="Microsoft FrontPage 5.0">
+ <meta http-equiv="Content-Type" content=
+ "text/html; charset=windows-1252">
+ <!-- tidy options: &dash;&dash;tidy-mark false -i -wrap 78 !-->
+<style type="text/css">
+div.sidebar {
+ margin-left: 1em ;
+ border: medium outset ;
+ padding: 0em 1em ;
+ background-color: #adbed2;
+ border-color: #000000;
+ border-width: 1;
+ width: 40% ;
+ float: right ;
+ clear: right }
+}
+
+div.sidebar p.rubric {
+ font-family: sans-serif ;
+ font-size: medium }
+</style>
+
+ <title>Boost.Build V2</title>
+ </head>
+
+ <body bgcolor="#FFFFFF" text="#000000">
+
+ <p align="center"><img src="boost_build.png" width="396" height="60" alt="Boost.Build V2"></img>
+
+ <div class="contents sidebar topic" id="index">
+ <p>
+ <b>Quick access</b>
+ <ul>
+ <li>Download: <a href=
+ "http://prdownloads.sourceforge.net/boost/boost-build-2.0-m12.zip">[zip]
+ </a>, <a href=
+ "http://prdownloads.sourceforge.net/boost/boost-build-2.0-m12.tar.bz2">[tar.bz2]
+ </a>
+ <li>Nightly build: <a href="http://boost.org/boost-build2/boost-build.zip">[zip]</a>,
+ <a href="http://boost.org/boost-build2/boost-build.tar.bz2">[tar.bz2]</a>
+ <li><a href="../../../doc/html/bbv2.html">Documentation</a>
+ (<a href="doc/userman.pdf">PDF</a>)
+ <li><a
+ href="http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost.Build_V2">Wiki
+ (User-contibuted documentation)</a>
+ <li>Feedback: <a
+ href="http://lists.boost.org/mailman/listinfo.cgi/boost-build">[mailing list]</a>,
+ <a
+ href="news://news.gmane.org/gmane.comp.lib.boost.build">[newsgroup]</a>
+ <ul>
+ <li>Before posting, <a href="http://lists.boost.org/mailman/listinfo.cgi/boost-build">subscribe</a>
+ <!--
+ <li><form method="get" action="http://search.gmane.org/">
+ <input type="text" name="query">
+ <input type="hidden" name="group" value="gmane.comp.lib.boost.build">
+ <input type="submit" value="Search">
+ </form> -->
+ </ul>
+ <li><a href="https://trac.lvk.cs.msu.su/boost.build">Bug tracker</a>
+<!-- <li>Rate Boost.Build: <a href="http://freshmeat.net/rate/38012/">Freshmeat</a> -->
+ </ul>
+ </p>
+ </div>
+
+<!-- <h1>Boost.Build V2</h1> -->
+
+
+ <h2>Overview</h2>
+
+ <p>Boost.Build is an easy way to build C++ projects, everywhere. You
+ name you executables and libraries and list their sources. Boost.Build
+ takes care about compiling your sources with right options, creating
+ static and shared libraries, making executables, and other chores --
+ whether you're using gcc, msvc, or a dozen more supported C++
+ compilers -- on Windows, OSX, Linux and commercial UNIX systems.
+
+ <p>Some of the most important features:
+ <ul>
+ <li><b>Simple and high level build description</b>. In most
+ cases a name of target and list of sources is all you need.</li>
+
+ <li><b>Portability</b>. Most important build properties have symbolic
+ names that work everywhere. Why memorize compiler flags necessary
+ for multi-threaded 64-bit shared library, if Boost.Build can do it for you?
+
+ <li><b>Variant builds</b>. When you build the same project
+ twice with different properties, all produced files are placed
+ in different directories, so you can build with 2 versions of
+ gcc, or both debug and release variants in one invocation.</li>
+
+ <li><b>Global dependencies</b>. No matter what directory you build
+ in, Boost.Build will always check all dependencies in your entire
+ project, preventing inconsistent binaries. And it's easy to
+ use one Boost.Build project in other, again with full dependency
+ tracking.
+
+ <li><b>Usage requirements</b>. A target can specify properties,
+ like include paths and preprocessor defines, that are necessary to use
+ it. Those properties will be automatically applied whenever the target
+ is used.</li>
+
+ <li><b>Standalone</b>. Boost.Build's only dependency is a C compiler,
+ so it's easy to setup. You can even include all of Boost.Build in your
+ project. Boost.Build does not depend on C++ Boost in any way.</li>
+ </ul>
+
+ <h2>Status and future</h2>
+
+ <p>Boost.Build is ready to use today, and new features are being actively
+ developed.
+
+ <p>The current version of 2.0 Milestone 12, which added support for
+ precompiled headers on gcc, and added 3 new C++ compilers
+ (<a href="http://svn.boost.org/svn/boost/trunk/tools/build/v2/changes.txt">full changelog</a>).
+
+ <p>Milestone 13 is planned as bugfix release. Milestone 14 will
+ focus on improving user documentation. Milestone 15 will see most
+ of Boost.Build reimplemented in Python, to make extending
+ Boost.Build even easier for end users (see <a href="https://trac.lvk.cs.msu.su/boost.build/wiki/PythonPort">PythonPort</a>).
+ The specific issues planned for each release can be found on the
+ <a href="https://trac.lvk.cs.msu.su/boost.build/roadmap">roadmap</a>.
+
+
+
+ <h2>Feedback and contributing</h2>
+
+ <p>Should you have any questions or comments, we'd be glad to hear them.
+ Post everything to the <a href="http://lists.boost.org/mailman/listinfo.cgi/boost-build">mailing list</a>.</p>
+
+ <p>Bugs and feature requests can be entered at our
+ <a href="https://trac.lvk.cs.msu.su/boost.build">bug tracker</a>.
+
+ <p>If you'd like to help with development, just pick a bug
+ in the tracker that you'd like to fix, or feel free to implement
+ any feature you like. There's a separate
+ <a href="hacking.txt">guidelines document</a> for working on code.</p>
+ <hr>
+
+ <p>&copy; Copyright David Abrahams and Vladimir Prus 2002-2007.
+ Permission to copy, use, modify, sell and distribute this document is
+ granted provided this copyright notice appears in all copies. This
+ document is provided "as is" without express or implied warranty, and
+ with no claim as to its suitability for any purpose.</p>
+
+ <p>Revised
+ <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
+ -->Oct 4, 2007
+ <!--webbot bot="Timestamp" endspan i-checksum="13972"
+ -->
+ </p>
+
+ </body>
+</html>
+
diff --git a/tools/build/v2/kernel/boost-build.jam b/tools/build/v2/kernel/boost-build.jam
new file mode 100644
index 0000000000..377f6ec023
--- /dev/null
+++ b/tools/build/v2/kernel/boost-build.jam
@@ -0,0 +1,5 @@
+# Copyright 2003 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+boost-build . ;
diff --git a/tools/build/v2/kernel/bootstrap.jam b/tools/build/v2/kernel/bootstrap.jam
new file mode 100644
index 0000000000..89048af922
--- /dev/null
+++ b/tools/build/v2/kernel/bootstrap.jam
@@ -0,0 +1,263 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2003, 2005, 2006 Rene Rivera
+# Copyright 2003, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# First of all, check the jam version
+
+if $(JAM_VERSION:J="") < 030112
+{
+ ECHO "error: Boost.Jam version 3.1.12 or later required" ;
+ EXIT ;
+}
+
+local required-rules = GLOB-RECURSIVELY HAS_NATIVE_RULE ;
+
+for local r in $(required-rules)
+{
+ if ! $(r) in [ RULENAMES ]
+ {
+ ECHO "error: builtin rule '$(r)' is not present" ;
+ ECHO "error: your version of bjam is likely out of date" ;
+ ECHO "error: please get a fresh version from SVN." ;
+ EXIT ;
+ }
+}
+
+local native =
+ regex transform 2
+ ;
+while $(native)
+{
+ if ! [ HAS_NATIVE_RULE $(native[1]) :
+ $(native[2]) :
+ $(native[3]) ]
+ {
+ ECHO "error: missing native rule '$(native[1]).$(native[2])'" ;
+ ECHO "error: or interface version of that rule is too low" ;
+ ECHO "error: your version of bjam is likely out of date" ;
+ ECHO "error: please get a fresh version from SVN." ;
+ EXIT ;
+ }
+ native = $(native[4-]) ;
+}
+
+# Check that the builtin .ENVIRON module is present. We don't have a
+# builtin to check that a module is present, so we assume that the PATH
+# environment variable is always set and verify that the .ENVIRON module
+# has non-empty value of that variable.
+module .ENVIRON
+{
+ local p = $(PATH) $(Path) $(path) ;
+ if ! $(p)
+ {
+ ECHO "error: no builtin module .ENVIRON is found" ;
+ ECHO "error: your version of bjam is likely out of date" ;
+ ECHO "error: please get a fresh version from SVN." ;
+ EXIT ;
+ }
+}
+
+# Check that @() functionality is present. Similarly to modules,
+# we don't have a way to test that directly. Instead we check that
+# $(TMPNAME) functionality is present which was added at roughly
+# the same time (more precisely it was added just before).
+{
+ if ! $(TMPNAME)
+ {
+ ECHO "error: no @() functionality found" ;
+ ECHO "error: your version of bjam is likely out of date" ;
+ ECHO "error: please get a fresh version from SVN." ;
+ EXIT ;
+ }
+}
+
+# Make sure that \n escape is avaiable.
+if "\n" = "n"
+{
+ if $(OS) = CYGWIN
+ {
+ ECHO "warning: escape sequences are not supported" ;
+ ECHO "warning: this will cause major misbehaviour on cygwin" ;
+ ECHO "warning: your version of bjam is likely out of date" ;
+ ECHO "warning: please get a fresh version from SVN." ;
+ }
+}
+
+# Bootstrap the module system. Then bring the import rule into the global module.
+#
+SEARCH on <module@>modules.jam = $(.bootstrap-file:D) ;
+module modules { include <module@>modules.jam ; }
+IMPORT modules : import : : import ;
+
+{
+ # Add module subdirectories to the BOOST_BUILD_PATH, which allows
+ # us to make an incremental refactoring step by moving modules to
+ # the appropriate subdirectories, thereby achieving some physical
+ # separation of different layers without changing all of our code
+ # to specify subdirectories in import statements or use an extra
+ # level of qualification on imported names.
+
+ local subdirs =
+ kernel # only the most-intrinsic modules: modules, errors
+ util # low-level substrate: string/number handling, etc.
+ build # essential elements of the build system architecture
+ tools # toolsets for handling specific build jobs and targets.
+ contrib # user contributed (unreviewed) modules
+ . # build-system.jam lives here
+ ;
+ local whereami = [ NORMALIZE_PATH $(.bootstrap-file:DT) ] ;
+ BOOST_BUILD_PATH += $(whereami:D)/$(subdirs) ;
+
+ modules.poke .ENVIRON : BOOST_BUILD_PATH : $(BOOST_BUILD_PATH) ;
+
+ modules.poke : EXTRA_PYTHONPATH : $(whereami) ;
+}
+
+# Reload the modules, to clean up things. The modules module can tolerate
+# being included twice.
+#
+import modules ;
+
+# Process option plugins first to alow them to prevent loading
+# the rest of the build system.
+#
+import option ;
+local dont-build = [ option.process ] ;
+
+# Should we skip building, i.e. loading the build system, according
+# to the options processed?
+#
+if ! $(dont-build)
+{
+ if ! --python in $(ARGV)
+ {
+ # Allow users to override the build system file from the
+ # command-line (mostly for testing)
+ local build-system = [ MATCH --build-system=(.*) : $(ARGV) ] ;
+ build-system ?= build-system ;
+
+ # Use last element in case of multiple command-line options
+ import $(build-system[-1]) ;
+ }
+ else
+ {
+ ECHO "Boost.Build V2 Python port (experimental)" ;
+
+ # Define additional interface that is exposed to Python code. Python code will
+ # also have access to select bjam builtins in the 'bjam' module, but some
+ # things are easier to define outside C.
+ module python_interface
+ {
+ rule load ( module-name : location )
+ {
+ USER_MODULE $(module-name) ;
+ # Make all rules in the loaded module available in
+ # the global namespace, so that we don't have
+ # to bother specifying "right" module when calling
+ # from Python.
+ module $(module-name)
+ {
+ __name__ = $(1) ;
+ include $(2) ;
+ local rules = [ RULENAMES $(1) ] ;
+ IMPORT $(1) : $(rules) : $(1) : $(1).$(rules) ;
+ }
+ }
+
+ rule peek ( module-name ? : variables + )
+ {
+ module $(<)
+ {
+ return $($(>)) ;
+ }
+ }
+
+ rule set-variable ( module-name : name : value * )
+ {
+ module $(<)
+ {
+ $(>) = $(3) ;
+ }
+ }
+
+ rule set-top-level-targets ( targets * )
+ {
+ DEPENDS all : $(targets) ;
+ }
+
+ rule call-in-module ( m : rulename : * )
+ {
+ module $(m)
+ {
+ return [ $(2) $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+ }
+
+
+ rule set-update-action ( action : targets * : sources * : properties * )
+ {
+ $(action) $(targets) : $(sources) : $(properties) ;
+ }
+
+ rule set-update-action-in-module ( m : action : targets * : sources * : properties * )
+ {
+ module $(m)
+ {
+ $(2) $(3) : $(4) : $(5) ;
+ }
+ }
+
+ rule set-target-variable ( targets + : variable : value * : append ? )
+ {
+ if $(append)
+ {
+ $(variable) on $(targets) += $(value) ;
+ }
+ else
+ {
+ $(variable) on $(targets) = $(value) ;
+ }
+ }
+
+ rule get-target-variable ( targets + : variable )
+ {
+ return [ on $(targets) return $($(variable)) ] ;
+ }
+
+ rule import-rules-from-parent ( parent-module : this-module : user-rules * )
+ {
+ IMPORT $(parent-module) : $(user-rules) : $(this-module) : $(user-rules) ;
+ EXPORT $(this-module) : $(user-rules) ;
+ }
+
+ rule mark-included ( targets * : includes * ) {
+ NOCARE $(includes) ;
+ INCLUDES $(targets) : $(includes) ;
+ ISFILE $(includes) ;
+ }
+ }
+
+ PYTHON_IMPORT_RULE bootstrap : bootstrap : PyBB : bootstrap ;
+ modules.poke PyBB : root : [ NORMALIZE_PATH $(.bootstrap-file:DT)/.. ] ;
+
+ module PyBB
+ {
+ local ok = [ bootstrap $(root) ] ;
+ if ! $(ok)
+ {
+ EXIT ;
+ }
+ }
+
+
+ #PYTHON_IMPORT_RULE boost.build.build_system : main : PyBB : main ;
+
+ #module PyBB
+ #{
+ # main ;
+ #}
+
+ }
+}
diff --git a/tools/build/v2/kernel/bootstrap.py b/tools/build/v2/kernel/bootstrap.py
new file mode 100644
index 0000000000..2e8dd37b7b
--- /dev/null
+++ b/tools/build/v2/kernel/bootstrap.py
@@ -0,0 +1,25 @@
+# Copyright 2009 Vladimir Prus
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import imp
+import sys
+
+def bootstrap(root_path):
+ """Performs python-side bootstrapping of Boost.Build/Python.
+
+ This function arranges for 'b2.whatever' package names to work, while also
+ allowing to put python files alongside corresponding jam modules.
+ """
+
+ m = imp.new_module("b2")
+ # Note that:
+ # 1. If __path__ is not list of strings, nothing will work
+ # 2. root_path is already list of strings.
+ m.__path__ = root_path
+ sys.modules["b2"] = m
+
+ import b2.build_system
+ return b2.build_system.main()
+
diff --git a/tools/build/v2/kernel/class.jam b/tools/build/v2/kernel/class.jam
new file mode 100644
index 0000000000..b8e55af355
--- /dev/null
+++ b/tools/build/v2/kernel/class.jam
@@ -0,0 +1,420 @@
+# Copyright 2001, 2002, 2003 Dave Abrahams
+# Copyright 2002, 2005 Rene Rivera
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Polymorphic class system built on top of core Jam facilities.
+#
+# Classes are defined by 'class' keywords::
+#
+# class myclass
+# {
+# rule __init__ ( arg1 ) # constructor
+# {
+# self.attribute = $(arg1) ;
+# }
+#
+# rule method1 ( ) # method
+# {
+# return [ method2 ] ;
+# }
+#
+# rule method2 ( ) # method
+# {
+# return $(self.attribute) ;
+# }
+# }
+#
+# The __init__ rule is the constructor, and sets member variables.
+#
+# New instances are created by invoking [ new <class> <args...> ]:
+#
+# local x = [ new myclass foo ] ; # x is a new myclass object
+# assert.result foo : [ $(x).method1 ] ; # $(x).method1 returns "foo"
+#
+# Derived class are created by mentioning base classes in the declaration::
+#
+# class derived : myclass
+# {
+# rule __init__ ( arg )
+# {
+# myclass.__init__ $(arg) ; # call base __init__
+#
+# }
+#
+# rule method2 ( ) # method override
+# {
+# return $(self.attribute)XXX ;
+# }
+# }
+#
+# All methods operate virtually, replacing behavior in the base classes. For
+# example::
+#
+# local y = [ new derived foo ] ; # y is a new derived object
+# assert.result fooXXX : [ $(y).method1 ] ; # $(y).method1 returns "foo"
+#
+# Each class instance is its own core Jam module. All instance attributes and
+# methods are accessible without additional qualification from within the class
+# instance. All rules imported in class declaration, or visible in base classses
+# are also visible. Base methods are available in qualified form:
+# base-name.method-name. By convention, attribute names are prefixed with
+# "self.".
+
+import modules ;
+import numbers ;
+
+
+rule xinit ( instance : class )
+{
+ module $(instance)
+ {
+ __class__ = $(2) ;
+ __name__ = $(1) ;
+ }
+}
+
+
+rule new ( class args * : * )
+{
+ .next-instance ?= 1 ;
+ local id = object($(class))@$(.next-instance) ;
+
+ xinit $(id) : $(class) ;
+
+ INSTANCE $(id) : class@$(class) ;
+ IMPORT_MODULE $(id) ;
+ $(id).__init__ $(args) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+
+ # Bump the next unique object name.
+ .next-instance = [ numbers.increment $(.next-instance) ] ;
+
+ # Return the name of the new instance.
+ return $(id) ;
+}
+
+
+rule bases ( class )
+{
+ module class@$(class)
+ {
+ return $(__bases__) ;
+ }
+}
+
+
+rule is-derived ( class : bases + )
+{
+ local stack = $(class) ;
+ local visited found ;
+ while ! $(found) && $(stack)
+ {
+ local top = $(stack[1]) ;
+ stack = $(stack[2-]) ;
+ if ! ( $(top) in $(visited) )
+ {
+ visited += $(top) ;
+ stack += [ bases $(top) ] ;
+
+ if $(bases) in $(visited)
+ {
+ found = true ;
+ }
+ }
+ }
+ return $(found) ;
+}
+
+
+# Returns true if the 'value' is a class instance.
+#
+rule is-instance ( value )
+{
+ return [ MATCH "^(object\\()[^@]+\\)@.*" : $(value) ] ;
+}
+
+
+# Check if the given value is of the given type.
+#
+rule is-a (
+ instance # The value to check.
+ : type # The type to test for.
+)
+{
+ if [ is-instance $(instance) ]
+ {
+ return [ class.is-derived [ modules.peek $(instance) : __class__ ] : $(type) ] ;
+ }
+}
+
+
+local rule typecheck ( x )
+{
+ local class-name = [ MATCH "^\\[(.*)\\]$" : [ BACKTRACE 1 ] ] ;
+ if ! [ is-a $(x) : $(class-name) ]
+ {
+ return "Expected an instance of "$(class-name)" but got \""$(x)"\" for argument" ;
+ }
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+ import "class" : new ;
+
+ # This will be the construction function for a class called 'myclass'.
+ #
+ class myclass
+ {
+ import assert ;
+
+ rule __init__ ( x_ * : y_ * )
+ {
+ # Set some instance variables.
+ x = $(x_) ;
+ y = $(y_) ;
+ foo += 10 ;
+ }
+
+ rule set-x ( newx * )
+ {
+ x = $(newx) ;
+ }
+
+ rule get-x ( )
+ {
+ return $(x) ;
+ }
+
+ rule set-y ( newy * )
+ {
+ y = $(newy) ;
+ }
+
+ rule get-y ( )
+ {
+ return $(y) ;
+ }
+
+ rule f ( )
+ {
+ return [ g $(x) ] ;
+ }
+
+ rule g ( args * )
+ {
+ if $(x) in $(y)
+ {
+ return $(x) ;
+ }
+ else if $(y) in $(x)
+ {
+ return $(y) ;
+ }
+ else
+ {
+ return ;
+ }
+ }
+
+ rule get-class ( )
+ {
+ return $(__class__) ;
+ }
+
+ rule get-instance ( )
+ {
+ return $(__name__) ;
+ }
+
+ rule invariant ( )
+ {
+ assert.equal 1 : 1 ;
+ }
+
+ rule get-foo ( )
+ {
+ return $(foo) ;
+ }
+ }
+# class myclass ;
+
+ class derived1 : myclass
+ {
+ rule __init__ ( z_ )
+ {
+ myclass.__init__ $(z_) : X ;
+ z = $(z_) ;
+ }
+
+ # Override g.
+ #
+ rule g ( args * )
+ {
+ return derived1.g ;
+ }
+
+ rule h ( )
+ {
+ return derived1.h ;
+ }
+
+ rule get-z ( )
+ {
+ return $(z) ;
+ }
+
+ # Check that 'assert.equal' visible in base class is visible here.
+ #
+ rule invariant2 ( )
+ {
+ assert.equal 2 : 2 ;
+ }
+
+ # Check that 'assert.variable-not-empty' visible in base class is
+ # visible here.
+ #
+ rule invariant3 ( )
+ {
+ local v = 10 ;
+ assert.variable-not-empty v ;
+ }
+ }
+# class derived1 : myclass ;
+
+ class derived2 : myclass
+ {
+ rule __init__ ( )
+ {
+ myclass.__init__ 1 : 2 ;
+ }
+
+ # Override g.
+ #
+ rule g ( args * )
+ {
+ return derived2.g ;
+ }
+
+ # Test the ability to call base class functions with qualification.
+ #
+ rule get-x ( )
+ {
+ return [ myclass.get-x ] ;
+ }
+ }
+# class derived2 : myclass ;
+
+ class derived2a : derived2
+ {
+ rule __init__
+ {
+ derived2.__init__ ;
+ }
+ }
+# class derived2a : derived2 ;
+
+ local rule expect_derived2 ( [derived2] x ) { }
+
+ local a = [ new myclass 3 4 5 : 4 5 ] ;
+ local b = [ new derived1 4 ] ;
+ local b2 = [ new derived1 4 ] ;
+ local c = [ new derived2 ] ;
+ local d = [ new derived2 ] ;
+ local e = [ new derived2a ] ;
+
+ expect_derived2 $(d) ;
+ expect_derived2 $(e) ;
+
+ # Argument checking is set up to call exit(1) directly on failure, and we
+ # can not hijack that with try, so we should better not do this test by
+ # default. We could fix this by having errors look up and invoke the EXIT
+ # rule instead; EXIT can be hijacked (;-)
+ if --fail-typecheck in [ modules.peek : ARGV ]
+ {
+ try ;
+ {
+ expect_derived2 $(a) ;
+ }
+ catch
+ "Expected an instance of derived2 but got" instead
+ ;
+ }
+
+ #try ;
+ #{
+ # new bad_subclass ;
+ #}
+ #catch
+ # bad_subclass.bad_subclass failed to call base class constructor myclass.__init__
+ # ;
+
+ #try ;
+ #{
+ # class bad_subclass ;
+ #}
+ #catch bad_subclass has already been declared ;
+
+ assert.result 3 4 5 : $(a).get-x ;
+ assert.result 4 5 : $(a).get-y ;
+ assert.result 4 : $(b).get-x ;
+ assert.result X : $(b).get-y ;
+ assert.result 4 : $(b).get-z ;
+ assert.result 1 : $(c).get-x ;
+ assert.result 2 : $(c).get-y ;
+ assert.result 4 5 : $(a).f ;
+ assert.result derived1.g : $(b).f ;
+ assert.result derived2.g : $(c).f ;
+ assert.result derived2.g : $(d).f ;
+
+ assert.result 10 : $(b).get-foo ;
+
+ $(a).invariant ;
+ $(b).invariant2 ;
+ $(b).invariant3 ;
+
+ # Check that the __class__ attribute is getting properly set.
+ assert.result myclass : $(a).get-class ;
+ assert.result derived1 : $(b).get-class ;
+ assert.result $(a) : $(a).get-instance ;
+
+ $(a).set-x a.x ;
+ $(b).set-x b.x ;
+ $(c).set-x c.x ;
+ $(d).set-x d.x ;
+ assert.result a.x : $(a).get-x ;
+ assert.result b.x : $(b).get-x ;
+ assert.result c.x : $(c).get-x ;
+ assert.result d.x : $(d).get-x ;
+
+ class derived3 : derived1 derived2
+ {
+ rule __init__ ( )
+ {
+ }
+ }
+
+ assert.result : bases myclass ;
+ assert.result myclass : bases derived1 ;
+ assert.result myclass : bases derived2 ;
+ assert.result derived1 derived2 : bases derived3 ;
+
+ assert.true is-derived derived1 : myclass ;
+ assert.true is-derived derived2 : myclass ;
+ assert.true is-derived derived3 : derived1 ;
+ assert.true is-derived derived3 : derived2 ;
+ assert.true is-derived derived3 : derived1 derived2 myclass ;
+ assert.true is-derived derived3 : myclass ;
+
+ assert.false is-derived myclass : derived1 ;
+
+ assert.true is-instance $(a) ;
+ assert.false is-instance bar ;
+
+ assert.true is-a $(a) : myclass ;
+ assert.true is-a $(c) : derived2 ;
+ assert.true is-a $(d) : myclass ;
+ assert.false is-a literal : myclass ;
+}
diff --git a/tools/build/v2/kernel/errors.jam b/tools/build/v2/kernel/errors.jam
new file mode 100644
index 0000000000..63b11e8674
--- /dev/null
+++ b/tools/build/v2/kernel/errors.jam
@@ -0,0 +1,274 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Print a stack backtrace leading to this rule's caller. Each argument
+# represents a line of output to be printed after the first line of the
+# backtrace.
+#
+rule backtrace ( skip-frames prefix messages * : * )
+{
+ local frame-skips = 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61 65 69 73 77 81 ;
+ local drop-elements = $(frame-skips[$(skip-frames)]) ;
+ if ! ( $(skip-frames) in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 )
+ {
+ ECHO "warning: backtrace doesn't support skipping $(skip-frames) frames;"
+ "using 1 instead." ;
+ drop-elements = 5 ;
+ }
+
+ local args = $(.args) ;
+ if $(.user-modules-only)
+ {
+ local bt = [ nearest-user-location ] ;
+ ECHO "$(prefix) at $(bt) " ;
+ for local n in $(args)
+ {
+ if $($(n))-is-not-empty
+ {
+ ECHO $(prefix) $($(n)) ;
+ }
+ }
+ }
+ else
+ {
+ # Get the whole backtrace, then drop the initial quadruples
+ # corresponding to the frames that must be skipped.
+ local bt = [ BACKTRACE ] ;
+ bt = $(bt[$(drop-elements)-]) ;
+
+ while $(bt)
+ {
+ local m = [ MATCH ^(.+)\\.$ : $(bt[3]) ] ;
+ ECHO $(bt[1]):$(bt[2]): "in" $(bt[4]) "from module" $(m) ;
+
+ # The first time through, print each argument on a separate line.
+ for local n in $(args)
+ {
+ if $($(n))-is-not-empty
+ {
+ ECHO $(prefix) $($(n)) ;
+ }
+ }
+ args = ; # Kill args so that this never happens again.
+
+ # Move on to the next quadruple.
+ bt = $(bt[5-]) ;
+ }
+ }
+}
+
+.args ?= messages 2 3 4 5 6 7 8 9 ;
+.disabled ?= ;
+.last-error-$(.args) ?= ;
+
+
+# try-catch --
+#
+# This is not really an exception-handling mechanism, but it does allow us to
+# perform some error-checking on our error-checking. Errors are suppressed after
+# a try, and the first one is recorded. Use catch to check that the error
+# message matched expectations.
+
+# Begin looking for error messages.
+#
+rule try ( )
+{
+ .disabled += true ;
+ .last-error-$(.args) = ;
+}
+
+
+# Stop looking for error messages; generate an error if an argument of messages
+# is not found in the corresponding argument in the error call.
+#
+rule catch ( messages * : * )
+{
+ .disabled = $(.disabled[2-]) ; # Pop the stack.
+
+ import sequence ;
+
+ if ! $(.last-error-$(.args))-is-not-empty
+ {
+ error-skip-frames 3 expected an error, but none occurred ;
+ }
+ else
+ {
+ for local n in $(.args)
+ {
+ if ! $($(n)) in $(.last-error-$(n))
+ {
+ local v = [ sequence.join $($(n)) : " " ] ;
+ v ?= "" ;
+ local joined = [ sequence.join $(.last-error-$(n)) : " " ] ;
+
+ .last-error-$(.args) = ;
+ error-skip-frames 3 expected \"$(v)\" in argument $(n) of error
+ : got \"$(joined)\" instead ;
+ }
+ }
+ }
+}
+
+
+rule error-skip-frames ( skip-frames messages * : * )
+{
+ if ! $(.disabled)
+ {
+ backtrace $(skip-frames) error: $(messages) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ EXIT ;
+ }
+ else if ! $(.last-error-$(.args))
+ {
+ for local n in $(.args)
+ {
+ # Add an extra empty string so that we always have
+ # something in the event of an error
+ .last-error-$(n) = $($(n)) "" ;
+ }
+ }
+}
+
+if --no-error-backtrace in [ modules.peek : ARGV ]
+{
+ .no-error-backtrace = true ;
+}
+
+
+# Print an error message with a stack backtrace and exit.
+#
+rule error ( messages * : * )
+{
+ if $(.no-error-backtrace)
+ {
+ # Print each argument on a separate line.
+ for local n in $(.args)
+ {
+ if $($(n))-is-not-empty
+ {
+ if ! $(first-printed)
+ {
+ ECHO error: $($(n)) ;
+ first-printed = true ;
+ }
+ else
+ {
+ ECHO $($(n)) ;
+ }
+ }
+ }
+ EXIT ;
+ }
+ else
+ {
+ error-skip-frames 3 $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+}
+
+
+# Same as 'error', but the generated backtrace will include only user files.
+#
+rule user-error ( messages * : * )
+{
+ .user-modules-only = 1 ;
+ error-skip-frames 3 $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+}
+
+
+# Print a warning message with a stack backtrace and exit.
+#
+rule warning
+{
+ backtrace 2 warning: $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+}
+
+
+# Convert an arbitrary argument list into a list with ":" separators and quoted
+# elements representing the same information. This is mostly useful for
+# formatting descriptions of arguments with which a rule was called when
+# reporting an error.
+#
+rule lol->list ( * )
+{
+ local result ;
+ local remaining = 1 2 3 4 5 6 7 8 9 ;
+ while $($(remaining))
+ {
+ local n = $(remaining[1]) ;
+ remaining = $(remaining[2-]) ;
+
+ if $(n) != 1
+ {
+ result += ":" ;
+ }
+ result += \"$($(n))\" ;
+ }
+ return $(result) ;
+}
+
+
+# Return the file:line for the nearest entry in backtrace which correspond to a
+# user module.
+#
+rule nearest-user-location ( )
+{
+ local bt = [ BACKTRACE ] ;
+
+ local result ;
+ while $(bt) && ! $(result)
+ {
+ local m = [ MATCH ^(.+)\\.$ : $(bt[3]) ] ;
+ local user-modules = ([Jj]amroot(.jam|.v2|)|([Jj]amfile(.jam|.v2|)|user-config.jam|site-config.jam|project-root.jam) ;
+
+ if [ MATCH $(user-modules) : $(bt[1]:D=) ]
+ {
+ result = $(bt[1]):$(bt[2]) ;
+ }
+ bt = $(bt[5-]) ;
+ }
+ return $(result) ;
+}
+
+
+# If optimized rule is available in Jam, use it.
+if NEAREST_USER_LOCATION in [ RULENAMES ]
+{
+ rule nearest-user-location ( )
+ {
+ local r = [ NEAREST_USER_LOCATION ] ;
+ return $(r[1]):$(r[2]) ;
+ }
+}
+
+
+rule __test__ ( )
+{
+ # Show that we can correctly catch an expected error.
+ try ;
+ {
+ error an error occurred : somewhere ;
+ }
+ catch an error occurred : somewhere ;
+
+ # Show that unexpected errors generate real errors.
+ try ;
+ {
+ try ;
+ {
+ error an error occurred : somewhere ;
+ }
+ catch an error occurred : nowhere ;
+ }
+ catch expected \"nowhere\" in argument 2 ;
+
+ # Show that not catching an error where one was expected is an error.
+ try ;
+ {
+ try ;
+ {
+ }
+ catch ;
+ }
+ catch expected an error, but none occurred ;
+}
diff --git a/tools/build/v2/kernel/modules.jam b/tools/build/v2/kernel/modules.jam
new file mode 100644
index 0000000000..1f75354fc2
--- /dev/null
+++ b/tools/build/v2/kernel/modules.jam
@@ -0,0 +1,354 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Essentially an include guard; ensures that no module is loaded multiple times.
+.loaded ?= ;
+
+# A list of modules currently being loaded for error reporting of circular
+# dependencies.
+.loading ?= ;
+
+# A list of modules needing to be tested using their __test__ rule.
+.untested ?= ;
+
+# A list of modules which have been tested using their __test__ rule.
+.tested ?= ;
+
+
+# Runs internal Boost Build unit tests for the specified module. The module's
+# __test__ rule is executed in its own module to eliminate any inadvertent
+# effects of testing module dependencies (such as assert) on the module itself.
+#
+local rule run-module-test ( m )
+{
+ local tested-modules = [ modules.peek modules : .tested ] ;
+
+ if ( ! $(m) in $(tested-modules) ) # Avoid recursive test invocations.
+ && ( ( --debug in $(argv) ) || ( --debug-module=$(m) in $(argv) ) )
+ {
+ modules.poke modules : .tested : $(tested-modules) $(m) ;
+
+ if ! ( __test__ in [ RULENAMES $(m) ] )
+ {
+ local argv = [ peek : ARGV ] ;
+ if ! ( --quiet in $(argv) ) && ( --debug-tests in $(argv) )
+ {
+ ECHO warning: no __test__ rule defined in module $(m) ;
+ }
+ }
+ else
+ {
+ if ! ( --quiet in $(argv) )
+ {
+ ECHO testing module $(m)... ;
+ }
+
+ local test-module = __test-$(m)__ ;
+ IMPORT $(m) : [ RULENAMES $(m) ] : $(test-module) : [ RULENAMES $(m) ] ;
+ IMPORT $(m) : __test__ : $(test-module) : __test__ : LOCALIZE ;
+ module $(test-module)
+ {
+ __test__ ;
+ }
+ }
+ }
+}
+
+
+# Return the binding of the given module.
+#
+rule binding ( module )
+{
+ return $($(module).__binding__) ;
+}
+
+
+# Sets the module-local value of a variable. This is the most reliable way to
+# set a module-local variable in a different module; it eliminates issues of
+# name shadowing due to dynamic scoping.
+#
+rule poke ( module-name ? : variables + : value * )
+{
+ module $(<)
+ {
+ $(>) = $(3) ;
+ }
+}
+
+
+# Returns the module-local value of a variable. This is the most reliable way to
+# examine a module-local variable in a different module; it eliminates issues of
+# name shadowing due to dynamic scoping.
+#
+rule peek ( module-name ? : variables + )
+{
+ module $(<)
+ {
+ return $($(>)) ;
+ }
+}
+
+
+# Call the given rule locally in the given module. Use this for rules accepting
+# rule names as arguments, so that the passed rule may be invoked in the context
+# of the rule's caller (for example, if the rule accesses module globals or is a
+# local rule). Note that rules called this way may accept at most 8 parameters.
+#
+rule call-in ( module-name ? : rule-name args * : * )
+{
+ module $(module-name)
+ {
+ return [ $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+}
+
+
+# Given a possibly qualified rule name and arguments, remove any initial module
+# qualification from the rule and invoke it in that module. If there is no
+# module qualification, the rule is invoked in the global module. Note that
+# rules called this way may accept at most 8 parameters.
+#
+rule call-locally ( qualified-rule-name args * : * )
+{
+ local module-rule = [ MATCH (.*)\\.(.*) : $(qualified-rule-name) ] ;
+ local rule-name = $(module-rule[2]) ;
+ rule-name ?= $(qualified-rule-name) ;
+ # We pass only 8 parameters here since Boost Jam allows at most 9 rule
+ # parameter positions and the call-in rule already uses up the initial
+ # position for the module name.
+ return [ call-in $(module-rule[1]) : $(rule-name) $(args) : $(2) : $(3) :
+ $(4) : $(5) : $(6) : $(7) : $(8) ] ;
+}
+
+
+# Load the indicated module if it is not already loaded.
+#
+rule load (
+ module-name # Name of module to load. Rules will be defined in this
+ # module.
+ : filename ? # (partial) path to file; Defaults to $(module-name).jam.
+ : search * # Directories in which to search for filename. Defaults to
+ # $(BOOST_BUILD_PATH).
+)
+{
+ # Avoid loading modules twice.
+ if ! ( $(module-name) in $(.loaded) )
+ {
+ filename ?= $(module-name).jam ;
+
+ # Mark the module loaded so we do not try to load it recursively.
+ .loaded += $(module-name) ;
+
+ # Suppress tests if any module loads are already in progress.
+ local suppress-test = $(.loading[1]) ;
+
+ # Push this module on the loading stack.
+ .loading += $(module-name) ;
+
+ # Remember that it is untested.
+ .untested += $(module-name) ;
+
+ # Insert the new module's __name__ and __file__ globals.
+ poke $(module-name) : __name__ : $(module-name) ;
+ poke $(module-name) : __file__ : $(filename) ;
+
+ module $(module-name)
+ {
+ # Add some grist so that the module will have a unique target name.
+ local module-target = $(__file__:G=module@) ;
+
+ local search = $(3) ;
+ search ?= [ modules.peek : BOOST_BUILD_PATH ] ;
+ SEARCH on $(module-target) = $(search) ;
+ BINDRULE on $(module-target) = modules.record-binding ;
+
+ include $(module-target) ;
+
+ # Allow the module to see its own names with full qualification.
+ local rules = [ RULENAMES $(__name__) ] ;
+ IMPORT $(__name__) : $(rules) : $(__name__) : $(__name__).$(rules) ;
+ }
+
+ if $(module-name) != modules && ! [ binding $(module-name) ]
+ {
+ import errors ;
+ errors.error "Could not find module" $(module-name) in $(search) ;
+ }
+
+ # Pop the loading stack. Must happen before testing or we will run into
+ # a circular loading dependency.
+ .loading = $(.loading[1--2]) ;
+
+ # Run any pending tests if this is an outer load.
+ if ! $(suppress-test)
+ {
+ local argv = [ peek : ARGV ] ;
+ for local m in $(.untested)
+ {
+ run-module-test $(m) ;
+ }
+ .untested = ;
+ }
+ }
+ else if $(module-name) in $(.loading)
+ {
+ import errors ;
+ errors.error loading \"$(module-name)\"
+ : circular module loading dependency:
+ : $(.loading)" ->" $(module-name) ;
+ }
+}
+
+
+# This helper is used by load (above) to record the binding (path) of each
+# loaded module.
+#
+rule record-binding ( module-target : binding )
+{
+ $(.loading[-1]).__binding__ = $(binding) ;
+}
+
+
+# Transform each path in the list, with all backslashes converted to forward
+# slashes and all detectable redundancy removed. Something like this is probably
+# needed in path.jam, but I am not sure of that, I do not understand it, and I
+# am not ready to move all of path.jam into the kernel.
+#
+local rule normalize-raw-paths ( paths * )
+{
+ local result ;
+ for p in $(paths:T)
+ {
+ result += [ NORMALIZE_PATH $(p) ] ;
+ }
+ return $(result) ;
+}
+
+
+.cwd = [ PWD ] ;
+
+
+# Load the indicated module and import rule names into the current module. Any
+# members of rules-opt will be available without qualification in the caller's
+# module. Any members of rename-opt will be taken as the names of the rules in
+# the caller's module, in place of the names they have in the imported module.
+# If rules-opt = '*', all rules from the indicated module are imported into the
+# caller's module. If rename-opt is supplied, it must have the same number of
+# elements as rules-opt.
+#
+rule import ( module-names + : rules-opt * : rename-opt * )
+{
+ if ( $(rules-opt) = * || ! $(rules-opt) ) && $(rename-opt)
+ {
+ import errors ;
+ errors.error "Rule aliasing is only available for explicit imports." ;
+ }
+
+ if $(module-names[2]) && ( $(rules-opt) || $(rename-opt) )
+ {
+ import errors ;
+ errors.error "When loading multiple modules, no specific rules or"
+ "renaming is allowed" ;
+ }
+
+ local caller = [ CALLER_MODULE ] ;
+
+ # Import each specified module
+ for local m in $(module-names)
+ {
+ if ! $(m) in $(.loaded)
+ {
+ # If the importing module isn't already in the BOOST_BUILD_PATH,
+ # prepend it to the path. We don't want to invert the search order
+ # of modules that are already there.
+
+ local caller-location ;
+ if $(caller)
+ {
+ caller-location = [ binding $(caller) ] ;
+ caller-location = $(caller-location:D) ;
+ caller-location = [ normalize-raw-paths $(caller-location:R=$(.cwd)) ] ;
+ }
+
+ local search = [ peek : BOOST_BUILD_PATH ] ;
+ search = [ normalize-raw-paths $(search:R=$(.cwd)) ] ;
+
+ if $(caller-location) && ! $(caller-location) in $(search)
+ {
+ search = $(caller-location) $(search) ;
+ }
+
+ load $(m) : : $(search) ;
+ }
+
+ IMPORT_MODULE $(m) : $(caller) ;
+
+ if $(rules-opt)
+ {
+ local source-names ;
+ if $(rules-opt) = *
+ {
+ local all-rules = [ RULENAMES $(m) ] ;
+ source-names = $(all-rules) ;
+ }
+ else
+ {
+ source-names = $(rules-opt) ;
+ }
+ local target-names = $(rename-opt) ;
+ target-names ?= $(source-names) ;
+ IMPORT $(m) : $(source-names) : $(caller) : $(target-names) ;
+ }
+ }
+}
+
+
+# Define exported copies in $(target-module) of all rules exported from
+# $(source-module). Also make them available in the global module with
+# qualification, so that it is just as though the rules were defined originally
+# in $(target-module).
+#
+rule clone-rules ( source-module target-module )
+{
+ local rules = [ RULENAMES $(source-module) ] ;
+
+ IMPORT $(source-module) : $(rules) : $(target-module) : $(rules) : LOCALIZE ;
+ EXPORT $(target-module) : $(rules) ;
+ IMPORT $(target-module) : $(rules) : : $(target-module).$(rules) ;
+}
+
+
+# These rules need to be available in all modules to implement module loading
+# itself and other fundamental operations.
+local globalize = peek poke record-binding ;
+IMPORT modules : $(globalize) : : modules.$(globalize) ;
+
+
+rule __test__ ( )
+{
+ import assert ;
+ import modules : normalize-raw-paths ;
+
+ module modules.__test__
+ {
+ foo = bar ;
+ }
+
+ assert.result bar : peek modules.__test__ : foo ;
+
+ poke modules.__test__ : foo : bar baz ;
+ assert.result bar baz : peek modules.__test__ : foo ;
+
+ assert.result c:/foo/bar : normalize-raw-paths c:/x/../foo/./xx/yy/../../bar ;
+ assert.result . : normalize-raw-paths . ;
+ assert.result .. : normalize-raw-paths .. ;
+ assert.result ../.. : normalize-raw-paths ../.. ;
+ assert.result .. : normalize-raw-paths ./.. ;
+ assert.result / / : normalize-raw-paths / \\ ;
+ assert.result a : normalize-raw-paths a ;
+ assert.result a : normalize-raw-paths a/ ;
+ assert.result /a : normalize-raw-paths /a/ ;
+ assert.result / : normalize-raw-paths /a/.. ;
+}
diff --git a/tools/build/v2/manager.py b/tools/build/v2/manager.py
new file mode 100644
index 0000000000..473857fc76
--- /dev/null
+++ b/tools/build/v2/manager.py
@@ -0,0 +1,110 @@
+# Copyright Pedro Ferreira 2005. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import bjam
+
+# To simplify implementation of tools level, we'll
+# have a global variable keeping the current manager.
+the_manager = None
+def get_manager():
+ return the_manager
+
+class Manager:
+ """ This class is a facade to the Boost.Build system.
+ It serves as the root to access all data structures in use.
+ """
+
+ def __init__ (self, engine, global_build_dir):
+ """ Constructor.
+ engine: the build engine that will actually construct the targets.
+ """
+ from build.virtual_target import VirtualTargetRegistry
+ from build.targets import TargetRegistry
+ from build.project import ProjectRegistry
+ from build.scanner import ScannerRegistry
+ from build.errors import Errors
+ from b2.util.logger import NullLogger
+ from build import build_request, property_set, feature
+
+ self.engine_ = engine
+ self.virtual_targets_ = VirtualTargetRegistry (self)
+ self.projects_ = ProjectRegistry (self, global_build_dir)
+ self.targets_ = TargetRegistry ()
+ self.logger_ = NullLogger ()
+ self.scanners_ = ScannerRegistry (self)
+ self.argv_ = bjam.variable("ARGV")
+ self.boost_build_path_ = bjam.variable("BOOST_BUILD_PATH")
+ self.errors_ = Errors()
+ self.command_line_free_features_ = property_set.empty()
+
+ global the_manager
+ the_manager = self
+
+ def scanners (self):
+ return self.scanners_
+
+ def engine (self):
+ return self.engine_
+
+ def virtual_targets (self):
+ return self.virtual_targets_
+
+ def targets (self):
+ return self.targets_
+
+ def projects (self):
+ return self.projects_
+
+ def argv (self):
+ return self.argv_
+
+ def logger (self):
+ return self.logger_
+
+ def set_logger (self, logger):
+ self.logger_ = logger
+
+ def errors (self):
+ return self.errors_
+
+ def getenv(self, name):
+ return bjam.variable(name)
+
+ def boost_build_path(self):
+ return self.boost_build_path_
+
+ def command_line_free_features(self):
+ return self.command_line_free_features_
+
+ def set_command_line_free_features(self, v):
+ self.command_line_free_features_ = v
+
+ def construct (self, properties = [], targets = []):
+ """ Constructs the dependency graph.
+ properties: the build properties.
+ targets: the targets to consider. If none is specified, uses all.
+ """
+ if not targets:
+ for name, project in self.projects ().projects ():
+ targets.append (project.target ())
+
+ property_groups = build_request.expand_no_defaults (properties)
+
+ virtual_targets = []
+ build_prop_sets = []
+ for p in property_groups:
+ build_prop_sets.append (property_set.create (feature.split (p)))
+
+ if not build_prop_sets:
+ build_prop_sets = [property_set.empty ()]
+
+ for build_properties in build_prop_sets:
+ for target in targets:
+ result = target.generate (build_properties)
+ virtual_targets.extend (result.targets ())
+
+ actual_targets = []
+ for virtual_target in virtual_targets:
+ actual_targets.extend (virtual_target.actualize ())
+
diff --git a/tools/build/v2/nightly.sh b/tools/build/v2/nightly.sh
new file mode 100755
index 0000000000..0d9f310c05
--- /dev/null
+++ b/tools/build/v2/nightly.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# Copyright 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This script create a nightly tarball of Boost.Build V2
+# and updates the web site.
+
+# Create the packages
+set -e
+trap "echo 'Nightly build failed'" ERR
+
+export QTDIR=/usr/share/qt3
+export LC_ALL=C
+export LC_MESSAGES=C
+export LANG=C
+cd /tmp
+rm -rf boost-build-nightly
+mkdir boost-build-nightly
+echo "Checking out sources"
+svn co http://svn.boost.org/svn/boost/trunk/tools/build/v2 boost-build-nightly/boost-build > /tmp/boost_build_checkout_log
+mv /tmp/boost_build_checkout_log boost-build-nightly/checkout-log
+cd boost-build-nightly/boost-build/
+echo "Building packages and uploading docs"
+./roll.sh > ../roll-log 2>&1
+cd ..
+echo "Uploading packages"
+scp boost-build.zip boost-build.tar.bz2 vladimir_prus,boost@web.sourceforge.net:/home/groups/b/bo/boost/htdocs/boost-build2 > scp-log
+echo "Nightly build successful"
diff --git a/tools/build/v2/notes/README.txt b/tools/build/v2/notes/README.txt
new file mode 100644
index 0000000000..c2e6ff6298
--- /dev/null
+++ b/tools/build/v2/notes/README.txt
@@ -0,0 +1,8 @@
+Copyright 2005 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+This directory contains various development notes. Some of them
+may eventually find the way into documentation, so are purely
+imlementation comments.
diff --git a/tools/build/v2/notes/build_dir_option.txt b/tools/build/v2/notes/build_dir_option.txt
new file mode 100644
index 0000000000..6dbecaed68
--- /dev/null
+++ b/tools/build/v2/notes/build_dir_option.txt
@@ -0,0 +1,77 @@
+Copyright 2005 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+Summary
+-------
+
+We need a --build-dir option that users building from read-only
+medium can use to force building to some other location. Pretty much
+every project need this functionality, so it's desirable to have it
+out-of-the box, without explicit setup.
+
+Design
+------
+
+We can achieve the desired effect manually by adding something like this
+to Jamroot:
+
+ project .... : build-dir [ my-rule-to-compute-build-dir ] ;
+
+Where 'my-rule-to-compute-build-dir' would look at the --build-dir option.
+
+We need to automate this, but essentially, --build-dir will only affect
+the 'build-dir' attribute of Jamroots.
+
+If Jamroot contains:
+
+ project foo ;
+
+and --build-dir options' value if /tmp/build, then we'll act as if Jamroot
+contained:
+
+ project foo : build-dir /tmp/build/foo ;
+
+If the 'project' rule has explicit 'build-dir':
+
+ project foo : build-dir bin.v2 ;
+
+then with the same value of --build-dir we'd act as if Jamroot contained:
+
+ project foo : build-dir /tmp/build/foo/bin.v2 ;
+
+We can't drop "bin.v2" because it's quite possible that the name of build dir
+have specific meaning. For example, it can be used to separate Boost.Build V1
+and V2 build results.
+
+The --build-dir option has no effect if Jamroot does not define any project id.
+Doing otherwise can lead to nasty problems if we're building two distinct
+projects (that is with two different Jamroot). They'll get the same build
+directory. Most likely, user will see the "duplicate target" error, which is
+generally confusing.
+
+It is expected that any non-trivial project will have top-level "project"
+invocation with non empty id, so the above limitation is not so drastic.
+We'll emit a warning if Jamroot does not define project id, and --build-dir
+is specified.
+
+Here's the exact behavior of the --build-dir option. If we're loading a
+Jamfile (either root or non-root), that declare some project id and some
+build-dir attribute, the following table gives the value of build-dir
+that will actually be used.
+
+-------------------------------------------------------------------------------
+Root? Id Build-dir attribute Resulting build dir
+-------------------------------------------------------------------------------
+yes none * --build-dir is ignored, with warning
+yes 'foo' none /tmp/build/foo
+yes 'foo' 'bin.v2' /tmp/build/foo/bin.v2
+yes 'foo' '/tmp/bar' Error [1]
+no * none --build-dir has no effect, inherited
+ build dir is used
+no * non-empty Error [2]
+-------------------------------------------------------------------------------
+[1] -- not clear what to do
+[2] -- can be made to work, but non-empty build-dir
+attribute in non-root Jamfile does not make much sense even without --build-dir
diff --git a/tools/build/v2/notes/relative_source_paths.txt b/tools/build/v2/notes/relative_source_paths.txt
new file mode 100644
index 0000000000..2f05578932
--- /dev/null
+++ b/tools/build/v2/notes/relative_source_paths.txt
@@ -0,0 +1,76 @@
+Copyright 2005 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+Hi,
+recently, we had a couple of problems caused by using relative file paths, and
+I'd like to discuss what to do.
+
+Let's use the case from CÊdric. Simplified version is:
+
+ exe a : a.cpp dir1/qt_file.h ;
+ exe b : a.cpp dir2/qt_file.h ;
+
+Both exes have the same source cpp file but different *.h files -- which are
+processed by Qt tools. V2 currently strips directory name from all targets,
+so it tries to
+
+ - create "bin/mvsc/debug/moc_qt_file.cpp" from dir1/qt_file.h
+ - create "bin/msvc/debug/moc_qt_file.cpp" from dir2/qt_file.h
+
+There are two solutions that I see:
+
+ 1. Rewrite the code like:
+
+ lib aux : a.cpp
+ exe a : aux dir1/qt_file.h : <location-prefix>a ;
+ exe b : aux dir2/qt_file.h : <location-prefix>b ;
+
+ This way, two version of moc_qt_file.cpp will be generated to different
+ places.
+
+ 2. Rewrite the code like:
+
+ obj a_moc : dir1/qt_file.h : <library>/qt//qt ;
+ exe a : a.cpp a_moc ;
+ obj b_moc : dir2/qt_file.h : <library>/qt//qt ;
+ exe b : a.cpp b_moc ;
+
+ Explicitly changing name for the problematic files.
+
+ 3. Generally change V2 so that directory part of source is preserved. This
+ will generate targets:
+ "bin/msvc/debug/dir1/moc_qt_file.cpp" and
+ "bin/msvc/debug/dir2/moc_qt_file.cpp". No problems.
+
+ However, there are some additional questions:
+
+ - What if source has absolute file name?
+ - What if source is "../../include/qt_file.h"?
+
+ We can ignore directory names in those cases (i.e. use the current
+ behaviour) but that would be a bit inconsistent.
+
+Any opinions?
+
+Pedro Ferreira:
+
+I think this is a corner case and BB should not try to solve everything
+automatically - otherwise it will become really complex.
+I don't see a problem in requiring the user to help the build system by
+using solutions 1 or 2.
+Of course, the better the error reporting, the easier it will be to
+find the cause and the cure of the problem.
+
+TEMPLIE Cedric:
+
+I agree with Pedro. Solution 1 or 2 is the best way to deal with this
+problem. Of course I have a preference for the solution 1, but the
+solution 2 has the advantage to work without any modification...
+
+Toon Knapen:
+
+I agree.
+
+
diff --git a/tools/build/v2/options/help.jam b/tools/build/v2/options/help.jam
new file mode 100644
index 0000000000..b507e1edd6
--- /dev/null
+++ b/tools/build/v2/options/help.jam
@@ -0,0 +1,212 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2003, 2006 Rene Rivera
+# Copyright 2003, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This module is the plug-in handler for the --help and --help-.*
+# command-line options
+import modules ;
+import assert ;
+import doc : do-scan set-option set-output set-output-file print-help-usage print-help-top ;
+import sequence ;
+import set ;
+import project ;
+import print ;
+import os ;
+import version ;
+import path ;
+
+# List of possible modules, but which really aren't.
+#
+.not-modules =
+ boost-build bootstrap site-config test user-config
+ -tools allyourbase boost-base features python stlport testing unit-tests ;
+
+# The help system options are parsed here and handed off to the doc
+# module to translate into documentation requests and actions. The
+# understood options are:
+#
+# --help-disable-<option>
+# --help-doc-options
+# --help-enable-<option>
+# --help-internal
+# --help-options
+# --help-usage
+# --help-output <type>
+# --help-output-file <file>
+# --help [<module-or-class>]
+#
+rule process (
+ command # The option.
+ : values * # The values, starting after the "=".
+ )
+{
+ assert.result --help : MATCH ^(--help).* : $(command) ;
+ local did-help = ;
+ switch $(command)
+ {
+ case --help-internal :
+ local path-to-modules = [ modules.peek : BOOST_BUILD_PATH ] ;
+ path-to-modules ?= . ;
+ local possible-modules = [ GLOB $(path-to-modules) : *\\.jam ] ;
+ local not-modules = [ GLOB $(path-to-modules) : *$(.not-modules)\\.jam ] ;
+ local modules-to-list =
+ [ sequence.insertion-sort
+ [ set.difference $(possible-modules:D=:S=) : $(not-modules:D=:S=) ] ] ;
+ local modules-to-scan ;
+ for local m in $(modules-to-list)
+ {
+ local module-files = [ GLOB $(path-to-modules) : $(m)\\.jam ] ;
+ modules-to-scan += $(module-files[1]) ;
+ }
+ do-scan $(modules-to-scan) : print-help-all ;
+ did-help = true ;
+
+ case --help-enable-* :
+ local option = [ MATCH --help-enable-(.*) : $(command) ] ; option = $(option:L) ;
+ set-option $(option) : enabled ;
+ did-help = true ;
+
+ case --help-disable-* :
+ local option = [ MATCH --help-disable-(.*) : $(command) ] ; option = $(option:L) ;
+ set-option $(option) ;
+ did-help = true ;
+
+ case --help-output :
+ set-output $(values[1]) ;
+ did-help = true ;
+
+ case --help-output-file :
+ set-output-file $(values[1]) ;
+ did-help = true ;
+
+ case --help-doc-options :
+ local doc-module-spec = [ split-symbol doc ] ;
+ do-scan $(doc-module-spec[1]) : print-help-options ;
+ did-help = true ;
+
+ case --help-options :
+ print-help-usage ;
+ did-help = true ;
+
+ case --help :
+ local spec = $(values[1]) ;
+ if $(spec)
+ {
+ local spec-parts = [ split-symbol $(spec) ] ;
+ if $(spec-parts)
+ {
+ if $(spec-parts[2])
+ {
+ do-scan $(spec-parts[1]) : print-help-classes $(spec-parts[2]) ;
+ do-scan $(spec-parts[1]) : print-help-rules $(spec-parts[2]) ;
+ do-scan $(spec-parts[1]) : print-help-variables $(spec-parts[2]) ;
+ }
+ else
+ {
+ do-scan $(spec-parts[1]) : print-help-module ;
+ }
+ }
+ else
+ {
+ EXIT "Unrecognized help option '"$(command)" "$(spec)"'." ;
+ }
+ }
+ else
+ {
+ version.print ;
+ ECHO ;
+ # First print documentation from the current Jamfile, if any.
+ # FIXME: Generally, this duplication of project.jam logic is bad.
+ local names = [ modules.peek project : JAMROOT ]
+ [ modules.peek project : JAMFILE ] ;
+ local project-file = [ path.glob . : $(names) ] ;
+ if ! $(project-file)
+ {
+ project-file = [ path.glob-in-parents . : $(names) ] ;
+ }
+
+ for local p in $(project-file)
+ {
+ do-scan $(p) : print-help-project $(p) ;
+ }
+
+ # Next any user-config help.
+ local user-path = [ os.home-directories ] [ os.environ BOOST_BUILD_PATH ] ;
+ local user-config = [ GLOB $(user-path) : user-config.jam ] ;
+ if $(user-config)
+ {
+ do-scan $(user-config[1]) : print-help-config user $(user-config[1]) ;
+ }
+
+ # Next any site-config help.
+ local site-config = [ GLOB $(user-path) : site-config.jam ] ;
+ if $(site-config)
+ {
+ do-scan $(site-config[1]) : print-help-config site $(site-config[1]) ;
+ }
+
+ # Then the overall help.
+ print-help-top ;
+ }
+ did-help = true ;
+ }
+ if $(did-help)
+ {
+ UPDATE all ;
+ NOCARE all ;
+ }
+ return $(did-help) ;
+}
+
+# Split a reference to a symbol into module and symbol parts.
+#
+local rule split-symbol (
+ symbol # The symbol to split.
+ )
+{
+ local path-to-modules = [ modules.peek : BOOST_BUILD_PATH ] ;
+ path-to-modules ?= . ;
+ local module-name = $(symbol) ;
+ local symbol-name = ;
+ local result = ;
+ while ! $(result)
+ {
+ local module-path = [ GLOB $(path-to-modules) : $(module-name)\\.jam ] ;
+ if $(module-path)
+ {
+ # The 'module-name' in fact refers to module. Return the full
+ # module path and a symbol within it. If 'symbol' passed to this
+ # rule is already module, 'symbol-name' will be empty. Otherwise,
+ # it's initialized on the previous loop iteration.
+ # In case there are several modules by this name,
+ # use the first one.
+ result = $(module-path[1]) $(symbol-name) ;
+ }
+ else
+ {
+ if ! $(module-name:S)
+ {
+ result = - ;
+ }
+ else
+ {
+ local next-symbol-part = [ MATCH ^.(.*) : $(module-name:S) ] ;
+ if $(symbol-name)
+ {
+ symbol-name = $(next-symbol-part).$(symbol-name) ;
+ }
+ else
+ {
+ symbol-name = $(next-symbol-part) ;
+ }
+ module-name = $(module-name:B) ;
+ }
+ }
+ }
+ if $(result) != -
+ {
+ return $(result) ;
+ }
+}
diff --git a/tools/build/v2/release_procedure.txt b/tools/build/v2/release_procedure.txt
new file mode 100644
index 0000000000..007921a614
--- /dev/null
+++ b/tools/build/v2/release_procedure.txt
@@ -0,0 +1,83 @@
+Copyright 2003, 2005, 2006 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+ Boost.Build V2 release procedure.
+
+[ Must be done from a Unix shell ]
+
+0. Look for all issues for current milestone in the tracker. Close the fixed one,
+ if not already closed. Move to a later milestone, or fix all the unfixed
+ ones.
+
+ Make sure that "bjam --version" output is correct. Update version string if
+ needed. Update bjam version and the version check is necessary.
+ Check the download locations in "index.html". Check that "last modified"
+ string in index.html is correct.
+
+1. Make sure you don't have any local modification, and create SVN directory
+
+ https://svn.boost.org/svn/boost/branches/build/Milestone_X
+
+ Then, copy:
+
+ https://svn.boost.org/svn/boost/trunk/tools/build
+ https://svn.boost.org/svn/boost/trunk/tools/jam
+
+ to that directory.
+
+2. Run
+
+ svn co https://svn.boost.org/svn/boost/branches/build/Milestone_X boost-build
+
+3. Go to "boost-build/build/v2" directory.
+
+4. Run "./roll.sh". This will create "boost-build.zip" and
+ "boost-build.tar.bz2" in parent directory, and also upload
+ new docs to sourceforge.
+
+5. Unpack "boost-build.tar.bz2", and build jam.
+
+6. Go to "test" and copy "test-config-example.jam" to "test-config.jam".
+ If you're not ghost, edit test-config.jam to specify all the right paths.
+ Run gcc tests:
+
+ python test_all.py gcc --extras
+
+7. Build all projects in examples-v2, using the bjam binary created at step 4.
+ Note: "threading=multi" might be needed to build QT examples.
+
+8. Make SF release:
+
+ - Go to
+ https://sourceforge.net/project/admin/editpackages.php?group_id=7586
+
+ - Create new Boost.Build release. Name it 2.0-mXX
+
+ - Upload the changelog. Be sure to turn the "Preserve my pre-formatted
+ text" checkbox.
+
+ - Rename previously built packages to boost-build-2.0-mXX.tar.bz2
+ and boost-build-2.0-mXX.zip. Upload them to the
+ /incoming directory on ftp://upload.sourceforge.net
+
+ - Add those file to release, edit file properties.
+
+ - In a separate browser, verify changelog is not damaged.
+
+ - In a separate browser, Download the files and verify checksums.
+
+ - In SF file release interface, send email notice.
+
+9. Announce the release, etc.
+
+10. Login to SF and update the current-release redirects in
+ /home/groups/b/bo/boost/htdocs/boost-build2/.htaccess.
+
+11. If any issues were found during release in this document or in
+ test-config-example.jam, commit those changes. The release need
+ not be redone, but changes must be comitted.
+
+12. Set release date in changes.txt and commit.
+
diff --git a/tools/build/v2/roll.sh b/tools/build/v2/roll.sh
new file mode 100755
index 0000000000..4a8f52ec4b
--- /dev/null
+++ b/tools/build/v2/roll.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# Copyright 2004 Aleksey Gurtovoy
+# Copyright 2006 Rene Rivera
+# Copyright 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+set -e
+
+# Capture the version
+revision=`svnversion .`
+echo "SVN Revision $revision" >> timestamp.txt
+date >> timestamp.txt
+
+# This one is not fully finished
+rm -rf example/versioned
+
+# Remove unnecessary top-level files
+find . -maxdepth 1 -type f | egrep -v "boost-build.jam|timestamp.txt|roll.sh|bootstrap.jam|build-system.jam|boost_build.png|index.html|hacking.txt|site-config.jam|user-config.jam|bootstrap.sh|bootstrap.bat|Jamroot.jam" | xargs rm -f
+
+# Build the documentation
+touch doc/jamroot.jam
+export BOOST_BUILD_PATH=`pwd`
+./bootstrap.sh
+cd doc
+../bjam --v2
+../bjam --v2 pdf
+cp `find bin -name "*.pdf"` ../..
+mv ../../standalone.pdf ../../userman.pdf
+cp ../../userman.pdf .
+rm -rf bin
+cd ..
+rm bjam
+
+# Get the boost logo.
+wget http://boost.sf.net/boost-build2/boost.png
+
+# Adjust the links, so they work with the standalone package
+perl -pi -e 's%../../../boost.png%boost.png%' index.html
+perl -pi -e 's%../../../doc/html/bbv2.html%doc/html/index.html%' index.html
+perl -pi -e 's%../../../doc/html/bbv2.installation.html%doc/html/bbv2.installation.html%' index.html
+
+# Make packages
+find . -name ".svn" | xargs rm -rf
+rm roll.sh
+chmod a+x engine/build.bat
+cd .. && zip -r boost-build.zip boost-build && tar --bzip2 -cf boost-build.tar.bz2 boost-build
+# Copy packages to a location where they are grabbed for beta.boost.org
+cp userman.pdf boost-build.zip boost-build.tar.bz2 ~/public_html/boost_build_nightly
+cd boost-build
+
+chmod -R u+w *
+# Upload docs to sourceforge
+x=`cat <<EOF
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+_uacct = "UA-2917240-2";
+urchinTracker();
+</script>
+EOF`
+echo $x
+perl -pi -e "s|</body>|$x</body>|" index.html `find doc -name '*.html'`
+scp -r doc example boost_build.png *.html hacking.txt vladimir_prus,boost@web.sourceforge.net:/home/groups/b/bo/boost/htdocs/boost-build2
+scp ../userman.pdf vladimir_prus,boost@web.sourceforge.net:/home/groups/b/bo/boost/htdocs/boost-build2/doc
diff --git a/tools/build/v2/site-config.jam b/tools/build/v2/site-config.jam
new file mode 100644
index 0000000000..ad22d67447
--- /dev/null
+++ b/tools/build/v2/site-config.jam
@@ -0,0 +1,4 @@
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
diff --git a/tools/build/v2/test/BoostBuild.py b/tools/build/v2/test/BoostBuild.py
new file mode 100644
index 0000000000..409a51b6e9
--- /dev/null
+++ b/tools/build/v2/test/BoostBuild.py
@@ -0,0 +1,921 @@
+# Copyright 2002-2005 Vladimir Prus.
+# Copyright 2002-2003 Dave Abrahams.
+# Copyright 2006 Rene Rivera.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import TestCmd
+import copy
+import fnmatch
+import glob
+import math
+import os
+import re
+import shutil
+import string
+import StringIO
+import sys
+import tempfile
+import time
+import traceback
+import tree
+import types
+
+from xml.sax.saxutils import escape
+
+
+annotations = []
+
+
+def print_annotation(name, value, xml):
+ """Writes some named bits of information about test run.
+ """
+ if xml:
+ print escape(name) + " {{{"
+ print escape(value)
+ print "}}}"
+ else:
+ print name + " {{{"
+ print value
+ print "}}}"
+
+def flush_annotations(xml=0):
+ global annotations
+ for ann in annotations:
+ print_annotation(ann[0], ann[1], xml)
+ annotations = []
+
+def clear_annotations():
+ global annotations
+ annotations = []
+
+defer_annotations = 0
+
+
+def set_defer_annotations(n):
+ global defer_annotations
+ defer_annotations = n
+
+
+def annotation(name, value):
+ """Records an annotation about the test run.
+ """
+ annotations.append((name, value))
+ if not defer_annotations:
+ flush_annotations()
+
+
+def get_toolset():
+ toolset = None;
+ for arg in sys.argv[1:]:
+ if not arg.startswith('-'):
+ toolset = arg
+ return toolset or 'gcc'
+
+
+# Detect the host OS.
+windows = False
+if os.environ.get('OS', '').lower().startswith('windows') or \
+ os.__dict__.has_key('uname') and \
+ os.uname()[0].lower().startswith('cygwin'):
+ windows = True
+
+
+suffixes = {}
+
+
+# Prepare the map of suffixes
+def prepare_suffix_map(toolset):
+ global windows
+ global suffixes
+ suffixes = {'.exe': '', '.dll': '.so', '.lib': '.a', '.obj': '.o'}
+ suffixes['.implib'] = '.no_implib_files_on_this_platform'
+ if windows:
+ suffixes = {}
+ if toolset in ["gcc"]:
+ suffixes['.lib'] = '.a' # static libs have '.a' suffix with mingw...
+ suffixes['.obj'] = '.o'
+ suffixes['.implib'] = '.lib'
+ if os.__dict__.has_key('uname') and (os.uname()[0] == 'Darwin'):
+ suffixes['.dll'] = '.dylib'
+
+
+def re_remove(sequence, regex):
+ me = re.compile(regex)
+ result = filter(lambda x: me.match(x), sequence)
+ if 0 == len(result):
+ raise ValueError()
+ for r in result:
+ sequence.remove(r)
+
+
+def glob_remove(sequence, pattern):
+ result = fnmatch.filter(sequence, pattern)
+ if 0 == len(result):
+ raise ValueError()
+ for r in result:
+ sequence.remove(r)
+
+
+# Configuration stating whether Boost Build is expected to automatically prepend
+# prefixes to built library targets.
+lib_prefix = True
+dll_prefix = True
+if windows:
+ dll_prefix = False
+
+
+#
+# FIXME: this is copy-pasted from TestSCons.py
+# Should be moved to TestCmd.py?
+#
+if os.name == 'posix':
+ def _failed(self, status=0):
+ if self.status is None:
+ return None
+ return _status(self) != status
+ def _status(self):
+ if os.WIFEXITED(self.status):
+ return os.WEXITSTATUS(self.status)
+ else:
+ return -1
+elif os.name == 'nt':
+ def _failed(self, status=0):
+ return not self.status is None and self.status != status
+ def _status(self):
+ return self.status
+
+
+class Tester(TestCmd.TestCmd):
+ """Main tester class for Boost Build.
+
+ Optional arguments:
+
+ `arguments` - Arguments passed to the run executable.
+ `executable` - Name of the executable to invoke.
+ `match` - Function to use for compating actual and
+ expected file contents.
+ `boost_build_path` - Boost build path to be passed to the run
+ executable.
+ `translate_suffixes` - Whether to update suffixes on the the file
+ names passed from the test script so they
+ match those actually created by the current
+ toolset. For example, static library files
+ are specified by using the .lib suffix but
+ when the 'gcc' toolset is used it actually
+ creates them using the .a suffix.
+ `pass_toolset` - Whether the test system should pass the
+ specified toolset to the run executable.
+ `use_test_config` - Whether the test system should tell the run
+ executable to read in the test_config.jam
+ configuration file.
+ `ignore_toolset_requirements` - Whether the test system should tell the run
+ executable to ignore toolset requirements.
+ `workdir` - indicates an absolute directory where the
+ test will be run from.
+
+ Optional arguments inherited from the base class:
+
+ `description` - Test description string displayed in case of
+ a failed test.
+ `subdir' - List of subdirectories to automatically
+ create under the working directory. Each
+ subdirectory needs to be specified
+ separately parent coming before its child.
+ `verbose` - Flag that may be used to enable more verbose
+ test system output. Note that it does not
+ also enable more verbose build system
+ output like the --verbose command line
+ option does.
+ """
+ def __init__(self, arguments="", executable="bjam",
+ match=TestCmd.match_exact, boost_build_path=None,
+ translate_suffixes=True, pass_toolset=True, use_test_config=True,
+ ignore_toolset_requirements=True, workdir="", **keywords):
+
+ self.original_workdir = os.getcwd()
+ if workdir != '' and not os.path.isabs(workdir):
+ raise "Parameter workdir <"+workdir+"> must point to an absolute directory: "
+
+ self.last_build_time_start = 0
+ self.last_build_time_finish = 0
+ self.translate_suffixes = translate_suffixes
+ self.use_test_config = use_test_config
+
+ self.toolset = get_toolset()
+ self.pass_toolset = pass_toolset
+ self.ignore_toolset_requirements = ignore_toolset_requirements
+
+ prepare_suffix_map(pass_toolset and self.toolset or 'gcc')
+
+ if not '--default-bjam' in sys.argv:
+ jam_build_dir = ""
+ if os.name == 'nt':
+ jam_build_dir = "bin.ntx86"
+ elif (os.name == 'posix') and os.__dict__.has_key('uname'):
+ if os.uname()[0].lower().startswith('cygwin'):
+ jam_build_dir = "bin.cygwinx86"
+ if 'TMP' in os.environ and os.environ['TMP'].find('~') != -1:
+ print 'Setting $TMP to /tmp to get around problem with short path names'
+ os.environ['TMP'] = '/tmp'
+ elif os.uname()[0] == 'Linux':
+ cpu = os.uname()[4]
+ if re.match("i.86", cpu):
+ jam_build_dir = "bin.linuxx86";
+ else:
+ jam_build_dir = "bin.linux" + os.uname()[4]
+ elif os.uname()[0] == 'SunOS':
+ jam_build_dir = "bin.solaris"
+ elif os.uname()[0] == 'Darwin':
+ if os.uname()[4] == 'i386':
+ jam_build_dir = "bin.macosxx86"
+ else:
+ jam_build_dir = "bin.macosxppc"
+ elif os.uname()[0] == "AIX":
+ jam_build_dir = "bin.aix"
+ elif os.uname()[0] == "IRIX64":
+ jam_build_dir = "bin.irix"
+ elif os.uname()[0] == "FreeBSD":
+ jam_build_dir = "bin.freebsd"
+ elif os.uname()[0] == "OSF1":
+ jam_build_dir = "bin.osf"
+ else:
+ raise "Don't know directory where Jam is built for this system: " + os.name + "/" + os.uname()[0]
+ else:
+ raise "Don't know directory where Jam is built for this system: " + os.name
+
+ # Find where jam_src is located. Try for the debug version if it is
+ # lying around.
+ dirs = [os.path.join('../engine', jam_build_dir + '.debug'),
+ os.path.join('../engine', jam_build_dir),
+ ]
+ for d in dirs:
+ if os.path.exists(d):
+ jam_build_dir = d
+ break
+ else:
+ print "Cannot find built Boost.Jam"
+ sys.exit(1)
+
+ verbosity = ['-d0', '--quiet']
+ if '--verbose' in sys.argv:
+ keywords['verbose'] = True
+ verbosity = ['-d+2']
+
+ if boost_build_path is None:
+ boost_build_path = self.original_workdir + "/.."
+
+ program_list = []
+
+ if '--default-bjam' in sys.argv:
+ program_list.append(executable)
+ inpath_bjam = True
+ else:
+ program_list.append(os.path.join(jam_build_dir, executable))
+ inpath_bjam = None
+ program_list.append('-sBOOST_BUILD_PATH="' + boost_build_path + '"')
+ if verbosity:
+ program_list += verbosity
+ if arguments:
+ program_list += arguments.split(" ")
+
+ TestCmd.TestCmd.__init__(
+ self
+ , program=program_list
+ , match=match
+ , workdir=workdir
+ , inpath=inpath_bjam
+ , **keywords)
+
+ os.chdir(self.workdir)
+
+ def cleanup(self):
+ try:
+ TestCmd.TestCmd.cleanup(self)
+ os.chdir(self.original_workdir)
+ except AttributeError:
+ # When this is called during TestCmd.TestCmd.__del__ we can have
+ # both 'TestCmd' and 'os' unavailable in our scope. Do nothing in
+ # this case.
+ pass
+
+ #
+ # Methods that change the working directory's content.
+ #
+ def set_tree(self, tree_location):
+ # It is not possible to remove the current directory.
+ d = os.getcwd()
+ os.chdir(os.path.dirname(self.workdir))
+ shutil.rmtree(self.workdir, ignore_errors=False)
+
+ if not os.path.isabs(tree_location):
+ tree_location = os.path.join(self.original_workdir, tree_location)
+ shutil.copytree(tree_location, self.workdir)
+
+ os.chdir(d)
+
+ def make_writable(unused, dir, entries):
+ for e in entries:
+ name = os.path.join(dir, e)
+ os.chmod(name, os.stat(name)[0] | 0222)
+
+ os.path.walk(".", make_writable, None)
+
+ def write(self, file, content):
+ self.wait_for_time_change_since_last_build()
+ nfile = self.native_file_name(file)
+ try:
+ os.makedirs(os.path.dirname(nfile))
+ except Exception, e:
+ pass
+ open(nfile, "wb").write(content)
+
+ def rename(self, old, new):
+ try:
+ os.makedirs(os.path.dirname(new))
+ except:
+ pass
+
+ try:
+ os.remove(new)
+ except:
+ pass
+
+ os.rename(old, new)
+ self.touch(new);
+
+ def copy(self, src, dst):
+ self.wait_for_time_change_since_last_build()
+ try:
+ self.write(dst, self.read(src, 1))
+ except:
+ self.fail_test(1)
+
+ def copy_preserving_timestamp(self, src, dst):
+ src_name = self.native_file_name(src)
+ dst_name = self.native_file_name(dst)
+ stats = os.stat(src_name)
+ self.write(dst, self.read(src, 1))
+ os.utime(dst_name, (stats.st_atime, stats.st_mtime))
+
+ def touch(self, names):
+ self.wait_for_time_change_since_last_build()
+ for name in self.adjust_names(names):
+ os.utime(self.native_file_name(name), None)
+
+ def rm(self, names):
+ self.wait_for_time_change_since_last_build()
+ if not type(names) == types.ListType:
+ names = [names]
+
+ # Avoid attempts to remove the current directory.
+ os.chdir(self.original_workdir)
+ for name in names:
+ n = self.native_file_name(name)
+ n = glob.glob(n)
+ if n: n = n[0]
+ if not n:
+ n = self.glob_file(string.replace(name, "$toolset", self.toolset+"*"))
+ if n:
+ if os.path.isdir(n):
+ shutil.rmtree(n, ignore_errors=False)
+ else:
+ os.unlink(n)
+
+ # Create working dir root again in case we removed it.
+ if not os.path.exists(self.workdir):
+ os.mkdir(self.workdir)
+ os.chdir(self.workdir)
+
+ def expand_toolset(self, name):
+ """Expands $toolset in the given file to tested toolset.
+ """
+ content = self.read(name)
+ content = string.replace(content, "$toolset", self.toolset)
+ self.write(name, content)
+
+ def dump_stdio(self):
+ annotation("STDOUT", self.stdout())
+ annotation("STDERR", self.stderr())
+
+ #
+ # FIXME: Large portion copied from TestSCons.py, should be moved?
+ #
+ def run_build_system(self, extra_args="", subdir="", stdout=None, stderr="",
+ status=0, match=None, pass_toolset=None, use_test_config=None,
+ ignore_toolset_requirements=None, expected_duration=None, **kw):
+
+ self.last_build_time_start = time.time()
+
+ try:
+ if os.path.isabs(subdir):
+ if stderr:
+ print "You must pass a relative directory to subdir <"+subdir+">."
+ status = 1
+ return
+
+ self.previous_tree = tree.build_tree(self.workdir)
+
+ if match is None:
+ match = self.match
+
+ if pass_toolset is None:
+ pass_toolset = self.pass_toolset
+
+ if use_test_config is None:
+ use_test_config = self.use_test_config
+
+ if ignore_toolset_requirements is None:
+ ignore_toolset_requirements = self.ignore_toolset_requirements
+
+ try:
+ kw['program'] = []
+ kw['program'] += self.program
+ if extra_args:
+ kw['program'] += extra_args.split(" ")
+ if pass_toolset:
+ kw['program'].append("toolset=" + self.toolset)
+ if use_test_config:
+ kw['program'].append('--test-config="%s"'
+ % os.path.join(self.original_workdir, "test-config.jam"))
+ if ignore_toolset_requirements:
+ kw['program'].append("--ignore-toolset-requirements")
+ if "--python" in sys.argv:
+ kw['program'].append("--python")
+ kw['chdir'] = subdir
+ self.last_program_invocation = kw['program']
+ apply(TestCmd.TestCmd.run, [self], kw)
+ except:
+ self.dump_stdio()
+ raise
+ finally:
+ self.last_build_time_finish = time.time()
+
+ if (status != None) and _failed(self, status):
+ expect = ''
+ if status != 0:
+ expect = " (expected %d)" % status
+
+ annotation("failure", '"%s" returned %d%s'
+ % (kw['program'], _status(self), expect))
+
+ annotation("reason", "unexpected status returned by bjam")
+ self.fail_test(1)
+
+ if not (stdout is None) and not match(self.stdout(), stdout):
+ annotation("failure", "Unexpected stdout")
+ annotation("Expected STDOUT", stdout)
+ annotation("Actual STDOUT", self.stdout())
+ stderr = self.stderr()
+ if stderr:
+ annotation("STDERR", stderr)
+ self.maybe_do_diff(self.stdout(), stdout)
+ self.fail_test(1, dump_stdio=False)
+
+ # Intel tends to produce some messages to stderr which make tests fail.
+ intel_workaround = re.compile("^xi(link|lib): executing.*\n", re.M)
+ actual_stderr = re.sub(intel_workaround, "", self.stderr())
+
+ if not (stderr is None) and not match(actual_stderr, stderr):
+ annotation("failure", "Unexpected stderr")
+ annotation("Expected STDERR", stderr)
+ annotation("Actual STDERR", self.stderr())
+ annotation("STDOUT", self.stdout())
+ self.maybe_do_diff(actual_stderr, stderr)
+ self.fail_test(1, dump_stdio=False)
+
+ if not expected_duration is None:
+ actual_duration = self.last_build_time_finish - self.last_build_time_start
+ if (actual_duration > expected_duration):
+ print "Test run lasted %f seconds while it was expected to " \
+ "finish in under %f seconds." % (actual_duration,
+ expected_duration)
+ self.fail_test(1, dump_stdio=False)
+
+ self.tree = tree.build_tree(self.workdir)
+ self.difference = tree.trees_difference(self.previous_tree, self.tree)
+ self.difference.ignore_directories()
+ self.unexpected_difference = copy.deepcopy(self.difference)
+
+ def glob_file(self, name):
+ result = None
+ if hasattr(self, 'difference'):
+ for f in self.difference.added_files+self.difference.modified_files+self.difference.touched_files:
+ if fnmatch.fnmatch(f, name):
+ result = self.native_file_name(f)
+ break
+ if not result:
+ result = glob.glob(self.native_file_name(name))
+ if result:
+ result = result[0]
+ return result
+
+ def read(self, name, binary=False):
+ try:
+ if self.toolset:
+ name = string.replace(name, "$toolset", self.toolset+"*")
+ name = self.glob_file(name)
+ openMode = "r"
+ if binary:
+ openMode += "b"
+ else:
+ openMode += "U"
+ return open(name, openMode).read()
+ except:
+ annotation("failure", "Could not open '%s'" % name)
+ self.fail_test(1)
+ return ''
+
+ def read_and_strip(self, name):
+ if not self.glob_file(name):
+ return ''
+ f = open(self.glob_file(name), "rb")
+ lines = f.readlines()
+ result = string.join(map(string.rstrip, lines), "\n")
+ if lines and lines[-1][-1] == '\n':
+ return result + '\n'
+ else:
+ return result
+
+ def fail_test(self, condition, dump_stdio=True, *args):
+ if not condition:
+ return
+
+ if hasattr(self, 'difference'):
+ f = StringIO.StringIO()
+ self.difference.pprint(f)
+ annotation("changes caused by the last build command", f.getvalue())
+
+ if dump_stdio:
+ self.dump_stdio()
+
+ if '--preserve' in sys.argv:
+ print
+ print "*** Copying the state of working dir into 'failed_test' ***"
+ print
+ path = os.path.join(self.original_workdir, "failed_test")
+ if os.path.isdir(path):
+ shutil.rmtree(path, ignore_errors=False)
+ elif os.path.exists(path):
+ raise "Path " + path + " already exists and is not a directory";
+ shutil.copytree(self.workdir, path)
+ print "The failed command was:"
+ print ' '.join(self.last_program_invocation)
+
+ at = TestCmd.caller(traceback.extract_stack(), 0)
+ annotation("stacktrace", at)
+ sys.exit(1)
+
+ # A number of methods below check expectations with actual difference
+ # between directory trees before and after a build. All the 'expect*'
+ # methods require exact names to be passed. All the 'ignore*' methods allow
+ # wildcards.
+
+ # All names can be lists, which are taken to be directory components.
+ def expect_addition(self, names):
+ for name in self.adjust_names(names):
+ try:
+ glob_remove(self.unexpected_difference.added_files, name)
+ except:
+ annotation("failure", "File %s not added as expected" % name)
+ self.fail_test(1)
+
+ def ignore_addition(self, wildcard):
+ self.ignore_elements(self.unexpected_difference.added_files, wildcard)
+
+ def expect_removal(self, names):
+ for name in self.adjust_names(names):
+ try:
+ glob_remove(self.unexpected_difference.removed_files, name)
+ except:
+ annotation("failure", "File %s not removed as expected" % name)
+ self.fail_test(1)
+
+ def ignore_removal(self, wildcard):
+ self.ignore_elements(self.unexpected_difference.removed_files, wildcard)
+
+ def expect_modification(self, names):
+ for name in self.adjust_names(names):
+ try:
+ glob_remove(self.unexpected_difference.modified_files, name)
+ except:
+ annotation("failure", "File %s not modified as expected" % name)
+ self.fail_test(1)
+
+ def ignore_modification(self, wildcard):
+ self.ignore_elements(self.unexpected_difference.modified_files, \
+ wildcard)
+
+ def expect_touch(self, names):
+ d = self.unexpected_difference
+ for name in self.adjust_names(names):
+ # We need to check both touched and modified files. The reason is
+ # that:
+ # (1) Windows binaries such as obj, exe or dll files have slight
+ # differences even with identical inputs due to Windows PE
+ # format headers containing an internal timestamp.
+ # (2) Intel's compiler for Linux has the same behaviour.
+ filesets = [d.modified_files, d.touched_files]
+
+ while filesets:
+ try:
+ glob_remove(filesets[-1], name)
+ break
+ except ValueError:
+ filesets.pop()
+
+ if not filesets:
+ annotation("failure", "File %s not touched as expected" % name)
+ self.fail_test(1)
+
+ def ignore_touch(self, wildcard):
+ self.ignore_elements(self.unexpected_difference.touched_files, wildcard)
+
+ def ignore(self, wildcard):
+ self.ignore_elements(self.unexpected_difference.added_files, wildcard)
+ self.ignore_elements(self.unexpected_difference.removed_files, wildcard)
+ self.ignore_elements(self.unexpected_difference.modified_files, wildcard)
+ self.ignore_elements(self.unexpected_difference.touched_files, wildcard)
+
+ def expect_nothing(self, names):
+ for name in self.adjust_names(names):
+ if name in self.difference.added_files:
+ annotation("failure",
+ "File %s added, but no action was expected" % name)
+ self.fail_test(1)
+ if name in self.difference.removed_files:
+ annotation("failure",
+ "File %s removed, but no action was expected" % name)
+ self.fail_test(1)
+ pass
+ if name in self.difference.modified_files:
+ annotation("failure",
+ "File %s modified, but no action was expected" % name)
+ self.fail_test(1)
+ if name in self.difference.touched_files:
+ annotation("failure",
+ "File %s touched, but no action was expected" % name)
+ self.fail_test(1)
+
+ def expect_nothing_more(self):
+ # Not totally sure about this change, but I do not see a good
+ # alternative.
+ if windows:
+ self.ignore('*.ilk') # MSVC incremental linking files.
+ self.ignore('*.pdb') # MSVC program database files.
+ self.ignore('*.rsp') # Response files.
+ self.ignore('*.tds') # Borland debug symbols.
+ self.ignore('*.manifest') # MSVC DLL manifests.
+
+ # Debug builds of bjam built with gcc produce this profiling data.
+ self.ignore('gmon.out')
+ self.ignore('*/gmon.out')
+
+ self.ignore("bin/config.log")
+
+ self.ignore("*.pyc")
+
+ if not self.unexpected_difference.empty():
+ annotation('failure', 'Unexpected changes found')
+ output = StringIO.StringIO()
+ self.unexpected_difference.pprint(output)
+ annotation("unexpected changes", output.getvalue())
+ self.fail_test(1)
+
+ def __expect_line(self, content, expected, expected_to_exist):
+ expected = expected.strip()
+ lines = content.splitlines()
+ found = False
+ for line in lines:
+ line = line.strip()
+ if fnmatch.fnmatch(line, expected):
+ found = True
+ break
+
+ if expected_to_exist and not found:
+ annotation("failure",
+ "Did not find expected line:\n%s\nin output:\n%s" %
+ (expected, content))
+ self.fail_test(1)
+ if not expected_to_exist and found:
+ annotation("failure",
+ "Found an unexpected line:\n%s\nin output:\n%s" %
+ (expected, content))
+ self.fail_test(1)
+
+ def expect_output_line(self, line, expected_to_exist=True):
+ self.__expect_line(self.stdout(), line, expected_to_exist)
+
+ def expect_content_line(self, name, line, expected_to_exist=True):
+ content = self.__read_file(name)
+ self.__expect_line(content, line, expected_to_exist)
+
+ def __read_file(self, name, exact=False):
+ name = self.adjust_names(name)[0]
+ result = ""
+ try:
+ if exact:
+ result = self.read(name)
+ else:
+ result = string.replace(self.read_and_strip(name), "\\", "/")
+ except (IOError, IndexError):
+ print "Note: could not open file", name
+ self.fail_test(1)
+ return result
+
+ def expect_content(self, name, content, exact=False):
+ actual = self.__read_file(name, exact)
+ content = string.replace(content, "$toolset", self.toolset+"*")
+
+ matched = False
+ if exact:
+ matched = fnmatch.fnmatch(actual, content)
+ else:
+ def sorted_(x):
+ x.sort()
+ return x
+ actual_ = map(lambda x: sorted_(x.split()), actual.splitlines())
+ content_ = map(lambda x: sorted_(x.split()), content.splitlines())
+ if len(actual_) == len(content_):
+ matched = map(
+ lambda x, y: map(lambda n, p: fnmatch.fnmatch(n, p), x, y),
+ actual_, content_)
+ matched = reduce(
+ lambda x, y: x and reduce(
+ lambda a, b: a and b,
+ y),
+ matched)
+
+ if not matched:
+ print "Expected:\n"
+ print content
+ print "Got:\n"
+ print actual
+ self.fail_test(1)
+
+ def maybe_do_diff(self, actual, expected):
+ if os.environ.has_key("DO_DIFF") and os.environ["DO_DIFF"] != '':
+ e = tempfile.mktemp("expected")
+ a = tempfile.mktemp("actual")
+ open(e, "w").write(expected)
+ open(a, "w").write(actual)
+ print "DIFFERENCE"
+ if os.system("diff -u " + e + " " + a):
+ print "Unable to compute difference: diff -u %s %s" % (e, a)
+ os.unlink(e)
+ os.unlink(a)
+ else:
+ print "Set environmental variable 'DO_DIFF' to examine difference."
+
+ # Helpers.
+ def mul(self, *arguments):
+ if len(arguments) == 0:
+ return None
+
+ here = arguments[0]
+ if type(here) == type(''):
+ here = [here]
+
+ if len(arguments) > 1:
+ there = apply(self.mul, arguments[1:])
+ result = []
+ for i in here:
+ for j in there:
+ result.append(i + j)
+ return result
+
+ return here
+
+ # Internal methods.
+ def ignore_elements(self, list, wildcard):
+ """Removes in-place, element of 'list' that match the given wildcard.
+ """
+ list[:] = filter(lambda x, w=wildcard: not fnmatch.fnmatch(x, w), list)
+
+ def adjust_lib_name(self, name):
+ global lib_prefix
+ result = name
+
+ pos = string.rfind(name, ".")
+ if pos != -1:
+ suffix = name[pos:]
+ if suffix == ".lib":
+ (head, tail) = os.path.split(name)
+ if lib_prefix:
+ tail = "lib" + tail
+ result = os.path.join(head, tail)
+ elif suffix == ".dll":
+ (head, tail) = os.path.split(name)
+ if dll_prefix:
+ tail = "lib" + tail
+ result = os.path.join(head, tail)
+ # If we want to use this name in a Jamfile, we better convert \ to /, as
+ # otherwise we would have to quote \.
+ result = string.replace(result, "\\", "/")
+ return result
+
+ def adjust_suffix(self, name):
+ if not self.translate_suffixes:
+ return name
+
+ pos = string.rfind(name, ".")
+ if pos != -1:
+ suffix = name[pos:]
+ name = name[:pos]
+
+ if suffixes.has_key(suffix):
+ suffix = suffixes[suffix]
+ else:
+ suffix = ''
+
+ return name + suffix
+
+ # Acceps either a string or a list of strings and returns a list of strings.
+ # Adjusts suffixes on all names.
+ def adjust_names(self, names):
+ if type(names) == types.StringType:
+ names = [names]
+ r = map(self.adjust_lib_name, names)
+ r = map(self.adjust_suffix, r)
+ r = map(lambda x, t=self.toolset: string.replace(x, "$toolset", t+"*"), r)
+ return r
+
+ def native_file_name(self, name):
+ name = self.adjust_names(name)[0]
+ elements = string.split(name, "/")
+ return os.path.normpath(apply(os.path.join, [self.workdir]+elements))
+
+ # Wait while time is no longer equal to the time last "run_build_system"
+ # call finished. Used to avoid subsequent builds treating existing files as
+ # 'current'.
+ def wait_for_time_change_since_last_build(self):
+ while 1:
+ # In fact, I'm not sure why "+ 2" as opposed to "+ 1" is needed but
+ # empirically, "+ 1" sometimes causes 'touch' and other functions
+ # not to bump the file time enough for a rebuild to happen.
+ if math.floor(time.time()) < math.floor(self.last_build_time_finish) + 2:
+ time.sleep(0.1)
+ else:
+ break
+
+
+class List:
+
+ def __init__(self, s=""):
+ elements = []
+ if isinstance(s, type("")):
+ # Have to handle espaced spaces correctly.
+ s = string.replace(s, "\ ", '\001')
+ elements = string.split(s)
+ else:
+ elements = s;
+
+ self.l = []
+ for e in elements:
+ self.l.append(string.replace(e, '\001', ' '))
+
+ def __len__(self):
+ return len(self.l)
+
+ def __getitem__(self, key):
+ return self.l[key]
+
+ def __setitem__(self, key, value):
+ self.l[key] = value
+
+ def __delitem__(self, key):
+ del self.l[key]
+
+ def __str__(self):
+ return str(self.l)
+
+ def __repr__(self):
+ return (self.__module__ + '.List('
+ + repr(string.join(self.l, ' '))
+ + ')')
+
+ def __mul__(self, other):
+ result = List()
+ if not isinstance(other, List):
+ other = List(other)
+ for f in self:
+ for s in other:
+ result.l.append(f + s)
+ return result
+
+ def __rmul__(self, other):
+ if not isinstance(other, List):
+ other = List(other)
+ return List.__mul__(other, self)
+
+ def __add__(self, other):
+ result = List()
+ result.l = self.l[:] + other.l[:]
+ return result
+
+# Quickie tests. Should use doctest instead.
+if __name__ == '__main__':
+ assert str(List("foo bar") * "/baz") == "['foo/baz', 'bar/baz']"
+ assert repr("foo/" * List("bar baz")) == "__main__.List('foo/bar foo/baz')"
+ print 'tests passed'
diff --git a/tools/build/v2/test/Jamrules b/tools/build/v2/test/Jamrules
new file mode 100644
index 0000000000..ff29a26bba
--- /dev/null
+++ b/tools/build/v2/test/Jamrules
@@ -0,0 +1,4 @@
+# This simple Jamrules file is used for the Boost.Build test project.
+
+# The testing framework itself gets no boost-Jambase
+BOOST_JAMBASE = empty.jam ;
diff --git a/tools/build/v2/test/TestCmd.py b/tools/build/v2/test/TestCmd.py
new file mode 100644
index 0000000000..b14e942655
--- /dev/null
+++ b/tools/build/v2/test/TestCmd.py
@@ -0,0 +1,651 @@
+"""
+TestCmd.py: a testing framework for commands and scripts.
+
+The TestCmd module provides a framework for portable automated testing of
+executable commands and scripts (in any language, not just Python), especially
+commands and scripts that require file system interaction.
+
+In addition to running tests and evaluating conditions, the TestCmd module
+manages and cleans up one or more temporary workspace directories, and provides
+methods for creating files and directories in those workspace directories from
+in-line data, here-documents), allowing tests to be completely self-contained.
+
+A TestCmd environment object is created via the usual invocation:
+
+ test = TestCmd()
+
+The TestCmd module provides pass_test(), fail_test(), and no_result() unbound
+methods that report test results for use with the Aegis change management
+system. These methods terminate the test immediately, reporting PASSED, FAILED
+or NO RESULT respectively and exiting with status 0 (success), 1 or 2
+respectively. This allows for a distinction between an actual failed test and a
+test that could not be properly evaluated because of an external condition (such
+as a full file system or incorrect permissions).
+"""
+
+# Copyright 2000 Steven Knight
+# This module is free software, and you may redistribute it and/or modify
+# it under the same terms as Python itself, so long as this copyright message
+# and disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+# SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
+# THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+#
+# THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
+# AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+# Copyright 2002-2003 Vladimir Prus.
+# Copyright 2002-2003 Dave Abrahams.
+# Copyright 2006 Rene Rivera.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+
+from string import join, split
+
+__author__ = "Steven Knight <knight@baldmt.com>"
+__revision__ = "TestCmd.py 0.D002 2001/08/31 14:56:12 software"
+__version__ = "0.02"
+
+from types import *
+
+import os
+import os.path
+import popen2
+import re
+import shutil
+import stat
+import sys
+import tempfile
+import traceback
+
+
+tempfile.template = 'testcmd.'
+
+_Cleanup = []
+
+def _clean():
+ global _Cleanup
+ list = _Cleanup[:]
+ _Cleanup = []
+ list.reverse()
+ for test in list:
+ test.cleanup()
+
+sys.exitfunc = _clean
+
+
+def caller(tblist, skip):
+ string = ""
+ arr = []
+ for file, line, name, text in tblist:
+ if file[-10:] == "TestCmd.py":
+ break
+ arr = [(file, line, name, text)] + arr
+ atfrom = "at"
+ for file, line, name, text in arr[skip:]:
+ if name == "?":
+ name = ""
+ else:
+ name = " (" + name + ")"
+ string = string + ("%s line %d of %s%s\n" % (atfrom, line, file, name))
+ atfrom = "\tfrom"
+ return string
+
+
+def fail_test(self=None, condition=True, function=None, skip=0):
+ """Cause the test to fail.
+
+ By default, the fail_test() method reports that the test FAILED and exits
+ with a status of 1. If a condition argument is supplied, the test fails only
+ if the condition is true.
+ """
+ if not condition:
+ return
+ if not function is None:
+ function()
+ of = ""
+ desc = ""
+ sep = " "
+ if not self is None:
+ if self.program:
+ of = " of " + join(self.program, " ")
+ sep = "\n\t"
+ if self.description:
+ desc = " [" + self.description + "]"
+ sep = "\n\t"
+
+ at = caller(traceback.extract_stack(), skip)
+
+ sys.stderr.write("FAILED test" + of + desc + sep + at + """
+in directory: """ + os.getcwd() )
+ sys.exit(1)
+
+
+def no_result(self=None, condition=True, function=None, skip=0):
+ """Causes a test to exit with no valid result.
+
+ By default, the no_result() method reports NO RESULT for the test and exits
+ with a status of 2. If a condition argument is supplied, the test fails only
+ if the condition is true.
+ """
+ if not condition:
+ return
+ if not function is None:
+ function()
+ of = ""
+ desc = ""
+ sep = " "
+ if not self is None:
+ if self.program:
+ of = " of " + self.program
+ sep = "\n\t"
+ if self.description:
+ desc = " [" + self.description + "]"
+ sep = "\n\t"
+
+ at = caller(traceback.extract_stack(), skip)
+ sys.stderr.write("NO RESULT for test" + of + desc + sep + at)
+ sys.exit(2)
+
+
+def pass_test(self=None, condition=True, function=None):
+ """Causes a test to pass.
+
+ By default, the pass_test() method reports PASSED for the test and exits
+ with a status of 0. If a condition argument is supplied, the test passes
+ only if the condition is true.
+ """
+ if not condition:
+ return
+ if not function is None:
+ function()
+ sys.stderr.write("PASSED\n")
+ sys.exit(0)
+
+
+def match_exact(lines=None, matches=None):
+ """Returns whether the given lists or strings containing lines separated
+ using newline characters contain exactly the same data.
+ """
+ if not type(lines) is ListType:
+ lines = split(lines, "\n")
+ if not type(matches) is ListType:
+ matches = split(matches, "\n")
+ if len(lines) != len(matches):
+ return
+ for i in range(len(lines)):
+ if lines[i] != matches[i]:
+ return
+ return 1
+
+
+def match_re(lines=None, res=None):
+ """Given lists or strings contain lines separated using newline characters.
+ This function matches those lines one by one, interpreting the lines in the
+ res parameter as regular expressions.
+ """
+ if not type(lines) is ListType:
+ lines = split(lines, "\n")
+ if not type(res) is ListType:
+ res = split(res, "\n")
+ if len(lines) != len(res):
+ return
+ for i in range(len(lines)):
+ if not re.compile("^" + res[i] + "$").search(lines[i]):
+ return
+ return 1
+
+
+class TestCmd:
+ """Class TestCmd.
+ """
+
+ def __init__(self, description=None, program=None, workdir=None,
+ subdir=None, verbose=False, match=None, inpath=None):
+
+ self._cwd = os.getcwd()
+ self.description_set(description)
+ if inpath:
+ self.program = program
+ else:
+ self.program_set(program)
+ self.verbose_set(verbose)
+ if not match is None:
+ self.match_func = match
+ else:
+ self.match_func = match_re
+ self._dirlist = []
+ self._preserve = {'pass_test': 0, 'fail_test': 0, 'no_result': 0}
+ if os.environ.has_key('PRESERVE') and not os.environ['PRESERVE'] is '':
+ self._preserve['pass_test'] = os.environ['PRESERVE']
+ self._preserve['fail_test'] = os.environ['PRESERVE']
+ self._preserve['no_result'] = os.environ['PRESERVE']
+ else:
+ try:
+ self._preserve['pass_test'] = os.environ['PRESERVE_PASS']
+ except KeyError:
+ pass
+ try:
+ self._preserve['fail_test'] = os.environ['PRESERVE_FAIL']
+ except KeyError:
+ pass
+ try:
+ self._preserve['no_result'] = os.environ['PRESERVE_NO_RESULT']
+ except KeyError:
+ pass
+ self._stdout = []
+ self._stderr = []
+ self.status = None
+ self.condition = 'no_result'
+ self.workdir_set(workdir)
+ self.subdir(subdir)
+
+ def __del__(self):
+ self.cleanup()
+
+ def __repr__(self):
+ return "%x" % id(self)
+
+ def cleanup(self, condition=None):
+ """Removes any temporary working directories for the specified TestCmd
+ environment. If the environment variable PRESERVE was set when the
+ TestCmd environment was created, temporary working directories are not
+ removed. If any of the environment variables PRESERVE_PASS,
+ PRESERVE_FAIL or PRESERVE_NO_RESULT were set when the TestCmd
+ environment was created, then temporary working directories are not
+ removed if the test passed, failed or had no result, respectively.
+ Temporary working directories are also preserved for conditions
+ specified via the preserve method.
+
+ Typically, this method is not called directly, but is used when the
+ script exits to clean up temporary working directories as appropriate
+ for the exit status.
+ """
+ if not self._dirlist:
+ return
+ if condition is None:
+ condition = self.condition
+ if self._preserve[condition]:
+ for dir in self._dirlist:
+ print "Preserved directory", dir
+ else:
+ list = self._dirlist[:]
+ list.reverse()
+ for dir in list:
+ self.writable(dir, 1)
+ shutil.rmtree(dir, ignore_errors = 1)
+
+ self._dirlist = []
+ self.workdir = None
+ os.chdir(self._cwd)
+ try:
+ global _Cleanup
+ _Cleanup.remove(self)
+ except (AttributeError, ValueError):
+ pass
+
+ def description_set(self, description):
+ """Set the description of the functionality being tested.
+ """
+ self.description = description
+
+ def fail_test(self, condition=True, function=None, skip=0):
+ """Cause the test to fail.
+ """
+ if not condition:
+ return
+ self.condition = 'fail_test'
+ fail_test(self = self,
+ condition = condition,
+ function = function,
+ skip = skip)
+
+ def match(self, lines, matches):
+ """Compare actual and expected file contents.
+ """
+ return self.match_func(lines, matches)
+
+ def match_exact(self, lines, matches):
+ """Compare actual and expected file contents.
+ """
+ return match_exact(lines, matches)
+
+ def match_re(self, lines, res):
+ """Compare actual and expected file contents.
+ """
+ return match_re(lines, res)
+
+ def no_result(self, condition=True, function=None, skip=0):
+ """Report that the test could not be run.
+ """
+ if not condition:
+ return
+ self.condition = 'no_result'
+ no_result(self = self,
+ condition = condition,
+ function = function,
+ skip = skip)
+
+ def pass_test(self, condition=True, function=None):
+ """Cause the test to pass.
+ """
+ if not condition:
+ return
+ self.condition = 'pass_test'
+ pass_test(self = self, condition = condition, function = function)
+
+ def preserve(self, *conditions):
+ """Arrange for the temporary working directories for the specified
+ TestCmd environment to be preserved for one or more conditions. If no
+ conditions are specified, arranges for the temporary working directories
+ to be preserved for all conditions.
+ """
+ if conditions is ():
+ conditions = ('pass_test', 'fail_test', 'no_result')
+ for cond in conditions:
+ self._preserve[cond] = 1
+
+ def program_set(self, program):
+ """Set the executable program or script to be tested.
+ """
+ if program and program[0] and not os.path.isabs(program[0]):
+ program[0] = os.path.join(self._cwd, program[0])
+ self.program = program
+
+ def read(self, file, mode='rb'):
+ """Reads and returns the contents of the specified file name. The file
+ name may be a list, in which case the elements are concatenated with the
+ os.path.join() method. The file is assumed to be under the temporary
+ working directory unless it is an absolute path name. The I/O mode for
+ the file may be specified; it must begin with an 'r'. The default is
+ 'rb' (binary read).
+ """
+ if type(file) is ListType:
+ file = apply(os.path.join, tuple(file))
+ if not os.path.isabs(file):
+ file = os.path.join(self.workdir, file)
+ if mode[0] != 'r':
+ raise ValueError, "mode must begin with 'r'"
+ return open(file, mode).read()
+
+ def run(self, program=None, arguments=None, chdir=None, stdin=None):
+ """Runs a test of the program or script for the test environment.
+ Standard output and error output are saved for future retrieval via the
+ stdout() and stderr() methods.
+ """
+ if chdir:
+ oldcwd = os.getcwd()
+ if not os.path.isabs(chdir):
+ chdir = os.path.join(self.workpath(chdir))
+ if self.verbose:
+ sys.stderr.write("chdir(" + chdir + ")\n")
+ os.chdir(chdir)
+ cmd = []
+ if program and program[0]:
+ if program[0] != self.program[0] and not os.path.isabs(program[0]):
+ program[0] = os.path.join(self._cwd, program[0])
+ cmd += program
+ else:
+ cmd += self.program
+ if arguments:
+ cmd += arguments.split(" ")
+ if self.verbose:
+ sys.stderr.write(join(cmd, " ") + "\n")
+ try:
+ p = popen2.Popen3(cmd, 1)
+ except AttributeError:
+ # We end up here in case the popen2.Popen3 class is not available
+ # (e.g. on Windows). We will be using the os.popen3() Python API
+ # which takes a string parameter and so needs its executable quoted
+ # in case its name contains spaces.
+ cmd[0] = '"' + cmd[0] + '"'
+ command_string = join(cmd, " ")
+ if ( os.name == 'nt' ):
+ # This is a workaround for a longstanding Python bug on Windows
+ # when using os.popen(), os.system() and similar functions to
+ # execute a command containing quote characters. The bug seems
+ # to be related to the quote stripping functionality used by the
+ # Windows cmd.exe interpreter when its /S is not specified.
+ #
+ # Cleaned up quote from the cmd.exe help screen as displayed on
+ # Windows XP SP2:
+ #
+ # 1. If all of the following conditions are met, then quote
+ # characters on the command line are preserved:
+ #
+ # - no /S switch
+ # - exactly two quote characters
+ # - no special characters between the two quote
+ # characters, where special is one of: &<>()@^|
+ # - there are one or more whitespace characters between
+ # the two quote characters
+ # - the string between the two quote characters is the
+ # name of an executable file.
+ #
+ # 2. Otherwise, old behavior is to see if the first character
+ # is a quote character and if so, strip the leading
+ # character and remove the last quote character on the
+ # command line, preserving any text after the last quote
+ # character.
+ #
+ # This causes some commands containing quotes not to be executed
+ # correctly. For example:
+ #
+ # "\Long folder name\aaa.exe" --name="Jurko" --no-surname
+ #
+ # would get its outermost quotes stripped and would be executed
+ # as:
+ #
+ # \Long folder name\aaa.exe" --name="Jurko --no-surname
+ #
+ # which would report an error about '\Long' not being a valid
+ # command.
+ #
+ # cmd.exe help seems to indicate it would be enough to add an
+ # extra space character in front of the command to avoid this
+ # but this does not work, most likely due to the shell first
+ # stripping all leading whitespace characters from the command.
+ #
+ # Solution implemented here is to quote the whole command in
+ # case it contains any quote characters. Note thought this will
+ # not work correctly should Python ever fix this bug.
+ # (01.05.2008.) (Jurko)
+ if command_string.find('"') != -1:
+ command_string = '"' + command_string + '"'
+ (tochild, fromchild, childerr) = os.popen3(command_string)
+ if stdin:
+ if type(stdin) is ListType:
+ for line in stdin:
+ tochild.write(line)
+ else:
+ tochild.write(stdin)
+ tochild.close()
+ self._stdout.append(fromchild.read())
+ self._stderr.append(childerr.read())
+ fromchild.close()
+ self.status = childerr.close()
+ if not self.status:
+ self.status = 0
+ except:
+ raise
+ else:
+ if stdin:
+ if type(stdin) is ListType:
+ for line in stdin:
+ p.tochild.write(line)
+ else:
+ p.tochild.write(stdin)
+ p.tochild.close()
+ self._stdout.append(p.fromchild.read())
+ self._stderr.append(p.childerr.read())
+ self.status = p.wait()
+
+ if self.verbose:
+ sys.stdout.write(self._stdout[-1])
+ sys.stderr.write(self._stderr[-1])
+
+ if chdir:
+ os.chdir(oldcwd)
+
+ def stderr(self, run=None):
+ """Returns the error output from the specified run number. If there is
+ no specified run number, then returns the error output of the last run.
+ If the run number is less than zero, then returns the error output from
+ that many runs back from the current run.
+ """
+ if not run:
+ run = len(self._stderr)
+ elif run < 0:
+ run = len(self._stderr) + run
+ run = run - 1
+ if (run < 0):
+ return ''
+ return self._stderr[run]
+
+ def stdout(self, run=None):
+ """Returns the standard output from the specified run number. If there
+ is no specified run number, then returns the standard output of the last
+ run. If the run number is less than zero, then returns the standard
+ output from that many runs back from the current run.
+ """
+ if not run:
+ run = len(self._stdout)
+ elif run < 0:
+ run = len(self._stdout) + run
+ run = run - 1
+ if (run < 0):
+ return ''
+ return self._stdout[run]
+
+ def subdir(self, *subdirs):
+ """Create new subdirectories under the temporary working directory, one
+ for each argument. An argument may be a list, in which case the list
+ elements are concatenated using the os.path.join() method.
+ Subdirectories multiple levels deep must be created using a separate
+ argument for each level:
+
+ test.subdir('sub', ['sub', 'dir'], ['sub', 'dir', 'ectory'])
+
+ Returns the number of subdirectories actually created.
+ """
+ count = 0
+ for sub in subdirs:
+ if sub is None:
+ continue
+ if type(sub) is ListType:
+ sub = apply(os.path.join, tuple(sub))
+ new = os.path.join(self.workdir, sub)
+ try:
+ os.mkdir(new)
+ except:
+ pass
+ else:
+ count = count + 1
+ return count
+
+ def unlink (self, file):
+ """Unlinks the specified file name. The file name may be a list, in
+ which case the elements are concatenated using the os.path.join()
+ method. The file is assumed to be under the temporary working directory
+ unless it is an absolute path name.
+ """
+ if type(file) is ListType:
+ file = apply(os.path.join, tuple(file))
+ if not os.path.isabs(file):
+ file = os.path.join(self.workdir, file)
+ os.unlink(file)
+
+ def verbose_set(self, verbose):
+ """Set the verbose level.
+ """
+ self.verbose = verbose
+
+ def workdir_set(self, path):
+ """Creates a temporary working directory with the specified path name.
+ If the path is a null string (''), a unique directory name is created.
+ """
+
+ if os.path.isabs(path):
+ self.workdir = path
+ else:
+ if (path != None):
+ if path == '':
+ path = tempfile.mktemp()
+ if path != None:
+ os.mkdir(path)
+ self._dirlist.append(path)
+ global _Cleanup
+ try:
+ _Cleanup.index(self)
+ except ValueError:
+ _Cleanup.append(self)
+ # We'd like to set self.workdir like this:
+ # self.workdir = path
+ # But symlinks in the path will report things differently from
+ # os.getcwd(), so chdir there and back to fetch the canonical
+ # path.
+ cwd = os.getcwd()
+ os.chdir(path)
+ self.workdir = os.getcwd()
+ os.chdir(cwd)
+ else:
+ self.workdir = None
+
+ def workpath(self, *args):
+ """Returns the absolute path name to a subdirectory or file within the
+ current temporary working directory. Concatenates the temporary working
+ directory name with the specified arguments using the os.path.join()
+ method.
+ """
+ return apply(os.path.join, (self.workdir,) + tuple(args))
+
+ def writable(self, top, write):
+ """Make the specified directory tree writable (write == 1) or not
+ (write == None).
+ """
+
+ def _walk_chmod(arg, dirname, names):
+ st = os.stat(dirname)
+ os.chmod(dirname, arg(st[stat.ST_MODE]))
+ for name in names:
+ n = os.path.join(dirname, name)
+ st = os.stat(n)
+ os.chmod(n, arg(st[stat.ST_MODE]))
+
+ def _mode_writable(mode):
+ return stat.S_IMODE(mode|0200)
+
+ def _mode_non_writable(mode):
+ return stat.S_IMODE(mode&~0200)
+
+ if write:
+ f = _mode_writable
+ else:
+ f = _mode_non_writable
+ try:
+ os.path.walk(top, _walk_chmod, f)
+ except:
+ pass # Ignore any problems changing modes.
+
+ def write(self, file, content, mode='wb'):
+ """Writes the specified content text (second argument) to the specified
+ file name (first argument). The file name may be a list, in which case
+ the elements are concatenated using the os.path.join() method. The file
+ is created under the temporary working directory. Any subdirectories in
+ the path must already exist. The I/O mode for the file may be specified;
+ it must begin with a 'w'. The default is 'wb' (binary write).
+ """
+ if type(file) is ListType:
+ file = apply(os.path.join, tuple(file))
+ if not os.path.isabs(file):
+ file = os.path.join(self.workdir, file)
+ if mode[0] != 'w':
+ raise ValueError, "mode must begin with 'w'"
+ open(file, mode).write(content)
diff --git a/tools/build/v2/test/abs_workdir.py b/tools/build/v2/test/abs_workdir.py
new file mode 100644
index 0000000000..29fab06fa4
--- /dev/null
+++ b/tools/build/v2/test/abs_workdir.py
@@ -0,0 +1,34 @@
+# Niklaus Giger, 2005-03-15
+# Testing whether we may run a test in absolute directories. There are no tests
+# for temporary directories as this is implictly tested in a lot of other cases.
+
+import BoostBuild
+import os
+import string
+
+t = BoostBuild.Tester(arguments="pwd", executable="jam", workdir=os.getcwd(),
+ pass_toolset=0)
+
+t.write("jamroot.jam", """
+actions print_pwd { pwd ; }
+print_pwd pwd ;
+ALWAYS pwd ;
+""")
+
+t.run_build_system(status=0)
+
+if 'TMP' in os.environ:
+ tmp_dir = os.environ.get('TMP')
+else:
+ tmp_dir = "/tmp"
+
+if string.rfind(t.stdout(), tmp_dir) != -1:
+ t.fail_test(1)
+
+if string.rfind(t.stdout(), 'build/v2/test') == -1:
+ t.fail_test(1)
+
+t.run_build_system(status=1, subdir="/must/fail/with/absolute/path",
+ stderr=None)
+
+t.cleanup()
diff --git a/tools/build/v2/test/absolute_sources.py b/tools/build/v2/test/absolute_sources.py
new file mode 100644
index 0000000000..58e2cf4516
--- /dev/null
+++ b/tools/build/v2/test/absolute_sources.py
@@ -0,0 +1,96 @@
+#!/usr/bin/python
+
+# Copyright 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that sources with absolute names are handled OK.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+path-constant TOP : . ;
+""")
+
+t.write("jamfile.jam", """
+local pwd = [ PWD ] ;
+ECHO $(pwd) XXXXX ;
+exe hello : $(pwd)/hello.cpp $(TOP)/empty.cpp ;
+""")
+
+t.write("hello.cpp", "int main() {}\n")
+
+t.write("empty.cpp", "\n")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+# Test a contrived case. There, absolute name is used in a standalone project
+# (not Jamfile). Moreover, the target with an absolute name is returned by
+# 'alias' and used from another project.
+t.write("a.cpp", """
+int main() {}
+""")
+
+t.write("jamfile.jam", """
+exe a : /standalone//a ;
+""")
+
+t.write("jamroot.jam", """
+import standalone ;
+""")
+
+t.write("standalone.jam", """
+import project ;
+
+project.initialize $(__name__) ;
+project standalone ;
+
+local pwd = [ PWD ] ;
+alias a : $(pwd)/a.cpp ;
+""")
+
+t.write("standalone.py", """
+from b2.manager import get_manager
+
+# FIXME: this is ugly as death
+get_manager().projects().initialize(__name__)
+
+import os ;
+
+# This use of list as parameter is also ugly.
+project(['standalone'])
+
+pwd = os.getcwd()
+alias('a', [os.path.join(pwd, 'a.cpp')])
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+
+# Test absolute path in target ids.
+t.rm(".")
+
+t.write("d1/jamroot.jam", "")
+
+t.write("d1/jamfile.jam", """
+exe a : a.cpp ;
+""")
+
+t.write("d1/a.cpp", """
+int main() {}
+""")
+
+t.write("d2/jamroot.jam", "")
+
+t.write("d2/jamfile.jam", """
+local pwd = [ PWD ] ;
+alias x : $(pwd)/../d1//a ;
+""")
+
+t.run_build_system(subdir="d2")
+t.expect_addition("d1/bin/$toolset/debug/a.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/alias.py b/tools/build/v2/test/alias.py
new file mode 100644
index 0000000000..107b12e87e
--- /dev/null
+++ b/tools/build/v2/test/alias.py
@@ -0,0 +1,107 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+
+################################################################################
+#
+# test_alias_rule()
+# -----------------
+#
+################################################################################
+
+def test_alias_rule(t):
+ """Basic alias rule test.
+ """
+
+ t.write("jamroot.jam", """
+exe a : a.cpp ;
+exe b : b.cpp ;
+exe c : c.cpp ;
+
+alias bin1 : a ;
+alias bin2 : a b ;
+
+alias src : s.cpp ;
+exe hello : hello.cpp src ;
+""")
+
+ t.write("a.cpp", "int main() {}\n")
+ t.copy("a.cpp", "b.cpp")
+ t.copy("a.cpp", "c.cpp")
+ t.copy("a.cpp", "hello.cpp")
+ t.write("s.cpp", "")
+
+ # Check that targets to which "bin1" refers are updated, and only those.
+ t.run_build_system("bin1")
+ t.expect_addition(BoostBuild.List("bin/$toolset/debug/") * "a.exe a.obj")
+ t.expect_nothing_more()
+
+ # Try again with "bin2"
+ t.run_build_system("bin2")
+ t.expect_addition(BoostBuild.List("bin/$toolset/debug/") * "b.exe b.obj")
+ t.expect_nothing_more()
+
+ # Try building everything, making sure 'hello' target is created.
+ t.run_build_system()
+ t.expect_addition(BoostBuild.List("bin/$toolset/debug/") * \
+ "hello.exe hello.obj")
+ t.expect_addition("bin/$toolset/debug/s.obj")
+ t.expect_addition(BoostBuild.List("bin/$toolset/debug/") * "c.exe c.obj")
+ t.expect_nothing_more()
+
+
+################################################################################
+#
+# test_alias_source_usage_requirements()
+# --------------------------------------
+#
+################################################################################
+
+def test_alias_source_usage_requirements(t):
+ """Check whether usage requirements are propagated via "alias". In case they
+ are not, linking will fail as there will be no main() function defined
+ anywhere in the source.
+ """
+
+ t.write("jamroot.jam", """
+lib l : l.cpp : : : <define>WANT_MAIN ;
+alias la : l ;
+exe main : main.cpp la ;
+""")
+
+ t.write("l.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+foo() {}
+""")
+
+ t.write("main.cpp", """
+#ifdef WANT_MAIN
+int main() {}
+#endif
+""")
+
+ t.run_build_system()
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+t = BoostBuild.Tester()
+
+test_alias_rule(t)
+test_alias_source_usage_requirements(t)
+
+t.cleanup()
diff --git a/tools/build/v2/test/alternatives.py b/tools/build/v2/test/alternatives.py
new file mode 100644
index 0000000000..6d423212f0
--- /dev/null
+++ b/tools/build/v2/test/alternatives.py
@@ -0,0 +1,113 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2003, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test main target alternatives.
+
+import BoostBuild
+import string
+
+t = BoostBuild.Tester()
+
+# Test that basic alternatives selection works.
+t.write("jamroot.jam", "")
+
+t.write("jamfile.jam", """
+exe a : a_empty.cpp ;
+exe a : a.cpp : <variant>release ;
+""")
+
+t.write("a_empty.cpp", "")
+
+t.write("a.cpp", "int main() {}\n")
+
+t.run_build_system("release")
+
+t.expect_addition("bin/$toolset/release/a.exe")
+
+# Test that alternative selection works for ordinary properties, in particular
+# user-defined.
+t.write("jamroot.jam", "")
+
+t.write("jamfile.jam", """
+import feature ;
+feature.feature X : off on : propagated ;
+exe a : b.cpp ;
+exe a : a.cpp : <X>on ;
+""")
+t.write("b.cpp", "int main() {}\n")
+
+t.rm("bin")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/b.obj")
+
+t.run_build_system("X=on")
+t.expect_addition("bin/$toolset/debug/X-on/a.obj")
+
+t.rm("bin")
+
+# Test that everything works ok even with default build.
+t.write("jamfile.jam", """
+exe a : a_empty.cpp : <variant>release ;
+exe a : a.cpp : <variant>debug ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+
+# Test that only properties which are in build request matter for alternative
+# selection. IOW, alternative with <variant>release is better than one with
+# <variant>debug when building release version.
+t.write("jamfile.jam", """
+exe a : a_empty.cpp : <variant>debug ;
+exe a : a.cpp : <variant>release ;
+""")
+
+t.run_build_system("release")
+t.expect_addition("bin/$toolset/release/a.exe")
+
+# Test that free properties do not matter. We really do not want <cxxflags>
+# property in build request to affect alternative selection.
+t.write("jamfile.jam", """
+exe a : a_empty.cpp : <variant>debug <define>FOO <include>BAR ;
+exe a : a.cpp : <variant>release ;
+""")
+
+t.rm("bin/$toolset/release/a.exe")
+t.run_build_system("release define=FOO")
+t.expect_addition("bin/$toolset/release/a.exe")
+
+# Test that ambiguity is reported correctly.
+t.write("jamfile.jam", """
+exe a : a_empty.cpp ;
+exe a : a.cpp ;
+""")
+t.run_build_system("--no-error-backtrace", status=None)
+t.fail_test(string.find(t.stdout(), "No best alternative") == -1)
+
+# Another ambiguity test: two matches properties in one alternative are neither
+# better nor worse than a single one in another alternative.
+t.write("jamfile.jam", """
+exe a : a_empty.cpp : <optimization>off <profiling>off ;
+exe a : a.cpp : <debug-symbols>on ;
+""")
+
+t.run_build_system("--no-error-backtrace", status=None)
+t.fail_test(string.find(t.stdout(), "No best alternative") == -1)
+
+# Test that we can have alternative without sources.
+t.write("jamfile.jam", """
+alias specific-sources ;
+import feature ;
+feature.extend os : MAGIC ;
+alias specific-sources : b.cpp : <os>MAGIC ;
+exe a : a.cpp specific-sources ;
+""")
+t.rm("bin")
+t.run_build_system()
+
+t.cleanup()
diff --git a/tools/build/v2/test/assert-equal.jam b/tools/build/v2/test/assert-equal.jam
new file mode 100644
index 0000000000..6ed501e74b
--- /dev/null
+++ b/tools/build/v2/test/assert-equal.jam
@@ -0,0 +1,33 @@
+# Copyright 2001 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Evaluates [ rulename arg1... : arg2... : ... : argN... ] and compares the
+# result to expected-results. If there is a mismatch, prints an error message
+# and exits.
+rule assert-equal ( expected-results *
+ : rulename a1 * : a2 * : a3 * : a4 * : a5 * : a6 * : a7 * : a8 * : a9 * )
+{
+
+ local results = [ $(rulename) $(a1) : $(a2) : $(a3)
+ : $(a4) : $(a5) : $(a6) : $(a7) : $(a8) ] ;
+
+ if $(results) != $(expected-results)
+ {
+ EXIT ******ASSERTION FAILURE******* "
+ [ $(rulename) " $(a1)
+ ": "$(a2[1]) $(a2[2-])
+ ": "$(a3[1]) $(a3[2-])
+ ": "$(a4[1]) $(a4[2-])
+ ": "$(a5[1]) $(a5[2-])
+ ": "$(a6[1]) $(a6[2-])
+ ": "$(a7[1]) $(a7[2-])
+ ": "$(a8[1]) $(a8[2-]) "]
+expected:
+ (" $(expected-results) ")
+result was:
+ (" $(results) ")"
+ ;
+
+ }
+}
diff --git a/tools/build/v2/test/bad_dirname.py b/tools/build/v2/test/bad_dirname.py
new file mode 100644
index 0000000000..961a45a48a
--- /dev/null
+++ b/tools/build/v2/test/bad_dirname.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Regression test: when directory of project root contained regex
+# metacharacters, Boost.Build failed to work. Bug reported by Michael Stevens.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("bad[abc]dirname/jamfile.jam", """
+""")
+
+t.write("bad[abc]dirname/jamroot.jam", """
+""")
+
+t.run_build_system(subdir="bad[abc]dirname")
+
+t.cleanup()
diff --git a/tools/build/v2/test/boost-build.jam b/tools/build/v2/test/boost-build.jam
new file mode 100644
index 0000000000..ad68a288ed
--- /dev/null
+++ b/tools/build/v2/test/boost-build.jam
@@ -0,0 +1,14 @@
+# Copyright 2002, 2003 Dave Abrahams
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Assume BOOST_BUILD_PATH point to the 'test' directory.
+# We need to leave 'test' there, so that 'test-config.jam'
+# can be found, but also add parent directory, to find
+# all the other modules.
+
+BOOST_BUILD_PATH = $(BOOST_BUILD_PATH)/.. $(BOOST_BUILD_PATH) ;
+
+# Find the boost build system in the ../kernel directory.
+boost-build ../kernel ;
diff --git a/tools/build/v2/test/boostbook.py b/tools/build/v2/test/boostbook.py
new file mode 100644
index 0000000000..78eab87d0d
--- /dev/null
+++ b/tools/build/v2/test/boostbook.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+
+# Copyright 2004, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import string
+
+t = BoostBuild.Tester()
+
+t.set_tree("boostbook")
+
+# For some reason, the messages are sent to stderr.
+t.run_build_system()
+t.fail_test(string.find(t.stdout(), """Writing boost/A.html for refentry(boost.A)
+Writing library/reference.html for section(library.reference)
+Writing index.html for chapter(library)
+Writing docs_HTML.manifest
+""") == -1)
+t.expect_addition(["html/boost/A.html", "html/index.html"])
+
+t.cleanup()
diff --git a/tools/build/v2/test/boostbook/a.hpp b/tools/build/v2/test/boostbook/a.hpp
new file mode 100644
index 0000000000..5fab129a9c
--- /dev/null
+++ b/tools/build/v2/test/boostbook/a.hpp
@@ -0,0 +1,16 @@
+/* Copyright 2004, 2006 Vladimir Prus */
+/* Distributed under the Boost Software License, Version 1.0. */
+/* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) */
+
+
+// Seems like Boostbook does like classes outside of namespaces,
+// and won't generate anything for them.
+namespace boost {
+
+/// A class
+class A {
+public:
+ /// A constructor
+ A();
+};
+}
diff --git a/tools/build/v2/test/boostbook/docs.xml b/tools/build/v2/test/boostbook/docs.xml
new file mode 100644
index 0000000000..c2d9b1f888
--- /dev/null
+++ b/tools/build/v2/test/boostbook/docs.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+<!-- Copyright 2004 Vladimir Prus -->
+<!-- Distributed under the Boost Software License, Version 1.0. -->
+<!-- (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) -->
+
+<library
+ name="library"
+ dirname="librarys" id="library"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <libraryinfo>
+ <author>
+ <firstname>Joe</firstname>
+ <surname>Hacker</surname>
+ </author>
+
+ <copyright>
+ <year>7002</year>
+ <holder>Joe Hacker</holder>
+ </copyright>
+
+ </libraryinfo>
+
+ <title>Documentation</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>This is introduction</para>
+
+ </section>
+
+ <xi:include href="autodoc.xml"/>
+</library>
diff --git a/tools/build/v2/test/boostbook/jamroot.jam b/tools/build/v2/test/boostbook/jamroot.jam
new file mode 100644
index 0000000000..94564ca29c
--- /dev/null
+++ b/tools/build/v2/test/boostbook/jamroot.jam
@@ -0,0 +1,3 @@
+
+boostbook docs : docs.xml autodoc ;
+doxygen autodoc : [ glob *.hpp ] ;
diff --git a/tools/build/v2/test/build_dir.py b/tools/build/v2/test/build_dir.py
new file mode 100644
index 0000000000..c5bcbc5b97
--- /dev/null
+++ b/tools/build/v2/test/build_dir.py
@@ -0,0 +1,106 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that we can change build directory using the 'build-dir' project
+# attribute.
+
+import BoostBuild
+import string
+import os
+
+t = BoostBuild.Tester()
+
+
+# Test that top-level project can affect build dir.
+t.write("jamroot.jam", "import gcc ;")
+t.write("jamfile.jam", """
+project : build-dir build ;
+exe a : a.cpp ;
+build-project src ;
+""")
+
+t.write("a.cpp", "int main() {}\n")
+
+t.write("src/jamfile.jam", "exe b : b.cpp ; ")
+
+t.write("src/b.cpp", "int main() {}\n")
+
+t.run_build_system()
+
+t.expect_addition(["build/$toolset/debug/a.exe",
+ "build/src/$toolset/debug/b.exe"])
+
+# Test that building from child projects work.
+t.run_build_system(subdir='src')
+t.ignore("build/config.log")
+t.expect_nothing_more()
+
+# Test that project can override build dir.
+t.write("jamfile.jam", """
+exe a : a.cpp ;
+build-project src ;
+""")
+
+t.write("src/jamfile.jam", """
+project : build-dir build ;
+exe b : b.cpp ;
+""")
+
+t.run_build_system()
+t.expect_addition(["bin/$toolset/debug/a.exe",
+ "src/build/$toolset/debug/b.exe"])
+
+# Now test the '--build-dir' option.
+t.rm(".")
+t.write("jamroot.jam", "")
+
+# Test that we get an error when no project id is specified.
+t.run_build_system("--build-dir=foo")
+t.fail_test(string.find(t.stdout(),
+ "warning: the --build-dir option will be ignored") == -1)
+
+t.write("jamroot.jam", """
+project foo ;
+exe a : a.cpp ;
+build-project sub ;
+""")
+t.write("a.cpp", "int main() {}\n")
+t.write("sub/jamfile.jam", "exe b : b.cpp ;\n")
+t.write("sub/b.cpp", "int main() {}\n")
+
+t.run_build_system("--build-dir=build")
+t.expect_addition(["build/foo/$toolset/debug/a.exe",
+ "build/foo/sub/$toolset/debug/b.exe"])
+
+t.write("jamroot.jam", """
+project foo : build-dir bin.v2 ;
+exe a : a.cpp ;
+build-project sub ;
+""")
+
+t.run_build_system("--build-dir=build")
+t.expect_addition(["build/foo/bin.v2/$toolset/debug/a.exe",
+ "build/foo/bin.v2/sub/$toolset/debug/b.exe"])
+
+# Try building in subdir. We expect that the entire build tree with be in
+# 'sub/build'. Today, I am not sure if this is what the user expects, but let it
+# be.
+t.rm('build')
+t.run_build_system("--build-dir=build", subdir="sub")
+t.expect_addition(["sub/build/foo/bin.v2/sub/$toolset/debug/b.exe"])
+
+t.write("jamroot.jam", """
+project foo : build-dir %s ;
+exe a : a.cpp ;
+build-project sub ;
+""" % string.replace(os.getcwd(), '\\', '\\\\'))
+
+t.run_build_system("--build-dir=build", status=1)
+t.fail_test(string.find(t.stdout(),
+ "Absolute directory specified via 'build-dir' project attribute") == -1)
+
+t.cleanup()
diff --git a/tools/build/v2/test/build_file.py b/tools/build/v2/test/build_file.py
new file mode 100644
index 0000000000..609690fea4
--- /dev/null
+++ b/tools/build/v2/test/build_file.py
@@ -0,0 +1,170 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Copyright (C) Jurko Gospodnetic 2008.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests that we explicitly request a file (not target) to be built by specifying
+# its name on the command line.
+
+import BoostBuild
+
+
+################################################################################
+#
+# test_building_file_from_specific_project()
+# ------------------------------------------
+#
+################################################################################
+
+def test_building_file_from_specific_project():
+ t = BoostBuild.Tester()
+
+ t.write("jamroot.jam", """
+exe hello : hello.cpp ;
+exe hello2 : hello.cpp ;
+build-project sub ;
+""")
+ t.write("hello.cpp", "int main() {}")
+ t.write("sub/jamfile.jam", """
+exe hello : hello.cpp ;
+exe hello2 : hello.cpp ;
+exe sub : hello.cpp ;
+""")
+ t.write("sub/hello.cpp", "int main() {}")
+
+ t.run_build_system("sub " + t.adjust_suffix("hello.obj"))
+ t.expect_output_line("*depends on itself*", False)
+ t.expect_addition("sub/bin/$toolset/debug/hello.obj")
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_building_file_from_specific_target()
+# -----------------------------------------
+#
+################################################################################
+
+def test_building_file_from_specific_target():
+ t = BoostBuild.Tester()
+
+ t.write("jamroot.jam", """
+exe hello1 : hello1.cpp ;
+exe hello2 : hello2.cpp ;
+exe hello3 : hello3.cpp ;
+""")
+ t.write("hello1.cpp", "int main() {}")
+ t.write("hello2.cpp", "int main() {}")
+ t.write("hello3.cpp", "int main() {}")
+
+ t.run_build_system("hello1 " + t.adjust_suffix("hello1.obj"))
+ t.expect_addition("bin/$toolset/debug/hello1.obj")
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_building_missing_file_from_specific_target()
+# -------------------------------------------------
+#
+################################################################################
+
+def test_building_missing_file_from_specific_target():
+ t = BoostBuild.Tester()
+
+ t.write("jamroot.jam", """
+exe hello1 : hello1.cpp ;
+exe hello2 : hello2.cpp ;
+exe hello3 : hello3.cpp ;
+""")
+ t.write("hello1.cpp", "int main() {}")
+ t.write("hello2.cpp", "int main() {}")
+ t.write("hello3.cpp", "int main() {}")
+
+ t.run_build_system("hello1 " + t.adjust_suffix("hello2.obj"), status=1)
+ t.expect_output_line("don't know how to make*" + t.adjust_suffix("hello2.obj"))
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_building_multiple_files_with_different_names()
+# ---------------------------------------------------
+#
+################################################################################
+
+def test_building_multiple_files_with_different_names():
+ t = BoostBuild.Tester()
+
+ t.write("jamroot.jam", """
+exe hello1 : hello1.cpp ;
+exe hello2 : hello2.cpp ;
+exe hello3 : hello3.cpp ;
+""")
+ t.write("hello1.cpp", "int main() {}")
+ t.write("hello2.cpp", "int main() {}")
+ t.write("hello3.cpp", "int main() {}")
+
+ t.run_build_system(
+ t.adjust_suffix("hello1.obj") + " " +
+ t.adjust_suffix("hello2.obj"))
+ t.expect_addition("bin/$toolset/debug/hello1.obj")
+ t.expect_addition("bin/$toolset/debug/hello2.obj")
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_building_multiple_files_with_the_same_name()
+# -------------------------------------------------
+#
+################################################################################
+
+def test_building_multiple_files_with_the_same_name():
+ t = BoostBuild.Tester()
+
+ t.write("jamroot.jam", """
+exe hello : hello.cpp ;
+exe hello2 : hello.cpp ;
+build-project sub ;
+""")
+ t.write("hello.cpp", "int main() {}")
+ t.write("sub/jamfile.jam", """
+exe hello : hello.cpp ;
+exe hello2 : hello.cpp ;
+exe sub : hello.cpp ;
+""")
+ t.write("sub/hello.cpp", "int main() {}")
+
+ t.run_build_system(t.adjust_suffix("hello.obj"))
+ t.expect_output_line("*depends on itself*", False)
+ t.expect_addition("bin/$toolset/debug/hello.obj")
+ t.expect_addition("sub/bin/$toolset/debug/hello.obj")
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+test_building_file_from_specific_project()
+test_building_file_from_specific_target()
+test_building_missing_file_from_specific_target()
+test_building_multiple_files_with_different_names()
+test_building_multiple_files_with_the_same_name()
diff --git a/tools/build/v2/test/build_no.py b/tools/build/v2/test/build_no.py
new file mode 100644
index 0000000000..f6e6f9305e
--- /dev/null
+++ b/tools/build/v2/test/build_no.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests that <build>no property prevents a target from being built.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+exe hello : hello.cpp : <variant>debug:<build>no ;
+""")
+
+t.write("hello.cpp", """
+int main() {}
+""")
+
+t.run_build_system()
+t.expect_nothing_more()
+
+t.run_build_system("release")
+t.expect_addition("bin/$toolset/release/hello.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/c_file.py b/tools/build/v2/test/c_file.py
new file mode 100644
index 0000000000..28fe253112
--- /dev/null
+++ b/tools/build/v2/test/c_file.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that C files are compiled by a C compiler.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+project ;
+exe hello : hello.cpp a.c ;
+""")
+
+t.write("hello.cpp", """
+extern "C" int foo();
+int main() { return foo(); }
+""")
+
+t.write("a.c", """
+// This will not compile unless in C mode.
+int foo()
+{
+ int new = 0;
+ new = (new+1)*7;
+ return new;
+}
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/chain.py b/tools/build/v2/test/chain.py
new file mode 100644
index 0000000000..a7cf1b8314
--- /dev/null
+++ b/tools/build/v2/test/chain.py
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This tests that :
+# 1) the 'make' correctly assigns types to produced targets
+# 2) if 'make' creates targets of type CPP, they are correctly used.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+# In order to correctly link this app, 'b.cpp', created by a 'make' rule, should
+# be compiled.
+
+t.write("jamroot.jam", "import gcc ;")
+
+t.write("jamfile.jam", r'''
+import os ;
+if [ os.name ] = NT
+{
+ actions create
+ {
+ echo int main() {} > $(<)
+ }
+}
+else
+{
+ actions create
+ {
+ echo "int main() {}" > $(<)
+ }
+}
+
+IMPORT $(__name__) : create : : create ;
+
+exe a : l dummy.cpp ;
+
+# Needs to be static lib for Windows - main() cannot appear in DLL.
+static-lib l : a.cpp b.cpp ;
+
+make b.cpp : : create ;
+''')
+
+t.write("a.cpp", "")
+
+t.write("dummy.cpp", "// msvc needs at least one object file\n")
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/a.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/check-arguments.jam b/tools/build/v2/test/check-arguments.jam
new file mode 100644
index 0000000000..20e025074d
--- /dev/null
+++ b/tools/build/v2/test/check-arguments.jam
@@ -0,0 +1,71 @@
+# Copyright 2001 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+#
+# Jam code for testing the named-argument patch.
+#
+
+include recursive.jam ;
+
+# Prefixes for all of the jam code we're going to test
+local ECHO_ARGS = "include echo_args.jam ; echo_args "
+ ;
+
+local ECHO_VARARGS = "include echo_args.jam ; echo_varargs "
+ ;
+
+# Check that it will find missing arguments
+Jam-fail $(ECHO_ARGS)";"
+ : "missing argument a"
+ ;
+
+# Check that it will find if too many arguments are passed
+Jam-fail $(ECHO_ARGS)"1 2 : 3 : 4 : 5 ;"
+ : "extra argument 5"
+ ;
+
+# Check that it will find when an argument has too many elements
+Jam-fail $(ECHO_ARGS)"a b c1 c2 : d ;"
+ : "extra argument c2"
+ ;
+
+# Check modifier '?'
+Jam $(ECHO_ARGS)"1 2 3 : 4 ;"
+ : "a= 1 b= 2 c= 3 : d= 4 : e=" ;
+Jam $(ECHO_ARGS)"1 2 : 3 ;"
+ : "a= 1 b= 2 c= : d= 3 : e=" ;
+Jam $(ECHO_ARGS)"1 : 2 ;"
+ : "a= 1 b= c= : d= 2 : e=" ;
+
+# Check modifier '+'
+Jam-fail $(ECHO_ARGS)"1 ;"
+ : "missing argument d" ;
+Jam $(ECHO_ARGS)"1 : 2 3 ;"
+ : "a= 1 b= c= : d= 2 3 : e=" ;
+Jam $(ECHO_ARGS)"1 : 2 3 4 ;"
+ : "a= 1 b= c= : d= 2 3 4 : e=" ;
+
+# Check modifier '*'
+Jam $(ECHO_ARGS)"1 : 2 : 3 ;"
+ : "a= 1 b= c= : d= 2 : e= 3" ;
+Jam $(ECHO_ARGS)"1 : 2 : 3 4 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4" ;
+Jam $(ECHO_ARGS)"1 : 2 : 3 4 5 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5" ;
+
+#
+# Check varargs
+#
+Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5" ;
+Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6" ;
+Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 7 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7" ;
+Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 7 : 8 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7 : 8" ;
+Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 7 : 8 : 9 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7 : 8 : 9" ;
+
+
diff --git a/tools/build/v2/test/check-bindrule.jam b/tools/build/v2/test/check-bindrule.jam
new file mode 100644
index 0000000000..f8eb986e39
--- /dev/null
+++ b/tools/build/v2/test/check-bindrule.jam
@@ -0,0 +1,29 @@
+# Copyright 2001 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This rule establishes a dependency, with no special build actions
+rule do-nothing ( target : source )
+{
+ DEPENDS $(target) : $(source) ;
+}
+actions quietly do-nothing
+{
+}
+
+# Make a non-file target which depends on a file that exists
+NOTFILE fake-target ;
+SEARCH on file-to-bind = subdir1 ;
+
+do-nothing fake-target
+ : file-to-bind ;
+
+# Set jam up to call our bind-rule
+BINDRULE = bind-rule ;
+
+rule bind-rule ( target : path )
+{
+ ECHO found: $(target) at $(path) ;
+}
+
+DEPENDS all : fake-target ;
diff --git a/tools/build/v2/test/check-jam-patches.jam b/tools/build/v2/test/check-jam-patches.jam
new file mode 100644
index 0000000000..7e00bec20c
--- /dev/null
+++ b/tools/build/v2/test/check-jam-patches.jam
@@ -0,0 +1,293 @@
+# Copyright 2001, 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Get the recursive Jam invocation code
+include recursive.jam ;
+include assert-equal.jam ;
+
+Jam "include check-bindrule.jam ;"
+ : "found: file-to-bind at subdir1$(SLASH)file-to-bind"
+ ;
+
+include check-arguments.jam ;
+
+if $(NT)
+{
+ # if this one fails, you don't have the line length patch
+ Jam "include test_nt_line_length.jam ;" ;
+}
+
+# a little utility for assertions
+rule identity ( list * )
+{
+ return $(list) ;
+}
+
+#
+# test rule indirection
+#
+rule select ( n list * )
+{
+ return $(list[$(n)]) ;
+}
+
+rule indirect1 ( rule + : args * )
+{
+ return [ $(rule) $(args) ] ;
+}
+
+assert-equal a : indirect1 select 1 : a b c d e ;
+assert-equal b : indirect1 select 2 : a b c d e ;
+
+x = reset ;
+rule reset-x ( new-value )
+{
+ x = $(new-value) ;
+}
+$(x)-x bar ; # invokes reset-x...
+assert-equal bar : identity $(x) ; # which changes x
+
+# Check that unmatched subst returns an empty list
+assert-equal # nothing
+ : SUBST "abc" "d+" x ;
+
+# Check that a matched subst works
+assert-equal x
+ : SUBST "ddd" "d+" x ;
+
+# Check that we can get multiple substitutions from a single invocation
+assert-equal x y x-y
+ : SUBST "x/y/z" "([^/]*)/([^/]*).*" "\\1" $2 "\\1-\\2" ;
+
+#
+# test local foreach modification
+#
+{
+ local x = 0 ;
+ local entered = ;
+ for local x in a b c # x declared local to for loop.
+ {
+ entered = 1 ;
+ if ! ( $(x) in a b c )
+ {
+ EXIT "local foreach: expected one of a, b, c; got" $(x) ;
+ }
+ }
+
+ if $(x) != 0 # if x was modified, it failed to be a local variable
+ {
+ EXIT "local foreach failed" ;
+ }
+}
+
+#
+# test while loops
+#
+{
+ local x = a b c ;
+ local y = $(x) ;
+ local z = ;
+
+ while $(y)
+ {
+ z += $(y[1]) ;
+ y = $(y[2-]) ;
+ }
+
+ if $(z) != $(x)
+ {
+ EXIT "while loops failed" ;
+ }
+}
+
+#
+# test negative list indices and slices
+#
+{
+ local x = a b c d e ;
+
+ rule assert-index ( index : list * )
+ {
+ if $(x[$(index)]) != $(list)
+ {
+ ECHO with x= $(x) ;
+ ECHO x[$(index)] == $(x[$(index)]) ;
+ EXIT expected $(list) ;
+ }
+ }
+
+ assert-index 1 : a ;
+ assert-index 3 : c ;
+ assert-index 1-2 : a b ;
+ assert-index -1 : e ;
+ assert-index -2 : d ;
+ assert-index 2--2 : b c d ;
+ assert-index -3--2 : c d ;
+ assert-index 1--2 : a b c d ;
+ assert-index 1--2 : a b c d ;
+ assert-index 1--10 : ;
+ x = a ;
+ assert-index 1--2 : ;
+ assert-index 1--2 : ;
+}
+
+#
+# test module primitives
+#
+{
+ local x = a b c d e f g h i j ;
+ local y = $(x[3-]) ;
+
+ rule shift1 ( dummy ) { }
+
+ rule my_module.not_really ( ) { return something ; }
+
+ # import the identity rule into my_module as "id"
+ IMPORT : identity : my_module : id ;
+ module my_module
+ {
+ # assert-equal operates in its own module, so call id in here and use
+ # identity later.
+ local f = [ id x y z ] ;
+ assert-equal x y z : identity $(f) ;
+
+ w = ;
+ y = ;
+ x2 = 1 2 3 ;
+ x3 = $(x2) ;
+ z = $(x2) ;
+
+ x3 = ; # should reset x3
+
+ # drops one element from the head of x
+ # moves the first element of z from the head of z to the head of y
+ rule shift1 ( )
+ {
+ x = $(x[2-]) ;
+ y = $(z[1]) $(y) ;
+ z = $(z[2-]) ;
+ }
+
+ rule shift2 ( )
+ {
+ shift1 ;
+ }
+
+ shift1 ;
+ shift2 ;
+
+ rule get ( symbol )
+ {
+ return $($(symbol)) ;
+ }
+ local rule not_really ( ) { return nothing ; }
+ }
+
+ local expected = shift1 shift2 get ;
+ if ! ( $(expected) in [ RULENAMES my_module ] )
+ || ! ( [ RULENAMES my_module ] in $(expected) )
+ {
+ EXIT "[ RULENAMES my_module ] =" [ RULENAMES my_module ] "!=" shift1 shift2 get ;
+ }
+
+
+ # show that not_really was actually a local definition
+ assert-equal something : my_module.not_really ;
+
+ if not_really in [ RULENAMES my_module ]
+ {
+ EXIT unexpectedly found local rule "not_really" in "my_module" ;
+ }
+ EXPORT my_module : not_really ;
+
+ if ! ( not_really in [ RULENAMES my_module ] )
+ {
+ EXIT unexpectedly failed to find exported rule "not_really" in "my_module" ;
+ }
+
+ # show that my_module doesn't have access to our variables
+ my_module.shift1 ;
+ assert-equal $(x[3-]) : identity $(y) ;
+
+ # check module locals
+ assert-equal : my_module.get w ;
+ assert-equal 3 2 1 : my_module.get y ;
+ assert-equal 1 2 3 : my_module.get x2 ;
+ assert-equal : my_module.get x3 ;
+ assert-equal : my_module.get z ;
+
+ my_module.shift2 ;
+ x = $(x[3-]) ;
+ assert-equal $(x) : identity $(y) ;
+
+ # Prove that the module's rule is not exposed to the world at large without
+ # qualification
+ shift1 nothing ;
+ assert-equal $(x) : identity $(y) ;
+
+ # import my_module.shift1 into the global module as "shifty", and
+ # my_module.shift2 into the global module as "shift2".
+ IMPORT my_module : shift1 shift2 : : shifty shift2 ;
+
+ shifty ;
+ assert-equal $(x) : identity $(y) ;
+
+ shift2 ;
+ assert-equal $(x) : identity $(y) ;
+
+ # Now do the same with localization
+ IMPORT my_module : shift1 : : shifty : LOCALIZE ;
+
+ shifty ;
+ y = $(y[3-]) ;
+ assert-equal $(x) : identity $(y) ;
+
+ # import everything from my_module into the global module using
+ # the same names.
+ IMPORT my_module : [ RULENAMES my_module ] : : [ RULENAMES my_module ] : LOCALIZE ;
+
+ shift1 ;
+ y = $(y[2-]) ;
+ assert-equal $(x) : identity $(y) ;
+
+ shift2 ;
+ y = $(y[2-]) ;
+ assert-equal $(x) : identity $(y) ;
+}
+
+#
+# test CALLER_MODULE and backtrace
+#
+{
+ rule backtrace ( )
+ {
+ local bt = [ BACKTRACE ] ;
+ bt = $(bt[5-]) ;
+ while $(bt)
+ {
+ ECHO $(bt[1]):$(bt[2]): "in" $(bt[4]) ;
+ bt = $(bt[5-]) ;
+ }
+ }
+ module module1
+ {
+ rule f ( )
+ {
+ local m = [ CALLER_MODULE ] ;
+ assert-equal : identity $(m) ;
+ module2.f ;
+ }
+
+ }
+ module module2
+ {
+ rule f ( )
+ {
+ local m = [ CALLER_MODULE ] ;
+ assert-equal module1 : identity $(m) ;
+ backtrace ;
+ }
+ }
+ module1.f ;
+}
diff --git a/tools/build/v2/test/check-test-tools.jam b/tools/build/v2/test/check-test-tools.jam
new file mode 100644
index 0000000000..adf78cc3b4
--- /dev/null
+++ b/tools/build/v2/test/check-test-tools.jam
@@ -0,0 +1,26 @@
+# Copyright 2001 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+include recursive.jam ;
+include assert-equal.jam ;
+
+#####################################
+# Test the testing tools right here #
+#####################################
+
+# This command always exits with a failure.
+Jam-fail "EXIT error ;" ;
+
+# This should fail to fail
+Jam-fail
+ "include recursive.jam ; Jam-fail \"# this innocuous Jamfile should fail to fail\" ;"
+ ;
+
+# the ECHO rule always has an empty result.
+Jam-fail "include assert-equal.jam ; assert-equal fubar : ECHO checking that assertions fail ;"
+ : "ASSERTION FAILURE"
+ ;
+
+local NOTHING = ;
+assert-equal $(NOTHING) : ECHO checking that assertions succeed ;
diff --git a/tools/build/v2/test/clean.py b/tools/build/v2/test/clean.py
new file mode 100644
index 0000000000..8c95e6127d
--- /dev/null
+++ b/tools/build/v2/test/clean.py
@@ -0,0 +1,116 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("a.cpp", """
+int main() {}
+""")
+
+t.write("jamroot.jam", """
+exe a : a.cpp sub1//sub1 sub2//sub2 sub3//sub3 ;
+""")
+
+t.write("sub1/jamfile.jam", """
+lib sub1 : sub1.cpp sub1_2 ../sub2//sub2 ;
+lib sub1_2 : sub1_2.cpp ;
+""")
+
+t.write("sub1/sub1.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void sub1() {}
+""")
+
+t.write("sub1/sub1_2.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void sub1() {}
+""")
+
+t.write("sub2/jamfile.jam", """
+lib sub2 : sub2.cpp ;
+""")
+
+t.write("sub2/sub2.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void sub2() {}
+""")
+
+t.write("sub3/jamroot.jam", """
+lib sub3 : sub3.cpp ;
+""")
+
+t.write("sub3/sub3.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void sub3() {}
+""")
+
+# The 'clean' should not remove files under separate jamroot.jam.
+t.run_build_system()
+t.run_build_system("--clean")
+t.expect_removal("bin/$toolset/debug/a.obj")
+t.expect_removal("sub1/bin/$toolset/debug/sub1.obj")
+t.expect_removal("sub1/bin/$toolset/debug/sub1_2.obj")
+t.expect_removal("sub2/bin/$toolset/debug/sub2.obj")
+t.expect_nothing("sub3/bin/$toolset/debug/sub3.obj")
+
+# The 'clean-all' removes everything it can reach.
+t.run_build_system()
+t.run_build_system("--clean-all")
+t.expect_removal("bin/$toolset/debug/a.obj")
+t.expect_removal("sub1/bin/$toolset/debug/sub1.obj")
+t.expect_removal("sub1/bin/$toolset/debug/sub1_2.obj")
+t.expect_removal("sub2/bin/$toolset/debug/sub2.obj")
+t.expect_nothing("sub3/bin/$toolset/debug/sub3.obj")
+
+# The 'clean' together with project target removes only under that project.
+t.run_build_system()
+t.run_build_system("sub1 --clean")
+t.expect_nothing("bin/$toolset/debug/a.obj")
+t.expect_removal("sub1/bin/$toolset/debug/sub1.obj")
+t.expect_removal("sub1/bin/$toolset/debug/sub1_2.obj")
+t.expect_nothing("sub2/bin/$toolset/debug/sub2.obj")
+t.expect_nothing("sub3/bin/$toolset/debug/sub3.obj")
+
+# And 'clean-all' removes everything.
+t.run_build_system()
+t.run_build_system("sub1 --clean-all")
+t.expect_nothing("bin/$toolset/debug/a.obj")
+t.expect_removal("sub1/bin/$toolset/debug/sub1.obj")
+t.expect_removal("sub1/bin/$toolset/debug/sub1_2.obj")
+t.expect_removal("sub2/bin/$toolset/debug/sub2.obj")
+t.expect_nothing("sub3/bin/$toolset/debug/sub3.obj")
+
+# If main target is explicitly named, we should not remove files from other
+# targets.
+t.run_build_system()
+t.run_build_system("sub1//sub1 --clean")
+t.expect_removal("sub1/bin/$toolset/debug/sub1.obj")
+t.expect_nothing("sub1/bin/$toolset/debug/sub1_2.obj")
+t.expect_nothing("sub2/bin/$toolset/debug/sub2.obj")
+t.expect_nothing("sub3/bin/$toolset/debug/sub3.obj")
+
+# Regression test: sources of the 'cast' rule were mistakenly deleted.
+t.rm(".")
+t.write("jamroot.jam", """
+import cast ;
+cast a cpp : a.h ;
+""")
+t.write("a.h", "")
+t.run_build_system("--clean")
+t.expect_nothing("a.h")
+
+t.cleanup()
diff --git a/tools/build/v2/test/composite.py b/tools/build/v2/test/composite.py
new file mode 100644
index 0000000000..ca3fb3272c
--- /dev/null
+++ b/tools/build/v2/test/composite.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that composite properties are handled correctly.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+exe hello : hello.cpp : <variant>release ;
+""")
+
+t.write("hello.cpp", """
+int main() {}
+""")
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/release/hello.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/conditionals.py b/tools/build/v2/test/conditionals.py
new file mode 100644
index 0000000000..b1d78a5406
--- /dev/null
+++ b/tools/build/v2/test/conditionals.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test conditional properties.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+# Arrange a project which will build only if 'a.cpp' is compiled with "STATIC"
+# define.
+t.write("a.cpp", """
+#ifdef STATIC
+int main() {}
+#endif
+""")
+
+# Test conditionals in target requirements.
+t.write("jamroot.jam", "exe a : a.cpp : <link>static:<define>STATIC ;")
+t.run_build_system("link=static")
+t.expect_addition("bin/$toolset/debug/link-static/a.exe")
+t.rm("bin")
+
+# Test conditionals in project requirements.
+t.write("jamroot.jam", """
+project : requirements <link>static:<define>STATIC ;
+exe a : a.cpp ;
+""")
+t.run_build_system("link=static")
+t.expect_addition("bin/$toolset/debug/link-static/a.exe")
+t.rm("bin")
+
+# Regression test for a bug found by Ali Azarbayejani. Conditionals inside usage
+# requirement were not being evaluated.
+t.write("jamroot.jam", """
+lib l : l.cpp : : : <link>static:<define>STATIC ;
+exe a : a.cpp l ;
+""")
+t.write("l.cpp", "int i;")
+t.run_build_system("link=static")
+t.expect_addition("bin/$toolset/debug/link-static/a.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/conditionals2.py b/tools/build/v2/test/conditionals2.py
new file mode 100644
index 0000000000..585e5ca774
--- /dev/null
+++ b/tools/build/v2/test/conditionals2.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Regression test: it was possible that due to evaluation of conditional
+# requirements, two different values of non-free features were present in a
+# property set.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("a.cpp", "")
+
+t.write("jamroot.jam", """
+import feature ;
+import common ;
+
+feature.feature the_feature : false true : propagated ;
+
+rule maker ( targets * : sources * : properties * )
+{
+ if <the_feature>false in $(properties) &&
+ <the_feature>true in $(properties)
+ {
+ EXIT "Oops, two different values of non-free feature" ;
+ }
+ CMD on $(targets) = [ common.file-creation-command ] ;
+}
+
+actions maker
+{
+ $(CMD) $(<) ;
+}
+
+make a : a.cpp : maker : <variant>debug:<the_feature>true ;
+""")
+
+t.run_build_system()
+
+t.cleanup()
diff --git a/tools/build/v2/test/conditionals3.py b/tools/build/v2/test/conditionals3.py
new file mode 100644
index 0000000000..ca328ff1b7
--- /dev/null
+++ b/tools/build/v2/test/conditionals3.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that conditional properties work, even if property is free, and value
+# includes a colon.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+exe hello : hello.cpp : <variant>debug:<define>CLASS=Foo::Bar ;
+""")
+
+t.write("hello.cpp", """
+namespace Foo { class Bar { } ; }
+int main()
+{
+ CLASS c;
+ c; // Disables the unused variable warning.
+}
+""")
+
+t.run_build_system(stdout=None, stderr=None)
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/conditionals_multiple.py b/tools/build/v2/test/conditionals_multiple.py
new file mode 100755
index 0000000000..20b6b47f7b
--- /dev/null
+++ b/tools/build/v2/test/conditionals_multiple.py
@@ -0,0 +1,297 @@
+#!/usr/bin/python
+
+# Copyright 2008 Jurko Gospodnetic
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests that properties conditioned on more than one other property work as
+# expected.
+
+import BoostBuild
+
+
+################################################################################
+#
+# test_multiple_conditions()
+# --------------------------
+#
+################################################################################
+
+def test_multiple_conditions():
+ """Basic tests for properties conditioned on multiple other properties.
+ """
+
+ t = BoostBuild.Tester("--ignore-regular-config toolset=testToolset",
+ pass_toolset=False, use_test_config=False)
+
+ t.write("testToolset.jam", """
+import feature ;
+feature.extend toolset : testToolset ;
+rule init ( ) { }
+""")
+
+ t.write("jamroot.jam", """
+import feature ;
+import notfile ;
+import toolset ;
+
+feature.feature description : : free incidental ;
+feature.feature aaa : 1 0 : incidental ;
+feature.feature bbb : 1 0 : incidental ;
+feature.feature ccc : 1 0 : incidental ;
+
+rule buildRule ( name : targets ? : properties * )
+{
+ for local description in [ feature.get-values description : $(properties) ]
+ {
+ ECHO "description:" /$(description)/ ;
+ }
+}
+
+notfile testTarget1 : @buildRule : :
+ <description>d
+ <aaa>0:<description>a0
+ <aaa>1:<description>a1
+ <aaa>0,<bbb>0:<description>a0-b0
+ <aaa>0,<bbb>1:<description>a0-b1
+ <aaa>1,<bbb>0:<description>a1-b0
+ <aaa>1,<bbb>1:<description>a1-b1
+ <aaa>0,<bbb>0,<ccc>0:<description>a0-b0-c0
+ <aaa>0,<bbb>0,<ccc>1:<description>a0-b0-c1
+ <aaa>0,<bbb>1,<ccc>1:<description>a0-b1-c1
+ <aaa>1,<bbb>0,<ccc>1:<description>a1-b0-c1
+ <aaa>1,<bbb>1,<ccc>0:<description>a1-b1-c0
+ <aaa>1,<bbb>1,<ccc>1:<description>a1-b1-c1 ;
+""")
+
+ t.run_build_system("aaa=1 bbb=1 ccc=1")
+ t.expect_output_line("description: /d/" )
+ t.expect_output_line("description: /a0/" , False)
+ t.expect_output_line("description: /a1/" )
+ t.expect_output_line("description: /a0-b0/" , False)
+ t.expect_output_line("description: /a0-b1/" , False)
+ t.expect_output_line("description: /a1-b0/" , False)
+ t.expect_output_line("description: /a1-b1/" )
+ t.expect_output_line("description: /a0-b0-c0/", False)
+ t.expect_output_line("description: /a0-b0-c1/", False)
+ t.expect_output_line("description: /a0-b1-c1/", False)
+ t.expect_output_line("description: /a1-b0-c1/", False)
+ t.expect_output_line("description: /a1-b1-c0/", False)
+ t.expect_output_line("description: /a1-b1-c1/" )
+
+ t.run_build_system("aaa=0 bbb=0 ccc=1")
+ t.expect_output_line("description: /d/" )
+ t.expect_output_line("description: /a0/" )
+ t.expect_output_line("description: /a1/" , False)
+ t.expect_output_line("description: /a0-b0/" )
+ t.expect_output_line("description: /a0-b1/" , False)
+ t.expect_output_line("description: /a1-b0/" , False)
+ t.expect_output_line("description: /a1-b1/" , False)
+ t.expect_output_line("description: /a0-b0-c0/", False)
+ t.expect_output_line("description: /a0-b0-c1/" )
+ t.expect_output_line("description: /a0-b1-c1/", False)
+ t.expect_output_line("description: /a1-b0-c1/", False)
+ t.expect_output_line("description: /a1-b1-c0/", False)
+ t.expect_output_line("description: /a1-b1-c1/", False)
+
+ t.run_build_system("aaa=0 bbb=0 ccc=0")
+ t.expect_output_line("description: /d/" )
+ t.expect_output_line("description: /a0/" )
+ t.expect_output_line("description: /a1/" , False)
+ t.expect_output_line("description: /a0-b0/" )
+ t.expect_output_line("description: /a0-b1/" , False)
+ t.expect_output_line("description: /a1-b0/" , False)
+ t.expect_output_line("description: /a1-b1/" , False)
+ t.expect_output_line("description: /a0-b0-c0/" )
+ t.expect_output_line("description: /a0-b0-c1/", False)
+ t.expect_output_line("description: /a0-b1-c1/", False)
+ t.expect_output_line("description: /a1-b0-c1/", False)
+ t.expect_output_line("description: /a1-b1-c0/", False)
+ t.expect_output_line("description: /a1-b1-c1/", False)
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_multiple_conditions_with_toolset_version()
+# -----------------------------------------------
+#
+################################################################################
+
+def test_multiple_conditions_with_toolset_version():
+ """Regression tests for properties conditioned on the toolset version
+ subfeature and some additional properties.
+ """
+
+ toolset = "testToolset" ;
+
+ t = BoostBuild.Tester("--ignore-regular-config", pass_toolset=False, use_test_config=False)
+
+ t.write( toolset + ".jam", """
+import feature ;
+feature.extend toolset : %(toolset)s ;
+feature.subfeature toolset %(toolset)s : version : 0 1 ;
+rule init ( version ? ) { }
+""" % {"toolset": toolset})
+
+ t.write("jamroot.jam", """
+import feature ;
+import notfile ;
+import toolset ;
+
+toolset.using testToolset ;
+
+feature.feature description : : free incidental ;
+feature.feature aaa : 0 1 : incidental ;
+feature.feature bbb : 0 1 : incidental ;
+feature.feature ccc : 0 1 : incidental ;
+
+rule buildRule ( name : targets ? : properties * )
+{
+ local ttt = [ feature.get-values toolset : $(properties) ] ;
+ local vvv = [ feature.get-values toolset-testToolset:version : $(properties) ] ;
+ local aaa = [ feature.get-values aaa : $(properties) ] ;
+ local bbb = [ feature.get-values bbb : $(properties) ] ;
+ local ccc = [ feature.get-values ccc : $(properties) ] ;
+ ECHO "toolset:" /$(ttt)/ "version:" /$(vvv)/ "aaa/bbb/ccc:" /$(aaa)/$(bbb)/$(ccc)/ ;
+ for local description in [ feature.get-values description : $(properties) ]
+ {
+ ECHO "description:" /$(description)/ ;
+ }
+}
+
+notfile testTarget1 : @buildRule : :
+ <toolset>testToolset,<aaa>0:<description>t-a0
+ <toolset>testToolset,<aaa>1:<description>t-a1
+
+ <toolset>testToolset-0,<aaa>0:<description>t0-a0
+ <toolset>testToolset-0,<aaa>1:<description>t0-a1
+ <toolset>testToolset-1,<aaa>0:<description>t1-a0
+ <toolset>testToolset-1,<aaa>1:<description>t1-a1
+
+ <toolset>testToolset,<aaa>0,<bbb>0:<description>t-a0-b0
+ <toolset>testToolset,<aaa>0,<bbb>1:<description>t-a0-b1
+ <toolset>testToolset,<aaa>1,<bbb>0:<description>t-a1-b0
+ <toolset>testToolset,<aaa>1,<bbb>1:<description>t-a1-b1
+
+ <aaa>0,<toolset>testToolset,<bbb>0:<description>a0-t-b0
+ <aaa>0,<toolset>testToolset,<bbb>1:<description>a0-t-b1
+ <aaa>1,<toolset>testToolset,<bbb>0:<description>a1-t-b0
+ <aaa>1,<toolset>testToolset,<bbb>1:<description>a1-t-b1
+
+ <aaa>0,<bbb>0,<toolset>testToolset:<description>a0-b0-t
+ <aaa>0,<bbb>1,<toolset>testToolset:<description>a0-b1-t
+ <aaa>1,<bbb>0,<toolset>testToolset:<description>a1-b0-t
+ <aaa>1,<bbb>1,<toolset>testToolset:<description>a1-b1-t
+
+ <toolset>testToolset-0,<aaa>0,<bbb>0:<description>t0-a0-b0
+ <toolset>testToolset-0,<aaa>0,<bbb>1:<description>t0-a0-b1
+ <toolset>testToolset-0,<aaa>1,<bbb>0:<description>t0-a1-b0
+ <toolset>testToolset-0,<aaa>1,<bbb>1:<description>t0-a1-b1
+ <toolset>testToolset-1,<aaa>0,<bbb>0:<description>t1-a0-b0
+ <toolset>testToolset-1,<aaa>0,<bbb>1:<description>t1-a0-b1
+ <toolset>testToolset-1,<aaa>1,<bbb>0:<description>t1-a1-b0
+ <toolset>testToolset-1,<aaa>1,<bbb>1:<description>t1-a1-b1
+
+ <aaa>0,<toolset>testToolset-1,<bbb>0:<description>a0-t1-b0
+ <aaa>0,<toolset>testToolset-1,<bbb>1:<description>a0-t1-b1
+ <aaa>1,<toolset>testToolset-0,<bbb>0:<description>a1-t0-b0
+ <aaa>1,<toolset>testToolset-0,<bbb>1:<description>a1-t0-b1
+
+ <bbb>0,<aaa>1,<toolset>testToolset-0:<description>b0-a1-t0
+ <bbb>0,<aaa>0,<toolset>testToolset-1:<description>b0-a0-t1
+ <bbb>0,<aaa>1,<toolset>testToolset-1:<description>b0-a1-t1
+ <bbb>1,<aaa>0,<toolset>testToolset-1:<description>b1-a0-t1
+ <bbb>1,<aaa>1,<toolset>testToolset-0:<description>b1-a1-t0
+ <bbb>1,<aaa>1,<toolset>testToolset-1:<description>b1-a1-t1 ;
+""")
+
+ t.run_build_system("aaa=1 bbb=1 ccc=1 toolset=%s-0" % toolset)
+ t.expect_output_line("description: /t-a0/" , False)
+ t.expect_output_line("description: /t-a1/" )
+ t.expect_output_line("description: /t0-a0/" , False)
+ t.expect_output_line("description: /t0-a1/" )
+ t.expect_output_line("description: /t1-a0/" , False)
+ t.expect_output_line("description: /t1-a1/" , False)
+ t.expect_output_line("description: /t-a0-b0/" , False)
+ t.expect_output_line("description: /t-a0-b1/" , False)
+ t.expect_output_line("description: /t-a1-b0/" , False)
+ t.expect_output_line("description: /t-a1-b1/" )
+ t.expect_output_line("description: /a0-t-b0/" , False)
+ t.expect_output_line("description: /a0-t-b1/" , False)
+ t.expect_output_line("description: /a1-t-b0/" , False)
+ t.expect_output_line("description: /a1-t-b1/" )
+ t.expect_output_line("description: /a0-b0-t/" , False)
+ t.expect_output_line("description: /a0-b1-t/" , False)
+ t.expect_output_line("description: /a1-b0-t/" , False)
+ t.expect_output_line("description: /a1-b1-t/" )
+ t.expect_output_line("description: /t0-a0-b0/", False)
+ t.expect_output_line("description: /t0-a0-b1/", False)
+ t.expect_output_line("description: /t0-a1-b0/", False)
+ t.expect_output_line("description: /t0-a1-b1/" )
+ t.expect_output_line("description: /t1-a0-b0/", False)
+ t.expect_output_line("description: /t1-a0-b1/", False)
+ t.expect_output_line("description: /t1-a1-b0/", False)
+ t.expect_output_line("description: /t1-a1-b1/", False)
+ t.expect_output_line("description: /a0-t1-b0/", False)
+ t.expect_output_line("description: /a0-t1-b1/", False)
+ t.expect_output_line("description: /a1-t0-b0/", False)
+ t.expect_output_line("description: /a1-t0-b1/" )
+ t.expect_output_line("description: /b0-a1-t0/", False)
+ t.expect_output_line("description: /b0-a0-t1/", False)
+ t.expect_output_line("description: /b0-a1-t1/", False)
+ t.expect_output_line("description: /b1-a0-t1/", False)
+ t.expect_output_line("description: /b1-a1-t0/" )
+ t.expect_output_line("description: /b1-a1-t1/", False)
+
+ t.run_build_system("aaa=1 bbb=1 ccc=1 toolset=%s-1" % toolset)
+ t.expect_output_line("description: /t-a0/" , False)
+ t.expect_output_line("description: /t-a1/" )
+ t.expect_output_line("description: /t0-a0/" , False)
+ t.expect_output_line("description: /t0-a1/" , False)
+ t.expect_output_line("description: /t1-a0/" , False)
+ t.expect_output_line("description: /t1-a1/" )
+ t.expect_output_line("description: /t-a0-b0/" , False)
+ t.expect_output_line("description: /t-a0-b1/" , False)
+ t.expect_output_line("description: /t-a1-b0/" , False)
+ t.expect_output_line("description: /t-a1-b1/" )
+ t.expect_output_line("description: /a0-t-b0/" , False)
+ t.expect_output_line("description: /a0-t-b1/" , False)
+ t.expect_output_line("description: /a1-t-b0/" , False)
+ t.expect_output_line("description: /a1-t-b1/" )
+ t.expect_output_line("description: /a0-b0-t/" , False)
+ t.expect_output_line("description: /a0-b1-t/" , False)
+ t.expect_output_line("description: /a1-b0-t/" , False)
+ t.expect_output_line("description: /a1-b1-t/" )
+ t.expect_output_line("description: /t0-a0-b0/", False)
+ t.expect_output_line("description: /t0-a0-b1/", False)
+ t.expect_output_line("description: /t0-a1-b0/", False)
+ t.expect_output_line("description: /t0-a1-b1/", False)
+ t.expect_output_line("description: /t1-a0-b0/", False)
+ t.expect_output_line("description: /t1-a0-b1/", False)
+ t.expect_output_line("description: /t1-a1-b0/", False)
+ t.expect_output_line("description: /t1-a1-b1/" )
+ t.expect_output_line("description: /a0-t1-b0/", False)
+ t.expect_output_line("description: /a0-t1-b1/", False)
+ t.expect_output_line("description: /a1-t0-b0/", False)
+ t.expect_output_line("description: /a1-t0-b1/", False)
+ t.expect_output_line("description: /b0-a1-t0/", False)
+ t.expect_output_line("description: /b0-a0-t1/", False)
+ t.expect_output_line("description: /b0-a1-t1/", False)
+ t.expect_output_line("description: /b1-a0-t1/", False)
+ t.expect_output_line("description: /b1-a1-t0/", False)
+ t.expect_output_line("description: /b1-a1-t1/" )
+
+ t.cleanup()
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+test_multiple_conditions()
+test_multiple_conditions_with_toolset_version()
diff --git a/tools/build/v2/test/configuration.py b/tools/build/v2/test/configuration.py
new file mode 100755
index 0000000000..46adfd3c9b
--- /dev/null
+++ b/tools/build/v2/test/configuration.py
@@ -0,0 +1,110 @@
+#!/usr/bin/python
+
+# Copyright 2008 Jurko Gospodnetic
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that Boost Build configuration file handling.
+
+import BoostBuild
+import os.path
+import string
+
+
+################################################################################
+#
+# test_user_configuration()
+# -------------------------
+#
+################################################################################
+
+def test_user_configuration():
+ """Test Boost Build user configuration handling. Both relative and absolute
+ path handling is tested.
+ """
+
+ t = BoostBuild.Tester("--debug-configuration", pass_toolset=False,
+ use_test_config=False)
+
+ implicitConfigLoadMessage = "notice: Loading user-config configuration file: *"
+ explicitConfigLoadMessage = "notice: Loading explicitly specified user configuration file:"
+ testMessage = "_!_!_!_!_!_!_!_!_ %s _!_!_!_!_!_!_!_!_"
+ toolsetName = "__myDummyToolset__"
+ subdirName = "ASubDirectory"
+ configFileNames = ["ups_lala_1.jam", "ups_lala_2.jam",
+ os.path.join(subdirName, "ups_lala_3.jam")]
+
+ for configFileName in configFileNames:
+ message = "ECHO \"%s\" ;" % testMessage % configFileName
+ # We need to double any backslashes in the message or Jam will interpret
+ # them as escape characters.
+ t.write(configFileName, message.replace("\\", "\\\\"))
+
+ # Prepare a dummy toolset so we do not get errors in case the default one is
+ # not found.
+ t.write(toolsetName + ".jam", """
+import feature ;
+feature.extend toolset : %s ;
+rule init ( ) { }
+""" % toolsetName )
+ t.write("jamroot.jam", "using %s ;" % toolsetName)
+
+ t.run_build_system()
+ t.expect_output_line(explicitConfigLoadMessage, False)
+ t.expect_output_line(testMessage % configFileNames[0], False)
+ t.expect_output_line(testMessage % configFileNames[1], False)
+ t.expect_output_line(testMessage % configFileNames[2], False)
+
+ t.run_build_system("--user-config=")
+ t.expect_output_line(implicitConfigLoadMessage, False)
+ t.expect_output_line(explicitConfigLoadMessage, False)
+ t.expect_output_line(testMessage % configFileNames[0], False)
+ t.expect_output_line(testMessage % configFileNames[1], False)
+ t.expect_output_line(testMessage % configFileNames[2], False)
+
+ t.run_build_system('--user-config=""')
+ t.expect_output_line(implicitConfigLoadMessage, False)
+ t.expect_output_line(explicitConfigLoadMessage, False)
+ t.expect_output_line(testMessage % configFileNames[0], False)
+ t.expect_output_line(testMessage % configFileNames[1], False)
+ t.expect_output_line(testMessage % configFileNames[2], False)
+
+ t.run_build_system('--user-config="%s"' % configFileNames[0])
+ t.expect_output_line(implicitConfigLoadMessage, False)
+ t.expect_output_line(explicitConfigLoadMessage)
+ t.expect_output_line(testMessage % configFileNames[0] )
+ t.expect_output_line(testMessage % configFileNames[1], False)
+ t.expect_output_line(testMessage % configFileNames[2], False)
+
+ t.run_build_system('--user-config="%s"' % configFileNames[2])
+ t.expect_output_line(implicitConfigLoadMessage, False)
+ t.expect_output_line(explicitConfigLoadMessage)
+ t.expect_output_line(testMessage % configFileNames[0], False)
+ t.expect_output_line(testMessage % configFileNames[1], False)
+ t.expect_output_line(testMessage % configFileNames[2] )
+
+ t.run_build_system('--user-config="%s"' % os.path.abspath(configFileNames[1]))
+ t.expect_output_line(implicitConfigLoadMessage, False)
+ t.expect_output_line(explicitConfigLoadMessage)
+ t.expect_output_line(testMessage % configFileNames[0], False)
+ t.expect_output_line(testMessage % configFileNames[1] )
+ t.expect_output_line(testMessage % configFileNames[2], False)
+
+ t.run_build_system('--user-config="%s"' % os.path.abspath(configFileNames[2]))
+ t.expect_output_line(implicitConfigLoadMessage, False)
+ t.expect_output_line(explicitConfigLoadMessage)
+ t.expect_output_line(testMessage % configFileNames[0], False)
+ t.expect_output_line(testMessage % configFileNames[1], False)
+ t.expect_output_line(testMessage % configFileNames[2] )
+
+ t.cleanup()
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+test_user_configuration()
diff --git a/tools/build/v2/test/copy_time.py b/tools/build/v2/test/copy_time.py
new file mode 100755
index 0000000000..8943d28575
--- /dev/null
+++ b/tools/build/v2/test/copy_time.py
@@ -0,0 +1,76 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2008
+# Steven Watanabe
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that the common.copy rule set the modification
+# date of the new file the current time.
+
+import BoostBuild
+
+tester = BoostBuild.Tester()
+
+tester.write("test1.cpp", """
+#include <iostream>
+template<bool, int M, class Next>
+struct time_waster {
+ typedef typename time_waster<true, M-1, time_waster>::type type1;
+ typedef typename time_waster<false, M-1, time_waster>::type type2;
+ typedef void type;
+};
+template<bool B, class Next>
+struct time_waster<B, 0, Next> {
+ typedef void type;
+};
+typedef time_waster<true, 10, void>::type type;
+int f() { return 0; }
+""")
+
+tester.write("test2.cpp", """
+#include <iostream>
+template<bool, int M, class Next>
+struct time_waster {
+ typedef typename time_waster<true, M-1, time_waster>::type type1;
+ typedef typename time_waster<false, M-1, time_waster>::type type2;
+ typedef void type;
+};
+template<bool B, class Next>
+struct time_waster<B, 0, Next> {
+ typedef void type;
+};
+typedef time_waster<true, 10, void>::type type;
+int g() { return 0; }
+""")
+
+tester.write("jamroot.jam", """
+obj test2 : test2.cpp ;
+obj test1 : test1.cpp : <dependency>test2 ;
+install test2i : test2 : <dependency>test1 ;
+""")
+
+tester.run_build_system()
+
+tester.expect_addition("bin/$toolset/debug/test2.obj")
+tester.expect_addition("bin/$toolset/debug/test1.obj")
+tester.expect_addition("test2i/test2.obj")
+tester.expect_nothing_more()
+
+test2src = tester.read("test2i/test2.obj")
+test2dest = tester.read("bin/$toolset/debug/test2.obj")
+
+if test2src != test2dest:
+ BoostBuild.annotation("failure", "The object file was not copied correctly")
+ tester.fail_test(1)
+
+del test2src
+del test2dest
+
+tester.run_build_system("-d1")
+tester.expect_output_line("common.copy*", expected_to_exist=False)
+tester.expect_nothing_more()
+
+tester.cleanup()
diff --git a/tools/build/v2/test/core_d12.py b/tools/build/v2/test/core_d12.py
new file mode 100644
index 0000000000..83076350af
--- /dev/null
+++ b/tools/build/v2/test/core_d12.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This tests correct handling of "-d1" and "-d2" options.
+
+import BoostBuild
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("file.jam", """
+actions a { }
+actions quietly b { }
+ALWAYS all ;
+a all ;
+b all ;
+""")
+
+t.run_build_system("-ffile.jam -d0", stdout="")
+
+t.run_build_system("-ffile.jam -d1", stdout=
+"""...found 1 target...
+...updating 1 target...
+a all
+...updated 1 target...
+""")
+
+t.run_build_system("-ffile.jam -d2")
+
+t.fail_test(t.stdout().find("a all") == -1)
+t.fail_test(t.stdout().find("b all") == -1)
+
+t.cleanup()
diff --git a/tools/build/v2/test/core_delete_module.py b/tools/build/v2/test/core_delete_module.py
new file mode 100644
index 0000000000..b02fd95a39
--- /dev/null
+++ b/tools/build/v2/test/core_delete_module.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This tests the facilities for deleting modules.
+
+import BoostBuild
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("file.jam", """
+module foo
+{
+ rule bar { }
+ var = x y ;
+}
+DELETE_MODULE foo ;
+if [ RULENAMES foo ]
+{
+ EXIT DELETE_MODULE failed to kill foo's rules: [ RULENAMES foo ] ;
+}
+
+module foo
+{
+ if $(var)
+ {
+ EXIT DELETE_MODULE failed to kill foo's variables ;
+ }
+
+ rule bar { }
+ var = x y ;
+
+ DELETE_MODULE foo ;
+
+ if $(var)
+ {
+ EXIT internal DELETE_MODULE failed to kill foo's variables ;
+ }
+ if [ RULENAMES foo ]
+ {
+ EXIT internal DELETE_MODULE failed to kill foo's rules: [ RULENAMES foo ] ;
+ }
+}
+DEPENDS all : xx ;
+NOTFILE xx ;
+""")
+
+t.run_build_system("-ffile.jam", status=0)
+t.cleanup()
diff --git a/tools/build/v2/test/core_dependencies.py b/tools/build/v2/test/core_dependencies.py
new file mode 100644
index 0000000000..2b2ef368d6
--- /dev/null
+++ b/tools/build/v2/test/core_dependencies.py
@@ -0,0 +1,157 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This tests correct handling of dependencies, specifically, on generated
+# sources, and from generated sources.
+
+import BoostBuild
+
+import string
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("core-dependency-helpers", """
+rule hdrrule
+{
+ INCLUDES $(1) : $(2) ;
+}
+actions copy
+{
+ cp $(>) $(<)
+}
+""")
+
+code = """include core-dependency-helpers ;
+DEPENDS all : a ;
+DEPENDS a : b ;
+
+actions create-b
+{
+ echo '#include <foo.h>' > $(<)
+}
+copy a : b ;
+create-b b ;
+HDRRULE on b foo.h bar.h = hdrrule ;
+HDRSCAN on b foo.h bar.h = \"#include <(.*)>\" ;
+"""
+
+# This creates 'a' which depends on 'b', which is generated. The generated 'b'
+# contains '#include <foo.h>' and no rules for foo.h are given. The system
+# should error out on the first invocation.
+t.run_build_system("-f-", stdin=code)
+t.fail_test(string.find(t.stdout(), "...skipped a for lack of foo.h...") == -1)
+
+t.rm('b')
+
+# Now test that if target 'c' also depends on 'b', then it will not be built, as
+# well.
+t.run_build_system("-f-", stdin=code + " copy c : b ; DEPENDS c : b ; DEPENDS all : c ; ")
+t.fail_test(string.find(t.stdout(), "...skipped c for lack of foo.h...") == -1)
+
+t.rm('b')
+
+# Now add a rule for creating foo.h.
+code += """
+actions create-foo
+{
+ echo // > $(<)
+}
+create-foo foo.h ;
+"""
+t.run_build_system("-f-", stdin=code)
+
+# Run two times, adding explicit dependency from all to foo.h at the beginning
+# and at the end, to make sure that foo.h is generated before 'a' in all cases.
+
+def mk_correct_order_func(s1, s2):
+ def correct_order(s):
+ n1 = string.find(s, s1)
+ n2 = string.find(s, s2)
+ return ( n1 != -1 ) and ( n2 != -1 ) and ( n1 < n2 )
+ return correct_order
+
+correct_order = mk_correct_order_func("create-foo", "copy a")
+
+t.rm(["a", "b", "foo.h"])
+t.run_build_system("-d+2 -f-", stdin=code + " DEPENDS all : foo.h ;")
+t.fail_test(not correct_order(t.stdout()))
+
+t.rm(["a", "b", "foo.h"])
+t.run_build_system("-d+2 -f-", stdin=" DEPENDS all : foo.h ; " + code)
+t.fail_test(not correct_order(t.stdout()))
+
+# Now foo.h exists. Test include from b -> foo.h -> bar.h -> biz.h. b and foo.h
+# already have updating actions.
+t.rm(["a", "b"])
+t.write("foo.h", "#include <bar.h>")
+t.write("bar.h", "#include <biz.h>")
+t.run_build_system("-d+2 -f-", stdin=code)
+t.fail_test(string.find(t.stdout(), "...skipped a for lack of biz.h...") == -1)
+
+# Add an action for biz.h.
+code += """
+actions create-biz
+{
+ echo // > $(<)
+}
+create-biz biz.h ;
+"""
+
+t.rm(["b"])
+correct_order = mk_correct_order_func("create-biz", "copy a")
+t.run_build_system("-d+2 -f-", stdin=code + " DEPENDS all : biz.h ;")
+t.fail_test(not correct_order(t.stdout()))
+
+t.rm(["a", "biz.h"])
+t.run_build_system("-d+2 -f-", stdin=" DEPENDS all : biz.h ; " + code)
+t.fail_test(not correct_order(t.stdout()))
+
+t.write("a", "")
+
+code="""
+DEPENDS all : main d ;
+
+actions copy
+{
+ cp $(>) $(<) ;
+}
+
+DEPENDS main : a ;
+copy main : a ;
+
+INCLUDES a : <1>c ;
+
+NOCARE <1>c ;
+SEARCH on <1>c = . ;
+
+actions create-c
+{
+ echo d > $(<)
+}
+
+actions create-d
+{
+ echo // > $(<)
+}
+
+create-c <2>c ;
+LOCATE on <2>c = . ;
+create-d d ;
+
+HDRSCAN on <1>c = (.*) ;
+HDRRULE on <1>c = hdrrule ;
+
+rule hdrrule
+{
+ INCLUDES $(1) : d ;
+}
+"""
+
+correct_order = mk_correct_order_func("create-d", "copy main")
+t.run_build_system("-d2 -f-", stdin=code)
+t.fail_test(not correct_order(t.stdout()))
+
+t.cleanup()
diff --git a/tools/build/v2/test/core_import_module.py b/tools/build/v2/test/core_import_module.py
new file mode 100644
index 0000000000..fab209e4cb
--- /dev/null
+++ b/tools/build/v2/test/core_import_module.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("code", """
+module a
+{
+ rule r1 ( )
+ {
+ ECHO R1 ;
+ }
+}
+module a2
+{
+ rule r2 ( )
+ {
+ ECHO R2 ;
+ }
+}
+IMPORT a2 : r2 : : a2.r2 ;
+
+module b
+{
+ IMPORT_MODULE a : b ;
+ rule test
+ {
+ # Call rule visible via IMPORT_MODULE
+ a.r1 ;
+ # Call rule in global scope
+ a2.r2 ;
+ }
+}
+
+IMPORT b : test : : test ;
+test ;
+
+module c
+{
+ rule test
+ {
+ ECHO CTEST ;
+ }
+}
+
+IMPORT_MODULE c : ;
+c.test ;
+
+actions do-nothing { }
+do-nothing all ;
+""")
+
+t.run_build_system("-fcode", stdout="""R1
+R2
+CTEST
+""")
+
+t.cleanup()
diff --git a/tools/build/v2/test/core_modifiers.py b/tools/build/v2/test/core_modifiers.py
new file mode 100644
index 0000000000..fb95cbfbd7
--- /dev/null
+++ b/tools/build/v2/test/core_modifiers.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This tests the "existing" and "updated" modifiers on actions.
+
+import BoostBuild
+import string
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+code = """
+DEPENDS all : a ;
+ALWAYS a ;
+NOTFILE a ;
+
+actions existing make-a
+{
+ echo $(>) > list
+}
+make-a a : a-1 a-2 a-3 ;
+DEPENDS a : a-1 a-2 a-3 ;
+NOCARE a-1 a-2 ;
+
+actions make-a3
+{
+ echo foo > $(<)
+}
+make-a3 a-3 ;
+"""
+
+t.write("file.jam", code)
+t.write("a-1", "")
+
+t.run_build_system("-ffile.jam")
+t.fail_test(string.strip(t.read("list")) != "a-1")
+t.rm(["a-3", "list"])
+
+code = string.replace(code, "existing", "updated")
+t.write("file.jam", code)
+t.run_build_system("-ffile.jam")
+t.fail_test(string.strip(t.read("list")) != "a-3")
+
+code = string.replace(code, "updated", "existing updated")
+t.write("file.jam", code)
+t.run_build_system("-ffile.jam")
+t.fail_test(string.strip(t.read("list")) != "a-1 a-3")
+
+t.cleanup()
diff --git a/tools/build/v2/test/core_typecheck.py b/tools/build/v2/test/core_typecheck.py
new file mode 100644
index 0000000000..31f408356d
--- /dev/null
+++ b/tools/build/v2/test/core_typecheck.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This tests the typechecking facilities.
+
+import BoostBuild
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("file.jam", """
+module .typecheck
+{
+ rule [path] ( x )
+ {
+ if ! [ MATCH "^(::)" : $(x) ]
+ {
+ ECHO "Error: $(x) is not a path" ;
+ return true ;
+ }
+ }
+}
+
+rule do ( [path] a )
+{
+}
+
+do $(ARGUMENT) ;
+
+actions dummy { }
+dummy all ;
+""")
+
+t.run_build_system("-ffile.jam -sARGUMENT=::a/b/c")
+t.run_build_system("-ffile.jam -sARGUMENT=a/b/c", status=1,
+ stdout="""Error: a/b/c is not a path
+file.jam:18: in module scope
+*** argument error
+* rule do ( [path] a )
+* called with: ( a/b/c )
+* true a
+file.jam:16:see definition of rule 'do' being called
+""")
+
+t.cleanup()
diff --git a/tools/build/v2/test/core_varnames.py b/tools/build/v2/test/core_varnames.py
new file mode 100644
index 0000000000..a94ed8fa58
--- /dev/null
+++ b/tools/build/v2/test/core_varnames.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This tests the core rule for enumerating the variable names in a module.
+
+import BoostBuild
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("file.jam", """
+module foo
+{
+ rule bar { }
+ var1 = x y ;
+ var2 = fubar ;
+}
+
+expected = var1 var2 ;
+names = [ VARNAMES foo ] ;
+if $(names) in $(expected) && $(expected) in $(names)
+{
+ # everything OK
+}
+else
+{
+ EXIT expected to find variables $(expected:J=", ") in module foo,
+ but found $(names:J=", ") instead. ;
+}
+DEPENDS all : xx ;
+NOTFILE xx ;
+""")
+
+t.run_build_system("-ffile.jam", status=0)
+
+t.cleanup()
diff --git a/tools/build/v2/test/custom_generator.py b/tools/build/v2/test/custom_generator.py
new file mode 100644
index 0000000000..9a1188a03d
--- /dev/null
+++ b/tools/build/v2/test/custom_generator.py
@@ -0,0 +1,66 @@
+#!/usr/bin/python
+
+# Copyright 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Attempt to declare a generator for creating OBJ from RC files. That generator
+# should be considered together with standard CPP->OBJ generators and
+# successfully create the target. Since we do not have a RC compiler everywhere,
+# we fake the action. The resulting OBJ will be unusable, but it must be
+# created.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+import rcc ;
+""")
+
+t.write("rcc.jam", """
+import type ;
+import generators ;
+import print ;
+
+# Use 'RCC' to avoid conflicts with definitions in the standard rc.jam and
+# msvc.jam
+type.register RCC : rcc ;
+
+rule resource-compile ( targets * : sources * : properties * )
+{
+ print.output $(targets[1]) ;
+ print.text "rc-object" ;
+}
+
+generators.register-standard rcc.resource-compile : RCC : OBJ ;
+""")
+
+t.write("rcc.py", """
+import b2.build.type as type
+import b2.build.generators as generators
+
+from b2.manager import get_manager
+
+# Use 'RCC' to avoid conflicts with definitions in the standard rc.jam and
+# msvc.jam
+type.register('RCC', ['rcc'])
+
+generators.register_standard("rcc.resource-compile", ["RCC"], ["OBJ"])
+
+get_manager().engine().register_action(
+ "rcc.resource-compile",
+ '@($(STDOUT):E=rc-object) > "$(<)"')
+""")
+
+t.write("jamfile.jam", """
+obj r : r.rcc ;
+""")
+
+t.write("r.rcc", """
+""")
+
+t.run_build_system()
+t.expect_content("bin/$toolset/debug/r.obj", "rc-object")
+
+t.cleanup()
diff --git a/tools/build/v2/test/default_build.py b/tools/build/v2/test/default_build.py
new file mode 100644
index 0000000000..33f2b5bbbe
--- /dev/null
+++ b/tools/build/v2/test/default_build.py
@@ -0,0 +1,93 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that default build clause actually has any effect.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", "import gcc ;")
+t.write("jamfile.jam", "exe a : a.cpp : : debug release ;")
+t.write("a.cpp", "int main() {}\n")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+t.expect_addition("bin/$toolset/release/a.exe")
+
+# Check that explictly-specified build variant supresses default-build.
+t.rm("bin")
+t.run_build_system("release")
+t.expect_addition(BoostBuild.List("bin/$toolset/release/") * "a.exe a.obj")
+t.expect_nothing_more()
+
+# Now check that we can specify explicit build request and default-build will be
+# combined with it.
+t.run_build_system("optimization=space")
+t.expect_addition("bin/$toolset/debug/optimization-space/a.exe")
+t.expect_addition("bin/$toolset/release/optimization-space/a.exe")
+
+# Test that default-build must be identical in all alternatives. Error case.
+t.write("jamfile.jam", """
+exe a : a.cpp : : debug ;
+exe a : b.cpp : : ;
+""")
+expected="""error: default build must be identical in all alternatives
+main target is ./a
+with
+differing from previous default build <variant>debug
+
+"""
+t.run_build_system("-n --no-error-backtrace", status=1)
+t.fail_test(t.stdout().find("default build must be identical in all alternatives") == -1)
+
+# Test that default-build must be identical in all alternatives. No Error case,
+# empty default build.
+t.write("jamfile.jam", """
+exe a : a.cpp : <variant>debug ;
+exe a : b.cpp : <variant>release ;
+""")
+t.run_build_system("-n --no-error-backtrace", status=0)
+
+
+# Now try a harder example: default build which contains <define> should cause
+# <define> to be present when "b" is compiled. This happens only if
+# "build-project b" is placed first.
+t.write("jamfile.jam", """
+project : default-build <define>FOO ;
+build-project a ;
+build-project b ;
+""")
+
+t.write("a/jamfile.jam", """
+exe a : a.cpp ../b//b ;
+""")
+
+t.write("a/a.cpp", """
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+void foo();
+int main() { foo(); }
+""")
+
+t.write("b/jamfile.jam", """
+lib b : b.cpp ;
+""")
+
+t.write("b/b.cpp", """
+#ifdef FOO
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {}
+#endif
+""")
+
+t.run_build_system()
+
+t.cleanup()
diff --git a/tools/build/v2/test/default_features.py b/tools/build/v2/test/default_features.py
new file mode 100644
index 0000000000..4d810caa71
--- /dev/null
+++ b/tools/build/v2/test/default_features.py
@@ -0,0 +1,50 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that features with default values are always present in build properties
+# of any target.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+# Declare *non-propagated* feature foo.
+t.write("jamroot.jam", """
+import feature : feature ;
+feature foo : on off ;
+""")
+
+# Note that '<foo>on' will not be propagated to 'd/l'.
+t.write("jamfile.jam", """
+exe hello : hello.cpp d//l ;
+""")
+
+t.write("hello.cpp", """
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+void foo();
+int main() { foo(); }
+""")
+
+t.write("d/jamfile.jam", """
+lib l : l.cpp : <foo>on:<define>FOO ;
+""")
+
+t.write("d/l.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+#ifdef FOO
+void foo() {}
+#endif
+""")
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/default_toolset.py b/tools/build/v2/test/default_toolset.py
new file mode 100755
index 0000000000..e430c68a7e
--- /dev/null
+++ b/tools/build/v2/test/default_toolset.py
@@ -0,0 +1,211 @@
+#!/usr/bin/python
+
+# Copyright 2008 Jurko Gospodnetic
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that the expected default toolset is used when no toolset is explicitly
+# specified on the command line or used from code via the using rule. Test that
+# the default toolset is correctly used just like any other explicitly used
+# toolset (e.g. toolset prerequisites, properties conditioned on toolset related
+# features, etc.).
+#
+# Note that we need to ignore regular site/user/test configuration files to
+# avoid them marking any toolsets not under our control as used.
+
+import BoostBuild
+
+
+# Line displayed by Boost Build when using the default toolset.
+configuring_default_toolset_message = \
+ 'warning: Configuring default toolset "%s".'
+
+
+################################################################################
+#
+# test_conditions_on_default_toolset()
+# ------------------------------------
+#
+################################################################################
+
+def test_conditions_on_default_toolset():
+ """Test that toolset and toolset subfeature conditioned properties get
+ applied correctly when the toolset is selected by default. Implicitly tests
+ that we can use the set-default-toolset rule to set the default toolset to
+ be used by Boost Build.
+ """
+
+ t = BoostBuild.Tester("--user-config= --ignore-site-config",
+ pass_toolset=False, use_test_config=False)
+
+ toolset_name = "myCustomTestToolset"
+ toolset_version = "v"
+ toolset_version_unused = "v_unused"
+ message_loaded = "Toolset '%s' loaded." % toolset_name
+ message_initialized = "Toolset '%s' initialized." % toolset_name ;
+
+ # Custom toolset.
+ t.write(toolset_name + ".jam", """
+import feature ;
+ECHO "%(message_loaded)s" ;
+feature.extend toolset : %(toolset_name)s ;
+feature.subfeature toolset %(toolset_name)s : version : %(toolset_version)s %(toolset_version_unused)s ;
+rule init ( version ) { ECHO "%(message_initialized)s" ; }
+""" % {'message_loaded' : message_loaded ,
+ 'message_initialized' : message_initialized,
+ 'toolset_name' : toolset_name ,
+ 'toolset_version' : toolset_version ,
+ 'toolset_version_unused': toolset_version_unused})
+
+ # Main Boost Build project script.
+ t.write("jamroot.jam", """
+import build-system ;
+import errors ;
+import feature ;
+import notfile ;
+
+build-system.set-default-toolset %(toolset_name)s : %(toolset_version)s ;
+
+feature.feature description : : free incidental ;
+
+# We use a rule instead of an action to avoid problems with action output not
+# getting piped to stdout by the testing system.
+rule buildRule ( names : targets ? : properties * )
+{
+ local descriptions = [ feature.get-values description : $(properties) ] ;
+ ECHO "descriptions:" /$(descriptions)/ ;
+ local toolset = [ feature.get-values toolset : $(properties) ] ;
+ ECHO "toolset:" /$(toolset)/ ;
+ local toolset-version = [ feature.get-values "toolset-$(toolset):version" : $(properties) ] ;
+ ECHO "toolset-version:" /$(toolset-version)/ ;
+}
+
+notfile testTarget
+ : @buildRule
+ :
+ :
+ <description>stand-alone
+ <toolset>%(toolset_name)s:<description>toolset
+ <toolset>%(toolset_name)s-%(toolset_version)s:<description>toolset-version
+ <toolset>%(toolset_name)s-%(toolset_version_unused)s:<description>toolset-version-unused ;
+""" % {'toolset_name' : toolset_name ,
+ 'toolset_version' : toolset_version,
+ 'toolset_version_unused': toolset_version_unused})
+
+ t.run_build_system()
+ t.expect_output_line(configuring_default_toolset_message % toolset_name)
+ t.expect_output_line(message_loaded)
+ t.expect_output_line(message_initialized)
+ t.expect_output_line("descriptions: /stand-alone/ /toolset/ /toolset-version/")
+ t.expect_output_line("toolset: /%s/" % toolset_name)
+ t.expect_output_line("toolset-version: /%s/" % toolset_version)
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_default_toolset_on_os()
+# ----------------------------
+#
+################################################################################
+
+def test_default_toolset_on_os( os, expected_toolset ):
+ """Test that the given toolset is used as the default toolset on the given
+ os. Uses hardcoded knowledge of how Boost Build decides on which host OS it
+ is currently running. Note that we must not do much after tricking Boost
+ Build into believing it has a specific host OS as this might mess up other
+ important internal Boost Build state.
+ """
+
+ t = BoostBuild.Tester("--user-config= --ignore-site-config",
+ pass_toolset=False, use_test_config=False)
+
+ t.write("jamroot.jam", "modules.poke os : .name : %s ;" % os)
+
+ # We need to tell the test system to ignore stderr output as attempting to
+ # load missing toolsets might cause random failures with which we are not
+ # concerned in this test.
+ t.run_build_system(stderr=None)
+ t.expect_output_line(configuring_default_toolset_message % expected_toolset)
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_default_toolset_requirements()
+# -----------------------------------
+#
+################################################################################
+
+def test_default_toolset_requirements():
+ """Test that default toolset's requirements get applied correctly.
+ """
+
+ t = BoostBuild.Tester("--user-config= --ignore-site-config",
+ pass_toolset=False, use_test_config=False,
+ ignore_toolset_requirements=False)
+
+ toolset_name = "customTestToolsetWithRequirements"
+
+ # Custom toolset.
+ t.write(toolset_name + ".jam", """
+import feature ;
+import toolset ;
+feature.extend toolset : %(toolset_name)s ;
+toolset.add-requirements <description>toolset-requirement ;
+rule init ( ) { }
+""" % {'toolset_name': toolset_name})
+
+ # Main Boost Build project script.
+ t.write("jamroot.jam", """
+import build-system ;
+import errors ;
+import feature ;
+import notfile ;
+
+build-system.set-default-toolset %(toolset_name)s ;
+
+feature.feature description : : free incidental ;
+
+# We use a rule instead of an action to avoid problems with action output not
+# getting piped to stdout by the testing system.
+rule buildRule ( names : targets ? : properties * )
+{
+ local descriptions = [ feature.get-values description : $(properties) ] ;
+ ECHO "descriptions:" /$(descriptions)/ ;
+ local toolset = [ feature.get-values toolset : $(properties) ] ;
+ ECHO "toolset:" /$(toolset)/ ;
+}
+
+notfile testTarget
+ : @buildRule
+ :
+ :
+ <description>target-requirement
+ <description>toolset-requirement:<description>conditioned-requirement
+ <description>unrelated-condition:<description>unrelated-description ;
+""" % {'toolset_name': toolset_name})
+
+ t.run_build_system()
+ t.expect_output_line(configuring_default_toolset_message % toolset_name)
+ t.expect_output_line("descriptions: /conditioned-requirement/ /target-requirement/ /toolset-requirement/")
+ t.expect_output_line("toolset: /%s/" % toolset_name)
+
+ t.cleanup()
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+test_default_toolset_on_os("NT" , "msvc")
+test_default_toolset_on_os("LINUX" , "gcc" )
+test_default_toolset_on_os("CYGWIN" , "gcc" )
+test_default_toolset_on_os("SomeOtherOS", "gcc" )
+test_default_toolset_requirements()
+test_conditions_on_default_toolset()
diff --git a/tools/build/v2/test/dependency-test/a.cpp b/tools/build/v2/test/dependency-test/a.cpp
new file mode 100644
index 0000000000..e77a4308d3
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/a.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include <a.h>
+# include "a.h"
+#include <x.h>
+
+int main()
+{
+ return 0;
+}
diff --git a/tools/build/v2/test/dependency-test/a.h b/tools/build/v2/test/dependency-test/a.h
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/a.h
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/dependency-test/a_c.c b/tools/build/v2/test/dependency-test/a_c.c
new file mode 100644
index 0000000000..18be81e274
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/a_c.c
@@ -0,0 +1,12 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include <a.h>
+# include "a.h"
+#include <x.h>
diff --git a/tools/build/v2/test/dependency-test/b.cpp b/tools/build/v2/test/dependency-test/b.cpp
new file mode 100644
index 0000000000..0af83d3aa2
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/b.cpp
@@ -0,0 +1,14 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include "a.h"
+
+int main()
+{
+}
diff --git a/tools/build/v2/test/dependency-test/b.h b/tools/build/v2/test/dependency-test/b.h
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/b.h
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/dependency-test/c.cpp b/tools/build/v2/test/dependency-test/c.cpp
new file mode 100644
index 0000000000..6d4170ff3c
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/c.cpp
@@ -0,0 +1,14 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include "x.h"
+
+int main()
+{
+}
diff --git a/tools/build/v2/test/dependency-test/e.cpp b/tools/build/v2/test/dependency-test/e.cpp
new file mode 100644
index 0000000000..43814b98e3
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/e.cpp
@@ -0,0 +1,15 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include "x.h"
+
+int main()
+{
+ return 0;
+}
diff --git a/tools/build/v2/test/dependency-test/foo.jam b/tools/build/v2/test/dependency-test/foo.jam
new file mode 100644
index 0000000000..1cf44681da
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/foo.jam
@@ -0,0 +1,34 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import type ;
+import generators ;
+import os ;
+import print ;
+
+type.register FOO : foo ;
+
+generators.register-standard foo.foo : FOO : CPP H ;
+
+nl = "
+" ;
+
+rule foo ( targets * : sources * : properties * )
+{
+ # On NT, you need an exported symbol in order to have an
+ # import lib generated
+ # We won't really use the symbol defined here, just force
+ # lib creation.
+ if ( [ os.name ] = NT || [ modules.peek : OS ] in CYGWIN )
+ && <main-target-type>LIB in $(properties)
+ {
+ .decl = "void __declspec(dllexport) foo(){}" ;
+ }
+
+ print.output $(<[1]) ;
+ print.text $(.decl:E="//")$(nl) ;
+ print.output $(<[2]) ;
+ print.text "#include <z.h>"$(nl) ;
+}
diff --git a/tools/build/v2/test/dependency-test/foo.py b/tools/build/v2/test/dependency-test/foo.py
new file mode 100644
index 0000000000..f807bf4fa9
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/foo.py
@@ -0,0 +1,26 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2005, 2010 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import bjam
+import b2.build.type as type
+import b2.build.generators as generators
+
+from b2.manager import get_manager
+
+type.register("FOO", ["foo"])
+generators.register_standard("foo.foo", ["FOO"], ["CPP", "H"])
+
+def prepare_foo(targets, sources, properties):
+
+ if properties.get('os') in ['windows', 'cygwin']:
+ bjam.call('set-target-variable', targets, "DECL",
+ "void __declspec(dllexport) foo(){}")
+
+ pass
+
+get_manager().engine().register_action("foo.foo",\
+"""echo -e $(DECL:E="//")\\n > $(<[1])
+echo -e "#include <z.h>\\n" > $(<[2])
+""", function=prepare_foo)
diff --git a/tools/build/v2/test/dependency-test/jamfile.jam b/tools/build/v2/test/dependency-test/jamfile.jam
new file mode 100644
index 0000000000..590d0865ca
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/jamfile.jam
@@ -0,0 +1,25 @@
+# Copyright 2002, 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project test
+ : requirements <include>src1
+ ;
+
+exe a
+ : x.foo a.cpp a_c.c
+ ;
+
+exe b
+ : b.cpp
+ ;
+
+# Because of <define>, c.cpp will be compiled to different
+# directory than everything for main target "a". Therefore
+# without <implicit-dependency>, it won't find "x.h", which is part
+# of "a"'s dependency graph.
+exe c
+ : c.cpp
+ : <define>FOO <implicit-dependency>a
+ ;
diff --git a/tools/build/v2/test/dependency-test/jamroot.jam b/tools/build/v2/test/dependency-test/jamroot.jam
new file mode 100644
index 0000000000..e779ecc913
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/jamroot.jam
@@ -0,0 +1,7 @@
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+import gcc ;
+import foo ;
diff --git a/tools/build/v2/test/dependency-test/src1/a.h b/tools/build/v2/test/dependency-test/src1/a.h
new file mode 100644
index 0000000000..d8b04ea0ad
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/src1/a.h
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include "b.h"
diff --git a/tools/build/v2/test/dependency-test/src1/b.h b/tools/build/v2/test/dependency-test/src1/b.h
new file mode 100644
index 0000000000..016b031374
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/src1/b.h
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include "c.h"
diff --git a/tools/build/v2/test/dependency-test/src1/c.h b/tools/build/v2/test/dependency-test/src1/c.h
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/src1/c.h
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/dependency-test/src1/z.h b/tools/build/v2/test/dependency-test/src1/z.h
new file mode 100644
index 0000000000..7b8ca34e6d
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/src1/z.h
@@ -0,0 +1,5 @@
+/* Copyright 2003, 2004, 2006 Vladimir Prus */
+/* Distributed under the Boost Software License, Version 1.0. */
+/* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) */
+
+extern int dummy_variabled_need_to_suppress_empty_file_warning_on_hp_cxx_compiler;
diff --git a/tools/build/v2/test/dependency-test/src2/b.h b/tools/build/v2/test/dependency-test/src2/b.h
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/src2/b.h
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/dependency-test/x.foo b/tools/build/v2/test/dependency-test/x.foo
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/x.foo
diff --git a/tools/build/v2/test/dependency-test/y.foo b/tools/build/v2/test/dependency-test/y.foo
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/test/dependency-test/y.foo
diff --git a/tools/build/v2/test/dependency_property.py b/tools/build/v2/test/dependency_property.py
new file mode 100644
index 0000000000..2f19ba3f8d
--- /dev/null
+++ b/tools/build/v2/test/dependency_property.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Regression test: virtual targets with different dependency properties were
+# considered different by 'virtual-target.register', but the code which
+# determined target paths ignored dependency properties --- so both targets used
+# to be placed to the same location.
+
+import BoostBuild
+import string
+
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+lib foo : foo.cpp ;
+exe hello : hello.cpp ;
+exe hello2 : hello.cpp : <library>foo ;
+""")
+
+t.write("hello.cpp", "int main() {}\n")
+
+t.write("foo.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {}
+""")
+
+t.run_build_system("--no-error-backtrace", status=1)
+t.fail_test(string.find(t.stdout(), "Duplicate name of actual target") == -1)
+
+t.cleanup()
diff --git a/tools/build/v2/test/dependency_test.py b/tools/build/v2/test/dependency_test.py
new file mode 100644
index 0000000000..7da20712ac
--- /dev/null
+++ b/tools/build/v2/test/dependency_test.py
@@ -0,0 +1,104 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree("dependency-test")
+
+t.run_build_system()
+
+# Check that main target 'c' was able to find 'x.h' from 'a's dependency graph.
+t.expect_addition("bin/$toolset/debug/c.exe")
+
+# Check handling of first level includes.
+
+# Both 'a' and 'b' include "a.h" and should be updated.
+t.touch("a.h")
+t.run_build_system()
+
+t.expect_touch("bin/$toolset/debug/a.exe")
+t.expect_touch("bin/$toolset/debug/a.obj")
+t.expect_touch("bin/$toolset/debug/a_c.obj")
+t.expect_touch("bin/$toolset/debug/b.exe")
+t.expect_touch("bin/$toolset/debug/b.obj")
+# Now, <dependency> does not add a dependency. It sound weird, but is
+# intentional. Need to rename <dependency> eventually.
+#t.expect_touch("bin/$toolset/debug/main-target-c/c.exe")
+t.ignore("*.tds")
+t.expect_nothing_more()
+
+# Only 'a' include <a.h> and should be updated.
+t.touch("src1/a.h")
+t.run_build_system()
+
+t.expect_touch("bin/$toolset/debug/a.exe")
+t.expect_touch("bin/$toolset/debug/a.obj")
+t.expect_touch("bin/$toolset/debug/a_c.obj")
+t.ignore("*.tds")
+t.expect_nothing_more()
+
+# "src/a.h" includes "b.h" (in the same dir).
+t.touch("src1/b.h")
+t.run_build_system()
+t.expect_touch("bin/$toolset/debug/a.exe")
+t.expect_touch("bin/$toolset/debug/a.obj")
+t.expect_touch("bin/$toolset/debug/a_c.obj")
+t.ignore("*.tds")
+t.expect_nothing_more()
+
+# Included by "src/b.h". We had a bug: file included via "", like "b.h" is in
+# this case was not scanned at all.
+t.touch("src1/c.h")
+t.run_build_system()
+t.expect_touch("bin/$toolset/debug/a.exe")
+
+t.touch("b.h")
+t.run_build_system()
+t.expect_nothing_more()
+
+# Test dependency on a generated header.
+#
+# TODO: we have also to check that generated header is found correctly if it is
+# different for different subvariants. Lacking any toolset support, this check
+# will be implemented later.
+t.touch("x.foo")
+t.run_build_system()
+t.expect_touch("bin/$toolset/debug/a.obj")
+t.expect_touch("bin/$toolset/debug/a_c.obj")
+
+# Check that generated headers are scanned for dependencies as well.
+t.touch("src1/z.h")
+t.run_build_system()
+t.expect_touch("bin/$toolset/debug/a.obj")
+t.expect_touch("bin/$toolset/debug/a_c.obj")
+
+# Regression test: on Windows, <includes> with absolute paths were not
+# considered when scanning dependencies.
+t.rm(".")
+
+t.write("jamroot.jam", """
+path-constant TOP : . ;
+exe app : main.cpp : <include>$(TOP)/include ;
+""");
+
+t.write("main.cpp", """
+#include <dir/header.h>
+int main() {}
+""")
+
+t.write("include/dir/header.h", "")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/main.obj")
+
+t.touch("include/dir/header.h")
+t.run_build_system()
+t.expect_touch("bin/$toolset/debug/main.obj")
+
+t.cleanup()
diff --git a/tools/build/v2/test/direct-request-test/a.cpp b/tools/build/v2/test/direct-request-test/a.cpp
new file mode 100644
index 0000000000..cb97ea0c3e
--- /dev/null
+++ b/tools/build/v2/test/direct-request-test/a.cpp
@@ -0,0 +1,19 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+void
+# ifdef _WIN32
+__declspec(dllimport)
+# endif
+foo();
+
+int main()
+{
+ foo();
+}
diff --git a/tools/build/v2/test/direct-request-test/b.cpp b/tools/build/v2/test/direct-request-test/b.cpp
new file mode 100644
index 0000000000..22dc6bb5d8
--- /dev/null
+++ b/tools/build/v2/test/direct-request-test/b.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+// This file will declare 'foo' is 'MACROS' is defined.
+
+#ifdef MACROS
+void
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+foo() {}
+#endif
+
+# ifdef _WIN32
+int __declspec(dllexport) force_implib_creation;
+# endif
diff --git a/tools/build/v2/test/direct-request-test/b_inverse.cpp b/tools/build/v2/test/direct-request-test/b_inverse.cpp
new file mode 100644
index 0000000000..5068f6118a
--- /dev/null
+++ b/tools/build/v2/test/direct-request-test/b_inverse.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+// This file will declare 'foo' is 'MACROS' is NOT defined.
+
+#ifndef MACROS
+void
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+foo() {}
+#endif
+
+# ifdef _WIN32
+int __declspec(dllexport) force_implib_creation;
+# endif
diff --git a/tools/build/v2/test/direct-request-test/jamfile.jam b/tools/build/v2/test/direct-request-test/jamfile.jam
new file mode 100644
index 0000000000..f57874d3f0
--- /dev/null
+++ b/tools/build/v2/test/direct-request-test/jamfile.jam
@@ -0,0 +1,13 @@
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+# This will link correctly only if symbol MACROS is defined when compiling
+# b.cpp. However, this is only possible if that symbol is requested
+# on command line and b.cpp is compiled with directly requested
+# properties.
+
+exe a : a.cpp b ;
+
+lib b : b.cpp ;
diff --git a/tools/build/v2/test/direct-request-test/jamfile2.jam b/tools/build/v2/test/direct-request-test/jamfile2.jam
new file mode 100644
index 0000000000..bc7e1bc74b
--- /dev/null
+++ b/tools/build/v2/test/direct-request-test/jamfile2.jam
@@ -0,0 +1,9 @@
+
+# This will link correctly only if symbol MACROS is not defined when
+# compiling b.cpp. This tests if direct build request
+# 'release <define>MACROS' to 'b' does not add 'MACROS' when 'b'
+# is compiled with 'debug' -- the version needed by 'a'.
+
+exe a : a.cpp b : <variant>debug ;
+
+lib b : b.cpp ; \ No newline at end of file
diff --git a/tools/build/v2/test/direct-request-test/jamroot.jam b/tools/build/v2/test/direct-request-test/jamroot.jam
new file mode 100644
index 0000000000..845aca8545
--- /dev/null
+++ b/tools/build/v2/test/direct-request-test/jamroot.jam
@@ -0,0 +1,6 @@
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+import gcc ;
diff --git a/tools/build/v2/test/direct_request_test.py b/tools/build/v2/test/direct_request_test.py
new file mode 100644
index 0000000000..000d15b64d
--- /dev/null
+++ b/tools/build/v2/test/direct_request_test.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+
+# First check some startup.
+t.set_tree("direct-request-test")
+t.run_build_system(extra_args="define=MACROS")
+t.expect_addition("bin/$toolset/debug/"
+ * (BoostBuild.List("a.obj b.obj b.dll a.exe")))
+
+
+# When building a debug version, the 'define' still applies.
+t.rm("bin")
+t.run_build_system(extra_args="debug define=MACROS")
+t.expect_addition("bin/$toolset/debug/"
+ * (BoostBuild.List("a.obj b.obj b.dll a.exe")))
+
+
+# When building release version, the 'define' should not apply: we will have
+# direct build request 'release <define>MACROS' and a real build property
+# 'debug'.
+t.copy("jamfile2.jam", "jamfile.jam")
+t.copy("b_inverse.cpp", "b.cpp")
+t.rm("bin")
+t.run_build_system(extra_args="release define=MACROS")
+
+
+# Regression test: direct build request was not working when there was more than
+# one level of 'build-project'.
+t.rm(".")
+t.write('jamroot.jam', '')
+t.write('jamfile.jam', 'build-project a ;')
+t.write('a/jamfile.jam', 'build-project b ;')
+t.write('a/b/jamfile.jam', '')
+t.run_build_system("release")
+
+t.cleanup()
diff --git a/tools/build/v2/test/disambiguation.py b/tools/build/v2/test/disambiguation.py
new file mode 100644
index 0000000000..91b14c5c17
--- /dev/null
+++ b/tools/build/v2/test/disambiguation.py
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that it is possible to add a suffix to a main target name to disambiguate
+# that main target from another, and that this does not affect the names of the
+# generated targets.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+exe hello.exe : hello.obj ;
+obj hello.obj : hello.cpp : <variant>debug ;
+obj hello.obj2 : hello.cpp : <variant>release ;
+""")
+
+t.write("hello.cpp", """
+int main() {}
+""")
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/hello.exe")
+t.expect_addition("bin/$toolset/debug/hello.obj")
+t.expect_addition("bin/$toolset/release/hello.obj")
+
+t.cleanup()
diff --git a/tools/build/v2/test/dll_path.py b/tools/build/v2/test/dll_path.py
new file mode 100644
index 0000000000..f88e06168b
--- /dev/null
+++ b/tools/build/v2/test/dll_path.py
@@ -0,0 +1,158 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2003. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+# Test that the <dll-path> property is correctly set when using
+# <hardcode-dll-paths>true.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+# The point of this test is to have exe "main" which uses library "b", which
+# uses library "a". When "main" is built with <hardcode-dll-paths>true, paths to
+# both libraries should be present as values of <dll-path> feature. We create a
+# special target type which reports <dll-path> values on its sources and compare
+# the list of found values with out expectations.
+
+t.write("jamfile.jam", """
+exe main : main.cpp b//b ;
+explicit main ;
+path-list mp : main ;
+""")
+
+t.write("main.cpp", """
+int main() {}
+""")
+
+t.write("jamroot.jam", """
+using dll_paths ;
+""")
+
+t.write("dll_paths.jam", """
+import type ;
+import generators ;
+import feature ;
+import sequence ;
+import print ;
+import "class" : new ;
+
+rule init ( )
+{
+ type.register PATH_LIST : pathlist ;
+
+ class dll-paths-list-generator : generator
+ {
+ rule __init__ ( )
+ {
+ generator.__init__ dll_paths.list : EXE : PATH_LIST ;
+ }
+
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ local dll-paths ;
+ for local s in $(sources)
+ {
+ local a = [ $(s).action ] ;
+ if $(a)
+ {
+ local p = [ $(a).properties ] ;
+ dll-paths += [ $(p).get <dll-path> ] ;
+ }
+ }
+ return [ generator.generated-targets $(sources) :
+ [ $(property-set).add-raw $(dll-paths:G=<dll-path>) ] :
+ $(project) $(name) ] ;
+
+ }
+ }
+ generators.register [ new dll-paths-list-generator ] ;
+}
+
+rule list ( target : sources * : properties * )
+{
+ local paths = [ feature.get-values <dll-path> : $(properties) ] ;
+ paths = [ sequence.insertion-sort $(paths) ] ;
+ print.output $(target) ;
+ print.text $(paths) ;
+}
+""")
+
+t.write("dll_paths.py", """
+import bjam
+
+import b2.build.type as type
+import b2.build.generators as generators
+
+from b2.manager import get_manager
+
+def init():
+ type.register("PATH_LIST", ["pathlist"])
+
+ class DllPathsListGenerator(generators.Generator):
+
+ def __init__(self):
+ generators.Generator.__init__(self, "dll_paths.list", False, ["EXE"], ["PATH_LIST"])
+
+ def generated_targets(self, sources, ps, project, name):
+
+ dll_paths = []
+ for s in sources:
+ a = s.action()
+ if a:
+ p = a.properties()
+ dll_paths += p.get('dll-path')
+ dll_paths.sort()
+ return generators.Generator.generated_targets(self,
+ sources, ps.add_raw(["<dll-path>" + p for p in dll_paths]),
+ project, name)
+
+ generators.register(DllPathsListGenerator())
+
+command = \"\"\"
+echo $(PATHS) > $(<[1])
+\"\"\"
+def function(target, sources, ps):
+ bjam.call('set-target-variable', target, "PATHS", ps.get('dll-path'))
+
+get_manager().engine().register_action("dll_paths.list", command, function=function)
+""")
+
+t.write("a/a.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+foo() {}
+""")
+
+t.write("a/jamfile.jam", """
+lib a : a.cpp ;
+""")
+
+t.write("b/b.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+bar() {}
+""")
+
+t.write("b/jamfile.jam", """
+lib b : b.cpp ../a//a ;
+""")
+
+t.run_build_system("hardcode-dll-paths=true")
+
+t.expect_addition("bin/$toolset/debug/mp.pathlist")
+
+es1 = t.adjust_names(["a/bin/$toolset/debug"])[0]
+es2 = t.adjust_names(["b/bin/$toolset/debug"])[0]
+
+t.expect_content_line("bin/$toolset/debug/mp.pathlist", "*" + es1);
+t.expect_content_line("bin/$toolset/debug/mp.pathlist", "*" + es2);
+
+t.cleanup()
diff --git a/tools/build/v2/test/double_loading.py b/tools/build/v2/test/double_loading.py
new file mode 100644
index 0000000000..27004a1767
--- /dev/null
+++ b/tools/build/v2/test/double_loading.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+# Regression test for double loading of the same Jamfile.
+t.write("jamroot.jam", "" )
+t.write("jamfile.jam", "build-project subdir ;")
+t.write("subdir/jamfile.jam", 'ECHO "Loaded subdir" ;')
+
+t.run_build_system(subdir="subdir")
+t.expect_output_line("Loaded subdir")
+
+
+# Regression test for a more contrived case. The top-level Jamfile refers to
+# subdir via use-project, while subdir's Jamfile is being loaded. The motivation
+# why use-project referring to subprojects is useful can be found at
+# http://article.gmane.org/gmane.comp.lib.boost.build/3906/
+t.write("jamroot.jam", "" )
+t.write("jamfile.jam", "use-project /subdir : subdir ;")
+t.write("subdir/jamfile.jam", "project subdir ;")
+
+t.run_build_system(subdir="subdir");
+
+t.cleanup()
diff --git a/tools/build/v2/test/duplicate.py b/tools/build/v2/test/duplicate.py
new file mode 100644
index 0000000000..1d0d5f7f22
--- /dev/null
+++ b/tools/build/v2/test/duplicate.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This test tries to stage the same file to the same location by *two* different
+# stage rules, in two different projects. This is not exactly good thing to do,
+# but still, V2 should handle this. We had two bugs:
+# - since the file is referred from two projects, we created to different
+# virtual targets
+# - we also failed to figure out that the two target corresponding to the copied
+# files (created in two projects) are actually equivalent.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("a.cpp", """
+""")
+
+t.write("jamroot.jam", """
+build-project a ;
+build-project b ;
+""")
+
+t.write("a/jamfile.jam", """
+stage bin : ../a.cpp : <location>../dist ;
+""")
+
+t.write("b/jamfile.jam", """
+stage bin : ../a.cpp : <location>../dist ;
+""")
+
+t.run_build_system()
+t.expect_addition("dist/a.cpp")
+
+t.cleanup()
diff --git a/tools/build/v2/test/echo_args.jam b/tools/build/v2/test/echo_args.jam
new file mode 100644
index 0000000000..0f6956e462
--- /dev/null
+++ b/tools/build/v2/test/echo_args.jam
@@ -0,0 +1,20 @@
+# Copyright 2001 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+rule echo_args ( a b ? c ? : d + : e * )
+{
+ ECHO a= $(a) b= $(b) c= $(c) ":" d= $(d) ":" e= $(e) ;
+}
+
+rule echo_varargs ( a b ? c ? : d + : e * : * )
+{
+ ECHO a= $(a) b= $(b) c= $(c) ":" d= $(d) ":" e= $(e)
+ ": rest= "$(4[1]) $(4[2])
+ ": "$(5[1]) $(5[2])
+ ": "$(6[1]) $(6[2])
+ ": "$(7[1]) $(7[2])
+ ": "$(8[1]) $(8[2])
+ ": "$(9[1]) $(9[2]) ;
+}
+
diff --git a/tools/build/v2/test/empty.jam b/tools/build/v2/test/empty.jam
new file mode 100644
index 0000000000..c6220580ca
--- /dev/null
+++ b/tools/build/v2/test/empty.jam
@@ -0,0 +1,5 @@
+# Copyright 2001 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This file is empty; it just suppresses warnings
diff --git a/tools/build/v2/test/engine/README.txt b/tools/build/v2/test/engine/README.txt
new file mode 100644
index 0000000000..c38701fb8a
--- /dev/null
+++ b/tools/build/v2/test/engine/README.txt
@@ -0,0 +1,5 @@
+
+This directory contains tests for the update engine of
+Boost.Build. They presently are not integrated with
+the Python based test system and must be run by
+hand.
diff --git a/tools/build/v2/test/engine/action_status.jam b/tools/build/v2/test/engine/action_status.jam
new file mode 100644
index 0000000000..ee1c6c382a
--- /dev/null
+++ b/tools/build/v2/test/engine/action_status.jam
@@ -0,0 +1,28 @@
+#~ Copyright 2007 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+if ! $(BJAM_SUBTEST)
+{
+ ECHO --- Testing \"actions status results\"... ;
+
+ assert "" 0 : (==) : [ SHELL "\"$(ARGV[1])\" -f action_status.jam -sBJAM_SUBTEST=1" : exit-status : no-output ] ;
+ if $(NT)
+ {
+ assert "" 0 : (==) : [ SHELL "\"$(ARGV[1])\" -f action_status.jam -sBJAM_SUBTEST=1 \"-sACTION=;\"" : exit-status : no-output ] ;
+ }
+ assert "" 0 : (!=) : [ SHELL "\"$(ARGV[1])\" -f action_status.jam -sBJAM_SUBTEST=1 -sACTION=invalid" : exit-status : no-output ] ;
+}
+else
+{
+ actions quietly .a. { $(ACTION) }
+
+ rule .a.
+ {
+ DEPENDS $(<) : $(>) ;
+ }
+
+ NOTFILE subtest ;
+ .a. subtest_a : subtest ;
+ DEPENDS all : subtest_a ;
+}
diff --git a/tools/build/v2/test/engine/actions_quietly.jam b/tools/build/v2/test/engine/actions_quietly.jam
new file mode 100644
index 0000000000..e7b9ad86cb
--- /dev/null
+++ b/tools/build/v2/test/engine/actions_quietly.jam
@@ -0,0 +1,55 @@
+#~ Copyright 2007 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+if ! $(BJAM_SUBTEST)
+{
+ ECHO --- Testing \"actions quietly\"... ;
+
+ assert "...found 4 targets...
+...updating 2 targets...
+.a. subtest_a
+
+echo [subtest_a] 0
+echo [subtest_a] 1
+echo [subtest_a] 2
+
+[subtest_a] 0
+[subtest_a] 1
+[subtest_a] 2
+.a. subtest_b
+
+echo [subtest_b] 0
+echo [subtest_b] 1
+echo [subtest_b] 2
+
+[subtest_b] 0
+[subtest_b] 1
+[subtest_b] 2
+...updated 2 targets...
+" : (==) : [ SHELL "\"$(ARGV[1])\" -f actions_quietly.jam -sBJAM_SUBTEST=1 -d2" ] ;
+
+ assert "...found 4 targets...
+...updating 2 targets...
+...updated 2 targets...
+" : (==) : [ SHELL "\"$(ARGV[1])\" -f actions_quietly.jam -sBJAM_SUBTEST=1" ] ;
+}
+else
+{
+ actions quietly .a.
+ {
+echo [$(<:B)] 0
+echo [$(<:B)] 1
+echo [$(<:B)] 2
+ }
+
+ rule .a.
+ {
+ DEPENDS $(<) : $(>) ;
+ }
+
+ NOTFILE subtest ;
+ .a. subtest_a : subtest ;
+ .a. subtest_b : subtest ;
+ DEPENDS all : subtest_a subtest_b ;
+}
diff --git a/tools/build/v2/test/engine/builtin_normalize_path.jam b/tools/build/v2/test/engine/builtin_normalize_path.jam
new file mode 100644
index 0000000000..76e0a9ddb0
--- /dev/null
+++ b/tools/build/v2/test/engine/builtin_normalize_path.jam
@@ -0,0 +1,60 @@
+#~ Copyright 2008 Jurko Gospodnetic.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+ECHO --- Testing NORMALIZE_PATH builtin... ;
+
+assert "." : (==) : [ NORMALIZE_PATH ] ;
+assert "." : (==) : [ NORMALIZE_PATH "" ] ;
+assert "." : (==) : [ NORMALIZE_PATH "." ] ;
+assert ".." : (==) : [ NORMALIZE_PATH ".." ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "/" ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "\\" ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "//" ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "\\\\" ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "//\\\\//\\\\" ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "/." ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "/./" ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "\\\\///.///\\\\\\" ] ;
+assert "." : (==) : [ NORMALIZE_PATH "./././././." ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "/./././././." ] ;
+assert "foo" : (==) : [ NORMALIZE_PATH "foo" ] ;
+assert "foo" : (==) : [ NORMALIZE_PATH "foo/" ] ;
+assert "foo" : (==) : [ NORMALIZE_PATH "foo\\" ] ;
+assert "foo" : (==) : [ NORMALIZE_PATH "foo\\\\/////" ] ;
+assert "foo" : (==) : [ NORMALIZE_PATH "foo\\\\/////././." ] ;
+assert "foo" : (==) : [ NORMALIZE_PATH "foo\\\\/////./././" ] ;
+assert "." : (==) : [ NORMALIZE_PATH "foo/.." ] ;
+assert "." : (==) : [ NORMALIZE_PATH "foo////.." ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "///foo/\\\\/.." ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "\\\\\\foo\\//\\.." ] ;
+assert "." : (==) : [ NORMALIZE_PATH "foo/./.." ] ;
+assert "." : (==) : [ NORMALIZE_PATH "foo/././././.." ] ;
+assert "foo" : (==) : [ NORMALIZE_PATH "foo/./././bar/./././.././././baz/./././.." ] ;
+assert "/foo" : (==) : [ NORMALIZE_PATH "/foo/./././bar/./././.././././baz/./././.." ] ;
+assert "foo" : (==) : [ NORMALIZE_PATH "foo/./././bar/./././////.././././baz/./././.." ] ;
+assert "/foo" : (==) : [ NORMALIZE_PATH "/foo/./././bar/./././////.././././baz/./././.." ] ;
+assert ".." : (==) : [ NORMALIZE_PATH "./.." ] ;
+assert ".." : (==) : [ NORMALIZE_PATH "././././.." ] ;
+assert "../.." : (==) : [ NORMALIZE_PATH "../.." ] ;
+assert "../.." : (==) : [ NORMALIZE_PATH "./../.." ] ;
+assert "../.." : (==) : [ NORMALIZE_PATH "././././../.." ] ;
+assert "../.." : (==) : [ NORMALIZE_PATH "./.././././.." ] ;
+assert "../.." : (==) : [ NORMALIZE_PATH "././././.././././.." ] ;
+assert "../.." : (==) : [ NORMALIZE_PATH "..//\\\\\\//.." ] ;
+assert "../.." : (==) : [ NORMALIZE_PATH "../..\\\\/\\\\" ] ;
+assert "." : (==) : [ NORMALIZE_PATH "foo/../bar/../baz/.." ] ;
+assert "." : (==) : [ NORMALIZE_PATH "foo////..////bar////.//////.////../baz/.." ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "/foo/../bar/../baz/.." ] ;
+assert "/" : (==) : [ NORMALIZE_PATH "/foo////..////bar////.//////.////../baz/.." ] ;
+
+# Invalid rooted paths with leading dotdots.
+assert : (==) : [ NORMALIZE_PATH "/.." ] ;
+assert : (==) : [ NORMALIZE_PATH "/../" ] ;
+assert : (==) : [ NORMALIZE_PATH "//\\\\//\\\\/.." ] ;
+assert : (==) : [ NORMALIZE_PATH "\\\\//\\\\//\\.." ] ;
+assert : (==) : [ NORMALIZE_PATH "/../.." ] ;
+assert : (==) : [ NORMALIZE_PATH "/../../.." ] ;
+assert : (==) : [ NORMALIZE_PATH "/foo/bar/../baz/../../.." ] ;
+assert : (==) : [ NORMALIZE_PATH "/../for/././../././bar/././../././.." ] ;
+assert : (==) : [ NORMALIZE_PATH "/../foo/bar" ] ;
diff --git a/tools/build/v2/test/engine/builtin_shell.jam b/tools/build/v2/test/engine/builtin_shell.jam
new file mode 100644
index 0000000000..13d6245e32
--- /dev/null
+++ b/tools/build/v2/test/engine/builtin_shell.jam
@@ -0,0 +1,31 @@
+#~ Copyright 2006 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# TODO: Here we should test for the Windows popen() command unquoting bug but
+# that test will have to wait until a better testing framework is implemented.
+# To reproduce the bug try executing any command with its first parameter quoted
+# and containing spaces and having at least one other quote in the command
+# string.
+#
+# For example:
+#
+# "\Long folder name\aaa.exe" --name="Jurko" --no-surname
+#
+# would get its outermost quotes stripped and would be executed as:
+#
+# \Long folder name\aaa.exe" --name="Jurko --no-surname
+
+ECHO --- Testing SHELL builtin... ;
+
+local c = "date" ;
+if $(NT) { c = "PATH" ; }
+
+assert "" : (!=) : [ SHELL $(c) ] ;
+assert "" : (==) : [ SHELL $(c) : no-output ] ;
+assert "" 0 : (!=) : [ SHELL $(c) : exit-status ] ;
+assert "" 0 : (==) : [ SHELL $(c) : no-output : exit-status ] ;
+assert "" : (!=) : [ COMMAND $(c) ] ;
+assert "" : (==) : [ COMMAND $(c) : no-output ] ;
+assert "" 0 : (!=) : [ COMMAND $(c) : exit-status ] ;
+assert "" 0 : (==) : [ COMMAND $(c) : no-output : exit-status ] ;
diff --git a/tools/build/v2/test/engine/builtin_w32_getregnames.jam b/tools/build/v2/test/engine/builtin_w32_getregnames.jam
new file mode 100644
index 0000000000..1082f4ad72
--- /dev/null
+++ b/tools/build/v2/test/engine/builtin_w32_getregnames.jam
@@ -0,0 +1,17 @@
+#~ Copyright 2006 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+ECHO --- Testing W32_GETREGNAMES builtin... ;
+
+if $(NT)
+{
+ assert "Beep" "ExtendedSounds"
+ : (==) : [ W32_GETREGNAMES "HKEY_CURRENT_USER\\Control Panel\\Sound" : values ] ;
+ assert "Beep" "ExtendedSounds"
+ : (==) : [ W32_GETREGNAMES "HKCU\\Control Panel\\Sound" : values ] ;
+ assert "Control" "Enum" "Hardware Profiles" "Services"
+ : (==) : [ W32_GETREGNAMES "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet" : subkeys ] ;
+ assert "Control" "Enum" "Hardware Profiles" "Services"
+ : (==) : [ W32_GETREGNAMES "HKLM\\SYSTEM\\CurrentControlSet" : subkeys ] ;
+}
diff --git a/tools/build/v2/test/engine/option_d2.jam b/tools/build/v2/test/engine/option_d2.jam
new file mode 100644
index 0000000000..6dee8f47e7
--- /dev/null
+++ b/tools/build/v2/test/engine/option_d2.jam
@@ -0,0 +1,50 @@
+#~ Copyright 2007 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+if ! $(BJAM_SUBTEST)
+{
+ ECHO --- Testing -d2 option... ;
+
+ assert "...found 4 targets...
+...updating 2 targets...
+.a. subtest_a
+
+echo [subtest_a] 0
+echo [subtest_a] 1
+echo [subtest_a] 2
+
+[subtest_a] 0
+[subtest_a] 1
+[subtest_a] 2
+.a. subtest_b
+
+echo [subtest_b] 0
+echo [subtest_b] 1
+echo [subtest_b] 2
+
+[subtest_b] 0
+[subtest_b] 1
+[subtest_b] 2
+...updated 2 targets...
+" : (==) : [ SHELL "\"$(ARGV[1])\" -f option_d2.jam -sBJAM_SUBTEST=1 -d2" ] ;
+}
+else
+{
+ actions .a.
+ {
+echo [$(<:B)] 0
+echo [$(<:B)] 1
+echo [$(<:B)] 2
+ }
+
+ rule .a.
+ {
+ DEPENDS $(<) : $(>) ;
+ }
+
+ NOTFILE subtest ;
+ .a. subtest_a : subtest ;
+ .a. subtest_b : subtest ;
+ DEPENDS all : subtest_a subtest_b ;
+}
diff --git a/tools/build/v2/test/engine/option_l.jam b/tools/build/v2/test/engine/option_l.jam
new file mode 100644
index 0000000000..16299d631b
--- /dev/null
+++ b/tools/build/v2/test/engine/option_l.jam
@@ -0,0 +1,34 @@
+#~ Copyright 2007 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+if ! $(BJAM_SUBTEST)
+{
+ ECHO --- Testing -l option... ;
+
+ assert "...found 2 targets...
+...updating 1 target...
+.a. sleeper
+2 second time limit exceeded
+001
+
+echo 001
+sleep 4
+echo 002
+
+...failed .a. sleeper...
+...failed updating 1 target...
+" : (==) : [ SHELL "\"$(ARGV[1])\" -f option_l.jam -sBJAM_SUBTEST=1 -l2" ] ;
+}
+else
+{
+ actions .a. {
+echo 001
+sleep 4
+echo 002
+}
+
+ .a. sleeper ;
+
+ DEPENDS all : sleeper ;
+}
diff --git a/tools/build/v2/test/engine/option_n.jam b/tools/build/v2/test/engine/option_n.jam
new file mode 100644
index 0000000000..901dfed8db
--- /dev/null
+++ b/tools/build/v2/test/engine/option_n.jam
@@ -0,0 +1,44 @@
+#~ Copyright 2007 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+if ! $(BJAM_SUBTEST)
+{
+ ECHO --- Testing -n option... ;
+
+ assert "...found 4 targets...
+...updating 2 targets...
+.a. subtest_a
+
+echo [subtest_a] 0
+echo [subtest_a] 1
+echo [subtest_a] 2
+
+.a. subtest_b
+
+echo [subtest_b] 0
+echo [subtest_b] 1
+echo [subtest_b] 2
+
+...updated 2 targets...
+" : (==) : [ SHELL "\"$(ARGV[1])\" -f option_n.jam -sBJAM_SUBTEST=1 -n" ] ;
+}
+else
+{
+ actions .a.
+ {
+echo [$(<:B)] 0
+echo [$(<:B)] 1
+echo [$(<:B)] 2
+ }
+
+ rule .a.
+ {
+ DEPENDS $(<) : $(>) ;
+ }
+
+ NOTFILE subtest ;
+ .a. subtest_a : subtest ;
+ .a. subtest_b : subtest ;
+ DEPENDS all : subtest_a subtest_b ;
+}
diff --git a/tools/build/v2/test/engine/parallel_actions.jam b/tools/build/v2/test/engine/parallel_actions.jam
new file mode 100644
index 0000000000..adcd1ad855
--- /dev/null
+++ b/tools/build/v2/test/engine/parallel_actions.jam
@@ -0,0 +1,91 @@
+#~ Copyright 2006 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+if ! $(BJAM_SUBTEST)
+{
+ ECHO --- Testing -jN parallel execution of actions... ;
+
+ assert "...found 12 targets...
+...updating 8 targets...
+sleeper 1.a
+[.a] 0
+[.a] 1
+[.a] 2
+sleeper 2.a
+[.a] 0
+[.a] 1
+[.a] 2
+sleeper 3.a
+[.a] 0
+[.a] 1
+[.a] 2
+sleeper 4.a
+[.a] 0
+[.a] 1
+[.a] 2
+sleeper 1.b
+[.b] 0
+[.b] 1
+[.b] 2
+sleeper 2.b
+[.b] 0
+[.b] 1
+[.b] 2
+sleeper 3.b
+[.b] 0
+[.b] 1
+[.b] 2
+sleeper 4.b
+[.b] 0
+[.b] 1
+[.b] 2
+...updated 8 targets...
+" : (==) : [ SHELL "\"$(ARGV[1])\" -f parallel_actions.jam -sBJAM_SUBTEST=1 -j4" ] ;
+}
+else
+{
+ if $(NT)
+ {
+ actions sleeper
+ {
+echo [$(<:S)] 0
+sleep 1
+echo [$(<:S)] 1
+sleep 1
+echo [$(<:S)] 2
+sleep $(<:B)
+ }
+ }
+ else
+ {
+ actions sleeper
+ {
+echo "[$(<:S)] 0" 1>&2
+sleep 1
+echo "[$(<:S)] 1"
+sleep 1
+echo "[$(<:S)] 2" 1>&2
+sleep $(<:B)
+ }
+ }
+
+ rule sleeper
+ {
+ DEPENDS $(<) : $(>) ;
+ }
+
+ NOTFILE front ;
+ sleeper 1.a : front ;
+ sleeper 2.a : front ;
+ sleeper 3.a : front ;
+ sleeper 4.a : front ;
+ NOTFILE choke ;
+ DEPENDS choke : 1.a 2.a 3.a 4.a ;
+ sleeper 1.b : choke ;
+ sleeper 2.b : choke ;
+ sleeper 3.b : choke ;
+ sleeper 4.b : choke ;
+ DEPENDS bottom : 1.b 2.b 3.b 4.b ;
+ DEPENDS all : bottom ;
+}
diff --git a/tools/build/v2/test/engine/parallel_multifile_actions_1.jam b/tools/build/v2/test/engine/parallel_multifile_actions_1.jam
new file mode 100644
index 0000000000..d11de7a123
--- /dev/null
+++ b/tools/build/v2/test/engine/parallel_multifile_actions_1.jam
@@ -0,0 +1,45 @@
+#~ Copyright 2007 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+if ! $(BJAM_SUBTEST)
+{
+ ECHO --- Testing -jN parallel execution of multi-file actions - 1... ;
+
+ assert "...found 6 targets...
+...updating 4 targets...
+.gen. g1.generated
+001
+002
+.use.1 u1.user
+003
+.use.2 u2.user
+004
+...updated 4 targets...
+" : (==) : [ SHELL "\"$(ARGV[1])\" -f parallel_multifile_actions_1.jam -sBJAM_SUBTEST=1 -j2" ] ;
+}
+else
+{
+ actions .gen. {
+echo 001
+sleep 4
+echo 002
+}
+ rule .use.1 { DEPENDS $(<) : $(>) ; }
+ actions .use.1 {
+echo 003
+}
+ rule .use.2 { DEPENDS $(<) : $(>) ; }
+ actions .use.2 {
+sleep 1
+echo 004
+}
+
+ .gen. g1.generated g2.generated ;
+ .use.1 u1.user : g1.generated ;
+ .use.2 u2.user : g2.generated ;
+
+ NOTFILE root ;
+ DEPENDS g1.generated g2.generated : root ;
+ DEPENDS all : u1.user u2.user ;
+}
diff --git a/tools/build/v2/test/engine/parallel_multifile_actions_2.jam b/tools/build/v2/test/engine/parallel_multifile_actions_2.jam
new file mode 100644
index 0000000000..a85cf63fdb
--- /dev/null
+++ b/tools/build/v2/test/engine/parallel_multifile_actions_2.jam
@@ -0,0 +1,49 @@
+# Copyright 2008 Jurko Gospodnetic, Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Added to guard against a bug causing targets to be used before they
+# themselves have finished building. This used to happen for targets built by a
+# multi-file action that got triggered by another target, except when the target
+# triggering the action was the first one in the list of targets produced by
+# that action.
+#
+# Example:
+# When target A and target B were declared as created by a single action with
+# A being the first one listed, and target B triggered running that action then
+# while the action was still running, target A was already reporting as being
+# built causing other targets depending on target A to be built prematurely.
+
+if ! $(BJAM_SUBTEST)
+{
+ ECHO --- Testing -jN parallel execution of multi-file actions - 2... ;
+
+ assert "...found 4 targets...
+...updating 3 targets...
+link dll
+001 - linked
+install installed_dll
+002 - installed
+...updated 3 targets...
+" : (==) : [ SHELL "\"$(ARGV[1])\" -f parallel_multifile_actions_2.jam -sBJAM_SUBTEST=1 -j2" ] ;
+}
+else
+{
+ actions link
+ {
+ sleep 1
+ echo 001 - linked
+ }
+
+ link dll lib ;
+
+ actions install
+ {
+ echo 002 - installed
+ }
+
+ install installed_dll : dll ;
+ DEPENDS installed_dll : dll ;
+
+ DEPENDS all : lib installed_dll ;
+}
diff --git a/tools/build/v2/test/engine/rule_param.jam b/tools/build/v2/test/engine/rule_param.jam
new file mode 100644
index 0000000000..8bc51becf3
--- /dev/null
+++ b/tools/build/v2/test/engine/rule_param.jam
@@ -0,0 +1,60 @@
+#~ Copyright 2008 Jonathan Biggar
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+ECHO -- Testing parameter passing... ;
+
+rule test_numeric_params
+{
+ assert $(1) : (==) : 1 ;
+ assert $(2) : (==) : 2 ;
+ assert $(3) : (==) : 3 ;
+ assert $(4) : (==) : 4 ;
+ assert $(5) : (==) : 5 ;
+ assert $(6) : (==) : 6 ;
+ assert $(7) : (==) : 7 ;
+ assert $(8) : (==) : 8 ;
+ assert $(9) : (==) : 9 ;
+ assert $(10) : (==) : 10 ;
+ assert $(11) : (==) : 11 ;
+ assert $(12) : (==) : 12 ;
+ assert $(13) : (==) : 13 ;
+ assert $(14) : (==) : 14 ;
+ assert $(15) : (==) : 15 ;
+ assert $(16) : (==) : 16 ;
+ assert $(17) : (==) : 17 ;
+ assert $(18) : (==) : 18 ;
+ assert $(19) : (==) : 19 ;
+}
+
+rule test_named_params ( p1 : p2 : p3 : p4 : p5 : p6 : p7 : p8 : p9 :
+ p10 : p11 : p12 : p13 : p14 : p15 : p16 : p17 : p18 : p19 )
+
+
+{
+ assert $(p1) : (==) : 1 ;
+ assert $(p2) : (==) : 2 ;
+ assert $(p3) : (==) : 3 ;
+ assert $(p4) : (==) : 4 ;
+ assert $(p5) : (==) : 5 ;
+ assert $(p6) : (==) : 6 ;
+ assert $(p7) : (==) : 7 ;
+ assert $(p8) : (==) : 8 ;
+ assert $(p9) : (==) : 9 ;
+ assert $(p10) : (==) : 10 ;
+ assert $(p11) : (==) : 11 ;
+ assert $(p12) : (==) : 12 ;
+ assert $(p13) : (==) : 13 ;
+ assert $(p14) : (==) : 14 ;
+ assert $(p15) : (==) : 15 ;
+ assert $(p16) : (==) : 16 ;
+ assert $(p17) : (==) : 17 ;
+ assert $(p18) : (==) : 18 ;
+ assert $(p19) : (==) : 19 ;
+}
+
+test_numeric_params 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 :
+ 10 : 11 : 12 : 13 : 14 : 15 : 16 : 17 : 18 : 19 ;
+
+test_named_params 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 :
+ 10 : 11 : 12 : 13 : 14 : 15 : 16 : 17 : 18 : 19 ;
diff --git a/tools/build/v2/test/engine/stress_var_expand.jam b/tools/build/v2/test/engine/stress_var_expand.jam
new file mode 100644
index 0000000000..e76b36ab35
--- /dev/null
+++ b/tools/build/v2/test/engine/stress_var_expand.jam
@@ -0,0 +1,14 @@
+#~ Copyright 2006 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+ECHO --- Testing var expansion... ;
+
+local i = 0 ;
+local v = one two ;
+while $(i) != 4
+{
+ i = [ CALC $(i) + 1 ] ;
+ v = $(v)$(v) ;
+ assert $(i) : (==) : $(i) ;
+}
diff --git a/tools/build/v2/test/engine/target_var.jam b/tools/build/v2/test/engine/target_var.jam
new file mode 100644
index 0000000000..d4fdae6314
--- /dev/null
+++ b/tools/build/v2/test/engine/target_var.jam
@@ -0,0 +1,16 @@
+#~ Copyright 2006 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+ECHO --- Testing var on target semantics... ;
+
+v on a = 1 ;
+v on b = 1 2 ;
+v on c = 1 2 3 ;
+v on d ?= 1 2 3 4 ;
+v on d ?= 5 6 7 8 ;
+v on a ?= 2 ;
+assert [ on a return $(v) ] : (==) : 1 ;
+assert [ on b return $(v) ] : (==) : 1 2 ;
+assert [ on c return $(v) ] : (==) : 1 2 3 ;
+assert [ on d return $(v) ] : (==) : 1 2 3 4 ;
diff --git a/tools/build/v2/test/engine/test.bat b/tools/build/v2/test/engine/test.bat
new file mode 100644
index 0000000000..a364fb50f3
--- /dev/null
+++ b/tools/build/v2/test/engine/test.bat
@@ -0,0 +1,53 @@
+@ECHO OFF
+
+REM ~ Copyright 2006-2008 Rene Rivera.
+REM ~ Distributed under the Boost Software License, Version 1.0.
+REM ~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+REM ~ set BJAM=bjam
+REM ~ set BJAM_SRC=..\src
+REM ~ set BJAM_BIN=..\src\bin.ntx86\bjam.exe
+
+setlocal
+goto Start
+
+:Test_Path
+REM Tests for the given file(executable) presence in the directories in the PATH
+REM environment variable. Additionaly sets FOUND_PATH to the path of the
+REM found file.
+setlocal & endlocal & ver>NUL
+setlocal
+set test=%~$PATH:1
+endlocal
+if not errorlevel 1 set FOUND_PATH=%~dp$PATH:1
+goto :eof
+
+:Guess_BJAM
+setlocal & endlocal & ver>NUL
+if NOT "_%BJAM%_" == "__" goto :eof
+call :Test_Path bjam.exe
+if not errorlevel 1 (
+ set BJAM=bjam.exe
+ goto :eof)
+if "_%BJAM%_" == "__" (
+ set BJAM=%BJAM_BIN%
+ goto :eof)
+setlocal & endlocal & ver>NUL
+goto :eof
+
+:Build_BJAM_To_Test
+setlocal & endlocal & ver>NUL
+if "_%BJAM_SRC%_" == "__" set BJAM_SRC=..\src
+PUSHD %BJAM_SRC%
+call build.bat
+@ECHO OFF
+POPD
+set BJAM_BIN=%BJAM_SRC%\bin.ntx86\bjam.exe
+setlocal & endlocal & ver>NUL
+goto :eof
+
+:Start
+call :Build_BJAM_To_Test
+call :Guess_BJAM
+@ECHO ON
+%BJAM% -f test.jam "-sBJAM=%BJAM_BIN%"
diff --git a/tools/build/v2/test/engine/test.jam b/tools/build/v2/test/engine/test.jam
new file mode 100644
index 0000000000..f6f537766d
--- /dev/null
+++ b/tools/build/v2/test/engine/test.jam
@@ -0,0 +1,91 @@
+#~ Copyright 2006-2008 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+TESTS =
+ action_status
+ actions_quietly
+ builtin_normalize_path
+ builtin_shell
+ builtin_w32_getregnames
+ option_d2
+ option_l
+ option_n
+ parallel_actions
+ parallel_multifile_actions_1
+ parallel_multifile_actions_2
+ rule_param
+ stress_var_expand
+ target_var
+ var_expand
+ ;
+
+BJAM ?= bjam ;
+
+#############################################################################
+
+if $(BJAM_RUN_TEST)
+{
+ fail-count = 0 ;
+ pass-count = 0 ;
+
+ rule message ( message * )
+ {
+ local b = [ BACKTRACE ] ;
+ ECHO "$(b[-4]):$(b[-3]):" $(message) ;
+ }
+
+
+ rule fail ( message * )
+ {
+ fail-count = [ CALC $(fail-count) + 1 ] ;
+ message "error:" [FAILED] $(message) ;
+ }
+
+
+ rule pass ( message * )
+ {
+ pass-count = [ CALC $(pass-count) + 1 ] ;
+ if --verbose in $(ARGV)
+ {
+ message "info:" [PASSED] $(message) ;
+ }
+ }
+
+
+ rule assert ( expected * : test ? : obtained * )
+ {
+ test ?= "(==)" ;
+ local r = 0 ;
+ if $(test) = "(==)" && "*$(expected)*" != "*$(obtained)*"
+ {
+ fail '$(expected)' $(test) '$(obtained)' ;
+ }
+ else if $(test) = "(!=)" && "*$(expected)*" = "*$(obtained)*"
+ {
+ fail '$(expected)' $(test) '$(obtained)' ;
+ }
+ else
+ {
+ pass '$(expected)' $(test) '$(obtained)' ;
+ }
+ }
+
+ include $(BJAM_RUN_TEST).jam ;
+
+ EXIT --- $(BJAM_RUN_TEST): PASSED($(pass-count)) *FAILED($(fail-count))* : $(fail-count) ;
+}
+else
+{
+ ECHO "Testing: $(BJAM)" ;
+ fail-count = 0 ;
+
+ for local test in $(TESTS)
+ {
+ local result = [ SHELL "\"$(BJAM)\" -f test.jam -sBJAM_RUN_TEST=$(test)" : exit-status ] ;
+ fail-count = [ CALC $(fail-count) + $(result[1]) ] ;
+ ECHO $(result[0]) ;
+ }
+
+ EXIT --- Complete: *FAILED($(fail-count))* : $(fail-count) ;
+}
diff --git a/tools/build/v2/test/engine/test.sh b/tools/build/v2/test/engine/test.sh
new file mode 100755
index 0000000000..5c092836a7
--- /dev/null
+++ b/tools/build/v2/test/engine/test.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+#~ Copyright 2006-2008 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+#~ BJAM=bjam
+#~ BJAM_SRC=../src
+#~ BJAM_BIN=`ls -1 ${BJAM_SRC}/bin.*/bjam`
+
+# Run a command, and echo before doing so. Also checks the exit
+# status and quits if there was an error.
+echo_run ()
+{
+ echo "$@"
+ $@
+ r=$?
+ if test $r -ne 0 ; then
+ exit $r
+ fi
+}
+
+# Check that a command is in the PATH.
+test_path ()
+{
+ if `command -v command 1>/dev/null 2>/dev/null`; then
+ command -v $1 1>/dev/null 2>/dev/null
+ else
+ hash $1 1>/dev/null 2>/dev/null
+ fi
+}
+
+Guess_BJAM ()
+{
+ if test_path bjam ; then BJAM=bjam
+ elif test -r ./bjam ; then BJAM=./bjam
+ elif test -r "${BJAM_BIN}" ; then BJAM="${BJAM_BIN}"
+ fi
+}
+
+Build_BJAM_To_Test ()
+{
+ cwd=`pwd`
+ if test "${BJAM_SRC}" = "" ; then BJAM_SRC=../src ; fi
+ cd "${BJAM_SRC}"
+ ./build.sh
+ if test "${BJAM_BIN}" = "" ; then BJAM_BIN=`ls -1 ${BJAM_SRC}/bin.*/bjam` ; fi
+ cd "${cwd}"
+}
+
+Build_BJAM_To_Test
+Guess_BJAM
+echo_run "${BJAM}" -f test.jam "-sBJAM=${BJAM_BIN}" "$@"
diff --git a/tools/build/v2/test/engine/var_expand.jam b/tools/build/v2/test/engine/var_expand.jam
new file mode 100644
index 0000000000..00b03a0ce1
--- /dev/null
+++ b/tools/build/v2/test/engine/var_expand.jam
@@ -0,0 +1,19 @@
+#~ Copyright 2006 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+ECHO --- Testing var expansion... ;
+
+local p0 = name ;
+local p1 = dir/name ;
+local p2 = dir/sub/name ;
+
+assert name : (==) : $(p0:D=) ;
+assert name : (==) : $(p1:D=) ;
+assert name : (==) : $(p2:D=) ;
+assert "" : (==) : $(p0:D) ;
+assert dir : (==) : $(p1:D) ;
+assert dir/sub : (==) : $(p2:D) ;
+assert "" : (==) : $(p0:S) ;
+assert ($(p0)) : (==) : [ MATCH ^@(.*) : "@($(p0))" ] ;
+assert ($(p0)) : (==) : [ MATCH @(.*) : "--@($(p0))" ] ;
diff --git a/tools/build/v2/test/example_customization.py b/tools/build/v2/test/example_customization.py
new file mode 100644
index 0000000000..f8fe15cc28
--- /dev/null
+++ b/tools/build/v2/test/example_customization.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the 'customization' example.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree("../example/customization")
+
+t.run_build_system()
+
+t.expect_addition(["bin/$toolset/debug/codegen.exe",
+ "bin/$toolset/debug/usage.cpp"])
+
+t.cleanup()
diff --git a/tools/build/v2/test/example_gettext.py b/tools/build/v2/test/example_gettext.py
new file mode 100644
index 0000000000..e7cfa8eb7b
--- /dev/null
+++ b/tools/build/v2/test/example_gettext.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the 'gettext' example.
+
+import BoostBuild
+import os
+import string
+
+t = BoostBuild.Tester()
+
+t.set_tree("../example/gettext")
+
+t.run_build_system(stderr=None)
+
+t.expect_addition(["bin/$toolset/debug/main.exe",
+ "bin/$toolset/debug/russian.mo"])
+
+file = t.adjust_names(["bin/$toolset/debug/main.exe"])[0]
+
+input_fd = os.popen(file)
+input = input_fd.read();
+
+t.fail_test(string.find(input, "international hello") != 0)
+
+t.cleanup()
diff --git a/tools/build/v2/test/example_libraries.py b/tools/build/v2/test/example_libraries.py
new file mode 100644
index 0000000000..c40af74de1
--- /dev/null
+++ b/tools/build/v2/test/example_libraries.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the 'libraries' example.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree("../example/libraries")
+
+t.run_build_system()
+
+t.expect_addition(["app/bin/$toolset/debug/app.exe",
+ "util/foo/bin/$toolset/debug/bar.dll"])
+
+t.cleanup()
diff --git a/tools/build/v2/test/example_make.py b/tools/build/v2/test/example_make.py
new file mode 100644
index 0000000000..1e62702eff
--- /dev/null
+++ b/tools/build/v2/test/example_make.py
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the 'make' example.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree("../example/make")
+
+t.run_build_system()
+
+t.expect_addition(["bin/$toolset/debug/main.cpp"])
+
+t.cleanup()
diff --git a/tools/build/v2/test/example_qt4.py b/tools/build/v2/test/example_qt4.py
new file mode 100644
index 0000000000..1b0dc27bda
--- /dev/null
+++ b/tools/build/v2/test/example_qt4.py
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the 'qt4' examples.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree("../example/qt/qt4/hello")
+t.run_build_system()
+t.expect_addition(["bin/$toolset/debug/threading-multi/arrow"])
+
+t.set_tree("../example/qt/qt4/moccable-cpp")
+t.run_build_system()
+t.expect_addition(["bin/$toolset/debug/threading-multi/main"])
+
+t.set_tree("../example/qt/qt4/uic")
+t.run_build_system()
+t.expect_addition(["bin/$toolset/debug/threading-multi/hello"])
+
+t.cleanup()
diff --git a/tools/build/v2/test/exit_status.py b/tools/build/v2/test/exit_status.py
new file mode 100755
index 0000000000..11c4abf76f
--- /dev/null
+++ b/tools/build/v2/test/exit_status.py
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2010.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that build failure results in non-zero exit status
+
+import BoostBuild
+
+# Create a temporary working directory.
+t = BoostBuild.Tester()
+
+# Create the needed files.
+t.write("jamroot.jam", """
+exe hello : hello.cpp ;
+""")
+
+t.write("hello.cpp", """
+int main() {
+""")
+
+t.run_build_system(status=1)
+
+t.cleanup()
diff --git a/tools/build/v2/test/expansion.py b/tools/build/v2/test/expansion.py
new file mode 100644
index 0000000000..a9f6653563
--- /dev/null
+++ b/tools/build/v2/test/expansion.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("a.cpp", """
+#ifdef CF_IS_OFF
+int main() {}
+#endif
+""")
+
+t.write("b.cpp", """
+#ifdef CF_1
+int main() {}
+#endif
+""")
+
+t.write("c.cpp", """
+#ifdef FOO
+int main() {}
+#endif
+""")
+
+t.write("jamfile.jam", """
+# See if default value of composite feature 'cf' will be expanded to
+# <define>CF_IS_OFF.
+exe a : a.cpp ;
+
+# See if subfeature in requirements in expanded.
+exe b : b.cpp : <cf>on-1 ;
+
+# See if conditional requirements are recursively expanded.
+exe c : c.cpp : <toolset>$toolset:<variant>release <variant>release:<define>FOO
+ ;
+""")
+
+t.write("jamroot.jam", """
+import feature ;
+feature.feature cf : off on : composite incidental ;
+feature.compose <cf>off : <define>CF_IS_OFF ;
+feature.subfeature cf on : version : 1 2 : composite optional incidental ;
+feature.compose <cf-on:version>1 : <define>CF_1 ;
+""")
+
+t.expand_toolset("jamfile.jam")
+
+t.run_build_system()
+t.expect_addition(["bin/$toolset/debug/a.exe",
+ "bin/$toolset/debug/b.exe",
+ "bin/$toolset/release/c.exe"])
+
+t.rm("bin")
+
+
+# Test for issue BB60.
+
+t.write("test.cpp", """
+#include "header.h"
+int main() {}
+""")
+
+t.write("jamfile.jam", """
+project : requirements <toolset>$toolset:<include>foo ;
+exe test : test.cpp : <toolset>$toolset ;
+""")
+
+t.expand_toolset("jamfile.jam")
+t.write("foo/header.h", "\n")
+t.write("jamroot.jam", "")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/test.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/explicit.py b/tools/build/v2/test/explicit.py
new file mode 100644
index 0000000000..43137402b4
--- /dev/null
+++ b/tools/build/v2/test/explicit.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+exe hello : hello.cpp ;
+exe hello2 : hello.cpp ;
+explicit hello2 ;
+""")
+
+t.write("hello.cpp", """
+int main() {}
+""")
+
+t.run_build_system()
+t.ignore("*.tds")
+t.expect_addition(BoostBuild.List("bin/$toolset/debug/hello") * \
+ [".exe", ".obj"])
+t.expect_nothing_more()
+
+t.run_build_system("hello2")
+t.expect_addition("bin/$toolset/debug/hello2.exe")
+
+t.rm(".")
+
+
+# Test that 'explicit' used in a helper rule applies to the current project, and
+# not to the Jamfile where the helper rule is defined.
+t.write("jamroot.jam", """
+rule myinstall ( name : target )
+{
+ install $(name)-bin : $(target) ;
+ explicit $(name)-bin ;
+ alias $(name) : $(name)-bin ;
+}
+""")
+
+t.write("sub/a.cpp", """
+""")
+
+t.write("sub/jamfile.jam", """
+myinstall dist : a.cpp ;
+""")
+
+t.run_build_system(subdir="sub")
+t.expect_addition("sub/dist-bin/a.cpp")
+
+t.rm("sub/dist-bin")
+
+t.write("sub/jamfile.jam", """
+myinstall dist : a.cpp ;
+explicit dist ;
+""")
+
+t.run_build_system(subdir="sub")
+t.expect_nothing_more()
+
+t.cleanup()
diff --git a/tools/build/v2/test/file_name_handling.py b/tools/build/v2/test/file_name_handling.py
new file mode 100755
index 0000000000..8e59e6821a
--- /dev/null
+++ b/tools/build/v2/test/file_name_handling.py
@@ -0,0 +1,255 @@
+#!/usr/bin/python
+
+# Copyright 2008 Jurko Gospodnetic
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests Boost Jam & Boost Build's source & target file name handling. Originally
+# added as a regression test for a bug causing versions included in the Boost
+# library 1.35 release (and earlier) not handling Windows short file names
+# correctly. Also tests handling target file names containing spaces.
+
+# Implementation notes:
+#
+# We expect Boost Jam to automatically update the 'all' target when no target
+# has been explicitly specified on the command line.
+#
+# Windows short & long file names can not be matched until the file in
+# question actually exists so we need to create the file before running Boost
+# Jam.
+#
+# Currently Windows short file names are hardcoded but in case this proves
+# insufficient we should use the GetShortPathName() Windows API to get the
+# correct short file for a given long file name.
+# (30.04.2008.) (Jurko)
+
+import BoostBuild
+import os
+import time
+
+
+################################################################################
+#
+# prepare_file()
+# --------------
+#
+################################################################################
+
+def prepare_file(tester, target_name, age_in_seconds=0):
+ """Prepares a new file with the given name, optionally setting its last
+ access and modification timestamps to the given number of seconds in the
+ history.
+ """
+ tester.write( target_name, "Original file content." )
+ if ( ( not age_in_seconds is None ) and ( age_in_seconds != 0 ) ):
+ t = time.time() - age_in_seconds
+ os.utime( tester.native_file_name( target_name ), ( t, t ) )
+
+
+################################################################################
+#
+# test_simple_file_names()
+# ------------------------
+#
+################################################################################
+
+def test_simple_file_names():
+ """Runs simple file name handling that is not expected to fail anywhere. Not
+ really needed for regular testing but the test is really fast and its
+ content may be used for comparing to other more complex test functions in
+ this module which test the same system but with some potentially more
+ problematic file names.
+ """
+ t = BoostBuild.Tester(pass_toolset=0)
+
+ prepare_file(t, "source.txt" )
+ prepare_file(t, "target.txt" , 120)
+ prepare_file(t, "target_noupdate.txt", 240)
+
+ t.write("testScript.jam", """
+actions create-file
+{
+ echo "Modified file content ($(1:E=""))."> "$(1:E="")"
+}
+
+DEPENDS all : standaloneTarget.txt ;
+create-file standaloneTarget.txt : all ;
+
+DEPENDS all : target.txt ;
+DEPENDS target.txt : source.txt ;
+create-file target.txt ;
+
+NOUPDATE target_noupdate.txt ;
+DEPENDS all : target_noupdate.txt ;
+DEPENDS target_noupdate.txt : source.txt ;
+create-file target_noupdate.txt ;
+
+create-file shouldNotBeCreated1 ;
+create-file shouldNotBeCreated2 ;
+create-file shouldNotBeCreated3 ;
+""")
+
+ t.run_build_system("-ftestScript.jam")
+ t.expect_addition("standaloneTarget.txt")
+ t.expect_modification("target.txt")
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_short_file_name_with_action()
+# ----------------------------------
+#
+################################################################################
+
+def test_short_file_name_with_action():
+ """Tests how Boost Jam handles the case when a Windows short file name is
+ passed to a Boost Jam action.
+ """
+ if ( not BoostBuild.windows ):
+ return
+
+ t = BoostBuild.Tester(pass_toolset=0)
+
+ long_file_name1 = "1__target that should be rebuilt.txt"
+ long_file_name2 = "2__target that should be rebuilt.txt"
+ short_file_name2 = "2__tar~1.txt"
+
+ prepare_file(t, long_file_name1)
+ prepare_file(t, long_file_name2)
+
+ t.write("testScript.jam", """
+actions create-file
+{
+ echo Modified file content ($(1:E="")).> "$(1:E="")"
+}
+
+ALWAYS "%(long_file_name1)s" ;
+DEPENDS all : "%(long_file_name1)s" ;
+create-file "%(long_file_name1)s" ;
+
+ALWAYS "%(long_file_name2)s" ;
+DEPENDS all : "%(long_file_name2)s" ;
+create-file "%(short_file_name2)s" ;
+""" % {'long_file_name1': long_file_name1,
+ 'long_file_name2' : long_file_name2,
+ 'short_file_name2' : short_file_name2})
+
+ t.run_build_system("-ftestScript.jam")
+ t.expect_modification(long_file_name1)
+ t.expect_modification(long_file_name2)
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_short_file_name_with_ALWAYS()
+# ----------------------------------
+#
+################################################################################
+
+def test_short_file_name_with_ALWAYS():
+ """Tests how Boost Jam handles the case when a Windows short file name is
+ passed to the builtin ALWAYS rule.
+ """
+ if ( not BoostBuild.windows ):
+ return
+
+ t = BoostBuild.Tester(pass_toolset=0)
+
+ long_file_name1 = "1__target that should be rebuilt.txt"
+ long_file_name2 = "2__target that should be rebuilt.txt"
+ short_file_name2 = "2__tar~1.txt"
+
+ prepare_file(t, long_file_name1)
+ prepare_file(t, long_file_name2)
+
+ t.write("testScript.jam", """
+actions create-file
+{
+ echo Modified file content ($(1:E="")).> "$(1:E="")"
+}
+
+ALWAYS "%(long_file_name1)s" ;
+DEPENDS all : "%(long_file_name1)s" ;
+create-file "%(long_file_name1)s" ;
+
+ALWAYS "%(short_file_name2)s" ;
+DEPENDS all : "%(long_file_name2)s" ;
+create-file "%(long_file_name2)s" ;
+""" % {'long_file_name1': long_file_name1,
+ 'long_file_name2' : long_file_name2,
+ 'short_file_name2' : short_file_name2})
+
+ t.run_build_system("-ftestScript.jam")
+ t.expect_modification(long_file_name1)
+ t.expect_modification(long_file_name2)
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_short_file_name_with_NOUPDATE()
+# ------------------------------------
+#
+################################################################################
+
+def test_short_file_name_with_NOUPDATE():
+ """Tests how Boost Jam handles the case when a Windows short file name is
+ passed to the builtin NOUPDATE rule.
+ """
+ if ( not BoostBuild.windows ):
+ return
+
+ t = BoostBuild.Tester(pass_toolset=0)
+
+ long_file_name1 = "1__target that should be rebuilt.txt"
+ long_file_name2 = "2__target that should not be rebuilt.txt"
+ short_file_name2 = "2__tar~1.txt"
+
+ prepare_file(t, "source.txt" )
+ prepare_file(t, long_file_name1, 120)
+ prepare_file(t, long_file_name2, 120)
+
+ t.write("testScript.jam", """
+actions create-file
+{
+ echo Modified file content ($(1:E="")).> "$(1:E="")"
+}
+
+DEPENDS all : "%(long_file_name1)s" ;
+DEPENDS "%(long_file_name1)s" : source.txt ;
+create-file "%(long_file_name1)s" ;
+
+NOUPDATE "%(short_file_name2)s" ;
+DEPENDS all : "%(long_file_name2)s" ;
+DEPENDS "%(long_file_name2)s" : source.txt ;
+create-file "%(long_file_name2)s" ;
+""" % {'long_file_name1': long_file_name1,
+ 'long_file_name2' : long_file_name2,
+ 'short_file_name2' : short_file_name2})
+
+ t.run_build_system("-ftestScript.jam")
+ t.expect_modification(long_file_name1)
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+test_simple_file_names()
+test_short_file_name_with_action()
+test_short_file_name_with_ALWAYS()
+test_short_file_name_with_NOUPDATE()
diff --git a/tools/build/v2/test/free_features_request.py b/tools/build/v2/test/free_features_request.py
new file mode 100644
index 0000000000..108072758a
--- /dev/null
+++ b/tools/build/v2/test/free_features_request.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2007.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests that a free feature specified on the command line applies to all targets
+# ever built.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+exe hello : hello.cpp foo ;
+lib foo : foo.cpp ;
+""")
+
+t.write("hello.cpp", """
+extern void foo();
+#ifdef FOO
+int main() { foo(); }
+#endif
+""")
+
+t.write("foo.cpp", """
+#ifdef FOO
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {}
+#endif
+""")
+
+# If FOO is not defined when compiling the 'foo' target, we will get a link
+# error at this point.
+t.run_build_system("hello define=FOO")
+
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/gcc_runtime.py b/tools/build/v2/test/gcc_runtime.py
new file mode 100644
index 0000000000..696b6a5fda
--- /dev/null
+++ b/tools/build/v2/test/gcc_runtime.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests that on gcc, we correctly report problem when static runtime is
+# requested for building a shared library.
+
+import BoostBuild
+import string
+
+t = BoostBuild.Tester()
+
+# Create the needed files.
+t.write("jamroot.jam", "")
+
+t.write("jamfile.jam", """
+lib hello : hello.cpp ;
+""")
+
+t.write("hello.cpp", """
+int main() { }
+""")
+
+t.run_build_system("runtime-link=static")
+t.fail_test(string.find(t.stdout(),
+ "On gcc, DLL can't be build with '<runtime-link>static'") == -1)
+
+t.run_build_system("link=static runtime-link=static")
+t.expect_addition("bin/$toolset/debug/link-static/runtime-link-static/hello.lib")
+
+t.cleanup()
diff --git a/tools/build/v2/test/generator_selection.py b/tools/build/v2/test/generator_selection.py
new file mode 100755
index 0000000000..e10cb0d3b2
--- /dev/null
+++ b/tools/build/v2/test/generator_selection.py
@@ -0,0 +1,140 @@
+#!/usr/bin/python
+
+# Copyright 2008 Jurko Gospodnetic
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests that generators get selected correctly.
+
+import BoostBuild
+
+
+################################################################################
+#
+# test_generator_added_after_already_building_a_target_of_its_target_type()
+# -------------------------------------------------------------------------
+#
+################################################################################
+
+def test_generator_added_after_already_building_a_target_of_its_target_type():
+ """Regression test for a Boost Build bug causing it to not use a generator
+ if it got added after already building a targer of its target type.
+ """
+
+ t = BoostBuild.Tester()
+
+ t.write("dummy.cpp", "void f() {}\n")
+
+ t.write("jamroot.jam", """
+# Building this dummy target must not cause a later defined CPP target type
+# generator not to be recognized as viable.
+obj dummy : dummy.cpp ;
+alias the-other-obj : Other//other-obj ;
+""")
+
+ t.write("Other/source.extension", "A dummy source file.")
+
+ t.write("Other/mygen.jam", """
+import generators ;
+import os ;
+import type ;
+type.register MY_TYPE : extension ;
+generators.register-standard mygen.generate-a-cpp-file : MY_TYPE : CPP ;
+rule generate-a-cpp-file { ECHO Generating a CPP file... ; }
+if [ os.name ] = NT
+{
+ actions generate-a-cpp-file { echo void g() {} > "$(<)" }
+}
+else
+{
+ actions generate-a-cpp-file { echo "void g() {}" > "$(<)" }
+}
+""")
+
+ t.write("Other/mygen.py", """
+import b2.build.generators as generators
+import b2.build.type as type
+
+from b2.manager import get_manager
+
+import os
+
+
+type.register('MY_TYPE', ['extension'])
+generators.register_standard('mygen.generate-a-cpp-file', ['MY_TYPE'], ['CPP'])
+if os.name == 'nt':
+ action = 'echo void g() {} > "$(<)"'
+else:
+ action = 'echo "void g() {}" > "$(<)"'
+def f(*args):
+ print "Generating a CPP file..."
+
+get_manager().engine().register_action("mygen.generate-a-cpp-file",
+ action, function=f)
+""")
+
+ t.write("Other/jamfile.jam", """
+import mygen ;
+obj other-obj : source.extension ;
+""")
+
+ t.run_build_system()
+ t.expect_output_line("Generating a CPP file...")
+ t.expect_addition("bin/$toolset/debug/dummy.obj")
+ t.expect_addition("Other/bin/$toolset/debug/other-obj.obj")
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_using_a_derived_source_type_created_after_generator_already_used()
+# -----------------------------------------------------------------------
+#
+################################################################################
+
+def test_using_a_derived_source_type_created_after_generator_already_used():
+ """Regression test for a Boost Build bug causing it to not use a generator
+ with a source type derived from one of the generator's sources but created
+ only after already using the generateor.
+ """
+
+ t = BoostBuild.Tester()
+
+ t.write("dummy.cpp", "void f() {}\n")
+
+ t.write("jamroot.jam", """
+# Building this dummy target must not cause a later defined UNGA_CPP target type
+# not to be recognized as a viable source type for building OBJ targets.
+obj dummy : dummy.cpp ;
+alias the-test-output : Other//other-obj ;
+""")
+
+ t.write("Other/source.unga_cpp", "void g() {}\n")
+
+ t.write("Other/jamfile.jam", """
+import type ;
+type.register UNGA_CPP : unga_cpp : CPP ;
+# We are careful not to do anything between defining our new UNGA_CPP target
+# type and using the CPP --> OBJ generator that could potentially cover the
+# Boost Build bug by clearing its internal viable source target type state.
+obj other-obj : source.unga_cpp ;
+""")
+
+ t.run_build_system()
+ t.expect_addition("bin/$toolset/debug/dummy.obj")
+ t.expect_addition("Other/bin/$toolset/debug/other-obj.obj")
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+test_generator_added_after_already_building_a_target_of_its_target_type()
+test_using_a_derived_source_type_created_after_generator_already_used()
diff --git a/tools/build/v2/test/generators-test/a.cpp b/tools/build/v2/test/generators-test/a.cpp
new file mode 100644
index 0000000000..7ef7f6872e
--- /dev/null
+++ b/tools/build/v2/test/generators-test/a.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+int foo();
+int bar();
+
+void z1(), z2();
+
+int main()
+{
+ foo();
+ bar();
+ z1();
+ z2();
+ return 0;
+}
diff --git a/tools/build/v2/test/generators-test/b.cxx b/tools/build/v2/test/generators-test/b.cxx
new file mode 100644
index 0000000000..85b41d3f9d
--- /dev/null
+++ b/tools/build/v2/test/generators-test/b.cxx
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+int foo() { return 0; }
diff --git a/tools/build/v2/test/generators-test/c.tui b/tools/build/v2/test/generators-test/c.tui
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/test/generators-test/c.tui
diff --git a/tools/build/v2/test/generators-test/d.wd b/tools/build/v2/test/generators-test/d.wd
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/test/generators-test/d.wd
diff --git a/tools/build/v2/test/generators-test/e.cpp b/tools/build/v2/test/generators-test/e.cpp
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/generators-test/e.cpp
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/generators-test/extra.jam b/tools/build/v2/test/generators-test/extra.jam
new file mode 100644
index 0000000000..d3500c73ca
--- /dev/null
+++ b/tools/build/v2/test/generators-test/extra.jam
@@ -0,0 +1,120 @@
+# Copyright 2002, 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+import type ;
+import generators ;
+import "class" : new ;
+import common ;
+
+type.register WHL : whl ;
+type.register DLP : dlp ;
+type.register WHL_LR0 : lr0 ;
+type.register WD : wd ;
+
+generators.register-standard extra.whale : WHL : CPP WHL_LR0 H H(%_symbols) ;
+generators.register-standard extra.dolphin : DLP : CPP ;
+generators.register-standard extra.wd : WD : WHL(%_parser) DLP(%_lexer) ;
+
+class wd-to-cpp : generator
+{
+ rule __init__ ( * : * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) ;
+ }
+
+ rule run ( project name ? : property-set : source )
+ {
+ local new-sources ;
+ if ! [ $(source).type ] in WHL DLP
+ {
+ local r1 = [ generators.construct $(project) $(name)
+ : WHL : $(property-set) : $(source) ] ;
+ local r2 = [ generators.construct $(project) $(name)
+ : DLP : $(property-set) : $(source) ] ;
+
+ new-sources = [ sequence.unique $(r1[2-]) $(r2[2-]) ] ;
+ }
+ else
+ {
+ new-sources = $(source) ;
+ }
+
+ local result ;
+ for local i in $(new-sources)
+ {
+ local t = [ generators.construct $(project) $(name) : CPP
+ : $(property-set) : $(i) ] ;
+ result += $(t[2-]) ;
+ }
+ return $(result) ;
+ }
+}
+generators.override extra.wd-to-cpp : extra.whale ;
+generators.override extra.wd-to-cpp : extra.dolphin ;
+
+generators.register [ new wd-to-cpp extra.wd-to-cpp : : CPP ] ;
+
+rule whale ( targets * : sources * : properties * )
+{
+}
+
+TOUCH = [ common.file-touch-command ] ;
+
+actions whale
+{
+ echo "Whale consuming " $(>)
+ $(TOUCH) $(<[1])
+ $(TOUCH) $(<[2])
+ $(TOUCH) $(<[3])
+ $(TOUCH) $(<[4])
+}
+
+rule dolphin ( targets * : source * : properties * )
+{
+}
+
+actions dolphin
+{
+ echo "Dolphin consuming" $(>)
+ $(TOUCH) $(<)
+}
+
+rule wd ( targets * : source * : properties * )
+{
+}
+
+actions wd
+{
+ echo "WD consuming" $(>)
+ $(TOUCH) $(<[1])
+ $(TOUCH) $(<[2])
+}
+
+rule x ( target * : source * : properties * )
+{
+}
+
+
+actions x
+{
+ echo "X: source is " $(>)
+ $(TOUCH) $(<[1])
+}
+
+rule x_pro ( target * : source * : properties * )
+{
+}
+
+
+actions x_pro
+{
+ echo "X_PRO: source is " $(>)
+ $(TOUCH) $(<[1])
+ $(TOUCH) $(<[2])
+}
+
+
+
+
diff --git a/tools/build/v2/test/generators-test/jamfile.jam b/tools/build/v2/test/generators-test/jamfile.jam
new file mode 100644
index 0000000000..e5d9242d35
--- /dev/null
+++ b/tools/build/v2/test/generators-test/jamfile.jam
@@ -0,0 +1,19 @@
+# Copyright 2002, 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project
+ # This is needed to supress gcc warning on flex output, which otherwise
+ # results in test failure
+ : requirements <define>YY_NO_UNPUT
+ ;
+
+exe a : a.cpp b.cxx obj_1 obj_2 c.tui d.wd x.l y.x_pro lib//auxilliary ;
+# This should not cause second compilation of a.cpp
+exe f : a.cpp b.cxx obj_1 obj_2 lib//auxilliary ;
+
+obj obj_1 : z.cpp : <define>SELECT=1 ;
+obj obj_2 : z.cpp : <define>SELECT=2 ;
+
+nm-exe e : e.cpp ;
diff --git a/tools/build/v2/test/generators-test/jamroot.jam b/tools/build/v2/test/generators-test/jamroot.jam
new file mode 100644
index 0000000000..abe08bc438
--- /dev/null
+++ b/tools/build/v2/test/generators-test/jamroot.jam
@@ -0,0 +1,95 @@
+# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+import "class" : new ;
+
+import lex ;
+import qt ;
+import extra ;
+
+import type ;
+
+type.register tUI : tui ;
+type.register tUIC_H ;
+type.set-generated-target-suffix tUIC_H : : h ;
+
+type.register X1 : x1 ;
+type.register X2 : x2 ;
+type.register X_PRO : x_pro ;
+
+import generators ;
+
+generators.register-standard qt.uic : tUI tUIC_H : CPP ;
+generators.register-standard qt.uic-h : tUI : tUIC_H ;
+
+# That's an interesting example. Currently, X_PRO will be processed
+# twice.
+generators.register-standard extra.x : X1 X2 : CPP ;
+generators.register-standard extra.x_pro : X_PRO : X1 X2 ;
+
+# The point of this setup of to implement this functionality
+# "When main target type is EST_EXE, build OBJ from CPP-MARKED, not
+# for anything else (like CPP)
+# Unfortunately, this does not really works.
+
+#if $(no-var) {
+import nm ;
+
+type.register CPP_MARKED : marked_cpp : CPP ;
+type.register POSITIONS : positions ;
+type.register NM.TARGET.CPP : target_cpp : CPP ;
+type.register NM_EXE : : EXE ;
+
+generators.register-standard nm.target-source : CPP_MARKED : NM.TARGET.CPP ;
+generators.register-standard nm.cpp-mark : CPP : CPP_MARKED POSITIONS ;
+
+class nm::target::cpp-obj-generator : generator
+{
+ rule __init__ ( )
+ {
+ generator.__init__ nm.target-obj : NM.TARGET.CPP : OBJ ;
+ }
+
+ rule requirements ( )
+ {
+ return <main-target-type>NM_EXE ;
+ }
+
+ # Consider: it it OK to ignore all other generated targets except for the first?
+ rule run ( project name ? : properties * : source : multiple ? )
+ {
+ if [ $(source).type ] = CPP {
+ local converted = [ generators.construct $(project) : NM.TARGET.CPP : $(properties) : $(source) ] ;
+ if $(converted[1])
+ {
+ local result = [ generators.construct $(project) : OBJ : $(properties) : $(converted[2]) ] ;
+ return $(result) ;
+ }
+ else
+ {
+ return ;
+ }
+ }
+ else
+ {
+ return ;
+ }
+ }
+}
+
+generators.register [ new nm::target::cpp-obj-generator ] ;
+
+generators.override nm.target-obj : all ;
+
+#}
+
+
+
+
+
+
+
+
+
diff --git a/tools/build/v2/test/generators-test/lex.jam b/tools/build/v2/test/generators-test/lex.jam
new file mode 100644
index 0000000000..4ae5422e9b
--- /dev/null
+++ b/tools/build/v2/test/generators-test/lex.jam
@@ -0,0 +1,26 @@
+# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import type ;
+import generators ;
+import feature ;
+import property ;
+import print ;
+
+type.register LEX : l ;
+
+generators.register-standard lex.lex : LEX : C ;
+
+rule lex ( targets * : sources * : properties * )
+{
+ print.output $(<) ;
+ # Need to supress SunCC's warning about empty source
+ # file.
+ print.text "void foo() {}
+" ;
+}
+
+actions lex
+{
+}
diff --git a/tools/build/v2/test/generators-test/lib/c.cpp b/tools/build/v2/test/generators-test/lib/c.cpp
new file mode 100644
index 0000000000..f32b624048
--- /dev/null
+++ b/tools/build/v2/test/generators-test/lib/c.cpp
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+int bar() { return 0; }
diff --git a/tools/build/v2/test/generators-test/lib/jamfile.jam b/tools/build/v2/test/generators-test/lib/jamfile.jam
new file mode 100644
index 0000000000..48ff90fd21
--- /dev/null
+++ b/tools/build/v2/test/generators-test/lib/jamfile.jam
@@ -0,0 +1,9 @@
+# Copyright 2002 Dave Abrahams
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+static-lib auxilliary : c.cpp ;
+
+lib auxilliary2 : c.cpp ;
diff --git a/tools/build/v2/test/generators-test/nm.jam b/tools/build/v2/test/generators-test/nm.jam
new file mode 100644
index 0000000000..0b1ad984a0
--- /dev/null
+++ b/tools/build/v2/test/generators-test/nm.jam
@@ -0,0 +1,43 @@
+# Copyright 2002, 2003 Dave Abrahams
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import modules ;
+import common ;
+
+TOUCH = [ common.file-touch-command ] ;
+
+rule target-source ( targets * : sources * : properties * )
+{
+ if [ modules.peek : NT ]
+ {
+ main on $(<) = "int main() { return 0; }" ;
+ }
+ else
+ {
+ main on $(<) = "\"int main() { return 0; }\"" ;
+ }
+}
+
+actions target-source
+{
+ echo "NM target source consuming " $(>)
+ echo $(main) > $(<)
+}
+
+rule cpp-mark ( targets * : sources * : properties * )
+{
+}
+
+actions cpp-mark
+{
+ echo "CPP-MARK consuming " $(>)
+ $(TOUCH) $(<[1])
+ $(TOUCH) $(<[2])
+}
+
+
+
+
+
diff --git a/tools/build/v2/test/generators-test/qt.jam b/tools/build/v2/test/generators-test/qt.jam
new file mode 100644
index 0000000000..ec0ee33749
--- /dev/null
+++ b/tools/build/v2/test/generators-test/qt.jam
@@ -0,0 +1,34 @@
+# Copyright 2002 Dave Abrahams
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import modules ;
+
+if [ modules.peek : NT ]
+{
+ comment = // ;
+}
+else
+{
+ comment = \"//\" ;
+}
+
+rule uic ( target : sources * : properties * )
+{
+ comment on $(<) = $(comment) ;
+}
+rule uic-h ( target : sources * : properties * )
+{
+ comment on $(<) = $(comment) ;
+}
+
+actions uic
+{
+ echo $(comment) $(>) > $(<)
+}
+
+actions uic-h
+{
+ echo $(comment) $(>) > $(<)
+}
diff --git a/tools/build/v2/test/generators-test/x.l b/tools/build/v2/test/generators-test/x.l
new file mode 100644
index 0000000000..16beb4d9b8
--- /dev/null
+++ b/tools/build/v2/test/generators-test/x.l
@@ -0,0 +1,5 @@
+%option noyywrap
+
+%%
+
+%% \ No newline at end of file
diff --git a/tools/build/v2/test/generators-test/y.x_pro b/tools/build/v2/test/generators-test/y.x_pro
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/test/generators-test/y.x_pro
diff --git a/tools/build/v2/test/generators-test/z.cpp b/tools/build/v2/test/generators-test/z.cpp
new file mode 100644
index 0000000000..7826c1ca77
--- /dev/null
+++ b/tools/build/v2/test/generators-test/z.cpp
@@ -0,0 +1,16 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#if SELECT == 1
+void z1() {}
+#elif SELECT == 2
+void z2() {}
+#else
+#error Invlid value of SELECT
+#endif
diff --git a/tools/build/v2/test/generators_test.py b/tools/build/v2/test/generators_test.py
new file mode 100644
index 0000000000..549a8e0ace
--- /dev/null
+++ b/tools/build/v2/test/generators_test.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree("generators-test")
+
+t.run_build_system()
+
+t.expect_addition( "bin/$toolset/debug/" * BoostBuild.List( "a.obj b.obj c.h "
+ + "c.cpp c.obj d_parser.whl d_lexer.dlp d_parser.cpp d_lexer.cpp "
+ + "d_parser.lr0 d_parser.h d_parser_symbols.h x.c x.obj y.x1 y.x2 y.cpp "
+ + "y.obj e.marked_cpp e.positions e.target_cpp e.obj"))
+t.expect_addition("bin/$toolset/debug/a.exe")
+t.expect_addition(["lib/bin/$toolset/debug/c.obj",
+ "lib/bin/$toolset/debug/auxilliary.lib"])
+
+t.run_build_system(subdir='lib')
+t.expect_addition(["lib/bin/$toolset/debug/auxilliary2.dll"])
+
+t.run_build_system(subdir='lib', extra_args="link=static")
+t.expect_addition(["lib/bin/$toolset/debug/link-static/auxilliary2.lib"])
+
+t.cleanup()
diff --git a/tools/build/v2/test/implicit_dependency.py b/tools/build/v2/test/implicit_dependency.py
new file mode 100644
index 0000000000..91e2644c8c
--- /dev/null
+++ b/tools/build/v2/test/implicit_dependency.py
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the <implicit-dependency> is respected even if the target referred to is
+# not built itself, but only referred to by <implicit-dependency>.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+make a.h : : gen-header ;
+explicit a.h ;
+
+exe hello : hello.cpp : <implicit-dependency>a.h ;
+
+import os ;
+if [ os.name ] = NT
+{
+ actions gen-header
+ {
+ echo int i; > $(<)
+ }
+}
+else
+{
+ actions gen-header
+ {
+ echo "int i;" > $(<)
+ }
+}
+""")
+
+t.write("hello.cpp", """
+#include "a.h"
+int main() { return i; }
+""")
+
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+t.rm("bin")
+
+t.write("jamroot.jam", """
+make dir/a.h : : gen-header ;
+explicit dir/a.h ;
+
+exe hello : hello.cpp : <implicit-dependency>dir/a.h ;
+
+import os ;
+if [ os.name ] = NT
+{
+ actions gen-header
+ {
+ echo int i; > $(<)
+ }
+}
+else
+{
+ actions gen-header
+ {
+ echo "int i;" > $(<)
+ }
+}
+""")
+
+t.write("hello.cpp", """
+#include "dir/a.h"
+int main() { return i; }
+""")
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/indirect_conditional.py b/tools/build/v2/test/indirect_conditional.py
new file mode 100644
index 0000000000..6e9c181417
--- /dev/null
+++ b/tools/build/v2/test/indirect_conditional.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+exe a1 : a1.cpp : <conditional>@a1-rule ;
+
+rule a1-rule ( properties * )
+{
+ if <variant>debug in $(properties)
+ {
+ return <define>OK ;
+ }
+}
+
+exe a2 : a2.cpp : <conditional>@$(__name__).a2-rule
+ <variant>debug:<optimization>speed ;
+
+rule a2-rule ( properties * )
+{
+ if <optimization>speed in $(properties)
+ {
+ return <define>OK ;
+ }
+}
+
+exe a3 : a3.cpp : <conditional>@$(__name__).a3-rule-1
+ <conditional>@$(__name__).a3-rule-2 ;
+
+rule a3-rule-1 ( properties * )
+{
+ if <optimization>speed in $(properties)
+ {
+ return <define>OK ;
+ }
+}
+
+rule a3-rule-2 ( properties * )
+{
+ if <variant>debug in $(properties)
+ {
+ return <optimization>speed ;
+ }
+}
+""")
+
+t.write("a1.cpp", """
+#ifdef OK
+int main() {}
+#endif
+""")
+
+t.write("a2.cpp", """
+#ifdef OK
+int main() {}
+#endif
+""")
+
+t.write("a3.cpp", """
+#ifdef OK
+int main() {}
+#endif
+""")
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/a1.exe")
+t.expect_addition("bin/$toolset/debug/optimization-speed/a2.exe")
+t.expect_addition("bin/$toolset/debug/optimization-speed/a3.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/inherit_toolset.py b/tools/build/v2/test/inherit_toolset.py
new file mode 100644
index 0000000000..ca050d2c4f
--- /dev/null
+++ b/tools/build/v2/test/inherit_toolset.py
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import string
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("a.cpp", """
+""")
+
+t.write("yfc1.jam", """
+import feature ;
+import generators ;
+
+feature.extend toolset : yfc1 ;
+rule init ( ) { }
+
+generators.register-standard yfc1.compile : CPP : OBJ : <toolset>yfc1 ;
+generators.register-standard yfc1.link : OBJ : EXE : <toolset>yfc1 ;
+
+actions compile { yfc1-compile }
+actions link { yfc1-link }
+""")
+
+t.write("yfc2.jam", """
+import feature ;
+import toolset ;
+
+feature.extend toolset : yfc2 ;
+toolset.inherit yfc2 : yfc1 ;
+rule init ( ) { }
+
+actions link { yfc2-link }
+""")
+
+t.write("jamfile.jam", """
+exe a : a.cpp ;
+""")
+
+t.write("jamroot.jam", """
+using yfc1 ;
+""")
+
+t.run_build_system("-n -d2 yfc1")
+t.fail_test(string.find(t.stdout(), "yfc1-link") == -1)
+
+# Make sure we do not have to explicitly 'use' yfc1.
+t.write("jamroot.jam", """
+using yfc2 ;
+""")
+
+t.run_build_system("-n -d2 yfc2")
+t.fail_test(string.find(t.stdout(), "yfc2-link") == -1)
+
+t.cleanup()
diff --git a/tools/build/v2/test/inherited_dependency.py b/tools/build/v2/test/inherited_dependency.py
new file mode 100755
index 0000000000..7d4895e07a
--- /dev/null
+++ b/tools/build/v2/test/inherited_dependency.py
@@ -0,0 +1,237 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2008 Steven Watanabe
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt) or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+tester = BoostBuild.Tester()
+
+
+################################################################################
+#
+# Test without giving the project an explicit id.
+#
+################################################################################
+
+tester.write("jamroot.jam", """
+lib test : test.cpp ;
+project : requirements <library>test ;
+build-project a ;
+""")
+
+tester.write("test.cpp", """
+#ifdef _WIN32
+ __declspec(dllexport)
+#endif
+void foo() {}
+""")
+
+tester.write("a/test1.cpp", """
+int main() {}
+""")
+
+tester.write("a/jamfile.jam", """
+exe test1 : test1.cpp ;
+""")
+
+tester.run_build_system()
+
+tester.expect_addition("bin/$toolset/debug/test.obj")
+tester.expect_addition("a/bin/$toolset/debug/test1.exe")
+
+tester.rm("bin")
+tester.rm("a/bin")
+
+
+################################################################################
+#
+# Run the same test from the "a" directory.
+#
+################################################################################
+
+tester.run_build_system(subdir="a")
+
+tester.expect_addition("bin/$toolset/debug/test.obj")
+tester.expect_addition("a/bin/$toolset/debug/test1.exe")
+
+tester.rm("bin")
+tester.rm("a/bin")
+
+
+################################################################################
+#
+# This time, do give the project an id.
+#
+################################################################################
+
+tester.write("jamroot.jam", """
+lib test : test.cpp ;
+project test_project : requirements <library>test ;
+build-project a ;
+""")
+
+tester.run_build_system()
+
+tester.expect_addition("bin/$toolset/debug/test.obj")
+tester.expect_addition("a/bin/$toolset/debug/test1.exe")
+
+tester.rm("bin")
+tester.rm("a/bin")
+
+
+################################################################################
+#
+# Now, give the project an id in its attributes.
+#
+################################################################################
+
+tester.write("jamroot.jam", """
+lib test : test.cpp ;
+project : id test_project : requirements <library>test ;
+build-project a ;
+""")
+
+tester.run_build_system()
+
+tester.expect_addition("bin/$toolset/debug/test.obj")
+tester.expect_addition("a/bin/$toolset/debug/test1.exe")
+
+tester.rm("bin")
+tester.rm("a/bin")
+
+
+################################################################################
+#
+# Give the project an id in both ways at once.
+#
+################################################################################
+
+tester.write("jamroot.jam", """
+lib test : test.cpp ;
+project test_project1 : id test_project : requirements <library>test ;
+build-project a ;
+""")
+
+tester.run_build_system()
+
+tester.expect_addition("bin/$toolset/debug/test.obj")
+tester.expect_addition("a/bin/$toolset/debug/test1.exe")
+
+tester.rm("bin")
+tester.rm("a/bin")
+
+
+################################################################################
+#
+# Test an absolute path in native format.
+#
+################################################################################
+
+tester.write("jamroot.jam", """
+import path ;
+path-constant here : . ;
+current-location = [ path.native [ path.root [ path.make $(here) ] [ path.pwd ]
+ ] ] ;
+project test : requirements <source>$(current-location)/a/test1.cpp ;
+exe test : test.cpp ;
+""")
+
+tester.run_build_system()
+tester.expect_addition("bin/$toolset/debug/test.exe")
+
+tester.rm("bin")
+tester.rm("a/bin")
+
+
+################################################################################
+#
+# Test an absolute path in canonical format.
+#
+################################################################################
+
+tester.write("jamroot.jam", """
+import path ;
+path-constant here : . ;
+current-location = [ path.root [ path.make $(here) ] [ path.pwd ] ] ;
+project test : requirements <source>$(current-location)/a/test1.cpp ;
+exe test : test.cpp ;
+""")
+
+tester.run_build_system()
+tester.expect_addition("bin/$toolset/debug/test.exe")
+
+tester.rm("bin")
+tester.rm("a/bin")
+
+
+################################################################################
+#
+# Test dependency properties (e.g. <source>) whose targets are specified using a
+# relative path.
+#
+################################################################################
+
+# Use jamroot.jam rather than jamfile.jam to avoid inheriting the <source> from
+# the parent as that would would make test3 a source of itself.
+tester.write("b/jamroot.jam", """
+obj test3 : test3.cpp ;
+""")
+
+tester.write("b/test3.cpp", """
+void bar() {}
+""")
+
+tester.write("jamroot.jam", """
+project test : requirements <source>b//test3 ;
+build-project a ;
+""")
+
+tester.write("a/jamfile.jam", """
+exe test : test1.cpp ;
+""")
+
+tester.write("a/test1.cpp", """
+void bar();
+int main() { bar(); }
+""")
+
+tester.run_build_system()
+tester.expect_addition("b/bin/$toolset/debug/test3.obj")
+tester.expect_addition("a/bin/$toolset/debug/test.exe")
+
+tester.rm("bin")
+tester.rm("a")
+tester.rm("jamroot.jam")
+tester.rm("test.cpp")
+
+
+################################################################################
+#
+# Test that source-location is respected.
+#
+################################################################################
+
+tester.write("build/jamroot.jam", """
+project : requirements <source>test.cpp : source-location ../src ;
+""")
+
+tester.write("src/test.cpp", """
+int main() {}
+""")
+
+tester.write("build/a/jamfile.jam", """
+project : source-location ../../a_src ;
+exe test : test1.cpp ;
+""")
+
+tester.write("a_src/test1.cpp", """
+""")
+
+tester.run_build_system(subdir="build/a")
+tester.expect_addition("build/a/bin/$toolset/debug/test.exe")
+
+tester.cleanup()
diff --git a/tools/build/v2/test/inline.py b/tools/build/v2/test/inline.py
new file mode 100644
index 0000000000..df6c098929
--- /dev/null
+++ b/tools/build/v2/test/inline.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+
+# Copyright 2003, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+project : requirements <link>static ;
+exe a : a.cpp [ lib helper : helper.cpp ] ;
+""")
+
+t.write("a.cpp", """
+extern void helper();
+int main() {}
+""")
+
+t.write("helper.cpp", """
+void helper() {}
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/link-static/a__helper.lib")
+t.rm("bin/$toolset/debug/link-static/a__helper.lib")
+
+t.run_build_system("a__helper")
+t.expect_addition("bin/$toolset/debug/link-static/a__helper.lib")
+
+t.rm("bin")
+
+
+# Now check that inline targets with the same name but present in different
+# places are not confused between each other, and with top-level targets.
+t.write("jamroot.jam", """
+project : requirements <link>static ;
+exe a : a.cpp [ lib helper : helper.cpp ] ;
+exe a2 : a.cpp [ lib helper : helper.cpp ] ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/link-static/a.exe")
+t.expect_addition("bin/$toolset/debug/link-static/a__helper.lib")
+t.expect_addition("bin/$toolset/debug/link-static/a2__helper.lib")
+
+
+# Check that the 'alias' target does not change the name of inline targets, and
+# that inline targets are explicit.
+t.write("jamroot.jam", """
+project : requirements <link>static ;
+alias a : [ lib helper : helper.cpp ] ;
+explicit a ;
+""")
+t.rm("bin")
+
+t.run_build_system()
+t.expect_nothing_more()
+
+t.run_build_system("a")
+t.expect_addition("bin/$toolset/debug/link-static/helper.lib")
+
+t.cleanup()
diff --git a/tools/build/v2/test/jamfile.jam b/tools/build/v2/test/jamfile.jam
new file mode 100644
index 0000000000..9d186f3c1f
--- /dev/null
+++ b/tools/build/v2/test/jamfile.jam
@@ -0,0 +1,11 @@
+# Copyright 2001 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+# establish a project root right here in the test directory, so that we can test
+# things independently of the boost jambase, etc.
+project-root ;
+
+include check-test-tools.jam ;
+include check-jam-patches.jam ;
diff --git a/tools/build/v2/test/lib_source_property.py b/tools/build/v2/test/lib_source_property.py
new file mode 100644
index 0000000000..2290c1fbf2
--- /dev/null
+++ b/tools/build/v2/test/lib_source_property.py
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Regression test: if a library had no explicit sources, but only <source>
+# properties, it was built as if it were a searched library, and the specified
+# sources were not compiled.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+lib a : : <source>a.cpp ;
+""")
+
+t.write("a.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {}
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.obj")
+
+t.rm("bin")
+
+
+# Now try with <conditional>.
+t.write("jamroot.jam", """
+rule test ( properties * )
+{
+ return <source>a.cpp ;
+}
+lib a : : <conditional>@test ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.obj")
+
+t.cleanup()
diff --git a/tools/build/v2/test/library_chain.py b/tools/build/v2/test/library_chain.py
new file mode 100644
index 0000000000..a51056ef95
--- /dev/null
+++ b/tools/build/v2/test/library_chain.py
@@ -0,0 +1,166 @@
+#!/usr/bin/python
+
+# Copyright 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that a chain of libraries works ok, no matter if we use static or shared
+# linking.
+
+import BoostBuild
+import string
+import os
+
+t = BoostBuild.Tester()
+
+t.write("jamfile.jam", """
+# Stage the binary, so that it will be relinked without hardcode-dll-paths. That
+# will chech that we pass correct -rpath-link, even if not passing -rpath.
+stage dist : main ;
+exe main : main.cpp b ;
+""")
+
+t.write("main.cpp", """
+void foo();
+int main() { foo(); }
+""")
+
+t.write("jamroot.jam", """
+""")
+
+t.write("a/a.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+gee() {}
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+geek() {}
+""")
+
+t.write("a/jamfile.jam", """
+lib a : a.cpp ;
+""")
+
+t.write("b/b.cpp", """
+void geek();
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+foo() { geek(); }
+""")
+
+t.write("b/jamfile.jam", """
+lib b : b.cpp ../a//a ;
+""")
+
+t.run_build_system("-d2", stderr=None)
+t.expect_addition("bin/$toolset/debug/main.exe")
+t.rm(["bin", "a/bin", "b/bin"])
+
+t.run_build_system("link=static")
+t.expect_addition("bin/$toolset/debug/link-static/main.exe")
+t.rm(["bin", "a/bin", "b/bin"])
+
+
+# Check that <library> works for static linking.
+t.write("b/jamfile.jam", """
+lib b : b.cpp : <library>../a//a ;
+""")
+
+t.run_build_system("link=static")
+t.expect_addition("bin/$toolset/debug/link-static/main.exe")
+
+t.rm(["bin", "a/bin", "b/bin"])
+
+t.write("b/jamfile.jam", """
+lib b : b.cpp ../a//a/<link>shared : <link>static ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/main.exe")
+
+t.rm(["bin", "a/bin", "b/bin"])
+
+
+# Test that putting a library in sources of a searched library works.
+t.write("jamfile.jam", """
+exe main : main.cpp png ;
+lib png : z : <name>png ;
+lib z : : <name>zzz ;
+""")
+
+t.run_build_system("-a -d+2", status=None, stderr=None)
+# Try to find the "zzz" string either in response file (for Windows compilers),
+# or in the standard output.
+rsp = t.adjust_names("bin/$toolset/debug/main.exe.rsp")[0]
+if os.path.exists(rsp) and ( string.find(open(rsp).read(), "zzz") != -1 ):
+ pass
+elif string.find(t.stdout(), "zzz") != -1:
+ pass
+else:
+ t.fail_test(1)
+
+# Test main -> libb -> liba chain in the case where liba is a file and not a
+# Boost.Build target.
+t.rm(".")
+
+t.write("jamroot.jam", "")
+
+t.write("a/jamfile.jam", """
+lib a : a.cpp ;
+install dist : a ;
+""")
+
+t.write("a/a.cpp", """
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+void a() {}
+""")
+
+t.run_build_system(subdir="a")
+t.expect_addition("a/dist/a.dll")
+
+if ( ( os.name == 'nt' ) or os.uname()[0].lower().startswith('cygwin') ) and \
+ ( BoostBuild.get_toolset() != 'gcc' ):
+ # This is windows import library -- we know the exact name.
+ file = "a/dist/a.lib"
+else:
+ file = t.adjust_names(["a/dist/a.dll"])[0]
+
+t.write("b/jamfile.jam", """
+lib b : b.cpp ../%s ;
+""" % file)
+
+t.write("b/b.cpp", """
+#if defined(_WIN32)
+__declspec(dllimport)
+#endif
+void a();
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+void b() { a(); }
+""")
+
+t.write("jamroot.jam", """
+exe main : main.cpp b//b ;
+""")
+
+t.write("main.cpp", """
+#if defined(_WIN32)
+__declspec(dllimport)
+#endif
+void b();
+int main() { b(); }
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/main.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/library_order.py b/tools/build/v2/test/library_order.py
new file mode 100644
index 0000000000..7baecf93e4
--- /dev/null
+++ b/tools/build/v2/test/library_order.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python
+
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that on compilers sensitive to library order on linker's command line, we
+# generate the correct order.
+
+import BoostBuild
+import string
+
+
+t = BoostBuild.Tester()
+
+t.write("a.cpp", """
+void b();
+void a() { b(); }
+""")
+
+t.write("b.cpp", """
+void c();
+void b() { c(); }
+""")
+
+t.write("c.cpp", """
+void d();
+void c() { d(); }
+""")
+
+t.write("d.cpp", """
+void d() {}
+""")
+
+# The order of libraries in 'main' is crafted so that we get error unless we do
+# something about the order ourselves.
+t.write("jamfile.jam", """
+exe main : main.cpp libd libc libb liba ;
+lib libd : d.cpp ;
+lib libc : c.cpp : <link>static <use>libd ;
+lib libb : b.cpp : <use>libc ;
+lib liba : a.cpp : <use>libb ;
+""")
+
+t.write("main.cpp", """
+void a();
+int main() { a(); }
+""")
+
+t.write("jamroot.jam", """
+""")
+
+t.run_build_system("-d2")
+t.expect_addition("bin/$toolset/debug/main.exe")
+
+
+# Test the order between searched libraries.
+t.write("jamfile.jam", """
+exe main : main.cpp png z ;
+lib png : z : <name>png ;
+lib z : : <name>zzz ;
+""")
+
+t.run_build_system("-a -n -d+2")
+t.fail_test(string.find(t.stdout(), "png") > string.find(t.stdout(), "zzz"))
+
+t.write("jamfile.jam", """
+exe main : main.cpp png z ;
+lib png : : <name>png ;
+lib z : png : <name>zzz ;
+""")
+
+t.run_build_system("-a -n -d+2")
+t.fail_test(string.find(t.stdout(), "png") < string.find(t.stdout(), "zzz"))
+
+
+# Test the order between prebuilt libraries.
+t.write("first.a", "")
+
+t.write("second.a", "")
+
+t.write("jamfile.jam", """
+exe main : main.cpp first second ;
+lib first : second : <file>first.a ;
+lib second : : <file>second.a ;
+""")
+
+t.run_build_system("-a -n -d+2")
+t.fail_test(string.find(t.stdout(), "first") > string.find(t.stdout(), "second"))
+
+t.write("jamfile.jam", """
+exe main : main.cpp first second ;
+lib first : : <file>first.a ;
+lib second : first : <file>second.a ;
+""")
+
+t.run_build_system("-a -n -d+2")
+t.fail_test(string.find(t.stdout(), "first") < string.find(t.stdout(), "second"))
+
+t.cleanup()
diff --git a/tools/build/v2/test/library_property.py b/tools/build/v2/test/library_property.py
new file mode 100644
index 0000000000..9430bb7054
--- /dev/null
+++ b/tools/build/v2/test/library_property.py
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that the <library> property has no effect on "obj" targets. Previously,
+# it affected all targets, so
+#
+# project : requirements <library>foo ;
+# exe a : a.cpp helper ;
+# obj helper : helper.cpp : <optimization>off ;
+#
+# caused 'foo' to be built with and without optimization.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+project : requirements <library>lib//x ;
+exe a : a.cpp foo ;
+obj foo : foo.cpp : <variant>release ;
+""")
+
+t.write("a.cpp", """
+void aux();
+int main() { aux(); }
+""")
+
+t.write("foo.cpp", """
+void gee();
+void aux() { gee(); }
+""")
+
+t.write("lib/x.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+gee() {}
+""")
+
+t.write("lib/jamfile.jam", """
+lib x : x.cpp ;
+""")
+
+t.write("lib/jamroot.jam", """
+""")
+
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+t.expect_nothing("lib/bin/$toolset/release/x.obj")
+
+t.cleanup()
diff --git a/tools/build/v2/test/load_dir.py b/tools/build/v2/test/load_dir.py
new file mode 100644
index 0000000000..09a59f9519
--- /dev/null
+++ b/tools/build/v2/test/load_dir.py
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+
+"""
+Traverses a directory and output the code that would create the same directory
+structure during testing. Assumes that the instance of Tester is called 't'.
+"""
+
+import sys
+import os
+import stat
+import string
+
+def usage():
+ print "usage: load_dir.py directory"
+
+
+def remove_first_component(path):
+ result = [path]
+ while 1:
+ s = os.path.split(result[0])
+ if not s[0]:
+ break
+ result[:1] = list(s)
+ return apply(os.path.join, result[1:])
+
+
+def create_file(arg, dirname, fnames):
+ for n in fnames:
+ path = os.path.join(dirname, n)
+ if not os.path.isdir(path):
+ print "t.write(\"%s\", \"\"\"" % (remove_first_component(path),),
+ f = open(path, "r")
+ for l in f:
+ print l,
+ print '\n""")\n'
+
+
+header = """#!/usr/bin/python
+
+# Copyright (C) FILL SOMETHING HERE 2005.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+"""
+
+footer = """
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/FILL_SOME_HERE.exe")
+
+t.cleanup()
+"""
+
+
+def main():
+ if len(sys.argv) != 2:
+ usage()
+ else:
+ path = sys.argv[1]
+
+ if not os.access(path, os.F_OK):
+ print "Path '%s' does not exist" % (path,)
+ sys.exit(1)
+
+ if not os.path.isdir(path):
+ print "Path '%s' is not a directory" % (path,)
+
+ print header
+
+ os.path.walk(path, create_file, None)
+
+ print footer
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tools/build/v2/test/load_order.py b/tools/build/v2/test/load_order.py
new file mode 100644
index 0000000000..34ceaaf448
--- /dev/null
+++ b/tools/build/v2/test/load_order.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+
+# Copyright 2004 Vladimir Prus.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that we load parent projects before loading children.
+
+import BoostBuild
+import string
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+use-project /child : child ;
+ECHO "Setting parent requirements" ;
+project : requirements <define>PASS_THE_TEST ;
+alias x : child//main ;
+""")
+
+t.write("child/jamfile.jam", """
+ECHO "Setting child requirements" ;
+project /child ;
+exe main : main.cpp ;
+""")
+
+t.write("child/main.cpp", """
+#if defined(PASS_THE_TEST)
+int main() {}
+#endif
+""")
+
+t.run_build_system()
+
+t.expect_addition("child/bin/$toolset/debug/main.exe")
+t.fail_test(string.find(t.stdout(), "Setting child requirements") <
+ string.find(t.stdout(), "Setting parent requirements"))
+
+
+# Regression test: parent requirements were ignored in some cases.
+t.rm(".")
+t.write("jamroot.jam", """
+build-project src ;
+""")
+
+t.write("src/jamfile.jam", """
+project : requirements <define>EVERYTHING_OK ;
+""")
+
+t.write("src/app/jamfile.jam", """
+exe test : test.cpp ;
+""")
+
+t.write("src/app/test.cpp", """
+#ifdef EVERYTHING_OK
+int main() {}
+#endif
+""")
+
+t.run_build_system(subdir="src/app")
+t.expect_addition("src/app/bin/$toolset/debug/test.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/loop.py b/tools/build/v2/test/loop.py
new file mode 100644
index 0000000000..f01b959735
--- /dev/null
+++ b/tools/build/v2/test/loop.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import string
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+lib main : main.cpp l ;
+lib l : l.cpp main ;
+""")
+
+t.write("main.cpp", "")
+
+t.write("l.cpp", "")
+
+t.run_build_system("--no-error-backtrace", status=1)
+t.fail_test(string.find(t.stdout(),
+ "error: Recursion in main target references") == -1)
+
+t.cleanup()
diff --git a/tools/build/v2/test/m1-01.py b/tools/build/v2/test/m1-01.py
new file mode 100644
index 0000000000..6c42c1eec8
--- /dev/null
+++ b/tools/build/v2/test/m1-01.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the very basic 'make' functionality.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree("test1")
+
+# Check that we can build something.
+t.run_build_system("-sTOOLSET=yfc")
+
+t.expect_addition("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
+t.expect_addition("bin/a/yfc/debug/runtime-link-dynamic/a")
+t.expect_nothing_more()
+
+t.fail(t.read("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+""")
+
+t.fail(t.read("bin/a/yfc/debug/runtime-link-dynamic/a") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+""")
+
+# Check that we have vanilla target names available.
+t.touch("a.cpp")
+t.run_build_system("-sTOOLSET a.obj")
+t.expect_touch("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
+t.expect_no_modification("bin/a/yfc/debug/runtime-link-dynamic/a")
+
+
+# Check that if a build request cannot be completely matches, a warning is
+# issued and a subvariant with link-compatible properties is used.
+t.write("jamfile.jam", t.read("jamfile2.jam"))
+stdout="""Warning: cannot exactly satisfy request for ./a with properties
+ <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+Using
+ <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+instead.
+""")
+t.run_build_system("-sTOOLSET=yfc", stdout=stdout)
+
+# Check that conflicting link-incompatible requirements prevent building.
+t.write("jamfile.jam", t.read("jamfile3.jam"))
+stdout="""Warning: cannot satisfy request for ./a with properties
+ <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+Nothing will be built.
+""")
+t.run_build_system("-sTOOLSET=yfc", stdout=stdout, status=1)
+
+t.pass_test()
diff --git a/tools/build/v2/test/m1-02.py b/tools/build/v2/test/m1-02.py
new file mode 100644
index 0000000000..13cc9dc1ae
--- /dev/null
+++ b/tools/build/v2/test/m1-02.py
@@ -0,0 +1,90 @@
+#!/usr/bin/python
+
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests that 'make' accepts targets from other directories and that build
+# requests for those targets can be overriden.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree("test1")
+
+t.run_build_system("-sTOOLSET=yfc")
+
+t.expect_addition("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
+t.expect_addition("auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/optimization-space/b.obj")
+t.expect_addition("bin/a/yfc/debug/runtime-link-dynamic/a")
+t.expect_nothing_more()
+
+t.fail(t.read("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+""")
+
+t.fail(t.read("auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/b.obj") !=\
+"""
+<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+b.cpp
+""")
+
+t.fail(t.read("bin/a/yfc/debug/runtime-link-dynamic/a") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+b.cpp
+""")
+
+# Check that we have vanilla target names available in subdirs.
+t.touch("auxillary/b.cpp")
+t.run_build_system("-sTOOLSET b.obj", subdir="auxillary")
+t.expect_touch("auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/optimization-space/b.obj")
+t.expect_no_modification("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
+t.expect_no_modification("bin/a/yfc/debug/runtime-link-dynamic/a")
+
+
+# Check that we can not request link-incompatible property for source target.
+t.write('jamfile.jam', t.read('jamfile2.jam'))
+stdout="""Error: subvariant of target ./a with properties
+ <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+requests link-incompatible property
+ <rtti>off
+for source @auxillary/b.obj
+"""
+t.run_build_system("-sTOOLSET=yfc", stdout=stdout)
+
+
+# Check that if we request link-compatible property then requirement for the
+# source target will override it, with a warning. This is similar to the way
+# build requests are satisfied (see the first test).
+#
+# CONSIDER: should be print the main target which requests this one (and
+# modifies requirements)?
+t.write('jamfile.jam', t.read('jamfile3.jam'))
+t.write('auxillary/jamfile.jam', t.read('auxillary/jamfile3.jam'))
+stdout="""Warning: cannot exactly satisfy request for auxillary/b.obj with properties
+ <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+Using
+ <optimization>speed <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+instead.
+"""
+t.run_build_system("-sTOOLSET=yfc", stdout=stdout)
+
+
+# Check for link-incompatible properties.
+t.write('jamfile.jam', t.read('jamfile4.jam'))
+t.write('auxillary/jamfile.jam', t.read('auxillary/jamfile4.jam'))
+stdout="""Warning: cannot satisfy request for auxillary/b.obj with properties
+ <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+Nothing will be built.
+"""
+t.run_build_system("-sTOOLSET=yfc", stdout=stdout)
+
+
+t.pass_test()
diff --git a/tools/build/v2/test/m1-03.py b/tools/build/v2/test/m1-03.py
new file mode 100644
index 0000000000..2f31ba27c8
--- /dev/null
+++ b/tools/build/v2/test/m1-03.py
@@ -0,0 +1,57 @@
+#!/usr/bin/python
+
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests that we can use objects from other projects, i.e. with other project
+# root. Test also that we can refer to those target using project-id.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree("test1")
+
+t.run_build_system("-sTOOLSET=yfc", subdir="p1")
+
+t.expect_addition("p1/bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
+t.expect_addition("p1/auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/optimization-space/b.obj")
+t.expect_addition("p2/bin/c.obj/yfc/debug/runtime-link-dynamic/c.obj")
+t.expect_addition("bin/a/yfc/debug/runtime-link-dynamic/a")
+t.expect_nothing_more()
+
+t.fail(t.read("p1/bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+""")
+
+t.fail(t.read("p1/auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/b.obj") !=\
+"""
+<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+b.cpp
+""")
+
+t.fail(t.read("p2/bin/c.obj/yfc/debug/runtime-link-dynamic/c.obj") !=\
+"""
+<include>everything <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+""")
+
+t.fail(t.read("bin/a/yfc/debug/runtime-link-dynamic/a") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+b.cpp
+<include>everything <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+c.cpp
+""")
+
+t.expect_nothing_more()
+
+# TODO: need to write test cases for referring to targets using project-id.
+
+t.pass_test()
diff --git a/tools/build/v2/test/make_rule.py b/tools/build/v2/test/make_rule.py
new file mode 100644
index 0000000000..3892009057
--- /dev/null
+++ b/tools/build/v2/test/make_rule.py
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2003, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the 'make' rule.
+
+import BoostBuild
+import string
+
+t = BoostBuild.Tester(pass_toolset=1)
+
+t.write("jamroot.jam", """
+import feature ;
+feature.feature test_feature : : free ;
+
+import toolset ;
+toolset.flags creator STRING : <test_feature> ;
+
+actions creator
+{
+ echo $(STRING) > $(<)
+}
+
+make foo.bar : : creator : <test_feature>12345678 ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/foo.bar")
+t.fail_test(string.find(t.read("bin/$toolset/debug/foo.bar"), "12345678") == -1)
+
+
+# Regression test. Make sure that if a main target is requested two times, and
+# build requests differ only in incidental properties, the main target is
+# created only once. The bug was discovered by Kirill Lapshin.
+t.write("jamroot.jam", """
+# Make sure that incidental property does not cause second creation of
+# 'hello1.cpp'.
+exe a : dir//hello1.cpp ;
+exe b : dir//hello1.cpp/<hardcode-dll-paths>true ;
+""")
+
+t.write("dir/jamfile.jam", """
+import common ;
+make hello1.cpp : hello.cpp : common.copy ;
+""")
+
+t.write("dir/hello.cpp", """
+int main() {}
+""")
+
+# Show only action names.
+t.run_build_system("-d1 -n")
+t.fail_test(t.stdout().count("copy") != 1)
+
+t.cleanup()
diff --git a/tools/build/v2/test/module-actions/boost-build.jam b/tools/build/v2/test/module-actions/boost-build.jam
new file mode 100644
index 0000000000..377f6ec023
--- /dev/null
+++ b/tools/build/v2/test/module-actions/boost-build.jam
@@ -0,0 +1,5 @@
+# Copyright 2003 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+boost-build . ;
diff --git a/tools/build/v2/test/module-actions/bootstrap.jam b/tools/build/v2/test/module-actions/bootstrap.jam
new file mode 100644
index 0000000000..6b024cac98
--- /dev/null
+++ b/tools/build/v2/test/module-actions/bootstrap.jam
@@ -0,0 +1,61 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2006 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Demonstration that module variables have the right effect in actions.
+
+
+# Top-level rule that causes a target to be built by invoking the specified
+# action.
+rule make ( target : sources * : act )
+{
+ DEPENDS all : $(target) ;
+ DEPENDS $(target) : $(sources) ;
+ $(act) $(target) : $(sources) ;
+}
+
+
+X1 = X1-global ;
+X2 = X2-global ;
+X3 = X3-global ;
+
+module A
+{
+ X1 = X1-A ;
+
+ rule act ( target )
+ {
+ NOTFILE $(target) ;
+ ALWAYS $(target) ;
+ }
+
+ actions act { echo A.act $(<): $(X1) $(X2) $(X3) }
+
+ make t1 : : A.act ;
+ make t2 : : A.act ;
+ make t3 : : A.act ;
+}
+
+module B
+{
+ X2 = X2-B ;
+
+ actions act { echo B.act $(<): $(X1) $(X2) $(X3) }
+
+ make t1 : : B.act ;
+ make t2 : : B.act ;
+ make t3 : : B.act ;
+}
+
+actions act { echo act $(<): $(X1) $(X2) $(X3) }
+
+make t1 : : act ;
+make t2 : : act ;
+make t3 : : act ;
+
+X1 on t1 = X1-t1 ;
+X2 on t2 = X2-t2 ;
+X3 on t3 = X3-t3 ;
+
+DEPENDS all : t1 t2 t3 ;
diff --git a/tools/build/v2/test/module_actions.py b/tools/build/v2/test/module_actions.py
new file mode 100644
index 0000000000..9f6da7ebc8
--- /dev/null
+++ b/tools/build/v2/test/module_actions.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2006 Rene Rivera
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import os
+import re
+
+spaces_re = re.compile("\ \ +")
+trailing_spaces_re = re.compile("\ +\n")
+
+t = BoostBuild.Tester("-d+1", pass_toolset=0)
+
+t.set_tree('module-actions')
+
+# Note that the following string contains some trailing spaces that should not
+# be removed.
+expected_output = """...found 4 targets...
+...updating 3 targets...
+A.act t1
+A.act t1: X1-t1
+B.act t1
+B.act t1: X1-t1 X2-B
+act t1
+act t1: X1-t1 X2-global X3-global
+A.act t2
+A.act t2: X1-A X2-t2
+B.act t2
+B.act t2: X2-t2
+act t2
+act t2: X1-global X2-t2 X3-global
+A.act t3
+A.act t3: X1-A X3-t3
+B.act t3
+B.act t3: X2-B X3-t3
+act t3
+act t3: X1-global X2-global X3-t3
+...updated 3 targets...
+"""
+
+# On Unixes, call to 'echo 1 2 3' produces '1 2 3' (note the spacing)
+# Accomodate for that fact.
+if os.name != 'nt':
+ expected_output = re.sub(spaces_re, " ", expected_output)
+ expected_output = re.sub(trailing_spaces_re, "\n", expected_output)
+
+t.run_build_system(stdout=expected_output)
+t.expect_nothing_more()
+t.cleanup()
diff --git a/tools/build/v2/test/ndebug.py b/tools/build/v2/test/ndebug.py
new file mode 100644
index 0000000000..123576f316
--- /dev/null
+++ b/tools/build/v2/test/ndebug.py
@@ -0,0 +1,39 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that building with optimization brings NDEBUG define, and, more
+# importantly, that dependency targets are built with NDEBUG as well, even if
+# they are not directly requested.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+exe hello : hello.cpp lib//lib1 ;
+""")
+
+t.write("hello.cpp", """
+#ifdef NDEBUG
+void foo();
+int main() { foo(); }
+#endif
+""")
+
+t.write("lib/jamfile.jam", """
+lib lib1 : lib1.cpp ;
+""")
+t.write("lib/lib1.cpp", """
+#ifdef NDEBUG
+void foo() {}
+#endif
+""")
+
+# 'release' builds should get the NDEBUG define. We use static linking to avoid
+# messing with imports/exports on windows.
+t.run_build_system("link=static release")
+
+t.cleanup()
diff --git a/tools/build/v2/test/no_type.py b/tools/build/v2/test/no_type.py
new file mode 100644
index 0000000000..0668e53ef5
--- /dev/null
+++ b/tools/build/v2/test/no_type.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that we cannot specify targets of unknown type as sources. This is based
+# on the fact that Unix 'ar' will happily consume just about anything.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+import gcc ;
+static-lib a : a.foo ;
+""")
+
+t.write("a.foo", "")
+
+t.run_build_system(status=1)
+
+t.cleanup()
diff --git a/tools/build/v2/test/notfile.py b/tools/build/v2/test/notfile.py
new file mode 100644
index 0000000000..f4db796654
--- /dev/null
+++ b/tools/build/v2/test/notfile.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2005.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Basic tests for the 'notfile' rule.
+
+import BoostBuild
+import string
+import os
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+import notfile ;
+notfile say : "echo hi" ;
+
+exe hello : hello.cpp ;
+notfile hello_valgrind : @valgrind : hello ;
+
+actions valgrind
+{
+ valgrind $(>[1])
+}
+""")
+
+t.write("hello.cpp", """
+#include <iostream>
+int main() { std::cout << "Hello!\\n"; }
+""")
+
+
+t.run_build_system("-n -d+2")
+
+t.fail_test(string.find(t.stdout(), "echo hi") == -1)
+
+name = t.adjust_names(["bin/$toolset/debug/hello.exe"])[0]
+name = apply(os.path.join, string.split(name, "/"));
+c = "valgrind *" + name
+t.expect_output_line(c)
+
+t.cleanup()
diff --git a/tools/build/v2/test/ordered_include.py b/tools/build/v2/test/ordered_include.py
new file mode 100644
index 0000000000..3de7295328
--- /dev/null
+++ b/tools/build/v2/test/ordered_include.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2008 Steven Watanabe
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt) or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+tester = BoostBuild.Tester()
+
+tester.write("jamroot.jam", """
+obj test : test.cpp : <include>a&&b ;
+""")
+
+tester.write("test.cpp", """
+#include <test1.hpp>
+#include <test2.hpp>
+int main() {}
+""")
+
+tester.write("a/test1.hpp", """
+""")
+
+tester.write("b/test2.hpp", """
+""")
+
+tester.run_build_system()
+
+tester.expect_addition("bin/$toolset/debug/test.obj")
+
+tester.touch("a/test1.hpp")
+tester.run_build_system()
+tester.expect_touch("bin/$toolset/debug/test.obj")
+
+tester.touch("b/test2.hpp")
+tester.run_build_system()
+tester.expect_touch("bin/$toolset/debug/test.obj")
+
+tester.cleanup()
diff --git a/tools/build/v2/test/ordered_properties.py b/tools/build/v2/test/ordered_properties.py
new file mode 100644
index 0000000000..58ea5a9f1f
--- /dev/null
+++ b/tools/build/v2/test/ordered_properties.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This checks that Boost.Build does not reorder <include> properties
+# lexicographically.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("a.cpp", """
+#include <a.h>
+int main() { foo(); }
+""")
+
+t.write("jamroot.jam", """
+exe a : a.cpp : <include>d2 <include>d1 ;
+""")
+
+t.write("d1/a.h", """
+""")
+
+t.write("d2/a.h", """
+inline void foo() {}
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/out_of_tree.py b/tools/build/v2/test/out_of_tree.py
new file mode 100644
index 0000000000..9e89cefbe1
--- /dev/null
+++ b/tools/build/v2/test/out_of_tree.py
@@ -0,0 +1,39 @@
+#!/usr/bin/python
+
+# Copyright (C) FILL SOMETHING HERE 2005.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests that we can build a project when the current directory is outside of
+# that project tree, that is 'bjam some_dir' works.
+
+import BoostBuild
+
+# Create a temporary working directory.
+t = BoostBuild.Tester()
+
+# Create the needed files.
+t.write("p1/jamroot.jam", """
+exe hello : hello.cpp ;
+""")
+
+t.write("p1/hello.cpp", """
+int main() {}
+""")
+
+t.write("p2/jamroot.jam", """
+exe hello2 : hello.cpp ;
+exe hello3 : hello.cpp ;
+""")
+
+t.write("p2/hello.cpp", """
+int main() {}
+""")
+
+t.run_build_system("p1 p2//hello3")
+
+t.expect_addition("p1/bin/$toolset/debug/hello.exe")
+t.expect_addition("p2/bin/$toolset/debug/hello3.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/path_features.py b/tools/build/v2/test/path_features.py
new file mode 100644
index 0000000000..231030be86
--- /dev/null
+++ b/tools/build/v2/test/path_features.py
@@ -0,0 +1,85 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", "import gcc ;")
+t.write("jamfile.jam", "lib a : a.cpp : <include>. ;")
+t.write("a.cpp", """
+#include <a.h>
+void
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+foo() {}
+""")
+t.write("a.h", "//empty file\n")
+
+t.write("d/jamfile.jam", "exe b : b.cpp ..//a ; ")
+t.write("d/b.cpp", """
+void foo();
+int main() { foo(); }
+""")
+
+t.run_build_system(subdir="d")
+
+# Now test the path features with condition work as well.
+t.write("jamfile.jam", "lib a : a.cpp : <variant>debug:<include>. ;")
+t.rm("bin")
+t.run_build_system(subdir="d")
+
+# Test path features with condition in usage requirements.
+t.write("jamfile.jam", """
+lib a : a.cpp : <include>. : : <variant>debug:<include>. ;
+""")
+t.write("d/b.cpp", """
+#include <a.h>
+void foo();
+int main() { foo(); }
+""")
+t.rm("d/bin")
+t.run_build_system(subdir="d")
+
+# Test that absolute paths inside requirements are ok. The problems appeared
+# only when building targets in subprojects.
+t.write("jamroot.jam", "")
+t.write("jamfile.jam", "build-project x ; ")
+t.write("x/jamfile.jam", """
+local pwd = [ PWD ] ;
+project : requirements <include>$(pwd)/x/include ;
+exe m : m.cpp : <include>$(pwd)/x/include2 ;
+""")
+t.write("x/m.cpp", """
+#include <h1.hpp>
+#include <h2.hpp>
+int main() {}
+""")
+t.write("x/include/h1.hpp", "\n")
+t.write("x/include2/h2.hpp", "\n")
+
+t.run_build_system()
+t.expect_addition("x/bin/$toolset/debug/m.exe")
+
+# Test that "&&" in path features is handled correctly.
+t.rm("bin")
+t.write("jamfile.jam", "build-project sub ;")
+t.write("sub/jamfile.jam", """
+exe a : a.cpp : <include>../h1&&../h2 ;
+""")
+t.write("sub/a.cpp", """
+#include <header.h>
+int main() { return OK; }
+""")
+t.write("h2/header.h", """
+const int OK = 0;
+""")
+t.run_build_system()
+t.expect_addition("sub/bin/$toolset/debug/a.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/pch.py b/tools/build/v2/test/pch.py
new file mode 100644
index 0000000000..d36260a55f
--- /dev/null
+++ b/tools/build/v2/test/pch.py
@@ -0,0 +1,55 @@
+#!/usr/bin/python
+
+# Copyright 2006 Vladimir Prus.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+import pch ;
+cpp-pch pch : pch.hpp : <toolset>msvc:<source>pch.cpp <include>. ;
+exe hello : hello.cpp pch : <include>. ;
+""")
+
+t.write("pch.hpp.bad", """
+THIS WILL NOT COMPILE
+""")
+
+# Note that pch.hpp is written after pch.hpp.bad, so its timestamp will not be
+# less than timestamp of pch.hpp.bad.
+t.write("pch.hpp", """
+class TestClass
+{
+public:
+ TestClass( int, int ) {}
+};
+""")
+
+t.write("pch.cpp", """#include <pch.hpp>
+""")
+
+t.write("hello.cpp", """#include <pch.hpp>
+int main() { TestClass c(1, 2); }
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+
+# Now make the header unusable, without changing timestamp. If everything is OK,
+# Boost.Build will not recreate PCH, and compiler will happily use pre-compiled
+# header, not noticing that the real header is bad.
+
+t.copy_preserving_timestamp("pch.hpp.bad", "pch.hpp")
+
+t.rm("bin/$toolset/debug/hello.obj")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/hello.obj")
+
+t.cleanup()
diff --git a/tools/build/v2/test/prebuilt.py b/tools/build/v2/test/prebuilt.py
new file mode 100644
index 0000000000..250cdc8201
--- /dev/null
+++ b/tools/build/v2/test/prebuilt.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python
+
+# Copyright 2002, 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that we can use already built sources
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree('prebuilt')
+
+t.expand_toolset("ext/jamroot.jam")
+t.expand_toolset("jamroot.jam")
+
+# First, build the external project.
+t.run_build_system("debug release", subdir="ext")
+
+# Then pretend that we do not have the sources for the external project, and can
+# only use compiled binaries.
+t.copy("ext/jamfile2.jam", "ext/jamfile.jam")
+t.expand_toolset("ext/jamfile.jam")
+
+# Now check that we can build the main project, and that correct prebuilt file
+# is picked, depending of variant. This also checks that correct includes for
+# prebuilt libraries are used.
+t.run_build_system("debug release")
+t.expect_addition("bin/$toolset/debug/hello.exe")
+t.expect_addition("bin/$toolset/release/hello.exe")
+
+t.rm("bin")
+
+
+# Now test that prebuilt file specified by absolute name works too.
+t.copy("ext/jamfile3.jam", "ext/jamfile.jam")
+t.expand_toolset("ext/jamfile.jam")
+t.run_build_system("debug release")
+t.expect_addition("bin/$toolset/debug/hello.exe")
+t.expect_addition("bin/$toolset/release/hello.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/prebuilt/ext/a.cpp b/tools/build/v2/test/prebuilt/ext/a.cpp
new file mode 100644
index 0000000000..c49a041533
--- /dev/null
+++ b/tools/build/v2/test/prebuilt/ext/a.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+#ifdef RELEASE
+void release() {}
+#else
+void debug() {}
+#endif
diff --git a/tools/build/v2/test/prebuilt/ext/debug/a.h b/tools/build/v2/test/prebuilt/ext/debug/a.h
new file mode 100644
index 0000000000..31b3182265
--- /dev/null
+++ b/tools/build/v2/test/prebuilt/ext/debug/a.h
@@ -0,0 +1,13 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+void debug();
diff --git a/tools/build/v2/test/prebuilt/ext/jamfile.jam b/tools/build/v2/test/prebuilt/ext/jamfile.jam
new file mode 100644
index 0000000000..e563f0d741
--- /dev/null
+++ b/tools/build/v2/test/prebuilt/ext/jamfile.jam
@@ -0,0 +1,13 @@
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project ext
+ : requirements <variant>release:<define>RELEASE
+ ;
+
+lib a : a.cpp ;
+
+install dist : a : <variant>release:<location>release
+ <variant>debug:<location>debug ;
diff --git a/tools/build/v2/test/prebuilt/ext/jamfile2.jam b/tools/build/v2/test/prebuilt/ext/jamfile2.jam
new file mode 100644
index 0000000000..dd79f4ea2d
--- /dev/null
+++ b/tools/build/v2/test/prebuilt/ext/jamfile2.jam
@@ -0,0 +1,39 @@
+
+import modules ;
+
+local dll-suffix = so ;
+local prefix = "" ;
+if [ modules.peek : OS ] in CYGWIN NT
+{
+ if [ MATCH ^(gcc) : $toolset ]
+ {
+ dll-suffix = dll ;
+ }
+ else
+ {
+ dll-suffix = lib ;
+ }
+}
+else
+{
+ prefix = "lib" ;
+}
+if [ MATCH ^(darwin) : $toolset ]
+{
+ dll-suffix = dylib ;
+}
+
+project ext ;
+
+lib a :
+ : <file>debug/$(prefix)a.$(dll-suffix) <variant>debug
+ :
+ : <include>debug
+ ;
+
+lib a :
+ : <file>release/$(prefix)a.$(dll-suffix) <variant>release
+ :
+ : <include>release
+ ;
+
diff --git a/tools/build/v2/test/prebuilt/ext/jamfile3.jam b/tools/build/v2/test/prebuilt/ext/jamfile3.jam
new file mode 100644
index 0000000000..f172a89d08
--- /dev/null
+++ b/tools/build/v2/test/prebuilt/ext/jamfile3.jam
@@ -0,0 +1,46 @@
+
+# This Jamfile is the same as Jamfile2, except that
+# it tries to access prebuilt targets using absolute
+# paths. It used to be broken on Windows.
+
+import modules ;
+
+local dll-suffix = so ;
+local prefix = "" ;
+if [ modules.peek : OS ] in CYGWIN NT
+{
+ if [ MATCH ^(gcc) : $toolset ]
+ {
+ dll-suffix = dll ;
+ }
+ else
+ {
+ dll-suffix = lib ;
+ }
+}
+else
+{
+ prefix = "lib" ;
+}
+if [ MATCH ^(darwin) : $toolset ]
+{
+ dll-suffix = dylib ;
+}
+
+project ext ;
+
+# Assumed bjam was invoked from the project root
+local pwd = [ PWD ] ;
+
+lib a :
+ : <file>$(pwd)/ext/debug/$(prefix)a.$(dll-suffix) <variant>debug
+ :
+ : <include>debug
+ ;
+
+lib a :
+ : <file>$(pwd)/ext/release/$(prefix)a.$(dll-suffix) <variant>release
+ :
+ : <include>release
+ ;
+
diff --git a/tools/build/v2/test/prebuilt/ext/jamroot.jam b/tools/build/v2/test/prebuilt/ext/jamroot.jam
new file mode 100644
index 0000000000..c7617d5d33
--- /dev/null
+++ b/tools/build/v2/test/prebuilt/ext/jamroot.jam
@@ -0,0 +1,5 @@
+# Copyright 2002, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
diff --git a/tools/build/v2/test/prebuilt/ext/release/a.h b/tools/build/v2/test/prebuilt/ext/release/a.h
new file mode 100644
index 0000000000..9ab71d88ce
--- /dev/null
+++ b/tools/build/v2/test/prebuilt/ext/release/a.h
@@ -0,0 +1,13 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+void release();
diff --git a/tools/build/v2/test/prebuilt/hello.cpp b/tools/build/v2/test/prebuilt/hello.cpp
new file mode 100644
index 0000000000..4c1ab7036f
--- /dev/null
+++ b/tools/build/v2/test/prebuilt/hello.cpp
@@ -0,0 +1,20 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+#include <a.h>
+
+int main()
+{
+ #ifdef RELEASE
+ release();
+ #else
+ debug();
+ #endif
+ return 0;
+}
diff --git a/tools/build/v2/test/prebuilt/jamfile.jam b/tools/build/v2/test/prebuilt/jamfile.jam
new file mode 100644
index 0000000000..18b731ae17
--- /dev/null
+++ b/tools/build/v2/test/prebuilt/jamfile.jam
@@ -0,0 +1,13 @@
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project test
+ : requirements <variant>release:<define>RELEASE
+ ;
+
+use-project /ext : ext ;
+
+exe hello : hello.cpp /ext//a ;
+
diff --git a/tools/build/v2/test/prebuilt/jamroot.jam b/tools/build/v2/test/prebuilt/jamroot.jam
new file mode 100644
index 0000000000..f022c0d64c
--- /dev/null
+++ b/tools/build/v2/test/prebuilt/jamroot.jam
@@ -0,0 +1,4 @@
+# Copyright 2002, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
diff --git a/tools/build/v2/test/preprocessor.py b/tools/build/v2/test/preprocessor.py
new file mode 100755
index 0000000000..9faa711b76
--- /dev/null
+++ b/tools/build/v2/test/preprocessor.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Copyright 2011 Steven Watanabe
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the C/C++ preprocessor.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+project ;
+preprocessed hello : hello.cpp ;
+preprocessed a : a.c ;
+exe hello.exe : hello a : <define>FAIL ;
+""")
+
+t.write("hello.cpp", """
+#ifndef __cplusplus
+#error "This file must be compiled as C++"
+#endif
+#ifdef FAIL
+#error "Not preprocessed?"
+#endif
+extern "C" int foo();
+int main() { return foo(); }
+""")
+
+t.write("a.c", """
+/* This will not compile unless in C mode. */
+#ifdef __cplusplus
+#error "This file must be compiled as C"
+#endif
+#ifdef FAIL
+#error "Not preprocessed?"
+#endif
+int foo()
+{
+ int new = 0;
+ new = (new+1)*7;
+ return new;
+}
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/hello.ii")
+t.expect_addition("bin/$toolset/debug/a.i")
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/print.py b/tools/build/v2/test/print.py
new file mode 100644
index 0000000000..65caf95e19
--- /dev/null
+++ b/tools/build/v2/test/print.py
@@ -0,0 +1,48 @@
+#!/usr/bin/python
+
+# Copyright 2003 Douglas Gregor
+# Copyright 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", "import gcc ;")
+
+t.write("jamfile.jam", """
+import print ;
+print.output foo ;
+print.text \\\"Something\\\" ;
+DEPENDS all : foo ;
+ALWAYS foo ;
+""")
+
+t.run_build_system()
+t.expect_content("foo", """\"Something\"""")
+
+t.write("jamfile.jam", """
+import print ;
+print.output foo ;
+print.text \\\n\\\"Somethingelse\\\" ;
+DEPENDS all : foo ;
+ALWAYS foo ;
+""")
+
+t.run_build_system()
+t.expect_content("foo", """\"Something\"
+\"Somethingelse\"""")
+
+t.write("jamfile.jam", """
+import print ;
+print.output foo ;
+print.text \\\"Different\\\" : true ;
+DEPENDS all : foo ;
+ALWAYS foo ;
+""")
+
+t.run_build_system()
+t.expect_content("foo", """\"Different\"""")
+
+t.cleanup()
diff --git a/tools/build/v2/test/project-test1.jam b/tools/build/v2/test/project-test1.jam
new file mode 100644
index 0000000000..c2d6ae5763
--- /dev/null
+++ b/tools/build/v2/test/project-test1.jam
@@ -0,0 +1,18 @@
+# Copyright 2002, 2003 Dave Abrahams
+# Copyright 2002 Rene Rivera
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import project ;
+import targets ;
+import assert ;
+
+project.load project-test1 ;
+import project-roots ;
+
+project-roots.print ;
+
+NOTFILE all ;
+
+
diff --git a/tools/build/v2/test/project-test1/dir/jamfile.jam b/tools/build/v2/test/project-test1/dir/jamfile.jam
new file mode 100644
index 0000000000..3434eb7911
--- /dev/null
+++ b/tools/build/v2/test/project-test1/dir/jamfile.jam
@@ -0,0 +1,10 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project /boost-build-test-project-1/dir
+ : source-location src
+ : default-build release
+ ;
diff --git a/tools/build/v2/test/project-test1/dir2/jamfile.jam b/tools/build/v2/test/project-test1/dir2/jamfile.jam
new file mode 100644
index 0000000000..8d1c48b65b
--- /dev/null
+++ b/tools/build/v2/test/project-test1/dir2/jamfile.jam
@@ -0,0 +1,9 @@
+# Copyright 2004 Rene Rivera
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project /cool-library
+ : requirements <include>/home/ghost/build/boost-cvs
+ ;
diff --git a/tools/build/v2/test/project-test1/dir2/jamroot.jam b/tools/build/v2/test/project-test1/dir2/jamroot.jam
new file mode 100644
index 0000000000..8cfc3a28e9
--- /dev/null
+++ b/tools/build/v2/test/project-test1/dir2/jamroot.jam
@@ -0,0 +1,4 @@
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
diff --git a/tools/build/v2/test/project-test1/jamfile.jam b/tools/build/v2/test/project-test1/jamfile.jam
new file mode 100644
index 0000000000..d343ba6df6
--- /dev/null
+++ b/tools/build/v2/test/project-test1/jamfile.jam
@@ -0,0 +1,10 @@
+# Copyright 2002 Dave Abrahams
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+project /boost-build-test-project-1
+ : requirements <threading>multi <include>/home/ghost/local/include ;
+
+build-project dir2 ;
+build-project dir ;
diff --git a/tools/build/v2/test/project-test1/jamroot.jam b/tools/build/v2/test/project-test1/jamroot.jam
new file mode 100644
index 0000000000..a61a11c1d5
--- /dev/null
+++ b/tools/build/v2/test/project-test1/jamroot.jam
@@ -0,0 +1,6 @@
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+import builtin ;
diff --git a/tools/build/v2/test/project-test1/project-test1.jam b/tools/build/v2/test/project-test1/project-test1.jam
new file mode 100644
index 0000000000..2f2aad25c8
--- /dev/null
+++ b/tools/build/v2/test/project-test1/project-test1.jam
@@ -0,0 +1,21 @@
+# Copyright 2002, 2003 Dave Abrahams
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import project ;
+import targets ;
+import assert ;
+import project-roots ;
+
+project.load "." ;
+
+import standalone-project ;
+
+project-roots.print ;
+
+assert.result standalone-project : project.find /teeest : "." ;
+
+NOTFILE all ;
+
+
diff --git a/tools/build/v2/test/project-test1/readme.txt b/tools/build/v2/test/project-test1/readme.txt
new file mode 100644
index 0000000000..0001799243
--- /dev/null
+++ b/tools/build/v2/test/project-test1/readme.txt
@@ -0,0 +1,8 @@
+Copyright 2003 Dave Abrahams
+Copyright 2002 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+This tests for basic project handling -- declaring subprojects, finding
+parent projects and project roots and for working project-ids.
diff --git a/tools/build/v2/test/project-test1/standalone-project.jam b/tools/build/v2/test/project-test1/standalone-project.jam
new file mode 100644
index 0000000000..48249b561d
--- /dev/null
+++ b/tools/build/v2/test/project-test1/standalone-project.jam
@@ -0,0 +1,12 @@
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+import project ;
+
+# Convert ourself into a real project.
+project.initialize $(__name__) ;
+
+# Now we can identify ourselfs.
+project /teeest ;
diff --git a/tools/build/v2/test/project-test3/a.cpp b/tools/build/v2/test/project-test3/a.cpp
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/project-test3/a.cpp
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/project-test3/jamfile.jam b/tools/build/v2/test/project-test3/jamfile.jam
new file mode 100644
index 0000000000..f079607707
--- /dev/null
+++ b/tools/build/v2/test/project-test3/jamfile.jam
@@ -0,0 +1,13 @@
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+use-project /lib2 : lib2 ;
+use-project /lib3 : lib3 ;
+
+make a.exe : a.obj lib//b.obj /lib2//c.obj lib2//d.obj lib2/helper//e.obj /lib3//f.obj : yfc-link ;
+make a.obj : a.cpp : yfc-compile ;
+
+build-project lib2 ;
+build-project lib ;
diff --git a/tools/build/v2/test/project-test3/jamroot.jam b/tools/build/v2/test/project-test3/jamroot.jam
new file mode 100644
index 0000000000..8de43be51d
--- /dev/null
+++ b/tools/build/v2/test/project-test3/jamroot.jam
@@ -0,0 +1,46 @@
+# Copyright 2002-2005 Vladimir Prus.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import gcc ;
+import property ;
+
+rule properties-as-path ( properties * )
+{
+ local r ;
+ for local p in $(properties)
+ {
+ if $(p:G) != <action>
+ {
+ r += $(p) ;
+ }
+ }
+ return [ property.as-path
+ [ property.remove incidental : $(r) ] ] ;
+}
+
+rule yfc-compile ( target : sources * : property-set * )
+{
+ PROPERTIES on $(target) = [ properties-as-path $(property-set) ] ;
+}
+
+actions yfc-compile
+{
+ echo $(PROPERTIES) > $(<)
+ echo $(>) >> $(<)
+}
+
+rule yfc-link ( target : sources * : property-set * )
+{
+ PROPERTIES on $(target) = [ properties-as-path $(property-set) ] ;
+}
+
+actions yfc-link
+{
+ echo $(PROPERTIES) > $(<)
+ echo $(>) >> $(<)
+}
+
+
+IMPORT $(__name__) : yfc-compile yfc-link : : yfc-compile yfc-link ;
diff --git a/tools/build/v2/test/project-test3/lib/b.cpp b/tools/build/v2/test/project-test3/lib/b.cpp
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/project-test3/lib/b.cpp
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/project-test3/lib/jamfile.jam b/tools/build/v2/test/project-test3/lib/jamfile.jam
new file mode 100644
index 0000000000..76b0829a9c
--- /dev/null
+++ b/tools/build/v2/test/project-test3/lib/jamfile.jam
@@ -0,0 +1,9 @@
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+use-project /lib2 : ../lib2 ;
+
+make b.obj : b.cpp : yfc-compile ;
+make m.exe : b.obj /lib2//c.obj : yfc-link ;
diff --git a/tools/build/v2/test/project-test3/lib2/c.cpp b/tools/build/v2/test/project-test3/lib2/c.cpp
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/project-test3/lib2/c.cpp
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/project-test3/lib2/d.cpp b/tools/build/v2/test/project-test3/lib2/d.cpp
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/project-test3/lib2/d.cpp
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/project-test3/lib2/helper/e.cpp b/tools/build/v2/test/project-test3/lib2/helper/e.cpp
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/project-test3/lib2/helper/e.cpp
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/project-test3/lib2/helper/jamfile.jam b/tools/build/v2/test/project-test3/lib2/helper/jamfile.jam
new file mode 100644
index 0000000000..0c82f92481
--- /dev/null
+++ b/tools/build/v2/test/project-test3/lib2/helper/jamfile.jam
@@ -0,0 +1,9 @@
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project lib2/helper ;
+
+make e.obj : e.cpp : yfc-compile ;
+
diff --git a/tools/build/v2/test/project-test3/lib2/jamfile.jam b/tools/build/v2/test/project-test3/lib2/jamfile.jam
new file mode 100644
index 0000000000..b6b0abc44b
--- /dev/null
+++ b/tools/build/v2/test/project-test3/lib2/jamfile.jam
@@ -0,0 +1,11 @@
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project lib2 ;
+use-project /lib2/helper : helper ;
+
+make c.obj : c.cpp : yfc-compile ;
+make d.obj : d.cpp : yfc-compile ;
+make l.exe : c.obj ..//a.obj : yfc-link ;
diff --git a/tools/build/v2/test/project-test3/lib3/f.cpp b/tools/build/v2/test/project-test3/lib3/f.cpp
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/project-test3/lib3/f.cpp
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/project-test3/lib3/jamfile.jam b/tools/build/v2/test/project-test3/lib3/jamfile.jam
new file mode 100644
index 0000000000..0d457817e7
--- /dev/null
+++ b/tools/build/v2/test/project-test3/lib3/jamfile.jam
@@ -0,0 +1,37 @@
+# Copyright 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This project-root.jam also serves the role of Jamfile
+project lib3 ;
+
+use-project /lib2/helper : ../lib2/helper ;
+
+import property ;
+
+rule properties-as-path ( properties * )
+{
+ local r ;
+ for local p in $(properties)
+ {
+ if $(p:G) != <action>
+ {
+ r += $(p) ;
+ }
+ }
+ return [ property.as-path
+ [ property.remove incidental : $(r) ] ] ;
+}
+
+rule mfc-compile ( target : sources * : property-set * )
+{
+ PROPERTIES on $(target) = [ properties-as-path $(property-set) ] ;
+}
+
+actions mfc-compile
+{
+ echo $(PROPERTIES) > $(<)
+ echo $(>) >> $(<)
+}
+
+make f.obj : f.cpp /lib2/helper//e.obj : mfc-compile ;
diff --git a/tools/build/v2/test/project-test3/lib3/jamroot.jam b/tools/build/v2/test/project-test3/lib3/jamroot.jam
new file mode 100644
index 0000000000..971f03096e
--- /dev/null
+++ b/tools/build/v2/test/project-test3/lib3/jamroot.jam
@@ -0,0 +1,5 @@
+# Copyright 2002 Rene Rivera
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
diff --git a/tools/build/v2/test/project-test3/readme.txt b/tools/build/v2/test/project-test3/readme.txt
new file mode 100644
index 0000000000..da27e54b2e
--- /dev/null
+++ b/tools/build/v2/test/project-test3/readme.txt
@@ -0,0 +1,7 @@
+Copyright 2002 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+This test checks that we have minimally working 'make' rule and that we can use target from
+different project with different project roots.
diff --git a/tools/build/v2/test/project-test4/a.cpp b/tools/build/v2/test/project-test4/a.cpp
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/project-test4/a.cpp
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/project-test4/a_gcc.cpp b/tools/build/v2/test/project-test4/a_gcc.cpp
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/project-test4/a_gcc.cpp
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/project-test4/jamfile.jam b/tools/build/v2/test/project-test4/jamfile.jam
new file mode 100644
index 0000000000..a34d5f2db7
--- /dev/null
+++ b/tools/build/v2/test/project-test4/jamfile.jam
@@ -0,0 +1,11 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project test : requirements <include>everything <threading>single ;
+
+make a.exe : a.obj lib//b.obj/<optimization>speed : yfc-link ;
+make b.exe : a.obj : yfc-link : <define>MACROS ;
+make a.obj : a.cpp : yfc-compile ;
diff --git a/tools/build/v2/test/project-test4/jamfile3.jam b/tools/build/v2/test/project-test4/jamfile3.jam
new file mode 100644
index 0000000000..9770362d7f
--- /dev/null
+++ b/tools/build/v2/test/project-test4/jamfile3.jam
@@ -0,0 +1,5 @@
+
+make a.exe : a.obj lib//b.obj/<optimization>on a_gcc.obj : yfc-link : <toolset>gcc ;
+make a.exe : a.obj lib//b.obj/<optimization>on : yfc-link : <threading>multi ;
+make a.obj : a.cpp : yfc-compile ;
+make a_gcc.obj : a_gcc.cpp : yfc-compile ;
diff --git a/tools/build/v2/test/project-test4/jamfile4.jam b/tools/build/v2/test/project-test4/jamfile4.jam
new file mode 100644
index 0000000000..e3257801a7
--- /dev/null
+++ b/tools/build/v2/test/project-test4/jamfile4.jam
@@ -0,0 +1,4 @@
+
+project test : requirements <include>everything <threading>single ;
+
+build-project lib2 ;
diff --git a/tools/build/v2/test/project-test4/jamfile5.jam b/tools/build/v2/test/project-test4/jamfile5.jam
new file mode 100644
index 0000000000..1010be5e46
--- /dev/null
+++ b/tools/build/v2/test/project-test4/jamfile5.jam
@@ -0,0 +1,6 @@
+
+project test : requirements <include>everything <threading>single ;
+
+make a.exe : a.obj lib//b.obj/<variant>release : yfc-link ;
+make b.exe : a.obj : yfc-link : <define>MACROS ;
+make a.obj : a.cpp : yfc-compile ;
diff --git a/tools/build/v2/test/project-test4/jamroot.jam b/tools/build/v2/test/project-test4/jamroot.jam
new file mode 100644
index 0000000000..801f0afb27
--- /dev/null
+++ b/tools/build/v2/test/project-test4/jamroot.jam
@@ -0,0 +1,47 @@
+# Copyright 2002, 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+import gcc ;
+import property ;
+
+rule properties-as-path ( properties * )
+{
+ local r ;
+ for local p in $(properties)
+ {
+ if $(p:G) != <action>
+ {
+ r += $(p) ;
+ }
+ }
+ return [ property.as-path
+ [ property.remove incidental : $(r) ] ] ;
+}
+
+
+rule yfc-compile ( target : sources * : property-set * )
+{
+ PROPERTIES on $(target) = [ properties-as-path $(property-set) ] ;
+}
+
+actions yfc-compile
+{
+ echo $(PROPERTIES) > $(<)
+ echo $(>) >> $(<)
+}
+
+rule yfc-link ( target : sources * : property-set * )
+{
+ PROPERTIES on $(target) = [ properties-as-path $(property-set) ] ;
+}
+
+actions yfc-link
+{
+ echo $(PROPERTIES) > $(<)
+ echo $(>) >> $(<)
+}
+
+
+IMPORT $(__name__) : yfc-compile yfc-link : : yfc-compile yfc-link ;
diff --git a/tools/build/v2/test/project-test4/lib/b.cpp b/tools/build/v2/test/project-test4/lib/b.cpp
new file mode 100644
index 0000000000..ccecbb414f
--- /dev/null
+++ b/tools/build/v2/test/project-test4/lib/b.cpp
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
diff --git a/tools/build/v2/test/project-test4/lib/jamfile.jam b/tools/build/v2/test/project-test4/lib/jamfile.jam
new file mode 100644
index 0000000000..1bdb7c122c
--- /dev/null
+++ b/tools/build/v2/test/project-test4/lib/jamfile.jam
@@ -0,0 +1,6 @@
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+make b.obj : b.cpp : yfc-compile ;
diff --git a/tools/build/v2/test/project-test4/lib/jamfile1.jam b/tools/build/v2/test/project-test4/lib/jamfile1.jam
new file mode 100644
index 0000000000..be2c3649a2
--- /dev/null
+++ b/tools/build/v2/test/project-test4/lib/jamfile1.jam
@@ -0,0 +1,2 @@
+
+make b.obj : b.cpp : yfc-compile ;
diff --git a/tools/build/v2/test/project-test4/lib/jamfile2.jam b/tools/build/v2/test/project-test4/lib/jamfile2.jam
new file mode 100644
index 0000000000..d47274bdfe
--- /dev/null
+++ b/tools/build/v2/test/project-test4/lib/jamfile2.jam
@@ -0,0 +1,4 @@
+
+project lib : requirements <threading>multi ;
+
+make b.obj : b.cpp : yfc-compile ;
diff --git a/tools/build/v2/test/project-test4/lib/jamfile3.jam b/tools/build/v2/test/project-test4/lib/jamfile3.jam
new file mode 100644
index 0000000000..73a78324b8
--- /dev/null
+++ b/tools/build/v2/test/project-test4/lib/jamfile3.jam
@@ -0,0 +1,2 @@
+
+make b.obj : b.cpp : yfc-compile : <rtti>off ;
diff --git a/tools/build/v2/test/project-test4/lib2/jamfile.jam b/tools/build/v2/test/project-test4/lib2/jamfile.jam
new file mode 100644
index 0000000000..389492bf0e
--- /dev/null
+++ b/tools/build/v2/test/project-test4/lib2/jamfile.jam
@@ -0,0 +1,8 @@
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project
+ : requirements <rtti>off
+ ;
diff --git a/tools/build/v2/test/project-test4/lib2/jamfile2.jam b/tools/build/v2/test/project-test4/lib2/jamfile2.jam
new file mode 100644
index 0000000000..94b144d068
--- /dev/null
+++ b/tools/build/v2/test/project-test4/lib2/jamfile2.jam
@@ -0,0 +1,4 @@
+
+project mylib
+ : requirements <rtti>off
+ ;
diff --git a/tools/build/v2/test/project-test4/readme.txt b/tools/build/v2/test/project-test4/readme.txt
new file mode 100644
index 0000000000..0c0ba2ca4b
--- /dev/null
+++ b/tools/build/v2/test/project-test4/readme.txt
@@ -0,0 +1,6 @@
+Copyright 2002 Vladimir Prus
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+This test checks for correct properties of generated and used targets.
diff --git a/tools/build/v2/test/project_dependencies.py b/tools/build/v2/test/project_dependencies.py
new file mode 100644
index 0000000000..96df9e250f
--- /dev/null
+++ b/tools/build/v2/test/project_dependencies.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that we can specify a dependency property in project requirements, and
+# that it will not cause every main target in the project to be generated in its
+# own subdirectory.
+
+# The whole test is somewhat moot now.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", "build-project src ;")
+
+t.write("lib/jamfile.jam", "lib lib1 : lib1.cpp ;")
+
+t.write("lib/lib1.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {}\n
+""")
+
+t.write("src/jamfile.jam", """
+project : requirements <library>../lib//lib1 ;
+exe a : a.cpp ;
+exe b : b.cpp ;
+""")
+
+t.write("src/a.cpp", """
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+void foo();
+int main() { foo(); }
+""")
+
+t.copy("src/a.cpp", "src/b.cpp")
+
+t.run_build_system()
+
+# Test that there is no "main-target-a" part.
+# t.expect_addition("src/bin/$toolset/debug/a.exe")
+# t.expect_addition("src/bin/$toolset/debug/b.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/project_glob.py b/tools/build/v2/test/project_glob.py
new file mode 100644
index 0000000000..1445eb2a69
--- /dev/null
+++ b/tools/build/v2/test/project_glob.py
@@ -0,0 +1,161 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2003.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the 'glob' rule in Jamfile context.
+
+import BoostBuild
+
+# Create a temporary working directory.
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+""")
+
+t.write("d1/a.cpp", """
+int main() {}
+""")
+
+t.write("d1/jamfile.jam", """
+exe a : [ glob *.cpp ] ../d2/d//l ;
+""")
+
+t.write("d2/d/l.cpp", """
+#if defined(_WIN32)
+__declspec(dllexport)
+void force_import_lib_creation() {}
+#endif
+""")
+
+t.write("d2/d/jamfile.jam", """
+lib l : [ glob *.cpp ] ;
+""")
+
+t.write("d3/d/jamfile.jam", """
+exe a : [ glob ../*.cpp ] ;
+""")
+
+t.write("d3/a.cpp", """
+int main() {}
+""")
+
+t.run_build_system(subdir="d1")
+t.expect_addition("d1/bin/$toolset/debug/a.exe")
+
+t.run_build_system(subdir="d3/d")
+t.expect_addition("d3/d/bin/$toolset/debug/a.exe")
+
+t.rm("d2/d/bin")
+
+t.run_build_system(subdir="d2/d")
+t.expect_addition("d2/d/bin/$toolset/debug/l.dll")
+
+
+# Test that when 'source-location' is explicitly-specified glob works relatively
+# to the source location.
+t.rm("d1")
+
+t.write("d1/src/a.cpp", """
+int main() {}
+""")
+
+t.write("d1/jamfile.jam", """
+project : source-location src ;
+exe a : [ glob *.cpp ] ../d2/d//l ;
+""")
+
+t.run_build_system(subdir="d1")
+t.expect_addition("d1/bin/$toolset/debug/a.exe")
+
+# Test that wildcards can include directories. Also test exclusion patterns.
+t.rm("d1")
+
+t.write("d1/src/foo/a.cpp", """
+void bar();
+int main() { bar(); }
+""")
+
+t.write("d1/src/bar/b.cpp", """
+void bar() {}
+""")
+
+t.write("d1/src/bar/bad.cpp", """
+very bad non-compilable file
+""")
+
+t.write("d1/jamfile.jam", """
+project : source-location src ;
+exe a : [ glob foo/*.cpp bar/*.cpp : bar/bad* ] ../d2/d//l ;
+""")
+
+t.run_build_system(subdir="d1")
+t.expect_addition("d1/bin/$toolset/debug/a.exe")
+
+
+# Test that 'glob-tree' works.
+t.rm("d1/bin/$toolset/debug/a.exe")
+
+t.write("d1/jamfile.jam", """
+project : source-location src ;
+exe a : [ glob-tree *.cpp : bad* ] ../d2/d//l ;
+""")
+
+t.run_build_system(subdir="d1")
+t.expect_addition("d1/bin/$toolset/debug/a.exe")
+
+
+# Test that directory names in patterns for 'glob-tree' are rejected.
+t.write("d1/jamfile.jam", """
+project : source-location src ;
+exe a : [ glob-tree foo/*.cpp bar/*.cpp : bad* ] ../d2/d//l ;
+""")
+
+t.run_build_system(subdir="d1", status=1)
+t.expect_output_line("error: The patterns * may not include directory")
+
+
+t.rm("d1/src/bar/bad.cpp")
+
+# Test that 'glob' works with absolute names.
+t.rm("d1/bin")
+
+# Note that to get current dir, we use bjam's PWD, not Python's os.getcwd(),
+# because the former will always return long path while the latter might return
+# a short path, and that will confuse path.glob.
+t.write("d1/jamfile.jam", """
+project : source-location src ;
+local pwd = [ PWD ] ; # Always absolute
+exe a : [ glob $(pwd)/src/foo/*.cpp $(pwd)/src/bar/*.cpp ] ../d2/d//l ;
+""")
+
+t.run_build_system(subdir="d1")
+t.expect_addition("d1/bin/$toolset/debug/a.exe")
+
+
+# Regression test: glob excludes used to be broken when building from a
+# subdirectory.
+t.rm(".")
+
+t.write("jamroot.jam", """
+build-project p ;
+""")
+
+t.write("p/p.c", """
+int main() {}
+""")
+
+t.write("p/p_x.c", """
+int main() {}
+""")
+
+t.write("p/jamfile.jam", """
+exe p : [ glob *.c : p_x.c ] ;
+""")
+
+t.run_build_system(subdir="p")
+t.expect_addition("p/bin/$toolset/debug/p.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/project_root_constants.py b/tools/build/v2/test/project_root_constants.py
new file mode 100644
index 0000000000..400c78b4ab
--- /dev/null
+++ b/tools/build/v2/test/project_root_constants.py
@@ -0,0 +1,66 @@
+#!/usr/bin/python
+
+# Copyright 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import string
+
+# Create a temporary working directory.
+t = BoostBuild.Tester()
+
+# Create the needed files.
+t.write("jamroot.jam", """
+constant FOO : foobar gee ;
+ECHO $(FOO) ;
+""")
+
+t.run_build_system()
+t.fail_test(string.find(t.stdout(), "foobar gee") == -1)
+
+# Regression test: when absolute paths were passed to path-constant rule,
+# Boost.Build failed to recognize path as absolute and prepended the current
+# dir.
+t.write("jamroot.jam", """
+import path ;
+local here = [ path.native [ path.pwd ] ] ;
+path-constant HERE : $(here) ;
+if $(HERE) != $(here)
+{
+ ECHO "PWD =" $(here) ;
+ ECHO "path constant =" $(HERE) ;
+ EXIT ;
+}
+""")
+t.write("jamfile.jam", "")
+
+t.run_build_system()
+
+t.write("jamfile.jam", """
+# This tests that rule 'hello' will be imported to children unlocalized, and
+# will still access variables in this Jamfile.
+x = 10 ;
+constant FOO : foo ;
+rule hello ( ) { ECHO "Hello $(x)" ; }
+""")
+
+t.write("d/jamfile.jam", """
+ECHO "d: $(FOO)" ;
+constant BAR : bar ;
+""")
+
+t.write("d/d2/jamfile.jam", """
+ECHO "d2: $(FOO)" ;
+ECHO "d2: $(BAR)" ;
+hello ;
+""")
+
+t.run_build_system(subdir="d/d2")
+t.fail_test(t.stdout().find("""d: foo
+d2: foo
+d2: bar
+Hello 10
+""") == -1)
+
+t.cleanup()
diff --git a/tools/build/v2/test/project_root_rule.py b/tools/build/v2/test/project_root_rule.py
new file mode 100644
index 0000000000..29fdcff4ca
--- /dev/null
+++ b/tools/build/v2/test/project_root_rule.py
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2005.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests that we can declare a rule in Jamroot that will be can be called in
+# child Jamfile to declare a target. Specifically test for use of 'glob' in that
+# rule.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+
+t.write("jamroot.jam", """
+project : requirements <link>static ;
+rule my-lib ( name ) { lib $(name) : [ glob *.cpp ] ; }
+""")
+
+t.write("sub/a.cpp", """
+""")
+
+t.write("sub/jamfile.jam", """
+my-lib foo ;
+""")
+
+
+t.run_build_system(subdir="sub")
+
+t.expect_addition("sub/bin/$toolset/debug/link-static/foo.lib")
+
+t.cleanup()
diff --git a/tools/build/v2/test/project_test1.py b/tools/build/v2/test/project_test1.py
new file mode 100644
index 0000000000..a2a2ada186
--- /dev/null
+++ b/tools/build/v2/test/project_test1.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+
+# Copyright 2002 Dave Abrahams
+# Copyright 2002, 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import os
+
+t = BoostBuild.Tester("--build-system=project-test1", boost_build_path='',
+ pass_toolset=0)
+
+# This test does no modifications, so run in in the invocation dir.
+os.chdir(t.original_workdir)
+
+expected_output1="""Project Roots:
+
+"""
+
+expected_output2="""'%(root-dir-prefix)sdir2':
+
+ Module for project-root is 'project-root<%(root-dir-prefix)sdir2>'
+
+Projects:
+
+'/cool-library':
+
+* Parent project: (none)
+* Requirements: <include>/home/ghost/build/boost-cvs
+* Default build:
+* Source location: %(root-dir-prefix)sdir2
+* Projects to build:
+
+"""
+
+expected_output3="""'%(root-dir)s':
+
+ Module for project-root is 'project-root<%(root-dir)s>'
+
+Projects:
+
+'/boost-build-test-project-1':
+
+* Parent project: (none)
+* Requirements: <include>/home/ghost/local/include <threading>multi
+* Default build:
+* Source location: %(root-dir)s
+* Projects to build: dir dir2
+
+'/boost-build-test-project-1/dir':
+
+* Parent project: %(root-dir)s
+* Requirements: <include>/home/ghost/local/include <threading>multi
+* Default build: <variant>release
+* Source location: %(root-dir-prefix)sdir/src
+* Projects to build:
+
+"""
+
+# Test that correct project structure is created when jam is invoked outside of
+# the source tree.
+expected = (expected_output1 + expected_output2 + expected_output3) % \
+ {"root-dir": "project-test1",
+ "root-dir-prefix": "project-test1/" }
+
+t.run_build_system(stdout=expected)
+
+# Test that correct project structure is created when jam is invoked at the top
+# of the source tree.
+expected = (expected_output1 + expected_output3 + expected_output2) % \
+ {"root-dir": ".",
+ "root-dir-prefix": "" }
+
+os.chdir("project-test1")
+t.run_build_system(stdout=expected)
+
+t.cleanup()
diff --git a/tools/build/v2/test/project_test3.py b/tools/build/v2/test/project_test3.py
new file mode 100644
index 0000000000..8a4421604a
--- /dev/null
+++ b/tools/build/v2/test/project_test3.py
@@ -0,0 +1,133 @@
+#!/usr/bin/python
+
+# Copyright 2002, 2003 Dave Abrahams
+# Copyright 2002, 2003, 2004, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import os
+
+t = BoostBuild.Tester(translate_suffixes=0)
+
+# First check some startup.
+t.set_tree("project-test3")
+os.remove("jamroot.jam")
+t.run_build_system(status=1, stdout=
+"""error: Could not find parent for project at '.'
+error: Did not find Jamfile.jam or Jamroot.jam in any parent directory.
+""")
+
+t.set_tree("project-test3")
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/a.obj")
+t.expect_content("bin/$toolset/debug/a.obj",
+"""$toolset/debug
+a.cpp
+""")
+
+t.expect_addition("bin/$toolset/debug/a.exe")
+t.expect_content("bin/$toolset/debug/a.exe",
+"$toolset/debug\n" +
+"bin/$toolset/debug/a.obj lib/bin/$toolset/debug/b.obj " +
+"lib2/bin/$toolset/debug/c.obj lib2/bin/$toolset/debug/d.obj " +
+"lib2/helper/bin/$toolset/debug/e.obj " +
+"lib3/bin/$toolset/debug/f.obj\n"
+)
+
+t.expect_addition("lib/bin/$toolset/debug/b.obj")
+t.expect_content("lib/bin/$toolset/debug/b.obj",
+"""$toolset/debug
+lib/b.cpp
+""")
+
+t.expect_addition("lib/bin/$toolset/debug/m.exe")
+t.expect_content("lib/bin/$toolset/debug/m.exe",
+"""$toolset/debug
+lib/bin/$toolset/debug/b.obj lib2/bin/$toolset/debug/c.obj
+""")
+
+t.expect_addition("lib2/bin/$toolset/debug/c.obj")
+t.expect_content("lib2/bin/$toolset/debug/c.obj",
+"""$toolset/debug
+lib2/c.cpp
+""")
+
+t.expect_addition("lib2/bin/$toolset/debug/d.obj")
+t.expect_content("lib2/bin/$toolset/debug/d.obj",
+"""$toolset/debug
+lib2/d.cpp
+""")
+
+t.expect_addition("lib2/bin/$toolset/debug/l.exe")
+t.expect_content("lib2/bin/$toolset/debug/l.exe",
+"""$toolset/debug
+lib2/bin/$toolset/debug/c.obj bin/$toolset/debug/a.obj
+""")
+
+t.expect_addition("lib2/helper/bin/$toolset/debug/e.obj")
+t.expect_content("lib2/helper/bin/$toolset/debug/e.obj",
+"""$toolset/debug
+lib2/helper/e.cpp
+""")
+
+t.expect_addition("lib3/bin/$toolset/debug/f.obj")
+t.expect_content("lib3/bin/$toolset/debug/f.obj",
+"""$toolset/debug
+lib3/f.cpp lib2/helper/bin/$toolset/debug/e.obj
+""")
+
+t.touch("a.cpp")
+t.run_build_system()
+t.expect_touch(["bin/$toolset/debug/a.obj",
+ "bin/$toolset/debug/a.exe",
+ "lib2/bin/$toolset/debug/l.exe"])
+
+t.run_build_system(extra_args="release optimization=off,speed")
+t.expect_addition(["bin/$toolset/release/a.exe",
+ "bin/$toolset/release/a.obj",
+ "bin/$toolset/release/optimization-off/a.exe",
+ "bin/$toolset/release/optimization-off/a.obj"])
+
+t.run_build_system(extra_args='--clean-all')
+t.expect_removal(["bin/$toolset/debug/a.obj",
+ "bin/$toolset/debug/a.exe",
+ "lib/bin/$toolset/debug/b.obj",
+ "lib/bin/$toolset/debug/m.exe",
+ "lib2/bin/$toolset/debug/c.obj",
+ "lib2/bin/$toolset/debug/d.obj",
+ "lib2/bin/$toolset/debug/l.exe",
+ "lib3/bin/$toolset/debug/f.obj"])
+
+# Now test target ids in command line.
+t.set_tree("project-test3")
+t.run_build_system("lib//b.obj")
+t.expect_addition("lib/bin/$toolset/debug/b.obj")
+t.expect_nothing_more()
+
+t.run_build_system("--clean lib//b.obj")
+t.expect_removal("lib/bin/$toolset/debug/b.obj")
+t.expect_nothing_more()
+
+t.run_build_system("lib//b.obj")
+t.expect_addition("lib/bin/$toolset/debug/b.obj")
+t.expect_nothing_more()
+
+t.run_build_system("release lib2/helper//e.obj /lib3//f.obj")
+t.expect_addition("lib2/helper/bin/$toolset/release/e.obj")
+t.expect_addition("lib3/bin/$toolset/release/f.obj")
+t.expect_nothing_more()
+
+# Test project ids in command line work as well.
+t.set_tree("project-test3")
+t.run_build_system("/lib2")
+t.expect_addition("lib2/bin/$toolset/debug/" * BoostBuild.List("c.obj d.obj l.exe"))
+t.expect_addition("bin/$toolset/debug/a.obj")
+t.expect_nothing_more()
+
+t.run_build_system("lib")
+t.expect_addition("lib/bin/$toolset/debug/" * BoostBuild.List("b.obj m.exe"))
+t.expect_nothing_more()
+
+t.cleanup()
diff --git a/tools/build/v2/test/project_test4.py b/tools/build/v2/test/project_test4.py
new file mode 100644
index 0000000000..fc4115017b
--- /dev/null
+++ b/tools/build/v2/test/project_test4.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester(translate_suffixes=0)
+
+
+t.set_tree("project-test4")
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/a.obj")
+t.expect_content("bin/$toolset/debug/a.obj",
+"""$toolset/debug/include-everything
+a.cpp
+""")
+
+t.expect_addition("bin/$toolset/debug/a.exe")
+t.expect_content("bin/$toolset/debug/a.exe",
+"$toolset/debug/include-everything\n" +
+"bin/$toolset/debug/a.obj lib/bin/$toolset/debug/optimization-speed/b.obj\n"
+)
+
+t.expect_addition("lib/bin/$toolset/debug/optimization-speed/b.obj")
+t.expect_content("lib/bin/$toolset/debug/optimization-speed/b.obj",
+"""$toolset/debug/include-everything/optimization-speed
+lib/b.cpp
+""")
+
+t.expect_addition("bin/$toolset/debug/b.exe")
+t.expect_content("bin/$toolset/debug/b.exe",
+"$toolset/debug/define-MACROS/include-everything\n" +
+"bin/$toolset/debug/a.obj\n"
+)
+
+t.copy("lib/jamfile3.jam", "lib/jamfile.jam")
+
+# Link-compatibility check for rtti is disabled...
+#t.run_build_system(status=None)
+#import string
+#t.fail_test(string.find(t.stdout(),
+#"""warning: targets produced from b.obj are link incompatible
+#warning: with main target a.exe""") !=-0)
+
+# Test that if we specified composite property in target reference, everything
+# works OK.
+
+t.copy("lib/jamfile1.jam", "lib/jamfile.jam")
+t.copy("jamfile5.jam", "jamfile.jam")
+
+t.run_build_system()
+
+t.expect_addition("lib/bin/$toolset/release/b.obj")
+
+t.expect_content("bin/$toolset/debug/a.exe",
+"$toolset/debug/include-everything\n" +
+"bin/$toolset/debug/a.obj lib/bin/$toolset/release/b.obj\n"
+)
+
+t.cleanup()
diff --git a/tools/build/v2/test/property_expansion.py b/tools/build/v2/test/property_expansion.py
new file mode 100644
index 0000000000..280f862085
--- /dev/null
+++ b/tools/build/v2/test/property_expansion.py
@@ -0,0 +1,29 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that free property inside.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+project ;
+variant debug-AA : debug : <define>AA ;
+alias all : hello ;
+exe hello : hello.cpp ;
+explicit hello ;
+""")
+
+t.write("hello.cpp", """
+#ifdef AA
+int main() {}
+#endif
+""")
+
+t.run_build_system("debug-AA")
+
+t.cleanup()
diff --git a/tools/build/v2/test/qt4.py b/tools/build/v2/test/qt4.py
new file mode 100755
index 0000000000..abb9594d58
--- /dev/null
+++ b/tools/build/v2/test/qt4.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+
+# (c) Copyright Juergen Hunold 2008
+# Use, modification, and distribution are subject to the
+# Boost Software License, Version 1.0. (See accompanying file
+# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import os
+
+# Run test in real directory in order to find Boost.Test via Boost Top-Level
+# Jamroot.
+qt4_dir = os.getcwd() + "/qt4"
+
+t = BoostBuild.Tester(workdir=qt4_dir)
+
+t.run_build_system()
+
+t.cleanup()
diff --git a/tools/build/v2/test/qt4/jamroot.jam b/tools/build/v2/test/qt4/jamroot.jam
new file mode 100644
index 0000000000..eeddc586f0
--- /dev/null
+++ b/tools/build/v2/test/qt4/jamroot.jam
@@ -0,0 +1,79 @@
+# (c) Copyright Juergen Hunold 2008
+# Use, modification, and distribution are subject to the
+# Boost Software License, Version 1.0. (See accompanying file
+# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import qt4 ;
+import testing ;
+import cast ;
+
+
+
+if [ qt4.initialized ]
+{
+ use-project /boost : ../../../../.. ;
+
+ project qttest
+ : requirements
+ <library>/boost/test//boost_unit_test_framework
+ ;
+
+ alias qt-tests :
+ # Check for explicit libraries, <use>/qt should not link any lib
+ [ link-fail qtcorefail.cpp : <use>/qt ]
+
+ [ run qtcore.cpp /qt//QtCore ]
+ [ run qtsql.cpp /qt//QtSql ]
+ [ run qtxml.cpp /qt//QtXml ]
+ [ run qtnetwork.cpp /qt//QtNetwork ]
+ [ run qtscript.cpp /qt//QtScript ]
+ [ run qtscripttools.cpp /qt//QtScriptTools ]
+ [ run qtxmlpatterns.cpp /qt//QtXmlPatterns ]
+
+ # ToDo: runable example code
+ [ link qtsvg.cpp /qt//QtSvg ]
+ [ link qtgui.cpp /qt//QtGui ]
+
+ # Multimedia toolkits.
+ [ link qtwebkit.cpp /qt//QtWebKit ]
+ [ link phonon.cpp /qt//phonon ]
+ [ link qtmultimedia.cpp /qt//QtMultimedia ]
+
+ # QML
+ [ link qtdeclarative.cpp /qt//QtDeclarative ]
+
+ # Help systems.
+ [ link qthelp.cpp /qt//QtHelp ]
+ [ link qtassistant.cpp /qt//QtAssistantClient : <conditional>@check_for_assistant ]
+
+ # Check working and disabled Qt3Support
+ [ link qt3support.cpp /qt//Qt3Support : <qt3support>on ]
+ [ compile-fail qt3support.cpp /qt//Qt3Support : <qt3support>off ]
+
+ # Testing using QtTest. Simple sample
+ # ToDo: better support for "automoc" aka '#include "qttest.moc"'
+ [ run qttest.cpp [ cast _ moccable-cpp : qttest.cpp ] /qt//QtTest : : : <define>TEST_MOCK ]
+
+ # Test moc rule
+ [ run mock.cpp mock.h /qt//QtCore : : : <define>TEST_MOCK ]
+
+ : # requirements
+ : # default-build
+ : # usage-requirements
+ ;
+}
+
+# QtAssistant is removed from Qt >= 4.6
+rule check_for_assistant ( properties * )
+{
+ # Extract version number from toolset
+ local version = [ MATCH "<qt>([0-9.]+).*"
+ : $(properties) ] ;
+
+ if $(version) > "4.6.99"
+ {
+ result += <build>no ;
+ }
+}
+
+
diff --git a/tools/build/v2/test/qt4/mock.cpp b/tools/build/v2/test/qt4/mock.cpp
new file mode 100644
index 0000000000..8f7a35c2dc
--- /dev/null
+++ b/tools/build/v2/test/qt4/mock.cpp
@@ -0,0 +1,26 @@
+// (c) Copyright Juergen Hunold 2011
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtMoc
+
+#include "mock.h"
+
+#include <boost/test/unit_test.hpp>
+
+Mock::Mock()
+{
+}
+
+/*!
+ Check that the compiler get the correct #defines.
+ The logic to test the moc is in the header file "mock.h"
+ */
+BOOST_AUTO_TEST_CASE(construct_mock)
+{
+ delete new Mock();
+
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(TEST_MOCK), true);
+}
diff --git a/tools/build/v2/test/qt4/mock.h b/tools/build/v2/test/qt4/mock.h
new file mode 100644
index 0000000000..1cc95b057a
--- /dev/null
+++ b/tools/build/v2/test/qt4/mock.h
@@ -0,0 +1,21 @@
+// (c) Copyright Juergen Hunold 2011
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <QtCore/QObject>
+
+class Mock : public QObject
+{
+ /*!
+ Test that the moc gets the necessary #defines
+ Else the moc will not see the Q_OBJECT macro, issue a warning
+ and linking will fail due to missing vtable symbols.
+ */
+#if defined(TEST_MOCK)
+ Q_OBJECT
+#endif
+ public:
+
+ Mock();
+};
diff --git a/tools/build/v2/test/qt4/phonon.cpp b/tools/build/v2/test/qt4/phonon.cpp
new file mode 100644
index 0000000000..3151f59115
--- /dev/null
+++ b/tools/build/v2/test/qt4/phonon.cpp
@@ -0,0 +1,23 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtPhonon
+
+#include <phonon/MediaObject>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_GUI_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_XML_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_PHONON_LIB), true);
+}
+
+BOOST_AUTO_TEST_CASE( phonon_object)
+{
+ Phonon::MediaObject player;
+}
diff --git a/tools/build/v2/test/qt4/qt3support.cpp b/tools/build/v2/test/qt4/qt3support.cpp
new file mode 100644
index 0000000000..35d8c73b9d
--- /dev/null
+++ b/tools/build/v2/test/qt4/qt3support.cpp
@@ -0,0 +1,29 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE Qt3Support
+
+#include <Q3Table>
+
+#include <boost/test/unit_test.hpp>
+
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_GUI_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_XML_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_SQL_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_NETWORK_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_QT3SUPPORT_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT3_SUPPORT), true);
+}
+
+BOOST_AUTO_TEST_CASE( q3table )
+{
+ Q3Table q3table;
+
+}
+
diff --git a/tools/build/v2/test/qt4/qtassistant.cpp b/tools/build/v2/test/qt4/qtassistant.cpp
new file mode 100644
index 0000000000..e2a6ed7bd2
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtassistant.cpp
@@ -0,0 +1,21 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtAssistant
+
+#include <QAssistantClient>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_GUI_LIB), true);
+}
+
+BOOST_AUTO_TEST_CASE( empty_assistant)
+{
+ QAssistantClient client(QString());
+}
diff --git a/tools/build/v2/test/qt4/qtcore.cpp b/tools/build/v2/test/qt4/qtcore.cpp
new file mode 100644
index 0000000000..f3c09039be
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtcore.cpp
@@ -0,0 +1,22 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtCore
+#include <QtCore>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE (defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+}
+
+
+BOOST_AUTO_TEST_CASE( qstring_test)
+{
+ QString dummy;
+
+ BOOST_CHECK_EQUAL(dummy.isEmpty(), true);
+}
diff --git a/tools/build/v2/test/qt4/qtcorefail.cpp b/tools/build/v2/test/qt4/qtcorefail.cpp
new file mode 100644
index 0000000000..15fd36aef8
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtcorefail.cpp
@@ -0,0 +1,23 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtCoreFail
+
+#include <QtCore>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE (defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+}
+
+
+BOOST_AUTO_TEST_CASE( qstring_test)
+{
+ QString dummy;
+
+ BOOST_CHECK_EQUAL(dummy.isEmpty(), true);
+}
diff --git a/tools/build/v2/test/qt4/qtdeclarative.cpp b/tools/build/v2/test/qt4/qtdeclarative.cpp
new file mode 100644
index 0000000000..817855bad1
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtdeclarative.cpp
@@ -0,0 +1,27 @@
+// (c) Copyright Juergen Hunold 2011
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtMultimedia
+
+#include <QApplication>
+#include <QDeclarativeView>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_GUI_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_XML_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_DECLARATIVE_LIB), true);
+}
+
+
+BOOST_AUTO_TEST_CASE( declarative )
+{
+ QApplication app(boost::unit_test::framework::master_test_suite().argc,
+ boost::unit_test::framework::master_test_suite().argv);
+ QDeclarativeView view;
+}
diff --git a/tools/build/v2/test/qt4/qtgui.cpp b/tools/build/v2/test/qt4/qtgui.cpp
new file mode 100644
index 0000000000..478e07a2af
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtgui.cpp
@@ -0,0 +1,42 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtGui
+
+#include <QApplication>
+
+#include <boost/test/unit_test.hpp>
+
+struct Fixture
+{
+ Fixture()
+ : application(boost::unit_test::framework::master_test_suite().argc,
+ boost::unit_test::framework::master_test_suite().argv,
+ false)
+ {
+ BOOST_TEST_MESSAGE( "setup QApplication fixture" );
+ }
+
+ ~Fixture()
+ {
+ BOOST_TEST_MESSAGE( "teardown QApplication fixture" );
+ }
+
+ QApplication application;
+};
+
+BOOST_GLOBAL_FIXTURE( Fixture )
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_GUI_LIB), true);
+}
+
+
+BOOST_AUTO_TEST_CASE( qtgui_test)
+{
+ BOOST_CHECK_EQUAL(true, true);
+}
diff --git a/tools/build/v2/test/qt4/qthelp.cpp b/tools/build/v2/test/qt4/qthelp.cpp
new file mode 100644
index 0000000000..32327de58b
--- /dev/null
+++ b/tools/build/v2/test/qt4/qthelp.cpp
@@ -0,0 +1,22 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtHelp
+
+#include <QtHelp>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_GUI_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_XML_LIB), true);
+}
+
+BOOST_AUTO_TEST_CASE( empty_engine)
+{
+ QHelpEngine engine(QString());
+}
diff --git a/tools/build/v2/test/qt4/qtmultimedia.cpp b/tools/build/v2/test/qt4/qtmultimedia.cpp
new file mode 100644
index 0000000000..dc5914aff3
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtmultimedia.cpp
@@ -0,0 +1,25 @@
+// (c) Copyright Juergen Hunold 2009
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtMultimedia
+
+#include <QAudioDeviceInfo>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_GUI_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_MULTIMEDIA_LIB), true);
+}
+
+BOOST_AUTO_TEST_CASE( audiodevices)
+{
+ QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
+ for(int i = 0; i < devices.size(); ++i) {
+ BOOST_TEST_MESSAGE(QAudioDeviceInfo(devices.at(i)).deviceName().constData());
+ }
+}
diff --git a/tools/build/v2/test/qt4/qtnetwork.cpp b/tools/build/v2/test/qt4/qtnetwork.cpp
new file mode 100644
index 0000000000..3f628d880c
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtnetwork.cpp
@@ -0,0 +1,33 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtNetwork
+
+#include <QHostInfo>
+
+#include <QTextStream>
+
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+BOOST_AUTO_TEST_CASE (defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_NETWORK_LIB), true);
+}
+
+BOOST_AUTO_TEST_CASE( hostname )
+{
+ QHostInfo info(QHostInfo::fromName("www.boost.org")); //blocking lookup
+
+ QTextStream stream(stdout, QIODevice::WriteOnly);
+
+ Q_FOREACH(QHostAddress address, info.addresses())
+ {
+ BOOST_CHECK_EQUAL(address.isNull(), false);
+ stream << address.toString() << endl;
+ }
+}
diff --git a/tools/build/v2/test/qt4/qtscript.cpp b/tools/build/v2/test/qt4/qtscript.cpp
new file mode 100644
index 0000000000..65353daeca
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtscript.cpp
@@ -0,0 +1,37 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtScript
+
+#include <QScriptEngine>
+
+#include <QCoreApplication>
+
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+std::ostream&
+operator << (std::ostream& stream, QString const& string)
+{
+ stream << qPrintable(string);
+ return stream;
+}
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_SCRIPT_LIB), true);
+}
+
+BOOST_AUTO_TEST_CASE( script )
+{
+ QCoreApplication app(boost::unit_test::framework::master_test_suite().argc,
+ boost::unit_test::framework::master_test_suite().argv);
+ QScriptEngine myEngine;
+ QScriptValue three = myEngine.evaluate("1 + 2");
+
+ BOOST_CHECK_EQUAL(three.toNumber(), 3);
+ BOOST_CHECK_EQUAL(three.toString(), QLatin1String("3"));
+}
diff --git a/tools/build/v2/test/qt4/qtscripttools.cpp b/tools/build/v2/test/qt4/qtscripttools.cpp
new file mode 100644
index 0000000000..4d0b7f2560
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtscripttools.cpp
@@ -0,0 +1,47 @@
+// (c) Copyright Juergen Hunold 2009
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtScriptTools
+
+#include <QScriptEngine>
+
+#include <QScriptEngineDebugger>
+
+#include <QApplication>
+
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+namespace utf = boost::unit_test::framework;
+
+std::ostream&
+operator << (std::ostream& stream, QString const& string)
+{
+ stream << qPrintable(string);
+ return stream;
+}
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_SCRIPTTOOLS_LIB), true);
+}
+
+BOOST_AUTO_TEST_CASE( script )
+{
+ QApplication app(utf::master_test_suite().argc,
+ utf::master_test_suite().argv);
+
+ QScriptEngine myEngine;
+ QScriptValue three = myEngine.evaluate("1 + 2");
+
+ QScriptEngineDebugger debugger;
+ debugger.attachTo(&myEngine);
+
+ BOOST_CHECK_EQUAL(three.toNumber(), 3);
+ BOOST_CHECK_EQUAL(three.toString(), QLatin1String("3"));
+
+ debugger.detach();
+}
diff --git a/tools/build/v2/test/qt4/qtsql.cpp b/tools/build/v2/test/qt4/qtsql.cpp
new file mode 100644
index 0000000000..aa506b1c7c
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtsql.cpp
@@ -0,0 +1,37 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtSql
+
+#include <QSqlDatabase>
+
+#include <QTextStream>
+#include <QStringList>
+
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+BOOST_AUTO_TEST_CASE (defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_SQL_LIB), true);
+}
+
+BOOST_AUTO_TEST_CASE( drivers )
+{
+ QTextStream stream(stdout, QIODevice::WriteOnly);
+
+ Q_FOREACH(QString it, QSqlDatabase:: drivers())
+ {
+ stream << it << endl;
+ }
+}
+
+BOOST_AUTO_TEST_CASE( construct )
+{
+ QSqlDatabase database;
+ BOOST_CHECK_EQUAL(database.isOpen(), false);
+}
diff --git a/tools/build/v2/test/qt4/qtsvg.cpp b/tools/build/v2/test/qt4/qtsvg.cpp
new file mode 100644
index 0000000000..8a13943805
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtsvg.cpp
@@ -0,0 +1,21 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtSvg
+
+#include <QtSvg>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_SVG_LIB), true);
+}
+
+BOOST_AUTO_TEST_CASE( generator_construct)
+{
+ QSvgGenerator generator;
+}
diff --git a/tools/build/v2/test/qt4/qttest.cpp b/tools/build/v2/test/qt4/qttest.cpp
new file mode 100644
index 0000000000..a2744cdc73
--- /dev/null
+++ b/tools/build/v2/test/qt4/qttest.cpp
@@ -0,0 +1,30 @@
+// (c) Copyright Juergen Hunold 2008-2011
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <QtTest>
+
+class QtTest: public QObject
+{
+ /*!
+ Test if the moc gets the #define
+ */
+#if defined(TEST_MOCK)
+ Q_OBJECT
+#endif
+
+private Q_SLOTS:
+ void toUpper();
+};
+
+void
+QtTest::toUpper()
+{
+ QString str = "Hello";
+ QCOMPARE(str.toUpper(), QString("HELLO"));
+}
+
+QTEST_MAIN(QtTest)
+#include "qttest.moc"
+
diff --git a/tools/build/v2/test/qt4/qtwebkit.cpp b/tools/build/v2/test/qt4/qtwebkit.cpp
new file mode 100644
index 0000000000..7d85f14731
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtwebkit.cpp
@@ -0,0 +1,24 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtWebKit
+
+#include <QWebPage>
+#include <QApplication>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_GUI_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_WEBKIT_LIB), true);
+}
+
+BOOST_AUTO_TEST_CASE( webkit )
+{
+ QWebPage page;
+ BOOST_CHECK_EQUAL(page.isModified(), false);
+}
diff --git a/tools/build/v2/test/qt4/qtxml.cpp b/tools/build/v2/test/qt4/qtxml.cpp
new file mode 100644
index 0000000000..8002c26584
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtxml.cpp
@@ -0,0 +1,29 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtXml
+
+#include <QtXml>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_XML_LIB), true);
+}
+
+BOOST_AUTO_TEST_CASE( reader_construct)
+{
+ QXmlStreamReader reader;
+ BOOST_CHECK_EQUAL(reader.atEnd(), false);
+}
+
+BOOST_AUTO_TEST_CASE( writer_construct)
+{
+ QXmlStreamWriter writer;
+ BOOST_CHECK_EQUAL(writer.device(), static_cast<QIODevice*>(0));
+}
+
diff --git a/tools/build/v2/test/qt4/qtxmlpatterns.cpp b/tools/build/v2/test/qt4/qtxmlpatterns.cpp
new file mode 100644
index 0000000000..dcec92fd34
--- /dev/null
+++ b/tools/build/v2/test/qt4/qtxmlpatterns.cpp
@@ -0,0 +1,76 @@
+// (c) Copyright Juergen Hunold 2008
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE QtXmlPatterns
+
+#include <QXmlQuery>
+#include <QXmlSerializer>
+
+#include <QCoreApplication>
+#include <QString>
+#include <QTextStream>
+#include <QBuffer>
+
+#include <boost/test/unit_test.hpp>
+
+
+struct Fixture
+{
+ Fixture()
+ : application(boost::unit_test::framework::master_test_suite().argc,
+ boost::unit_test::framework::master_test_suite().argv)
+ {
+ BOOST_TEST_MESSAGE( "setup QCoreApplication fixture" );
+ }
+
+ ~Fixture()
+ {
+ BOOST_TEST_MESSAGE( "teardown QCoreApplication fixture" );
+ }
+
+ QCoreApplication application;
+};
+
+BOOST_GLOBAL_FIXTURE( Fixture )
+
+QByteArray doc("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml/\" xml:lang=\"en\" lang=\"en\">"
+" <head>"
+" <title>Global variables report for globals.gccxml</title>"
+" </head>"
+"<body><p>Some Test text</p></body></html>");
+
+BOOST_AUTO_TEST_CASE( defines)
+{
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_CORE_LIB), true);
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_XMLPATTERNS_LIB), true);
+
+ BOOST_CHECK_EQUAL(BOOST_IS_DEFINED(QT_XML_LIB), false);
+}
+
+BOOST_AUTO_TEST_CASE( extract )
+{
+
+ QBuffer buffer(&doc); // This is a QIODevice.
+ buffer.open(QIODevice::ReadOnly);
+ QXmlQuery query;
+ query.bindVariable("myDocument", &buffer);
+ query.setQuery("declare variable $myDocument external;"
+ "doc($myDocument)");///p[1]");
+
+ BOOST_CHECK_EQUAL(query.isValid(), true);
+
+ QByteArray result;
+ QBuffer out(&result);
+ out.open(QIODevice::WriteOnly);
+
+ QXmlSerializer serializer(query, &out);
+ BOOST_CHECK_EQUAL(query.evaluateTo(&serializer), true);
+
+ QTextStream stream(stdout);
+ BOOST_CHECK_EQUAL(result.isEmpty(), false);
+ stream << "hallo" << result << endl;
+}
+
diff --git a/tools/build/v2/test/railsys.py b/tools/build/v2/test/railsys.py
new file mode 100644
index 0000000000..7b7f8bd0bd
--- /dev/null
+++ b/tools/build/v2/test/railsys.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree("railsys")
+t.run_build_system("--v2", subdir="program")
+
+t.cleanup()
diff --git a/tools/build/v2/test/railsys/libx/include/test_libx.h b/tools/build/v2/test/railsys/libx/include/test_libx.h
new file mode 100644
index 0000000000..fe573fc16f
--- /dev/null
+++ b/tools/build/v2/test/railsys/libx/include/test_libx.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2003 Institute of Transport,
+// Railway Construction and Operation,
+// University of Hanover, Germany
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifdef _WIN32
+#ifdef LIBX_SOURCE
+__declspec(dllexport)
+#else
+__declspec(dllimport)
+#endif
+#endif
+class TestLibX
+{
+public:
+
+ TestLibX();
+
+ // Needed to suppress 'unused variable' warning
+ // in some cases.
+ void do_something() {}
+};
diff --git a/tools/build/v2/test/railsys/libx/jamroot.jam b/tools/build/v2/test/railsys/libx/jamroot.jam
new file mode 100644
index 0000000000..d09982dd1a
--- /dev/null
+++ b/tools/build/v2/test/railsys/libx/jamroot.jam
@@ -0,0 +1,13 @@
+# Copyright (c) 2002 Institute of Transport,
+# Railway Construction and Operation,
+# University of Hanover, Germany
+# Copyright (c) 2006 Jürgen Hunold
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Tell that Qt3 should be used. QTDIR will give installation prefix.
+using qt3 ;
+
+
diff --git a/tools/build/v2/test/railsys/libx/src/jamfile.jam b/tools/build/v2/test/railsys/libx/src/jamfile.jam
new file mode 100644
index 0000000000..639e0cc90b
--- /dev/null
+++ b/tools/build/v2/test/railsys/libx/src/jamfile.jam
@@ -0,0 +1,19 @@
+# Copyright (c) 2003 Institute of Transport,
+# Railway Construction and Operation,
+# University of Hanover, Germany
+#
+# Copyright (c) 2006 Jürgen Hunold
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+project libx
+ : requirements
+ <include>../include
+ : usage-requirements
+ <include>../include
+ ;
+
+
+lib libx : test_libx.cpp ;
diff --git a/tools/build/v2/test/railsys/libx/src/test_libx.cpp b/tools/build/v2/test/railsys/libx/src/test_libx.cpp
new file mode 100644
index 0000000000..be1fbc27f7
--- /dev/null
+++ b/tools/build/v2/test/railsys/libx/src/test_libx.cpp
@@ -0,0 +1,15 @@
+// Copyright (c) 2003 Institute of Transport,
+// Railway Construction and Operation,
+// University of Hanover, Germany
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#define LIBX_SOURCE
+#include <test_libx.h>
+
+TestLibX::TestLibX()
+{
+}
diff --git a/tools/build/v2/test/railsys/program/include/test_a.h b/tools/build/v2/test/railsys/program/include/test_a.h
new file mode 100644
index 0000000000..8002859e15
--- /dev/null
+++ b/tools/build/v2/test/railsys/program/include/test_a.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2003 Institute of Transport,
+// Railway Construction and Operation,
+// University of Hanover, Germany
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#include <qobject.h>
+
+class TestA : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ TestA();
+
+ // Needed to suppress 'unused variable' varning.
+ void do_something() { }
+};
diff --git a/tools/build/v2/test/railsys/program/jamfile.jam b/tools/build/v2/test/railsys/program/jamfile.jam
new file mode 100644
index 0000000000..9d66f2dbb5
--- /dev/null
+++ b/tools/build/v2/test/railsys/program/jamfile.jam
@@ -0,0 +1,45 @@
+# ================================================================
+#
+# Railsys
+# --------------
+#
+# Copyright (c) 2002 Institute of Transport,
+# Railway Construction and Operation,
+# University of Hanover, Germany
+# Copyright (c) 2006 Jürgen Hunold
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+# 02/21/02! Jürgen Hunold
+#
+# $Id: jamfile.jam 55188 2009-07-26 20:11:03Z danieljames $
+#
+# ================================================================
+
+local BOOST_ROOT = [ modules.peek : BOOST_ROOT ] ;
+
+use-project /libx : ../libx/src ;
+
+project program
+ : requirements
+ <include>$(BOOST_ROOT)
+ <threading>multi
+ <library>/qt3//qt
+ <hardcode-dll-paths>true
+ <stdlib>stlport
+ <use>/libx
+ <library>/libx//libx
+
+ : usage-requirements
+ <include>$(BOOST_ROOT)
+ :
+ default-build release
+ <threading>multi
+ <library>/qt3//qt
+ <hardcode-dll-paths>true
+ ;
+
+build-project main ;
+
diff --git a/tools/build/v2/test/railsys/program/jamroot.jam b/tools/build/v2/test/railsys/program/jamroot.jam
new file mode 100644
index 0000000000..23d42195f7
--- /dev/null
+++ b/tools/build/v2/test/railsys/program/jamroot.jam
@@ -0,0 +1,14 @@
+# Copyright (c) 2002 Institute of Transport,
+# Railway Construction and Operation,
+# University of Hanover, Germany
+# Copyright (c) 2006 Jürgen Hunold
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Tell that Qt3 should be used. QTDIR will give installation prefix.
+using qt3 ;
+
+# Not that good, but sufficient for testing
+using stlport : : /path/to/stlport ;
diff --git a/tools/build/v2/test/railsys/program/liba/jamfile.jam b/tools/build/v2/test/railsys/program/liba/jamfile.jam
new file mode 100644
index 0000000000..f74311d0d0
--- /dev/null
+++ b/tools/build/v2/test/railsys/program/liba/jamfile.jam
@@ -0,0 +1,14 @@
+# Copyright (c) 2003 Institute of Transport,
+# Railway Construction and Operation,
+# University of Hanover, Germany
+# Copyright (c) 2006 Jürgen Hunold
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+project liba ;
+
+lib liba : test ../include/test_a.h ;
+
+obj test : test_a.cpp : <optimization>off ;
diff --git a/tools/build/v2/test/railsys/program/liba/test_a.cpp b/tools/build/v2/test/railsys/program/liba/test_a.cpp
new file mode 100644
index 0000000000..f9e5388570
--- /dev/null
+++ b/tools/build/v2/test/railsys/program/liba/test_a.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2003 Institute of Transport,
+// Railway Construction and Operation,
+// University of Hanover, Germany
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "../include/test_a.h"
+
+#include <test_libx.h>
+
+TestA::TestA()
+{
+ TestLibX aTestLibX;
+ aTestLibX.do_something();
+}
diff --git a/tools/build/v2/test/railsys/program/main/jamfile.jam b/tools/build/v2/test/railsys/program/main/jamfile.jam
new file mode 100644
index 0000000000..095978eaf9
--- /dev/null
+++ b/tools/build/v2/test/railsys/program/main/jamfile.jam
@@ -0,0 +1,12 @@
+# Copyright (c) 2002 Institute of Transport,
+# Railway Construction and Operation,
+# University of Hanover, Germany
+# Copyright (c) 2006 Jürgen Hunold
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+project main ;
+
+exe test_a : main.cpp ../liba//liba /libx ;
diff --git a/tools/build/v2/test/railsys/program/main/main.cpp b/tools/build/v2/test/railsys/program/main/main.cpp
new file mode 100644
index 0000000000..3f13f4bfc4
--- /dev/null
+++ b/tools/build/v2/test/railsys/program/main/main.cpp
@@ -0,0 +1,19 @@
+// Copyright (c) 2002 Institute of Transport,
+// Railway Construction and Operation,
+// University of Hanover, Germany
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "../include/test_a.h"
+
+#include <test_libx.h>
+
+int main()
+{
+ TestLibX stTestLibX;
+ TestA stTestA;
+
+ stTestLibX.do_something();
+};
diff --git a/tools/build/v2/test/readme.txt b/tools/build/v2/test/readme.txt
new file mode 100644
index 0000000000..48459f805c
--- /dev/null
+++ b/tools/build/v2/test/readme.txt
@@ -0,0 +1,6 @@
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+ See test_system.html for detailed information on using the Boost Build test
+system.
diff --git a/tools/build/v2/test/rebuilds.py b/tools/build/v2/test/rebuilds.py
new file mode 100644
index 0000000000..da64eada3a
--- /dev/null
+++ b/tools/build/v2/test/rebuilds.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+# Copyright 2005 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write('file.jam', '''
+rule make
+{
+ DEPENDS $(<) : $(>) ;
+ DEPENDS all : $(<) ;
+}
+actions make
+{
+ echo "******" making $(<) from $(>) "******"
+ echo made from $(>) > $(<)
+}
+
+make aux1 : bar ;
+make foo : bar ;
+REBUILDS foo : bar ;
+make bar : baz ;
+make aux2 : bar ;
+''')
+
+t.write('baz', 'nothing\n')
+
+t.run_build_system('-ffile.jam bar')
+t.expect_addition('bar')
+t.expect_nothing_more()
+
+t.wait_for_time_change_since_last_build()
+t.run_build_system('-ffile.jam foo')
+t.expect_touch('bar')
+t.expect_addition('foo')
+t.expect_nothing_more()
+
+t.run_build_system('-ffile.jam')
+t.expect_addition(['aux1', 'aux2'])
+t.expect_nothing_more()
+
+t.touch('bar')
+t.run_build_system('-ffile.jam')
+t.expect_touch(['foo', 'aux1', 'aux2'])
+t.expect_nothing_more()
+
+t.cleanup()
diff --git a/tools/build/v2/test/recursive.jam b/tools/build/v2/test/recursive.jam
new file mode 100644
index 0000000000..8087f7da75
--- /dev/null
+++ b/tools/build/v2/test/recursive.jam
@@ -0,0 +1,117 @@
+# Copyright 2001, 2002 Dave Abrahams
+# Copyright 2005 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+##############################################################
+# Rules and actions that test Jam by invoking it recursively #
+# #
+# This is necessary for testing anything that requires Jam #
+# to execute build actions whose results must be checked, #
+# and anything which exits Jam with a failure code (e.g. a #
+# failed assertion). #
+##############################################################
+
+# Creates a fake target, always built, which succeeds in building if Invoking a
+# Jamfile containing the given string succeeds. If optional-expected-output is
+# supplied, creates another fake target which succeeds in building if
+# optional-expected-output is in the Jam output.
+#
+# RETURNS: the target name of the Jam command.
+rule Jam ( command : expected-output ? )
+{
+ local jam-cmd = "$(command:G=jam_command)" ;
+
+ NOTFILE "$(jam-cmd)" ;
+ ALWAYS "$(jam-cmd)" ;
+ DEPENDS all : "$(jam-cmd)" ;
+
+ if ($NT)
+ {
+ redirect on $(jam-cmd) = "nul" ;
+ }
+ else if $(UNIX)
+ {
+ redirect on $(jam-cmd) = "/dev/null" ;
+ }
+
+ if $(VERBOSE)
+ {
+ redirect on $(jam-cmd) = ;
+ }
+
+ invoke-Jam "$(jam-cmd)" ;
+
+ if $(expected-output)
+ {
+ redirect on $(jam-cmd) = "scratch-output.txt" ;
+ local output-target = "$(expected-output:G=$(command))" ;
+ NOTFILE "$(output-target)" ;
+ ALWAYS "$(output-target)" ;
+ DEPENDS all : "$(output-target)" ;
+ Expect-in-output "$(output-target)" ;
+
+ if $(VERBOSE)
+ {
+ if $(NT) { VERBOSE on $(output-target) = "type " ; }
+ else { VERBOSE on $(output-target) = "cat " ; }
+ }
+ }
+ return $(jam-cmd) ;
+}
+
+# Just like the "Jam" rule, above, but only succeeds if the Jam command /fails/.
+rule Jam-fail ( command : expected-output ? )
+{
+ local target = [ Jam $(command) : $(expected-output) ] ;
+ FAIL_EXPECTED $(target) ;
+ return $(target) ;
+}
+
+# The temporary jamfile we write is called "temp.jam". If the user has set
+# BOOST_BUILD_ROOT, it will be built there.
+gBOOST_TEST_JAMFILE = temp.jam ;
+LOCATE on gBOOST_TEST_JAMFILE ?= $(BOOST_BUILD_ROOT) ;
+
+# Runs Jam on a temporary Jamfile which contains the string in $(command:G=)
+# and redirects the results into a file whose name is given by $(redirect) on
+# command
+rule invoke-Jam ( command )
+{
+ PREFIX on $(command) = "actions unbuilt { } unbuilt all ;" ;
+ if $(NT)
+ {
+ REMOVE on $(command) = $(SystemRoot)\System32\find ;
+ }
+ REMOVE on $(command) ?= rm ;
+}
+actions invoke-Jam
+{
+ echo $(PREFIX) $(<:G=) > $(gBOOST_TEST_JAMFILE)
+ jam -sBOOST_ROOT=../../.. -sJAMFILE=$(gBOOST_TEST_JAMFILE) $(JAMARGS) >$(redirect)
+}
+# $(REMOVE) $(gBOOST_TEST_JAMFILE)
+
+
+# These actions expect to find the ungristed part of $(<) in scratch-output.txt
+# and return a nonzero exit code otherwise
+if $(NT)
+{
+ # Explicitly get the NT find command in case someone has another find in their path.
+ actions quietly Expect-in-output
+ {
+ $(VERBOSE)scratch-output.txt ;
+ $(SystemRoot)\System32\find /C "$(<:G=)" scratch-output.txt >nul
+ }
+}
+else
+{
+ # Not really the right actions for Unix; the argument will be interpreted as
+ # a regular expression. Is there a simpler find?
+ actions quietly Expect-in-output
+ {
+ $(VERBOSE)scratch-output.txt;
+ grep "$(<:G=)" scratch-output.txt
+ }
+}
+
diff --git a/tools/build/v2/test/regression.py b/tools/build/v2/test/regression.py
new file mode 100644
index 0000000000..c65082810e
--- /dev/null
+++ b/tools/build/v2/test/regression.py
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2003.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test for the regression testing framework.
+
+import BoostBuild
+
+# Create a temporary working directory.
+t = BoostBuild.Tester()
+
+t.write("c.cpp", "\n")
+
+t.write("r.cpp", """
+void helper();
+
+#include <iostream>
+int main( int ac, char * av[] )
+{
+ helper();
+ for ( int i = 1; i < ac; ++i )
+ std::cout << av[ i ] << '\\n';
+}
+""")
+
+t.write("c-f.cpp", """
+int
+""")
+
+t.write("r-f.cpp", """
+int main() { return 1; }
+""")
+
+
+t.write("jamfile.jam", """
+import testing ;
+compile c.cpp ;
+compile-fail c-f.cpp ;
+run r.cpp libs//helper : foo bar ;
+run-fail r-f.cpp ;
+""")
+
+t.write("libs/jamfile.jam", """
+lib helper : helper.cpp ;
+""")
+
+t.write("libs/helper.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+helper() {}
+""")
+
+t.write("jamroot.jam", "")
+
+# First test that when outcomes are expected, all .test files are created.
+t.run_build_system("hardcode-dll-paths=false", stderr=None, status=None)
+t.expect_addition("bin/c.test/$toolset/debug/c.test")
+t.expect_addition("bin/c-f.test/$toolset/debug/c-f.test")
+t.expect_addition("bin/r.test/$toolset/debug/r.test")
+t.expect_addition("bin/r-f.test/$toolset/debug/r-f.test")
+
+# Make sure args are handled.
+t.expect_content("bin/r.test/$toolset/debug/r.output",
+ "foo\nbar\n*\nEXIT STATUS: 0*\n", True)
+
+# Test that input file is handled as well.
+t.write("r.cpp", """
+#include <iostream>
+#include <fstream>
+int main( int ac, char * av[] )
+{
+ for ( int i = 1; i < ac; ++i )
+ {
+ std::ifstream ifs( av[ i ] );
+ std::cout << ifs.rdbuf();
+ }
+}
+""")
+
+t.write("dir/input.txt", "test input")
+
+t.write("jamfile.jam", """
+import testing ;
+compile c.cpp ;
+obj c-obj : c.cpp ;
+compile-fail c-f.cpp ;
+run r.cpp : : dir/input.txt ;
+run-fail r-f.cpp ;
+time execution : r ;
+time compilation : c-obj ;
+""")
+
+t.run_build_system('hardcode-dll-paths=false')
+t.expect_content("bin/r.test/$toolset/debug/r.output",
+ "test input\nEXIT STATUS: 0\n")
+
+t.expect_addition('bin/$toolset/debug/execution.time')
+t.expect_addition('bin/$toolset/debug/compilation.time')
+
+# Make sure test failures are detected. Reverse expectation and see if .test
+# files are created or not.
+t.write("jamfile.jam", """
+import testing ;
+
+compile-fail c.cpp ;
+compile c-f.cpp ;
+run-fail r.cpp : : dir/input.txt ;
+run r-f.cpp ;
+""")
+
+t.touch(BoostBuild.List("c.cpp c-f.cpp r.cpp r-f.cpp"))
+
+t.run_build_system("hardcode-dll-paths=false", stderr=None, status=1)
+t.expect_removal("bin/c.test/$toolset/debug/c.test")
+t.expect_removal("bin/c-f.test/$toolset/debug/c-f.test")
+t.expect_removal("bin/r.test/$toolset/debug/r.test")
+t.expect_removal("bin/r-f.test/$toolset/debug/r-f.test")
+
+t.cleanup()
diff --git a/tools/build/v2/test/relative_sources.py b/tools/build/v2/test/relative_sources.py
new file mode 100644
index 0000000000..021d5975aa
--- /dev/null
+++ b/tools/build/v2/test/relative_sources.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that we can specify sources using relative names.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+# Test that relative path to source, 'src', is preserved.
+t.write("jamroot.jam", "exe a : src/a.cpp ;")
+t.write("src/a.cpp", "int main() {}\n")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/src/a.obj")
+
+# Test that the relative path to source is preserved
+# when using 'glob'.
+t.rm("bin")
+t.write("jamroot.jam", "exe a : [ glob src/*.cpp ] ;")
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/src/a.obj")
+
+
+# Test that relative path with ".." is *not* added to
+# target path.
+t.rm(".")
+t.write("jamroot.jam", "")
+t.write("a.cpp", "int main() { return 0; }\n")
+t.write("build/Jamfile", "exe a : ../a.cpp ; ")
+t.run_build_system(subdir="build")
+t.expect_addition("build/bin/$toolset/debug/a.obj")
+
+t.cleanup()
diff --git a/tools/build/v2/test/remove_requirement.py b/tools/build/v2/test/remove_requirement.py
new file mode 100644
index 0000000000..b060a2ab79
--- /dev/null
+++ b/tools/build/v2/test/remove_requirement.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+
+t.write("jamroot.jam", """
+project : requirements <threading>multi <variant>debug:<link>static ;
+
+build-project sub ;
+build-project sub2 ;
+build-project sub3 ;
+build-project sub4 ;
+""")
+
+t.write("sub/jamfile.jam", """
+exe hello : hello.cpp : -<threading>multi ;
+""")
+
+t.write("sub/hello.cpp", """
+int main() {}
+""")
+
+t.write("sub2/jamfile.jam", """
+project : requirements -<threading>multi ;
+exe hello : hello.cpp ;
+""")
+
+t.write("sub2/hello.cpp", """
+int main() {}
+""")
+
+t.write("sub3/hello.cpp", """
+int main() {}
+""")
+
+t.write("sub3/jamfile.jam", """
+exe hello : hello.cpp : -<variant>debug:<link>static ;
+""")
+
+t.write("sub4/hello.cpp", """
+int main() {}
+""")
+
+t.write("sub4/jamfile.jam", """
+project : requirements -<variant>debug:<link>static ;
+exe hello : hello.cpp ;
+""")
+
+t.run_build_system()
+
+t.expect_addition("sub/bin/$toolset/debug/link-static/hello.exe")
+t.expect_addition("sub2/bin/$toolset/debug/link-static/hello.exe")
+t.expect_addition("sub3/bin/$toolset/debug/threading-multi/hello.exe")
+t.expect_addition("sub4/bin/$toolset/debug/threading-multi/hello.exe")
+
+t.rm(".")
+
+# Now test that path requirements can be removed as well.
+t.write("jamroot.jam", """
+build-project sub ;
+""")
+
+t.write("sub/jamfile.jam", """
+project : requirements <include>broken ;
+exe hello : hello.cpp : -<include>broken ;
+""")
+
+t.write("sub/hello.cpp", """
+#include "math.h"
+int main() {}
+""")
+
+t.write("sub/broken/math.h", """
+Broken
+""")
+
+
+t.run_build_system()
+
+t.expect_addition("sub/bin/$toolset/debug/hello.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/resolution.py b/tools/build/v2/test/resolution.py
new file mode 100644
index 0000000000..31c122e197
--- /dev/null
+++ b/tools/build/v2/test/resolution.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests for the target id resolution process.
+
+import BoostBuild
+
+# Create a temporary working directory.
+t = BoostBuild.Tester()
+
+# Create the needed files
+t.write("jamroot.jam", """
+exe hello : hello.cpp ;
+# This should use the 'hello' target, even if there is a 'hello' file in the
+# current dir.
+install s : hello : <location>. ;
+""")
+
+t.write("hello.cpp", """
+int main() {}
+""")
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/hello.obj")
+
+t.touch("hello.cpp")
+t.run_build_system("s")
+# If 'hello' in the 's' target resolved to file in the current dir, nothing will
+# be rebuilt.
+t.expect_touch("bin/$toolset/debug/hello.obj")
+
+t.cleanup()
diff --git a/tools/build/v2/test/searched_lib.py b/tools/build/v2/test/searched_lib.py
new file mode 100644
index 0000000000..efbca36ca2
--- /dev/null
+++ b/tools/build/v2/test/searched_lib.py
@@ -0,0 +1,187 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test usage of searched-libs: one which are found via -l
+# switch to the linker/compiler.
+
+import BoostBuild
+import os
+import string
+
+t = BoostBuild.Tester()
+
+
+# To start with, we have to prepare a library to link with.
+t.write("lib/jamroot.jam", "")
+t.write("lib/jamfile.jam", "lib test_lib : test_lib.cpp ;")
+t.write("lib/test_lib.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {}
+""");
+
+t.run_build_system(subdir="lib")
+t.expect_addition("lib/bin/$toolset/debug/test_lib.dll")
+
+
+# Auto adjusting of suffixes does not work, since we need to
+# change dll to lib.
+if ( ( os.name == "nt" ) or os.uname()[0].lower().startswith("cygwin") ) and \
+ ( BoostBuild.get_toolset() != "gcc" ):
+ t.copy("lib/bin/$toolset/debug/test_lib.implib", "lib/test_lib.implib")
+ t.copy("lib/bin/$toolset/debug/test_lib.dll", "lib/test_lib.dll")
+else:
+ t.copy("lib/bin/$toolset/debug/test_lib.dll", "lib/test_lib.dll")
+
+
+# Test that the simplest usage of searched library works.
+t.write("jamroot.jam", "")
+
+t.write("jamfile.jam", """
+import path ;
+import project ;
+
+exe main : main.cpp helper ;
+lib helper : helper.cpp test_lib ;
+lib test_lib : : <name>test_lib <search>lib ;
+""")
+
+t.write("main.cpp", """
+void helper();
+int main() { helper(); }
+""")
+
+t.write("helper.cpp", """
+void foo();
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+helper() { foo(); }
+""")
+
+t.run_build_system("-d2")
+t.expect_addition("bin/$toolset/debug/main.exe")
+t.rm("bin/$toolset/debug/main.exe")
+
+
+# Test that 'unit-test' will correctly add runtime paths to searched libraries.
+t.write("jamfile.jam", """
+
+import path ;
+import project ;
+import testing ;
+
+project : requirements <hardcode-dll-paths>false ;
+
+unit-test main : main.cpp helper ;
+lib helper : helper.cpp test_lib ;
+lib test_lib : : <name>test_lib <search>lib ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/main.passed")
+t.rm("bin/$toolset/debug/main.exe")
+
+
+# Now try using searched lib from static lib. Request shared version of searched
+# lib, since we do not have a static one handy.
+t.write("jamfile.jam", """
+exe main : main.cpp helper ;
+lib helper : helper.cpp test_lib/<link>shared : <link>static ;
+lib test_lib : : <name>test_lib <search>lib ;
+""")
+
+t.run_build_system(stderr=None)
+t.expect_addition("bin/$toolset/debug/main.exe")
+t.expect_addition("bin/$toolset/debug/link-static/helper.lib")
+t.rm("bin/$toolset/debug/main.exe")
+
+# A regression test: <library>property referring to searched-lib was being
+# mishandled. As the result, we were putting target name to the command line!
+# Note that
+# g++ ...... <.>z
+# works nicely in some cases, sending output from compiler to file 'z'. This
+# problem shows up when searched libs are in usage requirements.
+t.write("jamfile.jam", "exe main : main.cpp d/d2//a ;")
+t.write("main.cpp", """
+void foo();
+int main() { foo(); }
+""")
+
+t.write("d/d2/jamfile.jam", """
+lib test_lib : : <name>test_lib <search>../../lib ;
+lib a : a.cpp : : : <library>test_lib ;
+""")
+
+t.write("d/d2/a.cpp", """
+#ifdef _WIN32
+__declspec(dllexport) int force_library_creation_for_a;
+#endif
+""")
+
+t.run_build_system()
+
+
+# A regression test. Searched targets were not associated with any properties.
+# For that reason, if the same searched lib is generated with two different
+# properties, we had an error saying they are actualized to the same Jam target
+# name.
+t.write("jamroot.jam", "")
+
+t.write("a.cpp", "")
+
+# The 'l' library will be built in two variants: 'debug' (directly requested)
+# and 'release' (requested from 'a').
+t.write("jamfile.jam", """
+exe a : a.cpp l/<variant>release ;
+lib l : : <name>l_d <variant>debug ;
+lib l : : <name>l_r <variant>release ;
+""")
+
+t.run_build_system("-n")
+
+
+# A regression test. Two virtual target with the same properties were created
+# for 'l' target, which caused and error to be reported when actualizing
+# targets. The final error is correct, but we should not create two duplicated
+# targets. Thanks to Andre Hentz for finding this bug.
+t.write("jamroot.jam", "")
+
+t.write("a.cpp", "")
+
+t.write("jamfile.jam", """
+project a : requirements <runtime-link>static ;
+static-lib a : a.cpp l ;
+lib l : : <name>l_f ;
+""")
+
+t.run_build_system("-n")
+
+
+# Make sure plain "lib foobar ; " works.
+t.write("jamfile.jam", """
+exe a : a.cpp foobar ;
+lib foobar ;
+""")
+
+t.run_build_system("-n -d2")
+t.fail_test(string.find(t.stdout(), "foobar") == -1)
+
+
+# Make sure plain "lib foo bar ; " works.
+t.write("jamfile.jam", """
+exe a : a.cpp foo bar ;
+lib foo bar ;
+""")
+
+t.run_build_system("-n -d2")
+t.fail_test(string.find(t.stdout(), "foo") == -1)
+t.fail_test(string.find(t.stdout(), "bar") == -1)
+
+t.cleanup()
diff --git a/tools/build/v2/test/skipping.py b/tools/build/v2/test/skipping.py
new file mode 100644
index 0000000000..b3575eafd3
--- /dev/null
+++ b/tools/build/v2/test/skipping.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that V2 does not fail gracelessy when any target is skipped.
+
+import BoostBuild
+
+# Create a temporary working directory.
+t = BoostBuild.Tester()
+
+t.write("a.cpp", """
+int main() {}
+""")
+
+t.write("b.cpp", """
+int main() {}
+""")
+
+t.write("c.cpp", """
+int main() {}
+""")
+
+t.write("jamroot.jam", """
+import feature ;
+feature.feature foo : 1 2 : link-incompatible ;
+exe a : a.cpp : <foo>1 ;
+exe b : b.cpp : <foo>2 ;
+exe c : c.cpp ;
+""")
+
+t.run_build_system("foo=1")
+
+t.cleanup()
diff --git a/tools/build/v2/test/sort_rule.py b/tools/build/v2/test/sort_rule.py
new file mode 100755
index 0000000000..f4a4acda13
--- /dev/null
+++ b/tools/build/v2/test/sort_rule.py
@@ -0,0 +1,95 @@
+#!/usr/bin/python
+
+# Copyright (C) Jurko Gospodnetic 2008.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests for the Boost Jam builtin SORT rule.
+
+import BoostBuild
+
+
+################################################################################
+#
+# testSORTCorrectness()
+# ---------------------
+#
+################################################################################
+
+def testSORTCorrectness():
+ """Testing that Boost Jam's SORT builtin rule actually sorts correctly.
+ """
+ t = BoostBuild.Tester("-f test.jam -d1", pass_toolset=False,
+ use_test_config=False)
+
+ t.write("test.jam", """
+NOCARE all ;
+source-data = 1 8 9 2 7 3 4 7 1 27 27 9 98 98 1 1 4 5 6 2 3 4 8 1 -2 -2 0 0 0 ;
+target-data = -2 -2 0 0 0 1 1 1 1 1 2 2 27 27 3 3 4 4 4 5 6 7 7 8 8 9 9 98 98 ;
+ECHO "starting up" ;
+sorted-data = [ SORT $(source-data) ] ;
+ECHO "done" ;
+if $(sorted-data) != $(target-data)
+{
+ ECHO "Source :" $(source-data) ;
+ ECHO "Expected :" $(target-data) ;
+ ECHO "SORT returned:" $(sorted-data) ;
+ EXIT "SORT error" : -2 ;
+}
+""")
+
+ t.run_build_system()
+ t.expect_output_line("starting up")
+ t.expect_output_line("done")
+ t.expect_output_line("SORT error", False)
+
+ t.cleanup()
+
+
+################################################################################
+#
+# testSORTDuration()
+# ------------------
+#
+################################################################################
+
+def testSORTDuration():
+ """Regression test making sure Boost Jam's SORT builtin rule does not get
+ quadratic behaviour again in this use case.
+ """
+ t = BoostBuild.Tester("-f test.jam -d1", pass_toolset=False,
+ use_test_config=False)
+
+ f = open(t.workpath("test.jam"), "w")
+ print >> f, "data = "
+ for i in range(0, 20000):
+ if i % 2 != 0:
+ print >> f, '"aaa"'
+ else:
+ print >> f, '"bbb"'
+ print >> f, """;
+
+ECHO "starting up" ;
+sorted = [ SORT $(data) ] ;
+ECHO "done" ;
+NOCARE all ;
+"""
+ f.close()
+
+ t.run_build_system(expected_duration=1)
+ t.expect_output_line("starting up")
+ t.expect_output_line("done")
+
+ t.cleanup()
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+testSORTCorrectness()
+testSORTDuration()
diff --git a/tools/build/v2/test/source_locations.py b/tools/build/v2/test/source_locations.py
new file mode 100644
index 0000000000..7133ab044e
--- /dev/null
+++ b/tools/build/v2/test/source_locations.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+# Copyright (C) Craig Rodrigues 2005.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that projects with multiple source-location directories are handled OK.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", """
+path-constant SRC1 : "./src1" ;
+path-constant SRC2 : "./src2" ;
+path-constant SRC3 : "./src3" ;
+path-constant BUILD : "build" ;
+
+project : requirements <include>$(SRC1)/include <threading>multi
+ : build-dir $(BUILD) ;
+
+build-project project1 ;
+""")
+
+t.write("project1/jamfile.jam", """
+project project1 : source-location $(SRC1) $(SRC2) $(SRC3) ;
+SRCS = s1.cpp s2.cpp testfoo.cpp ;
+exe test : $(SRCS) ;
+""")
+
+t.write("src1/s1.cpp", "int main() {}\n")
+t.write("src2/s2.cpp", "void hello() {}\n")
+t.write("src3/testfoo.cpp", "void testfoo() {}\n")
+
+# This file should not be picked up, because "src2" is before "src3" in the list
+# of source directories.
+t.write("src3/s2.cpp", "void hello() {}\n")
+
+t.run_build_system()
+
+t.cleanup()
diff --git a/tools/build/v2/test/stage.py b/tools/build/v2/test/stage.py
new file mode 100644
index 0000000000..9862138b0d
--- /dev/null
+++ b/tools/build/v2/test/stage.py
@@ -0,0 +1,258 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test staging.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", "import gcc ;")
+
+t.write("jamfile.jam", """
+lib a : a.cpp ;
+stage dist : a a.h auxilliary/1 ;
+""")
+
+t.write(
+ "a.cpp",
+"""
+int
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+must_export_something;
+""")
+
+t.write("a.h", "")
+t.write("auxilliary/1", "")
+
+t.run_build_system()
+t.expect_addition(["dist/a.dll", "dist/a.h", "dist/1"])
+
+
+# Regression test: the following was causing the "duplicate target name" error.
+t.write("jamfile.jam", """
+project : requirements <hardcode-dll-paths>true ;
+lib a : a.cpp ;
+stage dist : a a.h auxilliary/1 ;
+alias dist-alias : dist ;
+""")
+
+t.run_build_system()
+
+
+# Test the <location> property.
+t.write("jamfile.jam", """
+lib a : a.cpp ;
+stage dist : a : <variant>debug:<location>ds <variant>release:<location>rs ;
+""")
+
+t.run_build_system()
+t.expect_addition("ds/a.dll")
+
+t.run_build_system("release")
+t.expect_addition("rs/a.dll")
+
+
+# Test the <location> property in subprojects. Thanks to Kirill Lapshin for the
+# bug report.
+
+t.write("jamroot.jam", """
+path-constant DIST : dist ;
+""")
+
+t.write("jamfile.jam", "build-project d ;")
+
+t.write("d/jamfile.jam", """
+exe a : a.cpp ;
+stage dist : a : <location>$(DIST) ;
+""")
+
+t.write("d/a.cpp", "int main() {}\n")
+
+t.run_build_system()
+t.expect_addition("dist/a.exe")
+
+t.rm("dist")
+
+# Workaround a BIG BUG: the response file is not deleted, even if application
+# *is* deleted. We will try to use the same response file when building from
+# subdir, with very bad results.
+t.rm("d/bin")
+t.run_build_system(subdir="d")
+t.expect_addition("dist/a.exe")
+
+
+# Check that 'stage' does not incorrectly reset target suffixes.
+t.write("a.cpp", """
+int main() {}
+""")
+
+t.write("jamroot.jam", """
+import type ;
+type.register MYEXE : : EXE ;
+type.set-generated-target-suffix MYEXE : <optimization>off : myexe ;
+""")
+
+# Since <optimization>off is in properties when 'a' is built, and staged, its
+# suffix should be "myexe".
+t.write("jamfile.jam", """
+stage dist : a ;
+myexe a : a.cpp ;
+""")
+
+t.run_build_system()
+t.expect_addition("dist/a.myexe")
+
+# Test 'stage's ability to traverse dependencies.
+t.write("a.cpp", """
+int main() {}
+""")
+
+t.write("l.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+foo() {}
+""")
+
+t.write("jamfile.jam", """
+lib l : l.cpp ;
+exe a : a.cpp l ;
+stage dist : a : <install-dependencies>on <install-type>EXE <install-type>LIB ;
+""")
+
+t.write("jamroot.jam", "")
+
+t.rm("dist")
+
+t.run_build_system()
+t.expect_addition("dist/a.exe")
+t.expect_addition("dist/l.dll")
+
+# Check that <use> properties are ignored the traversing target for staging.
+t.copy("l.cpp", "l2.cpp")
+
+t.copy("l.cpp", "l3.cpp")
+
+t.write("jamfile.jam", """
+lib l2 : l2.cpp ;
+lib l3 : l3.cpp ;
+lib l : l.cpp : <use>l2 <dependency>l3 ;
+exe a : a.cpp l ;
+stage dist : a : <install-dependencies>on <install-type>EXE <install-type>LIB ;
+""")
+
+t.rm("dist")
+
+t.run_build_system()
+t.expect_addition("dist/l3.dll")
+t.expect_nothing("dist/l2.dll")
+
+# Check if <dependency> on 'stage' works.
+t.rm(".")
+t.write("jamroot.jam", """
+stage a1 : a1.txt : <location>dist ;
+stage a2 : a2.txt : <location>dist <dependency>a1 ;
+""")
+t.write("a1.txt", "")
+t.write("a2.txt", "")
+t.run_build_system("a2")
+t.expect_addition(["dist/a1.txt", "dist/a2.txt"])
+
+# Regression test: check that <location>. works.
+t.rm(".")
+
+t.write("jamroot.jam", """
+stage a1 : d/a1.txt : <location>. ;
+""")
+
+t.write("d/a1.txt", "")
+
+t.run_build_system()
+t.expect_addition("a1.txt")
+
+# Test that relative paths of sources can be preserved.
+t.rm(".")
+
+t.write("jamroot.jam", """
+install dist : a/b/c.h : <install-source-root>. ;
+""")
+
+t.write("a/b/c.h", "")
+
+t.run_build_system()
+t.expect_addition("dist/a/b/c.h")
+
+t.write("jamroot.jam", """
+install dist : a/b/c.h : <install-source-root>a ;
+""")
+
+t.write("a/b/c.h", "")
+
+t.run_build_system()
+t.expect_addition("dist/b/c.h")
+
+t.rm(".")
+t.write("build/jamroot.jam", """
+install dist : ../a/b/c.h : <location>../dist <install-source-root>../a ;
+""")
+
+t.write("a/b/c.h", "")
+
+t.run_build_system(subdir="build")
+t.expect_addition("dist/b/c.h")
+
+t.write("jamroot.jam", """
+install dist2 : a/b/c.h : <install-source-root>a ;
+""")
+
+t.write("a/b/c.h", "")
+
+t.write("sub/jamfile.jam", """
+alias h : ..//dist2 ;
+""")
+
+t.run_build_system(subdir="sub")
+t.expect_addition("dist2/b/c.h")
+
+# Test that when installing .cpp files, we do not scan include dependencies.
+t.rm(".")
+
+t.write("jamroot.jam", """
+install dist : a.cpp ;
+""")
+
+t.write("a.cpp", """
+#include "a.h"
+""")
+
+t.write("a.h", "")
+
+t.run_build_system()
+t.expect_addition("dist/a.cpp")
+
+t.touch("a.h")
+
+t.run_build_system()
+t.expect_nothing("dist/a.cpp")
+
+# Test that <name> property works, when there is just one file in sources.
+t.rm(".")
+
+t.write("jamroot.jam", """
+install dist : a.cpp : <name>b.cpp ;
+""")
+
+t.write("a.cpp", "test file")
+
+t.run_build_system()
+t.expect_addition("dist/b.cpp")
+
+t.cleanup()
diff --git a/tools/build/v2/test/standalone.py b/tools/build/v2/test/standalone.py
new file mode 100644
index 0000000000..31603fc974
--- /dev/null
+++ b/tools/build/v2/test/standalone.py
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+
+# Regression tests: standalone project were not able to refer to targets
+# declared in themselves.
+
+t.write("a.cpp", """
+int main() {}
+""")
+
+t.write("jamroot.jam", """
+import standalone ;
+""")
+
+t.write("standalone.jam", """
+import project ;
+
+project.initialize $(__name__) ;
+project standalone ;
+
+local pwd = [ PWD ] ;
+
+alias x : $(pwd)/../a.cpp ;
+alias runtime : x ;
+""")
+
+t.write("standalone.py", """
+from b2.manager import get_manager
+
+# FIXME: this is ugly as death
+get_manager().projects().initialize(__name__)
+
+import os ;
+
+# This use of list as parameter is also ugly.
+project(['standalone'])
+
+pwd = os.getcwd()
+alias('x', [os.path.join(pwd, '../a.cpp')])
+alias('runtime', ['x'])
+""")
+
+
+t.write("sub/jamfile.jam", """
+stage bin : /standalone//runtime ;
+""")
+
+t.run_build_system(subdir="sub")
+t.expect_addition("sub/bin/a.cpp")
+
+t.cleanup()
diff --git a/tools/build/v2/test/startup/boost-root/boost-build.jam b/tools/build/v2/test/startup/boost-root/boost-build.jam
new file mode 100644
index 0000000000..098889f7b7
--- /dev/null
+++ b/tools/build/v2/test/startup/boost-root/boost-build.jam
@@ -0,0 +1,7 @@
+# Copyright 2002 Dave Abrahams
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Emulate v1 behavior; with the boost-build file in the boost root directory.
+boost-build build ;
diff --git a/tools/build/v2/test/startup/boost-root/build/boost-build.jam b/tools/build/v2/test/startup/boost-root/build/boost-build.jam
new file mode 100644
index 0000000000..610ec79eeb
--- /dev/null
+++ b/tools/build/v2/test/startup/boost-root/build/boost-build.jam
@@ -0,0 +1,6 @@
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# The presence of this file emulates the Boost 1.27.0 release
+include $(BOOST_ROOT)/tools/build/bootstrap.jam ;
diff --git a/tools/build/v2/test/startup/boost-root/build/bootstrap.jam b/tools/build/v2/test/startup/boost-root/build/bootstrap.jam
new file mode 100644
index 0000000000..2ee3507c30
--- /dev/null
+++ b/tools/build/v2/test/startup/boost-root/build/bootstrap.jam
@@ -0,0 +1,7 @@
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+ECHO build system bootstrapped ;
+DEPENDS all : nothing ;
+NOTFILE nothing ;
diff --git a/tools/build/v2/test/startup/bootstrap-env/boost-build.jam b/tools/build/v2/test/startup/bootstrap-env/boost-build.jam
new file mode 100644
index 0000000000..67a285e7cc
--- /dev/null
+++ b/tools/build/v2/test/startup/bootstrap-env/boost-build.jam
@@ -0,0 +1,5 @@
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+boost-build ;
diff --git a/tools/build/v2/test/startup/bootstrap-explicit/boost-build.jam b/tools/build/v2/test/startup/bootstrap-explicit/boost-build.jam
new file mode 100644
index 0000000000..27d9108b77
--- /dev/null
+++ b/tools/build/v2/test/startup/bootstrap-explicit/boost-build.jam
@@ -0,0 +1,6 @@
+# Copyright 2002 Dave Abrahams
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+boost-build ../boost-root/build ;
diff --git a/tools/build/v2/test/startup/bootstrap-implicit/readme.txt b/tools/build/v2/test/startup/bootstrap-implicit/readme.txt
new file mode 100644
index 0000000000..0278716e5b
--- /dev/null
+++ b/tools/build/v2/test/startup/bootstrap-implicit/readme.txt
@@ -0,0 +1,5 @@
+Copyright 2002 Dave Abrahams
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+This file is only here so that cvs update -P won't fail to create a directory
diff --git a/tools/build/v2/test/startup/no-bootstrap1/boost-build.jam b/tools/build/v2/test/startup/no-bootstrap1/boost-build.jam
new file mode 100644
index 0000000000..b1b4dc696e
--- /dev/null
+++ b/tools/build/v2/test/startup/no-bootstrap1/boost-build.jam
@@ -0,0 +1,6 @@
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Bootstrap file not found via implicit lookup in BOOST_BUILD_PATH
+boost-build ;
diff --git a/tools/build/v2/test/startup/no-bootstrap1/subdir/readme.txt b/tools/build/v2/test/startup/no-bootstrap1/subdir/readme.txt
new file mode 100644
index 0000000000..00f428d443
--- /dev/null
+++ b/tools/build/v2/test/startup/no-bootstrap1/subdir/readme.txt
@@ -0,0 +1,5 @@
+Copyright 2002 Dave Abrahams
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+This file is only here so cvs update -P will create the directory.
diff --git a/tools/build/v2/test/startup/no-bootstrap2/boost-build.jam b/tools/build/v2/test/startup/no-bootstrap2/boost-build.jam
new file mode 100644
index 0000000000..505dcd7759
--- /dev/null
+++ b/tools/build/v2/test/startup/no-bootstrap2/boost-build.jam
@@ -0,0 +1,6 @@
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Bootstrap file not found via explicit lookup in .
+boost-build . ;
diff --git a/tools/build/v2/test/startup/no-bootstrap3/boost-build.jam b/tools/build/v2/test/startup/no-bootstrap3/boost-build.jam
new file mode 100644
index 0000000000..252a3993ca
--- /dev/null
+++ b/tools/build/v2/test/startup/no-bootstrap3/boost-build.jam
@@ -0,0 +1,5 @@
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Call to boost-build is intentionally missing
diff --git a/tools/build/v2/test/startup_v1.py b/tools/build/v2/test/startup_v1.py
new file mode 100644
index 0000000000..14a286a70f
--- /dev/null
+++ b/tools/build/v2/test/startup_v1.py
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+
+# Copyright 2002 Dave Abrahams
+# Copyright 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import os
+import re
+
+def expect_substring(actual, expected):
+ return actual.find(expected) != -1
+
+def match_re(actual, expected):
+ return re.match(expected, actual, re.DOTALL) != None
+
+# Test the v1 startup behavior.
+t = BoostBuild.Tester(executable='bjam', match=match_re, boost_build_path='',
+ pass_toolset=0)
+
+t.set_tree('startup')
+
+#if os.name == 'nt':
+# t.run_build_system(
+# status=1, stdout="You didn't set BOOST_ROOT", match = expect_substring)
+
+t.run_build_system(extra_args='-sBOOST_ROOT=.', status=1,
+ stdout=r'''Unable to load Boost\.Build: could not find ''' +
+ r'''"boost-build\.jam".''')
+
+os.chdir('no-bootstrap1')
+
+t.run_build_system(extra_args='-sBOOST_ROOT=.', status=1,
+ stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"''')
+
+# Descend to a subdirectory which /doesn't/ contain a boost-build.jam
+# file, and try again to test the crawl-up behavior.
+os.chdir('subdir')
+
+t.run_build_system(extra_args='-sBOOST_ROOT=.', status=1,
+ stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"''')
+
+os.chdir('../../no-bootstrap2')
+
+t.run_build_system(extra_args='-sBOOST_ROOT=.', status=1,
+ stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build \. ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"''')
+
+os.chdir('../no-bootstrap3')
+
+t.run_build_system(extra_args='-sBOOST_ROOT=.', status=1,
+ stdout=r'''Unable to load Boost.Build
+.*boost-build.jam" was found.*
+However, it failed to call the "boost-build" rule''')
+
+# test bootstrapping based on BOOST_BUILD_PATH
+os.chdir('../bootstrap-env')
+t.run_build_system(extra_args='-sBOOST_ROOT=../boost-root ' +
+ '-sBOOST_BUILD_PATH=../boost-root/build',
+ stdout='build system bootstrapped')
+
+# test bootstrapping based on an explicit path in boost-build.jam
+os.chdir('../bootstrap-explicit')
+t.run_build_system(extra_args='-sBOOST_ROOT=../boost-root',
+ stdout='build system bootstrapped')
+
+# test bootstrapping based on BOOST_ROOT
+os.chdir('../bootstrap-implicit')
+t.run_build_system(extra_args='-sBOOST_ROOT=../boost-root',
+ stdout='build system bootstrapped')
+
+t.cleanup()
diff --git a/tools/build/v2/test/startup_v2.py b/tools/build/v2/test/startup_v2.py
new file mode 100644
index 0000000000..a4faf56ded
--- /dev/null
+++ b/tools/build/v2/test/startup_v2.py
@@ -0,0 +1,79 @@
+#!/usr/bin/python
+
+# Copyright 2002 Dave Abrahams
+# Copyright 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import os
+import re
+
+
+def match_re(actual,expected):
+ return re.match(expected,actual,re.DOTALL) != None
+
+# Test the v1 startup behavior.
+t = BoostBuild.Tester(match=match_re, boost_build_path='', pass_toolset=0)
+
+t.set_tree('startup')
+
+t.run_build_system(
+ status=1, stdout=r'''Unable to load Boost\.Build: could not find "boost-build.jam"
+.*Attempted search from .* up to the root''', match = match_re)
+
+os.chdir('no-bootstrap1')
+
+t.run_build_system(
+ status=1
+ , stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"'''
+ )
+
+# Descend to a subdirectory which /doesn't/ contain a boost-build.jam file, and
+# try again to test the crawl-up behavior.
+os.chdir('subdir')
+
+t.run_build_system(
+ status=1
+ , stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"'''
+ )
+
+os.chdir('../../no-bootstrap2')
+
+t.run_build_system(
+ status=1
+ , stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build \. ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"'''
+ )
+
+os.chdir('../no-bootstrap3')
+
+t.run_build_system(
+ status=1
+ , stdout=r'''Unable to load Boost.Build
+.*boost-build.jam" was found.*
+However, it failed to call the "boost-build" rule'''
+ )
+
+# Test bootstrapping based on BOOST_BUILD_PATH.
+os.chdir('../bootstrap-env')
+t.run_build_system(
+ extra_args = '-sBOOST_BUILD_PATH=../boost-root/build'
+ , stdout = 'build system bootstrapped'
+ )
+
+# Test bootstrapping based on an explicit path in boost-build.jam.
+os.chdir('../bootstrap-explicit')
+t.run_build_system(
+ stdout = 'build system bootstrapped'
+ )
+
+t.cleanup()
diff --git a/tools/build/v2/test/subdir1/file-to-bind b/tools/build/v2/test/subdir1/file-to-bind
new file mode 100644
index 0000000000..7ff128fa69
--- /dev/null
+++ b/tools/build/v2/test/subdir1/file-to-bind
@@ -0,0 +1 @@
+# This file intentionally left blank \ No newline at end of file
diff --git a/tools/build/v2/test/suffix.py b/tools/build/v2/test/suffix.py
new file mode 100644
index 0000000000..386e36a9d5
--- /dev/null
+++ b/tools/build/v2/test/suffix.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+
+# Copyright 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+# Regression test: when staging V2 used to change suffixes on targets
+# corresponding to real files.
+t.write("jamfile.jam", """
+import type : register ;
+register A : a1 a2 a3 ;
+stage a : a.a3 ;
+""")
+
+t.write("jamroot.jam", "")
+t.write("a.a3", "")
+
+t.run_build_system()
+t.expect_addition("a/a.a3");
+
+# Regression test: we should be able to specify empty suffix for derived target
+# type, even if base type has non-empty suffix.
+t.write("a.cpp", "")
+
+t.write("suffixes.jam", """
+import type ;
+import generators ;
+import common ;
+
+type.register First : first : ;
+type.register Second : "" : First ;
+
+generators.register-standard $(__name__).second : CPP : Second ;
+
+rule second
+{
+ TOUCH on $(<) = [ common.file-creation-command ] ;
+}
+
+actions second
+{
+ $(TOUCH) $(<)
+}
+""")
+
+t.write("suffixes.py", """
+import b2.build.type as type
+import b2.build.generators as generators
+import b2.tools.common as common
+
+from b2.manager import get_manager
+
+type.register("First", ["first"])
+type.register("Second", [""], "First")
+
+generators.register_standard("suffixes.second", ["CPP"], ["Second"])
+
+get_manager().engine().register_action("suffixes.second",
+ "%s $(<)" % common.file_creation_command())
+
+""")
+
+t.write("jamroot.jam", """
+import suffixes ;
+""")
+
+t.write("jamfile.jam", """
+second a : a.cpp ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a")
+
+t.cleanup()
diff --git a/tools/build/v2/test/svn_tree.py b/tools/build/v2/test/svn_tree.py
new file mode 100644
index 0000000000..74bceb7f57
--- /dev/null
+++ b/tools/build/v2/test/svn_tree.py
@@ -0,0 +1,668 @@
+#!/usr/bin/env python
+#
+# tree.py: tools for comparing directory trees
+#
+# Subversion is a tool for revision control.
+# See http://subversion.tigris.org for more information.
+#
+# ====================================================================
+# Copyright (c) 2001 Sam Tobin-Hochstadt. All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at http://subversion.tigris.org/license-1.html.
+# If newer versions of this license are posted there, you may use a
+# newer version instead, at your option.
+#
+######################################################################
+
+# This file was modified by Vladimir Prus to store modification times in tree
+# nodes.
+
+import re
+import string
+import os.path
+import os
+import stat
+
+
+#========================================================================
+
+# ===> Overview of our Datastructures <===
+
+# The general idea here is that many, many things can be represented by
+# a tree structure:
+
+# - a working copy's structure and contents
+# - the output of 'svn status'
+# - the output of 'svn checkout/update'
+# - the output of 'svn commit'
+
+# The idea is that a test function creates a "expected" tree of some
+# kind, and is then able to compare it to an "actual" tree that comes
+# from running the Subversion client. This is what makes a test
+# automated; if an actual and expected tree match exactly, then the test
+# has passed. (See compare_trees() below.)
+
+# The SVNTreeNode class is the fundamental data type used to build tree
+# structures. The class contains a method for "dropping" a new node
+# into an ever-growing tree structure. (See also create_from_path()).
+
+# We have four parsers in this file for the four use cases listed above:
+# each parser examines some kind of input and returns a tree of
+# SVNTreeNode objects. (See build_tree_from_checkout(),
+# build_tree_from_commit(), build_tree_from_status(), and
+# build_tree_from_wc()). These trees are the "actual" trees that result
+# from running the Subversion client.
+
+# Also necessary, of course, is a convenient way for a test to create an
+# "expected" tree. The test *could* manually construct and link a bunch
+# of SVNTreeNodes, certainly. But instead, all the tests are using the
+# build_generic_tree() routine instead.
+
+# build_generic_tree() takes a specially-formatted list of lists as
+# input, and returns a tree of SVNTreeNodes. The list of lists has this
+# structure:
+
+# [ ['/full/path/to/item', 'text contents', {prop-hash}, {att-hash}],
+# [...],
+# [...],
+# ... ]
+
+# You can see that each item in the list essentially defines an
+# SVNTreeNode. build_generic_tree() instantiates a SVNTreeNode for each
+# item, and then drops it into a tree by parsing each item's full path.
+
+# So a typical test routine spends most of its time preparing lists of
+# this format and sending them to build_generic_tree(), rather than
+# building the "expected" trees directly.
+
+# ### Note: in the future, we'd like to remove this extra layer of
+# ### abstraction. We'd like the SVNTreeNode class to be more
+# ### directly programmer-friendly, providing a number of accessor
+# ### routines, so that tests can construct trees directly.
+
+# The first three fields of each list-item are self-explanatory. It's
+# the fourth field, the "attribute" hash, that needs some explanation.
+# The att-hash is used to place extra information about the node itself,
+# depending on the parsing context:
+
+# - in the 'svn co/up' use-case, each line of output starts with two
+# characters from the set of (A, D, G, U, C, _). This status code
+# is stored in a attribute named 'status'.
+
+# - in the 'svn ci/im' use-case, each line of output starts with one
+# of the words (Adding, Deleting, Sending). This verb is stored in
+# an attribute named 'verb'.
+
+# - in the 'svn status' use-case (which is always run with the -v
+# (--verbose) flag), each line of output contains a working revision
+# number and a two-letter status code similar to the 'svn co/up'
+# case. The repository revision is also printed. All of this
+# information is stored in attributes named 'wc_rev', 'status', and
+# 'repos_rev', respectively.
+
+# - in the working-copy use-case, the att-hash is ignored.
+
+
+# Finally, one last explanation: the file 'actions.py' contain a number
+# of helper routines named 'run_and_verify_FOO'. These routines take
+# one or more "expected" trees as input, then run some svn subcommand,
+# then push the output through an appropriate parser to derive an
+# "actual" tree. Then it runs compare_trees() and returns the result.
+# This is why most tests typically end with a call to
+# run_and_verify_FOO().
+
+
+
+
+# A node in a tree.
+#
+# If CHILDREN is None, then the node is a file. Otherwise, CHILDREN
+# is a list of the nodes making up that directory's children.
+#
+# NAME is simply the name of the file or directory. CONTENTS is a
+# string that contains the file's contents (if a file), PROPS are
+# properties attached to files or dirs, and ATTS is a dictionary of
+# other metadata attached to the node.
+
+class SVNTreeNode:
+
+ def __init__(self, name, children=None, contents=None, props={}, atts={}):
+ self.name = name
+ self.mtime = 0
+ self.children = children
+ self.contents = contents
+ self.props = props
+ self.atts = atts
+ self.path = name
+
+# TODO: Check to make sure contents and children are mutually exclusive
+
+ def add_child(self, newchild):
+ if self.children is None: # if you're a file,
+ self.children = [] # become an empty dir.
+ child_already_exists = 0
+ for a in self.children:
+ if a.name == newchild.name:
+ child_already_exists = 1
+ break
+ if child_already_exists == 0:
+ self.children.append(newchild)
+ newchild.path = os.path.join (self.path, newchild.name)
+
+ # If you already have the node,
+ else:
+ if newchild.children is None:
+ # this is the 'end' of the chain, so copy any content here.
+ a.contents = newchild.contents
+ a.props = newchild.props
+ a.atts = newchild.atts
+ a.path = os.path.join (self.path, newchild.name)
+ else:
+ # try to add dangling children to your matching node
+ for i in newchild.children:
+ a.add_child(i)
+
+
+ def pprint(self):
+ print " * Node name: ", self.name
+ print " Path: ", self.path
+ print " Contents: ", self.contents
+ print " Properties:", self.props
+ print " Attributes:", self.atts
+ ### FIXME: I'd like to be able to tell the difference between
+ ### self.children is None (file) and self.children == [] (empty
+ ### diretory), but it seems that most places that construct
+ ### SVNTreeNode objects don't even try to do that. --xbc
+ if self.children is not None:
+ print " Children: ", len(self.children)
+ else:
+ print " Children: is a file."
+
+# reserved name of the root of the tree
+
+root_node_name = "__SVN_ROOT_NODE"
+
+# Exception raised if you screw up in this module.
+
+class SVNTreeError(Exception): pass
+
+# Exception raised if two trees are unequal
+
+class SVNTreeUnequal(Exception): pass
+
+# Exception raised if one node is file and other is dir
+
+class SVNTypeMismatch(Exception): pass
+
+# Exception raised if get_child is passed a file.
+
+class SVNTreeIsNotDirectory(Exception): pass
+
+
+# Some attributes 'stack' on each other if the same node is added
+# twice to a tree. Place all such special cases in here.
+def attribute_merge(orighash, newhash):
+ "Merge the attributes in NEWHASH into ORIGHASH."
+
+ if orighash.has_key('verb') and newhash.has_key('verb'):
+ # Special case: if a commit reports a node as "deleted", then
+ # "added", it's a replacment.
+ if orighash['verb'] == "Deleting":
+ if newhash['verb'] == "Adding":
+ orighash['verb'] = "Replacing"
+
+ # Add future stackable attributes here...
+
+ return orighash
+
+
+# helper func
+def add_elements_as_path(top_node, element_list):
+ """Add the elements in ELEMENT_LIST as if they were a single path
+ below TOP_NODE."""
+
+ # The idea of this function is to take a list like so:
+ # ['A', 'B', 'C'] and a top node, say 'Z', and generate a tree
+ # like this:
+ #
+ # Z -> A -> B -> C
+ #
+ # where 1 -> 2 means 2 is a child of 1.
+ #
+
+ prev_node = top_node
+ for i in element_list:
+ new_node = SVNTreeNode(i, None)
+ prev_node.add_child(new_node)
+ prev_node = new_node
+
+
+# Sorting function -- sort 2 nodes by their names.
+def node_is_greater(a, b):
+ "Sort the names of two nodes."
+ # Interal use only
+ if a.name == b.name:
+ return 0
+ if a.name > b.name:
+ return 1
+ else:
+ return -1
+
+
+# Helper for compare_trees
+def compare_file_nodes(a, b):
+ """Compare two nodes' names, contents, and properties, ignoring
+ children. Return 0 if the same, 1 otherwise."""
+ if a.name != b.name:
+ return 1
+ if a.contents != b.contents:
+ return 1
+ if a.props != b.props:
+ return 1
+ if a.atts != b.atts:
+ return 1
+
+
+# Internal utility used by most build_tree_from_foo() routines.
+#
+# (Take the output and .add_child() it to a root node.)
+
+def create_from_path(path, contents=None, props={}, atts={}):
+ """Create and return a linked list of treenodes, given a PATH
+ representing a single entry into that tree. CONTENTS and PROPS are
+ optional arguments that will be deposited in the tail node."""
+
+ # get a list of all the names in the path
+ # each of these will be a child of the former
+ elements = path.split("/")
+ if len(elements) == 0:
+ raise SVNTreeError
+
+ root_node = SVNTreeNode(elements[0], None)
+
+ add_elements_as_path(root_node, elements[1:])
+
+ # deposit contents in the very last node.
+ node = root_node
+ while 1:
+ if node.children is None:
+ node.contents = contents
+ node.props = props
+ node.atts = atts
+ break
+ node = node.children[0]
+
+ return root_node
+
+
+# helper for handle_dir(), which is a helper for build_tree_from_wc()
+def get_props(path):
+ "Return a hash of props for PATH, using the svn client."
+
+ # It's not kosher to look inside SVN/ and try to read the internal
+ # property storage format. Instead, we use 'svn proplist'. After
+ # all, this is the only way the user can retrieve them, so we're
+ # respecting the black-box paradigm.
+
+ props = {}
+ output, errput = main.run_svn(1, "proplist", path, "--verbose")
+
+ for line in output:
+ name, value = line.split(' : ')
+ name = string.strip(name)
+ value = string.strip(value)
+ props[name] = value
+
+ return props
+
+
+# helper for handle_dir(), which helps build_tree_from_wc()
+def get_text(path):
+ "Return a string with the textual contents of a file at PATH."
+
+ # sanity check
+ if not os.path.isfile(path):
+ return None
+
+ fp = open(path, 'r')
+ contents = fp.read()
+ fp.close()
+ return contents
+
+
+# main recursive helper for build_tree_from_wc()
+def handle_dir(path, current_parent, load_props, ignore_svn):
+
+ # get a list of all the files
+ all_files = os.listdir(path)
+ files = []
+ dirs = []
+
+ # put dirs and files in their own lists, and remove SVN dirs
+ for f in all_files:
+ f = os.path.join(path, f)
+ if (os.path.isdir(f) and os.path.basename(f) != 'SVN'):
+ dirs.append(f)
+ elif os.path.isfile(f):
+ files.append(f)
+
+ # add each file as a child of CURRENT_PARENT
+ for f in files:
+ fcontents = get_text(f)
+ if load_props:
+ fprops = get_props(f)
+ else:
+ fprops = {}
+ c = SVNTreeNode(os.path.basename(f), None,
+ fcontents, fprops)
+ c.mtime = os.stat(f)[stat.ST_MTIME]
+ current_parent.add_child(c)
+
+ # for each subdir, create a node, walk its tree, add it as a child
+ for d in dirs:
+ if load_props:
+ dprops = get_props(d)
+ else:
+ dprops = {}
+ new_dir_node = SVNTreeNode(os.path.basename(d), [], None, dprops)
+ handle_dir(d, new_dir_node, load_props, ignore_svn)
+ new_dir_node.mtime = os.stat(f)[stat.ST_MTIME]
+ current_parent.add_child(new_dir_node)
+
+def get_child(node, name):
+ """If SVNTreeNode NODE contains a child named NAME, return child;
+ else, return None. If SVNTreeNode is not a directory, raise a
+ SVNTreeIsNotDirectory exception"""
+ if node.children == None:
+ raise SVNTreeIsNotDirectory
+ for n in node.children:
+ if (name == n.name):
+ return n
+ return None
+
+
+# Helper for compare_trees
+def default_singleton_handler(a, baton):
+ "Printing SVNTreeNode A's name, then raise SVNTreeUnequal."
+ print "Got singleton", a.name
+ a.pprint()
+ raise SVNTreeUnequal
+
+
+###########################################################################
+###########################################################################
+# EXPORTED ROUTINES ARE BELOW
+
+
+# Main tree comparison routine!
+
+def compare_trees(a, b,
+ singleton_handler_a = None,
+ a_baton = None,
+ singleton_handler_b = None,
+ b_baton = None):
+ """Compare SVNTreeNodes A and B, expressing differences using FUNC_A
+ and FUNC_B. FUNC_A and FUNC_B are functions of two arguments (a
+ SVNTreeNode and a context baton), and may raise exception
+ SVNTreeUnequal. Their return value is ignored.
+
+ If A and B are both files, then return 0 if their contents,
+ properties, and names are all the same; else raise a SVNTreeUnequal.
+ If A is a file and B is a directory, raise a SVNTypeMismatch; same
+ vice-versa. If both are directories, then for each entry that
+ exists in both, call compare_trees on the two entries; otherwise, if
+ the entry exists only in A, invoke FUNC_A on it, and likewise for
+ B with FUNC_B."""
+
+ def display_nodes(a, b):
+ 'Display two nodes, expected and actual.'
+ print "============================================================="
+ print "Expected", b.name, "and actual", a.name, "are different!"
+ print "============================================================="
+ print "EXPECTED NODE TO BE:"
+ print "============================================================="
+ b.pprint()
+ print "============================================================="
+ print "ACTUAL NODE FOUND:"
+ print "============================================================="
+ a.pprint()
+
+ # Setup singleton handlers
+ if (singleton_handler_a is None):
+ singleton_handler_a = default_singleton_handler
+ if (singleton_handler_b is None):
+ singleton_handler_b = default_singleton_handler
+
+ try:
+ # A and B are both files.
+ if ((a.children is None) and (b.children is None)):
+ if compare_file_nodes(a, b):
+ display_nodes(a, b)
+ raise main.SVNTreeUnequal
+ # One is a file, one is a directory.
+ elif (((a.children is None) and (b.children is not None))
+ or ((a.children is not None) and (b.children is None))):
+ display_nodes(a, b)
+ raise main.SVNTypeMismatch
+ # They're both directories.
+ else:
+ # First, compare the directories' two hashes.
+ if (a.props != b.props) or (a.atts != b.atts):
+ display_nodes(a, b)
+ raise main.SVNTreeUnequal
+
+ accounted_for = []
+ # For each child of A, check and see if it's in B. If so, run
+ # compare_trees on the two children and add b's child to
+ # accounted_for. If not, run FUNC_A on the child. Next, for each
+ # child of B, check and see if it's in accounted_for. If it is,
+ # do nothing. If not, run FUNC_B on it.
+ for a_child in a.children:
+ b_child = get_child(b, a_child.name)
+ if b_child:
+ accounted_for.append(b_child)
+ compare_trees(a_child, b_child,
+ singleton_handler_a, a_baton,
+ singleton_handler_b, b_baton)
+ else:
+ singleton_handler_a(a_child, a_baton)
+ for b_child in b.children:
+ if (b_child not in accounted_for):
+ singleton_handler_b(b_child, b_baton)
+ return 0
+ except SVNTypeMismatch:
+ print 'Unequal Types: one Node is a file, the other is a directory'
+ raise SVNTreeUnequal
+ except SVNTreeIsNotDirectory:
+ print "Error: Foolish call to get_child."
+ sys.exit(1)
+ except IndexError:
+ print "Error: unequal number of children"
+ raise SVNTreeUnequal
+ except SVNTreeUnequal:
+ if a.name == root_node_name:
+ return 1
+ else:
+ print "Unequal at node %s" % a.name
+ raise SVNTreeUnequal
+ return 0
+
+
+
+
+# Visually show a tree's structure
+
+def dump_tree(n,indent=""):
+ "Print out a nice representation of the tree's structure."
+
+ # Code partially stolen from Dave Beazley.
+ if n.children is None:
+ tmp_children = []
+ else:
+ tmp_children = n.children
+
+ if n.name == root_node_name:
+ print "%s%s" % (indent, "ROOT")
+ else:
+ print "%s%s" % (indent, n.name)
+
+ indent = indent.replace("-", " ")
+ indent = indent.replace("+", " ")
+ for i in range(len(tmp_children)):
+ c = tmp_children[i]
+ if i == len(tmp_children) - 1:
+ dump_tree(c,indent + " +-- ")
+ else:
+ dump_tree(c,indent + " |-- ")
+
+
+###################################################################
+###################################################################
+# PARSERS that return trees made of SVNTreeNodes....
+
+
+###################################################################
+# Build an "expected" static tree from a list of lists
+
+
+# Create a list of lists, of the form:
+#
+# [ [path, contents, props, atts], ... ]
+#
+# and run it through this parser. PATH is a string, a path to the
+# object. CONTENTS is either a string or None, and PROPS and ATTS are
+# populated dictionaries or {}. Each CONTENTS/PROPS/ATTS will be
+# attached to the basename-node of the associated PATH.
+
+def build_generic_tree(nodelist):
+ "Given a list of lists of a specific format, return a tree."
+
+ root = SVNTreeNode(root_node_name)
+
+ for list in nodelist:
+ new_branch = create_from_path(list[0], list[1], list[2], list[3])
+ root.add_child(new_branch)
+
+ return root
+
+
+####################################################################
+# Build trees from different kinds of subcommand output.
+
+
+# Parse co/up output into a tree.
+#
+# Tree nodes will contain no contents, and only one 'status' att.
+
+def build_tree_from_checkout(lines):
+ "Return a tree derived by parsing the output LINES from 'co' or 'up'."
+
+ root = SVNTreeNode(root_node_name)
+ rm = re.compile ('^([MAGCUD_ ][MAGCUD_ ]) (.+)')
+
+ for line in lines:
+ match = rm.search(line)
+ if match and match.groups():
+ new_branch = create_from_path(match.group(2), None, {},
+ {'status' : match.group(1)})
+ root.add_child(new_branch)
+
+ return root
+
+
+# Parse ci/im output into a tree.
+#
+# Tree nodes will contain no contents, and only one 'verb' att.
+
+def build_tree_from_commit(lines):
+ "Return a tree derived by parsing the output LINES from 'ci' or 'im'."
+
+ # Lines typically have a verb followed by whitespace then a path.
+ root = SVNTreeNode(root_node_name)
+ rm1 = re.compile ('^(\w+)\s+(.+)')
+ rm2 = re.compile ('^Transmitting')
+
+ for line in lines:
+ match = rm2.search(line)
+ if not match:
+ match = rm1.search(line)
+ if match and match.groups():
+ new_branch = create_from_path(match.group(2), None, {},
+ {'verb' : match.group(1)})
+ root.add_child(new_branch)
+
+ return root
+
+
+# Parse status output into a tree.
+#
+# Tree nodes will contain no contents, and these atts:
+#
+# 'status', 'wc_rev', 'repos_rev'
+# ... and possibly 'locked', 'copied', IFF columns non-empty.
+#
+
+def build_tree_from_status(lines):
+ "Return a tree derived by parsing the output LINES from 'st'."
+
+ root = SVNTreeNode(root_node_name)
+ rm = re.compile ('^.+\:.+(\d+)')
+ lastline = string.strip(lines.pop())
+ match = rm.search(lastline)
+ if match and match.groups():
+ repos_rev = match.group(1)
+ else:
+ repos_rev = '?'
+
+ # Try http://www.wordsmith.org/anagram/anagram.cgi?anagram=ACDRMGU
+ rm = re.compile ('^([MACDRUG_ ][MACDRUG_ ])(.)(.) . [^0-9-]+(\d+|-)(.{23})(.+)')
+ for line in lines:
+ match = rm.search(line)
+ if match and match.groups():
+ if match.group(5) != '-': # ignore items that only exist on repos
+ atthash = {'status' : match.group(1),
+ 'wc_rev' : match.group(4),
+ 'repos_rev' : repos_rev}
+ if match.group(2) != ' ':
+ atthash['locked'] = match.group(2)
+ if match.group(3) != ' ':
+ atthash['copied'] = match.group(3)
+ new_branch = create_from_path(match.group(6), None, {}, atthash)
+
+ root.add_child(new_branch)
+
+ return root
+
+
+####################################################################
+# Build trees by looking at the working copy
+
+
+# The reason the 'load_props' flag is off by default is because it
+# creates a drastic slowdown -- we spawn a new 'svn proplist'
+# process for every file and dir in the working copy!
+
+
+def build_tree_from_wc(wc_path, load_props=0, ignore_svn=1):
+ """Takes WC_PATH as the path to a working copy. Walks the tree below
+ that path, and creates the tree based on the actual found
+ files. If IGNORE_SVN is true, then exclude SVN dirs from the tree.
+ If LOAD_PROPS is true, the props will be added to the tree."""
+
+ root = SVNTreeNode(root_node_name, None)
+
+ # if necessary, store the root dir's props in the root node.
+ if load_props:
+ root.props = get_props(wc_path)
+
+ # Walk the tree recursively
+ handle_dir(os.path.normpath(wc_path), root, load_props, ignore_svn)
+
+ return root
+
+### End of file.
+# local variables:
+# eval: (load-file "../../../../../tools/dev/svn-dev.el")
+# end:
diff --git a/tools/build/v2/test/symlink.py b/tools/build/v2/test/symlink.py
new file mode 100644
index 0000000000..d78e96c15f
--- /dev/null
+++ b/tools/build/v2/test/symlink.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the 'symlink' rule.
+
+import os
+import BoostBuild
+
+
+if os.name != 'posix':
+ print "The symlink tests can be run on posix only."
+ import sys
+ sys.exit(1)
+
+
+t = BoostBuild.Tester()
+
+t.write("jamroot.jam", "import gcc ;")
+
+t.write("jamfile.jam", """
+exe hello : hello.cpp ;
+symlink hello_release : hello/<variant>release ;
+symlink hello_debug : hello/<variant>debug ;
+symlink links/hello_release : hello/<variant>release ;
+""")
+
+t.write("hello.cpp", """
+int main() {}
+""")
+
+t.run_build_system()
+t.expect_addition([
+ 'hello_debug.exe',
+ 'hello_release.exe',
+ 'links/hello_release.exe'])
+
+t.cleanup()
diff --git a/tools/build/v2/test/tag.py b/tools/build/v2/test/tag.py
new file mode 100644
index 0000000000..aef31e8081
--- /dev/null
+++ b/tools/build/v2/test/tag.py
@@ -0,0 +1,122 @@
+#!/usr/bin/python
+
+# Copyright (C) Pedro Ferreira 2003. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+import BoostBuild
+
+
+################################################################################
+#
+# test_folder_with_dot_in_name()
+# ------------------------------
+#
+################################################################################
+
+def test_folder_with_dot_in_name(t):
+ """ Regression test: the 'tag' feature did not work in directories that had
+ a dot in their name.
+ """
+
+ t.write("version-1.32.0/jamroot.jam", """
+project test : requirements <tag>@$(__name__).tag ;
+
+rule tag ( name : type ? : property-set )
+{
+ # Do nothing, just make sure the rule is invoked OK.
+ ECHO "The tag rule has been invoked." ;
+}
+exe a : a.cpp ;
+""")
+ t.write("version-1.32.0/a.cpp", "int main() {}\n")
+
+ t.run_build_system(subdir="version-1.32.0")
+ t.expect_addition("version-1.32.0/bin/$toolset/debug/a.exe")
+ t.expect_output_line("The tag rule has been invoked.")
+
+
+################################################################################
+#
+# test_tag_property()
+# -------------------
+#
+################################################################################
+
+def test_tag_property(t):
+ """Basic tag property test.
+ """
+
+ t.write("jamroot.jam", """
+import virtual-target ;
+
+rule tag ( name : type ? : property-set )
+{
+ local tags ;
+ switch [ $(property-set).get <variant> ]
+ {
+ case debug : tags += d ;
+ case release : tags += r ;
+ }
+ switch [ $(property-set).get <link> ]
+ {
+ case shared : tags += s ;
+ case static : tags += t ;
+ }
+ if $(tags)
+ {
+ return [ virtual-target.add-prefix-and-suffix $(name)_$(tags:J="")
+ : $(type) : $(property-set) ] ;
+ }
+}
+
+# Test both fully-qualified and local name of the rule
+exe a : a.cpp : <tag>@$(__name__).tag ;
+lib b : a.cpp : <tag>@tag ;
+stage c : a ;
+""")
+
+ t.write("a.cpp", """
+int main() {}
+#ifdef _MSC_VER
+__declspec (dllexport) void x () {}
+#endif
+""")
+
+ file_list = \
+ BoostBuild.List("bin/$toolset/debug/a_ds.exe") + \
+ BoostBuild.List("bin/$toolset/debug/b_ds.dll") + \
+ BoostBuild.List("c/a_ds.exe") + \
+ BoostBuild.List("bin/$toolset/release/a_rs.exe") + \
+ BoostBuild.List("bin/$toolset/release/b_rs.dll") + \
+ BoostBuild.List("c/a_rs.exe") + \
+ BoostBuild.List("bin/$toolset/debug/link-static/a_dt.exe") + \
+ BoostBuild.List("bin/$toolset/debug/link-static/b_dt.lib") + \
+ BoostBuild.List("c/a_dt.exe") + \
+ BoostBuild.List("bin/$toolset/release/link-static/a_rt.exe") + \
+ BoostBuild.List("bin/$toolset/release/link-static/b_rt.lib") + \
+ BoostBuild.List("c/a_rt.exe")
+
+ variants = "debug release link=static,shared"
+
+ t.run_build_system(variants)
+ t.expect_addition(file_list)
+
+ t.run_build_system(variants + " clean")
+ t.expect_removal(file_list)
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+t = BoostBuild.Tester()
+
+test_tag_property(t)
+test_folder_with_dot_in_name(t)
+
+t.cleanup()
diff --git a/tools/build/v2/test/template.py b/tools/build/v2/test/template.py
new file mode 100644
index 0000000000..1fbef07b8c
--- /dev/null
+++ b/tools/build/v2/test/template.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+# Copyright (C) FILL SOMETHING HERE 2006.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# This file is template for Boost.Build tests. It creates a simple project that
+# builds one exe from one source, and checks that the exe is really created.
+
+import BoostBuild
+
+
+# Create a temporary working directory.
+t = BoostBuild.Tester()
+
+# Create the needed files.
+t.write("jamroot.jam", """
+exe hello : hello.cpp ;
+""")
+
+t.write("hello.cpp", """
+int main() {}
+"""
+
+# Run the build.
+t.run_build_system()
+
+# First, create a list of three pathnames.
+file_list = BoostBuild.List("bin/$toolset/debug/") * \
+ BoostBuild.List("hello.exe hello.obj")
+# Second, assert that those files were added as result of the last build system
+# invocation.
+t.expect_addition(file_list)
+
+# Invoke the build system once again.
+t.run_build_system("clean")
+# Check if the files added previously were removed.
+t.expect_removal(file_list)
+
+# Remove temporary directories.
+t.cleanup()
diff --git a/tools/build/v2/test/test-config-example.jam b/tools/build/v2/test/test-config-example.jam
new file mode 100644
index 0000000000..6cb813fa0d
--- /dev/null
+++ b/tools/build/v2/test/test-config-example.jam
@@ -0,0 +1,19 @@
+# Copyright 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+# Skeleton for test configuration. If your local configuration
+# interferes with testing, rename this files to 'test-system.jam'
+# and tweak it. When tests are run, only this file will be loaded,
+# while site-config.jam and user-config.jam will be ignored.
+
+using gcc ;
+
+using boostbook
+ : /home/ghost/Store/docbook/xsl
+ : /home/ghost/Store/docbook/dtd
+ : /home/ghost/Work/Boost/boost-svn/tools/boostbook
+ ;
+using doxygen ;
+using qt4 : /usr/share/qt4 ;
diff --git a/tools/build/v2/test/test.jam b/tools/build/v2/test/test.jam
new file mode 100644
index 0000000000..5e1aae9bcd
--- /dev/null
+++ b/tools/build/v2/test/test.jam
@@ -0,0 +1,23 @@
+# Copyright 2001, 2002, 2003 Dave Abrahams
+# Copyright 2002 Rene Rivera
+# Copyright 2002, 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import indirect ;
+import string ;
+import numbers ;
+import sequence ;
+import "class" ;
+import os ;
+import path ;
+import feature ;
+import property ;
+import build-request ;
+import container ;
+import print ;
+import common ;
+
+
+actions nothing { }
+nothing all ;
diff --git a/tools/build/v2/test/test1.py b/tools/build/v2/test/test1.py
new file mode 100644
index 0000000000..3cdc71d2d2
--- /dev/null
+++ b/tools/build/v2/test/test1.py
@@ -0,0 +1,18 @@
+#!/usr/bin/python
+
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("test.jam", """
+actions unbuilt { }
+unbuilt all ;
+ECHO "Hi" ;
+""")
+
+t.run_build_system("-ftest.jam", stdout="Hi\n")
+t.pass_test()
diff --git a/tools/build/v2/test/test2.py b/tools/build/v2/test/test2.py
new file mode 100644
index 0000000000..b5c9ba824e
--- /dev/null
+++ b/tools/build/v2/test/test2.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+
+# Copyright 2002, 2003 Dave Abrahams
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.set_tree("test2")
+
+file_list = 'bin/foo/$toolset/debug/runtime-link-dynamic/' * \
+ BoostBuild.List("foo foo.o")
+
+t.run_build_system("-sBOOST_BUILD_PATH=" + t.original_workdir + "/..")
+t.expect_addition(file_list)
+
+
+t.write("foo.cpp", "int main() {}\n")
+t.run_build_system("-d2 -sBOOST_BUILD_PATH=" + t.original_workdir + "/..")
+t.expect_touch(file_list)
+
+t.pass_test()
diff --git a/tools/build/v2/test/test2/Jamrules b/tools/build/v2/test/test2/Jamrules
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/test/test2/Jamrules
diff --git a/tools/build/v2/test/test2/foo.cpp b/tools/build/v2/test/test2/foo.cpp
new file mode 100644
index 0000000000..135fa90f6d
--- /dev/null
+++ b/tools/build/v2/test/test2/foo.cpp
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org
+//
+
+int main() { return 0; }
diff --git a/tools/build/v2/test/test2/jamfile.jam b/tools/build/v2/test/test2/jamfile.jam
new file mode 100644
index 0000000000..670583964e
--- /dev/null
+++ b/tools/build/v2/test/test2/jamfile.jam
@@ -0,0 +1,8 @@
+# Copyright 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+project-root ;
+
+exe foo : foo.cpp ;
diff --git a/tools/build/v2/test/test_all.py b/tools/build/v2/test/test_all.py
new file mode 100644
index 0000000000..59476bd740
--- /dev/null
+++ b/tools/build/v2/test/test_all.py
@@ -0,0 +1,240 @@
+#!/usr/bin/python
+
+# Copyright 2002-2005 Dave Abrahams.
+# Copyright 2002-2006 Vladimir Prus.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import os
+import sys
+import string
+import BoostBuild
+
+xml = "--xml" in sys.argv
+toolset = BoostBuild.get_toolset()
+
+
+# Clear environment for testing.
+#
+for s in ('BOOST_ROOT', 'BOOST_BUILD_PATH', 'JAM_TOOLSET', 'BCCROOT', 'MSVCDir',
+ 'MSVC', 'MSVCNT', 'MINGW', 'watcom' ):
+ try:
+ del os.environ[s]
+ except:
+ pass
+
+BoostBuild.set_defer_annotations(1)
+
+
+def run_tests(critical_tests, other_tests):
+ """Runs first critical tests and then other_tests.
+
+ Stops on first error, and write the name of failed test to
+ test_results.txt. Critical tests are run in the specified order, other
+ tests are run starting with the one that failed the last time.
+ """
+ last_failed = last_failed_test()
+ other_tests = reorder_tests(other_tests, last_failed)
+ all_tests = critical_tests + other_tests
+
+ invocation_dir = os.getcwd()
+
+ pass_count = 0
+ failures_count = 0
+
+ for i in all_tests:
+ passed = 1
+ if not xml:
+ print ("%-25s : " %(i)),
+ try:
+ __import__(i)
+ except SystemExit:
+ passed = 0;
+ if failures_count == 0:
+ f = open(os.path.join(invocation_dir, 'test_results.txt'), 'w')
+ f.write(i)
+ f.close()
+ failures_count = failures_count + 1
+ # Restore the current directory, which might be changed by the test.
+ os.chdir(invocation_dir)
+
+ if not xml:
+ if passed:
+ print "PASSED"
+ else:
+ print "FAILED"
+
+ if i == "regression":
+ BoostBuild.flush_annotations()
+ BoostBuild.clear_annotations()
+ else:
+ rs = "succeed"
+ if not passed:
+ rs = "fail"
+ print """
+<test-log library="build" test-name="%s" test-type="run" toolset="%s" test-program="%s" target-directory="%s">
+<run result="%s">""" % (i, toolset, "tools/build/v2/test/" + i + ".py",
+ "boost/bin.v2/boost.build.tests/" + toolset + "/" + i, rs)
+
+ if not passed:
+ BoostBuild.flush_annotations(1)
+
+ print """
+</run>
+</test-log>
+"""
+ if passed:
+ pass_count = pass_count + 1
+ sys.stdout.flush() # Makes testing under emacs more entertaining.
+
+ # Erase the file on success.
+ if failures_count == 0:
+ open('test_results.txt', 'w')
+
+ if not xml:
+ print """
+ === Test summary ===
+ PASS: %d
+ FAIL: %d
+ """ % (pass_count, failures_count)
+
+
+def last_failed_test():
+ "Returns the name of last failed test or None"
+ try:
+ f = open("test_results.txt")
+ s = string.strip(f.read())
+ return s
+ except:
+ return None
+
+
+def reorder_tests(tests, first_test):
+ try:
+ n = tests.index(first_test)
+ return [first_test] + tests[:n] + tests[n+1:]
+ except ValueError:
+ return tests
+
+
+critical_tests = ["unit_tests", "module_actions", "startup_v1", "startup_v2"]
+
+critical_tests += ["core_d12", "core_typecheck", "core_delete_module",
+ "core_varnames", "core_import_module"]
+
+tests = [ "absolute_sources",
+ "alias",
+ "alternatives",
+ "bad_dirname",
+ "build_dir",
+ "build_file",
+ "build_no",
+ "c_file",
+ "chain",
+ "clean",
+ "composite",
+ "conditionals",
+ "conditionals2",
+ "conditionals3",
+ "conditionals_multiple",
+ "configuration",
+ "copy_time",
+ "custom_generator",
+ "default_build",
+ "default_features",
+# This test is known to be broken itself.
+# "default_toolset",
+ "dependency_property",
+ "dependency_test",
+ "disambiguation",
+ "dll_path",
+ "double_loading",
+ "duplicate",
+ "example_libraries",
+ "example_make",
+ "expansion",
+ "explicit",
+ "file_name_handling",
+ "free_features_request",
+ "generator_selection",
+ "generators_test",
+ "implicit_dependency",
+ "indirect_conditional",
+ "inherit_toolset",
+ "inherited_dependency",
+ "inline",
+ "lib_source_property",
+ "library_chain",
+ "library_property",
+ "load_order",
+ "loop",
+ "make_rule",
+ "ndebug",
+ "no_type",
+ "notfile",
+ "ordered_include",
+ "out_of_tree",
+ "path_features",
+ "prebuilt",
+ "print",
+ "project_dependencies",
+ "project_glob",
+ "project_root_constants",
+ "project_root_rule",
+ "project_test3",
+ "project_test4",
+ "property_expansion",
+ "rebuilds",
+ "regression",
+ "relative_sources",
+ "remove_requirement",
+ "resolution",
+ "searched_lib",
+ "skipping",
+ "sort_rule",
+ "source_locations",
+ "stage",
+ "standalone",
+ "suffix",
+ "tag",
+ "test_result_dumping",
+ "testing_support",
+ "timedata",
+ "unit_test",
+ "use_requirements",
+ "using",
+ "wrapper",
+ "wrong_project",
+ "exit_status",
+ ]
+
+if os.name == 'posix':
+ tests.append("symlink")
+ # On windows, library order is not important, so skip this test. Besides, it
+ # fails ;-). Further, the test relies on the fact that on Linux, one can
+ # build a shared library with unresolved symbols. This is not true on
+ # Windows (even with cygwin gcc).
+ if string.find(os.uname()[0], "CYGWIN") == -1:
+ tests.append("library_order")
+
+if string.find(BoostBuild.get_toolset(), 'gcc') == 0:
+ tests.append("gcc_runtime")
+
+if ( string.find(BoostBuild.get_toolset(), 'gcc') == 0 )or \
+ ( string.find(BoostBuild.get_toolset(), 'msvc') == 0 ):
+ tests.append("pch")
+
+if "--extras" in sys.argv:
+ tests.append("boostbook")
+ tests.append("qt4")
+ tests.append("example_qt4")
+ # Requires ./whatever.py to work, so is not guaranted to work everywhere.
+ tests.append("example_customization")
+ # Requires gettext tools.
+ tests.append("example_gettext")
+
+elif not xml:
+ print 'Note: skipping extra tests'
+
+run_tests(critical_tests, tests)
diff --git a/tools/build/v2/test/test_nt_line_length.jam b/tools/build/v2/test/test_nt_line_length.jam
new file mode 100644
index 0000000000..bc003964e3
--- /dev/null
+++ b/tools/build/v2/test/test_nt_line_length.jam
@@ -0,0 +1,39 @@
+# Copyright 2001 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that the patch which allows long command-lines in actions on NT is
+# working. For reasons of backward-compatibility, this patch requires that the
+# action fits on a single command-line, and that the JAMSHELL variable on the
+# target being built is set to "%".
+if $(NT)
+{
+ #
+ # Build a really long commandline. (> 10K characters).
+ #
+ ten = 0 1 2 3 4 5 6 7 8 9 ;
+ 1x7chars = 0_____ ;
+ # add a digit and multiply by 10
+ 10x8chars = $(ten)$(1x7chars) ;
+ # add a digit to each of 10 strings and multiply by 10
+ 100x9chars = $(ten)$(10x8chars) ;
+ # add a digit to each of 100 strings and multiply by 10
+ 1000x10chars = $(ten)$(100x9chars) ;
+
+ #
+ # Cause line_length_test to be built
+ #
+ actions do_echo
+ {
+ echo $(text)
+ }
+
+ 400x10chars = $(ten[1-4])$(100x9chars) ;
+
+ text on line_length_test = $(400x10chars) 40$(10x8chars[1-9]) 01234 ;
+ text on line_length_test = $(1000x10chars) $(1000x10chars) ;
+ JAMSHELL on line_length_test = % ;
+ DEPENDS all : line_length_test ;
+
+ do_echo line_length_test ;
+}
diff --git a/tools/build/v2/test/test_result_dumping.py b/tools/build/v2/test/test_result_dumping.py
new file mode 100755
index 0000000000..07eb594808
--- /dev/null
+++ b/tools/build/v2/test/test_result_dumping.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+
+# Copyright 2008 Jurko Gospodnetic
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests dumping Boost Build based testing results.
+
+import BoostBuild
+
+
+################################################################################
+#
+# Test that dumping Boost Build based testing results works in case test code
+# is not located in a folder under the Jamroot folder.
+#
+################################################################################
+
+t = BoostBuild.Tester("--dump-tests")
+
+t.write("TestBuild/jamroot.jam", """
+import testing ;
+test-suite testit : [ run ../TestSource/test.cpp ] ;
+""")
+
+t.write("TestSource/test.cpp", """
+int main() {}
+""")
+
+t.run_build_system("", subdir="TestBuild")
+t.expect_output_line('boost-test(RUN) "*/TestBuild/test" : "../TestSource/test.cpp"')
+
+t.cleanup()
diff --git a/tools/build/v2/test/test_system.html b/tools/build/v2/test/test_system.html
new file mode 100644
index 0000000000..e425ee1030
--- /dev/null
+++ b/tools/build/v2/test/test_system.html
@@ -0,0 +1,618 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+"http://www.w3.org/TR/html4/strict.dtd">
+
+<html>
+ <head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st March 2002), see www.w3.org">
+ <!--tidy options: -i -wrap 78 -->
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+
+ <title>A testing system for Boost.Build</title>
+<style type="text/css">
+ hr { color: black }
+ p.revision { text-align: right; font-style: italic }
+ pre.code { margin-left: 2em }
+ pre.example { margin-left: 2em; border: solid black thin }
+ pre.output { margin-left: 2em }
+ img.banner { border: 0; float: left }
+ h1 { text-align: right }
+ br.clear { clear: left }
+ div.attention { color: red }
+
+</style>
+ </head>
+
+ <body>
+ <p><a href="../../../../index.htm"><img class="banner" height="86" width=
+ "277" alt="C++ Boost" src="../../../../boost.png"></a></p>
+
+ <h1>A testing system for Boost.Build<br class="clear">
+ </h1>
+ <hr>
+
+ <dl class="page-index">
+ <dt><a href="#sec-intro">Introduction for users</a></dt>
+
+ <dd>
+ <dl class="page-index">
+ <dt><a href="#sec-command-line-options">Command line options</a></dt>
+ </dl>
+ </dd>
+
+ <dt><a href="#sec-developers">Introduction for developers</a></dt>
+
+ <dd>
+ <dl class="page-index">
+ <dt><a href="#sec-intro-changing">Changing the working
+ directory</a></dt>
+
+ <dt><a href="#sec-intro-examining">Examining the working directory and
+ changing it</a></dt>
+
+ <dt><a href="#sec-intro-results">Test result</a></dt>
+ </dl>
+ </dd>
+
+ <dt><a href="#sec-reference">Reference documentation</a></dt>
+
+ <dd>
+ <dl class="page-index">
+ <dt><a href="#method-__init__">Method __init__</a></dt>
+
+ <dt><a href="#method-set_tree">Method <tt>set_tree</tt></a></dt>
+
+ <dt><a href="#method-write">Method <tt>write</tt></a></dt>
+
+ <dt><a href="#method-copy">Method <tt>copy</tt></a></dt>
+
+ <dt><a href="#method-touch">Method <tt>touch</tt></a></dt>
+
+ <dt><a href="#method-run_build_system">Method
+ <tt>run_build_system</tt></a></dt>
+
+ <dt><a href="#method-read">Method <tt>read</tt></a></dt>
+
+ <dt><a href="#method-read_and_strip">Method
+ <tt>read_and_strip</tt></a></dt>
+
+ <dt><a href="#methods-expectations">Methods for declaring
+ expectations</a></dt>
+
+ <dt><a href="#methods-ignoring">Methods for ignoring
+ changes</a></dt>
+
+ <dt><a href="#methods-result">Methods for explicitly specifying
+ results</a></dt>
+
+ <dt><a href="#class-list">Helper class <tt>List</tt></a></dt>
+ </dl>
+ </dd>
+ </dl>
+ <hr>
+
+ <h2><a name="sec-intro">Introduction for users</a></h2>
+
+ <p>The testing system for Boost.Build is a small set of Python modules and
+ scripts for automatically testing user-obversable behaviour. It uses
+ components from testing systems of <a href="http://www.scons.org">Scons</a>
+ and <a href="http://subversion.tigris.org">Subversion</a>, together with
+ some additional functionality.</p>
+
+ <p>To run the tests you need to:</p>
+
+ <ol>
+ <li>Get the source tree of Boost.Build (located at <tt>tools/build</tt>
+ in Boost)</li>
+
+ <li>Have <a href="http://www.python.org">Python</a> installed. Version
+ 2.1 is known to work.</li>
+
+ <li>Build Boost.Jam. See <a href=
+ "../engine/index.html">$boost_build_root/engine/index.html</a> for
+ instructions.</li>
+
+ <li>Configure at least one toolset. You can edit <tt>site-config.jam</tt>
+ or <tt>user-config.jam</tt> to add new toolsets. Or you can create file
+ <tt>test-config.jam</tt> in <tt>$boost_build_root/test</tt> directory. In
+ this case, <tt>site-config.jam</tt> and <tt>user-config.jam</tt> will be
+ ignored for testing.</li>
+ </ol>
+
+ <p>When all is set, you can run all the tests using the <tt>test_all.py</tt>
+ script or you can run a specific test by starting its Python script
+ directly.</p>
+
+ <p>Examples:</p>
+
+<pre class="code">
+python test_all.py
+python generators_test.py
+</pre>
+
+ <p>If everything is OK, you will see a list of passed tests. Otherwise, a
+ failure will be reported.</p>
+
+ <h3><a name="sec-command-line-options">Command line options</a></h3>
+
+ <p>Test scripts will use the toolset you configured to be the default or
+ you can specify a specific one on the command line:</p>
+
+<pre class="code">
+python test_all.py borland
+python generators_test.py msvc-7.1
+</pre>
+
+ <p>Other test script flags you can specify on the command line are:</p>
+
+ <ul>
+ <li><tt>--default-bjam</tt> -- By default the test system will use the
+ Boost Jam executable found built in its default development build
+ location. This option makes it use the default one available on your
+ system, i.e. the one found in the system path.</li>
+
+ <li><tt>--preserve</tt> -- In case of a failed test its working
+ directory will be copied to the "failed_test" directory under the
+ current directory.</li>
+
+ <li><tt>--verbose</tt> -- Makes the test system and the run build system
+ display additional output. Note though that this may cause tests that
+ check the build system output to fail.</li>
+ </ul>
+
+ <h2><a name="sec-developers">Introduction for developers</a></h2>
+
+ <p>It is suggested that every new functionality come together with tests,
+ and that bugfixes are accompanied by tests. There's no need to say that
+ tests are good, but two points are extremely important:</p>
+
+ <ul>
+ <li>For an interpreted language like Jam, without any static checks,
+ testing is simply the only sefeguard we can have.</li>
+
+ <li>Good tests allow us to change internal design much more safely, and we
+ have not gotten everything nailed down yet.</li>
+ </ul>
+
+ <p>Adding a new test is simple:</p>
+
+ <ol>
+ <li>Go to <tt>$boost_build_root/test/test_all.py</tt> and add new test
+ name to the list at the end of the file. Suppose the test name is "hello".
+ </li>
+
+ <li>Add a new python module, in this example "hello.py", to do the actual
+ testing.</li>
+ </ol>
+
+ <p>The module, in general will perform these basic actions:</p>
+
+ <ol>
+ <li>Set up the initial working directory state</li>
+
+ <li>
+ Run the build system and check the results:
+
+ <ol>
+ <li>generated output,</li>
+
+ <li>changes made to the working directory,</li>
+
+ <li>new content of the working directory.</li>
+ </ol>
+ </li>
+
+ <li>Add, remove or touch files or change their content and then repeat
+ the previous step until satisfied.</li>
+
+ <li>Clean up</li>
+ </ol>
+
+ <p>The "hello.py" module might contain:</p>
+<pre class="example">
+from BoostBuild import List
+
+# Create a temporary working directory
+t = BoostBuild.Tester()
+
+# Create the needed files
+t.write("jamroot.jam", "")
+t.write("jamfile.jam", """
+exe hello : hello.cpp ;
+""")
+t.write("hello.cpp", """
+int main()
+{
+ return 0;
+}
+
+""")
+
+t.run_build_system()
+
+# First, create a list of three pathnames.
+file_list = List("bin/$toolset/debug/") * List("hello.exe hello.obj")
+# Second, assert that those files were added as result of the last build system invocation.
+t.expect_addition(file_list)
+
+# Invoke the build system once again.
+t.run_build_system("clean")
+# Check if the files added previously were removed.
+t.expect_removal(file_list)
+
+# Remove temporary directories
+t.cleanup()
+</pre>
+
+ <p>The <tt>test</tt> directory contains a file "template.py" which can be
+ used as a start for your own tests.</p>
+
+ <p>Overview of the most important methods of class <tt>Tester</tt> follows.
+ </p>
+
+ <h3><a name="sec-intro-changing">Changing the working directory</a></h3>
+
+ <p>The class <tt>Tester</tt> creates a temporary directory in its
+ constructor and changes to that directory. It can be modified by calling
+ these methods:</p>
+
+ <ul>
+ <li><tt>set_tree</tt> -- sets the content of the working directory to be
+ equal to the content of the specified directory. This method is
+ preferrable when directory tree for testing is large.</li>
+
+ <li><tt>write</tt> -- sets the content of file in a working directory.
+ This is optimal if you want to create a directory tree with 3-4 small
+ files.</li>
+
+ <li><tt>touch</tt> -- changes the modification times of a file</li>
+ </ul>
+
+ <h3><a name="sec-intro-examining">Examining the working directory and
+ changing it</a></h3>
+
+ <p>The method <tt>read</tt>, inherited from the <tt>TestCmd</tt> class, can
+ be used to read any file in the working directory and check its content.
+ <tt>Tester</tt> adds another method for tracking changes. Whenever the build
+ system is run (using <a href="#method-run_build_system"><tt>run_build_system
+ </tt></a>), the working dir state before and after running is recorded. In
+ addition, difference between the two states -- i.e. lists of files that were
+ added, removed, modified or touched -- are stored in two member variables -
+ <tt>tree_difference</tt> and <tt>unexpected_difference</tt>.</p>
+
+ <p>After than, the test author may specify that some change is expected, for
+ example, by calling <tt>expect_addition("foo")</tt>. This call will check if
+ the file was indeed added, and if so, will remove its name from the list of
+ added files in <tt>unexpected_difference</tt>. Likewise, it is possible to
+ specify that some changes are not interesting, for example a call to
+ <tt>ignore("*.obj")</tt> will just remove every file with the ".obj"
+ extension from <tt>unexpected_difference</tt>.</p>
+
+ <p>When test has finished with expectations and ignoring, the member
+ <tt>unexpected_difference</tt> will contain the list of all changes not yet
+ accounted for. It is possible to assure that this list is empty by calling
+ the <tt>expect_nothing_more</tt> member function.</p>
+
+ <h3><a name="sec-intro-results">Test result</a></h3>
+
+ <p>Any of the <tt>expect*</tt> methods below will fail the test if the
+ expectation is not met. It is also possible to perform manually arbitrary
+ test and explicitly cause the test to either pass or fail. Ordinary
+ filesystem functions can be used to work with the directory tree. Methods
+ <tt>pass_test</tt> and <tt>fail_test</tt> are used to explicitly give the
+ test outcome.</p>
+
+ <p>Typically, after test termination, the working directory is erased. See
+ the <a href="#sec-command-line-options">"--preserve" command line option</a>
+ for information on how to preserve the working directory content for failed
+ tests for debugging purposes.</p>
+
+ <h2 id="sec-reference">Reference documentation</h2>
+
+ <p>The test system is composed of class <tt>Tester</tt>, derived form
+ <tt>TestCmd.TestCmd</tt>, and helper class <tt>List</tt>. <tt>Tester</tt>
+ and <tt>List</tt> methods are described below.</p>
+
+ <p>The documentation frequently refers to <tt>filename</tt>. In all cases,
+ files are specified in unix style: a sequence of components, separated by
+ "/". This is true on all platforms. In some contexts a list of files is
+ allowed. In those cases any object with a sequence interface is allowed.</p>
+
+ <h3><a name="method-__init__">Method <tt>__init__(self, arguments="",
+ executable="bjam", match=TestCmd.match_exact, boost_build_path=None,
+ translate_suffixes=True, pass_toolset=True, use_test_config=True,
+ ignore_toolset_requirements=True, workdir="", **keywords)</tt></a></h3>
+
+ <p><b>Optional arguments:</b></p>
+
+ <ul>
+ <li><tt>arguments</tt>
+ -- Arguments passed to the run executable.</li>
+ <li><tt>executable</tt>
+ -- Name of the executable to invoke.</li>
+ <li><tt>match</tt>
+ -- Function to use for compating actual and expected file contents.
+ </li>
+ <li><tt>boost_build_path</tt>
+ -- Boost build path to be passed to the run executable.</li>
+ <li><tt>translate_suffixes</tt>
+ -- Whether to update suffixes on the the file names passed from the
+ test script so they match those actually created by the current
+ toolset. For example, static library files are specified by using
+ the .lib suffix but when the 'gcc' toolset is used it actually
+ creates them using the .a suffix.</li>
+ <li><tt>pass_toolset</tt>
+ -- Whether the test system should pass the specified toolset to the
+ run executable.</li>
+ <li><tt>use_test_config</tt>
+ -- Whether the test system should tell the run executable to read in
+ the test_config.jam configuration file.</li>
+ <li><tt>ignore_toolset_requirements</tt>
+ -- Whether the test system should tell the run executable to ignore
+ toolset requirements.</li>
+ <li><tt>workdir</tt>
+ -- Indicates an absolute directory where the test will be run from.
+ </li>
+ </ul>
+
+ <p><b>Optional arguments inherited from the base class:</b></p>
+
+ <ul>
+ <li><tt>description</tt>
+ -- Test description string displayed in case of a failed test.</li>
+ <li><tt>subdir</tt>
+ -- List of subdirectories to automatically create under the working
+ directory. Each subdirectory needs to be specified separately
+ parent coming before its child.</li>
+ <li><tt>verbose</tt>
+ -- Flag that may be used to enable more verbose test system output.
+ Note that it does not also enable more verbose build system output
+ like the <a href="#sec-command-line-options">"--verbose" command
+ line option</a> does.</li>
+ </ul>
+
+ <p><b>Effects:</b></p>
+
+ <ol>
+ <li>Remembers the current working directory in member
+ <tt>original_workdir</tt>.</li>
+
+ <li>Determines the location of the executable (<code>bjam</code> by
+ default) and build system files, assuming that the current directory is
+ <tt>tools/build/test</tt>. Formulates jam invocation command, which
+ will include explicit setting for the <tt>BOOST_BUILD_PATH</tt> variable
+ and arguments passed to this methods, if any. This command will be used
+ by subsequent invocation of <a href="#method-run_build_system"><tt>
+ run_build_system</tt></a>. Finally, initializes the base class.</li>
+
+ <li>Changes the current working directory to the temporary working
+ directory created by the base constructor.</li>
+
+ <li>If you want to run a test in an existing directory, pass it as
+ <tt>workdir</tt>.</li>
+
+ <li> Most parameters passed to this constructor function may be overruled
+ for each specific test system run using <a href=
+ "#method-run_build_system"><tt>run_build_system</tt></a> parameters.
+ </ol>
+
+ <h3><a name="method-set_tree">Method <tt>set_tree(self,
+ tree_location)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Replaces the content of the current working directory with the content
+ of directory at <tt>tree_location</tt>. If <tt>tree_location</tt> is not
+ absolute pathname, it will be treated as relative to
+ <tt>self.original_workdir</tt>. This methods also explicitly makes the
+ copied files writeable.</p>
+
+ <h3><a name="method-write">Method <tt>write(self, name,
+ content)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Writes the specified content to the file given by <tt>name</tt> under
+ the temporary working directory. If the file already exists, it is
+ overwritten. Any required directories are automatically created.</p>
+
+ <h3><a name="method-copy">Method <tt>copy(self, src, dst)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Equvivalent to <tt>self.write(self.read(src), dst)</tt>.</p>
+
+ <h3><a name="method-touch">Method <tt>touch(self, names)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Sets the access and modification times for all files in <tt>names</tt> to
+ the current time. All the elements in <tt>names</tt> should be relative
+ paths.</p>
+
+ <h3><a name="method-run_build_system">Method <tt>run_build_system(self,
+ extra_args="", subdir="", stdout=None, stderr="", status=0, match=None,
+ pass_toolset=None, use_test_config=None, ignore_toolset_requirements=None,
+ expected_duration=None, **kw)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <ol>
+ <li>Stores the state of the working directory in
+ <tt>self.previous_tree</tt>.</li>
+
+ <li>Changes to <tt>subdir</tt>, if it is specified. It is relative to
+ the <tt>original_workdir</tt> or the workdir specified in
+ <tt>__init</tt>.</li>
+
+ <li>Invokes the <tt>bjam</tt> executable, passing <tt>extra_args</tt>
+ to it. The binary should be located under
+ <tt>&lt;test_invocation_dir&gt;/../jam/src/bin.&lt;platform&gt;</tt>.
+ This is to make sure tests use the version of jam build from CVS.</li>
+
+ <li>Compares the stdout, stderr and exit status of build system
+ invocation with values to appropriate parameters, if they are not
+ <tt>None</tt>. If any difference is found, the test fails.</li>
+
+ <li>If the <tt>expected_duration</tt> parameter is specified then it
+ represents the maximal allowed time in seconds for the test to run. The
+ test will be marked as failed if its duration is greater than the given
+ <tt>expected_duration</tt> parameter value.</li>
+
+ <li>Stores the new state of the working directory in <tt>self.tree</tt>.
+ Computes the difference between previous and current trees and stores them
+ in variables <tt>self.tree_difference</tt> and
+ <tt>self.unexpected_difference</tt>. Both variables are instances of class
+ <tt>tree.Trees_different</tt>, which have four attributes:
+ <tt>added_files</tt>, <tt>removed_files</tt>, <tt>modified_files</tt> and
+ <tt>touched_files</tt>. Each is a list of strings.</p></li>
+ </ol>
+
+ <h3><a name="method-read">Method <tt>read(self, name)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Read the specified file and returns it content. Raises an exception is
+ the file is absent.</p>
+
+ <h3><a name="method-read_and_strip">Method <tt>read_and_strip(self, name)
+ </tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Read the specified file and returns it content, after removing trailing
+ whitespace from every line. Raises an exception is the file is absent.</p>
+
+ <p><b>Rationale:</b></p>
+
+ <p>Althought this method is questionable, there are a lot of cases when jam
+ or shells it uses insert spaces. It seems that introducing this method is
+ much simpler than dealing with all those cases.</p>
+
+ <h3><a name="methods-expectations">Methods for declaring expectations</a>
+ </h3>
+
+ <p>Accordingly to the number of changes kinds that are detected, there are
+ four methods that specify that test author expects a specific change to
+ occur. They check <tt>self.unexpected_difference</tt>, and if the change is
+ present there, it is removed. Otherwise, test fails.</p>
+
+ <p>Each method accepts a list of names. Those names use <tt>/</tt> path
+ separator on all systems. Additionaly, the test system translates suffixes
+ appropriately. For the test to be portable, suffixes should use Windows
+ convention: <tt>exe</tt> for executables, <tt>dll</tt> for dynamic libraries
+ and <tt>lib</tt> for static libraries. Lastly, the string "$toolset" in file
+ names is replaced by the name of tested toolset.</p>
+
+ <p><b>Note:</b> The <tt>List</tt> helper class might be useful to create
+ lists of names.</p>
+
+ <p><b>Note:</b> The file content can be examined using the
+ <tt>TestCmd.read</tt> function.</p>
+
+ <p>The members are:</p>
+
+ <ul>
+ <li>expect_addition</li>
+ <li>expect_removal</li>
+ <li>expect_modification</li>
+ <li>expect_nothing</li>
+ </ul>
+
+ <p>Note that <tt>expect_modification</tt> is used to check that a either
+ file content or timestamp has changed. The rationale is that some compilers
+ change content even if sources does not change, and it's easier to have a
+ method which checks for both content and time changes.</p>
+
+ <p>There's also a member <tt>expect_nothing_more</tt>, which checks that all
+ the changes are either expected or ignored, in other words that
+ <tt>unexpected_difference</tt> is empty by now.</p>
+
+ <p>Lastly, there's a method to compare file content with expected content:
+ </p>
+ <tt>expect_content(self, name, content, exact=0)</tt>
+
+ <p>The method fails the test if the content of file identified by 'name' is
+ different from 'content'. If 'exact' is true, the file content is used
+ as-is, otherwise, two transformations are applied:</p>
+
+ <ul>
+ <li>The <tt>read_and_strip</tt> method is used to read the file, which
+ removes trailing whitespace</li>
+
+ <li>Each backslash in the file content is converted to forward slash.</li>
+ </ul>
+
+ <h3><a name="methods-ignoring">Methods for ignoring changes</a></h3>
+
+ <p>There are five methods which ignore changes made to the working tree.
+ They silently remove elements from <tt>self.unexpected_difference</tt>, and
+ don't generate error if element is not found. They accept shell style
+ wildcard.</p>
+
+ <p>The following methods correspond to four kinds of changes:</p>
+
+ <ul>
+ <li>ignore_addition(self, wildcard)</li>
+ <li>ignore_removal(self, wildcard)</li>
+ <li>ignore_modification(self, wildcard)</li>
+ <li>ignore_touch(self, wilcard)</li>
+ </ul>
+
+ <p>The method <tt>ignore(self, wildcard)</tt> ignores all the changes made
+ to files that match a wildcard.</p>
+
+ <h3><a name="methods-result">Methods for explicitly specifying results</a>
+ </h3>
+
+ <h4>Method <tt>pass_test(self, condition=1)</tt></h4>
+
+ <div class="attention">
+ At this moment, the method should not be used.
+ </div>
+
+ <h4>Method <tt>fail_test(self, condition=1)</tt></h4>
+
+ <p><b>Effects:</b> Cause the test to fail if <tt>condition</tt> is true.</p>
+
+ <h3><a name="class-list">Helper class <tt>List</tt></a></h3>
+ The class has sequence interface and two additional methods.
+
+ <h4>Method <tt>__init__(self, string)</tt></h4>
+
+ <p><b>Effects:</b> Splits the string on unescaped spaces and tabs. The split
+ components can further be retrieved using standard sequence access.</p>
+
+ <h4>Method <tt>__mul__(self, other)</tt></h4>
+
+ <p><b>Effects:</b> Returns an <tt>List</tt> instance, which elements are all
+ possible concatenations of two string, first of which is from <tt>self</tt>,
+ and second of which is from <tt>other</tt>.</p>
+
+ <p>The class also defines <tt>__str__</tt> and <tt>__repr__</tt> methods.
+ Finally, there's <tt>__coerce__</tt> method which allows to convert strings
+ to instances of <tt>List</tt>.</p>
+
+ <p><b>Example:</b></p>
+<pre>
+ l = "a b" * List("c d")
+ for e in l:
+ print e
+</pre>
+
+ <p>will output:</p>
+<pre>
+ ac
+ ad
+ bc
+ bd
+
+</pre>
+ <hr>
+ <p class="revision">Last modified: May 02, 2008</p>
+ <p>&copy; Copyright Vladimir Prus 2002, 2003, 2004, 2005.<br>
+ &copy; Copyright Jurko Gospodnetic 2008.<br>
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)</p>
+ </body>
+</html>
diff --git a/tools/build/v2/test/testing-primitives/boost-build.jam b/tools/build/v2/test/testing-primitives/boost-build.jam
new file mode 100644
index 0000000000..667355a164
--- /dev/null
+++ b/tools/build/v2/test/testing-primitives/boost-build.jam
@@ -0,0 +1,5 @@
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+boost-build . ;
diff --git a/tools/build/v2/test/testing-primitives/bootstrap.jam b/tools/build/v2/test/testing-primitives/bootstrap.jam
new file mode 100644
index 0000000000..2b1ad48542
--- /dev/null
+++ b/tools/build/v2/test/testing-primitives/bootstrap.jam
@@ -0,0 +1,137 @@
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Proof-of-concept for bjam-based testing mechanism. This file should
+# work on NT, Cygwin, and Linux. No promises for other platforms.
+
+# Set a variable which says how to dump a file to stdout
+if $(NT)
+{
+ CATENATE = type ;
+}
+else
+{
+ CATENATE = cat ;
+}
+
+# invoke the given action rule `act' to build target from sources
+rule do-make ( target : sources * : act )
+{
+ DEPENDS $(target) : $(sources) ;
+ $(act) $(target) : $(sources) ;
+}
+
+# top-level version of do-make which causes target to be built by
+# default
+rule make ( target : sources * : act )
+{
+ DEPENDS all : $(target) ;
+ do-make $(target) : $(sources) : $(act) ;
+}
+
+# cause `target' to exist and building to succeed if invoking
+#
+# $(act) $(target) : $(sources)
+#
+# fails, and to fail if the action succeeds.
+rule make-fail ( target : sources * : act )
+{
+ # Establish another logical target which refers to the same file,
+ # by using different grist.
+ DEPENDS all : <different-grist>$(target) ;
+
+ # Make the new logical target depend on the target
+ DEPENDS <different-grist>$(target) : $(target) ;
+
+ # Cause the target to be built from sources using $(act).
+ do-make $(target) : $(sources) : $(act) ;
+
+ # Note that we expect target to fail to build
+ FAIL_EXPECTED $(target) ;
+
+ # Build a failure marker file. Because targets are only built if
+ # all their dependents "succeed", the marker will only be
+ # generated if $(target) failed to build, as expected.
+ failure-marker <different-grist>$(target) ;
+}
+
+# Simple action rules which write text into the target. Different
+# names for different purposes.
+actions failure-marker
+{
+ echo failed as expected > $(<)
+}
+
+actions create
+{
+ echo creating > $(<)
+}
+
+# An action which will always fail, for testing expected failure rules
+actions fail-to-create
+{
+ exit 1
+}
+
+# Basic rule-action pair which builds the target by executing the
+# given commands
+rule do-run ( target : commands + )
+{
+ COMMANDS on $(target) = $(commands) ;
+ NOTFILE $(commands) ;
+}
+
+# Run commands, leaving the output behind in $(<:S=.out). Echo to
+# stdout if the command fails.
+#
+# Detailed explanation:
+#
+# $(COMMANDS) Run commands
+# > $(<:S=.out) into the output file
+# 2>&1 including stderr
+# && and if that succeeds
+# cp -f $(<:S=.out) $(<) copy the output file into the target
+# || otherwise
+# ( $(CATENATE) $(<:S=.out) dump any output to stdout
+# && exit 1 and exit with an error code
+# )
+actions do-run
+{
+ $(COMMANDS) > $(<:S=.out) 2>&1 && cp -f $(<:S=.out) $(<) || ( $(CATENATE) $(<:S=.out) && exit 1 )
+}
+
+# top-level version of do-run which causes target to be built by
+# default
+rule run ( target : commands + )
+{
+ DEPENDS all : $(target) ;
+ do-run $(target) : $(commands) ;
+}
+
+# experimental expected-failure version of run. This doesn't have
+# quite the right semantics w.r.t. output dumping (it is still only
+# dumped if the run fails), but we don't need run-fail anyway so it
+# doesn't matter too much.
+rule run-fail ( target : commands + )
+{
+ make-fail $(target) : $(commands) : do-run ;
+}
+
+# A command which will always fail to run. There is no file called
+# nonexistent, so executing $(error) always causes an error. We can't
+# just use `exit 1' below because that will cause all command
+# processing to stop, and we want the rest of the do-run action
+# command-line to execute.
+error = $(CATENATE)" nonexistent" ;
+
+make-fail t1.txt : : create ;
+make-fail t2.txt : : fail-to-create ;
+make t3.txt : : create ;
+make t4.txt : : fail-to-create ;
+
+run t5.txt : "( echo failing t5 && $(error) )" ;
+run t6.txt : echo hi ;
+
+run-fail t7.txt : "( echo failing t7 && $(error) )" ;
+run-fail t8.txt : echo hi ;
diff --git a/tools/build/v2/test/testing_primitives.py b/tools/build/v2/test/testing_primitives.py
new file mode 100644
index 0000000000..ae62993b32
--- /dev/null
+++ b/tools/build/v2/test/testing_primitives.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import re
+
+def match_re(actual, expected):
+ return re.match(expected, actual, re.DOTALL) != None
+
+t = BoostBuild.Tester(match=match_re)
+
+t.set_tree('testing-primitives')
+
+# We expect t5 and t7's output to be dumped to stdout.
+t.run_build_system(stdout=r'''.*failing t5.*failing t7''')
+
+t.expect_addition('t2.txt')
+t.expect_addition('t3.txt')
+t.expect_addition('t5.out')
+t.expect_addition('t6.out')
+t.expect_addition('t6.txt')
+t.expect_addition('t7.out')
+t.expect_addition('t7.txt')
+t.expect_addition('t8.out')
+t.expect_nothing_more()
+
+t.cleanup()
diff --git a/tools/build/v2/test/testing_support.py b/tools/build/v2/test/testing_support.py
new file mode 100755
index 0000000000..eee4345c5a
--- /dev/null
+++ b/tools/build/v2/test/testing_support.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+
+# Copyright 2008 Jurko Gospodnetic
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests different aspects of Boost Builds automated testing support.
+
+import BoostBuild
+
+
+################################################################################
+#
+# test_files_with_spaces_in_their_name()
+# --------------------------------------
+#
+################################################################################
+
+def test_files_with_spaces_in_their_name():
+ """Regression test making sure test result files get created correctly when
+ testing files with spaces in their name.
+ """
+
+ t = BoostBuild.Tester()
+
+ t.write("valid source.cpp", "int main() {}\n");
+
+ t.write("invalid source.cpp", "this is not valid source code");
+
+ t.write("jamroot.jam", """
+import testing ;
+testing.compile "valid source.cpp" ;
+testing.compile-fail "invalid source.cpp" ;
+""")
+
+ t.run_build_system(status=0)
+ t.expect_addition("bin/invalid source.test/$toolset/debug/invalid source.obj")
+ t.expect_addition("bin/invalid source.test/$toolset/debug/invalid source.test")
+ t.expect_addition("bin/valid source.test/$toolset/debug/valid source.obj")
+ t.expect_addition("bin/valid source.test/$toolset/debug/valid source.test")
+
+ t.expect_content("bin/valid source.test/$toolset/debug/valid source.test", \
+ "passed" )
+ t.expect_content( \
+ "bin/invalid source.test/$toolset/debug/invalid source.test", \
+ "passed" )
+ t.expect_content( \
+ "bin/invalid source.test/$toolset/debug/invalid source.obj", \
+ "failed as expected" )
+
+ t.cleanup()
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+test_files_with_spaces_in_their_name()
diff --git a/tools/build/v2/test/timedata.py b/tools/build/v2/test/timedata.py
new file mode 100644
index 0000000000..04ec99f98a
--- /dev/null
+++ b/tools/build/v2/test/timedata.py
@@ -0,0 +1,155 @@
+#!/usr/bin/python
+
+# Copyright 2005 David Abrahams
+# Copyright 2008 Jurko Gospodnetic
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests the build step timing facilities.
+
+
+import BoostBuild
+import re
+
+
+################################################################################
+#
+# basic_jam_action_test()
+# -----------------------
+#
+################################################################################
+
+def basic_jam_action_test():
+ """Tests basic Jam action timing support."""
+
+ t = BoostBuild.Tester(pass_toolset=0)
+
+ t.write("file.jam", """
+rule time
+{
+ DEPENDS $(<) : $(>) ;
+ __TIMING_RULE__ on $(>) = record_time $(<) ;
+ DEPENDS all : $(<) ;
+}
+
+actions time
+{
+ echo $(>) user: $(__USER_TIME__) system: $(__SYSTEM_TIME__)
+ echo timed from $(>) >> $(<)
+}
+
+rule record_time ( target : source : start end user system )
+{
+ __USER_TIME__ on $(target) = $(user) ;
+ __SYSTEM_TIME__ on $(target) = $(system) ;
+}
+
+rule make
+{
+ DEPENDS $(<) : $(>) ;
+}
+
+actions make
+{
+ echo made from $(>) >> $(<)
+}
+
+time foo : bar ;
+make bar : baz ;
+""")
+
+ t.write("baz", "nothing\n")
+
+ expected_output = """\.\.\.found 4 targets\.\.\.
+\.\.\.updating 2 targets\.\.\.
+make bar
+time foo
+bar +user: [0-9\.]+ +system: +[0-9\.]+ *
+\.\.\.updated 2 targets\.\.\.$
+"""
+
+ t.run_build_system("-ffile.jam -d+1", stdout=expected_output, match=lambda
+ actual, expected: re.search(expected, actual, re.DOTALL))
+ t.expect_addition("foo")
+ t.expect_addition("bar")
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# boost_build_testing_support_timing_rule():
+# ------------------------------------------
+#
+################################################################################
+
+def boost_build_testing_support_timing_rule():
+ """Tests the target build timing rule provided by the Boost Build testing
+ support system.
+ """
+
+ t = BoostBuild.Tester()
+
+ t.write("aaa.cpp", "int main() {}\n")
+
+ t.write("jamroot.jam", """
+import testing ;
+exe my-exe : aaa.cpp ;
+time my-time : my-exe ;
+""")
+
+ t.run_build_system()
+ t.expect_addition("bin/$toolset/debug/aaa.obj")
+ t.expect_addition("bin/$toolset/debug/my-exe.exe")
+ t.expect_addition("bin/$toolset/debug/my-time.time")
+
+ t.expect_content_line("bin/$toolset/debug/my-time.time", "user: *")
+ t.expect_content_line("bin/$toolset/debug/my-time.time", "system: *")
+
+ t.cleanup()
+
+
+################################################################################
+#
+# boost_build_testing_support_timing_rule_with_spaces_in_names()
+# --------------------------------------------------------------
+#
+################################################################################
+
+def boost_build_testing_support_timing_rule_with_spaces_in_names():
+ """Tests the target build timing rule provided by the Boost Build testing
+ support system when used with targets contining spaces in their names.
+ """
+
+ t = BoostBuild.Tester()
+
+ t.write("aaa bbb.cpp", "int main() {}\n")
+
+ t.write("jamroot.jam", """
+import testing ;
+exe "my exe" : "aaa bbb.cpp" ;
+time "my time" : "my exe" ;
+""")
+
+ t.run_build_system()
+ t.expect_addition("bin/$toolset/debug/aaa bbb.obj")
+ t.expect_addition("bin/$toolset/debug/my exe.exe")
+ t.expect_addition("bin/$toolset/debug/my time.time")
+
+ t.expect_content_line("bin/$toolset/debug/my time.time", "user: *")
+ t.expect_content_line("bin/$toolset/debug/my time.time", "system: *")
+
+ t.cleanup()
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+basic_jam_action_test()
+boost_build_testing_support_timing_rule()
+boost_build_testing_support_timing_rule_with_spaces_in_names() \ No newline at end of file
diff --git a/tools/build/v2/test/tree.py b/tools/build/v2/test/tree.py
new file mode 100644
index 0000000000..89f8ad4ff1
--- /dev/null
+++ b/tools/build/v2/test/tree.py
@@ -0,0 +1,120 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2001, 2002 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This file is based in part on the content of svn_tree.py.
+
+import svn_tree;
+
+class Trees_difference:
+
+ def __init__(self):
+ self.added_files = []
+ self.removed_files = []
+ self.modified_files = []
+ self.touched_files = []
+
+ def append(self, other):
+ self.added_files.extend(other.added_files)
+ self.removed_files.extend(other.removed_files)
+ self.modified_files.extend(other.modified_files)
+ self.touched_files.extend(other.touched_files)
+
+ def ignore_directories(self):
+ "Removes directories for list of found differences"
+
+ def not_dir(x):
+ return x[-1] != "/"
+ self.added_files = filter(not_dir, self.added_files)
+ self.removed_files = filter(not_dir, self.removed_files)
+ self.modified_files = filter(not_dir, self.modified_files)
+ self.touched_files = filter(not_dir, self.touched_files)
+
+ def pprint(self, f=None):
+ print >> f, "Added files :", self.added_files
+ print >> f, "Removed files :", self.removed_files
+ print >> f, "Modified files:", self.modified_files
+ print >> f, "Touched files :", self.touched_files
+
+ def empty(self):
+ return ( len(self.added_files) == 0 ) and \
+ ( len(self.removed_files) == 0 ) and \
+ ( len(self.modified_files) == 0 ) and \
+ ( len(self.touched_files) == 0 )
+
+def build_tree(dir):
+ return svn_tree.build_tree_from_wc(dir, load_props=0, ignore_svn=1)
+
+def trees_difference(a, b, current_name=""):
+ """Compare SVNTreeNodes A and B, and create Trees_difference class."""
+
+ assert a.name == b.name
+
+ result = Trees_difference()
+ try:
+ # A and B are both files.
+ if ((a.children is None) and (b.children is None)):
+ assert a.name == b.name
+ if svn_tree.compare_file_nodes(a, b):
+ result.modified_files.append(current_name)
+ elif (a.mtime != b.mtime):
+ result.touched_files.append(current_name)
+
+ # One is a file, one is a directory.
+ # this case is disabled because svn_tree doesn't distinguish
+ # empty directories from files, at least on Cygwin.
+ elif 0 and (((a.children is None) and (b.children is not None))
+ or ((a.children is not None) and (b.children is None))):
+ a.pprint()
+ b.pprint()
+ raise svn_tree.SVNTypeMismatch
+ # They're both directories.
+ else:
+ # accounted_for holds childrens present in both trees
+ accounted_for = []
+ for a_child in (a.children or []):
+ b_child = svn_tree.get_child(b, a_child.name)
+ if b_child:
+ accounted_for.append(b_child)
+ if current_name:
+ result.append(trees_difference(a_child, b_child, current_name + "/" + a_child.name))
+ else:
+ result.append(trees_difference(a_child, b_child, a_child.name))
+ else:
+ if current_name:
+ result.removed_files.append(current_name + "/" + a_child.name)
+ else:
+ result.removed_files.append(a_child.name)
+ for b_child in (b.children or []):
+ if (b_child not in accounted_for):
+ result.added_files.extend(traverse_tree(b_child, current_name))
+
+ except svn_tree.SVNTypeMismatch:
+ print 'Unequal Types: one Node is a file, the other is a directory'
+ raise svn_tree.SVNTreeUnequal
+ except svn_tree.SVNTreeIsNotDirectory:
+ print "Error: Foolish call to get_child."
+ sys.exit(1)
+ except IndexError:
+ print "Error: unequal number of children"
+ raise svn_tree.SVNTreeUnequal
+ return result
+
+def dump_tree(t):
+ svn_tree.dump_tree(t)
+
+def traverse_tree(t, parent_name=""):
+ """ Returns the list of all names in tree. """
+ if parent_name:
+ full_node_name = parent_name + "/" + t.name
+ else:
+ full_node_name = t.name
+
+ if (t.children is None):
+ result = [full_node_name]
+ else:
+ result = [full_node_name + "/"]
+ for i in t.children:
+ result.extend(traverse_tree(i, full_node_name))
+ return result
diff --git a/tools/build/v2/test/unit-tests.jam b/tools/build/v2/test/unit-tests.jam
new file mode 100644
index 0000000000..212f4c3887
--- /dev/null
+++ b/tools/build/v2/test/unit-tests.jam
@@ -0,0 +1,262 @@
+# Copyright 2001 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# assert_equal a : b
+#
+# exits with an assertion failure if a != b
+rule assert_equal
+{
+ if $(<) != $(>)
+ {
+ EXIT "assertion failure: [" $(<) "] != [" $(>) "]" ;
+ }
+}
+
+rule assert_equal_sets
+{
+ if ! [ equal-sets $(<) : $(>) ]
+ {
+ EXIT "assertion failure: [" $(<) "] !=(set) [" $(>) "]" ;
+ }
+}
+
+# FAppendSuffix
+assert_equal [ FAppendSuffix yacc lex foo.bat : ] : yacc lex foo.bat ;
+assert_equal [ FAppendSuffix yacc lex foo.bat : .exe ] : yacc.exe lex.exe foo.bat ;
+assert_equal [ FAppendSuffix yacc lex foo.bat : .dll .lib ] : yacc.dll yacc.lib lex.dll lex.lib foo.bat foo.lib ;
+
+# sort
+assert_equal [ sort 7 3 5 6 2 4 ] : 2 3 4 5 6 7 ;
+
+# min
+assert_equal [ min 7 3 5 6 2 4 ] : 2 ;
+
+# difference
+assert_equal [ difference 0 1 2 3 4 5 6 7 8 9 : 2 3 5 7 ] : 0 1 4 6 8 9 ;
+
+# replace
+assert_equal [ replace 1 3 5 7 7 9 2 5 4 3 1 : 7 x ] : 1 3 5 x x 9 2 5 4 3 1 ;
+
+# select-ungristed
+assert_equal [ select-ungristed <a>b c <d>e f ] : c f ;
+
+# split-qualified-property
+assert_equal [ split-qualified-property <feature>value ]
+ : <*> <*> <feature>value ;
+
+assert_equal [ split-qualified-property <variant><feature>value ]
+ : <*> <variant> <feature>value ;
+
+assert_equal [ split-qualified-property <toolset><variant><feature>value ]
+ : <toolset> <variant> <feature>value ;
+
+# unique
+assert_equal [ unique 0 1 2 3 1 7 6 6 4 5 ] : 0 1 2 3 7 6 4 5 ;
+
+# get-properties
+assert_equal [ get-properties <foo> <bar> : <foo>bar <foo>baz <bar>fight <baz>niss ]
+ : <foo>bar <foo>baz <bar>fight ;
+
+# get-values
+assert_equal [ get-values <foo> : <foo>bar <foo>baz <bar>fight <baz>niss ] : bar baz ;
+
+# normalize-properties
+assert_equal [ normalize-properties <a>b <c><d>e <f><g><h>i ] :
+ <*><*><a>b <*><c><d>e <f><g><h>i ;
+
+# intersection
+assert_equal [ intersection 1 2 2 3 3 4 5 6 7 : 5 1 3 7 3 9 11 ] : 1 3 3 5 7 ;
+
+# is-subset
+assert_equal [ is-subset a b c : c a b d ] : true ;
+assert_equal [ is-subset a b z : c a b d ] : ;
+
+# split-path
+assert_equal [ split-path <a>b/c/<d>e ] : <a>b c <d>e ;
+assert_equal [ split-path <a>/<d>/<e> ] : <a> <d> <e> ;
+assert_equal [ split-path <a> ] : <a> ;
+assert_equal [ split-path x ] : x ;
+assert_equal [ split-path $(DOT) ] : $(DOT) ;
+assert_equal [ split-path a/b.c/d.e/f ] : a b.c d.e f ;
+if $(NT)
+{
+ assert_equal [ split-path x:\\y\\z\\w ] : x: y z w ;
+ assert_equal [ split-path x:\\y\\z ] : x: y z ;
+ assert_equal [ split-path x:\\y ] : x: y ;
+ assert_equal [ split-path x:\\ ] : x: ;
+ assert_equal [ split-path x: ] : x: ;
+}
+
+# distribute-feature
+assert_equal [ distribute-feature <feature>value1 ] : <feature>value1 ;
+assert_equal [ distribute-feature <feature>value1/value2 ] : <feature>value1 <feature>value2 ;
+assert_equal [ distribute-feature <feature>value1/value2/value3 ] : <feature>value1 <feature>value2 <feature>value3 ;
+
+# segregate-free-properties
+{
+ local gFREE_FEATURES = <a> <c> <e> ;
+ local x = <a>b <b>c <d>e ;
+ local y = <a>b <a>c <b>c <e>f ;
+ local free = [ segregate-free-properties x y ] ;
+ assert_equal $(free) : <a>b <a>c <e>f ;
+ assert_equal $(x) : <b>c <d>e ;
+ assert_equal $(y) : <b>c ;
+}
+
+# set-insert
+{
+ local gTEST_SET = 1 2 3 ;
+ set-insert gTEST_SET : 2 ;
+ assert_equal $(gTEST_SET) : 1 2 3 ;
+ set-insert gTEST_SET : 0 ;
+ assert_equal $(gTEST_SET) : 1 2 3 0 ;
+}
+
+# equal-sets
+assert_equal [ equal-sets 1 2 3 : 3 2 2 1 ] : true ;
+assert_equal [ equal-sets 1 2 3 3 : 3 2 2 1 ] : true ;
+assert_equal [ equal-sets 1 2 3 3 4 : 3 2 2 1 ] : ;
+
+# segregate-overrides
+{
+ local base = <a>b <c>d <e>f ;
+ local overrides = <a>b <c>c <d>e <f>g ;
+ segregate-overrides overrides : base ;
+ assert_equal $(overrides) : <c>c <d>e <f>g ;
+ assert_equal $(base) : <a>b <e>f ;
+}
+
+# select-properties
+{
+ local TOOLS = gcc msvc ;
+
+ local gRELEVANT_FEATURES(msvc) = <debug-symbols> <optimization> <inlining> <inline> <runtime-build> <runtime-link> <threading> <define> <undef> <include> <target-type> ;
+ local gRELEVANT_FEATURES(gcc) = <runtime-link> <debug-symbols> <optimization> <inlining> <profiling> <define> <undef> <include> <shared-linkable> <target-type> ;
+ local gFREE_FEATURES = <define> <undef> <include> ;
+
+ local gBASE_PROPERTIES(msvc,debug) = <debug-symbols>on <inlining>off <optimization>off <runtime-build>debug <threading>single ;
+ local gBASE_PROPERTIES(gcc,debug) = <debug-symbols>on <inlining>off <optimization>off <profiling>off <shared-linkable>false ;
+ local gBASE_PROPERTIES(msvc,release) = <debug-symbols>off <define>NDEBUG <inlining>full <optimization>speed <runtime-build>release <threading>single ;
+ local gBASE_PROPERTIES(gcc,release) = <debug-symbols>off <define>NDEBUG <inlining>full <optimization>speed <profiling>off <shared-linkable>false ;
+
+ local TEST_PROPERTIES = <inlining>off <define>FOO <*><release><inlining>on
+ <debug><define>DEBUG <msvc><release><foo>bar
+ <gcc><*><inlining>on
+ <msvc><*><foo>baz
+ <msvc><release><optimization>speed
+ <msvc><*><optimization>off
+ <*><debug><optimization>off
+ ;
+
+ assert_equal_sets [ select-properties gcc debug my-target : $(TEST_PROPERTIES) ]
+ : <define>FOO <define>DEBUG <inlining>on <optimization>off ;
+
+ assert_equal_sets [ select-properties gcc release my-target : $(TEST_PROPERTIES) ]
+ : <define>FOO <inlining>on ;
+
+ assert_equal_sets [ select-properties msvc debug my-target : $(TEST_PROPERTIES) ]
+ : <define>FOO <define>DEBUG <inlining>off <optimization>off ;
+
+ assert_equal_sets [ select-properties msvc release my-target : $(TEST_PROPERTIES) ]
+ : <define>FOO <inlining>on <optimization>speed ;
+}
+
+
+# ungrist-properties
+feature TEST_FEATURE1 : a b ;
+feature TEST_FEATURE2 : c d ;
+assert_equal [ ungrist-properties <TEST_FEATURE1>a <TEST_FEATURE2>c ]
+ : TEST_FEATURE1-a TEST_FEATURE2-c ;
+
+
+# fixup-path-properties
+{
+ local RELATIVE_SUBDIR = foobar ;
+ local gPATH_FEATURES = <include> ;
+ assert_equal [ fixup-path-properties <a>b <include>.. <c>d ]
+ : <include>foobar$(SLASH).. <a>b <c>d ;
+}
+# multiply-property-sets
+assert_equal [ multiply-property-sets <b>1 <a>2/3 <c>4/5 ]
+ : <a>2/<b>1/<c>4 <a>2/<b>1/<c>5 <a>3/<b>1/<c>4 <a>3/<b>1/<c>5 ;
+
+# make-path-property-sets
+{
+ local gUNGRISTED(<a>) = a ;
+ local gUNGRISTED(<c>) = c ;
+ local gUNGRISTED(<e>) = e ;
+ local gUNGRISTED(<g>) = g ;
+ local gUNGRISTED(<i>) = i ;
+ assert_equal [ make-path-property-sets foo$(SLASH)bar : <a>b <c>d : <e>f$(SLASH)<g>h <i>j ]
+ : foo$(SLASH)bar$(SLASH)e-f$(SLASH)g-h$(SLASH)<a>b$(SLASH)<c>d$(SLASH)<e>f$(SLASH)<g>h foo$(SLASH)bar$(SLASH)i-j$(SLASH)<a>b$(SLASH)<c>d$(SLASH)<i>j ;
+ assert_equal [ make-path-property-sets foo$(SLASH)bar : <a>b <c>d : ]
+ : foo$(SLASH)bar$(SLASH)<a>b$(SLASH)<c>d ;
+}
+
+
+# split-path-at-grist
+assert_equal
+ [ split-path-at-grist <a>b$(SLASH)c$(SLASH)<d>e$(SLASH)<f>g$(SLASH)h$(SLASH)i ]
+ : <a>b$(SLASH)c <d>e <f>g$(SLASH)h$(SLASH)i ;
+assert_equal
+ [ split-path-at-grist b$(SLASH)c$(SLASH)<d>e$(SLASH)<f>g$(SLASH)h$(SLASH)i ]
+ : b$(SLASH)c <d>e <f>g$(SLASH)h$(SLASH)i ;
+if $(NT)
+{
+ assert_equal
+ [ split-path-at-grist b\\c\\<include>e:\\f\\g\\<h>i ]
+ : b\\c <include>e:\\f\\g <h>i ;
+}
+# directory-of
+assert_equal [ directory-of a$(SLASH)b c d$(SLASH)e$(SLASH)f ] : a . d$(SLASH)e ;
+
+# top-relative-tokens
+{
+ local SUBDIR_TOKENS = a b c ;
+ assert_equal [ top-relative-tokens ..$(SLASH)d$(SLASH)e ] : a b d e ;
+}
+
+# flags
+{
+ local gBUILD_PROPERTIES = <a>b <c>d <e>f ;
+ local FLAGS1 FLAGS2 FLAGS3 ;
+ flags toolset FLAGS1 <a>b/<c>d <a>b/<e>f <x>y <a>/<c> <e> : foobar ;
+ assert_equal $(FLAGS1) : foobar b d f ;
+ flags toolset FLAGS2 <a> : foobar ;
+ assert_equal $(FLAGS2) : b ;
+ flags toolset FLAGS1 <a>b/<c>d <a>b/<e>f : foobar ;
+ assert_equal $(FLAGS1) : foobar b d f foobar ;
+}
+
+# get-BUILD
+{
+ local DEFAULT_BUILD = a ;
+ local BUILD = b ;
+ assert_equal [ get-BUILD c <d>e ] : b ;
+ BUILD = ;
+ assert_equal [ get-BUILD c <d>e ] : c <d>e ;
+ assert_equal [ get-BUILD ] : a ;
+ assert_equal [ get-BUILD <d>e ] : <d>e a ;
+ BUILD = <f>g ;
+ assert_equal [ get-BUILD c <d>e ] : <f>g a ;
+}
+
+# strip-initial
+assert_equal [ strip-initial a b c : a b c d e f g ] : d e f g ;
+assert_equal [ strip-initial a b c : a b d e f g ] : a b d e f g ;
+assert_equal [ strip-initial a b c : b d e f g ] : b d e f g ;
+assert_equal [ strip-initial a b c : ] : ;
+
+# simplify-path-tokens
+{
+ local $(gTOP)_TOKENS = .. .. .. ;
+ local gINVOCATION_SUBDIR_TOKENS = d e ;
+ assert_equal [ simplify-path-tokens a b . c .. .. d e ] : a d e ;
+ assert_equal [ simplify-path-tokens a b .. .. .. d e ] : .. d e ;
+ assert_equal [ simplify-path-tokens .. .. d e : xxx ] : .. .. d e ;
+ assert_equal [ simplify-path-tokens a b .. .. : xxx ] : xxx ;
+ $(gTOP)_TOKENS = .. .. ;
+ assert_equal [ simplify-path-tokens .. .. d e : xxx ] : xxx ;
+ assert_equal [ simplify-path-tokens .. .. d e f g : xxx ] : f g ;
+}
diff --git a/tools/build/v2/test/unit_test.py b/tools/build/v2/test/unit_test.py
new file mode 100644
index 0000000000..94575ad319
--- /dev/null
+++ b/tools/build/v2/test/unit_test.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+# Copyright 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test the unit_test rule.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+# Create the needed files.
+t.write("jamroot.jam", """
+using testing ;
+lib helper : helper.cpp ;
+unit-test test : test.cpp : <library>helper ;
+""")
+
+t.write("test.cpp", """
+void helper();
+int main() { helper(); }
+""")
+
+t.write("helper.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+helper() {}
+""")
+
+t.run_build_system("link=static")
+t.expect_addition("bin/$toolset/debug/link-static/test.passed")
+
+t.cleanup()
diff --git a/tools/build/v2/test/unit_tests.py b/tools/build/v2/test/unit_tests.py
new file mode 100644
index 0000000000..f306a90570
--- /dev/null
+++ b/tools/build/v2/test/unit_tests.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.run_build_system(extra_args="--debug --build-system=test/test")
+
+t.cleanup()
diff --git a/tools/build/v2/test/unused.py b/tools/build/v2/test/unused.py
new file mode 100644
index 0000000000..9db2380cd1
--- /dev/null
+++ b/tools/build/v2/test/unused.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that unused sources are at least reported.
+
+import BoostBuild
+from string import find
+
+t = BoostBuild.Tester()
+
+t.set_tree("unused")
+
+t.run_build_system()
+# The second invocation should do nothing, and produce no warning. The previous
+# invocation might have printed executed actions and other things, so it is not
+# easy to check if warning was issued or not.
+t.run_build_system()
+t.fail_test(find(t.stdout(), "warning: Unused source { b.X } in main target ./a") == -1)
+
+t.run_build_system("-sGENERATE_ONLY_UNUSABLE=1")
+t.fail_test(find(t.stdout(), "warning: Unused source { b.X } in main target ./a") == -1)
+
+# Now check that even if main target generates nothing, its usage requirements
+# are still propagated to dependants.
+t.write("a.cpp", """
+#ifdef FOO
+int main() {}
+#endif
+""")
+t.run_build_system("-sGENERATE_NOTHING=1")
+
+t.cleanup()
diff --git a/tools/build/v2/test/unused/a.cpp b/tools/build/v2/test/unused/a.cpp
new file mode 100644
index 0000000000..c4a7ae8926
--- /dev/null
+++ b/tools/build/v2/test/unused/a.cpp
@@ -0,0 +1,9 @@
+// Copyright Vladimir Prus 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+int main()
+{
+ return 0;
+}
diff --git a/tools/build/v2/test/unused/b.cpp b/tools/build/v2/test/unused/b.cpp
new file mode 100644
index 0000000000..5551e35f65
--- /dev/null
+++ b/tools/build/v2/test/unused/b.cpp
@@ -0,0 +1,4 @@
+/* Copyright 2003 Vladimir Prus */
+/* Distributed under the Boost Software License, Version 1.0. */
+/* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) */
+
diff --git a/tools/build/v2/test/unused/b.x b/tools/build/v2/test/unused/b.x
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/test/unused/b.x
diff --git a/tools/build/v2/test/unused/jamfile.jam b/tools/build/v2/test/unused/jamfile.jam
new file mode 100644
index 0000000000..58ef45605a
--- /dev/null
+++ b/tools/build/v2/test/unused/jamfile.jam
@@ -0,0 +1,11 @@
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+exe a : a.cpp b c ;
+
+make-b-main-target ;
+
+# Expands to nothing, intentionally.
+alias c ;
diff --git a/tools/build/v2/test/unused/jamroot.jam b/tools/build/v2/test/unused/jamroot.jam
new file mode 100644
index 0000000000..75832afd20
--- /dev/null
+++ b/tools/build/v2/test/unused/jamroot.jam
@@ -0,0 +1,57 @@
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+
+import type ;
+import generators ;
+import print ;
+import virtual-target ;
+import "class" : new ;
+import modules ;
+import targets ;
+
+
+type.register X : x ;
+
+class test-target-class : basic-target
+{
+ rule __init__ ( name : project )
+ {
+ basic-target.__init__ $(name) : $(project) ;
+ }
+
+ rule construct ( source-targets * : property-set )
+ {
+ if [ modules.peek : GENERATE_NOTHING ]
+ {
+ return ;
+ }
+ else if [ modules.peek : GENERATE_ONLY_UNUSABLE ]
+ {
+ return [ virtual-target.from-file b.x : $(self.project) ]
+ ;
+ }
+ else
+ {
+ return [ virtual-target.from-file b.x : $(self.project) ]
+ [ virtual-target.from-file b.cpp : $(self.project) ]
+ ;
+ }
+ }
+
+ rule compute-usage-requirements ( rproperties : targets * )
+ {
+ return [ property-set.create <define>FOO ] ;
+ }
+}
+
+rule make-b-main-target
+{
+ local project = [ CALLER_MODULE ] ;
+
+ targets.main-target-alternative
+ [ new test-target-class b : $(project) ] ;
+}
+
+IMPORT $(__name__) : make-b-main-target : : make-b-main-target ;
diff --git a/tools/build/v2/test/use_requirements.py b/tools/build/v2/test/use_requirements.py
new file mode 100644
index 0000000000..a73c01f1f5
--- /dev/null
+++ b/tools/build/v2/test/use_requirements.py
@@ -0,0 +1,295 @@
+#!/usr/bin/python
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2004, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+
+# Test that use requirements on main target work (and a propagated all the way
+# up, not only to direct dependants).
+t.write("jamroot.jam", "import gcc ;")
+
+# Note: 'lib cc ..', not 'lib c'. If using 'lib c: ...' the HP-CXX linker will
+# confuse it with the system C runtime.
+t.write("jamfile.jam", """
+lib b : b.cpp : <link>shared:<define>SHARED_B : :
+ <define>FOO <link>shared:<define>SHARED_B ;
+lib cc : c.cpp b ;
+exe a : a.cpp cc ;
+""")
+
+t.write("b.cpp", """
+void
+#if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+#endif
+foo() {}\n
+""")
+
+t.write("c.cpp", """
+void
+#if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+#endif
+create_lib_please() {}\n
+""")
+
+t.write("a.cpp", """
+#ifdef FOO
+void
+# if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+# endif
+foo() {}
+#endif
+int main() { foo(); }
+""")
+
+t.run_build_system()
+t.run_build_system("--clean")
+
+
+# Test that use requirements on main target work, when they are referred using
+# 'dependency' features.
+t.write("jamroot.jam", "import gcc ;")
+
+t.write("jamfile.jam", """
+lib b : b.cpp : <link>shared:<define>SHARED_B : : <define>FOO
+ <link>shared:<define>SHARED_B ;
+exe a : a.cpp : <use>b ;
+""")
+
+t.write("b.cpp", """
+void
+#if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+#endif
+foo() {}
+""")
+
+t.write("a.cpp", """
+#ifdef FOO
+int main() {}
+#endif
+""")
+
+t.run_build_system()
+
+t.run_build_system("--clean")
+
+
+# Test that usage requirements on a project work.
+t.write("jamfile.jam", "exe a : a.cpp lib//b ;")
+
+t.write("lib/jamfile.jam", """
+project
+ : requirements <link>shared:<define>SHARED_B
+ : usage-requirements <define>FOO <link>shared:<define>SHARED_B ;
+lib b : b.cpp ;
+""")
+
+t.write("lib/b.cpp", """
+void
+#if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+#endif
+foo() {}\n
+""")
+
+t.run_build_system()
+
+
+# Test that use requirements are inherited correctly.
+t.write("jamfile.jam", "exe a : a.cpp lib/1//b ;")
+
+t.write("a.cpp", """
+#if defined(FOO) && defined(ZOO)
+void foo() {}
+#endif
+int main() { foo(); }
+""")
+
+t.write("lib/jamfile.jam", """
+project : requirements : usage-requirements <define>FOO ;
+""")
+
+t.write("lib/1/jamfile.jam", """
+project
+ : requirements <link>shared:<define>SHARED_B
+ : usage-requirements <define>ZOO <link>shared:<define>SHARED_B ;
+lib b : b.cpp ;
+""")
+
+t.write("lib/1/b.cpp", """
+void
+#if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+#endif
+foo() {}\n
+""")
+
+t.run_build_system()
+t.run_build_system("--clean")
+
+
+# Test that we correctly handle dependency features in use requirements on
+# target.
+t.write("jamfile.jam", """
+lib b : b.cpp : <link>shared:<define>SHARED_B : : <define>FOO
+ <link>shared:<define>SHARED_B ;
+
+# Here's the test: we should correctly handle dependency feature and get usage
+# requirements from 'b'.
+lib cc : c.cpp : <link>shared:<define>SHARED_C : : <library>b ;
+
+# This will build only if <define>FOO was propagated from 'c'.
+exe a : a.cpp cc ;
+""")
+
+t.write("a.cpp", """
+#ifdef FOO
+void
+# if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+# endif
+foo();
+#endif
+
+int main() { foo(); }
+""")
+
+t.write("c.cpp", """
+int
+#if defined(_WIN32) && defined(SHARED_C)
+__declspec(dllexport)
+#endif
+must_export_something;
+""")
+
+t.run_build_system()
+t.run_build_system("--clean")
+
+
+# Test correct handling of dependency features in project requirements.
+t.write("jamfile.jam", """
+exe a : a.cpp lib1//cc ;
+""")
+
+t.write("lib1/jamfile.jam", """
+project
+ : requirements <link>shared:<define>SHARED_C
+ : usage-requirements <library>../lib2//b <link>shared:<define>SHARED_C ;
+lib cc : c.cpp ;
+""")
+
+t.write("lib1/c.cpp", """
+int
+#if defined(_WIN32) && defined(SHARED_C)
+__declspec(dllexport)
+#endif
+must_export_something;
+""")
+
+t.write("lib2/jamfile.jam", """
+lib b : b.cpp : <link>shared:<define>SHARED_B : : <define>FOO
+ <link>shared:<define>SHARED_B ;
+""")
+
+t.copy("b.cpp", "lib2/b.cpp")
+
+t.run_build_system()
+
+
+# Test that dependency feature in use requirements are built with the correct
+# properties.
+t.rm(".")
+
+t.write("jamfile.jam", """
+lib main : main.cpp : <use>libs//lib1 : : <library>libs//lib1 ;
+exe hello : hello.cpp main : ;
+""")
+
+t.write("main.cpp", """
+void
+#if defined(_WIN32) && defined(SHARED_LIB1)
+__declspec(dllimport)
+#endif
+foo();
+
+int main() { foo(); }
+""")
+
+t.write("hello.cpp", "\n")
+
+t.write("jamroot.jam", """
+import gcc ;
+""")
+
+t.write("libs/a.cpp", """
+void
+#if defined(_WIN32) && defined(SHARED_LIB1)
+__declspec(dllexport)
+#endif
+foo() {}
+""")
+
+
+# This library should be build with the same properties as 'main'. This is a
+# regression test for a bug when they were generated with empty properties, and
+# there were ambiguity between variants.
+t.write("libs/jamfile.jam", """
+lib lib1 : a_d.cpp : <variant>debug <link>shared:<define>SHARED_LIB1 : :
+ <link>shared:<define>SHARED_LIB1 ;
+lib lib1 : a.cpp : <variant>release <link>shared:<define>SHARED_LIB1 : :
+ <link>shared:<define>SHARED_LIB1 ;
+""")
+
+t.write("libs/a_d.cpp", """
+void
+#if defined(_WIN32) && defined(SHARED_LIB1)
+__declspec(dllexport)
+#endif
+foo() {}
+""")
+
+t.run_build_system("link=static")
+t.expect_addition("libs/bin/$toolset/debug/link-static/a_d.obj")
+
+
+# Test that indirect conditionals are respected in usage requirements.
+t.rm(".")
+
+t.write("jamroot.jam", """
+rule has-foo ( properties * )
+{
+ return <define>HAS_FOO ;
+}
+
+exe a : a.cpp b ;
+lib b : b.cpp : <link>static : : <conditional>@has-foo ;
+""")
+
+t.write("a.cpp", """
+#ifdef HAS_FOO
+void foo();
+int main() { foo(); }
+#endif
+""")
+
+t.write("b.cpp", """
+void
+#if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+#endif
+foo() {}\n
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/using.py b/tools/build/v2/test/using.py
new file mode 100644
index 0000000000..452e7363b2
--- /dev/null
+++ b/tools/build/v2/test/using.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2005.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("sub/a.cpp", """
+int main() {}
+""")
+
+t.write("jamroot.jam", """
+using some_tool ;
+""")
+
+t.write("some_tool.jam", """
+import project ;
+project.initialize $(__name__) ;
+rule init ( ) { }
+""")
+
+t.write("some_tool.py", """
+from b2.manager import get_manager
+
+get_manager().projects().initialize(__name__)
+
+def init():
+ pass
+""")
+
+t.write("sub/jamfile.jam", """
+exe a : a.cpp ;
+""")
+
+t.run_build_system(subdir="sub")
+t.expect_addition("sub/bin/$toolset/debug/a.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/test/v1-testing/a.cpp b/tools/build/v2/test/v1-testing/a.cpp
new file mode 100644
index 0000000000..8da76c54ec
--- /dev/null
+++ b/tools/build/v2/test/v1-testing/a.cpp
@@ -0,0 +1,5 @@
+// Copyright David Abrahams 2003-2004. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+void foo() {}
diff --git a/tools/build/v2/test/v1-testing/b.cpp b/tools/build/v2/test/v1-testing/b.cpp
new file mode 100644
index 0000000000..26e752aa5e
--- /dev/null
+++ b/tools/build/v2/test/v1-testing/b.cpp
@@ -0,0 +1,5 @@
+// Copyright David Abrahams 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#error this does not compile.
diff --git a/tools/build/v2/test/v1-testing/boost-build.jam b/tools/build/v2/test/v1-testing/boost-build.jam
new file mode 100644
index 0000000000..d9e748ec26
--- /dev/null
+++ b/tools/build/v2/test/v1-testing/boost-build.jam
@@ -0,0 +1,6 @@
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+TOOLS = gcc ;
+boost-build ../.. ;
diff --git a/tools/build/v2/test/v1-testing/c.cpp b/tools/build/v2/test/v1-testing/c.cpp
new file mode 100644
index 0000000000..42f5d9c58c
--- /dev/null
+++ b/tools/build/v2/test/v1-testing/c.cpp
@@ -0,0 +1,16 @@
+// Copyright David Abrahams 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#include <iostream>
+
+#ifndef RESULTCODE
+# define RESULTCODE 0
+#endif
+
+int main()
+{
+ std::cout << "returning result: " << RESULTCODE << std::endl;
+ return RESULTCODE;
+}
+
diff --git a/tools/build/v2/test/v1-testing/jamfile.jam b/tools/build/v2/test/v1-testing/jamfile.jam
new file mode 100644
index 0000000000..011940f8ae
--- /dev/null
+++ b/tools/build/v2/test/v1-testing/jamfile.jam
@@ -0,0 +1,26 @@
+# Copyright 2002, 2003 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import testing ;
+
+# A number of tests which should succeed
+compile a.cpp ;
+compile-fail b.cpp ;
+link-fail a.cpp : : link-no ;
+link c.cpp : : link-yes ;
+run c.cpp : : : : run-yes ;
+run-fail c.cpp : : : <define>RESULTCODE=1 : run-no ;
+
+# some tests which should fail
+
+compile-fail a.cpp : : fail-compile-no ;
+compile b.cpp : : fail-compile-yes ;
+link a.cpp : : fail-link-yes ;
+link-fail c.cpp : : fail-link-no ;
+run-fail c.cpp : : : : fail-run-no ;
+run c.cpp : : : <define>RESULTCODE=1 : fail-run-yes ;
+
+# Make sure we still fail if a dependency of an expected-failure test
+# fails.
+link-fail b.cpp : : fail-link-no-dependency ;
diff --git a/tools/build/v2/test/v1_testing.py b/tools/build/v2/test/v1_testing.py
new file mode 100644
index 0000000000..524775fac4
--- /dev/null
+++ b/tools/build/v2/test/v1_testing.py
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+
+# Copyright 2002 Dave Abrahams
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import BoostBuild
+import os
+from string import strip
+import re
+import time
+
+def match_re(actual,expected):
+ return re.match(expected,actual,re.DOTALL) != None
+
+t = BoostBuild.Tester(match = match_re, boost_build_path = os.path.join(os.getcwd(), ".."))
+t.set_tree('v1_testing')
+
+os.environ['TOOLS'] = 'gcc'
+os.environ['NOARSCAN'] = '1'
+
+# 1) No existing bin directories. Both build and test ran fine. As
+# expected, the residue files were a bit different: There was no
+# path_test.success, and path_test.test contained the word "passed"
+# instead of the path to the .cpp file. I've haven't looked yet to
+# see if the lack of the path is a problem for reporting, but
+# hopefully the information is trivially available somewhere else.
+t.run_build_system(arguments = 'test', status = 0)
+t.expect_addition(
+ ['bin/compile.test/gcc/debug/runtime-link-dynamic/compile.test'
+ , 'bin/nocompile.test/gcc/debug/runtime-link-dynamic/nocompile.test'
+ , 'bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
+ , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
+ , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
+
+
+# 2) Missing source file for the library build. path_test.test was
+# deleted, so the reporting programs would know that failure
+# occurred. The stdout messages also indicated what had
+# happened. Excellent!
+t.rename('lib.cpp', 'lib.cpp.bak')
+t.run_build_system(arguments = 'test', status = 1)
+t.expect_removal(
+ ['bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
+ , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
+ , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
+
+# 3) Missing file restored. Worked fine; path_test.test was recreated,
+# no other files were touched.
+t.rename('lib.cpp.bak', 'lib.cpp')
+t.run_build_system(arguments = 'test', status = 0)
+t.expect_addition(
+ [ 'bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
+ , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
+ , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
+ # I didn't add a test for 'no other files were touched', because
+ # it's a little complicated. There is an expect_nothing_more()
+ # function, but we actually need to spell out a lot more than
+ # what we currently have to do that.
+
+# 4) Introduced error into one of the library files, causing a library build
+# compile to fail. path_test.test was deleted, so the reporting programs
+# would know that failure occurred. Excellent! This is the case that has
+# caused regression testing to report the wrong results in the past, so it
+# was good news to see it working correctly now. We probably should figure
+# out some other test cases just to be sure it is working for full coverage.
+t.rename('lib.cpp', 'lib.cpp.bak')
+t.rename('lib-err.cpp', 'lib.cpp')
+t.touch('lib.cpp')
+t.run_build_system(arguments = 'test', status=1)
+t.expect_removal(
+ ['bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
+ , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
+ , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
+
+# 5) Fixed the error in the library file. The library build then worked, and
+# path_test.exe was relinked, without first recompiling path_test.obj. Test was
+# rerun. Exactly the right behavior!
+t.rename('lib.cpp.bak', 'lib.cpp')
+t.run_build_system(arguments = 'test', status = 0)
+t.expect_addition(
+ [ 'bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
+ , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
+ , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
+
+t.cleanup()
+print 'testing complete'
diff --git a/tools/build/v2/test/v1_testing/Jamrules b/tools/build/v2/test/v1_testing/Jamrules
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/test/v1_testing/Jamrules
diff --git a/tools/build/v2/test/v1_testing/boost-build.jam b/tools/build/v2/test/v1_testing/boost-build.jam
new file mode 100644
index 0000000000..d9e748ec26
--- /dev/null
+++ b/tools/build/v2/test/v1_testing/boost-build.jam
@@ -0,0 +1,6 @@
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+TOOLS = gcc ;
+boost-build ../.. ;
diff --git a/tools/build/v2/test/v1_testing/foo.cpp b/tools/build/v2/test/v1_testing/foo.cpp
new file mode 100644
index 0000000000..6741a59439
--- /dev/null
+++ b/tools/build/v2/test/v1_testing/foo.cpp
@@ -0,0 +1,22 @@
+// Copyright David Abrahams 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#if NOCOMPILE
+1 = 1;
+#endif
+
+void lib();
+
+void f()
+{
+ lib();
+}
+
+#ifndef NOLINK
+int main()
+{
+}
+#endif
+
diff --git a/tools/build/v2/test/v1_testing/jamfile.jam b/tools/build/v2/test/v1_testing/jamfile.jam
new file mode 100644
index 0000000000..2e0bedac7c
--- /dev/null
+++ b/tools/build/v2/test/v1_testing/jamfile.jam
@@ -0,0 +1,23 @@
+# Copyright 2002, 2003 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+TOOLS = $(TOOLS[1]) ;
+project-root ;
+
+# bring in rules for testing
+import testing ;
+
+lib mylib : lib.cpp ;
+
+compile foo.cpp : : compile ;
+compile-fail foo.cpp : <define>NOCOMPILE : nocompile ;
+
+link foo.cpp <lib>mylib : : link ;
+link-fail foo.cpp <lib>mylib : <define>NOLINK : nolink ;
+
+run foo.cpp <lib>mylib
+ : # args
+ : # input-files
+ : <define>RUN
+ : run ;
diff --git a/tools/build/v2/test/v1_testing/jamroot.jam b/tools/build/v2/test/v1_testing/jamroot.jam
new file mode 100644
index 0000000000..fe69424588
--- /dev/null
+++ b/tools/build/v2/test/v1_testing/jamroot.jam
@@ -0,0 +1,5 @@
+# Copyright 2002 Dave Abrahams
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# just label the project root
diff --git a/tools/build/v2/test/v1_testing/lib-err.cpp b/tools/build/v2/test/v1_testing/lib-err.cpp
new file mode 100644
index 0000000000..060fd73e56
--- /dev/null
+++ b/tools/build/v2/test/v1_testing/lib-err.cpp
@@ -0,0 +1,7 @@
+// Copyright David Abrahams 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+3 = 4;
+void lib() {}
diff --git a/tools/build/v2/test/v1_testing/lib.cpp b/tools/build/v2/test/v1_testing/lib.cpp
new file mode 100644
index 0000000000..1472b96ad5
--- /dev/null
+++ b/tools/build/v2/test/v1_testing/lib.cpp
@@ -0,0 +1,6 @@
+// Copyright David Abrahams 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+void lib() {}
diff --git a/tools/build/v2/test/wrapper.py b/tools/build/v2/test/wrapper.py
new file mode 100644
index 0000000000..676892fa95
--- /dev/null
+++ b/tools/build/v2/test/wrapper.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+
+# Copyright 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Test that the user can define his own rule that will call built-in main target
+# rule and that this will work.
+
+import BoostBuild
+
+
+t = BoostBuild.Tester()
+
+t.write("jamfile.jam", """
+my-test : test.cpp ;
+""")
+
+t.write("test.cpp", """
+int main() {}
+""")
+
+t.write("jamroot.jam", """
+using testing ;
+
+rule my-test ( name ? : sources + )
+{
+ name ?= test ;
+ unit-test $(name) : $(sources) ; # /site-config//cppunit /util//testMain ;
+}
+
+IMPORT $(__name__) : my-test : : my-test ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/test.passed")
+
+t.cleanup()
diff --git a/tools/build/v2/test/wrong_project.py b/tools/build/v2/test/wrong_project.py
new file mode 100644
index 0000000000..88315d64e9
--- /dev/null
+++ b/tools/build/v2/test/wrong_project.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+
+# Copyright Vladimir Prus 2005.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# Regression test. When Jamfile contained "using whatever ; " and the 'whatever'
+# module declared a project, then all targets in Jamfile were considered to be
+# declared in the project associated with 'whatever', not with the Jamfile.
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("a.cpp", "int main() {}\n")
+
+t.write("jamroot.jam", """
+using some_tool ;
+exe a : a.cpp ;
+""")
+
+t.write("some_tool.jam", """
+import project ;
+project.initialize $(__name__) ;
+rule init ( ) { }
+""")
+
+t.write("some_tool.py", """
+from b2.manager import get_manager
+
+get_manager().projects().initialize(__name__)
+
+def init():
+ pass
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+
+t.cleanup()
diff --git a/tools/build/v2/to_merge.sh b/tools/build/v2/to_merge.sh
new file mode 100755
index 0000000000..c514f2101e
--- /dev/null
+++ b/tools/build/v2/to_merge.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+for python in build/*.py; do
+ jam="${python%.py}.jam"
+ if [ -f "$jam" ]; then
+ line=`grep "Base revision" $python`
+ revision=`echo $line | sed 's/# Base revision: \([0-9]*\).*/\1/'`
+ if [ -e "$revision" ] ; then
+ echo "No base version for $python" >&2
+ else
+ svn diff -r $revision:HEAD "$jam"
+ fi
+ fi
+done
+
+
diff --git a/tools/build/v2/tools/__init__.py b/tools/build/v2/tools/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/tools/__init__.py
diff --git a/tools/build/v2/tools/acc.jam b/tools/build/v2/tools/acc.jam
new file mode 100644
index 0000000000..f04c9dc879
--- /dev/null
+++ b/tools/build/v2/tools/acc.jam
@@ -0,0 +1,118 @@
+# Copyright Vladimir Prus 2004.
+# Copyright Toon Knapen 2004.
+# Copyright Boris Gubenko 2007.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#
+# Boost.Build V2 toolset for the HP aC++ compiler.
+#
+
+import toolset : flags ;
+import feature ;
+import generators ;
+import common ;
+
+feature.extend toolset : acc ;
+toolset.inherit acc : unix ;
+generators.override builtin.lib-generator : acc.prebuilt ;
+generators.override acc.searched-lib-generator : searched-lib-generator ;
+
+# Configures the acc toolset.
+rule init ( version ? : user-provided-command * : options * )
+{
+ local condition = [ common.check-init-parameters acc
+ : version $(version) ] ;
+
+ local command = [ common.get-invocation-command acc : aCC
+ : $(user-provided-command) ] ;
+
+ common.handle-options acc : $(condition) : $(command) : $(options) ;
+}
+
+
+# Declare generators
+generators.register-c-compiler acc.compile.c : C : OBJ : <toolset>acc ;
+generators.register-c-compiler acc.compile.c++ : CPP : OBJ : <toolset>acc ;
+
+# Declare flags.
+flags acc CFLAGS <optimization>off : ;
+flags acc CFLAGS <optimization>speed : -O3 ;
+flags acc CFLAGS <optimization>space : -O2 ;
+
+flags acc CFLAGS <inlining>off : +d ;
+flags acc CFLAGS <inlining>on : ;
+flags acc CFLAGS <inlining>full : ;
+
+flags acc C++FLAGS <exception-handling>off : ;
+flags acc C++FLAGS <exception-handling>on : ;
+
+flags acc C++FLAGS <rtti>off : ;
+flags acc C++FLAGS <rtti>on : ;
+
+# We want the full path to the sources in the debug symbols because otherwise
+# the debugger won't find the sources when we use boost.build.
+flags acc CFLAGS <debug-symbols>on : -g ;
+flags acc LINKFLAGS <debug-symbols>on : -g ;
+flags acc LINKFLAGS <debug-symbols>off : -s ;
+
+# V2 does not have <shared-linkable>, not sure what this meant in V1.
+# flags acc CFLAGS <shared-linkable>true : +Z ;
+
+flags acc CFLAGS <profiling>on : -pg ;
+flags acc LINKFLAGS <profiling>on : -pg ;
+
+flags acc CFLAGS <address-model>64 : +DD64 ;
+flags acc LINKFLAGS <address-model>64 : +DD64 ;
+
+# It is unknown if there's separate option for rpath used only
+# at link time, similar to -rpath-link in GNU. We'll use -L.
+flags acc RPATH_LINK : <xdll-path> ;
+
+flags acc CFLAGS <cflags> ;
+flags acc C++FLAGS <cxxflags> ;
+flags acc DEFINES <define> ;
+flags acc UNDEFS <undef> ;
+flags acc HDRS <include> ;
+flags acc STDHDRS <sysinclude> ;
+flags acc LINKFLAGS <linkflags> ;
+flags acc ARFLAGS <arflags> ;
+
+flags acc LIBPATH <library-path> ;
+flags acc NEEDLIBS <library-file> ;
+flags acc FINDLIBS <find-shared-library> ;
+flags acc FINDLIBS <find-static-library> ;
+
+# Select the compiler name according to the threading model.
+flags acc CFLAGS <threading>multi : -mt ;
+flags acc LINKFLAGS <threading>multi : -mt ;
+
+flags acc.compile.c++ TEMPLATE_DEPTH <c++-template-depth> ;
+
+
+actions acc.link bind NEEDLIBS
+{
+ $(CONFIG_COMMAND) -AA $(LINKFLAGS) -o "$(<[1])" -L"$(RPATH_LINK)" -L$(LIBPATH) -L$(STDLIBPATH) "$(>)" "$(NEEDLIBS)" "$(NEEDLIBS)" -l$(FINDLIBS) $(OPTIONS)
+}
+
+SPACE = " " ;
+actions acc.link.dll bind NEEDLIBS
+{
+ $(CONFIG_COMMAND) -AA -b $(LINKFLAGS) -o "$(<[1])" -L"$(RPATH_LINK)" -Wl,+h$(<[-1]:D=) -L$(LIBPATH) -L$(STDLIBPATH) "$(>)" "$(NEEDLIBS)" "$(NEEDLIBS)" -l$(FINDLIBS) $(OPTIONS)
+}
+
+actions acc.compile.c
+{
+ cc -c -I$(BOOST_ROOT) -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o "$(<)" "$(>)" $(OPTIONS)
+}
+
+actions acc.compile.c++
+{
+ $(CONFIG_COMMAND) -AA -c -Wc,--pending_instantiations=$(TEMPLATE_DEPTH) -I$(BOOST_ROOT) -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o "$(<)" "$(>)" $(OPTIONS)
+}
+
+actions updated together piecemeal acc.archive
+{
+ ar ru$(ARFLAGS:E="") "$(<)" "$(>)"
+}
diff --git a/tools/build/v2/tools/auto-index.jam b/tools/build/v2/tools/auto-index.jam
new file mode 100644
index 0000000000..ebbf344eba
--- /dev/null
+++ b/tools/build/v2/tools/auto-index.jam
@@ -0,0 +1,212 @@
+
+import feature ;
+import generators ;
+import "class" ;
+import toolset ;
+import targets ;
+import "class" : new ;
+import project ;
+
+feature.feature auto-index : off "on" ;
+feature.feature auto-index-internal : off "on" ;
+feature.feature auto-index-verbose : off "on" ;
+feature.feature auto-index-no-duplicates : off "on" ;
+feature.feature auto-index-script : : free ;
+feature.feature auto-index-prefix : : free ;
+feature.feature auto-index-type : : free ;
+feature.feature auto-index-section-names : "on" off ;
+
+toolset.flags auto-index.auto-index FLAGS <auto-index-internal>on : --internal-index ;
+toolset.flags auto-index.auto-index SCRIPT <auto-index-script> ;
+toolset.flags auto-index.auto-index PREFIX <auto-index-prefix> ;
+toolset.flags auto-index.auto-index INDEX_TYPE <auto-index-type> ;
+toolset.flags auto-index.auto-index FLAGS <auto-index-verbose>on : --verbose ;
+toolset.flags auto-index.auto-index FLAGS <auto-index-no-duplicates>on : --no-duplicates ;
+toolset.flags auto-index.auto-index FLAGS <auto-index-section-names>off : --no-section-names ;
+
+# <auto-index-binary> shell command to run AutoIndex
+# <auto-index-binary-dependencies> targets to build AutoIndex from sources.
+feature.feature <auto-index-binary> : : free ;
+feature.feature <auto-index-binary-dependencies> : : free dependency ;
+
+class auto-index-generator : generator
+{
+ import common modules path targets build-system ;
+ rule run ( project name ? : property-set : sources * )
+ {
+ # AutoIndex invocation command and dependencies.
+ local auto-index-binary = [ modules.peek auto-index : .command ] ;
+ local auto-index-binary-dependencies ;
+
+ if $(auto-index-binary)
+ {
+ # Use user-supplied command.
+ auto-index-binary = [ common.get-invocation-command auto-index : auto-index : $(auto-index-binary) ] ;
+ }
+ else
+ {
+ # Search for AutoIndex sources in sensible places, like
+ # $(BOOST_ROOT)/tools/auto_index
+ # $(BOOST_BUILD_PATH)/../../auto_index
+
+ # And build auto-index executable from sources.
+
+ local boost-root = [ modules.peek : BOOST_ROOT ] ;
+ local boost-build-path = [ build-system.location ] ;
+ local boost-build-path2 = [ modules.peek : BOOST_BUILD_PATH ] ;
+
+ local auto-index-dir ;
+
+ if $(boost-root)
+ {
+ auto-index-dir += [ path.join $(boost-root) tools ] ;
+ }
+
+ if $(boost-build-path)
+ {
+ auto-index-dir += $(boost-build-path)/../.. ;
+ }
+ if $(boost-build-path2)
+ {
+ auto-index-dir += $(boost-build-path2)/.. ;
+ }
+
+ #ECHO $(auto-index-dir) ;
+ auto-index-dir = [ path.glob $(auto-index-dir) : auto_index ] ;
+ #ECHO $(auto-index-dir) ;
+
+ # If the AutoIndex source directory was found, mark its main target
+ # as a dependency for the current project. Otherwise, try to find
+ # 'auto-index' in user's PATH
+ if $(auto-index-dir)
+ {
+ auto-index-dir = [ path.make $(auto-index-dir[1]) ] ;
+ auto-index-dir = $(auto-index-dir)/build ;
+
+ #ECHO $(auto-index-dir) ;
+
+ # Get the main-target in AutoIndex directory.
+ local auto-index-main-target = [ targets.resolve-reference $(auto-index-dir) : $(project) ] ;
+
+ #ECHO $(auto-index-main-target) ;
+
+ # The first element are actual targets, the second are
+ # properties found in target-id. We do not care about these
+ # since we have passed the id ourselves.
+ auto-index-main-target =
+ [ $(auto-index-main-target[1]).main-target auto_index ] ;
+
+ #ECHO $(auto-index-main-target) ;
+
+ auto-index-binary-dependencies =
+ [ $(auto-index-main-target).generate [ $(property-set).propagated ] ] ;
+
+ # Ignore usage-requirements returned as first element.
+ auto-index-binary-dependencies = $(auto-index-binary-dependencies[2-]) ;
+
+ # Some toolsets generate extra targets (e.g. RSP). We must mark
+ # all targets as dependencies for the project, but we will only
+ # use the EXE target for auto-index-to-boostbook translation.
+ for local target in $(auto-index-binary-dependencies)
+ {
+ if [ $(target).type ] = EXE
+ {
+ auto-index-binary =
+ [ path.native
+ [ path.join
+ [ $(target).path ]
+ [ $(target).name ]
+ ]
+ ] ;
+ }
+ }
+ }
+ else
+ {
+ ECHO "AutoIndex warning: The path to the auto-index executable was" ;
+ ECHO " not provided. Additionally, couldn't find AutoIndex" ;
+ ECHO " sources searching in" ;
+ ECHO " * BOOST_ROOT/tools/auto-index" ;
+ ECHO " * BOOST_BUILD_PATH/../../auto-index" ;
+ ECHO " Will now try to find a precompiled executable by searching" ;
+ ECHO " the PATH for 'auto-index'." ;
+ ECHO " To disable this warning in the future, or to completely" ;
+ ECHO " avoid compilation of auto-index, you can explicitly set the" ;
+ ECHO " path to a auto-index executable command in user-config.jam" ;
+ ECHO " or site-config.jam with the call" ;
+ ECHO " using auto-index : /path/to/auto-index ;" ;
+
+ # As a last resort, search for 'auto-index' command in path. Note
+ # that even if the 'auto-index' command is not found,
+ # get-invocation-command will still return 'auto-index' and might
+ # generate an error while generating the virtual-target.
+
+ auto-index-binary = [ common.get-invocation-command auto-index : auto-index ] ;
+ }
+ }
+
+ # Add $(auto-index-binary-dependencies) as a dependency of the current
+ # project and set it as the <auto-index-binary> feature for the
+ # auto-index-to-boostbook rule, below.
+ property-set = [ $(property-set).add-raw
+ <dependency>$(auto-index-binary-dependencies)
+ <auto-index-binary>$(auto-index-binary)
+ <auto-index-binary-dependencies>$(auto-index-binary-dependencies)
+ ] ;
+
+ #ECHO "binary = " $(auto-index-binary) ;
+ #ECHO "dependencies = " $(auto-index-binary-dependencies) ;
+
+ if [ $(property-set).get <auto-index> ] = "on"
+ {
+ return [ generator.run $(project) $(name) : $(property-set) : $(sources) ] ;
+ }
+ else
+ {
+ return [ generators.construct $(project) $(name) : DOCBOOK : $(property-set)
+ : $(sources) ] ;
+ }
+ }
+}
+
+# Initialization of toolset.
+#
+# Parameters:
+# command ? -> path to AutoIndex executable.
+#
+# When command is not supplied toolset will search for AutoIndex directory and
+# compile the executable from source. If that fails we still search the path for
+# 'auto_index'.
+#
+rule init (
+ command ? # path to the AutoIndex executable.
+ )
+{
+ if ! $(.initialized)
+ {
+ .initialized = true ;
+ .command = $(command) ;
+ }
+}
+
+toolset.flags auto-index.auto-index AI-COMMAND <auto-index-binary> ;
+toolset.flags auto-index.auto-index AI-DEPENDENCIES <auto-index-binary-dependencies> ;
+
+generators.register [ class.new auto-index-generator auto-index.auto-index : DOCBOOK : DOCBOOK(%.auto_index) ] ;
+generators.override auto-index.auto-index : boostbook.boostbook-to-docbook ;
+
+rule auto-index ( target : source : properties * )
+{
+ # Signal dependency of auto-index sources on <auto-index-binary-dependencies>
+ # upon invocation of auto-index-to-boostbook.
+ #ECHO "AI-COMMAND= " $(AI-COMMAND) ;
+ DEPENDS $(target) : [ on $(target) return $(AI-DEPENDENCIES) ] ;
+ #DEPENDS $(target) : [ on $(target) return $(SCRIPT) ] ;
+}
+
+actions auto-index
+{
+ $(AI-COMMAND) $(FLAGS) "--prefix="$(PREFIX) "--script="$(SCRIPT) "--index-type="$(INDEX_TYPE) "--in="$(>) "--out="$(<)
+}
+
+
diff --git a/tools/build/v2/tools/bison.jam b/tools/build/v2/tools/bison.jam
new file mode 100644
index 0000000000..0689d4bd89
--- /dev/null
+++ b/tools/build/v2/tools/bison.jam
@@ -0,0 +1,32 @@
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import generators ;
+import feature ;
+import type ;
+import property ;
+
+feature.feature bison.prefix : : free ;
+type.register Y : y ;
+type.register YY : yy ;
+generators.register-standard bison.bison : Y : C H ;
+generators.register-standard bison.bison : YY : CPP HPP ;
+
+rule init ( )
+{
+}
+
+rule bison ( dst dst_header : src : properties * )
+{
+ local r = [ property.select bison.prefix : $(properties) ] ;
+ if $(r)
+ {
+ PREFIX_OPT on $(<) = -p $(r:G=) ;
+ }
+}
+
+actions bison
+{
+ bison $(PREFIX_OPT) -d -o $(<[1]) $(>)
+}
diff --git a/tools/build/v2/tools/boostbook-config.jam b/tools/build/v2/tools/boostbook-config.jam
new file mode 100644
index 0000000000..6e3f3ddc10
--- /dev/null
+++ b/tools/build/v2/tools/boostbook-config.jam
@@ -0,0 +1,13 @@
+#~ Copyright 2005 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Automatic configuration for BoostBook tools. To use, just import this module.
+#
+# This module is deprecated.
+# using boostbook ;
+# with no arguments now suffices.
+
+import toolset : using ;
+
+using boostbook ;
diff --git a/tools/build/v2/tools/boostbook.jam b/tools/build/v2/tools/boostbook.jam
new file mode 100644
index 0000000000..3a5964c627
--- /dev/null
+++ b/tools/build/v2/tools/boostbook.jam
@@ -0,0 +1,727 @@
+# Copyright 2003, 2004, 2005 Dave Abrahams
+# Copyright 2003, 2004, 2005 Douglas Gregor
+# Copyright 2005, 2006, 2007 Rene Rivera
+# Copyright 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This module defines rules to handle generation of documentation
+# from BoostBook sources.
+#
+# The type of output is controlled by the <format> feature which can
+# have the following values::
+#
+# * html: Generates html documention. This is the default.
+# * xhtml: Generates xhtml documentation
+# * htmlhelp: Generates html help output.
+# * onehtml: Generates a single html page.
+# * man: Generates man pages.
+# * pdf: Generates pdf documentation.
+# * ps: Generates postscript output.
+# * docbook: Generates docbook XML.
+# * fo: Generates XSL formating objects.
+# * tests: Extracts test cases from the boostbook XML.
+#
+# format is an implicit feature, so typing pdf on the command
+# line (for example) is a short-cut for format=pdf.
+
+import "class" : new ;
+import common ;
+import errors ;
+import targets ;
+import feature ;
+import generators ;
+import print ;
+import property ;
+import project ;
+import property-set ;
+import regex ;
+import scanner ;
+import sequence ;
+import make ;
+import os ;
+import type ;
+import modules path project ;
+import build-system ;
+
+import xsltproc : xslt xslt-dir ;
+
+# Make this module into a project.
+project.initialize $(__name__) ;
+project boostbook ;
+
+
+feature.feature format : html xhtml htmlhelp onehtml man pdf ps docbook fo tests
+ : incidental implicit composite propagated ;
+
+type.register DTDXML : dtdxml ;
+type.register XML : xml ;
+type.register BOOSTBOOK : boostbook : XML ;
+type.register DOCBOOK : docbook : XML ;
+type.register FO : fo : XML ;
+type.register PDF : pdf ;
+type.register PS : ps ;
+type.register XSLT : xsl : XML ;
+type.register HTMLDIR ;
+type.register XHTMLDIR ;
+type.register HTMLHELP ;
+type.register MANPAGES ;
+type.register TESTS : tests ;
+# Artificial target type, used to require invocation of top-level
+# BoostBook generator.
+type.register BOOSTBOOK_MAIN ;
+
+
+# Initialize BoostBook support.
+rule init (
+ docbook-xsl-dir ? # The DocBook XSL stylesheet directory. If not
+ # provided, we use DOCBOOK_XSL_DIR from the environment
+ # (if available) or look in standard locations.
+ # Otherwise, we let the XML processor load the
+ # stylesheets remotely.
+
+ : docbook-dtd-dir ? # The DocBook DTD directory. If not provided, we use
+ # DOCBOOK_DTD_DIR From the environment (if available) or
+ # look in standard locations. Otherwise, we let the XML
+ # processor load the DTD remotely.
+
+ : boostbook-dir ? # The BoostBook directory with the DTD and XSL subdirs.
+)
+{
+
+ if ! $(.initialized)
+ {
+ .initialized = true ;
+
+ check-boostbook-dir $(boostbook-dir) ;
+ find-tools $(docbook-xsl-dir) : $(docbook-dtd-dir) : $(boostbook-dir) ;
+
+ # Register generators only if we've were called via "using boostbook ; "
+ generators.register-standard boostbook.dtdxml-to-boostbook : DTDXML : XML ;
+ generators.register-standard boostbook.boostbook-to-docbook : XML : DOCBOOK ;
+ generators.register-standard boostbook.boostbook-to-tests : XML : TESTS ;
+ generators.register-standard boostbook.docbook-to-onehtml : DOCBOOK : HTML ;
+ generators.register-standard boostbook.docbook-to-htmldir : DOCBOOK : HTMLDIR ;
+ generators.register-standard boostbook.docbook-to-xhtmldir : DOCBOOK : XHTMLDIR ;
+ generators.register-standard boostbook.docbook-to-htmlhelp : DOCBOOK : HTMLHELP ;
+ generators.register-standard boostbook.docbook-to-manpages : DOCBOOK : MANPAGES ;
+ generators.register-standard boostbook.docbook-to-fo : DOCBOOK : FO ;
+
+ # The same about Jamfile main target rules.
+ IMPORT $(__name__) : boostbook : : boostbook ;
+ }
+ else
+ {
+ if $(docbook-xsl-dir)
+ {
+ modify-config ;
+ .docbook-xsl-dir = [ path.make $(docbook-xsl-dir) ] ;
+ check-docbook-xsl-dir ;
+ }
+ if $(docbook-dtd-dir)
+ {
+ modify-config ;
+ .docbook-dtd-dir = [ path.make $(docbook-dtd-dir) ] ;
+ check-docbook-dtd-dir ;
+ }
+ if $(boostbook-dir)
+ {
+ modify-config ;
+ check-boostbook-dir $(boostbook-dir) ;
+ local boostbook-xsl-dir = [ path.glob $(boostbook-dir) : xsl ] ;
+ local boostbook-dtd-dir = [ path.glob $(boostbook-dir) : dtd ] ;
+ .boostbook-xsl-dir = $(boostbook-xsl-dir[1]) ;
+ .boostbook-dtd-dir = $(boostbook-dtd-dir[1]) ;
+ check-boostbook-xsl-dir ;
+ check-boostbook-dtd-dir ;
+ }
+ }
+}
+
+rule lock-config ( )
+{
+ if ! $(.initialized)
+ {
+ errors.user-error "BoostBook has not been configured." ;
+ }
+ if ! $(.config-locked)
+ {
+ .config-locked = true ;
+ }
+}
+
+rule modify-config ( )
+{
+ if $(.config-locked)
+ {
+ errors.user-error "BoostBook configuration cannot be changed after it has been used." ;
+ }
+}
+
+rule find-boost-in-registry ( keys * )
+{
+ local boost-root = ;
+ for local R in $(keys)
+ {
+ local installed-boost = [ W32_GETREG
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\$(R)"
+ : "InstallRoot" ] ;
+ if $(installed-boost)
+ {
+ boost-root += [ path.make $(installed-boost) ] ;
+ }
+ }
+ return $(boost-root) ;
+}
+
+rule check-docbook-xsl-dir ( )
+{
+ if $(.docbook-xsl-dir)
+ {
+ if ! [ path.glob $(.docbook-xsl-dir) : common/common.xsl ]
+ {
+ errors.user-error "BoostBook: could not find docbook XSL stylesheets in:" [ path.native $(.docbook-xsl-dir) ] ;
+ }
+ else
+ {
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice: BoostBook: found docbook XSL stylesheets in:" [ path.native $(.docbook-xsl-dir) ] ;
+ }
+ }
+ }
+}
+
+rule check-docbook-dtd-dir ( )
+{
+ if $(.docbook-dtd-dir)
+ {
+ if ! [ path.glob $(.docbook-dtd-dir) : docbookx.dtd ]
+ {
+ errors.user-error "error: BoostBook: could not find docbook DTD in:" [ path.native $(.docbook-dtd-dir) ] ;
+ }
+ else
+ {
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice: BoostBook: found docbook DTD in:" [ path.native $(.docbook-dtd-dir) ] ;
+ }
+ }
+ }
+}
+
+rule check-boostbook-xsl-dir ( )
+{
+ if ! $(.boostbook-xsl-dir)
+ {
+ errors.user-error "error: BoostBook: could not find boostbook XSL stylesheets." ;
+ }
+ else if ! [ path.glob $(.boostbook-xsl-dir) : docbook.xsl ]
+ {
+ errors.user-error "error: BoostBook: could not find docbook XSL stylesheets in:" [ path.native $(.boostbook-xsl-dir) ] ;
+ }
+ else
+ {
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice: BoostBook: found boostbook XSL stylesheets in:" [ path.native $(.boostbook-xsl-dir) ] ;
+ }
+ }
+}
+
+rule check-boostbook-dtd-dir ( )
+{
+ if ! $(.boostbook-dtd-dir)
+ {
+ errors.user-error "error: BoostBook: could not find boostbook DTD." ;
+ }
+ else if ! [ path.glob $(.boostbook-dtd-dir) : boostbook.dtd ]
+ {
+ errors.user-error "error: BoostBook: could not find boostbook DTD in:" [ path.native $(.boostbook-dtd-dir) ] ;
+ }
+ else
+ {
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice: BoostBook: found boostbook DTD in:" [ path.native $(.boostbook-dtd-dir) ] ;
+ }
+ }
+}
+
+rule check-boostbook-dir ( boostbook-dir ? )
+{
+ if $(boostbook-dir) && ! [ path.glob $(boostbook-dir) : xsl ]
+ {
+ errors.user-error "error: BoostBook: could not find boostbook in:" [ path.native $(boostbook-dir) ] ;
+ }
+}
+
+rule find-tools ( docbook-xsl-dir ? : docbook-dtd-dir ? : boostbook-dir ? )
+{
+ docbook-xsl-dir ?= [ modules.peek : DOCBOOK_XSL_DIR ] ;
+ docbook-dtd-dir ?= [ modules.peek : DOCBOOK_DTD_DIR ] ;
+ boostbook-dir ?= [ modules.peek : BOOSTBOOK_DIR ] ;
+
+ # Look for the boostbook stylesheets relative to BOOST_ROOT
+ # and Boost.Build.
+ local boost-build-root = [ path.make [ build-system.location ] ] ;
+ local boostbook-search-dirs = [ path.join $(boost-build-root) .. .. ] ;
+
+ local boost-root = [ modules.peek : BOOST_ROOT ] ;
+ if $(boost-root)
+ {
+ boostbook-search-dirs += [ path.join [ path.make $(boost-root) ] tools ] ;
+ }
+ boostbook-dir ?= [ path.glob $(boostbook-search-dirs) : boostbook* ] ;
+
+ # Try to find the tools in platform specific locations
+ if [ os.name ] = NT
+ {
+ # If installed by the Boost installer.
+ local boost-root = ;
+
+ local boost-installer-versions = snapshot cvs 1.33.0 ;
+ local boost-consulting-installer-versions = 1.33.1 1.34.0 1.34.1 ;
+ local boostpro-installer-versions =
+ 1.35.0 1.36.0 1.37.0 1.38.0 1.39.0 1.40.0 1.41.0 1.42.0
+ 1.43.0 1.44.0 1.45.0 1.46.0 1.47.0 1.48.0 1.49.0 1.50.0 ;
+
+ local old-installer-root = [ find-boost-in-registry Boost.org\\$(boost-installer-versions) ] ;
+
+ # Make sure that the most recent version is searched for first
+ boost-root += [ sequence.reverse
+ [ find-boost-in-registry
+ Boost-Consulting.com\\$(boost-consulting-installer-versions)
+ boostpro.com\\$(boostpro-installer-versions) ] ] ;
+
+ # Plausible locations.
+ local root = [ PWD ] ;
+ while $(root) != $(root:D) { root = $(root:D) ; }
+ root = [ path.make $(root) ] ;
+ local search-dirs = ;
+ local docbook-search-dirs = ;
+ for local p in $(boost-root) {
+ search-dirs += [ path.join $(p) tools ] ;
+ }
+ for local p in $(old-installer-root)
+ {
+ search-dirs += [ path.join $(p) share ] ;
+ docbook-search-dirs += [ path.join $(p) share ] ;
+ }
+ search-dirs += [ path.join $(root) Boost tools ] ;
+ search-dirs += [ path.join $(root) Boost share ] ;
+ docbook-search-dirs += [ path.join $(root) Boost share ] ;
+
+ docbook-xsl-dir ?= [ path.glob $(docbook-search-dirs) : docbook-xsl* ] ;
+ docbook-dtd-dir ?= [ path.glob $(docbook-search-dirs) : docbook-xml* ] ;
+ boostbook-dir ?= [ path.glob $(search-dirs) : boostbook* ] ;
+ }
+ else
+ {
+ # Plausible locations.
+
+ local share = /usr/local/share /usr/share /opt/share /opt/local/share ;
+ local dtd-versions = 4.2 ;
+
+ docbook-xsl-dir ?= [ path.glob $(share) : docbook-xsl* ] ;
+ docbook-xsl-dir ?= [ path.glob $(share)/sgml/docbook : xsl-stylesheets ] ;
+ docbook-xsl-dir ?= [ path.glob $(share)/xsl : docbook* ] ;
+
+ docbook-dtd-dir ?= [ path.glob $(share) : docbook-xml* ] ;
+ docbook-dtd-dir ?= [ path.glob $(share)/sgml/docbook : xml-dtd-$(dtd-versions)* ] ;
+ docbook-dtd-dir ?= [ path.glob $(share)/xml/docbook : $(dtd-versions) ] ;
+
+ boostbook-dir ?= [ path.glob $(share) : boostbook* ] ;
+
+ # Ubuntu Linux
+ docbook-xsl-dir ?= [ path.glob /usr/share/xml/docbook/stylesheet : nwalsh ] ;
+ docbook-dtd-dir ?= [ path.glob /usr/share/xml/docbook/schema/dtd : $(dtd-versions) ] ;
+ }
+
+ if $(docbook-xsl-dir)
+ {
+ .docbook-xsl-dir = [ path.make $(docbook-xsl-dir[1]) ] ;
+ }
+ if $(docbook-dtd-dir)
+ {
+ .docbook-dtd-dir = [ path.make $(docbook-dtd-dir[1]) ] ;
+ }
+
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice: Boost.Book: searching XSL/DTD in" ;
+ ECHO "notice:" [ sequence.transform path.native : $(boostbook-dir) ] ;
+ }
+ local boostbook-xsl-dir ;
+ for local dir in $(boostbook-dir) {
+ boostbook-xsl-dir += [ path.glob $(dir) : xsl ] ;
+ }
+ local boostbook-dtd-dir ;
+ for local dir in $(boostbook-dir) {
+ boostbook-dtd-dir += [ path.glob $(dir) : dtd ] ;
+ }
+ .boostbook-xsl-dir = $(boostbook-xsl-dir[1]) ;
+ .boostbook-dtd-dir = $(boostbook-dtd-dir[1]) ;
+
+ check-docbook-xsl-dir ;
+ check-docbook-dtd-dir ;
+ check-boostbook-xsl-dir ;
+ check-boostbook-dtd-dir ;
+}
+
+rule xsl-dir
+{
+ lock-config ;
+ return $(.boostbook-xsl-dir) ;
+}
+
+rule dtd-dir
+{
+ lock-config ;
+ return $(.boostbook-dtd-dir) ;
+}
+
+rule docbook-xsl-dir
+{
+ lock-config ;
+ return $(.docbook-xsl-dir) ;
+}
+
+rule docbook-dtd-dir
+{
+ lock-config ;
+ return $(.docbook-dtd-dir) ;
+}
+
+rule dtdxml-to-boostbook ( target : source : properties * )
+{
+ lock-config ;
+ xslt $(target) : $(source) "$(.boostbook-xsl-dir)/dtd/dtd2boostbook.xsl"
+ : $(properties) ;
+}
+
+rule boostbook-to-docbook ( target : source : properties * )
+{
+ lock-config ;
+ local stylesheet = [ path.native $(.boostbook-xsl-dir)/docbook.xsl ] ;
+ xslt $(target) : $(source) $(stylesheet) : $(properties) ;
+}
+
+rule docbook-to-onehtml ( target : source : properties * )
+{
+ lock-config ;
+ local stylesheet = [ path.native $(.boostbook-xsl-dir)/html-single.xsl ] ;
+ xslt $(target) : $(source) $(stylesheet) : $(properties) ;
+}
+
+rule docbook-to-htmldir ( target : source : properties * )
+{
+ lock-config ;
+ local stylesheet = [ path.native $(.boostbook-xsl-dir)/html.xsl ] ;
+ xslt-dir $(target) : $(source) $(stylesheet) : $(properties) : html ;
+}
+
+rule docbook-to-xhtmldir ( target : source : properties * )
+{
+ lock-config ;
+ local stylesheet = [ path.native $(.boostbook-xsl-dir)/xhtml.xsl ] ;
+ xslt-dir $(target) : $(source) $(stylesheet) : $(properties) : xhtml ;
+}
+
+rule docbook-to-htmlhelp ( target : source : properties * )
+{
+ lock-config ;
+ local stylesheet = [ path.native $(.boostbook-xsl-dir)/html-help.xsl ] ;
+ xslt-dir $(target) : $(source) $(stylesheet) : $(properties) : htmlhelp ;
+}
+
+rule docbook-to-manpages ( target : source : properties * )
+{
+ lock-config ;
+ local stylesheet = [ path.native $(.boostbook-xsl-dir)/manpages.xsl ] ;
+ xslt-dir $(target) : $(source) $(stylesheet) : $(properties) : man ;
+}
+
+rule docbook-to-fo ( target : source : properties * )
+{
+ lock-config ;
+ local stylesheet = [ path.native $(.boostbook-xsl-dir)/fo.xsl ] ;
+ xslt $(target) : $(source) $(stylesheet) : $(properties) ;
+}
+
+rule format-catalog-path ( path )
+{
+ local result = $(path) ;
+ if [ xsltproc.is-cygwin ]
+ {
+ if [ os.name ] = NT
+ {
+ drive = [ MATCH ^/(.):(.*)$ : $(path) ] ;
+ result = /cygdrive/$(drive[1])$(drive[2]) ;
+ }
+ }
+ else
+ {
+ if [ os.name ] = CYGWIN
+ {
+ local native-path = [ path.native $(path) ] ;
+ result = [ path.make $(native-path:W) ] ;
+ }
+ }
+ return [ regex.replace $(result) " " "%20" ] ;
+}
+
+rule generate-xml-catalog ( target : sources * : properties * )
+{
+ print.output $(target) ;
+
+ # BoostBook DTD catalog entry
+ local boostbook-dtd-dir = [ boostbook.dtd-dir ] ;
+ if $(boostbook-dtd-dir)
+ {
+ boostbook-dtd-dir = [ format-catalog-path $(boostbook-dtd-dir) ] ;
+ }
+
+ print.text
+ "<?xml version=\"1.0\"?>"
+ "<!DOCTYPE catalog "
+ " PUBLIC \"-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN\""
+ " \"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd\">"
+ "<catalog xmlns=\"urn:oasis:names:tc:entity:xmlns:xml:catalog\">"
+ " <rewriteURI uriStartString=\"http://www.boost.org/tools/boostbook/dtd/\" rewritePrefix=\"file://$(boostbook-dtd-dir)/\"/>"
+ : true ;
+
+ local docbook-xsl-dir = [ boostbook.docbook-xsl-dir ] ;
+ if ! $(docbook-xsl-dir)
+ {
+ ECHO "BoostBook warning: no DocBook XSL directory specified." ;
+ ECHO " If you have the DocBook XSL stylesheets installed, please " ;
+ ECHO " set DOCBOOK_XSL_DIR to the stylesheet directory on either " ;
+ ECHO " the command line (via -sDOCBOOK_XSL_DIR=...) or in a " ;
+ ECHO " Boost.Jam configuration file. The DocBook XSL stylesheets " ;
+ ECHO " are available here: http://docbook.sourceforge.net/ " ;
+ ECHO " Stylesheets will be downloaded on-the-fly (very slow!) " ;
+ }
+ else
+ {
+ docbook-xsl-dir = [ format-catalog-path $(docbook-xsl-dir) ] ;
+ print.text " <rewriteURI uriStartString=\"http://docbook.sourceforge.net/release/xsl/current/\" rewritePrefix=\"file://$(docbook-xsl-dir)/\"/>" ;
+ }
+
+ local docbook-dtd-dir = [ boostbook.docbook-dtd-dir ] ;
+ if ! $(docbook-dtd-dir)
+ {
+ ECHO "BoostBook warning: no DocBook DTD directory specified." ;
+ ECHO " If you have the DocBook DTD installed, please set " ;
+ ECHO " DOCBOOK_DTD_DIR to the DTD directory on either " ;
+ ECHO " the command line (via -sDOCBOOK_DTD_DIR=...) or in a " ;
+ ECHO " Boost.Jam configuration file. The DocBook DTD is available " ;
+ ECHO " here: http://www.oasis-open.org/docbook/xml/4.2/index.shtml" ;
+ ECHO " The DTD will be downloaded on-the-fly (very slow!) " ;
+ }
+ else
+ {
+ docbook-dtd-dir = [ format-catalog-path $(docbook-dtd-dir) ] ;
+ print.text " <rewriteURI uriStartString=\"http://www.oasis-open.org/docbook/xml/4.2/\" rewritePrefix=\"file://$(docbook-dtd-dir)/\"/>" ;
+ }
+
+ print.text "</catalog>" ;
+}
+
+rule xml-catalog ( )
+{
+ if ! $(.xml-catalog)
+ {
+ # The target is created as part of the root project. But ideally
+ # it would be created as part of the boostbook project. This is not
+ # current possible as such global projects don't inherit things like
+ # the build directory.
+
+ # Find the root project.
+ local root-project = [ project.current ] ;
+ root-project = [ $(root-project).project-module ] ;
+ while
+ [ project.attribute $(root-project) parent-module ] &&
+ [ project.attribute $(root-project) parent-module ] != user-config &&
+ [ project.attribute $(root-project) parent-module ] != project-config
+ {
+ root-project = [ project.attribute $(root-project) parent-module ] ;
+ }
+ .xml-catalog = [ new file-target boostbook_catalog
+ : XML
+ : [ project.target $(root-project) ]
+ : [ new action : boostbook.generate-xml-catalog ]
+ :
+ ] ;
+ .xml-catalog-file = [ $(.xml-catalog).path ] [ $(.xml-catalog).name ] ;
+ .xml-catalog-file = $(.xml-catalog-file:J=/) ;
+ }
+ return $(.xml-catalog) $(.xml-catalog-file) ;
+}
+
+class boostbook-generator : generator
+{
+ import feature ;
+ import virtual-target ;
+ import generators ;
+ import boostbook ;
+
+
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * )
+ {
+ # Generate the catalog, but only once...
+ local global-catalog = [ boostbook.xml-catalog ] ;
+ local catalog = $(global-catalog[1]) ;
+ local catalog-file = $(global-catalog[2]) ;
+ local targets ;
+
+ # Add the catalog to the property set
+ property-set = [ $(property-set).add-raw <catalog>$(catalog-file) ] ;
+
+ local type = none ;
+ local manifest ;
+ local format = [ $(property-set).get <format> ] ;
+ switch $(format)
+ {
+ case html :
+ {
+ type = HTMLDIR ;
+ manifest = HTML.manifest ;
+ }
+ case xhtml :
+ {
+ type = XHTMLDIR ;
+ manifest = HTML.manifest ;
+ }
+ case htmlhelp :
+ {
+ type = HTMLHELP ;
+ manifest = HTML.manifest ;
+ }
+
+ case onehtml : type = HTML ;
+
+ case man :
+ {
+ type = MANPAGES ;
+ manifest = man.manifest ;
+ }
+
+ case docbook : type = DOCBOOK ;
+ case fo : type = FO ;
+ case pdf : type = PDF ;
+ case ps : type = PS ;
+ case tests : type = TESTS ;
+ }
+
+ if $(manifest)
+ {
+ # Create DOCBOOK file from BOOSTBOOK sources.
+ local base-target = [ generators.construct $(project)
+ : DOCBOOK : $(property-set) : $(sources) ] ;
+ base-target = $(base-target[2]) ;
+ $(base-target).depends $(catalog) ;
+
+ # Generate HTML/PDF/PS from DOCBOOK.
+ local target = [ generators.construct $(project) $(name)_$(manifest)
+ : $(type)
+ : [ $(property-set).add-raw
+ <xsl:param>manifest=$(name)_$(manifest) ]
+ : $(base-target) ] ;
+ local name = [ $(property-set).get <name> ] ;
+ name ?= $(format) ;
+ $(target[2]).set-path $(name) ;
+ $(target[2]).depends $(catalog) ;
+
+ targets += $(target[2]) ;
+ }
+ else {
+ local target = [ generators.construct $(project)
+ : $(type) : $(property-set) : $(sources) ] ;
+
+ if ! $(target)
+ {
+ errors.error "Cannot build documentation type '$(format)'" ;
+ }
+ else
+ {
+ $(target[2]).depends $(catalog) ;
+ targets += $(target[2]) ;
+ }
+ }
+
+ return $(targets) ;
+ }
+}
+
+generators.register [ new boostbook-generator boostbook.main : : BOOSTBOOK_MAIN ] ;
+
+# Creates a boostbook target.
+rule boostbook ( target-name : sources * : requirements * : default-build * )
+{
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new typed-target $(target-name) : $(project) : BOOSTBOOK_MAIN
+ : [ targets.main-target-sources $(sources) : $(target-name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+}
+
+#############################################################################
+# Dependency scanners
+#############################################################################
+# XInclude scanner. Mostly stolen from c-scanner :)
+# Note that this assumes an "xi" prefix for XIncludes. This isn't always the
+# case for XML documents, but we'll assume it's true for anything we encounter.
+class xinclude-scanner : scanner
+{
+ import virtual-target ;
+ import path ;
+ import scanner ;
+
+ rule __init__ ( includes * )
+ {
+ scanner.__init__ ;
+ self.includes = $(includes) ;
+ }
+
+ rule pattern ( )
+ {
+ return "xi:include[ ]*href=\"([^\"]*)\"" ;
+ }
+
+ rule process ( target : matches * : binding )
+ {
+ local target_path = [ NORMALIZE_PATH $(binding:D) ] ;
+
+ NOCARE $(matches) ;
+ INCLUDES $(target) : $(matches) ;
+ SEARCH on $(matches) = $(target_path) $(self.includes:G=) ;
+
+ scanner.propagate $(__name__) : $(matches) : $(target) ;
+ }
+}
+
+scanner.register xinclude-scanner : xsl:path ;
+type.set-scanner XML : xinclude-scanner ;
+
+rule boostbook-to-tests ( target : source : properties * )
+{
+ lock-config ;
+ local boost_root = [ modules.peek : BOOST_ROOT ] ;
+ local native-path =
+ [ path.native [ path.join $(.boostbook-xsl-dir) testing Jamfile ] ] ;
+ local stylesheet = $(native-path:S=.xsl) ;
+ xslt $(target) : $(source) $(stylesheet)
+ : $(properties) <xsl:param>boost.root=$(boost_root)
+ ;
+}
+
+
diff --git a/tools/build/v2/tools/borland.jam b/tools/build/v2/tools/borland.jam
new file mode 100644
index 0000000000..6e43ca93a5
--- /dev/null
+++ b/tools/build/v2/tools/borland.jam
@@ -0,0 +1,220 @@
+# Copyright 2005 Dave Abrahams
+# Copyright 2003 Rene Rivera
+# Copyright 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Support for the Borland's command line compiler
+
+import property ;
+import generators ;
+import os ;
+import toolset : flags ;
+import feature : get-values ;
+import type ;
+import common ;
+
+feature.extend toolset : borland ;
+
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters borland :
+ version $(version) ] ;
+
+ local command = [ common.get-invocation-command borland : bcc32.exe
+ : $(command) ] ;
+
+ common.handle-options borland : $(condition) : $(command) : $(options) ;
+
+ if $(command)
+ {
+ command = [ common.get-absolute-tool-path $(command[-1]) ] ;
+ }
+ root = $(command:D) ;
+
+ flags borland.compile STDHDRS $(condition) : $(root)/include/ ;
+ flags borland.link STDLIBPATH $(condition) : $(root)/lib ;
+ flags borland.link RUN_PATH $(condition) : $(root)/bin ;
+ flags borland .root $(condition) : $(root)/bin/ ;
+}
+
+
+# A borland-specific target type
+type.register BORLAND.TDS : tds ;
+
+# Declare generators
+
+generators.register-linker borland.link : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : <toolset>borland ;
+generators.register-linker borland.link.dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB : <toolset>borland ;
+
+generators.register-archiver borland.archive : OBJ : STATIC_LIB : <toolset>borland ;
+generators.register-c-compiler borland.compile.c++ : CPP : OBJ : <toolset>borland ;
+generators.register-c-compiler borland.compile.c : C : OBJ : <toolset>borland ;
+generators.register-standard borland.asm : ASM : OBJ : <toolset>borland ;
+
+# Declare flags
+
+flags borland.compile OPTIONS <debug-symbols>on : -v ;
+flags borland.link OPTIONS <debug-symbols>on : -v ;
+
+flags borland.compile OPTIONS <optimization>off : -Od ;
+flags borland.compile OPTIONS <optimization>speed : -O2 ;
+flags borland.compile OPTIONS <optimization>space : -O1 ;
+
+if $(.BORLAND_HAS_FIXED_INLINING_BUGS)
+{
+ flags borland CFLAGS <inlining>off : -vi- ;
+ flags borland CFLAGS <inlining>on : -vi -w-inl ;
+ flags borland CFLAGS <inlining>full : -vi -w-inl ;
+}
+else
+{
+ flags borland CFLAGS : -vi- ;
+}
+
+flags borland.compile OPTIONS <warnings>off : -w- ;
+flags borland.compile OPTIONS <warnings>all : -w ;
+flags borland.compile OPTIONS <warnings-as-errors>on : -w! ;
+
+
+# Deal with various runtime configs...
+
+# This should be not for DLL
+flags borland OPTIONS <user-interface>console : -tWC ;
+
+# -tWR sets -tW as well, so we turn it off here and then turn it
+# on again later if we need it:
+flags borland OPTIONS <runtime-link>shared : -tWR -tWC ;
+flags borland OPTIONS <user-interface>gui : -tW ;
+
+flags borland OPTIONS <main-target-type>LIB/<link>shared : -tWD ;
+# Hmm.. not sure what's going on here.
+flags borland OPTIONS : -WM- ;
+flags borland OPTIONS <threading>multi : -tWM ;
+
+
+
+flags borland.compile OPTIONS <cxxflags> ;
+flags borland.compile DEFINES <define> ;
+flags borland.compile INCLUDES <include> ;
+
+flags borland NEED_IMPLIB <main-target-type>LIB/<link>shared : "" ;
+
+#
+# for C++ compiles the following options are turned on by default:
+#
+# -j5 stops after 5 errors
+# -g255 allow an unlimited number of warnings
+# -q no banner
+# -c compile to object
+# -P C++ code regardless of file extention
+# -a8 8 byte alignment, this option is on in the IDE by default
+# and effects binary compatibility.
+#
+
+# -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o"$(<)" "$(>)"
+
+
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" -j5 -g255 -q -c -P -a8 -Vx- -Ve- -b- $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -I"$(STDHDRS)" -o"$(<)" "$(>)"
+}
+
+# For C, we don't pass -P flag
+actions compile.c
+{
+ "$(CONFIG_COMMAND)" -j5 -g255 -q -c -a8 -Vx- -Ve- -b- $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -I"$(STDHDRS)" -o"$(<)" "$(>)"
+}
+
+
+# Declare flags and action for linking
+toolset.flags borland.link OPTIONS <debug-symbols>on : -v ;
+toolset.flags borland.link LIBRARY_PATH <library-path> ;
+toolset.flags borland.link FINDLIBS_ST <find-static-library> ;
+toolset.flags borland.link FINDLIBS_SA <find-shared-library> ;
+toolset.flags borland.link LIBRARIES <library-file> ;
+
+flags borland.link OPTIONS <linkflags> ;
+flags borland.link OPTIONS <link>shared : -tWD ;
+
+flags borland.link LIBRARY_PATH_OPTION <toolset>borland : -L : unchecked ;
+flags borland.link LIBRARY_OPTION <toolset>borland : "" : unchecked ;
+
+
+
+# bcc32 needs to have ilink32 in the path in order to invoke it, so explicitly
+# specifying $(BCC_TOOL_PATH)bcc32 doesn't help. You need to add
+# $(BCC_TOOL_PATH) to the path
+# The NEED_IMPLIB variable controls whether we need to invoke implib.
+
+flags borland.archive AROPTIONS <archiveflags> ;
+
+# Declare action for archives. We don't use response file
+# since it's hard to get "+-" there.
+# The /P256 increases 'page' size -- with too low
+# values tlib fails when building large applications.
+# CONSIDER: don't know what 'together' is for...
+actions updated together piecemeal archive
+{
+ $(.set-path)$(.root:W)$(.old-path)
+ tlib $(AROPTIONS) /P256 /u /a /C "$(<:W)" +-"$(>:W)"
+}
+
+
+if [ os.name ] = CYGWIN
+{
+ .set-path = "cmd /S /C set \"PATH=" ;
+ .old-path = ";%PATH%\" \"&&\"" ;
+
+
+ # Couldn't get TLIB to stop being confused about pathnames
+ # containing dashes (it seemed to treat them as option separators
+ # when passed through from bash), so we explicitly write the
+ # command into a .bat file and execute that. TLIB is also finicky
+ # about pathname style! Forward slashes, too, are treated as
+ # options.
+ actions updated together piecemeal archive
+ {
+ chdir $(<:D)
+ echo +-$(>:BS) > $(<:BS).rsp
+ $(.set-path)$(.root)$(.old-path) "tlib.exe" $(AROPTIONS) /P256 /C $(<:BS) @$(<:BS).rsp && $(RM) $(<:BS).rsp
+ }
+}
+else if [ os.name ] = NT
+{
+ .set-path = "set \"PATH=" ;
+ .old-path = ";%PATH%\"
+ " ;
+}
+else
+{
+ .set-path = "PATH=\"" ;
+ .old-path = "\":$PATH
+ export PATH
+ " ;
+}
+
+RM = [ common.rm-command ] ;
+
+nl = "
+" ;
+
+actions link
+{
+ $(.set-path)$(.root:W)$(.old-path) "$(CONFIG_COMMAND)" -v -q $(OPTIONS) -L"$(LIBRARY_PATH:W)" -L"$(STDLIBPATH:W)" -e"$(<[1]:W)" @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")"
+}
+
+
+actions link.dll bind LIBRARIES RSP
+{
+ $(.set-path)$(.root:W)$(.old-path) "$(CONFIG_COMMAND)" -v -q $(OPTIONS) -L"$(LIBRARY_PATH:W)" -L"$(STDLIBPATH:W)" -e"$(<[1]:W)" @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")" && "$(.root)implib" "$(<[2]:W)" "$(<[1]:W)"
+}
+
+# It seems impossible to specify output file with directory when compiling
+# asm files using bcc32, so use tasm32 directly.
+# /ml makes all symbol names case-sensitive
+actions asm
+{
+ $(.set-path)$(.root:W)$(.old-path) tasm32.exe /ml "$(>)" "$(<)"
+}
+
diff --git a/tools/build/v2/tools/builtin.jam b/tools/build/v2/tools/builtin.jam
new file mode 100644
index 0000000000..d1351a4231
--- /dev/null
+++ b/tools/build/v2/tools/builtin.jam
@@ -0,0 +1,960 @@
+# Copyright 2002, 2003, 2004, 2005 Dave Abrahams
+# Copyright 2002, 2005, 2006, 2007, 2010 Rene Rivera
+# Copyright 2006 Juergen Hunold
+# Copyright 2005 Toon Knapen
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Defines standard features and rules.
+
+import alias ;
+import "class" : new ;
+import errors ;
+import feature ;
+import generators ;
+import numbers ;
+import os ;
+import path ;
+import print ;
+import project ;
+import property ;
+import regex ;
+import scanner ;
+import sequence ;
+import stage ;
+import symlink ;
+import toolset ;
+import type ;
+import targets ;
+import types/register ;
+import utility ;
+import virtual-target ;
+import message ;
+import convert ;
+
+# FIXME: the following generate module import is not needed here but removing it
+# too hastly will break using code (e.g. the main Boost library Jamroot file)
+# that forgot to import the generate module before calling the generate rule.
+import generate ;
+
+
+.os-names = aix bsd cygwin darwin freebsd hpux iphone linux netbsd
+ openbsd osf qnx qnxnto sgi solaris unix unixware windows
+ elf # Not actually an OS -- used for targeting bare metal where
+ # object format is ELF. This catches both -elf and -eabi gcc
+ # targets and well as other compilers targeting ELF. It is not
+ # clear how often do we need to key of ELF specifically as opposed
+ # to other bare metal targets, but let's stick with gcc naming.
+ ;
+
+# Feature used to determine which OS we're on. New <target-os> and <host-os>
+# features should be used instead.
+local os = [ modules.peek : OS ] ;
+feature.feature os : $(os) : propagated link-incompatible ;
+
+
+# Translates from bjam current OS to the os tags used in host-os and target-os,
+# i.e. returns the running host-os.
+#
+local rule default-host-os ( )
+{
+ local host-os ;
+ if [ os.name ] in $(.os-names:U)
+ {
+ host-os = [ os.name ] ;
+ }
+ else
+ {
+ switch [ os.name ]
+ {
+ case NT : host-os = windows ;
+ case AS400 : host-os = unix ;
+ case MINGW : host-os = windows ;
+ case BSDI : host-os = bsd ;
+ case COHERENT : host-os = unix ;
+ case DRAGONFLYBSD : host-os = bsd ;
+ case IRIX : host-os = sgi ;
+ case MACOSX : host-os = darwin ;
+ case KFREEBSD : host-os = freebsd ;
+ case LINUX : host-os = linux ;
+ case SUNOS :
+ ECHO "SunOS is not a supported operating system." ;
+ ECHO "We believe last version of SunOS was released in 1992, " ;
+ ECHO "so if you get this message, something is very wrong with configuration logic. " ;
+ ECHO "Please report this as a bug. " ;
+ EXIT ;
+ case * : host-os = unix ;
+ }
+ }
+ return $(host-os:L) ;
+}
+
+
+# The two OS features define a known set of abstract OS names. The host-os is
+# the OS under which bjam is running. Even though this should really be a fixed
+# property we need to list all the values to prevent unknown value errors. Both
+# set the default value to the current OS to account for the default use case of
+# building on the target OS.
+feature.feature host-os : $(.os-names) ;
+feature.set-default host-os : [ default-host-os ] ;
+
+feature.feature target-os : $(.os-names) : propagated link-incompatible ;
+feature.set-default target-os : [ default-host-os ] ;
+
+
+feature.feature toolset : : implicit propagated symmetric ;
+feature.feature stdlib : native : propagated composite ;
+feature.feature link : shared static : propagated ;
+feature.feature runtime-link : shared static : propagated ;
+feature.feature runtime-debugging : on off : propagated ;
+feature.feature optimization : off speed space : propagated ;
+feature.feature profiling : off on : propagated ;
+feature.feature inlining : off on full : propagated ;
+feature.feature threading : single multi : propagated ;
+feature.feature rtti : on off : propagated ;
+feature.feature exception-handling : on off : propagated ;
+
+# Whether there is support for asynchronous EH (e.g. catching SEGVs).
+feature.feature asynch-exceptions : off on : propagated ;
+
+# Whether all extern "C" functions are considered nothrow by default.
+feature.feature extern-c-nothrow : off on : propagated ;
+
+feature.feature debug-symbols : on off : propagated ;
+# Controls whether the binary should be stripped -- that is have
+# everything not necessary to running removed. This option should
+# not be very often needed. Also, this feature will show up in
+# target paths of everything, not just binaries. Should fix that
+# when impelementing feature relevance.
+feature.feature strip : off on : propagated ;
+feature.feature define : : free ;
+feature.feature undef : : free ;
+feature.feature "include" : : free path ; #order-sensitive ;
+feature.feature cflags : : free ;
+feature.feature cxxflags : : free ;
+feature.feature fflags : : free ;
+feature.feature asmflags : : free ;
+feature.feature linkflags : : free ;
+feature.feature archiveflags : : free ;
+feature.feature version : : free ;
+
+# Generic, i.e. non-language specific, flags for tools.
+feature.feature flags : : free ;
+feature.feature location-prefix : : free ;
+
+
+# The following features are incidental since they have no effect on built
+# products. Not making them incidental will result in problems in corner cases,
+# e.g.:
+#
+# unit-test a : a.cpp : <use>b ;
+# lib b : a.cpp b ;
+#
+# Here, if <use> is not incidental, we would decide we have two targets for
+# a.obj with different properties and complain about it.
+#
+# Note that making a feature incidental does not mean it is ignored. It may be
+# ignored when creating a virtual target, but the rest of build process will use
+# them.
+feature.feature use : : free dependency incidental ;
+feature.feature dependency : : free dependency incidental ;
+feature.feature implicit-dependency : : free dependency incidental ;
+
+feature.feature warnings :
+ on # Enable default/"reasonable" warning level for the tool.
+ all # Enable all possible warnings issued by the tool.
+ off # Disable all warnings issued by the tool.
+ : incidental propagated ;
+
+feature.feature warnings-as-errors :
+ off # Do not fail the compilation if there are warnings.
+ on # Fail the compilation if there are warnings.
+ : incidental propagated ;
+
+# Feature that allows us to configure the maximal template instantiation depth
+# level allowed by a C++ compiler. Applies only to C++ toolsets whose compilers
+# actually support this configuration setting.
+#
+# Note that Boost Build currently does not allow defining features that take any
+# positive integral value as a parameter, which is what we need here, so we just
+# define some of the values here and leave it up to the user to extend this set
+# as he needs using the feature.extend rule.
+#
+# TODO: This should be upgraded as soon as Boost Build adds support for custom
+# validated feature values or at least features allowing any positive integral
+# value. See related Boost Build related trac ticket #194.
+#
+feature.feature c++-template-depth
+ :
+ [ numbers.range 64 1024 : 64 ]
+ [ numbers.range 20 1000 : 10 ]
+ # Maximum template instantiation depth guaranteed for ANSI/ISO C++
+ # conforming programs.
+ 17
+ :
+ incidental optional propagated ;
+
+feature.feature source : : free dependency incidental ;
+feature.feature library : : free dependency incidental ;
+feature.feature file : : free dependency incidental ;
+feature.feature find-shared-library : : free ; #order-sensitive ;
+feature.feature find-static-library : : free ; #order-sensitive ;
+feature.feature library-path : : free path ; #order-sensitive ;
+
+# Internal feature.
+feature.feature library-file : : free dependency ;
+
+feature.feature name : : free ;
+feature.feature tag : : free ;
+feature.feature search : : free path ; #order-sensitive ;
+feature.feature location : : free path ;
+feature.feature dll-path : : free path ;
+feature.feature hardcode-dll-paths : true false : incidental ;
+
+
+# An internal feature that holds the paths of all dependency shared libraries.
+# On Windows, it is needed so that we can add all those paths to PATH when
+# running applications. On Linux, it is needed to add proper -rpath-link command
+# line options.
+feature.feature xdll-path : : free path ;
+
+# Provides means to specify def-file for windows DLLs.
+feature.feature def-file : : free dependency ;
+
+feature.feature suppress-import-lib : false true : incidental ;
+
+# Internal feature used to store the name of a bjam action to call when building
+# a target.
+feature.feature action : : free ;
+
+# This feature is used to allow specific generators to run. For example, QT
+# tools can only be invoked when QT library is used. In that case, <allow>qt
+# will be in usage requirement of the library.
+feature.feature allow : : free ;
+
+# The addressing model to generate code for. Currently a limited set only
+# specifying the bit size of pointers.
+feature.feature address-model : 16 32 64 32_64 : propagated optional ;
+
+# Type of CPU architecture to compile for.
+feature.feature architecture :
+ # x86 and x86-64
+ x86
+
+ # ia64
+ ia64
+
+ # Sparc
+ sparc
+
+ # RS/6000 & PowerPC
+ power
+
+ # MIPS/SGI
+ mips1 mips2 mips3 mips4 mips32 mips32r2 mips64
+
+ # HP/PA-RISC
+ parisc
+
+ # Advanced RISC Machines
+ arm
+
+ # Combined architectures for platforms/toolsets that support building for
+ # multiple architectures at once. "combined" would be the default multi-arch
+ # for the toolset.
+ combined
+ combined-x86-power
+
+ : propagated optional ;
+
+# The specific instruction set in an architecture to compile.
+feature.feature instruction-set :
+ # x86 and x86-64
+ native i386 i486 i586 i686 pentium pentium-mmx pentiumpro pentium2 pentium3
+ pentium3m pentium-m pentium4 pentium4m prescott nocona core2 conroe conroe-xe
+ conroe-l allendale mermon mermon-xe kentsfield kentsfield-xe penryn wolfdale
+ yorksfield nehalem k6 k6-2 k6-3 athlon athlon-tbird athlon-4 athlon-xp
+ athlon-mp k8 opteron athlon64 athlon-fx winchip-c6 winchip2 c3 c3-2
+
+ # ia64
+ itanium itanium1 merced itanium2 mckinley
+
+ # Sparc
+ v7 cypress v8 supersparc sparclite hypersparc sparclite86x f930 f934
+ sparclet tsc701 v9 ultrasparc ultrasparc3
+
+ # RS/6000 & PowerPC
+ 401 403 405 405fp 440 440fp 505 601 602 603 603e 604 604e 620 630 740 7400
+ 7450 750 801 821 823 860 970 8540 power-common ec603e g3 g4 g5 power power2
+ power3 power4 power5 powerpc powerpc64 rios rios1 rsc rios2 rs64a
+
+ # MIPS
+ 4kc 4kp 5kc 20kc m4k r2000 r3000 r3900 r4000 r4100 r4300 r4400 r4600 r4650
+ r6000 r8000 rm7000 rm9000 orion sb1 vr4100 vr4111 vr4120 vr4130 vr4300
+ vr5000 vr5400 vr5500
+
+ # HP/PA-RISC
+ 700 7100 7100lc 7200 7300 8000
+
+ # Advanced RISC Machines
+ armv2 armv2a armv3 armv3m armv4 armv4t armv5 armv5t armv5te armv6 armv6j iwmmxt ep9312
+
+ : propagated optional ;
+
+# Used to select a specific variant of C++ ABI if the compiler supports several.
+feature.feature c++abi : : propagated optional ;
+
+feature.feature conditional : : incidental free ;
+
+# The value of 'no' prevents building of a target.
+feature.feature build : yes no : optional ;
+
+# Windows-specific features
+
+feature.feature user-interface : console gui wince native auto ;
+
+feature.feature variant : : implicit composite propagated symmetric ;
+
+
+# Declares a new variant.
+#
+# First determines explicit properties for this variant, by refining parents'
+# explicit properties with the passed explicit properties. The result is
+# remembered and will be used if this variant is used as parent.
+#
+# Second, determines the full property set for this variant by adding to the
+# explicit properties default values for all missing non-symmetric properties.
+#
+# Lastly, makes appropriate value of 'variant' property expand to the full
+# property set.
+#
+rule variant ( name # Name of the variant
+ : parents-or-properties * # Specifies parent variants, if
+ # 'explicit-properties' are given, and
+ # explicit-properties or parents otherwise.
+ : explicit-properties * # Explicit properties.
+ )
+{
+ local parents ;
+ if ! $(explicit-properties)
+ {
+ if $(parents-or-properties[1]:G)
+ {
+ explicit-properties = $(parents-or-properties) ;
+ }
+ else
+ {
+ parents = $(parents-or-properties) ;
+ }
+ }
+ else
+ {
+ parents = $(parents-or-properties) ;
+ }
+
+ # The problem is that we have to check for conflicts between base variants.
+ if $(parents[2])
+ {
+ errors.error "multiple base variants are not yet supported" ;
+ }
+
+ local inherited ;
+ # Add explicitly specified properties for parents.
+ for local p in $(parents)
+ {
+ # TODO: This check may be made stricter.
+ if ! [ feature.is-implicit-value $(p) ]
+ {
+ errors.error "Invalid base variant" $(p) ;
+ }
+
+ inherited += $(.explicit-properties.$(p)) ;
+ }
+ property.validate $(explicit-properties) ;
+ explicit-properties = [ property.refine $(inherited)
+ : $(explicit-properties) ] ;
+
+ # Record explicitly specified properties for this variant. We do this after
+ # inheriting parents' properties so they affect other variants derived from
+ # this one.
+ .explicit-properties.$(name) = $(explicit-properties) ;
+
+ feature.extend variant : $(name) ;
+ feature.compose <variant>$(name) : $(explicit-properties) ;
+}
+IMPORT $(__name__) : variant : : variant ;
+
+
+variant debug : <optimization>off <debug-symbols>on <inlining>off
+ <runtime-debugging>on ;
+variant release : <optimization>speed <debug-symbols>off <inlining>full
+ <runtime-debugging>off <define>NDEBUG ;
+variant profile : release : <profiling>on <debug-symbols>on ;
+
+
+class searched-lib-target : abstract-file-target
+{
+ rule __init__ ( name
+ : project
+ : shared ?
+ : search *
+ : action
+ )
+ {
+ abstract-file-target.__init__ $(name) : SEARCHED_LIB : $(project)
+ : $(action) : ;
+
+ self.shared = $(shared) ;
+ self.search = $(search) ;
+ }
+
+ rule shared ( )
+ {
+ return $(self.shared) ;
+ }
+
+ rule search ( )
+ {
+ return $(self.search) ;
+ }
+
+ rule actualize-location ( target )
+ {
+ NOTFILE $(target) ;
+ }
+
+ rule path ( )
+ {
+ }
+}
+
+
+# The generator class for libraries (target type LIB). Depending on properties
+# it will request building of the appropriate specific library type --
+# -- SHARED_LIB, STATIC_LIB or SHARED_LIB.
+#
+class lib-generator : generator
+{
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * )
+ {
+ # The lib generator is composing, and can be only invoked with an
+ # explicit name. This check is present in generator.run (and so in
+ # builtin.linking-generator) but duplicated here to avoid doing extra
+ # work.
+ if $(name)
+ {
+ local properties = [ $(property-set).raw ] ;
+ # Determine the needed target type.
+ local actual-type ;
+ # <source>files can be generated by <conditional>@rule feature
+ # in which case we do not consider it a SEARCHED_LIB type.
+ if ! <source> in $(properties:G) &&
+ ( <search> in $(properties:G) || <name> in $(properties:G) )
+ {
+ actual-type = SEARCHED_LIB ;
+ }
+ else if <file> in $(properties:G)
+ {
+ actual-type = LIB ;
+ }
+ else if <link>shared in $(properties)
+ {
+ actual-type = SHARED_LIB ;
+ }
+ else
+ {
+ actual-type = STATIC_LIB ;
+ }
+ property-set = [ $(property-set).add-raw <main-target-type>LIB ] ;
+ # Construct the target.
+ return [ generators.construct $(project) $(name) : $(actual-type)
+ : $(property-set) : $(sources) ] ;
+ }
+ }
+
+ rule viable-source-types ( )
+ {
+ return * ;
+ }
+}
+
+
+generators.register [ new lib-generator builtin.lib-generator : : LIB ] ;
+
+
+# The implementation of the 'lib' rule. Beyond standard syntax that rule allows
+# simplified: "lib a b c ;".
+#
+rule lib ( names + : sources * : requirements * : default-build * :
+ usage-requirements * )
+{
+ if $(names[2])
+ {
+ if <name> in $(requirements:G)
+ {
+ errors.user-error "When several names are given to the 'lib' rule" :
+ "it is not allowed to specify the <name> feature." ;
+ }
+ if $(sources)
+ {
+ errors.user-error "When several names are given to the 'lib' rule" :
+ "it is not allowed to specify sources." ;
+ }
+ }
+
+ # This is a circular module dependency so it must be imported here.
+ import targets ;
+
+ local project = [ project.current ] ;
+ local result ;
+
+ for local name in $(names)
+ {
+ local r = $(requirements) ;
+ # Support " lib a ; " and " lib a b c ; " syntax.
+ if ! $(sources) && ! <name> in $(requirements:G)
+ && ! <file> in $(requirements:G)
+ {
+ r += <name>$(name) ;
+ }
+ result += [ targets.main-target-alternative
+ [ new typed-target $(name) : $(project) : LIB
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(r) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
+ ] ] ;
+ }
+ return $(result) ;
+}
+IMPORT $(__name__) : lib : : lib ;
+
+
+class searched-lib-generator : generator
+{
+ import property-set ;
+
+ rule __init__ ( )
+ {
+ # The requirements cause the generators to be tried *only* when we're
+ # building a lib target with a 'search' feature. This seems ugly --- all
+ # we want is to make sure searched-lib-generator is not invoked deep
+ # inside transformation search to produce intermediate targets.
+ generator.__init__ searched-lib-generator : : SEARCHED_LIB ;
+ }
+
+ rule run ( project name ? : property-set : sources * )
+ {
+ if $(name)
+ {
+ # If 'name' is empty, it means we have not been called to build a
+ # top-level target. In this case, we just fail immediately, because
+ # searched-lib-generator cannot be used to produce intermediate
+ # targets.
+
+ local properties = [ $(property-set).raw ] ;
+ local shared ;
+ if <link>shared in $(properties)
+ {
+ shared = true ;
+ }
+
+ local search = [ feature.get-values <search> : $(properties) ] ;
+
+ local a = [ new null-action $(property-set) ] ;
+ local lib-name = [ feature.get-values <name> : $(properties) ] ;
+ lib-name ?= $(name) ;
+ local t = [ new searched-lib-target $(lib-name) : $(project)
+ : $(shared) : $(search) : $(a) ] ;
+ # We return sources for a simple reason. If there is
+ # lib png : z : <name>png ;
+ # the 'z' target should be returned, so that apps linking to 'png'
+ # will link to 'z', too.
+ return [ property-set.create <xdll-path>$(search) ]
+ [ virtual-target.register $(t) ] $(sources) ;
+ }
+ }
+}
+
+generators.register [ new searched-lib-generator ] ;
+
+
+class prebuilt-lib-generator : generator
+{
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * )
+ {
+ local f = [ $(property-set).get <file> ] ;
+ return $(f) $(sources) ;
+ }
+}
+
+generators.register
+ [ new prebuilt-lib-generator builtin.prebuilt : : LIB : <file> ] ;
+
+generators.override builtin.prebuilt : builtin.lib-generator ;
+
+class preprocessed-target-class : basic-target
+{
+ import generators ;
+ rule construct ( name : sources * : property-set )
+ {
+ local result = [ generators.construct [ project ]
+ $(name) : PREPROCESSED_CPP : $(property-set) : $(sources) ] ;
+ if ! $(result)
+ {
+ result = [ generators.construct [ project ]
+ $(name) : PREPROCESSED_C : $(property-set) : $(sources) ] ;
+ }
+ if ! $(result)
+ {
+ local s ;
+ for x in $(sources)
+ {
+ s += [ $(x).name ] ;
+ }
+ local p = [ project ] ;
+ errors.user-error
+ "In project" [ $(p).name ] :
+ "Could not construct preprocessed file \"$(name)\" from $(s:J=, )." ;
+ }
+ return $(result) ;
+ }
+}
+
+rule preprocessed ( name : sources * : requirements * : default-build * :
+ usage-requirements * )
+{
+ local project = [ project.current ] ;
+ return [ targets.main-target-alternative
+ [ new preprocessed-target-class $(name) : $(project)
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(r) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
+ ] ] ;
+}
+
+IMPORT $(__name__) : preprocessed : : preprocessed ;
+
+class compile-action : action
+{
+ import sequence ;
+
+ rule __init__ ( targets * : sources * : action-name : properties * )
+ {
+ action.__init__ $(targets) : $(sources) : $(action-name) : $(properties) ;
+ }
+
+ # For all virtual targets for the same dependency graph as self, i.e. which
+ # belong to the same main target, add their directories to the include path.
+ #
+ rule adjust-properties ( property-set )
+ {
+ local s = [ $(self.targets[1]).creating-subvariant ] ;
+ return [ $(property-set).add-raw
+ [ $(s).implicit-includes "include" : H ] ] ;
+ }
+}
+
+
+# Declare a special compiler generator. The only thing it does is changing the
+# type used to represent 'action' in the constructed dependency graph to
+# 'compile-action'. That class in turn adds additional include paths to handle
+# cases when a source file includes headers which are generated themselves.
+#
+class C-compiling-generator : generator
+{
+ rule __init__ ( id : source-types + : target-types + : requirements *
+ : optional-properties * )
+ {
+ generator.__init__ $(id) : $(source-types) : $(target-types) :
+ $(requirements) : $(optional-properties) ;
+ }
+
+ rule action-class ( )
+ {
+ return compile-action ;
+ }
+}
+
+
+rule register-c-compiler ( id : source-types + : target-types + : requirements *
+ : optional-properties * )
+{
+ generators.register [ new C-compiling-generator $(id) : $(source-types) :
+ $(target-types) : $(requirements) : $(optional-properties) ] ;
+}
+
+# FIXME: this is ugly, should find a better way (we would like client code to
+# register all generators as "generators.some-rule" instead of
+# "some-module.some-rule".)
+#
+IMPORT $(__name__) : register-c-compiler : : generators.register-c-compiler ;
+
+
+# The generator class for handling EXE and SHARED_LIB creation.
+#
+class linking-generator : generator
+{
+ import path ;
+ import project ;
+ import property-set ;
+ import type ;
+
+ rule __init__ ( id
+ composing ? : # The generator will be composing if a non-empty
+ # string is passed or the parameter is not given. To
+ # make the generator non-composing, pass an empty
+ # string ("").
+ source-types + :
+ target-types + :
+ requirements * )
+ {
+ composing ?= true ;
+ generator.__init__ $(id) $(composing) : $(source-types)
+ : $(target-types) : $(requirements) ;
+ }
+
+ rule run ( project name ? : property-set : sources + )
+ {
+ sources += [ $(property-set).get <library> ] ;
+
+ # Add <library-path> properties for all searched libraries.
+ local extra ;
+ for local s in $(sources)
+ {
+ if [ $(s).type ] = SEARCHED_LIB
+ {
+ local search = [ $(s).search ] ;
+ extra += <library-path>$(search) ;
+ }
+ }
+
+ # It is possible that sources include shared libraries that did not came
+ # from 'lib' targets, e.g. .so files specified as sources. In this case
+ # we have to add extra dll-path properties and propagate extra xdll-path
+ # properties so that application linking to us will get xdll-path to
+ # those libraries.
+ local extra-xdll-paths ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] SHARED_LIB ] && ! [ $(s).action ]
+ {
+ # Unfortunately, we do not have a good way to find the path to a
+ # file, so use this nasty approach.
+ #
+ # TODO: This needs to be done better. One thing that is really
+ # broken with this is that it does not work correctly with
+ # projects having multiple source locations.
+ local p = [ $(s).project ] ;
+ local location = [ path.root [ $(s).name ]
+ [ $(p).get source-location ] ] ;
+ extra-xdll-paths += [ path.parent $(location) ] ;
+ }
+ }
+
+ # Hardcode DLL paths only when linking executables.
+ # Pros: do not need to relink libraries when installing.
+ # Cons: "standalone" libraries (plugins, python extensions) can not
+ # hardcode paths to dependent libraries.
+ if [ $(property-set).get <hardcode-dll-paths> ] = true
+ && [ type.is-derived $(self.target-types[1]) EXE ]
+ {
+ local xdll-path = [ $(property-set).get <xdll-path> ] ;
+ extra += <dll-path>$(xdll-path) <dll-path>$(extra-xdll-paths) ;
+ }
+
+ if $(extra)
+ {
+ property-set = [ $(property-set).add-raw $(extra) ] ;
+ }
+
+ local result = [ generator.run $(project) $(name) : $(property-set)
+ : $(sources) ] ;
+
+ local ur ;
+ if $(result)
+ {
+ ur = [ extra-usage-requirements $(result) : $(property-set) ] ;
+ ur = [ $(ur).add
+ [ property-set.create <xdll-path>$(extra-xdll-paths) ] ] ;
+ }
+ return $(ur) $(result) ;
+ }
+
+ rule extra-usage-requirements ( created-targets * : property-set )
+ {
+ local result = [ property-set.empty ] ;
+ local extra ;
+
+ # Add appropricate <xdll-path> usage requirements.
+ local raw = [ $(property-set).raw ] ;
+ if <link>shared in $(raw)
+ {
+ local paths ;
+ local pwd = [ path.pwd ] ;
+ for local t in $(created-targets)
+ {
+ if [ type.is-derived [ $(t).type ] SHARED_LIB ]
+ {
+ paths += [ path.root [ path.make [ $(t).path ] ] $(pwd) ] ;
+ }
+ }
+ extra += $(paths:G=<xdll-path>) ;
+ }
+
+ # We need to pass <xdll-path> features that we've got from sources,
+ # because if a shared library is built, exe using it needs to know paths
+ # to other shared libraries this one depends on in order to be able to
+ # find them all at runtime.
+
+ # Just pass all features in property-set, it is theorically possible
+ # that we will propagate <xdll-path> features explicitly specified by
+ # the user, but then the user is to blaim for using an internal feature.
+ local values = [ $(property-set).get <xdll-path> ] ;
+ extra += $(values:G=<xdll-path>) ;
+
+ if $(extra)
+ {
+ result = [ property-set.create $(extra) ] ;
+ }
+ return $(result) ;
+ }
+
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ local sources2 ; # Sources to pass to inherited rule.
+ local properties2 ; # Properties to pass to inherited rule.
+ local libraries ; # Library sources.
+
+ # Searched libraries are not passed as arguments to the linker but via
+ # some option. So, we pass them to the action using a property.
+ properties2 = [ $(property-set).raw ] ;
+ local fsa ;
+ local fst ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] SEARCHED_LIB ]
+ {
+ local name = [ $(s).name ] ;
+ if [ $(s).shared ]
+ {
+ fsa += $(name) ;
+ }
+ else
+ {
+ fst += $(name) ;
+ }
+ }
+ else
+ {
+ sources2 += $(s) ;
+ }
+ }
+ properties2 += <find-shared-library>$(fsa:J=&&)
+ <find-static-library>$(fst:J=&&) ;
+
+ return [ generator.generated-targets $(sources2)
+ : [ property-set.create $(properties2) ] : $(project) $(name) ] ;
+ }
+}
+
+
+rule register-linker ( id composing ? : source-types + : target-types +
+ : requirements * )
+{
+ generators.register [ new linking-generator $(id) $(composing)
+ : $(source-types) : $(target-types) : $(requirements) ] ;
+}
+
+
+# The generator class for handling STATIC_LIB creation.
+#
+class archive-generator : generator
+{
+ import property-set ;
+
+ rule __init__ ( id composing ? : source-types + : target-types +
+ : requirements * )
+ {
+ composing ?= true ;
+ generator.__init__ $(id) $(composing) : $(source-types)
+ : $(target-types) : $(requirements) ;
+ }
+
+ rule run ( project name ? : property-set : sources + )
+ {
+ sources += [ $(property-set).get <library> ] ;
+
+ local result = [ generator.run $(project) $(name) : $(property-set)
+ : $(sources) ] ;
+
+ # For static linking, if we get a library in source, we can not directly
+ # link to it so we need to cause our dependencies to link to that
+ # library. There are two approaches:
+ # - adding the library to the list of returned targets.
+ # - using the <library> usage requirements.
+ # The problem with the first is:
+ #
+ # lib a1 : : <file>liba1.a ;
+ # lib a2 : a2.cpp a1 : <link>static ;
+ # install dist : a2 ;
+ #
+ # here we will try to install 'a1', even though it is not necessary in
+ # the general case. With the second approach, even indirect dependants
+ # will link to the library, but it should not cause any harm. So, return
+ # all LIB sources together with created targets, so that dependants link
+ # to them.
+ local usage-requirements ;
+ if [ $(property-set).get <link> ] = static
+ {
+ for local t in $(sources)
+ {
+ if [ type.is-derived [ $(t).type ] LIB ]
+ {
+ usage-requirements += <library>$(t) ;
+ }
+ }
+ }
+
+ usage-requirements = [ property-set.create $(usage-requirements) ] ;
+
+ return $(usage-requirements) $(result) ;
+ }
+}
+
+
+rule register-archiver ( id composing ? : source-types + : target-types +
+ : requirements * )
+{
+ generators.register [ new archive-generator $(id) $(composing)
+ : $(source-types) : $(target-types) : $(requirements) ] ;
+}
+
+
+# Generator that accepts everything and produces nothing. Useful as a general
+# fallback for toolset-specific actions like PCH generation.
+#
+class dummy-generator : generator
+{
+ import property-set ;
+
+ rule run ( project name ? : property-set : sources + )
+ {
+ return [ property-set.empty ] ;
+ }
+}
+
+IMPORT $(__name__) : register-linker register-archiver
+ : : generators.register-linker generators.register-archiver ;
diff --git a/tools/build/v2/tools/builtin.py b/tools/build/v2/tools/builtin.py
new file mode 100644
index 0000000000..31a7bffeef
--- /dev/null
+++ b/tools/build/v2/tools/builtin.py
@@ -0,0 +1,718 @@
+# Status: minor updates by Steven Watanabe to make gcc work
+#
+# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+""" Defines standard features and rules.
+"""
+
+import b2.build.targets as targets
+
+import sys
+from b2.build import feature, property, virtual_target, generators, type, property_set, scanner
+from b2.util.utility import *
+from b2.util import path, regex, bjam_signature
+import b2.tools.types
+from b2.manager import get_manager
+
+
+# Records explicit properties for a variant.
+# The key is the variant name.
+__variant_explicit_properties = {}
+
+def reset ():
+ """ Clear the module state. This is mainly for testing purposes.
+ """
+ global __variant_explicit_properties
+
+ __variant_explicit_properties = {}
+
+@bjam_signature((["name"], ["parents_or_properties", "*"], ["explicit_properties", "*"]))
+def variant (name, parents_or_properties, explicit_properties = []):
+ """ Declares a new variant.
+ First determines explicit properties for this variant, by
+ refining parents' explicit properties with the passed explicit
+ properties. The result is remembered and will be used if
+ this variant is used as parent.
+
+ Second, determines the full property set for this variant by
+ adding to the explicit properties default values for all properties
+ which neither present nor are symmetric.
+
+ Lastly, makes appropriate value of 'variant' property expand
+ to the full property set.
+ name: Name of the variant
+ parents_or_properties: Specifies parent variants, if
+ 'explicit_properties' are given,
+ and explicit_properties otherwise.
+ explicit_properties: Explicit properties.
+ """
+ parents = []
+ if not explicit_properties:
+ explicit_properties = parents_or_properties
+ else:
+ parents = parents_or_properties
+
+ inherited = property_set.empty()
+ if parents:
+
+ # If we allow multiple parents, we'd have to to check for conflicts
+ # between base variants, and there was no demand for so to bother.
+ if len (parents) > 1:
+ raise BaseException ("Multiple base variants are not yet supported")
+
+ p = parents[0]
+ # TODO: the check may be stricter
+ if not feature.is_implicit_value (p):
+ raise BaseException ("Invalid base varaint '%s'" % p)
+
+ inherited = __variant_explicit_properties[p]
+
+ explicit_properties = property_set.create_with_validation(explicit_properties)
+ explicit_properties = inherited.refine(explicit_properties)
+
+ # Record explicitly specified properties for this variant
+ # We do this after inheriting parents' properties, so that
+ # they affect other variants, derived from this one.
+ __variant_explicit_properties[name] = explicit_properties
+
+ feature.extend('variant', [name])
+ feature.compose ("<variant>" + name, explicit_properties.all())
+
+__os_names = """
+ amiga aix bsd cygwin darwin dos emx freebsd hpux iphone linux netbsd
+ openbsd osf qnx qnxnto sgi solaris sun sunos svr4 sysv ultrix unix unixware
+ vms windows
+""".split()
+
+# Translates from bjam current OS to the os tags used in host-os and target-os,
+# i.e. returns the running host-os.
+#
+def default_host_os():
+ host_os = os_name()
+ if host_os not in (x.upper() for x in __os_names):
+ if host_os == 'NT': host_os = 'windows'
+ elif host_os == 'AS400': host_os = 'unix'
+ elif host_os == 'MINGW': host_os = 'windows'
+ elif host_os == 'BSDI': host_os = 'bsd'
+ elif host_os == 'COHERENT': host_os = 'unix'
+ elif host_os == 'DRAGONFLYBSD': host_os = 'bsd'
+ elif host_os == 'IRIX': host_os = 'sgi'
+ elif host_os == 'MACOSX': host_os = 'darwin'
+ elif host_os == 'KFREEBSD': host_os = 'freebsd'
+ elif host_os == 'LINUX': host_os = 'linux'
+ else: host_os = 'unix'
+ return host_os.lower()
+
+def register_globals ():
+ """ Registers all features and variants declared by this module.
+ """
+
+ # This feature is used to determine which OS we're on.
+ # In future, this may become <target-os> and <host-os>
+ # TODO: check this. Compatibility with bjam names? Subfeature for version?
+ os = sys.platform
+ feature.feature ('os', [os], ['propagated', 'link-incompatible'])
+
+
+ # The two OS features define a known set of abstract OS names. The host-os is
+ # the OS under which bjam is running. Even though this should really be a fixed
+ # property we need to list all the values to prevent unknown value errors. Both
+ # set the default value to the current OS to account for the default use case of
+ # building on the target OS.
+ feature.feature('host-os', __os_names)
+ feature.set_default('host-os', default_host_os())
+
+ feature.feature('target-os', __os_names, ['propagated', 'link-incompatible'])
+ feature.set_default('target-os', default_host_os())
+
+ feature.feature ('toolset', [], ['implicit', 'propagated' ,'symmetric'])
+
+ feature.feature ('stdlib', ['native'], ['propagated', 'composite'])
+
+ feature.feature ('link', ['shared', 'static'], ['propagated'])
+ feature.feature ('runtime-link', ['shared', 'static'], ['propagated'])
+ feature.feature ('runtime-debugging', ['on', 'off'], ['propagated'])
+
+
+ feature.feature ('optimization', ['off', 'speed', 'space'], ['propagated'])
+ feature.feature ('profiling', ['off', 'on'], ['propagated'])
+ feature.feature ('inlining', ['off', 'on', 'full'], ['propagated'])
+
+ feature.feature ('threading', ['single', 'multi'], ['propagated'])
+ feature.feature ('rtti', ['on', 'off'], ['propagated'])
+ feature.feature ('exception-handling', ['on', 'off'], ['propagated'])
+ feature.feature ('debug-symbols', ['on', 'off'], ['propagated'])
+ feature.feature ('define', [], ['free'])
+ feature.feature ('include', [], ['free', 'path']) #order-sensitive
+ feature.feature ('cflags', [], ['free'])
+ feature.feature ('cxxflags', [], ['free'])
+ feature.feature ('linkflags', [], ['free'])
+ feature.feature ('archiveflags', [], ['free'])
+ feature.feature ('version', [], ['free'])
+
+ feature.feature ('location-prefix', [], ['free'])
+
+ feature.feature ('action', [], ['free'])
+
+
+ # The following features are incidental, since
+ # in themself they have no effect on build products.
+ # Not making them incidental will result in problems in corner
+ # cases, for example:
+ #
+ # unit-test a : a.cpp : <use>b ;
+ # lib b : a.cpp b ;
+ #
+ # Here, if <use> is not incidental, we'll decide we have two
+ # targets for a.obj with different properties, and will complain.
+ #
+ # Note that making feature incidental does not mean it's ignored. It may
+ # be ignored when creating the virtual target, but the rest of build process
+ # will use them.
+ feature.feature ('use', [], ['free', 'dependency', 'incidental'])
+ feature.feature ('dependency', [], ['free', 'dependency', 'incidental'])
+ feature.feature ('implicit-dependency', [], ['free', 'dependency', 'incidental'])
+
+ feature.feature('warnings', [
+ 'on', # Enable default/"reasonable" warning level for the tool.
+ 'all', # Enable all possible warnings issued by the tool.
+ 'off'], # Disable all warnings issued by the tool.
+ ['incidental', 'propagated'])
+
+ feature.feature('warnings-as-errors', [
+ 'off', # Do not fail the compilation if there are warnings.
+ 'on'], # Fail the compilation if there are warnings.
+ ['incidental', 'propagated'])
+
+ feature.feature ('source', [], ['free', 'dependency', 'incidental'])
+ feature.feature ('library', [], ['free', 'dependency', 'incidental'])
+ feature.feature ('file', [], ['free', 'dependency', 'incidental'])
+ feature.feature ('find-shared-library', [], ['free']) #order-sensitive ;
+ feature.feature ('find-static-library', [], ['free']) #order-sensitive ;
+ feature.feature ('library-path', [], ['free', 'path']) #order-sensitive ;
+ # Internal feature.
+ feature.feature ('library-file', [], ['free', 'dependency'])
+
+ feature.feature ('name', [], ['free'])
+ feature.feature ('tag', [], ['free'])
+ feature.feature ('search', [], ['free', 'path']) #order-sensitive ;
+ feature.feature ('location', [], ['free', 'path'])
+
+ feature.feature ('dll-path', [], ['free', 'path'])
+ feature.feature ('hardcode-dll-paths', ['true', 'false'], ['incidental'])
+
+
+ # This is internal feature which holds the paths of all dependency
+ # dynamic libraries. On Windows, it's needed so that we can all
+ # those paths to PATH, when running applications.
+ # On Linux, it's needed to add proper -rpath-link command line options.
+ feature.feature ('xdll-path', [], ['free', 'path'])
+
+ #provides means to specify def-file for windows dlls.
+ feature.feature ('def-file', [], ['free', 'dependency'])
+
+ # This feature is used to allow specific generators to run.
+ # For example, QT tools can only be invoked when QT library
+ # is used. In that case, <allow>qt will be in usage requirement
+ # of the library.
+ feature.feature ('allow', [], ['free'])
+
+ # The addressing model to generate code for. Currently a limited set only
+ # specifying the bit size of pointers.
+ feature.feature('address-model', ['16', '32', '64'], ['propagated', 'optional'])
+
+ # Type of CPU architecture to compile for.
+ feature.feature('architecture', [
+ # x86 and x86-64
+ 'x86',
+
+ # ia64
+ 'ia64',
+
+ # Sparc
+ 'sparc',
+
+ # RS/6000 & PowerPC
+ 'power',
+
+ # MIPS/SGI
+ 'mips1', 'mips2', 'mips3', 'mips4', 'mips32', 'mips32r2', 'mips64',
+
+ # HP/PA-RISC
+ 'parisc',
+
+ # Advanced RISC Machines
+ 'arm',
+
+ # Combined architectures for platforms/toolsets that support building for
+ # multiple architectures at once. "combined" would be the default multi-arch
+ # for the toolset.
+ 'combined',
+ 'combined-x86-power'],
+
+ ['propagated', 'optional'])
+
+ # The specific instruction set in an architecture to compile.
+ feature.feature('instruction-set', [
+ # x86 and x86-64
+ 'i386', 'i486', 'i586', 'i686', 'pentium', 'pentium-mmx', 'pentiumpro', 'pentium2', 'pentium3',
+ 'pentium3m', 'pentium-m', 'pentium4', 'pentium4m', 'prescott', 'nocona', 'conroe', 'conroe-xe',
+ 'conroe-l', 'allendale', 'mermon', 'mermon-xe', 'kentsfield', 'kentsfield-xe', 'penryn', 'wolfdale',
+ 'yorksfield', 'nehalem', 'k6', 'k6-2', 'k6-3', 'athlon', 'athlon-tbird', 'athlon-4', 'athlon-xp',
+ 'athlon-mp', 'k8', 'opteron', 'athlon64', 'athlon-fx', 'winchip-c6', 'winchip2', 'c3', 'c3-2',
+
+ # ia64
+ 'itanium', 'itanium1', 'merced', 'itanium2', 'mckinley',
+
+ # Sparc
+ 'v7', 'cypress', 'v8', 'supersparc', 'sparclite', 'hypersparc', 'sparclite86x', 'f930', 'f934',
+ 'sparclet', 'tsc701', 'v9', 'ultrasparc', 'ultrasparc3',
+
+ # RS/6000 & PowerPC
+ '401', '403', '405', '405fp', '440', '440fp', '505', '601', '602',
+ '603', '603e', '604', '604e', '620', '630', '740', '7400',
+ '7450', '750', '801', '821', '823', '860', '970', '8540',
+ 'power-common', 'ec603e', 'g3', 'g4', 'g5', 'power', 'power2',
+ 'power3', 'power4', 'power5', 'powerpc', 'powerpc64', 'rios',
+ 'rios1', 'rsc', 'rios2', 'rs64a',
+
+ # MIPS
+ '4kc', '4kp', '5kc', '20kc', 'm4k', 'r2000', 'r3000', 'r3900', 'r4000',
+ 'r4100', 'r4300', 'r4400', 'r4600', 'r4650',
+ 'r6000', 'r8000', 'rm7000', 'rm9000', 'orion', 'sb1', 'vr4100',
+ 'vr4111', 'vr4120', 'vr4130', 'vr4300',
+ 'vr5000', 'vr5400', 'vr5500',
+
+ # HP/PA-RISC
+ '700', '7100', '7100lc', '7200', '7300', '8000',
+
+ # Advanced RISC Machines
+ 'armv2', 'armv2a', 'armv3', 'armv3m', 'armv4', 'armv4t', 'armv5',
+ 'armv5t', 'armv5te', 'armv6', 'armv6j', 'iwmmxt', 'ep9312'],
+
+ ['propagated', 'optional'])
+
+ feature.feature('conditional', [], ['incidental', 'free'])
+
+ # The value of 'no' prevents building of a target.
+ feature.feature('build', ['yes', 'no'], ['optional'])
+
+ # Windows-specific features
+ feature.feature ('user-interface', ['console', 'gui', 'wince', 'native', 'auto'], [])
+ feature.feature ('variant', [], ['implicit', 'composite', 'propagated', 'symmetric'])
+
+
+ variant ('debug', ['<optimization>off', '<debug-symbols>on', '<inlining>off', '<runtime-debugging>on'])
+ variant ('release', ['<optimization>speed', '<debug-symbols>off', '<inlining>full',
+ '<runtime-debugging>off', '<define>NDEBUG'])
+ variant ('profile', ['release'], ['<profiling>on', '<debug-symbols>on'])
+
+ type.register ('H', ['h'])
+ type.register ('HPP', ['hpp'], 'H')
+ type.register ('C', ['c'])
+
+
+reset ()
+register_globals ()
+
+class SearchedLibTarget (virtual_target.AbstractFileTarget):
+ def __init__ (self, name, project, shared, real_name, search, action):
+ virtual_target.AbstractFileTarget.__init__ (self, name, 'SEARCHED_LIB', project, action)
+
+ self.shared_ = shared
+ self.real_name_ = real_name
+ if not self.real_name_:
+ self.real_name_ = name
+ self.search_ = search
+
+ def shared (self):
+ return self.shared_
+
+ def real_name (self):
+ return self.real_name_
+
+ def search (self):
+ return self.search_
+
+ def actualize_location (self, target):
+ bjam.call("NOTFILE", target)
+
+ def path (self):
+ #FIXME: several functions rely on this not being None
+ return ""
+
+
+class CScanner (scanner.Scanner):
+ def __init__ (self, includes):
+ scanner.Scanner.__init__ (self)
+
+ self.includes_ = includes
+
+ def pattern (self):
+ return r'#[ \t]*include[ ]*(<(.*)>|"(.*)")'
+
+ def process (self, target, matches, binding):
+
+ angle = regex.transform (matches, "<(.*)>")
+ quoted = regex.transform (matches, '"(.*)"')
+
+ g = str(id(self))
+ b = os.path.normpath(os.path.dirname(binding[0]))
+
+ # Attach binding of including file to included targets.
+ # When target is directly created from virtual target
+ # this extra information is unnecessary. But in other
+ # cases, it allows to distinguish between two headers of the
+ # same name included from different places.
+ # We don't need this extra information for angle includes,
+ # since they should not depend on including file (we can't
+ # get literal "." in include path).
+ g2 = g + "#" + b
+
+ g = "<" + g + ">"
+ g2 = "<" + g2 + ">"
+ angle = [g + x for x in angle]
+ quoted = [g2 + x for x in quoted]
+
+ all = angle + quoted
+ bjam.call("mark-included", target, all)
+
+ engine = get_manager().engine()
+ engine.set_target_variable(angle, "SEARCH", get_value(self.includes_))
+ engine.set_target_variable(quoted, "SEARCH", [b] + get_value(self.includes_))
+
+ # Just propagate current scanner to includes, in a hope
+ # that includes do not change scanners.
+ get_manager().scanners().propagate(self, angle + quoted)
+
+scanner.register (CScanner, 'include')
+type.set_scanner ('CPP', CScanner)
+type.set_scanner ('C', CScanner)
+
+# Ported to trunk@47077
+class LibGenerator (generators.Generator):
+ """ The generator class for libraries (target type LIB). Depending on properties it will
+ request building of the approapriate specific type -- SHARED_LIB, STATIC_LIB or
+ SHARED_LIB.
+ """
+
+ def __init__(self, id = 'LibGenerator', composing = True, source_types = [], target_types_and_names = ['LIB'], requirements = []):
+ generators.Generator.__init__(self, id, composing, source_types, target_types_and_names, requirements)
+
+ def run(self, project, name, prop_set, sources):
+
+ # The lib generator is composing, and can be only invoked with
+ # explicit name. This check is present in generator.run (and so in
+ # builtin.LinkingGenerator), but duplicate it here to avoid doing
+ # extra work.
+ if name:
+ properties = prop_set.raw()
+ # Determine the needed target type
+ actual_type = None
+ properties_grist = get_grist(properties)
+ if '<source>' not in properties_grist and \
+ ('<search>' in properties_grist or '<name>' in properties_grist):
+ actual_type = 'SEARCHED_LIB'
+ elif '<file>' in properties_grist:
+ # The generator for
+ actual_type = 'LIB'
+ elif '<link>shared' in properties:
+ actual_type = 'SHARED_LIB'
+ else:
+ actual_type = 'STATIC_LIB'
+
+ prop_set = prop_set.add_raw(['<main-target-type>LIB'])
+
+ # Construct the target.
+ return generators.construct(project, name, actual_type, prop_set, sources)
+
+ def viable_source_types(self):
+ return ['*']
+
+generators.register(LibGenerator())
+
+def lib(names, sources=[], requirements=[], default_build=[], usage_requirements=[]):
+ """The implementation of the 'lib' rule. Beyond standard syntax that rule allows
+ simplified: 'lib a b c ;'."""
+
+ if len(names) > 1:
+ if any(r.startswith('<name>') for r in requirements):
+ get_manager().errors()("When several names are given to the 'lib' rule\n" +
+ "it is not allowed to specify the <name> feature.")
+
+ if sources:
+ get_manager().errors()("When several names are given to the 'lib' rule\n" +
+ "it is not allowed to specify sources.")
+
+ project = get_manager().projects().current()
+ result = []
+
+ for name in names:
+ r = requirements[:]
+
+ # Support " lib a ; " and " lib a b c ; " syntax.
+ if not sources and not any(r.startswith("<name>") for r in requirements) \
+ and not any(r.startswith("<file") for r in requirements):
+ r.append("<name>" + name)
+
+ result.append(targets.create_typed_metatarget(name, "LIB", sources,
+ r,
+ default_build,
+ usage_requirements))
+ return result
+
+get_manager().projects().add_rule("lib", lib)
+
+
+# Updated to trunk@47077
+class SearchedLibGenerator (generators.Generator):
+ def __init__ (self, id = 'SearchedLibGenerator', composing = False, source_types = [], target_types_and_names = ['SEARCHED_LIB'], requirements = []):
+ # TODO: the comment below looks strange. There are no requirements!
+ # The requirements cause the generators to be tried *only* when we're building
+ # lib target and there's 'search' feature. This seems ugly --- all we want
+ # is make sure SearchedLibGenerator is not invoked deep in transformation
+ # search.
+ generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
+
+ def run(self, project, name, prop_set, sources):
+
+ if not name:
+ return None
+
+ # If name is empty, it means we're called not from top-level.
+ # In this case, we just fail immediately, because SearchedLibGenerator
+ # cannot be used to produce intermediate targets.
+
+ properties = prop_set.raw ()
+ shared = '<link>shared' in properties
+
+ a = virtual_target.NullAction (project.manager(), prop_set)
+
+ real_name = feature.get_values ('<name>', properties)
+ if real_name:
+ real_name = real_name[0]
+ else:
+ real_nake = name
+ search = feature.get_values('<search>', properties)
+ usage_requirements = property_set.create(['<xdll-path>' + p for p in search])
+ t = SearchedLibTarget(name, project, shared, real_name, search, a)
+
+ # We return sources for a simple reason. If there's
+ # lib png : z : <name>png ;
+ # the 'z' target should be returned, so that apps linking to
+ # 'png' will link to 'z', too.
+ return(usage_requirements, [b2.manager.get_manager().virtual_targets().register(t)] + sources)
+
+generators.register (SearchedLibGenerator ())
+
+### class prebuilt-lib-generator : generator
+### {
+### rule __init__ ( * : * )
+### {
+### generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+### }
+###
+### rule run ( project name ? : prop_set : sources * : multiple ? )
+### {
+### local f = [ $(prop_set).get <file> ] ;
+### return $(f) $(sources) ;
+### }
+### }
+###
+### generators.register
+### [ new prebuilt-lib-generator builtin.prebuilt : : LIB : <file> ] ;
+
+
+class CompileAction (virtual_target.Action):
+ def __init__ (self, manager, sources, action_name, prop_set):
+ virtual_target.Action.__init__ (self, manager, sources, action_name, prop_set)
+
+ def adjust_properties (self, prop_set):
+ """ For all virtual targets for the same dependency graph as self,
+ i.e. which belong to the same main target, add their directories
+ to include path.
+ """
+ s = self.targets () [0].creating_subvariant ()
+
+ return prop_set.add_raw (s.implicit_includes ('include', 'H'))
+
+class CCompilingGenerator (generators.Generator):
+ """ Declare a special compiler generator.
+ The only thing it does is changing the type used to represent
+ 'action' in the constructed dependency graph to 'CompileAction'.
+ That class in turn adds additional include paths to handle a case
+ when a source file includes headers which are generated themselfs.
+ """
+ def __init__ (self, id, composing, source_types, target_types_and_names, requirements):
+ # TODO: (PF) What to do with optional_properties? It seemed that, in the bjam version, the arguments are wrong.
+ generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
+
+ def action_class (self):
+ return CompileAction
+
+def register_c_compiler (id, source_types, target_types, requirements, optional_properties = []):
+ g = CCompilingGenerator (id, False, source_types, target_types, requirements + optional_properties)
+ return generators.register (g)
+
+
+class LinkingGenerator (generators.Generator):
+ """ The generator class for handling EXE and SHARED_LIB creation.
+ """
+ def __init__ (self, id, composing, source_types, target_types_and_names, requirements):
+ generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
+
+ def run (self, project, name, prop_set, sources):
+
+ lib_sources = prop_set.get('<library>')
+ sources.extend(lib_sources)
+
+ # Add <library-path> properties for all searched libraries
+ extra = []
+ for s in sources:
+ if s.type () == 'SEARCHED_LIB':
+ search = s.search()
+ extra.extend(property.Property('<library-path>', sp) for sp in search)
+
+ orig_xdll_path = []
+
+ if prop_set.get('<hardcode-dll-paths>') == ['true'] \
+ and type.is_derived(self.target_types_ [0], 'EXE'):
+ xdll_path = prop_set.get('<xdll-path>')
+ orig_xdll_path = [ replace_grist(x, '<dll-path>') for x in xdll_path ]
+ # It's possible that we have libraries in sources which did not came
+ # from 'lib' target. For example, libraries which are specified
+ # just as filenames as sources. We don't have xdll-path properties
+ # for such target, but still need to add proper dll-path properties.
+ for s in sources:
+ if type.is_derived (s.type (), 'SHARED_LIB') and not s.action ():
+ # Unfortunately, we don't have a good way to find the path
+ # to a file, so use this nasty approach.
+ p = s.project()
+ location = path.root(s.name(), p.get('source-location'))
+ xdll_path.append(path.parent(location))
+
+ extra.extend(property.Property('<dll-path>', sp) for sp in xdll_path)
+
+ if extra:
+ prop_set = prop_set.add_raw (extra)
+
+ result = generators.Generator.run(self, project, name, prop_set, sources)
+
+ if result:
+ ur = self.extra_usage_requirements(result, prop_set)
+ ur = ur.add(property_set.create(orig_xdll_path))
+ else:
+ return None
+
+ return(ur, result)
+
+ def extra_usage_requirements (self, created_targets, prop_set):
+
+ result = property_set.empty ()
+ extra = []
+
+ # Add appropriate <xdll-path> usage requirements.
+ raw = prop_set.raw ()
+ if '<link>shared' in raw:
+ paths = []
+
+ # TODO: is it safe to use the current directory? I think we should use
+ # another mechanism to allow this to be run from anywhere.
+ pwd = os.getcwd()
+
+ for t in created_targets:
+ if type.is_derived(t.type(), 'SHARED_LIB'):
+ paths.append(path.root(path.make(t.path()), pwd))
+
+ extra += replace_grist(paths, '<xdll-path>')
+
+ # We need to pass <xdll-path> features that we've got from sources,
+ # because if shared library is built, exe which uses it must know paths
+ # to other shared libraries this one depends on, to be able to find them
+ # all at runtime.
+
+ # Just pass all features in property_set, it's theorically possible
+ # that we'll propagate <xdll-path> features explicitly specified by
+ # the user, but then the user's to blaim for using internal feature.
+ values = prop_set.get('<xdll-path>')
+ extra += replace_grist(values, '<xdll-path>')
+
+ if extra:
+ result = property_set.create(extra)
+
+ return result
+
+ def generated_targets (self, sources, prop_set, project, name):
+
+ # sources to pass to inherited rule
+ sources2 = []
+ # sources which are libraries
+ libraries = []
+
+ # Searched libraries are not passed as argument to linker
+ # but via some option. So, we pass them to the action
+ # via property.
+ fsa = []
+ fst = []
+ for s in sources:
+ if type.is_derived(s.type(), 'SEARCHED_LIB'):
+ n = s.real_name()
+ if s.shared():
+ fsa.append(n)
+
+ else:
+ fst.append(n)
+
+ else:
+ sources2.append(s)
+
+ add = []
+ if fsa:
+ add.append("<find-shared-library>" + '&&'.join(fsa))
+ if fst:
+ add.append("<find-static-library>" + '&&'.join(fst))
+
+ spawn = generators.Generator.generated_targets(self, sources2, prop_set.add_raw(add), project, name)
+ return spawn
+
+
+def register_linker(id, source_types, target_types, requirements):
+ g = LinkingGenerator(id, True, source_types, target_types, requirements)
+ generators.register(g)
+
+class ArchiveGenerator (generators.Generator):
+ """ The generator class for handling STATIC_LIB creation.
+ """
+ def __init__ (self, id, composing, source_types, target_types_and_names, requirements):
+ generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
+
+ def run (self, project, name, prop_set, sources):
+ sources += prop_set.get ('<library>')
+
+ result = generators.Generator.run (self, project, name, prop_set, sources)
+
+ return result
+
+### rule register-archiver ( id composing ? : source_types + : target_types + :
+### requirements * )
+### {
+### local g = [ new ArchiveGenerator $(id) $(composing) : $(source_types)
+### : $(target_types) : $(requirements) ] ;
+### generators.register $(g) ;
+### }
+###
+###
+### IMPORT $(__name__) : register-linker register-archiver
+### : : generators.register-linker generators.register-archiver ;
+###
+###
+###
+
+get_manager().projects().add_rule("variant", variant)
+
+import stage
+import symlink
+import message
diff --git a/tools/build/v2/tools/cast.jam b/tools/build/v2/tools/cast.jam
new file mode 100644
index 0000000000..6c84922f1f
--- /dev/null
+++ b/tools/build/v2/tools/cast.jam
@@ -0,0 +1,91 @@
+# Copyright 2005 Vladimir Prus.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Defines main target 'cast', used to change type for target. For example, in Qt
+# library one wants two kinds of CPP files -- those that just compiled and those
+# that are passed via the MOC tool.
+#
+# This is done with:
+#
+# exe main : main.cpp [ cast _ moccable-cpp : widget.cpp ] ;
+#
+# Boost.Build will assing target type CPP to both main.cpp and widget.cpp. Then,
+# the cast rule will change target type of widget.cpp to MOCCABLE-CPP, and Qt
+# support will run the MOC tool as part of the build process.
+#
+# At the moment, the 'cast' rule only works for non-derived (source) targets.
+#
+# TODO: The following comment is unclear or incorrect. Clean it up.
+# > Another solution would be to add a separate main target 'moc-them' that
+# > would moc all the passed sources, no matter what their type is, but I prefer
+# > cast, as defining a new target type + generator for that type is somewhat
+# > simpler than defining a main target rule.
+
+import "class" : new ;
+import errors ;
+import project ;
+import property-set ;
+import targets ;
+import type ;
+
+
+class cast-target-class : typed-target
+{
+ import type ;
+
+ rule __init__ ( name : project : type : sources * : requirements * :
+ default-build * : usage-requirements * )
+ {
+ typed-target.__init__ $(name) : $(project) : $(type) : $(sources) :
+ $(requirements) : $(default-build) : $(usage-requirements) ;
+ }
+
+ rule construct ( name : source-targets * : property-set )
+ {
+ local result ;
+ for local s in $(source-targets)
+ {
+ if ! [ class.is-a $(s) : file-target ]
+ {
+ import errors ;
+ errors.user-error Source to the 'cast' rule is not a file! ;
+ }
+ if [ $(s).action ]
+ {
+ import errors ;
+ errors.user-error Only non-derived target are allowed for
+ 'cast'. : when building [ full-name ] ;
+ }
+ local r = [ $(s).clone-with-different-type $(self.type) ] ;
+ result += [ virtual-target.register $(r) ] ;
+ }
+ return [ property-set.empty ] $(result) ;
+ }
+}
+
+
+rule cast ( name type : sources * : requirements * : default-build * :
+ usage-requirements * )
+{
+ local project = [ project.current ] ;
+
+ local real-type = [ type.type-from-rule-name $(type) ] ;
+ if ! $(real-type)
+ {
+ errors.user-error No type corresponds to the main target rule name
+ '$(type)' : "Hint: try a lowercase name" ;
+ }
+
+ targets.main-target-alternative [ new cast-target-class $(name) : $(project)
+ : $(real-type)
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) :
+ $(project) ] ] ;
+}
+
+
+IMPORT $(__name__) : cast : : cast ;
diff --git a/tools/build/v2/tools/cast.py b/tools/build/v2/tools/cast.py
new file mode 100644
index 0000000000..8f053f110c
--- /dev/null
+++ b/tools/build/v2/tools/cast.py
@@ -0,0 +1,69 @@
+# Status: ported
+# Base revision: 64432.
+# Copyright 2005-2010 Vladimir Prus.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Defines main target 'cast', used to change type for target. For example, in Qt
+# library one wants two kinds of CPP files -- those that just compiled and those
+# that are passed via the MOC tool.
+#
+# This is done with:
+#
+# exe main : main.cpp [ cast _ moccable-cpp : widget.cpp ] ;
+#
+# Boost.Build will assing target type CPP to both main.cpp and widget.cpp. Then,
+# the cast rule will change target type of widget.cpp to MOCCABLE-CPP, and Qt
+# support will run the MOC tool as part of the build process.
+#
+# At the moment, the 'cast' rule only works for non-derived (source) targets.
+#
+# TODO: The following comment is unclear or incorrect. Clean it up.
+# > Another solution would be to add a separate main target 'moc-them' that
+# > would moc all the passed sources, no matter what their type is, but I prefer
+# > cast, as defining a new target type + generator for that type is somewhat
+# > simpler than defining a main target rule.
+
+import b2.build.targets as targets
+import b2.build.virtual_target as virtual_target
+
+from b2.manager import get_manager
+from b2.util import bjam_signature
+
+class CastTargetClass(targets.TypedTarget):
+
+ def construct(name, source_targets, ps):
+ result = []
+ for s in source_targets:
+ if not isinstance(s, virtual_targets.FileTarget):
+ get_manager().errors()("Source to the 'cast' metatager is not a file")
+
+ if s.action():
+ get_manager().errors()("Only non-derived targets allowed as sources for 'cast'.")
+
+
+ r = s.clone_with_different_type(self.type())
+ result.append(get_manager().virtual_targets().register(r))
+
+ return result
+
+
+@bjam_signature((["name", "type"], ["sources", "*"], ["requirements", "*"],
+ ["default_build", "*"], ["usage_requirements", "*"]))
+def cast(name, type, sources, requirements, default_build, usage_requirements):
+
+ from b2.manager import get_manager
+ t = get_manager().targets()
+
+ project = get_manager().projects().current()
+
+ return t.main_target_alternative(
+ CastTargetClass(name, project, type,
+ t.main_target_sources(sources, name),
+ t.main_target_requirements(requirements, project),
+ t.main_target_default_build(default_build, project),
+ t.main_target_usage_requirements(usage_requirements, project)))
+
+
+get_manager().projects().add_rule("cast", cast)
diff --git a/tools/build/v2/tools/clang-darwin.jam b/tools/build/v2/tools/clang-darwin.jam
new file mode 100644
index 0000000000..a8abc7d6a0
--- /dev/null
+++ b/tools/build/v2/tools/clang-darwin.jam
@@ -0,0 +1,170 @@
+# Copyright Vladimir Prus 2004.
+# Copyright Noel Belcourt 2007.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import clang ;
+import feature : feature ;
+import os ;
+import toolset ;
+import toolset : flags ;
+import gcc ;
+import common ;
+import errors ;
+import generators ;
+
+feature.extend-subfeature toolset clang : platform : darwin ;
+
+toolset.inherit-generators clang-darwin
+ <toolset>clang <toolset-clang:platform>darwin
+ : gcc
+ # Don't inherit PCH generators. They were not tested, and probably
+ # don't work for this compiler.
+ : gcc.mingw.link gcc.mingw.link.dll gcc.compile.c.pch gcc.compile.c++.pch
+ ;
+
+generators.override clang-darwin.prebuilt : builtin.lib-generator ;
+generators.override clang-darwin.prebuilt : builtin.prebuilt ;
+generators.override clang-darwin.searched-lib-generator : searched-lib-generator ;
+
+toolset.inherit-rules clang-darwin : gcc ;
+toolset.inherit-flags clang-darwin : gcc
+ : <inlining>off <inlining>on <inlining>full <optimization>space
+ <warnings>off <warnings>all <warnings>on
+ <architecture>x86/<address-model>32
+ <architecture>x86/<address-model>64
+ ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+# vectorization diagnostics
+feature vectorize : off on full ;
+
+# Initializes the clang-darwin toolset
+# version in optional
+# name (default clang++) is used to invoke the specified clang complier
+# compile and link options allow you to specify addition command line options for each version
+rule init ( version ? : command * : options * )
+{
+ command = [ common.get-invocation-command clang-darwin : clang++
+ : $(command) ] ;
+
+ # Determine the version
+ local command-string = $(command:J=" ") ;
+ if $(command)
+ {
+ version ?= [ MATCH "^([0-9.]+)"
+ : [ SHELL "$(command-string) -dumpversion" ] ] ;
+ }
+
+ local condition = [ common.check-init-parameters clang-darwin
+ : version $(version) ] ;
+
+ common.handle-options clang-darwin : $(condition) : $(command) : $(options) ;
+
+ gcc.init-link-flags clang-darwin darwin $(condition) ;
+
+}
+
+SPACE = " " ;
+
+flags clang-darwin.compile OPTIONS <cflags> ;
+flags clang-darwin.compile OPTIONS <cxxflags> ;
+# flags clang-darwin.compile INCLUDES <include> ;
+
+# Declare flags and action for compilation.
+toolset.flags clang-darwin.compile OPTIONS <optimization>off : -O0 ;
+toolset.flags clang-darwin.compile OPTIONS <optimization>speed : -O3 ;
+toolset.flags clang-darwin.compile OPTIONS <optimization>space : -Os ;
+
+toolset.flags clang-darwin.compile OPTIONS <inlining>off : -fno-inline ;
+toolset.flags clang-darwin.compile OPTIONS <inlining>on : -Wno-inline ;
+toolset.flags clang-darwin.compile OPTIONS <inlining>full : -finline-functions -Wno-inline ;
+
+toolset.flags clang-darwin.compile OPTIONS <warnings>off : -w ;
+toolset.flags clang-darwin.compile OPTIONS <warnings>on : -Wall ;
+toolset.flags clang-darwin.compile OPTIONS <warnings>all : -Wall -pedantic ;
+toolset.flags clang-darwin.compile OPTIONS <warnings-as-errors>on : -Werror ;
+
+toolset.flags clang-darwin.compile OPTIONS <debug-symbols>on : -g ;
+toolset.flags clang-darwin.compile OPTIONS <profiling>on : -pg ;
+toolset.flags clang-darwin.compile OPTIONS <rtti>off : -fno-rtti ;
+
+actions compile.c
+{
+ "$(CONFIG_COMMAND)" -x c $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" -x c++ $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+flags clang-darwin ARFLAGS <archiveflags> ;
+
+# Default value. Mostly for the sake of clang-linux
+# that inherits from gcc, but does not has the same
+# logic to set the .AR variable. We can put the same
+# logic in clang-linux, but that's hardly worth the trouble
+# as on Linux, 'ar' is always available.
+.AR = ar ;
+
+rule archive ( targets * : sources * : properties * )
+{
+ # Always remove archive and start again. Here's rationale from
+ # Andre Hentz:
+ #
+ # I had a file, say a1.c, that was included into liba.a.
+ # I moved a1.c to a2.c, updated my Jamfiles and rebuilt.
+ # My program was crashing with absurd errors.
+ # After some debugging I traced it back to the fact that a1.o was *still*
+ # in liba.a
+ #
+ # Rene Rivera:
+ #
+ # Originally removing the archive was done by splicing an RM
+ # onto the archive action. That makes archives fail to build on NT
+ # when they have many files because it will no longer execute the
+ # action directly and blow the line length limit. Instead we
+ # remove the file in a different action, just before the building
+ # of the archive.
+ #
+ local clean.a = $(targets[1])(clean) ;
+ TEMPORARY $(clean.a) ;
+ NOCARE $(clean.a) ;
+ LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ;
+ DEPENDS $(clean.a) : $(sources) ;
+ DEPENDS $(targets) : $(clean.a) ;
+ common.RmTemps $(clean.a) : $(targets) ;
+}
+
+actions piecemeal archive
+{
+ "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"
+ "ranlib" -cs "$(<)"
+}
+
+flags clang-darwin.link USER_OPTIONS <linkflags> ;
+
+# Declare actions for linking
+rule link ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+ # Serialize execution of the 'link' action, since
+ # running N links in parallel is just slower.
+ JAM_SEMAPHORE on $(targets) = <s>clang-darwin-link-semaphore ;
+}
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(USER_OPTIONS) -L"$(LINKPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(OPTIONS)
+}
+
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(USER_OPTIONS) -L"$(LINKPATH)" -o "$(<)" -single_module -dynamiclib -install_name "$(<[1]:D=)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(OPTIONS)
+}
diff --git a/tools/build/v2/tools/clang-linux.jam b/tools/build/v2/tools/clang-linux.jam
new file mode 100644
index 0000000000..036d749e60
--- /dev/null
+++ b/tools/build/v2/tools/clang-linux.jam
@@ -0,0 +1,196 @@
+# Copyright (c) 2003 Michael Stevens
+# Copyright (c) 2010-2011 Bryce Lelbach (blelbach@cct.lsu.edu, maintainer)
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import toolset ;
+import feature ;
+import toolset : flags ;
+
+import clang ;
+import gcc ;
+import common ;
+import errors ;
+import generators ;
+import type ;
+import numbers ;
+
+feature.extend-subfeature toolset clang : platform : linux ;
+
+toolset.inherit-generators clang-linux
+ <toolset>clang <toolset-clang:platform>linux : gcc
+ : gcc.mingw.link gcc.mingw.link.dll gcc.cygwin.link gcc.cygwin.link.dll ;
+generators.override clang-linux.prebuilt : builtin.lib-generator ;
+generators.override clang-linux.prebuilt : builtin.prebuilt ;
+generators.override clang-linux.searched-lib-generator : searched-lib-generator ;
+
+# Override default do-nothing generators.
+generators.override clang-linux.compile.c.pch : pch.default-c-pch-generator ;
+generators.override clang-linux.compile.c++.pch : pch.default-cpp-pch-generator ;
+
+type.set-generated-target-suffix PCH
+ : <toolset>clang <toolset-clang:platform>linux : pth ;
+
+toolset.inherit-rules clang-linux : gcc ;
+toolset.inherit-flags clang-linux : gcc
+ : <inlining>off <inlining>on <inlining>full
+ <optimization>space <optimization>speed
+ <warnings>off <warnings>all <warnings>on ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] {
+ .debug-configuration = true ;
+}
+
+rule init ( version ? : command * : options * ) {
+ command = [ common.get-invocation-command clang-linux : clang++
+ : $(command) ] ;
+
+ # Determine the version
+ local command-string = $(command:J=" ") ;
+
+ if $(command) {
+ version ?= [ MATCH "version ([0-9.]+)"
+ : [ SHELL "$(command-string) --version" ] ] ;
+ }
+
+ local condition = [ common.check-init-parameters clang-linux
+ : version $(version) ] ;
+
+ common.handle-options clang-linux : $(condition) : $(command) : $(options) ;
+
+ gcc.init-link-flags clang-linux gnu $(condition) ;
+}
+
+###############################################################################
+# Flags
+
+toolset.flags clang-linux.compile OPTIONS <cflags> ;
+toolset.flags clang-linux.compile OPTIONS <cxxflags> ;
+
+toolset.flags clang-linux.compile OPTIONS <optimization>off : ;
+toolset.flags clang-linux.compile OPTIONS <optimization>speed : -O3 ;
+toolset.flags clang-linux.compile OPTIONS <optimization>space : -Os ;
+
+# note: clang silently ignores some of these inlining options
+toolset.flags clang-linux.compile OPTIONS <inlining>off : -fno-inline ;
+toolset.flags clang-linux.compile OPTIONS <inlining>on : -Wno-inline ;
+toolset.flags clang-linux.compile OPTIONS <inlining>full : -finline-functions -Wno-inline ;
+
+toolset.flags clang-linux.compile OPTIONS <warnings>off : -w ;
+toolset.flags clang-linux.compile OPTIONS <warnings>on : -Wall ;
+toolset.flags clang-linux.compile OPTIONS <warnings>all : -Wall -pedantic ;
+toolset.flags clang-linux.compile OPTIONS <warnings-as-errors>on : -Werror ;
+
+toolset.flags clang-linux.compile OPTIONS <debug-symbols>on : -g ;
+toolset.flags clang-linux.compile OPTIONS <profiling>on : -pg ;
+toolset.flags clang-linux.compile OPTIONS <rtti>off : -fno-rtti ;
+
+###############################################################################
+# C and C++ compilation
+
+rule compile.c++ ( targets * : sources * : properties * ) {
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-fpic $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+
+ local pth-file = [ on $(<) return $(PCH_FILE) ] ;
+
+ if $(pth-file) {
+ DEPENDS $(<) : $(pth-file) ;
+ compile.c++.with-pch $(targets) : $(sources) ;
+ }
+ else {
+ compile.c++.without-pth $(targets) : $(sources) ;
+ }
+}
+
+actions compile.c++.without-pth {
+ "$(CONFIG_COMMAND)" -c -x c++ $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -o "$(<)" "$(>)"
+}
+
+actions compile.c++.with-pch bind PCH_FILE
+{
+ "$(CONFIG_COMMAND)" -c -x c++ $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -Xclang -include-pth -Xclang "$(PCH_FILE)" -o "$(<)" "$(>)"
+}
+
+rule compile.c ( targets * : sources * : properties * )
+{
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-fpic $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+
+ local pth-file = [ on $(<) return $(PCH_FILE) ] ;
+
+ if $(pth-file) {
+ DEPENDS $(<) : $(pth-file) ;
+ compile.c.with-pch $(targets) : $(sources) ;
+ }
+ else {
+ compile.c.without-pth $(targets) : $(sources) ;
+ }
+}
+
+actions compile.c.without-pth
+{
+ "$(CONFIG_COMMAND)" -c -x c $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c.with-pch bind PCH_FILE
+{
+ "$(CONFIG_COMMAND)" -c -x c $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -Xclang -include-pth -Xclang "$(PCH_FILE)" -c -o "$(<)" "$(>)"
+}
+
+###############################################################################
+# PCH emission
+
+rule compile.c++.pch ( targets * : sources * : properties * ) {
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-fpic $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+}
+
+actions compile.c++.pch {
+ rm -f "$(<)" && "$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -Xclang -emit-pth -o "$(<)" "$(>)"
+}
+
+rule compile.c.pch ( targets * : sources * : properties * ) {
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-fpic $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+}
+
+actions compile.c.pch
+{
+ rm -f "$(<)" && "$(CONFIG_COMMAND)" -x c-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -Xclang -emit-pth -o "$(<)" "$(>)"
+}
+
+###############################################################################
+# Linking
+
+SPACE = " " ;
+
+rule link ( targets * : sources * : properties * ) {
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+ SPACE on $(targets) = " " ;
+ JAM_SEMAPHORE on $(targets) = <s>clang-linux-link-semaphore ;
+}
+
+actions link bind LIBRARIES {
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(OPTIONS) $(USER_OPTIONS)
+}
+
+rule link.dll ( targets * : sources * : properties * ) {
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+ SPACE on $(targets) = " " ;
+ JAM_SEMAPHORE on $(targets) = <s>clang-linux-link-semaphore ;
+}
+
+# Differ from 'link' above only by -shared.
+actions link.dll bind LIBRARIES {
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -o "$(<)" -Wl,-soname$(SPACE)-Wl,$(<[1]:D=) -shared "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(OPTIONS) $(USER_OPTIONS)
+}
+
diff --git a/tools/build/v2/tools/clang.jam b/tools/build/v2/tools/clang.jam
new file mode 100644
index 0000000000..e0ac9a553c
--- /dev/null
+++ b/tools/build/v2/tools/clang.jam
@@ -0,0 +1,27 @@
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# This is a generic 'clang' toolset. Depending on the current system, it
+# forwards either to 'clang-unix' or 'clang-darwin' modules.
+
+import feature ;
+import os ;
+import toolset ;
+
+feature.extend toolset : clang ;
+feature.subfeature toolset clang : platform : : propagated link-incompatible ;
+
+rule init ( * : * )
+{
+ if [ os.name ] = MACOSX
+ {
+ toolset.using clang-darwin :
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+ else
+ {
+ toolset.using clang-linux :
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+}
diff --git a/tools/build/v2/tools/common.jam b/tools/build/v2/tools/common.jam
new file mode 100644
index 0000000000..df914d9d46
--- /dev/null
+++ b/tools/build/v2/tools/common.jam
@@ -0,0 +1,986 @@
+# Copyright 2003, 2005 Dave Abrahams
+# Copyright 2005, 2006 Rene Rivera
+# Copyright 2005 Toon Knapen
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Provides actions common to all toolsets, such as creating directories and
+# removing files.
+
+import os ;
+import modules ;
+import utility ;
+import print ;
+import type ;
+import feature ;
+import errors ;
+import path ;
+import sequence ;
+import toolset ;
+import virtual-target ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+if [ MATCH (--show-configuration) : [ modules.peek : ARGV ] ]
+{
+ .show-configuration = true ;
+}
+
+# Configurations
+#
+# The following class helps to manage toolset configurations. Each configuration
+# has a unique ID and one or more parameters. A typical example of a unique ID
+# is a condition generated by 'common.check-init-parameters' rule. Other kinds
+# of IDs can be used. Parameters may include any details about the configuration
+# like 'command', 'path', etc.
+#
+# A toolset configuration may be in one of the following states:
+#
+# - registered
+# Configuration has been registered (e.g. explicitly or by auto-detection
+# code) but has not yet been marked as used, i.e. 'toolset.using' rule has
+# not yet been called for it.
+# - used
+# Once called 'toolset.using' rule marks the configuration as 'used'.
+#
+# The main difference between the states above is that while a configuration is
+# 'registered' its options can be freely changed. This is useful in particular
+# for autodetection code - all detected configurations may be safely overwritten
+# by user code.
+
+class configurations
+{
+ import errors ;
+
+ rule __init__ ( )
+ {
+ }
+
+ # Registers a configuration.
+ #
+ # Returns 'true' if the configuration has been added and an empty value if
+ # it already exists. Reports an error if the configuration is 'used'.
+ #
+ rule register ( id )
+ {
+ if $(id) in $(self.used)
+ {
+ errors.error "common: the configuration '$(id)' is in use" ;
+ }
+
+ local retval ;
+
+ if ! $(id) in $(self.all)
+ {
+ self.all += $(id) ;
+
+ # Indicate that a new configuration has been added.
+ retval = true ;
+ }
+
+ return $(retval) ;
+ }
+
+ # Mark a configuration as 'used'.
+ #
+ # Returns 'true' if the state of the configuration has been changed to
+ # 'used' and an empty value if it the state has not been changed. Reports an
+ # error if the configuration is not known.
+ #
+ rule use ( id )
+ {
+ if ! $(id) in $(self.all)
+ {
+ errors.error "common: the configuration '$(id)' is not known" ;
+ }
+
+ local retval ;
+
+ if ! $(id) in $(self.used)
+ {
+ self.used += $(id) ;
+
+ # Indicate that the configuration has been marked as 'used'.
+ retval = true ;
+ }
+
+ return $(retval) ;
+ }
+
+ # Return all registered configurations.
+ #
+ rule all ( )
+ {
+ return $(self.all) ;
+ }
+
+ # Return all used configurations.
+ #
+ rule used ( )
+ {
+ return $(self.used) ;
+ }
+
+ # Returns the value of a configuration parameter.
+ #
+ rule get ( id : param )
+ {
+ return $(self.$(param).$(id)) ;
+ }
+
+ # Sets the value of a configuration parameter.
+ #
+ rule set ( id : param : value * )
+ {
+ self.$(param).$(id) = $(value) ;
+ }
+}
+
+
+# The rule for checking toolset parameters. Trailing parameters should all be
+# parameter name/value pairs. The rule will check that each parameter either has
+# a value in each invocation or has no value in each invocation. Also, the rule
+# will check that the combination of all parameter values is unique in all
+# invocations.
+#
+# Each parameter name corresponds to a subfeature. This rule will declare a
+# subfeature the first time a non-empty parameter value is passed and will
+# extend it with all the values.
+#
+# The return value from this rule is a condition to be used for flags settings.
+#
+rule check-init-parameters ( toolset requirement * : * )
+{
+ local sig = $(toolset) ;
+ local condition = <toolset>$(toolset) ;
+ local subcondition ;
+ for local index in 2 3 4 5 6 7 8 9
+ {
+ local name = $($(index)[1]) ;
+ local value = $($(index)[2]) ;
+
+ if $(value)-is-not-empty
+ {
+ condition = $(condition)-$(value) ;
+ if $(.had-unspecified-value.$(toolset).$(name))
+ {
+ errors.user-error
+ "$(toolset) initialization: parameter '$(name)'"
+ "inconsistent" : "no value was specified in earlier"
+ "initialization" : "an explicit value is specified now" ;
+ }
+ # The below logic is for intel compiler. It calls this rule with
+ # 'intel-linux' and 'intel-win' as toolset, so we need to get the
+ # base part of toolset name. We can not pass 'intel' as toolset
+ # because in that case it will be impossible to register versionless
+ # intel-linux and intel-win toolsets of a specific version.
+ local t = $(toolset) ;
+ local m = [ MATCH ([^-]*)- : $(toolset) ] ;
+ if $(m)
+ {
+ t = $(m[1]) ;
+ }
+ if ! $(.had-value.$(toolset).$(name))
+ {
+ if ! $(.declared-subfeature.$(t).$(name))
+ {
+ feature.subfeature toolset $(t) : $(name) : : propagated ;
+ .declared-subfeature.$(t).$(name) = true ;
+ }
+ .had-value.$(toolset).$(name) = true ;
+ }
+ feature.extend-subfeature toolset $(t) : $(name) : $(value) ;
+ subcondition += <toolset-$(t):$(name)>$(value) ;
+ }
+ else
+ {
+ if $(.had-value.$(toolset).$(name))
+ {
+ errors.user-error
+ "$(toolset) initialization: parameter '$(name)'"
+ "inconsistent" : "an explicit value was specified in an"
+ "earlier initialization" : "no value is specified now" ;
+ }
+ .had-unspecified-value.$(toolset).$(name) = true ;
+ }
+ sig = $(sig)$(value:E="")- ;
+ }
+ if $(sig) in $(.all-signatures)
+ {
+ local message =
+ "duplicate initialization of $(toolset) with the following parameters: " ;
+ for local index in 2 3 4 5 6 7 8 9
+ {
+ local p = $($(index)) ;
+ if $(p)
+ {
+ message += "$(p[1]) = $(p[2]:E=<unspecified>)" ;
+ }
+ }
+ message += "previous initialization at $(.init-loc.$(sig))" ;
+ errors.user-error
+ $(message[1]) : $(message[2]) : $(message[3]) : $(message[4]) :
+ $(message[5]) : $(message[6]) : $(message[7]) : $(message[8]) ;
+ }
+ .all-signatures += $(sig) ;
+ .init-loc.$(sig) = [ errors.nearest-user-location ] ;
+
+ # If we have a requirement, this version should only be applied under that
+ # condition. To accomplish this we add a toolset requirement that imposes
+ # the toolset subcondition, which encodes the version.
+ if $(requirement)
+ {
+ local r = <toolset>$(toolset) $(requirement) ;
+ r = $(r:J=,) ;
+ toolset.add-requirements $(r):$(subcondition) ;
+ }
+
+ # We add the requirements, if any, to the condition to scope the toolset
+ # variables and options to this specific version.
+ condition += $(requirement) ;
+
+ if $(.show-configuration)
+ {
+ ECHO notice: $(condition) ;
+ }
+ return $(condition:J=/) ;
+}
+
+
+# A helper rule to get the command to invoke some tool. If
+# 'user-provided-command' is not given, tries to find binary named 'tool' in
+# PATH and in the passed 'additional-path'. Otherwise, verifies that the first
+# element of 'user-provided-command' is an existing program.
+#
+# This rule returns the command to be used when invoking the tool. If we can not
+# find the tool, a warning is issued. If 'path-last' is specified, PATH is
+# checked after 'additional-paths' when searching for 'tool'.
+#
+rule get-invocation-command-nodefault ( toolset : tool :
+ user-provided-command * : additional-paths * : path-last ? )
+{
+ local command ;
+ if ! $(user-provided-command)
+ {
+ command = [ find-tool $(tool) : $(additional-paths) : $(path-last) ] ;
+ if ! $(command) && $(.debug-configuration)
+ {
+ ECHO "warning: toolset $(toolset) initialization: can not find tool $(tool)" ;
+ ECHO "warning: initialized from" [ errors.nearest-user-location ] ;
+ }
+ }
+ else
+ {
+ command = [ check-tool $(user-provided-command) ] ;
+ if ! $(command) && $(.debug-configuration)
+ {
+ ECHO "warning: toolset $(toolset) initialization: " ;
+ ECHO "warning: can not find user-provided command " '$(user-provided-command)' ;
+ ECHO "warning: initialized from" [ errors.nearest-user-location ] ;
+ }
+ }
+
+ return $(command) ;
+}
+
+
+# Same as get-invocation-command-nodefault, except that if no tool is found,
+# returns either the user-provided-command, if present, or the 'tool' parameter.
+#
+rule get-invocation-command ( toolset : tool : user-provided-command * :
+ additional-paths * : path-last ? )
+{
+ local result = [ get-invocation-command-nodefault $(toolset) : $(tool) :
+ $(user-provided-command) : $(additional-paths) : $(path-last) ] ;
+
+ if ! $(result)
+ {
+ if $(user-provided-command)
+ {
+ result = $(user-provided-command) ;
+ }
+ else
+ {
+ result = $(tool) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Given an invocation command return the absolute path to the command. This
+# works even if command has no path element and was found on the PATH.
+#
+rule get-absolute-tool-path ( command )
+{
+ if $(command:D)
+ {
+ return $(command:D) ;
+ }
+ else
+ {
+ local m = [ GLOB [ modules.peek : PATH Path path ] : $(command) $(command).exe ] ;
+ return $(m[1]:D) ;
+ }
+}
+
+
+# Attempts to find tool (binary) named 'name' in PATH and in 'additional-paths'.
+# If found in PATH, returns 'name' and if found in additional paths, returns
+# absolute name. If the tool is found in several directories, returns the
+# first path found. Otherwise, returns an empty string. If 'path-last' is
+# specified, PATH is searched after 'additional-paths'.
+#
+local rule find-tool ( name : additional-paths * : path-last ? )
+{
+ local path = [ path.programs-path ] ;
+ local match = [ path.glob $(path) : $(name) $(name).exe ] ;
+ local additional-match = [ path.glob $(additional-paths) : $(name) $(name).exe ] ;
+
+ local result ;
+ if $(path-last)
+ {
+ result = $(additional-match) ;
+ if ! $(result) && $(match)
+ {
+ result = $(name) ;
+ }
+ }
+ else
+ {
+ if $(match)
+ {
+ result = $(name) ;
+ }
+ else
+ {
+ result = $(additional-match) ;
+ }
+ }
+ if $(result)
+ {
+ return [ path.native $(result[1]) ] ;
+ }
+}
+
+
+# Checks if 'command' can be found either in path or is a full name to an
+# existing file.
+#
+local rule check-tool-aux ( command )
+{
+ if $(command:D)
+ {
+ if [ path.exists $(command) ]
+ # Both NT and Cygwin will run .exe files by their unqualified names.
+ || ( [ os.on-windows ] && [ path.exists $(command).exe ] )
+ # Only NT will run .bat & .cmd files by their unqualified names.
+ || ( ( [ os.name ] = NT ) && ( [ path.exists $(command).bat ] ||
+ [ path.exists $(command).cmd ] ) )
+ {
+ return $(command) ;
+ }
+ }
+ else
+ {
+ if [ GLOB [ modules.peek : PATH Path path ] : $(command) ]
+ {
+ return $(command) ;
+ }
+ }
+}
+
+
+# Checks that a tool can be invoked by 'command'. If command is not an absolute
+# path, checks if it can be found in 'path'. If comand is an absolute path,
+# check that it exists. Returns 'command' if ok or empty string otherwise.
+#
+local rule check-tool ( xcommand + )
+{
+ if [ check-tool-aux $(xcommand[1]) ] ||
+ [ check-tool-aux $(xcommand[-1]) ]
+ {
+ return $(xcommand) ;
+ }
+}
+
+
+# Handle common options for toolset, specifically sets the following flag
+# variables:
+# - CONFIG_COMMAND to $(command)
+# - OPTIONS for compile to the value of <compileflags> in $(options)
+# - OPTIONS for compile.c to the value of <cflags> in $(options)
+# - OPTIONS for compile.c++ to the value of <cxxflags> in $(options)
+# - OPTIONS for compile.fortran to the value of <fflags> in $(options)
+# - OPTIONS for link to the value of <linkflags> in $(options)
+#
+rule handle-options ( toolset : condition * : command * : options * )
+{
+ if $(.debug-configuration)
+ {
+ ECHO "notice: will use '$(command)' for $(toolset), condition $(condition:E=(empty))" ;
+ }
+
+ # The last parameter ('unchecked') says it is OK to set flags for another
+ # module.
+ toolset.flags $(toolset) CONFIG_COMMAND $(condition) : $(command)
+ : unchecked ;
+
+ toolset.flags $(toolset).compile OPTIONS $(condition) :
+ [ feature.get-values <compileflags> : $(options) ] : unchecked ;
+
+ toolset.flags $(toolset).compile.c OPTIONS $(condition) :
+ [ feature.get-values <cflags> : $(options) ] : unchecked ;
+
+ toolset.flags $(toolset).compile.c++ OPTIONS $(condition) :
+ [ feature.get-values <cxxflags> : $(options) ] : unchecked ;
+
+ toolset.flags $(toolset).compile.fortran OPTIONS $(condition) :
+ [ feature.get-values <fflags> : $(options) ] : unchecked ;
+
+ toolset.flags $(toolset).link OPTIONS $(condition) :
+ [ feature.get-values <linkflags> : $(options) ] : unchecked ;
+}
+
+
+# Returns the location of the "program files" directory on a Windows platform.
+#
+rule get-program-files-dir ( )
+{
+ local ProgramFiles = [ modules.peek : ProgramFiles ] ;
+ if $(ProgramFiles)
+ {
+ ProgramFiles = "$(ProgramFiles:J= )" ;
+ }
+ else
+ {
+ ProgramFiles = "c:\\Program Files" ;
+ }
+ return $(ProgramFiles) ;
+}
+
+
+if [ os.name ] = NT
+{
+ RM = del /f /q ;
+ CP = copy /b ;
+ IGNORE = "2>nul >nul & setlocal" ;
+ LN ?= $(CP) ;
+ # Ugly hack to convince copy to set the timestamp of the
+ # destination to the current time by concatenating the
+ # source with a nonexistent file. Note that this requires
+ # /b (binary) as the default when concatenating files is /a (ascii).
+ WINDOWS-CP-HACK = "+ this-file-does-not-exist-A698EE7806899E69" ;
+}
+else
+{
+ RM = rm -f ;
+ CP = cp ;
+ LN = ln ;
+}
+
+
+rule rm-command ( )
+{
+ return $(RM) ;
+}
+
+
+rule copy-command ( )
+{
+ return $(CP) ;
+}
+
+
+if "\n" = "n"
+{
+ # Escape characters are not supported. Use ugly hacks that won't work,
+ # see below.
+ nl = "
+" ;
+ q = "" ;
+}
+else
+{
+ nl = "\n" ;
+ q = "\"" ;
+}
+
+# Returns the command needed to set an environment variable on the current
+# platform. The variable setting persists through all following commands and is
+# visible in the environment seen by subsequently executed commands. In other
+# words, on Unix systems, the variable is exported, which is consistent with the
+# only possible behavior on Windows systems.
+#
+rule variable-setting-command ( variable : value )
+{
+ if [ os.name ] = NT
+ {
+ return "set $(variable)=$(value)$(nl)" ;
+ }
+ else
+ {
+ # If we don't have escape characters support in bjam, the below blows
+ # up on CYGWIN, since the $(nl) variable holds a Windows new-line \r\n
+ # sequence that messes up the executed export command which then reports
+ # that the passed variable name is incorrect.
+ # But we have a check for cygwin in kernel/bootstrap.jam already.
+ return "$(variable)=$(q)$(value)$(q)$(nl)export $(variable)$(nl)" ;
+ }
+}
+
+
+# Returns a command to sets a named shell path variable to the given NATIVE
+# paths on the current platform.
+#
+rule path-variable-setting-command ( variable : paths * )
+{
+ local sep = [ os.path-separator ] ;
+ return [ variable-setting-command $(variable) : $(paths:J=$(sep)) ] ;
+}
+
+
+# Returns a command that prepends the given paths to the named path variable on
+# the current platform.
+#
+rule prepend-path-variable-command ( variable : paths * )
+{
+ return [ path-variable-setting-command $(variable)
+ : $(paths) [ os.expand-variable $(variable) ] ] ;
+}
+
+
+# Return a command which can create a file. If 'r' is result of invocation, then
+# 'r foobar' will create foobar with unspecified content. What happens if file
+# already exists is unspecified.
+#
+rule file-creation-command ( )
+{
+ if [ os.name ] = NT
+ {
+ # A few alternative implementations on Windows:
+ #
+ # 'type NUL >> '
+ # That would construct an empty file instead of a file containing
+ # a space and an end-of-line marker but it would also not change
+ # the target's timestamp in case the file already exists.
+ #
+ # 'type NUL > '
+ # That would construct an empty file instead of a file containing
+ # a space and an end-of-line marker but it would also destroy an
+ # already existing file by overwriting it with an empty one.
+ #
+ # I guess the best solution would be to allow Boost Jam to define
+ # built-in functions such as 'create a file', 'touch a file' or 'copy a
+ # file' which could be used from inside action code. That would allow
+ # completely portable operations without this kind of kludge.
+ # (22.02.2009.) (Jurko)
+ return "echo. > " ;
+ }
+ else
+ {
+ return "touch " ;
+ }
+}
+
+
+# Returns a command that may be used for 'touching' files. It is not a real
+# 'touch' command on NT because it adds an empty line at the end of file but it
+# works with source files.
+#
+rule file-touch-command ( )
+{
+ if [ os.name ] = NT
+ {
+ return "echo. >> " ;
+ }
+ else
+ {
+ return "touch " ;
+ }
+}
+
+
+rule MkDir
+{
+ # If dir exists, do not update it. Do this even for $(DOT).
+ NOUPDATE $(<) ;
+
+ if $(<) != $(DOT) && ! $($(<)-mkdir)
+ {
+ # Cheesy gate to prevent multiple invocations on same dir.
+ $(<)-mkdir = true ;
+
+ # Schedule the mkdir build action.
+ common.mkdir $(<) ;
+
+ # Prepare a Jam 'dirs' target that can be used to make the build only
+ # construct all the target directories.
+ DEPENDS dirs : $(<) ;
+
+ # Recursively create parent directories. $(<:P) = $(<)'s parent & we
+ # recurse until root.
+
+ local s = $(<:P) ;
+ if [ os.name ] = NT
+ {
+ switch $(s)
+ {
+ case *: : s = ;
+ case *:\\ : s = ;
+ }
+ }
+
+ if $(s)
+ {
+ if $(s) != $(<)
+ {
+ DEPENDS $(<) : $(s) ;
+ MkDir $(s) ;
+ }
+ else
+ {
+ NOTFILE $(s) ;
+ }
+ }
+ }
+}
+
+
+#actions MkDir1
+#{
+# mkdir "$(<)"
+#}
+
+# The following quick-fix actions should be replaced using the original MkDir1
+# action once Boost Jam gets updated to correctly detect different paths leading
+# up to the same filesystem target and triggers their build action only once.
+# (todo) (04.07.2008.) (Jurko)
+
+if [ os.name ] = NT
+{
+ actions mkdir
+ {
+ if not exist "$(<)\\" mkdir "$(<)"
+ }
+}
+else
+{
+ actions mkdir
+ {
+ mkdir -p "$(<)"
+ }
+}
+
+actions piecemeal together existing Clean
+{
+ $(RM) "$(>)"
+}
+
+
+rule copy
+{
+}
+
+
+actions copy
+{
+ $(CP) "$(>)" $(WINDOWS-CP-HACK) "$(<)"
+}
+
+
+rule RmTemps
+{
+}
+
+
+actions quietly updated piecemeal together RmTemps
+{
+ $(RM) "$(>)" $(IGNORE)
+}
+
+
+actions hard-link
+{
+ $(RM) "$(<)" 2$(NULL_OUT) $(NULL_OUT)
+ $(LN) "$(>)" "$(<)" $(NULL_OUT)
+}
+
+
+# Given a target, as given to a custom tag rule, returns a string formatted
+# according to the passed format. Format is a list of properties that is
+# represented in the result. For each element of format the corresponding target
+# information is obtained and added to the result string. For all, but the
+# literal, the format value is taken as the as string to prepend to the output
+# to join the item to the rest of the result. If not given "-" is used as a
+# joiner.
+#
+# The format options can be:
+#
+# <base>[joiner]
+# :: The basename of the target name.
+# <toolset>[joiner]
+# :: The abbreviated toolset tag being used to build the target.
+# <threading>[joiner]
+# :: Indication of a multi-threaded build.
+# <runtime>[joiner]
+# :: Collective tag of the build runtime.
+# <version:/version-feature | X.Y[.Z]/>[joiner]
+# :: Short version tag taken from the given "version-feature" in the
+# build properties. Or if not present, the literal value as the
+# version number.
+# <property:/property-name/>[joiner]
+# :: Direct lookup of the given property-name value in the build
+# properties. /property-name/ is a regular expression. E.g.
+# <property:toolset-.*:flavor> will match every toolset.
+# /otherwise/
+# :: The literal value of the format argument.
+#
+# For example this format:
+#
+# boost_ <base> <toolset> <threading> <runtime> <version:boost-version>
+#
+# Might return:
+#
+# boost_thread-vc80-mt-gd-1_33.dll, or
+# boost_regex-vc80-gd-1_33.dll
+#
+# The returned name also has the target type specific prefix and suffix which
+# puts it in a ready form to use as the value from a custom tag rule.
+#
+rule format-name ( format * : name : type ? : property-set )
+{
+ local result = "" ;
+ for local f in $(format)
+ {
+ switch $(f:G)
+ {
+ case <base> :
+ result += $(name:B) ;
+
+ case <toolset> :
+ result += [ join-tag $(f:G=) : [ toolset-tag $(name) : $(type) :
+ $(property-set) ] ] ;
+
+ case <threading> :
+ result += [ join-tag $(f:G=) : [ threading-tag $(name) : $(type)
+ : $(property-set) ] ] ;
+
+ case <runtime> :
+ result += [ join-tag $(f:G=) : [ runtime-tag $(name) : $(type) :
+ $(property-set) ] ] ;
+
+ case <qt> :
+ result += [ join-tag $(f:G=) : [ qt-tag $(name) : $(type) :
+ $(property-set) ] ] ;
+
+ case <address-model> :
+ result += [ join-tag $(f:G=) : [ address-model-tag $(name) : $(type) :
+ $(property-set) ] ] ;
+
+ case <version:*> :
+ local key = [ MATCH <version:(.*)> : $(f:G) ] ;
+ local version = [ $(property-set).get <$(key)> ] ;
+ version ?= $(key) ;
+ version = [ MATCH "^([^.]+)[.]([^.]+)[.]?([^.]*)" : $(version) ] ;
+ result += [ join-tag $(f:G=) : $(version[1])_$(version[2]) ] ;
+
+ case <property:*> :
+ local key = [ MATCH <property:(.*)> : $(f:G) ] ;
+ local p0 = [ MATCH <($(key))> : [ $(property-set).raw ] ] ;
+ if $(p0)
+ {
+ local p = [ $(property-set).get <$(p0)> ] ;
+ if $(p)
+ {
+ result += [ join-tag $(f:G=) : $(p) ] ;
+ }
+ }
+
+ case * :
+ result += $(f:G=) ;
+ }
+ }
+ result = [ virtual-target.add-prefix-and-suffix $(result:J=) : $(type) :
+ $(property-set) ] ;
+ return $(result) ;
+}
+
+
+local rule join-tag ( joiner ? : tag ? )
+{
+ if ! $(joiner) { joiner = - ; }
+ return $(joiner)$(tag) ;
+}
+
+
+local rule toolset-tag ( name : type ? : property-set )
+{
+ local tag = ;
+
+ local properties = [ $(property-set).raw ] ;
+ switch [ $(property-set).get <toolset> ]
+ {
+ case borland* : tag += bcb ;
+ case clang* :
+ {
+ switch [ $(property-set).get <toolset-clang:platform> ]
+ {
+ case darwin : tag += clang-darwin ;
+ case linux : tag += clang ;
+ }
+ }
+ case como* : tag += como ;
+ case cw : tag += cw ;
+ case darwin* : tag += xgcc ;
+ case edg* : tag += edg ;
+ case gcc* :
+ {
+ switch [ $(property-set).get <toolset-gcc:flavor> ]
+ {
+ case *mingw* : tag += mgw ;
+ case * : tag += gcc ;
+ }
+ }
+ case intel :
+ if [ $(property-set).get <toolset-intel:platform> ] = win
+ {
+ tag += iw ;
+ }
+ else
+ {
+ tag += il ;
+ }
+ case kcc* : tag += kcc ;
+ case kylix* : tag += bck ;
+ #case metrowerks* : tag += cw ;
+ #case mingw* : tag += mgw ;
+ case mipspro* : tag += mp ;
+ case msvc* : tag += vc ;
+ case qcc* : tag += qcc ;
+ case sun* : tag += sw ;
+ case tru64cxx* : tag += tru ;
+ case vacpp* : tag += xlc ;
+ }
+ local version = [ MATCH "<toolset.*version>([0123456789]+)[.]([0123456789]*)"
+ : $(properties) ] ;
+ # For historical reasons, vc6.0 and vc7.0 use different naming.
+ if $(tag) = vc
+ {
+ if $(version[1]) = 6
+ {
+ # Cancel minor version.
+ version = 6 ;
+ }
+ else if $(version[1]) = 7 && $(version[2]) = 0
+ {
+ version = 7 ;
+ }
+ }
+ # On intel, version is not added, because it does not matter and it is the
+ # version of vc used as backend that matters. Ideally, we should encode the
+ # backend version but that would break compatibility with V1.
+ if $(tag) = iw
+ {
+ version = ;
+ }
+
+ # On borland, version is not added for compatibility with V1.
+ if $(tag) = bcb
+ {
+ version = ;
+ }
+
+ tag += $(version) ;
+
+ return $(tag:J=) ;
+}
+
+
+local rule threading-tag ( name : type ? : property-set )
+{
+ local tag = ;
+ local properties = [ $(property-set).raw ] ;
+ if <threading>multi in $(properties) { tag = mt ; }
+
+ return $(tag:J=) ;
+}
+
+
+local rule runtime-tag ( name : type ? : property-set )
+{
+ local tag = ;
+
+ local properties = [ $(property-set).raw ] ;
+ if <runtime-link>static in $(properties) { tag += s ; }
+
+ # This is an ugly thing. In V1, there is code to automatically detect which
+ # properties affect a target. So, if <runtime-debugging> does not affect gcc
+ # toolset, the tag rules will not even see <runtime-debugging>. Similar
+ # functionality in V2 is not implemented yet, so we just check for toolsets
+ # known to care about runtime debugging.
+ if ( <toolset>msvc in $(properties) ) ||
+ ( <stdlib>stlport in $(properties) ) ||
+ ( <toolset-intel:platform>win in $(properties) )
+ {
+ if <runtime-debugging>on in $(properties) { tag += g ; }
+ }
+
+ if <python-debugging>on in $(properties) { tag += y ; }
+ if <variant>debug in $(properties) { tag += d ; }
+ if <stdlib>stlport in $(properties) { tag += p ; }
+ if <stdlib-stlport:iostream>hostios in $(properties) { tag += n ; }
+
+ return $(tag:J=) ;
+}
+
+# Create a tag for the Qt library version
+# "<qt>4.6.0" will result in tag "qt460"
+local rule qt-tag ( name : type ? : property-set )
+{
+ local properties = [ $(property-set).get <qt> ] ;
+ local version = [ MATCH "([0123456789]+)[.]?([0123456789]*)[.]?([0123456789]*)"
+ : $(properties) ] ;
+ local tag = "qt"$(version:J=) ;
+ return $(tag) ;
+}
+
+# Create a tag for the address-model
+# <address-model>64 will simply generate "64"
+local rule address-model-tag ( name : type ? : property-set )
+{
+ local tag = ;
+ local version = [ $(property-set).get <address-model> ] ;
+ return $(version) ;
+}
+
+rule __test__ ( )
+{
+ import assert ;
+
+ local nl = "
+" ;
+
+ local save-os = [ modules.peek os : .name ] ;
+
+ modules.poke os : .name : LINUX ;
+
+ assert.result "PATH=\"foo:bar:baz\"$(nl)export PATH$(nl)"
+ : path-variable-setting-command PATH : foo bar baz ;
+
+ assert.result "PATH=\"foo:bar:$PATH\"$(nl)export PATH$(nl)"
+ : prepend-path-variable-command PATH : foo bar ;
+
+ modules.poke os : .name : NT ;
+
+ assert.result "set PATH=foo;bar;baz$(nl)"
+ : path-variable-setting-command PATH : foo bar baz ;
+
+ assert.result "set PATH=foo;bar;%PATH%$(nl)"
+ : prepend-path-variable-command PATH : foo bar ;
+
+ modules.poke os : .name : $(save-os) ;
+}
diff --git a/tools/build/v2/tools/common.py b/tools/build/v2/tools/common.py
new file mode 100644
index 0000000000..612745b81f
--- /dev/null
+++ b/tools/build/v2/tools/common.py
@@ -0,0 +1,840 @@
+# Status: being ported by Steven Watanabe
+# Base revision: 47174
+#
+# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+""" Provides actions common to all toolsets, such as creating directories and
+ removing files.
+"""
+
+import re
+import bjam
+import os
+import os.path
+import sys
+
+from b2.build import feature
+from b2.util.utility import *
+from b2.util import path
+
+__re__before_first_dash = re.compile ('([^-]*)-')
+
+def reset ():
+ """ Clear the module state. This is mainly for testing purposes.
+ Note that this must be called _after_ resetting the module 'feature'.
+ """
+ global __had_unspecified_value, __had_value, __declared_subfeature
+ global __init_loc
+ global __all_signatures, __debug_configuration, __show_configuration
+
+ # Stores toolsets without specified initialization values.
+ __had_unspecified_value = {}
+
+ # Stores toolsets with specified initialization values.
+ __had_value = {}
+
+ # Stores toolsets with declared subfeatures.
+ __declared_subfeature = {}
+
+ # Stores all signatures of the toolsets.
+ __all_signatures = {}
+
+ # Stores the initialization locations of each toolset
+ __init_loc = {}
+
+ __debug_configuration = '--debug-configuration' in bjam.variable('ARGV')
+ __show_configuration = '--show-configuration' in bjam.variable('ARGV')
+
+ global __executable_path_variable
+ OS = bjam.call("peek", [], "OS")[0]
+ if OS == "NT":
+ # On Windows the case and capitalization of PATH is not always predictable, so
+ # let's find out what variable name was really set.
+ for n in sys.environ:
+ if n.lower() == "path":
+ __executable_path_variable = n
+ break
+ else:
+ __executable_path_variable = "PATH"
+
+ m = {"NT": __executable_path_variable,
+ "CYGWIN": "PATH",
+ "MACOSX": "DYLD_LIBRARY_PATH",
+ "AIX": "LIBPATH"}
+ global __shared_library_path_variable
+ __shared_library_path_variable = m.get(OS, "LD_LIBRARY_PATH")
+
+reset()
+
+def shared_library_path_variable():
+ return __shared_library_path_variable
+
+# ported from trunk@47174
+class Configurations(object):
+ """
+ This class helps to manage toolset configurations. Each configuration
+ has a unique ID and one or more parameters. A typical example of a unique ID
+ is a condition generated by 'common.check-init-parameters' rule. Other kinds
+ of IDs can be used. Parameters may include any details about the configuration
+ like 'command', 'path', etc.
+
+ A toolset configuration may be in one of the following states:
+
+ - registered
+ Configuration has been registered (e.g. by autodetection code) but has
+ not yet been marked as used, i.e. 'toolset.using' rule has not yet been
+ called for it.
+ - used
+ Once called 'toolset.using' rule marks the configuration as 'used'.
+
+ The main difference between the states above is that while a configuration is
+ 'registered' its options can be freely changed. This is useful in particular
+ for autodetection code - all detected configurations may be safely overwritten
+ by user code.
+ """
+
+ def __init__(self):
+ self.used_ = set()
+ self.all_ = set()
+ self.params = {}
+
+ def register(self, id):
+ """
+ Registers a configuration.
+
+ Returns True if the configuration has been added and False if
+ it already exists. Reports an error if the configuration is 'used'.
+ """
+ if id in self.used_:
+ #FIXME
+ errors.error("common: the configuration '$(id)' is in use")
+
+ if id not in self.all_:
+ self.all_ += [id]
+
+ # Indicate that a new configuration has been added.
+ return True
+ else:
+ return False
+
+ def use(self, id):
+ """
+ Mark a configuration as 'used'.
+
+ Returns True if the state of the configuration has been changed to
+ 'used' and False if it the state wasn't changed. Reports an error
+ if the configuration isn't known.
+ """
+ if id not in self.all_:
+ #FIXME:
+ errors.error("common: the configuration '$(id)' is not known")
+
+ if id not in self.used_:
+ self.used_ += [id]
+
+ # indicate that the configuration has been marked as 'used'
+ return True
+ else:
+ return False
+
+ def all(self):
+ """ Return all registered configurations. """
+ return self.all_
+
+ def used(self):
+ """ Return all used configurations. """
+ return self.used_
+
+ def get(self, id, param):
+ """ Returns the value of a configuration parameter. """
+ self.params_.getdefault(param, {}).getdefault(id, None)
+
+ def set (self, id, param, value):
+ """ Sets the value of a configuration parameter. """
+ self.params_.setdefault(param, {})[id] = value
+
+# Ported from trunk@47174
+def check_init_parameters(toolset, requirement, *args):
+ """ The rule for checking toolset parameters. Trailing parameters should all be
+ parameter name/value pairs. The rule will check that each parameter either has
+ a value in each invocation or has no value in each invocation. Also, the rule
+ will check that the combination of all parameter values is unique in all
+ invocations.
+
+ Each parameter name corresponds to a subfeature. This rule will declare a
+ subfeature the first time a non-empty parameter value is passed and will
+ extend it with all the values.
+
+ The return value from this rule is a condition to be used for flags settings.
+ """
+ # The type checking here is my best guess about
+ # what the types should be.
+ assert(isinstance(toolset, str))
+ assert(isinstance(requirement, str) or requirement is None)
+ sig = toolset
+ condition = replace_grist(toolset, '<toolset>')
+ subcondition = []
+
+ for arg in args:
+ assert(isinstance(arg, tuple))
+ assert(len(arg) == 2)
+ name = arg[0]
+ value = arg[1]
+ assert(isinstance(name, str))
+ assert(isinstance(value, str) or value is None)
+
+ str_toolset_name = str((toolset, name))
+
+ # FIXME: is this the correct translation?
+ ### if $(value)-is-not-empty
+ if value is not None:
+ condition = condition + '-' + value
+ if __had_unspecified_value.has_key(str_toolset_name):
+ raise BaseException("'%s' initialization: parameter '%s' inconsistent\n" \
+ "no value was specified in earlier initialization\n" \
+ "an explicit value is specified now" % (toolset, name))
+
+ # The logic below is for intel compiler. It calls this rule
+ # with 'intel-linux' and 'intel-win' as toolset, so we need to
+ # get the base part of toolset name.
+ # We can't pass 'intel' as toolset, because it that case it will
+ # be impossible to register versionles intel-linux and
+ # intel-win of specific version.
+ t = toolset
+ m = __re__before_first_dash.match(toolset)
+ if m:
+ t = m.group(1)
+
+ if not __had_value.has_key(str_toolset_name):
+ if not __declared_subfeature.has_key(str((t, name))):
+ feature.subfeature('toolset', t, name, [], ['propagated'])
+ __declared_subfeature[str((t, name))] = True
+
+ __had_value[str_toolset_name] = True
+
+ feature.extend_subfeature('toolset', t, name, [value])
+ subcondition += ['<toolset-' + t + ':' + name + '>' + value ]
+
+ else:
+ if __had_value.has_key(str_toolset_name):
+ raise BaseException ("'%s' initialization: parameter '%s' inconsistent\n" \
+ "an explicit value was specified in an earlier initialization\n" \
+ "no value is specified now" % (toolset, name))
+
+ __had_unspecified_value[str_toolset_name] = True
+
+ if value == None: value = ''
+
+ sig = sig + value + '-'
+
+ if __all_signatures.has_key(sig):
+ message = "duplicate initialization of '%s' with the following parameters: " % toolset
+
+ for arg in args:
+ name = arg[0]
+ value = arg[1]
+ if value == None: value = '<unspecified>'
+
+ message += "'%s' = '%s'\n" % (name, value)
+
+ raise BaseException(message)
+
+ __all_signatures[sig] = True
+ # FIXME
+ __init_loc[sig] = "User location unknown" #[ errors.nearest-user-location ] ;
+
+ # If we have a requirement, this version should only be applied under that
+ # condition. To accomplish this we add a toolset requirement that imposes
+ # the toolset subcondition, which encodes the version.
+ if requirement:
+ r = ['<toolset>' + toolset, requirement]
+ r = ','.join(r)
+ toolset.add_requirements([r + ':' + c for c in subcondition])
+
+ # We add the requirements, if any, to the condition to scope the toolset
+ # variables and options to this specific version.
+ condition = [condition]
+ if requirement:
+ condition += [requirement]
+
+ if __show_configuration:
+ print "notice:", condition
+ return ['/'.join(condition)]
+
+# Ported from trunk@47077
+def get_invocation_command_nodefault(
+ toolset, tool, user_provided_command=[], additional_paths=[], path_last=False):
+ """
+ A helper rule to get the command to invoke some tool. If
+ 'user-provided-command' is not given, tries to find binary named 'tool' in
+ PATH and in the passed 'additional-path'. Otherwise, verifies that the first
+ element of 'user-provided-command' is an existing program.
+
+ This rule returns the command to be used when invoking the tool. If we can't
+ find the tool, a warning is issued. If 'path-last' is specified, PATH is
+ checked after 'additional-paths' when searching for 'tool'.
+ """
+ assert(isinstance(toolset, str))
+ assert(isinstance(tool, str))
+ assert(isinstance(user_provided_command, list))
+ if additional_paths is not None:
+ assert(isinstance(additional_paths, list))
+ assert(all([isinstance(path, str) for path in additional_paths]))
+ assert(all(isinstance(path, str) for path in additional_paths))
+ assert(isinstance(path_last, bool))
+
+ if not user_provided_command:
+ command = find_tool(tool, additional_paths, path_last)
+ if not command and __debug_configuration:
+ print "warning: toolset", toolset, "initialization: can't find tool, tool"
+ #FIXME
+ #print "warning: initialized from" [ errors.nearest-user-location ] ;
+ else:
+ command = check_tool(user_provided_command)
+ if not command and __debug_configuration:
+ print "warning: toolset", toolset, "initialization:"
+ print "warning: can't find user-provided command", user_provided_command
+ #FIXME
+ #ECHO "warning: initialized from" [ errors.nearest-user-location ]
+
+ assert(isinstance(command, str))
+
+ return command
+
+# ported from trunk@47174
+def get_invocation_command(toolset, tool, user_provided_command = [],
+ additional_paths = [], path_last = False):
+ """ Same as get_invocation_command_nodefault, except that if no tool is found,
+ returns either the user-provided-command, if present, or the 'tool' parameter.
+ """
+
+ assert(isinstance(toolset, str))
+ assert(isinstance(tool, str))
+ assert(isinstance(user_provided_command, list))
+ if additional_paths is not None:
+ assert(isinstance(additional_paths, list))
+ assert(all([isinstance(path, str) for path in additional_paths]))
+ assert(isinstance(path_last, bool))
+
+ result = get_invocation_command_nodefault(toolset, tool,
+ user_provided_command,
+ additional_paths,
+ path_last)
+
+ if not result:
+ if user_provided_command:
+ result = user_provided_command[0]
+ else:
+ result = tool
+
+ assert(isinstance(result, str))
+
+ return result
+
+# ported from trunk@47281
+def get_absolute_tool_path(command):
+ """
+ Given an invocation command,
+ return the absolute path to the command. This works even if commnad
+ has not path element and is present in PATH.
+ """
+ if os.path.dirname(command):
+ return os.path.dirname(command)
+ else:
+ programs = path.programs_path()
+ m = path.glob(programs, [command, command + '.exe' ])
+ if not len(m):
+ print "Could not find:", command, "in", programs
+ return os.path.dirname(m[0])
+
+# ported from trunk@47174
+def find_tool(name, additional_paths = [], path_last = False):
+ """ Attempts to find tool (binary) named 'name' in PATH and in
+ 'additional-paths'. If found in path, returns 'name'. If
+ found in additional paths, returns full name. If the tool
+ is found in several directories, returns the first path found.
+ Otherwise, returns the empty string. If 'path_last' is specified,
+ path is checked after 'additional_paths'.
+ """
+ assert(isinstance(name, str))
+ assert(isinstance(additional_paths, list))
+ assert(isinstance(path_last, bool))
+
+ programs = path.programs_path()
+ match = path.glob(programs, [name, name + '.exe'])
+ additional_match = path.glob(additional_paths, [name, name + '.exe'])
+
+ result = []
+ if path_last:
+ result = additional_match
+ if not result and match:
+ result = match
+
+ else:
+ if match:
+ result = match
+
+ elif additional_match:
+ result = additional_match
+
+ if result:
+ return path.native(result[0])
+ else:
+ return ''
+
+#ported from trunk@47281
+def check_tool_aux(command):
+ """ Checks if 'command' can be found either in path
+ or is a full name to an existing file.
+ """
+ assert(isinstance(command, str))
+ dirname = os.path.dirname(command)
+ if dirname:
+ if os.path.exists(command):
+ return command
+ # Both NT and Cygwin will run .exe files by their unqualified names.
+ elif on_windows() and os.path.exists(command + '.exe'):
+ return command
+ # Only NT will run .bat files by their unqualified names.
+ elif os_name() == 'NT' and os.path.exists(command + '.bat'):
+ return command
+ else:
+ paths = path.programs_path()
+ if path.glob(paths, [command]):
+ return command
+
+# ported from trunk@47281
+def check_tool(command):
+ """ Checks that a tool can be invoked by 'command'.
+ If command is not an absolute path, checks if it can be found in 'path'.
+ If comand is absolute path, check that it exists. Returns 'command'
+ if ok and empty string otherwise.
+ """
+ assert(isinstance(command, list))
+ assert(all(isinstance(c, str) for c in command))
+ #FIXME: why do we check the first and last elements????
+ if check_tool_aux(command[0]) or check_tool_aux(command[-1]):
+ return command
+
+# ported from trunk@47281
+def handle_options(tool, condition, command, options):
+ """ Handle common options for toolset, specifically sets the following
+ flag variables:
+ - CONFIG_COMMAND to 'command'
+ - OPTIOns for compile to the value of <compileflags> in options
+ - OPTIONS for compile.c to the value of <cflags> in options
+ - OPTIONS for compile.c++ to the value of <cxxflags> in options
+ - OPTIONS for compile.fortran to the value of <fflags> in options
+ - OPTIONs for link to the value of <linkflags> in options
+ """
+ from b2.build import toolset
+
+ assert(isinstance(tool, str))
+ assert(isinstance(condition, list))
+ assert(isinstance(command, str))
+ assert(isinstance(options, list))
+ assert(command)
+ toolset.flags(tool, 'CONFIG_COMMAND', condition, [command])
+ toolset.flags(tool + '.compile', 'OPTIONS', condition, feature.get_values('<compileflags>', options))
+ toolset.flags(tool + '.compile.c', 'OPTIONS', condition, feature.get_values('<cflags>', options))
+ toolset.flags(tool + '.compile.c++', 'OPTIONS', condition, feature.get_values('<cxxflags>', options))
+ toolset.flags(tool + '.compile.fortran', 'OPTIONS', condition, feature.get_values('<fflags>', options))
+ toolset.flags(tool + '.link', 'OPTIONS', condition, feature.get_values('<linkflags>', options))
+
+# ported from trunk@47281
+def get_program_files_dir():
+ """ returns the location of the "program files" directory on a windows
+ platform
+ """
+ ProgramFiles = bjam.variable("ProgramFiles")
+ if ProgramFiles:
+ ProgramFiles = ' '.join(ProgramFiles)
+ else:
+ ProgramFiles = "c:\\Program Files"
+ return ProgramFiles
+
+# ported from trunk@47281
+def rm_command():
+ return __RM
+
+# ported from trunk@47281
+def copy_command():
+ return __CP
+
+# ported from trunk@47281
+def variable_setting_command(variable, value):
+ """
+ Returns the command needed to set an environment variable on the current
+ platform. The variable setting persists through all following commands and is
+ visible in the environment seen by subsequently executed commands. In other
+ words, on Unix systems, the variable is exported, which is consistent with the
+ only possible behavior on Windows systems.
+ """
+ assert(isinstance(variable, str))
+ assert(isinstance(value, str))
+
+ if os_name() == 'NT':
+ return "set " + variable + "=" + value + os.linesep
+ else:
+ # (todo)
+ # The following does not work on CYGWIN and needs to be fixed. On
+ # CYGWIN the $(nl) variable holds a Windows new-line \r\n sequence that
+ # messes up the executed export command which then reports that the
+ # passed variable name is incorrect. This is most likely due to the
+ # extra \r character getting interpreted as a part of the variable name.
+ #
+ # Several ideas pop to mind on how to fix this:
+ # * One way would be to separate the commands using the ; shell
+ # command separator. This seems like the quickest possible
+ # solution but I do not know whether this would break code on any
+ # platforms I I have no access to.
+ # * Another would be to not use the terminating $(nl) but that would
+ # require updating all the using code so it does not simply
+ # prepend this variable to its own commands.
+ # * I guess the cleanest solution would be to update Boost Jam to
+ # allow explicitly specifying \n & \r characters in its scripts
+ # instead of always relying only on the 'current OS native newline
+ # sequence'.
+ #
+ # Some code found to depend on this behaviour:
+ # * This Boost Build module.
+ # * __test__ rule.
+ # * path-variable-setting-command rule.
+ # * python.jam toolset.
+ # * xsltproc.jam toolset.
+ # * fop.jam toolset.
+ # (todo) (07.07.2008.) (Jurko)
+ #
+ # I think that this works correctly in python -- Steven Watanabe
+ return variable + "=" + value + os.linesep + "export " + variable + os.linesep
+
+def path_variable_setting_command(variable, paths):
+ """
+ Returns a command to sets a named shell path variable to the given NATIVE
+ paths on the current platform.
+ """
+ assert(isinstance(variable, str))
+ assert(isinstance(paths, list))
+ sep = os.path.pathsep
+ return variable_setting_command(variable, sep.join(paths))
+
+def prepend_path_variable_command(variable, paths):
+ """
+ Returns a command that prepends the given paths to the named path variable on
+ the current platform.
+ """
+ return path_variable_setting_command(variable,
+ paths + os.environ.get(variable, "").split(os.pathsep))
+
+def file_creation_command():
+ """
+ Return a command which can create a file. If 'r' is result of invocation, then
+ 'r foobar' will create foobar with unspecified content. What happens if file
+ already exists is unspecified.
+ """
+ if os_name() == 'NT':
+ return "echo. > "
+ else:
+ return "touch "
+
+#FIXME: global variable
+__mkdir_set = set()
+__re_windows_drive = re.compile(r'^.*:\$')
+
+def mkdir(engine, target):
+ # If dir exists, do not update it. Do this even for $(DOT).
+ bjam.call('NOUPDATE', target)
+
+ global __mkdir_set
+
+ # FIXME: Where is DOT defined?
+ #if $(<) != $(DOT) && ! $($(<)-mkdir):
+ if target != '.' and target not in __mkdir_set:
+ # Cheesy gate to prevent multiple invocations on same dir.
+ __mkdir_set.add(target)
+
+ # Schedule the mkdir build action.
+ if os_name() == 'NT':
+ engine.set_update_action("common.MkDir1-quick-fix-for-windows", target, [])
+ else:
+ engine.set_update_action("common.MkDir1-quick-fix-for-unix", target, [])
+
+ # Prepare a Jam 'dirs' target that can be used to make the build only
+ # construct all the target directories.
+ engine.add_dependency('dirs', target)
+
+ # Recursively create parent directories. $(<:P) = $(<)'s parent & we
+ # recurse until root.
+
+ s = os.path.dirname(target)
+ if os_name() == 'NT':
+ if(__re_windows_drive.match(s)):
+ s = ''
+
+ if s:
+ if s != target:
+ engine.add_dependency(target, s)
+ mkdir(engine, s)
+ else:
+ bjam.call('NOTFILE', s)
+
+__re_version = re.compile(r'^([^.]+)[.]([^.]+)[.]?([^.]*)')
+
+def format_name(format, name, target_type, prop_set):
+ """ Given a target, as given to a custom tag rule, returns a string formatted
+ according to the passed format. Format is a list of properties that is
+ represented in the result. For each element of format the corresponding target
+ information is obtained and added to the result string. For all, but the
+ literal, the format value is taken as the as string to prepend to the output
+ to join the item to the rest of the result. If not given "-" is used as a
+ joiner.
+
+ The format options can be:
+
+ <base>[joiner]
+ :: The basename of the target name.
+ <toolset>[joiner]
+ :: The abbreviated toolset tag being used to build the target.
+ <threading>[joiner]
+ :: Indication of a multi-threaded build.
+ <runtime>[joiner]
+ :: Collective tag of the build runtime.
+ <version:/version-feature | X.Y[.Z]/>[joiner]
+ :: Short version tag taken from the given "version-feature"
+ in the build properties. Or if not present, the literal
+ value as the version number.
+ <property:/property-name/>[joiner]
+ :: Direct lookup of the given property-name value in the
+ build properties. /property-name/ is a regular expression.
+ e.g. <property:toolset-.*:flavor> will match every toolset.
+ /otherwise/
+ :: The literal value of the format argument.
+
+ For example this format:
+
+ boost_ <base> <toolset> <threading> <runtime> <version:boost-version>
+
+ Might return:
+
+ boost_thread-vc80-mt-gd-1_33.dll, or
+ boost_regex-vc80-gd-1_33.dll
+
+ The returned name also has the target type specific prefix and suffix which
+ puts it in a ready form to use as the value from a custom tag rule.
+ """
+ assert(isinstance(format, list))
+ assert(isinstance(name, str))
+ assert(isinstance(target_type, str) or not type)
+ # assert(isinstance(prop_set, property_set.PropertySet))
+ if type.is_derived(target_type, 'LIB'):
+ result = "" ;
+ for f in format:
+ grist = get_grist(f)
+ if grist == '<base>':
+ result += os.path.basename(name)
+ elif grist == '<toolset>':
+ result += join_tag(ungrist(f),
+ toolset_tag(name, target_type, prop_set))
+ elif grist == '<threading>':
+ result += join_tag(ungrist(f),
+ threading_tag(name, target_type, prop_set))
+ elif grist == '<runtime>':
+ result += join_tag(ungrist(f),
+ runtime_tag(name, target_type, prop_set))
+ elif grist.startswith('<version:'):
+ key = grist[len('<version:'):-1]
+ version = prop_set.get('<' + key + '>')
+ if not version:
+ version = key
+ version = __re_version.match(version)
+ result += join_tag(ungrist(f), version[1] + '_' + version[2])
+ elif grist.startswith('<property:'):
+ key = grist[len('<property:'):-1]
+ property_re = re.compile('<(' + key + ')>')
+ p0 = None
+ for prop in prop_set.raw():
+ match = property_re.match(prop)
+ if match:
+ p0 = match[1]
+ break
+ if p0:
+ p = prop_set.get('<' + p0 + '>')
+ if p:
+ assert(len(p) == 1)
+ result += join_tag(ungrist(f), p)
+ else:
+ result += ungrist(f)
+
+ result = virtual_target.add_prefix_and_suffix(
+ ''.join(result), target_type, prop_set)
+ return result
+
+def join_tag(joiner, tag):
+ if not joiner: joiner = '-'
+ return joiner + tag
+
+__re_toolset_version = re.compile(r"<toolset.*version>(\d+)[.](\d*)")
+
+def toolset_tag(name, target_type, prop_set):
+ tag = ''
+
+ properties = prop_set.raw()
+ tools = prop_set.get('<toolset>')
+ assert(len(tools) == 0)
+ tools = tools[0]
+ if tools.startswith('borland'): tag += 'bcb'
+ elif tools.startswith('como'): tag += 'como'
+ elif tools.startswith('cw'): tag += 'cw'
+ elif tools.startswith('darwin'): tag += 'xgcc'
+ elif tools.startswith('edg'): tag += edg
+ elif tools.startswith('gcc'):
+ flavor = prop_set.get('<toolset-gcc:flavor>')
+ ''.find
+ if flavor.find('mingw') != -1:
+ tag += 'mgw'
+ else:
+ tag += 'gcc'
+ elif tools == 'intel':
+ if prop_set.get('<toolset-intel:platform>') == ['win']:
+ tag += 'iw'
+ else:
+ tag += 'il'
+ elif tools.startswith('kcc'): tag += 'kcc'
+ elif tools.startswith('kylix'): tag += 'bck'
+ #case metrowerks* : tag += cw ;
+ #case mingw* : tag += mgw ;
+ elif tools.startswith('mipspro'): tag += 'mp'
+ elif tools.startswith('msvc'): tag += 'vc'
+ elif tools.startswith('sun'): tag += 'sw'
+ elif tools.startswith('tru64cxx'): tag += 'tru'
+ elif tools.startswith('vacpp'): tag += 'xlc'
+
+ for prop in properties:
+ match = __re_toolset_version.match(prop)
+ if(match):
+ version = match
+ break
+ version_string = None
+ # For historical reasons, vc6.0 and vc7.0 use different naming.
+ if tag == 'vc':
+ if version.group(1) == '6':
+ # Cancel minor version.
+ version_string = '6'
+ elif version.group(1) == '7' and version.group(2) == '0':
+ version_string = '7'
+
+ # On intel, version is not added, because it does not matter and it's the
+ # version of vc used as backend that matters. Ideally, we'd encode the
+ # backend version but that would break compatibility with V1.
+ elif tag == 'iw':
+ version_string = ''
+
+ # On borland, version is not added for compatibility with V1.
+ elif tag == 'bcb':
+ version_string = ''
+
+ if version_string is None:
+ version = version.group(1) + version.group(2)
+
+ tag += version
+
+ return tag
+
+
+def threading_tag(name, target_type, prop_set):
+ tag = ''
+ properties = prop_set.raw()
+ if '<threading>multi' in properties: tag = 'mt'
+
+ return tag
+
+
+def runtime_tag(name, target_type, prop_set ):
+ tag = ''
+
+ properties = prop_set.raw()
+ if '<runtime-link>static' in properties: tag += 's'
+
+ # This is an ugly thing. In V1, there's a code to automatically detect which
+ # properties affect a target. So, if <runtime-debugging> does not affect gcc
+ # toolset, the tag rules won't even see <runtime-debugging>. Similar
+ # functionality in V2 is not implemented yet, so we just check for toolsets
+ # which are known to care about runtime debug.
+ if '<toolset>msvc' in properties \
+ or '<stdlib>stlport' in properties \
+ or '<toolset-intel:platform>win' in properties:
+ if '<runtime-debugging>on' in properties: tag += 'g'
+
+ if '<python-debugging>on' in properties: tag += 'y'
+ if '<variant>debug' in properties: tag += 'd'
+ if '<stdlib>stlport' in properties: tag += 'p'
+ if '<stdlib-stlport:iostream>hostios' in properties: tag += 'n'
+
+ return tag
+
+
+## TODO:
+##rule __test__ ( )
+##{
+## import assert ;
+##
+## local nl = "
+##" ;
+##
+## local save-os = [ modules.peek os : .name ] ;
+##
+## modules.poke os : .name : LINUX ;
+##
+## assert.result "PATH=foo:bar:baz$(nl)export PATH$(nl)"
+## : path-variable-setting-command PATH : foo bar baz ;
+##
+## assert.result "PATH=foo:bar:$PATH$(nl)export PATH$(nl)"
+## : prepend-path-variable-command PATH : foo bar ;
+##
+## modules.poke os : .name : NT ;
+##
+## assert.result "set PATH=foo;bar;baz$(nl)"
+## : path-variable-setting-command PATH : foo bar baz ;
+##
+## assert.result "set PATH=foo;bar;%PATH%$(nl)"
+## : prepend-path-variable-command PATH : foo bar ;
+##
+## modules.poke os : .name : $(save-os) ;
+##}
+
+def init(manager):
+ engine = manager.engine()
+
+ engine.register_action("common.MkDir1-quick-fix-for-unix", 'mkdir -p "$(<)"')
+ engine.register_action("common.MkDir1-quick-fix-for-windows", 'if not exist "$(<)\\" mkdir "$(<)"')
+
+ import b2.tools.make
+ import b2.build.alias
+
+ global __RM, __CP, __IGNORE, __LN
+ # ported from trunk@47281
+ if os_name() == 'NT':
+ __RM = 'del /f /q'
+ __CP = 'copy'
+ __IGNORE = '2>nul >nul & setlocal'
+ __LN = __CP
+ #if not __LN:
+ # __LN = CP
+ else:
+ __RM = 'rm -f'
+ __CP = 'cp'
+ __IGNORE = ''
+ __LN = 'ln'
+
+ engine.register_action("common.Clean", __RM + ' "$(>)"',
+ flags=['piecemeal', 'together', 'existing'])
+ engine.register_action("common.copy", __CP + ' "$(>)" "$(<)"')
+ engine.register_action("common.RmTemps", __RM + ' "$(>)" ' + __IGNORE,
+ flags=['quietly', 'updated', 'piecemeal', 'together'])
+
+ engine.register_action("common.hard-link",
+ __RM + ' "$(<)" 2$(NULL_OUT) $(NULL_OUT)' + os.linesep +
+ __LN + ' "$(>)" "$(<)" $(NULL_OUT)')
diff --git a/tools/build/v2/tools/como-linux.jam b/tools/build/v2/tools/como-linux.jam
new file mode 100644
index 0000000000..5c554c8f8b
--- /dev/null
+++ b/tools/build/v2/tools/como-linux.jam
@@ -0,0 +1,103 @@
+# Copyright 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# The following #// line will be used by the regression test table generation
+# program as the column heading for HTML tables. Must not include a version
+# number.
+#//<a href="http://www.comeaucomputing.com/">Comeau<br>C++</a>
+
+import toolset ;
+import feature ;
+import toolset : flags ;
+import common ;
+import generators ;
+
+import unix ;
+import como ;
+
+feature.extend-subfeature toolset como : platform : linux ;
+
+toolset.inherit-generators como-linux
+ <toolset>como <toolset-como:platform>linux : unix ;
+generators.override como-linux.prebuilt : builtin.lib-generator ;
+generators.override como-linux.searched-lib-generator : searched-lib-generator ;
+toolset.inherit-flags como-linux : unix ;
+toolset.inherit-rules como-linux : gcc ;
+
+generators.register-c-compiler como-linux.compile.c++ : CPP : OBJ
+ : <toolset>como <toolset-como:platform>linux ;
+generators.register-c-compiler como-linux.compile.c : C : OBJ
+ : <toolset>como <toolset-como:platform>linux ;
+
+
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters como-linux
+ : version $(version) ] ;
+
+ command = [ common.get-invocation-command como-linux : como
+ : $(command) ] ;
+
+ common.handle-options como-linux : $(condition) : $(command) : $(options) ;
+}
+
+
+flags como-linux C++FLAGS <exception-handling>off : --no_exceptions ;
+flags como-linux C++FLAGS <exception-handling>on : --exceptions ;
+
+flags como-linux CFLAGS <inlining>off : --no_inlining ;
+flags como-linux CFLAGS <inlining>on <inlining>full : --inlining ;
+
+flags como-linux CFLAGS <optimization>off : -O0 ;
+flags como-linux CFLAGS <optimization>speed : -O3 ;
+flags como-linux CFLAGS <optimization>space : -Os ;
+
+flags como-linux CFLAGS <debug-symbols>on : -g ;
+flags como-linux LINKFLAGS <debug-symbols>on : -g ;
+
+flags como-linux FINDLIBS : m ;
+flags como-linux FINDLIBS : rt ;
+
+flags como-linux CFLAGS <cflags> ;
+flags como-linux C++FLAGS <cxxflags> ;
+flags como-linux DEFINES <define> ;
+flags como-linux UNDEFS <undef> ;
+flags como-linux HDRS <include> ;
+flags como-linux STDHDRS <sysinclude> ;
+flags como-linux LINKFLAGS <linkflags> ;
+flags como-linux ARFLAGS <arflags> ;
+
+flags como-linux.link LIBRARIES <library-file> ;
+flags como-linux.link LINKPATH <library-path> ;
+flags como-linux.link FINDLIBS-ST <find-static-library> ;
+flags como-linux.link FINDLIBS-SA <find-shared-library> ;
+
+flags como-linux.link RPATH <dll-path> ;
+flags como-linux.link RPATH_LINK <xdll-path> ;
+
+
+actions link bind LIBRARIES
+{
+ $(CONFIG_COMMAND) $(LINKFLAGS) -o "$(<[1])" "$(>)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" "$(LIBRARIES)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) 2>&1
+}
+
+actions link.dll bind LIBRARIES
+{
+ $(CONFIG_COMMAND) $(LINKFLAGS) -shared -o "$(<[1])" "$(>)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" "$(LIBRARIES)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) 2>&1
+}
+
+actions compile.c
+{
+ $(CONFIG_COMMAND) -c --c99 --long_long -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o "$(<)" "$(>)" 2>&1
+}
+
+actions compile.c++
+{
+ $(CONFIG_COMMAND) -tused -c --long_long -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o "$(<)" "$(>)" 2>&1
+}
+
+actions archive
+{
+ ar rcu $(<) $(>)
+}
diff --git a/tools/build/v2/tools/como-win.jam b/tools/build/v2/tools/como-win.jam
new file mode 100644
index 0000000000..d21a70d6f1
--- /dev/null
+++ b/tools/build/v2/tools/como-win.jam
@@ -0,0 +1,117 @@
+# (C) Copyright David Abrahams 2001.
+# (C) Copyright MetaCommunications, Inc. 2004.
+
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# The following #// line will be used by the regression test table generation
+# program as the column heading for HTML tables. Must not include a version
+# number.
+#//<a href="http://www.comeaucomputing.com/">Comeau<br>C++</a>
+
+import common ;
+import como ;
+import feature ;
+import generators ;
+import toolset : flags ;
+
+feature.extend-subfeature toolset como : platform : win ;
+
+
+# Initializes the Comeau toolset for windows. The command is the command which
+# invokes the compiler. You should either set environment variable
+# COMO_XXX_INCLUDE where XXX is the used backend (as described in the
+# documentation), or pass that as part of command, e.g:
+#
+# using como-win : 4.3 : "set COMO_BCC_INCLUDE=C:/include &&" como.exe ;
+#
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters como-win
+ : version $(version) ] ;
+
+ command = [ common.get-invocation-command como-win : como.exe :
+ $(command) ] ;
+
+ common.handle-options como-win : $(condition) : $(command) : $(options) ;
+}
+
+generators.register-c-compiler como-win.compile.c++ : CPP : OBJ
+ : <toolset>como <toolset-como:platform>win ;
+generators.register-c-compiler como-win.compile.c : C : OBJ
+ : <toolset>como <toolset-como:platform>win ;
+
+
+generators.register-linker como-win.link
+ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB
+ : EXE
+ : <toolset>como <toolset-como:platform>win ;
+
+# Note that status of shared libraries support is not clear, so we do not define
+# the link.dll generator.
+generators.register-archiver como-win.archive
+ : OBJ : STATIC_LIB
+ : <toolset>como <toolset-como:platform>win ;
+
+
+flags como-win C++FLAGS <exception-handling>off : --no_exceptions ;
+flags como-win C++FLAGS <exception-handling>on : --exceptions ;
+
+flags como-win CFLAGS <inlining>off : --no_inlining ;
+flags como-win CFLAGS <inlining>on <inlining>full : --inlining ;
+
+
+# The following seems to be VC-specific options. At least, when I uncomment
+# then, Comeau with bcc as backend reports that bcc32 invocation failed.
+#
+#flags como-win CFLAGS <debug-symbols>on : /Zi ;
+#flags como-win CFLAGS <optimization>off : /Od ;
+
+
+flags como-win CFLAGS <cflags> ;
+flags como-win CFLAGS : -D_WIN32 ; # Make sure that we get the Boost Win32 platform config header.
+flags como-win CFLAGS <threading>multi : -D_MT ; # Make sure that our config knows that threading is on.
+flags como-win C++FLAGS <cxxflags> ;
+flags como-win DEFINES <define> ;
+flags como-win UNDEFS <undef> ;
+flags como-win HDRS <include> ;
+flags como-win SYSHDRS <sysinclude> ;
+flags como-win LINKFLAGS <linkflags> ;
+flags como-win ARFLAGS <arflags> ;
+flags como-win NO_WARN <no-warn> ;
+
+#flags como-win STDHDRS : $(COMO_INCLUDE_PATH) ;
+#flags como-win STDLIB_PATH : $(COMO_STDLIB_PATH)$(SLASH) ;
+
+flags como-win LIBPATH <library-path> ;
+flags como-win LIBRARIES <library-file> ;
+flags como-win FINDLIBS <find-shared-library> ;
+flags como-win FINDLIBS <find-static-library> ;
+
+nl = "
+" ;
+
+
+# For como, we repeat all libraries so that dependencies are always resolved.
+#
+actions link bind LIBRARIES
+{
+ $(CONFIG_COMMAND) --no_version --no_prelink_verbose $(LINKFLAGS) -o "$(<[1]:S=)" @"@($(<[1]:W).rsp:E=$(nl)"$(>)")" "$(LIBRARIES)" "$(FINDLIBS:S=.lib)"
+}
+
+actions compile.c
+{
+ $(CONFIG_COMMAND) -c --c99 -e5 --no_version --display_error_number --diag_suppress=9,21,161,748,940,962 -U$(UNDEFS) -D$(DEFINES) $(WARN) $(CFLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -I"$(SYSHDRS)" -o "$(<:D=)" "$(>)"
+}
+
+actions compile.c++
+{
+ $(CONFIG_COMMAND) -c -e5 --no_version --no_prelink_verbose --display_error_number --long_long --diag_suppress=9,21,161,748,940,962 --diag_error=461 -D__STL_LONG_LONG -U$(UNDEFS) -D$(DEFINES) $(WARN) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -I"$(SYSHDRS)" -o "$(<)" "$(>)"
+}
+
+actions archive
+{
+ $(CONFIG_COMMAND) --no_version --no_prelink_verbose --prelink_object @"@($(<[1]:W).rsp:E=$(nl)"$(>)")"
+ lib $(ARFLAGS) /nologo /out:"$(<:S=.lib)" @"@($(<[1]:W).rsp:E=$(nl)"$(>)")"
+}
diff --git a/tools/build/v2/tools/como.jam b/tools/build/v2/tools/como.jam
new file mode 100644
index 0000000000..04a05a94b1
--- /dev/null
+++ b/tools/build/v2/tools/como.jam
@@ -0,0 +1,29 @@
+# Copyright Vladimir Prus 2004.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# This is a generic 'como' toolset. Depending on the current system, it
+# forwards either to 'como-linux' or 'como-win' modules.
+
+import feature ;
+import os ;
+import toolset ;
+
+feature.extend toolset : como ;
+feature.subfeature toolset como : platform : : propagated link-incompatible ;
+
+rule init ( * : * )
+{
+ if [ os.name ] = LINUX
+ {
+ toolset.using como-linux :
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+ else
+ {
+ toolset.using como-win :
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+
+ }
+}
diff --git a/tools/build/v2/tools/convert.jam b/tools/build/v2/tools/convert.jam
new file mode 100644
index 0000000000..ac1d701015
--- /dev/null
+++ b/tools/build/v2/tools/convert.jam
@@ -0,0 +1,62 @@
+# Copyright (c) 2009 Vladimir Prus
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Implements 'convert' target that takes a bunch of source and
+# tries to convert each one to the specified type.
+#
+# For example:
+#
+# convert objects obj : a.cpp b.cpp ;
+#
+
+import targets ;
+import generators ;
+import project ;
+import type ;
+import "class" : new ;
+
+class convert-target-class : typed-target
+{
+ rule __init__ ( name : project : type
+ : sources * : requirements * : default-build * : usage-requirements * )
+ {
+ typed-target.__init__ $(name) : $(project) : $(type)
+ : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ;
+ }
+
+ rule construct ( name : source-targets * : property-set )
+ {
+ local r = [ generators.construct $(self.project) : $(self.type)
+ : [ property-set.create [ $(property-set).raw ] # [ feature.expand
+ <main-target-type>$(self.type) ]
+ # ]
+ : $(source-targets) ] ;
+ if ! $(r)
+ {
+ errors.error "unable to construct" [ full-name ] ;
+ }
+
+ return $(r) ;
+ }
+
+}
+
+rule convert ( name type : sources * : requirements * : default-build *
+ : usage-requirements * )
+{
+ local project = [ project.current ] ;
+
+ # This is a circular module dependency, so it must be imported here
+ modules.import targets ;
+ targets.main-target-alternative
+ [ new convert-target-class $(name) : $(project) : [ type.type-from-rule-name $(type) ]
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
+ ] ;
+}
+IMPORT $(__name__) : convert : : convert ;
diff --git a/tools/build/v2/tools/cw-config.jam b/tools/build/v2/tools/cw-config.jam
new file mode 100644
index 0000000000..1211b7c049
--- /dev/null
+++ b/tools/build/v2/tools/cw-config.jam
@@ -0,0 +1,34 @@
+#~ Copyright 2005 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Automatic configuration for CodeWarrior toolset. To use, just import this module.
+
+import os ;
+import toolset : using ;
+
+if [ os.name ] = NT
+{
+ for local R in 9 8 7
+ {
+ local cw-path = [ W32_GETREG
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Metrowerks\\CodeWarrior\\Product Versions\\CodeWarrior for Windows R$(R)"
+ : "PATH" ] ;
+ local cw-version = [ W32_GETREG
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Metrowerks\\CodeWarrior\\Product Versions\\CodeWarrior for Windows R$(R)"
+ : "VERSION" ] ;
+ cw-path ?= [ W32_GETREG
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Metrowerks\\CodeWarrior for Windows\\$(R).0"
+ : "PATH" ] ;
+ cw-version ?= $(R).0 ;
+
+ if $(cw-path)
+ {
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice:" using cw ":" $(cw-version) ":" "$(cw-path)\\Other Metrowerks Tools\\Command Line Tools\\mwcc.exe" ;
+ }
+ using cw : $(cw-version) : "$(cw-path)\\Other Metrowerks Tools\\Command Line Tools\\mwcc.exe" ;
+ }
+ }
+}
diff --git a/tools/build/v2/tools/cw.jam b/tools/build/v2/tools/cw.jam
new file mode 100644
index 0000000000..ddcbfeb2b6
--- /dev/null
+++ b/tools/build/v2/tools/cw.jam
@@ -0,0 +1,246 @@
+# Copyright (C) Reece H Dunn 2004
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# based on the msvc.jam toolset
+
+import property ;
+import generators ;
+import os ;
+import type ;
+import toolset : flags ;
+import errors : error ;
+import feature : feature get-values ;
+import path ;
+import sequence : unique ;
+import common ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+feature.extend toolset : cw ;
+
+toolset.add-requirements <toolset>cw,<runtime-link>shared:<threading>multi ;
+
+nl = "
+" ;
+
+rule init ( version ? : command * : options * )
+{
+ # TODO: fix the $(command[1]) = $(compiler) issue
+
+ setup = [ get-values <setup> : $(options) ] ;
+ setup ?= cwenv.bat ;
+ compiler = [ get-values <compiler> : $(options) ] ;
+ compiler ?= mwcc ;
+ linker = [ get-values <linker> : $(options) ] ;
+ linker ?= mwld ;
+
+ local condition = [ common.check-init-parameters cw :
+ version $(version) ] ;
+
+ command = [ common.get-invocation-command cw : mwcc.exe : $(command) :
+ [ default-paths $(version) ] ] ;
+
+ common.handle-options cw : $(condition) : $(command) : $(options) ;
+
+ local root = [ feature.get-values <root> : $(options) ] ;
+ if $(command)
+ {
+ command = [ common.get-absolute-tool-path $(command[-1]) ] ;
+ }
+ local tool-root = $(command) ;
+
+ setup = $(tool-root)\\$(setup) ;
+
+ # map the batch file in setup so it can be executed
+
+ other-tools = $(tool-root:D) ;
+ root ?= $(other-tools:D) ;
+
+ flags cw.link RUN_PATH $(condition) :
+ "$(root)\\Win32-x86 Support\\Libraries\\Runtime"
+ "$(root)\\Win32-x86 Support\\Libraries\\Runtime\\Libs\\MSL_All-DLLs" ;
+
+ setup = "set \"CWFOLDER="$(root)"\" && call \""$(setup)"\" > nul " ;
+
+ if [ os.name ] = NT
+ {
+ setup = $(setup)"
+" ;
+ }
+ else
+ {
+ setup = "cmd /S /C "$(setup)" \"&&\" " ;
+ }
+
+ # bind the setup command to the tool so it can be executed before the
+ # command
+
+ local prefix = $(setup) ;
+
+ flags cw.compile .CC $(condition) : $(prefix)$(compiler) ;
+ flags cw.link .LD $(condition) : $(prefix)$(linker) ;
+ flags cw.archive .LD $(condition) : $(prefix)$(linker) ;
+
+ if [ MATCH ^([89]\\.) : $(version) ]
+ {
+ if [ os.name ] = NT
+ {
+ # The runtime libraries
+ flags cw.compile CFLAGS <runtime-link>static/<threading>single/<runtime-debugging>off : -runtime ss ;
+ flags cw.compile CFLAGS <runtime-link>static/<threading>single/<runtime-debugging>on : -runtime ssd ;
+
+ flags cw.compile CFLAGS <runtime-link>static/<threading>multi/<runtime-debugging>off : -runtime sm ;
+ flags cw.compile CFLAGS <runtime-link>static/<threading>multi/<runtime-debugging>on : -runtime smd ;
+
+ flags cw.compile CFLAGS <runtime-link>shared/<runtime-debugging>off : -runtime dm ;
+ flags cw.compile CFLAGS <runtime-link>shared/<runtime-debugging>on : -runtime dmd ;
+ }
+ }
+}
+
+
+local rule default-paths ( version ? ) # FIXME
+{
+ local possible-paths ;
+ local ProgramFiles = [ common.get-program-files-dir ] ;
+
+ # TODO: add support for cw8 and cw9 detection
+
+ local version-6-path = $(ProgramFiles)"\\Metrowerks\\CodeWarrior" ;
+ possible-paths += $(version-6-path) ;
+
+ # perform post-processing
+
+ possible-paths
+ = $(possible-paths)"\\Other Metrowerks Tools\\Command Line Tools" ;
+
+ possible-paths += [ modules.peek : PATH Path path ] ;
+
+ return $(possible-paths) ;
+}
+
+
+
+
+## declare generators
+
+generators.register-c-compiler cw.compile.c++ : CPP : OBJ : <toolset>cw ;
+generators.register-c-compiler cw.compile.c : C : OBJ : <toolset>cw ;
+
+generators.register-linker cw.link
+ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB
+ : EXE
+ : <toolset>cw
+ ;
+generators.register-linker cw.link.dll
+ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB
+ : SHARED_LIB IMPORT_LIB
+ : <toolset>cw
+ ;
+
+generators.register-archiver cw.archive
+ : OBJ
+ : STATIC_LIB
+ : <toolset>cw
+ ;
+
+## compilation phase
+
+flags cw WHATEVER <toolset-cw:version> ;
+
+flags cw.compile CFLAGS <debug-symbols>on : -g ;
+flags cw.compile CFLAGS <optimization>off : -O0 ;
+flags cw.compile CFLAGS <optimization>speed : -O4,p ;
+flags cw.compile CFLAGS <optimization>space : -O4,s ;
+flags cw.compile CFLAGS <inlining>off : -inline off ;
+flags cw.compile CFLAGS <inlining>on : -inline on ;
+flags cw.compile CFLAGS <inlining>full : -inline all ;
+flags cw.compile CFLAGS <exception-handling>off : -Cpp_exceptions off ;
+
+
+flags cw.compile CFLAGS <rtti>on : -RTTI on ;
+flags cw.compile CFLAGS <rtti>off : -RTTI off ;
+
+flags cw.compile CFLAGS <warnings>on : -w on ;
+flags cw.compile CFLAGS <warnings>off : -w off ;
+flags cw.compile CFLAGS <warnings>all : -w all ;
+flags cw.compile CFLAGS <warnings-as-errors>on : -w error ;
+
+flags cw.compile USER_CFLAGS <cflags> : ;
+flags cw.compile.c++ USER_CFLAGS <cxxflags> : ;
+
+flags cw.compile DEFINES <define> ;
+flags cw.compile UNDEFS <undef> ;
+flags cw.compile INCLUDES <include> ;
+
+actions compile.c
+{
+ $(.CC) -c -cwd include -lang c -U$(UNDEFS) $(CFLAGS) $(USER_CFLAGS) -I- -o "$(<)" @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)-D$(DEFINES) $(nl)"-I$(INCLUDES)")"
+}
+actions compile.c++
+{
+ $(.CC) -c -cwd include -lang c++ -U$(UNDEFS) $(CFLAGS) $(USER_CFLAGS) -I- -o "$(<)" @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)-D$(DEFINES) $(nl)"-I$(INCLUDES)")"
+}
+
+## linking phase
+
+flags cw.link DEF_FILE <def-file> ;
+
+flags cw LINKFLAGS : -search ;
+flags cw LINKFLAGS <debug-symbols>on : -g ;
+flags cw LINKFLAGS <user-interface>console : -subsystem console ;
+flags cw LINKFLAGS <user-interface>gui : -subsystem windows ;
+flags cw LINKFLAGS <user-interface>wince : -subsystem wince ;
+flags cw LINKFLAGS <user-interface>native : -subsystem native ;
+flags cw LINKFLAGS <user-interface>auto : -subsystem auto ;
+
+flags cw LINKFLAGS <main-target-type>LIB/<link>static : -library ;
+
+flags cw.link USER_LINKFLAGS <linkflags> ;
+flags cw.link LINKPATH <library-path> ;
+
+flags cw.link FINDLIBS_ST <find-static-library> ;
+flags cw.link FINDLIBS_SA <find-shared-library> ;
+flags cw.link LIBRARY_OPTION <toolset>cw : "" : unchecked ;
+flags cw.link LIBRARIES_MENTIONED_BY_FILE : <library-file> ;
+
+rule link.dll ( targets + : sources * : properties * )
+{
+ DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
+}
+
+if [ os.name ] in NT
+{
+ actions archive
+ {
+ if exist "$(<[1])" DEL "$(<[1])"
+ $(.LD) -library -o "$(<[1])" @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")"
+ }
+}
+else # cygwin
+{
+ actions archive
+ {
+ _bbv2_out_="$(<)"
+ if test -f "$_bbv2_out_" ; then
+ _bbv2_existing_="$(<:W)"
+ fi
+ $(.LD) -library -o "$(<:W)" $_bbv2_existing_ @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")"
+ }
+}
+
+actions link bind DEF_FILE
+{
+ $(.LD) -o "$(<[1]:W)" -L"$(LINKPATH)" $(LINKFLAGS) $(USER_LINKFLAGS) @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")"
+}
+
+actions link.dll bind DEF_FILE
+{
+ $(.LD) -shared -o "$(<[1]:W)" -implib "$(<[2]:W)" -L"$(LINKPATH)" $(LINKFLAGS) -f"$(DEF_FILE)" $(USER_LINKFLAGS) @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")"
+}
+
diff --git a/tools/build/v2/tools/darwin.jam b/tools/build/v2/tools/darwin.jam
new file mode 100644
index 0000000000..283dface94
--- /dev/null
+++ b/tools/build/v2/tools/darwin.jam
@@ -0,0 +1,568 @@
+# Copyright 2003 Christopher Currie
+# Copyright 2006 Dave Abrahams
+# Copyright 2003, 2004, 2005, 2006 Vladimir Prus
+# Copyright 2005-2007 Mat Marcus
+# Copyright 2005-2007 Adobe Systems Incorporated
+# Copyright 2007-2010 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Please see http://article.gmane.org/gmane.comp.lib.boost.build/3389/
+# for explanation why it's a separate toolset.
+
+import feature : feature ;
+import toolset : flags ;
+import type ;
+import common ;
+import generators ;
+import path : basename ;
+import version ;
+import property-set ;
+import regex ;
+import errors ;
+
+## Use a framework.
+feature framework : : free ;
+
+## The MacOSX version to compile for, which maps to the SDK to use (sysroot).
+feature macosx-version : : propagated link-incompatible symmetric optional ;
+
+## The minimal MacOSX version to target.
+feature macosx-version-min : : propagated optional ;
+
+## A dependency, that is forced to be included in the link.
+feature force-load : : free dependency incidental ;
+
+#############################################################################
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+feature.extend toolset : darwin ;
+import gcc ;
+toolset.inherit-generators darwin : gcc : gcc.mingw.link gcc.mingw.link.dll ;
+
+generators.override darwin.prebuilt : builtin.prebuilt ;
+generators.override darwin.searched-lib-generator : searched-lib-generator ;
+
+# Override default do-nothing generators.
+generators.override darwin.compile.c.pch : pch.default-c-pch-generator ;
+generators.override darwin.compile.c++.pch : pch.default-cpp-pch-generator ;
+
+type.set-generated-target-suffix PCH : <toolset>darwin : gch ;
+
+toolset.inherit-rules darwin : gcc : localize ;
+toolset.inherit-flags darwin : gcc
+ : <runtime-link>static
+ <architecture>arm/<address-model>32
+ <architecture>arm/<address-model>64
+ <architecture>arm/<instruction-set>
+ <architecture>x86/<address-model>32
+ <architecture>x86/<address-model>64
+ <architecture>x86/<instruction-set>
+ <architecture>power/<address-model>32
+ <architecture>power/<address-model>64
+ <architecture>power/<instruction-set> ;
+
+# Options:
+#
+# <root>PATH
+# Platform root path. The common autodetection will set this to
+# "/Developer". And when a command is given it will be set to
+# the corresponding "*.platform/Developer" directory.
+#
+rule init ( version ? : command * : options * : requirement * )
+{
+ # First time around, figure what is host OSX version
+ if ! $(.host-osx-version)
+ {
+ .host-osx-version = [ MATCH "^([0-9.]+)"
+ : [ SHELL "/usr/bin/sw_vers -productVersion" ] ] ;
+ if $(.debug-configuration)
+ {
+ ECHO notice: OSX version on this machine is $(.host-osx-version) ;
+ }
+ }
+
+ # - The root directory of the tool install.
+ local root = [ feature.get-values <root> : $(options) ] ;
+
+ # - The bin directory where to find the commands to execute.
+ local bin ;
+
+ # - The configured compile driver command.
+ local command = [ common.get-invocation-command darwin : g++ : $(command) ] ;
+
+ # The version as reported by the compiler
+ local real-version ;
+
+ # - Autodetect the root and bin dir if not given.
+ if $(command)
+ {
+ bin ?= [ common.get-absolute-tool-path $(command[1]) ] ;
+ if $(bin) = "/usr/bin"
+ {
+ root ?= /Developer ;
+ }
+ else
+ {
+ local r = $(bin:D) ;
+ r = $(r:D) ;
+ root ?= $(r) ;
+ }
+ }
+
+ # - Autodetect the version if not given.
+ if $(command)
+ {
+ # - The 'command' variable can have multiple elements. When calling
+ # the SHELL builtin we need a single string.
+ local command-string = $(command:J=" ") ;
+ real-version = [ MATCH "^([0-9.]+)"
+ : [ SHELL "$(command-string) -dumpversion" ] ] ;
+ version ?= $(real-version) ;
+ }
+
+ .real-version.$(version) = $(real-version) ;
+
+ # - Define the condition for this toolset instance.
+ local condition =
+ [ common.check-init-parameters darwin $(requirement) : version $(version) ] ;
+
+ # - Set the toolset generic common options.
+ common.handle-options darwin : $(condition) : $(command) : $(options) ;
+
+ # - GCC 4.0 and higher in Darwin does not have -fcoalesce-templates.
+ if $(real-version) < "4.0.0"
+ {
+ flags darwin.compile.c++ OPTIONS $(condition) : -fcoalesce-templates ;
+ }
+ # - GCC 4.2 and higher in Darwin does not have -Wno-long-double.
+ if $(real-version) < "4.2.0"
+ {
+ flags darwin.compile OPTIONS $(condition) : -Wno-long-double ;
+ }
+
+ # - Set the link flags common with the GCC toolset.
+ gcc.init-link-flags darwin darwin $(condition) ;
+
+ # - The symbol strip program.
+ local strip ;
+ if <striper> in $(options)
+ {
+ # We can turn off strip by specifying it as empty. In which
+ # case we switch to using the linker to do the strip.
+ flags darwin.link.dll OPTIONS
+ $(condition)/<main-target-type>LIB/<link>shared/<address-model>32/<strip>on : -Wl,-x ;
+ flags darwin.link.dll OPTIONS
+ $(condition)/<main-target-type>LIB/<link>shared/<address-model>/<strip>on : -Wl,-x ;
+ flags darwin.link OPTIONS
+ $(condition)/<main-target-type>EXE/<address-model>32/<strip>on : -s ;
+ flags darwin.link OPTIONS
+ $(condition)/<main-target-type>EXE/<address-model>/<strip>on : -s ;
+ }
+ else
+ {
+ # Otherwise we need to find a strip program to use. And hence
+ # also tell the link action that we need to use a strip
+ # post-process.
+ flags darwin.link NEED_STRIP $(condition)/<strip>on : "" ;
+ strip =
+ [ common.get-invocation-command darwin
+ : strip : [ feature.get-values <striper> : $(options) ] : $(bin) : search-path ] ;
+ flags darwin.link .STRIP $(condition) : $(strip[1]) ;
+ if $(.debug-configuration)
+ {
+ ECHO notice: using strip for $(condition) at $(strip[1]) ;
+ }
+ }
+
+ # - The archive builder (libtool is the default as creating
+ # archives in darwin is complicated.
+ local archiver =
+ [ common.get-invocation-command darwin
+ : libtool : [ feature.get-values <archiver> : $(options) ] : $(bin) : search-path ] ;
+ flags darwin.archive .LIBTOOL $(condition) : $(archiver[1]) ;
+ if $(.debug-configuration)
+ {
+ ECHO notice: using archiver for $(condition) at $(archiver[1]) ;
+ }
+
+ # - Initialize the SDKs available in the root for this tool.
+ local sdks = [ init-available-sdk-versions $(condition) : $(root) ] ;
+
+ #~ ECHO --- ;
+ #~ ECHO --- bin :: $(bin) ;
+ #~ ECHO --- root :: $(root) ;
+ #~ ECHO --- version :: $(version) ;
+ #~ ECHO --- condition :: $(condition) ;
+ #~ ECHO --- strip :: $(strip) ;
+ #~ ECHO --- archiver :: $(archiver) ;
+ #~ ECHO --- sdks :: $(sdks) ;
+ #~ ECHO --- ;
+ #~ EXIT ;
+}
+
+# Add and set options for a discovered SDK version.
+local rule init-sdk ( condition * : root ? : version + : version-feature ? )
+{
+ local rule version-to-feature ( version + )
+ {
+ switch $(version[1])
+ {
+ case iphone* :
+ {
+ return $(version[1])-$(version[2-]:J=.) ;
+ }
+ case mac* :
+ {
+ return $(version[2-]:J=.) ;
+ }
+ case * :
+ {
+ return $(version:J=.) ;
+ }
+ }
+ }
+
+ if $(version-feature)
+ {
+ if $(.debug-configuration)
+ {
+ ECHO notice: available sdk for $(condition)/<macosx-version>$(version-feature) at $(sdk) ;
+ }
+
+ # Add the version to the features for specifying them.
+ if ! $(version-feature) in [ feature.values macosx-version ]
+ {
+ feature.extend macosx-version : $(version-feature) ;
+ }
+ if ! $(version-feature) in [ feature.values macosx-version-min ]
+ {
+ feature.extend macosx-version-min : $(version-feature) ;
+ }
+
+ # Set the flags the version needs to compile with, first
+ # generic options.
+ flags darwin.compile OPTIONS $(condition)/<macosx-version>$(version-feature)
+ : -isysroot $(sdk) ;
+ flags darwin.link OPTIONS $(condition)/<macosx-version>$(version-feature)
+ : -isysroot $(sdk) ;
+
+ # Then device variation options.
+ switch $(version[1])
+ {
+ case iphonesim* :
+ {
+ local N = $(version[2]) ;
+ if ! $(version[3]) { N += 00 ; }
+ else if [ regex.match (..) : $(version[3]) ] { N += $(version[3]) ; }
+ else { N += 0$(version[3]) ; }
+ if ! $(version[4]) { N += 00 ; }
+ else if [ regex.match (..) : $(version[4]) ] { N += $(version[4]) ; }
+ else { N += 0$(version[4]) ; }
+ N = $(N:J=) ;
+ flags darwin.compile OPTIONS <macosx-version-min>$(version-feature)
+ : -D__IPHONE_OS_VERSION_MIN_REQUIRED=$(N) ;
+ flags darwin.link OPTIONS <macosx-version-min>$(version-feature)
+ : -D__IPHONE_OS_VERSION_MIN_REQUIRED=$(N) ;
+ }
+
+ case iphone* :
+ {
+ flags darwin.compile OPTIONS <macosx-version-min>$(version-feature)
+ : -miphoneos-version-min=$(version[2-]:J=.) ;
+ flags darwin.link OPTIONS <macosx-version-min>$(version-feature)
+ : -miphoneos-version-min=$(version[2-]:J=.) ;
+ }
+
+ case mac* :
+ {
+ flags darwin.compile OPTIONS <macosx-version-min>$(version-feature)
+ : -mmacosx-version-min=$(version[2-]:J=.) ;
+ flags darwin.link OPTIONS <macosx-version-min>$(version-feature)
+ : -mmacosx-version-min=$(version[2-]:J=.) ;
+ }
+ }
+
+ return $(version-feature) ;
+ }
+ else if $(version[4])
+ {
+ # We have a patch version of an SDK. We want to set up
+ # both the specific patch version, and the minor version.
+ # So we recurse to set up the minor version. Plus the minor version.
+ return
+ [ init-sdk $(condition) : $(root)
+ : $(version[1-3]) : [ version-to-feature $(version[1-3]) ] ]
+ [ init-sdk $(condition) : $(root)
+ : $(version) : [ version-to-feature $(version) ] ] ;
+ }
+ else
+ {
+ # Yes, this is intentionally recursive.
+ return
+ [ init-sdk $(condition) : $(root)
+ : $(version) : [ version-to-feature $(version) ] ] ;
+ }
+}
+
+# Determine the MacOSX SDK versions installed and their locations.
+local rule init-available-sdk-versions ( condition * : root ? )
+{
+ root ?= /Developer ;
+ local sdks-root = $(root)/SDKs ;
+ local sdks = [ GLOB $(sdks-root) : MacOSX*.sdk iPhoneOS*.sdk iPhoneSimulator*.sdk ] ;
+ local result ;
+ for local sdk in $(sdks)
+ {
+ local sdk-match = [ MATCH ([^0-9]+)([0-9]+)[.]([0-9x]+)[.]?([0-9x]+)? : $(sdk:D=) ] ;
+ local sdk-platform = $(sdk-match[1]:L) ;
+ local sdk-version = $(sdk-match[2-]) ;
+ if $(sdk-version)
+ {
+ switch $(sdk-platform)
+ {
+ case macosx :
+ {
+ sdk-version = mac $(sdk-version) ;
+ }
+ case iphoneos :
+ {
+ sdk-version = iphone $(sdk-version) ;
+ }
+ case iphonesimulator :
+ {
+ sdk-version = iphonesim $(sdk-version) ;
+ }
+ case * :
+ {
+ sdk-version = $(sdk-version:J=-) ;
+ }
+ }
+ result += [ init-sdk $(condition) : $(sdk) : $(sdk-version) ] ;
+ }
+ }
+ return $(result) ;
+}
+
+# Generic options.
+flags darwin.compile OPTIONS <flags> ;
+
+# The following adds objective-c support to darwin.
+# Thanks to http://thread.gmane.org/gmane.comp.lib.boost.build/13759
+
+generators.register-c-compiler darwin.compile.m : OBJECTIVE_C : OBJ : <toolset>darwin ;
+generators.register-c-compiler darwin.compile.mm : OBJECTIVE_CPP : OBJ : <toolset>darwin ;
+
+rule setup-address-model ( targets * : sources * : properties * )
+{
+ local ps = [ property-set.create $(properties) ] ;
+ local arch = [ $(ps).get <architecture> ] ;
+ local address-model = [ $(ps).get <address-model> ] ;
+ local osx-version = [ $(ps).get <macosx-version> ] ;
+ local gcc-version = [ $(ps).get <toolset-darwin:version> ] ;
+ gcc-version = $(.real-version.$(gcc-version)) ;
+ local options ;
+
+ local support-ppc64 = 1 ;
+
+ osx-version ?= $(.host-osx-version) ;
+
+ switch $(osx-version)
+ {
+ case iphone* :
+ {
+ support-ppc64 = ;
+ }
+
+ case * :
+ if $(osx-version) && ! [ version.version-less [ regex.split $(osx-version) \\. ] : 10 6 ]
+ {
+ # When targeting 10.6:
+ # - gcc 4.2 will give a compiler errir if ppc64 compilation is requested
+ # - gcc 4.0 will compile fine, somehow, but then fail at link time
+ support-ppc64 = ;
+ }
+ }
+ switch $(arch)
+ {
+ case combined :
+ {
+ if $(address-model) = 32_64 {
+ if $(support-ppc64) {
+ options = -arch i386 -arch ppc -arch x86_64 -arch ppc64 ;
+ } else {
+ # Build 3-way binary
+ options = -arch i386 -arch ppc -arch x86_64 ;
+ }
+ } else if $(address-model) = 64 {
+ if $(support-ppc64) {
+ options = -arch x86_64 -arch ppc64 ;
+ } else {
+ errors.user-error "64-bit PPC compilation is not supported when targeting OSX 10.6 or later" ;
+ }
+ } else {
+ options = -arch i386 -arch ppc ;
+ }
+ }
+
+ case x86 :
+ {
+ if $(address-model) = 32_64 {
+ options = -arch i386 -arch x86_64 ;
+ } else if $(address-model) = 64 {
+ options = -arch x86_64 ;
+ } else {
+ options = -arch i386 ;
+ }
+ }
+
+ case power :
+ {
+ if ! $(support-ppc64)
+ && ( $(address-model) = 32_64 || $(address-model) = 64 )
+ {
+ errors.user-error "64-bit PPC compilation is not supported when targeting OSX 10.6 or later" ;
+ }
+
+ if $(address-model) = 32_64 {
+ options = -arch ppc -arch ppc64 ;
+ } else if $(address-model) = 64 {
+ options = -arch ppc64 ;
+ } else {
+ options = -arch ppc ;
+ }
+ }
+
+ case arm :
+ {
+ options = -arch armv6 ;
+ }
+ }
+
+ if $(options)
+ {
+ OPTIONS on $(targets) += $(options) ;
+ }
+}
+
+rule setup-threading ( targets * : sources * : properties * )
+{
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+}
+
+rule setup-fpic ( targets * : sources * : properties * )
+{
+ gcc.setup-fpic $(targets) : $(sources) : $(properties) ;
+}
+
+rule compile.m ( targets * : sources * : properties * )
+{
+ LANG on $(<) = "-x objective-c" ;
+ gcc.setup-fpic $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+}
+
+actions compile.m
+{
+ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+rule compile.mm ( targets * : sources * : properties * )
+{
+ LANG on $(<) = "-x objective-c++" ;
+ gcc.setup-fpic $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+}
+
+actions compile.mm
+{
+ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+# Set the max header padding to allow renaming of libs for installation.
+flags darwin.link.dll OPTIONS : -headerpad_max_install_names ;
+
+# To link the static runtime we need to link to all the core runtime libraries.
+flags darwin.link OPTIONS <runtime-link>static
+ : -nodefaultlibs -shared-libgcc -lstdc++-static -lgcc_eh -lgcc -lSystem ;
+
+# Strip as much as possible when optimizing.
+flags darwin.link OPTIONS <optimization>speed : -Wl,-dead_strip -no_dead_strip_inits_and_terms ;
+flags darwin.link OPTIONS <optimization>space : -Wl,-dead_strip -no_dead_strip_inits_and_terms ;
+
+# Dynamic/shared linking.
+flags darwin.compile OPTIONS <link>shared : -dynamic ;
+
+# Misc options.
+flags darwin.compile OPTIONS : -no-cpp-precomp -gdwarf-2 -fexceptions ;
+#~ flags darwin.link OPTIONS : -fexceptions ;
+
+# Add the framework names to use.
+flags darwin.link FRAMEWORK <framework> ;
+
+#
+flags darwin.link FORCE_LOAD <force-load> ;
+
+# This is flag is useful for debugging the link step
+# uncomment to see what libtool is doing under the hood
+#~ flags darwin.link.dll OPTIONS : -Wl,-v ;
+
+_ = " " ;
+
+# set up the -F option to include the paths to any frameworks used.
+local rule prepare-framework-path ( target + )
+{
+ # The -framework option only takes basename of the framework.
+ # The -F option specifies the directories where a framework
+ # is searched for. So, if we find <framework> feature
+ # with some path, we need to generate property -F option.
+ local framework-paths = [ on $(target) return $(FRAMEWORK:D) ] ;
+
+ # Be sure to generate no -F if there's no path.
+ for local framework-path in $(framework-paths)
+ {
+ if $(framework-path) != ""
+ {
+ FRAMEWORK_PATH on $(target) += -F$(framework-path) ;
+ }
+ }
+}
+
+rule link ( targets * : sources * : properties * )
+{
+ DEPENDS $(targets) : [ on $(targets) return $(FORCE_LOAD) ] ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+ prepare-framework-path $(<) ;
+}
+
+# Note that using strip without any options was reported to result in broken
+# binaries, at least on OS X 10.5.5, see:
+# http://svn.boost.org/trac/boost/ticket/2347
+# So we pass -S -x.
+actions link bind LIBRARIES FORCE_LOAD
+{
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" "$(>)" -Wl,-force_load$(_)"$(FORCE_LOAD)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(FRAMEWORK_PATH) -framework$(_)$(FRAMEWORK:D=:S=) $(OPTIONS) $(USER_OPTIONS)
+ $(NEED_STRIP)"$(.STRIP)" $(NEED_STRIP)-S $(NEED_STRIP)-x $(NEED_STRIP)"$(<)"
+}
+
+rule link.dll ( targets * : sources * : properties * )
+{
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+ prepare-framework-path $(<) ;
+}
+
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -dynamiclib -Wl,-single_module -install_name "$(<:B)$(<:S)" -L"$(LINKPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(FRAMEWORK_PATH) -framework$(_)$(FRAMEWORK:D=:S=) $(OPTIONS) $(USER_OPTIONS)
+}
+
+# We use libtool instead of ar to support universal binary linking
+# TODO: Find a way to use the underlying tools, i.e. lipo, to do this.
+actions piecemeal archive
+{
+ "$(.LIBTOOL)" -static -o "$(<:T)" $(ARFLAGS) "$(>:T)"
+}
diff --git a/tools/build/v2/tools/darwin.py b/tools/build/v2/tools/darwin.py
new file mode 100644
index 0000000000..c29196060b
--- /dev/null
+++ b/tools/build/v2/tools/darwin.py
@@ -0,0 +1,57 @@
+# Copyright (C) Christopher Currie 2003. Permission to copy, use,
+# modify, sell and distribute this software is granted provided this
+# copyright notice appears in all copies. This software is provided
+# "as is" without express or implied warranty, and with no claim as to
+# its suitability for any purpose.
+
+# Please see http://article.gmane.org/gmane.comp.lib.boost.build/3389/
+# for explanation why it's a separate toolset.
+
+import common, gcc, builtin
+from b2.build import feature, toolset, type, action, generators
+from b2.util.utility import *
+
+toolset.register ('darwin')
+
+toolset.inherit_generators ('darwin', [], 'gcc')
+toolset.inherit_flags ('darwin', 'gcc')
+toolset.inherit_rules ('darwin', 'gcc')
+
+def init (version = None, command = None, options = None):
+ options = to_seq (options)
+
+ condition = common.check_init_parameters ('darwin', None, ('version', version))
+
+ command = common.get_invocation_command ('darwin', 'g++', command)
+
+ common.handle_options ('darwin', condition, command, options)
+
+ gcc.init_link_flags ('darwin', 'darwin', condition)
+
+# Darwin has a different shared library suffix
+type.set_generated_target_suffix ('SHARED_LIB', ['<toolset>darwin'], 'dylib')
+
+# we need to be able to tell the type of .dylib files
+type.register_suffixes ('dylib', 'SHARED_LIB')
+
+feature.feature ('framework', [], ['free'])
+
+toolset.flags ('darwin.compile', 'OPTIONS', '<link>shared', ['-dynamic'])
+toolset.flags ('darwin.compile', 'OPTIONS', None, ['-Wno-long-double', '-no-cpp-precomp'])
+toolset.flags ('darwin.compile.c++', 'OPTIONS', None, ['-fcoalesce-templates'])
+
+toolset.flags ('darwin.link', 'FRAMEWORK', '<framework>')
+
+# This is flag is useful for debugging the link step
+# uncomment to see what libtool is doing under the hood
+# toolset.flags ('darwin.link.dll', 'OPTIONS', None, '[-Wl,-v'])
+
+action.register ('darwin.compile.cpp', None, ['$(CONFIG_COMMAND) $(ST_OPTIONS) -L"$(LINKPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) -framework$(_)$(FRAMEWORK) $(OPTIONS)'])
+
+# TODO: how to set 'bind LIBRARIES'?
+action.register ('darwin.link.dll', None, ['$(CONFIG_COMMAND) -dynamiclib -L"$(LINKPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) -framework$(_)$(FRAMEWORK) $(OPTIONS)'])
+
+def darwin_archive (manager, targets, sources, properties):
+ pass
+
+action.register ('darwin.archive', darwin_archive, ['ar -c -r -s $(ARFLAGS) "$(<:T)" "$(>:T)"'])
diff --git a/tools/build/v2/tools/dmc.jam b/tools/build/v2/tools/dmc.jam
new file mode 100644
index 0000000000..8af8725a8a
--- /dev/null
+++ b/tools/build/v2/tools/dmc.jam
@@ -0,0 +1,134 @@
+# Digital Mars C++
+
+# (C) Copyright Christof Meerwald 2003.
+# (C) Copyright Aleksey Gurtovoy 2004.
+# (C) Copyright Arjan Knepper 2006.
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# The following #// line will be used by the regression test table generation
+# program as the column heading for HTML tables. Must not include version number.
+#//<a href="http://www.digitalmars.com/">Digital<br>Mars C++</a>
+
+import feature generators common ;
+import toolset : flags ;
+import sequence regex ;
+
+feature.extend toolset : dmc ;
+
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters dmc : version $(version) ] ;
+
+ local command = [ common.get-invocation-command dmc : dmc : $(command) ] ;
+ command ?= dmc ;
+
+ common.handle-options dmc : $(condition) : $(command) : $(options) ;
+
+ if $(command)
+ {
+ command = [ common.get-absolute-tool-path $(command[-1]) ] ;
+ }
+ root = $(command:D) ;
+
+ if $(root)
+ {
+ # DMC linker is sensitive the the direction of slashes, and
+ # won't link if forward slashes are used in command.
+ root = [ sequence.join [ regex.split $(root) "/" ] : "\\" ] ;
+ flags dmc .root $(condition) : $(root)\\bin\\ ;
+ }
+ else
+ {
+ flags dmc .root $(condition) : "" ;
+ }
+}
+
+
+# Declare generators
+generators.register-linker dmc.link : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : <toolset>dmc ;
+generators.register-linker dmc.link.dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB : <toolset>dmc ;
+
+generators.register-archiver dmc.archive : OBJ : STATIC_LIB : <toolset>dmc ;
+generators.register-c-compiler dmc.compile.c++ : CPP : OBJ : <toolset>dmc ;
+generators.register-c-compiler dmc.compile.c : C : OBJ : <toolset>dmc ;
+
+
+# Declare flags
+# dmc optlink has some limitation on the amount of debug-info included. Therefore only linenumbers are enabled in debug builds.
+# flags dmc.compile OPTIONS <debug-symbols>on : -g ;
+flags dmc.compile OPTIONS <debug-symbols>on : -gl ;
+flags dmc.link OPTIONS <debug-symbols>on : /CO /NOPACKF /DEBUGLI ;
+flags dmc.link OPTIONS <debug-symbols>off : /PACKF ;
+
+flags dmc.compile OPTIONS <optimization>off : -S -o+none ;
+flags dmc.compile OPTIONS <optimization>speed : -o+time ;
+flags dmc.compile OPTIONS <optimization>space : -o+space ;
+flags dmc.compile OPTIONS <exception-handling>on : -Ae ;
+flags dmc.compile OPTIONS <rtti>on : -Ar ;
+# FIXME:
+# Compiling sources to be linked into a shared lib (dll) the -WD cflag should be used
+# Compiling sources to be linked into a static lib (lib) or executable the -WA cflag should be used
+# But for some reason the -WD cflag is always in use.
+# flags dmc.compile OPTIONS <link>shared : -WD ;
+# flags dmc.compile OPTIONS <link>static : -WA ;
+
+# Note that these two options actually imply multithreading support on DMC
+# because there is no single-threaded dynamic runtime library. Specifying
+# <threading>multi would be a bad idea, though, because no option would be
+# matched when the build uses the default settings of <runtime-link>dynamic
+# and <threading>single.
+flags dmc.compile OPTIONS <runtime-debugging>off/<runtime-link>shared : -ND ;
+flags dmc.compile OPTIONS <runtime-debugging>on/<runtime-link>shared : -ND ;
+
+flags dmc.compile OPTIONS <runtime-debugging>off/<runtime-link>static/<threading>single : ;
+flags dmc.compile OPTIONS <runtime-debugging>on/<runtime-link>static/<threading>single : ;
+flags dmc.compile OPTIONS <runtime-debugging>off/<runtime-link>static/<threading>multi : -D_MT ;
+flags dmc.compile OPTIONS <runtime-debugging>on/<runtime-link>static/<threading>multi : -D_MT ;
+
+flags dmc.compile OPTIONS : <cflags> ;
+flags dmc.compile.c++ OPTIONS : <cxxflags> ;
+
+flags dmc.compile DEFINES : <define> ;
+flags dmc.compile INCLUDES : <include> ;
+
+flags dmc.link <linkflags> ;
+flags dmc.archive OPTIONS <arflags> ;
+
+flags dmc LIBPATH <library-path> ;
+flags dmc LIBRARIES <library-file> ;
+flags dmc FINDLIBS <find-library-sa> ;
+flags dmc FINDLIBS <find-library-st> ;
+
+actions together link bind LIBRARIES
+{
+ "$(.root)link" $(OPTIONS) /NOI /DE /XN "$(>)" , "$(<[1])" ,, $(LIBRARIES) user32.lib kernel32.lib "$(FINDLIBS:S=.lib)" , "$(<[2]:B).def"
+}
+
+actions together link.dll bind LIBRARIES
+{
+ echo LIBRARY "$(<[1])" > $(<[2]:B).def
+ echo DESCRIPTION 'A Library' >> $(<[2]:B).def
+ echo EXETYPE NT >> $(<[2]:B).def
+ echo SUBSYSTEM WINDOWS >> $(<[2]:B).def
+ echo CODE EXECUTE READ >> $(<[2]:B).def
+ echo DATA READ WRITE >> $(<[2]:B).def
+ "$(.root)link" $(OPTIONS) /NOI /DE /XN /ENTRY:_DllMainCRTStartup /IMPLIB:"$(<[2])" "$(>)" $(LIBRARIES) , "$(<[1])" ,, user32.lib kernel32.lib "$(FINDLIBS:S=.lib)" , "$(<[2]:B).def"
+}
+
+actions compile.c
+{
+ "$(.root)dmc" -c $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -o"$(<)" "$(>)"
+}
+
+actions compile.c++
+{
+ "$(.root)dmc" -cpp -c -Ab $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -o"$(<)" "$(>)"
+}
+
+actions together piecemeal archive
+{
+ "$(.root)lib" $(OPTIONS) -c -n -p256 "$(<)" "$(>)"
+}
diff --git a/tools/build/v2/tools/docutils.jam b/tools/build/v2/tools/docutils.jam
new file mode 100644
index 0000000000..bf0616174b
--- /dev/null
+++ b/tools/build/v2/tools/docutils.jam
@@ -0,0 +1,84 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# Support for docutils ReStructuredText processing.
+
+import type ;
+import scanner ;
+import generators ;
+import os ;
+import common ;
+import toolset ;
+import path ;
+import feature : feature ;
+import property ;
+
+.initialized = ;
+
+type.register ReST : rst ;
+
+class rst-scanner : common-scanner
+{
+ rule __init__ ( paths * )
+ {
+ common-scanner.__init__ . $(paths) ;
+ }
+
+ rule pattern ( )
+ {
+ return "^[ ]*\\.\\.[ ]+include::[ ]+([^
+]+)"
+ "^[ ]*\\.\\.[ ]+image::[ ]+([^
+]+)"
+ "^[ ]*\\.\\.[ ]+figure::[ ]+([^
+]+)"
+ ;
+ }
+}
+
+scanner.register rst-scanner : include ;
+type.set-scanner ReST : rst-scanner ;
+
+generators.register-standard docutils.html : ReST : HTML ;
+
+rule init ( docutils-dir ? : tools-dir ? )
+{
+ docutils-dir ?= [ modules.peek : DOCUTILS_DIR ] ;
+ tools-dir ?= $(docutils-dir)/tools ;
+
+ if ! $(.initialized)
+ {
+ .initialized = true ;
+ .docutils-dir = $(docutils-dir) ;
+ .tools-dir = $(tools-dir:R="") ;
+
+ .setup = [
+ common.prepend-path-variable-command PYTHONPATH
+ : $(.docutils-dir) $(.docutils-dir)/extras ] ;
+ }
+}
+
+rule html ( target : source : properties * )
+{
+ if ! [ on $(target) return $(RST2XXX) ]
+ {
+ local python-cmd = [ property.select <python.interpreter> : $(properties) ] ;
+ RST2XXX on $(target) = $(python-cmd:G=:E="python") $(.tools-dir)/rst2html.py ;
+ }
+}
+
+
+feature docutils : : free ;
+feature docutils-html : : free ;
+feature docutils-cmd : : free ;
+toolset.flags docutils COMMON-FLAGS : <docutils> ;
+toolset.flags docutils HTML-FLAGS : <docutils-html> ;
+toolset.flags docutils RST2XXX : <docutils-cmd> ;
+
+actions html
+{
+ $(.setup)
+ "$(RST2XXX)" $(COMMON-FLAGS) $(HTML-FLAGS) $(>) $(<)
+}
+
diff --git a/tools/build/v2/tools/doxproc.py b/tools/build/v2/tools/doxproc.py
new file mode 100644
index 0000000000..4cbd5edd2f
--- /dev/null
+++ b/tools/build/v2/tools/doxproc.py
@@ -0,0 +1,859 @@
+#!/usr/bin/python
+# Copyright 2006 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+'''
+Processing of Doxygen generated XML.
+'''
+
+import os
+import os.path
+import sys
+import time
+import string
+import getopt
+import glob
+import re
+import xml.dom.minidom
+
+
+def usage():
+ print '''
+Usage:
+ %s options
+
+Options:
+ --xmldir Directory with the Doxygen xml result files.
+ --output Write the output BoostBook to the given location.
+ --id The ID of the top level BoostBook section.
+ --title The title of the top level BoostBook section.
+ --enable-index Generate additional index sections for classes and
+ types.
+''' % ( sys.argv[0] )
+
+
+def get_args( argv = sys.argv[1:] ):
+ spec = [
+ 'xmldir=',
+ 'output=',
+ 'id=',
+ 'title=',
+ 'enable-index',
+ 'help' ]
+ options = {
+ '--xmldir' : 'xml',
+ '--output' : None,
+ '--id' : 'dox',
+ '--title' : 'Doxygen'
+ }
+ ( option_pairs, other ) = getopt.getopt( argv, '', spec )
+ map( lambda x: options.__setitem__( x[0], x[1] ), option_pairs )
+
+ if options.has_key( '--help' ):
+ usage()
+ sys.exit(1)
+
+ return {
+ 'xmldir' : options['--xmldir'],
+ 'output' : options['--output'],
+ 'id' : options['--id'],
+ 'title' : options['--title'],
+ 'index' : options.has_key('--enable-index')
+ }
+
+def if_attribute(node, attribute, true_value, false_value=None):
+ if node.getAttribute(attribute) == 'yes':
+ return true_value
+ else:
+ return false_value
+
+class Doxygen2BoostBook:
+
+ def __init__( self, **kwargs ):
+ ##
+ self.args = kwargs
+ self.args.setdefault('id','')
+ self.args.setdefault('title','')
+ self.args.setdefault('last_revision', time.asctime())
+ self.args.setdefault('index', False)
+ self.id = '%(id)s.reference' % self.args
+ self.args['id'] = self.id
+ #~ This is our template BoostBook document we insert the generated content into.
+ self.boostbook = xml.dom.minidom.parseString('''<?xml version="1.0" encoding="UTF-8"?>
+<section id="%(id)s" name="%(title)s" last-revision="%(last_revision)s">
+ <title>%(title)s</title>
+ <library-reference id="%(id)s.headers">
+ <title>Headers</title>
+ </library-reference>
+ <index id="%(id)s.classes">
+ <title>Classes</title>
+ </index>
+ <index id="%(id)s.index">
+ <title>Index</title>
+ </index>
+</section>
+''' % self.args )
+ self.section = {
+ 'headers' : self._getChild('library-reference',id='%(id)s.headers' % self.args),
+ 'classes' : self._getChild('index',id='%(id)s.classes' % self.args),
+ 'index' : self._getChild('index',id='%(id)s.index' % self.args)
+ }
+ #~ Remove the index sections if we aren't generating it.
+ if not self.args['index']:
+ self.section['classes'].parentNode.removeChild(self.section['classes'])
+ self.section['classes'].unlink()
+ del self.section['classes']
+ self.section['index'].parentNode.removeChild(self.section['index'])
+ self.section['index'].unlink()
+ del self.section['index']
+ #~ The symbols, per Doxygen notion, that we translated.
+ self.symbols = {}
+ #~ Map of Doxygen IDs and BoostBook IDs, so we can translate as needed.
+ self.idmap = {}
+ #~ Marks generation, to prevent redoing it.
+ self.generated = False
+
+ #~ Add an Doxygen generated XML document to the content we are translating.
+ def addDox( self, document ):
+ self._translateNode(document.documentElement)
+
+ #~ Turns the internal XML tree into an output UTF-8 string.
+ def tostring( self ):
+ self._generate()
+ #~ return self.boostbook.toprettyxml(' ')
+ return self.boostbook.toxml('utf-8')
+
+ #~ Does post-processing on the partial generated content to generate additional info
+ #~ now that we have the complete source documents.
+ def _generate( self ):
+ if not self.generated:
+ self.generated = True
+ symbols = self.symbols.keys()
+ symbols.sort()
+ #~ Populate the header section.
+ for symbol in symbols:
+ if self.symbols[symbol]['kind'] in ('header'):
+ self.section['headers'].appendChild(self.symbols[symbol]['dom'])
+ for symbol in symbols:
+ if self.symbols[symbol]['kind'] not in ('namespace', 'header'):
+ container = self._resolveContainer(self.symbols[symbol],
+ self.symbols[self.symbols[symbol]['header']]['dom'])
+ if container.nodeName != 'namespace':
+ ## The current BoostBook to Docbook translation doesn't
+ ## respect, nor assign, IDs to inner types of any kind.
+ ## So nuke the ID entry so as not create bogus links.
+ del self.idmap[self.symbols[symbol]['id']]
+ container.appendChild(self.symbols[symbol]['dom'])
+ self._rewriteIDs(self.boostbook.documentElement)
+
+ #~ Rewrite the various IDs from Doxygen references to the newly created
+ #~ BoostBook references.
+ def _rewriteIDs( self, node ):
+ if node.nodeName in ('link'):
+ if (self.idmap.has_key(node.getAttribute('linkend'))):
+ #~ A link, and we have someplace to repoint it at.
+ node.setAttribute('linkend',self.idmap[node.getAttribute('linkend')])
+ else:
+ #~ A link, but we don't have a generated target for it.
+ node.removeAttribute('linkend')
+ elif hasattr(node,'hasAttribute') and node.hasAttribute('id') and self.idmap.has_key(node.getAttribute('id')):
+ #~ Simple ID, and we have a translation.
+ node.setAttribute('id',self.idmap[node.getAttribute('id')])
+ #~ Recurse, and iterate, depth-first traversal which turns out to be
+ #~ left-to-right and top-to-bottom for the document.
+ if node.firstChild:
+ self._rewriteIDs(node.firstChild)
+ if node.nextSibling:
+ self._rewriteIDs(node.nextSibling)
+
+ def _resolveContainer( self, cpp, root ):
+ container = root
+ for ns in cpp['namespace']:
+ node = self._getChild('namespace',name=ns,root=container)
+ if not node:
+ node = container.appendChild(
+ self._createNode('namespace',name=ns))
+ container = node
+ for inner in cpp['name'].split('::'):
+ node = self._getChild(name=inner,root=container)
+ if not node:
+ break
+ container = node
+ return container
+
+ def _setID( self, id, name ):
+ self.idmap[id] = name.replace('::','.').replace('/','.')
+ #~ print '--| setID:',id,'::',self.idmap[id]
+
+ #~ Translate a given node within a given context.
+ #~ The translation dispatches to a local method of the form
+ #~ "_translate[_context0,...,_contextN]", and the keyword args are
+ #~ passed along. If there is no translation handling method we
+ #~ return None.
+ def _translateNode( self, *context, **kwargs ):
+ node = None
+ names = [ ]
+ for c in context:
+ if c:
+ if not isinstance(c,xml.dom.Node):
+ suffix = '_'+c.replace('-','_')
+ else:
+ suffix = '_'+c.nodeName.replace('-','_')
+ node = c
+ names.append('_translate')
+ names = map(lambda x: x+suffix,names)
+ if node:
+ for name in names:
+ if hasattr(self,name):
+ return getattr(self,name)(node,**kwargs)
+ return None
+
+ #~ Translates the children of the given parent node, appending the results
+ #~ to the indicated target. For nodes not translated by the translation method
+ #~ it copies the child over and recurses on that child to translate any
+ #~ possible interior nodes. Hence this will translate the entire subtree.
+ def _translateChildren( self, parent, **kwargs ):
+ target = kwargs['target']
+ for n in parent.childNodes:
+ child = self._translateNode(n,target=target)
+ if child:
+ target.appendChild(child)
+ else:
+ child = n.cloneNode(False)
+ if hasattr(child,'data'):
+ child.data = re.sub(r'\s+',' ',child.data)
+ target.appendChild(child)
+ self._translateChildren(n,target=child)
+
+ #~ Translate the given node as a description, into the description subnode
+ #~ of the target. If no description subnode is present in the target it
+ #~ is created.
+ def _translateDescription( self, node, target=None, tag='description', **kwargs ):
+ description = self._getChild(tag,root=target)
+ if not description:
+ description = target.appendChild(self._createNode(tag))
+ self._translateChildren(node,target=description)
+ return description
+
+ #~ Top level translation of: <doxygen ...>...</doxygen>,
+ #~ translates the children.
+ def _translate_doxygen( self, node ):
+ #~ print '_translate_doxygen:', node.nodeName
+ result = []
+ for n in node.childNodes:
+ newNode = self._translateNode(n)
+ if newNode:
+ result.append(newNode)
+ return result
+
+ #~ Top level translation of:
+ #~ <doxygenindex ...>
+ #~ <compound ...>
+ #~ <member ...>
+ #~ <name>...</name>
+ #~ </member>
+ #~ ...
+ #~ </compound>
+ #~ ...
+ #~ </doxygenindex>
+ #~ builds the class and symbol sections, if requested.
+ def _translate_doxygenindex( self, node ):
+ #~ print '_translate_doxygenindex:', node.nodeName
+ if self.args['index']:
+ entries = []
+ classes = []
+ #~ Accumulate all the index entries we care about.
+ for n in node.childNodes:
+ if n.nodeName == 'compound':
+ if n.getAttribute('kind') not in ('file','dir','define'):
+ cpp = self._cppName(self._getChildData('name',root=n))
+ entry = {
+ 'name' : cpp['name'],
+ 'compoundname' : cpp['compoundname'],
+ 'id' : n.getAttribute('refid')
+ }
+ if n.getAttribute('kind') in ('class','struct'):
+ classes.append(entry)
+ entries.append(entry)
+ for m in n.childNodes:
+ if m.nodeName == 'member':
+ cpp = self._cppName(self._getChildData('name',root=m))
+ entry = {
+ 'name' : cpp['name'],
+ 'compoundname' : cpp['compoundname'],
+ 'id' : n.getAttribute('refid')
+ }
+ if hasattr(m,'getAttribute') and m.getAttribute('kind') in ('class','struct'):
+ classes.append(entry)
+ entries.append(entry)
+ #~ Put them in a sensible order.
+ entries.sort(lambda x,y: cmp(x['name'].lower(),y['name'].lower()))
+ classes.sort(lambda x,y: cmp(x['name'].lower(),y['name'].lower()))
+ #~ And generate the BoostBook for them.
+ self._translate_index_(entries,target=self.section['index'])
+ self._translate_index_(classes,target=self.section['classes'])
+ return None
+
+ #~ Translate a set of index entries in the BoostBook output. The output
+ #~ is grouped into groups of the first letter of the entry names.
+ def _translate_index_(self, entries, target=None, **kwargs ):
+ i = 0
+ targetID = target.getAttribute('id')
+ while i < len(entries):
+ dividerKey = entries[i]['name'][0].upper()
+ divider = target.appendChild(self._createNode('indexdiv',id=targetID+'.'+dividerKey))
+ divider.appendChild(self._createText('title',dividerKey))
+ while i < len(entries) and dividerKey == entries[i]['name'][0].upper():
+ iename = entries[i]['name']
+ ie = divider.appendChild(self._createNode('indexentry'))
+ ie = ie.appendChild(self._createText('primaryie',iename))
+ while i < len(entries) and entries[i]['name'] == iename:
+ ie.appendChild(self.boostbook.createTextNode(' ('))
+ ie.appendChild(self._createText(
+ 'link',entries[i]['compoundname'],linkend=entries[i]['id']))
+ ie.appendChild(self.boostbook.createTextNode(')'))
+ i += 1
+
+ #~ Translate a <compounddef ...>...</compounddef>,
+ #~ by retranslating with the "kind" of compounddef.
+ def _translate_compounddef( self, node, target=None, **kwargs ):
+ return self._translateNode(node,node.getAttribute('kind'))
+
+ #~ Translate a <compounddef kind="namespace"...>...</compounddef>. For
+ #~ namespaces we just collect the information for later use as there is no
+ #~ currently namespaces are not included in the BoostBook format. In the future
+ #~ it might be good to generate a namespace index.
+ def _translate_compounddef_namespace( self, node, target=None, **kwargs ):
+ namespace = {
+ 'id' : node.getAttribute('id'),
+ 'kind' : 'namespace',
+ 'name' : self._getChildData('compoundname',root=node),
+ 'brief' : self._getChildData('briefdescription',root=node),
+ 'detailed' : self._getChildData('detaileddescription',root=node),
+ 'parsed' : False
+ }
+ if self.symbols.has_key(namespace['name']):
+ if not self.symbols[namespace['name']]['parsed']:
+ self.symbols[namespace['name']]['parsed'] = True
+ #~ for n in node.childNodes:
+ #~ if hasattr(n,'getAttribute'):
+ #~ self._translateNode(n,n.getAttribute('kind'),target=target,**kwargs)
+ else:
+ self.symbols[namespace['name']] = namespace
+ #~ self._setID(namespace['id'],namespace['name'])
+ return None
+
+ #~ Translate a <compounddef kind="class"...>...</compounddef>, which
+ #~ forwards to the kind=struct as they are the same.
+ def _translate_compounddef_class( self, node, target=None, **kwargs ):
+ return self._translate_compounddef_struct(node,tag='class',target=target,**kwargs)
+
+ #~ Translate a <compounddef kind="struct"...>...</compounddef> into:
+ #~ <header id="?" name="?">
+ #~ <struct name="?">
+ #~ ...
+ #~ </struct>
+ #~ </header>
+ def _translate_compounddef_struct( self, node, tag='struct', target=None, **kwargs ):
+ result = None
+ includes = self._getChild('includes',root=node)
+ if includes:
+ ## Add the header into the output table.
+ self._translate_compounddef_includes_(includes,includes,**kwargs)
+ ## Compounds are the declared symbols, classes, types, etc.
+ ## We add them to the symbol table, along with the partial DOM for them
+ ## so that they can be organized into the output later.
+ compoundname = self._getChildData('compoundname',root=node)
+ compoundname = self._cppName(compoundname)
+ self._setID(node.getAttribute('id'),compoundname['compoundname'])
+ struct = self._createNode(tag,name=compoundname['name'].split('::')[-1])
+ self.symbols[compoundname['compoundname']] = {
+ 'header' : includes.firstChild.data,
+ 'namespace' : compoundname['namespace'],
+ 'id' : node.getAttribute('id'),
+ 'kind' : tag,
+ 'name' : compoundname['name'],
+ 'dom' : struct
+ }
+ ## Add the children which will be the members of the struct.
+ for n in node.childNodes:
+ self._translateNode(n,target=struct,scope=compoundname['compoundname'])
+ result = struct
+ return result
+
+ #~ Translate a <compounddef ...><includes ...>...</includes></compounddef>,
+ def _translate_compounddef_includes_( self, node, target=None, **kwargs ):
+ name = node.firstChild.data
+ if not self.symbols.has_key(name):
+ self._setID(node.getAttribute('refid'),name)
+ self.symbols[name] = {
+ 'kind' : 'header',
+ 'id' : node.getAttribute('refid'),
+ 'dom' : self._createNode('header',
+ id=node.getAttribute('refid'),
+ name=name)
+ }
+ return None
+
+ #~ Translate a <basecompoundref...>...</basecompoundref> into:
+ #~ <inherit access="?">
+ #~ ...
+ #~ </inherit>
+ def _translate_basecompoundref( self, ref, target=None, **kwargs ):
+ inherit = target.appendChild(self._createNode('inherit',
+ access=ref.getAttribute('prot')))
+ self._translateChildren(ref,target=inherit)
+ return
+
+ #~ Translate:
+ #~ <templateparamlist>
+ #~ <param>
+ #~ <type>...</type>
+ #~ <declname>...</declname>
+ #~ <defname>...</defname>
+ #~ <defval>...</defval>
+ #~ </param>
+ #~ ...
+ #~ </templateparamlist>
+ #~ Into:
+ #~ <template>
+ #~ <template-type-parameter name="?" />
+ #~ <template-nontype-parameter name="?">
+ #~ <type>?</type>
+ #~ <default>?</default>
+ #~ </template-nontype-parameter>
+ #~ </template>
+ def _translate_templateparamlist( self, templateparamlist, target=None, **kwargs ):
+ template = target.appendChild(self._createNode('template'))
+ for param in templateparamlist.childNodes:
+ if param.nodeName == 'param':
+ type = self._getChildData('type',root=param)
+ defval = self._getChild('defval',root=param)
+ paramKind = None
+ if type in ('class','typename'):
+ paramKind = 'template-type-parameter'
+ else:
+ paramKind = 'template-nontype-parameter'
+ templateParam = template.appendChild(
+ self._createNode(paramKind,
+ name=self._getChildData('declname',root=param)))
+ if paramKind == 'template-nontype-parameter':
+ template_type = templateParam.appendChild(self._createNode('type'))
+ self._translate_type(
+ self._getChild('type',root=param),target=template_type)
+ if defval:
+ value = self._getChildData('ref',root=defval.firstChild)
+ if not value:
+ value = self._getData(defval)
+ templateParam.appendChild(self._createText('default',value))
+ return template
+
+ #~ Translate:
+ #~ <briefdescription>...</briefdescription>
+ #~ Into:
+ #~ <purpose>...</purpose>
+ def _translate_briefdescription( self, brief, target=None, **kwargs ):
+ self._translateDescription(brief,target=target,**kwargs)
+ return self._translateDescription(brief,target=target,tag='purpose',**kwargs)
+
+ #~ Translate:
+ #~ <detaileddescription>...</detaileddescription>
+ #~ Into:
+ #~ <description>...</description>
+ def _translate_detaileddescription( self, detailed, target=None, **kwargs ):
+ return self._translateDescription(detailed,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="?">...</sectiondef>
+ #~ With kind specific translation.
+ def _translate_sectiondef( self, sectiondef, target=None, **kwargs ):
+ self._translateNode(sectiondef,sectiondef.getAttribute('kind'),target=target,**kwargs)
+
+ #~ Translate non-function sections.
+ def _translate_sectiondef_x_( self, sectiondef, target=None, **kwargs ):
+ for n in sectiondef.childNodes:
+ if hasattr(n,'getAttribute'):
+ self._translateNode(n,n.getAttribute('kind'),target=target,**kwargs)
+ return None
+
+ #~ Translate:
+ #~ <sectiondef kind="public-type">...</sectiondef>
+ def _translate_sectiondef_public_type( self, sectiondef, target=None, **kwargs ):
+ return self._translate_sectiondef_x_(sectiondef,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="public-sttrib">...</sectiondef>
+ def _translate_sectiondef_public_attrib( self, sectiondef, target=None, **kwargs):
+ return self._translate_sectiondef_x_(sectiondef,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="?-func">...</sectiondef>
+ #~ All the various function group translations end up here for which
+ #~ they are translated into:
+ #~ <method-group name="?">
+ #~ ...
+ #~ </method-group>
+ def _translate_sectiondef_func_( self, sectiondef, name='functions', target=None, **kwargs ):
+ members = target.appendChild(self._createNode('method-group',name=name))
+ for n in sectiondef.childNodes:
+ if hasattr(n,'getAttribute'):
+ self._translateNode(n,n.getAttribute('kind'),target=members,**kwargs)
+ return members
+
+ #~ Translate:
+ #~ <sectiondef kind="public-func">...</sectiondef>
+ def _translate_sectiondef_public_func( self, sectiondef, target=None, **kwargs ):
+ return self._translate_sectiondef_func_(sectiondef,
+ name='public member functions',target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="public-static-func">...</sectiondef>
+ def _translate_sectiondef_public_static_func( self, sectiondef, target=None, **kwargs):
+ return self._translate_sectiondef_func_(sectiondef,
+ name='public static functions',target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="protected-func">...</sectiondef>
+ def _translate_sectiondef_protected_func( self, sectiondef, target=None, **kwargs ):
+ return self._translate_sectiondef_func_(sectiondef,
+ name='protected member functions',target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="private-static-func">...</sectiondef>
+ def _translate_sectiondef_private_static_func( self, sectiondef, target=None, **kwargs):
+ return self._translate_sectiondef_func_(sectiondef,
+ name='private static functions',target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="public-func">...</sectiondef>
+ def _translate_sectiondef_private_func( self, sectiondef, target=None, **kwargs ):
+ return self._translate_sectiondef_func_(sectiondef,
+ name='private member functions',target=target,**kwargs)
+
+ #~ Translate:
+ #~ <sectiondef kind="user-defined"><header>...</header>...</sectiondef>
+ def _translate_sectiondef_user_defined( self, sectiondef, target=None, **kwargs ):
+ return self._translate_sectiondef_func_(sectiondef,
+ name=self._getChildData('header', root=sectiondef),target=target,**kwargs)
+
+ #~ Translate:
+ #~ <memberdef kind="typedef" id="?">
+ #~ <name>...</name>
+ #~ </memberdef>
+ #~ To:
+ #~ <typedef id="?" name="?">
+ #~ <type>...</type>
+ #~ </typedef>
+ def _translate_memberdef_typedef( self, memberdef, target=None, scope=None, **kwargs ):
+ self._setID(memberdef.getAttribute('id'),
+ scope+'::'+self._getChildData('name',root=memberdef))
+ typedef = target.appendChild(self._createNode('typedef',
+ id=memberdef.getAttribute('id'),
+ name=self._getChildData('name',root=memberdef)))
+ typedef_type = typedef.appendChild(self._createNode('type'))
+ self._translate_type(self._getChild('type',root=memberdef),target=typedef_type)
+ return typedef
+
+ #~ Translate:
+ #~ <memberdef kind="function" id="?" const="?" static="?" explicit="?" inline="?">
+ #~ <name>...</name>
+ #~ </memberdef>
+ #~ To:
+ #~ <method name="?" cv="?" specifiers="?">
+ #~ ...
+ #~ </method>
+ def _translate_memberdef_function( self, memberdef, target=None, scope=None, **kwargs ):
+ name = self._getChildData('name',root=memberdef)
+ self._setID(memberdef.getAttribute('id'),scope+'::'+name)
+ ## Check if we have some specific kind of method.
+ if name == scope.split('::')[-1]:
+ kind = 'constructor'
+ target = target.parentNode
+ elif name == '~'+scope.split('::')[-1]:
+ kind = 'destructor'
+ target = target.parentNode
+ elif name == 'operator=':
+ kind = 'copy-assignment'
+ target = target.parentNode
+ else:
+ kind = 'method'
+ method = target.appendChild(self._createNode(kind,
+ # id=memberdef.getAttribute('id'),
+ name=name,
+ cv=' '.join([
+ if_attribute(memberdef,'const','const','').strip()
+ ]),
+ specifiers=' '.join([
+ if_attribute(memberdef,'static','static',''),
+ if_attribute(memberdef,'explicit','explicit',''),
+ if_attribute(memberdef,'inline','inline','')
+ ]).strip()
+ ))
+ ## We iterate the children to translate each part of the function.
+ for n in memberdef.childNodes:
+ self._translateNode(memberdef,'function',n,target=method)
+ return method
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><templateparamlist>...</templateparamlist></memberdef>
+ def _translate_memberdef_function_templateparamlist(
+ self, templateparamlist, target=None, **kwargs ):
+ return self._translate_templateparamlist(templateparamlist,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><type>...</type></memberdef>
+ #~ To:
+ #~ ...<type>?</type>
+ def _translate_memberdef_function_type( self, resultType, target=None, **kwargs ):
+ methodType = self._createNode('type')
+ self._translate_type(resultType,target=methodType)
+ if methodType.hasChildNodes():
+ target.appendChild(methodType)
+ return methodType
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><briefdescription>...</briefdescription></memberdef>
+ def _translate_memberdef_function_briefdescription( self, description, target=None, **kwargs ):
+ result = self._translateDescription(description,target=target,**kwargs)
+ ## For functions if we translate the brief docs to the purpose they end up
+ ## right above the regular description. And since we just added the brief to that
+ ## on the previous line, don't bother with the repetition.
+ # result = self._translateDescription(description,target=target,tag='purpose',**kwargs)
+ return result
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><detaileddescription>...</detaileddescription></memberdef>
+ def _translate_memberdef_function_detaileddescription( self, description, target=None, **kwargs ):
+ return self._translateDescription(description,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><inbodydescription>...</inbodydescription></memberdef>
+ def _translate_memberdef_function_inbodydescription( self, description, target=None, **kwargs ):
+ return self._translateDescription(description,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <memberdef kind="function"...><param>...</param></memberdef>
+ def _translate_memberdef_function_param( self, param, target=None, **kwargs ):
+ return self._translate_param(param,target=target,**kwargs)
+
+ #~ Translate:
+ #~ <memberdef kind="variable" id="?">
+ #~ <name>...</name>
+ #~ <type>...</type>
+ #~ </memberdef>
+ #~ To:
+ #~ <data-member id="?" name="?">
+ #~ <type>...</type>
+ #~ </data-member>
+ def _translate_memberdef_variable( self, memberdef, target=None, scope=None, **kwargs ):
+ self._setID(memberdef.getAttribute('id'),
+ scope+'::'+self._getChildData('name',root=memberdef))
+ data_member = target.appendChild(self._createNode('data-member',
+ id=memberdef.getAttribute('id'),
+ name=self._getChildData('name',root=memberdef)))
+ data_member_type = data_member.appendChild(self._createNode('type'))
+ self._translate_type(self._getChild('type',root=memberdef),target=data_member_type)
+
+ #~ Translate:
+ #~ <memberdef kind="enum" id="?">
+ #~ <name>...</name>
+ #~ ...
+ #~ </memberdef>
+ #~ To:
+ #~ <enum id="?" name="?">
+ #~ ...
+ #~ </enum>
+ def _translate_memberdef_enum( self, memberdef, target=None, scope=None, **kwargs ):
+ self._setID(memberdef.getAttribute('id'),
+ scope+'::'+self._getChildData('name',root=memberdef))
+ enum = target.appendChild(self._createNode('enum',
+ id=memberdef.getAttribute('id'),
+ name=self._getChildData('name',root=memberdef)))
+ for n in memberdef.childNodes:
+ self._translateNode(memberdef,'enum',n,target=enum,scope=scope,**kwargs)
+ return enum
+
+ #~ Translate:
+ #~ <memberdef kind="enum"...>
+ #~ <enumvalue id="?">
+ #~ <name>...</name>
+ #~ <initializer>...</initializer>
+ #~ </enumvalue>
+ #~ </memberdef>
+ #~ To:
+ #~ <enumvalue id="?" name="?">
+ #~ <default>...</default>
+ #~ </enumvalue>
+ def _translate_memberdef_enum_enumvalue( self, enumvalue, target=None, scope=None, **kwargs ):
+ self._setID(enumvalue.getAttribute('id'),
+ scope+'::'+self._getChildData('name',root=enumvalue))
+ value = target.appendChild(self._createNode('enumvalue',
+ id=enumvalue.getAttribute('id'),
+ name=self._getChildData('name',root=enumvalue)))
+ initializer = self._getChild('initializer',root=enumvalue)
+ if initializer:
+ self._translateChildren(initializer,
+ target=target.appendChild(self._createNode('default')))
+ return value
+
+ #~ Translate:
+ #~ <param>
+ #~ <type>...</type>
+ #~ <declname>...</declname>
+ #~ <defval>...</defval>
+ #~ </param>
+ #~ To:
+ #~ <parameter name="?">
+ #~ <paramtype>...</paramtype>
+ #~ ...
+ #~ </parameter>
+ def _translate_param( self, param, target=None, **kwargs):
+ parameter = target.appendChild(self._createNode('parameter',
+ name=self._getChildData('declname',root=param)))
+ paramtype = parameter.appendChild(self._createNode('paramtype'))
+ self._translate_type(self._getChild('type',root=param),target=paramtype)
+ defval = self._getChild('defval',root=param)
+ if defval:
+ self._translateChildren(self._getChild('defval',root=param),target=parameter)
+ return parameter
+
+ #~ Translate:
+ #~ <ref kindref="?" ...>...</ref>
+ def _translate_ref( self, ref, **kwargs ):
+ return self._translateNode(ref,ref.getAttribute('kindref'))
+
+ #~ Translate:
+ #~ <ref refid="?" kindref="compound">...</ref>
+ #~ To:
+ #~ <link linkend="?"><classname>...</classname></link>
+ def _translate_ref_compound( self, ref, **kwargs ):
+ result = self._createNode('link',linkend=ref.getAttribute('refid'))
+ classname = result.appendChild(self._createNode('classname'))
+ self._translateChildren(ref,target=classname)
+ return result
+
+ #~ Translate:
+ #~ <ref refid="?" kindref="member">...</ref>
+ #~ To:
+ #~ <link linkend="?">...</link>
+ def _translate_ref_member( self, ref, **kwargs ):
+ result = self._createNode('link',linkend=ref.getAttribute('refid'))
+ self._translateChildren(ref,target=result)
+ return result
+
+ #~ Translate:
+ #~ <type>...</type>
+ def _translate_type( self, type, target=None, **kwargs ):
+ result = self._translateChildren(type,target=target,**kwargs)
+ #~ Filter types to clean up various readability problems, most notably
+ #~ with really long types.
+ xml = target.toxml('utf-8');
+ if (
+ xml.startswith('<type>boost::mpl::') or
+ xml.startswith('<type>BOOST_PP_') or
+ re.match('<type>boost::(lazy_)?(enable|disable)_if',xml)
+ ):
+ while target.firstChild:
+ target.removeChild(target.firstChild)
+ target.appendChild(self._createText('emphasis','unspecified'))
+ return result
+
+ def _getChild( self, tag = None, id = None, name = None, root = None ):
+ if not root:
+ root = self.boostbook.documentElement
+ for n in root.childNodes:
+ found = True
+ if tag and found:
+ found = found and tag == n.nodeName
+ if id and found:
+ if n.hasAttribute('id'):
+ found = found and n.getAttribute('id') == id
+ else:
+ found = found and n.hasAttribute('id') and n.getAttribute('id') == id
+ if name and found:
+ found = found and n.hasAttribute('name') and n.getAttribute('name') == name
+ if found:
+ #~ print '--|', n
+ return n
+ return None
+
+ def _getChildData( self, tag, **kwargs ):
+ return self._getData(self._getChild(tag,**kwargs),**kwargs)
+
+ def _getData( self, node, **kwargs ):
+ if node:
+ text = self._getChild('#text',root=node)
+ if text:
+ return text.data.strip()
+ return ''
+
+ def _cppName( self, type ):
+ parts = re.search('^([^<]+)[<]?(.*)[>]?$',type.strip().strip(':'))
+ result = {
+ 'compoundname' : parts.group(1),
+ 'namespace' : parts.group(1).split('::')[0:-1],
+ 'name' : parts.group(1).split('::')[-1],
+ 'specialization' : parts.group(2)
+ }
+ if result['namespace'] and len(result['namespace']) > 0:
+ namespace = '::'.join(result['namespace'])
+ while (
+ len(result['namespace']) > 0 and (
+ not self.symbols.has_key(namespace) or
+ self.symbols[namespace]['kind'] != 'namespace')
+ ):
+ result['name'] = result['namespace'].pop()+'::'+result['name']
+ namespace = '::'.join(result['namespace'])
+ return result
+
+ def _createNode( self, tag, **kwargs ):
+ result = self.boostbook.createElement(tag)
+ for k in kwargs.keys():
+ if kwargs[k] != '':
+ if k == 'id':
+ result.setAttribute('id',kwargs[k])
+ else:
+ result.setAttribute(k,kwargs[k])
+ return result
+
+ def _createText( self, tag, data, **kwargs ):
+ result = self._createNode(tag,**kwargs)
+ data = data.strip()
+ if len(data) > 0:
+ result.appendChild(self.boostbook.createTextNode(data))
+ return result
+
+
+def main( xmldir=None, output=None, id=None, title=None, index=False ):
+ #~ print '--- main: xmldir = %s, output = %s' % (xmldir,output)
+
+ input = glob.glob( os.path.abspath( os.path.join( xmldir, "*.xml" ) ) )
+ input.sort
+ translator = Doxygen2BoostBook(id=id, title=title, index=index)
+ #~ Feed in the namespaces first to build up the set of namespaces
+ #~ and definitions so that lookup is unambiguous when reading in the definitions.
+ namespace_files = filter(
+ lambda x:
+ os.path.basename(x).startswith('namespace'),
+ input)
+ decl_files = filter(
+ lambda x:
+ not os.path.basename(x).startswith('namespace') and not os.path.basename(x).startswith('_'),
+ input)
+ for dox in namespace_files:
+ #~ print '--|',os.path.basename(dox)
+ translator.addDox(xml.dom.minidom.parse(dox))
+ for dox in decl_files:
+ #~ print '--|',os.path.basename(dox)
+ translator.addDox(xml.dom.minidom.parse(dox))
+
+ if output:
+ output = open(output,'w')
+ else:
+ output = sys.stdout
+ if output:
+ output.write(translator.tostring())
+
+
+main( **get_args() )
diff --git a/tools/build/v2/tools/doxygen-config.jam b/tools/build/v2/tools/doxygen-config.jam
new file mode 100644
index 0000000000..2cd2ccaeb1
--- /dev/null
+++ b/tools/build/v2/tools/doxygen-config.jam
@@ -0,0 +1,11 @@
+#~ Copyright 2005, 2006 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Automatic configuration for Doxygen tools. To use, just import this module.
+
+import toolset : using ;
+
+ECHO "warning: doxygen-config.jam is deprecated. Use 'using doxygen ;' instead." ;
+
+using doxygen ;
diff --git a/tools/build/v2/tools/doxygen.jam b/tools/build/v2/tools/doxygen.jam
new file mode 100644
index 0000000000..8394848dd5
--- /dev/null
+++ b/tools/build/v2/tools/doxygen.jam
@@ -0,0 +1,776 @@
+# Copyright 2003, 2004 Douglas Gregor
+# Copyright 2003, 2004, 2005 Vladimir Prus
+# Copyright 2006 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This module defines rules to handle generation of various outputs from source
+# files documented with doxygen comments. The supported transformations are:
+#
+# * Source -> Doxygen XML -> BoostBook XML
+# * Source -> Doxygen HTML
+#
+# The type of transformation is selected based on the target requested. For
+# BoostBook XML, the default, specifying a target with an ".xml" suffix, or an
+# empty suffix, will produce a <target>.xml and <target>.boostbook. For Doxygen
+# HTML specifying a target with an ".html" suffix will produce a directory
+# <target> with the Doxygen html files, and a <target>.html file redirecting to
+# that directory.
+
+import "class" : new ;
+import targets ;
+import feature ;
+import property ;
+import generators ;
+import boostbook ;
+import type ;
+import path ;
+import print ;
+import regex ;
+import stage ;
+import project ;
+import xsltproc ;
+import make ;
+import os ;
+import toolset : flags ;
+import alias ;
+import common ;
+import modules ;
+import project ;
+import utility ;
+import errors ;
+
+
+# Use to specify extra configuration paramters. These get translated
+# into a doxyfile which configures the building of the docs.
+feature.feature doxygen:param : : free ;
+
+# Specify the "<xsl:param>boost.doxygen.header.prefix" XSLT option.
+feature.feature prefix : : free ;
+
+# Specify the "<xsl:param>boost.doxygen.reftitle" XSLT option.
+feature.feature reftitle : : free ;
+
+# Which processor to use for various translations from Doxygen.
+feature.feature doxygen.processor : xsltproc doxproc : propagated implicit ;
+
+# To generate, or not, index sections.
+feature.feature doxygen.doxproc.index : no yes : propagated incidental ;
+
+# The ID for the resulting BoostBook reference section.
+feature.feature doxygen.doxproc.id : : free ;
+
+# The title for the resulting BoostBook reference section.
+feature.feature doxygen.doxproc.title : : free ;
+
+# Location for images when generating XML
+feature.feature doxygen:xml-imagedir : : free ;
+
+# Indicates whether the entire directory should be deleted
+feature.feature doxygen.rmdir : off on : optional incidental ;
+
+# Doxygen configuration input file.
+type.register DOXYFILE : doxyfile ;
+
+# Doxygen XML multi-file output.
+type.register DOXYGEN_XML_MULTIFILE : xml-dir : XML ;
+
+# Doxygen XML coallesed output.
+type.register DOXYGEN_XML : doxygen : XML ;
+
+# Doxygen HTML multifile directory.
+type.register DOXYGEN_HTML_MULTIFILE : html-dir : HTML ;
+
+# Redirection HTML file to HTML multifile directory.
+type.register DOXYGEN_HTML : : HTML ;
+
+type.register DOXYGEN_XML_IMAGES : doxygen-xml-images ;
+
+# Initialize the Doxygen module. Parameters are:
+# name: the name of the 'doxygen' executable. If not specified, the name
+# 'doxygen' will be used
+#
+rule init ( name ? )
+{
+ if ! $(.initialized)
+ {
+ .initialized = true ;
+
+ .doxproc = [ modules.binding $(__name__) ] ;
+ .doxproc = $(.doxproc:D)/doxproc.py ;
+
+ generators.register-composing doxygen.headers-to-doxyfile
+ : H HPP CPP : DOXYFILE ;
+ generators.register-standard doxygen.run
+ : DOXYFILE : DOXYGEN_XML_MULTIFILE ;
+ generators.register-standard doxygen.xml-dir-to-boostbook
+ : DOXYGEN_XML_MULTIFILE : BOOSTBOOK : <doxygen.processor>doxproc ;
+ generators.register-standard doxygen.xml-to-boostbook
+ : DOXYGEN_XML : BOOSTBOOK : <doxygen.processor>xsltproc ;
+ generators.register-standard doxygen.collect
+ : DOXYGEN_XML_MULTIFILE : DOXYGEN_XML ;
+ generators.register-standard doxygen.run
+ : DOXYFILE : DOXYGEN_HTML_MULTIFILE ;
+ generators.register-standard doxygen.html-redirect
+ : DOXYGEN_HTML_MULTIFILE : DOXYGEN_HTML ;
+ generators.register-standard doxygen.copy-latex-pngs
+ : DOXYGEN_HTML : DOXYGEN_XML_IMAGES ;
+
+ IMPORT $(__name__) : doxygen : : doxygen ;
+ }
+
+ if $(name)
+ {
+ modify-config ;
+ .doxygen = $(name) ;
+ check-doxygen ;
+ }
+
+ if ! $(.doxygen)
+ {
+ check-doxygen ;
+ }
+}
+
+rule freeze-config ( )
+{
+ if ! $(.initialized)
+ {
+ errors.user-error "doxygen must be initialized before it can be used." ;
+ }
+ if ! $(.config-frozen)
+ {
+ .config-frozen = true ;
+
+ if [ .is-cygwin ]
+ {
+ .is-cygwin = true ;
+ }
+ }
+}
+
+rule modify-config ( )
+{
+ if $(.config-frozen)
+ {
+ errors.user-error "Cannot change doxygen after it has been used." ;
+ }
+}
+
+rule check-doxygen ( )
+{
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice:" using doxygen ":" $(.doxygen) ;
+ }
+ local extra-paths ;
+ if [ os.name ] = NT
+ {
+ local ProgramFiles = [ modules.peek : ProgramFiles ] ;
+ if $(ProgramFiles)
+ {
+ extra-paths = "$(ProgramFiles:J= )" ;
+ }
+ else
+ {
+ extra-paths = "C:\\Program Files" ;
+ }
+ }
+ .doxygen = [ common.get-invocation-command doxygen :
+ doxygen : $(.doxygen) : $(extra-paths) ] ;
+}
+
+rule name ( )
+{
+ freeze-config ;
+ return $(.doxygen) ;
+}
+
+rule .is-cygwin ( )
+{
+ if [ os.on-windows ]
+ {
+ local file = [ path.make [ modules.binding $(__name__) ] ] ;
+ local dir = [ path.native
+ [ path.join [ path.parent $(file) ] doxygen ] ] ;
+ local command =
+ "cd \"$(dir)\" && \"$(.doxygen)\" windows-paths-check.doxyfile 2>&1" ;
+ result = [ SHELL $(command) ] ;
+ if [ MATCH "(Parsing file /)" : $(result) ]
+ {
+ return true ;
+ }
+ }
+}
+
+# Runs Doxygen on the given Doxygen configuration file (the source) to generate
+# the Doxygen files. The output is dumped according to the settings in the
+# Doxygen configuration file, not according to the target! Because of this, we
+# essentially "touch" the target file, in effect making it look like we have
+# really written something useful to it. Anyone that uses this action must deal
+# with this behavior.
+#
+actions doxygen-action
+{
+ $(RM) "$(*.XML)" & "$(NAME:E=doxygen)" "$(>)" && echo "Stamped" > "$(<)"
+}
+
+
+# Runs the Python doxproc XML processor.
+#
+actions doxproc
+{
+ python "$(DOXPROC)" "--xmldir=$(>)" "--output=$(<)" "$(OPTIONS)" "--id=$(ID)" "--title=$(TITLE)"
+}
+
+
+rule translate-path ( path )
+{
+ freeze-config ;
+ if [ os.on-windows ]
+ {
+ if [ os.name ] = CYGWIN
+ {
+ if $(.is-cygwin)
+ {
+ return $(path) ;
+ }
+ else
+ {
+ return $(path:W) ;
+ }
+ }
+ else
+ {
+ if $(.is-cygwin)
+ {
+ match = [ MATCH ^(.):(.*) : $(path) ] ;
+ if $(match)
+ {
+ return /cygdrive/$(match[1])$(match[2]:T) ;
+ }
+ else
+ {
+ return $(path:T) ;
+ }
+ }
+ else
+ {
+ return $(path) ;
+ }
+ }
+ }
+ else
+ {
+ return $(path) ;
+ }
+}
+
+
+# Generates a doxygen configuration file (doxyfile) given a set of C++ sources
+# and a property list that may contain <doxygen:param> features.
+#
+rule headers-to-doxyfile ( target : sources * : properties * )
+{
+ local text "# Generated by Boost.Build version 2" ;
+
+ local output-dir ;
+
+ # Translate <doxygen:param> into command line flags.
+ for local param in [ feature.get-values <doxygen:param> : $(properties) ]
+ {
+ local namevalue = [ regex.match ([^=]*)=(.*) : $(param) ] ;
+ if $(namevalue[1]) = OUTPUT_DIRECTORY
+ {
+ output-dir = [ translate-path
+ [ utility.unquote $(namevalue[2]) ] ] ;
+ text += "OUTPUT_DIRECTORY = \"$(output-dir)\"" ;
+ }
+ else
+ {
+ text += "$(namevalue[1]) = $(namevalue[2])" ;
+ }
+ }
+
+ if ! $(output-dir)
+ {
+ output-dir = [ translate-path [ on $(target) return $(LOCATE) ] ] ;
+ text += "OUTPUT_DIRECTORY = \"$(output-dir)\"" ;
+ }
+
+ local headers = ;
+ for local header in $(sources:G=)
+ {
+ header = [ translate-path $(header) ] ;
+ headers += \"$(header)\" ;
+ }
+
+ # Doxygen generates LaTex by default. So disable it unconditionally, or at
+ # least until someone needs, and hence writes support for, LaTex output.
+ text += "GENERATE_LATEX = NO" ;
+ text += "INPUT = $(headers:J= )" ;
+ print.output $(target) plain ;
+ print.text $(text) : true ;
+}
+
+
+# Run Doxygen. See doxygen-action for a description of the strange properties of
+# this rule.
+#
+rule run ( target : source : properties * )
+{
+ freeze-config ;
+ if <doxygen.rmdir>on in $(properties)
+ {
+ local output-dir =
+ [ path.make
+ [ MATCH <doxygen:param>OUTPUT_DIRECTORY=\"?([^\"]*) :
+ $(properties) ] ] ;
+ local html-dir =
+ [ path.make
+ [ MATCH <doxygen:param>HTML_OUTPUT=(.*) :
+ $(properties) ] ] ;
+ if $(output-dir) && $(html-dir) &&
+ [ path.glob $(output-dir) : $(html-dir) ]
+ {
+ HTMLDIR on $(target) =
+ [ path.native [ path.join $(output-dir) $(html-dir) ] ] ;
+ rm-htmldir $(target) ;
+ }
+ }
+ doxygen-action $(target) : $(source) ;
+ NAME on $(target) = $(.doxygen) ;
+ RM on $(target) = [ modules.peek common : RM ] ;
+ *.XML on $(target) =
+ [ path.native
+ [ path.join
+ [ path.make [ on $(target) return $(LOCATE) ] ]
+ $(target:B:S=)
+ *.xml ] ] ;
+}
+
+if [ os.name ] = NT
+{
+ RMDIR = rmdir /s /q ;
+}
+else
+{
+ RMDIR = rm -rf ;
+}
+
+actions quietly rm-htmldir
+{
+ $(RMDIR) $(HTMLDIR)
+}
+
+# The rules below require Boost.Book stylesheets, so we need some code to check
+# that the boostbook module has actualy been initialized.
+#
+rule check-boostbook ( )
+{
+ if ! [ modules.peek boostbook : .initialized ]
+ {
+ ECHO "error: the boostbook module is not initialized" ;
+ ECHO "error: you've attempted to use the 'doxygen' toolset, " ;
+ ECHO "error: which requires Boost.Book," ;
+ ECHO "error: but never initialized Boost.Book." ;
+ EXIT "error: Hint: add 'using boostbook ;' to your user-config.jam" ;
+ }
+}
+
+
+# Collect the set of Doxygen XML files into a single XML source file that can be
+# handled by an XSLT processor. The source is completely ignored (see
+# doxygen-action), because this action picks up the Doxygen XML index file
+# xml/index.xml. This is because we can not teach Doxygen to act like a NORMAL
+# program and take a "-o output.xml" argument (grrrr). The target of the
+# collection will be a single Doxygen XML file.
+#
+rule collect ( target : source : properties * )
+{
+ check-boostbook ;
+ local collect-xsl-dir
+ = [ path.native [ path.join [ boostbook.xsl-dir ] doxygen collect ] ] ;
+ local source-path
+ = [ path.make [ on $(source) return $(LOCATE) ] ] ;
+ local collect-path
+ = [ path.root [ path.join $(source-path) $(source:B) ] [ path.pwd ] ] ;
+ local native-path
+ = [ path.native $(collect-path) ] ;
+ local real-source
+ = [ path.native [ path.join $(collect-path) index.xml ] ] ;
+ xsltproc.xslt $(target) : $(real-source) $(collect-xsl-dir:S=.xsl)
+ : <xsl:param>doxygen.xml.path=$(native-path) ;
+}
+
+
+# Translate Doxygen XML into BoostBook.
+#
+rule xml-to-boostbook ( target : source : properties * )
+{
+ check-boostbook ;
+ local xsl-dir = [ boostbook.xsl-dir ] ;
+ local d2b-xsl = [ path.native [ path.join [ boostbook.xsl-dir ] doxygen
+ doxygen2boostbook.xsl ] ] ;
+
+ local xslt-properties = $(properties) ;
+ for local prefix in [ feature.get-values <prefix> : $(properties) ]
+ {
+ xslt-properties += "<xsl:param>boost.doxygen.header.prefix=$(prefix)" ;
+ }
+ for local title in [ feature.get-values <reftitle> : $(properties) ]
+ {
+ xslt-properties += "<xsl:param>boost.doxygen.reftitle=$(title)" ;
+ }
+
+ xsltproc.xslt $(target) : $(source) $(d2b-xsl) : $(xslt-properties) ;
+}
+
+
+flags doxygen.xml-dir-to-boostbook OPTIONS <doxygen.doxproc.index>yes : --enable-index ;
+flags doxygen.xml-dir-to-boostbook ID <doxygen.doxproc.id> ;
+flags doxygen.xml-dir-to-boostbook TITLE <doxygen.doxproc.title> ;
+
+
+rule xml-dir-to-boostbook ( target : source : properties * )
+{
+ DOXPROC on $(target) = $(.doxproc) ;
+
+ LOCATE on $(source:S=) = [ on $(source) return $(LOCATE) ] ;
+
+ doxygen.doxproc $(target) : $(source:S=) ;
+}
+
+
+# Generate the HTML redirect to HTML dir index.html file.
+#
+rule html-redirect ( target : source : properties * )
+{
+ local uri = "$(target:B)/index.html" ;
+ print.output $(target) plain ;
+ print.text
+"<!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\">
+<head>
+ <meta http-equiv=\"refresh\" content=\"0; URL=$(uri)\" />
+
+ <title></title>
+</head>
+
+<body>
+ Automatic redirection failed, please go to <a href=
+ \"$(uri)\">$(uri)</a>.
+</body>
+</html>
+"
+ : true ;
+}
+
+rule copy-latex-pngs ( target : source : requirements * )
+{
+ local directory = [ path.native
+ [ feature.get-values <doxygen:xml-imagedir> :
+ $(requirements) ] ] ;
+
+ local location = [ on $(target) return $(LOCATE) ] ;
+
+ local pdf-location =
+ [ path.native
+ [ path.join
+ [ path.make $(location) ]
+ [ path.make $(directory) ] ] ] ;
+ local html-location =
+ [ path.native
+ [ path.join
+ .
+ html
+ [ path.make $(directory) ] ] ] ;
+
+ common.MkDir $(pdf-location) ;
+ common.MkDir $(html-location) ;
+
+ DEPENDS $(target) : $(pdf-location) $(html-location) ;
+
+ if [ os.name ] = NT
+ {
+ CP on $(target) = copy /y ;
+ FROM on $(target) = \\*.png ;
+ TOHTML on $(target) = .\\html\\$(directory) ;
+ TOPDF on $(target) = \\$(directory) ;
+ }
+ else
+ {
+ CP on $(target) = cp ;
+ FROM on $(target) = /*.png ;
+ TOHTML on $(target) = ./html/$(directory) ;
+ TOPDF on $(target) = $(target:D)/$(directory) ;
+ }
+}
+
+actions copy-latex-pngs
+{
+ $(CP) $(>:S=)$(FROM) $(TOHTML)
+ $(CP) $(>:S=)$(FROM) $(<:D)$(TOPDF)
+ echo "Stamped" > "$(<)"
+}
+
+# building latex images for doxygen XML depends
+# on latex, dvips, and ps being in your PATH.
+# This is true for most Unix installs, but
+# not on Win32, where you will need to install
+# MkTex and Ghostscript and add these tools
+# to your path.
+
+actions check-latex
+{
+ latex -version >$(<)
+}
+
+actions check-dvips
+{
+ dvips -version >$(<)
+}
+
+if [ os.name ] = "NT"
+{
+ actions check-gs
+ {
+ gswin32c -version >$(<)
+ }
+}
+else
+{
+ actions check-gs
+ {
+ gs -version >$(<)
+ }
+}
+
+rule check-tools ( )
+{
+ if ! $(.check-tools-targets)
+ {
+ # Find the root project.
+ local root-project = [ project.current ] ;
+ root-project = [ $(root-project).project-module ] ;
+ while
+ [ project.attribute $(root-project) parent-module ] &&
+ [ project.attribute $(root-project) parent-module ] != user-config
+ {
+ root-project =
+ [ project.attribute $(root-project) parent-module ] ;
+ }
+
+ .latex.check = [ new file-target latex.check
+ :
+ : [ project.target $(root-project) ]
+ : [ new action : doxygen.check-latex ]
+ :
+ ] ;
+ .dvips.check = [ new file-target dvips.check
+ :
+ : [ project.target $(root-project) ]
+ : [ new action : doxygen.check-dvips ]
+ :
+ ] ;
+ .gs.check = [ new file-target gs.check
+ :
+ : [ project.target $(root-project) ]
+ : [ new action : doxygen.check-gs ]
+ :
+ ] ;
+ .check-tools-targets = $(.latex.check) $(.dvips.check) $(.gs.check) ;
+ }
+ return $(.check-tools-targets) ;
+}
+
+project.initialize $(__name__) ;
+project doxygen ;
+
+class doxygen-check-tools-target-class : basic-target
+{
+ import doxygen ;
+ rule construct ( name : sources * : property-set )
+ {
+ return [ property-set.empty ] [ doxygen.check-tools ] ;
+ }
+}
+
+local project = [ project.current ] ;
+
+targets.main-target-alternative
+ [ new doxygen-check-tools-target-class check-tools : $(project)
+ : [ targets.main-target-sources : check-tools : no-renaming ]
+ : [ targets.main-target-requirements : $(project) ]
+ : [ targets.main-target-default-build : $(project) ]
+ : [ targets.main-target-usage-requirements : $(project) ]
+ ] ;
+
+# User-level rule to generate BoostBook XML from a set of headers via Doxygen.
+#
+rule doxygen ( target : sources * : requirements * : default-build * : usage-requirements * )
+{
+ freeze-config ;
+ local project = [ project.current ] ;
+
+ if $(target:S) = .html
+ {
+ # Build an HTML directory from the sources.
+ local html-location = [ feature.get-values <location> : $(requirements) ] ;
+ local output-dir ;
+ if [ $(project).get build-dir ]
+ {
+ # Explicitly specified build dir. Add html at the end.
+ output-dir = [ path.join [ $(project).build-dir ] $(html-location:E=html) ] ;
+ }
+ else
+ {
+ # Trim 'bin' from implicit build dir, for no other reason that backward
+ # compatibility.
+ output-dir = [ path.join [ path.parent [ $(project).build-dir ] ]
+ $(html-location:E=html) ] ;
+ }
+ output-dir = [ path.root $(output-dir) [ path.pwd ] ] ;
+ local output-dir-native = [ path.native $(output-dir) ] ;
+ requirements = [ property.change $(requirements) : <location> ] ;
+
+ ## The doxygen configuration file.
+ targets.main-target-alternative
+ [ new typed-target $(target:S=.tag) : $(project) : DOXYFILE
+ : [ targets.main-target-sources $(sources) : $(target:S=.tag) ]
+ : [ targets.main-target-requirements $(requirements)
+ <doxygen:param>GENERATE_HTML=YES
+ <doxygen:param>GENERATE_XML=NO
+ <doxygen:param>"OUTPUT_DIRECTORY=\"$(output-dir-native)\""
+ <doxygen:param>HTML_OUTPUT=$(target:B)
+ : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+ $(project).mark-target-as-explicit $(target:S=.tag) ;
+
+ ## The html directory to generate by running doxygen.
+ targets.main-target-alternative
+ [ new typed-target $(target:S=.dir) : $(project) : DOXYGEN_HTML_MULTIFILE
+ : $(target:S=.tag)
+ : [ targets.main-target-requirements $(requirements)
+ <doxygen:param>"OUTPUT_DIRECTORY=\"$(output-dir-native)\""
+ <doxygen:param>HTML_OUTPUT=$(target:B)
+ : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+ $(project).mark-target-as-explicit $(target:S=.dir) ;
+
+ ## The redirect html file into the generated html.
+ targets.main-target-alternative
+ [ new typed-target $(target) : $(project) : DOXYGEN_HTML
+ : $(target:S=.dir)
+ : [ targets.main-target-requirements $(requirements)
+ <location>$(output-dir)
+ : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+ }
+ else
+ {
+ # Build a BoostBook XML file from the sources.
+ local location-xml = [ feature.get-values <location> : $(requirements) ] ;
+ requirements = [ property.change $(requirements) : <location> ] ;
+ local target-xml = $(target:B=$(target:B)-xml) ;
+
+ # Check whether we need to build images
+ local images-location =
+ [ feature.get-values <doxygen:xml-imagedir> : $(requirements) ] ;
+ if $(images-location)
+ {
+ doxygen $(target).doxygen-xml-images.html : $(sources)
+ : $(requirements)
+ <doxygen.rmdir>on
+ <doxygen:param>QUIET=YES
+ <doxygen:param>WARNINGS=NO
+ <doxygen:param>WARN_IF_UNDOCUMENTED=NO
+ <dependency>/doxygen//check-tools ;
+ $(project).mark-target-as-explicit
+ $(target).doxygen-xml-images.html ;
+
+ targets.main-target-alternative
+ [ new typed-target $(target).doxygen-xml-images
+ : $(project) : DOXYGEN_XML_IMAGES
+ : $(target).doxygen-xml-images.html
+ : [ targets.main-target-requirements $(requirements)
+ : $(project) ]
+ : [ targets.main-target-default-build $(default-build)
+ : $(project) ]
+ ] ;
+
+ $(project).mark-target-as-explicit
+ $(target).doxygen-xml-images ;
+
+ if ! [ regex.match "^(.*/)$" : $(images-location) ]
+ {
+ images-location = $(images-location)/ ;
+ }
+
+ requirements +=
+ <dependency>$(target).doxygen-xml-images
+ <xsl:param>boost.doxygen.formuladir=$(images-location) ;
+ }
+
+ ## The doxygen configuration file.
+ targets.main-target-alternative
+ [ new typed-target $(target-xml:S=.tag) : $(project) : DOXYFILE
+ : [ targets.main-target-sources $(sources) : $(target-xml:S=.tag) ]
+ : [ targets.main-target-requirements $(requirements)
+ <doxygen:param>GENERATE_HTML=NO
+ <doxygen:param>GENERATE_XML=YES
+ <doxygen:param>XML_OUTPUT=$(target-xml)
+ : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+ $(project).mark-target-as-explicit $(target-xml:S=.tag) ;
+
+ ## The Doxygen XML directory of the processed source files.
+ targets.main-target-alternative
+ [ new typed-target $(target-xml:S=.dir) : $(project) : DOXYGEN_XML_MULTIFILE
+ : $(target-xml:S=.tag)
+ : [ targets.main-target-requirements $(requirements)
+ : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+ $(project).mark-target-as-explicit $(target-xml:S=.dir) ;
+
+ ## The resulting BoostBook file is generated by the processor tool. The
+ ## tool can be either the xsltproc plus accompanying XSL scripts. Or it
+ ## can be the python doxproc.py script.
+ targets.main-target-alternative
+ [ new typed-target $(target-xml) : $(project) : BOOSTBOOK
+ : $(target-xml:S=.dir)
+ : [ targets.main-target-requirements $(requirements)
+ : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+ $(project).mark-target-as-explicit $(target-xml) ;
+
+ targets.main-target-alternative
+ [ new install-target-class $(target:S=.xml) : $(project)
+ : $(target-xml)
+ : [ targets.main-target-requirements $(requirements)
+ <location>$(location-xml:E=.)
+ <name>$(target:S=.xml)
+ : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+ $(project).mark-target-as-explicit $(target:S=.xml) ;
+
+ targets.main-target-alternative
+ [ new alias-target-class $(target) : $(project)
+ :
+ : [ targets.main-target-requirements $(requirements)
+ : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements)
+ <dependency>$(target:S=.xml)
+ : $(project) ]
+ ] ;
+ }
+}
diff --git a/tools/build/v2/tools/doxygen/windows-paths-check.doxyfile b/tools/build/v2/tools/doxygen/windows-paths-check.doxyfile
new file mode 100644
index 0000000000..9b969df9c7
--- /dev/null
+++ b/tools/build/v2/tools/doxygen/windows-paths-check.doxyfile
@@ -0,0 +1,3 @@
+INPUT = windows-paths-check.hpp
+GENERATE_HTML = NO
+GENERATE_LATEX = NO
diff --git a/tools/build/v2/tools/doxygen/windows-paths-check.hpp b/tools/build/v2/tools/doxygen/windows-paths-check.hpp
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/build/v2/tools/doxygen/windows-paths-check.hpp
diff --git a/tools/build/v2/tools/fop.jam b/tools/build/v2/tools/fop.jam
new file mode 100644
index 0000000000..c24b8725f9
--- /dev/null
+++ b/tools/build/v2/tools/fop.jam
@@ -0,0 +1,69 @@
+# Copyright (C) 2003-2004 Doug Gregor and Dave Abrahams. Distributed
+# under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+# This module defines rules to handle generation of PDF and
+# PostScript files from XSL Formatting Objects via Apache FOP
+
+import generators ;
+import common ;
+import boostbook ;
+
+generators.register-standard fop.render.pdf : FO : PDF ;
+generators.register-standard fop.render.ps : FO : PS ;
+
+# Initializes the fop toolset.
+#
+rule init ( fop-command ? : java-home ? : java ? )
+{
+ local has-command = $(.has-command) ;
+
+ if $(fop-command)
+ {
+ .has-command = true ;
+ }
+
+ if $(fop-command) || ! $(has-command)
+ {
+ fop-command = [ common.get-invocation-command fop : fop : $(fop-command)
+ : [ modules.peek : FOP_DIR ] ] ;
+ }
+
+ if $(fop-command)
+ {
+ .FOP_COMMAND = $(fop-command) ;
+ }
+
+ if $(java-home) || $(java)
+ {
+ .FOP_SETUP = ;
+
+
+ # JAVA_HOME is the location that java was installed to.
+
+ if $(java-home)
+ {
+ .FOP_SETUP += [ common.variable-setting-command JAVA_HOME : $(java-home) ] ;
+ }
+
+ # JAVACMD is the location that of the java executable, useful for a
+ # non-standard java installation, where the executable isn't at
+ # $JAVA_HOME/bin/java.
+
+ if $(java)
+ {
+ .FOP_SETUP += [ common.variable-setting-command JAVACMD : $(java) ] ;
+ }
+ }
+}
+
+actions render.pdf
+{
+ $(.FOP_SETUP) $(.FOP_COMMAND:E=fop) $(>) $(<)
+}
+
+actions render.ps
+{
+ $(.FOP_SETUP) $(.FOP_COMMAND:E=fop) $(>) -ps $(<)
+}
diff --git a/tools/build/v2/tools/fortran.jam b/tools/build/v2/tools/fortran.jam
new file mode 100644
index 0000000000..37665825ef
--- /dev/null
+++ b/tools/build/v2/tools/fortran.jam
@@ -0,0 +1,55 @@
+# Copyright (C) 2004 Toon Knapen
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+#
+# This file contains common settings for all fortran tools
+#
+
+import "class" : new ;
+import feature : feature ;
+
+import type ;
+import generators ;
+import common ;
+
+type.register FORTRAN : f F for f77 ;
+type.register FORTRAN90 : f90 F90 ;
+
+feature fortran : : free ;
+feature fortran90 : : free ;
+
+class fortran-compiling-generator : generator
+{
+ rule __init__ ( id : source-types + : target-types + : requirements * : optional-properties * )
+ {
+ generator.__init__ $(id) : $(source-types) : $(target-types) : $(requirements) : $(optional-properties) ;
+ }
+}
+
+rule register-fortran-compiler ( id : source-types + : target-types + : requirements * : optional-properties * )
+{
+ local g = [ new fortran-compiling-generator $(id) : $(source-types) : $(target-types) : $(requirements) : $(optional-properties) ] ;
+ generators.register $(g) ;
+}
+
+class fortran90-compiling-generator : generator
+{
+ rule __init__ ( id : source-types + : target-types + : requirements * : optional-properties * )
+ {
+ generator.__init__ $(id) : $(source-types) : $(target-types) : $(requirements) : $(optional-properties) ;
+ }
+}
+
+rule register-fortran90-compiler ( id : source-types + : target-types + : requirements * : optional-properties * )
+{
+ local g = [ new fortran90-compiling-generator $(id) : $(source-types) : $(target-types) : $(requirements) : $(optional-properties) ] ;
+ generators.register $(g) ;
+}
+
+# FIXME: this is ugly, should find a better way (we'd want client code to
+# register all generators as "generator.some-rule", not with "some-module.some-rule".)
+IMPORT $(__name__) : register-fortran-compiler : : generators.register-fortran-compiler ;
+IMPORT $(__name__) : register-fortran90-compiler : : generators.register-fortran90-compiler ;
diff --git a/tools/build/v2/tools/gcc.jam b/tools/build/v2/tools/gcc.jam
new file mode 100644
index 0000000000..f7b0da542e
--- /dev/null
+++ b/tools/build/v2/tools/gcc.jam
@@ -0,0 +1,1185 @@
+# Copyright 2001 David Abrahams.
+# Copyright 2002-2006 Rene Rivera.
+# Copyright 2002-2003 Vladimir Prus.
+# Copyright (c) 2005 Reece H. Dunn.
+# Copyright 2006 Ilya Sokolov.
+# Copyright 2007 Roland Schwarz
+# Copyright 2007 Boris Gubenko.
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import "class" : new ;
+import common ;
+import errors ;
+import feature ;
+import generators ;
+import os ;
+import pch ;
+import property ;
+import property-set ;
+import toolset ;
+import type ;
+import rc ;
+import regex ;
+import set ;
+import unix ;
+import fortran ;
+
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+
+feature.extend toolset : gcc ;
+# feature.subfeature toolset gcc : flavor : : optional ;
+
+toolset.inherit-generators gcc : unix : unix.link unix.link.dll ;
+toolset.inherit-flags gcc : unix ;
+toolset.inherit-rules gcc : unix ;
+
+generators.override gcc.prebuilt : builtin.prebuilt ;
+generators.override gcc.searched-lib-generator : searched-lib-generator ;
+
+# Make gcc toolset object files use the "o" suffix on all platforms.
+type.set-generated-target-suffix OBJ : <toolset>gcc : o ;
+type.set-generated-target-suffix OBJ : <toolset>gcc <target-os>windows : o ;
+type.set-generated-target-suffix OBJ : <toolset>gcc <target-os>cygwin : o ;
+
+# Initializes the gcc toolset for the given version. If necessary, command may
+# be used to specify where the compiler is located. The parameter 'options' is a
+# space-delimited list of options, each one specified as
+# <option-name>option-value. Valid option names are: cxxflags, linkflags and
+# linker-type. Accepted linker-type values are aix, darwin, gnu, hpux, osf or
+# sun and the default value will be selected based on the current OS.
+# Example:
+# using gcc : 3.4 : : <cxxflags>foo <linkflags>bar <linker-type>sun ;
+#
+# The compiler command to use is detected in a three step manner:
+# 1) If an explicit command is specified by the user, it will be used and must available.
+# 2) If only a certain version is specified, it is enforced:
+# - either a command 'g++-VERSION' must be available
+# - or the default command 'g++' must be available and match the exact version.
+# 3) Without user-provided restrictions use default 'g++'
+rule init ( version ? : command * : options * )
+{
+ #1): use user-provided command
+ local tool-command = ;
+ if $(command)
+ {
+ tool-command = [ common.get-invocation-command-nodefault gcc : g++ : $(command) ] ;
+ if ! $(tool-command)
+ {
+ errors.error "toolset gcc initialization:" :
+ "provided command '$(command)' not found" :
+ "initialized from" [ errors.nearest-user-location ] ;
+ }
+ }
+ #2): enforce user-provided version
+ else if $(version)
+ {
+ tool-command = [ common.get-invocation-command-nodefault gcc : "g++-$(version[1])" ] ;
+
+ #2.1) fallback: check whether "g++" reports the requested version
+ if ! $(tool-command)
+ {
+ tool-command = [ common.get-invocation-command-nodefault gcc : g++ ] ;
+ if $(tool-command)
+ {
+ local tool-command-string = $(tool-command:J=" ") ;
+ local tool-version = [ MATCH "^([0-9.]+)" : [ SHELL "$(tool-command-string) -dumpversion" ] ] ;
+ if $(tool-version) != $(version)
+ {
+ # Permit a match betwen two-digit version specified by the user
+ # (e.g. 4.4) and 3-digit version reported by gcc.
+ # Since only two digits are present in binary name anyway,
+ # insisting that user specify 3-digit version when
+ # configuring Boost.Build while it's not required on
+ # command like would be strange.
+ local stripped = [ MATCH "^([0-9]+\.[0-9]+).*" : $(tool-version) ] ;
+ if $(stripped) != $(version)
+ {
+ errors.error "toolset gcc initialization:" :
+ "version '$(version)' requested but 'g++-$(version)' not found and version '$(tool-version)' of default '$(tool-command)' does not match" :
+ "initialized from" [ errors.nearest-user-location ] ;
+ tool-command = ;
+ }
+ # Use full 3-digit version to be compatible with the 'using gcc ;' case
+ version = $(tool-version) ;
+ }
+ }
+ else
+ {
+ errors.error "toolset gcc initialization:" :
+ "version '$(version)' requested but neither 'g++-$(version)' nor default 'g++' found" :
+ "initialized from" [ errors.nearest-user-location ] ;
+ }
+ }
+ }
+ #3) default: no command and no version specified, try using default command "g++"
+ else
+ {
+ tool-command = [ common.get-invocation-command-nodefault gcc : g++ ] ;
+ if ! $(tool-command)
+ {
+ errors.error "toolset gcc initialization:" :
+ "no command provided, default command 'g++' not found" :
+ "initialized from" [ errors.nearest-user-location ] ;
+ }
+ }
+
+
+ # Information about the gcc command...
+ # The command.
+ local command = $(tool-command) ;
+ # The root directory of the tool install.
+ local root = [ feature.get-values <root> : $(options) ] ;
+ # The bin directory where to find the command to execute.
+ local bin ;
+ # The flavor of compiler.
+ local flavor = [ feature.get-values <flavor> : $(options) ] ;
+ # Autodetect the root and bin dir if not given.
+ if $(command)
+ {
+ bin ?= [ common.get-absolute-tool-path $(command[-1]) ] ;
+ root ?= $(bin:D) ;
+ }
+ # The 'command' variable can have multiple elements. When calling
+ # the SHELL builtin we need a single string.
+ local command-string = $(command:J=" ") ;
+ # Autodetect the version and flavor if not given.
+ if $(command)
+ {
+ local machine = [ MATCH "^([^ ]+)"
+ : [ SHELL "$(command-string) -dumpmachine" ] ] ;
+ version ?= [ MATCH "^([0-9.]+)"
+ : [ SHELL "$(command-string) -dumpversion" ] ] ;
+ switch $(machine:L)
+ {
+ case *mingw* : flavor ?= mingw ;
+ }
+ }
+
+ local condition ;
+ if $(flavor)
+ {
+ condition = [ common.check-init-parameters gcc
+ : version $(version)
+ : flavor $(flavor)
+ ] ;
+ }
+ else
+ {
+ condition = [ common.check-init-parameters gcc
+ : version $(version)
+ ] ;
+ condition = $(condition) ; #/<toolset-gcc:flavor> ;
+ }
+
+ common.handle-options gcc : $(condition) : $(command) : $(options) ;
+
+ local linker = [ feature.get-values <linker-type> : $(options) ] ;
+ # The logic below should actually be keyed on <target-os>
+ if ! $(linker)
+ {
+ if [ os.name ] = OSF
+ {
+ linker = osf ;
+ }
+ else if [ os.name ] = HPUX
+ {
+ linker = hpux ;
+ }
+ else if [ os.name ] = AIX
+ {
+ linker = aix ;
+ }
+ else if [ os.name ] = SOLARIS
+ {
+ linker = sun ;
+ }
+ else
+ {
+ linker = gnu ;
+ }
+ }
+ init-link-flags gcc $(linker) $(condition) ;
+
+
+ # If gcc is installed in non-standard location, we'd need to add
+ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run
+ # rules).
+ if $(command)
+ {
+ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries
+ # and all must be added to LD_LIBRARY_PATH. The linker will pick the
+ # right onces. Note that we don't provide a clean way to build 32-bit
+ # binary with 64-bit compiler, but user can always pass -m32 manually.
+ local lib_path = $(root)/bin $(root)/lib $(root)/lib32 $(root)/lib64 ;
+ if $(.debug-configuration)
+ {
+ ECHO notice: using gcc libraries :: $(condition) :: $(lib_path) ;
+ }
+ toolset.flags gcc.link RUN_PATH $(condition) : $(lib_path) ;
+ }
+
+ # If it's not a system gcc install we should adjust the various programs as
+ # needed to prefer using the install specific versions. This is essential
+ # for correct use of MinGW and for cross-compiling.
+
+ local nl = "
+" ;
+
+ # - The archive builder.
+ local archiver = [ common.get-invocation-command gcc
+ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ar" ] ] ]
+ : [ feature.get-values <archiver> : $(options) ]
+ : $(bin)
+ : search-path ] ;
+ toolset.flags gcc.archive .AR $(condition) : $(archiver[1]) ;
+ if $(.debug-configuration)
+ {
+ ECHO notice: using gcc archiver :: $(condition) :: $(archiver[1]) ;
+ }
+
+ # - Ranlib
+ local ranlib = [ common.get-invocation-command gcc
+ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ranlib" ] ] ]
+ : [ feature.get-values <ranlib> : $(options) ]
+ : $(bin)
+ : search-path ] ;
+ toolset.flags gcc.archive .RANLIB $(condition) : $(ranlib[1]) ;
+ if $(.debug-configuration)
+ {
+ ECHO notice: using gcc ranlib :: $(condition) :: $(ranlib[1]) ;
+ }
+
+
+ # - The resource compiler.
+ local rc =
+ [ common.get-invocation-command-nodefault gcc
+ : windres : [ feature.get-values <rc> : $(options) ] : $(bin) : search-path ] ;
+ local rc-type =
+ [ feature.get-values <rc-type> : $(options) ] ;
+ rc-type ?= windres ;
+ if ! $(rc)
+ {
+ # If we can't find an RC compiler we fallback to a null RC compiler that
+ # creates empty object files. This allows the same Jamfiles to work
+ # across the board. The null RC uses the assembler to create the empty
+ # objects, so configure that.
+ rc = [ common.get-invocation-command gcc : as : : $(bin) : search-path ] ;
+ rc-type = null ;
+ }
+ rc.configure $(rc) : $(condition) : <rc-type>$(rc-type) ;
+}
+
+if [ os.name ] = NT
+{
+ # This causes single-line command invocation to not go through .bat files,
+ # thus avoiding command-line length limitations.
+ JAMSHELL = % ;
+}
+
+generators.register-c-compiler gcc.compile.c++.preprocess : CPP : PREPROCESSED_CPP : <toolset>gcc ;
+generators.register-c-compiler gcc.compile.c.preprocess : C : PREPROCESSED_C : <toolset>gcc ;
+generators.register-c-compiler gcc.compile.c++ : CPP : OBJ : <toolset>gcc ;
+generators.register-c-compiler gcc.compile.c : C : OBJ : <toolset>gcc ;
+generators.register-c-compiler gcc.compile.asm : ASM : OBJ : <toolset>gcc ;
+generators.register-fortran-compiler gcc.compile.fortran : FORTRAN FORTRAN90 : OBJ : <toolset>gcc ;
+
+# pch support
+
+# The compiler looks for a precompiled header in each directory just before it
+# looks for the include file in that directory. The name searched for is the
+# name specified in the #include directive with ".gch" suffix appended. The
+# logic in gcc-pch-generator will make sure that BASE_PCH suffix is appended to
+# full name of the header.
+
+type.set-generated-target-suffix PCH : <toolset>gcc : gch ;
+
+# GCC-specific pch generator.
+class gcc-pch-generator : pch-generator
+{
+ import project ;
+ import property-set ;
+ import type ;
+
+ rule run-pch ( project name ? : property-set : sources + )
+ {
+ # Find the header in sources. Ignore any CPP sources.
+ local header ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] H ]
+ {
+ header = $(s) ;
+ }
+ }
+
+ # Error handling: Base header file name should be the same as the base
+ # precompiled header name.
+ local header-name = [ $(header).name ] ;
+ local header-basename = $(header-name:B) ;
+ if $(header-basename) != $(name)
+ {
+ local location = [ $(project).project-module ] ;
+ errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ;
+ }
+
+ local pch-file = [ generator.run $(project) $(name) : $(property-set)
+ : $(header) ] ;
+
+ # return result of base class and pch-file property as usage-requirements
+ return
+ [ property-set.create <pch-file>$(pch-file) <cflags>-Winvalid-pch ]
+ $(pch-file)
+ ;
+ }
+
+ # Calls the base version specifying source's name as the name of the created
+ # target. As result, the PCH will be named whatever.hpp.gch, and not
+ # whatever.gch.
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ name = [ $(sources[1]).name ] ;
+ return [ generator.generated-targets $(sources)
+ : $(property-set) : $(project) $(name) ] ;
+ }
+}
+
+# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The
+# latter have HPP type, but HPP type is derived from H. The type of compilation
+# is determined entirely by the destination type.
+generators.register [ new gcc-pch-generator gcc.compile.c.pch : H : C_PCH : <pch>on <toolset>gcc ] ;
+generators.register [ new gcc-pch-generator gcc.compile.c++.pch : H : CPP_PCH : <pch>on <toolset>gcc ] ;
+
+# Override default do-nothing generators.
+generators.override gcc.compile.c.pch : pch.default-c-pch-generator ;
+generators.override gcc.compile.c++.pch : pch.default-cpp-pch-generator ;
+
+toolset.flags gcc.compile PCH_FILE <pch>on : <pch-file> ;
+
+# Declare flags and action for compilation.
+toolset.flags gcc.compile OPTIONS <optimization>off : -O0 ;
+toolset.flags gcc.compile OPTIONS <optimization>speed : -O3 ;
+toolset.flags gcc.compile OPTIONS <optimization>space : -Os ;
+
+toolset.flags gcc.compile OPTIONS <inlining>off : -fno-inline ;
+toolset.flags gcc.compile OPTIONS <inlining>on : -Wno-inline ;
+toolset.flags gcc.compile OPTIONS <inlining>full : -finline-functions -Wno-inline ;
+
+toolset.flags gcc.compile OPTIONS <warnings>off : -w ;
+toolset.flags gcc.compile OPTIONS <warnings>on : -Wall ;
+toolset.flags gcc.compile OPTIONS <warnings>all : -Wall -pedantic ;
+toolset.flags gcc.compile OPTIONS <warnings-as-errors>on : -Werror ;
+
+toolset.flags gcc.compile OPTIONS <debug-symbols>on : -g ;
+toolset.flags gcc.compile OPTIONS <profiling>on : -pg ;
+toolset.flags gcc.compile OPTIONS <rtti>off : -fno-rtti ;
+
+rule setup-fpic ( targets * : sources * : properties * )
+{
+ local link = [ feature.get-values link : $(properties) ] ;
+ if $(link) = shared
+ {
+ local target = [ feature.get-values target-os : $(properties) ] ;
+
+ # This logic will add -fPIC for all compilations:
+ #
+ # lib a : a.cpp b ;
+ # obj b : b.cpp ;
+ # exe c : c.cpp a d ;
+ # obj d : d.cpp ;
+ #
+ # This all is fine, except that 'd' will be compiled with -fPIC even though
+ # it is not needed, as 'd' is used only in exe. However, it is hard to
+ # detect where a target is going to be used. Alternatively, we can set -fPIC
+ # only when main target type is LIB but than 'b' would be compiled without
+ # -fPIC which would lead to link errors on x86-64. So, compile everything
+ # with -fPIC.
+ #
+ # Yet another alternative would be to create a propagated <sharedable>
+ # feature and set it when building shared libraries, but that would be hard
+ # to implement and would increase the target path length even more.
+
+ # On Windows, fPIC is default, specifying -fPIC explicitly leads to
+ # a warning.
+ if $(target) != cygwin && $(target) != windows
+ {
+ OPTIONS on $(targets) += -fPIC ;
+ }
+ }
+}
+
+rule setup-address-model ( targets * : sources * : properties * )
+{
+ local model = [ feature.get-values address-model : $(properties) ] ;
+ if $(model)
+ {
+ local option ;
+ local os = [ feature.get-values target-os : $(properties) ] ;
+ if $(os) = aix
+ {
+ if $(model) = 32
+ {
+ option = -maix32 ;
+ }
+ else
+ {
+ option = -maix64 ;
+ }
+ }
+ else if $(os) = hpux
+ {
+ if $(model) = 32
+ {
+ option = -milp32 ;
+ }
+ else
+ {
+ option = -mlp64 ;
+ }
+ }
+ else
+ {
+ if $(model) = 32
+ {
+ option = -m32 ;
+ }
+ else if $(model) = 64
+ {
+ option = -m64 ;
+ }
+ # For darwin, the model can be 32_64. darwin.jam will handle that
+ # on its own.
+ }
+ OPTIONS on $(targets) += $(option) ;
+ }
+}
+
+
+# FIXME: this should not use os.name.
+if [ os.name ] != NT && [ os.name ] != OSF && [ os.name ] != HPUX && [ os.name ] != AIX
+{
+ # OSF does have an option called -soname but it does not seem to work as
+ # expected, therefore it has been disabled.
+ HAVE_SONAME = "" ;
+ SONAME_OPTION = -h ;
+}
+
+# HPUX, for some reason, seem to use '+h', not '-h'.
+if [ os.name ] = HPUX
+{
+ HAVE_SONAME = "" ;
+ SONAME_OPTION = +h ;
+}
+
+toolset.flags gcc.compile USER_OPTIONS <cflags> ;
+toolset.flags gcc.compile.c++ USER_OPTIONS <cxxflags> ;
+toolset.flags gcc.compile DEFINES <define> ;
+toolset.flags gcc.compile INCLUDES <include> ;
+toolset.flags gcc.compile.c++ TEMPLATE_DEPTH <c++-template-depth> ;
+toolset.flags gcc.compile.fortran USER_OPTIONS <fflags> ;
+
+rule compile.c++.pch ( targets * : sources * : properties * )
+{
+ setup-threading $(targets) : $(sources) : $(properties) ;
+ setup-fpic $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+}
+
+actions compile.c++.pch
+{
+ "$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+rule compile.c.pch ( targets * : sources * : properties * )
+{
+ setup-threading $(targets) : $(sources) : $(properties) ;
+ setup-fpic $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+}
+
+actions compile.c.pch
+{
+ "$(CONFIG_COMMAND)" -x c-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+rule compile.c++.preprocess ( targets * : sources * : properties * )
+{
+ setup-threading $(targets) : $(sources) : $(properties) ;
+ setup-fpic $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+
+ # Some extensions are compiled as C++ by default. For others, we need to
+ # pass -x c++. We could always pass -x c++ but distcc does not work with it.
+ if ! $(>:S) in .cc .cp .cxx .cpp .c++ .C
+ {
+ LANG on $(<) = "-x c++" ;
+ }
+ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ;
+}
+
+rule compile.c.preprocess ( targets * : sources * : properties * )
+{
+ setup-threading $(targets) : $(sources) : $(properties) ;
+ setup-fpic $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+
+ # If we use the name g++ then default file suffix -> language mapping does
+ # not work. So have to pass -x option. Maybe, we can work around this by
+ # allowing the user to specify both C and C++ compiler names.
+ #if $(>:S) != .c
+ #{
+ LANG on $(<) = "-x c" ;
+ #}
+ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ;
+}
+
+rule compile.c++ ( targets * : sources * : properties * )
+{
+ setup-threading $(targets) : $(sources) : $(properties) ;
+ setup-fpic $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+
+ # Some extensions are compiled as C++ by default. For others, we need to
+ # pass -x c++. We could always pass -x c++ but distcc does not work with it.
+ if ! $(>:S) in .cc .cp .cxx .cpp .c++ .C
+ {
+ LANG on $(<) = "-x c++" ;
+ }
+ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ;
+
+ # Here we want to raise the template-depth parameter value to something
+ # higher than the default value of 17. Note that we could do this using the
+ # feature.set-default rule but we do not want to set the default value for
+ # all toolsets as well.
+ #
+ # TODO: This 'modified default' has been inherited from some 'older Boost
+ # Build implementation' and has most likely been added to make some Boost
+ # library parts compile correctly. We should see what exactly prompted this
+ # and whether we can get around the problem more locally.
+ local template-depth = [ on $(<) return $(TEMPLATE_DEPTH) ] ;
+ if ! $(template-depth)
+ {
+ TEMPLATE_DEPTH on $(<) = 128 ;
+ }
+}
+
+rule compile.c ( targets * : sources * : properties * )
+{
+ setup-threading $(targets) : $(sources) : $(properties) ;
+ setup-fpic $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+
+ # If we use the name g++ then default file suffix -> language mapping does
+ # not work. So have to pass -x option. Maybe, we can work around this by
+ # allowing the user to specify both C and C++ compiler names.
+ #if $(>:S) != .c
+ #{
+ LANG on $(<) = "-x c" ;
+ #}
+ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ;
+}
+
+rule compile.fortran ( targets * : sources * : properties * )
+{
+ setup-threading $(targets) : $(sources) : $(properties) ;
+ setup-fpic $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+}
+
+actions compile.c++ bind PCH_FILE
+{
+ "$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<:W)" "$(>:W)"
+}
+
+actions compile.c bind PCH_FILE
+{
+ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c++.preprocess bind PCH_FILE
+{
+ "$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" "$(>:W)" -E >"$(<:W)"
+}
+
+actions compile.c.preprocess bind PCH_FILE
+{
+ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" "$(>)" -E >$(<)
+}
+
+actions compile.fortran
+{
+ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+rule compile.asm ( targets * : sources * : properties * )
+{
+ setup-fpic $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+ LANG on $(<) = "-x assembler-with-cpp" ;
+}
+
+actions compile.asm
+{
+ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+# The class which check that we don't try to use the <runtime-link>static
+# property while creating or using shared library, since it's not supported by
+# gcc/libc.
+class gcc-linking-generator : unix-linking-generator
+{
+ rule run ( project name ? : property-set : sources + )
+ {
+ # TODO: Replace this with the use of a target-os property.
+ local no-static-link = ;
+ if [ modules.peek : UNIX ]
+ {
+ switch [ modules.peek : JAMUNAME ]
+ {
+ case * : no-static-link = true ;
+ }
+ }
+
+ local properties = [ $(property-set).raw ] ;
+ local reason ;
+ if $(no-static-link) && <runtime-link>static in $(properties)
+ {
+ if <link>shared in $(properties)
+ {
+ reason =
+ "On gcc, DLL can't be build with '<runtime-link>static'." ;
+ }
+ else if [ type.is-derived $(self.target-types[1]) EXE ]
+ {
+ for local s in $(sources)
+ {
+ local type = [ $(s).type ] ;
+ if $(type) && [ type.is-derived $(type) SHARED_LIB ]
+ {
+ reason =
+ "On gcc, using DLLS together with the"
+ "<runtime-link>static options is not possible " ;
+ }
+ }
+ }
+ }
+ if $(reason)
+ {
+ ECHO warning:
+ $(reason) ;
+ ECHO warning:
+ "It is suggested to use '<runtime-link>static' together"
+ "with '<link>static'." ;
+ return ;
+ }
+ else
+ {
+ local generated-targets = [ unix-linking-generator.run $(project)
+ $(name) : $(property-set) : $(sources) ] ;
+ return $(generated-targets) ;
+ }
+ }
+}
+
+# The set of permissible input types is different on mingw.
+# So, define two sets of generators, with mingw generators
+# selected when target-os=windows.
+
+local g ;
+g = [ new gcc-linking-generator gcc.mingw.link
+ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB
+ : EXE
+ : <toolset>gcc <target-os>windows ] ;
+$(g).set-rule-name gcc.link ;
+generators.register $(g) ;
+
+g = [ new gcc-linking-generator gcc.mingw.link.dll
+ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB
+ : IMPORT_LIB SHARED_LIB
+ : <toolset>gcc <target-os>windows ] ;
+$(g).set-rule-name gcc.link.dll ;
+generators.register $(g) ;
+
+generators.register
+ [ new gcc-linking-generator gcc.link
+ : LIB OBJ
+ : EXE
+ : <toolset>gcc ] ;
+generators.register
+ [ new gcc-linking-generator gcc.link.dll
+ : LIB OBJ
+ : SHARED_LIB
+ : <toolset>gcc ] ;
+
+generators.override gcc.mingw.link : gcc.link ;
+generators.override gcc.mingw.link.dll : gcc.link.dll ;
+
+# Cygwin is similar to msvc and mingw in that it uses import libraries.
+# While in simple cases, it can directly link to a shared library,
+# it is believed to be slower, and not always possible. Define cygwin-specific
+# generators here.
+
+g = [ new gcc-linking-generator gcc.cygwin.link
+ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB
+ : EXE
+ : <toolset>gcc <target-os>cygwin ] ;
+$(g).set-rule-name gcc.link ;
+generators.register $(g) ;
+
+g = [ new gcc-linking-generator gcc.cygwin.link.dll
+ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB
+ : IMPORT_LIB SHARED_LIB
+ : <toolset>gcc <target-os>cygwin ] ;
+$(g).set-rule-name gcc.link.dll ;
+generators.register $(g) ;
+
+generators.override gcc.cygwin.link : gcc.link ;
+generators.override gcc.cygwin.link.dll : gcc.link.dll ;
+
+# Declare flags for linking.
+# First, the common flags.
+toolset.flags gcc.link OPTIONS <debug-symbols>on : -g ;
+toolset.flags gcc.link OPTIONS <profiling>on : -pg ;
+toolset.flags gcc.link USER_OPTIONS <linkflags> ;
+toolset.flags gcc.link LINKPATH <library-path> ;
+toolset.flags gcc.link FINDLIBS-ST <find-static-library> ;
+toolset.flags gcc.link FINDLIBS-SA <find-shared-library> ;
+toolset.flags gcc.link LIBRARIES <library-file> ;
+
+toolset.flags gcc.link.dll .IMPLIB-COMMAND <target-os>windows : "-Wl,--out-implib," ;
+toolset.flags gcc.link.dll .IMPLIB-COMMAND <target-os>cygwin : "-Wl,--out-implib," ;
+
+# For <runtime-link>static we made sure there are no dynamic libraries in the
+# link. On HP-UX not all system libraries exist as archived libraries (for
+# example, there is no libunwind.a), so, on this platform, the -static option
+# cannot be specified.
+if [ os.name ] != HPUX
+{
+ toolset.flags gcc.link OPTIONS <runtime-link>static : -static ;
+}
+
+# Now, the vendor specific flags.
+# The parameter linker can be either aix, darwin, gnu, hpux, osf or sun.
+rule init-link-flags ( toolset linker condition )
+{
+ switch $(linker)
+ {
+ case aix :
+ {
+ #
+ # On AIX we *have* to use the native linker.
+ #
+ # Using -brtl, the AIX linker will look for libraries with both the .a
+ # and .so extensions, such as libfoo.a and libfoo.so. Without -brtl, the
+ # AIX linker looks only for libfoo.a. Note that libfoo.a is an archived
+ # file that may contain shared objects and is different from static libs
+ # as on Linux.
+ #
+ # The -bnoipath strips the prepending (relative) path of libraries from
+ # the loader section in the target library or executable. Hence, during
+ # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded
+ # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without
+ # this option, the prepending (relative) path + library name is
+ # hard-coded in the loader section, causing *only* this path to be
+ # searched during load-time. Note that the AIX linker does not have an
+ # -soname equivalent, this is as close as it gets.
+ #
+ # The above options are definately for AIX 5.x, and most likely also for
+ # AIX 4.x and AIX 6.x. For details about the AIX linker see:
+ # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf
+ #
+
+ toolset.flags $(toolset).link OPTIONS : -Wl,-brtl -Wl,-bnoipath
+ : unchecked ;
+ }
+
+ case darwin :
+ {
+ # On Darwin, the -s option to ld does not work unless we pass -static,
+ # and passing -static unconditionally is a bad idea. So, don't pass -s.
+ # at all, darwin.jam will use separate 'strip' invocation.
+ toolset.flags $(toolset).link RPATH $(condition) : <dll-path> : unchecked ;
+ toolset.flags $(toolset).link RPATH_LINK $(condition) : <xdll-path> : unchecked ;
+ }
+
+ case gnu :
+ {
+ # Strip the binary when no debugging is needed. We use --strip-all flag
+ # as opposed to -s since icc (intel's compiler) is generally
+ # option-compatible with and inherits from the gcc toolset, but does not
+ # support -s.
+ toolset.flags $(toolset).link OPTIONS $(condition)/<strip>on : -Wl,--strip-all : unchecked ;
+ toolset.flags $(toolset).link RPATH $(condition) : <dll-path> : unchecked ;
+ toolset.flags $(toolset).link RPATH_LINK $(condition) : <xdll-path> : unchecked ;
+ toolset.flags $(toolset).link START-GROUP $(condition) : -Wl,--start-group : unchecked ;
+ toolset.flags $(toolset).link END-GROUP $(condition) : -Wl,--end-group : unchecked ;
+
+ # gnu ld has the ability to change the search behaviour for libraries
+ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic
+ # and change search for -l switches that follow them. The following list
+ # shows the tried variants.
+ # The search stops at the first variant that has a match.
+ # *nix: -Bstatic -lxxx
+ # libxxx.a
+ #
+ # *nix: -Bdynamic -lxxx
+ # libxxx.so
+ # libxxx.a
+ #
+ # windows (mingw,cygwin) -Bstatic -lxxx
+ # libxxx.a
+ # xxx.lib
+ #
+ # windows (mingw,cygwin) -Bdynamic -lxxx
+ # libxxx.dll.a
+ # xxx.dll.a
+ # libxxx.a
+ # xxx.lib
+ # cygxxx.dll (*)
+ # libxxx.dll
+ # xxx.dll
+ # libxxx.a
+ #
+ # (*) This is for cygwin
+ # Please note that -Bstatic and -Bdynamic are not a guarantee that a
+ # static or dynamic lib indeed gets linked in. The switches only change
+ # search patterns!
+
+ # On *nix mixing shared libs with static runtime is not a good idea.
+ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/<runtime-link>shared
+ : -Wl,-Bstatic : unchecked ;
+ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/<runtime-link>shared
+ : -Wl,-Bdynamic : unchecked ;
+
+ # On windows allow mixing of static and dynamic libs with static
+ # runtime.
+ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/<runtime-link>static/<target-os>windows
+ : -Wl,-Bstatic : unchecked ;
+ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/<runtime-link>static/<target-os>windows
+ : -Wl,-Bdynamic : unchecked ;
+ toolset.flags $(toolset).link OPTIONS $(condition)/<runtime-link>static/<target-os>windows
+ : -Wl,-Bstatic : unchecked ;
+ }
+
+ case hpux :
+ {
+ toolset.flags $(toolset).link OPTIONS $(condition)/<strip>on
+ : -Wl,-s : unchecked ;
+ toolset.flags $(toolset).link OPTIONS $(condition)/<link>shared
+ : -fPIC : unchecked ;
+ }
+
+ case osf :
+ {
+ # No --strip-all, just -s.
+ toolset.flags $(toolset).link OPTIONS $(condition)/<strip>on
+ : -Wl,-s : unchecked ;
+ toolset.flags $(toolset).link RPATH $(condition) : <dll-path>
+ : unchecked ;
+ # This does not supports -R.
+ toolset.flags $(toolset).link RPATH_OPTION $(condition) : -rpath
+ : unchecked ;
+ # -rpath-link is not supported at all.
+ }
+
+ case sun :
+ {
+ toolset.flags $(toolset).link OPTIONS $(condition)/<strip>on
+ : -Wl,-s : unchecked ;
+ toolset.flags $(toolset).link RPATH $(condition) : <dll-path>
+ : unchecked ;
+ # Solaris linker does not have a separate -rpath-link, but allows to use
+ # -L for the same purpose.
+ toolset.flags $(toolset).link LINKPATH $(condition) : <xdll-path>
+ : unchecked ;
+
+ # This permits shared libraries with non-PIC code on Solaris.
+ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the
+ # following is not needed. Whether -fPIC should be hardcoded, is a
+ # separate question.
+ # AH, 2004/10/16: it is still necessary because some tests link against
+ # static libraries that were compiled without PIC.
+ toolset.flags $(toolset).link OPTIONS $(condition)/<link>shared
+ : -mimpure-text : unchecked ;
+ }
+
+ case * :
+ {
+ errors.user-error
+ "$(toolset) initialization: invalid linker '$(linker)'" :
+ "The value '$(linker)' specified for <linker> is not recognized." :
+ "Possible values are 'aix', 'darwin', 'gnu', 'hpux', 'osf' or 'sun'" ;
+ }
+ }
+}
+
+# Enclose the RPATH variable on 'targets' in (double) quotes,
+# unless it's already enclosed in single quotes.
+# This special casing is done because it's common to pass
+# '$ORIGIN' to linker -- and it has to have single quotes
+# to prevent expansion by shell -- and if we add double
+# quotes then preventing properties of single quotes disappear.
+rule quote-rpath ( targets * )
+{
+ local r = [ on $(targets[1]) return $(RPATH) ] ;
+ if ! [ MATCH "('.*')" : $(r) ]
+ {
+ r = "\"$(r)\"" ;
+ }
+ RPATH on $(targets) = $(r) ;
+}
+
+# Declare actions for linking.
+rule link ( targets * : sources * : properties * )
+{
+ setup-threading $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+ SPACE on $(targets) = " " ;
+ # Serialize execution of the 'link' action, since running N links in
+ # parallel is just slower. For now, serialize only gcc links, it might be a
+ # good idea to serialize all links.
+ JAM_SEMAPHORE on $(targets) = <s>gcc-link-semaphore ;
+ quote-rpath $(targets) ;
+}
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS)
+
+}
+
+# Default value. Mostly for the sake of intel-linux that inherits from gcc, but
+# does not have the same logic to set the .AR variable. We can put the same
+# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is
+# always available.
+.AR = ar ;
+.RANLIB = ranlib ;
+
+toolset.flags gcc.archive AROPTIONS <archiveflags> ;
+
+rule archive ( targets * : sources * : properties * )
+{
+ # Always remove archive and start again. Here is the rationale from
+ #
+ # Andre Hentz:
+ #
+ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to
+ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd
+ # errors. After some debugging I traced it back to the fact that a1.o was
+ # *still* in liba.a
+ #
+ # Rene Rivera:
+ #
+ # Originally removing the archive was done by splicing an RM onto the
+ # archive action. That makes archives fail to build on NT when they have
+ # many files because it will no longer execute the action directly and blow
+ # the line length limit. Instead we remove the file in a different action,
+ # just before building the archive.
+ #
+ local clean.a = $(targets[1])(clean) ;
+ TEMPORARY $(clean.a) ;
+ NOCARE $(clean.a) ;
+ LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ;
+ DEPENDS $(clean.a) : $(sources) ;
+ DEPENDS $(targets) : $(clean.a) ;
+ common.RmTemps $(clean.a) : $(targets) ;
+}
+
+# Declare action for creating static libraries.
+# The letter 'r' means to add files to the archive with replacement. Since we
+# remove archive, we don't care about replacement, but there's no option "add
+# without replacement".
+# The letter 'c' suppresses the warning in case the archive does not exists yet.
+# That warning is produced only on some platforms, for whatever reasons.
+actions piecemeal archive
+{
+ "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"
+ "$(.RANLIB)" "$(<)"
+}
+
+rule link.dll ( targets * : sources * : properties * )
+{
+ setup-threading $(targets) : $(sources) : $(properties) ;
+ setup-address-model $(targets) : $(sources) : $(properties) ;
+ SPACE on $(targets) = " " ;
+ JAM_SEMAPHORE on $(targets) = <s>gcc-link-semaphore ;
+ quote-rpath $(targets) ;
+}
+
+# Differs from 'link' above only by -shared.
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) "$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) -shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS)
+}
+
+rule setup-threading ( targets * : sources * : properties * )
+{
+ local threading = [ feature.get-values threading : $(properties) ] ;
+ if $(threading) = multi
+ {
+ local target = [ feature.get-values target-os : $(properties) ] ;
+ local option ;
+ local libs ;
+
+ switch $(target)
+ {
+ case windows :
+ {
+ option = -mthreads ;
+ }
+ case cygwin :
+ {
+ option = -mthreads ;
+ }
+ case solaris :
+ {
+ option = -pthreads ;
+ libs = rt ;
+ }
+ case beos :
+ {
+ # BeOS has no threading options, so do not set anything here.
+ }
+ case *bsd :
+ {
+ option = -pthread ;
+ # There is no -lrt on BSD.
+ }
+ case sgi :
+ {
+ # gcc on IRIX does not support multi-threading so do not set anything
+ # here.
+ }
+ case darwin :
+ {
+ # Darwin has no threading options so do not set anything here.
+ }
+ case * :
+ {
+ option = -pthread ;
+ libs = rt ;
+ }
+ }
+
+ if $(option)
+ {
+ OPTIONS on $(targets) += $(option) ;
+ }
+ if $(libs)
+ {
+ FINDLIBS-SA on $(targets) += $(libs) ;
+ }
+ }
+}
+
+local rule cpu-flags ( toolset variable : architecture : instruction-set + : values + : default ? )
+{
+ if $(default)
+ {
+ toolset.flags $(toolset) $(variable)
+ <architecture>$(architecture)/<instruction-set>
+ : $(values) ;
+ }
+ toolset.flags $(toolset) $(variable)
+ <architecture>/<instruction-set>$(instruction-set)
+ <architecture>$(architecture)/<instruction-set>$(instruction-set)
+ : $(values) ;
+}
+
+# Set architecture/instruction-set options.
+#
+# x86 and compatible
+# The 'native' option appeared in gcc 4.2 so we cannot safely use it
+# as default. Use conservative i386 instead.
+cpu-flags gcc OPTIONS : x86 : native : -march=native ;
+cpu-flags gcc OPTIONS : x86 : i386 : -march=i386 : default ;
+cpu-flags gcc OPTIONS : x86 : i486 : -march=i486 ;
+cpu-flags gcc OPTIONS : x86 : i586 : -march=i586 ;
+cpu-flags gcc OPTIONS : x86 : i686 : -march=i686 ;
+cpu-flags gcc OPTIONS : x86 : pentium : -march=pentium ;
+cpu-flags gcc OPTIONS : x86 : pentium-mmx : -march=pentium-mmx ;
+cpu-flags gcc OPTIONS : x86 : pentiumpro : -march=pentiumpro ;
+cpu-flags gcc OPTIONS : x86 : pentium2 : -march=pentium2 ;
+cpu-flags gcc OPTIONS : x86 : pentium3 : -march=pentium3 ;
+cpu-flags gcc OPTIONS : x86 : pentium3m : -march=pentium3m ;
+cpu-flags gcc OPTIONS : x86 : pentium-m : -march=pentium-m ;
+cpu-flags gcc OPTIONS : x86 : pentium4 : -march=pentium4 ;
+cpu-flags gcc OPTIONS : x86 : pentium4m : -march=pentium4m ;
+cpu-flags gcc OPTIONS : x86 : prescott : -march=prescott ;
+cpu-flags gcc OPTIONS : x86 : nocona : -march=nocona ;
+cpu-flags gcc OPTIONS : x86 : core2 : -march=core2 ;
+cpu-flags gcc OPTIONS : x86 : k6 : -march=k6 ;
+cpu-flags gcc OPTIONS : x86 : k6-2 : -march=k6-2 ;
+cpu-flags gcc OPTIONS : x86 : k6-3 : -march=k6-3 ;
+cpu-flags gcc OPTIONS : x86 : athlon : -march=athlon ;
+cpu-flags gcc OPTIONS : x86 : athlon-tbird : -march=athlon-tbird ;
+cpu-flags gcc OPTIONS : x86 : athlon-4 : -march=athlon-4 ;
+cpu-flags gcc OPTIONS : x86 : athlon-xp : -march=athlon-xp ;
+cpu-flags gcc OPTIONS : x86 : athlon-mp : -march=athlon-mp ;
+##
+cpu-flags gcc OPTIONS : x86 : k8 : -march=k8 ;
+cpu-flags gcc OPTIONS : x86 : opteron : -march=opteron ;
+cpu-flags gcc OPTIONS : x86 : athlon64 : -march=athlon64 ;
+cpu-flags gcc OPTIONS : x86 : athlon-fx : -march=athlon-fx ;
+cpu-flags gcc OPTIONS : x86 : winchip-c6 : -march=winchip-c6 ;
+cpu-flags gcc OPTIONS : x86 : winchip2 : -march=winchip2 ;
+cpu-flags gcc OPTIONS : x86 : c3 : -march=c3 ;
+cpu-flags gcc OPTIONS : x86 : c3-2 : -march=c3-2 ;
+# Sparc
+cpu-flags gcc OPTIONS : sparc : c3 : -mcpu=c3 : default ;
+cpu-flags gcc OPTIONS : sparc : v7 : -mcpu=v7 ;
+cpu-flags gcc OPTIONS : sparc : cypress : -mcpu=cypress ;
+cpu-flags gcc OPTIONS : sparc : v8 : -mcpu=v8 ;
+cpu-flags gcc OPTIONS : sparc : supersparc : -mcpu=supersparc ;
+cpu-flags gcc OPTIONS : sparc : sparclite : -mcpu=sparclite ;
+cpu-flags gcc OPTIONS : sparc : hypersparc : -mcpu=hypersparc ;
+cpu-flags gcc OPTIONS : sparc : sparclite86x : -mcpu=sparclite86x ;
+cpu-flags gcc OPTIONS : sparc : f930 : -mcpu=f930 ;
+cpu-flags gcc OPTIONS : sparc : f934 : -mcpu=f934 ;
+cpu-flags gcc OPTIONS : sparc : sparclet : -mcpu=sparclet ;
+cpu-flags gcc OPTIONS : sparc : tsc701 : -mcpu=tsc701 ;
+cpu-flags gcc OPTIONS : sparc : v9 : -mcpu=v9 ;
+cpu-flags gcc OPTIONS : sparc : ultrasparc : -mcpu=ultrasparc ;
+cpu-flags gcc OPTIONS : sparc : ultrasparc3 : -mcpu=ultrasparc3 ;
+# RS/6000 & PowerPC
+cpu-flags gcc OPTIONS : power : 403 : -mcpu=403 ;
+cpu-flags gcc OPTIONS : power : 505 : -mcpu=505 ;
+cpu-flags gcc OPTIONS : power : 601 : -mcpu=601 ;
+cpu-flags gcc OPTIONS : power : 602 : -mcpu=602 ;
+cpu-flags gcc OPTIONS : power : 603 : -mcpu=603 ;
+cpu-flags gcc OPTIONS : power : 603e : -mcpu=603e ;
+cpu-flags gcc OPTIONS : power : 604 : -mcpu=604 ;
+cpu-flags gcc OPTIONS : power : 604e : -mcpu=604e ;
+cpu-flags gcc OPTIONS : power : 620 : -mcpu=620 ;
+cpu-flags gcc OPTIONS : power : 630 : -mcpu=630 ;
+cpu-flags gcc OPTIONS : power : 740 : -mcpu=740 ;
+cpu-flags gcc OPTIONS : power : 7400 : -mcpu=7400 ;
+cpu-flags gcc OPTIONS : power : 7450 : -mcpu=7450 ;
+cpu-flags gcc OPTIONS : power : 750 : -mcpu=750 ;
+cpu-flags gcc OPTIONS : power : 801 : -mcpu=801 ;
+cpu-flags gcc OPTIONS : power : 821 : -mcpu=821 ;
+cpu-flags gcc OPTIONS : power : 823 : -mcpu=823 ;
+cpu-flags gcc OPTIONS : power : 860 : -mcpu=860 ;
+cpu-flags gcc OPTIONS : power : 970 : -mcpu=970 ;
+cpu-flags gcc OPTIONS : power : 8540 : -mcpu=8540 ;
+cpu-flags gcc OPTIONS : power : power : -mcpu=power ;
+cpu-flags gcc OPTIONS : power : power2 : -mcpu=power2 ;
+cpu-flags gcc OPTIONS : power : power3 : -mcpu=power3 ;
+cpu-flags gcc OPTIONS : power : power4 : -mcpu=power4 ;
+cpu-flags gcc OPTIONS : power : power5 : -mcpu=power5 ;
+cpu-flags gcc OPTIONS : power : powerpc : -mcpu=powerpc ;
+cpu-flags gcc OPTIONS : power : powerpc64 : -mcpu=powerpc64 ;
+cpu-flags gcc OPTIONS : power : rios : -mcpu=rios ;
+cpu-flags gcc OPTIONS : power : rios1 : -mcpu=rios1 ;
+cpu-flags gcc OPTIONS : power : rios2 : -mcpu=rios2 ;
+cpu-flags gcc OPTIONS : power : rsc : -mcpu=rsc ;
+cpu-flags gcc OPTIONS : power : rs64a : -mcpu=rs64 ;
+# AIX variant of RS/6000 & PowerPC
+toolset.flags gcc AROPTIONS <address-model>64/<target-os>aix : "-X 64" ;
diff --git a/tools/build/v2/tools/gcc.py b/tools/build/v2/tools/gcc.py
new file mode 100644
index 0000000000..2a3e675ef1
--- /dev/null
+++ b/tools/build/v2/tools/gcc.py
@@ -0,0 +1,796 @@
+# Status: being ported by Steven Watanabe
+# Base revision: 47077
+# TODO: common.jam needs to be ported
+# TODO: generators.jam needs to have register_c_compiler.
+#
+# Copyright 2001 David Abrahams.
+# Copyright 2002-2006 Rene Rivera.
+# Copyright 2002-2003 Vladimir Prus.
+# Copyright (c) 2005 Reece H. Dunn.
+# Copyright 2006 Ilya Sokolov.
+# Copyright 2007 Roland Schwarz
+# Copyright 2007 Boris Gubenko.
+# Copyright 2008 Steven Watanabe
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import os
+import subprocess
+import re
+
+import bjam
+
+from b2.tools import unix, common, rc, pch, builtin
+from b2.build import feature, type, toolset, generators
+from b2.util.utility import os_name, on_windows
+from b2.manager import get_manager
+from b2.build.generators import Generator
+from b2.build.toolset import flags
+from b2.util.utility import to_seq
+
+__debug = None
+
+def debug():
+ global __debug
+ if __debug is None:
+ __debug = "--debug-configuration" in bjam.variable("ARGV")
+ return __debug
+
+feature.extend('toolset', ['gcc'])
+
+
+toolset.inherit_generators('gcc', [], 'unix', ['unix.link', 'unix.link.dll'])
+toolset.inherit_flags('gcc', 'unix')
+toolset.inherit_rules('gcc', 'unix')
+
+generators.override('gcc.prebuilt', 'builtin.prebuilt')
+generators.override('gcc.searched-lib-generator', 'searched-lib-generator')
+
+# Target naming is determined by types/lib.jam and the settings below this
+# comment.
+#
+# On *nix:
+# libxxx.a static library
+# libxxx.so shared library
+#
+# On windows (mingw):
+# libxxx.lib static library
+# xxx.dll DLL
+# xxx.lib import library
+#
+# On windows (cygwin) i.e. <target-os>cygwin
+# libxxx.a static library
+# xxx.dll DLL
+# libxxx.dll.a import library
+#
+# Note: user can always override by using the <tag>@rule
+# This settings have been choosen, so that mingw
+# is in line with msvc naming conventions. For
+# cygwin the cygwin naming convention has been choosen.
+
+# Make the "o" suffix used for gcc toolset on all
+# platforms
+type.set_generated_target_suffix('OBJ', ['<toolset>gcc'], 'o')
+type.set_generated_target_suffix('STATIC_LIB', ['<toolset>gcc', '<target-os>cygwin'], 'a')
+
+type.set_generated_target_suffix('IMPORT_LIB', ['<toolset>gcc', '<target-os>cygwin'], 'dll.a')
+type.set_generated_target_prefix('IMPORT_LIB', ['<toolset>gcc', '<target-os>cygwin'], 'lib')
+
+__machine_match = re.compile('^([^ ]+)')
+__version_match = re.compile('^([0-9.]+)')
+
+def init(version = None, command = None, options = None):
+ """
+ Initializes the gcc toolset for the given version. If necessary, command may
+ be used to specify where the compiler is located. The parameter 'options' is a
+ space-delimited list of options, each one specified as
+ <option-name>option-value. Valid option names are: cxxflags, linkflags and
+ linker-type. Accepted linker-type values are gnu, darwin, osf, hpux or sun
+ and the default value will be selected based on the current OS.
+ Example:
+ using gcc : 3.4 : : <cxxflags>foo <linkflags>bar <linker-type>sun ;
+ """
+
+ options = to_seq(options)
+ command = to_seq(command)
+
+ # Information about the gcc command...
+ # The command.
+ command = to_seq(common.get_invocation_command('gcc', 'g++', command))
+ # The root directory of the tool install.
+ root = feature.get_values('<root>', options) ;
+ # The bin directory where to find the command to execute.
+ bin = None
+ # The flavor of compiler.
+ flavor = feature.get_values('<flavor>', options)
+ # Autodetect the root and bin dir if not given.
+ if command:
+ if not bin:
+ bin = common.get_absolute_tool_path(command[-1])
+ if not root:
+ root = os.path.dirname(bin)
+ # Autodetect the version and flavor if not given.
+ if command:
+ machine_info = subprocess.Popen(command + ['-dumpmachine'], stdout=subprocess.PIPE).communicate()[0]
+ machine = __machine_match.search(machine_info).group(1)
+
+ version_info = subprocess.Popen(command + ['-dumpversion'], stdout=subprocess.PIPE).communicate()[0]
+ version = __version_match.search(version_info).group(1)
+ if not flavor and machine.find('mingw') != -1:
+ flavor = 'mingw'
+
+ condition = None
+ if flavor:
+ condition = common.check_init_parameters('gcc', None,
+ ('version', version),
+ ('flavor', flavor))
+ else:
+ condition = common.check_init_parameters('gcc', None,
+ ('version', version))
+
+ if command:
+ command = command[0]
+
+ common.handle_options('gcc', condition, command, options)
+
+ linker = feature.get_values('<linker-type>', options)
+ if not linker:
+ if os_name() == 'OSF':
+ linker = 'osf'
+ elif os_name() == 'HPUX':
+ linker = 'hpux' ;
+ else:
+ linker = 'gnu'
+
+ init_link_flags('gcc', linker, condition)
+
+ # If gcc is installed in non-standard location, we'd need to add
+ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run
+ # rules).
+ if command:
+ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries
+ # and all must be added to LD_LIBRARY_PATH. The linker will pick the
+ # right onces. Note that we don't provide a clean way to build 32-bit
+ # binary with 64-bit compiler, but user can always pass -m32 manually.
+ lib_path = [os.path.join(root, 'bin'),
+ os.path.join(root, 'lib'),
+ os.path.join(root, 'lib32'),
+ os.path.join(root, 'lib64')]
+ if debug():
+ print 'notice: using gcc libraries ::', condition, '::', lib_path
+ toolset.flags('gcc.link', 'RUN_PATH', condition, lib_path)
+
+ # If it's not a system gcc install we should adjust the various programs as
+ # needed to prefer using the install specific versions. This is essential
+ # for correct use of MinGW and for cross-compiling.
+
+ # - The archive builder.
+ archiver = common.get_invocation_command('gcc',
+ 'ar', feature.get_values('<archiver>', options), [bin], path_last=True)
+ toolset.flags('gcc.archive', '.AR', condition, [archiver])
+ if debug():
+ print 'notice: using gcc archiver ::', condition, '::', archiver
+
+ # - The resource compiler.
+ rc_command = common.get_invocation_command_nodefault('gcc',
+ 'windres', feature.get_values('<rc>', options), [bin], path_last=True)
+ rc_type = feature.get_values('<rc-type>', options)
+
+ if not rc_type:
+ rc_type = 'windres'
+
+ if not rc_command:
+ # If we can't find an RC compiler we fallback to a null RC compiler that
+ # creates empty object files. This allows the same Jamfiles to work
+ # across the board. The null RC uses the assembler to create the empty
+ # objects, so configure that.
+ rc_command = common.get_invocation_command('gcc', 'as', [], [bin], path_last=True)
+ rc_type = 'null'
+ rc.configure(rc_command, condition, '<rc-type>' + rc_type)
+
+###if [ os.name ] = NT
+###{
+### # This causes single-line command invocation to not go through .bat files,
+### # thus avoiding command-line length limitations.
+### JAMSHELL = % ;
+###}
+
+#FIXME: when register_c_compiler is moved to
+# generators, these should be updated
+builtin.register_c_compiler('gcc.compile.c++', ['CPP'], ['OBJ'], ['<toolset>gcc'])
+builtin.register_c_compiler('gcc.compile.c', ['C'], ['OBJ'], ['<toolset>gcc'])
+builtin.register_c_compiler('gcc.compile.asm', ['ASM'], ['OBJ'], ['<toolset>gcc'])
+
+# pch support
+
+# The compiler looks for a precompiled header in each directory just before it
+# looks for the include file in that directory. The name searched for is the
+# name specified in the #include directive with ".gch" suffix appended. The
+# logic in gcc-pch-generator will make sure that BASE_PCH suffix is appended to
+# full name of the header.
+
+type.set_generated_target_suffix('PCH', ['<toolset>gcc'], 'gch')
+
+# GCC-specific pch generator.
+class GccPchGenerator(pch.PchGenerator):
+
+ # Inherit the __init__ method
+
+ def run_pch(self, project, name, prop_set, sources):
+ # Find the header in sources. Ignore any CPP sources.
+ header = None
+ for s in sources:
+ if type.is_derived(s.type, 'H'):
+ header = s
+
+ # Error handling: Base header file name should be the same as the base
+ # precompiled header name.
+ header_name = header.name
+ header_basename = os.path.basename(header_name).rsplit('.', 1)[0]
+ if header_basename != name:
+ location = project.project_module
+ ###FIXME:
+ raise Exception()
+ ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ;
+
+ pch_file = Generator.run(self, project, name, prop_set, [header])
+
+ # return result of base class and pch-file property as usage-requirements
+ # FIXME: what about multiple results from generator.run?
+ return (property_set.create('<pch-file>' + pch_file[0], '<cflags>-Winvalid-pch'),
+ pch_file)
+
+ # Calls the base version specifying source's name as the name of the created
+ # target. As result, the PCH will be named whatever.hpp.gch, and not
+ # whatever.gch.
+ def generated_targets(self, sources, prop_set, project, name = None):
+ name = sources[0].name
+ return Generator.generated_targets(self, sources,
+ prop_set, project, name)
+
+# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The
+# latter have HPP type, but HPP type is derived from H. The type of compilation
+# is determined entirely by the destination type.
+generators.register(GccPchGenerator('gcc.compile.c.pch', False, ['H'], ['C_PCH'], ['<pch>on', '<toolset>gcc' ]))
+generators.register(GccPchGenerator('gcc.compile.c++.pch', False, ['H'], ['CPP_PCH'], ['<pch>on', '<toolset>gcc' ]))
+
+# Override default do-nothing generators.
+generators.override('gcc.compile.c.pch', 'pch.default-c-pch-generator')
+generators.override('gcc.compile.c++.pch', 'pch.default-cpp-pch-generator')
+
+flags('gcc.compile', 'PCH_FILE', ['<pch>on'], ['<pch-file>'])
+
+# Declare flags and action for compilation
+flags('gcc.compile', 'OPTIONS', ['<optimization>off'], ['-O0'])
+flags('gcc.compile', 'OPTIONS', ['<optimization>speed'], ['-O3'])
+flags('gcc.compile', 'OPTIONS', ['<optimization>space'], ['-Os'])
+
+flags('gcc.compile', 'OPTIONS', ['<inlining>off'], ['-fno-inline'])
+flags('gcc.compile', 'OPTIONS', ['<inlining>on'], ['-Wno-inline'])
+flags('gcc.compile', 'OPTIONS', ['<inlining>full'], ['-finline-functions', '-Wno-inline'])
+
+flags('gcc.compile', 'OPTIONS', ['<warnings>off'], ['-w'])
+flags('gcc.compile', 'OPTIONS', ['<warnings>on'], ['-Wall'])
+flags('gcc.compile', 'OPTIONS', ['<warnings>all'], ['-Wall', '-pedantic'])
+flags('gcc.compile', 'OPTIONS', ['<warnings-as-errors>on'], ['-Werror'])
+
+flags('gcc.compile', 'OPTIONS', ['<debug-symbols>on'], ['-g'])
+flags('gcc.compile', 'OPTIONS', ['<profiling>on'], ['-pg'])
+flags('gcc.compile', 'OPTIONS', ['<rtti>off'], ['-fno-rtti'])
+
+# On cygwin and mingw, gcc generates position independent code by default, and
+# warns if -fPIC is specified. This might not be the right way of checking if
+# we're using cygwin. For example, it's possible to run cygwin gcc from NT
+# shell, or using crosscompiling. But we'll solve that problem when it's time.
+# In that case we'll just add another parameter to 'init' and move this login
+# inside 'init'.
+if not os_name () in ['CYGWIN', 'NT']:
+ # This logic will add -fPIC for all compilations:
+ #
+ # lib a : a.cpp b ;
+ # obj b : b.cpp ;
+ # exe c : c.cpp a d ;
+ # obj d : d.cpp ;
+ #
+ # This all is fine, except that 'd' will be compiled with -fPIC even though
+ # it's not needed, as 'd' is used only in exe. However, it's hard to detect
+ # where a target is going to be used. Alternative, we can set -fPIC only
+ # when main target type is LIB but than 'b' will be compiled without -fPIC.
+ # In x86-64 that will lead to link errors. So, compile everything with
+ # -fPIC.
+ #
+ # Yet another alternative would be to create propagated <sharedable>
+ # feature, and set it when building shared libraries, but that's hard to
+ # implement and will increase target path length even more.
+ flags('gcc.compile', 'OPTIONS', ['<link>shared'], ['-fPIC'])
+
+if os_name() != 'NT' and os_name() != 'OSF' and os_name() != 'HPUX':
+ # OSF does have an option called -soname but it doesn't seem to work as
+ # expected, therefore it has been disabled.
+ HAVE_SONAME = ''
+ SONAME_OPTION = '-h'
+
+
+flags('gcc.compile', 'USER_OPTIONS', [], ['<cflags>'])
+flags('gcc.compile.c++', 'USER_OPTIONS',[], ['<cxxflags>'])
+flags('gcc.compile', 'DEFINES', [], ['<define>'])
+flags('gcc.compile', 'INCLUDES', [], ['<include>'])
+
+engine = get_manager().engine()
+
+engine.register_action('gcc.compile.c++.pch',
+ '"$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"')
+
+engine.register_action('gcc.compile.c.pch',
+ '"$(CONFIG_COMMAND)" -x c-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"')
+
+
+def gcc_compile_cpp(targets, sources, properties):
+ # Some extensions are compiled as C++ by default. For others, we need to
+ # pass -x c++. We could always pass -x c++ but distcc does not work with it.
+ extension = os.path.splitext (sources [0]) [1]
+ lang = ''
+ if not extension in ['.cc', '.cp', '.cxx', '.cpp', '.c++', '.C']:
+ lang = '-x c++'
+ get_manager().engine().set_target_variable (targets, 'LANG', lang)
+ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE'))
+
+def gcc_compile_c(targets, sources, properties):
+ engine = get_manager().engine()
+ # If we use the name g++ then default file suffix -> language mapping does
+ # not work. So have to pass -x option. Maybe, we can work around this by
+ # allowing the user to specify both C and C++ compiler names.
+ #if $(>:S) != .c
+ #{
+ engine.set_target_variable (targets, 'LANG', '-x c')
+ #}
+ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE'))
+
+engine.register_action(
+ 'gcc.compile.c++',
+ '"$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-128 $(OPTIONS) ' +
+ '$(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" ' +
+ '-c -o "$(<:W)" "$(>:W)"',
+ function=gcc_compile_cpp,
+ bound_list=['PCH_FILE'])
+
+engine.register_action(
+ 'gcc.compile.c',
+ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) ' +
+ '-I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"',
+ function=gcc_compile_c,
+ bound_list=['PCH_FILE'])
+
+def gcc_compile_asm(targets, sources, properties):
+ get_manager().engine().set_target_variable(targets, 'LANG', '-x assembler-with-cpp')
+
+engine.register_action(
+ 'gcc.compile.asm',
+ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"',
+ function=gcc_compile_asm)
+
+
+class GccLinkingGenerator(unix.UnixLinkingGenerator):
+ """
+ The class which check that we don't try to use the <runtime-link>static
+ property while creating or using shared library, since it's not supported by
+ gcc/libc.
+ """
+ def run(self, project, name, ps, sources):
+ # TODO: Replace this with the use of a target-os property.
+
+ no_static_link = False
+ if bjam.variable('UNIX'):
+ no_static_link = True;
+ ##FIXME: what does this mean?
+## {
+## switch [ modules.peek : JAMUNAME ]
+## {
+## case * : no-static-link = true ;
+## }
+## }
+
+ reason = None
+ if no_static_link and ps.get('runtime-link') == 'static':
+ if ps.get('link') == 'shared':
+ reason = "On gcc, DLL can't be build with '<runtime-link>static'."
+ elif type.is_derived(self.target_types[0], 'EXE'):
+ for s in sources:
+ source_type = s.type()
+ if source_type and type.is_derived(source_type, 'SHARED_LIB'):
+ reason = "On gcc, using DLLS together with the " +\
+ "<runtime-link>static options is not possible "
+ if reason:
+ print 'warning:', reason
+ print 'warning:',\
+ "It is suggested to use '<runtime-link>static' together",\
+ "with '<link>static'." ;
+ return
+ else:
+ generated_targets = unix.UnixLinkingGenerator.run(self, project,
+ name, ps, sources)
+ return generated_targets
+
+if on_windows():
+ flags('gcc.link.dll', '.IMPLIB-COMMAND', [], ['-Wl,--out-implib,'])
+ generators.register(
+ GccLinkingGenerator('gcc.link', True,
+ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'],
+ [ 'EXE' ],
+ [ '<toolset>gcc' ]))
+ generators.register(
+ GccLinkingGenerator('gcc.link.dll', True,
+ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'],
+ ['IMPORT_LIB', 'SHARED_LIB'],
+ ['<toolset>gcc']))
+else:
+ generators.register(
+ GccLinkingGenerator('gcc.link', True,
+ ['LIB', 'OBJ'],
+ ['EXE'],
+ ['<toolset>gcc']))
+ generators.register(
+ GccLinkingGenerator('gcc.link.dll', True,
+ ['LIB', 'OBJ'],
+ ['SHARED_LIB'],
+ ['<toolset>gcc']))
+
+# Declare flags for linking.
+# First, the common flags.
+flags('gcc.link', 'OPTIONS', ['<debug-symbols>on'], ['-g'])
+flags('gcc.link', 'OPTIONS', ['<profiling>on'], ['-pg'])
+flags('gcc.link', 'USER_OPTIONS', [], ['<linkflags>'])
+flags('gcc.link', 'LINKPATH', [], ['<library-path>'])
+flags('gcc.link', 'FINDLIBS-ST', [], ['<find-static-library>'])
+flags('gcc.link', 'FINDLIBS-SA', [], ['<find-shared-library>'])
+flags('gcc.link', 'LIBRARIES', [], ['<library-file>'])
+
+# For <runtime-link>static we made sure there are no dynamic libraries in the
+# link. On HP-UX not all system libraries exist as archived libraries (for
+# example, there is no libunwind.a), so, on this platform, the -static option
+# cannot be specified.
+if os_name() != 'HPUX':
+ flags('gcc.link', 'OPTIONS', ['<runtime-link>static'], ['-static'])
+
+# Now, the vendor specific flags.
+# The parameter linker can be either gnu, darwin, osf, hpux or sun.
+def init_link_flags(toolset, linker, condition):
+ """
+ Now, the vendor specific flags.
+ The parameter linker can be either gnu, darwin, osf, hpux or sun.
+ """
+ toolset_link = toolset + '.link'
+ if linker == 'gnu':
+ # Strip the binary when no debugging is needed. We use --strip-all flag
+ # as opposed to -s since icc (intel's compiler) is generally
+ # option-compatible with and inherits from the gcc toolset, but does not
+ # support -s.
+
+ # FIXME: what does unchecked translate to?
+ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<debug-symbols>off', condition), ['-Wl,--strip-all']) # : unchecked ;
+ flags(toolset_link, 'RPATH', condition, ['<dll-path>']) # : unchecked ;
+ flags(toolset_link, 'RPATH_LINK', condition, ['<xdll-path>']) # : unchecked ;
+ flags(toolset_link, 'START-GROUP', condition, ['-Wl,--start-group'])# : unchecked ;
+ flags(toolset_link, 'END-GROUP', condition, ['-Wl,--end-group']) # : unchecked ;
+
+ # gnu ld has the ability to change the search behaviour for libraries
+ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic
+ # and change search for -l switches that follow them. The following list
+ # shows the tried variants.
+ # The search stops at the first variant that has a match.
+ # *nix: -Bstatic -lxxx
+ # libxxx.a
+ #
+ # *nix: -Bdynamic -lxxx
+ # libxxx.so
+ # libxxx.a
+ #
+ # windows (mingw,cygwin) -Bstatic -lxxx
+ # libxxx.a
+ # xxx.lib
+ #
+ # windows (mingw,cygwin) -Bdynamic -lxxx
+ # libxxx.dll.a
+ # xxx.dll.a
+ # libxxx.a
+ # xxx.lib
+ # cygxxx.dll (*)
+ # libxxx.dll
+ # xxx.dll
+ # libxxx.a
+ #
+ # (*) This is for cygwin
+ # Please note that -Bstatic and -Bdynamic are not a guarantee that a
+ # static or dynamic lib indeed gets linked in. The switches only change
+ # search patterns!
+
+ # On *nix mixing shared libs with static runtime is not a good idea.
+ flags(toolset_link, 'FINDLIBS-ST-PFX',
+ map(lambda x: x + '/<runtime-link>shared', condition),
+ ['-Wl,-Bstatic']) # : unchecked ;
+ flags(toolset_link, 'FINDLIBS-SA-PFX',
+ map(lambda x: x + '/<runtime-link>shared', condition),
+ ['-Wl,-Bdynamic']) # : unchecked ;
+
+ # On windows allow mixing of static and dynamic libs with static
+ # runtime.
+ flags(toolset_link, 'FINDLIBS-ST-PFX',
+ map(lambda x: x + '/<runtime-link>static/<target-os>windows', condition),
+ ['-Wl,-Bstatic']) # : unchecked ;
+ flags(toolset_link, 'FINDLIBS-SA-PFX',
+ map(lambda x: x + '/<runtime-link>static/<target-os>windows', condition),
+ ['-Wl,-Bdynamic']) # : unchecked ;
+ flags(toolset_link, 'OPTIONS',
+ map(lambda x: x + '/<runtime-link>static/<target-os>windows', condition),
+ ['-Wl,-Bstatic']) # : unchecked ;
+
+ elif linker == 'darwin':
+ # On Darwin, the -s option to ld does not work unless we pass -static,
+ # and passing -static unconditionally is a bad idea. So, don't pass -s.
+ # at all, darwin.jam will use separate 'strip' invocation.
+ flags(toolset_link, 'RPATH', condition, ['<dll-path>']) # : unchecked ;
+ flags(toolset_link, 'RPATH_LINK', condition, ['<xdll-path>']) # : unchecked ;
+
+ elif linker == 'osf':
+ # No --strip-all, just -s.
+ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<debug-symbols>off', condition), ['-Wl,-s'])
+ # : unchecked ;
+ flags(toolset_link, 'RPATH', condition, ['<dll-path>']) # : unchecked ;
+ # This does not supports -R.
+ flags(toolset_link, 'RPATH_OPTION', condition, ['-rpath']) # : unchecked ;
+ # -rpath-link is not supported at all.
+
+ elif linker == 'sun':
+ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<debug-symbols>off', condition), ['-Wl,-s'])
+ # : unchecked ;
+ flags(toolset_link, 'RPATH', condition, ['<dll-path>']) # : unchecked ;
+ # Solaris linker does not have a separate -rpath-link, but allows to use
+ # -L for the same purpose.
+ flags(toolset_link, 'LINKPATH', condition, ['<xdll-path>']) # : unchecked ;
+
+ # This permits shared libraries with non-PIC code on Solaris.
+ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the
+ # following is not needed. Whether -fPIC should be hardcoded, is a
+ # separate question.
+ # AH, 2004/10/16: it is still necessary because some tests link against
+ # static libraries that were compiled without PIC.
+ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<link>shared', condition), ['-mimpure-text'])
+ # : unchecked ;
+
+ elif linker == 'hpux':
+ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<debug-symbols>off', condition),
+ ['-Wl,-s']) # : unchecked ;
+ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<link>shared', condition),
+ ['-fPIC']) # : unchecked ;
+
+ else:
+ # FIXME:
+ errors.user_error(
+ "$(toolset) initialization: invalid linker '$(linker)' " +
+ "The value '$(linker)' specified for <linker> is not recognized. " +
+ "Possible values are 'gnu', 'darwin', 'osf', 'hpux' or 'sun'")
+
+# Declare actions for linking.
+def gcc_link(targets, sources, properties):
+ engine = get_manager().engine()
+ engine.set_target_variable(targets, 'SPACE', ' ')
+ # Serialize execution of the 'link' action, since running N links in
+ # parallel is just slower. For now, serialize only gcc links, it might be a
+ # good idea to serialize all links.
+ engine.set_target_variable(targets, 'JAM_SEMAPHORE', '<s>gcc-link-semaphore')
+
+engine.register_action(
+ 'gcc.link',
+ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' +
+ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' +
+ '-Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" ' +
+ '$(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' +
+ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' +
+ '$(OPTIONS) $(USER_OPTIONS)',
+ function=gcc_link,
+ bound_list=['LIBRARIES'])
+
+# Default value. Mostly for the sake of intel-linux that inherits from gcc, but
+# does not have the same logic to set the .AR variable. We can put the same
+# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is
+# always available.
+__AR = 'ar'
+
+flags('gcc.archive', 'AROPTIONS', [], ['<archiveflags>'])
+
+def gcc_archive(targets, sources, properties):
+ # Always remove archive and start again. Here's rationale from
+ #
+ # Andre Hentz:
+ #
+ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to
+ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd
+ # errors. After some debugging I traced it back to the fact that a1.o was
+ # *still* in liba.a
+ #
+ # Rene Rivera:
+ #
+ # Originally removing the archive was done by splicing an RM onto the
+ # archive action. That makes archives fail to build on NT when they have
+ # many files because it will no longer execute the action directly and blow
+ # the line length limit. Instead we remove the file in a different action,
+ # just before building the archive.
+ clean = targets[0] + '(clean)'
+ bjam.call('TEMPORARY', clean)
+ bjam.call('NOCARE', clean)
+ engine = get_manager().engine()
+ engine.set_target_variable('LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE'))
+ engine.add_dependency(clean, sources)
+ engine.add_dependency(targets, clean)
+ engine.set_update_action('common.RmTemps', clean, targets)
+
+# Declare action for creating static libraries.
+# The letter 'r' means to add files to the archive with replacement. Since we
+# remove archive, we don't care about replacement, but there's no option "add
+# without replacement".
+# The letter 'c' suppresses the warning in case the archive does not exists yet.
+# That warning is produced only on some platforms, for whatever reasons.
+engine.register_action('gcc.archive',
+ '"$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"',
+ function=gcc_archive,
+ flags=['piecemeal'])
+
+def gcc_link_dll(targets, sources, properties):
+ engine = get_manager().engine()
+ engine.set_target_variable(targets, 'SPACE', ' ')
+ engine.set_target_variable(targets, 'JAM_SEMAPHORE', '<s>gcc-link-semaphore')
+ engine.set_target_variable(targets, "HAVE_SONAME", HAVE_SONAME)
+ engine.set_target_variable(targets, "SONAME_OPTION", SONAME_OPTION)
+
+engine.register_action(
+ 'gcc.link.dll',
+ # Differ from 'link' above only by -shared.
+ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' +
+ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' +
+ '"$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" ' +
+ '$(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) ' +
+ '-shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' +
+ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' +
+ '$(OPTIONS) $(USER_OPTIONS)',
+ function = gcc_link_dll,
+ bound_list=['LIBRARIES'])
+
+# Set up threading support. It's somewhat contrived, so perform it at the end,
+# to avoid cluttering other code.
+
+if on_windows():
+ flags('gcc', 'OPTIONS', ['<threading>multi'], ['-mthreads'])
+elif bjam.variable('UNIX'):
+ jamuname = bjam.variable('JAMUNAME')
+ host_os_name = jamuname[0]
+ if host_os_name.startswith('SunOS'):
+ flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthreads'])
+ flags('gcc', 'FINDLIBS-SA', [], ['rt'])
+ elif host_os_name == 'BeOS':
+ # BeOS has no threading options, don't set anything here.
+ pass
+ elif host_os_name.endswith('BSD'):
+ flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread'])
+ # there is no -lrt on BSD
+ elif host_os_name == 'DragonFly':
+ flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread'])
+ # there is no -lrt on BSD - DragonFly is a FreeBSD variant,
+ # which anoyingly doesn't say it's a *BSD.
+ elif host_os_name == 'IRIX':
+ # gcc on IRIX does not support multi-threading, don't set anything here.
+ pass
+ elif host_os_name == 'Darwin':
+ # Darwin has no threading options, don't set anything here.
+ pass
+ else:
+ flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread'])
+ flags('gcc', 'FINDLIBS-SA', [], ['rt'])
+
+def cpu_flags(toolset, variable, architecture, instruction_set, values, default=None):
+ #FIXME: for some reason this fails. Probably out of date feature code
+## if default:
+## flags(toolset, variable,
+## ['<architecture>' + architecture + '/<instruction-set>'],
+## values)
+ flags(toolset, variable,
+ #FIXME: same as above
+ [##'<architecture>/<instruction-set>' + instruction_set,
+ '<architecture>' + architecture + '/<instruction-set>' + instruction_set],
+ values)
+
+# Set architecture/instruction-set options.
+#
+# x86 and compatible
+flags('gcc', 'OPTIONS', ['<architecture>x86/<address-model>32'], ['-m32'])
+flags('gcc', 'OPTIONS', ['<architecture>x86/<address-model>64'], ['-m64'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'i386', ['-march=i386'], default=True)
+cpu_flags('gcc', 'OPTIONS', 'x86', 'i486', ['-march=i486'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'i586', ['-march=i586'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'i686', ['-march=i686'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium', ['-march=pentium'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium-mmx', ['-march=pentium-mmx'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'pentiumpro', ['-march=pentiumpro'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium2', ['-march=pentium2'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium3', ['-march=pentium3'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium3m', ['-march=pentium3m'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium-m', ['-march=pentium-m'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium4', ['-march=pentium4'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium4m', ['-march=pentium4m'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'prescott', ['-march=prescott'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'nocona', ['-march=nocona'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'k6', ['-march=k6'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'k6-2', ['-march=k6-2'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'k6-3', ['-march=k6-3'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon', ['-march=athlon'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon-tbird', ['-march=athlon-tbird'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon-4', ['-march=athlon-4'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon-xp', ['-march=athlon-xp'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon-mp', ['-march=athlon-mp'])
+##
+cpu_flags('gcc', 'OPTIONS', 'x86', 'k8', ['-march=k8'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'opteron', ['-march=opteron'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon64', ['-march=athlon64'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon-fx', ['-march=athlon-fx'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'winchip-c6', ['-march=winchip-c6'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'winchip2', ['-march=winchip2'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'c3', ['-march=c3'])
+cpu_flags('gcc', 'OPTIONS', 'x86', 'c3-2', ['-march=c3-2'])
+# Sparc
+flags('gcc', 'OPTIONS', ['<architecture>sparc/<address-model>32'], ['-m32'])
+flags('gcc', 'OPTIONS', ['<architecture>sparc/<address-model>64'], ['-m64'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'c3', ['-mcpu=c3'], default=True)
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'v7', ['-mcpu=v7'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'cypress', ['-mcpu=cypress'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'v8', ['-mcpu=v8'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'supersparc', ['-mcpu=supersparc'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'sparclite', ['-mcpu=sparclite'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'hypersparc', ['-mcpu=hypersparc'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'sparclite86x', ['-mcpu=sparclite86x'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'f930', ['-mcpu=f930'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'f934', ['-mcpu=f934'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'sparclet', ['-mcpu=sparclet'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'tsc701', ['-mcpu=tsc701'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'v9', ['-mcpu=v9'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'ultrasparc', ['-mcpu=ultrasparc'])
+cpu_flags('gcc', 'OPTIONS', 'sparc', 'ultrasparc3', ['-mcpu=ultrasparc3'])
+# RS/6000 & PowerPC
+flags('gcc', 'OPTIONS', ['<architecture>power/<address-model>32'], ['-m32'])
+flags('gcc', 'OPTIONS', ['<architecture>power/<address-model>64'], ['-m64'])
+cpu_flags('gcc', 'OPTIONS', 'power', '403', ['-mcpu=403'])
+cpu_flags('gcc', 'OPTIONS', 'power', '505', ['-mcpu=505'])
+cpu_flags('gcc', 'OPTIONS', 'power', '601', ['-mcpu=601'])
+cpu_flags('gcc', 'OPTIONS', 'power', '602', ['-mcpu=602'])
+cpu_flags('gcc', 'OPTIONS', 'power', '603', ['-mcpu=603'])
+cpu_flags('gcc', 'OPTIONS', 'power', '603e', ['-mcpu=603e'])
+cpu_flags('gcc', 'OPTIONS', 'power', '604', ['-mcpu=604'])
+cpu_flags('gcc', 'OPTIONS', 'power', '604e', ['-mcpu=604e'])
+cpu_flags('gcc', 'OPTIONS', 'power', '620', ['-mcpu=620'])
+cpu_flags('gcc', 'OPTIONS', 'power', '630', ['-mcpu=630'])
+cpu_flags('gcc', 'OPTIONS', 'power', '740', ['-mcpu=740'])
+cpu_flags('gcc', 'OPTIONS', 'power', '7400', ['-mcpu=7400'])
+cpu_flags('gcc', 'OPTIONS', 'power', '7450', ['-mcpu=7450'])
+cpu_flags('gcc', 'OPTIONS', 'power', '750', ['-mcpu=750'])
+cpu_flags('gcc', 'OPTIONS', 'power', '801', ['-mcpu=801'])
+cpu_flags('gcc', 'OPTIONS', 'power', '821', ['-mcpu=821'])
+cpu_flags('gcc', 'OPTIONS', 'power', '823', ['-mcpu=823'])
+cpu_flags('gcc', 'OPTIONS', 'power', '860', ['-mcpu=860'])
+cpu_flags('gcc', 'OPTIONS', 'power', '970', ['-mcpu=970'])
+cpu_flags('gcc', 'OPTIONS', 'power', '8540', ['-mcpu=8540'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'power', ['-mcpu=power'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'power2', ['-mcpu=power2'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'power3', ['-mcpu=power3'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'power4', ['-mcpu=power4'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'power5', ['-mcpu=power5'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'powerpc', ['-mcpu=powerpc'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'powerpc64', ['-mcpu=powerpc64'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'rios', ['-mcpu=rios'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'rios1', ['-mcpu=rios1'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'rios2', ['-mcpu=rios2'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'rsc', ['-mcpu=rsc'])
+cpu_flags('gcc', 'OPTIONS', 'power', 'rs64a', ['-mcpu=rs64'])
+# AIX variant of RS/6000 & PowerPC
+flags('gcc', 'OPTIONS', ['<architecture>power/<address-model>32/<target-os>aix'], ['-maix32'])
+flags('gcc', 'OPTIONS', ['<architecture>power/<address-model>64/<target-os>aix'], ['-maix64'])
+flags('gcc', 'AROPTIONS', ['<architecture>power/<address-model>64/<target-os>aix'], ['-X 64'])
diff --git a/tools/build/v2/tools/generate.jam b/tools/build/v2/tools/generate.jam
new file mode 100644
index 0000000000..6732fa3551
--- /dev/null
+++ b/tools/build/v2/tools/generate.jam
@@ -0,0 +1,108 @@
+# Copyright 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Declares main target 'generate' used to produce targets by calling a
+# user-provided rule that takes and produces virtual targets.
+
+import "class" : new ;
+import errors ;
+import feature ;
+import project ;
+import property ;
+import property-set ;
+import targets ;
+import regex ;
+
+
+feature.feature generating-rule : : free ;
+
+
+class generated-target-class : basic-target
+{
+ import errors ;
+ import indirect ;
+ import virtual-target ;
+
+ rule __init__ ( name : project : sources * : requirements *
+ : default-build * : usage-requirements * )
+ {
+ basic-target.__init__ $(name) : $(project) : $(sources)
+ : $(requirements) : $(default-build) : $(usage-requirements) ;
+
+ if ! [ $(self.requirements).get <generating-rule> ]
+ {
+ errors.user-error "The generate rule requires the <generating-rule>"
+ "property to be set" ;
+ }
+ }
+
+ rule construct ( name : sources * : property-set )
+ {
+ local result ;
+ local gr = [ $(property-set).get <generating-rule> ] ;
+
+ # FIXME: this is a copy-paste from virtual-target.jam. We should add a
+ # utility rule to call a rule like this.
+ local rule-name = [ MATCH ^@(.*) : $(gr) ] ;
+ if $(rule-name)
+ {
+ if $(gr[2])
+ {
+ local target-name = [ full-name ] ;
+ errors.user-error "Multiple <generating-rule> properties"
+ "encountered for target $(target-name)." ;
+ }
+
+ result = [ indirect.call $(rule-name) $(self.project) $(name)
+ : $(property-set) : $(sources) ] ;
+
+ if ! $(result)
+ {
+ ECHO "warning: Unable to construct" [ full-name ] ;
+ }
+ }
+
+ local ur ;
+ local targets ;
+
+ if $(result)
+ {
+ if [ class.is-a $(result[1]) : property-set ]
+ {
+ ur = $(result[1]) ;
+ targets = $(result[2-]) ;
+ }
+ else
+ {
+ ur = [ property-set.empty ] ;
+ targets = $(result) ;
+ }
+ }
+ # FIXME: the following loop should be doable using sequence.transform or
+ # some similar utility rule.
+ local rt ;
+ for local t in $(targets)
+ {
+ rt += [ virtual-target.register $(t) ] ;
+ }
+ return $(ur) $(rt) ;
+ }
+}
+
+
+rule generate ( name : sources * : requirements * : default-build *
+ : usage-requirements * )
+{
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new generated-target-class $(name) : $(project)
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
+ ] ;
+}
+
+IMPORT $(__name__) : generate : : generate ;
diff --git a/tools/build/v2/tools/gettext.jam b/tools/build/v2/tools/gettext.jam
new file mode 100644
index 0000000000..99a43ffe9a
--- /dev/null
+++ b/tools/build/v2/tools/gettext.jam
@@ -0,0 +1,230 @@
+# Copyright 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This module support GNU gettext internationalization utilities.
+#
+# It provides two main target rules: 'gettext.catalog', used for
+# creating machine-readable catalogs from translations files, and
+# 'gettext.update', used for update translation files from modified
+# sources.
+#
+# To add i18n support to your application you should follow these
+# steps.
+#
+# - Decide on a file name which will contain translations and
+# what main target name will be used to update it. For example::
+#
+# gettext.update update-russian : russian.po a.cpp my_app ;
+#
+# - Create the initial translation file by running::
+#
+# bjam update-russian
+#
+# - Edit russian.po. For example, you might change fields like LastTranslator.
+#
+# - Create a main target for final message catalog::
+#
+# gettext.catalog russian : russian.po ;
+#
+# The machine-readable catalog will be updated whenever you update
+# "russian.po". The "russian.po" file will be updated only on explicit
+# request. When you're ready to update translations, you should
+#
+# - Run::
+#
+# bjam update-russian
+#
+# - Edit "russian.po" in appropriate editor.
+#
+# The next bjam run will convert "russian.po" into machine-readable form.
+#
+# By default, translations are marked by 'i18n' call. The 'gettext.keyword'
+# feature can be used to alter this.
+
+
+import targets ;
+import property-set ;
+import virtual-target ;
+import "class" : new ;
+import project ;
+import type ;
+import generators ;
+import errors ;
+import feature : feature ;
+import toolset : flags ;
+import regex ;
+
+.path = "" ;
+
+# Initializes the gettext module.
+rule init ( path ? # Path where all tools are located. If not specified,
+ # they should be in PATH.
+ )
+{
+ if $(.initialized) && $(.path) != $(path)
+ {
+ errors.error "Attempt to reconfigure with different path" ;
+ }
+ .initialized = true ;
+ if $(path)
+ {
+ .path = $(path)/ ;
+ }
+}
+
+# Creates a main target 'name', which, when updated, will cause
+# file 'existing-translation' to be updated with translations
+# extracted from 'sources'. It's possible to specify main target
+# in sources --- it which case all target from dependency graph
+# of those main targets will be scanned, provided they are of
+# appropricate type. The 'gettext.types' feature can be used to
+# control the types.
+#
+# The target will be updated only if explicitly requested on the
+# command line.
+rule update ( name : existing-translation sources + : requirements * )
+{
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new typed-target $(name) : $(project) : gettext.UPDATE :
+ $(existing-translation) $(sources)
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ ] ;
+ $(project).mark-target-as-explicit $(name) ;
+}
+
+
+# The human editable source, containing translation.
+type.register gettext.PO : po ;
+# The machine readable message catalog.
+type.register gettext.catalog : mo ;
+# Intermediate type produce by extracting translations from
+# sources.
+type.register gettext.POT : pot ;
+# Pseudo type used to invoke update-translations generator
+type.register gettext.UPDATE ;
+
+# Identifies the keyword that should be used when scanning sources.
+# Default: i18n
+feature gettext.keyword : : free ;
+# Contains space-separated list of sources types which should be scanned.
+# Default: "C CPP"
+feature gettext.types : : free ;
+
+generators.register-standard gettext.compile : gettext.PO : gettext.catalog ;
+
+class update-translations-generator : generator
+{
+ import regex : split ;
+ import property-set ;
+
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ # The rule should be called with at least two sources. The first source
+ # is the translation (.po) file to update. The remaining sources are targets
+ # which should be scanned for new messages. All sources files for those targets
+ # will be found and passed to the 'xgettext' utility, which extracts the
+ # messages for localization. Those messages will be merged to the .po file.
+ rule run ( project name ? : property-set : sources * : multiple ? )
+ {
+ local types = [ $(property-set).get <gettext.types> ] ;
+ types ?= "C CPP" ;
+ types = [ regex.split $(types) " " ] ;
+
+ local keywords = [ $(property-set).get <gettext.keyword> ] ;
+ property-set = [ property-set.create $(keywords:G=<gettext.keyword>) ] ;
+
+ # First deterime the list of sources that must be scanned for
+ # messages.
+ local all-sources ;
+ # CONSIDER: I'm not sure if the logic should be the same as for 'stage':
+ # i.e. following dependency properties as well.
+ for local s in $(sources[2-])
+ {
+ all-sources += [ virtual-target.traverse $(s) : : include-sources ] ;
+ }
+ local right-sources ;
+ for local s in $(all-sources)
+ {
+ if [ $(s).type ] in $(types)
+ {
+ right-sources += $(s) ;
+ }
+ }
+
+ local .constructed ;
+ if $(right-sources)
+ {
+ # Create the POT file, which will contain list of messages extracted
+ # from the sources.
+ local extract =
+ [ new action $(right-sources) : gettext.extract : $(property-set) ] ;
+ local new-messages = [ new file-target $(name) : gettext.POT
+ : $(project) : $(extract) ] ;
+
+ # Create a notfile target which will update the existing translation file
+ # with new messages.
+ local a = [ new action $(sources[1]) $(new-messages)
+ : gettext.update-po-dispatch ] ;
+ local r = [ new notfile-target $(name) : $(project) : $(a) ] ;
+ .constructed = [ virtual-target.register $(r) ] ;
+ }
+ else
+ {
+ errors.error "No source could be scanned by gettext tools" ;
+ }
+ return $(.constructed) ;
+ }
+}
+generators.register [ new update-translations-generator gettext.update : : gettext.UPDATE ] ;
+
+flags gettext.extract KEYWORD <gettext.keyword> ;
+actions extract
+{
+ $(.path)xgettext -k$(KEYWORD:E=i18n) -o $(<) $(>)
+}
+
+# Does realy updating of po file. The tricky part is that
+# we're actually updating one of the sources:
+# $(<) is the NOTFILE target we're updating
+# $(>[1]) is the PO file to be really updated.
+# $(>[2]) is the PO file created from sources.
+#
+# When file to be updated does not exist (during the
+# first run), we need to copy the file created from sources.
+# In all other cases, we need to update the file.
+rule update-po-dispatch
+{
+ NOCARE $(>[1]) ;
+ gettext.create-po $(<) : $(>) ;
+ gettext.update-po $(<) : $(>) ;
+ _ on $(<) = " " ;
+ ok on $(<) = "" ;
+ EXISTING_PO on $(<) = $(>[1]) ;
+}
+
+# Due to fancy interaction of existing and updated, this rule can be called with
+# one source, in which case we copy the lonely source into EXISTING_PO, or with
+# two sources, in which case the action body expands to nothing. I'd really like
+# to have "missing" action modifier.
+actions quietly existing updated create-po bind EXISTING_PO
+{
+ cp$(_)"$(>[1])"$(_)"$(EXISTING_PO)"$($(>[2]:E=ok))
+}
+
+actions updated update-po bind EXISTING_PO
+{
+ $(.path)msgmerge$(_)-U$(_)"$(EXISTING_PO)"$(_)"$(>[1])"
+}
+
+actions gettext.compile
+{
+ $(.path)msgfmt -o $(<) $(>)
+}
+
+IMPORT $(__name__) : update : : gettext.update ;
diff --git a/tools/build/v2/tools/gfortran.jam b/tools/build/v2/tools/gfortran.jam
new file mode 100644
index 0000000000..0aa69b85cc
--- /dev/null
+++ b/tools/build/v2/tools/gfortran.jam
@@ -0,0 +1,39 @@
+# Copyright (C) 2004 Toon Knapen
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import toolset : flags ;
+import feature ;
+import fortran ;
+
+rule init ( version ? : command * : options * )
+{
+}
+
+# Declare flags and action for compilation
+flags gfortran OPTIONS <fflags> ;
+
+flags gfortran OPTIONS <optimization>off : -O0 ;
+flags gfortran OPTIONS <optimization>speed : -O3 ;
+flags gfortran OPTIONS <optimization>space : -Os ;
+
+flags gfortran OPTIONS <debug-symbols>on : -g ;
+flags gfortran OPTIONS <profiling>on : -pg ;
+
+flags gfortran OPTIONS <link>shared/<main-target-type>LIB : -fPIC ;
+
+flags gfortran DEFINES <define> ;
+flags gfortran INCLUDES <include> ;
+
+rule compile.fortran
+{
+}
+
+actions compile.fortran
+{
+ gcc -Wall $(OPTIONS) -D$(DEFINES) -I$(INCLUDES) -c -o "$(<)" "$(>)"
+}
+
+generators.register-fortran-compiler gfortran.compile.fortran : FORTRAN FORTRAN90 : OBJ ;
diff --git a/tools/build/v2/tools/hp_cxx.jam b/tools/build/v2/tools/hp_cxx.jam
new file mode 100644
index 0000000000..86cd783e29
--- /dev/null
+++ b/tools/build/v2/tools/hp_cxx.jam
@@ -0,0 +1,181 @@
+# Copyright 2001 David Abrahams.
+# Copyright 2004, 2005 Markus Schoepflin.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+#
+# HP CXX compiler
+# See http://h30097.www3.hp.com/cplus/?jumpid=reg_R1002_USEN
+#
+#
+# Notes on this toolset:
+#
+# - Because of very subtle issues with the default ansi mode, strict_ansi mode
+# is used for compilation. One example of things that don't work correctly in
+# the default ansi mode is overload resolution of function templates when
+# mixed with non-template functions.
+#
+# - For template instantiation "-timplicit_local" is used. Previously,
+# "-tlocal" has been tried to avoid the need for a template repository
+# but this doesn't work with manually instantiated templates. "-tweak"
+# has not been used to avoid the stream of warning messages issued by
+# ar or ld when creating a library or linking an application.
+#
+# - Debug symbols are generated with "-g3", as this works both in debug and
+# release mode. When compiling C++ code without optimization, we additionally
+# use "-gall", which generates full symbol table information for all classes,
+# structs, and unions. As this turns off optimization, it can't be used when
+# optimization is needed.
+#
+
+import feature generators common ;
+import toolset : flags ;
+
+feature.extend toolset : hp_cxx ;
+feature.extend c++abi : cxxarm ;
+
+# Inherit from Unix toolset to get library ordering magic.
+toolset.inherit hp_cxx : unix ;
+
+generators.override hp_cxx.prebuilt : builtin.lib-generator ;
+generators.override hp_cxx.prebuilt : builtin.prebuilt ;
+generators.override hp_cxx.searched-lib-generator : searched-lib-generator ;
+
+
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters hp_cxx : version $(version) ] ;
+
+ local command = [ common.get-invocation-command hp_cxx : cxx : $(command) ] ;
+
+ if $(command)
+ {
+ local root = [ common.get-absolute-tool-path $(command[-1]) ] ;
+
+ if $(root)
+ {
+ flags hp_cxx .root $(condition) : "\"$(root)\"/" ;
+ }
+ }
+ # If we can't find 'cxx' anyway, at least show 'cxx' in the commands
+ command ?= cxx ;
+
+ common.handle-options hp_cxx : $(condition) : $(command) : $(options) ;
+}
+
+generators.register-c-compiler hp_cxx.compile.c++ : CPP : OBJ : <toolset>hp_cxx ;
+generators.register-c-compiler hp_cxx.compile.c : C : OBJ : <toolset>hp_cxx ;
+
+
+
+# No static linking as far as I can tell.
+# flags cxx LINKFLAGS <runtime-link>static : -bstatic ;
+flags hp_cxx.compile OPTIONS <debug-symbols>on : -g3 ;
+flags hp_cxx.compile OPTIONS <optimization>off/<debug-symbols>on : -gall ;
+flags hp_cxx.link OPTIONS <debug-symbols>on : -g ;
+flags hp_cxx.link OPTIONS <debug-symbols>off : -s ;
+
+flags hp_cxx.compile OPTIONS <optimization>off : -O0 ;
+flags hp_cxx.compile OPTIONS <optimization>speed/<inlining>on : -O2 ;
+flags hp_cxx.compile OPTIONS <optimization>speed : -O2 ;
+
+# This (undocumented) macro needs to be defined to get all C function
+# overloads required by the C++ standard.
+flags hp_cxx.compile.c++ OPTIONS : -D__CNAME_OVERLOADS ;
+
+# Added for threading support
+flags hp_cxx.compile OPTIONS <threading>multi : -pthread ;
+flags hp_cxx.link OPTIONS <threading>multi : -pthread ;
+
+flags hp_cxx.compile OPTIONS <optimization>space/<inlining>on : <inlining>size ;
+flags hp_cxx.compile OPTIONS <optimization>space : -O1 ;
+flags hp_cxx.compile OPTIONS <inlining>off : -inline none ;
+
+# The compiler versions tried (up to V6.5-040) hang when compiling Boost code
+# with full inlining enabled. So leave it at the default level for now.
+#
+# flags hp_cxx.compile OPTIONS <inlining>full : -inline all ;
+
+flags hp_cxx.compile OPTIONS <profiling>on : -pg ;
+flags hp_cxx.link OPTIONS <profiling>on : -pg ;
+
+# Selection of the object model. This flag is needed on both the C++ compiler
+# and linker command line.
+
+# Unspecified ABI translates to '-model ansi' as most
+# standard-conforming.
+flags hp_cxx.compile.c++ OPTIONS <c++abi> : -model ansi : : hack-hack ;
+flags hp_cxx.compile.c++ OPTIONS <c++abi>cxxarm : -model arm ;
+flags hp_cxx.link OPTIONS <c++abi> : -model ansi : : hack-hack ;
+flags hp_cxx.link OPTIONS <c++abi>cxxarm : -model arm ;
+
+# Display a descriptive tag together with each compiler message. This tag can
+# be used by the user to explicitely suppress the compiler message.
+flags hp_cxx.compile OPTIONS : -msg_display_tag ;
+
+flags hp_cxx.compile OPTIONS <cflags> ;
+flags hp_cxx.compile.c++ OPTIONS <cxxflags> ;
+flags hp_cxx.compile DEFINES <define> ;
+flags hp_cxx.compile INCLUDES <include> ;
+flags hp_cxx.link OPTIONS <linkflags> ;
+
+flags hp_cxx.link LIBPATH <library-path> ;
+flags hp_cxx.link LIBRARIES <library-file> ;
+flags hp_cxx.link FINDLIBS-ST <find-static-library> ;
+flags hp_cxx.link FINDLIBS-SA <find-shared-library> ;
+
+flags hp_cxx.compile.c++ TEMPLATE_DEPTH <c++-template-depth> ;
+
+actions link bind LIBRARIES
+{
+ $(CONFIG_COMMAND) -noimplicit_include $(OPTIONS) -o "$(<)" -L$(LIBPATH) "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-ST) -l$(FINDLIBS-SA) -lrt -lm
+}
+
+# When creating dynamic libraries, we don't want to be warned about unresolved
+# symbols, therefore all unresolved symbols are marked as expected by
+# '-expect_unresolved *'. This also mirrors the behaviour of the GNU tool
+# chain.
+
+actions link.dll bind LIBRARIES
+{
+ $(CONFIG_COMMAND) -shared -expect_unresolved \* -noimplicit_include $(OPTIONS) -o "$(<[1])" -L$(LIBPATH) "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-ST) -l$(FINDLIBS-SA) -lm
+}
+
+
+# Note: Relaxed ANSI mode (-std) is used for compilation because in strict ANSI
+# C89 mode (-std1) the compiler doesn't accept C++ comments in C files. As -std
+# is the default, no special flag is needed.
+actions compile.c
+{
+ $(.root:E=)cc -c $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -o "$(<)" "$(>)"
+}
+
+# Note: The compiler is forced to compile the files as C++ (-x cxx) because
+# otherwise it will silently ignore files with no file extension.
+#
+# Note: We deliberately don't suppress any warnings on the compiler command
+# line, the user can always do this in a customized toolset later on.
+
+rule compile.c++
+{
+ # We preprocess the TEMPLATE_DEPTH command line option here because we found
+ # no way to do it correctly in the actual action code. There we either get
+ # the -pending_instantiations parameter when no c++-template-depth property
+ # has been specified or we get additional quotes around
+ # "-pending_instantiations ".
+ local template-depth = [ on $(1) return $(TEMPLATE_DEPTH) ] ;
+ TEMPLATE_DEPTH on $(1) = "-pending_instantiations "$(template-depth) ;
+}
+
+actions compile.c++
+{
+ $(CONFIG_COMMAND) -x cxx -c -std strict_ansi -nopure_cname -noimplicit_include -timplicit_local -ptr "$(<[1]:D)/cxx_repository" $(OPTIONS) $(TEMPLATE_DEPTH) -D$(DEFINES) -I"$(INCLUDES)" -o "$(<)" "$(>)"
+}
+
+# Always create archive from scratch. See the gcc toolet for rationale.
+RM = [ common.rm-command ] ;
+actions together piecemeal archive
+{
+ $(RM) "$(<)"
+ ar rc $(<) $(>)
+}
diff --git a/tools/build/v2/tools/hpfortran.jam b/tools/build/v2/tools/hpfortran.jam
new file mode 100644
index 0000000000..96e8d18b5a
--- /dev/null
+++ b/tools/build/v2/tools/hpfortran.jam
@@ -0,0 +1,35 @@
+# Copyright (C) 2004 Toon Knapen
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import toolset : flags ;
+import feature ;
+import fortran ;
+
+rule init ( version ? : command * : options * )
+{
+}
+
+# Declare flags and action for compilation
+flags hpfortran OPTIONS <optimization>off : -O0 ;
+flags hpfortran OPTIONS <optimization>speed : -O3 ;
+flags hpfortran OPTIONS <optimization>space : -O1 ;
+
+flags hpfortran OPTIONS <debug-symbols>on : -g ;
+flags hpfortran OPTIONS <profiling>on : -pg ;
+
+flags hpfortran DEFINES <define> ;
+flags hpfortran INCLUDES <include> ;
+
+rule compile.fortran
+{
+}
+
+actions compile.fortran
+{
+ f77 +DD64 $(OPTIONS) -D$(DEFINES) -I$(INCLUDES) -c -o "$(<)" "$(>)"
+}
+
+generators.register-fortran-compiler hpfortran.compile.fortran : FORTRAN : OBJ ;
diff --git a/tools/build/v2/tools/ifort.jam b/tools/build/v2/tools/ifort.jam
new file mode 100644
index 0000000000..eb7c198818
--- /dev/null
+++ b/tools/build/v2/tools/ifort.jam
@@ -0,0 +1,44 @@
+# Copyright (C) 2004 Toon Knapen
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import toolset : flags ;
+import feature ;
+import fortran ;
+
+rule init ( version ? : command * : options * )
+{
+}
+
+# Declare flags and action for compilation
+flags ifort OPTIONS <fflags> ;
+
+flags ifort OPTIONS <optimization>off : /Od ;
+flags ifort OPTIONS <optimization>speed : /O3 ;
+flags ifort OPTIONS <optimization>space : /O1 ;
+
+flags ifort OPTIONS <debug-symbols>on : /debug:full ;
+flags ifort OPTIONS <profiling>on : /Qprof_gen ;
+
+flags ifort.compile FFLAGS <runtime-debugging>off/<runtime-link>shared : /MD ;
+flags ifort.compile FFLAGS <runtime-debugging>on/<runtime-link>shared : /MDd ;
+flags ifort.compile FFLAGS <runtime-debugging>off/<runtime-link>static/<threading>single : /ML ;
+flags ifort.compile FFLAGS <runtime-debugging>on/<runtime-link>static/<threading>single : /MLd ;
+flags ifort.compile FFLAGS <runtime-debugging>off/<runtime-link>static/<threading>multi : /MT ;
+flags ifort.compile FFLAGS <runtime-debugging>on/<runtime-link>static/<threading>multi : /MTd ;
+
+flags ifort DEFINES <define> ;
+flags ifort INCLUDES <include> ;
+
+rule compile.fortran
+{
+}
+
+actions compile.fortran
+{
+ ifort $(FFLAGS) $(OPTIONS) /names:lowercase /D$(DEFINES) /I"$(INCLUDES)" /c /object:"$(<)" "$(>)"
+}
+
+generators.register-fortran-compiler ifort.compile.fortran : FORTRAN : OBJ ;
diff --git a/tools/build/v2/tools/intel-darwin.jam b/tools/build/v2/tools/intel-darwin.jam
new file mode 100644
index 0000000000..aa0fd8fb6d
--- /dev/null
+++ b/tools/build/v2/tools/intel-darwin.jam
@@ -0,0 +1,220 @@
+# Copyright Vladimir Prus 2004.
+# Copyright Noel Belcourt 2007.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import intel ;
+import feature : feature ;
+import os ;
+import toolset ;
+import toolset : flags ;
+import gcc ;
+import common ;
+import errors ;
+import generators ;
+
+feature.extend-subfeature toolset intel : platform : darwin ;
+
+toolset.inherit-generators intel-darwin
+ <toolset>intel <toolset-intel:platform>darwin
+ : gcc
+ # Don't inherit PCH generators. They were not tested, and probably
+ # don't work for this compiler.
+ : gcc.mingw.link gcc.mingw.link.dll gcc.compile.c.pch gcc.compile.c++.pch
+ ;
+
+generators.override intel-darwin.prebuilt : builtin.lib-generator ;
+generators.override intel-darwin.prebuilt : builtin.prebuilt ;
+generators.override intel-darwin.searched-lib-generator : searched-lib-generator ;
+
+toolset.inherit-rules intel-darwin : gcc ;
+toolset.inherit-flags intel-darwin : gcc
+ : <inlining>off <inlining>on <inlining>full <optimization>space
+ <warnings>off <warnings>all <warnings>on
+ <architecture>x86/<address-model>32
+ <architecture>x86/<address-model>64
+ ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+# vectorization diagnostics
+feature vectorize : off on full ;
+
+# Initializes the intel-darwin toolset
+# version in mandatory
+# name (default icc) is used to invoke the specified intel complier
+# compile and link options allow you to specify addition command line options for each version
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters intel-darwin
+ : version $(version) ] ;
+
+ command = [ common.get-invocation-command intel-darwin : icc
+ : $(command) : /opt/intel_cc_80/bin ] ;
+
+ common.handle-options intel-darwin : $(condition) : $(command) : $(options) ;
+
+ gcc.init-link-flags intel-darwin darwin $(condition) ;
+
+ # handle <library-path>
+ # local library-path = [ feature.get-values <library-path> : $(options) ] ;
+ # flags intel-darwin.link USER_OPTIONS $(condition) : [ feature.get-values <dll-path> : $(options) ] ;
+
+ local root = [ feature.get-values <root> : $(options) ] ;
+ local bin ;
+ if $(command) || $(root)
+ {
+ bin ?= [ common.get-absolute-tool-path $(command[-1]) ] ;
+ root ?= $(bin:D) ;
+
+ if $(root)
+ {
+ # Libraries required to run the executable may be in either
+ # $(root)/lib (10.1 and earlier)
+ # or
+ # $(root)/lib/architecture-name (11.0 and later:
+ local lib_path = $(root)/lib $(root:P)/lib/$(bin:B) ;
+ if $(.debug-configuration)
+ {
+ ECHO notice: using intel libraries :: $(condition) :: $(lib_path) ;
+ }
+ flags intel-darwin.link RUN_PATH $(condition) : $(lib_path) ;
+ }
+ }
+
+ local m = [ MATCH (..).* : $(version) ] ;
+ local n = [ MATCH (.)\\. : $(m) ] ;
+ if $(n) {
+ m = $(n) ;
+ }
+
+ local major = $(m) ;
+
+ if $(major) = "9" {
+ flags intel-darwin.compile OPTIONS $(condition)/<inlining>off : -Ob0 ;
+ flags intel-darwin.compile OPTIONS $(condition)/<inlining>on : -Ob1 ;
+ flags intel-darwin.compile OPTIONS $(condition)/<inlining>full : -Ob2 ;
+ flags intel-darwin.compile OPTIONS $(condition)/<vectorize>off : -vec-report0 ;
+ flags intel-darwin.compile OPTIONS $(condition)/<vectorize>on : -vec-report1 ;
+ flags intel-darwin.compile OPTIONS $(condition)/<vectorize>full : -vec-report5 ;
+ flags intel-darwin.link OPTIONS $(condition)/<runtime-link>static : -static -static-libcxa -lstdc++ -lpthread ;
+ flags intel-darwin.link OPTIONS $(condition)/<runtime-link>shared : -shared-libcxa -lstdc++ -lpthread ;
+ }
+ else {
+ flags intel-darwin.compile OPTIONS $(condition)/<inlining>off : -inline-level=0 ;
+ flags intel-darwin.compile OPTIONS $(condition)/<inlining>on : -inline-level=1 ;
+ flags intel-darwin.compile OPTIONS $(condition)/<inlining>full : -inline-level=2 ;
+ flags intel-darwin.compile OPTIONS $(condition)/<vectorize>off : -vec-report0 ;
+ flags intel-darwin.compile OPTIONS $(condition)/<vectorize>on : -vec-report1 ;
+ flags intel-darwin.compile OPTIONS $(condition)/<vectorize>full : -vec-report5 ;
+ flags intel-darwin.link OPTIONS $(condition)/<runtime-link>static : -static -static-intel -lstdc++ -lpthread ;
+ flags intel-darwin.link OPTIONS $(condition)/<runtime-link>shared : -shared-intel -lstdc++ -lpthread ;
+ }
+
+ local minor = [ MATCH ".*\\.(.).*" : $(version) ] ;
+
+ # wchar_t char_traits workaround for compilers older than 10.2
+ if $(major) = "9" || ( $(major) = "10" && ( $(minor) = "0" || $(minor) = "1" ) ) {
+ flags intel-darwin.compile DEFINES $(condition) : __WINT_TYPE__=int : unchecked ;
+ }
+}
+
+SPACE = " " ;
+
+flags intel-darwin.compile OPTIONS <cflags> ;
+flags intel-darwin.compile OPTIONS <cxxflags> ;
+# flags intel-darwin.compile INCLUDES <include> ;
+
+flags intel-darwin.compile OPTIONS <optimization>space : -O1 ; # no specific space optimization flag in icc
+
+#
+cpu-type-em64t = prescott nocona ;
+flags intel-darwin.compile OPTIONS <instruction-set>$(cpu-type-em64t)/<address-model>32 : -m32 ; # -mcmodel=small ;
+flags intel-darwin.compile OPTIONS <instruction-set>$(cpu-type-em64t)/<address-model>64 : -m64 ; # -mcmodel=large ;
+
+flags intel-darwin.compile.c OPTIONS <warnings>off : -w0 ;
+flags intel-darwin.compile.c OPTIONS <warnings>on : -w1 ;
+flags intel-darwin.compile.c OPTIONS <warnings>all : -w2 ;
+
+flags intel-darwin.compile.c++ OPTIONS <warnings>off : -w0 ;
+flags intel-darwin.compile.c++ OPTIONS <warnings>on : -w1 ;
+flags intel-darwin.compile.c++ OPTIONS <warnings>all : -w2 ;
+
+actions compile.c
+{
+ "$(CONFIG_COMMAND)" -xc $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" -xc++ $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+flags intel-darwin ARFLAGS <archiveflags> ;
+
+# Default value. Mostly for the sake of intel-linux
+# that inherits from gcc, but does not has the same
+# logic to set the .AR variable. We can put the same
+# logic in intel-linux, but that's hardly worth the trouble
+# as on Linux, 'ar' is always available.
+.AR = ar ;
+
+rule archive ( targets * : sources * : properties * )
+{
+ # Always remove archive and start again. Here's rationale from
+ # Andre Hentz:
+ #
+ # I had a file, say a1.c, that was included into liba.a.
+ # I moved a1.c to a2.c, updated my Jamfiles and rebuilt.
+ # My program was crashing with absurd errors.
+ # After some debugging I traced it back to the fact that a1.o was *still*
+ # in liba.a
+ #
+ # Rene Rivera:
+ #
+ # Originally removing the archive was done by splicing an RM
+ # onto the archive action. That makes archives fail to build on NT
+ # when they have many files because it will no longer execute the
+ # action directly and blow the line length limit. Instead we
+ # remove the file in a different action, just before the building
+ # of the archive.
+ #
+ local clean.a = $(targets[1])(clean) ;
+ TEMPORARY $(clean.a) ;
+ NOCARE $(clean.a) ;
+ LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ;
+ DEPENDS $(clean.a) : $(sources) ;
+ DEPENDS $(targets) : $(clean.a) ;
+ common.RmTemps $(clean.a) : $(targets) ;
+}
+
+actions piecemeal archive
+{
+ "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"
+ "ranlib" -cs "$(<)"
+}
+
+flags intel-darwin.link USER_OPTIONS <linkflags> ;
+
+# Declare actions for linking
+rule link ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+ # Serialize execution of the 'link' action, since
+ # running N links in parallel is just slower.
+ JAM_SEMAPHORE on $(targets) = <s>intel-darwin-link-semaphore ;
+}
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(USER_OPTIONS) -L"$(LINKPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(OPTIONS)
+}
+
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(USER_OPTIONS) -L"$(LINKPATH)" -o "$(<)" -single_module -dynamiclib -install_name "$(<[1]:D=)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(OPTIONS)
+}
diff --git a/tools/build/v2/tools/intel-linux.jam b/tools/build/v2/tools/intel-linux.jam
new file mode 100644
index 0000000000..d9164add80
--- /dev/null
+++ b/tools/build/v2/tools/intel-linux.jam
@@ -0,0 +1,250 @@
+# Copyright (c) 2003 Michael Stevens
+# Copyright (c) 2011 Bryce Lelbach
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import toolset ;
+import feature ;
+import toolset : flags ;
+
+import intel ;
+import gcc ;
+import common ;
+import errors ;
+import generators ;
+import type ;
+import numbers ;
+
+feature.extend-subfeature toolset intel : platform : linux ;
+
+toolset.inherit-generators intel-linux
+ <toolset>intel <toolset-intel:platform>linux : gcc : gcc.mingw.link gcc.mingw.link.dll ;
+generators.override intel-linux.prebuilt : builtin.lib-generator ;
+generators.override intel-linux.prebuilt : builtin.prebuilt ;
+generators.override intel-linux.searched-lib-generator : searched-lib-generator ;
+
+# Override default do-nothing generators.
+generators.override intel-linux.compile.c.pch : pch.default-c-pch-generator ;
+generators.override intel-linux.compile.c++.pch : pch.default-cpp-pch-generator ;
+
+type.set-generated-target-suffix PCH : <toolset>intel <toolset-intel:platform>linux : pchi ;
+
+toolset.inherit-rules intel-linux : gcc ;
+toolset.inherit-flags intel-linux : gcc
+ : <inlining>off <inlining>on <inlining>full
+ <optimization>space <optimization>speed
+ <warnings>off <warnings>all <warnings>on
+ ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+# Initializes the intel-linux toolset
+# version in mandatory
+# name (default icpc) is used to invoke the specified intel-linux complier
+# compile and link options allow you to specify addition command line options for each version
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters intel-linux
+ : version $(version) ] ;
+
+ if $(.debug-configuration)
+ {
+ ECHO "notice: intel-linux version is" $(version) ;
+ }
+
+ local default_path ;
+
+ # Intel C++ Composer XE 2011 for Linux, aka Intel C++ Compiler XE 12.0,
+ # aka intel-linux-12.0. In this version, Intel thankfully decides to install
+ # to a sane 'intel' folder in /opt.
+ if [ MATCH "(12[.]0|12)" : $(version) ]
+ { default_path = /opt/intel/bin ; }
+ # Intel C++ Compiler 11.1.
+ else if [ MATCH "(11[.]1)" : $(version) ]
+ { default_path = /opt/intel_cce_11.1.064.x86_64/bin ; }
+ # Intel C++ Compiler 11.0.
+ else if [ MATCH "(11[.]0|11)" : $(version) ]
+ { default_path = /opt/intel_cce_11.0.074.x86_64/bin ; }
+ # Intel C++ Compiler 10.1.
+ else if [ MATCH "(10[.]1)" : $(version) ]
+ { default_path = /opt/intel_cce_10.1.013_x64/bin ; }
+ # Intel C++ Compiler 9.1.
+ else if [ MATCH "(9[.]1)" : $(version) ]
+ { default_path = /opt/intel_cc_91/bin ; }
+ # Intel C++ Compiler 9.0.
+ else if [ MATCH "(9[.]0|9)" : $(version) ]
+ { default_path = /opt/intel_cc_90/bin ; }
+ # Intel C++ Compiler 8.1.
+ else if [ MATCH "(8[.]1)" : $(version) ]
+ { default_path = /opt/intel_cc_81/bin ; }
+ # Intel C++ Compiler 8.0 - this used to be the default, so now it's the
+ # fallback.
+ else
+ { default_path = /opt/intel_cc_80/bin ; }
+
+ if $(.debug-configuration)
+ {
+ ECHO "notice: default search path for intel-linux is" $(default_path) ;
+ }
+
+ command = [ common.get-invocation-command intel-linux : icpc
+ : $(command) : $(default_path) ] ;
+
+ common.handle-options intel-linux : $(condition) : $(command) : $(options) ;
+
+ gcc.init-link-flags intel-linux gnu $(condition) ;
+
+ local root = [ feature.get-values <root> : $(options) ] ;
+ local bin ;
+ if $(command) || $(root)
+ {
+ bin ?= [ common.get-absolute-tool-path $(command[-1]) ] ;
+ root ?= $(bin:D) ;
+
+ local command-string = $(command:J=" ") ;
+ local version-output = [ SHELL "$(command-string) --version" ] ;
+ local real-version = [ MATCH "([0-9.]+)" : $(version-output) ] ;
+ local major = [ MATCH "([0-9]+).*" : $(real-version) ] ;
+
+ # If we failed to determine major version, use the behaviour for
+ # the current compiler.
+ if $(major) && [ numbers.less $(major) 10 ]
+ {
+ flags intel-linux.compile OPTIONS $(condition)/<inlining>off : "-Ob0" ;
+ flags intel-linux.compile OPTIONS $(condition)/<inlining>on : "-Ob1" ;
+ flags intel-linux.compile OPTIONS $(condition)/<inlining>full : "-Ob2" ;
+ flags intel-linux.compile OPTIONS $(condition)/<optimization>space : "-O1" ;
+ flags intel-linux.compile OPTIONS $(condition)/<optimization>speed : "-O3 -ip" ;
+ }
+ else if $(major) && [ numbers.less $(major) 11 ]
+ {
+ flags intel-linux.compile OPTIONS $(condition)/<inlining>off : "-inline-level=0" ;
+ flags intel-linux.compile OPTIONS $(condition)/<inlining>on : "-inline-level=1" ;
+ flags intel-linux.compile OPTIONS $(condition)/<inlining>full : "-inline-level=2" ;
+ flags intel-linux.compile OPTIONS $(condition)/<optimization>space : "-O1" ;
+ flags intel-linux.compile OPTIONS $(condition)/<optimization>speed : "-O3 -ip" ;
+ }
+ else # newer version of intel do have -Os (at least 11+, don't know about 10)
+ {
+ flags intel-linux.compile OPTIONS $(condition)/<inlining>off : "-inline-level=0" ;
+ flags intel-linux.compile OPTIONS $(condition)/<inlining>on : "-inline-level=1" ;
+ flags intel-linux.compile OPTIONS $(condition)/<inlining>full : "-inline-level=2" ;
+ flags intel-linux.compile OPTIONS $(condition)/<optimization>space : "-Os" ;
+ flags intel-linux.compile OPTIONS $(condition)/<optimization>speed : "-O3 -ip" ;
+ }
+
+ if $(root)
+ {
+ # Libraries required to run the executable may be in either
+ # $(root)/lib (10.1 and earlier)
+ # or
+ # $(root)/lib/architecture-name (11.0 and later:
+ local lib_path = $(root)/lib $(root:P)/lib/$(bin:B) ;
+ if $(.debug-configuration)
+ {
+ ECHO notice: using intel libraries :: $(condition) :: $(lib_path) ;
+ }
+ flags intel-linux.link RUN_PATH $(condition) : $(lib_path) ;
+ }
+ }
+}
+
+SPACE = " " ;
+
+flags intel-linux.compile OPTIONS <warnings>off : -w0 ;
+flags intel-linux.compile OPTIONS <warnings>on : -w1 ;
+flags intel-linux.compile OPTIONS <warnings>all : -w2 ;
+
+rule compile.c++ ( targets * : sources * : properties * )
+{
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-fpic $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ;
+}
+
+actions compile.c++ bind PCH_FILE
+{
+ "$(CONFIG_COMMAND)" -c -xc++ $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -use-pch"$(PCH_FILE)" -c -o "$(<)" "$(>)"
+}
+
+rule compile.c ( targets * : sources * : properties * )
+{
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-fpic $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ;
+}
+
+actions compile.c bind PCH_FILE
+{
+ "$(CONFIG_COMMAND)" -c -xc $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -use-pch"$(PCH_FILE)" -c -o "$(<)" "$(>)"
+}
+
+rule compile.c++.pch ( targets * : sources * : properties * )
+{
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-fpic $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+}
+#
+# Compiling a pch first deletes any existing *.pchi file, as Intel's compiler
+# won't over-write an existing pch: instead it creates filename$1.pchi, filename$2.pchi
+# etc - which appear not to do anything except take up disk space :-(
+#
+actions compile.c++.pch
+{
+ rm -f "$(<)" && "$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -pch-create "$(<)" "$(>)"
+}
+
+actions compile.fortran
+{
+ "ifort" -c $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+rule compile.c.pch ( targets * : sources * : properties * )
+{
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-fpic $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+}
+
+actions compile.c.pch
+{
+ rm -f "$(<)" && "$(CONFIG_COMMAND)" -x c-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -pch-create "$(<)" "$(>)"
+}
+
+rule link ( targets * : sources * : properties * )
+{
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+ SPACE on $(targets) = " " ;
+ JAM_SEMAPHORE on $(targets) = <s>intel-linux-link-semaphore ;
+}
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(OPTIONS) $(USER_OPTIONS)
+}
+
+rule link.dll ( targets * : sources * : properties * )
+{
+ gcc.setup-threading $(targets) : $(sources) : $(properties) ;
+ gcc.setup-address-model $(targets) : $(sources) : $(properties) ;
+ SPACE on $(targets) = " " ;
+ JAM_SEMAPHORE on $(targets) = <s>intel-linux-link-semaphore ;
+}
+
+# Differ from 'link' above only by -shared.
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -o "$(<)" -Wl,-soname$(SPACE)-Wl,$(<[1]:D=) -shared "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(OPTIONS) $(USER_OPTIONS)
+}
+
+
+
diff --git a/tools/build/v2/tools/intel-win.jam b/tools/build/v2/tools/intel-win.jam
new file mode 100644
index 0000000000..691b5dce98
--- /dev/null
+++ b/tools/build/v2/tools/intel-win.jam
@@ -0,0 +1,184 @@
+# Copyright Vladimir Prus 2004.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# Importing common is needed because the rules we inherit here depend on it.
+# That is nasty.
+import common ;
+import errors ;
+import feature ;
+import intel ;
+import msvc ;
+import os ;
+import toolset ;
+import generators ;
+import type ;
+
+feature.extend-subfeature toolset intel : platform : win ;
+
+toolset.inherit-generators intel-win <toolset>intel <toolset-intel:platform>win : msvc ;
+toolset.inherit-flags intel-win : msvc : : YLOPTION ;
+toolset.inherit-rules intel-win : msvc ;
+
+# Override default do-nothing generators.
+generators.override intel-win.compile.c.pch : pch.default-c-pch-generator ;
+generators.override intel-win.compile.c++.pch : pch.default-cpp-pch-generator ;
+generators.override intel-win.compile.rc : rc.compile.resource ;
+generators.override intel-win.compile.mc : mc.compile ;
+
+toolset.flags intel-win.compile PCH_SOURCE <pch>on : <pch-source> ;
+
+toolset.add-requirements <toolset>intel-win,<runtime-link>shared:<threading>multi ;
+
+# Initializes the intel toolset for windows
+rule init ( version ? : # the compiler version
+ command * : # the command to invoke the compiler itself
+ options * # Additional option: <compatibility>
+ # either 'vc6', 'vc7', 'vc7.1'
+ # or 'native'(default).
+ )
+{
+ local compatibility =
+ [ feature.get-values <compatibility> : $(options) ] ;
+ local condition = [ common.check-init-parameters intel-win
+ : version $(version) : compatibility $(compatibility) ] ;
+
+ command = [ common.get-invocation-command intel-win : icl.exe :
+ $(command) ] ;
+
+ common.handle-options intel-win : $(condition) : $(command) : $(options) ;
+
+ local root ;
+ if $(command)
+ {
+ root = [ common.get-absolute-tool-path $(command[-1]) ] ;
+ root = $(root)/ ;
+ }
+
+ local setup ;
+ setup = [ GLOB $(root) : iclvars_*.bat ] ;
+ if ! $(setup)
+ {
+ setup = $(root)/iclvars.bat ;
+ }
+ setup = "call \""$(setup)"\" > nul " ;
+
+ if [ os.name ] = NT
+ {
+ setup = $(setup)"
+" ;
+ }
+ else
+ {
+ setup = "cmd /S /C "$(setup)" \"&&\" " ;
+ }
+
+ toolset.flags intel-win.compile .CC $(condition) : $(setup)icl ;
+ toolset.flags intel-win.link .LD $(condition) : $(setup)xilink ;
+ toolset.flags intel-win.archive .LD $(condition) : $(setup)xilink /lib ;
+ toolset.flags intel-win.link .MT $(condition) : $(setup)mt -nologo ;
+ toolset.flags intel-win.compile .MC $(condition) : $(setup)mc ;
+ toolset.flags intel-win.compile .RC $(condition) : $(setup)rc ;
+
+ local m = [ MATCH (.).* : $(version) ] ;
+ local major = $(m[1]) ;
+
+ local C++FLAGS ;
+
+ C++FLAGS += /nologo ;
+
+ # Reduce the number of spurious error messages
+ C++FLAGS += /Qwn5 /Qwd985 ;
+
+ # Enable ADL
+ C++FLAGS += -Qoption,c,--arg_dep_lookup ; #"c" works for C++, too
+
+ # Disable Microsoft "secure" overloads in Dinkumware libraries since they
+ # cause compile errors with Intel versions 9 and 10.
+ C++FLAGS += -D_SECURE_SCL=0 ;
+
+ if $(major) > 5
+ {
+ C++FLAGS += /Zc:forScope ; # Add support for correct for loop scoping.
+ }
+
+ # Add options recognized only by intel7 and above.
+ if $(major) >= 7
+ {
+ C++FLAGS += /Qansi_alias ;
+ }
+
+ if $(compatibility) = vc6
+ {
+ C++FLAGS +=
+ # Emulate VC6
+ /Qvc6
+
+ # No wchar_t support in vc6 dinkum library. Furthermore, in vc6
+ # compatibility-mode, wchar_t is not a distinct type from unsigned
+ # short.
+ -DBOOST_NO_INTRINSIC_WCHAR_T
+ ;
+ }
+ else
+ {
+ if $(major) > 5
+ {
+ # Add support for wchar_t
+ C++FLAGS += /Zc:wchar_t
+ # Tell the dinkumware library about it.
+ -D_NATIVE_WCHAR_T_DEFINED
+ ;
+ }
+ }
+
+ if $(compatibility) && $(compatibility) != native
+ {
+ C++FLAGS += /Q$(base-vc) ;
+ }
+ else
+ {
+ C++FLAGS +=
+ -Qoption,cpp,--arg_dep_lookup
+ # The following options were intended to disable the Intel compiler's
+ # 'bug-emulation' mode, but were later reported to be causing ICE with
+ # Intel-Win 9.0. It is not yet clear which options can be safely used.
+ # -Qoption,cpp,--const_string_literals
+ # -Qoption,cpp,--new_for_init
+ # -Qoption,cpp,--no_implicit_typename
+ # -Qoption,cpp,--no_friend_injection
+ # -Qoption,cpp,--no_microsoft_bugs
+ ;
+ }
+
+ toolset.flags intel-win CFLAGS $(condition) : $(C++FLAGS) ;
+ # By default, when creating PCH, intel adds 'i' to the explicitly
+ # specified name of the PCH file. Of course, Boost.Build is not
+ # happy when compiler produces not the file it was asked for.
+ # The option below stops this behaviour.
+ toolset.flags intel-win CFLAGS : -Qpchi- ;
+
+ if ! $(compatibility)
+ {
+ # If there's no backend version, assume 7.1.
+ compatibility = vc7.1 ;
+ }
+
+ local extract-version = [ MATCH ^vc(.*) : $(compatibility) ] ;
+ if ! $(extract-version)
+ {
+ errors.user-error "Invalid value for compatibility option:"
+ $(compatibility) ;
+ }
+
+ # Depending on the settings, running of tests require some runtime DLLs.
+ toolset.flags intel-win RUN_PATH $(condition) : $(root) ;
+
+ msvc.configure-version-specific intel-win : $(extract-version[1]) : $(condition) ;
+}
+
+toolset.flags intel-win.link LIBRARY_OPTION <toolset>intel : "" ;
+
+toolset.flags intel-win YLOPTION ;
+
diff --git a/tools/build/v2/tools/intel.jam b/tools/build/v2/tools/intel.jam
new file mode 100644
index 0000000000..67038aa287
--- /dev/null
+++ b/tools/build/v2/tools/intel.jam
@@ -0,0 +1,34 @@
+# Copyright Vladimir Prus 2004.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# This is a generic 'intel' toolset. Depending on the current
+# system, it forwards either to 'intel-linux' or 'intel-win'
+# modules.
+
+import feature ;
+import os ;
+import toolset ;
+
+feature.extend toolset : intel ;
+feature.subfeature toolset intel : platform : : propagated link-incompatible ;
+
+rule init ( * : * )
+{
+ if [ os.name ] = LINUX
+ {
+ toolset.using intel-linux :
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+ else if [ os.name ] = MACOSX
+ {
+ toolset.using intel-darwin :
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+ else
+ {
+ toolset.using intel-win :
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+}
diff --git a/tools/build/v2/tools/lex.jam b/tools/build/v2/tools/lex.jam
new file mode 100644
index 0000000000..75d641318c
--- /dev/null
+++ b/tools/build/v2/tools/lex.jam
@@ -0,0 +1,33 @@
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import type ;
+import generators ;
+import feature ;
+import property ;
+
+
+feature.feature flex.prefix : : free ;
+type.register LEX : l ;
+type.register LEX++ : ll ;
+generators.register-standard lex.lex : LEX : C ;
+generators.register-standard lex.lex : LEX++ : CPP ;
+
+rule init ( )
+{
+}
+
+rule lex ( target : source : properties * )
+{
+ local r = [ property.select flex.prefix : $(properties) ] ;
+ if $(r)
+ {
+ PREFIX on $(<) = $(r:G=) ;
+ }
+}
+
+actions lex
+{
+ flex -P$(PREFIX) -o$(<) $(>)
+}
diff --git a/tools/build/v2/tools/make.jam b/tools/build/v2/tools/make.jam
new file mode 100644
index 0000000000..085672857b
--- /dev/null
+++ b/tools/build/v2/tools/make.jam
@@ -0,0 +1,72 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2003 Douglas Gregor
+# Copyright 2006 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This module defines the 'make' main target rule.
+
+import "class" : new ;
+import errors : error ;
+import project ;
+import property ;
+import property-set ;
+import regex ;
+import targets ;
+
+
+class make-target-class : basic-target
+{
+ import type regex virtual-target ;
+ import "class" : new ;
+
+ rule __init__ ( name : project : sources * : requirements *
+ : default-build * : usage-requirements * )
+ {
+ basic-target.__init__ $(name) : $(project) : $(sources) :
+ $(requirements) : $(default-build) : $(usage-requirements) ;
+ }
+
+ rule construct ( name : source-targets * : property-set )
+ {
+ local action-name = [ $(property-set).get <action> ] ;
+ # 'm' will always be set -- we add '@' ourselves in the 'make' rule
+ # below.
+ local m = [ MATCH ^@(.*) : $(action-name) ] ;
+
+ local a = [ new action $(source-targets) : $(m[1]) : $(property-set) ] ;
+ local t = [ new file-target $(self.name) exact : [ type.type
+ $(self.name) ] : $(self.project) : $(a) ] ;
+ return [ property-set.empty ] [ virtual-target.register $(t) ] ;
+ }
+}
+
+
+# Declares the 'make' main target.
+#
+rule make ( target-name : sources * : generating-rule + : requirements * :
+ usage-requirements * )
+{
+ local project = [ project.current ] ;
+
+ # The '@' sign causes the feature.jam module to qualify rule name with the
+ # module name of current project, if needed.
+ local m = [ MATCH ^(@).* : $(generating-rule) ] ;
+ if ! $(m)
+ {
+ generating-rule = @$(generating-rule) ;
+ }
+ requirements += <action>$(generating-rule) ;
+
+ targets.main-target-alternative
+ [ new make-target-class $(target-name) : $(project)
+ : [ targets.main-target-sources $(sources) : $(target-name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) :
+ $(project) ] ] ;
+}
+
+
+IMPORT $(__name__) : make : : make ;
diff --git a/tools/build/v2/tools/make.py b/tools/build/v2/tools/make.py
new file mode 100644
index 0000000000..10baa1cb41
--- /dev/null
+++ b/tools/build/v2/tools/make.py
@@ -0,0 +1,59 @@
+# Status: ported.
+# Base revision: 64068
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2003 Douglas Gregor
+# Copyright 2006 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This module defines the 'make' main target rule.
+
+from b2.build.targets import BasicTarget
+from b2.build.virtual_target import Action, FileTarget
+from b2.build import type
+from b2.manager import get_manager
+import b2.build.property_set
+
+
+class MakeTarget(BasicTarget):
+
+ def construct(self, name, source_targets, property_set):
+
+ action_name = property_set.get("<action>")[0]
+ action = Action(get_manager(), source_targets, action_name[1:], property_set)
+ target = FileTarget(self.name(), type.type(self.name()),
+ self.project(), action, exact=True)
+ return [ b2.build.property_set.empty(),
+ [self.project().manager().virtual_targets().register(target)]]
+
+def make (target_name, sources, generating_rule,
+ requirements=None, usage_requirements=None):
+
+ target_name = target_name[0]
+ generating_rule = generating_rule[0]
+ if generating_rule[0] != '@':
+ generating_rule = '@' + generating_rule
+
+ if not requirements:
+ requirements = []
+
+
+ requirements.append("<action>%s" % generating_rule)
+
+ m = get_manager()
+ targets = m.targets()
+ project = m.projects().current()
+ engine = m.engine()
+ engine.register_bjam_action(generating_rule)
+
+ targets.main_target_alternative(MakeTarget(
+ target_name, project,
+ targets.main_target_sources(sources, target_name),
+ targets.main_target_requirements(requirements, project),
+ targets.main_target_default_build([], project),
+ targets.main_target_usage_requirements(usage_requirements or [], project)))
+
+get_manager().projects().add_rule("make", make)
+
diff --git a/tools/build/v2/tools/mc.jam b/tools/build/v2/tools/mc.jam
new file mode 100644
index 0000000000..578377735e
--- /dev/null
+++ b/tools/build/v2/tools/mc.jam
@@ -0,0 +1,44 @@
+#~ Copyright 2005 Alexey Pakhunov.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Support for Microsoft message compiler tool.
+# Notes:
+# - there's just message compiler tool, there's no tool for
+# extracting message strings from sources
+# - This file allows to use Microsoft message compiler
+# with any toolset. In msvc.jam, there's more specific
+# message compiling action.
+
+import common ;
+import generators ;
+import feature : feature get-values ;
+import toolset : flags ;
+import type ;
+import rc ;
+
+rule init ( )
+{
+}
+
+type.register MC : mc ;
+
+
+# Command line options
+feature mc-input-encoding : ansi unicode : free ;
+feature mc-output-encoding : unicode ansi : free ;
+feature mc-set-customer-bit : no yes : free ;
+
+flags mc.compile MCFLAGS <mc-input-encoding>ansi : -a ;
+flags mc.compile MCFLAGS <mc-input-encoding>unicode : -u ;
+flags mc.compile MCFLAGS <mc-output-encoding>ansi : -A ;
+flags mc.compile MCFLAGS <mc-output-encoding>unicode : -U ;
+flags mc.compile MCFLAGS <mc-set-customer-bit>no : ;
+flags mc.compile MCFLAGS <mc-set-customer-bit>yes : -c ;
+
+generators.register-standard mc.compile : MC : H RC ;
+
+actions compile
+{
+ mc $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)"
+}
diff --git a/tools/build/v2/tools/message.jam b/tools/build/v2/tools/message.jam
new file mode 100644
index 0000000000..212d8542cd
--- /dev/null
+++ b/tools/build/v2/tools/message.jam
@@ -0,0 +1,55 @@
+# Copyright 2008 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Defines main target type 'message', that prints a message when built for the
+# first time.
+
+import project ;
+import "class" : new ;
+import targets ;
+import property-set ;
+
+class message-target-class : basic-target
+{
+ rule __init__ ( name-and-dir : project : * )
+ {
+ basic-target.__init__ $(name-and-dir) : $(project) ;
+ self.3 = $(3) ;
+ self.4 = $(4) ;
+ self.5 = $(5) ;
+ self.6 = $(6) ;
+ self.7 = $(7) ;
+ self.8 = $(8) ;
+ self.9 = $(9) ;
+ self.built = ;
+ }
+
+ rule construct ( name : source-targets * : property-set )
+ {
+ if ! $(self.built)
+ {
+ for i in 3 4 5 6 7 8 9
+ {
+ if $(self.$(i))
+ {
+ ECHO $(self.$(i)) ;
+ }
+ }
+ self.built = 1 ;
+ }
+
+ return [ property-set.empty ] ;
+ }
+}
+
+
+rule message ( name : * )
+{
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new message-target-class $(name) : $(project)
+ : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) ] ;
+}
+IMPORT $(__name__) : message : : message ; \ No newline at end of file
diff --git a/tools/build/v2/tools/message.py b/tools/build/v2/tools/message.py
new file mode 100644
index 0000000000..cc0b946ff1
--- /dev/null
+++ b/tools/build/v2/tools/message.py
@@ -0,0 +1,46 @@
+# Status: ported.
+# Base revision: 64488.
+#
+# Copyright 2008, 2010 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Defines main target type 'message', that prints a message when built for the
+# first time.
+
+import b2.build.targets as targets
+import b2.build.property_set as property_set
+
+from b2.manager import get_manager
+
+class MessageTargetClass(targets.BasicTarget):
+
+ def __init__(self, name, project, *args):
+
+ targets.BasicTarget.__init__(self, name, project, [])
+ self.args = args
+ self.built = False
+
+ def construct(self, name, sources, ps):
+
+ if not self.built:
+ for arg in self.args:
+ if type(arg) == type([]):
+ arg = " ".join(arg)
+ print arg
+ self.built = True
+
+ return (property_set.empty(), [])
+
+def message(name, *args):
+
+ if type(name) == type([]):
+ name = name[0]
+
+ t = get_manager().targets()
+
+ project = get_manager().projects().current()
+
+ return t.main_target_alternative(MessageTargetClass(*((name, project) + args)))
+
+get_manager().projects().add_rule("message", message)
diff --git a/tools/build/v2/tools/midl.jam b/tools/build/v2/tools/midl.jam
new file mode 100644
index 0000000000..0aa5dda31c
--- /dev/null
+++ b/tools/build/v2/tools/midl.jam
@@ -0,0 +1,142 @@
+# Copyright (c) 2005 Alexey Pakhunov.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Microsoft Interface Definition Language (MIDL) related routines
+
+import common ;
+import generators ;
+import feature : feature get-values ;
+import os ;
+import scanner ;
+import toolset : flags ;
+import type ;
+
+rule init ( )
+{
+}
+
+type.register IDL : idl ;
+
+# A type library (.tlb) is generated by MIDL compiler and can be included
+# to resources of an application (.rc). In order to be found by a resource
+# compiler its target type should be derived from 'H' - otherwise
+# the property '<implicit-dependency>' will be ignored.
+type.register MSTYPELIB : tlb : H ;
+
+
+# Register scanner for MIDL files
+class midl-scanner : scanner
+{
+ import path property-set regex scanner type virtual-target ;
+
+ rule __init__ ( includes * )
+ {
+ scanner.__init__ ;
+
+ self.includes = $(includes) ;
+
+ # List of quoted strings
+ self.re-strings = "[ \t]*\"([^\"]*)\"([ \t]*,[ \t]*\"([^\"]*)\")*[ \t]*" ;
+
+ # 'import' and 'importlib' directives
+ self.re-import = "import"$(self.re-strings)"[ \t]*;" ;
+ self.re-importlib = "importlib[ \t]*[(]"$(self.re-strings)"[)][ \t]*;" ;
+
+ # C preprocessor 'include' directive
+ self.re-include-angle = "#[ \t]*include[ \t]*<(.*)>" ;
+ self.re-include-quoted = "#[ \t]*include[ \t]*\"(.*)\"" ;
+ }
+
+ rule pattern ( )
+ {
+ # Match '#include', 'import' and 'importlib' directives
+ return "((#[ \t]*include|import(lib)?).+(<(.*)>|\"(.*)\").+)" ;
+ }
+
+ rule process ( target : matches * : binding )
+ {
+ local included-angle = [ regex.transform $(matches) : $(self.re-include-angle) : 1 ] ;
+ local included-quoted = [ regex.transform $(matches) : $(self.re-include-quoted) : 1 ] ;
+ local imported = [ regex.transform $(matches) : $(self.re-import) : 1 3 ] ;
+ local imported_tlbs = [ regex.transform $(matches) : $(self.re-importlib) : 1 3 ] ;
+
+ # CONSIDER: the new scoping rule seem to defeat "on target" variables.
+ local g = [ on $(target) return $(HDRGRIST) ] ;
+ local b = [ NORMALIZE_PATH $(binding:D) ] ;
+
+ # Attach binding of including file to included targets.
+ # When target is directly created from virtual target
+ # this extra information is unnecessary. But in other
+ # cases, it allows to distinguish between two headers of the
+ # same name included from different places.
+ local g2 = $(g)"#"$(b) ;
+
+ included-angle = $(included-angle:G=$(g)) ;
+ included-quoted = $(included-quoted:G=$(g2)) ;
+ imported = $(imported:G=$(g2)) ;
+ imported_tlbs = $(imported_tlbs:G=$(g2)) ;
+
+ local all = $(included-angle) $(included-quoted) $(imported) ;
+
+ INCLUDES $(target) : $(all) ;
+ DEPENDS $(target) : $(imported_tlbs) ;
+ NOCARE $(all) $(imported_tlbs) ;
+ SEARCH on $(included-angle) = $(self.includes:G=) ;
+ SEARCH on $(included-quoted) = $(b) $(self.includes:G=) ;
+ SEARCH on $(imported) = $(b) $(self.includes:G=) ;
+ SEARCH on $(imported_tlbs) = $(b) $(self.includes:G=) ;
+
+ scanner.propagate
+ [ type.get-scanner CPP : [ property-set.create $(self.includes) ] ] :
+ $(included-angle) $(included-quoted) : $(target) ;
+
+ scanner.propagate $(__name__) : $(imported) : $(target) ;
+ }
+}
+
+scanner.register midl-scanner : include ;
+type.set-scanner IDL : midl-scanner ;
+
+
+# Command line options
+feature midl-stubless-proxy : yes no : propagated ;
+feature midl-robust : yes no : propagated ;
+
+flags midl.compile.idl MIDLFLAGS <midl-stubless-proxy>yes : /Oicf ;
+flags midl.compile.idl MIDLFLAGS <midl-stubless-proxy>no : /Oic ;
+flags midl.compile.idl MIDLFLAGS <midl-robust>yes : /robust ;
+flags midl.compile.idl MIDLFLAGS <midl-robust>no : /no_robust ;
+
+# Architecture-specific options
+architecture-x86 = <architecture> <architecture>x86 ;
+address-model-32 = <address-model> <address-model>32 ;
+address-model-64 = <address-model> <address-model>64 ;
+
+flags midl.compile.idl MIDLFLAGS $(architecture-x86)/$(address-model-32) : /win32 ;
+flags midl.compile.idl MIDLFLAGS $(architecture-x86)/<address-model>64 : /x64 ;
+flags midl.compile.idl MIDLFLAGS <architecture>ia64/$(address-model-64) : /ia64 ;
+
+
+flags midl.compile.idl DEFINES <define> ;
+flags midl.compile.idl UNDEFS <undef> ;
+flags midl.compile.idl INCLUDES <include> ;
+
+
+generators.register-c-compiler midl.compile.idl : IDL : MSTYPELIB H C(%_i) C(%_proxy) C(%_dlldata) ;
+
+
+# MIDL does not always generate '%_proxy.c' and '%_dlldata.c'. This behavior
+# depends on contents of the source IDL file. Calling TOUCH_FILE below ensures
+# that both files will be created so bjam will not try to recreate them
+# constantly.
+TOUCH_FILE = [ common.file-touch-command ] ;
+
+actions compile.idl
+{
+ midl /nologo @"@($(<[1]:W).rsp:E=$(nl)"$(>:W)" $(nl)-D$(DEFINES) $(nl)"-I$(INCLUDES)" $(nl)-U$(UNDEFS) $(nl)$(MIDLFLAGS) $(nl)/tlb "$(<[1]:W)" $(nl)/h "$(<[2]:W)" $(nl)/iid "$(<[3]:W)" $(nl)/proxy "$(<[4]:W)" $(nl)/dlldata "$(<[5]:W)")"
+ $(TOUCH_FILE) "$(<[4]:W)"
+ $(TOUCH_FILE) "$(<[5]:W)"
+}
diff --git a/tools/build/v2/tools/mipspro.jam b/tools/build/v2/tools/mipspro.jam
new file mode 100644
index 0000000000..417eaefcf7
--- /dev/null
+++ b/tools/build/v2/tools/mipspro.jam
@@ -0,0 +1,145 @@
+# Copyright Noel Belcourt 2007.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import property ;
+import generators ;
+import os ;
+import toolset : flags ;
+import feature ;
+import fortran ;
+import type ;
+import common ;
+
+feature.extend toolset : mipspro ;
+toolset.inherit mipspro : unix ;
+generators.override mipspro.prebuilt : builtin.lib-generator ;
+generators.override mipspro.searched-lib-generator : searched-lib-generator ;
+
+# Documentation and toolchain description located
+# http://www.sgi.com/products/software/irix/tools/
+
+rule init ( version ? : command * : options * )
+{
+ local condition = [
+ common.check-init-parameters mipspro : version $(version) ] ;
+
+ command = [ common.get-invocation-command mipspro : CC : $(command) ] ;
+
+ common.handle-options mipspro : $(condition) : $(command) : $(options) ;
+
+ command_c = $(command_c[1--2]) $(command[-1]:B=cc) ;
+
+ toolset.flags mipspro CONFIG_C_COMMAND $(condition) : $(command_c) ;
+
+ # fortran support
+ local command = [
+ common.get-invocation-command mipspro : f77 : $(command) : $(install_dir) ] ;
+
+ command_f = $(command_f[1--2]) $(command[-1]:B=f77) ;
+ toolset.flags mipspro CONFIG_F_COMMAND $(condition) : $(command_f) ;
+
+ # set link flags
+ flags mipspro.link FINDLIBS-ST : [
+ feature.get-values <find-static-library> : $(options) ] : unchecked ;
+
+ flags mipspro.link FINDLIBS-SA : [
+ feature.get-values <find-shared-library> : $(options) ] : unchecked ;
+}
+
+# Declare generators
+generators.register-c-compiler mipspro.compile.c : C : OBJ : <toolset>mipspro ;
+generators.register-c-compiler mipspro.compile.c++ : CPP : OBJ : <toolset>mipspro ;
+generators.register-fortran-compiler mipspro.compile.fortran : FORTRAN : OBJ : <toolset>mipspro ;
+
+cpu-arch-32 =
+ <architecture>/<address-model>
+ <architecture>/<address-model>32 ;
+
+cpu-arch-64 =
+ <architecture>/<address-model>64 ;
+
+flags mipspro.compile OPTIONS $(cpu-arch-32) : -n32 ;
+flags mipspro.compile OPTIONS $(cpu-arch-64) : -64 ;
+
+# Declare flags and actions for compilation
+flags mipspro.compile OPTIONS <debug-symbols>on : -g ;
+# flags mipspro.compile OPTIONS <profiling>on : -xprofile=tcov ;
+flags mipspro.compile OPTIONS <warnings>off : -w ;
+flags mipspro.compile OPTIONS <warnings>on : -ansiW -diag_suppress 1429 ; # suppress long long is nonstandard warning
+flags mipspro.compile OPTIONS <warnings>all : -fullwarn ;
+flags mipspro.compile OPTIONS <optimization>speed : -Ofast ;
+flags mipspro.compile OPTIONS <optimization>space : -O2 ;
+flags mipspro.compile OPTIONS <cflags> : -LANG:std ;
+flags mipspro.compile.c++ OPTIONS <inlining>off : -INLINE:none ;
+flags mipspro.compile.c++ OPTIONS <cxxflags> ;
+flags mipspro.compile DEFINES <define> ;
+flags mipspro.compile INCLUDES <include> ;
+
+
+flags mipspro.compile.fortran OPTIONS <fflags> ;
+
+actions compile.c
+{
+ "$(CONFIG_C_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" -FE:template_in_elf_section -ptused $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.fortran
+{
+ "$(CONFIG_F_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+# Declare flags and actions for linking
+flags mipspro.link OPTIONS <debug-symbols>on : -g ;
+# Strip the binary when no debugging is needed
+# flags mipspro.link OPTIONS <debug-symbols>off : -s ;
+# flags mipspro.link OPTIONS <profiling>on : -xprofile=tcov ;
+# flags mipspro.link OPTIONS <threading>multi : -mt ;
+
+flags mipspro.link OPTIONS $(cpu-arch-32) : -n32 ;
+flags mipspro.link OPTIONS $(cpu-arch-64) : -64 ;
+
+flags mipspro.link OPTIONS <optimization>speed : -Ofast ;
+flags mipspro.link OPTIONS <optimization>space : -O2 ;
+flags mipspro.link OPTIONS <linkflags> ;
+flags mipspro.link LINKPATH <library-path> ;
+flags mipspro.link FINDLIBS-ST <find-static-library> ;
+flags mipspro.link FINDLIBS-SA <find-shared-library> ;
+flags mipspro.link FINDLIBS-SA <threading>multi : pthread ;
+flags mipspro.link LIBRARIES <library-file> ;
+flags mipspro.link LINK-RUNTIME <runtime-link>static : static ;
+flags mipspro.link LINK-RUNTIME <runtime-link>shared : dynamic ;
+flags mipspro.link RPATH <dll-path> ;
+
+rule link ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -FE:template_in_elf_section -ptused $(OPTIONS) -L"$(LINKPATH)" -R"$(RPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -Bdynamic -l$(FINDLIBS-SA) -Bstatic -l$(FINDLIBS-ST) -B$(LINK-RUNTIME) -lm
+}
+
+# Slight mods for dlls
+rule link.dll ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -L"$(LINKPATH)" -R"$(RPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -Bdynamic -l$(FINDLIBS-SA) -Bstatic -l$(FINDLIBS-ST) -B$(LINK-RUNTIME)
+}
+
+# Declare action for creating static libraries
+actions piecemeal archive
+{
+ ar -cr "$(<)" "$(>)"
+}
diff --git a/tools/build/v2/tools/mpi.jam b/tools/build/v2/tools/mpi.jam
new file mode 100644
index 0000000000..0fe490becd
--- /dev/null
+++ b/tools/build/v2/tools/mpi.jam
@@ -0,0 +1,583 @@
+# Support for the Message Passing Interface (MPI)
+#
+# (C) Copyright 2005, 2006 Trustees of Indiana University
+# (C) Copyright 2005 Douglas Gregor
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
+#
+# Authors: Douglas Gregor
+# Andrew Lumsdaine
+#
+# ==== MPI Configuration ====
+#
+# For many users, MPI support can be enabled simply by adding the following
+# line to your user-config.jam file:
+#
+# using mpi ;
+#
+# This should auto-detect MPI settings based on the MPI wrapper compiler in
+# your path, e.g., "mpic++". If the wrapper compiler is not in your path, or
+# has a different name, you can pass the name of the wrapper compiler as the
+# first argument to the mpi module:
+#
+# using mpi : /opt/mpich2-1.0.4/bin/mpiCC ;
+#
+# If your MPI implementation does not have a wrapper compiler, or the MPI
+# auto-detection code does not work with your MPI's wrapper compiler,
+# you can pass MPI-related options explicitly via the second parameter to the
+# mpi module:
+#
+# using mpi : : <find-shared-library>lammpio <find-shared-library>lammpi++
+# <find-shared-library>mpi <find-shared-library>lam
+# <find-shared-library>dl ;
+#
+# To see the results of MPI auto-detection, pass "--debug-configuration" on
+# the bjam command line.
+#
+# The (optional) fourth argument configures Boost.MPI for running
+# regression tests. These parameters specify the executable used to
+# launch jobs (default: "mpirun") followed by any necessary arguments
+# to this to run tests and tell the program to expect the number of
+# processors to follow (default: "-np"). With the default parameters,
+# for instance, the test harness will execute, e.g.,
+#
+# mpirun -np 4 all_gather_test
+#
+# ==== Linking Against the MPI Libraries ===
+#
+# To link against the MPI libraries, import the "mpi" module and add the
+# following requirement to your target:
+#
+# <library>/mpi//mpi
+#
+# Since MPI support is not always available, you should check
+# "mpi.configured" before trying to link against the MPI libraries.
+
+import "class" : new ;
+import common ;
+import feature : feature ;
+import generators ;
+import os ;
+import project ;
+import property ;
+import testing ;
+import toolset ;
+import type ;
+import path ;
+
+# Make this module a project
+project.initialize $(__name__) ;
+project mpi ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+# Assuming the first part of the command line is the given prefix
+# followed by some non-empty value, remove the first argument. Returns
+# either nothing (if there was no prefix or no value) or a pair
+#
+# <name>value rest-of-cmdline
+#
+# This is a subroutine of cmdline_to_features
+rule add_feature ( prefix name cmdline )
+{
+ local match = [ MATCH "^$(prefix)([^\" ]+|\"[^\"]+\") *(.*)$" : $(cmdline) ] ;
+
+ # If there was no value associated with the prefix, abort
+ if ! $(match) {
+ return ;
+ }
+
+ local value = $(match[1]) ;
+
+ if [ MATCH " +" : $(value) ] {
+ value = "\"$(value)\"" ;
+ }
+
+ return "<$(name)>$(value)" $(match[2]) ;
+}
+
+# Strip any end-of-line characters off the given string and return the
+# result.
+rule strip-eol ( string )
+{
+ local match = [ MATCH "^(([A-Za-z0-9~`\.!@#$%^&*()_+={};:'\",.<>/?\\| -]|[|])*).*$" : $(string) ] ;
+
+ if $(match)
+ {
+ return $(match[1]) ;
+ }
+ else
+ {
+ return $(string) ;
+ }
+}
+
+# Split a command-line into a set of features. Certain kinds of
+# compiler flags are recognized (e.g., -I, -D, -L, -l) and replaced
+# with their Boost.Build equivalents (e.g., <include>, <define>,
+# <library-path>, <find-library>). All other arguments are introduced
+# using the features in the unknown-features parameter, because we
+# don't know how to deal with them. For instance, if your compile and
+# correct. The incoming command line should be a string starting with
+# an executable (e.g., g++ -I/include/path") and may contain any
+# number of command-line arguments thereafter. The result is a list of
+# features corresponding to the given command line, ignoring the
+# executable.
+rule cmdline_to_features ( cmdline : unknown-features ? )
+{
+ local executable ;
+ local features ;
+ local otherflags ;
+ local result ;
+
+ unknown-features ?= <cxxflags> <linkflags> ;
+
+ # Pull the executable out of the command line. At this point, the
+ # executable is just thrown away.
+ local match = [ MATCH "^([^\" ]+|\"[^\"]+\") *(.*)$" : $(cmdline) ] ;
+ executable = $(match[1]) ;
+ cmdline = $(match[2]) ;
+
+ # List the prefix/feature pairs that we will be able to transform.
+ # Every kind of parameter not mentioned here will be placed in both
+ # cxxflags and linkflags, because we don't know where they should go.
+ local feature_kinds-D = "define" ;
+ local feature_kinds-I = "include" ;
+ local feature_kinds-L = "library-path" ;
+ local feature_kinds-l = "find-shared-library" ;
+
+ while $(cmdline) {
+
+ # Check for one of the feature prefixes we know about. If we
+ # find one (and the associated value is nonempty), convert it
+ # into a feature.
+ local match = [ MATCH "^(-.)(.*)" : $(cmdline) ] ;
+ local matched ;
+ if $(match) && $(match[2]) {
+ local prefix = $(match[1]) ;
+ if $(feature_kinds$(prefix)) {
+ local name = $(feature_kinds$(prefix)) ;
+ local add = [ add_feature $(prefix) $(name) $(cmdline) ] ;
+
+ if $(add) {
+
+ if $(add[1]) = <find-shared-library>pthread
+ {
+ # Uhm. It's not really nice that this MPI implementation
+ # uses -lpthread as opposed to -pthread. We do want to
+ # set <threading>multi, instead of -lpthread.
+ result += "<threading>multi" ;
+ MPI_EXTRA_REQUIREMENTS += "<threading>multi" ;
+ }
+ else
+ {
+ result += $(add[1]) ;
+ }
+
+ cmdline = $(add[2]) ;
+ matched = yes ;
+ }
+ }
+ }
+
+ # If we haven't matched a feature prefix, just grab the command-line
+ # argument itself. If we can map this argument to a feature
+ # (e.g., -pthread -> <threading>multi), then do so; otherwise,
+ # and add it to the list of "other" flags that we don't
+ # understand.
+ if ! $(matched) {
+ match = [ MATCH "^([^\" ]+|\"[^\"]+\") *(.*)$" : $(cmdline) ] ;
+ local value = $(match[1]) ;
+ cmdline = $(match[2]) ;
+
+ # Check for multithreading support
+ if $(value) = "-pthread" || $(value) = "-pthreads"
+ {
+ result += "<threading>multi" ;
+
+ # DPG: This is a hack intended to work around a BBv2 bug where
+ # requirements propagated from libraries are not checked for
+ # conflicts when BBv2 determines which "common" properties to
+ # apply to a target. In our case, the <threading>single property
+ # gets propagated from the common properties to Boost.MPI
+ # targets, even though <threading>multi is in the usage
+ # requirements of <library>/mpi//mpi.
+ MPI_EXTRA_REQUIREMENTS += "<threading>multi" ;
+ }
+ else if [ MATCH "(.*[a-zA-Z0-9<>?-].*)" : $(value) ] {
+ otherflags += $(value) ;
+ }
+ }
+ }
+
+ # If there are other flags that we don't understand, add them to the
+ # result as both <cxxflags> and <linkflags>
+ if $(otherflags) {
+ for unknown in $(unknown-features)
+ {
+ result += "$(unknown)$(otherflags:J= )" ;
+ }
+ }
+
+ return $(result) ;
+}
+
+# Determine if it is safe to execute the given shell command by trying
+# to execute it and determining whether the exit code is zero or
+# not. Returns true for an exit code of zero, false otherwise.
+local rule safe-shell-command ( cmdline )
+{
+ local result = [ SHELL "$(cmdline) > /dev/null 2>/dev/null; if [ "$?" -eq "0" ]; then echo SSCOK; fi" ] ;
+ return [ MATCH ".*(SSCOK).*" : $(result) ] ;
+}
+
+# Initialize the MPI module.
+rule init ( mpicxx ? : options * : mpirun-with-options * )
+{
+ if ! $(options) && $(.debug-configuration)
+ {
+ ECHO "===============MPI Auto-configuration===============" ;
+ }
+
+ if ! $(mpicxx) && [ os.on-windows ]
+ {
+ # Try to auto-configure to the Microsoft Compute Cluster Pack
+ local cluster_pack_path_native = "C:\\Program Files\\Microsoft Compute Cluster Pack" ;
+ local cluster_pack_path = [ path.make $(cluster_pack_path_native) ] ;
+ if [ GLOB $(cluster_pack_path_native)\\Include : mpi.h ]
+ {
+ if $(.debug-configuration)
+ {
+ ECHO "Found Microsoft Compute Cluster Pack: $(cluster_pack_path_native)" ;
+ }
+
+ # Pick up either the 32-bit or 64-bit library, depending on which address
+ # model the user has selected. Default to 32-bit.
+ options = <include>$(cluster_pack_path)/Include
+ <address-model>64:<library-path>$(cluster_pack_path)/Lib/amd64
+ <library-path>$(cluster_pack_path)/Lib/i386
+ <find-static-library>msmpi
+ <toolset>msvc:<define>_SECURE_SCL=0
+ ;
+
+ # Setup the "mpirun" equivalent (mpiexec)
+ .mpirun = "\"$(cluster_pack_path_native)\\Bin\\mpiexec.exe"\" ;
+ .mpirun_flags = -n ;
+ }
+ else if $(.debug-configuration)
+ {
+ ECHO "Did not find Microsoft Compute Cluster Pack in $(cluster_pack_path_native)." ;
+ }
+ }
+
+ if ! $(options)
+ {
+ # Try to auto-detect options based on the wrapper compiler
+ local command = [ common.get-invocation-command mpi : mpic++ : $(mpicxx) ] ;
+
+ if ! $(mpicxx) && ! $(command)
+ {
+ # Try "mpiCC", which is used by MPICH
+ command = [ common.get-invocation-command mpi : mpiCC ] ;
+ }
+
+ if ! $(mpicxx) && ! $(command)
+ {
+ # Try "mpicxx", which is used by OpenMPI and MPICH2
+ command = [ common.get-invocation-command mpi : mpicxx ] ;
+ }
+
+ local result ;
+ local compile_flags ;
+ local link_flags ;
+
+ if ! $(command)
+ {
+ # Do nothing: we'll complain later
+ }
+ # OpenMPI and newer versions of LAM-MPI have -showme:compile and
+ # -showme:link.
+ else if [ safe-shell-command "$(command) -showme:compile" ] &&
+ [ safe-shell-command "$(command) -showme:link" ]
+ {
+ if $(.debug-configuration)
+ {
+ ECHO "Found recent LAM-MPI or Open MPI wrapper compiler: $(command)" ;
+ }
+
+ compile_flags = [ SHELL "$(command) -showme:compile" ] ;
+ link_flags = [ SHELL "$(command) -showme:link" ] ;
+
+ # Prepend COMPILER as the executable name, to match the format of
+ # other compilation commands.
+ compile_flags = "COMPILER $(compile_flags)" ;
+ link_flags = "COMPILER $(link_flags)" ;
+ }
+ # Look for LAM-MPI's -showme
+ else if [ safe-shell-command "$(command) -showme" ]
+ {
+ if $(.debug-configuration)
+ {
+ ECHO "Found older LAM-MPI wrapper compiler: $(command)" ;
+ }
+
+ result = [ SHELL "$(command) -showme" ] ;
+ }
+ # Look for MPICH
+ else if [ safe-shell-command "$(command) -show" ]
+ {
+ if $(.debug-configuration)
+ {
+ ECHO "Found MPICH wrapper compiler: $(command)" ;
+ }
+ compile_flags = [ SHELL "$(command) -compile_info" ] ;
+ link_flags = [ SHELL "$(command) -link_info" ] ;
+ }
+ # Sun HPC and Ibm POE
+ else if [ SHELL "$(command) -v 2>/dev/null" ]
+ {
+ compile_flags = [ SHELL "$(command) -c -v -xtarget=native64 2>/dev/null" ] ;
+
+ local back = [ MATCH "--------------------(.*)" : $(compile_flags) ] ;
+ if $(back)
+ {
+ # Sun HPC
+ if $(.debug-configuration)
+ {
+ ECHO "Found Sun MPI wrapper compiler: $(command)" ;
+ }
+
+ compile_flags = [ MATCH "(.*)--------------------" : $(back) ] ;
+ compile_flags = [ MATCH "(.*)-v" : $(compile_flags) ] ;
+ link_flags = [ SHELL "$(command) -v -xtarget=native64 2>/dev/null" ] ;
+ link_flags = [ MATCH "--------------------(.*)" : $(link_flags) ] ;
+ link_flags = [ MATCH "(.*)--------------------" : $(link_flags) ] ;
+
+ # strip out -v from compile options
+ local front = [ MATCH "(.*)-v" : $(link_flags) ] ;
+ local back = [ MATCH "-v(.*)" : $(link_flags) ] ;
+ link_flags = "$(front) $(back)" ;
+ front = [ MATCH "(.*)-xtarget=native64" : $(link_flags) ] ;
+ back = [ MATCH "-xtarget=native64(.*)" : $(link_flags) ] ;
+ link_flags = "$(front) $(back)" ;
+ }
+ else
+ {
+ # Ibm POE
+ if $(.debug-configuration)
+ {
+ ECHO "Found IBM MPI wrapper compiler: $(command)" ;
+ }
+
+ #
+ compile_flags = [ SHELL "$(command) -c -v 2>/dev/null" ] ;
+ compile_flags = [ MATCH "(.*)exec: export.*" : $(compile_flags) ] ;
+ local front = [ MATCH "(.*)-v" : $(compile_flags) ] ;
+ local back = [ MATCH "-v(.*)" : $(compile_flags) ] ;
+ compile_flags = "$(front) $(back)" ;
+ front = [ MATCH "(.*)-c" : $(compile_flags) ] ;
+ back = [ MATCH "-c(.*)" : $(compile_flags) ] ;
+ compile_flags = "$(front) $(back)" ;
+ link_flags = $(compile_flags) ;
+
+ # get location of mpif.h from mpxlf
+ local f_flags = [ SHELL "mpxlf -v 2>/dev/null" ] ;
+ f_flags = [ MATCH "(.*)exec: export.*" : $(f_flags) ] ;
+ front = [ MATCH "(.*)-v" : $(f_flags) ] ;
+ back = [ MATCH "-v(.*)" : $(f_flags) ] ;
+ f_flags = "$(front) $(back)" ;
+ f_flags = [ MATCH "xlf_r(.*)" : $(f_flags) ] ;
+ f_flags = [ MATCH "-F:mpxlf_r(.*)" : $(f_flags) ] ;
+ compile_flags = [ strip-eol $(compile_flags) ] ;
+ compile_flags = "$(compile_flags) $(f_flags)" ;
+ }
+ }
+
+ if $(result) || $(compile_flags) && $(link_flags)
+ {
+ if $(result)
+ {
+ result = [ strip-eol $(result) ] ;
+ options = [ cmdline_to_features $(result) ] ;
+ }
+ else
+ {
+ compile_flags = [ strip-eol $(compile_flags) ] ;
+ link_flags = [ strip-eol $(link_flags) ] ;
+
+ # Separately process compilation and link features, then combine
+ # them at the end.
+ local compile_features = [ cmdline_to_features $(compile_flags)
+ : "<cxxflags>" ] ;
+ local link_features = [ cmdline_to_features $(link_flags)
+ : "<linkflags>" ] ;
+ options = $(compile_features) $(link_features) ;
+ }
+
+ # If requested, display MPI configuration information.
+ if $(.debug-configuration)
+ {
+ if $(result)
+ {
+ ECHO " Wrapper compiler command line: $(result)" ;
+ }
+ else
+ {
+ local match = [ MATCH "^([^\" ]+|\"[^\"]+\") *(.*)$"
+ : $(compile_flags) ] ;
+ ECHO "MPI compilation flags: $(match[2])" ;
+ local match = [ MATCH "^([^\" ]+|\"[^\"]+\") *(.*)$"
+ : $(link_flags) ] ;
+ ECHO "MPI link flags: $(match[2])" ;
+ }
+ }
+ }
+ else
+ {
+ if $(command)
+ {
+ ECHO "MPI auto-detection failed: unknown wrapper compiler $(command)" ;
+ ECHO "Please report this error to the Boost mailing list: http://www.boost.org" ;
+ }
+ else if $(mpicxx)
+ {
+ ECHO "MPI auto-detection failed: unable to find wrapper compiler $(mpicxx)" ;
+ }
+ else
+ {
+ ECHO "MPI auto-detection failed: unable to find wrapper compiler `mpic++' or `mpiCC'" ;
+ }
+ ECHO "You will need to manually configure MPI support." ;
+ }
+
+ }
+
+ # Find mpirun (or its equivalent) and its flags
+ if ! $(.mpirun)
+ {
+ .mpirun =
+ [ common.get-invocation-command mpi : mpirun : $(mpirun-with-options[1]) ] ;
+ .mpirun_flags = $(mpirun-with-options[2-]) ;
+ .mpirun_flags ?= -np ;
+ }
+
+ if $(.debug-configuration)
+ {
+ if $(options)
+ {
+ echo "MPI build features: " ;
+ ECHO $(options) ;
+ }
+
+ if $(.mpirun)
+ {
+ echo "MPI launcher: $(.mpirun) $(.mpirun_flags)" ;
+ }
+
+ ECHO "====================================================" ;
+ }
+
+ if $(options)
+ {
+ .configured = true ;
+
+ # Set up the "mpi" alias
+ alias mpi : : : : $(options) ;
+ }
+}
+
+# States whether MPI has bee configured
+rule configured ( )
+{
+ return $(.configured) ;
+}
+
+# Returs the "extra" requirements needed to build MPI. These requirements are
+# part of the /mpi//mpi library target, but they need to be added to anything
+# that uses MPI directly to work around bugs in BBv2's propagation of
+# requirements.
+rule extra-requirements ( )
+{
+ return $(MPI_EXTRA_REQUIREMENTS) ;
+}
+
+# Support for testing; borrowed from Python
+type.register RUN_MPI_OUTPUT ;
+type.register RUN_MPI : : TEST ;
+
+class mpi-test-generator : generator
+{
+ import property-set ;
+
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ self.composing = true ;
+ }
+
+ rule run ( project name ? : property-set : sources * : multiple ? )
+ {
+ # Generate an executable from the sources. This is the executable we will run.
+ local executable =
+ [ generators.construct $(project) $(name) : EXE : $(property-set) : $(sources) ] ;
+
+ result =
+ [ construct-result $(executable[2-]) : $(project) $(name)-run : $(property-set) ] ;
+ }
+}
+
+# Use mpi-test-generator to generate MPI tests from sources
+generators.register
+ [ new mpi-test-generator mpi.capture-output : : RUN_MPI_OUTPUT ] ;
+
+generators.register-standard testing.expect-success
+ : RUN_MPI_OUTPUT : RUN_MPI ;
+
+# The number of processes to spawn when executing an MPI test.
+feature mpi:processes : : free incidental ;
+
+# The flag settings on testing.capture-output do not
+# apply to mpi.capture output at the moment.
+# Redo this explicitly.
+toolset.flags mpi.capture-output ARGS <testing.arg> ;
+rule capture-output ( target : sources * : properties * )
+{
+ # Use the standard capture-output rule to run the tests
+ testing.capture-output $(target) : $(sources[1]) : $(properties) ;
+
+ # Determine the number of processes we should run on.
+ local num_processes = [ property.select <mpi:processes> : $(properties) ] ;
+ num_processes = $(num_processes:G=) ;
+
+ # serialize the MPI tests to avoid overloading systems
+ JAM_SEMAPHORE on $(target) = <s>mpi-run-semaphore ;
+
+ # We launch MPI processes using the "mpirun" equivalent specified by the user.
+ LAUNCHER on $(target) =
+ [ on $(target) return $(.mpirun) $(.mpirun_flags) $(num_processes) ] ;
+}
+
+# Creates a set of test cases to be run through the MPI launcher. The name, sources,
+# and requirements are the same as for any other test generator. However, schedule is
+# a list of numbers, which indicates how many processes each test run will use. For
+# example, passing 1 2 7 will run the test with 1 process, then 2 processes, then 7
+# 7 processes. The name provided is just the base name: the actual tests will be
+# the name followed by a hypen, then the number of processes.
+rule mpi-test ( name : sources * : requirements * : schedule * )
+{
+ sources ?= $(name).cpp ;
+ schedule ?= 1 2 3 4 7 8 13 17 ;
+
+ local result ;
+ for processes in $(schedule)
+ {
+ result += [ testing.make-test
+ run-mpi : $(sources) /boost/mpi//boost_mpi
+ : $(requirements) <toolset>msvc:<link>static <mpi:processes>$(processes) : $(name)-$(processes) ] ;
+ }
+ return $(result) ;
+}
diff --git a/tools/build/v2/tools/msvc-config.jam b/tools/build/v2/tools/msvc-config.jam
new file mode 100644
index 0000000000..6c71e3b002
--- /dev/null
+++ b/tools/build/v2/tools/msvc-config.jam
@@ -0,0 +1,12 @@
+#~ Copyright 2005 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Automatic configuration for VisualStudio toolset. To use, just import this module.
+
+import toolset : using ;
+
+ECHO "warning: msvc-config.jam is deprecated. Use 'using msvc : all ;' instead." ;
+
+using msvc : all ;
+
diff --git a/tools/build/v2/tools/msvc.jam b/tools/build/v2/tools/msvc.jam
new file mode 100644
index 0000000000..e33a66d22b
--- /dev/null
+++ b/tools/build/v2/tools/msvc.jam
@@ -0,0 +1,1392 @@
+# Copyright (c) 2003 David Abrahams.
+# Copyright (c) 2005 Vladimir Prus.
+# Copyright (c) 2005 Alexey Pakhunov.
+# Copyright (c) 2006 Bojan Resnik.
+# Copyright (c) 2006 Ilya Sokolov.
+# Copyright (c) 2007 Rene Rivera
+# Copyright (c) 2008 Jurko Gospodnetic
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+################################################################################
+#
+# MSVC Boost Build toolset module.
+# --------------------------------
+#
+# All toolset versions need to have their location either auto-detected or
+# explicitly specified except for the special 'default' version that expects the
+# environment to find the needed tools or report an error.
+#
+################################################################################
+
+import "class" : new ;
+import common ;
+import errors ;
+import feature ;
+import generators ;
+import mc ;
+import midl ;
+import os ;
+import path ;
+import pch ;
+import property ;
+import rc ;
+import toolset ;
+import type ;
+
+
+type.register MANIFEST : manifest ;
+feature.feature embed-manifest : on off : incidental propagated ;
+
+type.register PDB : pdb ;
+
+################################################################################
+#
+# Public rules.
+#
+################################################################################
+
+# Initialize a specific toolset version configuration. As the result, path to
+# compiler and, possible, program names are set up, and will be used when that
+# version of compiler is requested. For example, you might have:
+#
+# using msvc : 6.5 : cl.exe ;
+# using msvc : 7.0 : Y:/foo/bar/cl.exe ;
+#
+# The version parameter may be ommited:
+#
+# using msvc : : Z:/foo/bar/cl.exe ;
+#
+# The following keywords have special meanings when specified as versions:
+# - all - all detected but not yet used versions will be marked as used
+# with their default options.
+# - default - this is an equivalent to an empty version.
+#
+# Depending on a supplied version, detected configurations and presence 'cl.exe'
+# in the path different results may be achieved. The following table describes
+# the possible scenarios:
+#
+# Nothing "x.y"
+# Passed Nothing "x.y" detected, detected,
+# version detected detected cl.exe in path cl.exe in path
+#
+# default Error Use "x.y" Create "default" Use "x.y"
+# all None Use all None Use all
+# x.y - Use "x.y" - Use "x.y"
+# a.b Error Error Create "a.b" Create "a.b"
+#
+# "x.y" - refers to a detected version;
+# "a.b" - refers to an undetected version.
+#
+# FIXME: Currently the command parameter and the <compiler> property parameter
+# seem to overlap in duties. Remove this duplication. This seems to be related
+# to why someone started preparing to replace init with configure rules.
+#
+rule init (
+ # The msvc version being configured. When omitted the tools invoked when no
+ # explicit version is given will be configured.
+ version ?
+
+ # The command used to invoke the compiler. If not specified:
+ # - if version is given, default location for that version will be
+ # searched
+ #
+ # - if version is not given, default locations for MSVC 9.0, 8.0, 7.1, 7.0
+ # and 6.* will be searched
+ #
+ # - if compiler is not found in the default locations, PATH will be
+ # searched.
+ : command *
+
+ # Options may include:
+ #
+ # All options shared by multiple toolset types as handled by the
+ # common.handle-options() rule, e.g. <cflags>, <compileflags>, <cxxflags>,
+ # <fflags> & <linkflags>.
+ #
+ # <assembler>
+ # <compiler>
+ # <idl-compiler>
+ # <linker>
+ # <mc-compiler>
+ # <resource-compiler>
+ # Exact tool names to be used by this msvc toolset configuration.
+ #
+ # <compiler-filter>
+ # Command through which to pipe the output of running the compiler.
+ # For example to pass the output to STLfilt.
+ #
+ # <setup>
+ # Global setup command to invoke before running any of the msvc tools.
+ # It will be passed additional option parameters depending on the actual
+ # target platform.
+ #
+ # <setup-amd64>
+ # <setup-i386>
+ # <setup-ia64>
+ # Platform specific setup command to invoke before running any of the
+ # msvc tools used when builing a target for a specific platform, e.g.
+ # when building a 32 or 64 bit executable.
+ : options *
+)
+{
+ if $(command)
+ {
+ options += <command>$(command) ;
+ }
+ configure $(version) : $(options) ;
+}
+
+
+# 'configure' is a newer version of 'init'. The parameter 'command' is passed as
+# a part of the 'options' list. See the 'init' rule comment for more detailed
+# information.
+#
+rule configure ( version ? : options * )
+{
+ switch $(version)
+ {
+ case "all" :
+ if $(options)
+ {
+ errors.error "MSVC toolset configuration: options should be"
+ "empty when '$(version)' is specified." ;
+ }
+
+ # Configure (i.e. mark as used) all registered versions.
+ local all-versions = [ $(.versions).all ] ;
+ if ! $(all-versions)
+ {
+ if $(.debug-configuration)
+ {
+ ECHO "notice: [msvc-cfg] Asked to configure all registered"
+ "msvc toolset versions when there are none currently"
+ "registered." ;
+ }
+ }
+ else
+ {
+ for local v in $(all-versions)
+ {
+ # Note that there is no need to skip already configured
+ # versions here as this will request configure-really rule
+ # to configure the version using default options which will
+ # in turn cause it to simply do nothing in case the version
+ # has already been configured.
+ configure-really $(v) ;
+ }
+ }
+
+ case "default" :
+ configure-really : $(options) ;
+
+ case * :
+ configure-really $(version) : $(options) ;
+ }
+}
+
+
+# Sets up flag definitions dependent on the compiler version used.
+# - 'version' is the version of compiler in N.M format.
+# - 'conditions' is the property set to be used as flag conditions.
+# - 'toolset' is the toolset for which flag settings are to be defined.
+# This makes the rule reusable for other msvc-option-compatible compilers.
+#
+rule configure-version-specific ( toolset : version : conditions )
+{
+ toolset.push-checking-for-flags-module unchecked ;
+ # Starting with versions 7.0, the msvc compiler have the /Zc:forScope and
+ # /Zc:wchar_t options that improve C++ standard conformance, but those
+ # options are off by default. If we are sure that the msvc version is at
+ # 7.*, add those options explicitly. We can be sure either if user specified
+ # version 7.* explicitly or if we auto-detected the version ourselves.
+ if ! [ MATCH ^(6\\.) : $(version) ]
+ {
+ toolset.flags $(toolset).compile CFLAGS $(conditions) : /Zc:forScope /Zc:wchar_t ;
+ toolset.flags $(toolset).compile.c++ C++FLAGS $(conditions) : /wd4675 ;
+
+ # Explicitly disable the 'function is deprecated' warning. Some msvc
+ # versions have a bug, causing them to emit the deprecation warning even
+ # with /W0.
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/<warnings>off : /wd4996 ;
+
+ if [ MATCH ^([78]\\.) : $(version) ]
+ {
+ # 64-bit compatibility warning deprecated since 9.0, see
+ # http://msdn.microsoft.com/en-us/library/yt4xw8fh.aspx
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/<warnings>all : /Wp64 ;
+ }
+ }
+
+ #
+ # Processor-specific optimization.
+ #
+
+ if [ MATCH ^([67]) : $(version) ]
+ {
+ # 8.0 deprecates some of the options.
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>speed $(conditions)/<optimization>space : /Ogiy /Gs ;
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>speed : /Ot ;
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>space : /Os ;
+
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set> : /GB ;
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>i386 : /G3 ;
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>i486 : /G4 ;
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g5) : /G5 ;
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g6) : /G6 ;
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g7) : /G7 ;
+
+ # Improve floating-point accuracy. Otherwise, some of C++ Boost's "math"
+ # tests will fail.
+ toolset.flags $(toolset).compile CFLAGS $(conditions) : /Op ;
+
+ # 7.1 and below have single-threaded static RTL.
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>off/<runtime-link>static/<threading>single : /ML ;
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>on/<runtime-link>static/<threading>single : /MLd ;
+ }
+ else
+ {
+ # 8.0 and above adds some more options.
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set> : /favor:blend ;
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set>$(.cpu-type-em64t) : /favor:EM64T ;
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set>$(.cpu-type-amd64) : /favor:AMD64 ;
+
+ # 8.0 and above only has multi-threaded static RTL.
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>off/<runtime-link>static/<threading>single : /MT ;
+ toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>on/<runtime-link>static/<threading>single : /MTd ;
+
+ # Specify target machine type so the linker will not need to guess.
+ toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-amd64) : /MACHINE:X64 ;
+ toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-i386) : /MACHINE:X86 ;
+ toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-ia64) : /MACHINE:IA64 ;
+
+ # Make sure that manifest will be generated even if there is no
+ # dependencies to put there.
+ toolset.flags $(toolset).link LINKFLAGS $(conditions)/<embed-manifest>off : /MANIFEST ;
+ }
+ toolset.pop-checking-for-flags-module ;
+}
+
+
+# Registers this toolset including all of its flags, features & generators. Does
+# nothing on repeated calls.
+#
+rule register-toolset ( )
+{
+ if ! msvc in [ feature.values toolset ]
+ {
+ register-toolset-really ;
+ }
+}
+
+
+# Declare action for creating static libraries. If library exists, remove it
+# before adding files. See
+# http://article.gmane.org/gmane.comp.lib.boost.build/4241 for rationale.
+if [ os.name ] in NT
+{
+ # The 'DEL' command would issue a message to stdout if the file does not
+ # exist, so need a check.
+ actions archive
+ {
+ if exist "$(<[1])" DEL "$(<[1])"
+ $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
+ }
+}
+else
+{
+ actions archive
+ {
+ $(.RM) "$(<[1])"
+ $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
+ }
+}
+
+
+# For the assembler the following options are turned on by default:
+#
+# -Zp4 align structures to 4 bytes
+# -Cp preserve case of user identifiers
+# -Cx preserve case in publics, externs
+#
+actions compile.asm
+{
+ $(.ASM) -c -Zp4 -Cp -Cx -D$(DEFINES) $(ASMFLAGS) $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)"
+}
+
+
+rule compile.c ( targets + : sources * : properties * )
+{
+ C++FLAGS on $(targets[1]) = ;
+ get-rspline $(targets) : -TC ;
+ compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
+}
+
+
+rule compile.c.preprocess ( targets + : sources * : properties * )
+{
+ C++FLAGS on $(targets[1]) = ;
+ get-rspline $(targets) : -TC ;
+ preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
+}
+
+
+rule compile.c.pch ( targets + : sources * : properties * )
+{
+ C++FLAGS on $(targets[1]) = ;
+ get-rspline $(targets[1]) : -TC ;
+ get-rspline $(targets[2]) : -TC ;
+ local pch-source = [ on $(<) return $(PCH_SOURCE) ] ;
+ if $(pch-source)
+ {
+ DEPENDS $(<) : $(pch-source) ;
+ compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ;
+ }
+ else
+ {
+ compile-c-c++-pch $(targets) : $(sources) ;
+ }
+}
+
+toolset.flags msvc YLOPTION : "-Yl" ;
+
+# Action for running the C/C++ compiler without using precompiled headers.
+#
+# WARNING: Synchronize any changes this in action with intel-win
+#
+# Notes regarding PDB generation, for when we use <debug-symbols>on/<debug-store>database
+#
+# 1. PDB_CFLAG is only set for <debug-symbols>on/<debug-store>database, ensuring that the /Fd flag is dropped if PDB_CFLAG is empty
+#
+# 2. When compiling executables's source files, PDB_NAME is set on a per-source file basis by rule compile-c-c++.
+# The linker will pull these into the executable's PDB
+#
+# 3. When compiling library's source files, PDB_NAME is updated to <libname>.pdb for each source file by rule archive,
+# as in this case the compiler must be used to create a single PDB for our library.
+#
+actions compile-c-c++ bind PDB_NAME
+{
+ $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER)
+}
+
+actions preprocess-c-c++ bind PDB_NAME
+{
+ $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)"
+}
+
+rule compile-c-c++ ( targets + : sources * )
+{
+ DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ;
+ DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ;
+ PDB_NAME on $(<) = $(<:S=.pdb) ;
+}
+
+rule preprocess-c-c++ ( targets + : sources * )
+{
+ DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ;
+ DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ;
+ PDB_NAME on $(<) = $(<:S=.pdb) ;
+}
+
+# Action for running the C/C++ compiler using precompiled headers. In addition
+# to whatever else it needs to compile, this action also adds a temporary source
+# .cpp file used to compile the precompiled headers themselves.
+#
+# The global .escaped-double-quote variable is used to avoid messing up Emacs
+# syntax highlighting in the messy N-quoted code below.
+actions compile-c-c++-pch
+{
+ $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" "@($(<[1]:W).cpp:E=#include $(.escaped-double-quote)$(>[1]:D=)$(.escaped-double-quote)$(.nl))" $(.CC.FILTER)
+}
+
+
+# Action for running the C/C++ compiler using precompiled headers. An already
+# built source file for compiling the precompiled headers is expected to be
+# given as one of the source parameters.
+actions compile-c-c++-pch-s
+{
+ $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" $(.CC.FILTER)
+}
+
+
+rule compile.c++ ( targets + : sources * : properties * )
+{
+ get-rspline $(targets) : -TP ;
+ compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
+}
+
+rule compile.c++.preprocess ( targets + : sources * : properties * )
+{
+ get-rspline $(targets) : -TP ;
+ preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
+}
+
+
+rule compile.c++.pch ( targets + : sources * : properties * )
+{
+ get-rspline $(targets[1]) : -TP ;
+ get-rspline $(targets[2]) : -TP ;
+ local pch-source = [ on $(<) return $(PCH_SOURCE) ] ;
+ if $(pch-source)
+ {
+ DEPENDS $(<) : $(pch-source) ;
+ compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ;
+ }
+ else
+ {
+ compile-c-c++-pch $(targets) : $(sources) ;
+ }
+}
+
+
+# See midl.jam for details.
+#
+actions compile.idl
+{
+ $(.IDL) /nologo @"@($(<[1]:W).rsp:E=$(.nl)"$(>:W)" $(.nl)-D$(DEFINES) $(.nl)"-I$(INCLUDES:W)" $(.nl)-U$(UNDEFS) $(.nl)$(MIDLFLAGS) $(.nl)/tlb "$(<[1]:W)" $(.nl)/h "$(<[2]:W)" $(.nl)/iid "$(<[3]:W)" $(.nl)/proxy "$(<[4]:W)" $(.nl)/dlldata "$(<[5]:W)")"
+ $(.TOUCH_FILE) "$(<[4]:W)"
+ $(.TOUCH_FILE) "$(<[5]:W)"
+}
+
+
+actions compile.mc
+{
+ $(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)"
+}
+
+
+actions compile.rc
+{
+ $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)"
+}
+
+
+rule link ( targets + : sources * : properties * )
+{
+ if <embed-manifest>on in $(properties)
+ {
+ msvc.manifest $(targets) : $(sources) : $(properties) ;
+ }
+}
+
+rule link.dll ( targets + : sources * : properties * )
+{
+ DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
+ if <embed-manifest>on in $(properties)
+ {
+ msvc.manifest.dll $(targets) : $(sources) : $(properties) ;
+ }
+}
+
+# Incremental linking a DLL causes no end of problems: if the actual exports do
+# not change, the import .lib file is never updated. Therefore, the .lib is
+# always out-of-date and gets rebuilt every time. I am not sure that incremental
+# linking is such a great idea in general, but in this case I am sure we do not
+# want it.
+
+# Windows manifest is a new way to specify dependencies on managed DotNet
+# assemblies and Windows native DLLs. The manifests are embedded as resources
+# and are useful in any PE target (both DLL and EXE).
+
+if [ os.name ] in NT
+{
+ actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
+ {
+ $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
+ if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%
+ }
+
+ actions manifest
+ {
+ if exist "$(<[1]).manifest" (
+ $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1"
+ )
+ }
+
+ actions link.dll bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
+ {
+ $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
+ if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%
+ }
+
+ actions manifest.dll
+ {
+ if exist "$(<[1]).manifest" (
+ $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2"
+ )
+ }
+}
+else
+{
+ actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
+ {
+ $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
+ }
+
+ actions manifest
+ {
+ if test -e "$(<[1]).manifest"; then
+ $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);1"
+ fi
+ }
+
+ actions link.dll bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
+ {
+ $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
+ }
+
+ actions manifest.dll
+ {
+ if test -e "$(<[1]).manifest"; then
+ $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);2"
+ fi
+ }
+}
+
+# this rule sets up the pdb file that will be used when generating static
+# libraries and the debug-store option is database, so that the compiler
+# puts all debug info into a single .pdb file named after the library
+#
+# Poking at source targets this way is probably not clean, but it's the
+# easiest approach.
+rule archive ( targets + : sources * : properties * )
+{
+ PDB_NAME on $(>) = $(<:S=.pdb) ;
+}
+
+################################################################################
+#
+# Classes.
+#
+################################################################################
+
+class msvc-pch-generator : pch-generator
+{
+ import property-set ;
+
+ rule run-pch ( project name ? : property-set : sources * )
+ {
+ # Searching for the header and source file in the sources.
+ local pch-header ;
+ local pch-source ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] H ]
+ {
+ pch-header = $(s) ;
+ }
+ else if
+ [ type.is-derived [ $(s).type ] CPP ] ||
+ [ type.is-derived [ $(s).type ] C ]
+ {
+ pch-source = $(s) ;
+ }
+ }
+
+ if ! $(pch-header)
+ {
+ errors.user-error "can not build pch without pch-header" ;
+ }
+
+ # If we do not have the PCH source - that is fine. We will just create a
+ # temporary .cpp file in the action.
+
+ local generated = [ generator.run $(project) $(name)
+ : [ property-set.create
+ # Passing of <pch-source> is a dirty trick, needed because
+ # non-composing generators with multiple inputs are subtly
+ # broken. For more detailed information see:
+ # https://zigzag.cs.msu.su:7813/boost.build/ticket/111
+ <pch-source>$(pch-source)
+ [ $(property-set).raw ] ]
+ : $(pch-header) ] ;
+
+ local pch-file ;
+ for local g in $(generated)
+ {
+ if [ type.is-derived [ $(g).type ] PCH ]
+ {
+ pch-file = $(g) ;
+ }
+ }
+
+ return [ property-set.create <pch-header>$(pch-header)
+ <pch-file>$(pch-file) ] $(generated) ;
+ }
+}
+
+
+################################################################################
+#
+# Local rules.
+#
+################################################################################
+
+# Detects versions listed as '.known-versions' by checking registry information,
+# environment variables & default paths. Supports both native Windows and
+# Cygwin.
+#
+local rule auto-detect-toolset-versions ( )
+{
+ if [ os.name ] in NT CYGWIN
+ {
+ # Get installation paths from the registry.
+ for local i in $(.known-versions)
+ {
+ if $(.version-$(i)-reg)
+ {
+ local vc-path ;
+ for local x in "" "Wow6432Node\\"
+ {
+ vc-path += [ W32_GETREG
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\"$(x)"\\Microsoft\\"$(.version-$(i)-reg)
+ : "ProductDir" ] ;
+ }
+
+ if $(vc-path)
+ {
+ vc-path = [ path.join [ path.make-NT $(vc-path[1]) ] "bin" ] ;
+ register-configuration $(i) : [ path.native $(vc-path[1]) ] ;
+ }
+ }
+ }
+ }
+
+ # Check environment and default installation paths.
+ for local i in $(.known-versions)
+ {
+ if ! $(i) in [ $(.versions).all ]
+ {
+ register-configuration $(i) : [ default-path $(i) ] ;
+ }
+ }
+}
+
+
+# Worker rule for toolset version configuration. Takes an explicit version id or
+# nothing in case it should configure the default toolset version (the first
+# registered one or a new 'default' one in case no toolset versions have been
+# registered yet).
+#
+local rule configure-really ( version ? : options * )
+{
+ local v = $(version) ;
+
+ # Decide what the 'default' version is.
+ if ! $(v)
+ {
+ # Take the first registered (i.e. auto-detected) version.
+ version = [ $(.versions).all ] ;
+ version = $(version[1]) ;
+ v = $(version) ;
+
+ # Note: 'version' can still be empty at this point if no versions have
+ # been auto-detected.
+ version ?= "default" ;
+ }
+
+ # Version alias -> real version number.
+ if $(.version-alias-$(version))
+ {
+ version = $(.version-alias-$(version)) ;
+ }
+
+ # Check whether the selected configuration is already in use.
+ if $(version) in [ $(.versions).used ]
+ {
+ # Allow multiple 'toolset.using' calls for the same configuration if the
+ # identical sets of options are used.
+ if $(options) && ( $(options) != [ $(.versions).get $(version) : options ] )
+ {
+ errors.error "MSVC toolset configuration: Toolset version"
+ "'$(version)' already configured." ;
+ }
+ }
+ else
+ {
+ # Register a new configuration.
+ $(.versions).register $(version) ;
+
+ # Add user-supplied to auto-detected options.
+ options = [ $(.versions).get $(version) : options ] $(options) ;
+
+ # Mark the configuration as 'used'.
+ $(.versions).use $(version) ;
+
+ # Generate conditions and save them.
+ local conditions = [ common.check-init-parameters msvc : version $(v) ]
+ ;
+
+ $(.versions).set $(version) : conditions : $(conditions) ;
+
+ local command = [ feature.get-values <command> : $(options) ] ;
+
+ # If version is specified, we try to search first in default paths, and
+ # only then in PATH.
+ command = [ common.get-invocation-command msvc : cl.exe : $(command) :
+ [ default-paths $(version) ] : $(version) ] ;
+
+ common.handle-options msvc : $(conditions) : $(command) : $(options) ;
+
+ if ! $(version)
+ {
+ # Even if version is not explicitly specified, try to detect the
+ # version from the path.
+ # FIXME: We currently detect both Microsoft Visual Studio 9.0 and
+ # 9.0express as 9.0 here.
+ if [ MATCH "(Microsoft Visual Studio 10)" : $(command) ]
+ {
+ version = 10.0 ;
+ }
+ else if [ MATCH "(Microsoft Visual Studio 9)" : $(command) ]
+ {
+ version = 9.0 ;
+ }
+ else if [ MATCH "(Microsoft Visual Studio 8)" : $(command) ]
+ {
+ version = 8.0 ;
+ }
+ else if [ MATCH "(NET 2003[\/\\]VC7)" : $(command) ]
+ {
+ version = 7.1 ;
+ }
+ else if [ MATCH "(Microsoft Visual C\\+\\+ Toolkit 2003)" :
+ $(command) ]
+ {
+ version = 7.1toolkit ;
+ }
+ else if [ MATCH "(.NET[\/\\]VC7)" : $(command) ]
+ {
+ version = 7.0 ;
+ }
+ else
+ {
+ version = 6.0 ;
+ }
+ }
+
+ # Generate and register setup command.
+
+ local below-8.0 = [ MATCH ^([67]\\.) : $(version) ] ;
+
+ local cpu = i386 amd64 ia64 ;
+ if $(below-8.0)
+ {
+ cpu = i386 ;
+ }
+
+ local setup-amd64 ;
+ local setup-i386 ;
+ local setup-ia64 ;
+
+ if $(command)
+ {
+ # TODO: Note that if we specify a non-existant toolset version then
+ # this rule may find and use a corresponding compiler executable
+ # belonging to an incorrect toolset version. For example, if you
+ # have only MSVC 7.1 installed, have its executable on the path and
+ # specify you want Boost Build to use MSVC 9.0, then you want Boost
+ # Build to report an error but this may cause it to silently use the
+ # MSVC 7.1 compiler even though it thinks it is using the msvc-9.0
+ # toolset version.
+ command = [ common.get-absolute-tool-path $(command[-1]) ] ;
+ }
+
+ if $(command)
+ {
+ local parent = [ path.make $(command) ] ;
+ parent = [ path.parent $(parent) ] ;
+ parent = [ path.native $(parent) ] ;
+
+ # Setup will be used if the command name has been specified. If
+ # setup is not specified explicitly then a default setup script will
+ # be used instead. Setup scripts may be global or arhitecture/
+ # /platform/cpu specific. Setup options are used only in case of
+ # global setup scripts.
+
+ # Default setup scripts provided with different VC distributions:
+ #
+ # VC 7.1 had only the vcvars32.bat script specific to 32 bit i386
+ # builds. It was located in the bin folder for the regular version
+ # and in the root folder for the free VC 7.1 tools.
+ #
+ # Later 8.0 & 9.0 versions introduce separate platform specific
+ # vcvars*.bat scripts (e.g. 32 bit, 64 bit AMD or 64 bit Itanium)
+ # located in or under the bin folder. Most also include a global
+ # vcvarsall.bat helper script located in the root folder which runs
+ # one of the aforementioned vcvars*.bat scripts based on the options
+ # passed to it. So far only the version coming with some PlatformSDK
+ # distributions does not include this top level script but to
+ # support those we need to fall back to using the worker scripts
+ # directly in case the top level script can not be found.
+
+ local global-setup = [ feature.get-values <setup> : $(options) ] ;
+ global-setup = $(global-setup[1]) ;
+ if ! $(below-8.0)
+ {
+ global-setup ?= [ locate-default-setup $(command) : $(parent) :
+ vcvarsall.bat ] ;
+ }
+
+ local default-setup-amd64 = vcvarsx86_amd64.bat ;
+ local default-setup-i386 = vcvars32.bat ;
+ local default-setup-ia64 = vcvarsx86_ia64.bat ;
+
+ # http://msdn2.microsoft.com/en-us/library/x4d2c09s(VS.80).aspx and
+ # http://msdn2.microsoft.com/en-us/library/x4d2c09s(vs.90).aspx
+ # mention an x86_IPF option, that seems to be a documentation bug
+ # and x86_ia64 is the correct option.
+ local default-global-setup-options-amd64 = x86_amd64 ;
+ local default-global-setup-options-i386 = x86 ;
+ local default-global-setup-options-ia64 = x86_ia64 ;
+
+ # When using 64-bit Windows, and targeting 64-bit, it is possible to
+ # use a native 64-bit compiler, selected by the "amd64" & "ia64"
+ # parameters to vcvarsall.bat. There are two variables we can use --
+ # PROCESSOR_ARCHITECTURE and PROCESSOR_IDENTIFIER. The first is
+ # 'x86' when running 32-bit Windows, no matter which processor is
+ # used, and 'AMD64' on 64-bit windows on x86 (either AMD64 or EM64T)
+ # Windows.
+ #
+ if [ MATCH ^(AMD64) : [ os.environ PROCESSOR_ARCHITECTURE ] ]
+ {
+ default-global-setup-options-amd64 = amd64 ;
+ }
+ # TODO: The same 'native compiler usage' should be implemented for
+ # the Itanium platform by using the "ia64" parameter. For this
+ # though we need someone with access to this platform who can find
+ # out how to correctly detect this case.
+ else if $(somehow-detect-the-itanium-platform)
+ {
+ default-global-setup-options-ia64 = ia64 ;
+ }
+
+ local setup-prefix = "call " ;
+ local setup-suffix = " >nul"$(.nl) ;
+ if ! [ os.name ] in NT
+ {
+ setup-prefix = "cmd.exe /S /C call " ;
+ setup-suffix = " \">nul\" \"&&\" " ;
+ }
+
+ for local c in $(cpu)
+ {
+ local setup-options ;
+
+ setup-$(c) = [ feature.get-values <setup-$(c)> : $(options) ] ;
+
+ if ! $(setup-$(c))-is-not-empty
+ {
+ if $(global-setup)-is-not-empty
+ {
+ setup-$(c) = $(global-setup) ;
+
+ # If needed we can easily add using configuration flags
+ # here for overriding which options get passed to the
+ # global setup command for which target platform:
+ # setup-options = [ feature.get-values <setup-options-$(c)> : $(options) ] ;
+
+ setup-options ?= $(default-global-setup-options-$(c)) ;
+ }
+ else
+ {
+ setup-$(c) = [ locate-default-setup $(command) : $(parent) : $(default-setup-$(c)) ] ;
+ }
+ }
+
+ # Cygwin to Windows path translation.
+ setup-$(c) = "\""$(setup-$(c):W)"\"" ;
+
+ # Append setup options to the setup name and add the final setup
+ # prefix & suffix.
+ setup-options ?= "" ;
+ setup-$(c) = $(setup-prefix)$(setup-$(c):J=" ")" "$(setup-options:J=" ")$(setup-suffix) ;
+ }
+ }
+
+ # Get tool names (if any) and finish setup.
+
+ compiler = [ feature.get-values <compiler> : $(options) ] ;
+ compiler ?= cl ;
+
+ linker = [ feature.get-values <linker> : $(options) ] ;
+ linker ?= link ;
+
+ resource-compiler = [ feature.get-values <resource-compiler> : $(options) ] ;
+ resource-compiler ?= rc ;
+
+ # Turn on some options for i386 assembler
+ # -coff generate COFF format object file (compatible with cl.exe output)
+ local default-assembler-amd64 = ml64 ;
+ local default-assembler-i386 = "ml -coff" ;
+ local default-assembler-ia64 = ias ;
+
+ assembler = [ feature.get-values <assembler> : $(options) ] ;
+
+ idl-compiler = [ feature.get-values <idl-compiler> : $(options) ] ;
+ idl-compiler ?= midl ;
+
+ mc-compiler = [ feature.get-values <mc-compiler> : $(options) ] ;
+ mc-compiler ?= mc ;
+
+ manifest-tool = [ feature.get-values <manifest-tool> : $(options) ] ;
+ manifest-tool ?= mt ;
+
+ local cc-filter = [ feature.get-values <compiler-filter> : $(options) ] ;
+
+ for local c in $(cpu)
+ {
+ # Setup script is not required in some configurations.
+ setup-$(c) ?= "" ;
+
+ local cpu-conditions = $(conditions)/$(.cpu-arch-$(c)) ;
+
+ if $(.debug-configuration)
+ {
+ for local cpu-condition in $(cpu-conditions)
+ {
+ ECHO "notice: [msvc-cfg] condition: '$(cpu-condition)', setup: '$(setup-$(c))'" ;
+ }
+ }
+
+ local cpu-assembler = $(assembler) ;
+ cpu-assembler ?= $(default-assembler-$(c)) ;
+
+ toolset.flags msvc.compile .CC $(cpu-conditions) : $(setup-$(c))$(compiler) /Zm800 -nologo ;
+ toolset.flags msvc.compile .RC $(cpu-conditions) : $(setup-$(c))$(resource-compiler) ;
+ toolset.flags msvc.compile .ASM $(cpu-conditions) : $(setup-$(c))$(cpu-assembler) -nologo ;
+ toolset.flags msvc.link .LD $(cpu-conditions) : $(setup-$(c))$(linker) /NOLOGO /INCREMENTAL:NO ;
+ toolset.flags msvc.archive .LD $(cpu-conditions) : $(setup-$(c))$(linker) /lib /NOLOGO ;
+ toolset.flags msvc.compile .IDL $(cpu-conditions) : $(setup-$(c))$(idl-compiler) ;
+ toolset.flags msvc.compile .MC $(cpu-conditions) : $(setup-$(c))$(mc-compiler) ;
+
+ toolset.flags msvc.link .MT $(cpu-conditions) : $(setup-$(c))$(manifest-tool) -nologo ;
+
+ if $(cc-filter)
+ {
+ toolset.flags msvc .CC.FILTER $(cpu-conditions) : "|" $(cc-filter) ;
+ }
+ }
+
+ # Set version-specific flags.
+ configure-version-specific msvc : $(version) : $(conditions) ;
+ }
+}
+
+
+# Returns the default installation path for the given version.
+#
+local rule default-path ( version )
+{
+ # Use auto-detected path if possible.
+ local path = [ feature.get-values <command> : [ $(.versions).get $(version)
+ : options ] ] ;
+
+ if $(path)
+ {
+ path = $(path:D) ;
+ }
+ else
+ {
+ # Check environment.
+ if $(.version-$(version)-env)
+ {
+ local vc-path = [ os.environ $(.version-$(version)-env) ] ;
+ if $(vc-path)
+ {
+ vc-path = [ path.make $(vc-path) ] ;
+ vc-path = [ path.join $(vc-path) $(.version-$(version)-envpath) ] ;
+ vc-path = [ path.native $(vc-path) ] ;
+
+ path = $(vc-path) ;
+ }
+ }
+
+ # Check default path.
+ if ! $(path) && $(.version-$(version)-path)
+ {
+ path = [ path.native [ path.join $(.ProgramFiles) $(.version-$(version)-path) ] ] ;
+ }
+ }
+
+ return $(path) ;
+}
+
+
+# Returns either the default installation path (if 'version' is not empty) or
+# list of all known default paths (if no version is given)
+#
+local rule default-paths ( version ? )
+{
+ local possible-paths ;
+
+ if $(version)
+ {
+ possible-paths += [ default-path $(version) ] ;
+ }
+ else
+ {
+ for local i in $(.known-versions)
+ {
+ possible-paths += [ default-path $(i) ] ;
+ }
+ }
+
+ return $(possible-paths) ;
+}
+
+
+rule get-rspline ( target : lang-opt )
+{
+ CC_RSPLINE on $(target) = [ on $(target) return $(lang-opt) -U$(UNDEFS)
+ $(CFLAGS) $(C++FLAGS) $(OPTIONS) -c $(.nl)-D$(DEFINES)
+ $(.nl)\"-I$(INCLUDES:W)\" ] ;
+}
+
+class msvc-linking-generator : linking-generator
+{
+ # Calls the base version. If necessary, also create a target for the
+ # manifest file.specifying source's name as the name of the created
+ # target. As result, the PCH will be named whatever.hpp.gch, and not
+ # whatever.gch.
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ local result = [ linking-generator.generated-targets $(sources)
+ : $(property-set) : $(project) $(name) ] ;
+
+ if $(result)
+ {
+ local name-main = [ $(result[0]).name ] ;
+ local action = [ $(result[0]).action ] ;
+
+ if [ $(property-set).get <debug-symbols> ] = "on"
+ {
+ # We force exact name on PDB. The reason is tagging -- the tag rule may
+ # reasonably special case some target types, like SHARED_LIB. The tag rule
+ # will not catch PDB, and it cannot even easily figure if PDB is paired with
+ # SHARED_LIB or EXE or something else. Because PDB always get the
+ # same name as the main target, with .pdb as extension, just force it.
+ local target = [ class.new file-target $(name-main:S=.pdb) exact : PDB : $(project) : $(action) ] ;
+ local registered-target = [ virtual-target.register $(target) ] ;
+ if $(target) != $(registered-target)
+ {
+ $(action).replace-targets $(target) : $(registered-target) ;
+ }
+ result += $(registered-target) ;
+ }
+
+ if [ $(property-set).get <embed-manifest> ] = "off"
+ {
+ # Manifest is evil target. It has .manifest appened to the name of
+ # main target, including extension. E.g. a.exe.manifest. We use 'exact'
+ # name because to achieve this effect.
+ local target = [ class.new file-target $(name-main).manifest exact : MANIFEST : $(project) : $(action) ] ;
+ local registered-target = [ virtual-target.register $(target) ] ;
+ if $(target) != $(registered-target)
+ {
+ $(action).replace-targets $(target) : $(registered-target) ;
+ }
+ result += $(registered-target) ;
+ }
+ }
+ return $(result) ;
+ }
+}
+
+
+
+# Unsafe worker rule for the register-toolset() rule. Must not be called
+# multiple times.
+#
+local rule register-toolset-really ( )
+{
+ feature.extend toolset : msvc ;
+
+ # Intel and msvc supposedly have link-compatible objects.
+ feature.subfeature toolset msvc : vendor : intel : propagated optional ;
+
+ # Inherit MIDL flags.
+ toolset.inherit-flags msvc : midl ;
+
+ # Inherit MC flags.
+ toolset.inherit-flags msvc : mc ;
+
+ # Dynamic runtime comes only in MT flavour.
+ toolset.add-requirements
+ <toolset>msvc,<runtime-link>shared:<threading>multi ;
+
+ # Declare msvc toolset specific features.
+ {
+ feature.feature debug-store : object database : propagated ;
+ feature.feature pch-source : : dependency free ;
+ }
+
+ # Declare generators.
+ {
+ # TODO: Is it possible to combine these? Make the generators
+ # non-composing so that they do not convert each source into a separate
+ # .rsp file.
+ generators.register [ new msvc-linking-generator
+ msvc.link : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : <toolset>msvc ] ;
+ generators.register [ new msvc-linking-generator
+ msvc.link.dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB : <toolset>msvc ] ;
+
+ generators.register-archiver msvc.archive : OBJ : STATIC_LIB : <toolset>msvc ;
+ generators.register-c-compiler msvc.compile.c++ : CPP : OBJ : <toolset>msvc ;
+ generators.register-c-compiler msvc.compile.c : C : OBJ : <toolset>msvc ;
+ generators.register-c-compiler msvc.compile.c++.preprocess : CPP : PREPROCESSED_CPP : <toolset>msvc ;
+ generators.register-c-compiler msvc.compile.c.preprocess : C : PREPROCESSED_C : <toolset>msvc ;
+
+ # Using 'register-c-compiler' adds the build directory to INCLUDES.
+ generators.register-c-compiler msvc.compile.rc : RC : OBJ(%_res) : <toolset>msvc ;
+ generators.override msvc.compile.rc : rc.compile.resource ;
+ generators.register-standard msvc.compile.asm : ASM : OBJ : <toolset>msvc ;
+
+ generators.register-c-compiler msvc.compile.idl : IDL : MSTYPELIB H C(%_i) C(%_proxy) C(%_dlldata) : <toolset>msvc ;
+ generators.override msvc.compile.idl : midl.compile.idl ;
+
+ generators.register-standard msvc.compile.mc : MC : H RC : <toolset>msvc ;
+ generators.override msvc.compile.mc : mc.compile ;
+
+ # Note: the 'H' source type will catch both '.h' and '.hpp' headers as
+ # the latter have their HPP type derived from H. The type of compilation
+ # is determined entirely by the destination type.
+ generators.register [ new msvc-pch-generator msvc.compile.c.pch : H : C_PCH OBJ : <pch>on <toolset>msvc ] ;
+ generators.register [ new msvc-pch-generator msvc.compile.c++.pch : H : CPP_PCH OBJ : <pch>on <toolset>msvc ] ;
+
+ generators.override msvc.compile.c.pch : pch.default-c-pch-generator ;
+ generators.override msvc.compile.c++.pch : pch.default-cpp-pch-generator ;
+ }
+
+ toolset.flags msvc.compile PCH_FILE <pch>on : <pch-file> ;
+ toolset.flags msvc.compile PCH_SOURCE <pch>on : <pch-source> ;
+ toolset.flags msvc.compile PCH_HEADER <pch>on : <pch-header> ;
+
+ #
+ # Declare flags for compilation.
+ #
+
+ toolset.flags msvc.compile CFLAGS <optimization>speed : /O2 ;
+ toolset.flags msvc.compile CFLAGS <optimization>space : /O1 ;
+
+ toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/<instruction-set>$(.cpu-type-itanium) : /G1 ;
+ toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/<instruction-set>$(.cpu-type-itanium2) : /G2 ;
+
+ toolset.flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>object : /Z7 ;
+ toolset.flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>database : /Zi ;
+ toolset.flags msvc.compile CFLAGS <optimization>off : /Od ;
+ toolset.flags msvc.compile CFLAGS <inlining>off : /Ob0 ;
+ toolset.flags msvc.compile CFLAGS <inlining>on : /Ob1 ;
+ toolset.flags msvc.compile CFLAGS <inlining>full : /Ob2 ;
+
+ toolset.flags msvc.compile CFLAGS <warnings>on : /W3 ;
+ toolset.flags msvc.compile CFLAGS <warnings>off : /W0 ;
+ toolset.flags msvc.compile CFLAGS <warnings>all : /W4 ;
+ toolset.flags msvc.compile CFLAGS <warnings-as-errors>on : /WX ;
+
+ toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>off : /EHs ;
+ toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>on : /EHsc ;
+ toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>off : /EHa ;
+ toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>on : /EHac ;
+
+ # By default 8.0 enables rtti support while prior versions disabled it. We
+ # simply enable or disable it explicitly so we do not have to depend on this
+ # default behaviour.
+ toolset.flags msvc.compile CFLAGS <rtti>on : /GR ;
+ toolset.flags msvc.compile CFLAGS <rtti>off : /GR- ;
+ toolset.flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>shared : /MD ;
+ toolset.flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>shared : /MDd ;
+
+ toolset.flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>static/<threading>multi : /MT ;
+ toolset.flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>static/<threading>multi : /MTd ;
+
+ toolset.flags msvc.compile OPTIONS <cflags> : ;
+ toolset.flags msvc.compile.c++ OPTIONS <cxxflags> : ;
+
+ toolset.flags msvc.compile PDB_CFLAG <debug-symbols>on/<debug-store>database : /Fd ;
+
+ toolset.flags msvc.compile DEFINES <define> ;
+ toolset.flags msvc.compile UNDEFS <undef> ;
+ toolset.flags msvc.compile INCLUDES <include> ;
+
+ # Declare flags for the assembler.
+ toolset.flags msvc.compile.asm USER_ASMFLAGS <asmflags> ;
+
+ toolset.flags msvc.compile.asm ASMFLAGS <debug-symbols>on : "/Zi /Zd" ;
+
+ toolset.flags msvc.compile.asm ASMFLAGS <warnings>on : /W3 ;
+ toolset.flags msvc.compile.asm ASMFLAGS <warnings>off : /W0 ;
+ toolset.flags msvc.compile.asm ASMFLAGS <warnings>all : /W4 ;
+ toolset.flags msvc.compile.asm ASMFLAGS <warnings-as-errors>on : /WX ;
+
+ toolset.flags msvc.compile.asm DEFINES <define> ;
+
+ # Declare flags for linking.
+ {
+ toolset.flags msvc.link PDB_LINKFLAG <debug-symbols>on/<debug-store>database : /PDB: ; # not used yet
+ toolset.flags msvc.link LINKFLAGS <debug-symbols>on : /DEBUG ;
+ toolset.flags msvc.link DEF_FILE <def-file> ;
+
+ # The linker disables the default optimizations when using /DEBUG so we
+ # have to enable them manually for release builds with debug symbols.
+ toolset.flags msvc LINKFLAGS <debug-symbols>on/<runtime-debugging>off : /OPT:REF,ICF ;
+
+ toolset.flags msvc LINKFLAGS <user-interface>console : /subsystem:console ;
+ toolset.flags msvc LINKFLAGS <user-interface>gui : /subsystem:windows ;
+ toolset.flags msvc LINKFLAGS <user-interface>wince : /subsystem:windowsce ;
+ toolset.flags msvc LINKFLAGS <user-interface>native : /subsystem:native ;
+ toolset.flags msvc LINKFLAGS <user-interface>auto : /subsystem:posix ;
+
+ toolset.flags msvc.link OPTIONS <linkflags> ;
+ toolset.flags msvc.link LINKPATH <library-path> ;
+
+ toolset.flags msvc.link FINDLIBS_ST <find-static-library> ;
+ toolset.flags msvc.link FINDLIBS_SA <find-shared-library> ;
+ toolset.flags msvc.link LIBRARY_OPTION <toolset>msvc : "" : unchecked ;
+ toolset.flags msvc.link LIBRARIES_MENTIONED_BY_FILE : <library-file> ;
+ }
+
+ toolset.flags msvc.archive AROPTIONS <archiveflags> ;
+}
+
+
+# Locates the requested setup script under the given folder and returns its full
+# path or nothing in case the script can not be found. In case multiple scripts
+# are found only the first one is returned.
+#
+# TODO: There used to exist a code comment for the msvc.init rule stating that
+# we do not correctly detect the location of the vcvars32.bat setup script for
+# the free VC7.1 tools in case user explicitly provides a path. This should be
+# tested or simply remove this whole comment in case this toolset version is no
+# longer important.
+#
+local rule locate-default-setup ( command : parent : setup-name )
+{
+ local result = [ GLOB $(command) $(parent) : $(setup-name) ] ;
+ if $(result[1])
+ {
+ return $(result[1]) ;
+ }
+}
+
+
+# Validates given path, registers found configuration and prints debug
+# information about it.
+#
+local rule register-configuration ( version : path ? )
+{
+ if $(path)
+ {
+ local command = [ GLOB $(path) : cl.exe ] ;
+
+ if $(command)
+ {
+ if $(.debug-configuration)
+ {
+ ECHO "notice: [msvc-cfg] msvc-$(version) detected, command: '$(command)'" ;
+ }
+
+ $(.versions).register $(version) ;
+ $(.versions).set $(version) : options : <command>$(command) ;
+ }
+ }
+}
+
+
+################################################################################
+#
+# Startup code executed when loading this module.
+#
+################################################################################
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+# Miscellaneous constants.
+.RM = [ common.rm-command ] ;
+.nl = "
+" ;
+.ProgramFiles = [ path.make [ common.get-program-files-dir ] ] ;
+.escaped-double-quote = "\"" ;
+.TOUCH_FILE = [ common.file-touch-command ] ;
+
+# List of all registered configurations.
+.versions = [ new configurations ] ;
+
+# Supported CPU architectures.
+.cpu-arch-i386 =
+ <architecture>/<address-model>
+ <architecture>/<address-model>32
+ <architecture>x86/<address-model>
+ <architecture>x86/<address-model>32 ;
+
+.cpu-arch-amd64 =
+ <architecture>/<address-model>64
+ <architecture>x86/<address-model>64 ;
+
+.cpu-arch-ia64 =
+ <architecture>ia64/<address-model>
+ <architecture>ia64/<address-model>64 ;
+
+
+# Supported CPU types (only Itanium optimization options are supported from
+# VC++ 2005 on). See
+# http://msdn2.microsoft.com/en-us/library/h66s5s0e(vs.90).aspx for more
+# detailed information.
+.cpu-type-g5 = i586 pentium pentium-mmx ;
+.cpu-type-g6 = i686 pentiumpro pentium2 pentium3 pentium3m pentium-m k6
+ k6-2 k6-3 winchip-c6 winchip2 c3 c3-2 ;
+.cpu-type-em64t = prescott nocona conroe conroe-xe conroe-l allendale mermon
+ mermon-xe kentsfield kentsfield-xe penryn wolfdale
+ yorksfield nehalem ;
+.cpu-type-amd64 = k8 opteron athlon64 athlon-fx ;
+.cpu-type-g7 = pentium4 pentium4m athlon athlon-tbird athlon-4 athlon-xp
+ athlon-mp $(.cpu-type-em64t) $(.cpu-type-amd64) ;
+.cpu-type-itanium = itanium itanium1 merced ;
+.cpu-type-itanium2 = itanium2 mckinley ;
+
+
+# Known toolset versions, in order of preference.
+.known-versions = 10.0 10.0express 9.0 9.0express 8.0 8.0express 7.1 7.1toolkit 7.0 6.0 ;
+
+# Version aliases.
+.version-alias-6 = 6.0 ;
+.version-alias-6.5 = 6.0 ;
+.version-alias-7 = 7.0 ;
+.version-alias-8 = 8.0 ;
+.version-alias-9 = 9.0 ;
+.version-alias-10 = 10.0 ;
+
+# Names of registry keys containing the Visual C++ installation path (relative
+# to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft").
+.version-6.0-reg = "VisualStudio\\6.0\\Setup\\Microsoft Visual C++" ;
+.version-7.0-reg = "VisualStudio\\7.0\\Setup\\VC" ;
+.version-7.1-reg = "VisualStudio\\7.1\\Setup\\VC" ;
+.version-8.0-reg = "VisualStudio\\8.0\\Setup\\VC" ;
+.version-8.0express-reg = "VCExpress\\8.0\\Setup\\VC" ;
+.version-9.0-reg = "VisualStudio\\9.0\\Setup\\VC" ;
+.version-9.0express-reg = "VCExpress\\9.0\\Setup\\VC" ;
+.version-10.0-reg = "VisualStudio\\10.0\\Setup\\VC" ;
+.version-10.0express-reg = "VCExpress\\10.0\\Setup\\VC" ;
+
+# Visual C++ Toolkit 2003 does not store its installation path in the registry.
+# The environment variable 'VCToolkitInstallDir' and the default installation
+# path will be checked instead.
+.version-7.1toolkit-path = "Microsoft Visual C++ Toolkit 2003" "bin" ;
+.version-7.1toolkit-env = VCToolkitInstallDir ;
+
+# Path to the folder containing "cl.exe" relative to the value of the
+# corresponding environment variable.
+.version-7.1toolkit-envpath = "bin" ;
+
+
+# Auto-detect all the available msvc installations on the system.
+auto-detect-toolset-versions ;
+
+
+# And finally trigger the actual Boost Build toolset registration.
+register-toolset ;
diff --git a/tools/build/v2/tools/notfile.jam b/tools/build/v2/tools/notfile.jam
new file mode 100644
index 0000000000..97a5b0e876
--- /dev/null
+++ b/tools/build/v2/tools/notfile.jam
@@ -0,0 +1,74 @@
+# Copyright (c) 2005 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import "class" : new ;
+import generators ;
+import project ;
+import targets ;
+import toolset ;
+import type ;
+
+
+type.register NOTFILE_MAIN ;
+
+
+class notfile-generator : generator
+{
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * : multiple ? )
+ {
+ local action ;
+ local action-name = [ $(property-set).get <action> ] ;
+
+ local m = [ MATCH ^@(.*) : $(action-name) ] ;
+
+ if $(m)
+ {
+ action = [ new action $(sources) : $(m[1])
+ : $(property-set) ] ;
+ }
+ else
+ {
+ action = [ new action $(sources) : notfile.run
+ : $(property-set) ] ;
+ }
+ return [ virtual-target.register
+ [ new notfile-target $(name) : $(project) : $(action) ] ] ;
+ }
+}
+
+
+generators.register [ new notfile-generator notfile.main : : NOTFILE_MAIN ] ;
+
+
+toolset.flags notfile.run ACTION : <action> ;
+
+
+actions run
+{
+ $(ACTION)
+}
+
+
+rule notfile ( target-name : action + : sources * : requirements * : default-build * )
+{
+ local project = [ project.current ] ;
+
+ requirements += <action>$(action) ;
+
+ targets.main-target-alternative
+ [ new typed-target $(target-name) : $(project) : NOTFILE_MAIN
+ : [ targets.main-target-sources $(sources) : $(target-name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+}
+
+IMPORT $(__name__) : notfile : : notfile ;
diff --git a/tools/build/v2/tools/notfile.py b/tools/build/v2/tools/notfile.py
new file mode 100644
index 0000000000..afbf68fb0e
--- /dev/null
+++ b/tools/build/v2/tools/notfile.py
@@ -0,0 +1,51 @@
+# Status: ported.
+# Base revision: 64429.
+#
+# Copyright (c) 2005-2010 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+
+import b2.build.type as type
+import b2.build.generators as generators
+import b2.build.virtual_target as virtual_target
+import b2.build.toolset as toolset
+import b2.build.targets as targets
+
+from b2.manager import get_manager
+from b2.util import bjam_signature
+
+type.register("NOTFILE_MAIN")
+
+class NotfileGenerator(generators.Generator):
+
+ def run(self, project, name, ps, sources):
+ pass
+ action_name = ps.get('action')[0]
+ if action_name[0] == '@':
+ action = virtual_target.Action(get_manager(), sources, action_name[1:], ps)
+ else:
+ action = virtual_target.Action(get_manager(), sources, "notfile.run", ps)
+
+ return [get_manager().virtual_targets().register(
+ virtual_target.NotFileTarget(name, project, action))]
+
+generators.register(NotfileGenerator("notfile.main", False, [], ["NOTFILE_MAIN"]))
+
+toolset.flags("notfile.run", "ACTION", [], ["<action>"])
+
+get_manager().engine().register_action("notfile.run", "$(ACTION)")
+
+@bjam_signature((["target_name"], ["action"], ["sources", "*"], ["requirements", "*"],
+ ["default_build", "*"]))
+def notfile(target_name, action, sources, requirements, default_build):
+
+ requirements.append("<action>" + action)
+
+ return targets.create_typed_metatarget(target_name, "NOTFILE_MAIN", sources, requirements,
+ default_build, [])
+
+
+get_manager().projects().add_rule("notfile", notfile)
diff --git a/tools/build/v2/tools/package.jam b/tools/build/v2/tools/package.jam
new file mode 100644
index 0000000000..198c223151
--- /dev/null
+++ b/tools/build/v2/tools/package.jam
@@ -0,0 +1,165 @@
+# Copyright (c) 2005 Vladimir Prus.
+# Copyright 2006 Rene Rivera.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Provides mechanism for installing whole packages into a specific directory
+# structure. This is opposed to the 'install' rule, that installs a number of
+# targets to a single directory, and does not care about directory structure at
+# all.
+
+# Example usage:
+#
+# package.install boost : <properties>
+# : <binaries>
+# : <libraries>
+# : <headers>
+# ;
+#
+# This will install binaries, libraries and headers to the 'proper' location,
+# given by command line options --prefix, --exec-prefix, --bindir, --libdir and
+# --includedir.
+#
+# The rule is just a convenient wrapper, avoiding the need to define several
+# 'install' targets.
+#
+# The only install-related feature is <install-source-root>. It will apply to
+# headers only and if present, paths of headers relatively to source root will
+# be retained after installing. If it is not specified, then "." is assumed, so
+# relative paths in headers are always preserved.
+
+import "class" : new ;
+import option ;
+import project ;
+import feature ;
+import property ;
+import stage ;
+import targets ;
+import modules ;
+
+feature.feature install-default-prefix : : free incidental ;
+
+rule install ( name package-name ? : requirements * : binaries * : libraries * : headers * )
+{
+ package-name ?= $(name) ;
+ if [ MATCH --prefix=(.*) : [ modules.peek : ARGV ] ]
+ {
+ # If --prefix is explicitly specified on the command line,
+ # then we need wipe away any settings of libdir/includir that
+ # is specified via options in config files.
+ option.set bindir : ;
+ option.set libdir : ;
+ option.set includedir : ;
+ }
+
+ # If <install-source-root> is not specified, all headers are installed to
+ # prefix/include, no matter what their relative path is. Sometimes that is
+ # what is needed.
+ local install-source-root = [ property.select <install-source-root> :
+ $(requirements) ] ;
+ install-source-root = $(install-source-root:G=) ;
+ requirements = [ property.change $(requirements) : <install-source-root> ] ;
+
+ local install-header-subdir = [ property.select <install-header-subdir> :
+ $(requirements) ] ;
+ install-header-subdir = /$(install-header-subdir:G=) ;
+ install-header-subdir ?= "" ;
+ requirements = [ property.change $(requirements) : <install-header-subdir> ]
+ ;
+
+ # First, figure out all locations. Use the default if no prefix option
+ # given.
+ local prefix = [ get-prefix $(name) : $(requirements) ] ;
+
+ # Architecture dependent files.
+ local exec-locate = [ option.get exec-prefix : $(prefix) ] ;
+
+ # Binaries.
+ local bin-locate = [ option.get bindir : $(prefix)/bin ] ;
+
+ # Object code libraries.
+ local lib-locate = [ option.get libdir : $(prefix)/lib ] ;
+
+ # Source header files.
+ local include-locate = [ option.get includedir : $(prefix)/include ] ;
+
+ stage.install $(name)-bin : $(binaries) : $(requirements)
+ <location>$(bin-locate) ;
+ alias $(name)-lib : $(name)-lib-shared $(name)-lib-static ;
+
+ # Since the install location of shared libraries differs on universe
+ # and cygwin, use target alternatives to make different targets.
+ # We should have used indirection conditioanl requirements, but it's
+ # awkward to pass bin-locate and lib-locate from there to another rule.
+ alias $(name)-lib-shared : $(name)-lib-shared-universe ;
+ alias $(name)-lib-shared : $(name)-lib-shared-cygwin : <target-os>cygwin ;
+
+ # For shared libraries, we install both explicitly specified one and the
+ # shared libraries that the installed executables depend on.
+ stage.install $(name)-lib-shared-universe : $(binaries) $(libraries) : $(requirements)
+ <location>$(lib-locate) <install-dependencies>on <install-type>SHARED_LIB ;
+ stage.install $(name)-lib-shared-cygwin : $(binaries) $(libraries) : $(requirements)
+ <location>$(bin-locate) <install-dependencies>on <install-type>SHARED_LIB ;
+
+ # For static libraries, we do not care about executable dependencies, since
+ # static libraries are already incorporated into them.
+ stage.install $(name)-lib-static : $(libraries) : $(requirements)
+ <location>$(lib-locate) <install-dependencies>on <install-type>STATIC_LIB ;
+ stage.install $(name)-headers : $(headers) : $(requirements)
+ <location>$(include-locate)$(install-header-subdir)
+ <install-source-root>$(install-source-root) ;
+ alias $(name) : $(name)-bin $(name)-lib $(name)-headers ;
+
+ local c = [ project.current ] ;
+ local project-module = [ $(c).project-module ] ;
+ module $(project-module)
+ {
+ explicit $(1)-bin $(1)-lib $(1)-headers $(1) $(1)-lib-shared $(1)-lib-static
+ $(1)-lib-shared-universe $(1)-lib-shared-cygwin ;
+ }
+}
+
+rule install-data ( target-name : package-name : data * : requirements * )
+{
+ package-name ?= target-name ;
+ if [ MATCH --prefix=(.*) : [ modules.peek : ARGV ] ]
+ {
+ # If --prefix is explicitly specified on the command line,
+ # then we need wipe away any settings of datarootdir
+ option.set datarootdir : ;
+ }
+
+ local prefix = [ get-prefix $(package-name) : $(requirements) ] ;
+ local datadir = [ option.get datarootdir : $(prefix)/share ] ;
+
+ stage.install $(target-name)
+ : $(data)
+ : $(requirements) <location>$(datadir)/$(package-name)
+ ;
+
+ local c = [ project.current ] ;
+ local project-module = [ $(c).project-module ] ;
+ module $(project-module)
+ {
+ explicit $(1) ;
+ }
+}
+
+local rule get-prefix ( package-name : requirements * )
+{
+ local prefix = [ option.get prefix : [ property.select
+ <install-default-prefix> : $(requirements) ] ] ;
+ prefix = $(prefix:G=) ;
+ requirements = [ property.change $(requirements) : <install-default-prefix>
+ ] ;
+ # Or some likely defaults if neither is given.
+ if ! $(prefix)
+ {
+ if [ modules.peek : NT ] { prefix = C:\\$(package-name) ; }
+ else if [ modules.peek : UNIX ] { prefix = /usr/local ; }
+ }
+ return $(prefix) ;
+}
+
diff --git a/tools/build/v2/tools/package.py b/tools/build/v2/tools/package.py
new file mode 100644
index 0000000000..aa081b4f49
--- /dev/null
+++ b/tools/build/v2/tools/package.py
@@ -0,0 +1,168 @@
+# Status: ported
+# Base revision: 64488
+#
+# Copyright (c) 2005, 2010 Vladimir Prus.
+# Copyright 2006 Rene Rivera.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Provides mechanism for installing whole packages into a specific directory
+# structure. This is opposed to the 'install' rule, that installs a number of
+# targets to a single directory, and does not care about directory structure at
+# all.
+
+# Example usage:
+#
+# package.install boost : <properties>
+# : <binaries>
+# : <libraries>
+# : <headers>
+# ;
+#
+# This will install binaries, libraries and headers to the 'proper' location,
+# given by command line options --prefix, --exec-prefix, --bindir, --libdir and
+# --includedir.
+#
+# The rule is just a convenient wrapper, avoiding the need to define several
+# 'install' targets.
+#
+# The only install-related feature is <install-source-root>. It will apply to
+# headers only and if present, paths of headers relatively to source root will
+# be retained after installing. If it is not specified, then "." is assumed, so
+# relative paths in headers are always preserved.
+
+import b2.build.feature as feature
+import b2.build.property as property
+import b2.util.option as option
+import b2.tools.stage as stage
+
+from b2.build.alias import alias
+
+from b2.manager import get_manager
+
+from b2.util import bjam_signature
+from b2.util.utility import ungrist
+
+
+import os
+
+feature.feature("install-default-prefix", [], ["free", "incidental"])
+
+@bjam_signature((["name", "package_name", "?"], ["requirements", "*"],
+ ["binaries", "*"], ["libraries", "*"], ["headers", "*"]))
+def install(name, package_name=None, requirements=[], binaries=[], libraries=[], headers=[]):
+
+ requirements = requirements[:]
+ binaries = binaries[:]
+ libraries
+
+ if not package_name:
+ package_name = name
+
+ if option.get("prefix"):
+ # If --prefix is explicitly specified on the command line,
+ # then we need wipe away any settings of libdir/includir that
+ # is specified via options in config files.
+ option.set("bindir", None)
+ option.set("libdir", None)
+ option.set("includedir", None)
+
+ # If <install-source-root> is not specified, all headers are installed to
+ # prefix/include, no matter what their relative path is. Sometimes that is
+ # what is needed.
+ install_source_root = property.select('install-source-root', requirements)
+ if install_source_root:
+ requirements = property.change(requirements, 'install-source-root', None)
+
+ install_header_subdir = property.select('install-header-subdir', requirements)
+ if install_header_subdir:
+ install_header_subdir = ungrist(install_header_subdir[0])
+ requirements = property.change(requirements, 'install-header-subdir', None)
+
+ # First, figure out all locations. Use the default if no prefix option
+ # given.
+ prefix = get_prefix(name, requirements)
+
+ # Architecture dependent files.
+ exec_locate = option.get("exec-prefix", prefix)
+
+ # Binaries.
+ bin_locate = option.get("bindir", os.path.join(prefix, "bin"))
+
+ # Object code libraries.
+ lib_locate = option.get("libdir", os.path.join(prefix, "lib"))
+
+ # Source header files.
+ include_locate = option.get("includedir", os.path.join(prefix, "include"))
+
+ stage.install(name + "-bin", binaries, requirements + ["<location>" + bin_locate])
+
+ alias(name + "-lib", [name + "-lib-shared", name + "-lib-static"])
+
+ # Since the install location of shared libraries differs on universe
+ # and cygwin, use target alternatives to make different targets.
+ # We should have used indirection conditioanl requirements, but it's
+ # awkward to pass bin-locate and lib-locate from there to another rule.
+ alias(name + "-lib-shared", [name + "-lib-shared-universe"])
+ alias(name + "-lib-shared", [name + "-lib-shared-cygwin"], ["<target-os>cygwin"])
+
+ # For shared libraries, we install both explicitly specified one and the
+ # shared libraries that the installed executables depend on.
+ stage.install(name + "-lib-shared-universe", binaries + libraries,
+ requirements + ["<location>" + lib_locate, "<install-dependencies>on",
+ "<install-type>SHARED_LIB"])
+ stage.install(name + "-lib-shared-cygwin", binaries + libraries,
+ requirements + ["<location>" + bin_locate, "<install-dependencies>on",
+ "<install-type>SHARED_LIB"])
+
+ # For static libraries, we do not care about executable dependencies, since
+ # static libraries are already incorporated into them.
+ stage.install(name + "-lib-static", libraries, requirements +
+ ["<location>" + lib_locate, "<install-dependencies>on", "<install-type>STATIC_LIB"])
+ stage.install(name + "-headers", headers, requirements \
+ + ["<location>" + os.path.join(include_locate, s) for s in install_header_subdir]
+ + install_source_root)
+
+ alias(name, [name + "-bin", name + "-lib", name + "-headers"])
+
+ pt = get_manager().projects().current()
+
+ for subname in ["bin", "lib", "headers", "lib-shared", "lib-static", "lib-shared-universe", "lib-shared-cygwin"]:
+ pt.mark_targets_as_explicit([name + "-" + subname])
+
+@bjam_signature((["target_name"], ["package_name"], ["data", "*"], ["requirements", "*"]))
+def install_data(target_name, package_name, data, requirements):
+ if not package_name:
+ package_name = target_name
+
+ if option.get("prefix"):
+ # If --prefix is explicitly specified on the command line,
+ # then we need wipe away any settings of datarootdir
+ option.set("datarootdir", None)
+
+ prefix = get_prefix(package_name, requirements)
+ datadir = option.get("datarootdir", os.path.join(prefix, "share"))
+
+ stage.install(target_name, data,
+ requirements + ["<location>" + os.path.join(datadir, package_name)])
+
+ get_manager().projects().current().mark_targets_as_explicit([target_name])
+
+def get_prefix(package_name, requirements):
+
+ specified = property.select("install-default-prefix", requirements)
+ if specified:
+ specified = ungrist(specified[0])
+ prefix = option.get("prefix", specified)
+ requirements = property.change(requirements, "install-default-prefix", None)
+ # Or some likely defaults if neither is given.
+ if not prefix:
+ if os.name == "nt":
+ prefix = "C:\\" + package_name
+ elif os.name == "posix":
+ prefix = "/usr/local"
+
+ return prefix
+
diff --git a/tools/build/v2/tools/pathscale.jam b/tools/build/v2/tools/pathscale.jam
new file mode 100644
index 0000000000..454e34547e
--- /dev/null
+++ b/tools/build/v2/tools/pathscale.jam
@@ -0,0 +1,168 @@
+# Copyright 2006 Noel Belcourt
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import property ;
+import generators ;
+import toolset : flags ;
+import feature ;
+import type ;
+import common ;
+import fortran ;
+
+feature.extend toolset : pathscale ;
+toolset.inherit pathscale : unix ;
+generators.override pathscale.prebuilt : builtin.prebuilt ;
+generators.override pathscale.searched-lib-generator : searched-lib-generator ;
+
+# Documentation and toolchain description located
+# http://www.pathscale.com/docs.html
+
+rule init ( version ? : command * : options * )
+{
+ command = [ common.get-invocation-command pathscale : pathCC : $(command)
+ : /opt/ekopath/bin ] ;
+
+ # Determine the version
+ local command-string = $(command:J=" ") ;
+ if $(command)
+ {
+ version ?= [ MATCH "^([0-9.]+)"
+ : [ SHELL "$(command-string) -dumpversion" ] ] ;
+ }
+
+ local condition = [ common.check-init-parameters pathscale
+ : version $(version) ] ;
+
+ common.handle-options pathscale : $(condition) : $(command) : $(options) ;
+
+ toolset.flags pathscale.compile.fortran90 OPTIONS $(condition) :
+ [ feature.get-values <fflags> : $(options) ] : unchecked ;
+
+ command_c = $(command_c[1--2]) $(command[-1]:B=pathcc) ;
+
+ toolset.flags pathscale CONFIG_C_COMMAND $(condition) : $(command_c) ;
+
+ # fortran support
+ local f-command = [ common.get-invocation-command pathscale : pathf90 : $(command) ] ;
+ local command_f = $(command_f[1--2]) $(f-command[-1]:B=pathf90) ;
+ local command_f90 = $(command_f[1--2]) $(f-command[-1]:B=pathf90) ;
+
+ toolset.flags pathscale CONFIG_F_COMMAND $(condition) : $(command_f) ;
+ toolset.flags pathscale CONFIG_F90_COMMAND $(condition) : $(command_f90) ;
+
+ # always link lib rt to resolve clock_gettime()
+ flags pathscale.link FINDLIBS-SA : rt : unchecked ;
+}
+
+# Declare generators
+generators.register-c-compiler pathscale.compile.c : C : OBJ : <toolset>pathscale ;
+generators.register-c-compiler pathscale.compile.c++ : CPP : OBJ : <toolset>pathscale ;
+generators.register-fortran-compiler pathscale.compile.fortran : FORTRAN : OBJ : <toolset>pathscale ;
+generators.register-fortran90-compiler pathscale.compile.fortran90 : FORTRAN90 : OBJ : <toolset>pathscale ;
+
+# Declare flags and actions for compilation
+flags pathscale.compile OPTIONS <optimization>off : -O0 ;
+flags pathscale.compile OPTIONS <optimization>speed : -O3 ;
+flags pathscale.compile OPTIONS <optimization>space : -Os ;
+
+flags pathscale.compile OPTIONS <inlining>off : -noinline ;
+flags pathscale.compile OPTIONS <inlining>on : -inline ;
+flags pathscale.compile OPTIONS <inlining>full : -inline ;
+
+flags pathscale.compile OPTIONS <warnings>off : -woffall ;
+flags pathscale.compile OPTIONS <warnings>on : -Wall ;
+flags pathscale.compile OPTIONS <warnings>all : -Wall -pedantic ;
+flags pathscale.compile OPTIONS <warnings-as-errors>on : -Werror ;
+
+flags pathscale.compile OPTIONS <debug-symbols>on : -ggdb ;
+flags pathscale.compile OPTIONS <profiling>on : -pg ;
+flags pathscale.compile OPTIONS <link>shared : -fPIC ;
+flags pathscale.compile OPTIONS <address-model>32 : -m32 ;
+flags pathscale.compile OPTIONS <address-model>64 : -m64 ;
+
+flags pathscale.compile USER_OPTIONS <cflags> ;
+flags pathscale.compile.c++ USER_OPTIONS <cxxflags> ;
+flags pathscale.compile DEFINES <define> ;
+flags pathscale.compile INCLUDES <include> ;
+
+flags pathscale.compile.fortran USER_OPTIONS <fflags> ;
+flags pathscale.compile.fortran90 USER_OPTIONS <fflags> ;
+
+actions compile.c
+{
+ "$(CONFIG_C_COMMAND)" $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.fortran
+{
+ "$(CONFIG_F_COMMAND)" $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+rule compile.fortran90 ( targets * : sources * : properties * )
+{
+ # the space rule inserts spaces between targets and it's necessary
+ SPACE on $(targets) = " " ;
+ # Serialize execution of the compile.fortran90 action
+ # F90 source must be compiled in a particular order so we
+ # serialize the build as a parallel F90 compile might fail
+ JAM_SEMAPHORE on $(targets) = <s>pathscale-f90-semaphore ;
+}
+
+actions compile.fortran90
+{
+ "$(CONFIG_F90_COMMAND)" $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -module $(<[1]:D) -c -o "$(<)" "$(>)"
+}
+
+# Declare flags and actions for linking
+flags pathscale.link OPTIONS <debug-symbols>on : -ggdb -rdynamic ;
+# Strip the binary when no debugging is needed
+flags pathscale.link OPTIONS <debug-symbols>off : -g0 ;
+flags pathscale.link OPTIONS <profiling>on : -pg ;
+flags pathscale.link USER_OPTIONS <linkflags> ;
+flags pathscale.link LINKPATH <library-path> ;
+flags pathscale.link FINDLIBS-ST <find-static-library> ;
+flags pathscale.link FINDLIBS-SA <find-shared-library> ;
+flags pathscale.link FINDLIBS-SA <threading>multi : pthread ;
+flags pathscale.link LIBRARIES <library-file> ;
+flags pathscale.link LINK-RUNTIME <runtime-link>static : static ;
+flags pathscale.link LINK-RUNTIME <runtime-link>shared : dynamic ;
+flags pathscale.link RPATH <dll-path> ;
+# On gcc, there are separate options for dll path at runtime and
+# link time. On Solaris, there's only one: -R, so we have to use
+# it, even though it's bad idea.
+flags pathscale.link RPATH <xdll-path> ;
+
+rule link ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) $(USER_OPTIONS) -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST)
+}
+
+# Slight mods for dlls
+rule link.dll ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) $(USER_OPTIONS) -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" -o "$(<)" -Wl,-soname$(SPACE)-Wl,$(<[1]:D=) -shared "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST)
+}
+
+# Declare action for creating static libraries
+# "$(CONFIG_COMMAND)" -ar -o "$(<)" "$(>)"
+actions piecemeal archive
+{
+ ar $(ARFLAGS) ru "$(<)" "$(>)"
+}
diff --git a/tools/build/v2/tools/pch.jam b/tools/build/v2/tools/pch.jam
new file mode 100644
index 0000000000..0c6e98fac7
--- /dev/null
+++ b/tools/build/v2/tools/pch.jam
@@ -0,0 +1,95 @@
+# Copyright (c) 2005 Reece H. Dunn.
+# Copyright 2006 Ilya Sokolov
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+##### Using Precompiled Headers (Quick Guide) #####
+#
+# Make precompiled mypch.hpp:
+#
+# import pch ;
+#
+# cpp-pch mypch
+# : # sources
+# mypch.hpp
+# : # requiremnts
+# <toolset>msvc:<source>mypch.cpp
+# ;
+#
+# Add cpp-pch to sources:
+#
+# exe hello
+# : main.cpp hello.cpp mypch
+# ;
+
+import "class" : new ;
+import type ;
+import feature ;
+import generators ;
+
+type.register PCH : pch ;
+
+type.register C_PCH : : PCH ;
+type.register CPP_PCH : : PCH ;
+
+# Control precompiled header (PCH) generation.
+feature.feature pch :
+ on
+ off
+ : propagated ;
+
+
+feature.feature pch-header : : free dependency ;
+feature.feature pch-file : : free dependency ;
+
+# Base PCH generator. The 'run' method has the logic to prevent this generator
+# from being run unless it's being used for a top-level PCH target.
+class pch-generator : generator
+{
+ import property-set ;
+
+ rule action-class ( )
+ {
+ return compile-action ;
+ }
+
+ rule run ( project name ? : property-set : sources + )
+ {
+ if ! $(name)
+ {
+ # Unless this generator is invoked as the top-most generator for a
+ # main target, fail. This allows using 'H' type as input type for
+ # this generator, while preventing Boost.Build to try this generator
+ # when not explicitly asked for.
+ #
+ # One bad example is msvc, where pch generator produces both PCH
+ # target and OBJ target, so if there's any header generated (like by
+ # bison, or by msidl), we'd try to use pch generator to get OBJ from
+ # that H, which is completely wrong. By restricting this generator
+ # only to pch main target, such problem is solved.
+ }
+ else
+ {
+ local r = [ run-pch $(project) $(name)
+ : [ $(property-set).add-raw <define>BOOST_BUILD_PCH_ENABLED ]
+ : $(sources) ] ;
+ return [ generators.add-usage-requirements $(r)
+ : <define>BOOST_BUILD_PCH_ENABLED ] ;
+ }
+ }
+
+ # This rule must be overridden by the derived classes.
+ rule run-pch ( project name ? : property-set : sources + )
+ {
+ }
+}
+
+
+# NOTE: requirements are empty, default pch generator can be applied when
+# pch=off.
+generators.register
+ [ new dummy-generator pch.default-c-pch-generator : : C_PCH ] ;
+generators.register
+ [ new dummy-generator pch.default-cpp-pch-generator : : CPP_PCH ] ;
diff --git a/tools/build/v2/tools/pch.py b/tools/build/v2/tools/pch.py
new file mode 100644
index 0000000000..21d3db09df
--- /dev/null
+++ b/tools/build/v2/tools/pch.py
@@ -0,0 +1,83 @@
+# Status: Being ported by Steven Watanabe
+# Base revision: 47077
+#
+# Copyright (c) 2005 Reece H. Dunn.
+# Copyright 2006 Ilya Sokolov
+# Copyright (c) 2008 Steven Watanabe
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+##### Using Precompiled Headers (Quick Guide) #####
+#
+# Make precompiled mypch.hpp:
+#
+# import pch ;
+#
+# cpp-pch mypch
+# : # sources
+# mypch.hpp
+# : # requiremnts
+# <toolset>msvc:<source>mypch.cpp
+# ;
+#
+# Add cpp-pch to sources:
+#
+# exe hello
+# : main.cpp hello.cpp mypch
+# ;
+
+from b2.build import type, feature, generators
+
+type.register('PCH', ['pch'])
+type.register('C_PCH', [], 'PCH')
+type.register('CPP_PCH', [], 'PCH')
+
+# Control precompiled header (PCH) generation.
+feature.feature('pch',
+ ['on', 'off'],
+ ['propagated'])
+
+feature.feature('pch-header', [], ['free', 'dependency'])
+feature.feature('pch-file', [], ['free', 'dependency'])
+
+class PchGenerator(generators.Generator):
+ """
+ Base PCH generator. The 'run' method has the logic to prevent this generator
+ from being run unless it's being used for a top-level PCH target.
+ """
+ def action_class(self):
+ return 'compile-action'
+
+ def run(self, project, name, prop_set, sources):
+ if not name:
+ # Unless this generator is invoked as the top-most generator for a
+ # main target, fail. This allows using 'H' type as input type for
+ # this generator, while preventing Boost.Build to try this generator
+ # when not explicitly asked for.
+ #
+ # One bad example is msvc, where pch generator produces both PCH
+ # target and OBJ target, so if there's any header generated (like by
+ # bison, or by msidl), we'd try to use pch generator to get OBJ from
+ # that H, which is completely wrong. By restricting this generator
+ # only to pch main target, such problem is solved.
+ pass
+ else:
+ r = self.run_pch(project, name,
+ prop_set.add_raw('<define>BOOST_BUILD_PCH_ENABLED'),
+ sources)
+ return generators.add_usage_requirements(
+ r, ['<define>BOOST_BUILD_PCH_ENABLED'])
+
+ # This rule must be overridden by the derived classes.
+ def run_pch(self, project, name, prop_set, sources):
+ pass
+
+#FIXME: dummy-generator in builtins.jam needs to be ported.
+# NOTE: requirements are empty, default pch generator can be applied when
+# pch=off.
+###generators.register(
+### [ new dummy-generator pch.default-c-pch-generator : : C_PCH ] ;
+###generators.register
+### [ new dummy-generator pch.default-cpp-pch-generator : : CPP_PCH ] ;
diff --git a/tools/build/v2/tools/pgi.jam b/tools/build/v2/tools/pgi.jam
new file mode 100644
index 0000000000..3a35c64470
--- /dev/null
+++ b/tools/build/v2/tools/pgi.jam
@@ -0,0 +1,147 @@
+# Copyright Noel Belcourt 2007.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import property ;
+import generators ;
+import os ;
+import toolset : flags ;
+import feature ;
+import fortran ;
+import type ;
+import common ;
+import gcc ;
+
+feature.extend toolset : pgi ;
+toolset.inherit pgi : unix ;
+generators.override pgi.prebuilt : builtin.lib-generator ;
+generators.override pgi.searched-lib-generator : searched-lib-generator ;
+
+# Documentation and toolchain description located
+# http://www.pgroup.com/resources/docs.htm
+
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters pgi : version $(version) ] ;
+
+ local l_command = [ common.get-invocation-command pgi : pgCC : $(command) ] ;
+
+ common.handle-options pgi : $(condition) : $(l_command) : $(options) ;
+
+ command_c = $(command_c[1--2]) $(l_command[-1]:B=cc) ;
+
+ toolset.flags pgi CONFIG_C_COMMAND $(condition) : $(command_c) ;
+
+ flags pgi.compile DEFINES $(condition) :
+ [ feature.get-values <define> : $(options) ] : unchecked ;
+
+ # IOV_MAX support
+ flags pgi.compile DEFINES $(condition) : __need_IOV_MAX : unchecked ;
+
+ # set link flags
+ flags pgi.link FINDLIBS-ST : [
+ feature.get-values <find-static-library> : $(options) ] : unchecked ;
+
+ # always link lib rt to resolve clock_gettime()
+ flags pgi.link FINDLIBS-SA : rt [
+ feature.get-values <find-shared-library> : $(options) ] : unchecked ;
+
+ gcc.init-link-flags pgi gnu $(condition) ;
+}
+
+# Declare generators
+generators.register-c-compiler pgi.compile.c : C : OBJ : <toolset>pgi ;
+generators.register-c-compiler pgi.compile.c++ : CPP : OBJ : <toolset>pgi ;
+generators.register-fortran-compiler pgi.compile.fortran : FORTRAN : OBJ : <toolset>pgi ;
+
+# Declare flags and actions for compilation
+flags pgi.compile OPTIONS : -Kieee ;
+flags pgi.compile OPTIONS <link>shared : -fpic -fPIC ;
+flags pgi.compile OPTIONS <debug-symbols>on : -gopt ;
+flags pgi.compile OPTIONS <profiling>on : -xprofile=tcov ;
+flags pgi.compile OPTIONS <optimization>speed : -fast -Mx,8,0x10000000 ;
+flags pgi.compile OPTIONS <optimization>space : -xO2 -xspace ;
+# flags pgi.compile OPTIONS <threading>multi : -mt ;
+
+flags pgi.compile OPTIONS <warnings>off : -Minform=severe ;
+flags pgi.compile OPTIONS <warnings>on : -Minform=warn ;
+
+flags pgi.compile.c++ OPTIONS <inlining>off : -INLINE:none ;
+
+flags pgi.compile OPTIONS <cflags> ;
+flags pgi.compile.c++ OPTIONS <cxxflags> ;
+flags pgi.compile DEFINES <define> ;
+flags pgi.compile INCLUDES <include> ;
+
+flags pgi.compile.fortran OPTIONS <fflags> ;
+
+actions compile.c
+{
+ "$(CONFIG_C_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.fortran
+{
+ "$(CONFIG_F_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+# Declare flags and actions for linking
+flags pgi.link OPTIONS <debug-symbols>on : -gopt ;
+# Strip the binary when no debugging is needed
+flags pgi.link OPTIONS <debug-symbols>off : -s ;
+flags pgi.link OPTIONS <profiling>on : -xprofile=tcov ;
+flags pgi.link OPTIONS <linkflags> ;
+flags pgi.link OPTIONS <link>shared : -fpic -fPIC ;
+flags pgi.link LINKPATH <library-path> ;
+flags pgi.link FINDLIBS-ST <find-static-library> ;
+flags pgi.link FINDLIBS-SA <find-shared-library> ;
+flags pgi.link FINDLIBS-SA <threading>multi : pthread rt ;
+flags pgi.link LIBRARIES <library-file> ;
+flags pgi.link LINK-RUNTIME <runtime-link>static : static ;
+flags pgi.link LINK-RUNTIME <runtime-link>shared : dynamic ;
+flags pgi.link RPATH <dll-path> ;
+
+# On gcc, there are separate options for dll path at runtime and
+# link time. On Solaris, there's only one: -R, so we have to use
+# it, even though it's bad idea.
+flags pgi.link RPATH <xdll-path> ;
+
+rule link ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+# reddish can only link statically and, somehow, the presence of -Bdynamic on the link line
+# marks the executable as a dynamically linked exec even though no dynamic libraries are supplied.
+# Yod on redstorm refuses to load an executable that is dynamically linked.
+# removing the dynamic link options should get us where we need to be on redstorm.
+# "$(CONFIG_COMMAND)" $(OPTIONS) -L"$(LINKPATH)" -R"$(RPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -Bdynamic -l$(FINDLIBS-SA) -Bstatic -l$(FINDLIBS-ST) -B$(LINK-RUNTIME)
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -L"$(LINKPATH)" -R"$(RPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -Bstatic -l$(FINDLIBS-ST) -Bdynamic -l$(FINDLIBS-SA) -B$(LINK-RUNTIME)
+}
+
+# Slight mods for dlls
+rule link.dll ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+# "$(CONFIG_COMMAND)" $(OPTIONS) -L"$(LINKPATH)" -R"$(RPATH)" -o "$(<)" -h$(<[1]:D=) -G "$(>)" "$(LIBRARIES)" -Bdynamic -l$(FINDLIBS-SA) -Bstatic -l$(FINDLIBS-ST) -B$(LINK-RUNTIME)
+
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -shared -L"$(LINKPATH)" -R"$(RPATH)" -o "$(<)" "$(>)" -Wl,-h -Wl,$(<[1]:D=) "$(LIBRARIES)" -Bdynamic -l$(FINDLIBS-SA) -Bstatic -l$(FINDLIBS-ST) -B$(LINK-RUNTIME)
+}
+
+actions updated together piecemeal pgi.archive
+{
+ ar -rc$(ARFLAGS:E=) "$(<)" "$(>)"
+}
+
diff --git a/tools/build/v2/tools/python-config.jam b/tools/build/v2/tools/python-config.jam
new file mode 100644
index 0000000000..40aa825bc7
--- /dev/null
+++ b/tools/build/v2/tools/python-config.jam
@@ -0,0 +1,27 @@
+#~ Copyright 2005 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Automatic configuration for Python tools and librries. To use, just import this module.
+
+import os ;
+import toolset : using ;
+
+if [ os.name ] = NT
+{
+ for local R in 2.4 2.3 2.2
+ {
+ local python-path = [ W32_GETREG
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\$(R)\\InstallPath" ] ;
+ local python-version = $(R) ;
+
+ if $(python-path)
+ {
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice:" using python ":" $(python-version) ":" $(python-path) ;
+ }
+ using python : $(python-version) : $(python-path) ;
+ }
+ }
+}
diff --git a/tools/build/v2/tools/python.jam b/tools/build/v2/tools/python.jam
new file mode 100644
index 0000000000..66f2aabec3
--- /dev/null
+++ b/tools/build/v2/tools/python.jam
@@ -0,0 +1,1267 @@
+# Copyright 2004 Vladimir Prus.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Support for Python and the the Boost.Python library.
+#
+# This module defines
+#
+# - a project 'python' with a target 'python' in it, that corresponds to the
+# python library
+#
+# - a main target rule 'python-extension' which can be used to build a python
+# extension.
+#
+# Extensions that use Boost.Python must explicitly link to it.
+
+import type ;
+import testing ;
+import generators ;
+import project ;
+import errors ;
+import targets ;
+import "class" : new ;
+import os ;
+import common ;
+import toolset ;
+import regex ;
+import numbers ;
+import string ;
+import property ;
+import sequence ;
+import path ;
+import feature ;
+import set ;
+import builtin ;
+import version ;
+
+
+# Make this module a project.
+project.initialize $(__name__) ;
+project python ;
+
+# Save the project so that if 'init' is called several times we define new
+# targets in the python project, not in whatever project we were called by.
+.project = [ project.current ] ;
+
+# Dynamic linker lib. Necessary to specify it explicitly on some platforms.
+lib dl ;
+# This contains 'openpty' function need by python. Again, on some system need to
+# pass this to linker explicitly.
+lib util ;
+# Python uses pthread symbols.
+lib pthread ;
+# Extra library needed by phtread on some platforms.
+lib rt ;
+
+# The pythonpath feature specifies additional elements for the PYTHONPATH
+# environment variable, set by run-pyd. For example, pythonpath can be used to
+# access Python modules that are part of the product being built, but are not
+# installed in the development system's default paths.
+feature.feature pythonpath : : free optional path ;
+
+# Initializes the Python toolset. Note that all parameters are optional.
+#
+# - version -- the version of Python to use. Should be in Major.Minor format,
+# for example 2.3. Do not include the subminor version.
+#
+# - cmd-or-prefix: Preferably, a command that invokes a Python interpreter.
+# Alternatively, the installation prefix for Python libraries and includes. If
+# empty, will be guessed from the version, the platform's installation
+# patterns, and the python executables that can be found in PATH.
+#
+# - includes: the include path to Python headers. If empty, will be guessed.
+#
+# - libraries: the path to Python library binaries. If empty, will be guessed.
+# On MacOS/Darwin, you can also pass the path of the Python framework.
+#
+# - condition: if specified, should be a set of properties that are matched
+# against the build configuration when Boost.Build selects a Python
+# configuration to use.
+#
+# - extension-suffix: A string to append to the name of extension modules before
+# the true filename extension. Ordinarily we would just compute this based on
+# the value of the <python-debugging> feature. However ubuntu's python-dbg
+# package uses the windows convention of appending _d to debug-build extension
+# modules. We have no way of detecting ubuntu, or of probing python for the
+# "_d" requirement, and if you configure and build python using
+# --with-pydebug, you'll be using the standard *nix convention. Defaults to ""
+# (or "_d" when targeting windows and <python-debugging> is set).
+#
+# Example usage:
+#
+# using python : 2.3 ;
+# using python : 2.3 : /usr/local/bin/python ;
+#
+rule init ( version ? : cmd-or-prefix ? : includes * : libraries ?
+ : condition * : extension-suffix ? )
+{
+ project.push-current $(.project) ;
+
+ debug-message Configuring python... ;
+ for local v in version cmd-or-prefix includes libraries condition
+ {
+ if $($(v))
+ {
+ debug-message " user-specified "$(v): \"$($(v))\" ;
+ }
+ }
+
+ configure $(version) : $(cmd-or-prefix) : $(includes) : $(libraries) : $(condition) : $(extension-suffix) ;
+
+ project.pop-current ;
+}
+
+# A simpler version of SHELL that grabs stderr as well as stdout, but returns
+# nothing if there was an error.
+#
+local rule shell-cmd ( cmd )
+{
+ debug-message running command '$(cmd)" 2>&1"' ;
+ x = [ SHELL $(cmd)" 2>&1" : exit-status ] ;
+ if $(x[2]) = 0
+ {
+ return $(x[1]) ;
+ }
+ else
+ {
+ return ;
+ }
+}
+
+
+# Try to identify Cygwin symlinks. Invoking such a file directly as an NT
+# executable from a native Windows build of bjam would be fatal to the bjam
+# process. One /can/ invoke them through sh.exe or bash.exe, if you can prove
+# that those are not also symlinks. ;-)
+#
+# If a symlink is found returns non-empty; we try to extract the target of the
+# symlink from the file and return that.
+#
+# Note: 1. only works on NT 2. path is a native path.
+local rule is-cygwin-symlink ( path )
+{
+ local is-symlink = ;
+
+ # Look for a file with the given path having the S attribute set, as cygwin
+ # symlinks do. /-C means "do not use thousands separators in file sizes."
+ local dir-listing = [ shell-cmd "DIR /-C /A:S \""$(path)"\"" ] ;
+
+ if $(dir-listing)
+ {
+ # Escape any special regex characters in the base part of the path.
+ local base-pat = [ regex.escape $(path:D=) : ].[()*+?|\\$^ : \\ ] ;
+
+ # Extract the file's size from the directory listing.
+ local size-of-system-file = [ MATCH "([0-9]+) "$(base-pat) : $(dir-listing) : 1 ] ;
+
+ # If the file has a reasonably small size, look for the special symlink
+ # identification text.
+ if $(size-of-system-file) && [ numbers.less $(size-of-system-file) 1000 ]
+ {
+ local link = [ SHELL "FIND /OFF \"!<symlink>\" \""$(path)"\" 2>&1" ] ;
+ if $(link[2]) != 0
+ {
+ local nl = "
+
+" ;
+ is-symlink = [ MATCH ".*!<symlink>([^"$(nl)"]*)" : $(link[1]) : 1 ] ;
+ if $(is-symlink)
+ {
+ is-symlink = [ *nix-path-to-native $(is-symlink) ] ;
+ is-symlink = $(is-symlink:R=$(path:D)) ;
+ }
+
+ }
+ }
+ }
+ return $(is-symlink) ;
+}
+
+
+# Append ext to each member of names that does not contain '.'.
+#
+local rule default-extension ( names * : ext * )
+{
+ local result ;
+ for local n in $(names)
+ {
+ switch $(n)
+ {
+ case *.* : result += $(n) ;
+ case * : result += $(n)$(ext) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Tries to determine whether invoking "cmd" would actually attempt to launch a
+# cygwin symlink.
+#
+# Note: only works on NT.
+#
+local rule invokes-cygwin-symlink ( cmd )
+{
+ local dirs = $(cmd:D) ;
+ if ! $(dirs)
+ {
+ dirs = . [ os.executable-path ] ;
+ }
+ local base = [ default-extension $(cmd:D=) : .exe .cmd .bat ] ;
+ local paths = [ GLOB $(dirs) : $(base) ] ;
+ if $(paths)
+ {
+ # Make sure we have not run into a Cygwin symlink. Invoking such a file
+ # as an NT executable would be fatal for the bjam process.
+ return [ is-cygwin-symlink $(paths[1]) ] ;
+ }
+}
+
+
+local rule debug-message ( message * )
+{
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO notice: [python-cfg] $(message) ;
+ }
+}
+
+
+# Like W32_GETREG, except prepend HKEY_CURRENT_USER\SOFTWARE and
+# HKEY_LOCAL_MACHINE\SOFTWARE to the first argument, returning the first result
+# found. Also accounts for the fact that on 64-bit machines, 32-bit software has
+# its own area, under SOFTWARE\Wow6432node.
+#
+local rule software-registry-value ( path : data ? )
+{
+ local result ;
+ for local root in HKEY_CURRENT_USER HKEY_LOCAL_MACHINE
+ {
+ for local x64elt in "" Wow6432node\\ # Account for 64-bit windows
+ {
+ if ! $(result)
+ {
+ result = [ W32_GETREG $(root)\\SOFTWARE\\$(x64elt)$(path) : $(data) ] ;
+ }
+ }
+
+ }
+ return $(result) ;
+}
+
+
+.windows-drive-letter-re = ^([A-Za-z]):[\\/](.*) ;
+.cygwin-drive-letter-re = ^/cygdrive/([a-z])/(.*) ;
+
+.working-directory = [ PWD ] ;
+.working-drive-letter = [ SUBST $(.working-directory) $(.windows-drive-letter-re) $1 ] ;
+.working-drive-letter ?= [ SUBST $(.working-directory) $(.cygwin-drive-letter-re) $1 ] ;
+
+
+local rule windows-to-cygwin-path ( path )
+{
+ # If path is rooted with a drive letter, rewrite it using the /cygdrive
+ # mountpoint.
+ local p = [ SUBST $(path:T) $(.windows-drive-letter-re) /cygdrive/$1/$2 ] ;
+
+ # Else if path is rooted without a drive letter, use the working directory.
+ p ?= [ SUBST $(path:T) ^/(.*) /cygdrive/$(.working-drive-letter:L)/$2 ] ;
+
+ # Else return the path unchanged.
+ return $(p:E=$(path:T)) ;
+}
+
+
+# :W only works in Cygwin builds of bjam. This one works on NT builds as well.
+#
+local rule cygwin-to-windows-path ( path )
+{
+ path = $(path:R="") ; # strip any trailing slash
+
+ local drive-letter = [ SUBST $(path) $(.cygwin-drive-letter-re) $1:/$2 ] ;
+ if $(drive-letter)
+ {
+ path = $(drive-letter) ;
+ }
+ else if $(path:R=/x) = $(path) # already rooted?
+ {
+ # Look for a cygwin mount that includes each head sequence in $(path).
+ local head = $(path) ;
+ local tail = "" ;
+
+ while $(head)
+ {
+ local root = [ software-registry-value
+ "Cygnus Solutions\\Cygwin\\mounts v2\\"$(head) : native ] ;
+
+ if $(root)
+ {
+ path = $(tail:R=$(root)) ;
+ head = ;
+ }
+ tail = $(tail:R=$(head:D=)) ;
+
+ if $(head) = /
+ {
+ head = ;
+ }
+ else
+ {
+ head = $(head:D) ;
+ }
+ }
+ }
+ return [ regex.replace $(path:R="") / \\ ] ;
+}
+
+
+# Convert a *nix path to native.
+#
+local rule *nix-path-to-native ( path )
+{
+ if [ os.name ] = NT
+ {
+ path = [ cygwin-to-windows-path $(path) ] ;
+ }
+ return $(path) ;
+}
+
+
+# Convert an NT path to native.
+#
+local rule windows-path-to-native ( path )
+{
+ if [ os.name ] = NT
+ {
+ return $(path) ;
+ }
+ else
+ {
+ return [ windows-to-cygwin-path $(path) ] ;
+ }
+}
+
+
+# Return nonempty if path looks like a windows path, i.e. it starts with a drive
+# letter or contains backslashes.
+#
+local rule guess-windows-path ( path )
+{
+ return [ SUBST $(path) ($(.windows-drive-letter-re)|.*([\\]).*) $1 ] ;
+}
+
+
+local rule path-to-native ( paths * )
+{
+ local result ;
+
+ for local p in $(paths)
+ {
+ if [ guess-windows-path $(p) ]
+ {
+ result += [ windows-path-to-native $(p) ] ;
+ }
+ else
+ {
+ result += [ *nix-path-to-native $(p:T) ] ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Validate the version string and extract the major/minor part we care about.
+#
+local rule split-version ( version )
+{
+ local major-minor = [ MATCH ^([0-9]+)\.([0-9]+)(.*)$ : $(version) : 1 2 3 ] ;
+ if ! $(major-minor[2]) || $(major-minor[3])
+ {
+ ECHO "Warning: \"using python\" expects a two part (major, minor) version number; got" $(version) instead ;
+
+ # Add a zero to account for the missing digit if necessary.
+ major-minor += 0 ;
+ }
+
+ return $(major-minor[1]) $(major-minor[2]) ;
+}
+
+
+# Build a list of versions from 3.0 down to 1.5. Because bjam can not enumerate
+# registry sub-keys, we have no way of finding a version with a 2-digit minor
+# version, e.g. 2.10 -- let us hope that never happens.
+#
+.version-countdown = ;
+for local v in [ numbers.range 15 30 ]
+{
+ .version-countdown = [ SUBST $(v) (.)(.*) $1.$2 ] $(.version-countdown) ;
+}
+
+
+local rule windows-installed-pythons ( version ? )
+{
+ version ?= $(.version-countdown) ;
+ local interpreters ;
+
+ for local v in $(version)
+ {
+ local install-path = [
+ software-registry-value "Python\\PythonCore\\"$(v)"\\InstallPath" ] ;
+
+ if $(install-path)
+ {
+ install-path = [ windows-path-to-native $(install-path) ] ;
+ debug-message Registry indicates Python $(v) installed at \"$(install-path)\" ;
+ }
+
+ interpreters += $(:E=python:R=$(install-path)) ;
+ }
+ return $(interpreters) ;
+}
+
+
+local rule darwin-installed-pythons ( version ? )
+{
+ version ?= $(.version-countdown) ;
+
+ local prefix
+ = [ GLOB /System/Library/Frameworks /Library/Frameworks
+ : Python.framework ] ;
+
+ return $(prefix)/Versions/$(version)/bin/python ;
+}
+
+
+# Assume "python-cmd" invokes a python interpreter and invoke it to extract all
+# the information we care about from its "sys" module. Returns void if
+# unsuccessful.
+#
+local rule probe ( python-cmd )
+{
+ # Avoid invoking a Cygwin symlink on NT.
+ local skip-symlink ;
+ if [ os.name ] = NT
+ {
+ skip-symlink = [ invokes-cygwin-symlink $(python-cmd) ] ;
+ }
+
+ if $(skip-symlink)
+ {
+ debug-message -------------------------------------------------------------------- ;
+ debug-message \"$(python-cmd)\" would attempt to invoke a Cygwin symlink, ;
+ debug-message causing a bjam built for Windows to hang. ;
+ debug-message ;
+ debug-message If you intend to target a Cygwin build of Python, please ;
+ debug-message replace the path to the link with the path to a real executable ;
+ debug-message (guessing: \"$(skip-symlink)\") "in" your 'using python' line ;
+ debug-message "in" user-config.jam or site-config.jam. Do not forget to escape ;
+ debug-message backslashes ;
+ debug-message -------------------------------------------------------------------- ;
+ }
+ else
+ {
+ # Prepare a List of Python format strings and expressions that can be
+ # used to print the constants we want from the sys module.
+
+ # We do not really want sys.version since that is a complicated string,
+ # so get the information from sys.version_info instead.
+ local format = "version=%d.%d" ;
+ local exprs = "version_info[0]" "version_info[1]" ;
+
+ for local s in $(sys-elements[2-])
+ {
+ format += $(s)=%s ;
+ exprs += $(s) ;
+ }
+
+ # Invoke Python and ask it for all those values.
+ if [ version.check-jam-version 3 1 17 ] || ( [ os.name ] != NT )
+ {
+ # Prior to version 3.1.17 Boost Jam's SHELL command did not support
+ # quoted commands correctly on Windows. This means that on that
+ # platform we do not support using a Python command interpreter
+ # executable whose path contains a space character.
+ python-cmd = \"$(python-cmd)\" ;
+ }
+ local full-cmd =
+ $(python-cmd)" -c \"from sys import *; print('"$(format:J=\\n)"' % ("$(exprs:J=,)"))\"" ;
+
+ local output = [ shell-cmd $(full-cmd) ] ;
+ if $(output)
+ {
+ # Parse the output to get all the results.
+ local nl = "
+
+" ;
+ for s in $(sys-elements)
+ {
+ # These variables are expected to be declared local in the
+ # caller, so Jam's dynamic scoping will set their values there.
+ sys.$(s) = [ SUBST $(output) \\<$(s)=([^$(nl)]+) $1 ] ;
+ }
+ }
+ return $(output) ;
+ }
+}
+
+
+# Make sure the "libraries" and "includes" variables (in an enclosing scope)
+# have a value based on the information given.
+#
+local rule compute-default-paths ( target-os : version ? : prefix ? :
+ exec-prefix ? )
+{
+ exec-prefix ?= $(prefix) ;
+
+ if $(target-os) = windows
+ {
+ # The exec_prefix is where you're supposed to look for machine-specific
+ # libraries.
+ local default-library-path = $(exec-prefix)\\libs ;
+ local default-include-path = $(:E=Include:R=$(prefix)) ;
+
+ # If the interpreter was found in a directory called "PCBuild" or
+ # "PCBuild8," assume we're looking at a Python built from the source
+ # distro, and go up one additional level to the default root. Otherwise,
+ # the default root is the directory where the interpreter was found.
+
+ # We ask Python itself what the executable path is in case of
+ # intermediate symlinks or shell scripts.
+ local executable-dir = $(sys.executable:D) ;
+
+ if [ MATCH ^(PCBuild) : $(executable-dir:D=) ]
+ {
+ debug-message "This Python appears to reside in a source distribution;" ;
+ debug-message "prepending \""$(executable-dir)"\" to default library search path" ;
+
+ default-library-path = $(executable-dir) $(default-library-path) ;
+
+ default-include-path = $(:E=PC:R=$(executable-dir:D)) $(default-include-path) ;
+
+ debug-message "and \""$(default-include-path[1])"\" to default #include path" ;
+ }
+
+ libraries ?= $(default-library-path) ;
+ includes ?= $(default-include-path) ;
+ }
+ else
+ {
+ includes ?= $(prefix)/include/python$(version) ;
+
+ local lib = $(exec-prefix)/lib ;
+ libraries ?= $(lib)/python$(version)/config $(lib) ;
+ }
+}
+
+# The version of the python interpreter to use.
+feature.feature python : : propagated ;
+feature.feature python.interpreter : : free ;
+
+toolset.flags python.capture-output PYTHON : <python.interpreter> ;
+
+#
+# Support for Python configured --with-pydebug
+#
+feature.feature python-debugging : off on : propagated ;
+builtin.variant debug-python : debug : <python-debugging>on ;
+
+
+# Return a list of candidate commands to try when looking for a Python
+# interpreter. prefix is expected to be a native path.
+#
+local rule candidate-interpreters ( version ? : prefix ? : target-os )
+{
+ local bin-path = bin ;
+ if $(target-os) = windows
+ {
+ # On Windows, look in the root directory itself and, to work with the
+ # result of a build-from-source, the PCBuild directory.
+ bin-path = PCBuild8 PCBuild "" ;
+ }
+
+ bin-path = $(bin-path:R=$(prefix)) ;
+
+ if $(target-os) in windows darwin
+ {
+ return # Search:
+ $(:E=python:R=$(bin-path)) # Relative to the prefix, if any
+ python # In the PATH
+ [ $(target-os)-installed-pythons $(version) ] # Standard install locations
+ ;
+ }
+ else
+ {
+ # Search relative to the prefix, or if none supplied, in PATH.
+ local unversioned = $(:E=python:R=$(bin-path:E=)) ;
+
+ # If a version was specified, look for a python with that specific
+ # version appended before looking for one called, simply, "python"
+ return $(unversioned)$(version) $(unversioned) ;
+ }
+}
+
+
+# Compute system library dependencies for targets linking with static Python
+# libraries.
+#
+# On many systems, Python uses libraries such as pthreads or libdl. Since static
+# libraries carry no library dependency information of their own that the linker
+# can extract, these extra dependencies have to be given explicitly on the link
+# line of the client. The information about these dependencies is packaged into
+# the "python" target below.
+#
+# Even where Python itself uses pthreads, it never allows extension modules to
+# be entered concurrently (unless they explicitly give up the interpreter lock).
+# Therefore, extension modules do not need the efficiency overhead of threadsafe
+# code as produced by <threading>multi, and we handle libpthread along with
+# other libraries here. Note: this optimization is based on an assumption that
+# the compiler generates link-compatible code in both the single- and
+# multi-threaded cases, and that system libraries do not change their ABIs
+# either.
+#
+# Returns a list of usage-requirements that link to the necessary system
+# libraries.
+#
+local rule system-library-dependencies ( target-os )
+{
+ switch $(target-os)
+ {
+ case s[uo][nl]* : # solaris, sun, sunos
+ # Add a librt dependency for the gcc toolset on SunOS (the sun
+ # toolset adds -lrt unconditionally). While this appears to
+ # duplicate the logic already in gcc.jam, it does not as long as
+ # we are not forcing <threading>multi.
+
+ # On solaris 10, distutils.sysconfig.get_config_var('LIBS') yields
+ # '-lresolv -lsocket -lnsl -lrt -ldl'. However, that does not seem
+ # to be the right list for extension modules. For example, on my
+ # installation, adding -ldl causes at least one test to fail because
+ # the library can not be found and removing it causes no failures.
+
+ # Apparently, though, we need to add -lrt for gcc.
+ return <toolset>gcc:<library>rt ;
+
+ case osf : return <library>pthread <toolset>gcc:<library>rt ;
+
+ case qnx* : return ;
+ case darwin : return ;
+ case windows : return ;
+
+ case hpux : return <library>rt ;
+ case *bsd : return <library>pthread <toolset>gcc:<library>util ;
+
+ case aix : return <library>pthread <library>dl ;
+
+ case * : return <library>pthread <library>dl
+ <toolset>gcc:<library>util <toolset-intel:platform>linux:<library>util ;
+ }
+}
+
+
+# Declare a target to represent Python's library.
+#
+local rule declare-libpython-target ( version ? : requirements * )
+{
+ # Compute the representation of Python version in the name of Python's
+ # library file.
+ local lib-version = $(version) ;
+ if <target-os>windows in $(requirements)
+ {
+ local major-minor = [ split-version $(version) ] ;
+ lib-version = $(major-minor:J="") ;
+ if <python-debugging>on in $(requirements)
+ {
+ lib-version = $(lib-version)_d ;
+ }
+ }
+
+ if ! $(lib-version)
+ {
+ ECHO *** warning: could not determine Python version, which will ;
+ ECHO *** warning: probably prevent us from linking with the python ;
+ ECHO *** warning: library. Consider explicitly passing the version ;
+ ECHO *** warning: to 'using python'. ;
+ }
+
+ # Declare it.
+ lib python.lib : : <name>python$(lib-version) $(requirements) ;
+}
+
+
+# Implementation of init.
+local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
+ condition * : extension-suffix ? )
+{
+ local prefix ;
+ local exec-prefix ;
+ local cmds-to-try ;
+ local interpreter-cmd ;
+
+ local target-os = [ feature.get-values target-os : $(condition) ] ;
+ target-os ?= [ feature.defaults target-os ] ;
+ target-os = $(target-os:G=) ;
+
+ if $(target-os) = windows && <python-debugging>on in $(condition)
+ {
+ extension-suffix ?= _d ;
+ }
+ extension-suffix ?= "" ;
+
+ # Normalize and dissect any version number.
+ local major-minor ;
+ if $(version)
+ {
+ major-minor = [ split-version $(version) ] ;
+ version = $(major-minor:J=.) ;
+ }
+
+ local cmds-to-try ;
+
+ if ! $(cmd-or-prefix) || [ GLOB $(cmd-or-prefix) : * ]
+ {
+ # If the user did not pass a command, whatever we got was a prefix.
+ prefix = $(cmd-or-prefix) ;
+ cmds-to-try = [ candidate-interpreters $(version) : $(prefix) : $(target-os) ] ;
+ }
+ else
+ {
+ # Work with the command the user gave us.
+ cmds-to-try = $(cmd-or-prefix) ;
+
+ # On Windows, do not nail down the interpreter command just yet in case
+ # the user specified something that turns out to be a cygwin symlink,
+ # which could bring down bjam if we invoke it.
+ if $(target-os) != windows
+ {
+ interpreter-cmd = $(cmd-or-prefix) ;
+ }
+ }
+
+ # Values to use in case we can not really find anything in the system.
+ local fallback-cmd = $(cmds-to-try[1]) ;
+ local fallback-version ;
+
+ # Anything left to find or check?
+ if ! ( $(interpreter-cmd) && $(includes) && $(libraries) )
+ {
+ # Values to be extracted from python's sys module. These will be set by
+ # the probe rule, above, using Jam's dynamic scoping.
+ local sys-elements = version platform prefix exec_prefix executable ;
+ local sys.$(sys-elements) ;
+
+ # Compute the string Python's sys.platform needs to match. If not
+ # targeting Windows or cygwin we will assume only native builds can
+ # possibly run, so we will not require a match and we leave sys.platform
+ # blank.
+ local platform ;
+ switch $(target-os)
+ {
+ case windows : platform = win32 ;
+ case cygwin : platform = cygwin ;
+ }
+
+ while $(cmds-to-try)
+ {
+ # Pop top command.
+ local cmd = $(cmds-to-try[1]) ;
+ cmds-to-try = $(cmds-to-try[2-]) ;
+
+ debug-message Checking interpreter command \"$(cmd)\"... ;
+ if [ probe $(cmd) ]
+ {
+ fallback-version ?= $(sys.version) ;
+
+ # Check for version/platform validity.
+ for local x in version platform
+ {
+ if $($(x)) && $($(x)) != $(sys.$(x))
+ {
+ debug-message ...$(x) "mismatch (looking for"
+ $($(x)) but found $(sys.$(x))")" ;
+ cmd = ;
+ }
+ }
+
+ if $(cmd)
+ {
+ debug-message ...requested configuration matched! ;
+
+ exec-prefix = $(sys.exec_prefix) ;
+
+ compute-default-paths $(target-os) : $(sys.version) :
+ $(sys.prefix) : $(sys.exec_prefix) ;
+
+ version = $(sys.version) ;
+ interpreter-cmd ?= $(cmd) ;
+ cmds-to-try = ; # All done.
+ }
+ }
+ else
+ {
+ debug-message ...does not invoke a working interpreter ;
+ }
+ }
+ }
+
+ # Anything left to compute?
+ if $(includes) && $(libraries)
+ {
+ .configured = true ;
+ }
+ else
+ {
+ version ?= $(fallback-version) ;
+ version ?= 2.5 ;
+ exec-prefix ?= $(prefix) ;
+ compute-default-paths $(target-os) : $(version) : $(prefix:E=) ;
+ }
+
+ if ! $(interpreter-cmd)
+ {
+ fallback-cmd ?= python ;
+ debug-message No working Python interpreter found. ;
+ if [ os.name ] != NT || ! [ invokes-cygwin-symlink $(fallback-cmd) ]
+ {
+ interpreter-cmd = $(fallback-cmd) ;
+ debug-message falling back to \"$(interpreter-cmd)\" ;
+ }
+ }
+
+ includes = [ path-to-native $(includes) ] ;
+ libraries = [ path-to-native $(libraries) ] ;
+
+ debug-message "Details of this Python configuration:" ;
+ debug-message " interpreter command:" \"$(interpreter-cmd:E=<empty>)\" ;
+ debug-message " include path:" \"$(includes:E=<empty>)\" ;
+ debug-message " library path:" \"$(libraries:E=<empty>)\" ;
+ if $(target-os) = windows
+ {
+ debug-message " DLL search path:" \"$(exec-prefix:E=<empty>)\" ;
+ }
+
+ #
+ # End autoconfiguration sequence.
+ #
+ local target-requirements = $(condition) ;
+
+ # Add the version, if any, to the target requirements.
+ if $(version)
+ {
+ if ! $(version) in [ feature.values python ]
+ {
+ feature.extend python : $(version) ;
+ }
+ target-requirements += <python>$(version:E=default) ;
+ }
+
+ target-requirements += <target-os>$(target-os) ;
+
+ # See if we can find a framework directory on darwin.
+ local framework-directory ;
+ if $(target-os) = darwin
+ {
+ # Search upward for the framework directory.
+ local framework-directory = $(libraries[-1]) ;
+ while $(framework-directory:D=) && $(framework-directory:D=) != Python.framework
+ {
+ framework-directory = $(framework-directory:D) ;
+ }
+
+ if $(framework-directory:D=) = Python.framework
+ {
+ debug-message framework directory is \"$(framework-directory)\" ;
+ }
+ else
+ {
+ debug-message "no framework directory found; using library path" ;
+ framework-directory = ;
+ }
+ }
+
+ local dll-path = $(libraries) ;
+
+ # Make sure that we can find the Python DLL on Windows.
+ if ( $(target-os) = windows ) && $(exec-prefix)
+ {
+ dll-path += $(exec-prefix) ;
+ }
+
+ #
+ # Prepare usage requirements.
+ #
+ local usage-requirements = [ system-library-dependencies $(target-os) ] ;
+ usage-requirements += <include>$(includes) <python.interpreter>$(interpreter-cmd) ;
+ if <python-debugging>on in $(condition)
+ {
+ if $(target-os) = windows
+ {
+ # In pyconfig.h, Py_DEBUG is set if _DEBUG is set. If we define
+ # Py_DEBUG we will get multiple definition warnings.
+ usage-requirements += <define>_DEBUG ;
+ }
+ else
+ {
+ usage-requirements += <define>Py_DEBUG ;
+ }
+ }
+
+ # Global, but conditional, requirements to give access to the interpreter
+ # for general utilities, like other toolsets, that run Python scripts.
+ toolset.add-requirements
+ $(target-requirements:J=,):<python.interpreter>$(interpreter-cmd) ;
+
+ # Register the right suffix for extensions.
+ register-extension-suffix $(extension-suffix) : $(target-requirements) ;
+
+ #
+ # Declare the "python" target. This should really be called
+ # python_for_embedding.
+ #
+
+ if $(framework-directory)
+ {
+ alias python
+ :
+ : $(target-requirements)
+ :
+ : $(usage-requirements) <framework>$(framework-directory)
+ ;
+ }
+ else
+ {
+ declare-libpython-target $(version) : $(target-requirements) ;
+
+ # This is an evil hack. On, Windows, when Python is embedded, nothing
+ # seems to set up sys.path to include Python's standard library
+ # (http://article.gmane.org/gmane.comp.python.general/544986). The evil
+ # here, aside from the workaround necessitated by Python's bug, is that:
+ #
+ # a. we're guessing the location of the python standard library from the
+ # location of pythonXX.lib
+ #
+ # b. we're hijacking the <testing.launcher> property to get the
+ # environment variable set up, and the user may want to use it for
+ # something else (e.g. launch the debugger).
+ local set-PYTHONPATH ;
+ if $(target-os) = windows
+ {
+ set-PYTHONPATH = [ common.prepend-path-variable-command PYTHONPATH :
+ $(libraries:D)/Lib ] ;
+ }
+
+ alias python
+ :
+ : $(target-requirements)
+ :
+ # Why python.lib must be listed here instead of along with the
+ # system libs is a mystery, but if we do not do it, on cygwin,
+ # -lpythonX.Y never appears in the command line (although it does on
+ # linux).
+ : $(usage-requirements)
+ <testing.launcher>$(set-PYTHONPATH)
+ <library-path>$(libraries) <dll-path>$(dll-path) <library>python.lib
+ ;
+ }
+
+ # On *nix, we do not want to link either Boost.Python or Python extensions
+ # to libpython, because the Python interpreter itself provides all those
+ # symbols. If we linked to libpython, we would get duplicate symbols. So
+ # declare two targets -- one for building extensions and another for
+ # embedding.
+ #
+ # Unlike most *nix systems, Mac OS X's linker does not permit undefined
+ # symbols when linking a shared library. So, we still need to link against
+ # the Python framework, even when building extensions. Note that framework
+ # builds of Python always use shared libraries, so we do not need to worry
+ # about duplicate Python symbols.
+ if $(target-os) in windows cygwin darwin
+ {
+ alias python_for_extensions : python : $(target-requirements) ;
+ }
+ # On AIX we need Python extensions and Boost.Python to import symbols from
+ # the Python interpreter. Dynamic libraries opened with dlopen() do not
+ # inherit the symbols from the Python interpreter.
+ else if $(target-os) = aix
+ {
+ alias python_for_extensions
+ :
+ : $(target-requirements)
+ :
+ : $(usage-requirements) <linkflags>-Wl,-bI:$(libraries[1])/python.exp
+ ;
+ }
+ else
+ {
+ alias python_for_extensions
+ :
+ : $(target-requirements)
+ :
+ : $(usage-requirements)
+ ;
+ }
+}
+
+
+rule configured ( )
+{
+ return $(.configured) ;
+}
+
+
+type.register PYTHON_EXTENSION : : SHARED_LIB ;
+
+
+local rule register-extension-suffix ( root : condition * )
+{
+ local suffix ;
+
+ switch [ feature.get-values target-os : $(condition) ]
+ {
+ case windows : suffix = pyd ;
+ case cygwin : suffix = dll ;
+ case hpux :
+ {
+ if [ feature.get-values python : $(condition) ] in 1.5 1.6 2.0 2.1 2.2 2.3 2.4
+ {
+ suffix = sl ;
+ }
+ else
+ {
+ suffix = so ;
+ }
+ }
+ case * : suffix = so ;
+ }
+
+ type.set-generated-target-suffix PYTHON_EXTENSION : $(condition) : <$(root).$(suffix)> ;
+}
+
+
+# Unset 'lib' prefix for PYTHON_EXTENSION
+type.set-generated-target-prefix PYTHON_EXTENSION : : "" ;
+
+
+rule python-extension ( name : sources * : requirements * : default-build * :
+ usage-requirements * )
+{
+ if [ configured ]
+ {
+ requirements += <use>/python//python_for_extensions ;
+ }
+ requirements += <suppress-import-lib>true ;
+
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new typed-target $(name) : $(project) : PYTHON_EXTENSION
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+}
+
+IMPORT python : python-extension : : python-extension ;
+
+rule py2to3
+{
+ common.copy $(>) $(<) ;
+ 2to3 $(<) ;
+}
+
+actions 2to3
+{
+ 2to3 -wn "$(<)"
+ 2to3 -dwn "$(<)"
+}
+
+
+# Support for testing.
+type.register PY : py ;
+type.register RUN_PYD_OUTPUT ;
+type.register RUN_PYD : : TEST ;
+
+
+class python-test-generator : generator
+{
+ import set ;
+
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ self.composing = true ;
+ }
+
+ rule run ( project name ? : property-set : sources * : multiple ? )
+ {
+ local pyversion = [ $(property-set).get <python> ] ;
+ local python ;
+ local other-pythons ;
+
+ # Make new target that converting Python source by 2to3 when running with Python 3.
+ local rule make-2to3-source ( source )
+ {
+ if $(pyversion) >= 3.0
+ {
+ local a = [ new action $(source) : python.py2to3 : $(property-set) ] ;
+ local t = [ utility.basename [ $(s).name ] ] ;
+ local p = [ new file-target $(t) : PY : $(project) : $(a) ] ;
+ return $(p) ;
+ }
+ else
+ {
+ return $(source) ;
+ }
+ }
+
+ for local s in $(sources)
+ {
+ if [ $(s).type ] = PY
+ {
+ if ! $(python)
+ {
+ # First Python source ends up on command line.
+ python = [ make-2to3-source $(s) ] ;
+
+ }
+ else
+ {
+ # Other Python sources become dependencies.
+ other-pythons += [ make-2to3-source $(s) ] ;
+ }
+ }
+ }
+
+ local extensions ;
+ for local s in $(sources)
+ {
+ if [ $(s).type ] = PYTHON_EXTENSION
+ {
+ extensions += $(s) ;
+ }
+ }
+
+ local libs ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] LIB ]
+ && ! $(s) in $(extensions)
+ {
+ libs += $(s) ;
+ }
+ }
+
+ local new-sources ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] CPP ]
+ {
+ local name = [ utility.basename [ $(s).name ] ] ;
+ if $(name) = [ utility.basename [ $(python).name ] ]
+ {
+ name = $(name)_ext ;
+ }
+ local extension = [ generators.construct $(project) $(name) :
+ PYTHON_EXTENSION : $(property-set) : $(s) $(libs) ] ;
+
+ # The important part of usage requirements returned from
+ # PYTHON_EXTENSION generator are xdll-path properties that will
+ # allow us to find the python extension at runtime.
+ property-set = [ $(property-set).add $(extension[1]) ] ;
+
+ # Ignore usage requirements. We're a top-level generator and
+ # nobody is going to use what we generate.
+ new-sources += $(extension[2-]) ;
+ }
+ }
+
+ property-set = [ $(property-set).add-raw <dependency>$(other-pythons) ] ;
+
+ result = [ construct-result $(python) $(extensions) $(new-sources) :
+ $(project) $(name) : $(property-set) ] ;
+ }
+}
+
+
+generators.register
+ [ new python-test-generator python.capture-output : : RUN_PYD_OUTPUT ] ;
+
+generators.register-standard testing.expect-success
+ : RUN_PYD_OUTPUT : RUN_PYD ;
+
+
+# There are two different ways of spelling OS names. One is used for [ os.name ]
+# and the other is used for the <host-os> and <target-os> properties. Until that
+# is remedied, this sets up a crude mapping from the latter to the former, that
+# will work *for the purposes of cygwin/NT cross-builds only*. Could not think
+# of a better name than "translate".
+#
+.translate-os-windows = NT ;
+.translate-os-cygwin = CYGWIN ;
+local rule translate-os ( src-os )
+{
+ local x = $(.translate-os-$(src-os)) [ os.name ] ;
+ return $(x[1]) ;
+}
+
+
+# Extract the path to a single ".pyd" source. This is used to build the
+# PYTHONPATH for running bpl tests.
+#
+local rule pyd-pythonpath ( source )
+{
+ return [ on $(source) return $(LOCATE) $(SEARCH) ] ;
+}
+
+
+# The flag settings on testing.capture-output do not apply to python.capture
+# output at the moment. Redo this explicitly.
+toolset.flags python.capture-output ARGS <testing.arg> ;
+
+
+rule capture-output ( target : sources * : properties * )
+{
+ # Setup up a proper DLL search path. Here, $(sources[1]) is a python module
+ # and $(sources[2]) is a DLL. Only $(sources[1]) is passed to
+ # testing.capture-output, so RUN_PATH variable on $(sources[2]) is not
+ # consulted. Move it over explicitly.
+ RUN_PATH on $(sources[1]) = [ on $(sources[2-]) return $(RUN_PATH) ] ;
+
+ PYTHONPATH = [ sequence.transform pyd-pythonpath : $(sources[2-]) ] ;
+ PYTHONPATH += [ feature.get-values pythonpath : $(properties) ] ;
+
+ # After test is run, we remove the Python module, but not the Python script.
+ testing.capture-output $(target) : $(sources[1]) : $(properties) :
+ $(sources[2-]) ;
+
+ # PYTHONPATH is different; it will be interpreted by whichever Python is
+ # invoked and so must follow path rules for the target os. The only OSes
+ # where we can run python for other OSes currently are NT and CYGWIN so we
+ # only need to handle those cases.
+ local target-os = [ feature.get-values target-os : $(properties) ] ;
+ # Oddly, host-os is not in properties, so grab the default value.
+ local host-os = [ feature.defaults host-os ] ;
+ host-os = $(host-os:G=) ;
+ if $(target-os) != $(host-os)
+ {
+ PYTHONPATH = [ sequence.transform $(host-os)-to-$(target-os)-path :
+ $(PYTHONPATH) ] ;
+ }
+ local path-separator = [ os.path-separator [ translate-os $(target-os) ] ] ;
+ local set-PYTHONPATH = [ common.variable-setting-command PYTHONPATH :
+ $(PYTHONPATH:J=$(path-separator)) ] ;
+ LAUNCHER on $(target) = $(set-PYTHONPATH) [ on $(target) return \"$(PYTHON)\" ] ;
+}
+
+
+rule bpl-test ( name : sources * : requirements * )
+{
+ local s ;
+ sources ?= $(name).py $(name).cpp ;
+ return [ testing.make-test run-pyd : $(sources) /boost/python//boost_python
+ : $(requirements) : $(name) ] ;
+}
+
+
+IMPORT $(__name__) : bpl-test : : bpl-test ;
diff --git a/tools/build/v2/tools/qcc.jam b/tools/build/v2/tools/qcc.jam
new file mode 100644
index 0000000000..4f2a4fc14f
--- /dev/null
+++ b/tools/build/v2/tools/qcc.jam
@@ -0,0 +1,236 @@
+# Copyright (c) 2001 David Abrahams.
+# Copyright (c) 2002-2003 Rene Rivera.
+# Copyright (c) 2002-2003 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import "class" : new ;
+import common ;
+import errors ;
+import feature ;
+import generators ;
+import os ;
+import property ;
+import set ;
+import toolset ;
+import type ;
+import unix ;
+
+feature.extend toolset : qcc ;
+
+toolset.inherit-generators qcc : unix : unix.link unix.link.dll ;
+generators.override builtin.lib-generator : qcc.prebuilt ;
+toolset.inherit-flags qcc : unix ;
+toolset.inherit-rules qcc : unix ;
+
+# Initializes the qcc toolset for the given version. If necessary, command may
+# be used to specify where the compiler is located. The parameter 'options' is a
+# space-delimited list of options, each one being specified as
+# <option-name>option-value. Valid option names are: cxxflags, linkflags and
+# linker-type. Accepted values for linker-type are gnu and sun, gnu being the
+# default.
+#
+# Example:
+# using qcc : 3.4 : : <cxxflags>foo <linkflags>bar <linker-type>sun ;
+#
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters qcc : version $(version) ] ;
+ local command = [ common.get-invocation-command qcc : QCC : $(command) ] ;
+ common.handle-options qcc : $(condition) : $(command) : $(options) ;
+}
+
+
+generators.register-c-compiler qcc.compile.c++ : CPP : OBJ : <toolset>qcc ;
+generators.register-c-compiler qcc.compile.c : C : OBJ : <toolset>qcc ;
+generators.register-c-compiler qcc.compile.asm : ASM : OBJ : <toolset>qcc ;
+
+
+# Declare flags for compilation.
+toolset.flags qcc.compile OPTIONS <debug-symbols>on : -gstabs+ ;
+
+# Declare flags and action for compilation.
+toolset.flags qcc.compile OPTIONS <optimization>off : -O0 ;
+toolset.flags qcc.compile OPTIONS <optimization>speed : -O3 ;
+toolset.flags qcc.compile OPTIONS <optimization>space : -Os ;
+
+toolset.flags qcc.compile OPTIONS <inlining>off : -Wc,-fno-inline ;
+toolset.flags qcc.compile OPTIONS <inlining>on : -Wc,-Wno-inline ;
+toolset.flags qcc.compile OPTIONS <inlining>full : -Wc,-finline-functions -Wc,-Wno-inline ;
+
+toolset.flags qcc.compile OPTIONS <warnings>off : -w ;
+toolset.flags qcc.compile OPTIONS <warnings>all : -Wc,-Wall ;
+toolset.flags qcc.compile OPTIONS <warnings-as-errors>on : -Wc,-Werror ;
+
+toolset.flags qcc.compile OPTIONS <profiling>on : -p ;
+
+toolset.flags qcc.compile OPTIONS <cflags> ;
+toolset.flags qcc.compile.c++ OPTIONS <cxxflags> ;
+toolset.flags qcc.compile DEFINES <define> ;
+toolset.flags qcc.compile INCLUDES <include> ;
+
+toolset.flags qcc.compile OPTIONS <link>shared : -shared ;
+
+toolset.flags qcc.compile.c++ TEMPLATE_DEPTH <c++-template-depth> ;
+
+
+rule compile.c++
+{
+ # Here we want to raise the template-depth parameter value to something
+ # higher than the default value of 17. Note that we could do this using the
+ # feature.set-default rule but we do not want to set the default value for
+ # all toolsets as well.
+ #
+ # TODO: This 'modified default' has been inherited from some 'older Boost
+ # Build implementation' and has most likely been added to make some Boost
+ # library parts compile correctly. We should see what exactly prompted this
+ # and whether we can get around the problem more locally.
+ local template-depth = [ on $(1) return $(TEMPLATE_DEPTH) ] ;
+ if ! $(template-depth)
+ {
+ TEMPLATE_DEPTH on $(1) = 128 ;
+ }
+}
+
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" -Wc,-ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.asm
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+
+# The class checking that we do not try to use the <runtime-link>static property
+# while creating or using a shared library, since it is not supported by qcc/
+# /libc.
+#
+class qcc-linking-generator : unix-linking-generator
+{
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ if <runtime-link>static in [ $(property-set).raw ]
+ {
+ local m ;
+ if [ id ] = "qcc.link.dll"
+ {
+ m = "on qcc, DLL can't be build with <runtime-link>static" ;
+ }
+ if ! $(m)
+ {
+ for local s in $(sources)
+ {
+ local type = [ $(s).type ] ;
+ if $(type) && [ type.is-derived $(type) SHARED_LIB ]
+ {
+ m = "on qcc, using DLLS together with the <runtime-link>static options is not possible " ;
+ }
+ }
+ }
+ if $(m)
+ {
+ errors.user-error $(m) : "It is suggested to use"
+ "<runtime-link>static together with <link>static." ;
+ }
+ }
+
+ return [ unix-linking-generator.generated-targets
+ $(sources) : $(property-set) : $(project) $(name) ] ;
+ }
+}
+
+generators.register [ new qcc-linking-generator qcc.link : LIB OBJ : EXE
+ : <toolset>qcc ] ;
+
+generators.register [ new qcc-linking-generator qcc.link.dll : LIB OBJ
+ : SHARED_LIB : <toolset>qcc ] ;
+
+generators.override qcc.prebuilt : builtin.prebuilt ;
+generators.override qcc.searched-lib-generator : searched-lib-generator ;
+
+
+# Declare flags for linking.
+# First, the common flags.
+toolset.flags qcc.link OPTIONS <debug-symbols>on : -gstabs+ ;
+toolset.flags qcc.link OPTIONS <profiling>on : -p ;
+toolset.flags qcc.link OPTIONS <linkflags> ;
+toolset.flags qcc.link LINKPATH <library-path> ;
+toolset.flags qcc.link FINDLIBS-ST <find-static-library> ;
+toolset.flags qcc.link FINDLIBS-SA <find-shared-library> ;
+toolset.flags qcc.link LIBRARIES <library-file> ;
+
+toolset.flags qcc.link FINDLIBS-SA : m ;
+
+# For <runtime-link>static we made sure there are no dynamic libraries in the
+# link.
+toolset.flags qcc.link OPTIONS <runtime-link>static : -static ;
+
+# Assuming this is just like with gcc.
+toolset.flags qcc.link RPATH : <dll-path> : unchecked ;
+toolset.flags qcc.link RPATH_LINK : <xdll-path> : unchecked ;
+
+
+# Declare actions for linking.
+#
+rule link ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+ # Serialize execution of the 'link' action, since running N links in
+ # parallel is just slower. For now, serialize only qcc links while it might
+ # be a good idea to serialize all links.
+ JAM_SEMAPHORE on $(targets) = <s>qcc-link-semaphore ;
+}
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-ST) -l$(FINDLIBS-SA) $(OPTIONS)
+}
+
+
+# Always remove archive and start again. Here is the rationale from Andre Hentz:
+# I had a file, say a1.c, that was included into liba.a. I moved a1.c to a2.c,
+# updated my Jamfiles and rebuilt. My program was crashing with absurd errors.
+# After some debugging I traced it back to the fact that a1.o was *still* in
+# liba.a
+RM = [ common.rm-command ] ;
+if [ os.name ] = NT
+{
+ RM = "if exist \"$(<[1])\" DEL \"$(<[1])\"" ;
+}
+
+
+# Declare action for creating static libraries. The 'r' letter means to add
+# files to the archive with replacement. Since we remove the archive, we do not
+# care about replacement, but there is no option to "add without replacement".
+# The 'c' letter suppresses warnings in case the archive does not exists yet.
+# That warning is produced only on some platforms, for whatever reasons.
+#
+actions piecemeal archive
+{
+ $(RM) "$(<)"
+ ar rc "$(<)" "$(>)"
+}
+
+
+rule link.dll ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+ JAM_SEMAPHORE on $(targets) = <s>qcc-link-semaphore ;
+}
+
+
+# Differ from 'link' above only by -shared.
+#
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -o "$(<)" $(HAVE_SONAME)-Wl,-h$(SPACE)-Wl,$(<[1]:D=) -shared "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-ST) -l$(FINDLIBS-SA) $(OPTIONS)
+}
diff --git a/tools/build/v2/tools/qt.jam b/tools/build/v2/tools/qt.jam
new file mode 100644
index 0000000000..8aa7ca266c
--- /dev/null
+++ b/tools/build/v2/tools/qt.jam
@@ -0,0 +1,17 @@
+# Copyright (c) 2006 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Forwarning toolset file to Qt GUI library. Forwards to the toolset file
+# for the current version of Qt.
+
+import qt4 ;
+
+rule init ( prefix : full_bin ? : full_inc ? : full_lib ? : version ? : condition * )
+{
+ qt4.init $(prefix) : $(full_bin) : $(full_inc) : $(full_lib) : $(version) : $(condition) ;
+}
+
+
diff --git a/tools/build/v2/tools/qt3.jam b/tools/build/v2/tools/qt3.jam
new file mode 100644
index 0000000000..f82cf0ac33
--- /dev/null
+++ b/tools/build/v2/tools/qt3.jam
@@ -0,0 +1,209 @@
+# Copyright 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Support for the Qt GUI library version 3
+# (http://www.trolltech.com/products/qt3/index.html).
+# For new developments, it is recommended to use Qt4 via the qt4 Boost.Build
+# module.
+
+import modules ;
+import feature ;
+import errors ;
+import type ;
+import "class" : new ;
+import generators ;
+import project ;
+import toolset : flags ;
+
+# Convert this module into a project, so that we can declare targets here.
+project.initialize $(__name__) ;
+project qt3 ;
+
+
+# Initialized the QT support module. The 'prefix' parameter tells where QT is
+# installed. When not given, environmental variable QTDIR should be set.
+#
+rule init ( prefix ? )
+{
+ if ! $(prefix)
+ {
+ prefix = [ modules.peek : QTDIR ] ;
+ if ! $(prefix)
+ {
+ errors.error
+ "QT installation prefix not given and QTDIR variable is empty" ;
+ }
+ }
+
+ if $(.initialized)
+ {
+ if $(prefix) != $(.prefix)
+ {
+ errors.error
+ "Attempt the reinitialize QT with different installation prefix" ;
+ }
+ }
+ else
+ {
+ .initialized = true ;
+ .prefix = $(prefix) ;
+
+ generators.register-standard qt3.moc : H : CPP(moc_%) : <allow>qt3 ;
+ # Note: the OBJ target type here is fake, take a look at
+ # qt4.jam/uic-h-generator for explanations that apply in this case as
+ # well.
+ generators.register [ new moc-h-generator-qt3
+ qt3.moc.cpp : MOCCABLE_CPP : OBJ : <allow>qt3 ] ;
+
+ # The UI type is defined in types/qt.jam, and UIC_H is only used in
+ # qt.jam, but not in qt4.jam, so define it here.
+ type.register UIC_H : : H ;
+
+ generators.register-standard qt3.uic-h : UI : UIC_H : <allow>qt3 ;
+
+ # The following generator is used to convert UI files to CPP. It creates
+ # UIC_H from UI, and constructs CPP from UI/UIC_H. In addition, it also
+ # returns UIC_H target, so that it can be mocced.
+ class qt::uic-cpp-generator : generator
+ {
+ rule __init__ ( )
+ {
+ generator.__init__ qt3.uic-cpp : UI UIC_H : CPP : <allow>qt3 ;
+ }
+
+ rule run ( project name ? : properties * : sources + )
+ {
+ # Consider this:
+ # obj test : test_a.cpp : <optimization>off ;
+ #
+ # This generator will somehow be called in this case, and,
+ # will fail -- which is okay. However, if there are <library>
+ # properties they will be converted to sources, so the size of
+ # 'sources' will be more than 1. In this case, the base generator
+ # will just crash -- and that's not good. Just use a quick test
+ # here.
+
+ local result ;
+ if ! $(sources[2])
+ {
+ # Construct CPP as usual
+ result = [ generator.run $(project) $(name)
+ : $(properties) : $(sources) ] ;
+
+ # If OK, process UIC_H with moc. It's pretty clear that
+ # the object generated with UIC will have Q_OBJECT macro.
+ if $(result)
+ {
+ local action = [ $(result[1]).action ] ;
+ local sources = [ $(action).sources ] ;
+ local mocced = [ generators.construct $(project) $(name)
+ : CPP : $(properties) : $(sources[2]) ] ;
+ result += $(mocced[2-]) ;
+ }
+ }
+
+ return $(result) ;
+ }
+ }
+
+ generators.register [ new qt::uic-cpp-generator ] ;
+
+ # Finally, declare prebuilt target for QT library.
+ local usage-requirements =
+ <include>$(.prefix)/include
+ <dll-path>$(.prefix)/lib
+ <library-path>$(.prefix)/lib
+ <allow>qt3
+ ;
+ lib qt : : <name>qt-mt <threading>multi : : $(usage-requirements) ;
+ lib qt : : <name>qt <threading>single : : $(usage-requirements) ;
+ }
+}
+
+class moc-h-generator-qt3 : generator
+{
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * )
+ {
+ if ! $(sources[2]) && [ $(sources[1]).type ] = MOCCABLE_CPP
+ {
+ name = [ $(sources[1]).name ] ;
+ name = $(name:B) ;
+
+ local a = [ new action $(sources[1]) : qt3.moc.cpp :
+ $(property-set) ] ;
+
+ local target = [
+ new file-target $(name) : MOC : $(project) : $(a) ] ;
+
+ local r = [ virtual-target.register $(target) ] ;
+
+ # Since this generator will return a H target, the linking generator
+ # won't use it at all, and won't set any dependency on it. However,
+ # we need the target to be seen by bjam, so that the dependency from
+ # sources to this generated header is detected -- if Jam does not
+ # know about this target, it won't do anything.
+ DEPENDS all : [ $(r).actualize ] ;
+
+ return $(r) ;
+ }
+ }
+}
+
+
+# Query the installation directory. This is needed in at least two scenarios.
+# First, when re-using sources from the Qt-Tree. Second, to "install" custom Qt
+# plugins to the Qt-Tree.
+#
+rule directory
+{
+ return $(.prefix) ;
+}
+
+# -f forces moc to include the processed source file. Without it, it would think
+# that .qpp is not a header and would not include it from the generated file.
+#
+actions moc
+{
+ $(.prefix)/bin/moc -f $(>) -o $(<)
+}
+
+# When moccing .cpp files, we don't need -f, otherwise generated code will
+# include .cpp and we'll get duplicated symbols.
+#
+actions moc.cpp
+{
+ $(.prefix)/bin/moc $(>) -o $(<)
+}
+
+
+space = " " ;
+
+# Sometimes it's required to make 'plugins' available during uic invocation. To
+# help with this we add paths to all dependency libraries to uic commane line.
+# The intention is that it's possible to write
+#
+# exe a : ... a.ui ... : <uses>some_plugin ;
+#
+# and have everything work. We'd add quite a bunch of unrelated paths but it
+# won't hurt.
+#
+flags qt3.uic-h LIBRARY_PATH <xdll-path> ;
+actions uic-h
+{
+ $(.prefix)/bin/uic $(>) -o $(<) -L$(space)$(LIBRARY_PATH)
+}
+
+
+flags qt3.uic-cpp LIBRARY_PATH <xdll-path> ;
+# The second target is uic-generated header name. It's placed in build dir, but
+# we want to include it using only basename.
+actions uic-cpp
+{
+ $(.prefix)/bin/uic $(>[1]) -i $(>[2]:D=) -o $(<) -L$(space)$(LIBRARY_PATH)
+}
diff --git a/tools/build/v2/tools/qt4.jam b/tools/build/v2/tools/qt4.jam
new file mode 100644
index 0000000000..71d1b76207
--- /dev/null
+++ b/tools/build/v2/tools/qt4.jam
@@ -0,0 +1,724 @@
+# Copyright 2002-2006 Vladimir Prus
+# Copyright 2005 Alo Sarv
+# Copyright 2005-2009 Juergen Hunold
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Qt4 library support module
+#
+# The module attempts to auto-detect QT installation location from QTDIR
+# environment variable; failing that, installation location can be passed as
+# argument:
+#
+# toolset.using qt4 : /usr/local/Trolltech/Qt-4.0.0 ;
+#
+# The module supports code generation from .ui and .qrc files, as well as
+# running the moc preprocessor on headers. Note that you must list all your
+# moc-able headers in sources.
+#
+# Example:
+#
+# exe myapp : myapp.cpp myapp.h myapp.ui myapp.qrc
+# /qt4//QtGui /qt4//QtNetwork ;
+#
+# It's also possible to run moc on cpp sources:
+#
+# import cast ;
+#
+# exe myapp : myapp.cpp [ cast _ moccable-cpp : myapp.cpp ] /qt4//QtGui ;
+#
+# When moccing source file myapp.cpp you need to include "myapp.moc" from
+# myapp.cpp. When moccing .h files, the output of moc will be automatically
+# compiled and linked in, you don't need any includes.
+#
+# This is consistent with Qt guidelines:
+# http://doc.trolltech.com/4.0/moc.html
+
+import modules ;
+import feature ;
+import errors ;
+import type ;
+import "class" : new ;
+import generators ;
+import project ;
+import toolset : flags ;
+import os ;
+import virtual-target ;
+import scanner ;
+
+# Qt3Support control feature
+#
+# Qt4 configure defaults to build Qt4 libraries with Qt3Support.
+# The autodetection is missing, so we default to disable Qt3Support.
+# This prevents the user from inadvertedly using a deprecated API.
+#
+# The Qt3Support library can be activated by adding
+# "<qt3support>on" to requirements
+#
+# Use "<qt3support>on:<define>QT3_SUPPORT_WARNINGS"
+# to get warnings about deprecated Qt3 support funtions and classes.
+# Files ported by the "qt3to4" conversion tool contain _tons_ of
+# warnings, so this define is not set as default.
+#
+# Todo: Detect Qt3Support from Qt's configure data.
+# Or add more auto-configuration (like python).
+feature.feature qt3support : off on : propagated link-incompatible ;
+
+# The Qt version used for requirements
+# Valid are <qt>4.4 or <qt>4.5.0
+# Auto-detection via qmake sets '<qt>major.minor.patch'
+feature.feature qt : : propagated ;
+
+project.initialize $(__name__) ;
+project qt ;
+
+# Save the project so that we tolerate 'import + using' combo.
+.project = [ project.current ] ;
+
+# Helper utils for easy debug output
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = TRUE ;
+}
+
+local rule debug-message ( message * )
+{
+ if $(.debug-configuration) = TRUE
+ {
+ ECHO notice: [qt4-cfg] $(message) ;
+ }
+}
+
+# Capture qmake output line by line
+local rule read-output ( content )
+{
+ local lines ;
+ local nl = "
+" ;
+ local << = "([^$(nl)]*)[$(nl)](.*)" ;
+ local line+ = [ MATCH "$(<<)" : "$(content)" ] ;
+ while $(line+)
+ {
+ lines += $(line+[1]) ;
+ line+ = [ MATCH "$(<<)" : "$(line+[2])" ] ;
+ }
+ return $(lines) ;
+}
+
+# Capture Qt version from qmake
+local rule check-version ( bin_prefix )
+{
+ full-cmd = $(bin_prefix)"/qmake -v" ;
+ debug-message Running '$(full-cmd)' ;
+ local output = [ SHELL $(full-cmd) ] ;
+ for line in [ read-output $(output) ]
+ {
+ # Parse the output to get all the results.
+ if [ MATCH "QMake" : $(line) ]
+ {
+ # Skip first line of output
+ }
+ else
+ {
+ temp = [ MATCH "([0-9]*)\\.([0-9]*)\\.([0-9]*)" : $(line) ] ;
+ }
+ }
+ return $(temp) ;
+}
+
+# Validate the version string and extract the major/minor part we care about.
+#
+local rule split-version ( version )
+{
+ local major-minor = [ MATCH ^([0-9]+)\.([0-9]+)(.*)$ : $(version) : 1 2 3 ] ;
+ if ! $(major-minor[2]) || $(major-minor[3])
+ {
+ ECHO "Warning: 'using qt' expects a two part (major, minor) version number; got" $(version) instead ;
+
+ # Add a zero to account for the missing digit if necessary.
+ major-minor += 0 ;
+ }
+
+ return $(major-minor[1]) $(major-minor[2]) ;
+}
+
+# Initialize the QT support module.
+# Parameters:
+# - 'prefix' parameter tells where Qt is installed.
+# - 'full_bin' optional full path to Qt binaries (qmake,moc,uic,rcc)
+# - 'full_inc' optional full path to Qt top-level include directory
+# - 'full_lib' optional full path to Qt library directory
+# - 'version' optional version of Qt, else autodetected via 'qmake -v'
+# - 'condition' optional requirements
+rule init ( prefix : full_bin ? : full_inc ? : full_lib ? : version ? : condition * )
+{
+ project.push-current $(.project) ;
+
+ debug-message "==== Configuring Qt ... ====" ;
+ for local v in version cmd-or-prefix includes libraries condition
+ {
+ if $($(v))
+ {
+ debug-message " user-specified "$(v): '$($(v))' ;
+ }
+ }
+
+ # Needed as default value
+ .prefix = $(prefix) ;
+
+ # pre-build paths to detect reinitializations changes
+ local inc_prefix lib_prefix bin_prefix ;
+ if $(full_inc)
+ {
+ inc_prefix = $(full_inc) ;
+ }
+ else
+ {
+ inc_prefix = $(prefix)/include ;
+ }
+ if $(full_lib)
+ {
+ lib_prefix = $(full_lib) ;
+ }
+ else
+ {
+ lib_prefix = $(prefix)/lib ;
+ }
+ if $(full_bin)
+ {
+ bin_prefix = $(full_bin) ;
+ }
+ else
+ {
+ bin_prefix = $(prefix)/bin ;
+ }
+
+ # Globally needed variables
+ .incprefix = $(inc_prefix) ;
+ .libprefix = $(lib_prefix) ;
+ .binprefix = $(bin_prefix) ;
+
+ if ! $(.initialized)
+ {
+ # Make sure this is initialised only once
+ .initialized = true ;
+
+ # Generates cpp files from header files using "moc" tool
+ generators.register-standard qt4.moc : H : CPP(moc_%) : <allow>qt4 ;
+
+ # The OBJ result type is a fake, 'H' will be really produced. See
+ # comments on the generator class, defined below the 'init' function.
+ generators.register [ new uic-generator qt4.uic : UI : OBJ :
+ <allow>qt4 ] ;
+
+ # The OBJ result type is a fake here too.
+ generators.register [ new moc-h-generator
+ qt4.moc.inc : MOCCABLE_CPP : OBJ : <allow>qt4 ] ;
+
+ generators.register [ new moc-inc-generator
+ qt4.moc.inc : MOCCABLE_H : OBJ : <allow>qt4 ] ;
+
+ # Generates .cpp files from .qrc files.
+ generators.register-standard qt4.rcc : QRC : CPP(qrc_%) ;
+
+ # dependency scanner for wrapped files.
+ type.set-scanner QRC : qrc-scanner ;
+
+ # Save value of first occuring prefix
+ .PREFIX = $(prefix) ;
+ }
+
+ if $(version)
+ {
+ major-minor = [ split-version $(version) ] ;
+ version = $(major-minor:J=.) ;
+ }
+ else
+ {
+ version = [ check-version $(bin_prefix) ] ;
+ if $(version)
+ {
+ version = $(version:J=.) ;
+ }
+ debug-message Detected version '$(version)' ;
+ }
+
+ local target-requirements = $(condition) ;
+
+ # Add the version, if any, to the target requirements.
+ if $(version)
+ {
+ if ! $(version) in [ feature.values qt ]
+ {
+ feature.extend qt : $(version) ;
+ }
+ target-requirements += <qt>$(version:E=default) ;
+ }
+
+ local target-os = [ feature.get-values target-os : $(condition) ] ;
+ if ! $(target-os)
+ {
+ target-os ?= [ feature.defaults target-os ] ;
+ target-os = $(target-os:G=) ;
+ target-requirements += <target-os>$(target-os) ;
+ }
+
+ # Build exact requirements for the tools
+ local tools-requirements = $(target-requirements:J=/) ;
+
+ debug-message "Details of this Qt configuration:" ;
+ debug-message " prefix: " '$(prefix:E=<empty>)' ;
+ debug-message " binary path: " '$(bin_prefix:E=<empty>)' ;
+ debug-message " include path:" '$(inc_prefix:E=<empty>)' ;
+ debug-message " library path:" '$(lib_prefix:E=<empty>)' ;
+ debug-message " target requirements:" '$(target-requirements)' ;
+ debug-message " tool requirements: " '$(tools-requirements)' ;
+
+ # setup the paths for the tools
+ toolset.flags qt4.moc .BINPREFIX $(tools-requirements) : $(bin_prefix) ;
+ toolset.flags qt4.rcc .BINPREFIX $(tools-requirements) : $(bin_prefix) ;
+ toolset.flags qt4.uic .BINPREFIX $(tools-requirements) : $(bin_prefix) ;
+
+ # TODO: 2009-02-12: Better support for directories
+ # Most likely needed are separate getters for: include,libraries,binaries and sources.
+ toolset.flags qt4.directory .PREFIX $(tools-requirements) : $(prefix) ;
+
+ # Test for a buildable Qt.
+ if [ glob $(.prefix)/Jamroot ]
+ {
+ .bjam-qt = true
+
+ # this will declare QtCore (and qtmain on <target-os>windows)
+ add-shared-library QtCore ;
+ }
+ else
+ # Setup common pre-built Qt.
+ # Special setup for QtCore on which everything depends
+ {
+ local usage-requirements =
+ <include>$(.incprefix)
+ <library-path>$(.libprefix)
+ <dll-path>$(.libprefix)
+ <threading>multi
+ <allow>qt4 ;
+
+ local suffix ;
+
+ # Since Qt-4.2, debug versions on unix have to be built
+ # separately and therefore have no suffix.
+ .suffix_version = "" ;
+ .suffix_debug = "" ;
+
+ # Control flag for auto-configuration of the debug libraries.
+ # This setup requires Qt 'configure -debug-and-release'.
+ # Only available on some platforms.
+ # ToDo: 2009-02-12: Maybe throw this away and
+ # require separate setup with <variant>debug as condition.
+ .have_separate_debug = FALSE ;
+
+ # Setup other platforms
+ if $(target-os) in windows cygwin
+ {
+ .have_separate_debug = TRUE ;
+
+ # On NT, the libs have "4" suffix, and "d" suffix in debug builds.
+ .suffix_version = "4" ;
+ .suffix_debug = "d" ;
+
+ # On Windows we must link against the qtmain library
+ lib qtmain
+ : # sources
+ : # requirements
+ <name>qtmain$(.suffix_debug)
+ <variant>debug
+ $(target-requirements)
+ ;
+
+ lib qtmain
+ : # sources
+ : # requirements
+ <name>qtmain
+ $(target-requirements)
+ ;
+ }
+ else if $(target-os) = darwin
+ {
+ # On MacOS X, both debug and release libraries are available.
+ .suffix_debug = "_debug" ;
+
+ .have_separate_debug = TRUE ;
+
+ alias qtmain ;
+ }
+ else
+ {
+ alias qtmain : : $(target-requirements) ;
+ }
+
+ lib QtCore : qtmain
+ : # requirements
+ <name>QtCore$(.suffix_version)
+ $(target-requirements)
+ : # default-build
+ : # usage-requirements
+ <define>QT_CORE_LIB
+ <define>QT_NO_DEBUG
+ <include>$(.incprefix)/QtCore
+ $(usage-requirements)
+ ;
+
+ if $(.have_separate_debug) = TRUE
+ {
+ debug-message Configure debug libraries with suffix '$(.suffix_debug)' ;
+
+ lib QtCore : $(main)
+ : # requirements
+ <name>QtCore$(.suffix_debug)$(.suffix_version)
+ <variant>debug
+ $(target-requirements)
+ : # default-build
+ : # usage-requirements
+ <define>QT_CORE_LIB
+ <include>$(.incprefix)/QtCore
+ $(usage-requirements)
+ ;
+ }
+ }
+
+ # Initialising the remaining libraries is canonical
+ # parameters 'module' : 'depends-on' : 'usage-define' : 'requirements' : 'include'
+ # 'include' only for non-canonical include paths.
+ add-shared-library QtGui : QtCore : QT_GUI_LIB : $(target-requirements) ;
+ add-shared-library QtNetwork : QtCore : QT_NETWORK_LIB : $(target-requirements) ;
+ add-shared-library QtSql : QtCore : QT_SQL_LIB : $(target-requirements) ;
+ add-shared-library QtXml : QtCore : QT_XML_LIB : $(target-requirements) ;
+
+ add-shared-library Qt3Support : QtGui QtNetwork QtXml QtSql
+ : QT_QT3SUPPORT_LIB QT3_SUPPORT
+ : <qt3support>on $(target-requirements) ;
+
+ # Dummy target to enable "<qt3support>off" and
+ # "<library>/qt//Qt3Support" at the same time. This enables quick
+ # switching from one to the other for test/porting purposes.
+ alias Qt3Support : : <qt3support>off $(target-requirements) ;
+
+ # OpenGl Support
+ add-shared-library QtOpenGL : QtGui : QT_OPENGL_LIB : $(target-requirements) ;
+
+ # SVG-Support (Qt 4.1)
+ add-shared-library QtSvg : QtXml QtOpenGL : QT_SVG_LIB : $(target-requirements) ;
+
+ # Test-Support (Qt 4.1)
+ add-shared-library QtTest : QtCore : : $(target-requirements) ;
+
+ # Qt designer library
+ add-shared-library QtDesigner : QtGui QtXml : : $(target-requirements) ;
+ add-shared-library QtDesignerComponents : QtGui QtXml : : $(target-requirements) ;
+
+ # Support for dynamic Widgets (Qt 4.1)
+ add-static-library QtUiTools : QtGui QtXml : $(target-requirements) ;
+
+ # DBus-Support (Qt 4.2)
+ add-shared-library QtDBus : QtXml : : $(target-requirements) ;
+
+ # Script-Engine (Qt 4.3)
+ add-shared-library QtScript : QtGui QtXml : QT_SCRIPT_LIB : $(target-requirements) ;
+
+ # Tools for the Script-Engine (Qt 4.5)
+ add-shared-library QtScriptTools : QtScript : QT_SCRIPTTOOLS_LIB : $(target-requirements) ;
+
+ # WebKit (Qt 4.4)
+ add-shared-library QtWebKit : QtGui : QT_WEBKIT_LIB : $(target-requirements) ;
+
+ # Phonon Multimedia (Qt 4.4)
+ add-shared-library phonon : QtGui QtXml : QT_PHONON_LIB : $(target-requirements) ;
+
+ # Multimedia engine (Qt 4.6)
+ add-shared-library QtMultimedia : QtGui : QT_MULTIMEDIA_LIB : $(target-requirements) ;
+
+ # XmlPatterns-Engine (Qt 4.4)
+ add-shared-library QtXmlPatterns : QtNetwork : QT_XMLPATTERNS_LIB : $(target-requirements) ;
+
+ # Help-Engine (Qt 4.4)
+ add-shared-library QtHelp : QtGui QtSql QtXml : : $(target-requirements) ;
+ add-shared-library QtCLucene : QCore QtSql QtXml : : $(target-requirements) ;
+
+ # QML-Engine (Qt 4.7)
+ add-shared-library QtDeclarative : QtGui QtXml : : $(target-requirements) ;
+
+ # AssistantClient Support
+ # Compat library removed in 4.7.0
+ # Pre-4.4 help system, use QtHelp for new programs
+ if $(version) < "4.7"
+ {
+ add-shared-library QtAssistantClient : QtGui : : $(target-requirements) : QtAssistant ;
+ }
+ debug-message "==== Configured Qt-$(version) ====" ;
+
+ project.pop-current ;
+}
+
+rule initialized ( )
+{
+ return $(.initialized) ;
+}
+
+
+
+# This custom generator is needed because in QT4, UI files are translated only
+# into H files, and no C++ files are created. Further, the H files need not be
+# passed via MOC. The header is used only via inclusion. If we define a standard
+# UI -> H generator, Boost.Build will run MOC on H, and then compile the
+# resulting cpp. It will give a warning, since output from moc will be empty.
+#
+# This generator is declared with a UI -> OBJ signature, so it gets invoked when
+# linking generator tries to convert sources to OBJ, but it produces target of
+# type H. This is non-standard, but allowed. That header won't be mocced.
+#
+class uic-generator : generator
+{
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * )
+ {
+ if ! $(name)
+ {
+ name = [ $(sources[0]).name ] ;
+ name = $(name:B) ;
+ }
+
+ local a = [ new action $(sources[1]) : qt4.uic : $(property-set) ] ;
+
+ # The 'ui_' prefix is to match qmake's default behavior.
+ local target = [ new file-target ui_$(name) : H : $(project) : $(a) ] ;
+
+ local r = [ virtual-target.register $(target) ] ;
+
+ # Since this generator will return a H target, the linking generator
+ # won't use it at all, and won't set any dependency on it. However, we
+ # need the target to be seen by bjam, so that dependency from sources to
+ # this generated header is detected -- if jam does not know about this
+ # target, it won't do anything.
+ DEPENDS all : [ $(r).actualize ] ;
+
+ return $(r) ;
+ }
+}
+
+
+class moc-h-generator : generator
+{
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * )
+ {
+ if ! $(sources[2]) && [ $(sources[1]).type ] = MOCCABLE_CPP
+ {
+ name = [ $(sources[0]).name ] ;
+ name = $(name:B) ;
+
+ local a = [ new action $(sources[1]) : qt4.moc.inc :
+ $(property-set) ] ;
+
+ local target = [ new file-target $(name) : MOC : $(project) : $(a)
+ ] ;
+
+ local r = [ virtual-target.register $(target) ] ;
+
+ # Since this generator will return a H target, the linking generator
+ # won't use it at all, and won't set any dependency on it. However,
+ # we need the target to be seen by bjam, so that dependency from
+ # sources to this generated header is detected -- if jam does not
+ # know about this target, it won't do anything.
+ DEPENDS all : [ $(r).actualize ] ;
+
+ return $(r) ;
+ }
+ }
+}
+
+
+class moc-inc-generator : generator
+{
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * )
+ {
+ if ! $(sources[2]) && [ $(sources[1]).type ] = MOCCABLE_H
+ {
+ name = [ $(sources[0]).name ] ;
+ name = $(name:B) ;
+
+ local a = [ new action $(sources[1]) : qt4.moc.inc :
+ $(property-set) ] ;
+
+ local target = [ new file-target moc_$(name) : CPP : $(project) :
+ $(a) ] ;
+
+ # Since this generator will return a H target, the linking generator
+ # won't use it at all, and won't set any dependency on it. However,
+ # we need the target to be seen by bjam, so that dependency from
+ # sources to this generated header is detected -- if jam does not
+ # know about this target, it won't do anything.
+ DEPENDS all : [ $(target).actualize ] ;
+
+ return [ virtual-target.register $(target) ] ;
+ }
+ }
+}
+
+
+# Query the installation directory. This is needed in at least two scenarios.
+# First, when re-using sources from the Qt-Tree. Second, to "install" custom Qt
+# plugins to the Qt-Tree.
+#
+rule directory
+{
+ return $(.PREFIX) ;
+}
+
+# Add a shared Qt library.
+rule add-shared-library ( lib-name : depends-on * : usage-defines * : requirements * : include ? )
+{
+ add-library $(lib-name) : $(.suffix_version) : $(depends-on) : $(usage-defines) : $(requirements) : $(include) ;
+}
+
+# Add a static Qt library.
+rule add-static-library ( lib-name : depends-on * : usage-defines * : requirements * : include ? )
+{
+ add-library $(lib-name) : : $(depends-on) : $(usage-defines) : $(requirements) : $(include) ;
+}
+
+# Add a Qt library.
+# Static libs are unversioned, whereas shared libs have the major number as suffix.
+# Creates both release and debug versions on platforms where both are enabled by Qt configure.
+# Flags:
+# - lib-name Qt library Name
+# - version Qt major number used as shared library suffix (QtCore4.so)
+# - depends-on other Qt libraries
+# - usage-defines those are set by qmake, so set them when using this library
+# - requirements addional requirements
+# - include non-canonical include path. The canonical path is $(.incprefix)/$(lib-name).
+rule add-library ( lib-name : version ? : depends-on * : usage-defines * : requirements * : include ? )
+{
+ if $(.bjam-qt)
+ {
+ # Import Qt module
+ # Eveything will be setup there
+ alias $(lib-name)
+ : $(.prefix)//$(lib-name)
+ :
+ :
+ : <allow>qt4 ;
+ }
+ else
+ {
+ local real_include ;
+ real_include ?= $(include) ;
+ real_include ?= $(lib-name) ;
+
+ lib $(lib-name)
+ : # sources
+ $(depends-on)
+ : # requirements
+ <name>$(lib-name)$(version)
+ $(requirements)
+ : # default-build
+ : # usage-requirements
+ <define>$(usage-defines)
+ <include>$(.incprefix)/$(real_include)
+ ;
+
+ if $(.have_separate_debug) = TRUE
+ {
+ lib $(lib-name)
+ : # sources
+ $(depends-on)
+ : # requirements
+ <name>$(lib-name)$(.suffix_debug)$(version)
+ $(requirements)
+ <variant>debug
+ : # default-build
+ : # usage-requirements
+ <define>$(usage-defines)
+ <include>$(.incprefix)/$(real_include)
+ ;
+ }
+ }
+
+ # Make library explicit so that a simple <use>qt4 will not bring in everything.
+ # And some components like QtDBus/Phonon may not be available on all platforms.
+ explicit $(lib-name) ;
+}
+
+# Use $(.BINPREFIX[-1]) for the paths as several tools-requirements can match.
+# The exact match is the last one.
+
+# Get <include> and <defines> from current toolset.
+flags qt4.moc INCLUDES <include> ;
+flags qt4.moc DEFINES <define> ;
+
+# need a newline for expansion of DEFINES and INCLUDES in the response file.
+.nl = "
+" ;
+
+# Processes headers to create Qt MetaObject information. Qt4-moc has its
+# c++-parser, so pass INCLUDES and DEFINES.
+# We use response file with one INCLUDE/DEFINE per line
+#
+actions moc
+{
+ $(.BINPREFIX[-1])/moc -f $(>) -o $(<) @"@($(<).rsp:E=-D$(DEFINES)$(.nl) -I$(INCLUDES:T)$(.nl))"
+}
+
+# When moccing files for include only, we don't need -f, otherwise the generated
+# code will include the .cpp and we'll get duplicated symbols.
+#
+actions moc.inc
+{
+ $(.BINPREFIX[-1])/moc $(>) -o $(<) @"@($(<).rsp:E=-D$(DEFINES)$(.nl) -I$(INCLUDES:T)$(.nl))"
+}
+
+
+# Generates source files from resource files.
+#
+actions rcc
+{
+ $(.BINPREFIX[-1])/rcc $(>) -name $(>:B) -o $(<)
+}
+
+
+# Generates user-interface source from .ui files.
+#
+actions uic
+{
+ $(.BINPREFIX[-1])/uic $(>) -o $(<)
+}
+
+
+# Scanner for .qrc files. Look for the CDATA section of the <file> tag. Ignore
+# the "alias" attribute. See http://doc.trolltech.com/qt/resources.html for
+# detailed documentation of the Qt Resource System.
+#
+class qrc-scanner : common-scanner
+{
+ rule pattern ( )
+ {
+ return "<file.*>(.*)</file>" ;
+ }
+}
+
+
+# Wrapped files are "included".
+scanner.register qrc-scanner : include ;
diff --git a/tools/build/v2/tools/quickbook-config.jam b/tools/build/v2/tools/quickbook-config.jam
new file mode 100644
index 0000000000..e983a78a8e
--- /dev/null
+++ b/tools/build/v2/tools/quickbook-config.jam
@@ -0,0 +1,44 @@
+#~ Copyright 2005 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Automatic configuration for BoostBook tools. To use, just import this module.
+
+import os ;
+import toolset : using ;
+
+if [ os.name ] = NT
+{
+ local boost-dir = ;
+ for local R in snapshot cvs 1.33.0
+ {
+ boost-dir += [ W32_GETREG
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Boost.org\\$(R)"
+ : "InstallRoot" ] ;
+ }
+ local quickbook-path = [ GLOB "$(boost-dir)\\bin" "\\Boost\\bin" : quickbook.exe ] ;
+ quickbook-path = $(quickbook-path[1]) ;
+
+ if $(quickbook-path)
+ {
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice:" using quickbook ":" $(quickbook-path) ;
+ }
+ using quickbook : $(quickbook-path) ;
+ }
+}
+else
+{
+ local quickbook-path = [ GLOB "/usr/local/bin" "/usr/bin" "/opt/bin" : quickbook ] ;
+ quickbook-path = $(quickbook-path[1]) ;
+
+ if $(quickbook-path)
+ {
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice:" using quickbook ":" $(quickbook-path) ;
+ }
+ using quickbook : $(quickbook-path) ;
+ }
+}
diff --git a/tools/build/v2/tools/quickbook.jam b/tools/build/v2/tools/quickbook.jam
new file mode 100644
index 0000000000..6de2d42f84
--- /dev/null
+++ b/tools/build/v2/tools/quickbook.jam
@@ -0,0 +1,361 @@
+#
+# Copyright (c) 2005 João Abecasis
+# Copyright (c) 2005 Vladimir Prus
+# Copyright (c) 2006 Rene Rivera
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+# This toolset defines a generator to translate QuickBook to BoostBook. It can
+# be used to generate nice (!) user documentation in different formats
+# (pdf/html/...), from a single text file with simple markup.
+#
+# The toolset defines the QUICKBOOK type (file extension 'qbk') and
+# a QUICKBOOK to XML (BOOSTBOOK) generator.
+#
+#
+# ===========================================================================
+# Q & A
+# ===========================================================================
+#
+# If you don't know what this is all about, some Q & A will hopefully get you
+# up to speed with QuickBook and this toolset.
+#
+#
+# What is QuickBook ?
+#
+# QuickBook is a WikiWiki style documentation tool geared towards C++
+# documentation using simple rules and markup for simple formatting tasks.
+# QuickBook extends the WikiWiki concept. Like the WikiWiki, QuickBook
+# documents are simple text files. A single QuickBook document can
+# generate a fully linked set of nice HTML and PostScript/PDF documents
+# complete with images and syntax-colorized source code.
+#
+#
+# Where can I get QuickBook ?
+#
+# Quickbook can be found in Boost's repository, under the tools/quickbook
+# directory it was added there on Jan 2005, some time after the release of
+# Boost v1.32.0 and has been an integral part of the Boost distribution
+# since v1.33.
+#
+# Here's a link to the SVN repository:
+# https://svn.boost.org/svn/boost/trunk/tools/quickbook
+#
+# And to QuickBook's QuickBook-generated docs:
+# http://www.boost.org/doc/libs/release/tools/quickbook/index.html
+#
+#
+# How do I use QuickBook and this toolset in my projects ?
+#
+# The minimal example is:
+#
+# using boostbook ;
+# import quickbook ;
+#
+# boostbook my_docs : my_docs_source.qbk ;
+#
+# where my_docs is a target name and my_docs_source.qbk is a QuickBook
+# file. The documentation format to be generated is determined by the
+# boostbook toolset. By default html documentation should be generated,
+# but you should check BoostBook's docs to be sure.
+#
+#
+# What do I need ?
+#
+# You should start by setting up the BoostBook toolset. Please refer to
+# boostbook.jam and the BoostBook documentation for information on how to
+# do this.
+#
+# A QuickBook executable is also needed. The toolset will generate this
+# executable if it can find the QuickBook sources. The following
+# directories will be searched:
+#
+# BOOST_ROOT/tools/quickbook/
+# BOOST_BUILD_PATH/../../quickbook/
+#
+# (BOOST_ROOT and BOOST_BUILD_PATH are environment variables)
+#
+# If QuickBook sources are not found the toolset will then try to use
+# the shell command 'quickbook'.
+#
+#
+# How do I provide a custom QuickBook executable ?
+#
+# You may put the following in your user-config.jam or site-config.jam:
+#
+# using quickbook : /path/to/quickbook ;
+#
+# or, if 'quickbook' can be found in your PATH,
+#
+# using quickbook : quickbook ;
+#
+#
+# For convenience three alternatives are tried to get a QuickBook executable:
+#
+# 1. If the user points us to the a QuickBook executable, that is used.
+#
+# 2. Otherwise, we search for the QuickBook sources and compile QuickBook
+# using the default toolset.
+#
+# 3. As a last resort, we rely on the shell for finding 'quickbook'.
+#
+
+import boostbook ;
+import "class" : new ;
+import feature ;
+import generators ;
+import toolset ;
+import type ;
+import scanner ;
+import project ;
+import targets ;
+import build-system ;
+import path ;
+import common ;
+import errors ;
+
+# The one and only QUICKBOOK type!
+type.register QUICKBOOK : qbk ;
+
+# <quickbook-binary> shell command to run QuickBook
+# <quickbook-binary-dependencies> targets to build QuickBook from sources.
+feature.feature <quickbook-binary> : : free ;
+feature.feature <quickbook-binary-dependencies> : : free dependency ;
+feature.feature <quickbook-define> : : free ;
+feature.feature <quickbook-indent> : : free ;
+feature.feature <quickbook-line-width> : : free ;
+
+
+# quickbook-binary-generator handles generation of the QuickBook executable, by
+# marking it as a dependency for QuickBook docs.
+#
+# If the user supplied the QuickBook command that will be used.
+#
+# Otherwise we search some sensible places for the QuickBook sources and compile
+# from scratch using the default toolset.
+#
+# As a last resort we rely on the shell to find 'quickbook'.
+#
+class quickbook-binary-generator : generator
+{
+ import modules path targets quickbook ;
+
+ rule run ( project name ? : property-set : sources * : multiple ? )
+ {
+ quickbook.freeze-config ;
+ # QuickBook invocation command and dependencies.
+ local quickbook-binary = [ modules.peek quickbook : .quickbook-binary ] ;
+ local quickbook-binary-dependencies ;
+
+ if ! $(quickbook-binary)
+ {
+ # If the QuickBook source directory was found, mark its main target
+ # as a dependency for the current project. Otherwise, try to find
+ # 'quickbook' in user's PATH
+ local quickbook-dir = [ modules.peek quickbook : .quickbook-dir ] ;
+ if $(quickbook-dir)
+ {
+ # Get the main-target in QuickBook directory.
+ local quickbook-main-target = [ targets.resolve-reference $(quickbook-dir) : $(project) ] ;
+
+ # The first element are actual targets, the second are
+ # properties found in target-id. We do not care about these
+ # since we have passed the id ourselves.
+ quickbook-main-target =
+ [ $(quickbook-main-target[1]).main-target quickbook ] ;
+
+ quickbook-binary-dependencies =
+ [ $(quickbook-main-target).generate [ $(property-set).propagated ] ] ;
+
+ # Ignore usage-requirements returned as first element.
+ quickbook-binary-dependencies = $(quickbook-binary-dependencies[2-]) ;
+
+ # Some toolsets generate extra targets (e.g. RSP). We must mark
+ # all targets as dependencies for the project, but we will only
+ # use the EXE target for quickbook-to-boostbook translation.
+ for local target in $(quickbook-binary-dependencies)
+ {
+ if [ $(target).type ] = EXE
+ {
+ quickbook-binary =
+ [ path.native
+ [ path.join
+ [ $(target).path ]
+ [ $(target).name ]
+ ]
+ ] ;
+ }
+ }
+ }
+ }
+
+ # Add $(quickbook-binary-dependencies) as a dependency of the current
+ # project and set it as the <quickbook-binary> feature for the
+ # quickbook-to-boostbook rule, below.
+ property-set = [ $(property-set).add-raw
+ <dependency>$(quickbook-binary-dependencies)
+ <quickbook-binary>$(quickbook-binary)
+ <quickbook-binary-dependencies>$(quickbook-binary-dependencies)
+ ] ;
+
+ return [ generator.run $(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
+ }
+}
+
+
+# Define a scanner for tracking QBK include dependencies.
+#
+class qbk-scanner : common-scanner
+{
+ rule pattern ( )
+ {
+ return "\\[[ ]*include[ ]+([^]]+)\\]"
+ "\\[[ ]*include:[a-zA-Z0-9_]+[ ]+([^]]+)\\]"
+ "\\[[ ]*import[ ]+([^]]+)\\]" ;
+ }
+}
+
+
+scanner.register qbk-scanner : include ;
+
+type.set-scanner QUICKBOOK : qbk-scanner ;
+
+
+# Initialization of toolset.
+#
+# Parameters:
+# command ? -> path to QuickBook executable.
+#
+# When command is not supplied toolset will search for QuickBook directory and
+# compile the executable from source. If that fails we still search the path for
+# 'quickbook'.
+#
+rule init (
+ command ? # path to the QuickBook executable.
+ )
+{
+ if $(command)
+ {
+ if $(.config-frozen)
+ {
+ errors.user-error "quickbook: configuration cannot be changed after it has been used." ;
+ }
+ .command = $(command) ;
+ }
+}
+
+rule freeze-config ( )
+{
+ if ! $(.config-frozen)
+ {
+ .config-frozen = true ;
+
+ # QuickBook invocation command and dependencies.
+
+ .quickbook-binary = $(.command) ;
+
+ if $(.quickbook-binary)
+ {
+ # Use user-supplied command.
+ .quickbook-binary = [ common.get-invocation-command quickbook : quickbook : $(.quickbook-binary) ] ;
+ }
+ else
+ {
+ # Search for QuickBook sources in sensible places, like
+ # $(BOOST_ROOT)/tools/quickbook
+ # $(BOOST_BUILD_PATH)/../../quickbook
+
+ # And build quickbook executable from sources.
+
+ local boost-root = [ modules.peek : BOOST_ROOT ] ;
+ local boost-build-path = [ build-system.location ] ;
+
+ if $(boost-root)
+ {
+ .quickbook-dir += [ path.join $(boost-root) tools ] ;
+ }
+
+ if $(boost-build-path)
+ {
+ .quickbook-dir += $(boost-build-path)/../.. ;
+ }
+
+ .quickbook-dir = [ path.glob $(.quickbook-dir) : quickbook ] ;
+
+ # If the QuickBook source directory was found, mark its main target
+ # as a dependency for the current project. Otherwise, try to find
+ # 'quickbook' in user's PATH
+ if $(.quickbook-dir)
+ {
+ .quickbook-dir = [ path.make $(.quickbook-dir[1]) ] ;
+ }
+ else
+ {
+ ECHO "QuickBook warning: The path to the quickbook executable was" ;
+ ECHO " not provided. Additionally, couldn't find QuickBook" ;
+ ECHO " sources searching in" ;
+ ECHO " * BOOST_ROOT/tools/quickbook" ;
+ ECHO " * BOOST_BUILD_PATH/../../quickbook" ;
+ ECHO " Will now try to find a precompiled executable by searching" ;
+ ECHO " the PATH for 'quickbook'." ;
+ ECHO " To disable this warning in the future, or to completely" ;
+ ECHO " avoid compilation of quickbook, you can explicitly set the" ;
+ ECHO " path to a quickbook executable command in user-config.jam" ;
+ ECHO " or site-config.jam with the call" ;
+ ECHO " using quickbook : /path/to/quickbook ;" ;
+
+ # As a last resort, search for 'quickbook' command in path. Note
+ # that even if the 'quickbook' command is not found,
+ # get-invocation-command will still return 'quickbook' and might
+ # generate an error while generating the virtual-target.
+
+ .quickbook-binary = [ common.get-invocation-command quickbook : quickbook ] ;
+ }
+ }
+ }
+}
+
+
+generators.register [ new quickbook-binary-generator quickbook.quickbook-to-boostbook : QUICKBOOK : XML ] ;
+
+
+# <quickbook-binary> shell command to run QuickBook
+# <quickbook-binary-dependencies> targets to build QuickBook from sources.
+toolset.flags quickbook.quickbook-to-boostbook QB-COMMAND <quickbook-binary> ;
+toolset.flags quickbook.quickbook-to-boostbook QB-DEPENDENCIES <quickbook-binary-dependencies> ;
+toolset.flags quickbook.quickbook-to-boostbook INCLUDES <include> ;
+toolset.flags quickbook.quickbook-to-boostbook QB-DEFINES <quickbook-define> ;
+toolset.flags quickbook.quickbook-to-boostbook QB-INDENT <quickbook-indent> ;
+toolset.flags quickbook.quickbook-to-boostbook QB-LINE-WIDTH <quickbook-line-width> ;
+
+
+rule quickbook-to-boostbook ( target : source : properties * )
+{
+ # Signal dependency of quickbook sources on <quickbook-binary-dependencies>
+ # upon invocation of quickbook-to-boostbook.
+ DEPENDS $(target) : [ on $(target) return $(QB-DEPENDENCIES) ] ;
+}
+
+
+actions quickbook-to-boostbook
+{
+ "$(QB-COMMAND)" -I"$(INCLUDES)" -D"$(QB-DEFINES)" --indent="$(QB-INDENT)" --linewidth="$(QB-LINE-WIDTH)" --output-file="$(1)" "$(2)"
+}
+
+
+# Declare a main target to convert a quickbook source into a boostbook XML file.
+#
+rule to-boostbook ( target-name : sources * : requirements * : default-build * )
+{
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new typed-target $(target-name) : $(project) : XML
+ : [ targets.main-target-sources $(sources) : $(target-name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+}
diff --git a/tools/build/v2/tools/rc.jam b/tools/build/v2/tools/rc.jam
new file mode 100644
index 0000000000..9964d339ba
--- /dev/null
+++ b/tools/build/v2/tools/rc.jam
@@ -0,0 +1,156 @@
+# Copyright (C) Andre Hentz 2003. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+#
+# Copyright (c) 2006 Rene Rivera.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import type ;
+import generators ;
+import feature ;
+import errors ;
+import scanner ;
+import toolset : flags ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+type.register RC : rc ;
+
+rule init ( )
+{
+}
+
+# Configures a new resource compilation command specific to a condition,
+# usually a toolset selection condition. The possible options are:
+#
+# * <rc-type>(rc|windres) - Indicates the type of options the command
+# accepts.
+#
+# Even though the arguments are all optional, only when a command, condition,
+# and at minimum the rc-type option are given will the command be configured.
+# This is so that callers don't have to check auto-configuration values
+# before calling this. And still get the functionality of build failures when
+# the resource compiler can't be found.
+#
+rule configure ( command ? : condition ? : options * )
+{
+ local rc-type = [ feature.get-values <rc-type> : $(options) ] ;
+
+ if $(command) && $(condition) && $(rc-type)
+ {
+ flags rc.compile.resource .RC $(condition) : $(command) ;
+ flags rc.compile.resource .RC_TYPE $(condition) : $(rc-type:L) ;
+ flags rc.compile.resource DEFINES <define> ;
+ flags rc.compile.resource INCLUDES <include> ;
+ if $(.debug-configuration)
+ {
+ ECHO notice: using rc compiler :: $(condition) :: $(command) ;
+ }
+ }
+}
+
+rule compile.resource ( target : sources * : properties * )
+{
+ local rc-type = [ on $(target) return $(.RC_TYPE) ] ;
+ rc-type ?= null ;
+ compile.resource.$(rc-type) $(target) : $(sources[1]) ;
+}
+
+actions compile.resource.rc
+{
+ "$(.RC)" -l 0x409 "-U$(UNDEFS)" "-D$(DEFINES)" -I"$(>:D)" -I"$(<:D)" -I"$(INCLUDES)" -fo "$(<)" "$(>)"
+}
+
+actions compile.resource.windres
+{
+ "$(.RC)" "-U$(UNDEFS)" "-D$(DEFINES)" -I"$(>:D)" -I"$(<:D)" -I"$(INCLUDES)" -o "$(<)" -i "$(>)"
+}
+
+actions quietly compile.resource.null
+{
+ as /dev/null -o "$(<)"
+}
+
+# Since it's a common practice to write
+# exe hello : hello.cpp hello.rc
+# we change the name of object created from RC file, to
+# avoid conflict with hello.cpp.
+# The reason we generate OBJ and not RES, is that gcc does not
+# seem to like RES files, but works OK with OBJ.
+# See http://article.gmane.org/gmane.comp.lib.boost.build/5643/
+#
+# Using 'register-c-compiler' adds the build directory to INCLUDES
+generators.register-c-compiler rc.compile.resource : RC : OBJ(%_res) ;
+
+# Register scanner for resources
+class res-scanner : scanner
+{
+ import regex virtual-target path scanner ;
+
+ rule __init__ ( includes * )
+ {
+ scanner.__init__ ;
+
+ self.includes = $(includes) ;
+ }
+
+ rule pattern ( )
+ {
+ return "(([^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)[ ]+([^ \"]+|\"[^\"]+\"))|(#include[ ]*(<[^<]+>|\"[^\"]+\")))" ;
+ }
+
+ rule process ( target : matches * : binding )
+ {
+ local angle = [ regex.transform $(matches) : "#include[ ]*<([^<]+)>" ] ;
+ local quoted = [ regex.transform $(matches) : "#include[ ]*\"([^\"]+)\"" ] ;
+ local res = [ regex.transform $(matches) : "[^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)[ ]+(([^ \"]+)|\"([^\"]+)\")" : 3 4 ] ;
+
+ # Icons and other includes may referenced as
+ #
+ # IDR_MAINFRAME ICON "res\\icon.ico"
+ #
+ # so we have to replace double backslashes to single ones.
+ res = [ regex.replace-list $(res) : "\\\\\\\\" : "/" ] ;
+
+ # CONSIDER: the new scoping rule seem to defeat "on target" variables.
+ local g = [ on $(target) return $(HDRGRIST) ] ;
+ local b = [ NORMALIZE_PATH $(binding:D) ] ;
+
+ # Attach binding of including file to included targets.
+ # When target is directly created from virtual target
+ # this extra information is unnecessary. But in other
+ # cases, it allows to distinguish between two headers of the
+ # same name included from different places.
+ # We don't need this extra information for angle includes,
+ # since they should not depend on including file (we can't
+ # get literal "." in include path).
+ local g2 = $(g)"#"$(b) ;
+
+ angle = $(angle:G=$(g)) ;
+ quoted = $(quoted:G=$(g2)) ;
+ res = $(res:G=$(g2)) ;
+
+ local all = $(angle) $(quoted) ;
+
+ INCLUDES $(target) : $(all) ;
+ DEPENDS $(target) : $(res) ;
+ NOCARE $(all) $(res) ;
+ SEARCH on $(angle) = $(self.includes:G=) ;
+ SEARCH on $(quoted) = $(b) $(self.includes:G=) ;
+ SEARCH on $(res) = $(b) $(self.includes:G=) ;
+
+ # Just propagate current scanner to includes, in a hope
+ # that includes do not change scanners.
+ scanner.propagate $(__name__) : $(angle) $(quoted) : $(target) ;
+ }
+}
+
+scanner.register res-scanner : include ;
+type.set-scanner RC : res-scanner ;
diff --git a/tools/build/v2/tools/rc.py b/tools/build/v2/tools/rc.py
new file mode 100644
index 0000000000..0b82d231d7
--- /dev/null
+++ b/tools/build/v2/tools/rc.py
@@ -0,0 +1,189 @@
+# Status: being ported by Steven Watanabe
+# Base revision: 47077
+#
+# Copyright (C) Andre Hentz 2003. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+#
+# Copyright (c) 2006 Rene Rivera.
+#
+# Copyright (c) 2008 Steven Watanabe
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+##import type ;
+##import generators ;
+##import feature ;
+##import errors ;
+##import scanner ;
+##import toolset : flags ;
+
+from b2.build import type, toolset, generators, scanner, feature
+from b2.tools import builtin
+from b2.util import regex
+from b2.build.toolset import flags
+from b2.manager import get_manager
+
+__debug = None
+
+def debug():
+ global __debug
+ if __debug is None:
+ __debug = "--debug-configuration" in bjam.variable("ARGV")
+ return __debug
+
+type.register('RC', ['rc'])
+
+def init():
+ pass
+
+def configure (command = None, condition = None, options = None):
+ """
+ Configures a new resource compilation command specific to a condition,
+ usually a toolset selection condition. The possible options are:
+
+ * <rc-type>(rc|windres) - Indicates the type of options the command
+ accepts.
+
+ Even though the arguments are all optional, only when a command, condition,
+ and at minimum the rc-type option are given will the command be configured.
+ This is so that callers don't have to check auto-configuration values
+ before calling this. And still get the functionality of build failures when
+ the resource compiler can't be found.
+ """
+ rc_type = feature.get_values('<rc-type>', options)
+ if rc_type:
+ assert(len(rc_type) == 1)
+ rc_type = rc_type[0]
+
+ if command and condition and rc_type:
+ flags('rc.compile.resource', '.RC', condition, command)
+ flags('rc.compile.resource', '.RC_TYPE', condition, rc_type.lower())
+ flags('rc.compile.resource', 'DEFINES', [], ['<define>'])
+ flags('rc.compile.resource', 'INCLUDES', [], ['<include>'])
+ if debug():
+ print 'notice: using rc compiler ::', condition, '::', command
+
+engine = get_manager().engine()
+
+class RCAction:
+ """Class representing bjam action defined from Python.
+ The function must register the action to execute."""
+
+ def __init__(self, action_name, function):
+ self.action_name = action_name
+ self.function = function
+
+ def __call__(self, targets, sources, property_set):
+ if self.function:
+ self.function(targets, sources, property_set)
+
+# FIXME: What is the proper way to dispatch actions?
+def rc_register_action(action_name, function = None):
+ global engine
+ if engine.actions.has_key(action_name):
+ raise "Bjam action %s is already defined" % action_name
+ engine.actions[action_name] = RCAction(action_name, function)
+
+def rc_compile_resource(targets, sources, properties):
+ rc_type = bjam.call('get-target-variable', targets, '.RC_TYPE')
+ global engine
+ engine.set_update_action('rc.compile.resource.' + rc_type, targets, sources, properties)
+
+rc_register_action('rc.compile.resource', rc_compile_resource)
+
+
+engine.register_action(
+ 'rc.compile.resource.rc',
+ '"$(.RC)" -l 0x409 "-U$(UNDEFS)" "-D$(DEFINES)" -I"$(>:D)" -I"$(<:D)" -I"$(INCLUDES)" -fo "$(<)" "$(>)"')
+
+engine.register_action(
+ 'rc.compile.resource.windres',
+ '"$(.RC)" "-U$(UNDEFS)" "-D$(DEFINES)" -I"$(>:D)" -I"$(<:D)" -I"$(INCLUDES)" -o "$(<)" -i "$(>)"')
+
+# FIXME: this was originally declared quietly
+engine.register_action(
+ 'compile.resource.null',
+ 'as /dev/null -o "$(<)"')
+
+# Since it's a common practice to write
+# exe hello : hello.cpp hello.rc
+# we change the name of object created from RC file, to
+# avoid conflict with hello.cpp.
+# The reason we generate OBJ and not RES, is that gcc does not
+# seem to like RES files, but works OK with OBJ.
+# See http://article.gmane.org/gmane.comp.lib.boost.build/5643/
+#
+# Using 'register-c-compiler' adds the build directory to INCLUDES
+# FIXME: switch to generators
+builtin.register_c_compiler('rc.compile.resource', ['RC'], ['OBJ(%_res)'], [])
+
+__angle_include_re = "#include[ ]*<([^<]+)>"
+
+# Register scanner for resources
+class ResScanner(scanner.Scanner):
+
+ def __init__(self, includes):
+ scanner.__init__ ;
+ self.includes = includes
+
+ def pattern(self):
+ return "(([^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)" +\
+ "[ ]+([^ \"]+|\"[^\"]+\"))|(#include[ ]*(<[^<]+>|\"[^\"]+\")))" ;
+
+ def process(self, target, matches, binding):
+
+ angle = regex.transform(matches, "#include[ ]*<([^<]+)>")
+ quoted = regex.transform(matches, "#include[ ]*\"([^\"]+)\"")
+ res = regex.transform(matches,
+ "[^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)" +\
+ "[ ]+(([^ \"]+)|\"([^\"]+)\")", [3, 4])
+
+ # Icons and other includes may referenced as
+ #
+ # IDR_MAINFRAME ICON "res\\icon.ico"
+ #
+ # so we have to replace double backslashes to single ones.
+ res = [ re.sub(r'\\\\', '/', match) for match in res ]
+
+ # CONSIDER: the new scoping rule seem to defeat "on target" variables.
+ g = bjam.call('get-target-variable', target, 'HDRGRIST')
+ b = os.path.normalize_path(os.path.dirname(binding))
+
+ # Attach binding of including file to included targets.
+ # When target is directly created from virtual target
+ # this extra information is unnecessary. But in other
+ # cases, it allows to distinguish between two headers of the
+ # same name included from different places.
+ # We don't need this extra information for angle includes,
+ # since they should not depend on including file (we can't
+ # get literal "." in include path).
+ g2 = g + "#" + b
+
+ g = "<" + g + ">"
+ g2 = "<" + g2 + ">"
+ angle = [g + x for x in angle]
+ quoted = [g2 + x for x in quoted]
+ res = [g2 + x for x in res]
+
+ all = angle + quoted
+
+ bjam.call('mark-included', target, all)
+
+ engine = get_manager().engine()
+
+ engine.add_dependency(target, res)
+ bjam.call('NOCARE', all + res)
+ engine.set_target_variable(angle, 'SEARCH', ungrist(self.includes))
+ engine.set_target_variable(quoted, 'SEARCH', b + ungrist(self.includes))
+ engine.set_target_variable(res, 'SEARCH', b + ungrist(self.includes)) ;
+
+ # Just propagate current scanner to includes, in a hope
+ # that includes do not change scanners.
+ get_manager().scanners().propagate(self, angle + quoted)
+
+scanner.register(ResScanner, 'include')
+type.set_scanner('RC', ResScanner)
diff --git a/tools/build/v2/tools/stage.jam b/tools/build/v2/tools/stage.jam
new file mode 100644
index 0000000000..296e7558e4
--- /dev/null
+++ b/tools/build/v2/tools/stage.jam
@@ -0,0 +1,524 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2005, 2006 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This module defines the 'install' rule, used to copy a set of targets to a
+# single location.
+
+import targets ;
+import "class" : new ;
+import errors ;
+import type ;
+import generators ;
+import feature ;
+import project ;
+import virtual-target ;
+import path ;
+import types/register ;
+
+
+feature.feature <install-dependencies> : off on : incidental ;
+feature.feature <install-type> : : free incidental ;
+feature.feature <install-source-root> : : free path ;
+feature.feature <so-version> : : free incidental ;
+
+# If 'on', version symlinks for shared libraries will not be created. Affects
+# Unix builds only.
+feature.feature <install-no-version-symlinks> : on : optional incidental ;
+
+
+class install-target-class : basic-target
+{
+ import feature ;
+ import project ;
+ import type ;
+ import errors ;
+ import generators ;
+ import path ;
+ import stage ;
+ import "class" : new ;
+ import property ;
+ import property-set ;
+
+ rule __init__ ( name-and-dir : project : sources * : requirements * : default-build * )
+ {
+ basic-target.__init__ $(name-and-dir) : $(project) : $(sources) :
+ $(requirements) : $(default-build) ;
+ }
+
+ # If <location> is not set, sets it based on the project data.
+ #
+ rule update-location ( property-set )
+ {
+ local loc = [ $(property-set).get <location> ] ;
+ if ! $(loc)
+ {
+ loc = [ path.root $(self.name) [ $(self.project).get location ] ] ;
+ property-set = [ $(property-set).add-raw $(loc:G=<location>) ] ;
+ }
+
+ return $(property-set) ;
+ }
+
+ # Takes a target that is installed and a property set which is used when
+ # installing.
+ #
+ rule adjust-properties ( target : build-property-set )
+ {
+ local ps-raw ;
+ local a = [ $(target).action ] ;
+ if $(a)
+ {
+ local ps = [ $(a).properties ] ;
+ ps-raw = [ $(ps).raw ] ;
+
+ # Unless <hardcode-dll-paths>true is in properties, which can happen
+ # only if the user has explicitly requested it, nuke all <dll-path>
+ # properties.
+ if [ $(build-property-set).get <hardcode-dll-paths> ] != true
+ {
+ ps-raw = [ property.change $(ps-raw) : <dll-path> ] ;
+ }
+
+ # If any <dll-path> properties were specified for installing, add
+ # them.
+ local l = [ $(build-property-set).get <dll-path> ] ;
+ ps-raw += $(l:G=<dll-path>) ;
+
+ # Also copy <linkflags> feature from current build set, to be used
+ # for relinking.
+ local l = [ $(build-property-set).get <linkflags> ] ;
+ ps-raw += $(l:G=<linkflags>) ;
+
+ # Remove the <tag> feature on original targets.
+ ps-raw = [ property.change $(ps-raw) : <tag> ] ;
+
+ # And <location>. If stage target has another stage target in
+ # sources, then we shall get virtual targets with the <location>
+ # property set.
+ ps-raw = [ property.change $(ps-raw) : <location> ] ;
+ }
+
+ local d = [ $(build-property-set).get <dependency> ] ;
+ ps-raw += $(d:G=<dependency>) ;
+
+ local d = [ $(build-property-set).get <location> ] ;
+ ps-raw += $(d:G=<location>) ;
+
+ local ns = [ $(build-property-set).get <install-no-version-symlinks> ] ;
+ ps-raw += $(ns:G=<install-no-version-symlinks>) ;
+
+ local d = [ $(build-property-set).get <install-source-root> ] ;
+ # Make the path absolute: we shall use it to compute relative paths and
+ # making the path absolute will help.
+ if $(d)
+ {
+ d = [ path.root $(d) [ path.pwd ] ] ;
+ ps-raw += $(d:G=<install-source-root>) ;
+ }
+
+ if $(ps-raw)
+ {
+ return [ property-set.create $(ps-raw) ] ;
+ }
+ else
+ {
+ return [ property-set.empty ] ;
+ }
+ }
+
+ rule construct ( name : source-targets * : property-set )
+ {
+ source-targets = [ targets-to-stage $(source-targets) :
+ $(property-set) ] ;
+
+ property-set = [ update-location $(property-set) ] ;
+
+ local ename = [ $(property-set).get <name> ] ;
+
+ if $(ename) && $(source-targets[2])
+ {
+ errors.error "When <name> property is used in 'install', only one"
+ "source is allowed" ;
+ }
+
+ local result ;
+ for local i in $(source-targets)
+ {
+ local staged-targets ;
+
+ local new-properties = [ adjust-properties $(i) :
+ $(property-set) ] ;
+
+ # See if something special should be done when staging this type. It
+ # is indicated by the presence of a special "INSTALLED_" type.
+ local t = [ $(i).type ] ;
+ if $(t) && [ type.registered INSTALLED_$(t) ]
+ {
+ if $(ename)
+ {
+ errors.error "In 'install': <name> property specified with target that requires relinking." ;
+ }
+ else
+ {
+ local targets = [ generators.construct $(self.project)
+ $(name) : INSTALLED_$(t) : $(new-properties) : $(i) ] ;
+ staged-targets += $(targets[2-]) ;
+ }
+ }
+ else
+ {
+ staged-targets = [ stage.copy-file $(self.project) $(ename) :
+ $(i) : $(new-properties) ] ;
+ }
+
+ if ! $(staged-targets)
+ {
+ errors.error "Unable to generate staged version of " [ $(source).str ] ;
+ }
+
+ for t in $(staged-targets)
+ {
+ result += [ virtual-target.register $(t) ] ;
+ }
+ }
+
+ return [ property-set.empty ] $(result) ;
+ }
+
+ # Given the list of source targets explicitly passed to 'stage', returns the
+ # list of targets which must be staged.
+ #
+ rule targets-to-stage ( source-targets * : property-set )
+ {
+ local result ;
+
+ # Traverse the dependencies, if needed.
+ if [ $(property-set).get <install-dependencies> ] = "on"
+ {
+ source-targets = [ collect-targets $(source-targets) ] ;
+ }
+
+ # Filter the target types, if needed.
+ local included-types = [ $(property-set).get <install-type> ] ;
+ for local r in $(source-targets)
+ {
+ local ty = [ $(r).type ] ;
+ if $(ty)
+ {
+ # Do not stage searched libs.
+ if $(ty) != SEARCHED_LIB
+ {
+ if $(included-types)
+ {
+ if [ include-type $(ty) : $(included-types) ]
+ {
+ result += $(r) ;
+ }
+ }
+ else
+ {
+ result += $(r) ;
+ }
+ }
+ }
+ else if ! $(included-types)
+ {
+ # Don't install typeless target if there is an explicit list of
+ # allowed types.
+ result += $(r) ;
+ }
+ }
+
+ return $(result) ;
+ }
+
+ # CONSIDER: figure out why we can not use virtual-target.traverse here.
+ #
+ rule collect-targets ( targets * )
+ {
+ # Find subvariants
+ local s ;
+ for local t in $(targets)
+ {
+ s += [ $(t).creating-subvariant ] ;
+ }
+ s = [ sequence.unique $(s) ] ;
+
+ local result = [ new set ] ;
+ $(result).add $(targets) ;
+
+ for local i in $(s)
+ {
+ $(i).all-referenced-targets $(result) ;
+ }
+ local result2 ;
+ for local r in [ $(result).list ]
+ {
+ if $(r:G) != <use>
+ {
+ result2 += $(r:G=) ;
+ }
+ }
+ DELETE_MODULE $(result) ;
+ result = [ sequence.unique $(result2) ] ;
+ }
+
+ # Returns true iff 'type' is subtype of some element of 'types-to-include'.
+ #
+ local rule include-type ( type : types-to-include * )
+ {
+ local found ;
+ while $(types-to-include) && ! $(found)
+ {
+ if [ type.is-subtype $(type) $(types-to-include[1]) ]
+ {
+ found = true ;
+ }
+ types-to-include = $(types-to-include[2-]) ;
+ }
+
+ return $(found) ;
+ }
+}
+
+
+# Creates a copy of target 'source'. The 'properties' object should have a
+# <location> property which specifies where the target must be placed.
+#
+rule copy-file ( project name ? : source : properties )
+{
+ name ?= [ $(source).name ] ;
+ local relative ;
+
+ local new-a = [ new non-scanning-action $(source) : common.copy :
+ $(properties) ] ;
+ local source-root = [ $(properties).get <install-source-root> ] ;
+ if $(source-root)
+ {
+ # Get the real path of the target. We probably need to strip relative
+ # path from the target name at construction.
+ local path = [ $(source).path ] ;
+ path = [ path.root $(name:D) $(path) ] ;
+ # Make the path absolute. Otherwise, it would be hard to compute the
+ # relative path. The 'source-root' is already absolute, see the
+ # 'adjust-properties' method above.
+ path = [ path.root $(path) [ path.pwd ] ] ;
+
+ relative = [ path.relative-to $(source-root) $(path) ] ;
+ }
+
+ # Note: Using $(name:D=$(relative)) might be faster here, but then we would
+ # need to explicitly check that relative is not ".", otherwise we might get
+ # paths like '<prefix>/boost/.', try to create it and mkdir would obviously
+ # fail.
+ name = [ path.join $(relative) $(name:D=) ] ;
+
+ return [ new file-target $(name) exact : [ $(source).type ] : $(project) :
+ $(new-a) ] ;
+}
+
+
+rule symlink ( name : project : source : properties )
+{
+ local a = [ new action $(source) : symlink.ln : $(properties) ] ;
+ return [ new file-target $(name) exact : [ $(source).type ] : $(project) :
+ $(a) ] ;
+}
+
+
+rule relink-file ( project : source : property-set )
+{
+ local action = [ $(source).action ] ;
+ local cloned-action = [ virtual-target.clone-action $(action) : $(project) :
+ "" : $(property-set) ] ;
+ return [ $(cloned-action).targets ] ;
+}
+
+
+# Declare installed version of the EXE type. Generator for this type will cause
+# relinking to the new location.
+type.register INSTALLED_EXE : : EXE ;
+
+
+class installed-exe-generator : generator
+{
+ import type ;
+ import property-set ;
+ import modules ;
+ import stage ;
+
+ rule __init__ ( )
+ {
+ generator.__init__ install-exe : EXE : INSTALLED_EXE ;
+ }
+
+ rule run ( project name ? : property-set : source : multiple ? )
+ {
+ local need-relink ;
+
+ if [ $(property-set).get <os> ] in NT CYGWIN ||
+ [ $(property-set).get <target-os> ] in windows cygwin
+ {
+ }
+ else
+ {
+ # See if the dll-path properties are not changed during
+ # install. If so, copy, don't relink.
+ local a = [ $(source).action ] ;
+ local p = [ $(a).properties ] ;
+ local original = [ $(p).get <dll-path> ] ;
+ local current = [ $(property-set).get <dll-path> ] ;
+
+ if $(current) != $(original)
+ {
+ need-relink = true ;
+ }
+ }
+
+
+ if $(need-relink)
+ {
+ return [ stage.relink-file $(project)
+ : $(source) : $(property-set) ] ;
+ }
+ else
+ {
+ return [ stage.copy-file $(project)
+ : $(source) : $(property-set) ] ;
+ }
+ }
+}
+
+
+generators.register [ new installed-exe-generator ] ;
+
+
+# Installing a shared link on Unix might cause a creation of versioned symbolic
+# links.
+type.register INSTALLED_SHARED_LIB : : SHARED_LIB ;
+
+
+class installed-shared-lib-generator : generator
+{
+ import type ;
+ import property-set ;
+ import modules ;
+ import stage ;
+
+ rule __init__ ( )
+ {
+ generator.__init__ install-shared-lib : SHARED_LIB
+ : INSTALLED_SHARED_LIB ;
+ }
+
+ rule run ( project name ? : property-set : source : multiple ? )
+ {
+ if [ $(property-set).get <os> ] in NT CYGWIN ||
+ [ $(property-set).get <target-os> ] in windows cygwin
+ {
+ local copied = [ stage.copy-file $(project) : $(source) :
+ $(property-set) ] ;
+ return [ virtual-target.register $(copied) ] ;
+ }
+ else
+ {
+ local a = [ $(source).action ] ;
+ local copied ;
+ if ! $(a)
+ {
+ # Non-derived file, just copy.
+ copied = [ stage.copy-file $(project) : $(source) :
+ $(property-set) ] ;
+ }
+ else
+ {
+ local cp = [ $(a).properties ] ;
+ local current-dll-path = [ $(cp).get <dll-path> ] ;
+ local new-dll-path = [ $(property-set).get <dll-path> ] ;
+
+ if $(current-dll-path) != $(new-dll-path)
+ {
+ # Rpath changed, need to relink.
+ copied = [ stage.relink-file $(project) : $(source) :
+ $(property-set) ] ;
+ }
+ else
+ {
+ copied = [ stage.copy-file $(project) : $(source) :
+ $(property-set) ] ;
+ }
+ }
+
+ copied = [ virtual-target.register $(copied) ] ;
+
+ local result = $(copied) ;
+ # If the name is in the form NNN.XXX.YYY.ZZZ, where all 'X', 'Y' and
+ # 'Z' are numbers, we need to create NNN.XXX and NNN.XXX.YYY
+ # symbolic links.
+ local m = [ MATCH (.*)\\.([0123456789]+)\\.([0123456789]+)\\.([0123456789]+)$
+ : [ $(copied).name ] ] ;
+ if $(m)
+ {
+ # Symlink without version at all is used to make
+ # -lsome_library work.
+ result += [ stage.symlink $(m[1]) : $(project) : $(copied) :
+ $(property-set) ] ;
+
+ # Symlinks of some libfoo.N and libfoo.N.M are used so that
+ # library can found at runtime, if libfoo.N.M.X has soname of
+ # libfoo.N. That happens when the library makes some binary
+ # compatibility guarantees. If not, it is possible to skip those
+ # symlinks.
+ local suppress =
+ [ $(property-set).get <install-no-version-symlinks> ] ;
+
+ if $(suppress) != "on"
+ {
+ result += [ stage.symlink $(m[1]).$(m[2]) : $(project)
+ : $(copied) : $(property-set) ] ;
+ result += [ stage.symlink $(m[1]).$(m[2]).$(m[3]) : $(project)
+ : $(copied) : $(property-set) ] ;
+ }
+ }
+
+ return $(result) ;
+ }
+ }
+}
+
+generators.register [ new installed-shared-lib-generator ] ;
+
+
+# Main target rule for 'install'.
+#
+rule install ( name : sources * : requirements * : default-build * )
+{
+ local project = [ project.current ] ;
+
+ # Unless the user has explicitly asked us to hardcode dll paths, add
+ # <hardcode-dll-paths>false in requirements, to override default value.
+ if ! <hardcode-dll-paths>true in $(requirements)
+ {
+ requirements += <hardcode-dll-paths>false ;
+ }
+
+ if <tag> in $(requirements:G)
+ {
+ errors.user-error
+ "The <tag> property is not allowed for the 'install' rule" ;
+ }
+
+ targets.main-target-alternative
+ [ new install-target-class $(name) : $(project)
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+}
+
+
+IMPORT $(__name__) : install : : install ;
+IMPORT $(__name__) : install : : stage ;
diff --git a/tools/build/v2/tools/stage.py b/tools/build/v2/tools/stage.py
new file mode 100644
index 0000000000..25eccbe513
--- /dev/null
+++ b/tools/build/v2/tools/stage.py
@@ -0,0 +1,350 @@
+# Status: ported.
+# Base revision 64444.
+#
+# Copyright 2003 Dave Abrahams
+# Copyright 2005, 2006 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005, 2006, 2010 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This module defines the 'install' rule, used to copy a set of targets to a
+# single location.
+
+import b2.build.feature as feature
+import b2.build.targets as targets
+import b2.build.property as property
+import b2.build.property_set as property_set
+import b2.build.generators as generators
+import b2.build.virtual_target as virtual_target
+
+from b2.manager import get_manager
+from b2.util.sequence import unique
+from b2.util import bjam_signature
+
+import b2.build.type
+
+import os.path
+import re
+import types
+
+feature.feature('install-dependencies', ['off', 'on'], ['incidental'])
+feature.feature('install-type', [], ['free', 'incidental'])
+feature.feature('install-source-root', [], ['free', 'path'])
+feature.feature('so-version', [], ['free', 'incidental'])
+
+# If 'on', version symlinks for shared libraries will not be created. Affects
+# Unix builds only.
+feature.feature('install-no-version-symlinks', ['on'], ['optional', 'incidental'])
+
+class InstallTargetClass(targets.BasicTarget):
+
+ def update_location(self, ps):
+ """If <location> is not set, sets it based on the project data."""
+
+ loc = ps.get('location')
+ if not loc:
+ loc = os.path.join(self.project().get('location'), self.name())
+ ps = ps.add_raw(["<location>" + loc])
+
+ return ps
+
+ def adjust_properties(self, target, build_ps):
+ a = target.action()
+ properties = []
+ if a:
+ ps = a.properties()
+ properties = ps.all()
+
+ # Unless <hardcode-dll-paths>true is in properties, which can happen
+ # only if the user has explicitly requested it, nuke all <dll-path>
+ # properties.
+
+ if build_ps.get('hardcode-dll-paths') != ['true']:
+ properties = [p for p in properties if p.feature().name() != 'dll-path']
+
+ # If any <dll-path> properties were specified for installing, add
+ # them.
+ properties.extend(build_ps.get_properties('dll-path'))
+
+ # Also copy <linkflags> feature from current build set, to be used
+ # for relinking.
+ properties.extend(build_ps.get_properties('linkflags'))
+
+ # Remove the <tag> feature on original targets.
+ # And <location>. If stage target has another stage target in
+ # sources, then we shall get virtual targets with the <location>
+ # property set.
+ properties = [p for p in properties
+ if not p.feature().name() in ['tag', 'location']]
+
+ properties.extend(build_ps.get_properties('dependency'))
+
+ properties.extend(build_ps.get_properties('location'))
+
+
+ properties.extend(build_ps.get_properties('install-no-version-symlinks'))
+
+ d = build_ps.get_properties('install-source-root')
+
+ # Make the path absolute: we shall use it to compute relative paths and
+ # making the path absolute will help.
+ if d:
+ p = d[0]
+ properties.append(property.Property(p.feature(), os.path.abspath(p.value())))
+
+ return property_set.create(properties)
+
+
+ def construct(self, name, source_targets, ps):
+
+ source_targets = self.targets_to_stage(source_targets, ps)
+ ps = self.update_location(ps)
+
+ ename = ps.get('name')
+ if ename:
+ ename = ename[0]
+ if ename and len(source_targets) > 1:
+ get_manager().errors()("When <name> property is used in 'install', only one source is allowed")
+
+ result = []
+
+ for i in source_targets:
+
+ staged_targets = []
+ new_ps = self.adjust_properties(i, ps)
+
+ # See if something special should be done when staging this type. It
+ # is indicated by the presence of a special "INSTALLED_" type.
+ t = i.type()
+ if t and b2.build.type.registered("INSTALLED_" + t):
+
+ if ename:
+ get_manager().errors()("In 'install': <name> property specified with target that requires relinking.")
+ else:
+ (r, targets) = generators.construct(self.project(), name, "INSTALLED_" + t,
+ new_ps, [i])
+ assert isinstance(r, property_set.PropertySet)
+ staged_targets.extend(targets)
+
+ else:
+ staged_targets.append(copy_file(self.project(), ename, i, new_ps))
+
+ if not staged_targets:
+ get_manager().errors()("Unable to generate staged version of " + i)
+
+ result.extend(get_manager().virtual_targets().register(t) for t in staged_targets)
+
+ return (property_set.empty(), result)
+
+ def targets_to_stage(self, source_targets, ps):
+ """Given the list of source targets explicitly passed to 'stage', returns the
+ list of targets which must be staged."""
+
+ result = []
+
+ # Traverse the dependencies, if needed.
+ if ps.get('install-dependencies') == ['on']:
+ source_targets = self.collect_targets(source_targets)
+
+ # Filter the target types, if needed.
+ included_types = ps.get('install-type')
+ for r in source_targets:
+ ty = r.type()
+ if ty:
+ # Do not stage searched libs.
+ if ty != "SEARCHED_LIB":
+ if included_types:
+ if self.include_type(ty, included_types):
+ result.append(r)
+ else:
+ result.append(r)
+ elif not included_types:
+ # Don't install typeless target if there is an explicit list of
+ # allowed types.
+ result.append(r)
+
+ return result
+
+ # CONSIDER: figure out why we can not use virtual-target.traverse here.
+ #
+ def collect_targets(self, targets):
+
+ s = [t.creating_subvariant() for t in targets]
+ s = unique(s)
+
+ result = set(targets)
+ for i in s:
+ i.all_referenced_targets(result)
+
+ result2 = []
+ for r in result:
+ if isinstance(r, property.Property):
+
+ if r.feature().name() != 'use':
+ result2.append(r.value())
+ else:
+ result2.append(r)
+ result2 = unique(result2)
+ return result2
+
+ # Returns true iff 'type' is subtype of some element of 'types-to-include'.
+ #
+ def include_type(self, type, types_to_include):
+ return any(b2.build.type.is_subtype(type, ti) for ti in types_to_include)
+
+# Creates a copy of target 'source'. The 'properties' object should have a
+# <location> property which specifies where the target must be placed.
+#
+def copy_file(project, name, source, ps):
+
+ if not name:
+ name = source.name()
+
+ relative = ""
+
+ new_a = virtual_target.NonScanningAction([source], "common.copy", ps)
+ source_root = ps.get('install-source-root')
+ if source_root:
+ source_root = source_root[0]
+ # Get the real path of the target. We probably need to strip relative
+ # path from the target name at construction.
+ path = os.path.join(source.path(), os.path.dirname(name))
+ # Make the path absolute. Otherwise, it would be hard to compute the
+ # relative path. The 'source-root' is already absolute, see the
+ # 'adjust-properties' method above.
+ path = os.path.abspath(path)
+
+ relative = os.path.relpath(path, source_root)
+
+ name = os.path.join(relative, os.path.basename(name))
+ return virtual_target.FileTarget(name, source.type(), project, new_a, exact=True)
+
+def symlink(name, project, source, ps):
+ a = virtual_target.Action([source], "symlink.ln", ps)
+ return virtual_target.FileTarget(name, source.type(), project, a, exact=True)
+
+def relink_file(project, source, ps):
+ action = source.action()
+ cloned_action = virtual_target.clone_action(action, project, "", ps)
+ targets = cloned_action.targets()
+ # We relink only on Unix, where exe or shared lib is always a single file.
+ assert len(targets) == 1
+ return targets[0]
+
+
+# Declare installed version of the EXE type. Generator for this type will cause
+# relinking to the new location.
+b2.build.type.register('INSTALLED_EXE', [], 'EXE')
+
+class InstalledExeGenerator(generators.Generator):
+
+ def __init__(self):
+ generators.Generator.__init__(self, "install-exe", False, ['EXE'], ['INSTALLED_EXE'])
+
+ def run(self, project, name, ps, source):
+
+ need_relink = False;
+
+ if ps.get('os') in ['NT', 'CYGWIN'] or ps.get('target-os') in ['windows', 'cygwin']:
+ # Never relink
+ pass
+ else:
+ # See if the dll-path properties are not changed during
+ # install. If so, copy, don't relink.
+ need_relink = ps.get('dll-path') != source[0].action().properties().get('dll-path')
+
+ if need_relink:
+ return [relink_file(project, source, ps)]
+ else:
+ return [copy_file(project, None, source[0], ps)]
+
+generators.register(InstalledExeGenerator())
+
+
+# Installing a shared link on Unix might cause a creation of versioned symbolic
+# links.
+b2.build.type.register('INSTALLED_SHARED_LIB', [], 'SHARED_LIB')
+
+class InstalledSharedLibGenerator(generators.Generator):
+
+ def __init__(self):
+ generators.Generator.__init__(self, 'install-shared-lib', False, ['SHARED_LIB'], ['INSTALLED_SHARED_LIB'])
+
+ def run(self, project, name, ps, source):
+
+ source = source[0]
+ if ps.get('os') in ['NT', 'CYGWIN'] or ps.get('target-os') in ['windows', 'cygwin']:
+ copied = copy_file(project, None, source, ps)
+ return [get_manager().virtual_targets().register(copied)]
+ else:
+ a = source.action()
+ if not a:
+ # Non-derived file, just copy.
+ copied = copy_file(project, source, ps)
+ else:
+
+ need_relink = ps.get('dll-path') != source.action().properties().get('dll-path')
+
+ if need_relink:
+ # Rpath changed, need to relink.
+ copied = relink_file(project, source, ps)
+ else:
+ copied = copy_file(project, None, source, ps)
+
+ result = [get_manager().virtual_targets().register(copied)]
+ # If the name is in the form NNN.XXX.YYY.ZZZ, where all 'X', 'Y' and
+ # 'Z' are numbers, we need to create NNN.XXX and NNN.XXX.YYY
+ # symbolic links.
+ m = re.match("(.*)\\.([0123456789]+)\\.([0123456789]+)\\.([0123456789]+)$",
+ copied.name());
+ if m:
+ # Symlink without version at all is used to make
+ # -lsome_library work.
+ result.append(symlink(m.group(1), project, copied, ps))
+
+ # Symlinks of some libfoo.N and libfoo.N.M are used so that
+ # library can found at runtime, if libfoo.N.M.X has soname of
+ # libfoo.N. That happens when the library makes some binary
+ # compatibility guarantees. If not, it is possible to skip those
+ # symlinks.
+ if ps.get('install-no-version-symlinks') != ['on']:
+
+ result.append(symlink(m.group(1) + '.' + m.group(2), project, copied, ps))
+ result.append(symlink(m.group(1) + '.' + m.group(2) + '.' + m.group(3),
+ project, copied, ps))
+
+ return result
+
+generators.register(InstalledSharedLibGenerator())
+
+
+# Main target rule for 'install'.
+#
+@bjam_signature((["name"], ["sources", "*"], ["requirements", "*"],
+ ["default_build", "*"], ["usage_requirements", "*"]))
+def install(name, sources, requirements=[], default_build=[], usage_requirements=[]):
+
+ requirements = requirements[:]
+ # Unless the user has explicitly asked us to hardcode dll paths, add
+ # <hardcode-dll-paths>false in requirements, to override default value.
+ if not '<hardcode-dll-paths>true' in requirements:
+ requirements.append('<hardcode-dll-paths>false')
+
+ if any(r.startswith('<tag>') for r in requirements):
+ get_manager().errors()("The <tag> property is not allowed for the 'install' rule")
+
+ from b2.manager import get_manager
+ t = get_manager().targets()
+
+ project = get_manager().projects().current()
+
+ return t.main_target_alternative(
+ InstallTargetClass(name, project,
+ t.main_target_sources(sources, name),
+ t.main_target_requirements(requirements, project),
+ t.main_target_default_build(default_build, project),
+ t.main_target_usage_requirements(usage_requirements, project)))
+
+get_manager().projects().add_rule("install", install)
+get_manager().projects().add_rule("stage", install)
+
diff --git a/tools/build/v2/tools/stlport.jam b/tools/build/v2/tools/stlport.jam
new file mode 100644
index 0000000000..62eebda5f8
--- /dev/null
+++ b/tools/build/v2/tools/stlport.jam
@@ -0,0 +1,303 @@
+# Copyright Gennadiy Rozental
+# Copyright 2006 Rene Rivera
+# Copyright 2003, 2004, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# The STLPort is usable by means of 'stdlib' feature. When
+# stdlib=stlport is specified, default version of STLPort will be used,
+# while stdlib=stlport-4.5 will use specific version.
+# The subfeature value 'hostios' means to use host compiler's iostreams.
+#
+# The specific version of stlport is selected by features:
+# The <runtime-link> feature selects between static and shared library
+# The <runtime-debugging>on selects STLPort with debug symbols
+# and stl debugging.
+# There's no way to use STLPort with debug symbols but without
+# stl debugging.
+
+# TODO: must implement selection of different STLPort installations based
+# on used toolset.
+# Also, finish various flags:
+#
+# This is copied from V1 toolset, "+" means "implemented"
+#+flags $(CURR_TOOLSET) DEFINES <stlport-iostream>off : _STLP_NO_OWN_IOSTREAMS=1 _STLP_HAS_NO_NEW_IOSTREAMS=1 ;
+#+flags $(CURR_TOOLSET) DEFINES <stlport-extensions>off : _STLP_NO_EXTENSIONS=1 ;
+# flags $(CURR_TOOLSET) DEFINES <stlport-anachronisms>off : _STLP_NO_ANACHRONISMS=1 ;
+# flags $(CURR_TOOLSET) DEFINES <stlport-cstd-namespace>global : _STLP_VENDOR_GLOBAL_CSTD=1 ;
+# flags $(CURR_TOOLSET) DEFINES <exception-handling>off : _STLP_NO_EXCEPTIONS=1 ;
+# flags $(CURR_TOOLSET) DEFINES <stlport-debug-alloc>on : _STLP_DEBUG_ALLOC=1 ;
+#+flags $(CURR_TOOLSET) DEFINES <runtime-build>debug : _STLP_DEBUG=1 _STLP_DEBUG_UNINITIALIZED=1 ;
+#+flags $(CURR_TOOLSET) DEFINES <runtime-link>dynamic : _STLP_USE_DYNAMIC_LIB=1 ;
+
+
+import feature : feature subfeature ;
+import project ;
+import "class" : new ;
+import targets ;
+import property-set ;
+import common ;
+import type ;
+
+# Make this module into a project.
+project.initialize $(__name__) ;
+project stlport ;
+
+# The problem: how to request to use host compiler's iostreams?
+#
+# Solution 1: Global 'stlport-iostream' feature.
+# That's ugly. Subfeature make more sense for stlport-specific thing.
+# Solution 2: Use subfeature with two values, one of which ("use STLPort iostream")
+# is default.
+# The problem is that such subfeature will appear in target paths, and that's ugly
+# Solution 3: Use optional subfeature with only one value.
+
+feature.extend stdlib : stlport ;
+feature.compose <stdlib>stlport : <library>/stlport//stlport ;
+
+# STLport iostreams or native iostreams
+subfeature stdlib stlport : iostream : hostios : optional propagated ;
+
+# STLport extensions
+subfeature stdlib stlport : extensions : noext : optional propagated ;
+
+# STLport anachronisms -- NOT YET SUPPORTED
+# subfeature stdlib stlport : anachronisms : on off ;
+
+# STLport debug allocation -- NOT YET SUPPORTED
+#subfeature stdlib stlport : debug-alloc : off on ;
+
+# Declare a special target class to handle the creation of search-lib-target
+# instances for STLport. We need a special class, because otherwise we'll have
+# - declare prebuilt targets for all possible toolsets. And by the time 'init'
+# is called we don't even know the list of toolsets that are registered
+# - when host iostreams are used, we really should produce nothing. It would
+# be hard/impossible to achieve this using prebuilt targets.
+
+class stlport-target-class : basic-target
+{
+ import feature project type errors generators ;
+ import set : difference ;
+
+ rule __init__ ( project : headers ? : libraries * : version ? )
+ {
+ basic-target.__init__ stlport : $(project) ;
+ self.headers = $(headers) ;
+ self.libraries = $(libraries) ;
+ self.version = $(version) ;
+ self.version.5 = [ MATCH "^(5[.][0123456789]+).*" : $(version) ] ;
+
+ local requirements ;
+ requirements += <stdlib-stlport:version>$(self.version) ;
+ self.requirements = [ property-set.create $(requirements) ] ;
+ }
+
+ rule generate ( property-set )
+ {
+ # Since this target is built with <stdlib>stlport, it will also
+ # have <library>/stlport//stlport in requirements, which will
+ # cause a loop in main target references. Remove that property
+ # manually.
+
+ property-set = [ property-set.create
+ [ difference
+ [ $(property-set).raw ] :
+ <library>/stlport//stlport
+ <stdlib>stlport
+ ]
+ ] ;
+ return [ basic-target.generate $(property-set) ] ;
+ }
+
+ rule construct ( name : source-targets * : property-set )
+ {
+ # Deduce the name of stlport library, based on toolset and
+ # debug setting.
+ local raw = [ $(property-set).raw ] ;
+ local hostios = [ feature.get-values <stdlib-stlport:iostream> : $(raw) ] ;
+ local toolset = [ feature.get-values <toolset> : $(raw) ] ;
+
+ if $(self.version.5)
+ {
+ # Version 5.x
+
+ # STLport host IO streams no longer supported. So we always
+ # need libraries.
+
+ # name: stlport(stl)?[dg]?(_static)?.M.R
+ local name = stlport ;
+ if [ feature.get-values <runtime-debugging> : $(raw) ] = "on"
+ {
+ name += stl ;
+ switch $(toolset)
+ {
+ case gcc* : name += g ;
+ case darwin* : name += g ;
+ case * : name += d ;
+ }
+ }
+
+ if [ feature.get-values <runtime-link> : $(raw) ] = "static"
+ {
+ name += _static ;
+ }
+
+ # Starting with version 5.2.0, the STLport static libraries no longer
+ # include a version number in their name
+ local version.pre.5.2 = [ MATCH "^(5[.][01]+).*" : $(version) ] ;
+ if $(version.pre.5.2) || [ feature.get-values <runtime-link> : $(raw) ] != "static"
+ {
+ name += .$(self.version.5) ;
+ }
+
+ name = $(name:J=) ;
+
+ if [ feature.get-values <install-dependencies> : $(raw) ] = "on"
+ {
+ #~ Allow explicitly asking to install the STLport lib by
+ #~ refering to it directly: /stlport//stlport/<install-dependencies>on
+ #~ This allows for install packaging of all libs one might need for
+ #~ a standalone distribution.
+ import path : make : path-make ;
+ local runtime-link
+ = [ feature.get-values <runtime-link> : $(raw) ] ;
+ local lib-file.props
+ = [ property-set.create $(raw) <link>$(runtime-link) ] ;
+ local lib-file.prefix
+ = [ type.generated-target-prefix $(runtime-link:U)_LIB : $(lib-file.props) ] ;
+ local lib-file.suffix
+ = [ type.generated-target-suffix $(runtime-link:U)_LIB : $(lib-file.props) ] ;
+ lib-file.prefix
+ ?= "" "lib" ;
+ lib-file.suffix
+ ?= "" ;
+ local lib-file
+ = [ GLOB $(self.libraries) [ modules.peek : PATH ] :
+ $(lib-file.prefix)$(name).$(lib-file.suffix) ] ;
+ lib-file
+ = [ new file-reference [ path-make $(lib-file[1]) ] : $(self.project) ] ;
+ lib-file
+ = [ $(lib-file).generate "" ] ;
+ local lib-file.requirements
+ = [ targets.main-target-requirements
+ [ $(lib-file.props).raw ] <file>$(lib-file[-1])
+ : $(self.project) ] ;
+ return [ generators.construct $(self.project) $(name) : LIB : $(lib-file.requirements) ] ;
+ }
+ else
+ {
+ #~ Otherwise, it's just a regular usage of the library.
+ return [ generators.construct
+ $(self.project) $(name) : SEARCHED_LIB : $(property-set) ] ;
+ }
+ }
+ else if ! $(hostios) && $(toolset) != msvc
+ {
+ # We don't need libraries if host istreams are used. For
+ # msvc, automatic library selection will be used.
+
+ # name: stlport_<toolset>(_stldebug)?
+ local name = stlport ;
+ name = $(name)_$(toolset) ;
+ if [ feature.get-values <runtime-debugging> : $(raw) ] = "on"
+ {
+ name = $(name)_stldebug ;
+ }
+
+ return [ generators.construct
+ $(self.project) $(name) : SEARCHED_LIB : $(property-set) ] ;
+ }
+ else
+ {
+ return [ property-set.empty ] ;
+ }
+ }
+
+ rule compute-usage-requirements ( subvariant )
+ {
+ local usage-requirements =
+ <include>$(self.headers)
+ <dll-path>$(self.libraries)
+ <library-path>$(self.libraries)
+ ;
+
+ local rproperties = [ $(subvariant).build-properties ] ;
+ # CONSIDER: should this "if" sequence be replaced with
+ # some use of 'property-map' class?
+ if [ $(rproperties).get <runtime-debugging> ] = "on"
+ {
+ usage-requirements +=
+ <define>_STLP_DEBUG=1
+ <define>_STLP_DEBUG_UNINITIALIZED=1 ;
+ }
+ if [ $(rproperties).get <runtime-link> ] = "shared"
+ {
+ usage-requirements +=
+ <define>_STLP_USE_DYNAMIC_LIB=1 ;
+ }
+ if [ $(rproperties).get <stdlib-stlport:extensions> ] = noext
+ {
+ usage-requirements +=
+ <define>_STLP_NO_EXTENSIONS=1 ;
+ }
+ if [ $(rproperties).get <stdlib-stlport:iostream> ] = hostios
+ {
+ usage-requirements +=
+ <define>_STLP_NO_OWN_IOSTREAMS=1
+ <define>_STLP_HAS_NO_NEW_IOSTREAMS=1 ;
+ }
+ if $(self.version.5)
+ {
+ # Version 5.x
+ if [ $(rproperties).get <threading> ] = "single"
+ {
+ # Since STLport5 doesn't normally support single-thread
+ # we force STLport5 into the multi-thread mode. Hence
+ # getting what other libs provide of single-thread code
+ # linking against a multi-thread lib.
+ usage-requirements +=
+ <define>_STLP_THREADS=1 ;
+ }
+ }
+
+ return [ property-set.create $(usage-requirements) ] ;
+ }
+}
+
+rule stlport-target ( headers ? : libraries * : version ? )
+{
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new stlport-target-class $(project) : $(headers) : $(libraries)
+ : $(version)
+ ] ;
+}
+
+local .version-subfeature-defined ;
+
+# Initialize stlport support.
+rule init (
+ version ? :
+ headers : # Location of header files
+ libraries * # Location of libraries, lib and bin subdirs of STLport.
+ )
+{
+ # FIXME: need to use common.check-init-parameters here.
+ # At the moment, that rule always tries to define subfeature
+ # of the 'toolset' feature, while we need to define subfeature
+ # of <stdlib>stlport, so tweaks to check-init-parameters are needed.
+ if $(version)
+ {
+ if ! $(.version-subfeature-defined)
+ {
+ feature.subfeature stdlib stlport : version : : propagated ;
+ .version-subfeature-defined = true ;
+ }
+ feature.extend-subfeature stdlib stlport : version : $(version) ;
+ }
+
+ # Declare the main target for this STLPort version.
+ stlport-target $(headers) : $(libraries) : $(version) ;
+}
+
diff --git a/tools/build/v2/tools/sun.jam b/tools/build/v2/tools/sun.jam
new file mode 100644
index 0000000000..0ca927d3e4
--- /dev/null
+++ b/tools/build/v2/tools/sun.jam
@@ -0,0 +1,142 @@
+# Copyright (C) Christopher Currie 2003. Permission to copy, use,
+# modify, sell and distribute this software is granted provided this
+# copyright notice appears in all copies. This software is provided
+# "as is" without express or implied warranty, and with no claim as
+# to its suitability for any purpose.
+
+import property ;
+import generators ;
+import os ;
+import toolset : flags ;
+import feature ;
+import type ;
+import common ;
+
+feature.extend toolset : sun ;
+toolset.inherit sun : unix ;
+generators.override sun.prebuilt : builtin.lib-generator ;
+generators.override sun.prebuilt : builtin.prebuilt ;
+generators.override sun.searched-lib-generator : searched-lib-generator ;
+
+feature.extend stdlib : sun-stlport ;
+feature.compose <stdlib>sun-stlport
+ : <cxxflags>-library=stlport4 <linkflags>-library=stlport4
+ ;
+
+rule init ( version ? : command * : options * )
+{
+ local condition = [
+ common.check-init-parameters sun : version $(version) ] ;
+
+ command = [ common.get-invocation-command sun : CC
+ : $(command) : "/opt/SUNWspro/bin" ] ;
+
+ # Even if the real compiler is not found, put CC to
+ # command line so that user see command line that would have being executed.
+ command ?= CC ;
+
+ common.handle-options sun : $(condition) : $(command) : $(options) ;
+
+ command_c = $(command[1--2]) $(command[-1]:B=cc) ;
+
+ toolset.flags sun CONFIG_C_COMMAND $(condition) : $(command_c) ;
+}
+
+# Declare generators
+generators.register-c-compiler sun.compile.c : C : OBJ : <toolset>sun ;
+generators.register-c-compiler sun.compile.c++ : CPP : OBJ : <toolset>sun ;
+
+# Declare flags and actions for compilation
+flags sun.compile OPTIONS <debug-symbols>on : -g ;
+flags sun.compile OPTIONS <profiling>on : -xprofile=tcov ;
+flags sun.compile OPTIONS <optimization>speed : -xO4 ;
+flags sun.compile OPTIONS <optimization>space : -xO2 -xspace ;
+flags sun.compile OPTIONS <threading>multi : -mt ;
+flags sun.compile OPTIONS <warnings>off : -erroff ;
+flags sun.compile OPTIONS <warnings>on : -erroff=%none ;
+flags sun.compile OPTIONS <warnings>all : -erroff=%none ;
+flags sun.compile OPTIONS <warnings-as-errors>on : -errwarn ;
+
+flags sun.compile.c++ OPTIONS <inlining>off : +d ;
+
+# The -m32 and -m64 options are supported starting
+# with Sun Studio 12. On earlier compilers, the
+# 'address-model' feature is not supported and should not
+# be used. Instead, use -xarch=generic64 command line
+# option.
+# See http://svn.boost.org/trac/boost/ticket/1186
+# for details.
+flags sun OPTIONS <address-model>32 : -m32 ;
+flags sun OPTIONS <address-model>64 : -m64 ;
+# On sparc, there's a difference between -Kpic
+# and -KPIC. The first is slightly more efficient,
+# but has the limits on the size of GOT table.
+# For minimal fuss on user side, we use -KPIC here.
+# See http://svn.boost.org/trac/boost/ticket/1186#comment:6
+# for detailed explanation.
+flags sun OPTIONS <link>shared : -KPIC ;
+
+flags sun.compile OPTIONS <cflags> ;
+flags sun.compile.c++ OPTIONS <cxxflags> ;
+flags sun.compile DEFINES <define> ;
+flags sun.compile INCLUDES <include> ;
+
+actions compile.c
+{
+ "$(CONFIG_C_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+# Declare flags and actions for linking
+flags sun.link OPTIONS <debug-symbols>on : -g ;
+# Strip the binary when no debugging is needed
+flags sun.link OPTIONS <debug-symbols>off : -s ;
+flags sun.link OPTIONS <profiling>on : -xprofile=tcov ;
+flags sun.link OPTIONS <threading>multi : -mt ;
+flags sun.link OPTIONS <linkflags> ;
+flags sun.link LINKPATH <library-path> ;
+flags sun.link FINDLIBS-ST <find-static-library> ;
+flags sun.link FINDLIBS-SA <find-shared-library> ;
+flags sun.link LIBRARIES <library-file> ;
+flags sun.link LINK-RUNTIME <runtime-link>static : static ;
+flags sun.link LINK-RUNTIME <runtime-link>shared : dynamic ;
+flags sun.link RPATH <dll-path> ;
+# On gcc, there are separate options for dll path at runtime and
+# link time. On Solaris, there's only one: -R, so we have to use
+# it, even though it's bad idea.
+flags sun.link RPATH <xdll-path> ;
+
+# The POSIX real-time library is always needed (nanosleep, clock_gettime etc.)
+flags sun.link FINDLIBS-SA : rt ;
+
+rule link ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -L"$(LINKPATH)" -R"$(RPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -Bdynamic -l$(FINDLIBS-SA) -Bstatic -l$(FINDLIBS-ST) -B$(LINK-RUNTIME)
+}
+
+# Slight mods for dlls
+rule link.dll ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -L"$(LINKPATH)" -R"$(RPATH)" -o "$(<)" -h$(<[1]:D=) -G "$(>)" "$(LIBRARIES)" -Bdynamic -l$(FINDLIBS-SA) -Bstatic -l$(FINDLIBS-ST) -B$(LINK-RUNTIME)
+}
+
+# Declare action for creating static libraries
+actions piecemeal archive
+{
+ "$(CONFIG_COMMAND)" -xar -o "$(<)" "$(>)"
+}
+
diff --git a/tools/build/v2/tools/symlink.jam b/tools/build/v2/tools/symlink.jam
new file mode 100644
index 0000000000..b33e8260c2
--- /dev/null
+++ b/tools/build/v2/tools/symlink.jam
@@ -0,0 +1,140 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Defines the "symlink" special target. 'symlink' targets make symbolic links
+# to the sources.
+
+import targets modules path class os feature project property-set ;
+
+.count = 0 ;
+
+feature.feature symlink-location : project-relative build-relative : incidental ;
+
+# The class representing "symlink" targets.
+#
+class symlink-targets : basic-target
+{
+ import numbers modules class property project path ;
+
+ rule __init__ (
+ project
+ : targets *
+ : sources *
+ )
+ {
+ # Generate a fake name for now. Need unnamed targets eventually.
+ local c = [ modules.peek symlink : .count ] ;
+ modules.poke symlink : .count : [ numbers.increment $(c) ] ;
+ local fake-name = symlink#$(c) ;
+
+ basic-target.__init__ $(fake-name) : $(project) : $(sources) ;
+
+ # Remember the targets to map the sources onto. Pad or truncate
+ # to fit the sources given.
+ self.targets = ;
+ for local source in $(sources)
+ {
+ if $(targets)
+ {
+ self.targets += $(targets[1]) ;
+ targets = $(targets[2-]) ;
+ }
+ else
+ {
+ self.targets += $(source) ;
+ }
+ }
+
+ # The virtual targets corresponding to the given targets.
+ self.virtual-targets = ;
+ }
+
+ rule construct ( name : source-targets * : property-set )
+ {
+ local i = 1 ;
+ for local t in $(source-targets)
+ {
+ local s = $(self.targets[$(i)]) ;
+ local a = [ class.new action $(t) : symlink.ln : $(property-set) ] ;
+ local vt = [ class.new file-target $(s:D=)
+ : [ $(t).type ] : $(self.project) : $(a) ] ;
+
+ # Place the symlink in the directory relative to the project
+ # location, instead of placing it in the build directory.
+ if [ property.select <symlink-location> : [ $(property-set).raw ] ] = <symlink-location>project-relative
+ {
+ $(vt).set-path [ path.root $(s:D) [ $(self.project).get location ] ] ;
+ }
+
+ self.virtual-targets += $(vt) ;
+ i = [ numbers.increment $(i) ] ;
+ }
+ return [ property-set.empty ] $(self.virtual-targets) ;
+ }
+}
+
+# Creates a symbolic link from a set of targets to a set of sources.
+# The targets and sources map one to one. The symlinks generated are
+# limited to be the ones given as the sources. That is, the targets
+# are either padded or trimmed to equate to the sources. The padding
+# is done with the name of the corresponding source. For example::
+#
+# symlink : one two ;
+#
+# Is equal to::
+#
+# symlink one two : one two ;
+#
+# Names for symlink are relative to the project location. They cannot
+# include ".." path components.
+rule symlink (
+ targets *
+ : sources *
+ )
+{
+ local project = [ project.current ] ;
+
+ return [ targets.main-target-alternative
+ [ class.new symlink-targets $(project) : $(targets) :
+ # Note: inline targets are not supported for symlink, intentionally,
+ # since it's used to linking existing non-local targets.
+ $(sources) ] ] ;
+}
+
+rule ln
+{
+ local os ;
+ if [ modules.peek : UNIX ] { os = UNIX ; }
+ else { os ?= [ os.name ] ; }
+ # Remember the path to make the link relative to where the symlink is located.
+ local path-to-source = [ path.relative-to
+ [ path.make [ on $(<) return $(LOCATE) ] ]
+ [ path.make [ on $(>) return $(LOCATE) ] ] ] ;
+ if $(path-to-source) = .
+ {
+ PATH_TO_SOURCE on $(<) = "" ;
+ }
+ else
+ {
+ PATH_TO_SOURCE on $(<) = [ path.native $(path-to-source) ] ;
+ }
+ ln-$(os) $(<) : $(>) ;
+}
+
+actions ln-UNIX
+{
+ ln -f -s '$(>:D=:R=$(PATH_TO_SOURCE))' '$(<)'
+}
+
+# there is a way to do this; we fall back to a copy for now
+actions ln-NT
+{
+ echo "NT symlinks not supported yet, making copy"
+ del /f /q "$(<)" 2>nul >nul
+ copy "$(>)" "$(<)" $(NULL_OUT)
+}
+
+IMPORT $(__name__) : symlink : : symlink ;
diff --git a/tools/build/v2/tools/symlink.py b/tools/build/v2/tools/symlink.py
new file mode 100644
index 0000000000..6345ded6d3
--- /dev/null
+++ b/tools/build/v2/tools/symlink.py
@@ -0,0 +1,112 @@
+# Status: ported.
+# Base revision: 64488.
+
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Defines the "symlink" special target. 'symlink' targets make symbolic links
+# to the sources.
+
+import b2.build.feature as feature
+import b2.build.targets as targets
+import b2.build.property_set as property_set
+import b2.build.virtual_target as virtual_target
+import b2.build.targets
+
+from b2.manager import get_manager
+
+import bjam
+
+import os
+
+
+feature.feature("symlink-location", ["project-relative", "build-relative"], ["incidental"])
+
+class SymlinkTarget(targets.BasicTarget):
+
+ _count = 0
+
+ def __init__(self, project, targets, sources):
+
+ # Generate a fake name for now. Need unnamed targets eventually.
+ fake_name = "symlink#%s" % SymlinkTarget._count
+ SymlinkTarget._count = SymlinkTarget._count + 1
+
+ b2.build.targets.BasicTarget.__init__(self, fake_name, project, sources)
+
+ # Remember the targets to map the sources onto. Pad or truncate
+ # to fit the sources given.
+ assert len(targets) <= len(sources)
+ self.targets = targets[:] + sources[len(targets):]
+
+ # The virtual targets corresponding to the given targets.
+ self.virtual_targets = []
+
+ def construct(self, name, source_targets, ps):
+ i = 0
+ for t in source_targets:
+ s = self.targets[i]
+ a = virtual_target.Action(self.manager(), [t], "symlink.ln", ps)
+ vt = virtual_target.FileTarget(os.path.basename(s), t.type(), self.project(), a)
+
+ # Place the symlink in the directory relative to the project
+ # location, instead of placing it in the build directory.
+ if not ps.get('symlink-location') == "project-relative":
+ vt.set_path(os.path.join(self.project().get('location'), os.path.dirname(s)))
+
+ vt = get_manager().virtual_targets().register(vt)
+ self.virtual_targets.append(vt)
+ i = i + 1
+
+ return (property_set.empty(), self.virtual_targets)
+
+# Creates a symbolic link from a set of targets to a set of sources.
+# The targets and sources map one to one. The symlinks generated are
+# limited to be the ones given as the sources. That is, the targets
+# are either padded or trimmed to equate to the sources. The padding
+# is done with the name of the corresponding source. For example::
+#
+# symlink : one two ;
+#
+# Is equal to::
+#
+# symlink one two : one two ;
+#
+# Names for symlink are relative to the project location. They cannot
+# include ".." path components.
+def symlink(targets, sources):
+
+ from b2.manager import get_manager
+ t = get_manager().targets()
+ p = get_manager().projects().current()
+
+ return t.main_target_alternative(
+ SymlinkTarget(p, targets,
+ # Note: inline targets are not supported for symlink, intentionally,
+ # since it's used to linking existing non-local targets.
+ sources))
+
+
+def setup_ln(targets, sources, ps):
+
+ source_path = bjam.call("get-target-variable", sources[0], "LOCATE")[0]
+ target_path = bjam.call("get-target-variable", targets[0], "LOCATE")[0]
+ rel = os.path.relpath(source_path, target_path)
+ if rel == ".":
+ bjam.call("set-target-variable", targets, "PATH_TO_SOURCE", "")
+ else:
+ bjam.call("set-target-variable", targets, "PATH_TO_SOURCE", rel)
+
+if os.name == 'nt':
+ ln_action = """echo "NT symlinks not supported yet, making copy"
+del /f /q "$(<)" 2>nul >nul
+copy "$(>)" "$(<)" $(NULL_OUT)"""
+else:
+ ln_action = "ln -f -s '$(>:D=:R=$(PATH_TO_SOURCE))' '$(<)'"
+
+get_manager().engine().register_action("symlink.ln", ln_action, function=setup_ln)
+
+get_manager().projects().add_rule("symlink", symlink)
diff --git a/tools/build/v2/tools/testing-aux.jam b/tools/build/v2/tools/testing-aux.jam
new file mode 100644
index 0000000000..525dafd0cb
--- /dev/null
+++ b/tools/build/v2/tools/testing-aux.jam
@@ -0,0 +1,210 @@
+# This module is imported by testing.py. The definitions here are
+# too tricky to do in Python
+
+# Causes the 'target' to exist after bjam invocation if and only if all the
+# dependencies were successfully built.
+#
+rule expect-success ( target : dependency + : requirements * )
+{
+ **passed** $(target) : $(sources) ;
+}
+IMPORT testing : expect-success : : testing.expect-success ;
+
+# Causes the 'target' to exist after bjam invocation if and only if all some of
+# the dependencies were not successfully built.
+#
+rule expect-failure ( target : dependency + : properties * )
+{
+ local grist = [ MATCH ^<(.*)> : $(dependency:G) ] ;
+ local marker = $(dependency:G=$(grist)*fail) ;
+ (failed-as-expected) $(marker) ;
+ FAIL_EXPECTED $(dependency) ;
+ LOCATE on $(marker) = [ on $(dependency) return $(LOCATE) ] ;
+ RMOLD $(marker) ;
+ DEPENDS $(marker) : $(dependency) ;
+ DEPENDS $(target) : $(marker) ;
+ **passed** $(target) : $(marker) ;
+}
+IMPORT testing : expect-failure : : testing.expect-failure ;
+
+# The rule/action combination used to report successful passing of a test.
+#
+rule **passed**
+{
+ # Force deletion of the target, in case any dependencies failed to build.
+ RMOLD $(<) ;
+}
+
+
+# Used to create test files signifying passed tests.
+#
+actions **passed**
+{
+ echo passed > "$(<)"
+}
+
+
+# Used to create replacement object files that do not get created during tests
+# that are expected to fail.
+#
+actions (failed-as-expected)
+{
+ echo failed as expected > "$(<)"
+}
+
+# Runs executable 'sources' and stores stdout in file 'target'. Unless
+# --preserve-test-targets command line option has been specified, removes the
+# executable. The 'target-to-remove' parameter controls what should be removed:
+# - if 'none', does not remove anything, ever
+# - if empty, removes 'source'
+# - if non-empty and not 'none', contains a list of sources to remove.
+#
+rule capture-output ( target : source : properties * : targets-to-remove * )
+{
+ output-file on $(target) = $(target:S=.output) ;
+ LOCATE on $(target:S=.output) = [ on $(target) return $(LOCATE) ] ;
+
+ # The INCLUDES kill a warning about independent target...
+ INCLUDES $(target) : $(target:S=.output) ;
+ # but it also puts .output into dependency graph, so we must tell jam it is
+ # OK if it cannot find the target or updating rule.
+ NOCARE $(target:S=.output) ;
+
+ # This has two-fold effect. First it adds input files to the dependendency
+ # graph, preventing a warning. Second, it causes input files to be bound
+ # before target is created. Therefore, they are bound using SEARCH setting
+ # on them and not LOCATE setting of $(target), as in other case (due to jam
+ # bug).
+ DEPENDS $(target) : [ on $(target) return $(INPUT_FILES) ] ;
+
+ if $(targets-to-remove) = none
+ {
+ targets-to-remove = ;
+ }
+ else if ! $(targets-to-remove)
+ {
+ targets-to-remove = $(source) ;
+ }
+
+ if [ on $(target) return $(REMOVE_TEST_TARGETS) ]
+ {
+ TEMPORARY $(targets-to-remove) ;
+ # Set a second action on target that will be executed after capture
+ # output action. The 'RmTemps' rule has the 'ignore' modifier so it is
+ # always considered succeeded. This is needed for 'run-fail' test. For
+ # that test the target will be marked with FAIL_EXPECTED, and without
+ # 'ignore' successful execution will be negated and be reported as
+ # failure. With 'ignore' we do not detect a case where removing files
+ # fails, but it is not likely to happen.
+ RmTemps $(target) : $(targets-to-remove) ;
+ }
+}
+
+
+if [ os.name ] = NT
+{
+ .STATUS = %status% ;
+ .SET_STATUS = "set status=%ERRORLEVEL%" ;
+ .RUN_OUTPUT_NL = "echo." ;
+ .STATUS_0 = "%status% EQU 0 (" ;
+ .STATUS_NOT_0 = "%status% NEQ 0 (" ;
+ .VERBOSE = "%verbose% EQU 1 (" ;
+ .ENDIF = ")" ;
+ .SHELL_SET = "set " ;
+ .CATENATE = type ;
+ .CP = copy ;
+}
+else
+{
+ .STATUS = "$status" ;
+ .SET_STATUS = "status=$?" ;
+ .RUN_OUTPUT_NL = "echo" ;
+ .STATUS_0 = "test $status -eq 0 ; then" ;
+ .STATUS_NOT_0 = "test $status -ne 0 ; then" ;
+ .VERBOSE = "test $verbose -eq 1 ; then" ;
+ .ENDIF = "fi" ;
+ .SHELL_SET = "" ;
+ .CATENATE = cat ;
+ .CP = cp ;
+}
+
+
+.VERBOSE_TEST = 0 ;
+if --verbose-test in [ modules.peek : ARGV ]
+{
+ .VERBOSE_TEST = 1 ;
+}
+
+
+.RM = [ common.rm-command ] ;
+
+
+actions capture-output bind INPUT_FILES output-file
+{
+ $(PATH_SETUP)
+ $(LAUNCHER) "$(>)" $(ARGS) "$(INPUT_FILES)" > "$(output-file)" 2>&1
+ $(.SET_STATUS)
+ $(.RUN_OUTPUT_NL) >> "$(output-file)"
+ echo EXIT STATUS: $(.STATUS) >> "$(output-file)"
+ if $(.STATUS_0)
+ $(.CP) "$(output-file)" "$(<)"
+ $(.ENDIF)
+ $(.SHELL_SET)verbose=$(.VERBOSE_TEST)
+ if $(.STATUS_NOT_0)
+ $(.SHELL_SET)verbose=1
+ $(.ENDIF)
+ if $(.VERBOSE)
+ echo ====== BEGIN OUTPUT ======
+ $(.CATENATE) "$(output-file)"
+ echo ====== END OUTPUT ======
+ $(.ENDIF)
+ exit $(.STATUS)
+}
+
+IMPORT testing : capture-output : : testing.capture-output ;
+
+
+actions quietly updated ignore piecemeal together RmTemps
+{
+ $(.RM) "$(>)"
+}
+
+
+.MAKE_FILE = [ common.file-creation-command ] ;
+
+actions unit-test
+{
+ $(PATH_SETUP)
+ $(LAUNCHER) $(>) $(ARGS) && $(.MAKE_FILE) $(<)
+}
+
+rule record-time ( target : source : start end user system )
+{
+ local src-string = [$(source:G=:J=",")"] " ;
+ USER_TIME on $(target) += $(src-string)$(user) ;
+ SYSTEM_TIME on $(target) += $(src-string)$(system) ;
+}
+
+# Calling this rule requests that Boost Build time how long it taks to build the
+# 'source' target and display the results both on the standard output and in the
+# 'target' file.
+#
+rule time ( target : source : properties * )
+{
+ # Set up rule for recording timing information.
+ __TIMING_RULE__ on $(source) = testing.record-time $(target) ;
+
+ # Make sure that the source is rebuilt any time we need to retrieve that
+ # information.
+ REBUILDS $(target) : $(source) ;
+}
+
+
+actions time
+{
+ echo user: $(USER_TIME)
+ echo system: $(SYSTEM_TIME)
+
+ echo user: $(USER_TIME)" seconds" > "$(<)"
+ echo system: $(SYSTEM_TIME)" seconds" >> "$(<)"
+}
diff --git a/tools/build/v2/tools/testing.jam b/tools/build/v2/tools/testing.jam
new file mode 100644
index 0000000000..c42075b78a
--- /dev/null
+++ b/tools/build/v2/tools/testing.jam
@@ -0,0 +1,581 @@
+# Copyright 2005 Dave Abrahams
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This module implements regression testing framework. It declares a number of
+# main target rules which perform some action and, if the results are OK,
+# creates an output file.
+#
+# The exact list of rules is:
+# 'compile' -- creates .test file if compilation of sources was
+# successful.
+# 'compile-fail' -- creates .test file if compilation of sources failed.
+# 'run' -- creates .test file is running of executable produced from
+# sources was successful. Also leaves behind .output file
+# with the output from program run.
+# 'run-fail' -- same as above, but .test file is created if running fails.
+#
+# In all cases, presence of .test file is an indication that the test passed.
+# For more convenient reporting, you might want to use C++ Boost regression
+# testing utilities (see http://www.boost.org/more/regression.html).
+#
+# For historical reason, a 'unit-test' rule is available which has the same
+# syntax as 'exe' and behaves just like 'run'.
+
+# Things to do:
+# - Teach compiler_status handle Jamfile.v2.
+# Notes:
+# - <no-warn> is not implemented, since it is Como-specific, and it is not
+# clear how to implement it
+# - std::locale-support is not implemented (it is used in one test).
+
+
+import alias ;
+import "class" ;
+import common ;
+import errors ;
+import feature ;
+import generators ;
+import os ;
+import path ;
+import project ;
+import property ;
+import property-set ;
+import regex ;
+import sequence ;
+import targets ;
+import toolset ;
+import type ;
+import virtual-target ;
+
+
+rule init ( )
+{
+}
+
+
+# Feature controling the command used to lanch test programs.
+feature.feature testing.launcher : : free optional ;
+
+feature.feature test-info : : free incidental ;
+feature.feature testing.arg : : free incidental ;
+feature.feature testing.input-file : : free dependency ;
+
+feature.feature preserve-test-targets : on off : incidental propagated ;
+
+# Register target types.
+type.register TEST : test ;
+type.register COMPILE : : TEST ;
+type.register COMPILE_FAIL : : TEST ;
+type.register RUN_OUTPUT : run ;
+type.register RUN : : TEST ;
+type.register RUN_FAIL : : TEST ;
+type.register LINK_FAIL : : TEST ;
+type.register LINK : : TEST ;
+type.register UNIT_TEST : passed : TEST ;
+
+
+# Declare the rules which create main targets. While the 'type' module already
+# creates rules with the same names for us, we need extra convenience: default
+# name of main target, so write our own versions.
+
+# Helper rule. Create a test target, using basename of first source if no target
+# name is explicitly passed. Remembers the created target in a global variable.
+#
+rule make-test ( target-type : sources + : requirements * : target-name ? )
+{
+ target-name ?= $(sources[1]:D=:S=) ;
+
+ # Having periods (".") in the target name is problematic because the typed
+ # generator will strip the suffix and use the bare name for the file
+ # targets. Even though the location-prefix averts problems most times it
+ # does not prevent ambiguity issues when referring to the test targets. For
+ # example when using the XML log output. So we rename the target to remove
+ # the periods, and provide an alias for users.
+ local real-name = [ regex.replace $(target-name) "[.]" "~" ] ;
+
+ local project = [ project.current ] ;
+ # The <location-prefix> forces the build system for generate paths in the
+ # form '$build_dir/array1.test/gcc/debug'. This is necessary to allow
+ # post-processing tools to work.
+ local t = [ targets.create-typed-target [ type.type-from-rule-name
+ $(target-type) ] : $(project) : $(real-name) : $(sources) :
+ $(requirements) <location-prefix>$(real-name).test ] ;
+
+ # The alias to the real target, per period replacement above.
+ if $(real-name) != $(target-name)
+ {
+ alias $(target-name) : $(t) ;
+ }
+
+ # Remember the test (for --dump-tests). A good way would be to collect all
+ # given a project. This has some technical problems: e.g. we can not call
+ # this dump from a Jamfile since projects referred by 'build-project' are
+ # not available until the whole Jamfile has been loaded.
+ .all-tests += $(t) ;
+ return $(t) ;
+}
+
+
+# Note: passing more that one cpp file here is known to fail. Passing a cpp file
+# and a library target works.
+#
+rule compile ( sources + : requirements * : target-name ? )
+{
+ return [ make-test compile : $(sources) : $(requirements) : $(target-name) ]
+ ;
+}
+
+
+rule compile-fail ( sources + : requirements * : target-name ? )
+{
+ return [ make-test compile-fail : $(sources) : $(requirements) :
+ $(target-name) ] ;
+}
+
+
+rule link ( sources + : requirements * : target-name ? )
+{
+ return [ make-test link : $(sources) : $(requirements) : $(target-name) ] ;
+}
+
+
+rule link-fail ( sources + : requirements * : target-name ? )
+{
+ return [ make-test link-fail : $(sources) : $(requirements) : $(target-name)
+ ] ;
+}
+
+
+rule handle-input-files ( input-files * )
+{
+ if $(input-files[2])
+ {
+ # Check that sorting made when creating property-set instance will not
+ # change the ordering.
+ if [ sequence.insertion-sort $(input-files) ] != $(input-files)
+ {
+ errors.user-error "Names of input files must be sorted alphabetically"
+ : "due to internal limitations" ;
+ }
+ }
+ return <testing.input-file>$(input-files) ;
+}
+
+
+rule run ( sources + : args * : input-files * : requirements * : target-name ? :
+ default-build * )
+{
+ requirements += <testing.arg>$(args:J=" ") ;
+ requirements += [ handle-input-files $(input-files) ] ;
+ return [ make-test run : $(sources) : $(requirements) : $(target-name) ] ;
+}
+
+
+rule run-fail ( sources + : args * : input-files * : requirements * :
+ target-name ? : default-build * )
+{
+ requirements += <testing.arg>$(args:J=" ") ;
+ requirements += [ handle-input-files $(input-files) ] ;
+ return [ make-test run-fail : $(sources) : $(requirements) : $(target-name)
+ ] ;
+}
+
+
+# Use 'test-suite' as a synonym for 'alias', for backward compatibility.
+IMPORT : alias : : test-suite ;
+
+
+# For all main targets in 'project-module', which are typed targets with type
+# derived from 'TEST', produce some interesting information.
+#
+rule dump-tests
+{
+ for local t in $(.all-tests)
+ {
+ dump-test $(t) ;
+ }
+}
+
+
+# Given a project location in normalized form (slashes are forward), compute the
+# name of the Boost library.
+#
+local rule get-library-name ( path )
+{
+ # Path is in normalized form, so all slashes are forward.
+ local match1 = [ MATCH /(tools|libs)/(.*)/(test|example) : $(path) ] ;
+ local match2 = [ MATCH /(tools|libs)/(.*)$ : $(path) ] ;
+ local match3 = [ MATCH (/status$) : $(path) ] ;
+
+ if $(match1) { return $(match1[2]) ; }
+ else if $(match2) { return $(match2[2]) ; }
+ else if $(match3) { return "" ; }
+ else if --dump-tests in [ modules.peek : ARGV ]
+ {
+ # The 'run' rule and others might be used outside boost. In that case,
+ # just return the path, since the 'library name' makes no sense.
+ return $(path) ;
+ }
+}
+
+
+# Was an XML dump requested?
+.out-xml = [ MATCH --out-xml=(.*) : [ modules.peek : ARGV ] ] ;
+
+
+# Takes a target (instance of 'basic-target') and prints
+# - its type
+# - its name
+# - comments specified via the <test-info> property
+# - relative location of all source from the project root.
+#
+rule dump-test ( target )
+{
+ local type = [ $(target).type ] ;
+ local name = [ $(target).name ] ;
+ local project = [ $(target).project ] ;
+
+ local project-root = [ $(project).get project-root ] ;
+ local library = [ get-library-name [ path.root [ $(project).get location ]
+ [ path.pwd ] ] ] ;
+ if $(library)
+ {
+ name = $(library)/$(name) ;
+ }
+
+ local sources = [ $(target).sources ] ;
+ local source-files ;
+ for local s in $(sources)
+ {
+ if [ class.is-a $(s) : file-reference ]
+ {
+ local location = [ path.root [ path.root [ $(s).name ]
+ [ $(s).location ] ] [ path.pwd ] ] ;
+
+ source-files += [ path.relative-to [ path.root $(project-root)
+ [ path.pwd ] ] $(location) ] ;
+ }
+ }
+
+ local target-name = [ $(project).get location ] // [ $(target).name ] .test
+ ;
+ target-name = $(target-name:J=) ;
+
+ local r = [ $(target).requirements ] ;
+ # Extract values of the <test-info> feature.
+ local test-info = [ $(r).get <test-info> ] ;
+
+ # If the user requested XML output on the command-line, add the test info to
+ # that XML file rather than dumping them to stdout.
+ if $(.out-xml)
+ {
+ local nl = "
+" ;
+ .contents on $(.out-xml) +=
+ "$(nl) <test type=\"$(type)\" name=\"$(name)\">"
+ "$(nl) <target><![CDATA[$(target-name)]]></target>"
+ "$(nl) <info><![CDATA[$(test-info)]]></info>"
+ "$(nl) <source><![CDATA[$(source-files)]]></source>"
+ "$(nl) </test>"
+ ;
+ }
+ else
+ {
+ # Format them into a single string of quoted strings.
+ test-info = \"$(test-info:J=\"\ \")\" ;
+
+ ECHO boost-test($(type)) \"$(name)\" [$(test-info)] ":"
+ \"$(source-files)\" ;
+ }
+}
+
+
+# Register generators. Depending on target type, either 'expect-success' or
+# 'expect-failure' rule will be used.
+generators.register-standard testing.expect-success : OBJ : COMPILE ;
+generators.register-standard testing.expect-failure : OBJ : COMPILE_FAIL ;
+generators.register-standard testing.expect-success : RUN_OUTPUT : RUN ;
+generators.register-standard testing.expect-failure : RUN_OUTPUT : RUN_FAIL ;
+generators.register-standard testing.expect-failure : EXE : LINK_FAIL ;
+generators.register-standard testing.expect-success : EXE : LINK ;
+
+# Generator which runs an EXE and captures output.
+generators.register-standard testing.capture-output : EXE : RUN_OUTPUT ;
+
+# Generator which creates a target if sources run successfully. Differs from RUN
+# in that run output is not captured. The reason why it exists is that the 'run'
+# rule is much better for automated testing, but is not user-friendly (see
+# http://article.gmane.org/gmane.comp.lib.boost.build/6353).
+generators.register-standard testing.unit-test : EXE : UNIT_TEST ;
+
+
+# The action rules called by generators.
+
+# Causes the 'target' to exist after bjam invocation if and only if all the
+# dependencies were successfully built.
+#
+rule expect-success ( target : dependency + : requirements * )
+{
+ **passed** $(target) : $(sources) ;
+}
+
+
+# Causes the 'target' to exist after bjam invocation if and only if all some of
+# the dependencies were not successfully built.
+#
+rule expect-failure ( target : dependency + : properties * )
+{
+ local grist = [ MATCH ^<(.*)> : $(dependency:G) ] ;
+ local marker = $(dependency:G=$(grist)*fail) ;
+ (failed-as-expected) $(marker) ;
+ FAIL_EXPECTED $(dependency) ;
+ LOCATE on $(marker) = [ on $(dependency) return $(LOCATE) ] ;
+ RMOLD $(marker) ;
+ DEPENDS $(marker) : $(dependency) ;
+ DEPENDS $(target) : $(marker) ;
+ **passed** $(target) : $(marker) ;
+}
+
+
+# The rule/action combination used to report successful passing of a test.
+#
+rule **passed**
+{
+ # Dump all the tests, if needed. We do it here, since dump should happen
+ # only after all Jamfiles have been read, and there is no such place
+ # currently defined (but there should be).
+ if ! $(.dumped-tests) && ( --dump-tests in [ modules.peek : ARGV ] )
+ {
+ .dumped-tests = true ;
+ dump-tests ;
+ }
+
+ # Force deletion of the target, in case any dependencies failed to build.
+ RMOLD $(<) ;
+}
+
+
+# Used to create test files signifying passed tests.
+#
+actions **passed**
+{
+ echo passed > "$(<)"
+}
+
+
+# Used to create replacement object files that do not get created during tests
+# that are expected to fail.
+#
+actions (failed-as-expected)
+{
+ echo failed as expected > "$(<)"
+}
+
+
+rule run-path-setup ( target : source : properties * )
+{
+ # For testing, we need to make sure that all dynamic libraries needed by the
+ # test are found. So, we collect all paths from dependency libraries (via
+ # xdll-path property) and add whatever explicit dll-path user has specified.
+ # The resulting paths are added to the environment on each test invocation.
+ local dll-paths = [ feature.get-values <dll-path> : $(properties) ] ;
+ dll-paths += [ feature.get-values <xdll-path> : $(properties) ] ;
+ dll-paths += [ on $(source) return $(RUN_PATH) ] ;
+ dll-paths = [ sequence.unique $(dll-paths) ] ;
+ if $(dll-paths)
+ {
+ dll-paths = [ sequence.transform path.native : $(dll-paths) ] ;
+ PATH_SETUP on $(target) = [ common.prepend-path-variable-command
+ [ os.shared-library-path-variable ] : $(dll-paths) ] ;
+ }
+}
+
+
+local argv = [ modules.peek : ARGV ] ;
+
+toolset.flags testing.capture-output ARGS <testing.arg> ;
+toolset.flags testing.capture-output INPUT_FILES <testing.input-file> ;
+toolset.flags testing.capture-output LAUNCHER <testing.launcher> ;
+
+
+# Runs executable 'sources' and stores stdout in file 'target'. Unless
+# --preserve-test-targets command line option has been specified, removes the
+# executable. The 'target-to-remove' parameter controls what should be removed:
+# - if 'none', does not remove anything, ever
+# - if empty, removes 'source'
+# - if non-empty and not 'none', contains a list of sources to remove.
+#
+rule capture-output ( target : source : properties * : targets-to-remove * )
+{
+ output-file on $(target) = $(target:S=.output) ;
+ LOCATE on $(target:S=.output) = [ on $(target) return $(LOCATE) ] ;
+
+ # The INCLUDES kill a warning about independent target...
+ INCLUDES $(target) : $(target:S=.output) ;
+ # but it also puts .output into dependency graph, so we must tell jam it is
+ # OK if it cannot find the target or updating rule.
+ NOCARE $(target:S=.output) ;
+
+ # This has two-fold effect. First it adds input files to the dependendency
+ # graph, preventing a warning. Second, it causes input files to be bound
+ # before target is created. Therefore, they are bound using SEARCH setting
+ # on them and not LOCATE setting of $(target), as in other case (due to jam
+ # bug).
+ DEPENDS $(target) : [ on $(target) return $(INPUT_FILES) ] ;
+
+ if $(targets-to-remove) = none
+ {
+ targets-to-remove = ;
+ }
+ else if ! $(targets-to-remove)
+ {
+ targets-to-remove = $(source) ;
+ }
+
+ run-path-setup $(target) : $(source) : $(properties) ;
+
+ if [ feature.get-values preserve-test-targets : $(properties) ] = off
+ {
+ TEMPORARY $(targets-to-remove) ;
+ # Set a second action on target that will be executed after capture
+ # output action. The 'RmTemps' rule has the 'ignore' modifier so it is
+ # always considered succeeded. This is needed for 'run-fail' test. For
+ # that test the target will be marked with FAIL_EXPECTED, and without
+ # 'ignore' successful execution will be negated and be reported as
+ # failure. With 'ignore' we do not detect a case where removing files
+ # fails, but it is not likely to happen.
+ RmTemps $(target) : $(targets-to-remove) ;
+ }
+}
+
+
+if [ os.name ] = NT
+{
+ .STATUS = %status% ;
+ .SET_STATUS = "set status=%ERRORLEVEL%" ;
+ .RUN_OUTPUT_NL = "echo." ;
+ .STATUS_0 = "%status% EQU 0 (" ;
+ .STATUS_NOT_0 = "%status% NEQ 0 (" ;
+ .VERBOSE = "%verbose% EQU 1 (" ;
+ .ENDIF = ")" ;
+ .SHELL_SET = "set " ;
+ .CATENATE = type ;
+ .CP = copy ;
+}
+else
+{
+ .STATUS = "$status" ;
+ .SET_STATUS = "status=$?" ;
+ .RUN_OUTPUT_NL = "echo" ;
+ .STATUS_0 = "test $status -eq 0 ; then" ;
+ .STATUS_NOT_0 = "test $status -ne 0 ; then" ;
+ .VERBOSE = "test $verbose -eq 1 ; then" ;
+ .ENDIF = "fi" ;
+ .SHELL_SET = "" ;
+ .CATENATE = cat ;
+ .CP = cp ;
+}
+
+
+.VERBOSE_TEST = 0 ;
+if --verbose-test in [ modules.peek : ARGV ]
+{
+ .VERBOSE_TEST = 1 ;
+}
+
+
+.RM = [ common.rm-command ] ;
+
+
+actions capture-output bind INPUT_FILES output-file
+{
+ $(PATH_SETUP)
+ $(LAUNCHER) "$(>)" $(ARGS) "$(INPUT_FILES)" > "$(output-file)" 2>&1
+ $(.SET_STATUS)
+ $(.RUN_OUTPUT_NL) >> "$(output-file)"
+ echo EXIT STATUS: $(.STATUS) >> "$(output-file)"
+ if $(.STATUS_0)
+ $(.CP) "$(output-file)" "$(<)"
+ $(.ENDIF)
+ $(.SHELL_SET)verbose=$(.VERBOSE_TEST)
+ if $(.STATUS_NOT_0)
+ $(.SHELL_SET)verbose=1
+ $(.ENDIF)
+ if $(.VERBOSE)
+ echo ====== BEGIN OUTPUT ======
+ $(.CATENATE) "$(output-file)"
+ echo ====== END OUTPUT ======
+ $(.ENDIF)
+ exit $(.STATUS)
+}
+
+
+actions quietly updated ignore piecemeal together RmTemps
+{
+ $(.RM) "$(>)"
+}
+
+
+.MAKE_FILE = [ common.file-creation-command ] ;
+
+toolset.flags testing.unit-test LAUNCHER <testing.launcher> ;
+toolset.flags testing.unit-test ARGS <testing.arg> ;
+
+
+rule unit-test ( target : source : properties * )
+{
+ run-path-setup $(target) : $(source) : $(properties) ;
+}
+
+
+actions unit-test
+{
+ $(PATH_SETUP)
+ $(LAUNCHER) $(>) $(ARGS) && $(.MAKE_FILE) $(<)
+}
+
+
+IMPORT $(__name__) : compile compile-fail run run-fail link link-fail
+ : : compile compile-fail run run-fail link link-fail ;
+
+
+type.register TIME : time ;
+generators.register-standard testing.time : : TIME ;
+
+
+rule record-time ( target : source : start end user system )
+{
+ local src-string = [$(source:G=:J=",")"] " ;
+ USER_TIME on $(target) += $(src-string)$(user) ;
+ SYSTEM_TIME on $(target) += $(src-string)$(system) ;
+}
+
+
+IMPORT testing : record-time : : testing.record-time ;
+
+
+# Calling this rule requests that Boost Build time how long it taks to build the
+# 'source' target and display the results both on the standard output and in the
+# 'target' file.
+#
+rule time ( target : source : properties * )
+{
+ # Set up rule for recording timing information.
+ __TIMING_RULE__ on $(source) = testing.record-time $(target) ;
+
+ # Make sure that the source is rebuilt any time we need to retrieve that
+ # information.
+ REBUILDS $(target) : $(source) ;
+}
+
+
+actions time
+{
+ echo user: $(USER_TIME)
+ echo system: $(SYSTEM_TIME)
+
+ echo user: $(USER_TIME)" seconds" > "$(<)"
+ echo system: $(SYSTEM_TIME)" seconds" >> "$(<)"
+}
diff --git a/tools/build/v2/tools/testing.py b/tools/build/v2/tools/testing.py
new file mode 100644
index 0000000000..3b53500cc2
--- /dev/null
+++ b/tools/build/v2/tools/testing.py
@@ -0,0 +1,342 @@
+# Status: ported, except for --out-xml
+# Base revision: 64488
+#
+# Copyright 2005 Dave Abrahams
+# Copyright 2002, 2003, 2004, 2005, 2010 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This module implements regression testing framework. It declares a number of
+# main target rules which perform some action and, if the results are OK,
+# creates an output file.
+#
+# The exact list of rules is:
+# 'compile' -- creates .test file if compilation of sources was
+# successful.
+# 'compile-fail' -- creates .test file if compilation of sources failed.
+# 'run' -- creates .test file is running of executable produced from
+# sources was successful. Also leaves behind .output file
+# with the output from program run.
+# 'run-fail' -- same as above, but .test file is created if running fails.
+#
+# In all cases, presence of .test file is an indication that the test passed.
+# For more convenient reporting, you might want to use C++ Boost regression
+# testing utilities (see http://www.boost.org/more/regression.html).
+#
+# For historical reason, a 'unit-test' rule is available which has the same
+# syntax as 'exe' and behaves just like 'run'.
+
+# Things to do:
+# - Teach compiler_status handle Jamfile.v2.
+# Notes:
+# - <no-warn> is not implemented, since it is Como-specific, and it is not
+# clear how to implement it
+# - std::locale-support is not implemented (it is used in one test).
+
+import b2.build.feature as feature
+import b2.build.type as type
+import b2.build.targets as targets
+import b2.build.generators as generators
+import b2.build.toolset as toolset
+import b2.tools.common as common
+import b2.util.option as option
+import b2.build_system as build_system
+
+
+
+from b2.manager import get_manager
+from b2.util import stem, bjam_signature
+from b2.util.sequence import unique
+
+import bjam
+
+import re
+import os.path
+import sys
+
+def init():
+ pass
+
+# Feature controling the command used to lanch test programs.
+feature.feature("testing.launcher", [], ["free", "optional"])
+
+feature.feature("test-info", [], ["free", "incidental"])
+feature.feature("testing.arg", [], ["free", "incidental"])
+feature.feature("testing.input-file", [], ["free", "dependency"])
+
+feature.feature("preserve-test-targets", ["on", "off"], ["incidental", "propagated"])
+
+# Register target types.
+type.register("TEST", ["test"])
+type.register("COMPILE", [], "TEST")
+type.register("COMPILE_FAIL", [], "TEST")
+
+type.register("RUN_OUTPUT", ["run"])
+type.register("RUN", [], "TEST")
+type.register("RUN_FAIL", [], "TEST")
+
+type.register("LINK", [], "TEST")
+type.register("LINK_FAIL", [], "TEST")
+type.register("UNIT_TEST", ["passed"], "TEST")
+
+__all_tests = []
+
+# Declare the rules which create main targets. While the 'type' module already
+# creates rules with the same names for us, we need extra convenience: default
+# name of main target, so write our own versions.
+
+# Helper rule. Create a test target, using basename of first source if no target
+# name is explicitly passed. Remembers the created target in a global variable.
+def make_test(target_type, sources, requirements, target_name=None):
+
+ if not target_name:
+ target_name = stem(os.path.basename(sources[0]))
+
+ # Having periods (".") in the target name is problematic because the typed
+ # generator will strip the suffix and use the bare name for the file
+ # targets. Even though the location-prefix averts problems most times it
+ # does not prevent ambiguity issues when referring to the test targets. For
+ # example when using the XML log output. So we rename the target to remove
+ # the periods, and provide an alias for users.
+ real_name = target_name.replace(".", "~")
+
+ project = get_manager().projects().current()
+ # The <location-prefix> forces the build system for generate paths in the
+ # form '$build_dir/array1.test/gcc/debug'. This is necessary to allow
+ # post-processing tools to work.
+ t = get_manager().targets().create_typed_target(
+ type.type_from_rule_name(target_type), project, real_name, sources,
+ requirements + ["<location-prefix>" + real_name + ".test"], [], [])
+
+ # The alias to the real target, per period replacement above.
+ if real_name != target_name:
+ get_manager().projects().project_rules().all_names_["alias"](
+ target_name, [t])
+
+ # Remember the test (for --dump-tests). A good way would be to collect all
+ # given a project. This has some technical problems: e.g. we can not call
+ # this dump from a Jamfile since projects referred by 'build-project' are
+ # not available until the whole Jamfile has been loaded.
+ __all_tests.append(t)
+ return t
+
+
+# Note: passing more that one cpp file here is known to fail. Passing a cpp file
+# and a library target works.
+#
+@bjam_signature((["sources", "*"], ["requirements", "*"], ["target_name", "?"]))
+def compile(sources, requirements, target_name=None):
+ return make_test("compile", sources, requirements, target_name)
+
+@bjam_signature((["sources", "*"], ["requirements", "*"], ["target_name", "?"]))
+def compile_fail(sources, requirements, target_name=None):
+ return make_test("compile-fail", sources, requirements, target_name)
+
+@bjam_signature((["sources", "*"], ["requirements", "*"], ["target_name", "?"]))
+def link(sources, requirements, target_name=None):
+ return make_test("link", sources, requirements, target_name)
+
+@bjam_signature((["sources", "*"], ["requirements", "*"], ["target_name", "?"]))
+def link_fail(sources, requirements, target_name=None):
+ return make_test("link-fail", sources, requirements, target_name)
+
+def handle_input_files(input_files):
+ if len(input_files) > 1:
+ # Check that sorting made when creating property-set instance will not
+ # change the ordering.
+ if sorted(input_files) != input_files:
+ get_manager().errors()("Names of input files must be sorted alphabetically\n" +
+ "due to internal limitations")
+ return ["<testing.input-file>" + f for f in input_files]
+
+@bjam_signature((["sources", "*"], ["args", "*"], ["input_files", "*"],
+ ["requirements", "*"], ["target_name", "?"],
+ ["default_build", "*"]))
+def run(sources, args, input_files, requirements, target_name=None, default_build=[]):
+ if args:
+ requirements.append("<testing.arg>" + " ".join(args))
+ requirements.extend(handle_input_files(input_files))
+ return make_test("run", sources, requirements, target_name)
+
+@bjam_signature((["sources", "*"], ["args", "*"], ["input_files", "*"],
+ ["requirements", "*"], ["target_name", "?"],
+ ["default_build", "*"]))
+def run_fail(sources, args, input_files, requirements, target_name=None, default_build=[]):
+ if args:
+ requirements.append("<testing.arg>" + " ".join(args))
+ requirements.extend(handle_input_files(input_files))
+ return make_test("run-fail", sources, requirements, target_name)
+
+# Register all the rules
+for name in ["compile", "compile-fail", "link", "link-fail", "run", "run-fail"]:
+ get_manager().projects().add_rule(name, getattr(sys.modules[__name__], name.replace("-", "_")))
+
+# Use 'test-suite' as a synonym for 'alias', for backward compatibility.
+from b2.build.alias import alias
+get_manager().projects().add_rule("test-suite", alias)
+
+# For all main targets in 'project-module', which are typed targets with type
+# derived from 'TEST', produce some interesting information.
+#
+def dump_tests():
+ for t in __all_tests:
+ dump_test(t)
+
+# Given a project location in normalized form (slashes are forward), compute the
+# name of the Boost library.
+#
+__ln1 = re.compile("/(tools|libs)/(.*)/(test|example)")
+__ln2 = re.compile("/(tools|libs)/(.*)$")
+__ln3 = re.compile("(/status$)")
+def get_library_name(path):
+
+ path = path.replace("\\", "/")
+ match1 = __ln1.match(path)
+ match2 = __ln2.match(path)
+ match3 = __ln3.match(path)
+
+ if match1:
+ return match1.group(2)
+ elif match2:
+ return match2.group(2)
+ elif match3:
+ return ""
+ elif option.get("dump-tests", False, True):
+ # The 'run' rule and others might be used outside boost. In that case,
+ # just return the path, since the 'library name' makes no sense.
+ return path
+
+# Was an XML dump requested?
+__out_xml = option.get("out-xml", False, True)
+
+# Takes a target (instance of 'basic-target') and prints
+# - its type
+# - its name
+# - comments specified via the <test-info> property
+# - relative location of all source from the project root.
+#
+def dump_test(target):
+ type = target.type()
+ name = target.name()
+ project = target.project()
+
+ project_root = project.get('project-root')
+ library = get_library_name(os.path.abspath(project.get('location')))
+ if library:
+ name = library + "/" + name
+
+ sources = target.sources()
+ source_files = []
+ for s in sources:
+ if isinstance(s, targets.FileReference):
+ location = os.path.abspath(os.path.join(s.location(), s.name()))
+ source_files.append(os.path.relpath(location, os.path.abspath(project_root)))
+
+ target_name = project.get('location') + "//" + target.name() + ".test"
+
+ test_info = target.requirements().get('test-info')
+ test_info = " ".join('"' + ti + '"' for ti in test_info)
+
+ # If the user requested XML output on the command-line, add the test info to
+ # that XML file rather than dumping them to stdout.
+ #if $(.out-xml)
+ #{
+# local nl = "
+#" ;
+# .contents on $(.out-xml) +=
+# "$(nl) <test type=\"$(type)\" name=\"$(name)\">"
+# "$(nl) <target><![CDATA[$(target-name)]]></target>"
+# "$(nl) <info><![CDATA[$(test-info)]]></info>"
+# "$(nl) <source><![CDATA[$(source-files)]]></source>"
+# "$(nl) </test>"
+# ;
+# }
+# else
+
+ source_files = " ".join('"' + s + '"' for s in source_files)
+ if test_info:
+ print 'boost-test(%s) "%s" [%s] : %s' % (type, name, test_info, source_files)
+ else:
+ print 'boost-test(%s) "%s" : %s' % (type, name, source_files)
+
+# Register generators. Depending on target type, either 'expect-success' or
+# 'expect-failure' rule will be used.
+generators.register_standard("testing.expect-success", ["OBJ"], ["COMPILE"])
+generators.register_standard("testing.expect-failure", ["OBJ"], ["COMPILE_FAIL"])
+generators.register_standard("testing.expect-success", ["RUN_OUTPUT"], ["RUN"])
+generators.register_standard("testing.expect-failure", ["RUN_OUTPUT"], ["RUN_FAIL"])
+generators.register_standard("testing.expect-success", ["EXE"], ["LINK"])
+generators.register_standard("testing.expect-failure", ["EXE"], ["LINK_FAIL"])
+
+# Generator which runs an EXE and captures output.
+generators.register_standard("testing.capture-output", ["EXE"], ["RUN_OUTPUT"])
+
+# Generator which creates a target if sources run successfully. Differs from RUN
+# in that run output is not captured. The reason why it exists is that the 'run'
+# rule is much better for automated testing, but is not user-friendly (see
+# http://article.gmane.org/gmane.comp.lib.boost.build/6353).
+generators.register_standard("testing.unit-test", ["EXE"], ["UNIT_TEST"])
+
+# FIXME: if those calls are after bjam.call, then bjam will crash
+# when toolset.flags calls bjam.caller.
+toolset.flags("testing.capture-output", "ARGS", [], ["<testing.arg>"])
+toolset.flags("testing.capture-output", "INPUT_FILES", [], ["<testing.input-file>"])
+toolset.flags("testing.capture-output", "LAUNCHER", [], ["<testing.launcher>"])
+
+toolset.flags("testing.unit-test", "LAUNCHER", [], ["<testing.launcher>"])
+toolset.flags("testing.unit-test", "ARGS", [], ["<testing.arg>"])
+
+type.register("TIME", ["time"])
+generators.register_standard("testing.time", [], ["TIME"])
+
+
+# The following code sets up actions for this module. It's pretty convoluted,
+# but the basic points is that we most of actions are defined by Jam code
+# contained in testing-aux.jam, which we load into Jam module named 'testing'
+
+def run_path_setup(target, sources, ps):
+
+ # For testing, we need to make sure that all dynamic libraries needed by the
+ # test are found. So, we collect all paths from dependency libraries (via
+ # xdll-path property) and add whatever explicit dll-path user has specified.
+ # The resulting paths are added to the environment on each test invocation.
+ dll_paths = ps.get('dll-path')
+ dll_paths.extend(ps.get('xdll-path'))
+ dll_paths.extend(bjam.call("get-target-variable", sources, "RUN_PATH"))
+ dll_paths = unique(dll_paths)
+ if dll_paths:
+ bjam.call("set-target-variable", target, "PATH_SETUP",
+ common.prepend_path_variable_command(
+ common.shared_library_path_variable(), dll_paths))
+
+def capture_output_setup(target, sources, ps):
+ run_path_setup(target, sources, ps)
+
+ if ps.get('preserve-test-targets') == ['off']:
+ bjam.call("set-target-variable", target, "REMOVE_TEST_TARGETS", "1")
+
+get_manager().engine().register_bjam_action("testing.capture-output",
+ capture_output_setup)
+
+
+path = os.path.dirname(get_manager().projects().loaded_tool_module_path_[__name__])
+import b2.util.os_j
+get_manager().projects().project_rules()._import_rule("testing", "os.name",
+ b2.util.os_j.name)
+import b2.tools.common
+get_manager().projects().project_rules()._import_rule("testing", "common.rm-command",
+ b2.tools.common.rm_command)
+get_manager().projects().project_rules()._import_rule("testing", "common.file-creation-command",
+ b2.tools.common.file_creation_command)
+
+bjam.call("load", "testing", os.path.join(path, "testing-aux.jam"))
+
+
+for name in ["expect-success", "expect-failure", "time"]:
+ get_manager().engine().register_bjam_action("testing." + name)
+
+get_manager().engine().register_bjam_action("testing.unit-test",
+ run_path_setup)
+
+if option.get("dump-tests", False, True):
+ build_system.add_pre_build_hook(dump_tests)
diff --git a/tools/build/v2/tools/types/__init__.py b/tools/build/v2/tools/types/__init__.py
new file mode 100644
index 0000000000..f972b71495
--- /dev/null
+++ b/tools/build/v2/tools/types/__init__.py
@@ -0,0 +1,18 @@
+__all__ = [
+ 'asm',
+ 'cpp',
+ 'exe',
+ 'html',
+ 'lib',
+ 'obj',
+ 'rsp',
+]
+
+def register_all ():
+ for i in __all__:
+ m = __import__ (__name__ + '.' + i)
+ reg = i + '.register ()'
+ #exec (reg)
+
+# TODO: (PF) I thought these would be imported automatically. Anyone knows why they aren't?
+register_all ()
diff --git a/tools/build/v2/tools/types/asm.jam b/tools/build/v2/tools/types/asm.jam
new file mode 100644
index 0000000000..a340db36a3
--- /dev/null
+++ b/tools/build/v2/tools/types/asm.jam
@@ -0,0 +1,4 @@
+# Copyright Craig Rodrigues 2005. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+type ASM : s S asm ;
diff --git a/tools/build/v2/tools/types/asm.py b/tools/build/v2/tools/types/asm.py
new file mode 100644
index 0000000000..b4e1c30e78
--- /dev/null
+++ b/tools/build/v2/tools/types/asm.py
@@ -0,0 +1,13 @@
+# Copyright Craig Rodrigues 2005.
+# Copyright (c) 2008 Steven Watanabe
+#
+# Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+from b2.build import type
+
+def register():
+ type.register_type('ASM', ['s', 'S', 'asm'])
+
+register()
diff --git a/tools/build/v2/tools/types/cpp.jam b/tools/build/v2/tools/types/cpp.jam
new file mode 100644
index 0000000000..3159cdd772
--- /dev/null
+++ b/tools/build/v2/tools/types/cpp.jam
@@ -0,0 +1,86 @@
+# Copyright David Abrahams 2004.
+# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
+# Copyright 2010 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+import type ;
+import scanner ;
+
+class c-scanner : scanner
+{
+ import path ;
+ import regex ;
+ import scanner ;
+ import sequence ;
+ import virtual-target ;
+
+ rule __init__ ( includes * )
+ {
+ scanner.__init__ ;
+
+ for local i in $(includes)
+ {
+ self.includes += [ sequence.transform path.native
+ : [ regex.split $(i:G=) "&&" ] ] ;
+ }
+ }
+
+ rule pattern ( )
+ {
+ return "#[ \t]*include[ ]*(<(.*)>|\"(.*)\")" ;
+ }
+
+ rule process ( target : matches * : binding )
+ {
+ local angle = [ regex.transform $(matches) : "<(.*)>" ] ;
+ angle = [ sequence.transform path.native : $(angle) ] ;
+ local quoted = [ regex.transform $(matches) : "\"(.*)\"" ] ;
+ quoted = [ sequence.transform path.native : $(quoted) ] ;
+
+ # CONSIDER: the new scoping rule seem to defeat "on target" variables.
+ local g = [ on $(target) return $(HDRGRIST) ] ;
+ local b = [ NORMALIZE_PATH $(binding:D) ] ;
+
+ # Attach binding of including file to included targets. When a target is
+ # directly created from virtual target this extra information is
+ # unnecessary. But in other cases, it allows us to distinguish between
+ # two headers of the same name included from different places. We do not
+ # need this extra information for angle includes, since they should not
+ # depend on including file (we can not get literal "." in include path).
+ local g2 = $(g)"#"$(b) ;
+
+ angle = $(angle:G=$(g)) ;
+ quoted = $(quoted:G=$(g2)) ;
+
+ local all = $(angle) $(quoted) ;
+
+ INCLUDES $(target) : $(all) ;
+ NOCARE $(all) ;
+ SEARCH on $(angle) = $(self.includes:G=) ;
+ SEARCH on $(quoted) = $(b) $(self.includes:G=) ;
+
+ # Just propagate the current scanner to includes in hope that includes
+ # do not change scanners.
+ scanner.propagate $(__name__) : $(angle) $(quoted) : $(target) ;
+
+ ISFILE $(angle) $(quoted) ;
+ }
+}
+
+scanner.register c-scanner : include ;
+
+type.register CPP : cpp cxx cc ;
+type.register H : h ;
+type.register HPP : hpp : H ;
+type.register C : c ;
+
+# It most cases where a CPP file or a H file is a source of some action, we
+# should rebuild the result if any of files included by CPP/H are changed. One
+# case when this is not needed is installation, which is handled specifically.
+type.set-scanner CPP : c-scanner ;
+type.set-scanner C : c-scanner ;
+# One case where scanning of H/HPP files is necessary is PCH generation -- if
+# any header included by HPP being precompiled changes, we need to recompile the
+# header.
+type.set-scanner H : c-scanner ;
+type.set-scanner HPP : c-scanner ;
diff --git a/tools/build/v2/tools/types/cpp.py b/tools/build/v2/tools/types/cpp.py
new file mode 100644
index 0000000000..7b56111c85
--- /dev/null
+++ b/tools/build/v2/tools/types/cpp.py
@@ -0,0 +1,10 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+from b2.build import type
+
+def register ():
+ type.register_type ('CPP', ['cpp', 'cxx', 'cc'])
+
+register ()
diff --git a/tools/build/v2/tools/types/exe.jam b/tools/build/v2/tools/types/exe.jam
new file mode 100644
index 0000000000..47109513a4
--- /dev/null
+++ b/tools/build/v2/tools/types/exe.jam
@@ -0,0 +1,9 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import type ;
+
+type.register EXE ;
+type.set-generated-target-suffix EXE : <target-os>windows : "exe" ;
+type.set-generated-target-suffix EXE : <target-os>cygwin : "exe" ;
diff --git a/tools/build/v2/tools/types/exe.py b/tools/build/v2/tools/types/exe.py
new file mode 100644
index 0000000000..a4935e24ed
--- /dev/null
+++ b/tools/build/v2/tools/types/exe.py
@@ -0,0 +1,11 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+from b2.build import type
+
+def register ():
+ type.register_type ('EXE', ['exe'], None, ['NT', 'CYGWIN'])
+ type.register_type ('EXE', [], None, [])
+
+register ()
diff --git a/tools/build/v2/tools/types/html.jam b/tools/build/v2/tools/types/html.jam
new file mode 100644
index 0000000000..5cd337d094
--- /dev/null
+++ b/tools/build/v2/tools/types/html.jam
@@ -0,0 +1,4 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+type HTML : html ;
diff --git a/tools/build/v2/tools/types/html.py b/tools/build/v2/tools/types/html.py
new file mode 100644
index 0000000000..63af4d9078
--- /dev/null
+++ b/tools/build/v2/tools/types/html.py
@@ -0,0 +1,10 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+from b2.build import type
+
+def register ():
+ type.register_type ('HTML', ['html'])
+
+register ()
diff --git a/tools/build/v2/tools/types/lib.jam b/tools/build/v2/tools/types/lib.jam
new file mode 100644
index 0000000000..854ab8fd5c
--- /dev/null
+++ b/tools/build/v2/tools/types/lib.jam
@@ -0,0 +1,74 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import type ; # for set-generated-target-suffix
+import os ;
+
+# The following naming scheme is used for libraries.
+#
+# On *nix:
+# libxxx.a static library
+# libxxx.so shared library
+#
+# On windows (msvc)
+# libxxx.lib static library
+# xxx.dll DLL
+# xxx.lib import library
+#
+# On windows (mingw):
+# libxxx.a static library
+# libxxx.dll DLL
+# libxxx.dll.a import library
+#
+# On cygwin i.e. <target-os>cygwin
+# libxxx.a static library
+# cygxxx.dll DLL
+# libxxx.dll.a import library
+#
+
+type.register LIB ;
+
+# FIXME: should not register both extensions on both platforms.
+type.register STATIC_LIB : a lib : LIB ;
+
+# The 'lib' prefix is used everywhere
+type.set-generated-target-prefix STATIC_LIB : : lib ;
+
+# Use '.lib' suffix for windows
+type.set-generated-target-suffix STATIC_LIB : <target-os>windows : lib ;
+
+# Except with gcc.
+type.set-generated-target-suffix STATIC_LIB : <toolset>gcc <target-os>windows : a ;
+
+# Use xxx.lib for import libs
+type IMPORT_LIB : : STATIC_LIB ;
+type.set-generated-target-prefix IMPORT_LIB : : "" ;
+type.set-generated-target-suffix IMPORT_LIB : : lib ;
+
+# Except with gcc (mingw or cygwin), where use libxxx.dll.a
+type.set-generated-target-prefix IMPORT_LIB : <toolset>gcc : lib ;
+type.set-generated-target-suffix IMPORT_LIB : <toolset>gcc : dll.a ;
+
+type.register SHARED_LIB : so dll dylib : LIB ;
+
+# Both mingw and cygwin use libxxx.dll naming scheme.
+# On Linux, use "lib" prefix
+type.set-generated-target-prefix SHARED_LIB : : lib ;
+# But don't use it on windows
+type.set-generated-target-prefix SHARED_LIB : <target-os>windows : "" ;
+# But use it again on mingw
+type.set-generated-target-prefix SHARED_LIB : <toolset>gcc <target-os>windows : lib ;
+# And use 'cyg' on cygwin
+type.set-generated-target-prefix SHARED_LIB : <target-os>cygwin : cyg ;
+
+
+type.set-generated-target-suffix SHARED_LIB : <target-os>windows : dll ;
+type.set-generated-target-suffix SHARED_LIB : <target-os>cygwin : dll ;
+type.set-generated-target-suffix SHARED_LIB : <target-os>darwin : dylib ;
+
+type SEARCHED_LIB : : LIB ;
+# This is needed so that when we create a target of SEARCHED_LIB
+# type, there's no prefix or suffix automatically added.
+type.set-generated-target-prefix SEARCHED_LIB : : "" ;
+type.set-generated-target-suffix SEARCHED_LIB : : "" ;
diff --git a/tools/build/v2/tools/types/lib.py b/tools/build/v2/tools/types/lib.py
new file mode 100644
index 0000000000..d0ec1fb52a
--- /dev/null
+++ b/tools/build/v2/tools/types/lib.py
@@ -0,0 +1,77 @@
+# Status: ported
+# Base revision: 64456.
+# Copyright David Abrahams 2004.
+# Copyright Vladimir Prus 2010.
+# Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import b2.build.type as type
+
+# The following naming scheme is used for libraries.
+#
+# On *nix:
+# libxxx.a static library
+# libxxx.so shared library
+#
+# On windows (msvc)
+# libxxx.lib static library
+# xxx.dll DLL
+# xxx.lib import library
+#
+# On windows (mingw):
+# libxxx.a static library
+# libxxx.dll DLL
+# libxxx.dll.a import library
+#
+# On cygwin i.e. <target-os>cygwin
+# libxxx.a static library
+# cygxxx.dll DLL
+# libxxx.dll.a import library
+#
+
+type.register('LIB')
+
+# FIXME: should not register both extensions on both platforms.
+type.register('STATIC_LIB', ['a', 'lib'], 'LIB')
+
+# The 'lib' prefix is used everywhere
+type.set_generated_target_prefix('STATIC_LIB', [], 'lib')
+
+# Use '.lib' suffix for windows
+type.set_generated_target_suffix('STATIC_LIB', ['<target-os>windows'], 'lib')
+
+# Except with gcc.
+type.set_generated_target_suffix('STATIC_LIB', ['<toolset>gcc', '<target-os>windows'], 'a')
+
+# Use xxx.lib for import libs
+type.register('IMPORT_LIB', [], 'STATIC_LIB')
+type.set_generated_target_prefix('IMPORT_LIB', [], '')
+type.set_generated_target_suffix('IMPORT_LIB', [], 'lib')
+
+# Except with gcc (mingw or cygwin), where use libxxx.dll.a
+type.set_generated_target_prefix('IMPORT_LIB', ['<toolset>gcc'], 'lib')
+type.set_generated_target_suffix('IMPORT_LIB', ['<toolset>gcc'], 'dll.a')
+
+type.register('SHARED_LIB', ['so', 'dll', 'dylib'], 'LIB')
+
+# Both mingw and cygwin use libxxx.dll naming scheme.
+# On Linux, use "lib" prefix
+type.set_generated_target_prefix('SHARED_LIB', [], 'lib')
+# But don't use it on windows
+type.set_generated_target_prefix('SHARED_LIB', ['<target-os>windows'], '')
+# But use it again on mingw
+type.set_generated_target_prefix('SHARED_LIB', ['<toolset>gcc', '<target-os>windows'], 'lib')
+# And use 'cyg' on cygwin
+type.set_generated_target_prefix('SHARED_LIB', ['<target-os>cygwin'], 'cyg')
+
+
+type.set_generated_target_suffix('SHARED_LIB', ['<target-os>windows'], 'dll')
+type.set_generated_target_suffix('SHARED_LIB', ['<target-os>cygwin'], 'dll')
+type.set_generated_target_suffix('SHARED_LIB', ['<target-os>darwin'], 'dylib')
+
+type.register('SEARCHED_LIB', [], 'LIB')
+# This is needed so that when we create a target of SEARCHED_LIB
+# type, there's no prefix or suffix automatically added.
+type.set_generated_target_prefix('SEARCHED_LIB', [], '')
+type.set_generated_target_suffix('SEARCHED_LIB', [], '')
diff --git a/tools/build/v2/tools/types/obj.jam b/tools/build/v2/tools/types/obj.jam
new file mode 100644
index 0000000000..6afbcaa6f3
--- /dev/null
+++ b/tools/build/v2/tools/types/obj.jam
@@ -0,0 +1,9 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import type ;
+
+type.register OBJ : o obj ;
+type.set-generated-target-suffix OBJ : <target-os>windows : obj ;
+type.set-generated-target-suffix OBJ : <target-os>cygwin : obj ;
diff --git a/tools/build/v2/tools/types/obj.py b/tools/build/v2/tools/types/obj.py
new file mode 100644
index 0000000000..e61e99a81c
--- /dev/null
+++ b/tools/build/v2/tools/types/obj.py
@@ -0,0 +1,11 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+from b2.build import type
+
+def register ():
+ type.register_type ('OBJ', ['obj'], None, ['NT', 'CYGWIN'])
+ type.register_type ('OBJ', ['o'])
+
+register ()
diff --git a/tools/build/v2/tools/types/objc.jam b/tools/build/v2/tools/types/objc.jam
new file mode 100644
index 0000000000..709cbd0c7d
--- /dev/null
+++ b/tools/build/v2/tools/types/objc.jam
@@ -0,0 +1,26 @@
+# Copyright Rene Rivera 2008, 2010.
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+import type ;
+import scanner ;
+import types/cpp ;
+
+class objc-scanner : c-scanner
+{
+ rule __init__ ( includes * )
+ {
+ c-scanner.__init__ $(includes) ;
+ }
+
+ rule pattern ( )
+ {
+ return "#[ \t]*include|import[ ]*(<(.*)>|\"(.*)\")" ;
+ }
+}
+
+scanner.register objc-scanner : include ;
+
+type.register OBJECTIVE_C : m ;
+type.register OBJECTIVE_CPP : mm ;
+type.set-scanner OBJECTIVE_C : objc-scanner ;
+type.set-scanner OBJECTIVE_CPP : objc-scanner ;
diff --git a/tools/build/v2/tools/types/preprocessed.jam b/tools/build/v2/tools/types/preprocessed.jam
new file mode 100644
index 0000000000..c9187ba671
--- /dev/null
+++ b/tools/build/v2/tools/types/preprocessed.jam
@@ -0,0 +1,9 @@
+# Copyright Steven Watanabe 2011
+# Distributed under the Boost Software License Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import type ;
+
+type.register PREPROCESSED_C : i : C ;
+type.register PREPROCESSED_CPP : ii : CPP ;
diff --git a/tools/build/v2/tools/types/qt.jam b/tools/build/v2/tools/types/qt.jam
new file mode 100644
index 0000000000..6d1dfbd42f
--- /dev/null
+++ b/tools/build/v2/tools/types/qt.jam
@@ -0,0 +1,10 @@
+# Copyright Vladimir Prus 2005. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+type UI : ui ;
+type QRC : qrc ;
+type MOCCABLE_CPP ;
+type MOCCABLE_H ;
+# Result of running moc.
+type MOC : moc : H ;
diff --git a/tools/build/v2/tools/types/register.jam b/tools/build/v2/tools/types/register.jam
new file mode 100644
index 0000000000..203992ca92
--- /dev/null
+++ b/tools/build/v2/tools/types/register.jam
@@ -0,0 +1,39 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# This module's job is to automatically import all the type
+# registration modules in its directory.
+import type os path modules ;
+
+# Register the given type on the specified OSes, or on remaining OSes
+# if os is not specified. This rule is injected into each of the type
+# modules for the sake of convenience.
+local rule type ( type : suffixes * : base-type ? : os * )
+{
+ if ! [ type.registered $(type) ]
+ {
+ if ( ! $(os) ) || [ os.name ] in $(os)
+ {
+ type.register $(type) : $(suffixes) : $(base-type) ;
+ }
+ }
+}
+
+.this-module's-file = [ modules.binding $(__name__) ] ;
+.this-module's-dir = [ path.parent $(.this-module's-file) ] ;
+.sibling-jamfiles = [ path.glob $(.this-module's-dir) : *.jam ] ;
+.sibling-modules = [ MATCH ^(.*)\.jam$ : $(.sibling-jamfiles) ] ;
+
+# A loop over all modules in this directory
+for m in $(.sibling-modules)
+{
+ m = [ path.basename $(m) ] ;
+ m = types/$(m) ;
+
+ # Inject the type rule into the new module
+ IMPORT $(__name__) : type : $(m) : type ;
+ import $(m) ;
+}
+
+
diff --git a/tools/build/v2/tools/types/rsp.jam b/tools/build/v2/tools/types/rsp.jam
new file mode 100644
index 0000000000..bdf8a7c989
--- /dev/null
+++ b/tools/build/v2/tools/types/rsp.jam
@@ -0,0 +1,4 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+type RSP : rsp ;
diff --git a/tools/build/v2/tools/types/rsp.py b/tools/build/v2/tools/types/rsp.py
new file mode 100644
index 0000000000..ccb379e951
--- /dev/null
+++ b/tools/build/v2/tools/types/rsp.py
@@ -0,0 +1,10 @@
+# Copyright David Abrahams 2004. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+from b2.build import type
+
+def register ():
+ type.register_type ('RSP', ['rsp'])
+
+register ()
diff --git a/tools/build/v2/tools/unix.jam b/tools/build/v2/tools/unix.jam
new file mode 100644
index 0000000000..75949851a0
--- /dev/null
+++ b/tools/build/v2/tools/unix.jam
@@ -0,0 +1,224 @@
+# Copyright (c) 2004 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# This file implements linking semantic common to all unixes. On unix, static
+# libraries must be specified in a fixed order on the linker command line. Generators
+# declared there store information about the order and use it property.
+
+import feature ;
+import "class" : new ;
+import generators ;
+import type ;
+import set ;
+import order ;
+import builtin ;
+
+class unix-linking-generator : linking-generator
+{
+ import property-set ;
+ import type ;
+ import unix ;
+
+ rule __init__ ( id
+ composing ? : # Specify if generator is composing. The generator will be
+ # composing if non-empty string is passed, or parameter is
+ # not given. To make generator non-composing, pass empty
+ # string ("")
+ source-types + : target-types + :
+ requirements * )
+ {
+ composing ?= true ;
+ generator.__init__ $(id) $(composing) : $(source-types) : $(target-types) :
+ $(requirements) ;
+ }
+
+ rule run ( project name ? : property-set : sources + )
+ {
+ local result = [ linking-generator.run $(project) $(name) : $(property-set)
+ : $(sources) ] ;
+
+ unix.set-library-order $(sources) : $(property-set) : $(result[2-]) ;
+
+ return $(result) ;
+ }
+
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ local sources2 ;
+ local libraries ;
+ for local l in $(sources)
+ {
+ if [ type.is-derived [ $(l).type ] LIB ]
+ {
+ libraries += $(l) ;
+ }
+ else
+ {
+ sources2 += $(l) ;
+ }
+ }
+
+ sources = $(sources2) [ unix.order-libraries $(libraries) ] ;
+
+ return [ linking-generator.generated-targets $(sources) : $(property-set)
+ : $(project) $(name) ] ;
+ }
+
+}
+
+class unix-archive-generator : archive-generator
+{
+ import unix ;
+
+ rule __init__ ( id composing ? : source-types + : target-types + :
+ requirements * )
+ {
+ composing ?= true ;
+ archive-generator.__init__ $(id) $(composing) : $(source-types) : $(target-types) :
+ $(requirements) ;
+ }
+
+ rule run ( project name ? : property-set : sources + )
+ {
+ local result = [ archive-generator.run $(project) $(name) : $(property-set)
+ : $(sources) ] ;
+
+ unix.set-library-order $(sources) : $(property-set) : $(result[2-]) ;
+
+ return $(result) ;
+
+ }
+}
+
+class unix-searched-lib-generator : searched-lib-generator
+{
+ import unix ;
+ rule __init__ ( * : * )
+ {
+ generator.__init__
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule optional-properties ( )
+ {
+ return $(self.requirements) ;
+ }
+
+ rule run ( project name ? : property-set : sources * )
+ {
+ local result = [ searched-lib-generator.run $(project) $(name)
+ : $(property-set) : $(sources) ] ;
+
+ unix.set-library-order $(sources) : $(property-set) : $(result[2-]) ;
+
+ return $(result) ;
+ }
+}
+
+class unix-prebuilt-lib-generator : generator
+{
+ import unix ;
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * )
+ {
+ local f = [ $(property-set).get <file> ] ;
+ unix.set-library-order-aux $(f) : $(sources) ;
+ return $(f) $(sources) ;
+ }
+}
+
+generators.register
+ [ new unix-prebuilt-lib-generator unix.prebuilt : : LIB
+ : <file> <toolset>unix ] ;
+
+generators.override unix.prebuilt : builtin.lib-generator ;
+
+
+# Declare generators
+generators.register [ new unix-linking-generator unix.link : LIB OBJ : EXE
+ : <toolset>unix ] ;
+
+generators.register [ new unix-archive-generator unix.archive : OBJ : STATIC_LIB
+ : <toolset>unix ] ;
+
+generators.register [ new unix-linking-generator unix.link.dll : LIB OBJ : SHARED_LIB
+ : <toolset>unix ] ;
+
+generators.register [ new unix-searched-lib-generator
+ unix.searched-lib-generator : : SEARCHED_LIB : <toolset>unix ] ;
+
+
+# The derived toolset must specify their own actions.
+actions link {
+}
+
+actions link.dll {
+}
+
+actions archive {
+}
+
+actions searched-lib-generator {
+}
+
+actions prebuilt {
+}
+
+
+
+
+
+.order = [ new order ] ;
+
+rule set-library-order-aux ( from * : to * )
+{
+ for local f in $(from)
+ {
+ for local t in $(to)
+ {
+ if $(f) != $(t)
+ {
+ $(.order).add-pair $(f) $(t) ;
+ }
+ }
+ }
+}
+
+rule set-library-order ( sources * : property-set : result * )
+{
+ local used-libraries ;
+ local deps = [ $(property-set).dependency ] ;
+ for local l in $(sources) $(deps:G=)
+ {
+ if [ $(l).type ] && [ type.is-derived [ $(l).type ] LIB ]
+ {
+ used-libraries += $(l) ;
+ }
+ }
+
+ local created-libraries ;
+ for local l in $(result)
+ {
+ if [ $(l).type ] && [ type.is-derived [ $(l).type ] LIB ]
+ {
+ created-libraries += $(l) ;
+ }
+ }
+
+ created-libraries = [ set.difference $(created-libraries) : $(used-libraries) ] ;
+ set-library-order-aux $(created-libraries) : $(used-libraries) ;
+}
+
+rule order-libraries ( libraries * )
+{
+ local r = [ $(.order).order $(libraries) ] ;
+ return $(r) ;
+}
+ \ No newline at end of file
diff --git a/tools/build/v2/tools/unix.py b/tools/build/v2/tools/unix.py
new file mode 100644
index 0000000000..d409c2e460
--- /dev/null
+++ b/tools/build/v2/tools/unix.py
@@ -0,0 +1,150 @@
+# Copyright (c) 2004 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+""" This file implements linking semantics common to all unixes. On unix, static
+ libraries must be specified in a fixed order on the linker command line. Generators
+ declared there store information about the order and use it properly.
+"""
+
+import builtin
+from b2.build import generators, type
+from b2.util.utility import *
+from b2.util import set, sequence
+
+class UnixLinkingGenerator (builtin.LinkingGenerator):
+
+ def __init__ (self, id, composing, source_types, target_types, requirements):
+ builtin.LinkingGenerator.__init__ (self, id, composing, source_types, target_types, requirements)
+
+ def run (self, project, name, prop_set, sources):
+ result = builtin.LinkingGenerator.run (self, project, name, prop_set, sources)
+ if result:
+ set_library_order (project.manager (), sources, prop_set, result [1])
+
+ return result
+
+ def generated_targets (self, sources, prop_set, project, name):
+ sources2 = []
+ libraries = []
+ for l in sources:
+ if type.is_derived (l.type (), 'LIB'):
+ libraries.append (l)
+
+ else:
+ sources2.append (l)
+
+ sources = sources2 + order_libraries (libraries)
+
+ return builtin.LinkingGenerator.generated_targets (self, sources, prop_set, project, name)
+
+
+class UnixArchiveGenerator (builtin.ArchiveGenerator):
+ def __init__ (self, id, composing, source_types, target_types_and_names, requirements):
+ builtin.ArchiveGenerator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
+
+ def run (self, project, name, prop_set, sources):
+ result = builtin.ArchiveGenerator.run(self, project, name, prop_set, sources)
+ set_library_order(project.manager(), sources, prop_set, result)
+ return result
+
+class UnixSearchedLibGenerator (builtin.SearchedLibGenerator):
+
+ def __init__ (self):
+ builtin.SearchedLibGenerator.__init__ (self)
+
+ def optional_properties (self):
+ return self.requirements ()
+
+ def run (self, project, name, prop_set, sources, multiple):
+ result = SearchedLibGenerator.run (project, name, prop_set, sources, multiple)
+
+ set_library_order (sources, prop_set, result)
+
+ return result
+
+class UnixPrebuiltLibGenerator (generators.Generator):
+ def __init__ (self, id, composing, source_types, target_types_and_names, requirements):
+ generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
+
+ def run (self, project, name, prop_set, sources, multiple):
+ f = prop_set.get ('<file>')
+ set_library_order_aux (f, sources)
+ return (f, sources)
+
+### # The derived toolset must specify their own rules and actions.
+# FIXME: restore?
+# action.register ('unix.prebuilt', None, None)
+
+
+generators.register (UnixPrebuiltLibGenerator ('unix.prebuilt', False, [], ['LIB'], ['<file>', '<toolset>unix']))
+
+
+
+
+
+### # Declare generators
+### generators.register [ new UnixLinkingGenerator unix.link : LIB OBJ : EXE
+### : <toolset>unix ] ;
+generators.register (UnixArchiveGenerator ('unix.archive', True, ['OBJ'], ['STATIC_LIB'], ['<toolset>unix']))
+
+### generators.register [ new UnixLinkingGenerator unix.link.dll : LIB OBJ : SHARED_LIB
+### : <toolset>unix ] ;
+###
+### generators.register [ new UnixSearchedLibGenerator
+### unix.SearchedLibGenerator : : SEARCHED_LIB : <toolset>unix ] ;
+###
+###
+### # The derived toolset must specify their own actions.
+### actions link {
+### }
+###
+### actions link.dll {
+### }
+
+def unix_archive (manager, targets, sources, properties):
+ pass
+
+# FIXME: restore?
+#action.register ('unix.archive', unix_archive, [''])
+
+### actions searched-lib-generator {
+### }
+###
+### actions prebuilt {
+### }
+
+
+from b2.util.order import Order
+__order = Order ()
+
+def set_library_order_aux (from_libs, to_libs):
+ for f in from_libs:
+ for t in to_libs:
+ if f != t:
+ __order.add_pair (f, t)
+
+def set_library_order (manager, sources, prop_set, result):
+ used_libraries = []
+ deps = prop_set.dependency ()
+
+ sources.extend(d.value() for d in deps)
+ sources = sequence.unique(sources)
+
+ for l in sources:
+ if l.type () and type.is_derived (l.type (), 'LIB'):
+ used_libraries.append (l)
+
+ created_libraries = []
+ for l in result:
+ if l.type () and type.is_derived (l.type (), 'LIB'):
+ created_libraries.append (l)
+
+ created_libraries = set.difference (created_libraries, used_libraries)
+ set_library_order_aux (created_libraries, used_libraries)
+
+def order_libraries (libraries):
+ return __order.order (libraries)
+
diff --git a/tools/build/v2/tools/vacpp.jam b/tools/build/v2/tools/vacpp.jam
new file mode 100644
index 0000000000..f4080fc04d
--- /dev/null
+++ b/tools/build/v2/tools/vacpp.jam
@@ -0,0 +1,150 @@
+# Copyright Vladimir Prus 2004.
+# Copyright Toon Knapen 2004.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt
+# or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#
+# Boost.Build V2 toolset for the IBM XL C++ compiler
+#
+
+import toolset : flags ;
+import feature ;
+import common ;
+import generators ;
+import os ;
+
+feature.extend toolset : vacpp ;
+toolset.inherit vacpp : unix ;
+generators.override vacpp.prebuilt : builtin.prebuilt ;
+generators.override vacpp.searched-lib-generator : searched-lib-generator ;
+
+# Configure the vacpp toolset
+rule init ( version ? : command * : options * )
+{
+ local condition = [
+ common.check-init-parameters vacpp : version $(version) ] ;
+
+ command = [ common.get-invocation-command vacpp : xlC
+ : $(command) : "/usr/vacpp/bin/xlC" ] ;
+
+ common.handle-options vacpp : $(condition) : $(command) : $(options) ;
+}
+
+# Declare generators
+generators.register-c-compiler vacpp.compile.c : C : OBJ : <toolset>vacpp ;
+generators.register-c-compiler vacpp.compile.c++ : CPP : OBJ : <toolset>vacpp ;
+
+# Allow C++ style comments in C files
+flags vacpp CFLAGS : -qcpluscmt ;
+
+# Declare flags
+flags vacpp CFLAGS <optimization>off : -qNOOPTimize ;
+flags vacpp CFLAGS <optimization>speed : -O3 -qstrict ;
+flags vacpp CFLAGS <optimization>space : -O2 -qcompact ;
+
+# Discretionary inlining (not recommended)
+flags vacpp CFLAGS <inlining>off : -qnoinline ;
+flags vacpp CFLAGS <inlining>on : -qinline ;
+#flags vacpp CFLAGS <inlining>full : -qinline ;
+flags vacpp CFLAGS <inlining>full : ;
+
+# Exception handling
+flags vacpp C++FLAGS <exception-handling>off : -qnoeh ;
+flags vacpp C++FLAGS <exception-handling>on : -qeh ;
+
+# Run-time Type Identification
+flags vacpp C++FLAGS <rtti>off : -qnortti ;
+flags vacpp C++FLAGS <rtti>on : -qrtti ;
+
+# Enable 64-bit memory addressing model
+flags vacpp CFLAGS <address-model>64 : -q64 ;
+flags vacpp LINKFLAGS <address-model>64 : -q64 ;
+flags vacpp ARFLAGS <target-os>aix/<address-model>64 : -X 64 ;
+
+# Use absolute path when generating debug information
+flags vacpp CFLAGS <debug-symbols>on : -g -qfullpath ;
+flags vacpp LINKFLAGS <debug-symbols>on : -g -qfullpath ;
+flags vacpp LINKFLAGS <debug-symbols>off : -s ;
+
+if [ os.name ] = AIX
+{
+ flags vacpp.compile C++FLAGS : -qfuncsect ;
+
+ # The -bnoipath strips the prepending (relative) path of libraries from
+ # the loader section in the target library or executable. Hence, during
+ # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded
+ # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without
+ # this option, the prepending (relative) path + library name is
+ # hard-coded in the loader section, causing *only* this path to be
+ # searched during load-time. Note that the AIX linker does not have an
+ # -soname equivalent, this is as close as it gets.
+ #
+ # The above options are definately for AIX 5.x, and most likely also for
+ # AIX 4.x and AIX 6.x. For details about the AIX linker see:
+ # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf
+ #
+ flags vacpp.link LINKFLAGS <link>shared : -bnoipath ;
+
+ # Run-time linking
+ flags vacpp.link EXE-LINKFLAGS <link>shared : -brtl ;
+}
+else
+{
+ # Linux PPC
+ flags vacpp.compile CFLAGS <link>shared : -qpic=large ;
+ flags vacpp FINDLIBS : rt ;
+}
+
+# Profiling
+flags vacpp CFLAGS <profiling>on : -pg ;
+flags vacpp LINKFLAGS <profiling>on : -pg ;
+
+flags vacpp.compile OPTIONS <cflags> ;
+flags vacpp.compile.c++ OPTIONS <cxxflags> ;
+flags vacpp DEFINES <define> ;
+flags vacpp UNDEFS <undef> ;
+flags vacpp HDRS <include> ;
+flags vacpp STDHDRS <sysinclude> ;
+flags vacpp.link OPTIONS <linkflags> ;
+flags vacpp ARFLAGS <arflags> ;
+
+flags vacpp LIBPATH <library-path> ;
+flags vacpp NEEDLIBS <library-file> ;
+flags vacpp FINDLIBS <find-shared-library> ;
+flags vacpp FINDLIBS <find-static-library> ;
+
+# Select the compiler name according to the threading model.
+flags vacpp VA_C_COMPILER <threading>single : xlc ;
+flags vacpp VA_C_COMPILER <threading>multi : xlc_r ;
+flags vacpp VA_CXX_COMPILER <threading>single : xlC ;
+flags vacpp VA_CXX_COMPILER <threading>multi : xlC_r ;
+
+SPACE = " " ;
+
+flags vacpp.link.dll HAVE_SONAME <target-os>linux : "" ;
+
+actions vacpp.link bind NEEDLIBS
+{
+ $(VA_CXX_COMPILER) $(EXE-LINKFLAGS) $(LINKFLAGS) -o "$(<[1])" -L$(LIBPATH) -L$(STDLIBPATH) "$(>)" "$(NEEDLIBS)" "$(NEEDLIBS)" -l$(FINDLIBS) $(OPTIONS) $(USER_OPTIONS)
+}
+
+actions vacpp.link.dll bind NEEDLIBS
+{
+ xlC_r -G $(LINKFLAGS) -o "$(<[1])" $(HAVE_SONAME)-Wl,-soname$(SPACE)-Wl,$(<[-1]:D=) -L$(LIBPATH) -L$(STDLIBPATH) "$(>)" "$(NEEDLIBS)" "$(NEEDLIBS)" -l$(FINDLIBS) $(OPTIONS) $(USER_OPTIONS)
+}
+
+actions vacpp.compile.c
+{
+ $(VA_C_COMPILER) -c $(OPTIONS) $(USER_OPTIONS) -I$(BOOST_ROOT) -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o "$(<)" "$(>)"
+}
+
+actions vacpp.compile.c++
+{
+ $(VA_CXX_COMPILER) -c $(OPTIONS) $(USER_OPTIONS) -I$(BOOST_ROOT) -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o "$(<)" "$(>)"
+}
+
+actions updated together piecemeal vacpp.archive
+{
+ ar $(ARFLAGS) ru "$(<)" "$(>)"
+}
diff --git a/tools/build/v2/tools/whale.jam b/tools/build/v2/tools/whale.jam
new file mode 100644
index 0000000000..9335ff0c0c
--- /dev/null
+++ b/tools/build/v2/tools/whale.jam
@@ -0,0 +1,116 @@
+# Copyright (C) Vladimir Prus 2002-2005.
+
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# This module implements support for Whale/Dolphin/WD parser/lexer tools.
+# See http://www.cs.queensu.ca/home/okhotin/whale/ for details.
+#
+# There are three interesting target types:
+# - WHL (the parser sources), that are converted to CPP and H
+# - DLP (the lexer sources), that are converted to CPP and H
+# - WD (combined parser/lexer sources), that are converted to WHL + DLP
+
+import type ;
+import generators ;
+import path ;
+import "class" : new ;
+import errors ;
+
+rule init ( path # path the Whale/Dolphin/WD binaries
+ )
+{
+ if $(.configured) && $(.path) != $(path)
+ {
+ errors.user-error "Attempt to reconfigure Whale support" :
+ "Previously configured with path \"$(.path:E=<empty>)\"" :
+ "Now configuring with path \"$(path:E=<empty>)\"" ;
+
+ }
+ .configured = true ;
+ .path = $(path) ;
+
+ .whale = [ path.join $(path) whale ] ;
+ .dolphin = [ path.join $(path) dolphin ] ;
+ .wd = [ path.join $(path) wd ] ;
+}
+
+
+# Declare the types.
+type.register WHL : whl ;
+type.register DLP : dlp ;
+type.register WHL_LR0 : lr0 ;
+type.register WD : wd ;
+
+# Declare standard generators.
+generators.register-standard whale.whale : WHL : CPP H H(%_symbols) ;
+generators.register-standard whale.dolphin : DLP : CPP H ;
+generators.register-standard whale.wd : WD : WHL(%_parser) DLP(%_lexer) ;
+
+# The conversions defines above a ambiguious when we generated CPP from WD.
+# We can either go via WHL type, or via DLP type.
+# The following custom generator handles this by running both conversions.
+
+class wd-to-cpp : generator
+{
+ rule __init__ ( * : * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) ;
+ }
+
+ rule run ( project name ? : property-set : source * )
+ {
+ if ! $(source[2])
+ {
+ local new-sources ;
+ if ! [ $(source).type ] in WHL DLP
+ {
+ local r1 = [ generators.construct $(project) $(name)
+ : WHL : $(property-set) : $(source) ] ;
+ local r2 = [ generators.construct $(project) $(name)
+ : DLP : $(property-set) : $(source) ] ;
+
+ new-sources = [ sequence.unique $(r1[2-]) $(r2[2-]) ] ;
+ }
+ else
+ {
+ new-sources = $(source) ;
+ }
+
+ local result ;
+ for local i in $(new-sources)
+ {
+ local t = [ generators.construct $(project) $(name) : CPP
+ : $(property-set) : $(i) ] ;
+ result += $(t[2-]) ;
+ }
+ return $(result) ;
+ }
+ }
+
+}
+
+
+generators.override whale.wd-to-cpp : whale.whale ;
+generators.override whale.wd-to-cpp : whale.dolphin ;
+
+
+generators.register [ new wd-to-cpp whale.wd-to-cpp : : CPP ] ;
+
+
+actions whale
+{
+ $(.whale) -d $(<[1]:D) $(>)
+}
+
+actions dolphin
+{
+ $(.dolphin) -d $(<[1]:D) $(>)
+}
+
+actions wd
+{
+ $(.wd) -d $(<[1]:D) -g $(>)
+}
+
diff --git a/tools/build/v2/tools/xlf.jam b/tools/build/v2/tools/xlf.jam
new file mode 100644
index 0000000000..e7fcc6086a
--- /dev/null
+++ b/tools/build/v2/tools/xlf.jam
@@ -0,0 +1,39 @@
+# Copyright (C) 2004 Toon Knapen
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+#
+# toolset configuration for the IBM Fortran compiler (xlf)
+#
+
+import toolset : flags ;
+import feature ;
+import fortran ;
+
+rule init ( version ? : command * : options * )
+{
+}
+
+# Declare flags and action for compilation
+flags xlf OPTIONS <optimization>off : -O0 ;
+flags xlf OPTIONS <optimization>speed : -O3 ;
+flags xlf OPTIONS <optimization>space : -Os ;
+
+flags xlf OPTIONS <debug-symbols>on : -g ;
+flags xlf OPTIONS <profiling>on : -pg ;
+
+flags xlf DEFINES <define> ;
+flags xlf INCLUDES <include> ;
+
+rule compile-fortran
+{
+}
+
+actions compile-fortran
+{
+ xlf $(OPTIONS) -I$(INCLUDES) -c -o "$(<)" "$(>)"
+}
+
+generators.register-fortran-compiler xlf.compile-fortran : FORTRAN : OBJ ;
diff --git a/tools/build/v2/tools/xsltproc-config.jam b/tools/build/v2/tools/xsltproc-config.jam
new file mode 100644
index 0000000000..de54a2eb37
--- /dev/null
+++ b/tools/build/v2/tools/xsltproc-config.jam
@@ -0,0 +1,37 @@
+#~ Copyright 2005 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Automatic configuration for Python tools and librries. To use, just import this module.
+
+import os ;
+import toolset : using ;
+
+if [ os.name ] = NT
+{
+ local xsltproc-path = [ GLOB [ modules.peek : PATH ] "C:\\Boost\\bin" : xsltproc\.exe ] ;
+ xsltproc-path = $(xsltproc-path[1]) ;
+
+ if $(xsltproc-path)
+ {
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice:" using xsltproc ":" $(xsltproc-path) ;
+ }
+ using xsltproc : $(xsltproc-path) ;
+ }
+}
+else
+{
+ local xsltproc-path = [ GLOB [ modules.peek : PATH ] : xsltproc ] ;
+ xsltproc-path = $(xsltproc-path[1]) ;
+
+ if $(xsltproc-path)
+ {
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice:" using xsltproc ":" $(xsltproc-path) ;
+ }
+ using xsltproc : $(xsltproc-path) ;
+ }
+}
diff --git a/tools/build/v2/tools/xsltproc.jam b/tools/build/v2/tools/xsltproc.jam
new file mode 100644
index 0000000000..96f5170bed
--- /dev/null
+++ b/tools/build/v2/tools/xsltproc.jam
@@ -0,0 +1,194 @@
+# Copyright (C) 2003 Doug Gregor. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+# This module defines rules to apply an XSLT stylesheet to an XML file using the
+# xsltproc driver, part of libxslt.
+#
+# Note: except for 'init', this modules does not provide any rules for end
+# users.
+
+import feature ;
+import regex ;
+import sequence ;
+import common ;
+import os ;
+import modules ;
+import path ;
+import errors ;
+
+feature.feature xsl:param : : free ;
+feature.feature xsl:path : : free ;
+feature.feature catalog : : free ;
+
+
+# Initialize xsltproc support. The parameters are:
+# xsltproc: The xsltproc executable
+#
+rule init ( xsltproc ? )
+{
+ if $(xsltproc)
+ {
+ modify-config ;
+ .xsltproc = $(xsltproc) ;
+ check-xsltproc ;
+ }
+}
+
+rule freeze-config ( )
+{
+ if ! $(.config-frozen)
+ {
+ .config-frozen = true ;
+ .xsltproc ?= [ modules.peek : XSLTPROC ] ;
+ .xsltproc ?= xsltproc ;
+ check-xsltproc ;
+ .is-cygwin = [ .is-cygwin $(.xsltproc) ] ;
+ }
+}
+
+rule modify-config
+{
+ if $(.config-frozen)
+ {
+ errors.user-error "xsltproc: Cannot change xsltproc command after it has been used." ;
+ }
+}
+
+rule check-xsltproc ( )
+{
+ if $(.xsltproc)
+ {
+ local status = [ SHELL "\"$(.xsltproc)\" -V" : no-output : exit-status ] ;
+ if $(status[2]) != "0"
+ {
+ errors.user-error "xsltproc: Could not run \"$(.xsltproc)\" -V." ;
+ }
+ }
+}
+
+# Returns a non-empty string if a cygwin xsltproc binary was specified.
+rule is-cygwin ( )
+{
+ freeze-config ;
+ return $(.is-cygwin) ;
+}
+
+rule .is-cygwin ( xsltproc )
+{
+ if [ os.on-windows ]
+ {
+ local file = [ path.make [ modules.binding $(__name__) ] ] ;
+ local dir = [ path.native
+ [ path.join [ path.parent $(file) ] xsltproc ] ] ;
+ if [ os.name ] = CYGWIN
+ {
+ dir = $(dir:W) ;
+ }
+ local command =
+ "\"$(xsltproc)\" \"$(dir)\\test.xsl\" \"$(dir)\\test.xml\" 2>&1" ;
+ local status = [ SHELL $(command) : no-output : exit-status ] ;
+ if $(status[2]) != "0"
+ {
+ return true ;
+ }
+ }
+}
+
+rule compute-xslt-flags ( target : properties * )
+{
+ local flags ;
+
+ # Raw flags.
+ flags += [ feature.get-values <flags> : $(properties) ] ;
+
+ # Translate <xsl:param> into command line flags.
+ for local param in [ feature.get-values <xsl:param> : $(properties) ]
+ {
+ local namevalue = [ regex.split $(param) "=" ] ;
+ flags += --stringparam $(namevalue[1]) \"$(namevalue[2])\" ;
+ }
+
+ # Translate <xsl:path>.
+ for local path in [ feature.get-values <xsl:path> : $(properties) ]
+ {
+ flags += --path \"$(path:G=)\" ;
+ }
+
+ # Take care of implicit dependencies.
+ local other-deps ;
+ for local dep in [ feature.get-values <implicit-dependency> : $(properties) ]
+ {
+ other-deps += [ $(dep:G=).creating-subvariant ] ;
+ }
+
+ local implicit-target-directories ;
+ for local dep in [ sequence.unique $(other-deps) ]
+ {
+ implicit-target-directories += [ $(dep).all-target-directories ] ;
+ }
+
+ for local dir in $(implicit-target-directories)
+ {
+ flags += --path \"$(dir:T)\" ;
+ }
+
+ return $(flags) ;
+}
+
+
+local rule .xsltproc ( target : source stylesheet : properties * : dirname ? : action )
+{
+ freeze-config ;
+ STYLESHEET on $(target) = $(stylesheet) ;
+ FLAGS on $(target) += [ compute-xslt-flags $(target) : $(properties) ] ;
+ NAME on $(target) = $(.xsltproc) ;
+
+ for local catalog in [ feature.get-values <catalog> : $(properties) ]
+ {
+ CATALOG = [ common.variable-setting-command XML_CATALOG_FILES : $(catalog:T) ] ;
+ }
+
+ if [ os.on-windows ] && ! [ is-cygwin ]
+ {
+ action = $(action).windows ;
+ }
+
+ $(action) $(target) : $(source) ;
+}
+
+
+rule xslt ( target : source stylesheet : properties * )
+{
+ return [ .xsltproc $(target) : $(source) $(stylesheet) : $(properties) : : xslt-xsltproc ] ;
+}
+
+
+rule xslt-dir ( target : source stylesheet : properties * : dirname )
+{
+ return [ .xsltproc $(target) : $(source) $(stylesheet) : $(properties) : $(dirname) : xslt-xsltproc-dir ] ;
+}
+
+actions xslt-xsltproc.windows
+{
+ $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --xinclude -o "$(<)" "$(STYLESHEET:W)" "$(>:W)"
+}
+
+
+actions xslt-xsltproc bind STYLESHEET
+{
+ $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --xinclude -o "$(<)" "$(STYLESHEET:T)" "$(>:T)"
+}
+
+
+actions xslt-xsltproc-dir.windows bind STYLESHEET
+{
+ $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --xinclude -o "$(<:D)/" "$(STYLESHEET:W)" "$(>:W)"
+}
+
+
+actions xslt-xsltproc-dir bind STYLESHEET
+{
+ $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --xinclude -o "$(<:D)/" "$(STYLESHEET:T)" "$(>:T)"
+}
diff --git a/tools/build/v2/tools/xsltproc/included.xsl b/tools/build/v2/tools/xsltproc/included.xsl
new file mode 100644
index 0000000000..ef86394a99
--- /dev/null
+++ b/tools/build/v2/tools/xsltproc/included.xsl
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2010 Steven Watanabe
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+</xsl:stylesheet>
diff --git a/tools/build/v2/tools/xsltproc/test.xml b/tools/build/v2/tools/xsltproc/test.xml
new file mode 100644
index 0000000000..57c8ba187e
--- /dev/null
+++ b/tools/build/v2/tools/xsltproc/test.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root/>
diff --git a/tools/build/v2/tools/xsltproc/test.xsl b/tools/build/v2/tools/xsltproc/test.xsl
new file mode 100644
index 0000000000..a142c91dd6
--- /dev/null
+++ b/tools/build/v2/tools/xsltproc/test.xsl
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2010 Steven Watanabe
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:include href="included.xsl"/>
+</xsl:stylesheet>
diff --git a/tools/build/v2/tools/zlib.jam b/tools/build/v2/tools/zlib.jam
new file mode 100644
index 0000000000..f9138fd573
--- /dev/null
+++ b/tools/build/v2/tools/zlib.jam
@@ -0,0 +1,92 @@
+# Copyright (c) 2010 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Supports the zlib library
+#
+# After 'using zlib', the following targets are available:
+#
+# /zlib//zlib -- The zlib library
+
+
+# In addition to direct purpose of supporting zlib, this module also
+# serves as canonical example of how third-party condiguration works
+# in Boost.Build. The operation is as follows
+#
+# - For each 'using zlib : condition ... : ...' we create a target alternative
+# for zlib, with the specified condition.
+# - There's one target alternative for 'zlib' with no specific condition
+# properties.
+#
+# Two invocations of 'using zlib' with the same condition but different
+# properties are not permitted, e.g.:
+#
+# using zlib : condition <target-os>windows : include foo ;
+# using zlib : condition <target-os>windows : include bar ;
+#
+# is in error. One exception is for empty condition, 'using' without any
+# parameters is overridable. That is:
+#
+# using zlib ;
+# using zlib : include foo ;
+#
+# Is OK then the first 'using' is ignored. Likewise if the order of the statements
+# is reversed.
+#
+# When 'zlib' target is built, a target alternative is selected as usual for
+# Boost.Build. The selected alternative is a custom target class, which:
+#
+# - calls ac.find-include-path to find header path. If explicit path is provided
+# in 'using', only that path is checked, and if no header is found there, error
+# is emitted. Otherwise, we check a directory specified using ZLIB_INCLUDE
+# environment variable, and failing that, in standard directories.
+# [TODO: document sysroot handling]
+# - calls ac.find-library to find the library, in an identical fashion.
+#
+
+import project ;
+import ac ;
+import errors ;
+import "class" : new ;
+import targets ;
+
+project.initialize $(__name__) ;
+project = [ project.current ] ;
+project zlib ;
+
+header = zlib.h ;
+names = z zlib zll zdll ;
+
+.default-alternative = [ new ac-library zlib : $(project) ] ;
+$(.default-alternative).set-header $(header) ;
+$(.default-alternative).set-default-names $(names) ;
+targets.main-target-alternative $(.default-alternative) ;
+
+rule init ( * : * )
+{
+ if ! $(condition)
+ {
+ # Special case the no-condition case so that 'using' without parameters
+ # can mix with more specific 'using'.
+ $(.default-alternative).reconfigure $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+ else
+ {
+ # FIXME: consider if we should allow overriding definitions for a given
+ # condition -- e.g. project-config.jam might want to override whatever is
+ # in user-config.jam.
+ local mt = [ new ac-library zlib : $(project)
+ : $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ $(mt).set-header $(header) ;
+ $(mt).set-default-names $(names) ;
+ targets.main-target-alternative $(mt) ;
+ }
+}
+
+
+
+
+
+
diff --git a/tools/build/v2/user-config.jam b/tools/build/v2/user-config.jam
new file mode 100644
index 0000000000..fbbf13fd0c
--- /dev/null
+++ b/tools/build/v2/user-config.jam
@@ -0,0 +1,92 @@
+# Copyright 2003, 2005 Douglas Gregor
+# Copyright 2004 John Maddock
+# Copyright 2002, 2003, 2004, 2007 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# This file is used to configure your Boost.Build installation. You can modify
+# this file in place, or you can place it in a permanent location so that it
+# does not get overwritten should you get a new version of Boost.Build. See:
+#
+# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html
+#
+# for documentation about possible permanent locations.
+
+# This file specifies which toolsets (C++ compilers), libraries, and other
+# tools are available. Often, you should be able to just uncomment existing
+# example lines and adjust them to taste. The complete list of supported tools,
+# and configuration instructions can be found at:
+#
+# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html
+#
+
+# This file uses Jam language syntax to describe available tools. Mostly,
+# there are 'using' lines, that contain the name of the used tools, and
+# parameters to pass to those tools -- where paremeters are separated by
+# semicolons. Important syntax notes:
+#
+# - Both ':' and ';' must be separated from other tokens by whitespace
+# - The '\' symbol is a quote character, so when specifying Windows paths you
+# should use '/' or '\\' instead.
+#
+# More details about the syntax can be found at:
+#
+# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language
+#
+
+# ------------------
+# GCC configuration.
+# ------------------
+
+# Configure gcc (default version).
+# using gcc ;
+
+# Configure specific gcc version, giving alternative name to use.
+# using gcc : 3.2 : g++-3.2 ;
+
+
+# -------------------
+# MSVC configuration.
+# -------------------
+
+# Configure msvc (default version, searched for in standard locations and PATH).
+# using msvc ;
+
+# Configure specific msvc version (searched for in standard locations and PATH).
+# using msvc : 8.0 ;
+
+
+# ----------------------
+# Borland configuration.
+# ----------------------
+# using borland ;
+
+
+# ----------------------
+# STLPort configuration.
+# ----------------------
+
+# Configure specifying location of STLPort headers. Libraries must be either
+# not needed or available to the compiler by default.
+# using stlport : : /usr/include/stlport ;
+
+# Configure specifying location of both headers and libraries explicitly.
+# using stlport : : /usr/include/stlport /usr/lib ;
+
+
+# -----------------
+# QT configuration.
+# -----------------
+
+# Configure assuming QTDIR gives the installation prefix.
+# using qt ;
+
+# Configure with an explicit installation prefix.
+# using qt : /usr/opt/qt ;
+
+# ---------------------
+# Python configuration.
+# ---------------------
+
+# Configure specific Python version.
+# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ;
diff --git a/tools/build/v2/util/__init__.py b/tools/build/v2/util/__init__.py
new file mode 100644
index 0000000000..f80fe70e90
--- /dev/null
+++ b/tools/build/v2/util/__init__.py
@@ -0,0 +1,136 @@
+
+import bjam
+import re
+import types
+
+# Decorator the specifies bjam-side prototype for a Python function
+def bjam_signature(s):
+
+ def wrap(f):
+ f.bjam_signature = s
+ return f
+
+ return wrap
+
+def metatarget(f):
+
+ f.bjam_signature = (["name"], ["sources", "*"], ["requirements", "*"],
+ ["default_build", "*"], ["usage_requirements", "*"])
+ return f
+
+class cached(object):
+
+ def __init__(self, function):
+ self.function = function
+ self.cache = {}
+
+ def __call__(self, *args):
+ try:
+ return self.cache[args]
+ except KeyError:
+ v = self.function(*args)
+ self.cache[args] = v
+ return v
+
+ def __get__(self, instance, type):
+ return types.MethodType(self, instance, type)
+
+def unquote(s):
+ if s and s[0] == '"' and s[-1] == '"':
+ return s[1:-1]
+ else:
+ return s
+
+_extract_jamfile_and_rule = re.compile("(Jamfile<.*>)%(.*)")
+
+def qualify_jam_action(action_name, context_module):
+
+ if action_name.startswith("###"):
+ # Callable exported from Python. Don't touch
+ return action_name
+ elif _extract_jamfile_and_rule.match(action_name):
+ # Rule is already in indirect format
+ return action_name
+ else:
+ ix = action_name.find('.')
+ if ix != -1 and action_name[:ix] == context_module:
+ return context_module + '%' + action_name[ix+1:]
+
+ return context_module + '%' + action_name
+
+
+def set_jam_action(name, *args):
+
+ m = _extract_jamfile_and_rule.match(name)
+ if m:
+ args = ("set-update-action-in-module", m.group(1), m.group(2)) + args
+ else:
+ args = ("set-update-action", name) + args
+
+ return bjam.call(*args)
+
+
+def call_jam_function(name, *args):
+
+ m = _extract_jamfile_and_rule.match(name)
+ if m:
+ args = ("call-in-module", m.group(1), m.group(2)) + args
+ return bjam.call(*args)
+ else:
+ return bjam.call(*((name,) + args))
+
+__value_id = 0
+__python_to_jam = {}
+__jam_to_python = {}
+
+def value_to_jam(value, methods=False):
+ """Makes a token to refer to a Python value inside Jam language code.
+
+ The token is merely a string that can be passed around in Jam code and
+ eventually passed back. For example, we might want to pass PropertySet
+ instance to a tag function and it might eventually call back
+ to virtual_target.add_suffix_and_prefix, passing the same instance.
+
+ For values that are classes, we'll also make class methods callable
+ from Jam.
+
+ Note that this is necessary to make a bit more of existing Jamfiles work.
+ This trick should not be used to much, or else the performance benefits of
+ Python port will be eaten.
+ """
+
+ global __value_id
+
+ r = __python_to_jam.get(value, None)
+ if r:
+ return r
+
+ exported_name = '###_' + str(__value_id)
+ __value_id = __value_id + 1
+ __python_to_jam[value] = exported_name
+ __jam_to_python[exported_name] = value
+
+ if methods and type(value) == types.InstanceType:
+ for field_name in dir(value):
+ field = getattr(value, field_name)
+ if callable(field) and not field_name.startswith("__"):
+ bjam.import_rule("", exported_name + "." + field_name, field)
+
+ return exported_name
+
+def record_jam_to_value_mapping(jam_value, python_value):
+ __jam_to_python[jam_value] = python_value
+
+def jam_to_value_maybe(jam_value):
+
+ if type(jam_value) == type(""):
+ return __jam_to_python.get(jam_value, jam_value)
+ else:
+ return jam_value
+
+def stem(filename):
+ i = filename.find('.')
+ if i != -1:
+ return filename[0:i]
+ else:
+ return filename
diff --git a/tools/build/v2/util/assert.jam b/tools/build/v2/util/assert.jam
new file mode 100644
index 0000000000..abedad5259
--- /dev/null
+++ b/tools/build/v2/util/assert.jam
@@ -0,0 +1,336 @@
+# Copyright 2001, 2002, 2003 Dave Abrahams
+# Copyright 2006 Rene Rivera
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import errors ;
+import modules ;
+
+
+################################################################################
+#
+# Private implementation details.
+#
+################################################################################
+
+# Rule added as a replacement for the regular Jam = operator but which does not
+# ignore trailing empty string elements.
+#
+local rule exact-equal-test ( lhs * : rhs * )
+{
+ local lhs_extended = $(lhs) xxx ;
+ local rhs_extended = $(rhs) xxx ;
+ if $(lhs_extended) = $(rhs_extended)
+ {
+ return true ;
+ }
+}
+
+
+# Two lists are considered set-equal if they contain the same elements, ignoring
+# duplicates and ordering.
+#
+local rule set-equal-test ( set1 * : set2 * )
+{
+ if ( $(set1) in $(set2) ) && ( $(set2) in $(set1) )
+ {
+ return true ;
+ }
+}
+
+
+################################################################################
+#
+# Public interface.
+#
+################################################################################
+
+# Assert the equality of A and B, ignoring trailing empty string elements.
+#
+rule equal ( a * : b * )
+{
+ if $(a) != $(b)
+ {
+ errors.error-skip-frames 3 assertion failure: \"$(a)\" "==" \"$(b)\"
+ (ignoring trailing empty strings) ;
+ }
+}
+
+
+# Assert that the result of calling RULE-NAME on the given arguments has a false
+# logical value (is either an empty list or all empty strings).
+#
+rule false ( rule-name args * : * )
+{
+ local result ;
+ module [ CALLER_MODULE ]
+ {
+ modules.poke assert : result : [ $(1) : $(2) : $(3) : $(4) : $(5) : $(6)
+ : $(7) : $(8) : $(9) ] ;
+ }
+
+ if $(result)
+ {
+ errors.error-skip-frames 3 assertion failure: Expected false result from
+ "[" $(rule-name) [ errors.lol->list $(args) : $(2) : $(3) : $(4) :
+ $(5) : $(6) : $(7) : $(8) : $(9) ] "]" : Got: "[" \"$(result)\" "]" ;
+ }
+}
+
+
+# Assert that ELEMENT is present in LIST.
+#
+rule "in" ( element : list * )
+{
+ if ! $(element) in $(list)
+ {
+ errors.error-skip-frames 3 assertion failure: Expected \"$(element)\" in
+ "[" \"$(list)\" "]" ;
+ }
+}
+
+
+# Assert the inequality of A and B, ignoring trailing empty string elements.
+#
+rule not-equal ( a * : b * )
+{
+ if $(a) = $(b)
+ {
+ errors.error-skip-frames 3 assertion failure: \"$(a)\" "!=" \"$(b)\"
+ (ignoring trailing empty strings) ;
+ }
+}
+
+
+# Assert that ELEMENT is not present in LIST.
+#
+rule not-in ( element : list * )
+{
+ if $(element) in $(list)
+ {
+ errors.error-skip-frames 3 assertion failure: Did not expect
+ \"$(element)\" in "[" \"$(list)\" "]" ;
+ }
+}
+
+
+# Assert the inequality of A and B as sets.
+#
+rule not-set-equal ( a * : b * )
+{
+ if [ set-equal-test $(a) : $(b) ]
+ {
+ errors.error-skip-frames 3 assertion failure: Expected "[" \"$(a)\" "]"
+ and "[" \"$(b)\" "]" to not be equal as sets ;
+ }
+}
+
+
+# Assert that A and B are not exactly equal, not ignoring trailing empty string
+# elements.
+#
+rule not-exact-equal ( a * : b * )
+{
+ if [ exact-equal-test $(a) : $(b) ]
+ {
+ errors.error-skip-frames 3 assertion failure: \"$(a)\" "!=" \"$(b)\" ;
+ }
+}
+
+
+# Assert that EXPECTED is the result of calling RULE-NAME with the given
+# arguments.
+#
+rule result ( expected * : rule-name args * : * )
+{
+ local result ;
+ module [ CALLER_MODULE ]
+ {
+ modules.poke assert : result : [ $(2) : $(3) : $(4) : $(5) : $(6) : $(7)
+ : $(8) : $(9) ] ;
+ }
+
+ if ! [ exact-equal-test $(result) : $(expected) ]
+ {
+ errors.error-skip-frames 3 assertion failure: "[" $(rule-name) [
+ errors.lol->list $(args) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) :
+ $(9) ] "]" : Expected: "[" \"$(expected)\" "]" : Got: "["
+ \"$(result)\" "]" ;
+ }
+}
+
+
+# Assert that EXPECTED is set-equal (i.e. duplicates and ordering are ignored)
+# to the result of calling RULE-NAME with the given arguments. Note that rules
+# called this way may accept at most 8 parameters.
+#
+rule result-set-equal ( expected * : rule-name args * : * )
+{
+ local result ;
+ module [ CALLER_MODULE ]
+ {
+ modules.poke assert : result : [ $(2) : $(3) : $(4) : $(5) : $(6) : $(7)
+ : $(8) : $(9) ] ;
+ }
+
+ if ! [ set-equal-test $(result) : $(expected) ]
+ {
+ errors.error-skip-frames 3 assertion failure: "[" $(rule-name) [
+ errors.lol->list $(args) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) :
+ $(9) ] "]" : Expected: "[" \"$(expected)\" "]" : Got: "["
+ \"$(result)\" "]" ;
+ }
+}
+
+
+# Assert the equality of A and B as sets.
+#
+rule set-equal ( a * : b * )
+{
+ if ! [ set-equal-test $(a) : $(b) ]
+ {
+ errors.error-skip-frames 3 assertion failure: Expected "[" \"$(a)\" "]"
+ and "[" \"$(b)\" "]" to be equal as sets ;
+ }
+}
+
+
+# Assert that the result of calling RULE-NAME on the given arguments has a true
+# logical value (is neither an empty list nor all empty strings).
+#
+rule true ( rule-name args * : * )
+{
+ local result ;
+ module [ CALLER_MODULE ]
+ {
+ modules.poke assert : result : [ $(1) : $(2) : $(3) : $(4) : $(5) : $(6)
+ : $(7) : $(8) : $(9) ] ;
+ }
+
+ if ! $(result)
+ {
+ errors.error-skip-frames 3 assertion failure: Expected true result from
+ "[" $(rule-name) [ errors.lol->list $(args) : $(2) : $(3) : $(4) :
+ $(5) : $(6) : $(7) : $(8) : $(9) ] "]" ;
+ }
+}
+
+
+# Assert the exact equality of A and B, not ignoring trailing empty string
+# elements.
+#
+rule exact-equal ( a * : b * )
+{
+ if ! [ exact-equal-test $(a) : $(b) ]
+ {
+ errors.error-skip-frames 3 assertion failure: \"$(a)\" "==" \"$(b)\" ;
+ }
+}
+
+
+# Assert that the given variable is not an empty list.
+#
+rule variable-not-empty ( name )
+{
+ local value = [ modules.peek [ CALLER_MODULE ] : $(name) ] ;
+ if ! $(value)-is-not-empty
+ {
+ errors.error-skip-frames 3 assertion failure: Expected variable
+ \"$(name)\" not to be an empty list ;
+ }
+}
+
+
+rule __test__ ( )
+{
+ # Helper rule used to avoid test duplication related to different list
+ # equality test rules.
+ #
+ local rule run-equality-test ( equality-assert : ignore-trailing-empty-strings ? )
+ {
+ local not-equality-assert = not-$(equality-assert) ;
+
+ # When the given equality test is expected to ignore trailing empty
+ # strings some of the test results should be inverted.
+ local not-equality-assert-i = not-$(equality-assert) ;
+ if $(ignore-trailing-empty-strings)
+ {
+ not-equality-assert-i = $(equality-assert) ;
+ }
+
+ $(equality-assert) : ;
+ $(equality-assert) "" "" : "" "" ;
+ $(not-equality-assert-i) : "" "" ;
+ $(equality-assert) x : x ;
+ $(not-equality-assert) : x ;
+ $(not-equality-assert) "" : x ;
+ $(not-equality-assert) "" "" : x ;
+ $(not-equality-assert-i) x : x "" ;
+ $(equality-assert) x "" : x "" ;
+ $(not-equality-assert) x : "" x ;
+ $(equality-assert) "" x : "" x ;
+
+ $(equality-assert) 1 2 3 : 1 2 3 ;
+ $(not-equality-assert) 1 2 3 : 3 2 1 ;
+ $(not-equality-assert) 1 2 3 : 1 5 3 ;
+ $(not-equality-assert) 1 2 3 : 1 "" 3 ;
+ $(not-equality-assert) 1 2 3 : 1 1 2 3 ;
+ $(not-equality-assert) 1 2 3 : 1 2 2 3 ;
+ $(not-equality-assert) 1 2 3 : 5 6 7 ;
+
+ # Extra variables used here just to make sure Boost Jam or Boost Build
+ # do not handle lists with empty strings differently depending on
+ # whether they are literals or stored in variables.
+
+ local empty = ;
+ local empty-strings = "" "" ;
+ local x-empty-strings = x "" "" ;
+ local empty-strings-x = "" "" x ;
+
+ $(equality-assert) : $(empty) ;
+ $(not-equality-assert-i) "" : $(empty) ;
+ $(not-equality-assert-i) "" "" : $(empty) ;
+ $(not-equality-assert-i) : $(empty-strings) ;
+ $(not-equality-assert-i) "" : $(empty-strings) ;
+ $(equality-assert) "" "" : $(empty-strings) ;
+ $(equality-assert) $(empty) : $(empty) ;
+ $(equality-assert) $(empty-strings) : $(empty-strings) ;
+ $(not-equality-assert-i) $(empty) : $(empty-strings) ;
+ $(equality-assert) $(x-empty-strings) : $(x-empty-strings) ;
+ $(equality-assert) $(empty-strings-x) : $(empty-strings-x) ;
+ $(not-equality-assert) $(empty-strings-x) : $(x-empty-strings) ;
+ $(not-equality-assert-i) x : $(x-empty-strings) ;
+ $(not-equality-assert) x : $(empty-strings-x) ;
+ $(not-equality-assert-i) x : $(x-empty-strings) ;
+ $(not-equality-assert-i) x "" : $(x-empty-strings) ;
+ $(equality-assert) x "" "" : $(x-empty-strings) ;
+ $(not-equality-assert) x : $(empty-strings-x) ;
+ $(not-equality-assert) "" x : $(empty-strings-x) ;
+ $(equality-assert) "" "" x : $(empty-strings-x) ;
+ }
+
+
+ # ---------------
+ # Equality tests.
+ # ---------------
+
+ run-equality-test equal : ignore-trailing-empty-strings ;
+ run-equality-test exact-equal ;
+
+
+ # -------------------------
+ # assert.set-equal() tests.
+ # -------------------------
+
+ set-equal : ;
+ not-set-equal "" "" : ;
+ set-equal "" "" : "" ;
+ set-equal "" "" : "" "" ;
+ set-equal a b c : a b c ;
+ set-equal a b c : b c a ;
+ set-equal a b c a : a b c ;
+ set-equal a b c : a b c a ;
+ not-set-equal a b c : a b c d ;
+ not-set-equal a b c d : a b c ;
+}
diff --git a/tools/build/v2/util/container.jam b/tools/build/v2/util/container.jam
new file mode 100644
index 0000000000..dd4963938e
--- /dev/null
+++ b/tools/build/v2/util/container.jam
@@ -0,0 +1,339 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003 Rene Rivera
+# Copyright 2002, 2003, 2004 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Various container classes.
+
+# Base for container objects. This lets us construct recursive structures. That
+# is containers with containers in them, specifically so we can tell literal
+# values from node values.
+#
+class node
+{
+ rule __init__ (
+ value ? # Optional value to set node to initially.
+ )
+ {
+ self.value = $(value) ;
+ }
+
+ # Set the value of this node, passing nothing will clear it.
+ #
+ rule set ( value * )
+ {
+ self.value = $(value) ;
+ }
+
+ # Get the value of this node.
+ #
+ rule get ( )
+ {
+ return $(self.value) ;
+ }
+}
+
+
+# A simple vector. Interface mimics the C++ std::vector and std::list, with the
+# exception that indices are one (1) based to follow Jam standard.
+#
+# TODO: Possibly add assertion checks.
+#
+class vector : node
+{
+ import numbers ;
+ import utility ;
+ import sequence ;
+
+ rule __init__ (
+ values * # Initial contents of vector.
+ )
+ {
+ node.__init__ ;
+ self.value = $(values) ;
+ }
+
+ # Get the value of the first element.
+ #
+ rule front ( )
+ {
+ return $(self.value[1]) ;
+ }
+
+ # Get the value of the last element.
+ #
+ rule back ( )
+ {
+ return $(self.value[-1]) ;
+ }
+
+ # Get the value of the element at the given index, one based. Access to
+ # elements of recursive structures is supported directly. Specifying
+ # additional index values recursively accesses the elements as containers.
+ # For example: [ $(v).at 1 : 2 ] would retrieve the second element of our
+ # first element, assuming the first element is a container.
+ #
+ rule at (
+ index # The element index, one based.
+ : * # Additional indices to access recursively.
+ )
+ {
+ local r = $(self.value[$(index)]) ;
+ if $(2)
+ {
+ r = [ $(r).at $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+ return $(r) ;
+ }
+
+ # Get the value contained in the given element. This has the same
+ # functionality and interface as "at" but in addition gets the value of the
+ # referenced element, assuming it is a "node".
+ #
+ rule get-at (
+ index # The element index, one based.
+ : * # Additional indices to access recursively.
+ )
+ {
+ local r = $(self.value[$(index)]) ;
+ if $(2)
+ {
+ r = [ $(r).at $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+ return [ $(r).get ] ;
+ }
+
+ # Insert the given value into the front of the vector pushing the rest of
+ # the elements back.
+ #
+ rule push-front (
+ value # Value to become first element.
+ )
+ {
+ self.value = $(value) $(self.value) ;
+ }
+
+ # Remove the front element from the vector. Does not return the value. No
+ # effect if vector is empty.
+ #
+ rule pop-front ( )
+ {
+ self.value = $(self.value[2-]) ;
+ }
+
+ # Add the given value at the end of the vector.
+ #
+ rule push-back (
+ value # Value to become back element.
+ )
+ {
+ self.value += $(value) ;
+ }
+
+ # Remove the back element from the vector. Does not return the value. No
+ # effect if vector is empty.
+ #
+ rule pop-back ( )
+ {
+ self.value = $(self.value[1--2]) ;
+ }
+
+ # Insert the given value at the given index, one based. The values at and to
+ # the right of the index are pushed back to make room for the new value.
+ # If the index is passed the end of the vector the element is added to the
+ # end.
+ #
+ rule insert (
+ index # The index to insert at, one based.
+ : value # The value to insert.
+ )
+ {
+ local left = $(self.value[1-$(index)]) ;
+ local right = $(self.value[$(index)-]) ;
+ if $(right)-is-not-empty
+ {
+ left = $(left[1--2]) ;
+ }
+ self.value = $(left) $(value) $(right) ;
+ }
+
+ # Remove one or more elements from the vector. The range is inclusive, and
+ # not specifying an end is equivalent to the [start, start] range.
+ #
+ rule erase (
+ start # Index of first element to remove.
+ end ? # Optional, index of last element to remove.
+ )
+ {
+ end ?= $(start) ;
+ local left = $(self.value[1-$(start)]) ;
+ left = $(left[1--2]) ;
+ local right = $(self.value[$(end)-]) ;
+ right = $(right[2-]) ;
+ self.value = $(left) $(right) ;
+ }
+
+ # Remove all elements from the vector.
+ #
+ rule clear ( )
+ {
+ self.value = ;
+ }
+
+ # The number of elements in the vector.
+ #
+ rule size ( )
+ {
+ return [ sequence.length $(self.value) ] ;
+ }
+
+ # Returns "true" if there are NO elements in the vector, empty otherwise.
+ #
+ rule empty ( )
+ {
+ if ! $(self.value)-is-not-empty
+ {
+ return true ;
+ }
+ }
+
+ # Returns the textual representation of content.
+ #
+ rule str ( )
+ {
+ return "[" [ sequence.transform utility.str : $(self.value) ] "]" ;
+ }
+
+ # Sorts the vector inplace, calling 'utility.less' for comparisons.
+ #
+ rule sort ( )
+ {
+ self.value = [ sequence.insertion-sort $(self.value) : utility.less ] ;
+ }
+
+ # Returns true if content is equal to the content of other vector. Uses
+ # 'utility.equal' for comparison.
+ #
+ rule equal ( another )
+ {
+ local mismatch ;
+ local size = [ size ] ;
+ if $(size) = [ $(another).size ]
+ {
+ for local i in [ numbers.range 1 $(size) ]
+ {
+ if ! [ utility.equal [ at $(i) ] [ $(another).at $(i) ] ]
+ {
+ mismatch = true ;
+ }
+ }
+ }
+ else
+ {
+ mismatch = true ;
+ }
+
+ if ! $(mismatch)
+ {
+ return true ;
+ }
+ }
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+ import "class" : new ;
+
+ local v1 = [ new vector ] ;
+ assert.true $(v1).equal $(v1) ;
+ assert.true $(v1).empty ;
+ assert.result 0 : $(v1).size ;
+ assert.result "[" "]" : $(v1).str ;
+ $(v1).push-back b ;
+ $(v1).push-front a ;
+ assert.result "[" a b "]" : $(v1).str ;
+ assert.result a : $(v1).front ;
+ assert.result b : $(v1).back ;
+ $(v1).insert 2 : d ;
+ $(v1).insert 2 : c ;
+ $(v1).insert 4 : f ;
+ $(v1).insert 4 : e ;
+ $(v1).pop-back ;
+ assert.result 5 : $(v1).size ;
+ assert.result d : $(v1).at 3 ;
+ $(v1).pop-front ;
+ assert.result c : $(v1).front ;
+ assert.false $(v1).empty ;
+ $(v1).erase 3 4 ;
+ assert.result 2 : $(v1).size ;
+
+ local v2 = [ new vector q w e r t y ] ;
+ assert.result 6 : $(v2).size ;
+ $(v1).push-back $(v2) ;
+ assert.result 3 : $(v1).size ;
+ local v2-alias = [ $(v1).back ] ;
+ assert.result e : $(v2-alias).at 3 ;
+ $(v1).clear ;
+ assert.true $(v1).empty ;
+ assert.false $(v2-alias).empty ;
+ $(v2).pop-back ;
+ assert.result t : $(v2-alias).back ;
+
+ local v3 = [ new vector ] ;
+ $(v3).push-back [ new vector 1 2 3 4 5 ] ;
+ $(v3).push-back [ new vector a b c ] ;
+ assert.result "[" "[" 1 2 3 4 5 "]" "[" a b c "]" "]" : $(v3).str ;
+ $(v3).push-back [ new vector [ new vector x y z ] [ new vector 7 8 9 ] ] ;
+ assert.result 1 : $(v3).at 1 : 1 ;
+ assert.result b : $(v3).at 2 : 2 ;
+ assert.result a b c : $(v3).get-at 2 ;
+ assert.result 7 8 9 : $(v3).get-at 3 : 2 ;
+
+ local v4 = [ new vector 4 3 6 ] ;
+ $(v4).sort ;
+ assert.result 3 4 6 : $(v4).get ;
+ assert.false $(v4).equal $(v3) ;
+
+ local v5 = [ new vector 3 4 6 ] ;
+ assert.true $(v4).equal $(v5) ;
+ # Check that vectors of different sizes are considered non-equal.
+ $(v5).pop-back ;
+ assert.false $(v4).equal $(v5) ;
+
+ local v6 = [ new vector [ new vector 1 2 3 ] ] ;
+ assert.true $(v6).equal [ new vector [ new vector 1 2 3 ] ] ;
+
+ local v7 = [ new vector 111 222 333 ] ;
+ assert.true $(v7).equal $(v7) ;
+ $(v7).insert 4 : 444 ;
+ assert.result 111 222 333 444 : $(v7).get ;
+ $(v7).insert 999 : xxx ;
+ assert.result 111 222 333 444 xxx : $(v7).get ;
+
+ local v8 = [ new vector "" "" "" ] ;
+ assert.true $(v8).equal $(v8) ;
+ assert.false $(v8).empty ;
+ assert.result 3 : $(v8).size ;
+ assert.result "" : $(v8).at 1 ;
+ assert.result "" : $(v8).at 2 ;
+ assert.result "" : $(v8).at 3 ;
+ assert.result : $(v8).at 4 ;
+ $(v8).insert 2 : 222 ;
+ assert.result 4 : $(v8).size ;
+ assert.result "" 222 "" "" : $(v8).get ;
+ $(v8).insert 999 : "" ;
+ assert.result 5 : $(v8).size ;
+ assert.result "" 222 "" "" "" : $(v8).get ;
+ $(v8).insert 999 : xxx ;
+ assert.result 6 : $(v8).size ;
+ assert.result "" 222 "" "" "" xxx : $(v8).get ;
+
+ # Regression test for a bug causing vector.equal to compare only the first
+ # and the last element in the given vectors.
+ local v9 = [ new vector 111 xxx 222 ] ;
+ local v10 = [ new vector 111 yyy 222 ] ;
+ assert.false $(v9).equal $(v10) ;
+}
diff --git a/tools/build/v2/util/doc.jam b/tools/build/v2/util/doc.jam
new file mode 100644
index 0000000000..a751558821
--- /dev/null
+++ b/tools/build/v2/util/doc.jam
@@ -0,0 +1,997 @@
+# Copyright 2002, 2005 Dave Abrahams
+# Copyright 2002, 2003, 2006 Rene Rivera
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Documentation system, handles --help requests.
+# It defines rules that attach documentation to modules, rules, and variables.
+# Collects and generates documentation for the various parts of the build
+# system. The documentation is collected from comments integrated into the code.
+
+import modules ;
+import print ;
+import set ;
+import container ;
+import "class" ;
+import sequence ;
+import path ;
+
+
+# The type of output to generate.
+# "console" is formated text echoed to the console (the default);
+# "text" is formated text appended to the output file;
+# "html" is HTML output to the file.
+#
+help-output = console ;
+
+
+# The file to output documentation to when generating "text" or "html" help.
+# This is without extension as the extension is determined by the type of
+# output.
+#
+help-output-file = help ;
+
+# Whether to include local rules in help output.
+#
+.option.show-locals ?= ;
+
+# When showing documentation for a module, whether to also generate
+# automatically the detailed docs for each item in the module.
+#
+.option.detailed ?= ;
+
+# Generate debug output as the help is generated and modules are parsed.
+#
+.option.debug ?= ;
+
+# Enable or disable a documentation option.
+#
+local rule set-option (
+ option # The option name.
+ : value ? # Enabled (non-empty), or disabled (empty)
+)
+{
+ .option.$(option) = $(value) ;
+}
+
+
+# Set the type of output.
+#
+local rule set-output ( type )
+{
+ help-output = $(type) ;
+}
+
+
+# Set the output to a file.
+#
+local rule set-output-file ( file )
+{
+ help-output-file = $(file) ;
+}
+
+
+# Extracts the brief comment from a complete comment. The brief comment is the
+# first sentence.
+#
+local rule brief-comment (
+ docs * # The comment documentation.
+)
+{
+ local d = $(docs:J=" ") ;
+ local p = [ MATCH ".*([.])$" : $(d) ] ;
+ if ! $(p) { d = $(d)"." ; }
+ d = $(d)" " ;
+ local m = [ MATCH "^([^.]+[.])(.*)" : $(d) ] ;
+ local brief = $(m[1]) ;
+ while $(m[2]) && [ MATCH "^([^ ])" : $(m[2]) ]
+ {
+ m = [ MATCH "^([^.]+[.])(.*)" : $(m[2]) ] ;
+ brief += $(m[1]) ;
+ }
+ return $(brief:J="") ;
+}
+
+
+# Specifies the documentation for the current module.
+#
+local rule set-module-doc (
+ module-name ? # The name of the module to document.
+ : docs * # The documentation for the module.
+)
+{
+ module-name ?= * ;
+
+ $(module-name).brief = [ brief-comment $(docs) ] ;
+ $(module-name).docs = $(docs) ;
+
+ if ! $(module-name) in $(documented-modules)
+ {
+ documented-modules += $(module-name) ;
+ }
+}
+
+
+# Specifies the documentation for the current module.
+#
+local rule set-module-copyright (
+ module-name ? # The name of the module to document.
+ : copyright * # The copyright for the module.
+)
+{
+ module-name ?= * ;
+
+ $(module-name).copy-brief = [ brief-comment $(copyright) ] ;
+ $(module-name).copy-docs = $(docs) ;
+
+ if ! $(module-name) in $(documented-modules)
+ {
+ documented-modules += $(module-name) ;
+ }
+}
+
+
+# Specifies the documentation for a rule in the current module. If called in the
+# global module, this documents a global rule.
+#
+local rule set-rule-doc (
+ name # The name of the rule.
+ module-name ? # The name of the module to document.
+ is-local ? # Whether the rule is local to the module.
+ : docs * # The documentation for the rule.
+)
+{
+ module-name ?= * ;
+
+ $(module-name).$(name).brief = [ brief-comment $(docs) ] ;
+ $(module-name).$(name).docs = $(docs) ;
+ $(module-name).$(name).is-local = $(is-local) ;
+
+ if ! $(name) in $($(module-name).rules)
+ {
+ $(module-name).rules += $(name) ;
+ }
+}
+
+
+# Specify a class, will turn a rule into a class.
+#
+local rule set-class-doc (
+ name # The name of the class.
+ module-name ? # The name of the module to document.
+ : super-name ? # The super class name.
+)
+{
+ module-name ?= * ;
+
+ $(module-name).$(name).is-class = true ;
+ $(module-name).$(name).super-name = $(super-name) ;
+ $(module-name).$(name).class-rules =
+ [ MATCH "^($(name)[.].*)" : $($(module-name).rules) ] ;
+ $(module-name).$($(module-name).$(name).class-rules).is-class-rule = true ;
+
+ $(module-name).classes += $(name) ;
+ $(module-name).class-rules += $($(module-name).$(name).class-rules) ;
+ $(module-name).rules =
+ [ set.difference $($(module-name).rules) :
+ $(name) $($(module-name).$(name).class-rules) ] ;
+}
+
+
+# Set the argument call signature of a rule.
+#
+local rule set-rule-arguments-signature (
+ name # The name of the rule.
+ module-name ? # The name of the module to document.
+ : signature * # The arguments signature.
+)
+{
+ module-name ?= * ;
+
+ $(module-name).$(name).signature = $(signature) ;
+}
+
+
+# Specifies the documentation for an argument of a rule.
+#
+local rule set-argument-doc (
+ name # The name of the argument.
+ qualifier # Argument syntax qualifier, "*", "+", etc.
+ rule-name # The name of the rule.
+ module-name ? # THe optional name of the module.
+ : docs * # The documentation.
+)
+{
+ module-name ?= * ;
+
+ $(module-name).$(rule-name).args.$(name).qualifier = $(qualifier) ;
+ $(module-name).$(rule-name).args.$(name).docs = $(docs) ;
+
+ if ! $(name) in $($(module-name).$(rule-name).args)
+ {
+ $(module-name).$(rule-name).args += $(name) ;
+ }
+}
+
+
+# Specifies the documentation for a variable in the current module. If called in
+# the global module, the global variable is documented.
+#
+local rule set-variable-doc (
+ name # The name of the variable.
+ default # The default value.
+ initial # The initial value.
+ module-name ? # The name of the module to document.
+ : docs * # The documentation for the variable.
+)
+{
+ module-name ?= * ;
+
+ $(module-name).$(name).brief = [ brief-comment $(docs) ] ;
+ $(module-name).$(name).default = $(default) ;
+ $(module-name).$(name).initial = $(initial) ;
+ $(module-name).$(name).docs = $(docs) ;
+
+ if ! $(name) in $($(module-name).variables)
+ {
+ $(module-name).variables += $(name) ;
+ }
+}
+
+
+# Generates a general description of the documentation and help system.
+#
+local rule print-help-top ( )
+{
+ print.section "General command line usage" ;
+
+ print.text " bjam [options] [properties] [targets]
+
+ Options, properties and targets can be specified in any order.
+ " ;
+
+ print.section "Important Options" ;
+
+ print.list-start ;
+ print.list-item "--clean Remove targets instead of building" ;
+ print.list-item "-a Rebuild everything" ;
+ print.list-item "-n Don't execute the commands, only print them" ;
+ print.list-item "-d+2 Show commands as they are executed" ;
+ print.list-item "-d0 Supress all informational messages" ;
+ print.list-item "-q Stop at first error" ;
+ print.list-item "--debug-configuration Diagnose configuration" ;
+ print.list-item "--debug-building Report which targets are built with what properties" ;
+ print.list-item "--debug-generator Diagnose generator search/execution" ;
+ print.list-end ;
+
+ print.section "Further Help"
+ The following options can be used to obtain additional documentation.
+ ;
+
+ print.list-start ;
+ print.list-item "--help-options Print more obscure command line options." ;
+ print.list-item "--help-internal Boost.Build implementation details." ;
+ print.list-item "--help-doc-options Implementation details doc formatting." ;
+ print.list-end ;
+}
+
+
+# Generate Jam/Boost.Jam command usage information.
+#
+local rule print-help-usage ( )
+{
+ print.section "Boost.Jam Usage"
+ "bjam [ options... ] targets..."
+ ;
+ print.list-start ;
+ print.list-item -a;
+ Build all targets, even if they are current. ;
+ print.list-item -fx;
+ Read '"x"' as the Jamfile for building instead of searching for the
+ Boost.Build system. ;
+ print.list-item -jx;
+ Run up to '"x"' commands concurrently. ;
+ print.list-item -n;
+ Do not execute build commands. Instead print out the commands as they
+ would be executed if building. ;
+ print.list-item -ox;
+ Output the used build commands to file '"x"'. ;
+ print.list-item -q;
+ Quit as soon as a build failure is encountered. Without this option
+ Boost.Jam will continue building as many targets as it can.
+ print.list-item -sx=y;
+ Sets a Jam variable '"x"' to the value '"y"', overriding any value that
+ variable would have from the environment. ;
+ print.list-item -tx;
+ Rebuild the target '"x"', even if it is up-to-date. ;
+ print.list-item -v;
+ Display the version of bjam. ;
+ print.list-item --x;
+ Any option not explicitly handled by Boost.Jam remains available to
+ build scripts using the '"ARGV"' variable. ;
+ print.list-item -dn;
+ Enables output of diagnostic messages. The debug level '"n"' and all
+ below it are enabled by this option. ;
+ print.list-item -d+n;
+ Enables output of diagnostic messages. Only the output for debug level
+ '"n"' is enabled. ;
+ print.list-end ;
+ print.section "Debug Levels"
+ Each debug level shows a different set of information. Usually with
+ higher levels producing more verbose information. The following levels
+ are supported: ;
+ print.list-start ;
+ print.list-item 0;
+ Turn off all diagnostic output. Only errors are reported. ;
+ print.list-item 1;
+ Show the actions taken for building targets, as they are executed. ;
+ print.list-item 2;
+ Show "quiet" actions and display all action text, as they are executed. ;
+ print.list-item 3;
+ Show dependency analysis, and target/source timestamps/paths. ;
+ print.list-item 4;
+ Show arguments of shell invocations. ;
+ print.list-item 5;
+ Show rule invocations and variable expansions. ;
+ print.list-item 6;
+ Show directory/header file/archive scans, and attempts at binding to targets. ;
+ print.list-item 7;
+ Show variable settings. ;
+ print.list-item 8;
+ Show variable fetches, variable expansions, and evaluation of '"if"' expressions. ;
+ print.list-item 9;
+ Show variable manipulation, scanner tokens, and memory usage. ;
+ print.list-item 10;
+ Show execution times for rules. ;
+ print.list-item 11;
+ Show parsing progress of Jamfiles. ;
+ print.list-item 12;
+ Show graph for target dependencies. ;
+ print.list-item 13;
+ Show changes in target status (fate). ;
+ print.list-end ;
+}
+
+
+# Generates description of options controlling the help system. This
+# automatically reads the options as all variables in the doc module of the form
+# ".option.*".
+#
+local rule print-help-options (
+ module-name # The doc module.
+)
+{
+ print.section "Help Options"
+ These are all the options available for enabling or disabling to control
+ the help system in various ways. Options can be enabled or disabled with
+ '"--help-enable-<option>"', and "'--help-disable-<option>'"
+ respectively.
+ ;
+ local options-to-list = [ MATCH ^[.]option[.](.*) : $($(module-name).variables) ] ;
+ if $(options-to-list)
+ {
+ print.list-start ;
+ for local option in [ sequence.insertion-sort $(options-to-list) ]
+ {
+ local def = disabled ;
+ if $($(module-name)..option.$(option).default) != "(empty)"
+ {
+ def = enabled ;
+ }
+ print.list-item $(option): $($(module-name)..option.$(option).docs)
+ Default is $(def). ;
+ }
+ print.list-end ;
+ }
+}
+
+
+# Generate brief documentation for all the known items in the section for a
+# module. Possible sections are: "rules", and "variables".
+#
+local rule print-help-module-section (
+ module # The module name.
+ section # rules or variables.
+ : section-head # The title of the section.
+ section-description * # The detailed description of the section.
+)
+{
+ if $($(module).$(section))
+ {
+ print.section $(section-head) $(section-description) ;
+ print.list-start ;
+ for local item in [ sequence.insertion-sort $($(module).$(section)) ]
+ {
+ local show = ;
+ if ! $($(module).$(item).is-local)
+ {
+ show = yes ;
+ }
+ if $(.option.show-locals)
+ {
+ show = yes ;
+ }
+ if $(show)
+ {
+ print.list-item $(item): $($(module).$(item).brief) ;
+ }
+ }
+ print.list-end ;
+ }
+}
+
+
+# Generate documentation for all possible modules. We attempt to list all known
+# modules together with a brief description of each.
+#
+local rule print-help-all (
+ ignored # Usually the module name, but is ignored here.
+)
+{
+ print.section "Modules"
+ "These are all the known modules. Use --help <module> to get more"
+ "detailed information."
+ ;
+ if $(documented-modules)
+ {
+ print.list-start ;
+ for local module-name in [ sequence.insertion-sort $(documented-modules) ]
+ {
+ # The brief docs for each module.
+ print.list-item $(module-name): $($(module-name).brief) ;
+ }
+ print.list-end ;
+ }
+ # The documentation for each module when details are requested.
+ if $(documented-modules) && $(.option.detailed)
+ {
+ for local module-name in [ sequence.insertion-sort $(documented-modules) ]
+ {
+ # The brief docs for each module.
+ print-help-module $(module-name) ;
+ }
+ }
+}
+
+
+# Generate documentation for a module. Basic information about the module is
+# generated.
+#
+local rule print-help-module (
+ module-name # The module to generate docs for.
+)
+{
+ # Print the docs.
+ print.section "Module '$(module-name)'" $($(module-name).docs) ;
+
+ # Print out the documented classes.
+ print-help-module-section $(module-name) classes : "Module '$(module-name)' classes"
+ Use --help $(module-name).<class-name> to get more information. ;
+
+ # Print out the documented rules.
+ print-help-module-section $(module-name) rules : "Module '$(module-name)' rules"
+ Use --help $(module-name).<rule-name> to get more information. ;
+
+ # Print out the documented variables.
+ print-help-module-section $(module-name) variables : "Module '$(module-name)' variables"
+ Use --help $(module-name).<variable-name> to get more information. ;
+
+ # Print out all the same information but indetailed form.
+ if $(.option.detailed)
+ {
+ print-help-classes $(module-name) ;
+ print-help-rules $(module-name) ;
+ print-help-variables $(module-name) ;
+ }
+}
+
+
+# Generate documentation for a set of rules in a module.
+#
+local rule print-help-rules (
+ module-name # Module of the rules.
+ : name * # Optional list of rules to describe.
+)
+{
+ name ?= $($(module-name).rules) ;
+ if [ set.intersection $(name) : $($(module-name).rules) $($(module-name).class-rules) ]
+ {
+ # Print out the given rules.
+ for local rule-name in [ sequence.insertion-sort $(name) ]
+ {
+ if $(.option.show-locals) || ! $($(module-name).$(rule-name).is-local)
+ {
+ local signature = $($(module-name).$(rule-name).signature:J=" ") ;
+ signature ?= "" ;
+ print.section "Rule '$(module-name).$(rule-name) ( $(signature) )'"
+ $($(module-name).$(rule-name).docs) ;
+ if $($(module-name).$(rule-name).args)
+ {
+ print.list-start ;
+ for local arg-name in $($(module-name).$(rule-name).args)
+ {
+ print.list-item $(arg-name): $($(module-name).$(rule-name).args.$(arg-name).docs) ;
+ }
+ print.list-end ;
+ }
+ }
+ }
+ }
+}
+
+
+# Generate documentation for a set of classes in a module.
+#
+local rule print-help-classes (
+ module-name # Module of the classes.
+ : name * # Optional list of classes to describe.
+)
+{
+ name ?= $($(module-name).classes) ;
+ if [ set.intersection $(name) : $($(module-name).classes) ]
+ {
+ # Print out the given classes.
+ for local class-name in [ sequence.insertion-sort $(name) ]
+ {
+ if $(.option.show-locals) || ! $($(module-name).$(class-name).is-local)
+ {
+ local signature = $($(module-name).$(class-name).signature:J=" ") ;
+ signature ?= "" ;
+ print.section "Class '$(module-name).$(class-name) ( $(signature) )'"
+ $($(module-name).$(class-name).docs)
+ "Inherits from '"$($(module-name).$(class-name).super-name)"'." ;
+ if $($(module-name).$(class-name).args)
+ {
+ print.list-start ;
+ for local arg-name in $($(module-name).$(class-name).args)
+ {
+ print.list-item $(arg-name): $($(module-name).$(class-name).args.$(arg-name).docs) ;
+ }
+ print.list-end ;
+ }
+ }
+
+ # Print out the documented rules of the class.
+ print-help-module-section $(module-name) $(class-name).class-rules : "Class '$(module-name).$(class-name)' rules"
+ Use --help $(module-name).<rule-name> to get more information. ;
+
+ # Print out all the rules if details are requested.
+ if $(.option.detailed)
+ {
+ print-help-rules $(module-name) : $($(module-name).$(class-name).class-rules) ;
+ }
+ }
+ }
+}
+
+
+# Generate documentation for a set of variables in a module.
+#
+local rule print-help-variables (
+ module-name ? # Module of the variables.
+ : name * # Optional list of variables to describe.
+)
+{
+ name ?= $($(module-name).variables) ;
+ if [ set.intersection $(name) : $($(module-name).variables) ]
+ {
+ # Print out the given variables.
+ for local variable-name in [ sequence.insertion-sort $(name) ]
+ {
+ print.section "Variable '$(module-name).$(variable-name)'" $($(module-name).$(variable-name).docs) ;
+ if $($(module-name).$(variable-name).default) ||
+ $($(module-name).$(variable-name).initial)
+ {
+ print.list-start ;
+ if $($(module-name).$(variable-name).default)
+ {
+ print.list-item "default value:" '$($(module-name).$(variable-name).default:J=" ")' ;
+ }
+ if $($(module-name).$(variable-name).initial)
+ {
+ print.list-item "initial value:" '$($(module-name).$(variable-name).initial:J=" ")' ;
+ }
+ print.list-end ;
+ }
+ }
+ }
+}
+
+
+# Generate documentation for a project.
+#
+local rule print-help-project (
+ unused ?
+ : jamfile * # The project Jamfile.
+)
+{
+ if $(jamfile<$(jamfile)>.docs)
+ {
+ # Print the docs.
+ print.section "Project-specific help"
+ Project has jamfile at $(jamfile) ;
+
+ print.lines $(jamfile<$(jamfile)>.docs) "" ;
+ }
+}
+
+
+# Generate documentation for a config file.
+#
+local rule print-help-config (
+ unused ?
+ : type # The type of configuration file user or site.
+ config-file # The configuration Jamfile.
+)
+{
+ if $(jamfile<$(config-file)>.docs)
+ {
+ # Print the docs.
+ print.section "Configuration help"
+ Configuration file at $(config-file) ;
+
+ print.lines $(jamfile<$(config-file)>.docs) "" ;
+ }
+}
+
+
+ws = " " ;
+
+# Extract the text from a block of comments.
+#
+local rule extract-comment (
+ var # The name of the variable to extract from.
+)
+{
+ local comment = ;
+ local line = $($(var)[1]) ;
+ local l = [ MATCH "^[$(ws)]*(#)(.*)$" : $(line) ] ;
+ while $(l[1]) && $($(var))
+ {
+ if $(l[2]) { comment += [ MATCH "^[$(ws)]?(.*)$" : $(l[2]) ] ; }
+ else { comment += "" ; }
+ $(var) = $($(var)[2-]) ;
+ line = $($(var)[1]) ;
+ l = [ MATCH "^[$(ws)]*(#)(.*)$" : $(line) ] ;
+ }
+ return $(comment) ;
+}
+
+
+# Extract s single line of Jam syntax, ignoring any comments.
+#
+local rule extract-syntax (
+ var # The name of the variable to extract from.
+)
+{
+ local syntax = ;
+ local line = $($(var)[1]) ;
+ while ! $(syntax) && ! [ MATCH "^[$(ws)]*(#)" : $(line) ] && $($(var))
+ {
+ local m = [ MATCH "^[$(ws)]*(.*)$" : $(line) ] ;
+ if $(m) && ! $(m) = ""
+ {
+ syntax = $(m) ;
+ }
+ $(var) = $($(var)[2-]) ;
+ line = $($(var)[1]) ;
+ }
+ return $(syntax) ;
+}
+
+
+# Extract the next token, this is either a single Jam construct or a comment as
+# a single token.
+#
+local rule extract-token (
+ var # The name of the variable to extract from.
+)
+{
+ local parts = ;
+ while ! $(parts)
+ {
+ parts = [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]*(.*)" : $($(var)[1]) ] ;
+ if ! $(parts)
+ {
+ $(var) = $($(var)[2-]) ;
+ }
+ }
+ local token = ;
+ if [ MATCH "^(#)" : $(parts[1]) ]
+ {
+ token = $(parts:J=" ") ;
+ $(var) = $($(var)[2-]) ;
+ }
+ else
+ {
+ token = $(parts[1]) ;
+ $(var) = $(parts[2-]:J=" ") $($(var)[2-]) ;
+ }
+ return $(token) ;
+}
+
+
+# Scan for a rule declaration as the next item in the variable.
+#
+local rule scan-rule (
+ syntax ? # The first part of the text which contains the rule declaration.
+ : var # The name of the variable to extract from.
+)
+{
+ local rule-parts =
+ [ MATCH "^[$(ws)]*(rule|local[$(ws)]*rule)[$(ws)]+([^$(ws)]+)[$(ws)]*(.*)" : $(syntax:J=" ") ] ;
+ if $(rule-parts[1])
+ {
+ # Mark as doc for rule.
+ local rule-name = $(rule-parts[2]) ;
+ if $(scope-name)
+ {
+ rule-name = $(scope-name).$(rule-name) ;
+ }
+ local is-local = [ MATCH "^(local).*" : $(rule-parts[1]) ] ;
+ if $(comment-block)
+ {
+ set-rule-doc $(rule-name) $(module-name) $(is-local) : $(comment-block) ;
+ }
+ # Parse args of rule.
+ $(var) = $(rule-parts[3-]) $($(var)) ;
+ set-rule-arguments-signature $(rule-name) $(module-name) : [ scan-rule-arguments $(var) ] ;
+ # Scan within this rules scope.
+ local scope-level = [ extract-token $(var) ] ;
+ local scope-name = $(rule-name) ;
+ while $(scope-level)
+ {
+ local comment-block = [ extract-comment $(var) ] ;
+ local syntax-block = [ extract-syntax $(var) ] ;
+ if [ scan-rule $(syntax-block) : $(var) ]
+ {
+ }
+ else if [ MATCH "^(\\{)" : $(syntax-block) ]
+ {
+ scope-level += "{" ;
+ }
+ else if [ MATCH "^[^\\}]*([\\}])[$(ws)]*$" : $(syntax-block) ]
+ {
+ scope-level = $(scope-level[2-]) ;
+ }
+ }
+
+ return true ;
+ }
+}
+
+
+# Scan the arguments of a rule.
+#
+local rule scan-rule-arguments (
+ var # The name of the variable to extract from.
+)
+{
+ local arg-syntax = ;
+ local token = [ extract-token $(var) ] ;
+ while $(token) != "(" && $(token) != "{"
+ {
+ token = [ extract-token $(var) ] ;
+ }
+ if $(token) != "{"
+ {
+ token = [ extract-token $(var) ] ;
+ }
+ local arg-signature = ;
+ while $(token) != ")" && $(token) != "{"
+ {
+ local arg-name = ;
+ local arg-qualifier = " " ;
+ local arg-doc = ;
+ if $(token) = ":"
+ {
+ arg-signature += $(token) ;
+ token = [ extract-token $(var) ] ;
+ }
+ arg-name = $(token) ;
+ arg-signature += $(token) ;
+ token = [ extract-token $(var) ] ;
+ if [ MATCH "^([\\*\\+\\?])" : $(token) ]
+ {
+ arg-qualifier = $(token) ;
+ arg-signature += $(token) ;
+ token = [ extract-token $(var) ] ;
+ }
+ if $(token) = ":"
+ {
+ arg-signature += $(token) ;
+ token = [ extract-token $(var) ] ;
+ }
+ if [ MATCH "^(#)" : $(token) ]
+ {
+ $(var) = $(token) $($(var)) ;
+ arg-doc = [ extract-comment $(var) ] ;
+ token = [ extract-token $(var) ] ;
+ }
+ set-argument-doc $(arg-name) $(arg-qualifier) $(rule-name) $(module-name) : $(arg-doc) ;
+ }
+ while $(token) != "{"
+ {
+ token = [ extract-token $(var) ] ;
+ }
+ $(var) = "{" $($(var)) ;
+ arg-signature ?= "" ;
+ return $(arg-signature) ;
+}
+
+
+# Scan for a variable declaration.
+#
+local rule scan-variable (
+ syntax ? # The first part of the text which contains the variable declaration.
+ : var # The name of the variable to extract from.
+)
+{
+ # [1] = name, [2] = value(s)
+ local var-parts =
+ [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]+([\\?\\=]*)[$(ws)]+([^\\;]*)\\;" : $(syntax) ] ;
+ if $(var-parts)
+ {
+ local value = [ MATCH "^(.*)[ ]$" : $(var-parts[3-]:J=" ") ] ;
+ local default-value = "" ;
+ local initial-valie = "" ;
+ if $(var-parts[2]) = "?="
+ {
+ default-value = $(value) ;
+ default-value ?= "(empty)" ;
+ }
+ else
+ {
+ initial-value = $(value) ;
+ initial-value ?= "(empty)" ;
+ }
+ if $(comment-block)
+ {
+ set-variable-doc $(var-parts[1]) $(default-value) $(initial-value) $(module-name) : $(comment-block) ;
+ }
+ return true ;
+ }
+}
+
+
+# Scan a class declaration.
+#
+local rule scan-class (
+ syntax ? # The syntax text for the class declaration.
+)
+{
+ # [1] = class?, [2] = name, [3] = superclass
+ local class-parts =
+ [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]+([^$(ws)]+)[$(ws)]+:*[$(ws)]*([^$(ws);]*)" : $(syntax) ] ;
+ if $(class-parts[1]) = "class" || $(class-parts[1]) = "class.class"
+ {
+ set-class-doc $(class-parts[2]) $(module-name) : $(class-parts[3]) ;
+ }
+}
+
+
+# Scan a module file for documentation comments. This also invokes any actions
+# assigned to the module. The actions are the rules that do the actual output of
+# the documentation. This rule is invoked as the header scan rule for the module
+# file.
+#
+rule scan-module (
+ target # The module file.
+ : text * # The text in the file, one item per line.
+ : action * # Rule to call to output docs for the module.
+)
+{
+ if $(.option.debug) { ECHO "HELP:" scanning module target '$(target)' ; }
+ local module-name = $(target:B) ;
+ local module-documented = ;
+ local comment-block = ;
+ local syntax-block = ;
+ # This is a hack because we can not get the line of a file if it happens to
+ # not have a new-line termination.
+ text += "}" ;
+ while $(text)
+ {
+ comment-block = [ extract-comment text ] ;
+ syntax-block = [ extract-syntax text ] ;
+ if $(.option.debug)
+ {
+ ECHO "HELP:" comment block; '$(comment-block)' ;
+ ECHO "HELP:" syntax block; '$(syntax-block)' ;
+ }
+ if [ scan-rule $(syntax-block) : text ] { }
+ else if [ scan-variable $(syntax-block) : text ] { }
+ else if [ scan-class $(syntax-block) ] { }
+ else if [ MATCH .*([cC]opyright).* : $(comment-block:J=" ") ]
+ {
+ # mark as the copy for the module.
+ set-module-copyright $(module-name) : $(comment-block) ;
+ }
+ else if $(action[1]) in "print-help-project" "print-help-config"
+ && ! $(jamfile<$(target)>.docs)
+ {
+ # special module docs for the project jamfile.
+ jamfile<$(target)>.docs = $(comment-block) ;
+ }
+ else if ! $(module-documented)
+ {
+ # document the module.
+ set-module-doc $(module-name) : $(comment-block) ;
+ module-documented = true ;
+ }
+ }
+ if $(action)
+ {
+ $(action[1]) $(module-name) : $(action[2-]) ;
+ }
+}
+
+
+# Import scan-module to global scope, so that it is available during header
+# scanning phase.
+#
+IMPORT $(__name__) : scan-module : : doc.scan-module ;
+
+
+# Read in a file using the SHELL builtin and return the individual lines as
+# would be done for header scanning.
+#
+local rule read-file (
+ file # The file to read in.
+)
+{
+ file = [ path.native [ path.root [ path.make $(file) ] [ path.pwd ] ] ] ;
+ if ! $(.file<$(file)>.lines)
+ {
+ local content ;
+ switch [ modules.peek : OS ]
+ {
+ case NT :
+ content = [ SHELL "TYPE \"$(file)\"" ] ;
+
+ case * :
+ content = [ SHELL "cat \"$(file)\"" ] ;
+ }
+ local lines ;
+ local nl = "
+" ;
+ local << = "([^$(nl)]*)[$(nl)](.*)" ;
+ local line+ = [ MATCH "$(<<)" : "$(content)" ] ;
+ while $(line+)
+ {
+ lines += $(line+[1]) ;
+ line+ = [ MATCH "$(<<)" : "$(line+[2])" ] ;
+ }
+ .file<$(file)>.lines = $(lines) ;
+ }
+ return $(.file<$(file)>.lines) ;
+}
+
+
+# Add a scan action to perform to generate the help documentation. The action
+# rule is passed the name of the module as the first argument. The second
+# argument(s) are optional and passed directly as specified here.
+#
+local rule do-scan (
+ modules + # The modules to scan and perform the action on.
+ : action * # The action rule, plus the secondary arguments to pass to the action rule.
+)
+{
+ if $(help-output) = text
+ {
+ print.output $(help-output-file).txt plain ;
+ ALWAYS $(help-output-file).txt ;
+ DEPENDS all : $(help-output-file).txt ;
+ }
+ if $(help-output) = html
+ {
+ print.output $(help-output-file).html html ;
+ ALWAYS $(help-output-file).html ;
+ DEPENDS all : $(help-output-file).html ;
+ }
+ for local module-file in $(modules[1--2])
+ {
+ scan-module $(module-file) : [ read-file $(module-file) ] ;
+ }
+ scan-module $(modules[-1]) : [ read-file $(modules[-1]) ] : $(action) ;
+}
diff --git a/tools/build/v2/util/indirect.jam b/tools/build/v2/util/indirect.jam
new file mode 100644
index 0000000000..ec63f1920b
--- /dev/null
+++ b/tools/build/v2/util/indirect.jam
@@ -0,0 +1,115 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import modules ;
+import numbers ;
+
+
+# The pattern that indirect rules must match: module%rule
+.pattern = ^([^%]*)%([^%]+)$ ;
+
+
+#
+# Type checking rules.
+#
+local rule indirect-rule ( x )
+{
+ if ! [ MATCH $(.pattern) : $(x) ]
+ {
+ return "expected a string of the form module%rule, but got \""$(x)"\" for argument" ;
+ }
+}
+
+
+# Make an indirect rule which calls the given rule. If context is supplied it is
+# expected to be the module in which to invoke the rule by the 'call' rule
+# below. Otherwise, the rule will be invoked in the module of this rule's
+# caller.
+#
+rule make ( rulename bound-args * : context ? )
+{
+ context ?= [ CALLER_MODULE ] ;
+ context ?= "" ;
+ return $(context)%$(rulename) $(bound-args) ;
+}
+
+
+# Make an indirect rule which calls the given rule. 'rulename' may be a
+# qualified rule; if so it is returned unchanged. Otherwise, if frames is not
+# supplied, the result will be invoked (by 'call', below) in the module of the
+# caller. Otherwise, frames > 1 specifies additional call frames to back up in
+# order to find the module context.
+#
+rule make-qualified ( rulename bound-args * : frames ? )
+{
+ if [ MATCH $(.pattern) : $(rulename) ]
+ {
+ return $(rulename) $(bound-args) ;
+ }
+ else
+ {
+ frames ?= 1 ;
+ # If the rule name includes a Jamfile module, grab it.
+ local module-context = [ MATCH ^(Jamfile<[^>]*>)\\..* : $(rulename) ] ;
+
+ if ! $(module-context)
+ {
+ # Take the first dot-separated element as module name. This disallows
+ # module names with dots, but allows rule names with dots.
+ module-context = [ MATCH ^([^.]*)\\..* : $(rulename) ] ;
+ }
+ module-context ?= [ CALLER_MODULE $(frames) ] ;
+ return [ make $(rulename) $(bound-args) : $(module-context) ] ;
+ }
+}
+
+
+# Returns the module name in which the given indirect rule will be invoked.
+#
+rule get-module ( [indirect-rule] x )
+{
+ local m = [ MATCH $(.pattern) : $(x) ] ;
+ if ! $(m[1])
+ {
+ m = ;
+ }
+ return $(m[1]) ;
+}
+
+
+# Returns the rulename that will be called when x is invoked.
+#
+rule get-rule ( [indirect-rule] x )
+{
+ local m = [ MATCH $(.pattern) : $(x) ] ;
+ return $(m[2]) ;
+}
+
+
+# Invoke the given indirect-rule.
+#
+rule call ( [indirect-rule] r args * : * )
+{
+ return [ modules.call-in [ get-module $(r) ] : [ get-rule $(r) ] $(args)
+ : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+}
+
+
+rule __test__
+{
+ import assert ;
+
+ rule foo-barr! ( x )
+ {
+ assert.equal $(x) : x ;
+ }
+
+ assert.equal [ get-rule [ make foo-barr! ] ] : foo-barr! ;
+ assert.equal [ get-module [ make foo-barr! ] ] : [ CALLER_MODULE ] ;
+
+ call [ make foo-barr! ] x ;
+ call [ make foo-barr! x ] ;
+ call [ make foo-barr! : [ CALLER_MODULE ] ] x ;
+}
diff --git a/tools/build/v2/util/indirect.py b/tools/build/v2/util/indirect.py
new file mode 100644
index 0000000000..78fa89946b
--- /dev/null
+++ b/tools/build/v2/util/indirect.py
@@ -0,0 +1,15 @@
+# Status: minimally ported. This module is not supposed to be used much
+# with Boost.Build/Python.
+#
+# Copyright 2003 Dave Abrahams
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+from b2.util import call_jam_function, bjam_signature
+
+def call(*args):
+ a1 = args[0]
+ name = a1[0]
+ a1tail = a1[1:]
+ call_jam_function(name, *((a1tail,) + args[1:]))
diff --git a/tools/build/v2/util/logger.py b/tools/build/v2/util/logger.py
new file mode 100644
index 0000000000..de6521290a
--- /dev/null
+++ b/tools/build/v2/util/logger.py
@@ -0,0 +1,46 @@
+# Copyright Pedro Ferreira 2005. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import sys
+
+class NullLogger:
+ def __init__ (self):
+ self.indent_ = ''
+
+ def log (self, source_name, *args):
+ if self.on () and self.interesting (source_name):
+ self.do_log (self.indent_)
+ for i in args:
+ self.do_log (i)
+ self.do_log ('\n')
+
+ def increase_indent (self):
+ if self.on ():
+ self.indent_ += ' '
+
+ def decrease_indent (self):
+ if self.on () and len (self.indent_) > 4:
+ self.indent_ = self.indent_ [-4:]
+
+ def do_log (self, *args):
+ pass
+
+ def interesting (self, source_name):
+ return False
+
+ def on (self):
+ return True
+
+class TextLogger (NullLogger):
+ def __init__ (self):
+ NullLogger.__init__ (self)
+
+ def do_log (self, arg):
+ sys.stdout.write (str (arg))
+
+ def interesting (self, source_name):
+ return True
+
+ def on (self):
+ return True
diff --git a/tools/build/v2/util/numbers.jam b/tools/build/v2/util/numbers.jam
new file mode 100644
index 0000000000..665347d318
--- /dev/null
+++ b/tools/build/v2/util/numbers.jam
@@ -0,0 +1,218 @@
+# Copyright 2001, 2002 Dave Abrahams
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import errors ;
+
+
+rule trim-leading-zeroes ( value )
+{
+ return [ CALC $(value) + 0 ] ;
+}
+
+
+rule check ( numbers * )
+{
+ for local n in $(numbers)
+ {
+ switch $(n)
+ {
+ case *[^0-9]* :
+ errors.error $(n) "in" $(numbers) : is not a number ;
+ }
+ }
+}
+
+
+rule increment ( number )
+{
+ return [ CALC $(number) + 1 ] ;
+}
+
+
+rule decrement ( number )
+{
+ return [ CALC $(number) - 1 ] ;
+}
+
+
+rule range ( start finish ? : step ? )
+{
+ if ! $(finish)
+ {
+ finish = $(start) ;
+ start = 1 ;
+ }
+ step ?= 1 ;
+
+ check $(start) $(finish) $(step) ;
+
+ if $(finish) != 0
+ {
+ local result ;
+ while [ less $(start) $(finish) ] || $(start) = $(finish)
+ {
+ result += $(start) ;
+ start = [ CALC $(start) + $(step) ] ;
+ }
+ return $(result) ;
+ }
+}
+
+
+rule less ( n1 n2 )
+{
+ switch [ CALC $(n2) - $(n1) ]
+ {
+ case [1-9]* : return true ;
+ }
+}
+
+
+rule log10 ( number )
+{
+ switch $(number)
+ {
+ case *[^0-9]* : errors.error $(number) is not a number ;
+ case 0 : errors.error can't take log of zero ;
+ case [1-9] : return 0 ;
+ case [1-9]? : return 1 ;
+ case [1-9]?? : return 2 ;
+ case [1-9]??? : return 3 ;
+ case [1-9]???? : return 4 ;
+ case [1-9]????? : return 5 ;
+ case [1-9]?????? : return 6 ;
+ case [1-9]??????? : return 7 ;
+ case [1-9]???????? : return 8 ;
+ case [1-9]????????? : return 9 ;
+ case * :
+ {
+ import sequence ;
+ import string ;
+ local chars = [ string.chars $(number) ] ;
+ while $(chars[1]) = 0
+ {
+ chars = $(chars[2-]) ;
+ }
+ if ! $(chars)
+ {
+ errors.error can't take log of zero ;
+ }
+ else
+ {
+ return [ decrement [ sequence.length $(chars) ] ] ;
+ }
+ }
+ }
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+
+ assert.result 1 : increment 0 ;
+ assert.result 2 : increment 1 ;
+ assert.result 1 : decrement 2 ;
+ assert.result 0 : decrement 1 ;
+ assert.result 50 : increment 49 ;
+ assert.result 49 : decrement 50 ;
+ assert.result 99 : increment 98 ;
+ assert.result 99 : decrement 100 ;
+ assert.result 100 : increment 99 ;
+ assert.result 999 : decrement 1000 ;
+ assert.result 1000 : increment 999 ;
+
+ assert.result 1 2 3 : range 3 ;
+ assert.result 1 2 3 4 5 6 7 8 9 10 11 12 : range 12 ;
+ assert.result 3 4 5 6 7 8 9 10 11 : range 3 11 ;
+ assert.result : range 0 ;
+ assert.result 1 4 7 10 : range 10 : 3 ;
+ assert.result 2 4 6 8 10 : range 2 10 : 2 ;
+ assert.result 25 50 75 100 : range 25 100 : 25 ;
+
+ assert.result 0 : trim-leading-zeroes 0 ;
+ assert.result 1234 : trim-leading-zeroes 1234 ;
+ assert.result 123456 : trim-leading-zeroes 0000123456 ;
+ assert.result 1000123456 : trim-leading-zeroes 1000123456 ;
+ assert.result 10000 : trim-leading-zeroes 10000 ;
+ assert.result 10000 : trim-leading-zeroes 00010000 ;
+
+ assert.true less 1 2 ;
+ assert.true less 1 12 ;
+ assert.true less 1 21 ;
+ assert.true less 005 217 ;
+ assert.false less 0 0 ;
+ assert.false less 03 3 ;
+ assert.false less 3 03 ;
+ assert.true less 005 217 ;
+ assert.true less 0005 217 ;
+ assert.true less 5 00217 ;
+
+ # TEMPORARY disabled, because nested "try"/"catch" do not work and I do no
+ # have the time to fix that right now.
+ if $(0)
+ {
+ try ;
+ {
+ decrement 0 ;
+ }
+ catch can't decrement zero! ;
+
+ try ;
+ {
+ check foo ;
+ }
+ catch : not a number ;
+
+ try ;
+ {
+ increment foo ;
+ }
+ catch : not a number ;
+
+ try ;
+ {
+ log10 0 ;
+ }
+ catch can't take log of zero ;
+
+ try ;
+ {
+ log10 000 ;
+ }
+ catch can't take log of zero ;
+
+ }
+
+ assert.result 0 : log10 1 ;
+ assert.result 0 : log10 9 ;
+ assert.result 1 : log10 10 ;
+ assert.result 1 : log10 99 ;
+ assert.result 2 : log10 100 ;
+ assert.result 2 : log10 101 ;
+ assert.result 2 : log10 125 ;
+ assert.result 2 : log10 999 ;
+ assert.result 3 : log10 1000 ;
+ assert.result 10 : log10 12345678901 ;
+
+ for local x in [ range 75 110 : 5 ]
+ {
+ for local y in [ range $(x) 111 : 3 ]
+ {
+ if $(x) != $(y)
+ {
+ assert.true less $(x) $(y) ;
+ }
+ }
+ }
+
+ for local x in [ range 90 110 : 2 ]
+ {
+ for local y in [ range 80 $(x) : 4 ]
+ {
+ assert.false less $(x) $(y) ;
+ }
+ }
+}
diff --git a/tools/build/v2/util/option.jam b/tools/build/v2/util/option.jam
new file mode 100644
index 0000000000..f6dc375223
--- /dev/null
+++ b/tools/build/v2/util/option.jam
@@ -0,0 +1,109 @@
+# Copyright (c) 2005 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import modules ;
+
+# Set a value for a named option, to be used when not overridden on the command
+# line.
+rule set ( name : value ? )
+{
+ .option.$(name) = $(value) ;
+}
+
+rule get ( name : default-value ? : implied-value ? )
+{
+ local m = [ MATCH --$(name)=(.*) : [ modules.peek : ARGV ] ] ;
+ if $(m)
+ {
+ return $(m[1]) ;
+ }
+ else
+ {
+ m = [ MATCH (--$(name)) : [ modules.peek : ARGV ] ] ;
+ if $(m) && $(implied-value)
+ {
+ return $(implied-value) ;
+ }
+ else if $(.option.$(name))
+ {
+ return $(.option.$(name)) ;
+ }
+ else
+ {
+ return $(default-value) ;
+ }
+ }
+}
+
+
+# Check command-line args as soon as possible. For each option try to load
+# module named after option. Is that succeeds, invoke 'process' rule in the
+# module. The rule may return "true" to indicate that the regular build process
+# should not be attempted.
+#
+# Options take the general form of: --<name>[=<value>] [<value>]
+#
+rule process ( )
+{
+ local ARGV = [ modules.peek : ARGV ] ;
+ local BOOST_BUILD_PATH = [ modules.peek : BOOST_BUILD_PATH ] ;
+
+ local dont-build ;
+ local args = $(ARGV) ;
+ while $(args)
+ {
+ local arg = [ MATCH ^--(.*) : $(args[1]) ] ;
+ while $(args[2-]) && ! $(arg)
+ {
+ args = $(args[2-]) ;
+ arg = [ MATCH ^--(.*) : $(args[1]) ] ;
+ }
+ args = $(args[2-]) ;
+
+ if $(arg)
+ {
+ local split = [ MATCH ^(([^-=]+)[^=]*)(=?)(.*)$ : $(arg) ] ;
+ local full-name = $(split[1]) ;
+ local prefix = $(split[2]) ;
+ local values ;
+
+ if $(split[3])
+ {
+ values = $(split[4]) ;
+ }
+ if $(args) && ! [ MATCH ^(--).* : $(args[1]) ]
+ {
+ values += $(args[1]) ;
+ args = $(args[2-]) ;
+ }
+
+ # Jook in options subdirectories of BOOST_BUILD_PATH for modules
+ # matching the full option name and then its prefix.
+ local plugin-dir = options ;
+ local option-files = [ GLOB $(plugin-dir:D=$(BOOST_BUILD_PATH)) :
+ $(full-name).jam $(prefix).jam ] ;
+
+ if $(option-files)
+ {
+ # Load the file into a module named for the option.
+ local f = $(option-files[1]) ;
+ local module-name = --$(f:D=:S=) ;
+ modules.load $(module-name) : $(f:D=) : $(f:D) ;
+
+ # If there is a process rule, call it with the full option name
+ # and its value (if any). If there was no "=" in the option, the
+ # value will be empty.
+ if process in [ RULENAMES $(module-name) ]
+ {
+ dont-build += [ modules.call-in $(module-name) : process
+ --$(full-name) : $(values) ] ;
+ }
+ }
+ }
+ }
+
+ return $(dont-build) ;
+}
diff --git a/tools/build/v2/util/option.py b/tools/build/v2/util/option.py
new file mode 100644
index 0000000000..47d6abdff6
--- /dev/null
+++ b/tools/build/v2/util/option.py
@@ -0,0 +1,35 @@
+# Copyright (c) 2005-2010 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import sys
+import re
+import b2.util.regex
+
+options = {}
+
+# Set a value for a named option, to be used when not overridden on the command
+# line.
+def set(name, value=None):
+
+ global options
+
+ options[name] = value
+
+def get(name, default_value=None, implied_value=None):
+
+ global options
+
+ matches = b2.util.regex.transform(sys.argv, "--" + re.escape(name) + "=(.*)")
+ if matches:
+ return matches[-1]
+ else:
+ m = b2.util.regex.transform(sys.argv, "--(" + re.escape(name) + ")")
+ if m and implied_value:
+ return implied_value
+ elif options.has_key(name) and options[name] != None:
+ return options[name]
+ else:
+ return default_value
diff --git a/tools/build/v2/util/order.jam b/tools/build/v2/util/order.jam
new file mode 100644
index 0000000000..a74fc8c849
--- /dev/null
+++ b/tools/build/v2/util/order.jam
@@ -0,0 +1,169 @@
+# Copyright (C) 2003 Vladimir Prus
+# Use, modification, and distribution is subject to the Boost Software
+# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
+# at http://www.boost.org/LICENSE_1_0.txt)
+
+# This module defines a class which allows to order arbitrary object with
+# regard to arbitrary binary relation.
+#
+# The primary use case is the gcc toolset, which is sensitive to library order:
+# if library 'a' uses symbols from library 'b', then 'a' must be present before
+# 'b' on the linker's command line.
+#
+# This requirement can be lifted for gcc with GNU ld, but for gcc with Solaris
+# LD (and for Solaris toolset as well), the order always matters.
+#
+# So, we need to store order requirements and then order libraries according to
+# them. It is not possible to use the dependency graph as order requirements.
+# What we need is a "use symbols" relationship while dependency graph provides
+# the "needs to be updated" relationship.
+#
+# For example::
+# lib a : a.cpp b;
+# lib b ;
+#
+# For static linking, library 'a' need not depend on 'b'. However, it should
+# still come before 'b' on the command line.
+
+class order
+{
+ rule __init__ ( )
+ {
+ }
+
+ # Adds the constraint that 'first' should preceede 'second'.
+ rule add-pair ( first second )
+ {
+ .constraits += $(first)--$(second) ;
+ }
+ NATIVE_RULE class@order : add-pair ;
+
+ # Given a list of objects, reorder them so that the constraints specified by
+ # 'add-pair' are satisfied.
+ #
+ # The algorithm was adopted from an awk script by Nikita Youshchenko
+ # (yoush at cs dot msu dot su)
+ rule order ( objects * )
+ {
+ # The algorithm used is the same is standard transitive closure, except
+ # that we're not keeping in-degree for all vertices, but rather removing
+ # edges.
+ local result ;
+ if $(objects)
+ {
+ local constraints = [ eliminate-unused-constraits $(objects) ] ;
+
+ # Find some library that nobody depends upon and add it to the
+ # 'result' array.
+ local obj ;
+ while $(objects)
+ {
+ local new_objects ;
+ while $(objects)
+ {
+ obj = $(objects[1]) ;
+ if [ has-no-dependents $(obj) : $(constraints) ]
+ {
+ # Emulate break ;
+ new_objects += $(objects[2-]) ;
+ objects = ;
+ }
+ else
+ {
+ new_objects += $(obj) ;
+ obj = ;
+ objects = $(objects[2-]) ;
+ }
+ }
+
+ if ! $(obj)
+ {
+ errors.error "Circular order dependencies" ;
+ }
+ # No problem with placing first.
+ result += $(obj) ;
+ # Remove all contraints where 'obj' comes first, since they are
+ # already satisfied.
+ constraints = [ remove-satisfied $(constraints) : $(obj) ] ;
+
+ # Add the remaining objects for further processing on the next
+ # iteration
+ objects = $(new_objects) ;
+ }
+
+ }
+ return $(result) ;
+ }
+ NATIVE_RULE class@order : order ;
+
+ # Eliminate constraints which mention objects not in 'objects'. In
+ # graph-theory terms, this is finding a subgraph induced by ordered
+ # vertices.
+ rule eliminate-unused-constraits ( objects * )
+ {
+ local result ;
+ for local c in $(.constraints)
+ {
+ local m = [ MATCH (.*)--(.*) : $(c) ] ;
+ if $(m[1]) in $(objects) && $(m[2]) in $(objects)
+ {
+ result += $(c) ;
+ }
+ }
+ return $(result) ;
+ }
+
+ # Returns true if there's no constraint in 'constaraints' where 'obj' comes
+ # second.
+ rule has-no-dependents ( obj : constraints * )
+ {
+ local failed ;
+ while $(constraints) && ! $(failed)
+ {
+ local c = $(constraints[1]) ;
+ local m = [ MATCH (.*)--(.*) : $(c) ] ;
+ if $(m[2]) = $(obj)
+ {
+ failed = true ;
+ }
+ constraints = $(constraints[2-]) ;
+ }
+ if ! $(failed)
+ {
+ return true ;
+ }
+ }
+
+ rule remove-satisfied ( constraints * : obj )
+ {
+ local result ;
+ for local c in $(constraints)
+ {
+ local m = [ MATCH (.*)--(.*) : $(c) ] ;
+ if $(m[1]) != $(obj)
+ {
+ result += $(c) ;
+ }
+ }
+ return $(result) ;
+ }
+}
+
+
+rule __test__ ( )
+{
+ import "class" : new ;
+ import assert ;
+
+ c1 = [ new order ] ;
+ $(c1).add-pair l1 l2 ;
+
+ assert.result l1 l2 : $(c1).order l1 l2 ;
+ assert.result l1 l2 : $(c1).order l2 l1 ;
+
+ $(c1).add-pair l2 l3 ;
+ assert.result l1 l2 : $(c1).order l2 l1 ;
+ $(c1).add-pair x l2 ;
+ assert.result l1 l2 : $(c1).order l2 l1 ;
+ assert.result l1 l2 l3 : $(c1).order l2 l3 l1 ;
+}
diff --git a/tools/build/v2/util/order.py b/tools/build/v2/util/order.py
new file mode 100644
index 0000000000..4e67b3f1a1
--- /dev/null
+++ b/tools/build/v2/util/order.py
@@ -0,0 +1,121 @@
+# Copyright (C) 2003 Vladimir Prus
+# Use, modification, and distribution is subject to the Boost Software
+# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
+# at http://www.boost.org/LICENSE_1_0.txt)
+
+class Order:
+ """Allows ordering arbitrary objects with regard to arbitrary binary relation.
+
+ The primary use case is the gcc toolset, which is sensitive to
+ library order: if library 'a' uses symbols from library 'b',
+ then 'a' must be present before 'b' on the linker's command line.
+
+ This requirement can be lifted for gcc with GNU ld, but for gcc with
+ Solaris LD (and for Solaris toolset as well), the order always matters.
+
+ So, we need to store order requirements and then order libraries
+ according to them. It it not possible to use dependency graph as
+ order requirements. What we need is "use symbols" relationship
+ while dependency graph provides "needs to be updated" relationship.
+
+ For example::
+ lib a : a.cpp b;
+ lib b ;
+
+ For static linking, the 'a' library need not depend on 'b'. However, it
+ still should come before 'b' on the command line.
+ """
+
+ def __init__ (self):
+ self.constraints_ = []
+
+ def add_pair (self, first, second):
+ """ Adds the constraint that 'first' should precede 'second'.
+ """
+ self.constraints_.append ((first, second))
+
+ def order (self, objects):
+ """ Given a list of objects, reorder them so that the constains specified
+ by 'add_pair' are satisfied.
+
+ The algorithm was adopted from an awk script by Nikita Youshchenko
+ (yoush at cs dot msu dot su)
+ """
+ # The algorithm used is the same is standard transitive closure,
+ # except that we're not keeping in-degree for all vertices, but
+ # rather removing edges.
+ result = []
+
+ if not objects:
+ return result
+
+ constraints = self.__eliminate_unused_constraits (objects)
+
+ # Find some library that nobody depends upon and add it to
+ # the 'result' array.
+ obj = None
+ while objects:
+ new_objects = []
+ while objects:
+ obj = objects [0]
+
+ if self.__has_no_dependents (obj, constraints):
+ # Emulate break ;
+ new_objects.extend (objects [1:])
+ objects = []
+
+ else:
+ new_objects.append (obj)
+ obj = None
+ objects = objects [1:]
+
+ if not obj:
+ raise BaseException ("Circular order dependencies")
+
+ # No problem with placing first.
+ result.append (obj)
+
+ # Remove all containts where 'obj' comes first,
+ # since they are already satisfied.
+ constraints = self.__remove_satisfied (constraints, obj)
+
+ # Add the remaining objects for further processing
+ # on the next iteration
+ objects = new_objects
+
+ return result
+
+ def __eliminate_unused_constraits (self, objects):
+ """ Eliminate constraints which mention objects not in 'objects'.
+ In graph-theory terms, this is finding subgraph induced by
+ ordered vertices.
+ """
+ result = []
+ for c in self.constraints_:
+ if c [0] in objects and c [1] in objects:
+ result.append (c)
+
+ return result
+
+ def __has_no_dependents (self, obj, constraints):
+ """ Returns true if there's no constraint in 'constraints' where
+ 'obj' comes second.
+ """
+ failed = False
+ while constraints and not failed:
+ c = constraints [0]
+
+ if c [1] == obj:
+ failed = True
+
+ constraints = constraints [1:]
+
+ return not failed
+
+ def __remove_satisfied (self, constraints, obj):
+ result = []
+ for c in constraints:
+ if c [0] != obj:
+ result.append (c)
+
+ return result
diff --git a/tools/build/v2/util/os.jam b/tools/build/v2/util/os.jam
new file mode 100644
index 0000000000..daef27f77f
--- /dev/null
+++ b/tools/build/v2/util/os.jam
@@ -0,0 +1,171 @@
+# Copyright 2001, 2002, 2003, 2005 Dave Abrahams
+# Copyright 2006 Rene Rivera
+# Copyright 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import modules ;
+import string ;
+
+
+# Return the value(s) of the given environment variable(s) at the time bjam was
+# invoked.
+rule environ ( variable-names + )
+{
+ return [ modules.peek .ENVIRON : $(variable-names) ] ;
+}
+
+.name = [ modules.peek : OS ] ;
+.platform = [ modules.peek : OSPLAT ] ;
+.version = [ modules.peek : OSVER ] ;
+
+
+local rule constant ( c : os ? )
+{
+ os ?= $(.name) ;
+ # First look for a platform-specific name, then the general value.
+ local variables = .$(c)-$(os) .$(c) ;
+ local result = $($(variables)) ;
+ return $(result[1]) ;
+}
+
+rule get-constant ( os ? )
+{
+ # Find the name of the constant being accessed, which is equal to the name
+ # used to invoke us.
+ local bt = [ BACKTRACE 1 ] ;
+ local rulename = [ MATCH ([^.]*)$ : $(bt[4]) ] ;
+ return [ constant $(rulename) : $(os) ] ;
+}
+
+
+# export all the common constants
+.constants = name platform version shared-library-path-variable path-separator executable-path-variable executable-suffix ;
+for local constant in $(.constants)
+{
+ IMPORT $(__name__) : get-constant : $(__name__) : $(constant) ;
+}
+EXPORT $(__name__) : $(.constants) ;
+
+.executable-path-variable-NT = PATH ;
+# On Windows the case and capitalization of PATH is not always predictable, so
+# let's find out what variable name was really set.
+if $(.name) = NT
+{
+ for local n in [ VARNAMES .ENVIRON ]
+ {
+ if $(n:L) = path
+ {
+ .executable-path-variable-NT = $(n) ;
+ }
+ }
+}
+
+# Specific constants for various platforms. There's no need to define any
+# constant whose value would be the same as the default, below.
+.shared-library-path-variable-NT = $(.executable-path-variable-NT) ;
+.path-separator-NT = ";" ;
+.expand-variable-prefix-NT = % ;
+.expand-variable-suffix-NT = % ;
+.executable-suffix-NT = .exe ;
+
+.shared-library-path-variable-CYGWIN = PATH ;
+
+.shared-library-path-variable-MACOSX = DYLD_LIBRARY_PATH ;
+
+.shared-library-path-variable-AIX = LIBPATH ;
+
+# Default constants
+.shared-library-path-variable = LD_LIBRARY_PATH ;
+.path-separator = ":" ;
+.expand-variable-prefix = $ ;
+.expand-variable-suffix = "" ;
+.executable-path-variable = PATH ;
+.executable-suffix = "" ;
+
+
+# Return a list of the directories in the PATH. Yes, that information is (sort
+# of) available in the global module, but jam code can change those values, and
+# it isn't always clear what case/capitalization to use when looking. This rule
+# is a more reliable way to get there.
+rule executable-path ( )
+{
+ return [ string.words [ environ [ constant executable-path-variable ] ]
+ : [ constant path-separator ] ] ;
+}
+
+
+# Initialize the list of home directories for the current user depending on the
+# OS.
+if $(.name) = NT
+{
+ local home = [ environ HOMEDRIVE HOMEPATH ] ;
+ .home-directories = $(home[1])$(home[2]) [ environ HOME ] [ environ USERPROFILE ] ;
+}
+else
+{
+ .home-directories = [ environ HOME ] ;
+}
+
+
+# Can't use 'constant' mechanism because it only returns 1-element values.
+rule home-directories ( )
+{
+ return $(.home-directories) ;
+}
+
+
+# Return the string needed to represent the expansion of the named shell
+# variable.
+rule expand-variable ( variable )
+{
+ local prefix = [ constant expand-variable-prefix ] ;
+ local suffix = [ constant expand-variable-suffix ] ;
+ return $(prefix)$(variable)$(suffix) ;
+}
+
+
+# Returns true if running on windows, whether in cygwin or not.
+rule on-windows ( )
+{
+ local result ;
+ if [ modules.peek : NT ]
+ {
+ result = true ;
+ }
+ else if [ modules.peek : UNIX ]
+ {
+ switch [ modules.peek : JAMUNAME ]
+ {
+ case CYGWIN* :
+ {
+ result = true ;
+ }
+ }
+ }
+ return $(result) ;
+}
+
+
+if ! [ on-windows ]
+{
+ .on-unix = 1 ;
+}
+
+
+rule on-unix
+{
+ return $(.on-unix) ;
+}
+
+
+rule __test__
+{
+ import assert ;
+ if ! ( --quiet in [ modules.peek : ARGV ] )
+ {
+ ECHO os: name= [ name ] ;
+ ECHO os: version= [ version ] ;
+ }
+ assert.true name ;
+}
diff --git a/tools/build/v2/util/os_j.py b/tools/build/v2/util/os_j.py
new file mode 100644
index 0000000000..f44cca6201
--- /dev/null
+++ b/tools/build/v2/util/os_j.py
@@ -0,0 +1,19 @@
+# Status: stub, just enough to make tests work.
+#
+# Named os_j to avoid conflicts with standard 'os'. See
+# project.py:import for special-casing.
+#
+# Copyright 2001, 2002, 2003, 2005 Dave Abrahams
+# Copyright 2006 Rene Rivera
+# Copyright 2003, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import bjam
+
+__OS = bjam.call("peek", [], "OS")[0]
+
+# Return Jam's name of OS to prevent existing code from burning
+# when faced with Python naming
+def name():
+ return __OS
diff --git a/tools/build/v2/util/path.jam b/tools/build/v2/util/path.jam
new file mode 100644
index 0000000000..ea26b816bc
--- /dev/null
+++ b/tools/build/v2/util/path.jam
@@ -0,0 +1,934 @@
+# Copyright Vladimir Prus 2002-2006.
+# Copyright Dave Abrahams 2003-2004.
+# Copyright Rene Rivera 2003-2006.
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Performs various path manipulations. Paths are always in a 'normalized'
+# representation. In it, a path may be either:
+#
+# - '.', or
+#
+# - ['/'] [ ( '..' '/' )* (token '/')* token ]
+#
+# In plain english, path can be rooted, '..' elements are allowed only at the
+# beginning, and it never ends in slash, except for path consisting of slash
+# only.
+
+import errors ;
+import modules ;
+import regex ;
+import sequence ;
+import set ;
+import version ;
+
+
+os = [ modules.peek : OS ] ;
+if [ modules.peek : UNIX ]
+{
+ local uname = [ modules.peek : JAMUNAME ] ;
+ switch $(uname)
+ {
+ case CYGWIN* : os = CYGWIN ;
+ case * : os = UNIX ;
+ }
+}
+
+
+# Converts the native path into normalized form.
+#
+rule make ( native )
+{
+ return [ make-$(os) $(native) ] ;
+}
+
+
+# Builds native representation of the path.
+#
+rule native ( path )
+{
+ return [ native-$(os) $(path) ] ;
+}
+
+
+# Tests if a path is rooted.
+#
+rule is-rooted ( path )
+{
+ return [ MATCH "^(/)" : $(path) ] ;
+}
+
+
+# Tests if a path has a parent.
+#
+rule has-parent ( path )
+{
+ if $(path) != /
+ {
+ return 1 ;
+ }
+ else
+ {
+ return ;
+ }
+}
+
+
+# Returns the path without any directory components.
+#
+rule basename ( path )
+{
+ return [ MATCH "([^/]+)$" : $(path) ] ;
+}
+
+
+# Returns parent directory of the path. If no parent exists, error is issued.
+#
+rule parent ( path )
+{
+ if [ has-parent $(path) ]
+ {
+ if $(path) = .
+ {
+ return .. ;
+ }
+ else
+ {
+ # Strip everything at the end of path up to and including the last
+ # slash.
+ local result = [ regex.match "((.*)/)?([^/]+)" : $(path) : 2 3 ] ;
+
+ # Did we strip what we shouldn't?
+ if $(result[2]) = ".."
+ {
+ return $(path)/.. ;
+ }
+ else
+ {
+ if ! $(result[1])
+ {
+ if [ is-rooted $(path) ]
+ {
+ result = / ;
+ }
+ else
+ {
+ result = . ;
+ }
+ }
+ return $(result[1]) ;
+ }
+ }
+ }
+ else
+ {
+ errors.error "Path '$(path)' has no parent" ;
+ }
+}
+
+
+# Returns path2 such that "[ join path path2 ] = .". The path may not contain
+# ".." element or be rooted.
+#
+rule reverse ( path )
+{
+ if $(path) = .
+ {
+ return $(path) ;
+ }
+ else
+ {
+ local tokens = [ regex.split $(path) "/" ] ;
+ local tokens2 ;
+ for local i in $(tokens)
+ {
+ tokens2 += .. ;
+ }
+ return [ sequence.join $(tokens2) : "/" ] ;
+ }
+}
+
+
+# Concatenates the passed path elements. Generates an error if any element other
+# than the first one is rooted. Skips any empty or undefined path elements.
+#
+rule join ( elements + )
+{
+ if ! $(elements[2-])
+ {
+ return $(elements[1]) ;
+ }
+ else
+ {
+ for local e in $(elements[2-])
+ {
+ if [ is-rooted $(e) ]
+ {
+ errors.error only the first element may be rooted ;
+ }
+ }
+ if [ version.check-jam-version 3 1 17 ]
+ {
+ return [ NORMALIZE_PATH "$(elements)" ] ;
+ }
+ else
+ {
+ # Boost Jam prior to version 3.1.17 had problems with its
+ # NORMALIZE_PATH rule in case you passed it a leading backslash
+ # instead of a slash, in some cases when you sent it an empty
+ # initial path element and possibly some others. At least some of
+ # those cases were being hit and relied upon when calling this rule
+ # from the path.make-NT rule.
+ if ! $(elements[1]) && $(elements[2])
+ {
+ return [ NORMALIZE_PATH "/" "$(elements[2-])" ] ;
+ }
+ else
+ {
+ return [ NORMALIZE_PATH "$(elements)" ] ;
+ }
+ }
+ }
+}
+
+
+# If 'path' is relative, it is rooted at 'root'. Otherwise, it is unchanged.
+#
+rule root ( path root )
+{
+ if [ is-rooted $(path) ]
+ {
+ return $(path) ;
+ }
+ else
+ {
+ return [ join $(root) $(path) ] ;
+ }
+}
+
+
+# Returns the current working directory.
+#
+rule pwd ( )
+{
+ if ! $(.pwd)
+ {
+ .pwd = [ make [ PWD ] ] ;
+ }
+ return $(.pwd) ;
+}
+
+
+# Returns the list of files matching the given pattern in the specified
+# directory. Both directories and patterns are supplied as portable paths. Each
+# pattern should be non-absolute path, and can't contain "." or ".." elements.
+# Each slash separated element of pattern can contain the following special
+# characters:
+# - '?', which match any character
+# - '*', which matches arbitrary number of characters.
+# A file $(d)/e1/e2/e3 (where 'd' is in $(dirs)) matches pattern p1/p2/p3 if and
+# only if e1 matches p1, e2 matches p2 and so on.
+#
+# For example:
+# [ glob . : *.cpp ]
+# [ glob . : */build/Jamfile ]
+#
+rule glob ( dirs * : patterns + : exclude-patterns * )
+{
+ local result ;
+ local real-patterns ;
+ local real-exclude-patterns ;
+ for local d in $(dirs)
+ {
+ for local p in $(patterns)
+ {
+ local pattern = [ path.root $(p) $(d) ] ;
+ real-patterns += [ path.native $(pattern) ] ;
+ }
+
+ for local p in $(exclude-patterns)
+ {
+ local pattern = [ path.root $(p) $(d) ] ;
+ real-exclude-patterns += [ path.native $(pattern) ] ;
+ }
+ }
+
+ local inc = [ GLOB-RECURSIVELY $(real-patterns) ] ;
+ inc = [ sequence.transform NORMALIZE_PATH : $(inc) ] ;
+ local exc = [ GLOB-RECURSIVELY $(real-exclude-patterns) ] ;
+ exc = [ sequence.transform NORMALIZE_PATH : $(exc) ] ;
+
+ return [ sequence.transform path.make : [ set.difference $(inc) : $(exc) ] ]
+ ;
+}
+
+
+# Recursive version of GLOB. Builds the glob of files while also searching in
+# the subdirectories of the given roots. An optional set of exclusion patterns
+# will filter out the matching entries from the result. The exclusions also
+# apply to the subdirectory scanning, such that directories that match the
+# exclusion patterns will not be searched.
+#
+rule glob-tree ( roots * : patterns + : exclude-patterns * )
+{
+ return [ sequence.transform path.make : [ .glob-tree [ sequence.transform
+ path.native : $(roots) ] : $(patterns) : $(exclude-patterns) ] ] ;
+}
+
+
+local rule .glob-tree ( roots * : patterns * : exclude-patterns * )
+{
+ local excluded ;
+ if $(exclude-patterns)
+ {
+ excluded = [ GLOB $(roots) : $(exclude-patterns) ] ;
+ }
+ local result = [ set.difference [ GLOB $(roots) : $(patterns) ] :
+ $(excluded) ] ;
+ local subdirs ;
+ for local d in [ set.difference [ GLOB $(roots) : * ] : $(excluded) ]
+ {
+ if ! ( $(d:D=) in . .. ) && ! [ CHECK_IF_FILE $(d) ]
+ {
+ subdirs += $(d) ;
+ }
+ }
+ if $(subdirs)
+ {
+ result += [ .glob-tree $(subdirs) : $(patterns) : $(exclude-patterns) ]
+ ;
+ }
+ return $(result) ;
+}
+
+
+# Returns true is the specified file exists.
+#
+rule exists ( file )
+{
+ return [ path.glob $(file:D) : $(file:D=) ] ;
+}
+NATIVE_RULE path : exists ;
+
+
+# Find out the absolute name of path and returns the list of all the parents,
+# starting with the immediate one. Parents are returned as relative names. If
+# 'upper_limit' is specified, directories above it will be pruned.
+#
+rule all-parents ( path : upper_limit ? : cwd ? )
+{
+ cwd ?= [ pwd ] ;
+ local path_ele = [ regex.split [ root $(path) $(cwd) ] "/" ] ;
+
+ if ! $(upper_limit)
+ {
+ upper_limit = / ;
+ }
+ local upper_ele = [ regex.split [ root $(upper_limit) $(cwd) ] "/" ] ;
+
+ # Leave only elements in 'path_ele' below 'upper_ele'.
+ while $(path_ele) && ( $(upper_ele[1]) = $(path_ele[1]) )
+ {
+ upper_ele = $(upper_ele[2-]) ;
+ path_ele = $(path_ele[2-]) ;
+ }
+
+ # Have all upper elements been removed ?
+ if $(upper_ele)
+ {
+ errors.error "$(upper_limit) is not prefix of $(path)" ;
+ }
+
+ # Create the relative paths to parents, number of elements in 'path_ele'.
+ local result ;
+ for local i in $(path_ele)
+ {
+ path = [ parent $(path) ] ;
+ result += $(path) ;
+ }
+ return $(result) ;
+}
+
+
+# Search for 'pattern' in parent directories of 'dir', up till and including
+# 'upper_limit', if it is specified, or till the filesystem root otherwise.
+#
+rule glob-in-parents ( dir : patterns + : upper-limit ? )
+{
+ local result ;
+ local parent-dirs = [ all-parents $(dir) : $(upper-limit) ] ;
+
+ while $(parent-dirs) && ! $(result)
+ {
+ result = [ glob $(parent-dirs[1]) : $(patterns) ] ;
+ parent-dirs = $(parent-dirs[2-]) ;
+ }
+ return $(result) ;
+}
+
+
+# Assuming 'child' is a subdirectory of 'parent', return the relative path from
+# 'parent' to 'child'.
+#
+rule relative ( child parent : no-error ? )
+{
+ local not-a-child ;
+ if $(parent) = "."
+ {
+ return $(child) ;
+ }
+ else
+ {
+ local split1 = [ regex.split $(parent) / ] ;
+ local split2 = [ regex.split $(child) / ] ;
+
+ while $(split1)
+ {
+ if $(split1[1]) = $(split2[1])
+ {
+ split1 = $(split1[2-]) ;
+ split2 = $(split2[2-]) ;
+ }
+ else
+ {
+ not-a-child = true ;
+ split1 = ;
+ }
+ }
+ if $(split2)
+ {
+ if $(not-a-child)
+ {
+ if $(no-error)
+ {
+ return not-a-child ;
+ }
+ else
+ {
+ errors.error $(child) is not a subdir of $(parent) ;
+ }
+ }
+ else
+ {
+ return [ join $(split2) ] ;
+ }
+ }
+ else
+ {
+ return "." ;
+ }
+ }
+}
+
+
+# Returns the minimal path to path2 that is relative path1.
+#
+rule relative-to ( path1 path2 )
+{
+ local root_1 = [ regex.split [ reverse $(path1) ] / ] ;
+ local split1 = [ regex.split $(path1) / ] ;
+ local split2 = [ regex.split $(path2) / ] ;
+
+ while $(split1) && $(root_1)
+ {
+ if $(split1[1]) = $(split2[1])
+ {
+ root_1 = $(root_1[2-]) ;
+ split1 = $(split1[2-]) ;
+ split2 = $(split2[2-]) ;
+ }
+ else
+ {
+ split1 = ;
+ }
+ }
+ return [ join . $(root_1) $(split2) ] ;
+}
+
+
+# Returns the list of paths which are used by the operating system for looking
+# up programs.
+#
+rule programs-path ( )
+{
+ local result ;
+ local raw = [ modules.peek : PATH Path path ] ;
+ for local p in $(raw)
+ {
+ if $(p)
+ {
+ result += [ path.make $(p) ] ;
+ }
+ }
+ return $(result) ;
+}
+
+rule makedirs ( path )
+{
+ local result = true ;
+ local native = [ native $(path) ] ;
+ if ! [ exists $(native) ]
+ {
+ if [ makedirs [ parent $(path) ] ]
+ {
+ if ! [ MAKEDIR $(native) ]
+ {
+ errors.error "Could not create directory '$(path)'" ;
+ result = ;
+ }
+ }
+ }
+ return $(result) ;
+}
+
+# Converts native Windows paths into our internal canonic path representation.
+# Supports 'invalid' paths containing multiple successive path separator
+# characters.
+#
+# TODO: Check and if needed add support for Windows 'X:file' path format where
+# the file is located in the current folder on drive X.
+#
+rule make-NT ( native )
+{
+ local result ;
+
+ if [ version.check-jam-version 3 1 17 ]
+ {
+ result = [ NORMALIZE_PATH $(native) ] ;
+ }
+ else
+ {
+ # This old implementation is really fragile due to a not so clear way
+ # NORMALIZE_PATH rule worked in Boost.Jam versions prior to 3.1.17. E.g.
+ # path.join would mostly ignore empty path elements but would root the
+ # joined path in case the initial two path elements were empty or some
+ # similar accidental wierdness.
+ result = [ path.join [ regex.split $(native) "[/\\]" ] ] ;
+ }
+
+ # We need to add an extra '/' in front in case this is a rooted Windows path
+ # starting with a drive letter and not a path separator character since the
+ # builtin NORMALIZE_PATH rule has no knowledge of this leading drive letter
+ # and treats it as a regular folder name.
+ if [ regex.match "(^.:)" : $(native) ]
+ {
+ result = /$(result) ;
+ }
+
+ return $(result) ;
+}
+
+
+rule native-NT ( path )
+{
+ local result ;
+ if [ is-rooted $(path) ] && ! [ regex.match "^/(.:)" : $(path) ]
+ {
+ result = $(path) ;
+ }
+ else
+ {
+ result = [ MATCH "^/?(.*)" : $(path) ] ;
+ }
+ result = [ sequence.join [ regex.split $(result) "/" ] : "\\" ] ;
+ return $(result) ;
+}
+
+
+rule make-UNIX ( native )
+{
+ # VP: I have no idea now 'native' can be empty here! But it can!
+ if ! $(native)
+ {
+ errors.error "Empty path passed to 'make-UNIX'" ;
+ }
+ else
+ {
+ return [ NORMALIZE_PATH $(native:T) ] ;
+ }
+}
+
+
+rule native-UNIX ( path )
+{
+ return $(path) ;
+}
+
+
+rule make-CYGWIN ( path )
+{
+ return [ make-NT $(path) ] ;
+}
+
+
+rule native-CYGWIN ( path )
+{
+ local result = $(path) ;
+ if [ regex.match "(^/.:)" : $(path) ] # Windows absolute path.
+ {
+ result = [ MATCH "^/?(.*)" : $(path) ] ; # Remove leading '/'.
+ }
+ return [ native-UNIX $(result) ] ;
+}
+
+
+# split-path-VMS: splits input native path into device dir file (each part is
+# optional).
+#
+# example:
+#
+# dev:[dir]file.c => dev: [dir] file.c
+#
+rule split-path-VMS ( native )
+{
+ local matches = [ MATCH ([a-zA-Z0-9_-]+:)?(\\[[^\]]*\\])?(.*)?$ : $(native) ] ;
+ local device = $(matches[1]) ;
+ local dir = $(matches[2]) ;
+ local file = $(matches[3]) ;
+
+ return $(device) $(dir) $(file) ;
+}
+
+
+# Converts a native VMS path into a portable path spec.
+#
+# Does not handle current-device absolute paths such as "[dir]File.c" as it is
+# not clear how to represent them in the portable path notation.
+#
+# Adds a trailing dot (".") to the file part if no extension is present (helps
+# when converting it back into native path).
+#
+rule make-VMS ( native )
+{
+ if [ MATCH ^(\\[[a-zA-Z0-9]) : $(native) ]
+ {
+ errors.error "Can't handle default-device absolute paths: " $(native) ;
+ }
+
+ local parts = [ split-path-VMS $(native) ] ;
+ local device = $(parts[1]) ;
+ local dir = $(parts[2]) ;
+ local file = $(parts[3]) ;
+ local elems ;
+
+ if $(device)
+ {
+ #
+ # rooted
+ #
+ elems = /$(device) ;
+ }
+
+ if $(dir) = "[]"
+ {
+ #
+ # Special case: current directory
+ #
+ elems = $(elems) "." ;
+ }
+ else if $(dir)
+ {
+ dir = [ regex.replace $(dir) "\\[|\\]" "" ] ;
+ local dir_parts = [ regex.split $(dir) \\. ] ;
+
+ if $(dir_parts[1]) = ""
+ {
+ #
+ # Relative path
+ #
+ dir_parts = $(dir_parts[2--1]) ;
+ }
+
+ #
+ # replace "parent-directory" parts (- => ..)
+ #
+ dir_parts = [ regex.replace-list $(dir_parts) : - : .. ] ;
+
+ elems = $(elems) $(dir_parts) ;
+ }
+
+ if $(file)
+ {
+ if ! [ MATCH (\\.) : $(file) ]
+ {
+ #
+ # Always add "." to end of non-extension file.
+ #
+ file = $(file). ;
+ }
+ elems = $(elems) $(file) ;
+ }
+
+ local portable = [ path.join $(elems) ] ;
+
+ return $(portable) ;
+}
+
+
+# Converts a portable path spec into a native VMS path.
+#
+# Relies on having at least one dot (".") included in the file name to be able
+# to differentiate it from the directory part.
+#
+rule native-VMS ( path )
+{
+ local device = "" ;
+ local dir = $(path) ;
+ local file = "" ;
+ local native ;
+ local split ;
+
+ #
+ # Has device ?
+ #
+ if [ is-rooted $(dir) ]
+ {
+ split = [ MATCH ^/([^:]+:)/?(.*) : $(dir) ] ;
+ device = $(split[1]) ;
+ dir = $(split[2]) ;
+ }
+
+ #
+ # Has file ?
+ #
+ # This is no exact science, just guess work:
+ #
+ # If the last part of the current path spec
+ # includes some chars, followed by a dot,
+ # optionally followed by more chars -
+ # then it is a file (keep your fingers crossed).
+ #
+ split = [ regex.split $(dir) / ] ;
+ local maybe_file = $(split[-1]) ;
+
+ if [ MATCH ^([^.]+\\..*) : $(maybe_file) ]
+ {
+ file = $(maybe_file) ;
+ dir = [ sequence.join $(split[1--2]) : / ] ;
+ }
+
+ #
+ # Has dir spec ?
+ #
+ if $(dir) = "."
+ {
+ dir = "[]" ;
+ }
+ else if $(dir)
+ {
+ dir = [ regex.replace $(dir) \\.\\. - ] ;
+ dir = [ regex.replace $(dir) / . ] ;
+
+ if $(device) = ""
+ {
+ #
+ # Relative directory
+ #
+ dir = "."$(dir) ;
+ }
+ dir = "["$(dir)"]" ;
+ }
+
+ native = [ sequence.join $(device) $(dir) $(file) ] ;
+
+ return $(native) ;
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+ import errors : try catch ;
+
+ assert.true is-rooted "/" ;
+ assert.true is-rooted "/foo" ;
+ assert.true is-rooted "/foo/bar" ;
+ assert.result : is-rooted "." ;
+ assert.result : is-rooted "foo" ;
+ assert.result : is-rooted "foo/bar" ;
+
+ assert.true has-parent "foo" ;
+ assert.true has-parent "foo/bar" ;
+ assert.true has-parent "." ;
+ assert.result : has-parent "/" ;
+
+ assert.result "." : basename "." ;
+ assert.result ".." : basename ".." ;
+ assert.result "foo" : basename "foo" ;
+ assert.result "foo" : basename "bar/foo" ;
+ assert.result "foo" : basename "gaz/bar/foo" ;
+ assert.result "foo" : basename "/gaz/bar/foo" ;
+
+ assert.result "." : parent "foo" ;
+ assert.result "/" : parent "/foo" ;
+ assert.result "foo/bar" : parent "foo/bar/giz" ;
+ assert.result ".." : parent "." ;
+ assert.result ".." : parent "../foo" ;
+ assert.result "../../foo" : parent "../../foo/bar" ;
+
+ assert.result "." : reverse "." ;
+ assert.result ".." : reverse "foo" ;
+ assert.result "../../.." : reverse "foo/bar/giz" ;
+
+ assert.result "foo" : join "foo" ;
+ assert.result "/foo" : join "/" "foo" ;
+ assert.result "foo/bar" : join "foo" "bar" ;
+ assert.result "foo/bar" : join "foo/giz" "../bar" ;
+ assert.result "foo/giz" : join "foo/bar/baz" "../../giz" ;
+ assert.result ".." : join "." ".." ;
+ assert.result ".." : join "foo" "../.." ;
+ assert.result "../.." : join "../foo" "../.." ;
+ assert.result "/foo" : join "/bar" "../foo" ;
+ assert.result "foo/giz" : join "foo/giz" "." ;
+ assert.result "." : join lib2 ".." ;
+ assert.result "/" : join "/a" ".." ;
+
+ assert.result /a/b : join /a/b/c .. ;
+
+ assert.result "foo/bar/giz" : join "foo" "bar" "giz" ;
+ assert.result "giz" : join "foo" ".." "giz" ;
+ assert.result "foo/giz" : join "foo" "." "giz" ;
+
+ try ;
+ {
+ join "a" "/b" ;
+ }
+ catch only first element may be rooted ;
+
+ local CWD = "/home/ghost/build" ;
+ assert.result : all-parents . : . : $(CWD) ;
+ assert.result . .. ../.. ../../.. : all-parents "Jamfile" : "" : $(CWD) ;
+ assert.result foo . .. ../.. ../../.. : all-parents "foo/Jamfile" : "" : $(CWD) ;
+ assert.result ../Work .. ../.. ../../.. : all-parents "../Work/Jamfile" : "" : $(CWD) ;
+
+ local CWD = "/home/ghost" ;
+ assert.result . .. : all-parents "Jamfile" : "/home" : $(CWD) ;
+ assert.result . : all-parents "Jamfile" : "/home/ghost" : $(CWD) ;
+
+ assert.result "c/d" : relative "a/b/c/d" "a/b" ;
+ assert.result "foo" : relative "foo" "." ;
+
+ local save-os = [ modules.peek path : os ] ;
+ modules.poke path : os : NT ;
+
+ assert.result "foo/bar/giz" : make "foo/bar/giz" ;
+ assert.result "foo/bar/giz" : make "foo\\bar\\giz" ;
+ assert.result "foo" : make "foo/" ;
+ assert.result "foo" : make "foo\\" ;
+ assert.result "foo" : make "foo/." ;
+ assert.result "foo" : make "foo/bar/.." ;
+ assert.result "foo" : make "foo/bar/../" ;
+ assert.result "foo" : make "foo/bar/..\\" ;
+ assert.result "foo/bar" : make "foo/././././bar" ;
+ assert.result "/foo" : make "\\foo" ;
+ assert.result "/D:/My Documents" : make "D:\\My Documents" ;
+ assert.result "/c:/boost/tools/build/new/project.jam" : make "c:\\boost\\tools\\build\\test\\..\\new\\project.jam" ;
+
+ # Test processing 'invalid' paths containing multiple successive path
+ # separators.
+ assert.result "foo" : make "foo//" ;
+ assert.result "foo" : make "foo///" ;
+ assert.result "foo" : make "foo\\\\" ;
+ assert.result "foo" : make "foo\\\\\\" ;
+ assert.result "/foo" : make "//foo" ;
+ assert.result "/foo" : make "///foo" ;
+ assert.result "/foo" : make "\\\\foo" ;
+ assert.result "/foo" : make "\\\\\\foo" ;
+ assert.result "/foo" : make "\\/\\/foo" ;
+ assert.result "foo/bar" : make "foo//\\//\\\\bar//\\//\\\\\\//\\//\\\\" ;
+ assert.result "foo" : make "foo/bar//.." ;
+ assert.result "foo/bar" : make "foo/bar/giz//.." ;
+ assert.result "foo/giz" : make "foo//\\//\\\\bar///\\\\//\\\\////\\/..///giz\\//\\\\\\//\\//\\\\" ;
+ assert.result "../../../foo" : make "..///.//..///.//..////foo///" ;
+
+ # Test processing 'invalid' rooted paths with too many '..' path elements
+ # that would place them before the root.
+ assert.result : make "/.." ;
+ assert.result : make "/../" ;
+ assert.result : make "/../." ;
+ assert.result : make "/.././" ;
+ assert.result : make "/foo/../bar/giz/.././././../../." ;
+ assert.result : make "/foo/../bar/giz/.././././../.././" ;
+ assert.result : make "//foo/../bar/giz/.././././../../." ;
+ assert.result : make "//foo/../bar/giz/.././././../.././" ;
+ assert.result : make "\\\\foo/../bar/giz/.././././../../." ;
+ assert.result : make "\\\\foo/../bar/giz/.././././../.././" ;
+ assert.result : make "/..///.//..///.//..////foo///" ;
+
+ assert.result "foo\\bar\\giz" : native "foo/bar/giz" ;
+ assert.result "foo" : native "foo" ;
+ assert.result "\\foo" : native "/foo" ;
+ assert.result "D:\\My Documents\\Work" : native "/D:/My Documents/Work" ;
+
+ modules.poke path : os : UNIX ;
+
+ assert.result "foo/bar/giz" : make "foo/bar/giz" ;
+ assert.result "/sub1" : make "/sub1/." ;
+ assert.result "/sub1" : make "/sub1/sub2/.." ;
+ assert.result "sub1" : make "sub1/." ;
+ assert.result "sub1" : make "sub1/sub2/.." ;
+ assert.result "/foo/bar" : native "/foo/bar" ;
+
+ modules.poke path : os : VMS ;
+
+ #
+ # Don't really need to poke os before these
+ #
+ assert.result "disk:" "[dir]" "file" : split-path-VMS "disk:[dir]file" ;
+ assert.result "disk:" "[dir]" "" : split-path-VMS "disk:[dir]" ;
+ assert.result "disk:" "" "" : split-path-VMS "disk:" ;
+ assert.result "disk:" "" "file" : split-path-VMS "disk:file" ;
+ assert.result "" "[dir]" "file" : split-path-VMS "[dir]file" ;
+ assert.result "" "[dir]" "" : split-path-VMS "[dir]" ;
+ assert.result "" "" "file" : split-path-VMS "file" ;
+ assert.result "" "" "" : split-path-VMS "" ;
+
+ #
+ # Special case: current directory
+ #
+ assert.result "" "[]" "" : split-path-VMS "[]" ;
+ assert.result "disk:" "[]" "" : split-path-VMS "disk:[]" ;
+ assert.result "" "[]" "file" : split-path-VMS "[]file" ;
+ assert.result "disk:" "[]" "file" : split-path-VMS "disk:[]file" ;
+
+ #
+ # Make portable paths
+ #
+ assert.result "/disk:" : make "disk:" ;
+ assert.result "foo/bar/giz" : make "[.foo.bar.giz]" ;
+ assert.result "foo" : make "[.foo]" ;
+ assert.result "foo" : make "[.foo.bar.-]" ;
+ assert.result ".." : make "[.-]" ;
+ assert.result ".." : make "[-]" ;
+ assert.result "." : make "[]" ;
+ assert.result "giz.h" : make "giz.h" ;
+ assert.result "foo/bar/giz.h" : make "[.foo.bar]giz.h" ;
+ assert.result "/disk:/my_docs" : make "disk:[my_docs]" ;
+ assert.result "/disk:/boost/tools/build/new/project.jam" : make "disk:[boost.tools.build.test.-.new]project.jam" ;
+
+ #
+ # Special case (adds '.' to end of file w/o extension to
+ # disambiguate from directory in portable path spec).
+ #
+ assert.result "Jamfile." : make "Jamfile" ;
+ assert.result "dir/Jamfile." : make "[.dir]Jamfile" ;
+ assert.result "/disk:/dir/Jamfile." : make "disk:[dir]Jamfile" ;
+
+ #
+ # Make native paths
+ #
+ assert.result "disk:" : native "/disk:" ;
+ assert.result "[.foo.bar.giz]" : native "foo/bar/giz" ;
+ assert.result "[.foo]" : native "foo" ;
+ assert.result "[.-]" : native ".." ;
+ assert.result "[.foo.-]" : native "foo/.." ;
+ assert.result "[]" : native "." ;
+ assert.result "disk:[my_docs.work]" : native "/disk:/my_docs/work" ;
+ assert.result "giz.h" : native "giz.h" ;
+ assert.result "disk:Jamfile." : native "/disk:Jamfile." ;
+ assert.result "disk:[my_docs.work]Jamfile." : native "/disk:/my_docs/work/Jamfile." ;
+
+ modules.poke path : os : $(save-os) ;
+}
diff --git a/tools/build/v2/util/path.py b/tools/build/v2/util/path.py
new file mode 100644
index 0000000000..222b96bfe2
--- /dev/null
+++ b/tools/build/v2/util/path.py
@@ -0,0 +1,904 @@
+# Status: this module is ported on demand by however needs something
+# from it. Functionality that is not needed by Python port will
+# be dropped.
+
+# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+# Performs various path manipulations. Path are always in a 'normilized'
+# representation. In it, a path may be either:
+#
+# - '.', or
+#
+# - ['/'] [ ( '..' '/' )* (token '/')* token ]
+#
+# In plain english, path can be rooted, '..' elements are allowed only
+# at the beginning, and it never ends in slash, except for path consisting
+# of slash only.
+
+import os.path
+from utility import to_seq
+from glob import glob as builtin_glob
+
+from b2.util import bjam_signature
+
+@bjam_signature((["path", "root"],))
+def root (path, root):
+ """ If 'path' is relative, it is rooted at 'root'. Otherwise, it's unchanged.
+ """
+ if os.path.isabs (path):
+ return path
+ else:
+ return os.path.join (root, path)
+
+@bjam_signature((["native"],))
+def make (native):
+ """ Converts the native path into normalized form.
+ """
+ # TODO: make os selection here.
+ return make_UNIX (native)
+
+def make_UNIX (native):
+
+ # VP: I have no idea now 'native' can be empty here! But it can!
+ assert (native)
+
+ return os.path.normpath (native)
+
+@bjam_signature((["path"],))
+def native (path):
+ """ Builds a native representation of the path.
+ """
+ # TODO: make os selection here.
+ return native_UNIX (path)
+
+def native_UNIX (path):
+ return path
+
+
+def pwd ():
+ """ Returns the current working directory.
+ # TODO: is it a good idea to use the current dir? Some use-cases
+ may not allow us to depend on the current dir.
+ """
+ return make (os.getcwd ())
+
+def is_rooted (path):
+ """ Tests if a path is rooted.
+ """
+ return path and path [0] == '/'
+
+
+###################################################################
+# Still to port.
+# Original lines are prefixed with "# "
+#
+# # Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
+# # distribute this software is granted provided this copyright notice appears in
+# # all copies. This software is provided "as is" without express or implied
+# # warranty, and with no claim as to its suitability for any purpose.
+#
+# # Performs various path manipulations. Path are always in a 'normilized'
+# # representation. In it, a path may be either:
+# #
+# # - '.', or
+# #
+# # - ['/'] [ ( '..' '/' )* (token '/')* token ]
+# #
+# # In plain english, path can be rooted, '..' elements are allowed only
+# # at the beginning, and it never ends in slash, except for path consisting
+# # of slash only.
+#
+# import modules ;
+# import sequence ;
+# import regex ;
+# import errors : error ;
+#
+#
+# os = [ modules.peek : OS ] ;
+# if [ modules.peek : UNIX ]
+# {
+# local uname = [ modules.peek : JAMUNAME ] ;
+# switch $(uname)
+# {
+# case CYGWIN* :
+# os = CYGWIN ;
+#
+# case * :
+# os = UNIX ;
+# }
+# }
+#
+# #
+# # Tests if a path is rooted.
+# #
+# rule is-rooted ( path )
+# {
+# return [ MATCH "^(/)" : $(path) ] ;
+# }
+#
+# #
+# # Tests if a path has a parent.
+# #
+# rule has-parent ( path )
+# {
+# if $(path) != / {
+# return 1 ;
+# } else {
+# return ;
+# }
+# }
+#
+# #
+# # Returns the path without any directory components.
+# #
+# rule basename ( path )
+# {
+# return [ MATCH "([^/]+)$" : $(path) ] ;
+# }
+#
+# #
+# # Returns parent directory of the path. If no parent exists, error is issued.
+# #
+# rule parent ( path )
+# {
+# if [ has-parent $(path) ] {
+#
+# if $(path) = . {
+# return .. ;
+# } else {
+#
+# # Strip everything at the end of path up to and including
+# # the last slash
+# local result = [ regex.match "((.*)/)?([^/]+)" : $(path) : 2 3 ] ;
+#
+# # Did we strip what we shouldn't?
+# if $(result[2]) = ".." {
+# return $(path)/.. ;
+# } else {
+# if ! $(result[1]) {
+# if [ is-rooted $(path) ] {
+# result = / ;
+# } else {
+# result = . ;
+# }
+# }
+# return $(result[1]) ;
+# }
+# }
+# } else {
+# error "Path '$(path)' has no parent" ;
+# }
+# }
+#
+# #
+# # Returns path2 such that "[ join path path2 ] = .".
+# # The path may not contain ".." element or be rooted.
+# #
+# rule reverse ( path )
+# {
+# if $(path) = .
+# {
+# return $(path) ;
+# }
+# else
+# {
+# local tokens = [ regex.split $(path) "/" ] ;
+# local tokens2 ;
+# for local i in $(tokens) {
+# tokens2 += .. ;
+# }
+# return [ sequence.join $(tokens2) : "/" ] ;
+# }
+# }
+#
+# #
+# # Auxillary rule: does all the semantic of 'join', except for error cheching.
+# # The error checking is separated because this rule is recursive, and I don't
+# # like the idea of checking the same input over and over.
+# #
+# local rule join-imp ( elements + )
+# {
+# return [ NORMALIZE_PATH $(elements:J="/") ] ;
+# }
+#
+# #
+# # Contanenates the passed path elements. Generates an error if
+# # any element other than the first one is rooted.
+# #
+# rule join ( elements + )
+# {
+# if ! $(elements[2])
+# {
+# return $(elements[1]) ;
+# }
+# else
+# {
+# for local e in $(elements[2-])
+# {
+# if [ is-rooted $(e) ]
+# {
+# error only first element may be rooted ;
+# }
+# }
+# return [ join-imp $(elements) ] ;
+# }
+# }
+
+
+def glob (dirs, patterns):
+ """ Returns the list of files matching the given pattern in the
+ specified directory. Both directories and patterns are
+ supplied as portable paths. Each pattern should be non-absolute
+ path, and can't contain "." or ".." elements. Each slash separated
+ element of pattern can contain the following special characters:
+ - '?', which match any character
+ - '*', which matches arbitrary number of characters.
+ A file $(d)/e1/e2/e3 (where 'd' is in $(dirs)) matches pattern p1/p2/p3
+ if and only if e1 matches p1, e2 matches p2 and so on.
+
+ For example:
+ [ glob . : *.cpp ]
+ [ glob . : */build/Jamfile ]
+ """
+# {
+# local result ;
+# if $(patterns:D)
+# {
+# # When a pattern has a directory element, we first glob for
+# # directory, and then glob for file name is the found directories.
+# for local p in $(patterns)
+# {
+# # First glob for directory part.
+# local globbed-dirs = [ glob $(dirs) : $(p:D) ] ;
+# result += [ glob $(globbed-dirs) : $(p:D="") ] ;
+# }
+# }
+# else
+# {
+# # When a pattern has not directory, we glob directly.
+# # Take care of special ".." value. The "GLOB" rule simply ignores
+# # the ".." element (and ".") element in directory listings. This is
+# # needed so that
+# #
+# # [ glob libs/*/Jamfile ]
+# #
+# # don't return
+# #
+# # libs/../Jamfile (which is the same as ./Jamfile)
+# #
+# # On the other hand, when ".." is explicitly present in the pattern
+# # we need to return it.
+# #
+# for local dir in $(dirs)
+# {
+# for local p in $(patterns)
+# {
+# if $(p) != ".."
+# {
+# result += [ sequence.transform make
+# : [ GLOB [ native $(dir) ] : $(p) ] ] ;
+# }
+# else
+# {
+# result += [ path.join $(dir) .. ] ;
+# }
+# }
+# }
+# }
+# return $(result) ;
+# }
+#
+
+# TODO: (PF) I replaced the code above by this. I think it should work but needs to be tested.
+ result = []
+ dirs = to_seq (dirs)
+ patterns = to_seq (patterns)
+
+ splitdirs = []
+ for dir in dirs:
+ splitdirs += dir.split (os.pathsep)
+
+ for dir in splitdirs:
+ for pattern in patterns:
+ p = os.path.join (dir, pattern)
+ import glob
+ result.extend (glob.glob (p))
+ return result
+
+#
+# Find out the absolute name of path and returns the list of all the parents,
+# starting with the immediate one. Parents are returned as relative names.
+# If 'upper_limit' is specified, directories above it will be pruned.
+#
+def all_parents(path, upper_limit=None, cwd=None):
+
+ if not cwd:
+ cwd = os.getcwd()
+
+ path_abs = os.path.join(cwd, path)
+
+ if upper_limit:
+ upper_limit = os.path.join(cwd, upper_limit)
+
+ result = []
+ while path_abs and path_abs != upper_limit:
+ (head, tail) = os.path.split(path)
+ path = os.path.join(path, "..")
+ result.append(path)
+ path_abs = head
+
+ if upper_limit and path_abs != upper_limit:
+ raise BaseException("'%s' is not a prefix of '%s'" % (upper_limit, path))
+
+ return result
+
+# Search for 'pattern' in parent directories of 'dir', up till and including
+# 'upper_limit', if it is specified, or till the filesystem root otherwise.
+#
+def glob_in_parents(dir, patterns, upper_limit=None):
+
+ result = []
+ parent_dirs = all_parents(dir, upper_limit)
+
+ for p in parent_dirs:
+ result = glob(p, patterns)
+ if result: break
+
+ return result
+
+#
+# #
+# # Assuming 'child' is a subdirectory of 'parent', return the relative
+# # path from 'parent' to 'child'
+# #
+# rule relative ( child parent )
+# {
+# if $(parent) = "."
+# {
+# return $(child) ;
+# }
+# else
+# {
+# local split1 = [ regex.split $(parent) / ] ;
+# local split2 = [ regex.split $(child) / ] ;
+#
+# while $(split1)
+# {
+# if $(split1[1]) = $(split2[1])
+# {
+# split1 = $(split1[2-]) ;
+# split2 = $(split2[2-]) ;
+# }
+# else
+# {
+# errors.error $(child) is not a subdir of $(parent) ;
+# }
+# }
+# return [ join $(split2) ] ;
+# }
+# }
+#
+# # Returns the minimal path to path2 that is relative path1.
+# #
+# rule relative-to ( path1 path2 )
+# {
+# local root_1 = [ regex.split [ reverse $(path1) ] / ] ;
+# local split1 = [ regex.split $(path1) / ] ;
+# local split2 = [ regex.split $(path2) / ] ;
+#
+# while $(split1) && $(root_1)
+# {
+# if $(split1[1]) = $(split2[1])
+# {
+# root_1 = $(root_1[2-]) ;
+# split1 = $(split1[2-]) ;
+# split2 = $(split2[2-]) ;
+# }
+# else
+# {
+# split1 = ;
+# }
+# }
+# return [ join . $(root_1) $(split2) ] ;
+# }
+
+# Returns the list of paths which are used by the operating system
+# for looking up programs
+def programs_path ():
+ raw = []
+ names = ['PATH', 'Path', 'path']
+
+ for name in names:
+ raw.append(os.environ.get (name, ''))
+
+ result = []
+ for elem in raw:
+ if elem:
+ for p in elem.split(os.path.pathsep):
+ result.append(make(p))
+
+ return result
+
+# rule make-NT ( native )
+# {
+# local tokens = [ regex.split $(native) "[/\\]" ] ;
+# local result ;
+#
+# # Handle paths ending with slashes
+# if $(tokens[-1]) = ""
+# {
+# tokens = $(tokens[1--2]) ; # discard the empty element
+# }
+#
+# result = [ path.join $(tokens) ] ;
+#
+# if [ regex.match "(^.:)" : $(native) ]
+# {
+# result = /$(result) ;
+# }
+#
+# if $(native) = ""
+# {
+# result = "." ;
+# }
+#
+# return $(result) ;
+# }
+#
+# rule native-NT ( path )
+# {
+# local result = [ MATCH "^/?(.*)" : $(path) ] ;
+# result = [ sequence.join [ regex.split $(result) "/" ] : "\\" ] ;
+# return $(result) ;
+# }
+#
+# rule make-CYGWIN ( path )
+# {
+# return [ make-NT $(path) ] ;
+# }
+#
+# rule native-CYGWIN ( path )
+# {
+# local result = $(path) ;
+# if [ regex.match "(^/.:)" : $(path) ] # win absolute
+# {
+# result = [ MATCH "^/?(.*)" : $(path) ] ; # remove leading '/'
+# }
+# return [ native-UNIX $(result) ] ;
+# }
+#
+# #
+# # split-VMS: splits input native path into
+# # device dir file (each part is optional),
+# # example:
+# #
+# # dev:[dir]file.c => dev: [dir] file.c
+# #
+# rule split-path-VMS ( native )
+# {
+# local matches = [ MATCH ([a-zA-Z0-9_-]+:)?(\\[[^\]]*\\])?(.*)?$ : $(native) ] ;
+# local device = $(matches[1]) ;
+# local dir = $(matches[2]) ;
+# local file = $(matches[3]) ;
+#
+# return $(device) $(dir) $(file) ;
+# }
+#
+# #
+# # Converts a native VMS path into a portable path spec.
+# #
+# # Does not handle current-device absolute paths such
+# # as "[dir]File.c" as it is not clear how to represent
+# # them in the portable path notation.
+# #
+# # Adds a trailing dot (".") to the file part if no extension
+# # is present (helps when converting it back into native path).
+# #
+# rule make-VMS ( native )
+# {
+# if [ MATCH ^(\\[[a-zA-Z0-9]) : $(native) ]
+# {
+# errors.error "Can't handle default-device absolute paths: " $(native) ;
+# }
+#
+# local parts = [ split-path-VMS $(native) ] ;
+# local device = $(parts[1]) ;
+# local dir = $(parts[2]) ;
+# local file = $(parts[3]) ;
+# local elems ;
+#
+# if $(device)
+# {
+# #
+# # rooted
+# #
+# elems = /$(device) ;
+# }
+#
+# if $(dir) = "[]"
+# {
+# #
+# # Special case: current directory
+# #
+# elems = $(elems) "." ;
+# }
+# else if $(dir)
+# {
+# dir = [ regex.replace $(dir) "\\[|\\]" "" ] ;
+# local dir_parts = [ regex.split $(dir) \\. ] ;
+#
+# if $(dir_parts[1]) = ""
+# {
+# #
+# # Relative path
+# #
+# dir_parts = $(dir_parts[2--1]) ;
+# }
+#
+# #
+# # replace "parent-directory" parts (- => ..)
+# #
+# dir_parts = [ regex.replace-list $(dir_parts) : - : .. ] ;
+#
+# elems = $(elems) $(dir_parts) ;
+# }
+#
+# if $(file)
+# {
+# if ! [ MATCH (\\.) : $(file) ]
+# {
+# #
+# # Always add "." to end of non-extension file
+# #
+# file = $(file). ;
+# }
+# elems = $(elems) $(file) ;
+# }
+#
+# local portable = [ path.join $(elems) ] ;
+#
+# return $(portable) ;
+# }
+#
+# #
+# # Converts a portable path spec into a native VMS path.
+# #
+# # Relies on having at least one dot (".") included in the file
+# # name to be able to differentiate it ftom the directory part.
+# #
+# rule native-VMS ( path )
+# {
+# local device = "" ;
+# local dir = $(path) ;
+# local file = "" ;
+# local native ;
+# local split ;
+#
+# #
+# # Has device ?
+# #
+# if [ is-rooted $(dir) ]
+# {
+# split = [ MATCH ^/([^:]+:)/?(.*) : $(dir) ] ;
+# device = $(split[1]) ;
+# dir = $(split[2]) ;
+# }
+#
+# #
+# # Has file ?
+# #
+# # This is no exact science, just guess work:
+# #
+# # If the last part of the current path spec
+# # includes some chars, followed by a dot,
+# # optionally followed by more chars -
+# # then it is a file (keep your fingers crossed).
+# #
+# split = [ regex.split $(dir) / ] ;
+# local maybe_file = $(split[-1]) ;
+#
+# if [ MATCH ^([^.]+\\..*) : $(maybe_file) ]
+# {
+# file = $(maybe_file) ;
+# dir = [ sequence.join $(split[1--2]) : / ] ;
+# }
+#
+# #
+# # Has dir spec ?
+# #
+# if $(dir) = "."
+# {
+# dir = "[]" ;
+# }
+# else if $(dir)
+# {
+# dir = [ regex.replace $(dir) \\.\\. - ] ;
+# dir = [ regex.replace $(dir) / . ] ;
+#
+# if $(device) = ""
+# {
+# #
+# # Relative directory
+# #
+# dir = "."$(dir) ;
+# }
+# dir = "["$(dir)"]" ;
+# }
+#
+# native = [ sequence.join $(device) $(dir) $(file) ] ;
+#
+# return $(native) ;
+# }
+#
+#
+# rule __test__ ( ) {
+#
+# import assert ;
+# import errors : try catch ;
+#
+# assert.true is-rooted "/" ;
+# assert.true is-rooted "/foo" ;
+# assert.true is-rooted "/foo/bar" ;
+# assert.result : is-rooted "." ;
+# assert.result : is-rooted "foo" ;
+# assert.result : is-rooted "foo/bar" ;
+#
+# assert.true has-parent "foo" ;
+# assert.true has-parent "foo/bar" ;
+# assert.true has-parent "." ;
+# assert.result : has-parent "/" ;
+#
+# assert.result "." : basename "." ;
+# assert.result ".." : basename ".." ;
+# assert.result "foo" : basename "foo" ;
+# assert.result "foo" : basename "bar/foo" ;
+# assert.result "foo" : basename "gaz/bar/foo" ;
+# assert.result "foo" : basename "/gaz/bar/foo" ;
+#
+# assert.result "." : parent "foo" ;
+# assert.result "/" : parent "/foo" ;
+# assert.result "foo/bar" : parent "foo/bar/giz" ;
+# assert.result ".." : parent "." ;
+# assert.result ".." : parent "../foo" ;
+# assert.result "../../foo" : parent "../../foo/bar" ;
+#
+#
+# assert.result "." : reverse "." ;
+# assert.result ".." : reverse "foo" ;
+# assert.result "../../.." : reverse "foo/bar/giz" ;
+#
+# assert.result "foo" : join "foo" ;
+# assert.result "/foo" : join "/" "foo" ;
+# assert.result "foo/bar" : join "foo" "bar" ;
+# assert.result "foo/bar" : join "foo/giz" "../bar" ;
+# assert.result "foo/giz" : join "foo/bar/baz" "../../giz" ;
+# assert.result ".." : join "." ".." ;
+# assert.result ".." : join "foo" "../.." ;
+# assert.result "../.." : join "../foo" "../.." ;
+# assert.result "/foo" : join "/bar" "../foo" ;
+# assert.result "foo/giz" : join "foo/giz" "." ;
+# assert.result "." : join lib2 ".." ;
+# assert.result "/" : join "/a" ".." ;
+#
+# assert.result /a/b : join /a/b/c .. ;
+#
+# assert.result "foo/bar/giz" : join "foo" "bar" "giz" ;
+# assert.result "giz" : join "foo" ".." "giz" ;
+# assert.result "foo/giz" : join "foo" "." "giz" ;
+#
+# try ;
+# {
+# join "a" "/b" ;
+# }
+# catch only first element may be rooted ;
+#
+# local CWD = "/home/ghost/build" ;
+# assert.result : all-parents . : . : $(CWD) ;
+# assert.result . .. ../.. ../../.. : all-parents "Jamfile" : "" : $(CWD) ;
+# assert.result foo . .. ../.. ../../.. : all-parents "foo/Jamfile" : "" : $(CWD) ;
+# assert.result ../Work .. ../.. ../../.. : all-parents "../Work/Jamfile" : "" : $(CWD) ;
+#
+# local CWD = "/home/ghost" ;
+# assert.result . .. : all-parents "Jamfile" : "/home" : $(CWD) ;
+# assert.result . : all-parents "Jamfile" : "/home/ghost" : $(CWD) ;
+#
+# assert.result "c/d" : relative "a/b/c/d" "a/b" ;
+# assert.result "foo" : relative "foo" "." ;
+#
+# local save-os = [ modules.peek path : os ] ;
+# modules.poke path : os : NT ;
+#
+# assert.result "foo/bar/giz" : make "foo/bar/giz" ;
+# assert.result "foo/bar/giz" : make "foo\\bar\\giz" ;
+# assert.result "foo" : make "foo/." ;
+# assert.result "foo" : make "foo/bar/.." ;
+# assert.result "/D:/My Documents" : make "D:\\My Documents" ;
+# assert.result "/c:/boost/tools/build/new/project.jam" : make "c:\\boost\\tools\\build\\test\\..\\new\\project.jam" ;
+#
+# assert.result "foo\\bar\\giz" : native "foo/bar/giz" ;
+# assert.result "foo" : native "foo" ;
+# assert.result "D:\\My Documents\\Work" : native "/D:/My Documents/Work" ;
+#
+# modules.poke path : os : UNIX ;
+#
+# assert.result "foo/bar/giz" : make "foo/bar/giz" ;
+# assert.result "/sub1" : make "/sub1/." ;
+# assert.result "/sub1" : make "/sub1/sub2/.." ;
+# assert.result "sub1" : make "sub1/." ;
+# assert.result "sub1" : make "sub1/sub2/.." ;
+# assert.result "/foo/bar" : native "/foo/bar" ;
+#
+# modules.poke path : os : VMS ;
+#
+# #
+# # Don't really need to poke os before these
+# #
+# assert.result "disk:" "[dir]" "file" : split-path-VMS "disk:[dir]file" ;
+# assert.result "disk:" "[dir]" "" : split-path-VMS "disk:[dir]" ;
+# assert.result "disk:" "" "" : split-path-VMS "disk:" ;
+# assert.result "disk:" "" "file" : split-path-VMS "disk:file" ;
+# assert.result "" "[dir]" "file" : split-path-VMS "[dir]file" ;
+# assert.result "" "[dir]" "" : split-path-VMS "[dir]" ;
+# assert.result "" "" "file" : split-path-VMS "file" ;
+# assert.result "" "" "" : split-path-VMS "" ;
+#
+# #
+# # Special case: current directory
+# #
+# assert.result "" "[]" "" : split-path-VMS "[]" ;
+# assert.result "disk:" "[]" "" : split-path-VMS "disk:[]" ;
+# assert.result "" "[]" "file" : split-path-VMS "[]file" ;
+# assert.result "disk:" "[]" "file" : split-path-VMS "disk:[]file" ;
+#
+# #
+# # Make portable paths
+# #
+# assert.result "/disk:" : make "disk:" ;
+# assert.result "foo/bar/giz" : make "[.foo.bar.giz]" ;
+# assert.result "foo" : make "[.foo]" ;
+# assert.result "foo" : make "[.foo.bar.-]" ;
+# assert.result ".." : make "[.-]" ;
+# assert.result ".." : make "[-]" ;
+# assert.result "." : make "[]" ;
+# assert.result "giz.h" : make "giz.h" ;
+# assert.result "foo/bar/giz.h" : make "[.foo.bar]giz.h" ;
+# assert.result "/disk:/my_docs" : make "disk:[my_docs]" ;
+# assert.result "/disk:/boost/tools/build/new/project.jam" : make "disk:[boost.tools.build.test.-.new]project.jam" ;
+#
+# #
+# # Special case (adds '.' to end of file w/o extension to
+# # disambiguate from directory in portable path spec).
+# #
+# assert.result "Jamfile." : make "Jamfile" ;
+# assert.result "dir/Jamfile." : make "[.dir]Jamfile" ;
+# assert.result "/disk:/dir/Jamfile." : make "disk:[dir]Jamfile" ;
+#
+# #
+# # Make native paths
+# #
+# assert.result "disk:" : native "/disk:" ;
+# assert.result "[.foo.bar.giz]" : native "foo/bar/giz" ;
+# assert.result "[.foo]" : native "foo" ;
+# assert.result "[.-]" : native ".." ;
+# assert.result "[.foo.-]" : native "foo/.." ;
+# assert.result "[]" : native "." ;
+# assert.result "disk:[my_docs.work]" : native "/disk:/my_docs/work" ;
+# assert.result "giz.h" : native "giz.h" ;
+# assert.result "disk:Jamfile." : native "/disk:Jamfile." ;
+# assert.result "disk:[my_docs.work]Jamfile." : native "/disk:/my_docs/work/Jamfile." ;
+#
+# modules.poke path : os : $(save-os) ;
+#
+# }
+
+#
+
+
+#def glob(dir, patterns):
+# result = []
+# for pattern in patterns:
+# result.extend(builtin_glob(os.path.join(dir, pattern)))
+# return result
+
+def glob(dirs, patterns, exclude_patterns=None):
+ """Returns the list of files matching the given pattern in the
+ specified directory. Both directories and patterns are
+ supplied as portable paths. Each pattern should be non-absolute
+ path, and can't contain '.' or '..' elements. Each slash separated
+ element of pattern can contain the following special characters:
+ - '?', which match any character
+ - '*', which matches arbitrary number of characters.
+ A file $(d)/e1/e2/e3 (where 'd' is in $(dirs)) matches pattern p1/p2/p3
+ if and only if e1 matches p1, e2 matches p2 and so on.
+ For example:
+ [ glob . : *.cpp ]
+ [ glob . : */build/Jamfile ]
+ """
+
+ assert(isinstance(patterns, list))
+ assert(isinstance(dirs, list))
+
+ if not exclude_patterns:
+ exclude_patterns = []
+ else:
+ assert(isinstance(exclude_patterns, list))
+
+ real_patterns = [os.path.join(d, p) for p in patterns for d in dirs]
+ real_exclude_patterns = [os.path.join(d, p) for p in exclude_patterns
+ for d in dirs]
+
+ inc = [os.path.normpath(name) for p in real_patterns
+ for name in builtin_glob(p)]
+ exc = [os.path.normpath(name) for p in real_exclude_patterns
+ for name in builtin_glob(p)]
+ return [x for x in inc if x not in exc]
+
+def glob_tree(roots, patterns, exclude_patterns=None):
+ """Recursive version of GLOB. Builds the glob of files while
+ also searching in the subdirectories of the given roots. An
+ optional set of exclusion patterns will filter out the
+ matching entries from the result. The exclusions also apply
+ to the subdirectory scanning, such that directories that
+ match the exclusion patterns will not be searched."""
+
+ if not exclude_patterns:
+ exclude_patterns = []
+
+ result = glob(roots, patterns, exclude_patterns)
+ subdirs = [s for s in glob(roots, ["*"]) if s != "." and s != ".." and os.path.isdir(s)]
+ if subdirs:
+ result.extend(glob_tree(subdirs, patterns, exclude_patterns))
+
+ return result
+
+def glob_in_parents(dir, patterns, upper_limit=None):
+ """Recursive version of GLOB which glob sall parent directories
+ of dir until the first match is found. Returns an empty result if no match
+ is found"""
+
+ assert(isinstance(dir, str))
+ assert(isinstance(patterns, list))
+
+ result = []
+
+ absolute_dir = os.path.join(os.getcwd(), dir)
+ absolute_dir = os.path.normpath(absolute_dir)
+ while absolute_dir:
+ new_dir = os.path.split(absolute_dir)[0]
+ if new_dir == absolute_dir:
+ break
+ result = glob([new_dir], patterns)
+ if result:
+ break
+ absolute_dir = new_dir
+
+ return result
+
+
+# The relpath functionality is written by
+# Cimarron Taylor
+def split(p, rest=[]):
+ (h,t) = os.path.split(p)
+ if len(h) < 1: return [t]+rest
+ if len(t) < 1: return [h]+rest
+ return split(h,[t]+rest)
+
+def commonpath(l1, l2, common=[]):
+ if len(l1) < 1: return (common, l1, l2)
+ if len(l2) < 1: return (common, l1, l2)
+ if l1[0] != l2[0]: return (common, l1, l2)
+ return commonpath(l1[1:], l2[1:], common+[l1[0]])
+
+def relpath(p1, p2):
+ (common,l1,l2) = commonpath(split(p1), split(p2))
+ p = []
+ if len(l1) > 0:
+ p = [ '../' * len(l1) ]
+ p = p + l2
+ if p:
+ return os.path.join( *p )
+ else:
+ return "."
diff --git a/tools/build/v2/util/print.jam b/tools/build/v2/util/print.jam
new file mode 100644
index 0000000000..708d21abaa
--- /dev/null
+++ b/tools/build/v2/util/print.jam
@@ -0,0 +1,488 @@
+# Copyright 2003 Douglas Gregor
+# Copyright 2002, 2003, 2005 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Utilities for generating format independent output. Using these
+# will help in generation of documentation in at minimum plain/console
+# and html.
+
+import modules ;
+import numbers ;
+import string ;
+import regex ;
+import "class" ;
+import scanner ;
+import path ;
+
+# The current output target. Defaults to console.
+output-target = console ;
+
+# The current output type. Defaults to plain. Other possible values are "html".
+output-type = plain ;
+
+# Whitespace.
+.whitespace = [ string.whitespace ] ;
+
+
+# Set the target and type of output to generate. This sets both the destination
+# output and the type of docs to generate to that output. The target can be
+# either a file or "console" for echoing to the console. If the type of output
+# is not specified it defaults to plain text.
+#
+rule output (
+ target # The target file or device; file or "console".
+ type ? # The type of output; "plain" or "html".
+)
+{
+ type ?= plain ;
+ if $(output-target) != $(target)
+ {
+ output-target = $(target) ;
+ output-type = $(type) ;
+ if $(output-type) = html
+ {
+ text
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"
+ "<html>"
+ "<head>"
+ "</head>"
+ "<body link=\"#0000ff\" vlink=\"#800080\">"
+ : true
+ : prefix ;
+ text
+ "</body>"
+ "</html>"
+ :
+ : suffix ;
+ }
+ }
+}
+
+
+# Generate a section with a description. The type of output can be controlled by
+# the value of the 'output-type' variable.
+#
+rule section (
+ name # The name of the section.
+ description * # A number of description lines.
+)
+{
+ if $(output-type) = plain
+ {
+ lines [ split-at-words $(name): ] ;
+ lines ;
+ }
+ else if $(output-type) = html
+ {
+ name = [ escape-html $(name) ] ;
+ text <h3>$(name)</h3> <p> ;
+ }
+ local pre = ;
+ while $(description)
+ {
+ local paragraph = ;
+ while $(description) && [ string.is-whitespace $(description[1]) ] { description = $(description[2-]) ; }
+ if $(pre)
+ {
+ while $(description) && (
+ $(pre) = " $(description[1])" ||
+ ( $(pre) < [ string.chars [ MATCH "^([$(.whitespace)]*)" : " $(description[1])" ] ] )
+ )
+ { paragraph += $(description[1]) ; description = $(description[2-]) ; }
+ while [ string.is-whitespace $(paragraph[-1]) ] { paragraph = $(paragraph[1--2]) ; }
+ pre = ;
+ if $(output-type) = plain
+ {
+ lines $(paragraph) "" : " " " " ;
+ }
+ else if $(output-type) = html
+ {
+ text <blockquote> ;
+ lines $(paragraph) ;
+ text </blockquote> ;
+ }
+ }
+ else
+ {
+ while $(description) && ! [ string.is-whitespace $(description[1]) ]
+ { paragraph += $(description[1]) ; description = $(description[2-]) ; }
+ if $(paragraph[1]) = :: && ! $(paragraph[2])
+ {
+ pre = " " ;
+ }
+ if $(paragraph[1]) = ::
+ {
+ if $(output-type) = plain
+ {
+ lines $(paragraph[2-]) "" : " " " " ;
+ lines ;
+ }
+ else if $(output-type) = html
+ {
+ text <blockquote> ;
+ lines $(paragraph[2-]) ;
+ text </blockquote> ;
+ }
+ }
+ else
+ {
+ local p = [ MATCH "(.*)(::)$" : $(paragraph[-1]) ] ;
+ local pws = [ MATCH "([ ]*)$" : $(p[1]) ] ;
+ p = [ MATCH "(.*)($(pws))($(p[2]))$" : $(paragraph[-1]) ] ;
+ if $(p[3]) = ::
+ {
+ pre = [ string.chars [ MATCH "^([$(.whitespace)]*)" : " $(p[1])" ] ] ;
+ if ! $(p[2]) || $(p[2]) = "" { paragraph = $(paragraph[1--2]) $(p[1]): ; }
+ else { paragraph = $(paragraph[1--2]) $(p[1]) ; }
+ if $(output-type) = plain
+ {
+ lines [ split-at-words " " $(paragraph) ] : " " " " ;
+ lines ;
+ }
+ else if $(output-type) = html
+ {
+ text </p> <p> [ escape-html $(paragraph) ] ;
+ }
+ }
+ else
+ {
+ if $(output-type) = plain
+ {
+ lines [ split-at-words " " $(paragraph) ] : " " " " ;
+ lines ;
+ }
+ else if $(output-type) = html
+ {
+ text </p> <p> [ escape-html $(paragraph) ] ;
+ }
+ }
+ }
+ }
+ }
+ if $(output-type) = html
+ {
+ text </p> ;
+ }
+}
+
+
+# Generate the start of a list of items. The type of output can be controlled by
+# the value of the 'output-type' variable.
+#
+rule list-start ( )
+{
+ if $(output-type) = plain
+ {
+ }
+ else if $(output-type) = html
+ {
+ text <ul> ;
+ }
+}
+
+
+# Generate an item in a list. The type of output can be controlled by the value
+# of the 'output-type' variable.
+#
+rule list-item (
+ item + # The item to list.
+)
+{
+ if $(output-type) = plain
+ {
+ lines [ split-at-words "*" $(item) ] : " " " " ;
+ }
+ else if $(output-type) = html
+ {
+ text <li> [ escape-html $(item) ] </li> ;
+ }
+}
+
+
+# Generate the end of a list of items. The type of output can be controlled by
+# the value of the 'output-type' variable.
+#
+rule list-end ( )
+{
+ if $(output-type) = plain
+ {
+ lines ;
+ }
+ else if $(output-type) = html
+ {
+ text </ul> ;
+ }
+}
+
+
+# Split the given text into separate lines, word-wrapping to a margin. The
+# default margin is 78 characters.
+#
+rule split-at-words (
+ text + # The text to split.
+ : margin ? # An optional margin, default is 78.
+)
+{
+ local lines = ;
+ text = [ string.words $(text:J=" ") ] ;
+ text = $(text:J=" ") ;
+ margin ?= 78 ;
+ local char-match-1 = ".?" ;
+ local char-match = "" ;
+ while $(margin) != 0
+ {
+ char-match = $(char-match)$(char-match-1) ;
+ margin = [ numbers.decrement $(margin) ] ;
+ }
+ while $(text)
+ {
+ local s = "" ;
+ local t = "" ;
+ # divide s into the first X characters and the rest
+ s = [ MATCH "^($(char-match))(.*)" : $(text) ] ;
+
+ if $(s[2])
+ {
+ # split the first half at a space
+ t = [ MATCH "^(.*)[\\ ]([^\\ ]*)$" : $(s[1]) ] ;
+ }
+ else
+ {
+ t = $(s) ;
+ }
+
+ if ! $(t[2])
+ {
+ t += "" ;
+ }
+
+ text = $(t[2])$(s[2]) ;
+ lines += $(t[1]) ;
+ }
+ return $(lines) ;
+}
+
+
+# Generate a set of fixed lines. Each single item passed in is output on a
+# separate line. For console this just echos each line, but for html this will
+# split them with <br>.
+#
+rule lines (
+ text * # The lines of text.
+ : indent ? # Optional indentation prepended to each line after the first one.
+ outdent ? # Optional indentation to prepend to the first line.
+)
+{
+ text ?= "" ;
+ indent ?= "" ;
+ outdent ?= "" ;
+ if $(output-type) = plain
+ {
+ text $(outdent)$(text[1]) $(indent)$(text[2-]) ;
+ }
+ else if $(output-type) = html
+ {
+ local indent-chars = [ string.chars $(indent) ] ;
+ indent = "" ;
+ for local c in $(indent-chars)
+ {
+ if $(c) = " " { c = "&nbsp;" ; }
+ else if $(c) = " " { c = "&nbsp;&nbsp;&nbsp;&nbsp;" ; }
+ indent = $(indent)$(c) ;
+ }
+ local html-text = [ escape-html $(text) : "&nbsp;" ] ;
+ text $(html-text[1])<br> $(indent)$(html-text[2-])<br> ;
+ }
+}
+
+
+# Output text directly to the current target. When doing output to a file, one
+# can indicate if the text should be output to "prefix" it, as the "body"
+# (default), or "suffix" of the file. This is independant of the actual
+# execution order of the text rule. This rule invokes a singular action, one
+# action only once, which does the build of the file. Therefore actions on the
+# target outside of this rule will happen entirely before and/or after all
+# output using this rule.
+#
+rule text (
+ strings * # The strings of text to output.
+ : overwrite ? # true to overwrite the output (if it is a file)
+ : prefix-body-suffix ? # Indication to output prefix, body, or suffix (for a file).
+)
+{
+ prefix-body-suffix ?= body ;
+ if $(output-target) = console
+ {
+ if ! $(strings)
+ {
+ ECHO ;
+ }
+ else
+ {
+ for local s in $(strings)
+ {
+ ECHO $(s) ;
+ }
+ }
+ }
+ if ! $($(output-target).did-action)
+ {
+ $(output-target).did-action = yes ;
+ $(output-target).text-prefix = ;
+ $(output-target).text-body = ;
+ $(output-target).text-suffix = ;
+
+ nl on $(output-target) = "
+" ;
+ text-redirect on $(output-target) = ">>" ;
+ if $(overwrite)
+ {
+ text-redirect on $(output-target) = ">" ;
+ }
+ text-content on $(output-target) = ;
+
+ text-action $(output-target) ;
+
+ if $(overwrite) && $(output-target) != console
+ {
+ check-for-update $(output-target) ;
+ }
+ }
+ $(output-target).text-$(prefix-body-suffix) += $(strings) ;
+ text-content on $(output-target) =
+ $($(output-target).text-prefix)
+ $($(output-target).text-body)
+ $($(output-target).text-suffix) ;
+}
+
+
+# Outputs the text to the current targets, after word-wrapping it.
+#
+rule wrapped-text ( text + )
+{
+ local lines = [ split-at-words $(text) ] ;
+ text $(lines) ;
+}
+
+
+# Escapes text into html/xml printable equivalents. Does not know about tags and
+# therefore tags fed into this will also be escaped. Currently escapes space,
+# "<", ">", and "&".
+#
+rule escape-html (
+ text + # The text to escape.
+ : space ? # What to replace spaces with, defaults to " ".
+)
+{
+ local html-text = ;
+ while $(text)
+ {
+ local html = $(text[1]) ;
+ text = $(text[2-]) ;
+ html = [ regex.replace $(html) "&" "&amp;" ] ;
+ html = [ regex.replace $(html) "<" "&lt;" ] ;
+ html = [ regex.replace $(html) ">" "&gt;" ] ;
+ if $(space)
+ {
+ html = [ regex.replace $(html) " " "$(space)" ] ;
+ }
+ html-text += $(html) ;
+ }
+ return $(html-text) ;
+}
+
+
+# Outputs the text strings collected by the text rule to the output file.
+#
+actions quietly text-action
+{
+ @($(STDOUT):E=$(text-content:J=$(nl))) $(text-redirect) "$(<)"
+}
+
+
+rule get-scanner ( )
+{
+ if ! $(.scanner)
+ {
+ .scanner = [ class.new print-scanner ] ;
+ }
+ return $(.scanner) ;
+}
+
+
+# The following code to update print targets when their contents
+# change is a horrible hack. It basically creates a target which
+# binds to this file (print.jam) and installs a scanner on it
+# which reads the target and compares its contents to the new
+# contents that we're writing.
+#
+rule check-for-update ( target )
+{
+ local scanner = [ get-scanner ] ;
+ local file = [ path.native [ modules.binding $(__name__) ] ] ;
+ local g = [ MATCH <(.*)> : $(target:G) ] ;
+ local dependency-target = $(__file__:G=$(g:E=)-$(target:G=)-$(scanner)) ;
+ DEPENDS $(target) : $(dependency-target) ;
+ SEARCH on $(dependency-target) = $(file:D) ;
+ ISFILE $(dependency-target) ;
+ NOUPDATE $(dependency-target) ;
+ base on $(dependency-target) = $(target) ;
+ scanner.install $(scanner) : $(dependency-target) none ;
+ return $(dependency-target) ;
+}
+
+
+class print-scanner : scanner
+{
+ import path ;
+ import os ;
+
+ rule pattern ( )
+ {
+ return "(One match...)" ;
+ }
+
+ rule process ( target : matches * : binding )
+ {
+ local base = [ on $(target) return $(base) ] ;
+ local nl = [ on $(base) return $(nl) ] ;
+ local text-content = [ on $(base) return $(text-content) ] ;
+ local dir = [ on $(base) return $(LOCATE) ] ;
+ if $(dir)
+ {
+ dir = [ path.make $(dir) ] ;
+ }
+ local file = [ path.native [ path.join $(dir) $(base:G=) ] ] ;
+ local actual-content ;
+ if [ os.name ] = NT
+ {
+ actual-content = [ SHELL "type \"$(file)\" 2>nul" ] ;
+ }
+ else
+ {
+ actual-content = [ SHELL "cat \"$(file)\" 2>/dev/null" ] ;
+ }
+ if $(text-content:J=$(nl)) != $(actual-content)
+ {
+ ALWAYS $(base) ;
+ }
+ }
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+
+ assert.result one two three : split-at-words one two three : 5 ;
+ assert.result "one two" three : split-at-words one two three : 8 ;
+ assert.result "one two" three : split-at-words one two three : 9 ;
+ assert.result "one two three" : split-at-words one two three ;
+
+ # VP, 2004-12-03 The following test fails for some reason, so commenting it
+ # out.
+ #assert.result "one&nbsp;two&nbsp;three" "&amp;&lt;&gt;" :
+ # escape-html "one two three" "&<>" ;
+}
diff --git a/tools/build/v2/util/regex.jam b/tools/build/v2/util/regex.jam
new file mode 100644
index 0000000000..234c36f62d
--- /dev/null
+++ b/tools/build/v2/util/regex.jam
@@ -0,0 +1,193 @@
+# Copyright 2001, 2002 Dave Abrahams
+# Copyright 2003 Douglas Gregor
+# Copyright 2003 Rene Rivera
+# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+#
+# Returns a list of the following substrings:
+# 1) from beginning till the first occurrence of 'separator' or till the end,
+# 2) between each occurrence of 'separator' and the next occurrence,
+# 3) from the last occurrence of 'separator' till the end.
+# If no separator is present, the result will contain only one element.
+#
+
+rule split ( string separator )
+{
+ local result ;
+ local s = $(string) ;
+
+ # Break pieaces off 's' until it has no separators left.
+ local match = 1 ;
+ while $(match)
+ {
+ match = [ MATCH ^(.*)($(separator))(.*) : $(s) ] ;
+ if $(match)
+ {
+ match += "" ; # in case 3rd item was empty - works around MATCH bug
+ result = $(match[3]) $(result) ;
+ s = $(match[1]) ;
+ }
+ }
+ # Combine the remaining part at the beginning, which does not have
+ # separators, with the pieces broken off. Note that the rule's signature
+ # does not allow the initial s to be empty.
+ return $(s) $(result) ;
+}
+
+
+# Returns the concatenated results of Applying regex.split to every element of
+# the list using the separator pattern.
+#
+rule split-list ( list * : separator )
+{
+ local result ;
+ for s in $(list)
+ {
+ result += [ split $(s) $(separator) ] ;
+ }
+ return $(result) ;
+}
+
+
+# Match string against pattern, and return the elements indicated by indices.
+#
+rule match ( pattern : string : indices * )
+{
+ indices ?= 1 2 3 4 5 6 7 8 9 ;
+ local x = [ MATCH $(pattern) : $(string) ] ;
+ return $(x[$(indices)]) ;
+}
+
+
+# Matches all elements of 'list' agains the 'pattern' and returns a list of
+# elements indicated by indices of all successful matches. If 'indices' is
+# omitted returns a list of first paranthethised groups of all successful
+# matches.
+#
+rule transform ( list * : pattern : indices * )
+{
+ indices ?= 1 ;
+ local result ;
+ for local e in $(list)
+ {
+ local m = [ MATCH $(pattern) : $(e) ] ;
+ if $(m)
+ {
+ result += $(m[$(indices)]) ;
+ }
+ }
+ return $(result) ;
+}
+
+NATIVE_RULE regex : transform ;
+
+
+# Escapes all of the characters in symbols using the escape symbol escape-symbol
+# for the given string, and returns the escaped string.
+#
+rule escape ( string : symbols : escape-symbol )
+{
+ local result = "" ;
+ local m = 1 ;
+ while $(m)
+ {
+ m = [ MATCH ^([^$(symbols)]*)([$(symbols)])(.*) : $(string) ] ;
+ if $(m)
+ {
+ m += "" ; # Supposedly a bug fix; borrowed from regex.split
+ result = "$(result)$(m[1])$(escape-symbol)$(m[2])" ;
+ string = $(m[3]) ;
+ }
+ }
+ string ?= "" ;
+ result = "$(result)$(string)" ;
+ return $(result) ;
+}
+
+
+# Replaces occurrences of a match string in a given string and returns the new
+# string. The match string can be a regex expression.
+#
+rule replace (
+ string # The string to modify.
+ match # The characters to replace.
+ replacement # The string to replace with.
+ )
+{
+ local result = "" ;
+ local parts = 1 ;
+ while $(parts)
+ {
+ parts = [ MATCH ^(.*)($(match))(.*) : $(string) ] ;
+ if $(parts)
+ {
+ parts += "" ;
+ result = "$(replacement)$(parts[3])$(result)" ;
+ string = $(parts[1]) ;
+ }
+ }
+ string ?= "" ;
+ result = "$(string)$(result)" ;
+ return $(result) ;
+}
+
+
+# Replaces occurrences of a match string in a given list of strings and returns
+# a list of new strings. The match string can be a regex expression.
+#
+# list - the list of strings to modify.
+# match - the search expression.
+# replacement - the string to replace with.
+#
+rule replace-list ( list * : match : replacement )
+{
+ local result ;
+ for local e in $(list)
+ {
+ result += [ replace $(e) $(match) $(replacement) ] ;
+ }
+ return $(result) ;
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+
+ assert.result a b c : split "a/b/c" / ;
+ assert.result "" a b c : split "/a/b/c" / ;
+ assert.result "" "" a b c : split "//a/b/c" / ;
+ assert.result "" a "" b c : split "/a//b/c" / ;
+ assert.result "" a "" b c "" : split "/a//b/c/" / ;
+ assert.result "" a "" b c "" "" : split "/a//b/c//" / ;
+
+ assert.result a c b d
+ : match (.)(.)(.)(.) : abcd : 1 3 2 4 ;
+
+ assert.result a b c d
+ : match (.)(.)(.)(.) : abcd ;
+
+ assert.result ababab cddc
+ : match ((ab)*)([cd]+) : abababcddc : 1 3 ;
+
+ assert.result a.h c.h
+ : transform <a.h> \"b.h\" <c.h> : <(.*)> ;
+
+ assert.result a.h b.h c.h
+ : transform <a.h> \"b.h\" <c.h> : <([^>]*)>|\"([^\"]*)\" : 1 2 ;
+
+ assert.result "^<?xml version=\"1.0\"^>"
+ : escape "<?xml version=\"1.0\">" : "&|()<>^" : "^" ;
+
+ assert.result "<?xml version=\\\"1.0\\\">"
+ : escape "<?xml version=\"1.0\">" : "\\\"" : "\\" ;
+
+ assert.result "string&nbsp;string&nbsp;" : replace "string string " " " "&nbsp;" ;
+ assert.result "&nbsp;string&nbsp;string" : replace " string string" " " "&nbsp;" ;
+ assert.result "string&nbsp;&nbsp;string" : replace "string string" " " "&nbsp;" ;
+ assert.result "-" : replace "&" "&" "-" ;
+
+ assert.result "-" "a-b" : replace-list "&" "a&b" : "&" : "-" ;
+}
diff --git a/tools/build/v2/util/regex.py b/tools/build/v2/util/regex.py
new file mode 100644
index 0000000000..29e26ecf43
--- /dev/null
+++ b/tools/build/v2/util/regex.py
@@ -0,0 +1,25 @@
+# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+import re
+
+def transform (list, pattern, indices = [1]):
+ """ Matches all elements of 'list' agains the 'pattern'
+ and returns a list of the elements indicated by indices of
+ all successfull matches. If 'indices' is omitted returns
+ a list of first paranthethised groups of all successfull
+ matches.
+ """
+ result = []
+
+ for e in list:
+ m = re.match (pattern, e)
+
+ if m:
+ for i in indices:
+ result.append (m.group (i))
+
+ return result
+
diff --git a/tools/build/v2/util/sequence.jam b/tools/build/v2/util/sequence.jam
new file mode 100644
index 0000000000..73919a65dd
--- /dev/null
+++ b/tools/build/v2/util/sequence.jam
@@ -0,0 +1,335 @@
+# Copyright 2001, 2002, 2003 Dave Abrahams
+# Copyright 2006 Rene Rivera
+# Copyright 2002, 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import assert ;
+import numbers ;
+import modules ;
+
+
+# Note that algorithms in this module execute largely in the caller's module
+# namespace, so that local rules can be used as function objects. Also note that
+# most predicates can be multi-element lists. In that case, all but the first
+# element are prepended to the first argument which is passed to the rule named
+# by the first element.
+
+
+# Return the elements e of $(sequence) for which [ $(predicate) e ] has a
+# non-null value.
+#
+rule filter ( predicate + : sequence * )
+{
+ local caller = [ CALLER_MODULE ] ;
+ local result ;
+
+ for local e in $(sequence)
+ {
+ if [ modules.call-in $(caller) : $(predicate) $(e) ]
+ {
+ result += $(e) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Return a new sequence consisting of [ $(function) $(e) ] for each element e of
+# $(sequence).
+#
+rule transform ( function + : sequence * )
+{
+ local caller = [ CALLER_MODULE ] ;
+ local result ;
+
+ for local e in $(sequence)
+ {
+ result += [ modules.call-in $(caller) : $(function) $(e) ] ;
+ }
+ return $(result) ;
+}
+
+
+rule reverse ( s * )
+{
+ local r ;
+ for local x in $(s)
+ {
+ r = $(x) $(r) ;
+ }
+ return $(r) ;
+}
+
+
+rule less ( a b )
+{
+ if $(a) < $(b)
+ {
+ return true ;
+ }
+}
+
+
+# Insertion-sort s using the BinaryPredicate ordered.
+#
+rule insertion-sort ( s * : ordered * )
+{
+ if ! $(ordered)
+ {
+ return [ SORT $(s) ] ;
+ }
+ else
+ {
+ local caller = [ CALLER_MODULE ] ;
+ ordered ?= sequence.less ;
+ local result = $(s[1]) ;
+ if $(ordered) = sequence.less
+ {
+ local head tail ;
+ for local x in $(s[2-])
+ {
+ head = ;
+ tail = $(result) ;
+ while $(tail) && ( $(tail[1]) < $(x) )
+ {
+ head += $(tail[1]) ;
+ tail = $(tail[2-]) ;
+ }
+ result = $(head) $(x) $(tail) ;
+ }
+ }
+ else
+ {
+ for local x in $(s[2-])
+ {
+ local head tail ;
+ tail = $(result) ;
+ while $(tail) && [ modules.call-in $(caller) : $(ordered) $(tail[1]) $(x) ]
+ {
+ head += $(tail[1]) ;
+ tail = $(tail[2-]) ;
+ }
+ result = $(head) $(x) $(tail) ;
+ }
+ }
+
+ return $(result) ;
+ }
+}
+
+
+# Merge two ordered sequences using the BinaryPredicate ordered.
+#
+rule merge ( s1 * : s2 * : ordered * )
+{
+ ordered ?= sequence.less ;
+ local result__ ;
+ local caller = [ CALLER_MODULE ] ;
+
+ while $(s1) && $(s2)
+ {
+ if [ modules.call-in $(caller) : $(ordered) $(s1[1]) $(s2[1]) ]
+ {
+ result__ += $(s1[1]) ;
+ s1 = $(s1[2-]) ;
+ }
+ else if [ modules.call-in $(caller) : $(ordered) $(s2[1]) $(s1[1]) ]
+ {
+ result__ += $(s2[1]) ;
+ s2 = $(s2[2-]) ;
+ }
+ else
+ {
+ s2 = $(s2[2-]) ;
+ }
+
+ }
+ result__ += $(s1) ;
+ result__ += $(s2) ;
+
+ return $(result__) ;
+}
+
+
+# Join the elements of s into one long string. If joint is supplied, it is used
+# as a separator.
+#
+rule join ( s * : joint ? )
+{
+ joint ?= "" ;
+ return $(s:J=$(joint)) ;
+}
+
+
+# Find the length of any sequence.
+#
+rule length ( s * )
+{
+ local result = 0 ;
+ for local i in $(s)
+ {
+ result = [ CALC $(result) + 1 ] ;
+ }
+ return $(result) ;
+}
+
+
+rule unique ( list * : stable ? )
+{
+ local result ;
+ local prev ;
+ if $(stable)
+ {
+ for local f in $(list)
+ {
+ if ! $(f) in $(result)
+ {
+ result += $(f) ;
+ }
+ }
+ }
+ else
+ {
+ for local i in [ SORT $(list) ]
+ {
+ if $(i) != $(prev)
+ {
+ result += $(i) ;
+ }
+ prev = $(i) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Returns the maximum number in 'elements'. Uses 'ordered' for comparisons or
+# 'numbers.less' if none is provided.
+#
+rule max-element ( elements + : ordered ? )
+{
+ ordered ?= numbers.less ;
+
+ local max = $(elements[1]) ;
+ for local e in $(elements[2-])
+ {
+ if [ $(ordered) $(max) $(e) ]
+ {
+ max = $(e) ;
+ }
+ }
+ return $(max) ;
+}
+
+
+# Returns all of 'elements' for which corresponding element in parallel list
+# 'rank' is equal to the maximum value in 'rank'.
+#
+rule select-highest-ranked ( elements * : ranks * )
+{
+ if $(elements)
+ {
+ local max-rank = [ max-element $(ranks) ] ;
+ local result ;
+ while $(elements)
+ {
+ if $(ranks[1]) = $(max-rank)
+ {
+ result += $(elements[1]) ;
+ }
+ elements = $(elements[2-]) ;
+ ranks = $(ranks[2-]) ;
+ }
+ return $(result) ;
+ }
+}
+NATIVE_RULE sequence : select-highest-ranked ;
+
+
+rule __test__ ( )
+{
+ # Use a unique module so we can test the use of local rules.
+ module sequence.__test__
+ {
+ import assert ;
+ import sequence ;
+
+ local rule is-even ( n )
+ {
+ if $(n) in 0 2 4 6 8
+ {
+ return true ;
+ }
+ }
+
+ assert.result 4 6 4 2 8 : sequence.filter is-even : 1 4 6 3 4 7 2 3 8 ;
+
+ # Test that argument binding works.
+ local rule is-equal-test ( x y )
+ {
+ if $(x) = $(y)
+ {
+ return true ;
+ }
+ }
+
+ assert.result 3 3 3 : sequence.filter is-equal-test 3 : 1 2 3 4 3 5 3 5 7 ;
+
+ local rule append-x ( n )
+ {
+ return $(n)x ;
+ }
+
+ assert.result 1x 2x 3x : sequence.transform append-x : 1 2 3 ;
+
+ local rule repeat2 ( x )
+ {
+ return $(x) $(x) ;
+ }
+
+ assert.result 1 1 2 2 3 3 : sequence.transform repeat2 : 1 2 3 ;
+
+ local rule test-greater ( a b )
+ {
+ if $(a) > $(b)
+ {
+ return true ;
+ }
+ }
+ assert.result 1 2 3 4 5 6 7 8 9 : sequence.insertion-sort 9 6 5 3 8 7 1 2 4 ;
+ assert.result 9 8 7 6 5 4 3 2 1 : sequence.insertion-sort 9 6 5 3 8 7 1 2 4 : test-greater ;
+ assert.result 1 2 3 4 5 6 : sequence.merge 1 3 5 : 2 4 6 ;
+ assert.result 6 5 4 3 2 1 : sequence.merge 5 3 1 : 6 4 2 : test-greater ;
+ assert.result 1 2 3 : sequence.merge 1 2 3 : ;
+ assert.result 1 : sequence.merge 1 : 1 ;
+
+ assert.result foo-bar-baz : sequence.join foo bar baz : - ;
+ assert.result substandard : sequence.join sub stan dard ;
+ assert.result 3.0.1 : sequence.join 3.0.1 : - ;
+
+ assert.result 0 : sequence.length ;
+ assert.result 3 : sequence.length a b c ;
+ assert.result 17 : sequence.length 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 ;
+
+ assert.result 1 : sequence.length a ;
+ assert.result 10 : sequence.length a b c d e f g h i j ;
+ assert.result 11 : sequence.length a b c d e f g h i j k ;
+ assert.result 12 : sequence.length a b c d e f g h i j k l ;
+
+ local p2 = x ;
+ for local i in 1 2 3 4 5 6 7 8
+ {
+ p2 = $(p2) $(p2) ;
+ }
+ assert.result 256 : sequence.length $(p2) ;
+
+ assert.result 1 2 3 4 5 : sequence.unique 1 2 3 2 4 3 3 5 5 5 ;
+
+ assert.result 5 : sequence.max-element 1 3 5 0 4 ;
+
+ assert.result e-3 h-3 : sequence.select-highest-ranked e-1 e-3 h-3 m-2 : 1 3 3 2 ;
+
+ assert.result 7 6 5 4 3 2 1 : sequence.reverse 1 2 3 4 5 6 7 ;
+ }
+}
diff --git a/tools/build/v2/util/sequence.py b/tools/build/v2/util/sequence.py
new file mode 100644
index 0000000000..1d32efd2e3
--- /dev/null
+++ b/tools/build/v2/util/sequence.py
@@ -0,0 +1,50 @@
+# (C) Copyright David Abrahams 2002. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+import operator
+
+def unique (values, stable=False):
+ if stable:
+ s = set()
+ r = []
+ for v in values:
+ if not v in s:
+ r.append(v)
+ s.add(v)
+ return r
+ else:
+ return list(set(values))
+
+def max_element (elements, ordered = None):
+ """ Returns the maximum number in 'elements'. Uses 'ordered' for comparisons,
+ or '<' is none is provided.
+ """
+ if not ordered: ordered = operator.lt
+
+ max = elements [0]
+ for e in elements [1:]:
+ if ordered (max, e):
+ max = e
+
+ return max
+
+def select_highest_ranked (elements, ranks):
+ """ Returns all of 'elements' for which corresponding element in parallel
+ list 'rank' is equal to the maximum value in 'rank'.
+ """
+ if not elements:
+ return []
+
+ max_rank = max_element (ranks)
+
+ result = []
+ while elements:
+ if ranks [0] == max_rank:
+ result.append (elements [0])
+
+ elements = elements [1:]
+ ranks = ranks [1:]
+
+ return result
diff --git a/tools/build/v2/util/set.jam b/tools/build/v2/util/set.jam
new file mode 100644
index 0000000000..fc179134f3
--- /dev/null
+++ b/tools/build/v2/util/set.jam
@@ -0,0 +1,93 @@
+# Copyright 2001, 2002 Dave Abrahams
+# Copyright 2003 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+class set
+{
+ rule __init__ ( )
+ {
+ }
+
+ rule add ( elements * )
+ {
+ for local e in $(elements)
+ {
+ if ! $($(e))
+ {
+ $(e) = 1 ;
+ self.result += $(e) ;
+ }
+ }
+ }
+
+ rule contains ( element )
+ {
+ return $($(element)) ;
+ }
+
+ rule list ( )
+ {
+ return $(self.result) ;
+ }
+}
+
+
+
+# Returns the elements of set1 that are not in set2.
+#
+rule difference ( set1 * : set2 * )
+{
+ local result = ;
+ for local element in $(set1)
+ {
+ if ! ( $(element) in $(set2) )
+ {
+ result += $(element) ;
+ }
+ }
+ return $(result) ;
+}
+
+NATIVE_RULE set : difference ;
+
+
+# Removes all the items appearing in both set1 & set2.
+#
+rule intersection ( set1 * : set2 * )
+{
+ local result ;
+ for local v in $(set1)
+ {
+ if $(v) in $(set2)
+ {
+ result += $(v) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Returns whether set1 & set2 contain the same elements. Note that this ignores
+# any element ordering differences as well as any element duplication.
+#
+rule equal ( set1 * : set2 * )
+{
+ if $(set1) in $(set2) && ( $(set2) in $(set1) )
+ {
+ return true ;
+ }
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+
+ assert.result 0 1 4 6 8 9 : difference 0 1 2 3 4 5 6 7 8 9 : 2 3 5 7 ;
+ assert.result 2 5 7 : intersection 0 1 2 4 5 6 7 8 9 : 2 3 5 7 ;
+
+ assert.true equal : ;
+ assert.true equal 1 1 2 3 : 3 2 2 1 ;
+ assert.false equal 2 3 : 3 2 2 1 ;
+}
diff --git a/tools/build/v2/util/set.py b/tools/build/v2/util/set.py
new file mode 100644
index 0000000000..dc7cf32822
--- /dev/null
+++ b/tools/build/v2/util/set.py
@@ -0,0 +1,42 @@
+# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+from utility import to_seq
+
+def difference (b, a):
+ """ Returns the elements of B that are not in A.
+ """
+ result = []
+ for element in b:
+ if not element in a:
+ result.append (element)
+
+ return result
+
+def intersection (set1, set2):
+ """ Removes from set1 any items which don't appear in set2 and returns the result.
+ """
+ result = []
+ for v in set1:
+ if v in set2:
+ result.append (v)
+ return result
+
+def contains (small, large):
+ """ Returns true iff all elements of 'small' exist in 'large'.
+ """
+ small = to_seq (small)
+ large = to_seq (large)
+
+ for s in small:
+ if not s in large:
+ return False
+ return True
+
+def equal (a, b):
+ """ Returns True iff 'a' contains the same elements as 'b', irrespective of their order.
+ # TODO: Python 2.4 has a proper set class.
+ """
+ return contains (a, b) and contains (b, a)
diff --git a/tools/build/v2/util/string.jam b/tools/build/v2/util/string.jam
new file mode 100644
index 0000000000..a39ed119e2
--- /dev/null
+++ b/tools/build/v2/util/string.jam
@@ -0,0 +1,189 @@
+# Copyright 2002 Dave Abrahams
+# Copyright 2002, 2003 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import regex ;
+
+
+# Characters considered whitespace, as a list.
+.whitespace-chars = " " " " "
+" ;
+
+# Characters considered whitespace, as a single string.
+.whitespace = $(.whitespace-chars:J="") ;
+
+
+# Returns the canonical set of whitespace characters, as a list.
+#
+rule whitespace-chars ( )
+{
+ return $(.whitespace-chars) ;
+}
+
+
+# Returns the canonical set of whitespace characters, as a single string.
+#
+rule whitespace ( )
+{
+ return $(.whitespace) ;
+}
+
+
+# Splits the given string into a list of strings composed of each character of
+# the string in sequence.
+#
+rule chars (
+ string # The string to split.
+ )
+{
+ local result ;
+ while $(string)
+ {
+ local s = [ MATCH (.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.*) : $(string) ] ;
+ string = $(s[9]) ;
+ result += $(s[1-8]) ;
+ }
+
+ # Trim off empty strings.
+ while $(result[1]) && ! $(result[-1])
+ {
+ result = $(result[1--2]) ;
+ }
+
+ return $(result) ;
+}
+
+
+# Apply a set of standard transformations to string to produce an abbreviation
+# no more than 5 characters long.
+#
+rule abbreviate ( string )
+{
+ local r = $(.abbreviated-$(string)) ;
+ if $(r)
+ {
+ return $(r) ;
+ }
+ # Anything less than 4 characters gets no abbreviation.
+ else if ! [ MATCH (....) : $(string) ]
+ {
+ .abbreviated-$(string) = $(string) ;
+ return $(string) ;
+ }
+ else
+ {
+ # Separate the initial letter in case it's a vowel.
+ local s1 = [ MATCH ^(.)(.*) : $(string) ] ;
+
+ # Drop trailing "ing".
+ local s2 = [ MATCH ^(.*)ing$ : $(s1[2]) ] ;
+ s2 ?= $(s1[2]) ;
+
+ # Reduce all doubled characters to one.
+ local last = "" ;
+ for local c in [ chars $(s2) ]
+ {
+ if $(c) != $(last)
+ {
+ r += $(c) ;
+ last = $(c) ;
+ }
+ }
+ s2 = $(r:J="") ;
+
+ # Chop all vowels out of the remainder.
+ s2 = [ regex.replace $(s2) [AEIOUaeiou] "" ] ;
+
+ # Shorten remaining consonants to 4 characters.
+ s2 = [ MATCH ^(.?.?.?.?) : $(s2) ] ;
+
+ # Glue the initial character back on to the front.
+ s2 = $(s1[1])$(s2) ;
+
+ .abbreviated-$(string) = $(s2) ;
+ return $(s2) ;
+ }
+}
+
+
+# Concatenates the given strings, inserting the given separator between each
+# string.
+#
+rule join (
+ strings * # The strings to join.
+ : separator ? # The optional separator.
+ )
+{
+ separator ?= "" ;
+ return $(strings:J=$(separator)) ;
+}
+
+
+# Split a string into whitespace separated words.
+#
+rule words (
+ string # The string to split.
+ : whitespace * # Optional, characters to consider as whitespace.
+ )
+{
+ whitespace = $(whitespace:J="") ;
+ whitespace ?= $(.whitespace) ;
+ local w = ;
+ while $(string)
+ {
+ string = [ MATCH "^[$(whitespace)]*([^$(whitespace)]*)(.*)" : $(string) ] ;
+ if $(string[1]) && $(string[1]) != ""
+ {
+ w += $(string[1]) ;
+ }
+ string = $(string[2]) ;
+ }
+ return $(w) ;
+}
+
+
+# Check that the given string is composed entirely of whitespace.
+#
+rule is-whitespace (
+ string ? # The string to test.
+ )
+{
+ if ! $(string) { return true ; }
+ else if $(string) = "" { return true ; }
+ else if [ MATCH "^([$(.whitespace)]+)$" : $(string) ] { return true ; }
+ else { return ; }
+}
+
+rule __test__ ( )
+{
+ import assert ;
+ assert.result a b c : chars abc ;
+
+ assert.result rntm : abbreviate runtime ;
+ assert.result ovrld : abbreviate overload ;
+ assert.result dbg : abbreviate debugging ;
+ assert.result async : abbreviate asynchronous ;
+ assert.result pop : abbreviate pop ;
+ assert.result aaa : abbreviate aaa ;
+ assert.result qck : abbreviate quack ;
+ assert.result sttc : abbreviate static ;
+
+ # Check boundary cases.
+ assert.result a : chars a ;
+ assert.result : chars "" ;
+ assert.result a b c d e f g h : chars abcdefgh ;
+ assert.result a b c d e f g h i : chars abcdefghi ;
+ assert.result a b c d e f g h i j : chars abcdefghij ;
+ assert.result a b c d e f g h i j k : chars abcdefghijk ;
+
+ assert.result a//b/c/d : join a "" b c d : / ;
+ assert.result abcd : join a "" b c d ;
+
+ assert.result a b c : words "a b c" ;
+
+ assert.true is-whitespace " " ;
+ assert.false is-whitespace " a b c " ;
+ assert.true is-whitespace "" ;
+ assert.true is-whitespace ;
+}
diff --git a/tools/build/v2/util/utility.jam b/tools/build/v2/util/utility.jam
new file mode 100644
index 0000000000..c46747f586
--- /dev/null
+++ b/tools/build/v2/util/utility.jam
@@ -0,0 +1,235 @@
+# Copyright 2001, 2002 Dave Abrahams
+# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
+# Copyright 2008 Jurko Gospodnetic
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import "class" : is-instance ;
+import errors ;
+
+
+# For all elements of 'list' which do not already have 'suffix', add 'suffix'.
+#
+rule apply-default-suffix ( suffix : list * )
+{
+ local result ;
+ for local i in $(list)
+ {
+ if $(i:S) = $(suffix)
+ {
+ result += $(i) ;
+ }
+ else
+ {
+ result += $(i)$(suffix) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# If 'name' contains a dot, returns the part before the last dot. If 'name'
+# contains no dot, returns it unmodified.
+#
+rule basename ( name )
+{
+ if $(name:S)
+ {
+ name = $(name:B) ;
+ }
+ return $(name) ;
+}
+
+
+# Return the file of the caller of the rule that called caller-file.
+#
+rule caller-file ( )
+{
+ local bt = [ BACKTRACE ] ;
+ return $(bt[9]) ;
+}
+
+
+# Tests if 'a' is equal to 'b'. If 'a' is a class instance, calls its 'equal'
+# method. Uses ordinary jam's comparison otherwise.
+#
+rule equal ( a b )
+{
+ if [ is-instance $(a) ]
+ {
+ return [ $(a).equal $(b) ] ;
+ }
+ else
+ {
+ if $(a) = $(b)
+ {
+ return true ;
+ }
+ }
+}
+
+
+# Tests if 'a' is less than 'b'. If 'a' is a class instance, calls its 'less'
+# method. Uses ordinary jam's comparison otherwise.
+#
+rule less ( a b )
+{
+ if [ is-instance $(a) ]
+ {
+ return [ $(a).less $(b) ] ;
+ }
+ else
+ {
+ if $(a) < $(b)
+ {
+ return true ;
+ }
+ }
+}
+
+
+# Returns the textual representation of argument. If it is a class instance,
+# class its 'str' method. Otherwise, returns the argument.
+#
+rule str ( value )
+{
+ if [ is-instance $(value) ]
+ {
+ return [ $(value).str ] ;
+ }
+ else
+ {
+ return $(value) ;
+ }
+}
+
+
+# Accepts a list of gristed values and returns them ungristed. Reports an error
+# in case any of the passed parameters is not gristed, i.e. surrounded in angle
+# brackets < and >.
+#
+rule ungrist ( names * )
+{
+ local result ;
+ for local name in $(names)
+ {
+ local stripped = [ MATCH ^<(.*)>$ : $(name) ] ;
+ if ! $(stripped)
+ {
+ errors.error "in ungrist $(names) : $(name) is not of the form <.*>" ;
+ }
+ result += $(stripped) ;
+ }
+ return $(result) ;
+}
+
+
+# If the passed value is quoted, unquotes it. Otherwise returns the value
+# unchanged.
+#
+rule unquote ( value ? )
+{
+ local match-result = [ MATCH ^(\")(.*)(\")$ : $(value) ] ;
+ if $(match-result)
+ {
+ return $(match-result[2]) ;
+ }
+ else
+ {
+ return $(value) ;
+ }
+}
+
+
+rule __test__ ( )
+{
+ import assert ;
+ import "class" : new ;
+ import errors : try catch ;
+
+ assert.result 123 : str 123 ;
+
+ class test-class__
+ {
+ rule __init__ ( ) { }
+ rule str ( ) { return "str-test-class" ; }
+ rule less ( a ) { return "yes, of course!" ; }
+ rule equal ( a ) { return "not sure" ; }
+ }
+
+ assert.result "str-test-class" : str [ new test-class__ ] ;
+ assert.true less 1 2 ;
+ assert.false less 2 1 ;
+ assert.result "yes, of course!" : less [ new test-class__ ] 1 ;
+ assert.true equal 1 1 ;
+ assert.false equal 1 2 ;
+ assert.result "not sure" : equal [ new test-class__ ] 1 ;
+
+ assert.result foo.lib foo.lib : apply-default-suffix .lib : foo.lib foo.lib
+ ;
+
+ assert.result foo : basename foo ;
+ assert.result foo : basename foo.so ;
+ assert.result foo.so : basename foo.so.1 ;
+
+ assert.result : unquote ;
+ assert.result "" : unquote "" ;
+ assert.result foo : unquote foo ;
+ assert.result \"foo : unquote \"foo ;
+ assert.result foo\" : unquote foo\" ;
+ assert.result foo : unquote \"foo\" ;
+ assert.result \"foo\" : unquote \"\"foo\"\" ;
+
+ assert.result : ungrist ;
+ assert.result foo : ungrist <foo> ;
+ assert.result <foo> : ungrist <<foo>> ;
+ assert.result foo bar : ungrist <foo> <bar> ;
+
+ try ;
+ {
+ ungrist "" ;
+ }
+ catch "in ungrist : is not of the form <.*>" ;
+
+ try ;
+ {
+ ungrist <> ;
+ }
+ catch "in ungrist <> : <> is not of the form <.*>" ;
+
+ try ;
+ {
+ ungrist foo ;
+ }
+ catch "in ungrist foo : foo is not of the form <.*>" ;
+
+ try ;
+ {
+ ungrist <foo ;
+ }
+ catch "in ungrist <foo : <foo is not of the form <.*>" ;
+
+ try ;
+ {
+ ungrist foo> ;
+ }
+ catch "in ungrist foo> : foo> is not of the form <.*>" ;
+
+ try ;
+ {
+ ungrist foo bar ;
+ }
+ catch "in ungrist foo : foo is not of the form <.*>" ;
+
+ try ;
+ {
+ ungrist foo <bar> ;
+ }
+ catch "in ungrist foo : foo is not of the form <.*>" ;
+
+ try ;
+ {
+ ungrist <foo> bar ;
+ }
+ catch "in ungrist bar : bar is not of the form <.*>" ;
+}
diff --git a/tools/build/v2/util/utility.py b/tools/build/v2/util/utility.py
new file mode 100644
index 0000000000..afea765b97
--- /dev/null
+++ b/tools/build/v2/util/utility.py
@@ -0,0 +1,155 @@
+# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
+# distribute this software is granted provided this copyright notice appears in
+# all copies. This software is provided "as is" without express or implied
+# warranty, and with no claim as to its suitability for any purpose.
+
+""" Utility functions to add/remove/get grists.
+ Grists are string enclosed in angle brackets (<>) that are used as prefixes. See Jam for more information.
+"""
+
+import re
+import os
+import bjam
+from b2.exceptions import *
+
+__re_grist_and_value = re.compile (r'(<[^>]*>)(.*)')
+__re_grist_content = re.compile ('^<(.*)>$')
+__re_backslash = re.compile (r'\\')
+
+def to_seq (value):
+ """ If value is a sequence, returns it.
+ If it is a string, returns a sequence with value as its sole element.
+ """
+ if not value:
+ return []
+
+ if isinstance (value, str):
+ return [value]
+
+ else:
+ return value
+
+def replace_references_by_objects (manager, refs):
+ objs = []
+ for r in refs:
+ objs.append (manager.get_object (r))
+ return objs
+
+def add_grist (features):
+ """ Transform a string by bracketing it with "<>". If already bracketed, does nothing.
+ features: one string or a sequence of strings
+ return: the gristed string, if features is a string, or a sequence of gristed strings, if features is a sequence
+ """
+
+ def grist_one (feature):
+ if feature [0] != '<' and feature [len (feature) - 1] != '>':
+ return '<' + feature + '>'
+ else:
+ return feature
+
+ if isinstance (features, str):
+ return grist_one (features)
+ else:
+ return [ grist_one (feature) for feature in features ]
+
+def replace_grist (features, new_grist):
+ """ Replaces the grist of a string by a new one.
+ Returns the string with the new grist.
+ """
+ def replace_grist_one (name, new_grist):
+ split = __re_grist_and_value.match (name)
+ if not split:
+ return new_grist + name
+ else:
+ return new_grist + split.group (2)
+
+ if isinstance (features, str):
+ return replace_grist_one (features, new_grist)
+ else:
+ return [ replace_grist_one (feature, new_grist) for feature in features ]
+
+def get_value (property):
+ """ Gets the value of a property, that is, the part following the grist, if any.
+ """
+ return replace_grist (property, '')
+
+def get_grist (value):
+ """ Returns the grist of a string.
+ If value is a sequence, does it for every value and returns the result as a sequence.
+ """
+ def get_grist_one (name):
+ split = __re_grist_and_value.match (name)
+ if not split:
+ return ''
+ else:
+ return split.group (1)
+
+ if isinstance (value, str):
+ return get_grist_one (value)
+ else:
+ return [ get_grist_one (v) for v in value ]
+
+def ungrist (value):
+ """ Returns the value without grist.
+ If value is a sequence, does it for every value and returns the result as a sequence.
+ """
+ def ungrist_one (value):
+ stripped = __re_grist_content.match (value)
+ if not stripped:
+ raise BaseException ("in ungrist: '%s' is not of the form <.*>" % value)
+
+ return stripped.group (1)
+
+ if isinstance (value, str):
+ return ungrist_one (value)
+ else:
+ return [ ungrist_one (v) for v in value ]
+
+def replace_suffix (name, new_suffix):
+ """ Replaces the suffix of name by new_suffix.
+ If no suffix exists, the new one is added.
+ """
+ split = os.path.splitext (name)
+ return split [0] + new_suffix
+
+def forward_slashes (s):
+ """ Converts all backslashes to forward slashes.
+ """
+ return __re_backslash.sub ('/', s)
+
+
+def split_action_id (id):
+ """ Splits an id in the toolset and specific rule parts. E.g.
+ 'gcc.compile.c++' returns ('gcc', 'compile.c++')
+ """
+ split = id.split ('.', 1)
+ toolset = split [0]
+ name = ''
+ if len (split) > 1:
+ name = split [1]
+ return (toolset, name)
+
+def os_name ():
+ result = bjam.variable("OS")
+ assert(len(result) == 1)
+ return result[0]
+
+def platform ():
+ return bjam.variable("OSPLAT")
+
+def os_version ():
+ return bjam.variable("OSVER")
+
+def on_windows ():
+ """ Returns true if running on windows, whether in cygwin or not.
+ """
+ if bjam.variable("NT"):
+ return True
+
+ elif bjam.variable("UNIX"):
+
+ uname = bjam.variable("JAMUNAME")
+ if uname and uname[0].startswith("CYGWIN"):
+ return True
+
+ return False
diff --git a/tools/index.html b/tools/index.html
new file mode 100644
index 0000000000..77f7f59cd8
--- /dev/null
+++ b/tools/index.html
@@ -0,0 +1,112 @@
+<!-- Copyright 2004 Aleksey Gurtovoy -->
+<!-- Copyright 2003 Beman Dawes -->
+<!-- Copyright 2003 Douglas Gregor -->
+<!-- Copyright 2005 Eric Niebler -->
+<!-- Copyright 2005 Hartmut Kaiser -->
+<!-- Copyright 2004 John Maddock -->
+<!-- Distributed under the Boost Software License, Version 1.0. -->
+<!-- (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) -->
+
+<html>
+ <head>
+ <title>Boost Tools</title>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta name="GENERATOR" content="Microsoft FrontPage 5.0">
+ <meta name="ProgId" content="FrontPage.Editor.Document">
+ <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+ <link rel="stylesheet" href="../doc/src/boostbook.css" type="text/css" />
+ </head>
+ <body bgcolor="#ffffff">
+
+ <table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
+ <tr>
+ <td width="277">
+ <a href="../index.html">
+ <img src="../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86" border="0"></a></td>
+ <td width="337" align="middle">
+ <font size="7">Tools</font>
+ </td>
+ </tr>
+ </table>
+
+ <table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF" height="26" width="681">
+ <tr>
+ <td height="16" width="671"><a href="../more/getting_started/index.html">Getting Started</a>&nbsp;&nbsp;<font color="#FFFFFF">&nbsp;
+ </font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="../libs/libraries.htm">
+ Libraries</a><a href="../tools/index.html">&nbsp;</a>&nbsp;<font color="#FFFFFF">&nbsp;
+ </font>&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://www.boost.org">Web Site</a>&nbsp;&nbsp;<font color="#FFFFFF">&nbsp;
+ </font>&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://www.boost.org/users/news/">News</a>&nbsp;&nbsp;<font color="#FFFFFF">&nbsp;
+ </font>&nbsp;&nbsp;&nbsp; <a href="http://www.boost.org/community/">Community</a>&nbsp;&nbsp;<font color="#FFFFFF">&nbsp;
+ </font>&nbsp;&nbsp;&nbsp;&nbsp;
+ <a href="http://www.boost.org/users/faq.html">FAQ</a>&nbsp;&nbsp;<font color="#FFFFFF">&nbsp;
+ </font>&nbsp;&nbsp;&nbsp;&nbsp; <a href="../more/index.htm">More Info</a>&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>Boost developers, testers, and maintainers have developed various tools to
+ help with the administration of the Boost Libraries. Like everything else about
+ Boost, these tools are available in source form, and are part of the regular
+ Boost distribution.</p>
+ <p>Users may find these tools useful when porting Boost libraries to a new
+ platform, or for use with their own applications.</p>
+ <ul>
+ <li>
+ <a href="build/index.html">Boost.Build</a> - The Boost build system, including
+ the full Boost version of the jam sources.<br>
+ &nbsp;
+ <li>
+ <a href="regression/index.html">Regression</a> - The Boost regression testing
+ system reporting sources.<br>
+&nbsp;<li>
+ <a href="release/index.html">Release</a> - Scripts used to build the
+ release tarballs and zips.<br>
+ &nbsp;
+ <li>
+ <a href="inspect/index.html">Inspect </a>- The inspection tool used to detect
+ errors in the Boost directory hierarchy.<br>
+ &nbsp;
+ <li>
+ <a href="../doc/html/boostbook.html">BoostBook</a> - A Boost documentation
+ system, based on <a href="http://www.docbook.org/">DocBook</a> and the <a href="http://www.w3.org/Style/XSL/">
+ Extensible Stylesheet Language (XSL)</a>, used by some Boost libraries.<br>
+ &nbsp;
+ <li>
+ <a href="bcp/index.html">bcp</a> - A utility to extract subsets of Boost; to
+ determine which parts of Boost your code is using; and to print reports on
+ Boost usage (including Licence information).<br>
+ &nbsp;
+ <li>
+ <a href="quickbook/index.html">QuickBook</a> - QuickBook is a WikiWiki style
+ documentation tool geared towards C++ documentation using simple rules and markup
+ for simple formatting tasks. QuickBook generates <a href="../doc/html/boostbook.html">
+ BoostBook</a> XML.<br>
+ &nbsp;
+ <li>
+ <a href="../libs/wave/doc/wave_driver.html">Wave</a> - A Standards conformant C/C++
+ preprocessor usable on top of any other compiler. Usable for instance for the debugging
+ of the expansion of macros in your code or as a replacement for your built-in
+ preprocessor. <br>
+ &nbsp;
+ <li>
+ <a href="auto_index/index.html">AutoIndex</a> - A tool for indexing Boostbook/Docbook
+ documents. <br>
+ &nbsp;
+ </li>
+ </ul>
+ <hr>
+ <p>Revised
+<!--webbot bot="Timestamp" s-type="EDITED"
+s-format="%d %b %Y" startspan -->13 Mar 2008<!--webbot bot="Timestamp" endspan i-checksum="14911" --></p>
+
+<p>© Copyright Beman Dawes 2003<br>
+© Copyright Douglas Gregor 2003<br>
+© Copyright Aleksey Gurtovoy 2004<br>
+© Copyright John Maddock 2004<br>
+© Copyright Eric Niebler 2005<br>
+© Copyright Hartmut Kaiser 2005<br>
+<br>
+Distributed under the Boost Software License, Version 1.0.
+(See file <a href="../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
+or <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>) </p>
+ </body>
+</html>
diff --git a/tools/inspect/apple_macro_check.cpp b/tools/inspect/apple_macro_check.cpp
new file mode 100644
index 0000000000..ce917e0d8a
--- /dev/null
+++ b/tools/inspect/apple_macro_check.cpp
@@ -0,0 +1,105 @@
+// apple_macro_check implementation ------------------------------------------------//
+
+// Copyright Marshall Clow 2007.
+// Based on the tab-check checker by Beman Dawes
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "apple_macro_check.hpp"
+#include <functional>
+#include "boost/regex.hpp"
+#include "boost/lexical_cast.hpp"
+#include "boost/filesystem/operations.hpp"
+
+namespace fs = boost::filesystem;
+
+namespace
+{
+ boost::regex apple_macro_regex(
+ "("
+ "^\\s*#\\s*undef\\s*" // # undef
+ "\\b(check|verify|require|check_error)\\b" // followed by apple macro name, whole word
+ ")"
+ "|" // or (ignored)
+ "("
+ "//[^\\n]*" // single line comments (//)
+ "|"
+ "/\\*.*?\\*/" // multi line comments (/**/)
+ "|"
+ "\"(?:\\\\\\\\|\\\\\"|[^\"])*\"" // string literals
+ ")"
+ "|" // or
+ "("
+ "\\b(check|verify|require|check_error)\\b" // apple macro name, whole word
+ "\\s*\\(" // followed by 0 or more spaces and an opening paren
+ ")"
+ , boost::regex::normal);
+
+} // unnamed namespace
+
+
+namespace boost
+{
+ namespace inspect
+ {
+ apple_macro_check::apple_macro_check() : m_files_with_errors(0)
+ {
+ register_signature( ".c" );
+ register_signature( ".cpp" );
+ register_signature( ".cxx" );
+ register_signature( ".h" );
+ register_signature( ".hpp" );
+ register_signature( ".hxx" );
+ register_signature( ".ipp" );
+ }
+
+ void apple_macro_check::inspect(
+ const string & library_name,
+ const path & full_path, // example: c:/foo/boost/filesystem/path.hpp
+ const string & contents ) // contents of file to be inspected
+ {
+ if (contents.find( "boostinspect:" "naapple_macros" ) != string::npos) return;
+
+ // Only check files in the boost directory, as we can avoid including the
+ // apple test headers elsewhere.
+ path relative( relative_to( full_path, fs::initial_path() ) );
+ if ( relative.empty() || *relative.begin() != "boost") return;
+
+ boost::sregex_iterator cur(contents.begin(), contents.end(), apple_macro_regex), end;
+
+ long errors = 0;
+
+ for( ; cur != end; ++cur /*, ++m_files_with_errors*/ )
+ {
+
+ if(!(*cur)[3].matched)
+ {
+ string::const_iterator it = contents.begin();
+ string::const_iterator match_it = (*cur)[0].first;
+
+ string::const_iterator line_start = it;
+
+ string::size_type line_number = 1;
+ for ( ; it != match_it; ++it) {
+ if (string::traits_type::eq(*it, '\n')) {
+ ++line_number;
+ line_start = it + 1; // could be end()
+ }
+ }
+
+ ++errors;
+ error( library_name, full_path,
+ "Apple macro clash: " + std::string((*cur)[0].first, (*cur)[0].second-1),
+ line_number );
+ }
+ }
+ if(errors > 0) {
+ ++m_files_with_errors;
+ }
+ }
+ } // namespace inspect
+} // namespace boost
+
+
diff --git a/tools/inspect/apple_macro_check.hpp b/tools/inspect/apple_macro_check.hpp
new file mode 100644
index 0000000000..5acdcf70c1
--- /dev/null
+++ b/tools/inspect/apple_macro_check.hpp
@@ -0,0 +1,39 @@
+// apple_macro_check header --------------------------------------------------------//
+
+// Copyright Marshall Clow 2007.
+// Based on the tab-check checker by Beman Dawes
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_APPLE_MACRO_CHECK_HPP
+#define BOOST_APPLE_MACRO_CHECK_HPP
+
+#include "inspector.hpp"
+
+
+namespace boost
+{
+ namespace inspect
+ {
+ class apple_macro_check : public inspector
+ {
+ long m_files_with_errors;
+ public:
+
+ apple_macro_check();
+ virtual const char * name() const { return "*APPLE-MACROS*"; }
+ virtual const char * desc() const { return "calls to Apple's debugging macros in file"; }
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path,
+ const std::string & contents );
+
+ virtual ~apple_macro_check()
+ { std::cout << " " << m_files_with_errors << " files with Apple macros" << line_break(); }
+ };
+ }
+}
+
+#endif // BOOST_APPLE_MACRO_CHECK_HPP
diff --git a/tools/inspect/ascii_check.cpp b/tools/inspect/ascii_check.cpp
new file mode 100644
index 0000000000..da2aa40201
--- /dev/null
+++ b/tools/inspect/ascii_check.cpp
@@ -0,0 +1,102 @@
+// ascii_check implementation ------------------------------------------------//
+
+// Copyright Marshall Clow 2007.
+// Based on the tab-check checker by Beman Dawes
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+// √ -- this is a test.
+
+#include "ascii_check.hpp"
+#include <functional>
+
+namespace boost
+{
+ namespace inspect
+ {
+
+ static const string gPunct ( "$_{}[]#()<>%:;.?*+-/ˆ&|~!=,\\\"'@^`" );
+
+ // Legal characters for a source file are defined in section 2.2 of the standard
+ // I have added '@', '^', and '`' to the "legal" chars because they are commonly
+ // used in comments, and they are strictly ASCII.
+ struct non_ascii : public std::unary_function<char, bool> {
+ public:
+ non_ascii () {}
+ ~non_ascii () {}
+ bool operator () ( char c ) const
+ {
+ if ( c == ' ' ) return false;
+ if ( c >= 'a' && c <= 'z' ) return false;
+ if ( c >= 'A' && c <= 'Z' ) return false;
+ if ( c >= '0' && c <= '9' ) return false;
+ // Horizontal/Vertical tab, newline, and form feed
+ if ( c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f' ) return false;
+ return gPunct.find ( c ) == string::npos;
+ }
+ };
+
+ struct is_CRLF : public std::unary_function<char, bool> {
+ public:
+ is_CRLF () {}
+ ~is_CRLF () {}
+ bool operator () ( char c ) const
+ {
+ return c == '\015' || c == '\012';
+ }
+ };
+
+ const char *kCRLF = "\012\015";
+
+// Given a position in the file, extract and return the line
+ std::string find_line ( const std::string &contents, std::string::const_iterator iter_pos )
+ {
+ std::size_t pos = iter_pos - contents.begin ();
+
+ // Search backwards for a CR or LR
+ std::size_t start_pos = contents.find_last_of ( kCRLF, pos );
+ std::string::const_iterator line_start = contents.begin () + ( start_pos == std::string::npos ? 0 : start_pos + 1 );
+
+
+ // Search forwards for a CR or LF
+ std::size_t end_pos = contents.find_first_of ( kCRLF, pos + 1 );
+ std::string::const_iterator line_end;
+ if ( end_pos == std::string::npos )
+ line_end = contents.end ();
+ else
+ line_end = contents.begin () + end_pos - 1;
+
+ return std::string ( line_start, line_end );
+ }
+
+ ascii_check::ascii_check() : m_files_with_errors(0)
+ {
+ register_signature( ".c" );
+ register_signature( ".cpp" );
+ register_signature( ".cxx" );
+ register_signature( ".h" );
+ register_signature( ".hpp" );
+ register_signature( ".hxx" );
+ register_signature( ".ipp" );
+ }
+
+ void ascii_check::inspect(
+ const string & library_name,
+ const path & full_path, // example: c:/foo/boost/filesystem/path.hpp
+ const string & contents ) // contents of file to be inspected
+ {
+ if (contents.find( "boostinspect:" "noascii" ) != string::npos) return;
+ string::const_iterator bad_char = std::find_if ( contents.begin (), contents.end (), non_ascii ());
+ if ( bad_char != contents.end ())
+ {
+ ++m_files_with_errors;
+ int ln = std::count( contents.begin(), bad_char, '\n' ) + 1;
+ string the_line = find_line ( contents, bad_char );
+ error( library_name, full_path, "Non-ASCII: " + the_line, ln );
+ }
+ }
+ } // namespace inspect
+} // namespace boost
+
+
diff --git a/tools/inspect/ascii_check.hpp b/tools/inspect/ascii_check.hpp
new file mode 100644
index 0000000000..878909e31c
--- /dev/null
+++ b/tools/inspect/ascii_check.hpp
@@ -0,0 +1,38 @@
+// ascii_check header --------------------------------------------------------//
+
+// Copyright Marshall Clow 2007.
+// Based on the tab-check checker by Beman Dawes
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_ASCII_CHECK_HPP
+#define BOOST_ASCII_CHECK_HPP
+
+#include "inspector.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ class ascii_check : public inspector
+ {
+ long m_files_with_errors;
+ public:
+
+ ascii_check();
+ virtual const char * name() const { return "*ASCII*"; }
+ virtual const char * desc() const { return "non-ASCII chars in file"; }
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path,
+ const std::string & contents );
+
+ virtual ~ascii_check()
+ { std::cout << " " << m_files_with_errors << " files with non-ASCII chars" << line_break(); }
+ };
+ }
+}
+
+#endif // BOOST_TAB_CHECK_HPP
diff --git a/tools/inspect/assert_macro_check.cpp b/tools/inspect/assert_macro_check.cpp
new file mode 100644
index 0000000000..a91cb8a9f8
--- /dev/null
+++ b/tools/inspect/assert_macro_check.cpp
@@ -0,0 +1,110 @@
+// assert_macro_check implementation ------------------------------------------------//
+
+// Copyright Eric Niebler 2010.
+// Based on the assert_macro_check checker by Marshall Clow
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "assert_macro_check.hpp"
+#include <functional>
+#include "boost/regex.hpp"
+#include "boost/lexical_cast.hpp"
+#include "boost/filesystem/operations.hpp"
+
+namespace fs = boost::filesystem;
+
+namespace
+{
+ boost::regex assert_macro_regex(
+ "("
+ "^\\s*#\\s*undef\\s*" // # undef
+ "\\b(assert)\\b" // followed by assert macro, whole word
+ ")"
+ "|" // or (ignored)
+ "("
+ "//[^\\n]*" // single line comments (//)
+ "|"
+ "/\\*.*?\\*/" // multi line comments (/**/)
+ "|"
+ "\"(?:\\\\\\\\|\\\\\"|[^\"])*\"" // string literals
+ ")"
+ "|" // or
+ "("
+ "\\b(assert)\\b" // assert macro, whole word
+ "\\s*\\(" // followed by 0 or more spaces and an opening paren
+ ")"
+ , boost::regex::normal);
+
+} // unnamed namespace
+
+
+namespace boost
+{
+ namespace inspect
+ {
+ assert_macro_check::assert_macro_check()
+ : m_files_with_errors(0)
+ , m_from_boost_root(
+ fs::exists(fs::initial_path() / "boost") &&
+ fs::exists(fs::initial_path() / "libs"))
+ {
+ register_signature( ".c" );
+ register_signature( ".cpp" );
+ register_signature( ".cxx" );
+ register_signature( ".h" );
+ register_signature( ".hpp" );
+ register_signature( ".hxx" );
+ register_signature( ".ipp" );
+ }
+
+ void assert_macro_check::inspect(
+ const string & library_name,
+ const path & full_path, // example: c:/foo/boost/filesystem/path.hpp
+ const string & contents ) // contents of file to be inspected
+ {
+ if (contents.find( "boostinspect:" "naassert_macro" ) != string::npos)
+ return;
+
+ // Check files iff (a) they are in the boost directory, or (b) they
+ // are in the src directory under libs.
+ if (m_from_boost_root) {
+ path relative( relative_to( full_path, fs::initial_path() ) );
+ path::const_iterator pbeg = relative.begin(), pend = relative.end();
+ if (pbeg != std::find(pbeg, pend, "boost") &&
+ !(pbeg == std::find(pbeg, pend, "libs") && pend != std::find(pbeg, pend, "src")))
+ return;
+ }
+
+ long errors = 0;
+ boost::sregex_iterator cur(contents.begin(), contents.end(), assert_macro_regex), end;
+ for( ; cur != end; ++cur )
+ {
+ if(!(*cur)[3].matched)
+ {
+ string::const_iterator it = contents.begin();
+ string::const_iterator match_it = (*cur)[0].first;
+
+ string::const_iterator line_start = it;
+
+ string::size_type line_number = 1;
+ for ( ; it != match_it; ++it) {
+ if (string::traits_type::eq(*it, '\n')) {
+ ++line_number;
+ line_start = it + 1; // could be end()
+ }
+ }
+
+ ++errors;
+ error( library_name, full_path, "C-style assert macro on line "
+ + boost::lexical_cast<string>( line_number ) );
+ }
+ }
+ if(errors > 0)
+ ++m_files_with_errors;
+ }
+ } // namespace inspect
+} // namespace boost
+
+
diff --git a/tools/inspect/assert_macro_check.hpp b/tools/inspect/assert_macro_check.hpp
new file mode 100644
index 0000000000..c28a377f34
--- /dev/null
+++ b/tools/inspect/assert_macro_check.hpp
@@ -0,0 +1,40 @@
+// assert_macro_check header --------------------------------------------------------//
+
+// Copyright Eric Niebler 2010.
+// Based on the apple_macro_check checker by Marshall Clow
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_ASSERT_MACRO_CHECK_HPP
+#define BOOST_ASSERT_MACRO_CHECK_HPP
+
+#include "inspector.hpp"
+
+
+namespace boost
+{
+ namespace inspect
+ {
+ class assert_macro_check : public inspector
+ {
+ long m_files_with_errors;
+ bool m_from_boost_root;
+ public:
+
+ assert_macro_check();
+ virtual const char * name() const { return "*ASSERT-MACROS*"; }
+ virtual const char * desc() const { return "presence of C-style assert macro in file (use BOOST_ASSERT instead)"; }
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path,
+ const std::string & contents );
+
+ virtual ~assert_macro_check()
+ { std::cout << " " << m_files_with_errors << " files with a C-style assert macro" << line_break(); }
+ };
+ }
+}
+
+#endif // BOOST_ASSERT_MACRO_CHECK_HPP
diff --git a/tools/inspect/build/Jamfile.v2 b/tools/inspect/build/Jamfile.v2
new file mode 100644
index 0000000000..f9355baa32
--- /dev/null
+++ b/tools/inspect/build/Jamfile.v2
@@ -0,0 +1,55 @@
+# Inspect Jamfile
+
+# Copyright Vladimir Prus
+
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+project
+ :
+ requirements
+ :
+ source-location ..
+ ;
+
+exe inspect
+ :
+ apple_macro_check.cpp
+ ascii_check.cpp
+ assert_macro_check.cpp
+ copyright_check.cpp
+ crlf_check.cpp
+ end_check.cpp
+ inspect.cpp
+ license_check.cpp
+ link_check.cpp
+ minmax_check.cpp
+ path_name_check.cpp
+ tab_check.cpp
+ unnamed_namespace_check.cpp
+ /boost//filesystem/<link>static
+ /boost//regex/<link>static
+ :
+ :
+ release
+ ;
+
+install dist-bin
+ :
+ inspect
+ :
+ <install-type>EXE
+ <location>../../../dist/bin
+ :
+ release
+ ;
+
+install dist-lib
+ :
+ inspect
+ :
+ <install-type>LIB
+ <location>../../../dist/lib
+ :
+ release
+ ;
diff --git a/tools/inspect/build/msvc/boost_inspect.sln b/tools/inspect/build/msvc/boost_inspect.sln
new file mode 100644
index 0000000000..c01f5e330c
--- /dev/null
+++ b/tools/inspect/build/msvc/boost_inspect.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boost_inspect", "boost_inspect.vcproj", "{0EC8AC1C-6D1F-47FC-A06A-9CC3F924BD82}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0EC8AC1C-6D1F-47FC-A06A-9CC3F924BD82}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0EC8AC1C-6D1F-47FC-A06A-9CC3F924BD82}.Debug|Win32.Build.0 = Debug|Win32
+ {0EC8AC1C-6D1F-47FC-A06A-9CC3F924BD82}.Release|Win32.ActiveCfg = Release|Win32
+ {0EC8AC1C-6D1F-47FC-A06A-9CC3F924BD82}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/tools/inspect/build/msvc/boost_inspect.vcproj b/tools/inspect/build/msvc/boost_inspect.vcproj
new file mode 100644
index 0000000000..372c14b06f
--- /dev/null
+++ b/tools/inspect/build/msvc/boost_inspect.vcproj
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="inspect"
+ ProjectGUID="{0EC8AC1C-6D1F-47FC-A06A-9CC3F924BD82}"
+ RootNamespace="boost_inspect"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ ExceptionHandling="2"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="..\..\..\..\stage\lib"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\..\.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ ExceptionHandling="2"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="..\..\..\..\stage\lib"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\apple_macro_check.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\ascii_check.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\assert_macro_check.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\copyright_check.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\crlf_check.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\end_check.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\inspect.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\license_check.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\link_check.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\minmax_check.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\path_name_check.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tab_check.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\unnamed_namespace_check.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tools/inspect/build/msvc/readme.txt b/tools/inspect/build/msvc/readme.txt
new file mode 100644
index 0000000000..1f8de0cb28
--- /dev/null
+++ b/tools/inspect/build/msvc/readme.txt
@@ -0,0 +1,4 @@
+The provided Microsoft VC++ solution assumes the following commands have been run in the root directory:
+
+ bjam --toolset=msvc-9.0express --build-type=complete --with-filesystem stage
+ bjam --toolset=msvc-9.0express --build-type=complete --with-regex stage
diff --git a/tools/inspect/copyright_check.cpp b/tools/inspect/copyright_check.cpp
new file mode 100644
index 0000000000..f56bbc9550
--- /dev/null
+++ b/tools/inspect/copyright_check.cpp
@@ -0,0 +1,35 @@
+// copyright_check implementation ------------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "copyright_check.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ copyright_check::copyright_check() : m_files_with_errors(0)
+ {
+ }
+
+ void copyright_check::inspect(
+ const string & library_name,
+ const path & full_path, // example: c:/foo/boost/filesystem/path.hpp
+ const string & contents ) // contents of file to be inspected
+ {
+ if (contents.find( "boostinspect:" "nocopyright" ) != string::npos) return;
+
+ if ( contents.find( "Copyright" ) == string::npos
+ && contents.find( "copyright" ) == string::npos )
+ {
+ ++m_files_with_errors;
+ error( library_name, full_path, name() );
+ }
+ }
+ } // namespace inspect
+} // namespace boost
+
+
diff --git a/tools/inspect/copyright_check.hpp b/tools/inspect/copyright_check.hpp
new file mode 100644
index 0000000000..278596e3eb
--- /dev/null
+++ b/tools/inspect/copyright_check.hpp
@@ -0,0 +1,39 @@
+// copyright_check header --------------------------------------------------//
+
+// Copyright Beman Dawes 2002, 2003.
+// Copyright Rene Rivera 2004.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COPYRIGHT_CHECK_HPP
+#define BOOST_COPYRIGHT_CHECK_HPP
+
+#include "inspector.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ class copyright_check : public source_inspector
+ {
+ long m_files_with_errors;
+ public:
+
+ copyright_check();
+ virtual const char * name() const { return "*C*"; }
+ virtual const char * desc() const { return "missing copyright notice"; }
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path,
+ const std::string & contents );
+
+ virtual ~copyright_check()
+ { std::cout << " " << m_files_with_errors << " files " << desc() << line_break(); }
+ };
+ }
+}
+
+#endif // BOOST_COPYRIGHT_CHECK_HPP
diff --git a/tools/inspect/crlf_check.cpp b/tools/inspect/crlf_check.cpp
new file mode 100644
index 0000000000..c382711403
--- /dev/null
+++ b/tools/inspect/crlf_check.cpp
@@ -0,0 +1,97 @@
+// crlf_check implementation ------------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Contributed by Joerg Walter
+
+#include "crlf_check.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ crlf_check::crlf_check() : m_files_with_errors(0)
+ {
+ }
+
+ void crlf_check::inspect(
+ const string & library_name,
+ const path & full_path, // example: c:/foo/boost/filesystem/path.hpp
+ const string & contents ) // contents of file to be inspected
+ {
+ if (contents.find( "boostinspect:" "nocrlf" ) != string::npos) return;
+
+ // this file deliberately contains errors
+ const char test_file_name[] = "wrong_line_ends_test.cpp";
+
+ bool failed = false;
+ // The understanding on line endings, as I remember it, was that
+ // either "\n" or "\r\n" is OK, and they can be mixed, but "\r" alone
+ // is not acceptable. Mixed line endings are allowed because Boost files
+ // are commonly edited in both Windows and UNIX environments, and editors
+ // in those environments generally accept either ending. Even Mac people
+ // agreed with this policy. --Beman
+
+ // Joerg's original implementation is saved below,
+ // in case we change our minds!
+
+ for ( std::string::const_iterator itr ( contents.begin() );
+ itr != contents.end(); ++itr )
+ {
+ if ( *itr == '\r' && ((itr+1) == contents.end() || *(itr+1) != '\n') )
+ {
+ failed = true;
+ break;
+ }
+ }
+
+ if (failed && full_path.leaf() != test_file_name)
+ {
+ ++m_files_with_errors;
+ error( library_name, full_path, name() );
+ }
+
+ if (!failed && full_path.leaf() == test_file_name)
+ {
+ ++m_files_with_errors;
+ error( library_name, full_path, string(name()) + " should have cr-only line endings" );
+ }
+
+/*
+ size_t cr_count = 0;
+ size_t lf_count = 0;
+ size_t crlf_count = 0;
+ bool had_cr = false;
+ for ( size_t i = 0; i < contents.length(); ++i )
+ {
+ switch ( contents[i] )
+ {
+ case '\r':
+ had_cr = true;
+ ++cr_count;
+ break;
+ case '\n':
+ ++lf_count;
+ if ( had_cr )
+ ++crlf_count;
+ // fallthrough
+ default:
+ had_cr = false;
+ break;
+ }
+ }
+ if ( cr_count > 0 && lf_count != crlf_count )
+ {
+ ++m_files_with_errors;
+ error( library_name, full_path, desc() );
+ }
+*/
+ }
+ } // namespace inspect
+} // namespace boost
+
+
diff --git a/tools/inspect/crlf_check.hpp b/tools/inspect/crlf_check.hpp
new file mode 100644
index 0000000000..c6627ceeeb
--- /dev/null
+++ b/tools/inspect/crlf_check.hpp
@@ -0,0 +1,40 @@
+// crfl_check header --------------------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+// Copyright Rene Rivera 2004.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Contributed by Joerg Walter
+
+#ifndef BOOST_CRLF_CHECK_HPP
+#define BOOST_CRLF_CHECK_HPP
+
+#include "inspector.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ class crlf_check : public source_inspector
+ {
+ long m_files_with_errors;
+ public:
+
+ crlf_check();
+ virtual const char * name() const { return "*EOL*"; }
+ virtual const char * desc() const { return "invalid (cr only) line-ending"; }
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path,
+ const std::string & contents );
+
+ virtual ~crlf_check()
+ { std::cout << " " << m_files_with_errors << " files with invalid line endings" << line_break(); }
+ };
+ }
+}
+
+#endif // BOOST_CRLF_CHECK_HPP
diff --git a/tools/inspect/cvs_iterator.hpp b/tools/inspect/cvs_iterator.hpp
new file mode 100644
index 0000000000..538534074f
--- /dev/null
+++ b/tools/inspect/cvs_iterator.hpp
@@ -0,0 +1,81 @@
+// cvs_iterator ------------------------------------------------------------//
+
+// Copyright Beman Dawes 2003.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// WARNING: This is just a quick hack. It doesn't conform to C++ Standard
+// Library iterator requirements.
+
+#ifndef BOOST_CVS_ITERATOR_HPP
+#define BOOST_CVS_ITERATOR_HPP
+
+#include <string>
+#include <assert.h>
+
+#include "boost/filesystem/path.hpp"
+#include "boost/filesystem/operations.hpp"
+#include "boost/filesystem/fstream.hpp"
+#include "boost/noncopyable.hpp"
+
+namespace hack
+{
+ class cvs_iterator : boost::noncopyable
+ {
+ boost::filesystem::ifstream entries_file;
+ boost::filesystem::path dir_path;
+ boost::filesystem::path value_path;
+ public:
+
+ cvs_iterator(){} // end iterator
+
+ ~cvs_iterator() { if ( !!entries_file ) entries_file.close(); }
+
+ cvs_iterator( const boost::filesystem::path & dir_path ) : dir_path(dir_path)
+ {
+ boost::filesystem::path entries_file_path( dir_path / "CVS/Entries" );
+ entries_file.open( entries_file_path );
+ if ( !entries_file )
+ throw std::string( "could not open: " ) + entries_file_path.string();
+ ++*this;
+ }
+
+ const boost::filesystem::path & operator*() const { return value_path; }
+
+ cvs_iterator & operator++()
+ {
+ assert( !!entries_file );
+ std::string contents;
+ do
+ {
+ do
+ {
+ std::getline( entries_file, contents );
+ if ( entries_file.eof() )
+ {
+ entries_file.close();
+ value_path = "";
+ return *this;
+ }
+ } while ( contents == "D" );
+ if ( contents[0] == 'D' ) contents.erase( 0, 1 );
+ value_path = dir_path
+ / boost::filesystem::path( contents.substr( 1, contents.find( '/', 1 ) ) );
+
+ // in case entries file is mistaken, do until value_path actually found
+ } while ( !boost::filesystem::exists( value_path ) );
+ return *this;
+ }
+
+ bool operator==( const cvs_iterator & rhs )
+ { return value_path.string() == rhs.value_path.string(); }
+
+ bool operator!=( const cvs_iterator & rhs )
+ { return value_path.string() != rhs.value_path.string(); }
+
+ };
+}
+
+#endif // include guard
diff --git a/tools/inspect/doc/build.jam b/tools/inspect/doc/build.jam
new file mode 100644
index 0000000000..498c959556
--- /dev/null
+++ b/tools/inspect/doc/build.jam
@@ -0,0 +1,21 @@
+project tools/inspect/doc ;
+
+import path ;
+
+using quickbook ;
+
+xml inspect
+ :
+ inspect.qbk
+ ;
+
+boostbook standalone
+ :
+ inspect
+ :
+ <xsl:param>boost.root=../../../..
+ ;
+
+#~ Copyright Rene Rivera 2006.
+#~ Distributed under the Boost Software License, Version 1.0. (See accompanying
+#~ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/tools/inspect/doc/inspect.qbk b/tools/inspect/doc/inspect.qbk
new file mode 100644
index 0000000000..87f95e69ac
--- /dev/null
+++ b/tools/inspect/doc/inspect.qbk
@@ -0,0 +1,128 @@
+[article Inspect
+ [quickbook 1.3]
+ [authors [Dawes, Beman], [Prota, Gennaro], [Rivera, Rene]]
+ [copyright 2003 2006 Beman Dawes, Rene Rivera]
+ [category tool-build]
+ [id inspect]
+ [dirname inspect]
+ [purpose
+ The inspect program detects and reports several common errors and
+ Boost guideline violations.
+ ]
+ [license
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ [@http://www.boost.org/LICENSE_1_0.txt])
+ ]
+]
+
+[/ QuickBook Document version 1.3 ]
+
+[/ Shortcuts ]
+
+[def :version: 3.1.14]
+
+[/ Images ]
+
+[def :NOTE: [$images/note.png]]
+[def :ALERT: [$images/caution.png]]
+[def :DETAIL: [$images/note.png]]
+[def :TIP: [$images/tip.png]]
+
+[/ Links ]
+
+[def :Boost: [@http://www.boost.org Boost]]
+
+[section:intro Introduction]
+
+It is not uncommon for various common errors or [@http://www.boost.org/more/lib_guide.htm guideline violations] to creep into the Boost libraries. The inspect program detects and reports several common problems. It can be used to scan a proposed Boost submission to identify various failures.
+
+The inspect program is written in C++ to limit tool chain dependencies, and should be portable to any system.
+
+[endsect]
+
+[section:usage Using Inspect]
+
+The program is run in the directory to be scanned for errors. Sub-directories are also included in the scan. For best results in the generated reports one should run inspect from the Boost root directory. The program generates, by default, an HTML report with summaries and per library details of the infractions.
+
+If the first program argument is -help, a usage message is displayed, showing all available program options:
+
+[pre
+Usage: inspect \[-cvs\] \[-text\] \[-brief\] \[options...\]
+
+ Options:
+ -license
+ -copyright
+ -crlf
+ -end
+ -link
+ -path_name
+ -tab
+ -ascii
+ -apple_macro
+ -assert_macro
+ -minmax
+ -unnamed
+ default is all checks on; otherwise options specify desired checks
+]
+
+[section:options Options]
+
+There are two types of options allowed, ones that control general operation and kind of output produced, and the ones that indicate the checks to perform.
+
+[variablelist
+
+ [ [[^-cvs]]
+ [Only files and directories in the CVS tree of the current directory are scanned. Otherwise all files and sub-directories are included in the scan.] ]
+
+ [ [[^-text]]
+ [Generate plain text report instead of the default HTML.] ]
+
+ [ [[^-brief]]
+ [The default report style can be rather verobse. This generates a more condesed report, for example suitable to send as an email.] ]
+
+ [ [[^-license]]
+ [Checks for presense of approved license text.] ]
+
+ [ [[^-copyright]]
+ [Checks that files are copyright assigned to someone.] ]
+
+ [ [[^-crlf]]
+ [Checks that files use consistent EOL chanracters.] ]
+
+ [ [[^-end]]
+ [Checks that files end with a newline character.] ]
+
+ [ [[^-link]]
+ [Checks the validity of URIs in HTML files.] ]
+
+ [ [[^-path_name]]
+ [Checks for long names, and a variety of other file name problems that inhibit portability of files.] ]
+
+ [ [[^-tab]]
+ [Checks for files with tab characters.] ]
+
+ [ [[^-ascii]]
+ [Checks for files with non-ASCII characters.] ]
+
+ [ [[^-apple_macro]]
+ [Checks for conflicts with to Apple's unfortunately named debugging macros.] ]
+
+ [ [[^-assert_macro]]
+ [Checks for presence of C-style assert macros (instead of BOOST_ASSERT).] ]
+
+ [ [[^-minmax]]
+ [Checks for violations of the Boost min/max quidelines.] ]
+
+ [ [[^-unnamed]]
+ [Checks for unnamed namespace in C++ header files.] ]
+
+]
+
+[endsect]
+
+[endsect]
+
+[section:checks Checks]
+
+[endsect]
diff --git a/tools/inspect/end_check.cpp b/tools/inspect/end_check.cpp
new file mode 100644
index 0000000000..9c1e438afd
--- /dev/null
+++ b/tools/inspect/end_check.cpp
@@ -0,0 +1,58 @@
+// end_check implementation -------------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+// Copyright Daniel James 2009.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "end_check.hpp"
+#include <boost/next_prior.hpp>
+
+namespace boost
+{
+ namespace inspect
+ {
+ end_check::end_check() : m_files_with_errors(0)
+ {
+ register_signature( ".c" );
+ register_signature( ".cpp" );
+ register_signature( ".cxx" );
+ register_signature( ".h" );
+ register_signature( ".hpp" );
+ register_signature( ".hxx" );
+ register_signature( ".ipp" );
+ }
+
+ void end_check::inspect(
+ const string & library_name,
+ const path & full_path, // example: c:/foo/boost/filesystem/path.hpp
+ const string & contents ) // contents of file to be inspected
+ {
+ if (contents.find( "boostinspect:" "noend" ) != string::npos) return;
+
+ // this file deliberately contains errors
+ const char test_file_name[] = "wrong_line_ends_test.cpp";
+
+ char final_char = contents.begin() == contents.end() ? '\0'
+ : *(boost::prior(contents.end()));
+
+ bool failed = final_char != '\n' && final_char != '\r';
+
+ if (failed && full_path.leaf() != test_file_name)
+ {
+ ++m_files_with_errors;
+ error( library_name, full_path, string(name()) + ' ' + desc() );
+ }
+
+ if (!failed && full_path.leaf() == test_file_name)
+ {
+ ++m_files_with_errors;
+ error( library_name, full_path, string(name()) + " should not end with a newline" );
+ }
+ }
+ } // namespace inspect
+} // namespace boost
+
+
diff --git a/tools/inspect/end_check.hpp b/tools/inspect/end_check.hpp
new file mode 100644
index 0000000000..41e5041ced
--- /dev/null
+++ b/tools/inspect/end_check.hpp
@@ -0,0 +1,40 @@
+// end_check header ---------------------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+// Copyright Rene Rivera 2004.
+// Copyright Daniel James 2009.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_END_CHECK_HPP
+#define BOOST_END_CHECK_HPP
+
+#include "inspector.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ class end_check : public inspector
+ {
+ long m_files_with_errors;
+ public:
+
+ end_check();
+ virtual const char * name() const { return "*END*"; }
+ virtual const char * desc() const { return "file doesn't end with a newline"; }
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path,
+ const std::string & contents );
+
+ virtual ~end_check()
+ { std::cout << " " << m_files_with_errors << " files that don't end with a newline" << line_break(); }
+ };
+ }
+}
+
+#endif // BOOST_END_CHECK_HPP
diff --git a/tools/inspect/index.html b/tools/inspect/index.html
new file mode 100644
index 0000000000..bfecc45f06
--- /dev/null
+++ b/tools/inspect/index.html
@@ -0,0 +1,58 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<title>Inspect Tool</title>
+</head>
+
+<body bgcolor="#FFFFFF">
+
+<h1>
+<img src="../../boost.png" alt="boost.png (6897 bytes)" align="center" width="277" height="86">Inspect
+Tool</h1>
+<p>It is not uncommon for various common errors or
+<a href="http://www.boost.org/more/lib_guide.htm">guideline violations</a> to creep into the
+Boost libraries. The <i>inspect</i> program detects and reports several common
+problems. It can be used to scan a proposed Boost submission to identify various
+failures.</p>
+<p>The <i>inspect</i> program is written in C++ to limit tool chain
+dependencies, and should be portable to any system.</p>
+<p>The program is run in the directory to be scanned for errors. Sub-directories
+are also included in the scan.</p>
+<p>If the first program argument is <code>-cvs</code>, only files and
+directories in the CVS tree of the current directory are scanned. Otherwise all
+files and sub-directories are included in the scan.</p>
+<p>If the first program argument is <code>-help</code>, a usage message is
+displayed, showing all available program options.</p>
+<p>The program sources include:</p>
+<ul>
+ <li><a href="inspector.hpp">inspect.hpp</a> and <a href="inspect.cpp">
+ inspect.cpp</a></li>
+ <li><a href="link_check.hpp">link_check.hpp</a> and <a href="link_check.cpp">
+ link_check.cpp</a></li>
+ <li><a href="path_name_check.hpp">path_name_check.hpp</a> and
+ <a href="path_name_check.cpp">path_name_check.cpp</a></li>
+ <li><a href="tab_check.hpp">tab_check.hpp</a> and <a href="tab_check.cpp">
+ tab_check.cpp</a></li>
+</ul>
+<p>A <a href="build/Jamfile.v2">Jamfile</a> is provided to build the program
+using Boost.Build.</p>
+<p>A Microsoft Visual Studio solution file is provided to aid maintenance. See
+<a href="build/msvc/readme.txt">readme.txt</a>
+before using it.</p>
+<hr>
+<p>Revised
+<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->29 June, 2008<!--webbot bot="Timestamp" endspan i-checksum="19976" --></p>
+
+<p>© Copyright Beman Dawes, 2003</p>
+<p> Distributed under the Boost Software
+License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt">
+LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+www.boost.org/LICENSE_1_0.txt</a>)</p>
+
+</body>
+
+</html>
diff --git a/tools/inspect/inspect.cpp b/tools/inspect/inspect.cpp
new file mode 100644
index 0000000000..00e72f9935
--- /dev/null
+++ b/tools/inspect/inspect.cpp
@@ -0,0 +1,1000 @@
+// inspect program ---------------------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+// Copyright Rene Rivera 2004-2006.
+// Copyright Gennaro Prota 2006.
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// This program recurses through sub-directories looking for various problems.
+// It contains some Boost specific features, like ignoring "CVS" and "bin",
+// and the code that identifies library names assumes the Boost directory
+// structure.
+
+// See http://www.boost.org/tools/inspect/ for more information.
+
+
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <cstring>
+
+#include "boost/shared_ptr.hpp"
+#include "boost/lexical_cast.hpp"
+#include "boost/filesystem/operations.hpp"
+#include "boost/filesystem/fstream.hpp"
+
+#include "time_string.hpp"
+
+#include "inspector.hpp"
+
+// the inspectors
+#include "copyright_check.hpp"
+#include "crlf_check.hpp"
+#include "end_check.hpp"
+#include "license_check.hpp"
+#include "link_check.hpp"
+#include "path_name_check.hpp"
+#include "tab_check.hpp"
+#include "ascii_check.hpp"
+#include "apple_macro_check.hpp"
+#include "assert_macro_check.hpp"
+#include "minmax_check.hpp"
+#include "unnamed_namespace_check.hpp"
+
+#include "cvs_iterator.hpp"
+
+#include "boost/test/included/prg_exec_monitor.hpp"
+
+namespace fs = boost::filesystem;
+
+using namespace boost::inspect;
+
+namespace
+{
+ class inspector_element
+ {
+ typedef boost::shared_ptr< boost::inspect::inspector > inspector_ptr;
+
+ public:
+ inspector_ptr inspector;
+ explicit
+ inspector_element( boost::inspect::inspector * p ) : inspector(p) {}
+ };
+
+ typedef std::list< inspector_element > inspector_list;
+
+ long file_count = 0;
+ long directory_count = 0;
+ long error_count = 0;
+ const int max_offenders = 5; // maximum "worst offenders" to display
+
+ boost::inspect::string_set content_signatures;
+
+ struct error_msg
+ {
+ string library;
+ string rel_path;
+ string msg;
+ int line_number;
+
+ bool operator<( const error_msg & rhs ) const
+ {
+ if ( library < rhs.library ) return true;
+ if ( library > rhs.library ) return false;
+ if ( rel_path < rhs.rel_path ) return true;
+ if ( rel_path > rhs.rel_path ) return false;
+ if ( line_number < rhs.line_number ) return true;
+ if ( line_number > rhs.line_number ) return false;
+ return msg < rhs.msg;
+ }
+ };
+
+ typedef std::vector< error_msg > error_msg_vector;
+ error_msg_vector msgs;
+
+ struct lib_error_count
+ {
+ int error_count;
+ string library;
+
+ bool operator<( const lib_error_count & rhs ) const
+ {
+ return error_count > rhs.error_count;
+ }
+ };
+
+ typedef std::vector< lib_error_count > lib_error_count_vector;
+ lib_error_count_vector libs;
+
+// get info (as a string) if inspect_root is svn working copy --------------//
+
+ void extract_info( fs::ifstream & entries_file, string & rev, string & repos )
+ {
+ std::getline( entries_file, rev );
+ std::getline( entries_file, rev );
+ std::getline( entries_file, rev );
+ std::getline( entries_file, rev ); // revision number as a string
+ std::getline( entries_file, repos ); // repository as a string
+ }
+
+ string info( const fs::path & inspect_root )
+ {
+ string rev( "?" );
+ string repos( "unknown" );
+ fs::path entries( inspect_root / ".svn" / "entries" );
+ fs::ifstream entries_file( entries );
+ if ( entries_file )
+ extract_info( entries_file, rev, repos );
+ else
+ {
+ entries = inspect_root / ".." / "svn_info" / ".svn" / "entries";
+ fs::ifstream entries_file( entries );
+ if ( entries_file )
+ extract_info( entries_file, rev, repos );
+ }
+ return repos + " at revision " + rev;
+ }
+
+// visit_predicate (determines which directories are visited) --------------//
+
+ typedef bool(*pred_type)(const path&);
+
+ bool visit_predicate( const path & pth )
+ {
+ string local( boost::inspect::relative_to( pth, fs::initial_path() ) );
+ string leaf( pth.leaf().string() );
+ return
+ // so we can inspect a checkout
+ leaf != "CVS"
+ // don't look at binaries
+ && leaf != "bin"
+ && leaf != "bin.v2"
+ // no point in checking doxygen xml output
+ && local.find("doc/xml") != 0
+ && local.find("doc\\xml") != 0
+ // ignore some web files
+ && leaf != ".htaccess"
+ // ignore svn files:
+ && leaf != ".svn"
+ // ignore other version control files
+ && leaf != ".git"
+ && leaf != ".bzr"
+ // ignore OS X directory info files:
+ && leaf != ".DS_Store"
+ // ignore if tag file present
+ && !boost::filesystem::exists(pth / "boost-no-inspect")
+ ;
+ }
+
+// library_from_content ----------------------------------------------------//
+
+ string library_from_content( const string & content )
+ {
+ const string unknown_library ( "unknown" );
+ const string lib_root ( "www.boost.org/libs/" );
+ string::size_type pos( content.find( lib_root ) );
+
+ string lib = unknown_library;
+
+ if ( pos != string::npos ) {
+
+ pos += lib_root.length();
+
+ const char delims[] = " " // space and...
+ "/\n\r\t";
+
+ string::size_type n = content.find_first_of( string(delims), pos );
+ if (n != string::npos)
+ lib = string(content, pos, n - pos);
+
+ }
+
+ return lib;
+ }
+
+// find_signature ----------------------------------------------------------//
+
+ bool find_signature( const path & file_path,
+ const boost::inspect::string_set & signatures )
+ {
+ string name( file_path.leaf().string() );
+ if ( signatures.find( name ) == signatures.end() )
+ {
+ string::size_type pos( name.rfind( '.' ) );
+ if ( pos == string::npos
+ || signatures.find( name.substr( pos ) )
+ == signatures.end() ) return false;
+ }
+ return true;
+ }
+
+// load_content ------------------------------------------------------------//
+
+ void load_content( const path & file_path, string & target )
+ {
+ target = "";
+
+ if ( !find_signature( file_path, content_signatures ) ) return;
+
+ fs::ifstream fin( file_path, std::ios_base::in|std::ios_base::binary );
+ if ( !fin )
+ throw string( "could not open input file: " ) + file_path.string();
+ std::getline( fin, target, '\0' ); // read the whole file
+ }
+
+// check -------------------------------------------------------------------//
+
+ void check( const string & lib,
+ const path & pth, const string & content, const inspector_list & insp_list )
+ {
+ // invoke each inspector
+ for ( inspector_list::const_iterator itr = insp_list.begin();
+ itr != insp_list.end(); ++itr )
+ {
+ itr->inspector->inspect( lib, pth ); // always call two-argument form
+ if ( find_signature( pth, itr->inspector->signatures() ) )
+ {
+ itr->inspector->inspect( lib, pth, content );
+ }
+ }
+ }
+
+// visit_all ---------------------------------------------------------------//
+
+ template< class DirectoryIterator >
+ void visit_all( const string & lib,
+ const path & dir_path, const inspector_list & insps )
+ {
+ static DirectoryIterator end_itr;
+ ++directory_count;
+
+ for ( DirectoryIterator itr( dir_path ); itr != end_itr; ++itr )
+ {
+
+ if ( fs::is_directory( *itr ) )
+ {
+ if ( visit_predicate( *itr ) )
+ {
+ string cur_lib( boost::inspect::impute_library( *itr ) );
+ check( cur_lib, *itr, "", insps );
+ visit_all<DirectoryIterator>( cur_lib, *itr, insps );
+ }
+ }
+ else
+ {
+ ++file_count;
+ string content;
+ load_content( *itr, content );
+ check( lib.empty()
+ ? library_from_content( content ) : lib
+ , *itr, content, insps );
+ }
+ }
+ }
+
+// display -----------------------------------------------------------------//
+
+ enum display_format_type
+ {
+ display_html, display_text
+ }
+ display_format = display_html;
+
+ enum display_mode_type
+ {
+ display_full, display_brief
+ }
+ display_mode = display_full;
+
+// display_summary_helper --------------------------------------------------//
+
+ void display_summary_helper( const string & current_library, int err_count )
+ {
+ if (display_text == display_format)
+ {
+ std::cout << " " << current_library << " (" << err_count << ")\n";
+ }
+ else
+ {
+ std::cout
+ << " <a href=\"#"
+ << current_library // what about malformed for URI refs? [gps]
+ << "\">" << current_library
+ << "</a> ("
+ << err_count << ")<br>\n";
+ }
+ }
+
+// display_summary ---------------------------------------------------------//
+
+ void display_summary()
+ {
+ if (display_text == display_format)
+ {
+ std::cout << "Summary:\n";
+ }
+ else
+ {
+ std::cout <<
+ "<h2>Summary</h2>\n"
+ "<blockquote>\n"
+ ;
+ }
+
+ string current_library( msgs.begin()->library );
+ int err_count = 0;
+ for ( error_msg_vector::iterator itr ( msgs.begin() );
+ itr != msgs.end(); ++itr )
+ {
+ if ( current_library != itr->library )
+ {
+ display_summary_helper( current_library, err_count );
+ current_library = itr->library;
+ err_count = 0;
+ }
+ ++err_count;
+ }
+ display_summary_helper( current_library, err_count );
+
+ if (display_text == display_format)
+ std::cout << "\n";
+ else
+ std::cout << "</blockquote>\n";
+ }
+
+// html_encode -------------------------------------------------------------//
+
+ std::string html_encode(std::string const& text)
+ {
+ std::string result;
+
+ for(std::string::const_iterator it = text.begin(),
+ end = text.end(); it != end; ++it)
+ {
+ switch(*it) {
+ case '<':
+ result += "&lt;";
+ break;
+ case '>':
+ result += "&gt;";
+ break;
+ case '&':
+ result += "&amp;";
+ break;
+ default:
+ result += *it;
+ }
+ }
+
+ return result;
+ }
+
+// display_details ---------------------------------------------------------//
+
+ void display_details()
+ {
+ // gps - review this
+
+ if (display_text == display_format)
+ {
+ // display error messages with group indication
+ error_msg current;
+ string sep;
+ for ( error_msg_vector::iterator itr ( msgs.begin() );
+ itr != msgs.end(); ++itr )
+ {
+ if ( current.library != itr->library )
+ {
+ if ( display_full == display_mode )
+ std::cout << "\n|" << itr->library << "|\n";
+ else
+ std::cout << "\n\n|" << itr->library << '|';
+ }
+
+ if ( current.library != itr->library
+ || current.rel_path != itr->rel_path )
+ {
+ if ( display_full == display_mode )
+ {
+ std::cout << " " << itr->rel_path << ":\n";
+ }
+ else
+ {
+ path current_rel_path(current.rel_path);
+ path this_rel_path(itr->rel_path);
+ if (current_rel_path.branch_path() != this_rel_path.branch_path())
+ {
+ std::cout << "\n " << this_rel_path.branch_path().string() << '/';
+ }
+ std::cout << "\n " << this_rel_path.leaf() << ':';
+ }
+ }
+ if ( current.library != itr->library
+ || current.rel_path != itr->rel_path
+ || current.msg != itr->msg )
+ {
+ const string m = itr->msg;
+
+ if ( display_full == display_mode )
+ std::cout << " " << m << '\n';
+ else
+ std::cout << ' ' << m;
+ }
+ current.library = itr->library;
+ current.rel_path = itr->rel_path;
+ current.msg = itr->msg;
+ }
+ std::cout << "\n";
+ }
+ else // html
+ {
+ // display error messages with group indication
+ error_msg current;
+ bool first_sep = true;
+ bool first = true;
+ for ( error_msg_vector::iterator itr ( msgs.begin() );
+ itr != msgs.end(); ++itr )
+ {
+ if ( current.library != itr->library )
+ {
+ if ( !first ) std::cout << "</pre>\n";
+ std::cout << "\n<h3><a name=\"" << itr->library
+ << "\">" << itr->library << "</a></h3>\n<pre>";
+ }
+ if ( current.library != itr->library
+ || current.rel_path != itr->rel_path )
+ {
+ std::cout << "\n";
+ std::cout << itr->rel_path;
+ first_sep = true;
+ }
+ if ( current.library != itr->library
+ || current.rel_path != itr->rel_path
+ || current.msg != itr->msg )
+ {
+ std::string sep;
+ if (first_sep)
+ if (itr->line_number) sep = ":<br>&nbsp;&nbsp;&nbsp; ";
+ else sep = ": ";
+ else
+ if (itr->line_number) sep = "<br>&nbsp;&nbsp;&nbsp; ";
+ else sep = ", ";
+
+ // print the message
+ if (itr->line_number)
+ std::cout << sep << "(line " << itr->line_number << ") " << html_encode(itr->msg);
+ else std::cout << sep << html_encode(itr->msg);
+
+ first_sep = false;
+ }
+ current.library = itr->library;
+ current.rel_path = itr->rel_path;
+ current.msg = itr->msg;
+ first = false;
+ }
+ std::cout << "</pre>\n";
+ }
+ }
+
+
+// worst_offenders_count_helper --------------------------------------------------//
+
+ void worst_offenders_count_helper( const string & current_library, int err_count )
+ {
+ lib_error_count lec;
+ lec.library = current_library;
+ lec.error_count = err_count;
+ libs.push_back( lec );
+ }
+// worst_offenders_count -----------------------------------------------------//
+
+ void worst_offenders_count()
+ {
+ if ( msgs.empty() )
+ {
+ return;
+ }
+ string current_library( msgs.begin()->library );
+ int err_count = 0;
+ for ( error_msg_vector::iterator itr ( msgs.begin() );
+ itr != msgs.end(); ++itr )
+ {
+ if ( current_library != itr->library )
+ {
+ worst_offenders_count_helper( current_library, err_count );
+ current_library = itr->library;
+ err_count = 0;
+ }
+ ++err_count;
+ }
+ worst_offenders_count_helper( current_library, err_count );
+ }
+
+// display_worst_offenders -------------------------------------------------//
+
+ void display_worst_offenders()
+ {
+ if (display_text == display_format)
+ {
+ std::cout << "Worst Offenders:\n";
+ }
+ else
+ {
+ std::cout <<
+ "<h2>Worst Offenders</h2>\n"
+ "<blockquote>\n"
+ ;
+ }
+
+ int display_count = 0;
+ int last_error_count = 0;
+ for ( lib_error_count_vector::iterator itr ( libs.begin() );
+ itr != libs.end()
+ && (display_count < max_offenders
+ || itr->error_count == last_error_count);
+ ++itr, ++display_count )
+ {
+ if (display_text == display_format)
+ {
+ std::cout << itr->library << " " << itr->error_count << "\n";
+ }
+ else
+ {
+ std::cout
+ << " <a href=\"#"
+ << itr->library
+ << "\">" << itr->library
+ << "</a> ("
+ << itr->error_count << ")<br>\n";
+ }
+ last_error_count = itr->error_count;
+ }
+
+ if (display_text == display_format)
+ std::cout << "\n";
+ else
+ std::cout << "</blockquote>\n";
+ }
+
+
+ const char * options()
+ {
+ return
+ " -license\n"
+ " -copyright\n"
+ " -crlf\n"
+ " -end\n"
+ " -link\n"
+ " -path_name\n"
+ " -tab\n"
+ " -ascii\n"
+ " -apple_macro\n"
+ " -assert_macro\n"
+ " -minmax\n"
+ " -unnamed\n"
+ " default is all checks on; otherwise options specify desired checks"
+ "\n";
+ }
+
+ const char * doctype_declaration()
+ {
+ return
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
+ "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
+ ;
+ }
+
+ std::string validator_link(const std::string & text)
+ {
+ return
+ // with link to validation service
+ "<a href=\"http://validator.w3.org/check?uri=referer\">"
+ + text
+ + "</a>"
+ ;
+ }
+
+} // unnamed namespace
+
+namespace boost
+{
+ namespace inspect
+ {
+
+// line_break --------------------------------------------------------------//
+
+ const char * line_break()
+ {
+ return display_format ? "\n" : "<br>\n";
+ }
+
+
+// register_signature ------------------------------------------------------//
+
+ void inspector::register_signature( const string & signature )
+ {
+ m_signatures.insert( signature );
+ content_signatures.insert( signature );
+ }
+
+// error -------------------------------------------------------------------//
+
+ void inspector::error( const string & library_name,
+ const path & full_path, const string & msg, int line_number )
+ {
+ ++error_count;
+ error_msg err_msg;
+ err_msg.library = library_name;
+ err_msg.rel_path = relative_to( full_path, fs::initial_path() );
+ err_msg.msg = msg;
+ err_msg.line_number = line_number;
+ msgs.push_back( err_msg );
+
+// std::cout << library_name << ": "
+// << full_path.string() << ": "
+// << msg << '\n';
+
+ }
+
+ source_inspector::source_inspector()
+ {
+ // C/C++ source code...
+ register_signature( ".c" );
+ register_signature( ".cpp" );
+ register_signature( ".css" );
+ register_signature( ".cxx" );
+ register_signature( ".h" );
+ register_signature( ".hpp" );
+ register_signature( ".hxx" );
+ register_signature( ".inc" );
+ register_signature( ".ipp" );
+
+ // Boost.Build BJam source code...
+ register_signature( "Jamfile" );
+ register_signature( ".jam" );
+ register_signature( ".v2" );
+
+ // Other scripts; Python, shell, autoconfig, etc.
+ register_signature( "configure.in" );
+ register_signature( "GNUmakefile" );
+ register_signature( "Makefile" );
+ register_signature( ".bat" );
+ register_signature( ".mak" );
+ register_signature( ".pl" );
+ register_signature( ".py" );
+ register_signature( ".sh" );
+
+ // Hypertext, Boost.Book, and other text...
+ register_signature( "news" );
+ register_signature( "readme" );
+ register_signature( "todo" );
+ register_signature( "NEWS" );
+ register_signature( "README" );
+ register_signature( "TODO" );
+ register_signature( ".boostbook" );
+ register_signature( ".htm" );
+ register_signature( ".html" );
+ register_signature( ".rst" );
+ register_signature( ".sgml" );
+ register_signature( ".shtml" );
+ register_signature( ".txt" );
+ register_signature( ".xml" );
+ register_signature( ".xsd" );
+ register_signature( ".xsl" );
+ register_signature( ".qbk" );
+ }
+
+ hypertext_inspector::hypertext_inspector()
+ {
+ register_signature( ".htm" );
+ register_signature( ".html" );
+ register_signature( ".shtml" );
+ }
+
+// impute_library ----------------------------------------------------------//
+
+ // may return an empty string [gps]
+ string impute_library( const path & full_dir_path )
+ {
+ path relative( relative_to( full_dir_path, fs::initial_path() ) );
+ if ( relative.empty() ) return "boost-root";
+ string first( (*relative.begin()).string() );
+ string second = // borland 5.61 requires op=
+ ++relative.begin() == relative.end()
+ ? string() : (*++relative.begin()).string();
+
+ if ( first == "boost" )
+ return second;
+
+ return (( first == "libs" || first == "tools" ) && !second.empty())
+ ? second : first;
+ }
+
+ } // namespace inspect
+} // namespace boost
+
+// cpp_main() --------------------------------------------------------------//
+
+int cpp_main( int argc_param, char * argv_param[] )
+{
+ // <hack> for the moment, let's be on the safe side
+ // and ensure we don't modify anything being pointed to;
+ // then we'll do some cleanup here
+ int argc = argc_param;
+ const char* const * argv = &argv_param[0];
+
+ if ( argc > 1 && (std::strcmp( argv[1], "-help" ) == 0
+ || std::strcmp( argv[1], "--help" ) == 0 ) )
+ {
+ std::clog << "Usage: inspect [-cvs] [-text] [-brief] [options...]\n\n"
+ " Options:\n"
+ << options() << '\n';
+ return 0;
+ }
+
+ bool license_ck = true;
+ bool copyright_ck = true;
+ bool crlf_ck = true;
+ bool end_ck = true;
+ bool link_ck = true;
+ bool path_name_ck = true;
+ bool tab_ck = true;
+ bool ascii_ck = true;
+ bool apple_ok = true;
+ bool assert_ok = true;
+ bool minmax_ck = true;
+ bool unnamed_ck = true;
+ bool cvs = false;
+
+ if ( argc > 1 && std::strcmp( argv[1], "-cvs" ) == 0 )
+ {
+ cvs = true;
+ --argc; ++argv;
+ }
+
+ if ( argc > 1 && std::strcmp( argv[1], "-text" ) == 0 )
+ {
+ display_format = display_text;
+ --argc; ++argv;
+ }
+
+ if ( argc > 1 && std::strcmp( argv[1], "-brief" ) == 0 )
+ {
+ display_mode = display_brief;
+ --argc; ++argv;
+ }
+
+ if ( argc > 1 && *argv[1] == '-' )
+ {
+ license_ck = false;
+ copyright_ck = false;
+ crlf_ck = false;
+ end_ck = false;
+ link_ck = false;
+ path_name_ck = false;
+ tab_ck = false;
+ ascii_ck = false;
+ apple_ok = false;
+ assert_ok = false;
+ minmax_ck = false;
+ unnamed_ck = false;
+ }
+
+ bool invalid_options = false;
+ for(; argc > 1; --argc, ++argv )
+ {
+ if ( std::strcmp( argv[1], "-license" ) == 0 )
+ license_ck = true;
+ else if ( std::strcmp( argv[1], "-copyright" ) == 0 )
+ copyright_ck = true;
+ else if ( std::strcmp( argv[1], "-crlf" ) == 0 )
+ crlf_ck = true;
+ else if ( std::strcmp( argv[1], "-end" ) == 0 )
+ end_ck = true;
+ else if ( std::strcmp( argv[1], "-link" ) == 0 )
+ link_ck = true;
+ else if ( std::strcmp( argv[1], "-path_name" ) == 0 )
+ path_name_ck = true;
+ else if ( std::strcmp( argv[1], "-tab" ) == 0 )
+ tab_ck = true;
+ else if ( std::strcmp( argv[1], "-ascii" ) == 0 )
+ ascii_ck = true;
+ else if ( std::strcmp( argv[1], "-apple_macro" ) == 0 )
+ apple_ok = true;
+ else if ( std::strcmp( argv[1], "-assert_macro" ) == 0 )
+ assert_ok = true;
+ else if ( std::strcmp( argv[1], "-minmax" ) == 0 )
+ minmax_ck = true;
+ else if ( std::strcmp( argv[1], "-unnamed" ) == 0 )
+ unnamed_ck = true;
+ else
+ {
+ std::cerr << "unknown option: " << argv[1] << '\n';
+ invalid_options = true;
+ }
+ }
+ if ( invalid_options ) {
+ std::cerr << "\nvalid options are:\n"
+ << options();
+ return 1;
+ }
+
+ string inspector_keys;
+ fs::initial_path();
+
+
+ { // begin reporting block
+
+ // since this is in its own block; reporting will happen
+ // automatically, from each registered inspector, when
+ // leaving, due to destruction of the inspector_list object
+ inspector_list inspectors;
+
+ if ( license_ck )
+ inspectors.push_back( inspector_element( new boost::inspect::license_check ) );
+ if ( copyright_ck )
+ inspectors.push_back( inspector_element( new boost::inspect::copyright_check ) );
+ if ( crlf_ck )
+ inspectors.push_back( inspector_element( new boost::inspect::crlf_check ) );
+ if ( end_ck )
+ inspectors.push_back( inspector_element( new boost::inspect::end_check ) );
+ if ( link_ck )
+ inspectors.push_back( inspector_element( new boost::inspect::link_check ) );
+ if ( path_name_ck )
+ inspectors.push_back( inspector_element( new boost::inspect::file_name_check ) );
+ if ( tab_ck )
+ inspectors.push_back( inspector_element( new boost::inspect::tab_check ) );
+ if ( ascii_ck )
+ inspectors.push_back( inspector_element( new boost::inspect::ascii_check ) );
+ if ( apple_ok )
+ inspectors.push_back( inspector_element( new boost::inspect::apple_macro_check ) );
+ if ( assert_ok )
+ inspectors.push_back( inspector_element( new boost::inspect::assert_macro_check ) );
+ if ( minmax_ck )
+ inspectors.push_back( inspector_element( new boost::inspect::minmax_check ) );
+ if ( unnamed_ck )
+ inspectors.push_back( inspector_element( new boost::inspect::unnamed_namespace_check ) );
+
+ // perform the actual inspection, using the requested type of iteration
+ if ( cvs )
+ visit_all<hack::cvs_iterator>( "boost-root",
+ fs::initial_path(), inspectors );
+ else
+ visit_all<fs::directory_iterator>( "boost-root",
+ fs::initial_path(), inspectors );
+
+ // close
+ for ( inspector_list::iterator itr = inspectors.begin();
+ itr != inspectors.end(); ++itr )
+ {
+ itr->inspector->close();
+ }
+
+ string run_date ( "n/a" );
+ boost::time_string( run_date );
+
+ if (display_text == display_format)
+ {
+ std::cout
+ <<
+ "Boost Inspection Report\n"
+ "Run Date: " << run_date << "\n"
+ "\n"
+ "An inspection program <http://www.boost.org/tools/inspect/index.html>\n"
+ "checks each file in the current Boost CVS for various problems,\n"
+ "generating an HTML page as output.\n"
+ "\n"
+ ;
+
+ std::cout
+ << "Totals:\n"
+ << " " << file_count << " files scanned\n"
+ << " " << directory_count << " directories scanned (including root)\n"
+ << " " << error_count << " problems reported\n"
+ << '\n'
+ ;
+ }
+ else
+ {
+ //
+ std::cout << doctype_declaration() << '\n';
+
+ std::cout
+ << "<html>\n"
+ "<head>\n"
+ "<style> body { font-family: sans-serif; } </style>\n"
+ "<title>Boost Inspection Report</title>\n"
+ "</head>\n"
+
+ "<body>\n"
+ // we should not use a table, of course [gps]
+ "<table>\n"
+ "<tr>\n"
+ "<td><img src=\"http://www.boost.org/boost.png\" alt=\"Boost logo\" />"
+ "</td>\n"
+ "<td>\n"
+ "<h1>Boost Inspection Report</h1>\n"
+ "<b>Run Date:</b> " << run_date << "\n"
+ //"&nbsp;&nbsp;/ " << validator_link( "validate me" ) << " /\n"
+ "</td>\n"
+ "</tr>\n"
+ "</table>\n"
+
+ "<p>This report is generated by an <a href=\"http://www.boost.org/tools/inspect/index.html\">inspection\n"
+ "program</a> that checks files for the problems noted below.</p>\n"
+ ;
+ std::cout
+ << "<p>The files checked were from "
+ << info( fs::initial_path() )
+ << ".</p>\n";
+
+
+ std::cout
+ << "<h2>Totals</h2>\n"
+ << file_count << " files scanned<br>\n"
+ << directory_count << " directories scanned (including root)<br>\n"
+ << error_count << " problems reported\n<p>";
+ }
+
+ for ( inspector_list::iterator itr = inspectors.begin();
+ itr != inspectors.end(); ++itr )
+ {
+
+ inspector_keys += static_cast<string>(" ")
+ + itr->inspector->name()
+ + ' ' + itr->inspector->desc()
+ + line_break()
+ ;
+ }
+
+ if (display_text == display_format)
+ std::cout << "\nProblem counts:\n";
+ else
+ std::cout << "\n<h2>Problem counts</h2>\n<blockquote><p>\n" ;
+
+ } // end of block: starts reporting
+
+ if (display_text == display_format)
+ std::cout << "\n" ;
+ else
+ std::cout << "</blockquote>\n";
+
+ std::sort( msgs.begin(), msgs.end() );
+
+ worst_offenders_count();
+ std::stable_sort( libs.begin(), libs.end() );
+
+ if ( !libs.empty() )
+ display_worst_offenders();
+
+ if ( !msgs.empty() )
+ {
+ display_summary();
+
+ if (display_text == display_format)
+ {
+ std::cout << "Details:\n" << inspector_keys;
+ }
+ else
+ {
+ std::cout << "<h2>Details</h2>\n" << inspector_keys;
+ }
+ display_details();
+ }
+
+ if (display_text == display_format)
+ {
+ std::cout << "\n\n" ;
+ }
+ else
+ {
+ std::cout
+ << "</body>\n"
+ "</html>\n";
+ }
+
+ return 0;
+}
diff --git a/tools/inspect/inspector.hpp b/tools/inspect/inspector.hpp
new file mode 100644
index 0000000000..ad9fdd01f9
--- /dev/null
+++ b/tools/inspect/inspector.hpp
@@ -0,0 +1,106 @@
+// inspector header --------------------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+// Copyright Rene Rivera 2004.
+// Copyright Gennaro Prota 2006.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_INSPECTOR_HPP
+#define BOOST_INSPECTOR_HPP
+
+#include <set>
+#include <iostream>
+#include <ostream>
+#include <string>
+#include "boost/filesystem/path.hpp"
+
+using std::string;
+using boost::filesystem::path;
+
+namespace boost
+{
+ namespace inspect
+ {
+ typedef std::set< string > string_set;
+
+ const char * line_break();
+
+ class inspector
+ {
+ protected:
+ inspector() {}
+
+ public:
+ virtual ~inspector() {}
+
+ virtual const char * name() const = 0; // example: "tab-check"
+ virtual const char * desc() const = 0; // example: "verify no tabs"
+
+ // always called:
+ virtual void inspect(
+ const string & /*library_name*/, // "filesystem"
+ const path & /*full_path*/ ) {} // "c:/foo/boost/filesystem/path.hpp"
+
+ // called only for registered leaf() signatures:
+ virtual void inspect(
+ const string & library_name, // "filesystem"
+ const path & full_path, // "c:/foo/boost/filesystem/path.hpp"
+ const string & contents ) // contents of file
+ = 0
+ ;
+
+ // called after all paths visited, but still in time to call error():
+ virtual void close() {}
+
+ // callback used by constructor to register leaf() signature.
+ // Signature can be a full file name (Jamfile) or partial (.cpp)
+ void register_signature( const string & signature );
+ const string_set & signatures() const { return m_signatures; }
+
+ // report error callback (from inspect(), close() ):
+ void error(
+ const string & library_name,
+ const path & full_path,
+ const string & msg,
+ int line_number =0 ); // 0 if not available or not applicable
+
+ private:
+ string_set m_signatures;
+ };
+
+ // for inspection of source code of one form or other
+ class source_inspector : public inspector
+ {
+ public:
+ // registers the basic set of known source signatures
+ source_inspector();
+ };
+
+ // for inspection of hypertext, specifically html
+ class hypertext_inspector : public inspector
+ {
+ public:
+ // registers the set of known html source signatures
+ hypertext_inspector();
+ };
+
+ inline string relative_to( const path & src_arg, const path & base_arg )
+ {
+ path base( base_arg );
+ base.normalize();
+ string::size_type pos( base.string().size() );
+ path src( src_arg.string().substr(pos) );
+ src.normalize();
+ return src.string().substr(1);
+ }
+
+ string impute_library( const path & full_dir_path );
+
+ }
+}
+
+#endif // BOOST_INSPECTOR_HPP
+
diff --git a/tools/inspect/license_check.cpp b/tools/inspect/license_check.cpp
new file mode 100644
index 0000000000..86d1d20e70
--- /dev/null
+++ b/tools/inspect/license_check.cpp
@@ -0,0 +1,48 @@
+// license_check implementation --------------------------------------------//
+
+// Copyright Beman Dawes 2002-2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "boost/regex.hpp"
+#include "license_check.hpp"
+
+namespace
+{
+ boost::regex license_regex(
+ //~ The next two lines change the regex so that it detects when the license
+ //~ doesn't follow the prefered statement. Disabled because it currently
+ //~ generates a large number of issues.
+ //~ "Distributed[\\s\\W]+"
+ //~ "under[\\s\\W]+the[\\s\\W]+"
+ "boost[\\s\\W]+software[\\s\\W]+license",
+ boost::regbase::normal | boost::regbase::icase);
+
+} // unnamed namespace
+
+namespace boost
+{
+ namespace inspect
+ {
+ license_check::license_check() : m_files_with_errors(0)
+ {
+ }
+
+ void license_check::inspect(
+ const string & library_name,
+ const path & full_path, // example: c:/foo/boost/filesystem/path.hpp
+ const string & contents ) // contents of file to be inspected
+ {
+ if (contents.find( "boostinspect:" "nolicense" ) != string::npos) return;
+
+ if ( !boost::regex_search( contents, license_regex ) )
+ {
+ ++m_files_with_errors;
+ error( library_name, full_path, name() );
+ }
+ }
+ } // namespace inspect
+} // namespace boost
+
+
diff --git a/tools/inspect/license_check.hpp b/tools/inspect/license_check.hpp
new file mode 100644
index 0000000000..8312023632
--- /dev/null
+++ b/tools/inspect/license_check.hpp
@@ -0,0 +1,40 @@
+// license_check header ----------------------------------------------------//
+
+// Copyright Beman Dawes 2002, 2003.
+// Copyright Rene Rivera 2004.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_LICENSE_CHECK_HPP
+#define BOOST_LICENSE_CHECK_HPP
+
+#include "inspector.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ class license_check : public source_inspector
+ {
+ long m_files_with_errors;
+ public:
+
+ license_check();
+ virtual const char * name() const { return "*Lic*"; }
+ virtual const char * desc() const { return "missing Boost license info, or wrong reference text"; }
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path,
+ const std::string & contents );
+
+ virtual ~license_check()
+ { std::cout << " "
+ << m_files_with_errors << " files missing Boost license info or having wrong reference text" << line_break(); }
+ };
+ }
+}
+
+#endif // BOOST_LICENSE_CHECK_HPP
diff --git a/tools/inspect/link_check.cpp b/tools/inspect/link_check.cpp
new file mode 100644
index 0000000000..ca692bdfb2
--- /dev/null
+++ b/tools/inspect/link_check.cpp
@@ -0,0 +1,487 @@
+// link_check implementation -----------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "link_check.hpp"
+#include "boost/regex.hpp"
+#include "boost/filesystem/operations.hpp"
+#include <boost/algorithm/string/case_conv.hpp>
+#include <cstdlib>
+#include <set>
+
+// #include <iostream>
+
+namespace fs = boost::filesystem;
+
+namespace
+{
+ boost::regex html_bookmark_regex(
+ "<([^\\s<>]*)\\s*[^<>]*\\s+(NAME|ID)\\s*=\\s*(['\"])(.*?)\\3"
+ "|<!--.*?-->",
+ boost::regbase::normal | boost::regbase::icase);
+ boost::regex html_url_regex(
+ "<([^\\s<>]*)\\s*[^<>]*\\s+(?:HREF|SRC)" // HREF or SRC
+ "\\s*=\\s*(['\"])\\s*(.*?)\\s*\\2"
+ "|<!--.*?-->",
+ boost::regbase::normal | boost::regbase::icase);
+ boost::regex css_url_regex(
+ "(\\@import\\s*[\"']|url\\s*\\(\\s*[\"']?)([^\"')]*)"
+ "|/\\*.*?\\*/",
+ boost::regbase::normal | boost::regbase::icase);
+
+ // Regular expression for parsing URLS from:
+ // http://tools.ietf.org/html/rfc3986#appendix-B
+ boost::regex url_decompose_regex(
+ "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$",
+ boost::regbase::normal);
+
+ typedef std::set<std::string> bookmark_set;
+ bookmark_set bookmarks;
+ bookmark_set bookmarks_lowercase; // duplicate check needs case insensitive
+
+ // Decode html escapsed ampersands, returns an empty string if there's an error.
+ std::string decode_ampersands(std::string const& url_path) {
+ std::string::size_type pos = 0, next;
+ std::string result;
+ result.reserve(url_path.length());
+
+ while((next = url_path.find('&', pos)) != std::string::npos) {
+ result.append(url_path, pos, next - pos);
+ pos = next;
+ if(url_path.substr(pos, 5) == "&amp;") {
+ result += '&'; pos += 5;
+ }
+ else {
+ result += '&'; pos += 1;
+ }
+ break;
+ }
+
+ result.append(url_path, pos, url_path.length());
+
+ return result;
+ }
+
+ // Decode percent encoded characters, returns an empty string if there's an error.
+ std::string decode_percents(std::string const& url_path) {
+ std::string::size_type pos = 0, next;
+ std::string result;
+ result.reserve(url_path.length());
+
+ while((next = url_path.find('%', pos)) != std::string::npos) {
+ result.append(url_path, pos, next - pos);
+ pos = next;
+ switch(url_path[pos]) {
+ case '%': {
+ if(url_path.length() - next < 3) return "";
+ char hex[3] = { url_path[next + 1], url_path[next + 2], '\0' };
+ char* end_ptr;
+ result += (char) std::strtol(hex, &end_ptr, 16);
+ if(*end_ptr) return "";
+ pos = next + 3;
+ break;
+ }
+ }
+ }
+
+ result.append(url_path, pos, url_path.length());
+
+ return result;
+ }
+
+ bool is_css(const path & p) {
+ return p.extension() == ".css";
+ }
+
+} // unnamed namespace
+
+namespace boost
+{
+ namespace inspect
+ {
+
+// link_check constructor --------------------------------------------------//
+
+ link_check::link_check()
+ : m_broken_errors(0), m_unlinked_errors(0), m_invalid_errors(0),
+ m_bookmark_errors(0), m_duplicate_bookmark_errors(0)
+ {
+ // HTML signatures are already registered by the base class,
+ // 'hypertext_inspector'
+ register_signature(".css");
+ }
+
+// inspect (all) -----------------------------------------------------------//
+
+ void link_check::inspect(
+ const string & /*library_name*/,
+ const path & full_path )
+ {
+ // keep track of paths already encountered to reduce disk activity
+ if ( !fs::is_directory( full_path ) )
+ m_paths[ relative_to( full_path, fs::initial_path() ) ] |= m_present;
+ }
+
+// inspect ( .htm, .html, .shtml, .css ) -----------------------------------//
+
+ void link_check::inspect(
+ const string & library_name,
+ const path & full_path, // example: c:/foo/boost/filesystem/path.hpp
+ const string & contents ) // contents of file to be inspected
+ {
+ if (contents.find( "boostinspect:" "nounlinked" ) != string::npos)
+ m_paths[ relative_to( full_path, fs::initial_path() ) ] |= m_nounlinked_errors;
+
+ bool no_link_errors =
+ (contents.find( "boostinspect:" "nolink" ) != string::npos);
+
+ // build bookmarks databases
+ bookmarks.clear();
+ bookmarks_lowercase.clear();
+ string::const_iterator a_start( contents.begin() );
+ string::const_iterator a_end( contents.end() );
+ boost::match_results< string::const_iterator > a_what;
+ boost::match_flag_type a_flags = boost::match_default;
+
+ if(!is_css(full_path))
+ {
+ string previous_id;
+
+ while( boost::regex_search( a_start, a_end, a_what, html_bookmark_regex, a_flags) )
+ {
+ // a_what[0] contains the whole string iterators.
+ // a_what[1] contains the tag iterators.
+ // a_what[2] contains the attribute name.
+ // a_what[4] contains the bookmark iterators.
+
+ if (a_what[4].matched)
+ {
+ string tag( a_what[1].first, a_what[1].second );
+ boost::algorithm::to_lower(tag);
+ string attribute( a_what[2].first, a_what[2].second );
+ boost::algorithm::to_lower(attribute);
+ string bookmark( a_what[4].first, a_what[4].second );
+
+ bool name_following_id = ( attribute == "name" && previous_id == bookmark );
+ if ( tag != "meta" && attribute == "id" ) previous_id = bookmark;
+ else previous_id.clear();
+
+ if ( tag != "meta" && !name_following_id )
+ {
+ bookmarks.insert( bookmark );
+// std::cout << "******************* " << bookmark << '\n';
+
+ // w3.org recommends case-insensitive checking for duplicate bookmarks
+ // since some browsers do a case-insensitive match.
+ string bookmark_lowercase( bookmark );
+ boost::algorithm::to_lower(bookmark_lowercase);
+
+ std::pair<bookmark_set::iterator, bool> result
+ = bookmarks_lowercase.insert( bookmark_lowercase );
+ if (!result.second)
+ {
+ ++m_duplicate_bookmark_errors;
+ int ln = std::count( contents.begin(), a_what[3].first, '\n' ) + 1;
+ error( library_name, full_path, "Duplicate bookmark: " + bookmark, ln );
+ }
+ }
+ }
+
+ a_start = a_what[0].second; // update search position
+ a_flags |= boost::match_prev_avail; // update flags
+ a_flags |= boost::match_not_bob;
+ }
+ }
+
+ // process urls
+ string::const_iterator start( contents.begin() );
+ string::const_iterator end( contents.end() );
+ boost::match_results< string::const_iterator > what;
+ boost::match_flag_type flags = boost::match_default;
+
+ if(!is_css(full_path))
+ {
+ while( boost::regex_search( start, end, what, html_url_regex, flags) )
+ {
+ // what[0] contains the whole string iterators.
+ // what[1] contains the element type iterators.
+ // what[3] contains the URL iterators.
+
+ if(what[3].matched)
+ {
+ string type( what[1].first, what[1].second );
+ boost::algorithm::to_lower(type);
+
+ // TODO: Complain if 'link' tags use external stylesheets.
+ do_url( string( what[3].first, what[3].second ),
+ library_name, full_path, no_link_errors,
+ type == "a" || type == "link", contents.begin(), what[3].first );
+ }
+
+ start = what[0].second; // update search position
+ flags |= boost::match_prev_avail; // update flags
+ flags |= boost::match_not_bob;
+ }
+ }
+
+ while( boost::regex_search( start, end, what, css_url_regex, flags) )
+ {
+ // what[0] contains the whole string iterators.
+ // what[2] contains the URL iterators.
+
+ if(what[2].matched)
+ {
+ do_url( string( what[2].first, what[2].second ),
+ library_name, full_path, no_link_errors, false,
+ contents.begin(), what[3].first );
+ }
+
+ start = what[0].second; // update search position
+ flags |= boost::match_prev_avail; // update flags
+ flags |= boost::match_not_bob;
+ }
+ }
+
+// do_url ------------------------------------------------------------------//
+
+ void link_check::do_url( const string & url, const string & library_name,
+ const path & source_path, bool no_link_errors, bool allow_external_content,
+ std::string::const_iterator contents_begin, std::string::const_iterator url_start )
+ // precondition: source_path.is_complete()
+ {
+ if(!no_link_errors && url.empty()) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Empty URL.", ln );
+ return;
+ }
+
+ // Decode ampersand encoded characters.
+ string decoded_url = is_css(source_path) ? url : decode_ampersands(url);
+ if(decoded_url.empty()) {
+ if(!no_link_errors) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid URL (invalid ampersand encodings): " + url, ln );
+ }
+ return;
+ }
+
+ boost::smatch m;
+ if(!boost::regex_match(decoded_url, m, url_decompose_regex)) {
+ if(!no_link_errors) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Invalid URL: " + decoded_url, ln );
+ }
+ return;
+ }
+
+ bool scheme_matched = m[2].matched,
+ authority_matched = m[4].matched,
+ //query_matched = m[7].matched,
+ fragment_matched = m[9].matched;
+
+ std::string scheme(m[2]),
+ authority(m[4]),
+ url_path(m[5]),
+ //query(m[7]),
+ fragment(m[9]);
+
+ // Check for external content
+ if(!allow_external_content && (authority_matched || scheme_matched)) {
+ if(!no_link_errors) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "External content: " + decoded_url, ln );
+ }
+ }
+
+ // Protocol checks
+ if(scheme_matched) {
+ if(scheme == "http" || scheme == "https") {
+ // All http links should have a hostname. Generally if they don't
+ // it's by mistake. If they shouldn't, then a protocol isn't
+ // required.
+ if(!authority_matched) {
+ if(!no_link_errors) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "No hostname: " + decoded_url, ln );
+ }
+ }
+
+ return;
+ }
+ else if(scheme == "file") {
+ if(!no_link_errors) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid URL (hardwired file): " + decoded_url, ln );
+ }
+ }
+ else if(scheme == "mailto" || scheme == "ftp" || scheme == "news" || scheme == "javascript") {
+ if ( !no_link_errors && is_css(source_path) ) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid protocol for css: " + decoded_url, ln );
+ }
+ }
+ else {
+ if(!no_link_errors) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Unknown protocol: '" + scheme + "' in url: " + decoded_url, ln );
+ }
+ }
+
+ return;
+ }
+
+ // Hostname without protocol.
+ if(authority_matched) {
+ if(!no_link_errors) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid URL (hostname without protocol): " + decoded_url, ln );
+ }
+ }
+
+ // Check the fragment identifier
+ if ( fragment_matched ) {
+ if ( is_css(source_path) ) {
+ if ( !no_link_errors ) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Fragment link in CSS: " + decoded_url, ln );
+ }
+ }
+ else {
+ if ( !no_link_errors && fragment.find( '#' ) != string::npos )
+ {
+ ++m_bookmark_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Invalid bookmark: " + decoded_url, ln );
+ }
+ else if ( !no_link_errors && url_path.empty() && !fragment.empty()
+ // w3.org recommends case-sensitive broken bookmark checking
+ // since some browsers do a case-sensitive match.
+ && bookmarks.find(decode_percents(fragment)) == bookmarks.end() )
+ {
+ ++m_broken_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Unknown bookmark: " + decoded_url, ln );
+ }
+ }
+
+ // No more to do if it's just a fragment identifier
+ if(url_path.empty()) return;
+ }
+
+ // Detect characters banned by RFC2396:
+ if ( !no_link_errors && decoded_url.find_first_of( " <>\"{}|\\^[]'" ) != string::npos )
+ {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid character in URL: " + decoded_url, ln );
+ }
+
+ // Check that we actually have a path.
+ if(url_path.empty()) {
+ if(!no_link_errors) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid URL (empty path in relative url): " + decoded_url, ln );
+ }
+ }
+
+ // Decode percent encoded characters.
+ string decoded_path = decode_percents(url_path);
+ if(decoded_path.empty()) {
+ if(!no_link_errors) {
+ ++m_invalid_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid URL (invalid character encodings): " + decoded_url, ln );
+ }
+ return;
+ }
+
+ // strip url of references to current dir
+ if ( decoded_path[0]=='.' && decoded_path[1]=='/' ) decoded_path.erase( 0, 2 );
+
+ // url is relative source_path.branch()
+ // convert to target_path, which is_complete()
+ path target_path;
+ try { target_path = source_path.branch_path() /= path( decoded_path ); }
+ catch ( const fs::filesystem_error & )
+ {
+ if(!no_link_errors) {
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ ++m_invalid_errors;
+ error( library_name, source_path,
+ "Invalid URL (error resolving path): " + decoded_url, ln );
+ }
+ return;
+ }
+
+ // create a m_paths entry if necessary
+ std::pair< const string, int > entry(
+ relative_to( target_path, fs::initial_path() ), 0 );
+ m_path_map::iterator itr( m_paths.find( entry.first ) );
+ if ( itr == m_paths.end() )
+ {
+ if ( fs::exists( target_path ) ) entry.second = m_present;
+ itr = m_paths.insert( entry ).first;
+ }
+
+ // itr now points to the m_paths entry
+ itr->second |= m_linked_to;
+
+ // if target isn't present, the link is broken
+ if ( !no_link_errors && (itr->second & m_present) == 0 )
+ {
+ ++m_broken_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Broken link: " + decoded_url, ln );
+ }
+ }
+
+// close -------------------------------------------------------------------//
+
+ void link_check::close()
+ {
+ for ( m_path_map::const_iterator itr = m_paths.begin();
+ itr != m_paths.end(); ++itr )
+ {
+// std::clog << itr->first << " " << itr->second << "\n";
+ if ( (itr->second & m_linked_to) != m_linked_to
+ && (itr->second & m_nounlinked_errors) != m_nounlinked_errors
+ && (itr->first.rfind( ".html" ) == itr->first.size()-5
+ || itr->first.rfind( ".htm" ) == itr->first.size()-4
+ || itr->first.rfind( ".css" ) == itr->first.size()-4)
+ // because they may be redirectors, it is OK if these are unlinked:
+ && itr->first.rfind( "index.html" ) == string::npos
+ && itr->first.rfind( "index.htm" ) == string::npos )
+ {
+ ++m_unlinked_errors;
+ path full_path( fs::initial_path() / path(itr->first) );
+ error( impute_library( full_path ), full_path, "Unlinked file" );
+ }
+ }
+ }
+
+ } // namespace inspect
+} // namespace boost
+
diff --git a/tools/inspect/link_check.hpp b/tools/inspect/link_check.hpp
new file mode 100644
index 0000000000..2878c4db02
--- /dev/null
+++ b/tools/inspect/link_check.hpp
@@ -0,0 +1,72 @@
+// link_check header -------------------------------------------------------//
+
+// Copyright Beman Dawes 2002
+// Copyright Rene Rivera 2004.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_LINK_CHECK_HPP
+#define BOOST_LINK_CHECK_HPP
+
+#include <map>
+
+#include "inspector.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ const int m_linked_to = 1;
+ const int m_present = 2;
+ const int m_nounlinked_errors = 4;
+
+ class link_check : public hypertext_inspector
+ {
+ long m_broken_errors;
+ long m_unlinked_errors;
+ long m_invalid_errors;
+ long m_bookmark_errors;
+ long m_duplicate_bookmark_errors;
+
+ typedef std::map< string, int > m_path_map;
+ m_path_map m_paths; // first() is relative initial_path()
+
+ void do_url( const string & url, const string & library_name,
+ const path & full_source_path, bool no_link_errors,
+ bool allow_external_links,
+ std::string::const_iterator contents_begin, std::string::const_iterator url_start);
+ public:
+
+ link_check();
+ virtual const char * name() const { return "*LINK*"; }
+ virtual const char * desc() const
+ { return "invalid bookmarks, duplicate bookmarks,"
+ " invalid urls, broken links, unlinked files"; }
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path );
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path,
+ const std::string & contents );
+
+ virtual void close();
+
+ virtual ~link_check()
+ {
+ std::cout << " " << m_bookmark_errors
+ << " bookmarks with invalid characters" << line_break();
+ std::cout << " " << m_duplicate_bookmark_errors
+ << " duplicate bookmarks" << line_break();
+ std::cout << " " << m_invalid_errors << " invalid urls" << line_break();
+ std::cout << " " << m_broken_errors << " broken links" << line_break();
+ std::cout << " " << m_unlinked_errors << " unlinked files" << line_break();
+ }
+ };
+ }
+}
+
+#endif // BOOST_LINK_CHECK_HPP
diff --git a/tools/inspect/link_check_test.html b/tools/inspect/link_check_test.html
new file mode 100644
index 0000000000..2d1e9845e4
--- /dev/null
+++ b/tools/inspect/link_check_test.html
@@ -0,0 +1,24 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<title>valid link</title>
+</head>
+
+<body>
+
+<p><a href="#link-target">valid bookmark link</a></p>
+<p><a href="link_check_test.html">valid relative link</a></p>
+<p><a href="foo.html#bar">broken relative link with bookmark</a></p>
+<p><a href="#broken">broken bookmark link</a></p>
+<p><a name="link-target">bookmark</a></p>
+<p><a name="second-target">second bookmark</a></p>
+<p><a name="SECOND-TARGET">duplicate second bookmark</a></p>
+<p>&nbsp;</p>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/tools/inspect/minmax_check.cpp b/tools/inspect/minmax_check.cpp
new file mode 100644
index 0000000000..00cc44bca2
--- /dev/null
+++ b/tools/inspect/minmax_check.cpp
@@ -0,0 +1,102 @@
+// minmax_check implementation --------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+// Copyright Gennaro Prota 2006.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#include <algorithm>
+
+#include "minmax_check.hpp"
+#include "boost/regex.hpp"
+#include "boost/lexical_cast.hpp"
+
+namespace
+{
+ boost::regex minmax_regex(
+ "("
+ "^\\s*#\\s*undef\\s*" // # undef
+ "\\b(min|max)\\b" // followed by min or max, whole word
+ ")"
+ "|" // or (ignored)
+ "("
+ "//[^\\n]*" // single line comments (//)
+ "|"
+ "/\\*.*?\\*/" // multi line comments (/**/)
+ "|"
+ "\"(?:\\\\\\\\|\\\\\"|[^\"])*\"" // string literals
+ ")"
+ "|" // or
+ "("
+ "\\b(min|max)\\b" // min or max, whole word
+ "\\s*\\(" // followed by 0 or more spaces and an opening paren
+ ")"
+ , boost::regex::normal);
+
+} // unnamed namespace
+
+namespace boost
+{
+ namespace inspect
+ {
+
+ // minmax_check constructor -------------------------------------------//
+
+ minmax_check::minmax_check()
+ : m_errors(0)
+ {
+ // C/C++ source code...
+ register_signature( ".c" );
+ register_signature( ".cpp" );
+ register_signature( ".cxx" );
+ register_signature( ".h" );
+ register_signature( ".hpp" );
+ register_signature( ".hxx" );
+ register_signature( ".inc" );
+ register_signature( ".ipp" );
+ }
+
+ // inspect ( C++ source files ) ---------------------------------------//
+
+ void minmax_check::inspect(
+ const string & library_name,
+ const path & full_path, // example: c:/foo/boost/filesystem/path.hpp
+ const string & contents) // contents of file to be inspected
+ {
+ if (contents.find( "boostinspect:" "nominmax" ) != string::npos) return;
+
+ boost::sregex_iterator cur(contents.begin(), contents.end(), minmax_regex), end;
+
+ for( ; cur != end; ++cur /*, ++m_errors*/ )
+ {
+
+ if(!(*cur)[3].matched)
+ {
+ string::const_iterator it = contents.begin();
+ string::const_iterator match_it = (*cur)[0].first;
+
+ string::const_iterator line_start = it;
+
+ string::size_type line_number = 1;
+ for ( ; it != match_it; ++it) {
+ if (string::traits_type::eq(*it, '\n')) {
+ ++line_number;
+ line_start = it + 1; // could be end()
+ }
+ }
+
+ ++m_errors;
+ error( library_name, full_path, string(name())
+ + " violation of Boost min/max guidelines on line "
+ + boost::lexical_cast<string>( line_number ) );
+ }
+
+ }
+ }
+
+ } // namespace inspect
+} // namespace boost
+
diff --git a/tools/inspect/minmax_check.hpp b/tools/inspect/minmax_check.hpp
new file mode 100644
index 0000000000..03ff923eaf
--- /dev/null
+++ b/tools/inspect/minmax_check.hpp
@@ -0,0 +1,45 @@
+// minmax_check header -------------------------------------------------------//
+
+// Copyright Beman Dawes 2002
+// Copyright Rene Rivera 2004.
+// Copyright Gennaro Prota 2006.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MINMAX_CHECK_HPP
+#define BOOST_MINMAX_CHECK_HPP
+
+#include "inspector.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ class minmax_check : public inspector
+ {
+ long m_errors;
+
+ public:
+
+ minmax_check();
+ virtual const char * name() const { return "*M*"; }
+ virtual const char * desc() const { return "uses of min or max that"
+ " have not been protected from the min/max macros,"
+ " or unallowed #undef-s"; }
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path,
+ const std::string & contents);
+
+ virtual ~minmax_check()
+ {
+ std::cout << " " << m_errors << " violations of the Boost min/max guidelines" << line_break();
+ }
+ };
+ }
+}
+
+#endif // BOOST_MINMAX_CHECK_HPP
diff --git a/tools/inspect/path_name_check.cpp b/tools/inspect/path_name_check.cpp
new file mode 100644
index 0000000000..87bc6842c9
--- /dev/null
+++ b/tools/inspect/path_name_check.cpp
@@ -0,0 +1,110 @@
+// path_name_check implementation ------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+// Copyright Gennaro Prota 2006.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "path_name_check.hpp"
+
+#include "boost/filesystem/operations.hpp"
+#include "boost/lexical_cast.hpp"
+
+#include <string>
+#include <algorithm>
+#include <cctype>
+#include <cstring>
+
+using std::string;
+
+namespace
+{
+ const char allowable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.";
+ const char initial_char[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+}
+
+namespace boost
+{
+ namespace inspect
+ {
+
+
+ file_name_check::file_name_check() : m_name_errors(0) {}
+
+ void file_name_check::inspect(
+ const string & library_name,
+ const path & full_path )
+ {
+ string::size_type pos;
+
+ // called for each file and directory, so only the leaf need be tested
+ string const leaf( full_path.leaf().string() );
+
+ // includes only allowable characters
+ if ( (pos = leaf.find_first_not_of( allowable )) != string::npos )
+ {
+ ++m_name_errors;
+ error( library_name, full_path, string(name())
+ + " file or directory name contains unacceptable character '"
+ + leaf[pos] + "'" );
+ }
+
+ // allowable initial character
+ if ( std::strchr( initial_char, leaf[0] ) == 0 )
+ {
+ ++m_name_errors;
+ error( library_name, full_path, string(name())
+ + " file or directory name begins with an unacceptable character" );
+ }
+
+ // rules for dot characters differ slightly for directories and files
+ if ( filesystem::is_directory( full_path ) )
+ {
+ if ( std::strchr( leaf.c_str(), '.' ) )
+ {
+ ++m_name_errors;
+ error( library_name, full_path, string(name())
+ + " directory name contains a dot character ('.')" );
+ }
+ }
+ //else // not a directory
+ //{
+ // // includes at most one dot character
+ // const char * first_dot = std::strchr( leaf.c_str(), '.' );
+ // if ( first_dot && std::strchr( first_dot+1, '.' ) )
+ // {
+ // ++m_name_errors;
+ // error( library_name, full_path, string(name())
+ // + " file name with more than one dot character ('.')" );
+ // }
+ //}
+
+ // the path, including a presumed root, does not exceed the maximum size
+ path const relative_path( relative_to( full_path, filesystem::initial_path() ) );
+ const unsigned max_relative_path = 207; // ISO 9660:1999 sets this limit
+ const string generic_root( "boost_X_XX_X/" );
+ if ( relative_path.string().size() >
+ ( max_relative_path - generic_root.size() ) )
+ {
+ ++m_name_errors;
+ error( library_name, full_path,
+ string(name())
+ + " path will exceed "
+ + boost::lexical_cast<string>(max_relative_path)
+ + " characters in a directory tree with a root in the form "
+ + generic_root + ", and this exceeds ISO 9660:1999 limit of 207" )
+ ;
+ }
+
+ }
+
+ file_name_check::~file_name_check()
+ {
+ std::cout << " " << m_name_errors << " " << desc() << line_break();
+ }
+
+
+ } // namespace inspect
+} // namespace boost
diff --git a/tools/inspect/path_name_check.hpp b/tools/inspect/path_name_check.hpp
new file mode 100644
index 0000000000..ec1218ace1
--- /dev/null
+++ b/tools/inspect/path_name_check.hpp
@@ -0,0 +1,48 @@
+// long_name_check header --------------------------------------------------//
+// (main class renamed to: file_name_check) - gps
+
+// Copyright Beman Dawes 2002.
+// Copyright Gennaro Prota 2006.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FILE_NAME_CHECK_HPP
+#define BOOST_FILE_NAME_CHECK_HPP
+
+#include "inspector.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ class file_name_check : public inspector
+ {
+ long m_name_errors;
+
+ public:
+
+ file_name_check();
+ virtual ~file_name_check();
+
+ virtual const char * name() const { return "*N*"; }
+ virtual const char * desc() const { return "file and directory name issues"; }
+
+ virtual void inspect(
+ const string & library_name,
+ const path & full_path );
+
+ virtual void inspect(
+ const string &, // "filesystem"
+ const path &, // "c:/foo/boost/filesystem/path.hpp"
+ const string &)
+ { /* empty */ }
+
+
+
+ };
+ }
+}
+
+#endif // BOOST_FILE_NAME_CHECK_HPP
diff --git a/tools/inspect/tab_check.cpp b/tools/inspect/tab_check.cpp
new file mode 100644
index 0000000000..e84d088da3
--- /dev/null
+++ b/tools/inspect/tab_check.cpp
@@ -0,0 +1,44 @@
+// tab_check implementation ------------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "tab_check.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ tab_check::tab_check() : m_files_with_errors(0)
+ {
+ register_signature( ".c" );
+ register_signature( ".cpp" );
+ register_signature( ".cxx" );
+ register_signature( ".h" );
+ register_signature( ".hpp" );
+ register_signature( ".hxx" );
+ register_signature( ".ipp" );
+ register_signature( "Jamfile" );
+ register_signature( ".py" );
+ }
+
+ void tab_check::inspect(
+ const string & library_name,
+ const path & full_path, // example: c:/foo/boost/filesystem/path.hpp
+ const string & contents ) // contents of file to be inspected
+ {
+ if (contents.find( "boostinspect:" "notab" ) != string::npos) return;
+
+ if ( contents.find( '\t' ) != string::npos )
+ {
+ ++m_files_with_errors;
+ error( library_name, full_path, name() );
+ }
+ }
+ } // namespace inspect
+} // namespace boost
+
+
diff --git a/tools/inspect/tab_check.hpp b/tools/inspect/tab_check.hpp
new file mode 100644
index 0000000000..9cc4cc3f9e
--- /dev/null
+++ b/tools/inspect/tab_check.hpp
@@ -0,0 +1,37 @@
+// tab_check header --------------------------------------------------------//
+
+// Copyright Beman Dawes 2002.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TAB_CHECK_HPP
+#define BOOST_TAB_CHECK_HPP
+
+#include "inspector.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ class tab_check : public inspector
+ {
+ long m_files_with_errors;
+ public:
+
+ tab_check();
+ virtual const char * name() const { return "*Tab*"; }
+ virtual const char * desc() const { return "tabs in file"; }
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path,
+ const std::string & contents );
+
+ virtual ~tab_check()
+ { std::cout << " " << m_files_with_errors << " files with tabs" << line_break(); }
+ };
+ }
+}
+
+#endif // BOOST_TAB_CHECK_HPP
diff --git a/tools/inspect/time_string.hpp b/tools/inspect/time_string.hpp
new file mode 100644
index 0000000000..fc005dddde
--- /dev/null
+++ b/tools/inspect/time_string.hpp
@@ -0,0 +1,55 @@
+// ---- time_string: thin wrapper around std::strftime -------- //
+//
+// Copyright Gennaro Prota 2006
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// ------------------------------------------------------------------
+//
+// $Id: time_string.hpp 47222 2008-07-08 14:29:03Z bemandawes $
+
+#ifndef BOOST_TIME_STRING_HPP_GP_20060731
+#define BOOST_TIME_STRING_HPP_GP_20060731
+
+#include <string>
+#include <ctime>
+
+#include <boost/config/warning_disable.hpp>
+
+namespace boost {
+
+// Many of the boost tools just need a quick way to obtain
+// a formatted "run date" string or similar. This is one.
+//
+// In case of failure false is returned and result is
+// unchanged.
+//
+inline
+bool time_string(std::string & result
+ , const std::string & format = "%X UTC, %A %d %B %Y")
+{
+ // give up qualifying names and using std::size_t,
+ // to avoid including "config.hpp"
+ using namespace std;
+
+ const int sz = 256;
+ char buffer [ sz ] = { 0 };
+ const time_t no_cal_time ( -1 );
+ time_t tod;
+
+ const bool ok =
+ time ( &tod ) != no_cal_time
+ && strftime( buffer, sz, format.c_str(), gmtime( &tod ) ) != 0
+ ;
+
+ if (ok)
+ result = buffer;
+
+ return ok;
+}
+
+}
+
+#endif // include guard
diff --git a/tools/inspect/unnamed_namespace_check.cpp b/tools/inspect/unnamed_namespace_check.cpp
new file mode 100644
index 0000000000..3850e3af6c
--- /dev/null
+++ b/tools/inspect/unnamed_namespace_check.cpp
@@ -0,0 +1,62 @@
+// unnamed_namespace_check -----------------------------------------//
+
+// Copyright Gennaro Prota 2006.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "boost/regex.hpp"
+#include "boost/lexical_cast.hpp"
+#include "unnamed_namespace_check.hpp"
+
+
+namespace
+{
+
+ boost::regex unnamed_namespace_regex(
+ "\\<namespace\\s(\\?\\?<|\\{)" // trigraph ??< or {
+ );
+
+} // unnamed namespace (ironical? :-)
+
+
+
+namespace boost
+{
+ namespace inspect
+ {
+ unnamed_namespace_check::unnamed_namespace_check() : m_errors(0)
+ {
+ register_signature( ".h" );
+ register_signature( ".hh" ); // just in case
+ register_signature( ".hpp" );
+ register_signature( ".hxx" ); // just in case
+ register_signature( ".inc" );
+ register_signature( ".ipp" );
+ register_signature( ".inl" );
+ }
+
+ void unnamed_namespace_check::inspect(
+ const string & library_name,
+ const path & full_path, // example: c:/foo/boost/filesystem/path.hpp
+ const string & contents ) // contents of file to be inspected
+ {
+ if (contents.find( "boostinspect:" "nounnamed" ) != string::npos) return;
+
+
+ boost::sregex_iterator cur(contents.begin(), contents.end(), unnamed_namespace_regex), end;
+ for( ; cur != end; ++cur, ++m_errors )
+ {
+ const string::size_type
+ ln = std::count( contents.begin(), (*cur)[0].first, '\n' ) + 1;
+
+ error( library_name, full_path, "Unnamed namespace", ln );
+ }
+
+
+ }
+ } // namespace inspect
+} // namespace boost
+
+
diff --git a/tools/inspect/unnamed_namespace_check.hpp b/tools/inspect/unnamed_namespace_check.hpp
new file mode 100644
index 0000000000..87f36b7170
--- /dev/null
+++ b/tools/inspect/unnamed_namespace_check.hpp
@@ -0,0 +1,39 @@
+// unnamed_namespace_check -----------------------------------------//
+
+// Copyright Gennaro Prota 2006.
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNNAMED_NAMESPACE_CHECK_HPP_GP_20060718
+#define BOOST_UNNAMED_NAMESPACE_CHECK_HPP_GP_20060718
+
+#include "inspector.hpp"
+
+namespace boost
+{
+ namespace inspect
+ {
+ class unnamed_namespace_check : public inspector
+ {
+ long m_errors;
+ public:
+
+ unnamed_namespace_check();
+ virtual const char * name() const { return "*U*"; }
+ virtual const char * desc() const { return "unnamed namespace in header"; }
+
+ virtual void inspect(
+ const std::string & library_name,
+ const path & full_path,
+ const std::string & contents );
+
+ virtual ~unnamed_namespace_check()
+ { std::cout << " " << m_errors << " usages of unnamed namespaces in headers (including .ipp files)" << line_break(); }
+ };
+ }
+}
+
+
+#endif // include guard
diff --git a/tools/inspect/wrong_line_ends_test.cpp b/tools/inspect/wrong_line_ends_test.cpp
new file mode 100644
index 0000000000..05d1a1b42e
--- /dev/null
+++ b/tools/inspect/wrong_line_ends_test.cpp
@@ -0,0 +1 @@
+// this is a test file; it isn't supposed to have correct line endings // Copyright Beman Dawes, 2003. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) line ending with cr line ending without any cr or nl \ No newline at end of file
diff --git a/tools/litre/cplusplus.py b/tools/litre/cplusplus.py
new file mode 100644
index 0000000000..c48e0678ed
--- /dev/null
+++ b/tools/litre/cplusplus.py
@@ -0,0 +1,810 @@
+# Copyright David Abrahams 2004.
+# Copyright Daniel Wallin 2006.
+# Distributed under the Boost
+# Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import os
+import tempfile
+import litre
+import re
+import sys
+import traceback
+
+# Thanks to Jean Brouwers for this snippet
+def _caller(up=0):
+ '''Get file name, line number, function name and
+ source text of the caller's caller as 4-tuple:
+ (file, line, func, text).
+
+ The optional argument 'up' allows retrieval of
+ a caller further back up into the call stack.
+
+ Note, the source text may be None and function
+ name may be '?' in the returned result. In
+ Python 2.3+ the file name may be an absolute
+ path.
+ '''
+ try: # just get a few frames'
+ f = traceback.extract_stack(limit=up+2)
+ if f:
+ return f[0]
+ except:
+ pass
+ # running with psyco?
+ return ('', 0, '', None)
+
+class Example:
+ closed = False
+ in_emph = None
+
+ def __init__(self, node, section, line_offset, line_hash = '#'):
+ # A list of text fragments comprising the Example. Start with a #line
+ # directive
+ self.section = section
+ self.line_hash = line_hash
+ self.node = node
+ self.body = []
+ self.line_offset = line_offset
+ self._number_of_prefixes = 0
+
+ self.emphasized = [] # indices of text strings that have been
+ # emphasized. These are generally expected to be
+ # invalid C++ and will need special treatment
+
+ def begin_emphasis(self):
+ self.in_emph = len(self.body)
+
+ def end_emphasis(self):
+ self.emphasized.append( (self.in_emph, len(self.body)) )
+
+ def append(self, s):
+ self.append_raw(self._make_line(s))
+
+ def prepend(self, s):
+ self.prepend_raw(self._make_line(s))
+
+ def append_raw(self, s):
+ self.body.append(s)
+
+ def prepend_raw(self, s):
+ self.body.insert(0,s)
+ self.emphasized = [ (x[0]+1,x[1]+1) for x in self.emphasized ]
+ self._number_of_prefixes += 1
+
+ def replace(self, s1, s2):
+ self.body = [x.replace(s1,s2) for x in self.body]
+
+ def sub(self, pattern, repl, count = 1, flags = re.MULTILINE):
+ pat = re.compile(pattern, flags)
+ for i,txt in enumerate(self.body):
+ if count > 0:
+ x, subs = pat.subn(repl, txt, count)
+ self.body[i] = x
+ count -= subs
+
+ def wrap(self, s1, s2):
+ self.append_raw(self._make_line(s2))
+ self.prepend_raw(self._make_line(s1, offset = -s1.count('\n')))
+
+ def replace_emphasis(self, s, index = 0):
+ """replace the index'th emphasized text with s"""
+ e = self.emphasized[index]
+ self.body[e[0]:e[1]] = [s]
+ del self.emphasized[index]
+
+ elipsis = re.compile('^([ \t]*)([.][.][.][ \t]*)$', re.MULTILINE)
+
+ def __str__(self):
+ # Comment out any remaining emphasized sections
+ b = [self.elipsis.sub(r'\1// \2', s) for s in self.body]
+ emph = self.emphasized
+ emph.reverse()
+ for e in emph:
+ b.insert(e[1], ' */')
+ b.insert(e[0], '/* ')
+ emph.reverse()
+
+ # Add initial #line
+ b.insert(
+ self._number_of_prefixes,
+ self._line_directive(self.node.line, self.node.source)
+ )
+
+ # Add trailing newline to avoid warnings
+ b.append('\n')
+ return ''.join(b)
+
+ def __repr__(self):
+ return "Example: " + repr(str(self))
+
+ def raw(self):
+ return ''.join(self.body)
+
+ def _make_line(self, s, offset = 0):
+ c = _caller(2)[1::-1]
+ offset -= s.count('\n')
+ return '\n%s%s\n' % (self._line_directive(offset = offset, *c), s.strip('\n'))
+
+ def _line_directive(self, line, source, offset = None):
+ if self.line_hash is None:
+ return '\n'
+
+ if offset is None:
+ offset = self.line_offset
+
+ if line is None or line <= -offset:
+ line = 1
+ else:
+ line += offset
+
+ if source is None:
+ return '%sline %d\n' % (self.line_hash, line)
+ else:
+ return '%sline %d "%s"\n' % (self.line_hash, line, source)
+
+
+def syscmd(
+ cmd
+ , expect_error = False
+ , input = None
+ , max_output_lines = None
+ ):
+
+ # On windows close() returns the exit code, on *nix it doesn't so
+ # we need to use popen2.Popen4 instead.
+ if sys.platform == 'win32':
+ stdin, stdout_stderr = os.popen4(cmd)
+ if input: stdin.write(input)
+ stdin.close()
+
+ out = stdout_stderr.read()
+ status = stdout_stderr.close()
+ else:
+ import popen2
+ process = popen2.Popen4(cmd)
+ if input: process.tochild.write(input)
+ out = process.fromchild.read()
+ status = process.wait()
+
+ if max_output_lines is not None:
+ out = '\n'.join(out.split('\n')[:max_output_lines])
+
+ if expect_error:
+ status = not status
+
+ if status:
+ print
+ print '========== offending command ==========='
+ print cmd
+ print '------------ stdout/stderr -------------'
+ print expect_error and 'Error expected, but none seen' or out
+ elif expect_error > 1:
+ print
+ print '------ Output of Expected Error --------'
+ print out
+ print '----------------------------------------'
+
+ sys.stdout.flush()
+
+ return (status,out)
+
+
+def expand_vars(path):
+ if os.name == 'nt':
+ re_env = re.compile(r'%\w+%')
+ return re_env.sub(
+ lambda m: os.environ.get( m.group(0)[1:-1] )
+ , path
+ )
+ else:
+ return os.path.expandvars(path)
+
+def remove_directory_and_contents(path):
+ for root, dirs, files in os.walk(path, topdown=False):
+ for name in files:
+ os.remove(os.path.join(root, name))
+ for name in dirs:
+ os.rmdir(os.path.join(root, name))
+ os.rmdir(path)
+
+class BuildResult:
+ def __init__(self, path):
+ self.path = path
+
+ def __repr__(self):
+ return self.path
+
+ def __del__(self):
+ remove_directory_and_contents(self.path)
+
+class CPlusPlusTranslator(litre.LitreTranslator):
+
+ _exposed_attrs = ['compile', 'test', 'ignore', 'match_stdout', 'stack', 'config'
+ , 'example', 'prefix', 'preprocessors', 'litre_directory',
+ 'litre_translator', 'includes', 'build', 'jam_prefix',
+ 'run_python']
+
+ last_run_output = ''
+
+ """Attributes that will be made available to litre code"""
+
+ def __init__(self, document, config):
+ litre.LitreTranslator.__init__(self, document, config)
+ self.in_literal = False
+ self.in_table = True
+ self.preprocessors = []
+ self.stack = []
+ self.example = None
+ self.prefix = []
+ self.includes = config.includes
+ self.litre_directory = os.path.split(__file__)[0]
+ self.config = config
+ self.litre_translator = self
+ self.line_offset = 0
+ self.last_source = None
+ self.jam_prefix = []
+
+ self.globals = { 'test_literals_in_tables' : False }
+ for m in self._exposed_attrs:
+ self.globals[m] = getattr(self, m)
+
+ self.examples = {}
+ self.current_section = None
+
+ #
+ # Stuff for use by docutils writer framework
+ #
+ def visit_emphasis(self, node):
+ if self.in_literal:
+ self.example.begin_emphasis()
+
+ def depart_emphasis(self, node):
+ if self.in_literal:
+ self.example.end_emphasis()
+
+ def visit_section(self, node):
+ self.current_section = node['ids'][0]
+
+ def visit_literal_block(self, node):
+ if node.source is None:
+ node.source = self.last_source
+ self.last_source = node.source
+
+ # create a new example
+ self.example = Example(node, self.current_section, line_offset = self.line_offset, line_hash = self.config.line_hash)
+
+ self.stack.append(self.example)
+
+ self.in_literal = True
+
+ def depart_literal_block(self, node):
+ self.in_literal = False
+
+ def visit_literal(self, node):
+ if self.in_table and self.globals['test_literals_in_tables']:
+ self.visit_literal_block(node)
+ else:
+ litre.LitreTranslator.visit_literal(self,node)
+
+ def depart_literal(self, node):
+ if self.in_table and self.globals['test_literals_in_tables']:
+ self.depart_literal_block(node)
+ else:
+ litre.LitreTranslator.depart_literal(self,node)
+
+ def visit_table(self,node):
+ self.in_table = True
+ litre.LitreTranslator.visit_table(self,node)
+
+ def depart_table(self,node):
+ self.in_table = False
+ litre.LitreTranslator.depart_table(self,node)
+
+ def visit_Text(self, node):
+ if self.in_literal:
+ self.example.append_raw(node.astext())
+
+ def depart_document(self, node):
+ self.write_examples()
+
+ #
+ # Private stuff
+ #
+
+ def handled(self, n = 1):
+ r = self.stack[-n:]
+ del self.stack[-n:]
+ return r
+
+ def _execute(self, code):
+ """Override of litre._execute; sets up variable context before
+ evaluating code
+ """
+ self.globals['example'] = self.example
+ eval(code, self.globals)
+
+ #
+ # Stuff for use by embedded python code
+ #
+
+ def match_stdout(self, expected = None):
+
+ if expected is None:
+ expected = self.example.raw()
+ self.handled()
+
+ if not re.search(expected, self.last_run_output, re.MULTILINE):
+ #if self.last_run_output.strip('\n') != expected.strip('\n'):
+ print 'output failed to match example'
+ print '-------- Actual Output -------------'
+ print repr(self.last_run_output)
+ print '-------- Expected Output -----------'
+ print repr(expected)
+ print '------------------------------------'
+ sys.stdout.flush()
+
+ def ignore(self, n = 1):
+ if n == 'all':
+ n = len(self.stack)
+ return self.handled(n)
+
+ def wrap(self, n, s1, s2):
+ self.stack[-1].append(s2)
+ self.stack[-n].prepend(s1)
+
+
+ def compile(
+ self
+ , howmany = 1
+ , pop = -1
+ , expect_error = False
+ , extension = '.o'
+ , options = ['-c']
+ , built_handler = lambda built_file: None
+ , source_file = None
+ , source_suffix = '.cpp'
+ # C-style comments by default; handles C++ and YACC
+ , make_comment = lambda text: '/*\n%s\n*/' % text
+ , built_file = None
+ , command = None
+ ):
+ """
+ Compile examples on the stack, whose topmost item is the last example
+ seen but not yet handled so far.
+
+ :howmany: How many of the topmost examples on the stack to compile.
+ You can pass a number, or 'all' to indicate that all examples should
+ be compiled.
+
+ :pop: How many of the topmost examples to discard. By default, all of
+ the examples that are compiled are discarded.
+
+ :expect_error: Whether a compilation error is to be expected. Any value
+ > 1 will cause the expected diagnostic's text to be dumped for
+ diagnostic purposes. It's common to expect an error but see a
+ completely unrelated one because of bugs in the example (you can get
+ this behavior for all examples by setting show_expected_error_output
+ in your config).
+
+ :extension: The extension of the file to build (set to .exe for
+ run)
+
+ :options: Compiler flags
+
+ :built_file: A path to use for the built file. By default, a temp
+ filename is conjured up
+
+ :built_handler: A function that's called with the name of the built file
+ upon success.
+
+ :source_file: The full name of the source file to write
+
+ :source_suffix: If source_file is None, the suffix to use for the source file
+
+ :make_comment: A function that transforms text into an appropriate comment.
+
+ :command: A function that is passed (includes, opts, target, source), where
+ opts is a string representing compiler options, target is the name of
+ the file to build, and source is the name of the file into which the
+ example code is written. By default, the function formats
+ litre.config.compiler with its argument tuple.
+ """
+
+ # Grab one example by default
+ if howmany == 'all':
+ howmany = len(self.stack)
+
+ source = '\n'.join(
+ self.prefix
+ + [str(x) for x in self.stack[-howmany:]]
+ )
+
+ source = reduce(lambda s, f: f(s), self.preprocessors, source)
+
+ if pop:
+ if pop < 0:
+ pop = howmany
+ del self.stack[-pop:]
+
+ if len(self.stack):
+ self.example = self.stack[-1]
+
+ cpp = self._source_file_path(source_file, source_suffix)
+
+ if built_file is None:
+ built_file = self._output_file_path(source_file, extension)
+
+ opts = ' '.join(options)
+
+ includes = ' '.join(['-I%s' % d for d in self.includes])
+ if not command:
+ command = self.config.compiler
+
+ if type(command) == str:
+ command = lambda i, o, t, s, c = command: c % (i, o, t, s)
+
+ cmd = command(includes, opts, expand_vars(built_file), expand_vars(cpp))
+
+ if expect_error and self.config.show_expected_error_output:
+ expect_error += 1
+
+
+ comment_cmd = command(includes, opts, built_file, os.path.basename(cpp))
+ comment = make_comment(config.comment_text(comment_cmd, expect_error))
+
+ self._write_source(cpp, '\n'.join([comment, source]))
+
+ #print 'wrote in', cpp
+ #print 'trying command', cmd
+
+ status, output = syscmd(cmd, expect_error)
+
+ if status or expect_error > 1:
+ print
+ if expect_error and expect_error < 2:
+ print 'Compilation failure expected, but none seen'
+ print '------------ begin offending source ------------'
+ print open(cpp).read()
+ print '------------ end offending source ------------'
+
+ if self.config.save_cpp:
+ print 'saved in', repr(cpp)
+ else:
+ self._remove_source(cpp)
+
+ sys.stdout.flush()
+ else:
+ print '.',
+ sys.stdout.flush()
+ built_handler(built_file)
+
+ self._remove_source(cpp)
+
+ try:
+ self._unlink(built_file)
+ except:
+ if not expect_error:
+ print 'failed to unlink', built_file
+
+ return status
+
+ def test(
+ self
+ , rule = 'run'
+ , howmany = 1
+ , pop = -1
+ , expect_error = False
+ , requirements = ''
+ , input = ''
+ ):
+
+ # Grab one example by default
+ if howmany == 'all':
+ howmany = len(self.stack)
+
+ source = '\n'.join(
+ self.prefix
+ + [str(x) for x in self.stack[-howmany:]]
+ )
+
+ source = reduce(lambda s, f: f(s), self.preprocessors, source)
+
+ id = self.example.section
+ if not id:
+ id = 'top-level'
+
+ if not self.examples.has_key(self.example.section):
+ self.examples[id] = [(rule, source)]
+ else:
+ self.examples[id].append((rule, source))
+
+ if pop:
+ if pop < 0:
+ pop = howmany
+ del self.stack[-pop:]
+
+ if len(self.stack):
+ self.example = self.stack[-1]
+
+ def write_examples(self):
+ jam = open(os.path.join(self.config.dump_dir, 'Jamfile.v2'), 'w')
+
+ jam.write('''
+import testing ;
+
+''')
+
+ for id,examples in self.examples.items():
+ for i in range(len(examples)):
+ cpp = '%s%d.cpp' % (id, i)
+
+ jam.write('%s %s ;\n' % (examples[i][0], cpp))
+
+ outfile = os.path.join(self.config.dump_dir, cpp)
+ print cpp,
+ try:
+ if open(outfile, 'r').read() == examples[i][1]:
+ print ' .. skip'
+ continue
+ except:
+ pass
+
+ open(outfile, 'w').write(examples[i][1])
+ print ' .. written'
+
+ jam.close()
+
+ def build(
+ self
+ , howmany = 1
+ , pop = -1
+ , source_file = 'example.cpp'
+ , expect_error = False
+ , target_rule = 'obj'
+ , requirements = ''
+ , input = ''
+ , output = 'example_output'
+ ):
+
+ # Grab one example by default
+ if howmany == 'all':
+ howmany = len(self.stack)
+
+ source = '\n'.join(
+ self.prefix
+ + [str(x) for x in self.stack[-howmany:]]
+ )
+
+ source = reduce(lambda s, f: f(s), self.preprocessors, source)
+
+ if pop:
+ if pop < 0:
+ pop = howmany
+ del self.stack[-pop:]
+
+ if len(self.stack):
+ self.example = self.stack[-1]
+
+ dir = tempfile.mkdtemp()
+ cpp = os.path.join(dir, source_file)
+ self._write_source(cpp, source)
+ self._write_jamfile(
+ dir
+ , target_rule = target_rule
+ , requirements = requirements
+ , input = input
+ , output = output
+ )
+
+ cmd = 'bjam'
+ if self.config.bjam_options:
+ cmd += ' %s' % self.config.bjam_options
+
+ os.chdir(dir)
+ status, output = syscmd(cmd, expect_error)
+
+ if status or expect_error > 1:
+ print
+ if expect_error and expect_error < 2:
+ print 'Compilation failure expected, but none seen'
+ print '------------ begin offending source ------------'
+ print open(cpp).read()
+ print '------------ begin offending Jamfile -----------'
+ print open(os.path.join(dir, 'Jamroot')).read()
+ print '------------ end offending Jamfile -------------'
+
+ sys.stdout.flush()
+ else:
+ print '.',
+ sys.stdout.flush()
+
+ if status: return None
+ else: return BuildResult(dir)
+
+ def _write_jamfile(self, path, target_rule, requirements, input, output):
+ jamfile = open(os.path.join(path, 'Jamroot'), 'w')
+ contents = r"""
+import modules ;
+
+BOOST_ROOT = [ modules.peek : BOOST_ROOT ] ;
+use-project /boost : $(BOOST_ROOT) ;
+
+%s
+
+%s %s
+ : example.cpp %s
+ : <include>.
+ %s
+ %s
+ ;
+ """ % (
+ '\n'.join(self.jam_prefix)
+ , target_rule
+ , output
+ , input
+ , ' '.join(['<include>%s' % d for d in self.includes])
+ , requirements
+ )
+
+ jamfile.write(contents)
+
+ def run_python(
+ self
+ , howmany = 1
+ , pop = -1
+ , module_path = []
+ , expect_error = False
+ ):
+ # Grab one example by default
+ if howmany == 'all':
+ howmany = len(self.stack)
+
+ if module_path == None: module_path = []
+
+ if isinstance(module_path, BuildResult) or type(module_path) == str:
+ module_path = [module_path]
+
+ module_path = map(lambda p: str(p), module_path)
+
+ source = '\n'.join(
+ self.prefix
+ + [str(x) for x in self.stack[-howmany:]]
+ )
+
+ if pop:
+ if pop < 0:
+ pop = howmany
+ del self.stack[-pop:]
+
+ if len(self.stack):
+ self.example = self.stack[-1]
+
+ r = re.compile(r'^(>>>|\.\.\.) (.*)$', re.MULTILINE)
+ source = r.sub(r'\2', source)
+ py = self._source_file_path(source_file = None, source_suffix = 'py')
+ open(py, 'w').write(source)
+
+ old_path = os.getenv('PYTHONPATH')
+ if old_path == None:
+ pythonpath = ':'.join(module_path)
+ old_path = ''
+ else:
+ pythonpath = old_path + ':%s' % ':'.join(module_path)
+
+ os.putenv('PYTHONPATH', pythonpath)
+ status, output = syscmd('python %s' % py)
+
+ if status or expect_error > 1:
+ print
+ if expect_error and expect_error < 2:
+ print 'Compilation failure expected, but none seen'
+ print '------------ begin offending source ------------'
+ print open(py).read()
+ print '------------ end offending Jamfile -------------'
+
+ sys.stdout.flush()
+ else:
+ print '.',
+ sys.stdout.flush()
+
+ self.last_run_output = output
+ os.putenv('PYTHONPATH', old_path)
+ self._unlink(py)
+
+ def _write_source(self, filename, contents):
+ open(filename,'w').write(contents)
+
+ def _remove_source(self, source_path):
+ os.unlink(source_path)
+
+ def _source_file_path(self, source_file, source_suffix):
+ if source_file is None:
+ cpp = tempfile.mktemp(suffix=source_suffix)
+ else:
+ cpp = os.path.join(tempfile.gettempdir(), source_file)
+ return cpp
+
+ def _output_file_path(self, source_file, extension):
+ return tempfile.mktemp(suffix=extension)
+
+ def _unlink(self, file):
+ file = expand_vars(file)
+ if os.path.exists(file):
+ os.unlink(file)
+
+ def _launch(self, exe, stdin = None):
+ status, output = syscmd(exe, input = stdin)
+ self.last_run_output = output
+
+ def run_(self, howmany = 1, stdin = None, **kw):
+ new_kw = { 'options':[], 'extension':'.exe' }
+ new_kw.update(kw)
+
+ self.compile(
+ howmany
+ , built_handler = lambda exe: self._launch(exe, stdin = stdin)
+ , **new_kw
+ )
+
+ def astext(self):
+ return ""
+ return '\n\n ---------------- Unhandled Fragment ------------ \n\n'.join(
+ [''] # generates a leading announcement
+ + [ unicode(s) for s in self.stack]
+ )
+
+class DumpTranslator(CPlusPlusTranslator):
+ example_index = 1
+
+ def _source_file_path(self, source_file, source_suffix):
+ if source_file is None:
+ source_file = 'example%s%s' % (self.example_index, source_suffix)
+ self.example_index += 1
+
+ cpp = os.path.join(config.dump_dir, source_file)
+ return cpp
+
+ def _output_file_path(self, source_file, extension):
+ chapter = os.path.basename(config.dump_dir)
+ return '%%TEMP%%\metaprogram-%s-example%s%s' \
+ % ( chapter, self.example_index - 1, extension)
+
+ def _remove_source(self, source_path):
+ pass
+
+
+class WorkaroundTranslator(DumpTranslator):
+ """Translator used to test/dump workaround examples for vc6 and vc7. Just
+ like a DumpTranslator except that we leave existing files alone.
+
+ Warning: not sensitive to changes in .rst source!! If you change the actual
+ examples in source files you will have to move the example files out of the
+ way and regenerate them, then re-incorporate the workarounds.
+ """
+ def _write_source(self, filename, contents):
+ if not os.path.exists(filename):
+ DumpTranslator._write_source(self, filename, contents)
+
+class Config:
+ save_cpp = False
+ line_hash = '#'
+ show_expected_error_output = False
+ max_output_lines = None
+
+class Writer(litre.Writer):
+ translator = CPlusPlusTranslator
+
+ def __init__(
+ self
+ , config
+ ):
+ litre.Writer.__init__(self)
+ self._config = Config()
+ defaults = Config.__dict__
+
+ # update config elements
+ self._config.__dict__.update(config.__dict__)
+# dict([i for i in config.__dict__.items()
+# if i[0] in config.__all__]))
+
diff --git a/tools/litre/litre.py b/tools/litre/litre.py
new file mode 100644
index 0000000000..c0ac67e28d
--- /dev/null
+++ b/tools/litre/litre.py
@@ -0,0 +1,61 @@
+from docutils import writers
+from docutils import nodes
+
+class LitreTranslator(nodes.GenericNodeVisitor):
+
+ def __init__(self, document, config):
+ nodes.GenericNodeVisitor.__init__(self,document)
+ self._config = config
+
+ def default_visit(self, node):
+ pass
+ # print '**visiting:', repr(node)
+
+ def default_departure(self, node):
+ pass
+ # print '**departing:', repr(node)
+
+ def visit_raw(self, node):
+ if node.has_key('format'):
+ key = node['format'].lower()
+ if key == 'litre':
+ # This is probably very evil ;-)
+ #if node.has_key('source'):
+ # node.file = node.attributes['source']
+
+ self._handle_code(node, node.astext())
+
+ raise nodes.SkipNode
+
+ def visit_comment(self, node):
+ code = node.astext()
+ if code[0] == '@':
+ self._handle_code(node, code[1:].strip())
+
+ def _handle_code(self, node, code):
+ start_line = node.line or 0
+ start_line -= code.count('\n') + 2 # docutils bug workaround?
+ try:
+ self._execute(compile( start_line*'\n' + code, str(node.source), 'exec'))
+ except:
+ print '\n------- begin offending Python source -------'
+ print code
+ print '------- end offending Python source -------'
+ raise
+
+ def _execute(self, code):
+ """Override this to set up local variable context for code before
+ invoking it
+ """
+ eval(code)
+
+class Writer(writers.Writer):
+ translator = LitreTranslator
+ _config = None
+
+ def translate(self):
+ visitor = self.translator(self.document, self._config)
+ self.document.walkabout(visitor)
+ self.output = visitor.astext()
+
+
diff --git a/tools/litre/tool.py b/tools/litre/tool.py
new file mode 100644
index 0000000000..1533fc33d4
--- /dev/null
+++ b/tools/litre/tool.py
@@ -0,0 +1,67 @@
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+
+# try to import a litre_config.py file.
+try:
+ import litre_config as config
+except:
+ class config: pass
+
+import sys
+try: # if the user has set up docutils_root in his config, add it to the PYTHONPATH.
+ sys.path += ['%s/docutils' % config.docutils_root
+ , '%s/docutils/extras' % config.docutils_root]
+except: pass
+
+import docutils.writers
+import cplusplus
+import os
+
+from docutils.core import publish_cmdline, default_description
+
+description = ('Literate programming from ReStructuredText '
+ 'sources. ' + default_description)
+
+def _pop_option(prefix):
+ found = None
+ for opt in sys.argv:
+ if opt.startswith(prefix):
+ sys.argv = [ x for x in sys.argv if x != opt ]
+ found = opt
+ if prefix.endswith('='):
+ found = opt[len(prefix):]
+ return found
+
+
+dump_dir = _pop_option('--dump_dir=')
+max_output_lines = _pop_option('--max_output_lines=')
+
+if dump_dir:
+
+ cplusplus.Writer.translator = cplusplus.DumpTranslator
+ if _pop_option('--workaround'):
+ cplusplus.Writer.translator = cplusplus.WorkaroundTranslator
+ config.includes.insert(0, os.path.join(os.path.split(dump_dir)[0], 'patches'))
+
+ config.dump_dir = os.path.abspath(dump_dir)
+ if _pop_option('--cleanup_source'):
+ config.line_hash = None
+
+ if not os.path.exists(config.dump_dir):
+ os.makedirs(config.dump_dir)
+
+if max_output_lines:
+ config.max_output_lines = int(max_output_lines)
+
+config.bjam_options = _pop_option('--bjam=')
+
+config.includes = []
+
+publish_cmdline(
+ writer=cplusplus.Writer(config),
+ description=description
+ )
diff --git a/tools/make-cputime-page.pl b/tools/make-cputime-page.pl
new file mode 100644
index 0000000000..e6969be597
--- /dev/null
+++ b/tools/make-cputime-page.pl
@@ -0,0 +1,54 @@
+#!/usr/bin/perl -w
+
+# Copyright 2004 Aleksey Gurtovoy
+# Copyright 2001 Jens Maurer
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+use strict;
+
+my $filename;
+my $compiler;
+my $time = 0;
+my $ct = 0;
+my $first = 2;
+
+print "<html>\n<head>\n<title>\nCompile Times</title>\n</head>\n\n";
+print "<body bgcolor=\"#ffffff\" text=\"#000000\">\n";
+print "<img border=\"0\" src=\"boost.png\" width=\"277\" height=\"86\">";
+print "<p>\n";
+print "Compile time for each successful regression test in seconds.\n";
+print "<p>\n";
+
+print "<table border=\"1\">\n";
+print "<tr><td>Test</td>\n";
+
+while(<>) {
+ if(/^\*\*\* (.*) \*\*\*$/) {
+ $filename = $1;
+ $first = ($first == 0 ? 0 : $first-1);
+ if($first == 0) {
+ print "</tr>\n\n<tr align=right>\n<td align=left><a href=\"http://www.boost.org/$filename\">$filename</a></td>\n";
+ }
+ } elsif(/^\*\* (.*)/) {
+ $compiler = $1;
+ if($first) {
+ print "<td>$compiler</td>\n";
+ } else {
+ $ct = 1;
+ }
+ } elsif($ct && /^CPU time: ([.0-9]*) s user, ([.0-9]*) s system/) {
+ $time = $1 + $2;
+ } elsif($ct && /^Pass$/) {
+ printf "<td>%.02f</td>\n", $time;
+ $ct = 0;
+ } elsif($ct && /^Fail$/) {
+ print "<td>-</td>\n";
+ $ct = 0;
+ }
+}
+
+print "</tr>\n";
+print "</table>\n";
+print "</body>\n</html>\n";
+
diff --git a/tools/quickbook/Jamfile.v2 b/tools/quickbook/Jamfile.v2
new file mode 100644
index 0000000000..5a7cec8158
--- /dev/null
+++ b/tools/quickbook/Jamfile.v2
@@ -0,0 +1,31 @@
+#==============================================================================
+# Copyright (c) 2002 2004 2006 Joel de Guzman
+# Copyright (c) 2004 Eric Niebler
+# http://spirit.sourceforge.net/
+#
+# Use, modification and distribution is subject to the Boost Software
+# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+
+# Install quickbook by default.
+
+install dist-bin
+ :
+ src//quickbook
+ :
+ <install-type>EXE
+ <location>../../dist/bin
+ :
+ release
+ ;
+
+# Target for quickbook toolset's auto build.
+
+alias quickbook
+ : src//quickbook
+ : release
+ ;
+
+explicit quickbook
+ ;
diff --git a/tools/quickbook/doc/1_6.qbk b/tools/quickbook/doc/1_6.qbk
new file mode 100644
index 0000000000..c3ca99c0a0
--- /dev/null
+++ b/tools/quickbook/doc/1_6.qbk
@@ -0,0 +1,281 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[chapter Language Versions
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ [id quickbook.versions]
+ [source-mode teletype]
+]
+
+[section:stable Stable Versions]
+
+Since quickbook 1.3 the `quickbook` attribute in the document block selects
+which version of the language to use. Not all changes to quickbook are
+implemented using a version switch, it's mainly just the changes that change
+the way a document is interpreted or would break existing documentation.
+
+[heading Quickbook 1.3 and later]
+
+* Introduced quickbook language versioning.
+* In the documentation info, allow phrase markup in license and purpose
+ attributes.
+* Fully qualified section and headers. Subsection names are concatenated to the
+ ID to avoid clashing. Example: `doc_name.sect_name.sub_sect_name.sub_sub_sect_name`.
+
+[heading Quickbook 1.5 and later]
+
+* Ignore template argument separators inside square brackets.
+* Don't separate the final template argument if the `..` separator was
+ used. i.e. never mix `..` and whitespace separators.
+* Statically scope templates and their arguments rather than dynamically
+ scope them.
+* Give table ids, and let you set them.
+* Allow spaces between the `:` character and ids in elements which can
+ have ids.
+
+[endsect]
+
+[section:1_6 Quickbook 1.6]
+
+Everything described in here may change depending on the feedback received.
+
+[section:docinfo Includes with docinfo]
+
+In quickbook 1.5 if you include a file which starts with a docinfo block, it's
+ignored and the file is expanded in place. In quickbook 1.6 it's treated as a
+document nested in the current position. So if it has an 'article' docinfo block,
+boostbook 'article' tags are used.
+
+It also mostly generates the same markup as if the file was converted separately -
+so for example, the same ids are generated, the document is processed using the
+language version specified in the docinfo block. If no language is specified it
+uses the default (1.1) not the version of the document that included it. This
+might seem surprising, but is requried so that quickbook will convert it the same
+way as if it was converted separately.
+
+So for the most part, includes with a docinfo are like an `xinclude`, apart from
+a couple of differences. Templates and macros defined in the parent document are
+used in the included document, and the id generator rewrites ids that clash
+between multiple documents.
+
+If an included document doesn't have a docinfo block, it's just included as
+before.
+
+[endsect] [/docinfo]
+
+[section:scope Scoping templates and macros]
+
+A long standing quickbook bug is that macros are scoped by file, but templates
+aren't. So you can define templates in a separate file and include them, but not
+macros. This has been fixed so that templates defined in one file won't 'leak'
+into another.
+
+But this means there's no way to define templates in a separate file - a useful
+feature. To do this the `import` element has been adapted to also support
+quickbook files. If a quickbook file is imported, the templates and macros
+defined in it are added to the current scope, but nothing else contained in that
+file is used. This could be used to create template and macro library files.
+This matches the existing semantics of importing code snippets.
+
+When importing templates, they're bound to the language version of the file
+they were defined in. This means that if you import them into a file with
+a different version it won't change the way they're interpreted. Although,
+as we'll see [link compatibility later], the generated boostbook is slightly
+different.
+
+[endsect] [/scope]
+
+[section:include Including C++ and python files]
+
+As `import` now supports quickbook files, `include` also supports source files.
+It includes any quickbook contained in comments outside of code snippets.
+Code snippets in the file are available to be expanded within the file but
+are scoped to the file. In exactly the same manner as when templates and macros
+are scoped in an included quickbook file.
+
+[endsect] [/include]
+
+[section:ids Id Generation]
+
+Id generation in quickbook 1.5 is a bit buggy, but that can't be fixed without a
+version switch as it will break existing documents. For example in quickbook 1.5
+when you include a quickbook file, it stops using the explicit id from the
+documentation info and generates a new id from the document title to use instead.
+
+The id generator in quickbook 1.6 has been improved in some other ways to. When
+generating ids from section titles, table titles etc. it always uses the
+quickbook source rather than the generated boostbook to generate the id. It then
+cleans up the id slightly, trimming leading and trailing underscores and replacing
+multiple underscores with a single underscore. Then if the newly generated part
+of the id is longer than 32 characters it truncates it.
+
+While the new id generator generally creates better ids, it's more likely to
+generate duplicates so quickbook needs to handle duplicates better. When there
+are multiple identical ids, quickbook chooses one to use based on a priority
+list - anchors are preferred, then explicit document and section ids, then other
+explicit ids, followed by the generated ids. Then any other explicit ids in the
+document have numbers added to avoid duplicates - first the explicit ids in the
+order they appear and then the generated ids. A generated id which accidentally
+clashes with an explicit id should never change the explicit id.
+
+Older language versions still generate the same ids they always have, with the
+exception of duplicate ids which are handled using the new mechanism - this
+is not a breaking change since duplicate ids can't be linked to.
+
+[endsect] [/ids]
+
+[#compatibility]
+[section:compatibility Compatibility Mode]
+
+As mentioned before, changing the id generator will break links in documents
+written using an old language version. So to ease the transition a
+'compatibility mode' is used, this just requires an extra attribute in the
+docinfo, for example if you're converting a 1.5 document to 1.6:
+
+ [article Document
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ ]
+
+This means the document will be parsed as 1.6, using all the new features, but
+ids (and possibly other markup) will generated as they were for a 1.5 document.
+
+Compatibility mode is also implicitly used when generating templates written
+in a different language version to the current document. So the template is
+parsed in the version it was written for, but generates boostbook that's
+compatible with the current document.
+
+[endsect] [/compatibility]
+
+[section:version Version info outside of document info block]
+
+Can now use `quickbook` and `compatibility-mode` tags at the beginning of the
+file. Either before or without a document info block. This is useful for
+files just containing templates, which don't really need a document info
+block.
+
+If you don't specify `compatibility-mode`, the behaviour depends on whether or
+not you have a docinfo block. If you do it uses the file's quickbook version,
+if you don't it inherits the parent's compatibility mode even if you specify
+a quickbook version. This is the right thing to do - mixing compatibility modes
+within documents is problematic. It might actually be a mistake to allow them
+to specified outside docinfo blocks.
+
+This change is also backdated to older versions. So when including from an
+older version, the included file's version can be set (older versions
+ignore document info in included files).
+
+[endsect]
+
+[section:heading_ids Explicit Heading Ids]
+
+Headings can now be given explicit ids:
+
+ [heading:id A heading with an explicit id]
+
+[endsect] [/heading_ids]
+
+[section:escapes Punctuation changes]
+
+In 1.6, quickbook is more consistent about how it parses punctuation.
+Escapes are now supported in links, anchors, table titles, image
+attributes etc. The flip side of this is that quickbook is now stricter
+about unescaped brackets. They can still be used, but need to match up,
+otherwise there's an error.
+
+Since quickbook now matches up square brackets it will fix some
+mis-parses. For example `[*[bold]]` used to parse as [*\[bold]\] - note
+that the closing square bracket isn't bold, now it parses as
+[*\[bold\]]. In this case it's just a subtle visual difference, but it
+could cause odd problems, for example when nested in a table cell.
+
+[endsect] [/escapes]
+
+[section:table Table Titles]
+
+Table titles are now parsed as phrases, so some markup is allowd:
+
+ [table [*bold title]]
+
+Which is an empty table with a bold title. The title is no longer ended
+by a newline, but by either a closing square bracket, or two opening
+square brackets - which you get at the start of the table cells, so
+this now works:
+
+ [table Simple[[heading 1][heading 2]][[cell 1][cell 2]]]
+
+[endsect] [/table]
+
+[section:xmlbase XML base]
+
+A problem when using `xi:include` tags in escaped boostbook is that you
+typically don't know which directory the boostbook file will be in, so
+it's impossible to use relative links. This can be fixed by adding an
+`xml:base` attribute to the document tag. To do this use the new
+`xmlbase` attribute in your document's docinfo block. For example to
+make escaped `xi:include`s be relative to the directory of the file:
+
+ [library Library documentation
+ [quickbook 1.6]
+ [xmlbase .]
+ ]
+
+Any paths in `xinclude` elements will be rewritten accordingly. Note that
+most documents won't need this, and probably shouldn't use it. Only use it
+if you're totally sure that you will need it.
+
+[endsect] [/xmlbase]
+
+[section:elements New Elements]
+
+New elements in 1.6 (to be documented later):
+
+* `block`
+* `ordered_list`
+* `itemized_list`
+* `role`
+
+[endsect]
+
+[section:listparagraphs Pargraphs in lists]
+
+I'm still refining this, but paragraphs and block elements can now be used
+in lists:
+
+[pre
+* Para 1
+
+ Para 2
+ * Nested Para 1
+
+ Nested Para 2
+
+ Code block
+ Para 3
+]
+
+generates:
+
+* Para 1
+
+ Para 2
+ * Nested Para 1
+
+ Nested Para 2
+
+ Code block
+ Para 3
+
+The docbook markup that this generates is pretty bad, but seems to create okay
+html.
+
+[endsect]
+
+[endsect] [/ Quickbok 1.6] \ No newline at end of file
diff --git a/tools/quickbook/doc/Jamfile.v2 b/tools/quickbook/doc/Jamfile.v2
new file mode 100644
index 0000000000..f2f11f09eb
--- /dev/null
+++ b/tools/quickbook/doc/Jamfile.v2
@@ -0,0 +1,28 @@
+#==============================================================================
+# Copyright (c) 2002 2004 2006 Joel de Guzman
+# Copyright (c) 2004 Eric Niebler
+# http://spirit.sourceforge.net/
+#
+# Use, modification and distribution is subject to the Boost Software
+# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+
+project boost/quickbook/doc ;
+
+using boostbook ;
+using quickbook ;
+
+xml quickbook : quickbook.qbk ;
+
+path-constant images : ../../../doc/src ;
+
+boostbook standalone
+ :
+ quickbook
+ :
+ <xsl:param>boost.root=../../../..
+ #<xsl:param>callout.graphics.path=../../images/callouts//
+ <format>pdf:<xsl:param>img.src.path=$(images)/
+ <format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
+ ;
diff --git a/tools/quickbook/doc/block.qbk b/tools/quickbook/doc/block.qbk
new file mode 100644
index 0000000000..f9da265b77
--- /dev/null
+++ b/tools/quickbook/doc/block.qbk
@@ -0,0 +1,1113 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[chapter Block Level Elements
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ [id quickbook.syntax.block]
+ [source-mode teletype]
+]
+
+[section xinclude]
+
+You can include another XML file with:
+
+```
+[xinclude file.xml]
+```
+
+This is useful when file.xml has been generated by Doxygen and contains your
+reference section.
+
+[endsect] [/xinclude]
+
+[section Paragraphs]
+
+Paragraphs start left-flushed and are terminated by two or more newlines. No
+markup is needed for paragraphs. QuickBook automatically detects paragraphs from
+the context. Block markups \[section, endsect, h1, h2, h3, h4, h5, h6, blurb,
+(block-quote) ':', pre, def, table and include \] may also terminate a paragraph.
+ [/ <-- There's a space here. Don't remove. this is intentianal, for testing]
+This is a new paragraph...
+
+[endsect] [/Paragraphs]
+
+[section Lists]
+[section Ordered lists]
+
+[pre
+# One
+# Two
+# Three
+]
+
+will generate:
+
+# One
+# Two
+# Three
+
+[endsect] [/Ordered lists]
+[section List Hierarchies]
+
+List hierarchies are supported. Example:
+
+[pre
+# One
+# Two
+# Three
+ # Three.a
+ # Three.b
+ # Three.c
+# Four
+ # Four.a
+ # Four.a.i
+ # Four.a.ii
+# Five
+]
+
+will generate:
+
+# One
+# Two
+# Three
+ # Three.a
+ # Three.b
+ # Three.c
+# Fourth
+ # Four.a
+ # Four.a.i
+ # Four.a.ii
+# Five
+
+[endsect] [/List Hierarchies]
+[section Long List Lines]
+
+Long lines will be wrapped appropriately. Example:
+
+[pre
+# A short item.
+# A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+# A short item.
+]
+
+# A short item.
+# A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+# A short item.
+
+[endsect] [/Long list lines]
+[section Unordered lists]
+
+```
+* First
+* Second
+* Third
+```
+
+will generate:
+
+* First
+* Second
+* Third
+
+[endsect] [/Unordered lists]
+[section Mixed lists]
+
+Mixed lists (ordered and unordered) are supported. Example:
+
+```
+# One
+# Two
+# Three
+ * Three.a
+ * Three.b
+ * Three.c
+# Four
+```
+
+will generate:
+
+# One
+# Two
+# Three
+ * Three.a
+ * Three.b
+ * Three.c
+# Four
+
+And...
+
+```
+# 1
+ * 1.a
+ # 1.a.1
+ # 1.a.2
+ * 1.b
+# 2
+ * 2.a
+ * 2.b
+ # 2.b.1
+ # 2.b.2
+ * 2.b.2.a
+ * 2.b.2.b
+```
+
+will generate:
+
+# 1
+ * 1.a
+ # 1.a.1
+ # 1.a.2
+ * 1.b
+# 2
+ * 2.a
+ * 2.b
+ # 2.b.1
+ # 2.b.2
+ * 2.b.2.a
+ * 2.b.2.b
+
+[endsect] [/Mixed lists]
+[endsect] [/Lists]
+
+[section Code]
+
+Preformatted code starts with a space or a tab. The code will be
+syntax highlighted according to the current __source_mode__:
+
+[c++]
+
+ #include <iostream>
+
+ int main()
+ {
+ // Sample code
+ std::cout << "Hello, World\n";
+ return 0;
+ }
+
+[python]
+
+ import cgi
+
+ def cookForHtml(text):
+ '''"Cooks" the input text for HTML.'''
+
+ return cgi.escape(text)
+
+[teletype]
+
+Macros that are already defined are expanded in source code. Example:
+
+```
+[def __array__ [@http://www.boost.org/doc/html/array/reference.html array]]
+[def __boost__ [@http://www.boost.org/libs/libraries.htm boost]]
+
+ using __boost__::__array__;
+```
+
+Generates:
+
+[def __array__ [@http://www.boost.org/doc/html/array/reference.html array]]
+[def __boost__ [@http://www.boost.org/libs/libraries.htm boost]]
+
+ using __boost__::__array__;
+
+[endsect] [/Code]
+
+[section:escape_back Escaping Back To QuickBook]
+
+Inside code, code blocks and inline code, QuickBook does not allow any
+markup to avoid conflicts with the target syntax (e.g. c++). In case you
+need to switch back to QuickBook markup inside code, you can do so using a
+language specific /escape-back/ delimiter. In C++ and Python, the delimiter
+is the double tick (back-quote): "\`\`" and "\`\`". Example:
+
+```
+void ``[@http://en.wikipedia.org/wiki/Foo#Foo.2C_Bar_and_Baz foo]``()
+{
+}
+```
+
+Will generate:
+
+ void ``[@http://en.wikipedia.org/wiki/Foo#Foo.2C_Bar_and_Baz foo]``()
+ {
+ }
+
+When escaping from code to QuickBook, only phrase level markups are
+allowed. Block level markups like lists, tables etc. are not allowed.
+
+[endsect] [/Escaping back to quickbook]
+
+[section Preformatted]
+
+Sometimes, you don't want some preformatted text to be parsed as source code. In such
+cases, use the [^\[pre ... \]] markup block.
+
+```
+[pre
+
+ Some *preformatted* text Some *preformatted* text
+
+ Some *preformatted* text Some *preformatted* text
+
+ Some *preformatted* text Some *preformatted* text
+
+]
+```
+
+Spaces, tabs and newlines are rendered as-is. Unlike all quickbook block level
+markup, pre (and Code) are the only ones that allow multiple newlines. The
+markup above will generate:
+
+[pre
+
+Some *preformatted* text Some *preformatted* text
+
+ Some *preformatted* text Some *preformatted* text
+
+ Some *preformatted* text Some *preformatted* text
+
+]
+
+Notice that unlike Code, phrase markup such as font style is still permitted
+inside =pre= blocks.
+
+[endsect] [/Preformatted]
+
+[section Blockquote]
+
+[pre
+'''[:sometext...]'''
+]
+
+[:Indents the paragraph. This applies to one paragraph only.]
+
+[endsect] [/Blockquote]
+
+[section Admonitions]
+
+```
+[note This is a note]
+[tip This is a tip]
+[important This is important]
+[caution This is a caution]
+[warning This is a warning]
+```
+
+generates __docbook__ admonitions:
+
+[note This is a note]
+[tip This is a tip]
+[important This is important]
+[caution This is a caution]
+[warning This is a warning]
+
+These are the only admonitions supported by __docbook__. So,
+for example [^\[information This is some information\]] is unlikely
+to produce the desired effect.
+
+[endsect] [/Admonitions]
+
+[section Headings]
+
+```
+[h1 Heading 1]
+[h2 Heading 2]
+[h3 Heading 3]
+[h4 Heading 4]
+[h5 Heading 5]
+[h6 Heading 6]
+```
+
+[h1 Heading 1]
+[h2 Heading 2]
+[h3 Heading 3]
+[h4 Heading 4]
+[h5 Heading 5]
+[h6 Heading 6]
+
+Headings 1-3 \[h1 h2 and h3\] will automatically have anchors with
+normalized names with
+[^name="document_id.section_id.normalized_header_text"] (i.e. valid
+characters are =a-z=, =A-Z=, =0-9= and =_=. All non-valid characters are
+converted to underscore and all upper-case are converted to lower-case.
+For example: Heading 1 in section Section 2 will be normalized to
+[^section_2.heading_1]). You can use:
+
+```
+[link document_id.section_id.normalized_header_text The link text]
+```
+
+to link to them. See __anchor_links__ and __section__ for more info.
+
+[endsect] [/Headings]
+
+[section Generic Heading]
+
+In cases when you don't want to care about the heading level (1 to 6), you
+can use the /Generic Heading/:
+
+```
+[heading Heading]
+```
+
+The /Generic Heading/ assumes the level, plus one, of the innermost section
+where it is placed. For example, if it is placed in the outermost section,
+then, it assumes /h2/.
+
+Headings are often used as an alternative to sections. It is used
+particularly if you do not want to start a new section. In many cases,
+however, headings in a particular section is just flat. Example:
+
+```
+[section A]
+[h2 X]
+[h2 Y]
+[h2 Z]
+[endsect]
+```
+
+Here we use h2 assuming that section A is the outermost level. If it is
+placed in an inner level, you'll have to use h3, h4, etc. depending on
+where the section is. In general, it is the section level plus one. It is
+rather tedious, however, to scan the section level everytime. If you
+rewrite the example above as shown below, this will be automatic:
+
+```
+[section A]
+[heading X]
+[heading Y]
+[heading Z]
+[endsect]
+```
+
+They work well regardless where you place them. You can rearrange sections
+at will without any extra work to ensure correct heading levels. In fact,
+with /section/ and /heading/, you have all you need. /h1/../h6/ becomes
+redundant. /h1/../h6/ might be deprecated in the future.
+
+[endsect] [/Generic Heading]
+
+[section Macros]
+
+```
+[def macro_identifier some text]
+```
+
+When a macro is defined, the identifier replaces the text anywhere in the
+file, in paragraphs, in markups, etc. macro_identifier is a string of non-
+white space characters except '\]'. A macro may not follow an alphabetic
+character or the underscore. The replacement text can be any phrase (even
+marked up). Example:
+
+```
+[def sf_logo [$http://sourceforge.net/sflogo.php?group_id=28447&amp;type=1]]
+sf_logo
+```
+
+Now everywhere the sf_logo is placed, the picture will be inlined.
+
+[def sf_logo [$http://sourceforge.net/sflogo.php?group_id=28447&type=1]]
+sf_logo
+
+[tip It's a good idea to use macro identifiers that are distinguishable.
+For instance, in this document, macro identifiers have two leading and
+trailing underscores (e.g. [^\__spirit__]). The reason is to avoid
+unwanted macro replacement.]
+
+Links (URLS) and images are good candidates for macros. *1*) They tend to
+change a lot. It is a good idea to place all links and images in one place near the top
+to make it easy to make changes. *2*) The syntax is not pretty. It's easier to read and
+write, e.g. [^\__spirit__] than `[@http://spirit.sourceforge.net Spirit]`.
+
+Some more examples:
+
+```
+[def ``\:-)`` [$theme/smiley.png]]
+[def ``\__spirit__`` [@http://spirit.sourceforge.net Spirit]]
+```
+
+(See __images__ and __links__)
+
+Invoking these macros:
+
+```
+Hi ``\__spirit__`` ``\:-)``
+```
+
+will generate this:
+
+Hi __spirit__ :-)
+
+[endsect] [/Macros]
+
+[section Predefined Macros]
+
+Quickbook has some predefined macros that you can already use.
+
+[table Predefined Macros
+ [[Macro] [Meaning] [Example]]
+ [[[^\__DATE__]] [Today's date] [__DATE__]]
+ [[[^\__TIME__]] [The current time] [__TIME__]]
+ [[[^\__FILENAME__]][Quickbook source filename] [__FILENAME__]]
+]
+
+[endsect] [/Predefined Macros]
+
+[section Templates]
+
+Templates provide a more versatile text substitution mechanism. Templates
+come in handy when you need to create parameterizable, multi-line,
+boilerplate text that you specify once and expand many times. Templates
+accept one or more arguments. These arguments act like place-holders for
+text replacement. Unlike simple macros, which are limited to phrase level
+markup, templates can contain block level markup (e.g. paragraphs, code
+blocks and tables).
+
+Example template:
+
+```
+[template person[name age what]
+
+Hi, my name is [name]. I am [age] years old. I am a [what].
+
+]
+```
+
+[template person[name age what]
+
+Hi, my name is [name]. I am [age] years old. I am a [what].
+
+]
+
+[heading Template Identifier]
+
+Template identifiers can either consist of:
+
+* An initial alphabetic character or the underscore, followed by
+ zero or more alphanumeric characters or the underscore. This is
+ similar to your typical C/C++ identifier.
+* A single character punctuation (a non-alphanumeric printable character)
+
+[heading Formal Template Arguments]
+
+Template formal arguments are identifiers consisting of an initial
+alphabetic character or the underscore, followed by zero or more
+alphanumeric characters or the underscore. This is similar to your typical
+C/C++ identifier.
+
+A template formal argument temporarily hides a template of the same name at
+the point where the [link quickbook.syntax.block.templates.template_expansion
+template is expanded]. Note that the body of the [^person] template above
+refers to [^name] [^age] and [^what] as [^\[name\]] [^\[age\]] and
+[^\[what\]]. [^name] [^age] and [^what] are actually templates that exist
+in the duration of the template call.
+
+[heading Template Body]
+
+The template body can be just about any QuickBook block or phrase. There
+are actually two forms. Templates may be phrase or block level. Phrase
+templates are of the form:
+
+```
+[template sample[arg1 arg2...argN] replacement text... ]
+```
+
+Block templates are of the form:
+
+```
+[template sample[arg1 arg2...argN]
+replacement text...
+]
+```
+
+The basic rule is as follows: if a newline immediately follows the argument
+list, then it is a block template, otherwise, it is a phrase template.
+Phrase templates are typically expanded as part of phrases. Like macros,
+block level elements are not allowed in phrase templates.
+
+[heading Template Expansion]
+
+You expand a template this way:
+
+```
+[template_identifier arg1..arg2..arg3]
+```
+
+At template expansion, you supply the actual arguments. The template will
+be expanded with your supplied arguments. Example:
+
+```
+[person James Bond..39..Spy]
+[person Santa Clause..87..Big Red Fatso]
+```
+
+Which will expand to:
+
+[person James Bond..39..Spy]
+[person Santa Clause..87..Big Red Fatso]
+
+[caution A word of caution: Templates are recursive. A template can call
+another template or even itself, directly or indirectly. There are no
+control structures in QuickBook (yet) so this will always mean infinite
+recursion. QuickBook can detect this situation and report an error if
+recursion exceeds a certain limit.]
+
+Each actual argument can be a word, a text fragment or just about any [link
+quickbook.syntax.phrase QuickBook phrase]. Arguments are separated by the
+double dot [^".."] and terminated by the close parenthesis.
+
+Note that templates and template parameters can't be expanded
+everywhere, only where text is interpreted as a phrase. So they can't be
+expanded in places such as table titles and link's urls. If you want to
+use a template to generate a link based of the template parameter, you
+can't use a normal link and will need to use escaped docbook instead.
+Example:
+
+[teletype]
+```
+[template boost_ticket[key] '''<ulink url="https://svn.boost.org/trac/boost/ticket/'''[key]'''">#'''[key]'''</ulink>''']
+
+[boost_ticket 2035]
+```
+
+will expand to:
+
+[template boost_ticket[key] '''<ulink url="https://svn.boost.org/trac/boost/ticket/'''[key]'''">#'''[key]'''</ulink>''']
+
+[boost_ticket 2035]
+
+[caution Since quickbook doesn't understand the context where the
+parameter is being used, it will interpret it as quickbook markup, so
+when writing a template like this, you'll need to escape any meaningful
+punctuation.]
+
+[heading Nullary Templates]
+
+Nullary templates look and act like simple macros. Example:
+
+```
+[template alpha[]&apos;&apos;&apos;&amp;#945;&apos;&apos;&apos;]
+[template beta[]&apos;&apos;&apos;&amp;#946;&apos;&apos;&apos;]
+```
+
+[template alpha[]'''&#945;''']
+[template beta[]'''&#946;''']
+
+Expanding:
+
+```Some squigles...[*[alpha][beta]]```
+
+We have:
+
+Some squiggles...[*[alpha][beta]]
+
+The difference with macros are
+
+* The explicit [link quickbook.syntax.block.templates.template_expansion
+ template expansion syntax]. This is an advantage because, now, we don't
+ have to use obscure naming conventions like double underscores (e.g.
+ \_\_alpha\_\_) to avoid unwanted
+ macro replacement.
+* The template is expanded at the point where it is invoked. A macro is
+ expanded immediately at its point of declaration. This is subtle and
+ can cause a slight difference in behavior especially if you refer to
+ other macros and templates in the body.
+
+The empty brackets after the template identifier ([^alpha\[\]]) indicates no
+arguments. If the template body does not look like a template argument list, we
+can elide the empty brackets. Example:
+
+```
+[template aristotle_quote Aristotle: [*['Education is the best provision
+for the journey to old age.]]]
+```
+
+[template aristotle_quote\ Aristotle: [*['Education is the best provision
+for the journey to old age.]]]
+
+Expanding:
+
+```
+Here's a quote from [aristotle_quote].
+```
+
+We have:
+
+Here's a quote from [aristotle_quote].
+
+The disadvantage is that you can't avoid the space between the template
+identifier, `aristotle_quote`, and the template body "Aristotle...". This space
+will be part of the template body. If that space is unwanted, use empty
+brackets or use the space escape: "`\ `". Example:
+
+```
+[template tag\ _tag]
+```
+
+[template tag\ _tag]
+
+Then expanding:
+
+```
+`struct` x[tag];
+```
+
+We have:
+
+`struct` x[tag];
+
+You have a couple of ways to do it. I personally prefer the explicit empty
+brackets, though.
+
+[heading Simple Arguments]
+
+As mentioned, arguments are separated by the double dot [^".."]. Alternatively,
+if the double dot isn't used and more than one argument is expected, QuickBook
+uses whitespace to separate the arguments, following this logic:
+
+* Break the last argument into two, at the first space found ([^'', '\\n',
+ \\t' or '\\r']).
+* Repeat until there are enough arguments or if there are no more spaces
+ found (in which case, an error is reported).
+
+For example:
+
+```
+[template simple[a b c d] [a][b][c][d]]
+[simple w x y z]
+```
+
+will produce:
+
+[template simple[a b c d] [a][b][c][d]]
+[simple w x y z]
+
+"w x y z" is initially treated as a single argument because we didn't
+supply any [^".."] separators. However, since [^simple] expects 4
+arguments, "w x y z" is broken down iteratively (applying the logic above)
+until we have "w", "x", "y" and "z".
+
+QuickBook only tries to get the arguments it needs. For example:
+
+```
+[simple w x y z trail]
+```
+
+will produce:
+
+[simple w x y z trail]
+
+The arguments being: "w", "x", "y" and "z trail".
+
+[caution The behavior described here is for QuickBook 1.5. In older versions you
+could use both the double dot and whitespace as separators in the same template
+call. If your document is marked up as an older version, it will use the old
+behavior, which is described in the
+[@http://www.boost.org/doc/libs/1_40_0/doc/html/quickbook/syntax.html#quickbook.syntax.block.templates.simple_arguments
+QuickBook 1.4 documentation].]
+
+[heading Punctuation Templates]
+
+With templates, one of our objectives is to allow us to rewrite QuickBook
+in QuickBook (as a qbk library). For that to happen, we need to accommodate
+single character punctuation templates which are fairly common in
+QuickBook. You might have noticed that single character punctuations are
+allowed as [link quickbook.syntax.block.templates.template_identifier
+template identifiers]. Example:
+
+```
+[template ![bar] <hey>[bar]</hey>]
+```
+
+Now, expanding this:
+
+```
+[!baz]
+```
+
+We will have:
+
+[pre
+<hey>baz</hey>
+]
+
+[endsect] [/Templates]
+
+[section Blurbs]
+
+```
+[blurb ``\:-)`` [*An eye catching advertisement or note...]
+
+ __spirit__ is an object-oriented recursive-descent parser generator framework
+ implemented using template meta-programming techniques. Expression templates
+ allow us to approximate the syntax of Extended Backus-Normal Form (EBNF)
+ completely in C++.
+]
+```
+
+will generate this:
+
+[blurb :-) [*An eye catching advertisement or note...]
+
+ __spirit__ is an object-oriented recursive-descent parser generator
+ framework implemented using template meta-programming techniques. Expression
+ templates allow us to approximate the syntax of Extended Backus-Normal Form
+ (EBNF) completely in C++.
+]
+
+[note Prefer [link quickbook.syntax.block.admonitions admonitions] wherever
+appropriate.]
+
+[endsect] [/Blurbs]
+
+[section Tables]
+
+```
+[table:id A Simple Table
+ [[Heading 1] [Heading 2] [Heading 3]]
+ [[R0-C0] [R0-C1] [R0-C2]]
+ [[R1-C0] [R1-C1] [R1-C2]]
+ [[R2-C0] [R2-C1] [R2-C2]]
+]
+```
+
+will generate:
+
+[table:id A Simple Table
+ [[Heading 1] [Heading 2] [Heading 3]]
+ [[R0-C0] [R0-C1] [R0-C2]]
+ [[R1-C0] [R1-C1] [R1-C2]]
+ [[R2-C0] [R2-C1] [R2-C2]]
+]
+
+The table title is optional. The first row of the table is automatically
+treated as the table header; that is, it is wrapped in [^<thead>...</thead>]
+XML tags. Note that unlike the original QuickDoc, the columns are nested in
+[cells... ].
+
+Giving tables an id is a new feature for quickbook 1.5 onwards. As with
+sections, the id is optional. If the table has a title but no id, an id will
+be generated from the title. The table above can be linked to using:
+
+```
+[link quickbook.syntax.block.tables.id link to table]
+```
+
+which will generate:
+
+[link quickbook.syntax.block.tables.id link to table]
+
+The syntax is free-format and allows big cells to be formatted
+nicely. Example:
+
+```
+[table Table with fat cells
+ [[Heading 1] [Heading 2]]
+ [
+ [Row 0, Col 0: a small cell]
+ [
+ Row 0, Col 1: a big fat cell with paragraphs
+
+ Boost provides free peer-reviewed portable C++ source libraries.
+
+ We emphasize libraries that work well with the C++ Standard Library.
+ Boost libraries are intended to be widely useful, and usable across
+ a broad spectrum of applications. The Boost license encourages both
+ commercial and non-commercial use.
+ ]
+ ]
+ [
+ [Row 1, Col 0: a small cell]
+ [Row 1, Col 1: a small cell]
+ ]
+]
+```
+
+and thus:
+
+[table Table with fat cells
+ [[Heading 1] [Heading 2]]
+ [
+ [Row 0, Col 0: a small cell]
+ [
+ Row 0, Col 1: a big fat cell with paragraphs
+
+ Boost provides free peer-reviewed portable C++ source libraries.
+ [/ <-- There's a space here. Don't remove. This is intentional, for testing]
+ We emphasize libraries that work well with the C++ Standard Library.
+ Boost libraries are intended to be widely useful, and usable across
+ a broad spectrum of applications. The Boost license encourages both
+ commercial and non-commercial use.
+ ]
+ ]
+ [
+ [Row 1, Col 0: a small cell]
+ [Row 1, Col 1: a small cell]
+ ]
+]
+
+Here's how to have preformatted blocks of code in a table cell:
+
+```
+[table Table with code
+ [[Comment] [Code]]
+ [
+ [My first program]
+ [``\`\`\ ``
+ #include <iostream>
+
+ int main()
+ {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+ ``\`\`\ ``]
+ ]
+]
+```
+
+[table Table with code
+ [[Comment] [Code]]
+ [
+ [My first program]
+ [``
+ #include <iostream>
+
+ int main()
+ {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+ ``]
+ ]
+]
+
+[endsect] [/Tables]
+
+[section Variable Lists]
+
+```
+[variablelist A Variable List
+ [[term 1] [The definition of term 1]]
+ [[term 2] [The definition of term 2]]
+ [[term 3] [
+ The definition of term 3.
+
+ Definitions may contain paragraphs.
+ ]]
+]
+```
+
+will generate:
+
+[variablelist A Variable List
+ [[term 1] [The definition of term 1]]
+ [[term 2] [The definition of term 2]]
+ [[term 3] [
+ The definition of term 3.
+
+ Definitions may contain paragraphs.
+ ]]
+]
+
+The rules for variable lists are the same as for tables, except that
+only 2 "columns" are allowed. The first column contains the terms, and
+the second column contains the definitions. Those familiar with HTML
+will recognize this as a "definition list".
+
+[endsect] [/Variable Lists]
+
+[section Include]
+
+You can include one QuickBook file from another. The syntax is simply:
+
+```
+[include someother.qbk]
+```
+
+The included file will be processed as if it had been cut and pasted
+into the current document, with the following exceptions:
+
+* The '''__FILENAME__''' predefined macro will reflect the name of the
+ file currently being processed.
+* Any macros defined in the included file are scoped to that file.
+
+The [^\[include\]] directive lets you specify a document id to use for the
+included file. When this id is not explicitly specified, the id defaults to
+the filename ("someother", in the example above). You can specify the id
+like this:
+
+```
+[include:someid someother.qbk]
+```
+
+All auto-generated anchors will use the document id as a unique prefix. So
+for instance, if there is a top section in someother.qbk named "Intro", the
+named anchor for that section will be "someid.intro", and you can link to
+it with [^\[link someid.intro The Intro\]].
+
+[endsect] [/Include]
+
+[section Import]
+
+When documenting code, you'd surely need to present code from actual source
+files. While it is possible to copy some code and paste them in your QuickBook
+file, doing so is error prone and the extracted code in the documentation tends
+to get out of sync with the actual code as the code evolves. The problem, as
+always, is that once documentation is written, the tendency is for the docs to
+languish in the archives without maintenance.
+
+QuickBook's import facility provides a nice solution.
+
+[heading Example]
+
+You can effortlessly import code snippets from source code into your QuickBook.
+The following illustrates how this is done:
+
+```
+[import ../test/stub.cpp]
+[foo]
+[bar]
+```
+
+The first line:
+
+```
+[import ../test/stub.cpp]
+```
+
+collects specially marked-up code snippets from
+[@boost:/tools/quickbook/test/stub.cpp stub.cpp]
+and places them in your QuickBook file as virtual templates. Each of the
+specially marked-up code snippets has a name (e.g. `foo` and `bar` in the
+example above). This shall be the template identifier for that particular code
+snippet. The second and third line above does the actual template expansion:
+
+```
+[foo]
+[bar]
+```
+
+And the result is:
+
+[import ../test/stub.cpp]
+[foo]
+[bar]
+
+[heading Code Snippet Markup]
+
+Note how the code snippets in [@boost:/tools/quickbook/test/stub.cpp stub.cpp]
+get marked up. We use distinguishable comments following the form:
+
+ //[id
+ some code here
+ //]
+
+The first comment line above initiates a named code-snippet. This prefix will
+not be visible in quickbook. The entire code-snippet in between `//[id` and
+`//]` will be inserted as a template in quickbook with name ['/id/]. The comment
+`//]` ends a code-snippet This too will not be visible in quickbook.
+
+[heading Special Comments]
+
+Special comments of the form:
+
+ //` some [*quickbook] markup here
+
+and:
+
+ /*` some [*quickbook] markup here */
+
+will be parsed by QuickBook. This can contain quickbook /blocks/ (e.g. sections,
+paragraphs, tables, etc). In the first case, the initial slash-slash, tick and
+white-space shall be ignored. In the second, the initial slash-star-tick and the
+final star-slash shall be ignored.
+
+Special comments of the form:
+
+ /*<- this C++ comment will be ignored ->*/
+
+or
+
+ /*<-*/ "this c++ code will be ignored" /*->*/
+
+or
+
+ //<-
+ private:
+ int some_member;
+ //->
+
+can be used to inhibit code from passing through to quickbook. All text between
+the delimeters will simply be ignored.
+
+Comments of this form:
+
+ //=int main() {}
+
+or
+
+ /*=foo()*/
+
+will be displayed as code that isn't in comments. This allows you to
+include some code in the snippet but not actually use it when
+compiling your example.
+
+[heading Callouts]
+
+Special comments of the form:
+
+ /*< some [*quickbook] markup here >*/
+
+will be regarded as callouts. These will be collected, numbered and
+rendered as a "callout bug" (a small icon with a number). After the
+whole snippet is parsed, the callout list is generated. See
+[@http://www.docbook.org/tdg/en/html/callout.html Callouts] for details.
+Example:
+
+[foo_bar]
+
+This is the actual code:
+
+ //[ foo_bar
+ std::string foo_bar() /*< The /Mythical/ FooBar.
+ See [@http://en.wikipedia.org/wiki/Foobar Foobar for details] >*/
+ {
+ return "foo-bar"; /*< return 'em, foo-bar man! >*/
+ }
+ //]
+
+The callouts bugs are placed exactly where the special callout comment
+is situated. It can be anywhere in the code. The bugs can be rather
+obtrusive, however. They get in the way of the clarity of the code.
+Another special callout comment style is available:
+
+ /*<< some [*quickbook] markup here >>*/
+
+This is the line-oriented version of the callout. With this, the "bug"
+is placed at the very left of the code block, away from the actual code.
+By placing it at the far left, the code is rendered un-obscured.
+Example:
+
+[class_]
+
+See the actual code here: [@boost:/tools/quickbook/test/stub.cpp]
+
+[endsect] [/Import]
diff --git a/tools/quickbook/doc/change_log.qbk b/tools/quickbook/doc/change_log.qbk
new file mode 100644
index 0000000000..96fa45dec3
--- /dev/null
+++ b/tools/quickbook/doc/change_log.qbk
@@ -0,0 +1,250 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[chapter Change Log
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ [id quickbook.change_log]
+ [source-mode teletype]
+]
+
+[heading:version_1_1 Version 1.1 - Boost 1.33.0]
+
+* First version to be included in boost.
+
+[heading:version_1_3 Version 1.3 - Boost 1.34.0 to 1.34.1]
+
+* Quickbook file inclusion \[include\].
+* Better xml output (pretty layout). Check out the generated XML.
+* Regression testing facility: to make sure your document will always be
+ compatible (full backward compatibility) regardless of changes to
+ QuickBook.
+* Code cleanup and refactoring.
+* Allow phrase markup in the doc-info.
+* Preformatted code blocks via \`\`code\`\` (double ticks) allows code in tables
+ and lists, for example.
+* Quickbook versioning; allows full backward compatibility. You have to add
+ \[quickbook 1.3\] to the doc-info header to enable the new features. Without
+ this, QuickBook will assume that the document is a pre-1.3 document.
+* Better (intuitive) paragraph termination. Some markups may terminate a paragraph.
+ Example:``
+ [section x]
+ blah...
+ [endsect]``
+* Fully qualified section and headers. Subsection names are concatenated to the
+ ID to avoid clashing. Example: `doc_name.sect_name.sub_sect_name.sub_sub_sect_name`
+* Better &nbsp; and whitespace handling in code snippets.
+* \[xinclude\] fixes up the relative path to the target XML file when
+ input_directory is not the same as the output_directory.
+* Allow untitled tables.
+* Allow phrase markups in section titles.
+* Allow escaping back to QuickBook from code, code blocks and inline code.
+* Footnotes, with the \[footnote This is the footnote\] syntax.
+* Post-processor bug fix for escaped XML code that it does not recognize.
+* Replaceable, with the \[~replacement\] syntax.
+
+[heading:version_1_4 Version 1.4 - Boost 1.35.0 to 1.40.0]
+
+* Generic Headers
+* Code changes to allow full recursion (i.e. Collectors and push/pop functions)
+* Various code cleanup/maintenance
+* Templates!
+* \[conceptref\] for referencing BoostBook <concept> entities.
+* Allow escape of spaces. The escaped space is removed from the output. Syntax:
+ `\ `.
+* Nested comments are now allowed.
+* Quickbook blocks can nest inside comments.
+* __import__ facility.
+* Callouts on imported code
+* Simple markups can now span a whole block.
+* __blurbs__, __admonitions__ and table cells (see __tables__) may now
+ contain paragraphs.
+* `\n` and `[br]` are now deprecated.
+* __cond__. Ala C++ #ifdef.
+* Searching of included and imported files in an extensible search path with
+ `--include-path` (`-I`) option.
+
+[heading:version_1_5 Version 1.5 - Boost 1.41.0 to 1.42.0]
+
+* Support multiple copyright entrys in document info.
+* Improved SVG support.
+* \[globalref\] for referencing BoostBook <global> entities.
+* Fail on error.
+* Fix crash for templates with too many arguments or trailing space.
+* Improved handling of unexpected characters in code blocks.
+* Improved handling of unmatched escape in code blocks.
+* Support for python snippets.
+* `teletype` source mode.
+* Use static scoping in templates, should be a lot more intuitive.
+* Accept a space between `section:` and the section id.
+* Support table ids.
+
+[heading Version 1.5.1 - Boost 1.43.0]
+
+* Improve the post processor's list of block elements. `table`, `entry` and
+ `varlistentry` are treated as blocks. `replaceable` is treated as an inline
+ element.
+* Check that `[section]` and `[endsect]` tags are balanced in templates.
+* Add unicode escape characters, eg. `\u03B1` for \u03B1.
+* Support UTF-8 files with a unicode byte order mark.
+* Disallow `[` in simple markup. Fixes some errors with mismatched punctuation.
+* Add command line flag to define macros at the command line,
+ e.g. `quickbook "-D__italic_foo__=/foo/"`.
+
+[heading Version 1.5.2 - Boost 1.44.0]
+
+* Use the cygwin 1.7 API for better path handling.
+* Improved boostbook generation:
+ * XML encode the documentation info correctly.
+ * Avoid generating empty paragraphs.
+ * No longer wraps block templates in paragraphs.
+ * Warns if you use invalid doc_info members for docbook document types.
+ * Fixes some other causes of invalid boostbook, although it still
+ generates invalid boostbook in places.
+* Improved grammar:
+ * Supports multiple categories in library doc_info.
+ * No longer requires commas between authors in docinfo.
+ * Allows empty document bodies.
+ * A line containing only a comment is no longer interpreted as a
+ paragraph break.
+ * If a line starts with a comment, interpret it as a paragraph even if it's
+ followed by whitespace or a list character.
+ * Doesn't treat several consecutive blank lines as multiple paragraph breaks.
+* Fixes duplicate image attribute detection.
+* Fixes using code snippets more than once.
+* Early work on quickbook 1.6, available using the `[quickbook 1.6]` version switch,
+ but liable to change in future versions.
+ * When automatically generating ids for headers, use the quickbook
+ source, rather than the generated docbook.
+ * Fix id generation in included files. It wasn't correctly using the
+ main document's documentation id.
+ * Correctly restore the quickbook version switch after including a file
+ with a different version.
+
+[heading Version 1.5.3 - Boost 1.45.0]
+
+* Fix command line flag for defining macros.
+* Fix a couple of issues with the code block parser:
+ * A comment with no indentation will now end a code block.
+ * Code blocks no longer have to be followed by a blank line.
+* Improved tracking of file position in templates and imported code blocks.
+* Better generated markup for callout lists.
+* In docbook, variable list entries can only have one `listitem`, so if an
+ entry has multiple values, merge them into one `listitem`.
+* Support nested code snippets.
+* Support nested blocks in document info comments.
+* Revert xml escaping document info, it broke some documentation files
+ (now a 1.6 feature).
+* Further work on quickbook 1.6, still not stable.
+ * Allow heading to have ids, using the syntax: `[heading:id title]`.
+ * XML escape documentation fields, with escapes to allow encoding unicode
+ in ASCII.
+
+[heading Version 1.5.4 - Boost 1.46.1]
+
+Boost 1.46.0:
+
+* Add support for `lang` attribute in documentation info.
+* Improved anchor implementation. Especially for using an anchor
+ before a section or heading.
+* Fixed some more issues where lines containing comments were treated
+ as blank lines.
+* Allow import, include and xinclude in conditional phrases. Will
+ allow more block elements in a future version.
+* Rearrange the structure of the grammar.
+* Use filesystem 3. Remove cygwin 1.5 support.
+
+Boost 1.46.1:
+
+* Work around optimization bug in g++ 4.4 on 64 bit linux.
+
+[heading Version 1.5.5 - Boost 1.47]
+
+* Tweak anchor placement for titles.
+* Hard code the quickbook path into the quickbook testing tools. This
+ means that they can be used from multiple locations.
+* Generate an id for boostbook `bridgehead` elements. This results in
+ more consistent html, since docbook generates a random id if they
+ don't have one.
+* Improved unicode support on windows. Unicode can now be used from the
+ command line, and unicode filenames are supported. Unicode output is
+ a bit weak.
+* Check for windows paths, and warn about them.
+* Fix relative path detection on windows.
+* Reverse deprecation of `[br]`, printing a single warning about
+ generating invalid boostbook.
+* Fix handling empty category attributes.
+* Store data from the parser in a dynamic data structure.
+ This simplifies the implementation and makes it easier to parse
+ more complicated data structures.
+* Improved error messages for unknown doc info attributes.
+* Richer copyright syntax. Now understands:
+ `[copyright 2001-2006, 2010 One person, 2008 Another person]`.
+* Fix delimeter checking for simple markup.
+* Allow more block elements to be nested.
+* Go back to using invalid markup for lists. It generates better html.
+* Better anchor placement for lists.
+* Pass-thru comments in code snippets.
+* Use relative paths for '''<code>__FILENAME__</code>''' macro.
+* Rewrite xinclude path generator so that it doesn't use deprecated
+ filesystem functions.
+* Allow quickbook escapes inside comments in syntax highlighted code.
+* Quickbook 1.6:
+ * Scope source mode changes to the file they're made in.
+ * Explicit markup for lists. e.g.
+ `[ordered_list [item1][item2]]` or
+ `[itemized_list [item1][item2]]`.
+
+[heading Version 1.5.6 - Boost 1.48]
+
+* Xml encode escaped punctuation (eg. `\<` is correctly encodes to \<).
+* Rename duplicate generated ids.
+* Close open sections at end of document (still warns about them).
+* New anchor markup for headers, will hopefully generate better pdfs.
+* Remove some whitespace around code from post processed output.
+
+[heading Version 1.5.7 - Boost 1.49]
+
+* Several internal changes.
+* Some improved error messages.
+* Better handling of block templates expanded in a phrase context.
+* Avoids empty simple markup (i.e. \/\/ is not treated as an italic empty
+ space.
+* Better anchor markup for headers, which should be better for printing
+ - suggested by John Maddock.
+* Further improvements to the id generator.
+* If sections are left unopened at the end of a document, then close them
+ in the generated markup.
+* Try to handle whitespace better at the beginning and end of code blocks.
+* Handle lists that come immediately after an anchor.
+* Make horizontal rules followed by multi-line comments a little more
+ sensible.
+* Better support for empty ids and titles in docinfo.
+* Fix some minor regressions in SVG handling.
+* Better handling of invalid command line macros.
+* When auto-building quickbook, build the release version.
+* Lots of changes for 1.6:
+ * Scope templates in included files.
+ * Support import of templates and macros.
+ * Including top level quickbook blocks from source files.
+ * Use doc info blocks in included quickbook files.
+ * Better handling of macros with the same name.
+ * `block` element.
+ * Better handling of significant punctuation (e.g. escapes, square brackets).
+ * Support escapes in links, anchors, images, includes etc.
+ * Improved table title syntax.
+ * Paragraphs nested in lists.
+ * New docinfo attributes:
+ * `compatibility-mode` to make it possible to upgrade documents without
+ breaking ids.
+ * `xmlbase` for escaped `xi:include`s.
+ * Allow some docinfo attributes to be used before, or without, a doc info
+ block (`quickbook`, `compatibility-mode`, `source-mode`).
+ * Only add explicit alt text to images.
+ * Don't put 'inline' code blocks inside paragraphs.
diff --git a/tools/quickbook/doc/editors.qbk b/tools/quickbook/doc/editors.qbk
new file mode 100644
index 0000000000..08f4176b49
--- /dev/null
+++ b/tools/quickbook/doc/editors.qbk
@@ -0,0 +1,56 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[chapter Editor Support
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ [id quickbook.editors]
+ [source-mode teletype]
+]
+
+Editing quickbook files is usually done with text editors both simple and
+powerful. The following sections list the settings for some editors which can
+help make editing quickbook files a bit easier.
+
+[note You may submit your settings, tips, and suggestions to the
+authors, or through the [@https://lists.sourceforge.net/lists/listinfo/boost-
+docs Boost Docs mailing list].]
+
+[section:scite Scintilla Text Editor]
+
+[:['Section contributed by Dean Michael Berris]]
+
+The Scintilla Text Editor (SciTE) is a free source code editor for Win32 and X.
+It uses the SCIntilla source code editing component.
+
+[tip SciTE can be downloaded from [@http://www.scintilla.org/SciTE.html]]
+
+You can use the following settings to highlight quickbook tags when
+editing quickbook files.
+
+```
+qbk=*.qbk
+lexer.*.qbk=props
+use.tabs.$(qbk)=0
+tab.size.$(qbk)=4
+indent.size.$(qbk)=4
+style.props.32=$(font.base)
+comment.stream.start.props=[/
+comment.stream.end.props=]
+comment.box.start.props=[/
+comment.box.middle.props=
+comment.box.end.props=]
+```
+
+[note Thanks to Rene Rivera for the above SciTE settings.]
+
+[endsect] [/scite]
+
+[/ KDE support (Kate, KWrite, Konqueror, KDevelop) ]
+[include ../extra/katepart/katepart.qbk]
diff --git a/tools/quickbook/doc/faq.qbk b/tools/quickbook/doc/faq.qbk
new file mode 100644
index 0000000000..2921ac17da
--- /dev/null
+++ b/tools/quickbook/doc/faq.qbk
@@ -0,0 +1,55 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[chapter Frequently Asked Questions
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ [id quickbook.faq]
+ [source-mode teletype]
+]
+
+[heading Can I use QuickBook for non-Boost documentation?]
+
+QuickBook can be used for non-Boost documentation with a little extra work.
+
+[:['Faq contributed by Michael Marcin]]
+
+When building HTML documentation with BoostBook a Boost C++ Libraries header
+is added to the files. When using QuickBook to document projects outside of
+Boost this is not desirable. This behavior can be overridden at the BoostBook
+level by specifying some XSLT options. When using Boost Build version 2 (BBv2)
+this can be achieved by adding parameters to the BoostBook target declaration.
+
+For example:
+[pre
+using quickbook ;
+
+xml my_doc : my_doc.qbk ;
+
+boostbook standalone
+ :
+ my_doc
+ :
+ <xsl:param>boost.image.src\=images/my_project_logo.png
+ <xsl:param>boost.image.alt\="\\"My Project\\""
+ <xsl:param>boost.image.w=100
+ <xsl:param>boost.image.h=50
+ <xsl:param>nav.layout=none
+ ;
+]
+
+[heading Is there an easy way to convert BoostBook docs to QuickBook?]
+
+There's a stylesheet that allows Boostbook generated HTML to be viewed
+as quickbook source, see
+[@http://svn.boost.org/trac/boost/wiki/QuickbookSourceStylesheetProject],
+so it's then just a cut and paste job to convert the BoostBook to
+QuickBook (which IMO is a whole lot easier to edit and maintain).
+
+--John Maddock
diff --git a/tools/quickbook/doc/html/images/callouts/1.png b/tools/quickbook/doc/html/images/callouts/1.png
new file mode 100644
index 0000000000..6003ad3af4
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/1.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/10.png b/tools/quickbook/doc/html/images/callouts/10.png
new file mode 100644
index 0000000000..0426f516a4
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/10.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/11.png b/tools/quickbook/doc/html/images/callouts/11.png
new file mode 100644
index 0000000000..821afc4fa8
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/11.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/12.png b/tools/quickbook/doc/html/images/callouts/12.png
new file mode 100644
index 0000000000..7cec72720f
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/12.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/13.png b/tools/quickbook/doc/html/images/callouts/13.png
new file mode 100644
index 0000000000..5b41e02a67
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/13.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/14.png b/tools/quickbook/doc/html/images/callouts/14.png
new file mode 100644
index 0000000000..de5bdbd3eb
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/14.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/15.png b/tools/quickbook/doc/html/images/callouts/15.png
new file mode 100644
index 0000000000..3fd6ac3860
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/15.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/2.png b/tools/quickbook/doc/html/images/callouts/2.png
new file mode 100644
index 0000000000..f7c1578846
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/2.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/3.png b/tools/quickbook/doc/html/images/callouts/3.png
new file mode 100644
index 0000000000..3ff0a93931
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/3.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/4.png b/tools/quickbook/doc/html/images/callouts/4.png
new file mode 100644
index 0000000000..6aa29fc0b4
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/4.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/5.png b/tools/quickbook/doc/html/images/callouts/5.png
new file mode 100644
index 0000000000..36e785867a
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/5.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/6.png b/tools/quickbook/doc/html/images/callouts/6.png
new file mode 100644
index 0000000000..c943676bea
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/6.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/7.png b/tools/quickbook/doc/html/images/callouts/7.png
new file mode 100644
index 0000000000..20940de30d
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/7.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/8.png b/tools/quickbook/doc/html/images/callouts/8.png
new file mode 100644
index 0000000000..d8e34d4a09
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/8.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/callouts/9.png b/tools/quickbook/doc/html/images/callouts/9.png
new file mode 100644
index 0000000000..abe636072b
--- /dev/null
+++ b/tools/quickbook/doc/html/images/callouts/9.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/extra/katepart/boost.hs.logo.png b/tools/quickbook/doc/html/images/extra/katepart/boost.hs.logo.png
new file mode 100644
index 0000000000..01a8150329
--- /dev/null
+++ b/tools/quickbook/doc/html/images/extra/katepart/boost.hs.logo.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/extra/katepart/table.boost.hs.png b/tools/quickbook/doc/html/images/extra/katepart/table.boost.hs.png
new file mode 100644
index 0000000000..87315e0341
--- /dev/null
+++ b/tools/quickbook/doc/html/images/extra/katepart/table.boost.hs.png
Binary files differ
diff --git a/tools/quickbook/doc/html/images/extra/katepart/table.text.editor.png b/tools/quickbook/doc/html/images/extra/katepart/table.text.editor.png
new file mode 100644
index 0000000000..a59d0e7bcb
--- /dev/null
+++ b/tools/quickbook/doc/html/images/extra/katepart/table.text.editor.png
Binary files differ
diff --git a/tools/quickbook/doc/install.qbk b/tools/quickbook/doc/install.qbk
new file mode 100644
index 0000000000..5515fd9b74
--- /dev/null
+++ b/tools/quickbook/doc/install.qbk
@@ -0,0 +1,317 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[chapter Installation and configuration
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ [id quickbook.install]
+ [source-mode teletype]
+]
+
+This section provides some guidelines on how to install and configure
+BoostBook and Quickbook under several operating systems. Before installing
+you'll need a local copy of boost, and to install the version of `bjam`
+which comes with it (or a later version).
+
+[/ I don't think this is needed any more]
+[/
+Before continuing, it is very important that you keep this in mind: if you
+try to build some documents and the process breaks due to misconfiguration,
+be absolutely sure to delete any `bin` and `bin.v2` directories generated
+by the build before trying again. Otherwise your configuration fixes will
+not take any effect.
+]
+
+[section:macosx Mac OS X]
+
+The simplest way to install on OS X is to use macports.
+If you don't want to use macports and are using Snow Leopard or later,
+there are instructions [link quickbook.install.macosx.native later].
+Earlier versions of OS X need to use something like macports to install
+`xsltproc` because the version they come with is very old, and doesn't have
+good enough XSL support for boostbook's stylesheets.
+
+[section:macports Mac OS X, using macports]
+
+First install the `libxslt`, `docbook-xsl` and `docbook-xml-4.2`
+packages:
+
+ sudo port install libxslt docbook-xsl docbook-xml-4.2
+
+Next, we need to configure Boost Build to compile BoostBook files. Add the
+following to your `user-config.jam` file, which should be in your home
+directory. If you don't have one, create a file containing this text. For more
+information on setting up `user-config.jam`, see the
+[@http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html Boost
+Build documentation].
+
+ using xsltproc
+ : /opt/local/bin/xsltproc
+ ;
+
+ using boostbook
+ : /opt/local/share/xsl/docbook-xsl/
+ : /opt/local/share/xml/docbook/4.2
+ ;
+
+The above steps are enough to get a functional BoostBook setup. Quickbook
+will be automatically built when needed. If you want to avoid these
+rebuilds:
+
+# Go to Quickbook's source directory (`BOOST_ROOT/tools/quickbook`).
+
+# Build the utility by issuing `bjam`.
+
+# Copy the resulting `quickbook` binary (located at
+ `BOOST_ROOT/dist/bin`) to a safe place. The traditional location is
+ `/usr/local/bin`.
+
+# Add the following to your `user-config.jam` file, using the full path of the
+ quickbook executable:
+ ```
+ using quickbook
+ : /usr/local/bin/quickbook
+ ;
+ ```
+
+If you need to build documentation that uses Doxygen, you will need to install it as well:
+
+ sudo port install doxygen
+
+And then add to your `user-config.jam`:
+
+ using doxygen ;
+
+Alternatively, you can install from the official doxygen `dmg`.
+This is described at [link osx-prebuilt-doxygen the end of the next section].
+
+[endsect] [/ macports]
+
+[section:native Mac OS X, Snow Leopard (or later)]
+
+[:['Section contributed by Julio M. Merino Vidal]]
+
+The text below assumes you want to install all the necessary utilities in a
+system-wide location, allowing any user in the machine to have access to
+them. Therefore, all files will be put in the `/usr/local` hierarchy. If
+you do not want this, you can choose any other prefix such as
+`~/Applications` for a single-user installation.
+
+Snow Leopard comes with `xsltproc` and all related libraries preinstalled, so
+you do not need to take any extra steps to set them up. It is probable
+that future versions will include them too, but these instructions may not
+apply to older versions.
+
+To get started:
+
+# Download [@http://www.docbook.org/xml/4.2/docbook-xml-4.2.zip Docbook XML
+ 4.2] and unpack it inside `/usr/local/share/xml/docbook/4.2`.
+
+# Download the latest
+ [@http://sourceforge.net/project/showfiles.php?group_id=21935&package_id=16608
+ Docbook XSL] version and unpack it. Be careful that you download the correct
+ file, sometimes the 'looking for the latest version' link often links to
+ another file. The name should be of the form
+ '''<code>docbook-xsl-1.<emphasis>nn</emphasis>.<emphasis>n</emphasis>.tar.bz2</code>''',
+ with no suffix such as `-ns.tar.bz2` or `-doc.tar.bz2`.
+ Put the results in
+ `/usr/local/share/xsl/docbook`, thus effectively removing the version
+ number from the directory name (for simplicity).
+
+# Add the following to your `user-config.jam` file, which should live in
+ your home directory (`/Users/<your_username>`). You must already have it
+ somewhere or otherwise you could not be building Boost (i.e. missing
+ tools configuration).
+ ```
+ using xsltproc ;
+
+ using boostbook
+ : "/usr/local/share/xsl/docbook"
+ : "/usr/local/share/xml/docbook/4.2"
+ ;
+ ```
+
+The above steps are enough to get a functional BoostBook setup. Quickbook
+will be automatically built when needed. If you want to avoid these
+rebuilds and install a system-wide Quickbook instead:
+
+# Go to Quickbook's source directory (`BOOST_ROOT/tools/quickbook`).
+
+# Build the utility by issuing `bjam`.
+
+# Copy the resulting `quickbook` binary (located at
+ `BOOST_ROOT/dist/bin`) to a safe place. Following our previous
+ example, you can install it into: `/usr/local/bin`.
+
+# Add the following to your `user-config.jam` file:
+ ```
+ using quickbook
+ : "/usr/local/bin/quickbook" ;
+ ;
+ ```
+
+[# osx-prebuilt-doxygen]
+Additionally, if you need to build documentation that uses
+[@http://www.doxygen.org Doxygen], you will need to install it too:
+
+# Go to the [@http://www.stack.nl/~dimitri/doxygen/download.html#latestsrc
+ downloads section] and get the disk image (`dmg` file) for Mac OS X.
+
+# Open the disk image and drag the Doxygen application to your
+ `Applications` folder to install it.
+
+# Add the following to your `user-config.jam` file:
+ ```
+ using doxygen
+ : /Applications/Doxygen.app/Contents/Resources/doxygen
+ ;
+ ```
+
+[/ Removed this, since there are macports based instructions earlier.
+ Instructions for pkgsrc welcome]
+[/
+Alternatively, you may want to install all the prerequistes through a
+package system to avoid manual management of the installations. In that
+case, check out [@http://www.pkgsrc.org pkgsrc].
+]
+
+[endsect] [/ native]
+
+[endsect] [/ macosx]
+
+[section:windows Windows 2000, XP, 2003, Vista, 7]
+
+[:['Section contributed by Julio M. Merino Vidal]]
+
+The following instructions apply to any Windows system based on Windows
+2000, including Windows XP, Windows 2003 Server, Windows Vista, and Windows 7. The
+paths shown below are taken from a Windows Vista machine; you will need to
+adjust them to match your system in case you are running an older version.
+
+# First of all you need to have a copy of `xsltproc` for Windows. There
+ are many ways to get this tool, but to keep things simple, use the
+ [@http://www.zlatkovic.com/pub/libxml/ binary packages] made by Igor
+ Zlatkovic. At the very least, you need to download the following
+ packages: `iconv`, `zlib`, `libxml2` and `libxslt`.
+
+# Unpack all these packages in the same directory so that you get unique
+ `bin`, `include` and `lib` directories within the hierarchy. These
+ instructions use `C:\Users\example\Documents\boost\xml` as the root for
+ all files.
+
+# From the command line, go to the `bin` directory and launch
+ `xsltproc.exe` to ensure it works. You should get usage information on
+ screen.
+
+# Download [@http://www.docbook.org/xml/4.2/docbook-xml-4.2.zip Docbook XML
+ 4.2] and unpack it in the same directory used above. That is:
+ `C:\Users\example\Documents\boost\xml\docbook-xml`.
+
+# Download the latest
+ [@http://sourceforge.net/project/showfiles.php?group_id=21935&package_id=16608
+ Docbook XSL] version and unpack it, again in the same directory
+ used before. Be careful that you download the correct
+ file, sometimes the 'looking for the latest version' link often links to
+ another file. The name should be of the form
+ '''<code>docbook-xsl-1.<emphasis>nn</emphasis>.<emphasis>n</emphasis>.tar.bz2</code>''',
+ with no suffix such as `-ns.tar.bz2` or `-doc.tar.bz2`.
+ To make things easier, rename the directory created
+ during the extraction to `docbook-xsl` (bypassing the version name):
+ `C:\Users\example\Documents\boost\xml\docbook-xsl`.
+
+# Add the following to your `user-config.jam` file, which should live in
+ your home directory (`%HOMEDRIVE%%HOMEPATH%`). You must already have it
+ somewhere or otherwise you could not be building Boost (i.e. missing
+ tools configuration).
+ ```
+ using xsltproc
+ : "C:/Users/example/Documents/boost/xml/bin/xsltproc.exe"
+ ;
+
+ using boostbook
+ : "C:/Users/example/Documents/boost/xml/docbook-xsl"
+ : "C:/Users/example/Documents/boost/xml/docbook-xml"
+ ;
+ ```
+
+The above steps are enough to get a functional BoostBook setup. Quickbook
+will be automatically built when needed. If you want to avoid these
+rebuilds:
+
+# Go to Quickbook's source directory (`BOOST_ROOT\tools\quickbook`).
+
+# Build the utility by issuing `bjam`.
+
+# Copy the resulting `quickbook.exe` binary (located at
+ `BOOST_ROOT\dist\bin`) to a safe place. Following our previous
+ example, you can install it into:
+ `C:\Users\example\Documents\boost\xml\bin`.
+
+# Add the following to your `user-config.jam` file:
+ ```
+ using quickbook
+ : "C:/Users/example/Documents/boost/xml/bin/quickbook.exe"
+ ;
+ ```
+
+[endsect] [/Windows]
+
+[section:linux Debian, Ubuntu]
+
+The following instructions apply to Debian and its derivatives. They are based
+on a Ubuntu Edgy install but should work on other Debian based systems. They
+assume you've already installed an appropriate version of `bjam` for your
+copy of boost.
+
+First install the `xsltproc`, `docbook-xsl` and `docbook-xml` packages.
+For example, using `apt-get`:
+
+ sudo apt-get install xsltproc docbook-xsl docbook-xml
+
+If you're planning on building boost's documentation, you'll also need to
+install the `doxygen` package as well.
+
+Next, we need to configure Boost Build to compile BoostBook files. Add the
+following to your `user-config.jam` file, which should be in your home
+directory. If you don't have one, create a file containing this text. For more
+information on setting up `user-config.jam`, see the
+[@http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html Boost
+Build documentation].
+
+ using xsltproc ;
+
+ using boostbook
+ : /usr/share/xml/docbook/stylesheet/nwalsh
+ : /usr/share/xml/docbook/schema/dtd/4.2
+ ;
+
+ # Remove this line if you're not using doxygen
+ using doxygen ;
+
+The above steps are enough to get a functional BoostBook setup. Quickbook
+will be automatically built when needed. If you want to avoid these
+rebuilds:
+
+# Go to Quickbook's source directory (`BOOST_ROOT/tools/quickbook`).
+
+# Build the utility by issuing `bjam`.
+
+# Copy the resulting `quickbook` binary (located at
+ `BOOST_ROOT/dist/bin`) to a safe place. The traditional location is
+ `/usr/local/bin`.
+
+# Add the following to your `user-config.jam` file, using the full path of the
+ quickbook executable:
+ ```
+ using quickbook
+ : /usr/local/bin/quickbook
+ ;
+ ```
+
+[endsect] [/Linux] \ No newline at end of file
diff --git a/tools/quickbook/doc/introduction.qbk b/tools/quickbook/doc/introduction.qbk
new file mode 100644
index 0000000000..fc44d2d127
--- /dev/null
+++ b/tools/quickbook/doc/introduction.qbk
@@ -0,0 +1,57 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[chapter Introduction
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ [id quickbook.intro]
+ [source-mode teletype]
+]
+
+[:[*['["Why program by hand in five days what you can spend five years of your
+life automating?]]]
+
+-- Terrence Parr, author ANTLR/PCCTS
+]
+
+Well, QuickBook started as a weekend hack. It was originally intended to be a
+sample application using __spirit__. What is it? What you are viewing now, this
+documentation, is autogenerated by QuickBook. These files were generated from
+one master:
+
+[:[@boost:/tools/quickbook/doc/quickbook.qbk quickbook.qbk]]
+
+Originally named QuickDoc, this funky tool that never dies, evolved into a
+funkier tool thanks to Eric Niebler who resurrected the project making it
+generate __boostbook__ instead of HTML. The __boostbook__ documentation format
+is an extension of __docbook__, an SGML or XML based format for describing
+documentation.
+
+[tip You don't need to know anything about __boostbook__ or __docbook__
+to use QuickBook. A basic understanding of __docbook__ might help, but
+shouldn't be necessary. For really advanced stuff you will need to know
+__docbook__, but you can ignore it at first, and maybe continue to do so.
+]
+
+QuickBook is a WikiWiki style documentation tool geared towards C++
+documentation using simple rules and markup for simple formatting tasks.
+QuickBook extends the WikiWiki concept. Like the WikiWiki, QuickBook documents are
+simple text files. A single QuickBook document can generate a fully linked set
+of nice HTML and PostScript/PDF documents complete with images and syntax-
+colorized source code.
+
+Features include:
+
+* generate __boostbook__ xml, to generate HTML, PostScript and PDF
+* simple markup to link to Doxygen-generated entities
+* macro system for simple text substitution
+* simple markup for italics, bold, preformatted, blurbs, code samples,
+ tables, URLs, anchors, images, etc.
+* automatic syntax coloring of code samples
+* CSS support
diff --git a/tools/quickbook/doc/phrase.qbk b/tools/quickbook/doc/phrase.qbk
new file mode 100644
index 0000000000..613d730bc5
--- /dev/null
+++ b/tools/quickbook/doc/phrase.qbk
@@ -0,0 +1,546 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[chapter Phrase Level Elements
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ [id quickbook.syntax.phrase]
+ [source-mode teletype]
+]
+
+[section Font Styles]
+
+```
+['italic], [*bold], [_underline], [^teletype], [-strikethrough]
+```
+
+will generate:
+
+['italic], [*bold], [_underline], [^teletype], [-strikethrough]
+
+Like all non-terminal phrase level elements, this can of course be nested:
+
+```
+[*['bold-italic]]
+```
+
+will generate:
+
+[*['bold-italic]]
+
+[endsect] [/Font Styles]
+
+[section Replaceable]
+
+When you want content that may or must be replaced by the user, use the syntax:
+
+```
+[~replacement]
+```
+
+This will generate:
+
+[~replacement]
+
+[endsect] [/Replaceable]
+
+[section Quotations]
+
+```
+["A question that sometimes drives me hazy: am I or are the others crazy?]--Einstein
+```
+
+will generate:
+
+["A question that sometimes drives me hazy: am I or are the others crazy?]--Einstein
+
+Note the proper left and right quote marks. Also, while you can simply use
+ordinary quote marks like "quoted", our quotation, above, will generate correct
+DocBook quotations (e.g. <quote>quoted</quote>).
+
+Like all phrase elements, quotations may be nested. Example:
+
+```
+["Here's the rule for bargains: ["Do other men, for they would do you.] That's
+the true business precept.]
+```
+
+will generate:
+
+["Here's the rule for bargains: ["Do other men, for they would do you.]
+That's the true business precept.]
+
+[endsect] [/Quotations]
+
+[section Simple formatting]
+
+Simple markup for formatting text, common in many applications, is now supported:
+
+```
+/italic/, *bold*, _underline_, =teletype=
+```
+
+will generate:
+
+/italic/, *bold*, _underline_, =teletype=
+
+Unlike QuickBook's standard formatting scheme, the rules for simpler
+alternatives are much stricter[footnote Thanks to David Barrett, author of
+[@http://quinthar.com/qwikiwiki/index.php?page=Home Qwiki], for sharing
+these samples and teaching me these obscure formatting rules. I wasn't sure
+at all if __spirit__, being more or less a formal EBNF parser, can handle
+the context sensitivity and ambiguity.].
+
+* Simple markups cannot nest. You can combine a simple markup with a nestable markup.
+* Simple markups cannot contain any other form of quickbook markup.
+* A non-space character must follow the leading markup
+* A non-space character must precede the trailing markup
+* A space or a punctuation must follow the trailing markup
+* If the matching markup cannot be found within a block, the formatting
+ will not be applied. This is to ensure that un-matched formatting markups,
+ which can be a common mistake, does not corrupt anything past a single block.
+ We do not want the rest of the document to be rendered bold just because we
+ forgot a trailing '*'. A single block is terminated by two end of lines or
+ the close bracket: '\]'.
+* A line starting with the star will be interpreted as an unordered list.
+ See __unordered_lists__.
+
+[table More Formatting Samples
+ [[Markup] [Result]]
+ [[`*Bold*`] [*Bold*]]
+ [[`*Is bold*`] [*Is bold*]]
+ [[`* Not bold* *Not bold * * Not bold *`] [* Not bold* *Not bold * * Not bold *]]
+ [[`This*Isn't*Bold (no bold)`] [This*Isn't*Bold (no bold)]]
+ [[`(*Bold Inside*) (parenthesis not bold)`] [(*Bold Inside*) (parenthesis not bold)]]
+ [[`*(Bold Outside)* (parenthesis bold)`] [*(Bold Outside)* (parenthesis bold)]]
+ [[`3*4*5 = 60 (no bold)`] [3*4*5 = 60 (no bold)]]
+ [[`3 * 4 * 5 = 60 (no bold)`] [3 * 4 * 5 = 60 (no bold)]]
+ [[`3 *4* 5 = 60 (4 is bold)`] [3 *4* 5 = 60 (4 is bold)]]
+ [[`*This is bold* this is not *but this is*`] [*This is bold* this is not *but this is*]]
+ [[`*This is bold*.`] [*This is bold*.]]
+ [[`*B*. (bold B)`] [*B*. (bold B)]]
+ [[`['*Bold-Italic*]`] [['*Bold-Italic*]]]
+ [[`*side-by*/-side/`] [*side-by*/-side/]]
+]
+
+As mentioned, simple markups cannot go past a single block. The text
+from "have" to "full" in the following paragraph will be rendered as
+bold:
+
+```
+Baa baa black sheep, *have you any wool?
+Yes sir, yes sir, three bags full!*
+One for the master, one for the dame,
+And one for the little boy who lives down the lane.
+```
+
+Baa baa black sheep, *have you any wool?
+Yes sir, yes sir, three bags full!*
+One for the master, one for the dame,
+And one for the little boy who lives down the lane.
+
+But in the following paragraph, bold is not applied:
+
+```
+Baa baa black sheep, *have you any wool?
+Yes sir, yes sir, three bags full!
+One for the master, one for the dame,
+And one for the little boy who lives down the lane.
+```
+
+Baa baa black sheep, *have you any wool?
+Yes sir, yes sir, three bags full!
+One for the master, one for the dame,
+And one for the little boy who lives down the lane.
+
+[endsect] [/Simple Formatting]
+
+[section Inline code]
+
+Inlining code in paragraphs is quite common when writing C++ documentation. We
+provide a very simple markup for this. For example, this:
+
+```
+This text has inlined code `int main() { return 0; }` in it.
+```
+
+will generate:
+
+This text has inlined code `int main() { return 0; }` in it. The code will be
+syntax highlighted.
+
+[note We simply enclose the code with the tick: [^"\`"], not the
+single quote: `"'"`. Note too that [^\`some code\`] is preferred over
+`[^some code]`. ]
+
+[endsect] [/Inline Code]
+
+[section Code blocks]
+
+Preformatted code simply starts with a space or a tab (See __code__).
+However, such a simple syntax cannot be used as phrase elements in lists
+(See __ordered_lists__ and __unordered_lists__), tables (See __tables__),
+etc. Inline code (see above) can. The problem is, inline code does not
+allow formatting with newlines, spaces, and tabs. These are lost.
+
+We provide a phrase level markup that is a mix between the two. By using the
+double-tick or triple-tick, instead of the single-tick, we are telling QuickBook
+to use preformatted blocks of code. Example:
+
+```
+``\`\` ``
+ #include <iostream>
+
+ int main()
+ {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+``\`\`\ ``
+```
+
+or:
+
+```
+``\`\`\` ``
+ #include <iostream>
+
+ int main()
+ {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+``\`\`\` ``
+```
+
+will generate:
+
+[c++]
+
+``
+ #include <iostream>
+
+ int main()
+ {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+``
+
+[teletype]
+
+[endsect] [/Code blocks]
+
+[section Source Mode]
+
+If a document contains more than one type of source code then the source
+mode may be changed dynamically as the document is processed. All QuickBook
+documents are initially in C++ mode by default, though an alternative
+initial value may be set in the __document__ section.
+
+To change the source mode, use the [^\[source-mode\]] markup, where
+=source-mode= is one of the supported modes. For example, this:
+
+```
+Python's [python] `import` is rather like C++'s [c++] `#include`. A
+C++ comment `// looks like this` whereas a Python comment [python]
+`# looks like this`.
+```
+
+will generate:
+
+Python's [python] `import` is rather like C++'s [c++] `#include`. A
+C++ comment `// looks like this` whereas a Python comment [python]
+`#looks like this`.
+
+[teletype]
+
+[table Supported Source Modes
+ [[Mode] [Source Mode Markup]]
+ [[C++] [[^\[c++\]]]]
+ [[Python] [[^\[python\]]]]
+ [[Plain Text] [[^\[teletype\]]]]
+]
+
+[note The source mode strings are lowercase.]
+
+[endsect] [/Source Mode]
+
+[#ref-line-break]
+[section line-break]
+
+```
+[br]
+```
+
+[warning `[br]` generates invalid docbook. It seems to mostly work okay but
+there might be problems, especially when using an alternative docbook
+processor.]
+
+[endsect] [/Line break]
+
+[section Anchors]
+
+```
+[#named_anchor]
+```
+
+A named anchor is a hook that can be referenced by a link elsewhere in the
+document. You can then reference an anchor with `[link named_anchor
+Some link text]`. See __anchor_links__, __section__ and __heading__.
+
+These anchors are global and can be accessed from anywhere in the
+quickbook documentation. Be careful to avoid clashes with anchors in
+other sections.
+
+[endsect] [/Anchors]
+
+[section Links]
+
+```
+[@http://www.boost.org this is [*boost's] website....]
+```
+
+will generate:
+
+[@http://www.boost.org this is [*boost's] website....]
+
+URL links where the link text is the link itself is common. Example:
+
+```
+see http://spirit.sourceforge.net/
+```
+
+so, when the text is absent in a link markup, the URL is assumed. Example:
+
+```
+see [@http://spirit.sourceforge.net/]
+```
+
+will generate:
+
+see [@http://spirit.sourceforge.net/]
+
+Boostbook also support a custom url schema for linking to files within
+the boost distribution:
+
+```
+[@boost:/libs/spirit/index.html the Boost.Spirit documentation]
+```
+
+will generate: [@boost:/libs/spirit/index.html the Boost.Spirit documentation]
+
+Note that this is only available when using BoostBook, and only for links
+- it can't be used for images.
+
+[endsect] [/Links]
+
+[section Anchor links]
+
+You can link within a document using:
+
+```
+[link document_id.section_id.normalized_header_text The link text]
+```
+
+See sections __section__ and __heading__ for more info.
+
+[endsect] [/Anchor links]
+
+[section refentry links]
+
+In addition, you can link internally to an XML refentry like:
+
+```
+[link xml.refentry The link text]
+```
+
+This gets converted into [^<link linkend="xml.refentry">The link text</link>].
+
+Like URLs, the link text is optional. If this is not present, the link text will
+automatically be the refentry. Example:
+
+```
+[link xml.refentry]
+```
+
+This gets converted into [^<link linkend="xml.refentry">xml.refentry</link>].
+
+[endsect] [/refentry links]
+
+[section:code_links Code Links]
+
+If you want to link to a function, class, member, enum, concept, global, or header in
+the reference section, you can use:
+
+```
+[funcref fully::qualified::function_name The link text]
+[classref fully::qualified::class_name The link text]
+[memberref fully::qualified::member_name The link text]
+[enumref fully::qualified::enum_name The link text]
+[macroref MACRO_NAME The link text]
+[conceptref ConceptName The link text]
+[headerref path/to/header.hpp The link text]
+[globalref fully::qualified::global The link text]
+```
+
+Again, the link text is optional. If this is not present, the link text will
+automatically be the function, class, member, enum, macro, concept, global, or header name.
+Example:
+
+```
+[classref boost::bar::baz]
+```
+
+would have "boost::bar::baz" as the link text.
+
+[endsect] [/Code Links]
+
+[section Escape]
+
+The escape mark-up is used when we don't want to do any processing.
+
+```
+'''
+escape (no processing/formatting)
+'''
+```
+
+Escaping allows us to pass XML markup to __boostbook__ or __docbook__. For example:
+
+```
+'''
+<emphasis role="bold">This is direct XML markup</emphasis>
+'''
+```
+
+'''
+<emphasis role="bold">This is direct XML markup</emphasis>
+'''
+
+[important Be careful when using the escape. The text must conform to
+__boostbook__/__docbook__ syntax.]
+
+[endsect] [/Escape]
+
+[section Single char escape]
+
+The backslash may be used to escape a single punctuation character. The
+punctuation immediately after the backslash is passed without any processing.
+This is useful when we need to escape QuickBook punctuations such as `[` and `]`.
+For example, how do you escape the triple quote? Simple: [^\\'\\'\\']
+
+
+`\n` has a special meaning. It is used to generate line breaks.
+
+[warning `\n` is now deprecated, use [link ref-line-break `[br]`]
+instead. Although, use it sparingly as it can generated invalid docbook]
+
+The escaped space: `\ ` also has a special meaning. The escaped space is removed
+from the output.
+
+[endsect] [/Single char escape]
+
+[section Unicode escape]
+
+You can enter any 16-bit unicode character by using `\u` followed by its 4 digit
+hexadecimal code, or a 32-bit character by using `\U` followed by an 8 digit
+hexadecimal code. eg.
+
+```
+\u03B1 + \u03B2
+```
+
+will generate:
+
+[:
+\u03B1 + \u03B2
+]
+
+[endsect] [/Unicode escape]
+
+[section Images]
+
+```
+[$image.jpg]
+```
+
+From version 1.5, you can also use
+[@http://www.docbook.org/tdg/en/html/imagedata.html
+DocBook imagedata attributes]:
+
+```
+[$image.jpg [width 200in] [height 200in]]
+```
+
+[endsect] [/Images]
+
+[section Footnotes]
+
+As of version 1.3, QuickBook supports footnotes. Just put the text of the
+footnote in a `[footnote]` block, and the text will be put at the bottom
+of the current page. For example, this:
+
+```
+[footnote A sample footnote]
+```
+
+will generate this[footnote A sample footnote].
+
+[endsect] [/Footnotes]
+
+[section Macro Expansion]
+
+```
+__a_macro_identifier__
+```
+
+See __macros__ for details.
+
+[endsect] [/Macro Expansion]
+
+[section Template Expansion]
+
+```
+[a_template_identifier]
+```
+
+See __templates__ for details.
+
+[endsect] [/Template Expansion]
+
+[section:cond Conditional Generation]
+
+Like C++ `#ifdef`, you can generate phrases depending on the presence of
+a macro. Example:
+
+```
+[? __to_be__ To be or not to be]
+```
+
+[? __to_be__ To be or not to be]
+
+Here, the phrase "To be or not to be" will only be generated if the
+macro symbol `__to_be__` has been previously defined. The phrase
+above will not do anything since we haven't defined `__to_be__`.
+Now, let's define the symbol:
+
+```
+[def __to_be__]
+```
+
+[def __to_be__]
+
+And try again:
+
+[? __to_be__ To be or not to be]
+
+Yes!
+
+[endsect] [/Condition Generation]
diff --git a/tools/quickbook/doc/quickbook.qbk b/tools/quickbook/doc/quickbook.qbk
new file mode 100644
index 0000000000..da3f9a8fbe
--- /dev/null
+++ b/tools/quickbook/doc/quickbook.qbk
@@ -0,0 +1,94 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[part Quickbook
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ [id quickbook]
+ [version 1.5]
+ [authors [de Guzman, Joel], [Niebler, Eric]]
+ [copyright 2002 2004 2006 Joel de Guzman, Eric Niebler]
+ [copyright 2010-2011 Daniel James]
+ [purpose /WikiWiki/ style documentation tool]
+ [license
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ [@http://www.boost.org/LICENSE_1_0.txt])
+ ]
+ [source-mode teletype]
+]
+
+[/ QuickBook Document version 1.5 ]
+[/ Sept 24, 2002 ]
+[/ Sept 2, 2004 ]
+[/ Feb 14, 2005 ]
+[/ Sept 13, 2005 ]
+
+[/ Some links]
+
+[def :-) [$../src/images/smiley.png]]
+[def __spirit__ [@http://spirit.sourceforge.net Spirit]]
+[def __boostbook__ [@http://www.boost.org/doc/html/boostbook.html BoostBook]]
+[def __docbook__ [@http://www.docbook.org/ DocBook]]
+
+[def __comments__ [link quickbook.syntax.comments Comments]]
+
+[def __font_styles__ [link quickbook.syntax.phrase.font_styles Font Styles]]
+[def __quotations__ [link quickbook.syntax.phrase.quotations Quotations]]
+[def __replaceable__ [link quickbook.syntax.phrase.replaceable Replaceble]]
+[def __simple_formatting__ [link quickbook.syntax.phrase.simple_formatting Simple formatting]]
+[def __inline_code__ [link quickbook.syntax.phrase.inline_code Inline code]]
+[def __code_blocks__ [link quickbook.syntax.phrase.code_blocks Code blocks]]
+[def __source_mode__ [link quickbook.syntax.phrase.source_mode Source Mode]]
+[def __line_break__ [link quickbook.syntax.phrase.line_break line-break]]
+[def __anchors__ [link quickbook.syntax.phrase.anchors Anchors]]
+[def __links__ [link quickbook.syntax.phrase.links Links]]
+[def __anchor_links__ [link quickbook.syntax.phrase.anchor_links Anchor links]]
+[def __refentry_links__ [link quickbook.syntax.phrase.refentry_links refentry links]]
+[def __code_links__ [link quickbook.syntax.phrase.code_links function, class, member, enum, macro, concept or header links]]
+[def __escape__ [link quickbook.syntax.phrase.escape Escape]]
+[def __single_char_escape__ [link quickbook.syntax.phrase.single_char_escape Single char escape]]
+[def __images__ [link quickbook.syntax.phrase.images Images]]
+[def __cond__ [link quickbook.syntax.phrase.cond Conditional Generation]]
+
+[def __document__ [link quickbook.syntax.structure.docinfo Document]]
+[def __section__ [link quickbook.syntax.structure.section Section]]
+[def __xinclude__ [link quickbook.syntax.block.xinclude xinclude]]
+[def __paragraphs__ [link quickbook.syntax.block.paragraphs Paragraphs]]
+[def __ordered_lists__ [link quickbook.syntax.block.lists.ordered_lists Ordered lists]]
+[def __list_hierarchies__ [link quickbook.syntax.block.lists.list_hierarchies List Hierarchies]]
+[def __long_list_lines__ [link quickbook.syntax.block.lists.long_list_lines Long List Lines]]
+[def __unordered_lists__ [link quickbook.syntax.block.lists.unordered_lists Unordered lists]]
+[def __mixed_lists__ [link quickbook.syntax.block.lists.mixed_lists Mixed lists]]
+[def __code__ [link quickbook.syntax.block.code Code]]
+[def __escape_back__ [link quickbook.syntax.block.escape_back Escaping Back To QuickBook]]
+[def __preformatted__ [link quickbook.syntax.block.preformatted Preformatted]]
+[def __blockquote__ [link quickbook.syntax.block.blockquote Blockquote]]
+[def __heading__ [link quickbook.syntax.block.headings Heading]]
+[def __macros__ [link quickbook.syntax.block.macros Macros]]
+[def __templates__ [link quickbook.syntax.block.templates Templates]]
+[def __predefined_macros__ [link quickbook.syntax.block.predefined_macros Predefined Macros]]
+[def __blurbs__ [link quickbook.syntax.block.blurbs Blurbs]]
+[def __admonitions__ [link quickbook.syntax.block.admonitions Admonitions]]
+[def __tables__ [link quickbook.syntax.block.tables Tables]]
+[def __variable_lists__ [link quickbook.syntax.block.variable_lists Variable Lists]]
+[def __include__ [link quickbook.syntax.block.include Include]]
+[def __import__ [link quickbook.syntax.block.import Import]]
+
+[include introduction.qbk]
+[include change_log.qbk]
+[include syntax.qbk]
+[include structure.qbk]
+[include phrase.qbk]
+[include block.qbk]
+[include 1_6.qbk]
+[include install.qbk]
+[include editors.qbk]
+[include faq.qbk]
+[include ref.qbk] \ No newline at end of file
diff --git a/tools/quickbook/doc/ref.qbk b/tools/quickbook/doc/ref.qbk
new file mode 100644
index 0000000000..20bdb6d627
--- /dev/null
+++ b/tools/quickbook/doc/ref.qbk
@@ -0,0 +1,106 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[chapter Quick Reference
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ [id quickbook.ref]
+ [source-mode teletype]
+]
+
+[teletype]
+
+[template ordered_list_sample[]
+```
+# one
+# two
+# three
+```
+]
+
+[template unordered_list_sample[]
+```
+* one
+* two
+* three
+```
+]
+
+[template table_sample[]
+```
+[table Title
+[[a][b][c]]
+[[a][b][c]]
+]
+```
+]
+
+[template var_list_sample[]
+```
+[variablelist Title
+[[a][b]]
+[[a][b]]
+]
+```
+]
+
+
+[table Syntax Compendium
+ [[To do this...] [Use this...] [See this...]]
+ [[comment] [`[/ some comment]`] [__comments__]]
+ [[['italics]] [`['italics] or /italics/`] [__font_styles__ and __simple_formatting__]]
+ [[[*bold]] [`[*bold] or *bold*`] [__font_styles__ and __simple_formatting__]]
+ [[[_underline]] [`[_underline] or _underline_`] [__font_styles__ and __simple_formatting__]]
+ [[[^teletype]] [`[^teletype] or =teletype=`] [__font_styles__ and __simple_formatting__]]
+ [[[-strikethrough]] [`[-strikethrough]`] [__font_styles__ and __simple_formatting__]]
+ [[[~replaceable]] [`[~replaceable]`] [__replaceable__]]
+ [[source mode] [`[c++]` or `[python]`] [__source_mode__]]
+ [[inline code] [[^'''`int main();`''']] [__inline_code__]]
+ [[code block] [[^'''``int main();``''']] [__code__]]
+ [[code escape] [[^'''``from c++ to QuickBook``''']] [__escape_back__]]
+ [[line break] [`[br] or \n`] [__line_break__ *DEPRECATED*]]
+ [[anchor] [`[#anchor]`] [__anchors__]]
+ [[link] [`[@http://www.boost.org Boost]`] [__links__]]
+ [[anchor link] [`[link section.anchor Link text]`] [__anchor_links__]]
+ [[refentry link] [`[link xml.refentry Link text]`] [__refentry_links__]]
+ [[function link] [`[funcref fully::qualified::function_name Link text]`] [__code_links__]]
+ [[class link] [`[classref fully::qualified::class_name Link text]`] [__code_links__]]
+ [[member link] [`[memberref fully::qualified::member_name Link text]`] [__code_links__]]
+ [[enum link] [`[enumref fully::qualified::enum_name Link text]`] [__code_links__]]
+ [[macro link] [`[macroref MACRO_NAME Link text]`] [__code_links__]]
+ [[concept link] [`[conceptref ConceptName Link text]`] [__code_links__]]
+ [[header link] [`[headerref path/to/header.hpp Link text]`] [__code_links__]]
+ [[global link] [`[globalref fully::qualified::global Link text]`] [__code_links__]]
+ [[escape] [`'''escaped text (no processing/formatting)'''`] [__escape__]]
+ [[single char escape] [`\c`] [__single_char_escape__]]
+ [[images] [`[$image.jpg]`] [__images__]]
+ [[begin section] [`[section The Section Title]`] [__section__]]
+ [[end section] [`[endsect]`] [__section__]]
+ [[paragraph] [No markup. Paragraphs start left-flushed and are terminated by two or more newlines.] [__paragraphs__]]
+ [[ordered list] [[ordered_list_sample]] [__ordered_lists__]]
+ [[unordered list] [[unordered_list_sample]] [__unordered_lists__]]
+ [[code] [No markup. Preformatted code starts with a space or a tab.] [__code__]]
+ [[preformatted] [`[pre preformatted]`] [__preformatted__]]
+ [[block quote] [`[:sometext...]`] [__blockquote__]]
+ [[heading 1] [`[h1 Heading 1]`] [__heading__]]
+ [[heading 2] [`[h2 Heading 2]`] [__heading__]]
+ [[heading 3] [`[h3 Heading 3]`] [__heading__]]
+ [[heading 4] [`[h4 Heading 4]`] [__heading__]]
+ [[heading 5] [`[h5 Heading 5]`] [__heading__]]
+ [[heading 6] [`[h6 Heading 6]`] [__heading__]]
+ [[macro] [`[def macro_identifier some text]`] [__macros__]]
+ [[template] [`[template[a b] [a] body [b]]`] [__templates__]]
+ [[blurb] [`[blurb advertisement or note...]`] [__blurbs__]]
+ [[admonition] [`[warning Warning text...]`] [__admonitions__]]
+ [[table] [[table_sample]] [__tables__]]
+ [[variablelist] [[var_list_sample]] [__variable_lists__]]
+ [[include] [`[include someother.qbk]`] [__include__]]
+ [[conditional generation]
+ [`[? symbol phrase]`] [__cond__]]
+]
diff --git a/tools/quickbook/doc/structure.qbk b/tools/quickbook/doc/structure.qbk
new file mode 100644
index 0000000000..80e812c2f1
--- /dev/null
+++ b/tools/quickbook/doc/structure.qbk
@@ -0,0 +1,192 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ [@http://www.boost.org/LICENSE_1_0.txt])
+]
+
+[chapter Document Structure
+ [quickbook 1.6]
+ [id quickbook.syntax.structure]
+ [source-mode teletype]
+]
+
+[/TODO: I started to write this in the syntax chapter, but it was too
+much information, will incorporate into this file.]
+[/
+To avoid breaking old documentation we support using different versions
+of the language, compatibility is not 100% but we try to avoid
+problematic changes. This documentation applies to the current version,
+`[quickbook 1.5]`.
+
+There is also some mention of the next version `[quickbook 1.6]`. While
+quickbook allows you to use it now, it isn't recommended as it is
+currently a work in progress and subject to change.
+]
+
+[#ref-docinfo]
+[section:docinfo Document Info]
+
+Every document must begin with a Document Info section, which looks something
+like this:
+
+```
+[article The Document Title
+ [quickbook 1.5]
+ [version 1.0]
+ [id the_document_name]
+ [copyright 2000 2002 2003 Joe Blow, Jane Doe]
+ [authors [Blow, Joe] [Doe, Jane]]
+ [license The document's license]
+ [source-mode c++]
+]
+```
+
+`article` is the document type. There are several possible document types,
+most of these are based on docbook document elements. These are fully
+described in
+[@http://www.docbook.org/tdg/ DocBook: The Definitive Guide]:
+
+* [@http://www.docbook.org/tdg/en/html/book.html book]
+* [@http://www.docbook.org/tdg/en/html/article.html article]
+* [@http://www.docbook.org/tdg/en/html/chapter.html chapter]
+* [@http://www.docbook.org/tdg/en/html/part.html part]
+* [@http://www.docbook.org/tdg/en/html/appendix.html appendix]
+* [@http://www.docbook.org/tdg/en/html/preface.html preface]
+* [@http://www.docbook.org/tdg/en/html/qandadiv.html qandadiv]
+* [@http://www.docbook.org/tdg/en/html/qandaset.html qandaset]
+* [@http://www.docbook.org/tdg/en/html/reference.html reference]
+* [@http://www.docbook.org/tdg/en/html/set.html set]
+
+Boostbook also adds another document type [^[link boostbook.defining library]]
+for documenting software libraries.
+
+So the documentation for the 'foo' library might start:
+
+```
+[library Foo
+ [quickbook 1.5]
+ [id foo]
+ [version 1.0]
+]
+```
+
+[section:attributes Document Info Attributes]
+
+The document info block has a few different types of attributes.
+They are all optional.
+
+[heading Quickbook specific meta data]
+
+```
+ [quickbook 1.5]
+```
+
+The `quickbook` attribute declares the version of quickbook
+the document is written for.
+In its absence, version 1.1 is assumed. It's recommended that
+you use `[quickbook 1.5]` which is the version described here.
+
+```
+ [source-mode teletype]
+```
+
+The `source-mode` attribute sets the initial __source_mode__. If
+it is omitted, the default value of =c++= will be used.
+
+[heading Boostbook/Docbook root element attributes]
+
+```
+[id foo]
+```
+
+`id` specifies the id of the document element. If it isn't specified
+the id is automatically generated from the title. This id is also
+used to generate the nested ids.
+
+```
+[lang en]
+```
+
+`lang` specifies the document language. This is used by docbook to
+localize the documentation. Note that Boostbook doesn't have any
+localization support so if you use it to generate the reference
+documentation it will be in English regardless.
+
+It should be a language code
+drawn from ISO 639 (perhaps extended with a country code drawn from
+ISO 3166, as en-US).
+
+```
+[dirname foo]
+```
+
+`dirname` is used to specify the directory name of the library in the
+repository. This is a boostbook extension so it's only valid for
+`library` documentation blocks. It's used for some boostbook
+functionality, but for pure quickbook documentation has no practical
+effect.
+
+[heading Docbook Metadata]
+
+=version=, =copyright=, =authors=,
+=license=, =last-revision= and =bibliod= are optional information.
+
+[heading Boostbook Metadata]
+
+=purpose= and =category= are boostbook attributes which are only
+valid for =library= documents. If you use them for other document types,
+quickbook will warn about them, but still use them, generating invalid markup,
+that's just ignored by the style sheets.
+
+[endsect] [/attributes]
+
+[endsect] [/docinfo]
+
+[section:section Sections]
+
+Quickbook documents are structured using 'sections'. These are used
+to generate the table of contents, and, when generating html, to
+split the document into pages. This is optional but a good idea for
+all but the simplest of documents.
+
+A sectioned document might look like:
+
+```
+ [book Title
+ [quickbook 1.5]
+ ]
+
+ [section First Section]
+
+ [/...]
+
+ [endsect]
+
+ [section Second Section]
+
+ [/...]
+
+ [endsect]
+```
+
+Sections start with the `section` tag, and end with the `[endsect]` tag.
+(`[/...]` is a comment, [link quickbook.syntax.comments described later]).
+
+Sections can be given an optional id:
+
+```
+[section:id The Section Title]
+```
+
+`id` will be the filename of the generated section.
+If it is not present, "The Section Title" will be normalized and become the id.
+Valid characters are =a-Z=, =A-Z=, =0-9= and =_=. All non-valid characters are
+converted to underscore and all upper-case are converted to lower case.
+Thus: "The Section Title" will be normalized to "the_section_title".
+
+Sections can nest, and that results in a hierarchy in the table of contents.
+
+[endsect] [/Section]
diff --git a/tools/quickbook/doc/syntax.qbk b/tools/quickbook/doc/syntax.qbk
new file mode 100644
index 0000000000..2c3c41e465
--- /dev/null
+++ b/tools/quickbook/doc/syntax.qbk
@@ -0,0 +1,54 @@
+[/
+ Copyright 2002,2004,2006 Joel de Guzman, Eric Niebler
+ Copyright 2010-2011 Daniel James
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[chapter Syntax Summary
+ [quickbook 1.6]
+ [compatibility-mode 1.5]
+ [id quickbook.syntax]
+ [source-mode teletype]
+]
+
+A QuickBook document is composed of one or more blocks. An example of
+a block is the paragraph or a C++ code snippet. Some blocks have
+special mark-ups. Blocks, except code snippets which have their own
+grammar (C++ or Python), are composed of one or more phrases. A phrase
+can be a simple contiguous run of characters. Phrases can have special
+mark-ups. Marked up phrases can recursively contain other phrases, but
+cannot contain blocks. A terminal is a self contained block-level or
+phrase-level element that does not nest anything.
+
+Blocks, in general, are delimited by two end-of-lines (the block terminator).
+Phrases in each block cannot contain a block terminator. This way, syntax errors
+such as un-matched closing brackets do not go haywire and corrupt anything past
+a single block.
+
+[section Comments]
+
+Can be placed anywhere.
+
+```
+[/ comment (no output generated) ]
+```
+
+[/ for testing only... ]
+
+```
+[/ comments can be nested [/ some more here] ]
+```
+
+[/ for testing [/ only ] ]
+
+```
+[/ Quickbook blocks can nest inside comments. [*Comment this out too!] ]
+```
+
+[/ for testing [*only ] ]
+
+[endsect] [/Comments]
+
diff --git a/tools/quickbook/extra/katepart/install.sh b/tools/quickbook/extra/katepart/install.sh
new file mode 100644
index 0000000000..cab05d8488
--- /dev/null
+++ b/tools/quickbook/extra/katepart/install.sh
@@ -0,0 +1,24 @@
+#! /bin/bash
+
+# boost::hs installer
+#
+# Copyright 2006 Matias Capeletto
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# This script install the .xml kate syntax files in KDE
+
+echo "Installing boost::hs"
+echo "A few xml files will be copy to the place KDE store katepart sources."
+echo "Files to install"
+
+ls syntax/*.xml -1
+
+echo "Installing..."
+
+cp syntax/*.xml /usr/share/apps/katepart/syntax
+
+echo "Done!"
+echo ""
+
diff --git a/tools/quickbook/extra/katepart/katepart.qbk b/tools/quickbook/extra/katepart/katepart.qbk
new file mode 100644
index 0000000000..5af40afa78
--- /dev/null
+++ b/tools/quickbook/extra/katepart/katepart.qbk
@@ -0,0 +1,125 @@
+[/
+ Boost.hs
+
+ Copyright 2007 Matias Capeletto
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+]
+
+[section KDE Support]
+
+[heading boost::hs::quickbook]
+
+boost::hs::quickbook is a syntax highlighting designed to work with Katepart.
+It can be used in KWrite, Kate, Konqueror and KDevelop, and supports all the
+constructs of Quickbook 1.4 including tables, list, templates and macros.
+
+[variablelist
+[[.qbk loaded in a text editor][
+[$../../tools/quickbook/doc/html/images/extra/katepart/table.text.editor.png]
+]]
+[[.qbk loaded with boost::hs support][
+[$../../tools/quickbook/doc/html/images/extra/katepart/table.boost.hs.png]
+]]
+]
+
+[*html generated from this .qbk file]
+
+[table Code examples
+[[Name][Code][Description]]
+[[for loop ][` for(int k=0; k<10; k++) v+=k; ` ][Sums some numbers. ]]
+[[while loop ][` { int k; while( k < 10 ) { v+=k; k++ } } `][Same effect. ]]
+[[infinite loop][` while( true ) { v+=1; } ` ][Not a good example.]]
+]
+
+[heading Code Folding ]
+
+boost::hs goes far beyond simple coloring. One useful thing
+you can get the editor to do is to mark regions. They appear in a small grey line
+and each region can be folded or unfolded independently.
+
+[heading Auto Comment / Uncomment ]
+
+Another important feature is the possibility to auto-comment or uncomment some
+piece of code (/Tools - Comment/).
+Commented regions can be uncommented simple calling the /uncomment/ command
+while being in it.
+
+[heading Styles reference ]
+
+[table
+[[ Name ][ Style ][ Description ]]
+
+[[*plain text* ][normal black ]
+[Plain text at each level. ]]
+
+[[*formatted text* ][formatted black ]
+[ Bold, italic, underline and mixes. Teletype, replaceable, strikeout. ]]
+
+[[*structure* ][light blue ]
+[All quickbook structures characters (\[, \], \[block-type, simple
+formating boundaries, lists keywords (\*, \#) ]]
+
+[[*macros* ][red ]
+[Names in macro definitions, macros insertion if it is used the \_\_xxx\_\_
+proposed sintaxis. ]]
+
+[[*templates* ][red ]
+[Names in template definitions ]]
+
+[[*anchors* ][red ]
+[All the keywords that are used to link quickbooks together. ]]
+
+[[*comments* ][italic light gray ]
+[Inside the commentaries. ]]
+
+[[*tables* ][HTML like ]
+[Reveal the structure, bold title, higlighted HTML like columns titles. ]]
+
+[[*variable lists* ][HTML like ]
+[Reveal the structure, bold title, bold HTML like items names. ]]
+
+[[*c++ code* ][cpp Kate syntax ]
+[Code blocks and inline code. ]]
+
+[[*paths* ][green ]
+[Image, files and web paths ]]
+
+[[*IDE specific* ][dark blue ]
+[IDE commands ]]
+]
+
+[heading About boost::hs]
+
+[$../../tools/quickbook/doc/html/images/extra/katepart/boost.hs.logo.png]
+
+boost::hs::quickbook is a component of boost::hs, a syntax highlighting
+for C++, doxygen, Boost.Build jamfiles and QuickBook.
+boost::hs has his own page [@http://tinyurl.com/2l7u33 here].
+
+[note
+boost::hs::cpp support QuickBook code import comments style!
+]
+
+[heading Installing boost::hs]
+
+There exist an ongoing effort to push boost::hs upstream to the KatePart
+project. In a few months KDE may have native Quickbook support!
+For the moment you must download and install it.
+
+You can download boost::hs from
+[@http://matias.capeletto.googlepages.com/boost_hs.zip here].
+
+[note
+A copy of boost::hs::quickbook and boost::hs::cpp is available in `boost/tools/quickbook/extra/katepart`.
+]
+
+In order to install it you must copy the content in the folder
+[*katepart\/syntax\/] to the appropriate katepart syntax folder in your
+machine. In general this folder will be in
+[*\/usr\/share\/apps\/katepart\/syntax]. A bash script named ['install.sh]
+is included that copy the files to this folder.
+
+[endsect]
diff --git a/tools/quickbook/extra/katepart/syntax/boost_hs_boost.xml b/tools/quickbook/extra/katepart/syntax/boost_hs_boost.xml
new file mode 100644
index 0000000000..7c2b5fcc72
--- /dev/null
+++ b/tools/quickbook/extra/katepart/syntax/boost_hs_boost.xml
@@ -0,0 +1,3020 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE language SYSTEM "language.dtd">
+<language
+
+name="boost"
+version="0.1.0"
+kateversion="2.4"
+section="boost::hs"
+extensions="*.boost"
+mimetype="allFiles"
+author="Copyright 2006 -2007 Matias Capeletto, matias.capeletto@gmail.com"
+license="Distributed under the Boost Software License, Version 1.0.
+http://www.boost.org/LICENSE_1_0.txt"
+
+>
+
+<highlighting>
+
+
+<list name="boost.free.function">
+
+ <!-- boost.any -->
+
+ <item> any_cast </item>
+
+ <!-- boost.asign -->
+
+ <item> ptr_list_of </item>
+ <item> list_of </item>
+ <item> map_list_of </item>
+ <item> tuple_list_of </item>
+ <item> ref_list_of </item>
+ <item> cref_list_of </item>
+ <item> make_list_inserter </item>
+
+ <!-- boost.bind -->
+
+ <item> bind </item>
+ <item> mem_fn </item>
+
+ <!-- boost.conversion -->
+
+ <item> polymorphic_cast </item>
+ <item> polymorphic_downcast </item>
+ <item> lexical_cast </item>
+
+ <!-- boost.fusion -->
+
+ <item> at </item>
+ <item> value_at </item>
+ <item> has_key </item>
+ <item> at_key </item>
+ <item> value_at_key </item>
+ <item> at_c </item>
+ <item> value_at_c </item>
+
+ <item> advance_c </item>
+ <item> next </item>
+ <item> equal_to </item>
+ <item> advance </item>
+ <item> distance </item>
+ <item> deref </item>
+ <item> value_of </item>
+ <item> prior </item>
+ <item> begin </item>
+ <item> end </item>
+ <item> size </item>
+ <item> empty </item>
+ <item> front </item>
+ <item> back </item>
+
+ <item> is_sequence </item>
+ <item> is_view </item>
+ <item> value_of </item>
+ <item> tag_of </item>
+ <item> category_of </item>
+
+ <item> as_list </item>
+ <item> as_vector </item>
+ <item> as_set </item>
+ <item> as_map </item>
+
+ <item> make_list </item>
+ <item> make_cons </item>
+ <item> make_vector </item>
+ <item> make_set </item>
+ <item> make_map </item>
+
+ <item> tuple_open </item>
+ <item> tuple_close </item>
+ <item> tuple_delimiter </item>
+
+ <item> fold </item>
+ <item> accumulate </item>
+ <item> for_each </item>
+
+ <item> any </item>
+ <item> all </item>
+ <item> none </item>
+ <item> find </item>
+ <item> find_if </item>
+ <item> count </item>
+ <item> count_if </item>
+
+ <item> filter </item>
+ <item> filter_if </item>
+ <item> transform </item>
+ <item> replace </item>
+ <item> replace_if </item>
+ <item> remove </item>
+ <item> remove_if </item>
+ <item> reverse </item>
+ <item> clear </item>
+ <item> erase </item>
+ <item> erase_key </item>
+ <item> insert </item>
+ <item> insert_range </item>
+ <item> join </item>
+ <item> zip </item>
+ <item> pop_back </item>
+ <item> pop_front </item>
+ <item> push_back </item>
+ <item> push_front </item>
+
+ <item> tuple_size </item>
+ <item> tuple_element </item>
+ <item> get </item>
+ <item> tag_of </item>
+
+ <!-- boost.hash -->
+
+ <item> hash_combine </item>
+ <item> hash_range </item>
+ <item> hash_value </item>
+
+ <!-- boost.multi_index -->
+
+ <item> get </item>
+ <item> project </item>
+
+ <!-- boost.optional -->
+
+ <item> get_pointer </item>
+
+ <!-- boost.property_map -->
+
+ <item> put </item>
+
+ <!-- boost.ref -->
+
+ <item> unwrap_reference </item>
+
+ <!-- boost.test -->
+
+ <item> init_unit_test_suite </item>
+
+ <!-- boost.concepts -->
+
+ <item> distance </item>
+ <item> advance </item>
+ <item> swap </item>
+
+</list>
+
+
+
+
+<list name="boost.template.classes">
+
+ <!-- boost.any -->
+
+ <item> any </item>
+
+ <!-- boost.commpressed_pair -->
+
+ <item> compressed_pair </item>
+
+ <!-- boost.fusion -->
+
+ <item> cons </item>
+ <item> single_view </item>
+ <item> filter_view </item>
+ <item> iterator_range </item>
+ <item> joint_view </item>
+ <item> zip_view </item>
+ <item> transform_view </item>
+ <item> reverse_view </item>
+ <item> list_tie </item>
+ <item> vector_tie </item>
+
+ <!-- boost.hash -->
+
+ <item> hash </item>
+
+ <!-- boost.iterators -->
+
+ <item> counting_iterator </item>
+ <item> filter_iterator </item>
+ <item> function_output_iterator </item>
+ <item> dereferenced iterator </item>
+ <item> indirect_iterator </item>
+ <item> permutation_iterator </item>
+ <item> reverse_iterator </item>
+ <item> shared_container_iterator </item>
+ <item> transform_iterator </item>
+ <item> zip_iterator </item>
+
+ <!-- boost.iterator -->
+
+ <item> iterator_facade </item>
+ <item> iterator_adaptor </item>
+ <item> iterator_adaptor_ </item>
+
+ <!-- boost.multi_index -->
+
+ <item> nth_index </item>
+ <item> index </item>
+ <item> nth_index_iterator </item>
+ <item> nth_index_const_iterator </item>
+ <item> index_iterator </item>
+ <item> index_const_iterator </item>
+
+ <item> sequenced </item>
+ <item> ordered_unique </item>
+ <item> ordered_non_unique </item>
+ <item> hashed_unique </item>
+ <item> hashed_non_unique </item>
+ <item> identity </item>
+ <item> member </item>
+ <item> member_offset </item>
+
+ <item> const_mem_fun </item>
+ <item> mem_fun </item>
+ <item> const_mem_fun_explicit </item>
+ <item> mem_fun_explicit </item>
+
+ <item> composite_key </item>
+ <item> composite_key_result </item>
+ <item> composite_key_equal_to </item>
+ <item> composite_key_result_equal_to </item>
+ <item> composite_key_compare </item>
+ <item> composite_key_result_less </item>
+ <item> composite_key_result_greater </item>
+ <item> composite_key_hash </item>
+ <item> composite_key_result_hash </item>
+
+ <item> indexed_by </item>
+ <item> tag </item>
+
+ <!-- boost.optional -->
+
+ <item> optional </item>
+
+ <!-- boost.ref -->
+
+ <item> ref </item>
+ <item> cref </item>
+ <item> reference_wrapper </item>
+
+ <!-- boost.bimap -->
+
+ <item> set_of </item>
+ <item> multiset_of </item>
+ <item> unordered_set_of </item>
+ <item> unordered_multiset_of </item>
+ <item> list_of </item>
+ <item> vector_of </item>
+ <item> set_of_relation </item>
+ <item> multiset_of_relation </item>
+ <item> unordered_set_of_relation </item>
+ <item> unordered_multiset_of_relation </item>
+ <item> list_of_relation </item>
+ <item> vector_of_relation </item>
+
+ <!-- boost.function -->
+
+ <item> function </item>
+
+</list>
+
+
+
+<list name="boost.classes">
+
+ <!-- boost.fusion -->
+
+ <item> ignore </item>
+
+ <!-- boost.iterator -->
+
+ <item> iterator_core_access </item>
+
+ <!-- boost.test -->
+
+ <item> execution_monitor </item>
+ <item> execution_exception </item>
+ <item> execution_aborted </item>
+
+
+</list>
+
+
+<list name="boost.metaprogramming">
+
+ <!-- boost.call_traits -->
+
+ <item> call_traits </item>
+
+ <!-- boost.ConceptCheck -->
+
+ <item> function_requires </item>
+ <item> IntegerConcept </item>
+ <item> SignedIntegerConcept </item>
+ <item> UnsignedIntegerConcept </item>
+ <item> ConvertibleConcept </item>
+ <item> AssignableConcept </item>
+ <item> SGIAssignableConcept </item>
+ <item> DefaultConstructibleConcept </item>
+ <item> CopyConstructibleConcept </item>
+ <item> EqualityComparableConcept </item>
+ <item> LessThanComparableConcept </item>
+ <item> ComparableConcept </item>
+ <item> InputIteratorConcept </item>
+ <item> OutputIteratorConcept </item>
+ <item> ForwardIteratorConcept </item>
+ <item> Mutable_ForwardIteratorConcept </item>
+ <item> BidirectionalIteratorConcept </item>
+ <item> Mutable_BidirectionalIteratorConcept </item>
+ <item> RandomAccessIteratorConcept </item>
+ <item> Mutable_RandomAccessIteratorConcept </item>
+ <item> GeneratorConcept </item>
+ <item> UnaryFunctionConcept </item>
+ <item> BinaryFunctionConcept </item>
+ <item> UnaryPredicateConcept </item>
+ <item> BinaryPredicateConcept </item>
+ <item> Const_BinaryPredicateConcept </item>
+ <item> AdaptableGeneratorConcept </item>
+ <item> AdaptableUnaryFunctionConcept </item>
+ <item> AdaptableBinaryFunctionConcept </item>
+ <item> AdaptablePredicateConcept </item>
+ <item> AdaptableBinaryPredicateConcept </item>
+ <item> ContainerConcept </item>
+ <item> Mutable_ContainerConcept </item>
+ <item> ForwardContainerConcept </item>
+ <item> Mutable_ForwardContainerConcept </item>
+ <item> ReversibleContainerConcept </item>
+ <item> Mutable_ReversibleContainerConcept </item>
+ <item> RandomAccessContainerConcept </item>
+ <item> Mutable_RandomAccessContainerConcept </item>
+ <item> SequenceConcept </item>
+ <item> FrontInsertionSequenceConcept </item>
+ <item> BackInsertionSequenceConcept </item>
+ <item> AssociativeContainerConcept </item>
+ <item> UniqueAssociativeContainerConcept </item>
+ <item> MultipleAssociativeContainerConcept </item>
+ <item> SimpleAssociativeContainerConcept </item>
+ <item> PairAssociativeContainerConcept </item>
+ <item> SortedAssociativeContainerConcept </item>
+ <item> null_archetype </item>
+ <item> default_constructible_archetype </item>
+ <item> assignable_archetype </item>
+ <item> copy_constructible_archetype </item>
+ <item> equality_comparable_archetype </item>
+ <item> convertible_to_archetype </item>
+ <item> trivial_iterator_archetype </item>
+ <item> mutable_trivial_iterator_archetype </item>
+ <item> input_iterator_archetype </item>
+ <item> forward_iterator_archetype </item>
+ <item> bidirectional_iterator_archetype </item>
+ <item> random_access_iterator_archetype </item>
+ <item> unary_function_archetype </item>
+ <item> binary_function_archetype </item>
+ <item> predicate_archetype </item>
+ <item> binary_predicate_archetype </item>
+
+ <!-- boost.iterator -->
+
+ <item> ReadableIteratorConcept </item>
+ <item> WritableIteratorConcept </item>
+ <item> SwappableIteratorConcept </item>
+ <item> LvalueIteratorConcept </item>
+ <item> IncrementableIteratorConcept </item>
+ <item> SinglePassIteratorConcept </item>
+ <item> ForwardTraversalConcept </item>
+ <item> BidirectionalTraversalConcept </item>
+ <item> RandomAccessTraversalConcept </item>
+ <item> InteroperableIteratorConcept </item>
+
+ <!-- boost.enable_if -->
+
+ <item> enable_if </item>
+ <item> disable_if </item>
+ <item> lazy_enable_if </item>
+ <item> lazy_disable_if </item>
+ <item> enable_if_c </item>
+ <item> disable_if_c </item>
+ <item> lazy_enable_if_c </item>
+ <item> lazy_disable_if_c </item>
+
+ <!-- boost.iterator -->
+
+ <item> indirect_reference </item>
+ <item> pointee </item>
+
+ <!-- boost.mpl -->
+
+ <item> empty_sequence </item>
+ <item> filter_view </item>
+ <item> iterator_range </item>
+ <item> joint_view </item>
+ <item> single_view </item>
+ <item> transform_view </item>
+ <item> zip_view </item>
+
+ <item> at </item>
+ <item> at_c </item>
+ <item> back </item>
+ <item> begin </item>
+ <item> clear </item>
+ <item> empty </item>
+ <item> end </item>
+ <item> erase </item>
+ <item> erase_key </item>
+ <item> front </item>
+ <item> has_key </item>
+ <item> insert </item>
+ <item> insert_range </item>
+ <item> is_sequence </item>
+ <item> order </item>
+ <item> pop_back </item>
+ <item> pop_front </item>
+ <item> push_back </item>
+ <item> push_front </item>
+ <item> sequence_tag </item>
+ <item> size </item>
+
+ <item> advance </item>
+ <item> distance </item>
+ <item> next </item>
+ <item> prior </item>
+ <item> deref </item>
+ <item> iterator_category </item>
+
+ <item> back_inserter </item>
+ <item> front_inserter </item>
+ <item> inserter </item>
+
+ <item> fold </item>
+ <item> iter_fold </item>
+ <item> reverse_fold </item>
+ <item> reverse_iter_fold </item>
+ <item> accumulate </item>
+
+ <item> find </item>
+ <item> find_if </item>
+ <item> contains </item>
+ <item> count </item>
+ <item> count_if </item>
+ <item> lower_bound </item>
+ <item> upper_bound </item>
+ <item> min_element </item>
+ <item> max_element </item>
+ <item> equal </item>
+
+ <item> copy </item>
+ <item> copy_if </item>
+ <item> transform </item>
+ <item> replace </item>
+ <item> replace_if </item>
+ <item> remove </item>
+ <item> remove_if </item>
+ <item> unique </item>
+ <item> partition </item>
+ <item> stable_partition </item>
+ <item> sort </item>
+ <item> reverse </item>
+ <item> reverse_copy </item>
+ <item> reverse_copy_if </item>
+ <item> reverse_transform </item>
+ <item> reverse_replace </item>
+ <item> reverse_replace_if </item>
+ <item> reverse_remove </item>
+ <item> reverse_remove_if </item>
+ <item> reverse_unique </item>
+ <item> reverse_partition </item>
+ <item> reverse_stable_partition </item>
+
+ <item> if_ </item>
+ <item> if_c </item>
+ <item> eval_if </item>
+ <item> eval_if_c </item>
+
+ <item> apply </item>
+ <item> apply_wrap </item>
+ <item> unpack_args </item>
+
+ <item> _ </item>
+ <item> _1 </item>
+ <item> _2 </item>
+ <item> _3 </item>
+ <item> _4 </item>
+ <item> _5 </item>
+
+ <item> bind </item>
+ <item> quote </item>
+ <item> arg </item>
+ <item> protect </item>
+
+ <item> plus </item>
+ <item> minus </item>
+ <item> times </item>
+ <item> divides </item>
+ <item> modulus </item>
+ <item> negate </item>
+
+ <item> less </item>
+ <item> less_equal </item>
+ <item> greater </item>
+ <item> greater_equal </item>
+ <item> equal_to </item>
+ <item> not_equal_to </item>
+
+ <item> and_ </item>
+ <item> or_ </item>
+ <item> not_ </item>
+
+ <item> bitand_ </item>
+ <item> bitor_ </item>
+ <item> bitxor_ </item>
+ <item> shift_left </item>
+ <item> shift_right </item>
+
+ <item> identity </item>
+ <item> always </item>
+ <item> inherit </item>
+ <item> inherit_linearly </item>
+ <item> numeric_cast </item>
+ <item> min </item>
+ <item> max </item>
+ <item> sizeof_ </item>
+
+ <item> bool_ </item>
+ <item> int_ </item>
+ <item> long_ </item>
+ <item> size_t </item>
+ <item> integral_c </item>
+
+ <item> pair </item>
+ <item> empty_base </item>
+ <item> void_ </item>
+
+ <!-- boost.operators -->
+
+ <item> less_than_comparable </item>
+ <item> less_than_comparable1 </item>
+ <item> less_than_comparable2 </item>
+
+ <item> equality_comparable </item>
+ <item> equality_comparable1 </item>
+
+ <item> equality_comparable2 </item>
+
+ <item> addable </item>
+ <item> addable1 </item>
+
+ <item> addable2 </item>
+
+ <item> subtractable </item>
+ <item> subtractable1 </item>
+
+ <item> subtractable2 </item>
+
+ <item> subtractable2_left </item>
+
+ <item> multipliable </item>
+ <item> multipliable1 </item>
+ <item> multipliable2 </item>
+
+ <item> dividable </item>
+ <item> dividable1 </item>
+ <item> dividable2 </item>
+
+ <item> dividable2_left </item>
+
+ <item> modable </item>
+ <item> modable1 </item>
+ <item> modable2 </item>
+
+ <item> modable2_left </item>
+
+ <item> orable </item>
+ <item> orable1 </item>
+ <item> orable2 </item>
+
+ <item> andable </item>
+ <item> andable1 </item>
+ <item> andable2 </item>
+
+ <item> xorable </item>
+ <item> xorable1 </item>
+ <item> xorable2 </item>
+
+ <item> incrementable </item>
+ <item> decrementable </item>
+
+ <item> left_shiftable </item>
+ <item> left_shiftable1 </item>
+ <item> left_shiftable2 </item>
+
+ <item> right_shiftable </item>
+ <item> right_shiftable1 </item>
+ <item> right_shiftable2 </item>
+
+ <item> equivalent </item>
+ <item> equivalent1 </item>
+ <item> equivalent2 </item>
+
+ <item> partially_ordered </item>
+ <item> partially_ordered1 </item>
+ <item> partially_ordered2 </item>
+
+ <item> totally_ordered </item>
+ <item> totally_ordered1 </item>
+ <item> totally_ordered2 </item>
+
+ <item> additive </item>
+ <item> additive1 </item>
+ <item> additive2 </item>
+
+ <item> multiplicative </item>
+ <item> multiplicative1 </item>
+ <item> multiplicative2 </item>
+
+ <item> integer_multiplicative </item>
+ <item> integer_multiplicative1 </item>
+ <item> integer_multiplicative2 </item>
+
+ <item> arithmetic </item>
+ <item> arithmetic1 </item>
+ <item> arithmetic2 </item>
+
+ <item> integer_arithmetic </item>
+ <item> integer_arithmetic1 </item>
+ <item> integer_arithmetic2 </item>
+
+ <item> bitwise </item>
+ <item> bitwise1 </item>
+ <item> bitwise2 </item>
+
+ <item> unit_steppable </item>
+
+ <item> shiftable </item>
+ <item> shiftable1 </item>
+ <item> shiftable2 </item>
+
+ <item> ring_operators </item>
+ <item> ring_operators1 </item>
+ <item> ring_operators2 </item>
+
+ <item> ordered_ring_operators </item>
+ <item> ordered_ring_operators1 </item>
+ <item> ordered_ring_operators2 </item>
+
+ <item> field_operators </item>
+ <item> field_operators1 </item>
+ <item> field_operators2 </item>
+
+ <item> ordered_field_operators </item>
+ <item> ordered_field_operators1 </item>
+
+ <item> ordered_field_operators2 </item>
+
+ <item> euclidian_ring_operators </item>
+ <item> euclidian_ring_operators1 </item>
+ <item> euclidian_ring_operators2 </item>
+
+ <item> ordered_euclidian_ring_operators </item>
+ <item> ordered_euclidian_ring_operators1 </item>
+ <item> ordered_euclidian_ring_operators2 </item>
+
+ <item> operators </item>
+ <item> operators2 </item>
+
+ <item> dereferenceable </item>
+ <item> indexable </item>
+
+ <item> input_iteratable </item>
+ <item> output_iteratable </item>
+ <item> forward_iteratable </item>
+ <item> bidirectional_iteratable </item>
+ <item> random_access_iteratable </item>
+
+ <item> input_iterator_helper </item>
+ <item> output_iterator_helper </item>
+ <item> forward_iterator_helper </item>
+ <item> bidirectional_iterator_helper </item>
+ <item> random_access_iterator_helper </item>
+
+ <!-- boost.property_map -->
+
+ <item> property_traits </item>
+
+
+ <!-- boost.ref -->
+
+ <item> is_reference_wrapper </item>
+
+ <!-- boost.type_traits -->
+
+ <item> add_const </item>
+ <item> add_cv </item>
+ <item> add_pointer </item>
+ <item> add_reference </item>
+ <item> add_volatile </item>
+ <item> aligned_storage </item>
+ <item> alignment_of </item>
+ <item> extent </item>
+ <item> function_traits </item>
+ <item> has_nothrow_assign </item>
+ <item> has_nothrow_constructor </item>
+ <item> has_nothrow_copy </item>
+ <item> has_trivial_assign </item>
+ <item> has_trivial_constructor </item>
+ <item> has_trivial_copy </item>
+ <item> has_trivial_destructor </item>
+ <item> has_virtual_destructor </item>
+ <item> integral_constant </item>
+ <item> is_abstract </item>
+ <item> is_arithmetic </item>
+ <item> is_array </item>
+ <item> is_base_of </item>
+ <item> is_class </item>
+ <item> is_compound </item>
+ <item> is_const </item>
+ <item> is_convertible </item>
+ <item> is_empty </item>
+ <item> is_enum </item>
+ <item> is_floating_point </item>
+ <item> is_function </item>
+ <item> is_fundamental </item>
+ <item> is_integral </item>
+ <item> is_member_function_pointer </item>
+ <item> is_member_object_pointer </item>
+ <item> is_member_pointer </item>
+ <item> is_object </item>
+ <item> is_pod </item>
+ <item> is_pointer </item>
+ <item> is_polymorphic </item>
+ <item> is_same </item>
+ <item> is_scalar </item>
+ <item> is_stateless </item>
+ <item> is_reference </item>
+ <item> is_union </item>
+ <item> is_void </item>
+ <item> is_volatile </item>
+ <item> rank </item>
+ <item> remove_all_extents </item>
+ <item> remove_const </item>
+ <item> remove_cv </item>
+ <item> remove_extent </item>
+ <item> remove_pointer </item>
+ <item> remove_reference </item>
+ <item> remove_volatile </item>
+ <item> type_with_alignment </item>
+
+
+
+ <!-- boost.utility (TODO) -->
+
+ <item> base_from_member </item>
+ <item> checked_delete </item>
+ <item> checked_array_delete </item>
+ <item> next </item>
+ <item> prior </item>
+ <item> noncopyable </item>
+ <item> addressof </item>
+ <item> result_of </item>
+
+</list>
+
+
+
+
+<list name="boost.exception">
+
+ <!-- boost.any -->
+
+ <item> bad_any_cast </item>
+
+ <!-- boost.assign -->
+
+ <item> assignment_exception </item>
+
+</list>
+
+
+
+<list name="boost.container">
+
+ <!-- boost.array -->
+
+ <item> array </item>
+
+ <!-- boost.dynamic_bitset -->
+
+ <item> dynamic_bitset </item>
+
+ <!-- boost.fusion -->
+
+ <item> tuple </item>
+
+ <!-- boost.mpl -->
+
+ <item> range_c </item>
+ <item> vector_c </item>
+ <item> list_c </item>
+ <item> set_c </item>
+
+ <!-- boost.multi_index -->
+
+ <item> multi_index_container </item>
+
+ <!-- boost.bimap -->
+
+ <item> bimap </item>
+
+ <!-- boost.property_map -->
+
+ <item> identity_property_map </item>
+ <item> iterator_property_map </item>
+ <item> associative_property_map </item>
+ <item> const_associative_property_map </item>
+ <item> vector_property_map </item>
+
+</list>
+
+
+
+
+<list name="boost.macro">
+
+ <!-- boost.ConceptCheck -->
+
+ <item> BOOST_CLASS_REQUIRE </item>
+
+ <!-- boost.fusion -->
+
+ <item> FUSION_MAX_VECTOR_SIZE </item>
+ <item> FUSION_MAX_LIST_SIZE </item>
+ <item> FUSION_MAX_SET_SIZE </item>
+ <item> FUSION_MAX_MAP_SIZE </item>
+
+ <!-- boost.mpl -->
+
+ <item> BOOST_MPL_ASSERT </item>
+ <item> BOOST_MPL_ASSERT_MSG </item>
+ <item> BOOST_MPL_ASSERT_NOT </item>
+ <item> BOOST_MPL_ASSERT_RELATION </item>
+
+ <item> BOOST_MPL_HAS_XXX_TRAIT_DEF </item>
+ <item> BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF </item>
+
+ <item> BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS </item>
+ <item> BOOST_MPL_CFG_NO_HAS_XXX </item>
+ <item> BOOST_MPL_LIMIT_METAFUNCTION_ARITY </item>
+ <item> BOOST_MPL_LIMIT_VECTOR_SIZE </item>
+ <item> BOOST_MPL_LIMIT_LIST_SIZE </item>
+ <item> BOOST_MPL_LIMIT_SET_SIZE </item>
+ <item> BOOST_MPL_LIMIT_MAP_SIZE </item>
+ <item> BOOST_MPL_LIMIT_UNROLLING </item>
+
+ <item> BOOST_MPL_AUX_LAMBDA_SUPPORT </item>
+
+ <!-- boost.multi_index -->
+
+ <item> BOOST_MULTI_INDEX_MEMBER </item>
+ <item> BOOST_MULTI_INDEX_CONST_MEM_FUN </item>
+ <item> BOOST_MULTI_INDEX_MEM_FUN </item>
+
+ <!-- boost.static_assert -->
+
+ <item> BOOST_STATIC_ASSERT </item>
+
+ <!-- boost.test -->
+
+ <item> BOOST_TEST_CATCH_SYSTEM_ERRORS </item>
+ <item> BOOST_PRG_MON_CONFIRM </item>
+ <item> BOOST_TEST_DONT_PRINT_LOG_VALUE </item>
+
+ <item> BOOST_CHECK </item>
+ <item> BOOST_CHECK_PRED </item>
+ <item> BOOST_CHECK_MSG </item>
+ <item> BOOST_CHECK_EQUAL </item>
+ <item> BOOST_CHECK_CLOSE </item>
+ <item> BOOST_CHECK_SMALL </item>
+ <item> BOOST_CHECK_BITWISE_EQUAL </item>
+
+ <item> BOOST_WARN </item>
+ <item> BOOST_WARN_PRED </item>
+ <item> BOOST_WARN_MSG </item>
+ <item> BOOST_WARN_EQUAL </item>
+ <item> BOOST_WARN_CLOSE </item>
+ <item> BOOST_WARN_SMALL </item>
+ <item> BOOST_WARN_BITWISE_EQUAL </item>
+
+ <item> BOOST_REQUIRE </item>
+ <item> BOOST_REQUIRE_PRED </item>
+ <item> BOOST_REQUIRE_MSG </item>
+ <item> BOOST_REQUIRE_EQUAL </item>
+ <item> BOOST_REQUIRE_CLOSE </item>
+ <item> BOOST_REQUIRE_SMALL </item>
+ <item> BOOST_REQUIRE_BITWISE_EQUAL </item>
+
+ <item> BOOST_PASS </item>
+ <item> BOOST_PASS_PRED </item>
+ <item> BOOST_PASS_MSG </item>
+ <item> BOOST_PASS_EQUAL </item>
+ <item> BOOST_PASS_CLOSE </item>
+ <item> BOOST_PASS_SMALL </item>
+ <item> BOOST_PASS_BITWISE_EQUAL </item>
+
+ <item> BOOST_MSG_ONLY </item>
+ <item> BOOST_SET_CHECKPOINT </item>
+ <item> BOOST_CHECK_PRED_WITH_ARGS </item>
+ <item> BOOST_CHECK_EQUAL_COLL </item>
+
+ <item> BOOST_ERROR </item>
+ <item> BOOST_FAIL </item>
+
+</list>
+
+
+<list name="boost.fusion.result_of">
+
+ <item> advance_c </item>
+ <item> next </item>
+ <item> equal_to </item>
+ <item> advance </item>
+ <item> distance </item>
+ <item> deref </item>
+ <item> value_of </item>
+ <item> prior </item>
+ <item> begin </item>
+ <item> end </item>
+ <item> size </item>
+ <item> empty </item>
+ <item> front </item>
+ <item> back </item>
+
+</list>
+
+
+
+
+<list name="boost.concepts.member.functions">
+
+ <!-- boost.iterator -->
+
+ <item> dereference </item>
+ <item> equal </item>
+ <item> increment </item>
+ <item> decrement </item>
+ <item> advance </item>
+ <item> distance_to </item>
+ <item> begin </item>
+ <item> end </item>
+ <item> size </item>
+ <item> max_size </item>
+ <item> empty </item>
+ <item> swap </item>
+ <item> rbegin </item>
+ <item> rend </item>
+ <item> front </item>
+ <item> insert </item>
+ <item> erase </item>
+ <item> clear </item>
+ <item> resize </item>
+ <item> push_front </item>
+ <item> pop_front </item>
+ <item> push_back </item>
+ <item> pop_back </item>
+ <item> erase </item>
+ <item> clear </item>
+ <item> find </item>
+ <item> count </item>
+ <item> equal_range </item>
+ <item> key_comp </item>
+ <item> lower_bound </item>
+ <item> upper_bound </item>
+ <item> equal_range </item>
+ <item> get_allocator </item>
+ <item> hash_function </item>
+ <item> key_eq </item>
+ <item> bucket_count </item>
+ <item> max_bucket_count </item>
+ <item> bucket_size </item>
+ <item> bucket </item>
+ <item> load_factor </item>
+ <item> max_load_factor </item>
+ <item> at </item>
+
+</list>
+
+
+
+
+<list name="boost.concepts.free.functions">
+
+ <!-- boost.test -->
+
+ <item> cpp_main </item>
+ <item> test_main </item>
+
+</list>
+
+
+
+
+<list name="boost.tags">
+
+ <!-- boost.iterator -->
+
+ <item> readable_iterator_t </item>
+ <item> writable_iterator_t </item>
+ <item> readable_writable_iterator_t </item>
+ <item> readable_lvalue_iterator_t </item>
+ <item> writable_lvalue_iterator_t </item>
+
+ <!-- boost.property_map -->
+
+ <item> readable_property_map_tag </item>
+ <item> writable_property_map_tag </item>
+ <item> read_write_property_map_tag </item>
+ <item> lvalue_property_map_tag </item>
+
+</list>
+
+
+
+
+<list name="boost.member.functions">
+
+ <item> base </item>
+ <item> base_reference </item>
+
+</list>
+
+<list name="boost.constants">
+
+ <!-- boost.test -->
+ <item> exit_success </item>
+ <item> exit_failure </item>
+ <item> exit_exception_failure </item>
+
+</list>
+
+<list name="boost.concepts.member.typedef">
+
+ <item> value_type </item>
+ <item> iterator </item>
+ <item> const_iterator </item>
+ <item> reference </item>
+ <item> const_reference </item>
+ <item> pointer </item>
+ <item> difference_type </item>
+ <item> size_type </item>
+ <item> reverse_iterator </item>
+ <item> const_reverse_iterator </item>
+ <item> key_type </item>
+ <item> data_type </item>
+ <item> hasher </item>
+ <item> key_equal </item>
+ <item> local_iterator </item>
+ <item> const_local_iterator </item>
+ <item> key_compare </item>
+ <item> value_compare </item>
+ <item> iterator_category </item>
+ <item> value_type </item>
+ <item> difference_type </item>
+ <item> pointer </item>
+ <item> reference </item>
+
+</list>
+
+<list name="boost.namespaces" >
+
+ <item> std </item>
+ <item> boost </item>
+ <item> assign </item>
+ <item> bimaps </item>
+ <item> call_traits </item>
+ <item> concept_check </item>
+ <item> conversion </item>
+ <item> date_time </item>
+ <item> dynamic_bitset </item>
+ <item> enable_if </item>
+ <item> filesystem </item>
+ <item> format </item>
+ <item> hash </item>
+ <item> graph </item>
+ <item> integer </item>
+ <item> in_place_factory </item>
+ <item> io_state_saver </item>
+ <item> iostream </item>
+ <item> lambda </item>
+ <item> math </item>
+ <item> minmax </item>
+ <item> mpl </item>
+ <item> multi_array </item>
+ <item> multi_index </item>
+ <item> numeric </item>
+ <item> operators </item>
+ <item> parameter </item>
+ <item> pointer_container </item>
+ <item> pool </item>
+ <item> preprocesor </item>
+ <item> program_options </item>
+ <item> property_map </item>
+ <item> python </item>
+ <item> random </item>
+ <item> regex </item>
+ <item> serialization </item>
+ <item> signals </item>
+ <item> smart_ptr </item>
+ <item> static_assert </item>
+ <item> spirit </item>
+ <item> string_algo </item>
+ <item> test </item>
+ <item> thread </item>
+ <item> timer </item>
+ <item> tokenizer </item>
+ <item> tribool </item>
+ <item> tuples </item>
+ <item> type_traits </item>
+ <item> uBLAS </item>
+ <item> utility </item>
+ <item> value_initialized </item>
+ <item> wave </item>
+ <item> fusion </item>
+
+</list>
+
+
+<!-- TODO LIST BEGIN
+
+<list name="boost.date_time">
+
+ <item> day_functor </item>
+ <item> month_functor </item>
+ <item> week_functor </item>
+ <item> year_functor </item>
+ <item> c_local_adjustor </item>
+ <item> c_time </item>
+ <item> constrained_value </item>
+ <item> date </item>
+ <item> day_clock </item>
+ <item> weekdays::Sunday </item>
+ <item> weekdays::Monday </item>
+ <item> weekdays::Tuesday </item>
+ <item> weekdays::Wednesday </item>
+ <item> weekdays::Thursday </item>
+ <item> weekdays::Friday </item>
+ <item> weekdays::Saturday </item>
+ <item> weekdays </item>
+ <item> months_of_year::Jan </item>
+ <item> months_of_year::Feb </item>
+ <item> months_of_year::Mar </item>
+ <item> months_of_year::Apr </item>
+ <item> months_of_year::May </item>
+ <item> months_of_year::Jun </item>
+ <item> months_of_year::Jul </item>
+ <item> months_of_year::Aug </item>
+ <item> months_of_year::Sep </item>
+ <item> months_of_year::Oct </item>
+ <item> months_of_year::Nov </item>
+ <item> months_of_year::Dec </item>
+ <item> months_of_year </item>
+ <item> NotAMonth </item>
+ <item> NumMonths </item>
+ <item> date_duration </item>
+ <item> duration_traits_long </item>
+ <item> duration_traits_adapted </item>
+ <item> weeks_duration </item>
+ <item> months_duration </item>
+ <item> years_duration </item>
+ <item> date_facet </item>
+ <item> date_input_facet </item>
+ <item> simple_format </item>
+ <item> month_formatter </item>
+ <item> ymd_formatter </item>
+ <item> date_formatter </item>
+ <item> ostream_month_formatter </item>
+ <item> ostream_weekday_formatter </item>
+ <item> ostream_ymd_formatter </item>
+ <item> ostream_date_formatter </item>
+ <item> date_generator_formatter </item>
+ <item> date_generator_parser </item>
+ <item> year_based_generator </item>
+ <item> partial_date </item>
+ <item> nth_kday_of_month </item>
+ <item> first_kday_of_month </item>
+ <item> last_kday_of_month </item>
+ <item> first_kday_after </item>
+ <item> first_kday_before </item>
+ <item> days_until_weekday </item>
+ <item> days_before_weekday </item>
+ <item> next_weekday </item>
+ <item> previous_weekday </item>
+ <item> date_itr_base </item>
+ <item> date_itr </item>
+ <item> date_resolutions </item>
+ <item> date_resolutions::day </item>
+ <item> date_resolutions::week </item>
+ <item> date_resolutions::months </item>
+ <item> date_resolutions::year </item>
+ <item> date_resolutions::decade </item>
+ <item> date_resolutions::century </item>
+ <item> date_names_put </item>
+ <item> all_date_names_put </item>
+ <item> dst_calculator </item>
+ <item> dst_calc_engine </item>
+ <item> us_dst_rules </item>
+ <item> null_dst_rules </item>
+ <item> dst_day_calc_rule </item>
+ <item> day_calc_dst_rule </item>
+ <item> time_from_ftime </item>
+ <item> format_date_parser </item>
+ <item> gregorian_calendar_base </item>
+ <item> iso_format_base </item>
+ <item> iso_format </item>
+ <item> iso_extended_format </item>
+ <item> utc_adjustment </item>
+ <item> dynamic_local_time_adjustor </item>
+ <item> class static_local_time_adjustor </item>
+ <item> local_adjustor </item>
+ <item> us_dst_trait </item>
+ <item> eu_dst_trait </item>
+ <item> uk_dst_trait </item>
+ <item> acst_dst_trait </item>
+ <item> microsec_clock </item>
+ <item> month_format_spec </item>
+ <item> month_format_spec::month_as_integer </item>
+ <item> month_format_spec::month_as_short_string </item>
+ <item> month_format_spec::month_as_long_string </item>
+ <item> ymd_order_spec </item>
+ <item> period </item>
+ <item> period_formatter </item>
+ <item> period_parser </item>
+ <item> special_values </item>
+ <item> special_values::not_a_date_time </item>
+ <item> special_values::neg_infin </item>
+ <item> special_values::pos_infin </item>
+ <item> special_values::min_date_time </item>
+ <item> special_values::max_date_time </item>
+ <item> special_values::not_special </item>
+ <item> special_values_formatter </item>
+ <item> special_values_parser </item>
+ <item> convert_string_type </item>
+ <item> gather_month_strings </item>
+ <item> gather_weekday_strings </item>
+ <item> base_time </item>
+ <item> second_clock </item>
+ <item> time_resolutions </item>
+ <item> time_resolutions::sec </item>
+ <item> time_resolutions::tenth </item>
+ <item> time_resolutions::hundreth </item>
+ <item> time_resolutions::milli </item>
+ <item> time_resolutions::ten_thousandth </item>
+ <item> time_resolutions::micro </item>
+ <item> time_resolutions::nano </item>
+ <item> dst_flags </item>
+ <item> dst_flags::not_dst </item>
+ <item> dst_flags::is_dst </item>
+ <item> dst_flags::calculate </item>
+ <item> time_duration </item>
+ <item> subsecond_duration </item>
+ <item> time_formats </item>
+ <item> time_facet </item>
+ <item> time_input_facet </item>
+ <item> ostream_time_duration_formatter </item>
+ <item> ostream_time_formatter </item>
+ <item> ostream_time_period_formatter </item>
+ <item> time_itr </item>
+ <item> parse_delimited_time_duration </item>
+ <item> parse_delimited_time </item>
+ <item> parse_undelimited_time_duration </item>
+ <item> parse_iso_time </item>
+ <item> time_resolution_traits </item>
+ <item> counted_time_rep </item>
+ <item> counted_time_system </item>
+ <item> split_timedate_system </item>
+ <item> time_zone_base </item>
+ <item> dst_adjustment_offsets </item>
+ <item> time_zone_names_base </item>
+ <item> time_zone_names </item>
+ <item> year_month_day_base </item>
+
+ <item> gregorian_calendar </item>
+ <item> fancy_date_rep </item>
+ <item> bad_day_of_month </item>
+ <item> greg_day </item>
+ <item> greg_day_policies </item>
+ <item> greg_day_rep </item>
+ <item> bad_day_of_year </item>
+ <item> greg_day_of_year_policies </item>
+ <item> greg_day_of_year_rep </item>
+ <item> date_duration_rep </item>
+ <item> date_duration </item>
+ <item> greg_durations_config </item>
+ <item> months </item>
+ <item> years </item>
+ <item> weeks </item>
+ <item> bad_month </item>
+ <item> greg_month </item>
+ <item> greg_month_policies </item>
+ <item> greg_month_rep </item>
+ <item> bad_weekday </item>
+ <item> greg_weekday </item>
+ <item> greg_weekday_policies </item>
+ <item> greg_weekday_rep </item>
+ <item> bad_year </item>
+ <item> greg_year </item>
+ <item> greg_year_policies </item>
+ <item> greg_year_rep </item>
+ <item> greg_year_month_day </item>
+ <item> date_period </item>
+ <item> day_clock </item>
+ <item> date_iterator </item>
+ <item> day_iterator </item>
+ <item> week_iterator </item>
+ <item> month_iterator </item>
+ <item> year_iterator </item>
+ <item> date_from_iso_string </item>
+ <item> from_streamdate_period_from_string </item>
+ <item> date_period_from_wstring </item>
+
+ <item> ptime </item>
+ <item> time_duration </item>
+ <item> simple_time_rep </item>
+ <item> posix_time_system_config </item>
+ <item> millisec_posix_time_system_config </item>
+ <item> hours </item>
+ <item> minutes </item>
+ <item> seconds </item>
+ <item> millisec </item>
+ <item> milliseconds </item>
+ <item> microsec </item>
+ <item> microseconds </item>
+ <item> nanosec </item>
+ <item> nanoseconds </item>
+ <item> posix_time_system </item>
+ <item> time_iterator </item>
+ <item> second_clock </item>
+ <item> microsec_clock </item>
+ <item> no_dst </item>
+ <item> us_dst </item>
+ <item> duration_from_string </item>
+ <item> time_from_string </item>
+ <item> time_period </item>
+
+ <item> to_tm </item>
+ <item> custom_time_zone </item>
+ <item> dst_calc_rule_ptr </item>
+ <item> dst_calc_rule </item>
+ <item> partial_date_dst_rule </item>
+ <item> first_last_dst_rule </item>
+ <item> last_last_dst_rule </item>
+ <item> nth_last_dst_rule </item>
+ <item> nth_kday_dst_rule </item>
+ <item> nth_day_of_the_week_in_month_dst_rule </item>
+ <item> ambiguous_result </item>
+ <item> time_label_invalid </item>
+ <item> dst_not_valid </item>
+ <item> local_date_time_base </item>
+ <item> local_date_time </item>
+ <item> BOOST_SERIALIZATION_SPLIT_FREE </item>
+ <item> local_time_period </item>
+ <item> local_time_iterator </item>
+ <item> local_sec_clock </item>
+ <item> local_microsec_clock </item>
+ <item> time_zone_ptr </item>
+
+</list>
+
+<list name="boost.filesystem">
+
+ <item> path </item>
+ <item> portable_posix_name </item>
+ <item> windows_name </item>
+ <item> portable_name </item>
+ <item> portable_directory_name </item>
+ <item> portable_file_name </item>
+ <item> no_check </item>
+ <item> native </item>
+
+ <item> directory_iterator </item>
+ <item> exists </item>
+ <item> symbolic_link_exists </item>
+ <item> is_directory </item>
+ <item> is_empty </item>
+ <item> equivalent </item>
+ <item> file_size </item>
+ <item> last_write_time </item>
+ <item> create_directory </item>
+ <item> remove </item>
+ <item> remove_all </item>
+ <item> rename </item>
+ <item> copy_file </item>
+ <item> initial_path </item>
+ <item> current_path </item>
+ <item> complete </item>
+ <item> system_complete </item>
+
+ <item> error_code </item>
+ <item> error_code::no_error </item>
+ <item> error_code::system_error </item>
+ <item> error_code::other_error </item>
+ <item> error_code::security_error </item>
+ <item> error_code::read_only_error </item>
+ <item> error_code::io_error </item>
+ <item> error_code::path_error </item>
+ <item> error_code::not_found_error </item>
+ <item> error_code::not_directory_error </item>
+ <item> error_code::busy_error </item>
+ <item> error_code::already_exists_error </item>
+ <item> error_code::not_empty_error </item>
+ <item> error_code::error_code::is_directory_error </item>
+ <item> error_code::out_of_space_error </item>
+ <item> error_code::out_of_memory_error </item>
+ <item> error_code::out_of_resource_error </item>
+ <item> filesystem_error </item>
+
+ <item> create_directories </item>
+ <item> extension </item>
+ <item> basename </item>
+ <item> change_extension </item>
+
+</list>
+
+<list name="boost.format">
+
+ <item> basic_format </item>
+ <item> format </item>
+ <item> wformat </item>
+
+</list>
+
+<list name="boost.function">
+
+ <item> bad_function_call </item>
+ <item> function_base </item>
+ <item> functionN </item>
+ <item> function </item>
+ <item> function_equal </item>
+
+</list>
+
+<list name="boost.graph">
+
+</list>
+
+<list name="boost.integer">
+
+ <item> integer_traits </item>
+
+ <item> int_fast_t </item>
+ <item> int_t </item>
+ <item> uint_t </item>
+ <item> int_max_value_t </item>
+ <item> int_min_value_t </item>
+ <item> uint_value_t </item>
+
+ <item> high_bit_mask_t </item>
+ <item> low_bits_mask_t </item>
+
+ <item> static_log2 </item>
+
+ <item> static_signed_min </item>
+ <item> static_signed_max </item>
+ <item> static_unsigned_min </item>
+ <item> static_unsigned_max </item>
+
+</list>
+
+<list name="boost.interval">
+
+ <item> interval_policies </item>
+ <item> interval </item>
+ <item> lower </item>
+ <item> upper </item>
+ <item> width </item>
+ <item> median </item>
+ <item> norm </item>
+ <item> singleton </item>
+ <item> in_zero </item>
+ <item> subset </item>
+ <item> proper_subset </item>
+ <item> overlap </item>
+ <item> intersection </item>
+ <item> hull </item>
+ <item> bisect </item>
+ <item> division_part1 </item>
+ <item> division_part2 </item>
+ <item> multiplicative_inverse </item>
+
+</list>
+
+<list name="boost.in_place_factory">
+
+ <item> in_place_factory_base </item>
+ <item> in_place_factory </item>
+ <item> in_place </item>
+ <item> typed_in_place_factory_base </item>
+ <item> typed_in_place_factory </item>
+
+</list>
+
+<list name="boost.io_state_saver">
+
+ <item> ios_flags_saver </item>
+ <item> ios_precision_saver </item>
+ <item> ios_width_saver </item>
+ <item> ios_base_all_saver </item>
+ <item> basic_ios_iostate_saver </item>
+ <item> basic_ios_exception_saver </item>
+ <item> basic_ios_tie_saver </item>
+ <item> basic_ios_rdbuf_saver </item>
+ <item> basic_ios_fill_saver </item>
+ <item> basic_ios_locale_saver </item>
+ <item> basic_ios_all_saver </item>
+ <item> ios_iostate_saver </item>
+ <item> wios_iostate_saver </item>
+ <item> ios_exception_saver </item>
+ <item> wios_exception_saver </item>
+ <item> ios_tie_saver </item>
+ <item> wios_tie_saver </item>
+ <item> ios_rdbuf_saver </item>
+ <item> wios_rdbuf_saver </item>
+ <item> ios_fill_saver </item>
+ <item> wios_fill_saver </item>
+ <item> ios_locale_saver </item>
+ <item> wios_locale_saver </item>
+ <item> ios_all_saver </item>
+ <item> wios_all_saver </item>
+ <item> ios_iword_saver </item>
+ <item> ios_pword_saver </item>
+ <item> ios_all_word_saver </item>
+
+</list>
+
+<list name="boost.iostream">
+
+ <item> aggregate_filter </item>
+ <item> array </item>
+ <item> array_sink </item>
+ <item> array_source </item>
+ <item> back_insert_device </item>
+ <item> basic_array </item>
+ <item> basic_array_sink </item>
+ <item> basic_array_source </item>
+ <item> basic_bzip2_compressor </item>
+ <item> basic_bzip2_decompressor </item>
+ <item> basic_counter </item>
+ <item> basic_file </item>
+ <item> basic_file_sink </item>
+ <item> basic_file_source </item>
+ <item> basic_gzip_compressor </item>
+ <item> basic_gzip_decompressor </item>
+ <item> basic_line_filter </item>
+ <item> basic_null_device </item>
+ <item> basic_null_sink </item>
+ <item> basic_null_source </item>
+ <item> basic_regex_filter </item>
+ <item> basic_stdio_filter </item>
+ <item> basic_zlib_compressor </item>
+ <item> basic_zlib_decompressor </item>
+ <item> bzip2_compressor </item>
+ <item> bzip2_decompressor </item>
+ <item> bzip2_error </item>
+ <item> bzip2_params </item>
+ <item> category_of </item>
+ <item> chain </item>
+ <item> char_traits </item>
+ <item> char_type_of </item>
+ <item> code_converter </item>
+ <item> combination </item>
+ <item> composite </item>
+ <item> counter </item>
+ <item> device </item>
+ <item> dual_use_filter </item>
+ <item> dual_use_wfilter </item>
+ <item> file </item>
+ <item> file_descriptor </item>
+ <item> file_descriptor_sink </item>
+ <item> file_descriptor_source </item>
+ <item> file_sink </item>
+ <item> file_source </item>
+ <item> filtering_stream </item>
+ <item> filtering_streambuf </item>
+ <item> filter </item>
+ <item> gzip_compressor </item>
+ <item> gzip_decompressor </item>
+ <item> gzip_error </item>
+ <item> gzip_params </item>
+ <item> input_filter </item>
+ <item> input_wfilter </item>
+ <item> inverse </item>
+ <item> line_filter </item>
+ <item> mapped_file </item>
+ <item> mapped_file_sink </item>
+ <item> mapped_file_source </item>
+ <item> mode_of </item>
+ <item> multichar_dual_use_filter </item>
+ <item> multichar_dual_use_wfilter </item>
+ <item> multichar_filter </item>
+ <item> multichar_input_filter </item>
+ <item> multichar_input_wfilter </item>
+ <item> multichar_output_filter </item>
+ <item> multichar_output_wfilter </item>
+ <item> multichar_wfilter </item>
+ <item> newline_filter </item>
+ <item> null_sink </item>
+ <item> null_source </item>
+ <item> output_filter </item>
+ <item> output_wfilter </item>
+ <item> regex_filter </item>
+ <item> restriction </item>
+ <item> seekable_filter </item>
+ <item> seekable_wfilter </item>
+ <item> sink </item>
+ <item> source </item>
+ <item> stdio_filter </item>
+ <item> stream </item>
+ <item> stream_buffer </item>
+ <item> symmetric_filter </item>
+ <item> tee_device </item>
+ <item> tee_filter </item>
+ <item> warray </item>
+ <item> warray_sink </item>
+ <item> warray_source </item>
+ <item> wchain </item>
+ <item> wcounter </item>
+ <item> wdevice </item>
+ <item> wfile </item>
+ <item> wfile_sink </item>
+ <item> wfile_source </item>
+ <item> wfilter </item>
+ <item> wline_filter </item>
+ <item> wnull_sink </item>
+ <item> wnull_source </item>
+ <item> wregex_filter </item>
+ <item> wsink </item>
+ <item> wsource </item>
+ <item> wstdio_filter </item>
+ <item> zlib_compressor </item>
+ <item> zlib_decompressor </item>
+ <item> zlib_error </item>
+ <item> zlib_params </item>
+
+ <item> back_inserter </item>
+ <item> close </item>
+ <item> combine </item>
+ <item> compose </item>
+ <item> copy </item>
+ <item> flush </item>
+ <item> get </item>
+ <item> imbue </item>
+ <item> invert </item>
+ <item> offset_to_position </item>
+ <item> optimal_buffer_size </item>
+ <item> position_to_offset </item>
+ <item> put </item>
+ <item> putback </item>
+ <item> read </item>
+ <item> restrict </item>
+ <item> seek </item>
+ <item> tee </item>
+ <item> test_filter_pair </item>
+ <item> test_input_filter </item>
+ <item> test_output_filter </item>
+ <item> write </item>
+
+ <item> BOOST_IOS </item>
+ <item> BOOST_IOSTREAMS_BASIC_ISTREAM </item>
+ <item> BOOST_IOSTREAMS_BASIC_IOS </item>
+ <item> BOOST_IOSTREAMS_BASIC_IOSTREAM </item>
+ <item> BOOST_IOSTREAMS_BASIC_OSTREAM </item>
+ <item> BOOST_IOSTREAMS_BASIC_STREAMBUF </item>
+ <item> BOOST_IOSTREAMS_CHAR_TRAITS </item>
+ <item> BOOST_IOSTREAMS_COMPONENT </item>
+ <item> BOOST_IOSTREAMS_COMPONENT_TYPE </item>
+ <item> BOOST_IOSTREAMS_DEFAULT_DEVICE_BUFFER_SIZE </item>
+ <item> BOOST_IOSTREAMS_DEFAULT_FILTER_BUFFER_SIZE </item>
+ <item> BOOST_IOSTREAMS_DEFAULT_PBACK_BUFFER_SIZE </item>
+ <item> BOOST_IOSTREAMS_FAILURE </item>
+ <item> BOOST_IOSTREAMS_PIPABLE </item>
+ <item> BOOST_IOSTREAMS_PUBSEEKOFF </item>
+ <item> BOOST_IOSTREAMS_PUBSEEKPOS </item>
+ <item> BOOST_IOSTREAMS_PUBSYNC </item>
+
+</list>
+
+<list name="boost.lambda">
+
+ <item> _1 </item>
+ <item> _2 </item>
+ <item> _3 </item>
+
+ <item> placeholder1_type </item>
+ <item> placeholder2_type </item>
+ <item> placeholder3_type </item>
+
+ <item> bind </item>
+
+ <item> ret </item>
+ <item> var </item>
+ <item> constant </item>
+ <item> var_type </item>
+ <item> constant_type </item>
+
+ <item> if_then </item>
+ <item> if_then_else </item>
+ <item> if_then_else_return </item>
+ <item> while_loop </item>
+ <item> do_while_loop </item>
+ <item> for_loop </item>
+ <item> switch_statement </item>
+ <item> case_statement </item>
+ <item> default_statement </item>
+
+ <item> if_ </item>
+ <item> else_ </item>
+ <item> while_ </item>
+ <item> do_ </item>
+ <item> for_ </item>
+
+ <item> try_catch </item>
+ <item> catch_exception </item>
+ <item> catch_all </item>
+
+ <item> constructor </item>
+ <item> destructor </item>
+ <item> destructor </item>
+ <item> new_ptr </item>
+ <item> new_array </item>
+ <item> delete_ptr </item>
+ <item> delete_array </item>
+
+ <item> unlambda </item>
+ <item> protect </item>
+
+ <item> make_const </item>
+ <item> const_parameters </item>
+ <item> break_const </item>
+
+ <item> ll_static_cast </item>
+ <item> ll_dynamic_cast </item>
+ <item> ll_const_cast </item>
+ <item> ll_reinterpret_cast </item>
+
+ <item> ll_sizeof </item>
+ <item> ll_typeid </item>
+
+ <item> call_begin </item>
+ <item> call_end </item>
+
+</list>
+
+<list name="boost.math">
+
+ <item> quaternion </item>
+ <item> octonion </item>
+
+ <item> gcd </item>
+ <item> lcm </item>
+ <item> static_gcd </item>
+ <item> static_lcm </item>
+ <item> gcd_evaluator </item>
+ <item> lcm_evaluator </item>
+
+ <item> acosh </item>
+ <item> asinh </item>
+ <item> atanh </item>
+ <item> sinc </item>
+ <item> sinhc </item>
+
+</list>
+
+<list name="boost.minmax">
+
+ <item> minmax </item>
+ <item> minmax_element </item>
+ <item> first_min_element </item>
+ <item> last_min_element </item>
+ <item> first_max_element </item>
+ <item> last_max_element </item>
+ <item> first_min_first_max_element </item>
+ <item> first_min_last_max_element </item>
+ <item> last_min_first_max_element </item>
+ <item> last_min_last_max_element </item>
+
+</list>
+
+<list name="boost.multi_array">
+
+ <item> multi_array_types </item>
+ <item> multi_array_types::index </item>
+ <item> multi_array_types::size_type </item>
+ <item> multi_array_types::difference_type </item>
+ <item> multi_array_types::index_range </item>
+ <item> multi_array_types::extent_range </item>
+ <item> multi_array_types::index_gen </item>
+ <item> multi_array_types::extent_gen </item>
+
+ <item> multi_array </item>
+ <item> multi_array_ref </item>
+ <item> const_multi_array_ref </item>
+
+ <item> extents </item>
+ <item> indices </item>
+
+ <item> subarray_gen </item>
+ <item> const_subarray_gen </item>
+ <item> array_view_gen </item>
+ <item> const_array_view_gen </item>
+
+ <item> c_storage_order </item>
+ <item> fortran_storage_order </item>
+ <item> general_storage_order </item>
+
+</list>
+
+<list name="boost.numeric">
+
+ <item> converter </item>
+ <item> bounds </item>
+
+ <item> int_float_mixture_enum </item>
+
+ <item> int_float_mixture_enum::integral_to_integral </item>
+ <item> int_float_mixture_enum::integral_to_float </item>
+ <item> int_float_mixture_enum::float_to_integral </item>
+ <item> int_float_mixture_enum::float_to_float </item>
+
+ <item> sign_mixture_enum </item>
+ <item> sign_mixture_enum::unsigned_to_unsigned </item>
+ <item> sign_mixture_enum::signed_to_signed </item>
+ <item> sign_mixture_enum::signed_to_unsigned </item>
+ <item> sign_mixture_enum::unsigned_to_signed </item>
+
+ <item> udt_builtin_mixture_enum </item>
+ <item> udt_builtin_mixture_enum::builtin_to_builtin </item>
+ <item> udt_builtin_mixture_enum::builtin_to_udt </item>
+ <item> udt_builtin_mixture_enum::udt_to_builtin </item>
+ <item> udt_builtin_mixture_enum::udt_to_udt </item>
+
+ <item> int_float_mixture </item>
+ <item> sign_mixture </item>
+ <item> udt_builtin_mixture </item>
+ <item> is_subranged </item>
+
+ <item> conversion_traits </item>
+
+ <item> range_check_result </item>
+ <item> range_check_result::cInRange </item>
+ <item> range_check_result::cNegOverflow </item>
+ <item> range_check_result::cPosOverflow </item>
+
+ <item> def_overflow_handler </item>
+ <item> silent_overflow_handler </item>
+
+ <item> bad_numeric_cast </item>
+ <item> negative_overflow </item>
+ <item> positive_overflow </item>
+
+ <item> Trunc </item>
+ <item> RoundEven </item>
+ <item> Ceil </item>
+ <item> Floor </item>
+
+ <item> raw_numeric_converter </item>
+
+ <item> UseInternalRangeChecker </item>
+
+ <item> numeric_cast </item>
+
+</list>
+
+<list name="boost.parameter">
+
+ <item> BOOST_PARAMETER_KEYWORD </item>
+ <item> BOOST_PARAMETER_FUN </item>
+ <item> BOOST_PARAMETER_MATCH </item>
+
+</list>
+
+<list name="boost.pointer_container">
+
+ <item> new_clone </item>
+ <item> delete_clone </item>
+ <item> allocate_clone </item>
+ <item> deallocate_clone </item>
+ <item> heap_clone_allocator </item>
+ <item> view_clone_allocator </item>
+
+ <item> ptr_sequence_adapter </item>
+ <item> ptr_set_adapter </item>
+ <item> ptr_multiset_adapter </item>
+ <item> ptr_map_adapter </item>
+ <item> ptr_multimap_adapter </item>
+
+ <item> ptr_vector </item>
+ <item> ptr_deque </item>
+ <item> ptr_list </item>
+ <item> ptr_array </item>
+
+ <item> ptr_set </item>
+ <item> ptr_multiset </item>
+ <item> ptr_map </item>
+ <item> ptr_multimap </item>
+
+ <item> nullable </item>
+ <item> bad_ptr_container_operation </item>
+ <item> bad_index </item>
+ <item> bad_pointer </item>
+
+</list>
+
+<list name="boost.pool">
+
+ <item> pool </item>
+ <item> object_pool </item>
+ <item> singleton_pool </item>
+ <item> pool_allocator </item>
+
+</list>
+
+<list name="boost.preprocesor">
+
+ <item> BOOST_PP_ADD </item>
+ <item> BOOST_PP_ADD_D </item>
+ <item> BOOST_PP_AND </item>
+ <item> BOOST_PP_APPLY </item>
+ <item> BOOST_PP_ARRAY_DATA </item>
+ <item> BOOST_PP_ARRAY_ELEM </item>
+ <item> BOOST_PP_ARRAY_INSERT </item>
+ <item> BOOST_PP_ARRAY_INSERT_D </item>
+ <item> BOOST_PP_ARRAY_POP_BACK </item>
+ <item> BOOST_PP_ARRAY_POP_BACK_Z </item>
+ <item> BOOST_PP_ARRAY_POP_FRONT </item>
+ <item> BOOST_PP_ARRAY_POP_FRONT_Z </item>
+ <item> BOOST_PP_ARRAY_PUSH_BACK </item>
+ <item> BOOST_PP_ARRAY_PUSH_FRONT </item>
+ <item> BOOST_PP_ARRAY_REMOVE </item>
+ <item> BOOST_PP_ARRAY_REMOVE_D </item>
+ <item> BOOST_PP_ARRAY_REPLACE </item>
+ <item> BOOST_PP_ARRAY_REPLACE_D </item>
+ <item> BOOST_PP_ARRAY_REVERSE </item>
+ <item> BOOST_PP_ARRAY_SIZE </item>
+ <item> BOOST_PP_ASSERT </item>
+ <item> BOOST_PP_ASSERT_MSG </item>
+ <item> BOOST_PP_ASSIGN_SLOT </item>
+ <item> BOOST_PP_BITAND </item>
+ <item> BOOST_PP_BITNOR </item>
+ <item> BOOST_PP_BITOR </item>
+ <item> BOOST_PP_BITXOR </item>
+ <item> BOOST_PP_BOOL </item>
+ <item> BOOST_PP_CAT </item>
+ <item> BOOST_PP_COMMA </item>
+ <item> BOOST_PP_COMMA_IF </item>
+ <item> BOOST_PP_COMPL </item>
+ <item> BOOST_PP_CONFIG_EXTENDED_LINE_INFO </item>
+ <item> BOOST_PP_DEC </item>
+ <item> BOOST_PP_DEDUCE_D </item>
+ <item> BOOST_PP_DEDUCE_R </item>
+ <item> BOOST_PP_DEDUCE_Z </item>
+ <item> BOOST_PP_DIV </item>
+ <item> BOOST_PP_DIV_D </item>
+ <item> BOOST_PP_EMPTY </item>
+ <item> BOOST_PP_ENUM </item>
+ <item> BOOST_PP_ENUM_BINARY_PARAMS </item>
+ <item> BOOST_PP_ENUM_BINARY_PARAMS_Z </item>
+ <item> BOOST_PP_ENUM_PARAMS </item>
+ <item> BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT </item>
+ <item> BOOST_PP_ENUM_PARAMS_WITH_DEFAULTS </item>
+ <item> BOOST_PP_ENUM_PARAMS_Z </item>
+ <item> BOOST_PP_ENUM_SHIFTED </item>
+ <item> BOOST_PP_ENUM_SHIFTED_PARAMS </item>
+ <item> BOOST_PP_ENUM_SHIFTED_PARAMS_Z </item>
+ <item> BOOST_PP_ENUM_TRAILING </item>
+ <item> BOOST_PP_ENUM_TRAILING_BINARY_PARAMS </item>
+ <item> BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z </item>
+ <item> BOOST_PP_ENUM_TRAILING_PARAMS </item>
+ <item> BOOST_PP_ENUM_TRAILING_PARAMS_Z </item>
+ <item> BOOST_PP_EQUAL </item>
+ <item> BOOST_PP_EQUAL_D </item>
+ <item> BOOST_PP_EXPAND </item>
+ <item> BOOST_PP_EXPR_IF </item>
+ <item> BOOST_PP_EXPR_IIF </item>
+ <item> BOOST_PP_FILENAME_x </item>
+ <item> BOOST_PP_FOR </item>
+ <item> BOOST_PP_FRAME_FINISH </item>
+ <item> BOOST_PP_FRAME_FLAGS </item>
+ <item> BOOST_PP_FRAME_ITERATION </item>
+ <item> BOOST_PP_FRAME_START </item>
+ <item> BOOST_PP_GREATER </item>
+ <item> BOOST_PP_GREATER_D </item>
+ <item> BOOST_PP_GREATER_EQUAL </item>
+ <item> BOOST_PP_GREATER_EQUAL_D </item>
+ <item> BOOST_PP_IDENTITY </item>
+ <item> BOOST_PP_IF </item>
+ <item> BOOST_PP_IIF </item>
+ <item> BOOST_PP_INC </item>
+ <item> BOOST_PP_INCLUDE_SELF </item>
+ <item> BOOST_PP_INDIRECT_SELF </item>
+ <item> BOOST_PP_INTERCEPT </item>
+ <item> BOOST_PP_IS_ITERATING </item>
+ <item> BOOST_PP_IS_SELFISH </item>
+ <item> BOOST_PP_ITERATE </item>
+ <item> BOOST_PP_ITERATION </item>
+ <item> BOOST_PP_ITERATION_DEPTH </item>
+ <item> BOOST_PP_ITERATION_FINISH </item>
+ <item> BOOST_PP_ITERATION_FLAGS </item>
+ <item> BOOST_PP_ITERATION_LIMITS </item>
+ <item> BOOST_PP_ITERATION_START </item>
+ <item> BOOST_PP_LESS </item>
+ <item> BOOST_PP_LESS_D </item>
+ <item> BOOST_PP_LESS_EQUAL </item>
+ <item> BOOST_PP_LESS_EQUAL_D </item>
+ <item> BOOST_PP_LIMIT_DIM </item>
+ <item> BOOST_PP_LIMIT_FOR </item>
+ <item> BOOST_PP_LIMIT_ITERATION </item>
+ <item> BOOST_PP_LIMIT_ITERATION_DIM </item>
+ <item> BOOST_PP_LIMIT_MAG </item>
+ <item> BOOST_PP_LIMIT_REPEAT </item>
+ <item> BOOST_PP_LIMIT_SEQ </item>
+ <item> BOOST_PP_LIMIT_SLOT_COUNT </item>
+ <item> BOOST_PP_LIMIT_SLOT_SIG </item>
+ <item> BOOST_PP_LIMIT_TUPLE </item>
+ <item> BOOST_PP_LIMIT_WHILE </item>
+ <item> BOOST_PP_LINE </item>
+ <item> BOOST_PP_LIST_APPEND </item>
+ <item> BOOST_PP_LIST_APPEND_D </item>
+ <item> BOOST_PP_LIST_AT </item>
+ <item> BOOST_PP_LIST_AT_D </item>
+ <item> BOOST_PP_LIST_CAT </item>
+ <item> BOOST_PP_LIST_CAT_D </item>
+ <item> BOOST_PP_LIST_CONS </item>
+ <item> BOOST_PP_LIST_ENUM </item>
+ <item> BOOST_PP_LIST_ENUM_R </item>
+ <item> BOOST_PP_LIST_FILTER </item>
+ <item> BOOST_PP_LIST_FILTER_D </item>
+ <item> BOOST_PP_LIST_FIRST </item>
+ <item> BOOST_PP_LIST_FIRST_N </item>
+ <item> BOOST_PP_LIST_FIRST_N_D </item>
+ <item> BOOST_PP_LIST_FOLD_LEFT </item>
+ <item> BOOST_PP_LIST_FOLD_LEFT_2ND </item>
+ <item> BOOST_PP_LIST_FOLD_LEFT_2ND_D </item>
+ <item> BOOST_PP_LIST_FOLD_LEFT_D </item>
+ <item> BOOST_PP_LIST_FOLD_RIGHT </item>
+ <item> BOOST_PP_LIST_FOLD_RIGHT_2ND </item>
+ <item> BOOST_PP_LIST_FOLD_RIGHT_2ND_D </item>
+ <item> BOOST_PP_LIST_FOLD_RIGHT_D </item>
+ <item> BOOST_PP_LIST_FOR_EACH </item>
+ <item> BOOST_PP_LIST_FOR_EACH_I </item>
+ <item> BOOST_PP_LIST_FOR_EACH_I_R </item>
+ <item> BOOST_PP_LIST_FOR_EACH_PRODUCT </item>
+ <item> BOOST_PP_LIST_FOR_EACH_PRODUCT_R </item>
+ <item> BOOST_PP_LIST_FOR_EACH_R </item>
+ <item> BOOST_PP_LIST_IS_CONS </item>
+ <item> BOOST_PP_LIST_IS_NIL </item>
+ <item> BOOST_PP_LIST_NIL </item>
+ <item> BOOST_PP_LIST_REST </item>
+ <item> BOOST_PP_LIST_REST_N </item>
+ <item> BOOST_PP_LIST_REST_N_D </item>
+ <item> BOOST_PP_LIST_REVERSE </item>
+ <item> BOOST_PP_LIST_REVERSE_D </item>
+ <item> BOOST_PP_LIST_SIZE </item>
+ <item> BOOST_PP_LIST_SIZE_D </item>
+ <item> BOOST_PP_LIST_TO_TUPLE </item>
+ <item> BOOST_PP_LIST_TO_TUPLE_R </item>
+ <item> BOOST_PP_LIST_TRANSFORM </item>
+ <item> BOOST_PP_LIST_TRANSFORM_D </item>
+ <item> BOOST_PP_LOCAL_ITERATE </item>
+ <item> BOOST_PP_LOCAL_LIMITS </item>
+ <item> BOOST_PP_LOCAL_MACRO </item>
+ <item> BOOST_PP_LPAREN </item>
+ <item> BOOST_PP_LPAREN_IF </item>
+ <item> BOOST_PP_MAX </item>
+ <item> BOOST_PP_MAX_D </item>
+ <item> BOOST_PP_MIN </item>
+ <item> BOOST_PP_MIN_D </item>
+ <item> BOOST_PP_MOD </item>
+ <item> BOOST_PP_MOD_D </item>
+ <item> BOOST_PP_MUL </item>
+ <item> BOOST_PP_MUL_D </item>
+ <item> BOOST_PP_NIL </item>
+ <item> BOOST_PP_NOR </item>
+ <item> BOOST_PP_NOT </item>
+ <item> BOOST_PP_NOT_EQUAL </item>
+ <item> BOOST_PP_NOT_EQUAL_D </item>
+ <item> BOOST_PP_OR </item>
+ <item> BOOST_PP_RELATIVE_FINISH </item>
+ <item> BOOST_PP_RELATIVE_FLAGS </item>
+ <item> BOOST_PP_RELATIVE_ITERATION </item>
+ <item> BOOST_PP_RELATIVE_START </item>
+ <item> BOOST_PP_REPEAT </item>
+ <item> BOOST_PP_REPEAT_1ST </item>
+ <item> BOOST_PP_REPEAT_2ND </item>
+ <item> BOOST_PP_REPEAT_3RD </item>
+ <item> BOOST_PP_REPEAT_FROM_TO </item>
+ <item> BOOST_PP_REPEAT_FROM_TO_1ST </item>
+ <item> BOOST_PP_REPEAT_FROM_TO_2ND </item>
+ <item> BOOST_PP_REPEAT_FROM_TO_3RD </item>
+ <item> BOOST_PP_REPEAT_FROM_TO_D </item>
+ <item> BOOST_PP_RPAREN </item>
+ <item> BOOST_PP_RPAREN_IF </item>
+ <item> BOOST_PP_SEQ_CAT </item>
+ <item> BOOST_PP_SEQ_CAT_S </item>
+ <item> BOOST_PP_SEQ_ELEM </item>
+ <item> BOOST_PP_SEQ_ENUM </item>
+ <item> BOOST_PP_SEQ_FILTER </item>
+ <item> BOOST_PP_SEQ_FILTER_S </item>
+ <item> BOOST_PP_SEQ_FIRST_N </item>
+ <item> BOOST_PP_SEQ_FOLD_LEFT </item>
+ <item> BOOST_PP_SEQ_FOLD_RIGHT </item>
+ <item> BOOST_PP_SEQ_FOR_EACH </item>
+ <item> BOOST_PP_SEQ_FOR_EACH_I </item>
+ <item> BOOST_PP_SEQ_FOR_EACH_I_R </item>
+ <item> BOOST_PP_SEQ_FOR_EACH_PRODUCT </item>
+ <item> BOOST_PP_SEQ_FOR_EACH_PRODUCT_R </item>
+ <item> BOOST_PP_SEQ_FOR_EACH_R </item>
+ <item> BOOST_PP_SEQ_HEAD </item>
+ <item> BOOST_PP_SEQ_INSERT </item>
+ <item> BOOST_PP_SEQ_NIL </item>
+ <item> BOOST_PP_SEQ_POP_BACK </item>
+ <item> BOOST_PP_SEQ_POP_FRONT </item>
+ <item> BOOST_PP_SEQ_PUSH_BACK </item>
+ <item> BOOST_PP_SEQ_PUSH_FRONT </item>
+ <item> BOOST_PP_SEQ_REMOVE </item>
+ <item> BOOST_PP_SEQ_REPLACE </item>
+ <item> BOOST_PP_SEQ_REST_N </item>
+ <item> BOOST_PP_SEQ_REVERSE </item>
+ <item> BOOST_PP_SEQ_REVERSE_S </item>
+ <item> BOOST_PP_SEQ_SIZE </item>
+ <item> BOOST_PP_SEQ_SUBSEQ </item>
+ <item> BOOST_PP_SEQ_TAIL </item>
+ <item> BOOST_PP_SEQ_TO_ARRAY </item>
+ <item> BOOST_PP_SEQ_TO_TUPLE </item>
+ <item> BOOST_PP_SEQ_TRANSFORM </item>
+ <item> BOOST_PP_SEQ_TRANSFORM_S </item>
+ <item> BOOST_PP_SLOT </item>
+ <item> BOOST_PP_STRINGIZE </item>
+ <item> BOOST_PP_SUB </item>
+ <item> BOOST_PP_SUB_D </item>
+ <item> BOOST_PP_TUPLE_EAT </item>
+ <item> BOOST_PP_TUPLE_ELEM </item>
+ <item> BOOST_PP_TUPLE_REM </item>
+ <item> BOOST_PP_TUPLE_REM_CTOR </item>
+ <item> BOOST_PP_TUPLE_REVERSE </item>
+ <item> BOOST_PP_TUPLE_TO_LIST </item>
+ <item> BOOST_PP_TUPLE_TO_SEQ </item>
+ <item> BOOST_PP_VALUE </item>
+ <item> BOOST_PP_WHILE </item>
+ <item> BOOST_PP_WSTRINGIZE </item>
+ <item> BOOST_PP_XOR </item>
+
+</list>
+
+
+<list name="boost.program_options">
+
+ <item> environment_iterator </item>
+ <item> eof_iterator </item>
+
+ <item> error </item>
+ <item> invalid_syntax </item>
+ <item> unknown_option </item>
+ <item> ambiguous_option </item>
+ <item> multiple_values </item>
+ <item> multiple_occurrences </item>
+ <item> validation_error </item>
+ <item> invalid_option_value </item>
+ <item> too_many_positional_options_error </item>
+ <item> too_few_positional_options_error </item>
+ <item> invalid_command_line_syntax </item>
+ <item> invalid_command_line_style </item>
+
+ <item> basic_option </item>
+ <item> option </item>
+ <item> woption </item>
+
+ <item> option_description </item>
+ <item> options_description_easy_init </item>
+ <item> options_description </item>
+ <item> duplicate_option_error </item>
+
+ <item> basic_parsed_options </item>
+ <item> basic_command_line_parser </item>
+ <item> parsed_options </item>
+ <item> wparsed_options </item>
+ <item> ext_parser </item>
+ <item> command_line_parser </item>
+ <item> wcommand_line_parser </item>
+ <item> parse_command_line </item>
+ <item> parse_config_file </item>
+ <item> collect_unrecognized </item>
+ <item> parse_environment </item>
+
+ <item> positional_options_description </item>
+
+ <item> value_semantic </item>
+ <item> value_semantic_codecvt_helper </item>
+ <item> untyped_value </item>
+ <item> typed_value </item>
+ <item> value </item>
+ <item> wvalue </item>
+ <item> bool_switch </item>
+
+ <item> variable_value </item>
+ <item> abstract_variables_map </item>
+ <item> variables_map </item>
+ <item> store </item>
+ <item> notify </item>
+
+ <item> BOOST_PROGRAM_OPTIONS_VERSION </item>
+
+</list>
+
+<list name="boost.python">
+
+</list>
+
+<list name="boost.random">
+
+</list>
+
+<list name="boost.range">
+
+ <item> range_value </item>
+ <item> range_iterator </item>
+ <item> range_const_iterator </item>
+ <item> range_difference </item>
+ <item> range_size </item>
+ <item> range_reverse_iterator </item>
+ <item> range_const_reverse_iterator </item>
+ <item> range_result_iterator </item>
+ <item> range_reverse_result_iterator </item>
+ <item> begin </item>
+ <item> end </item>
+ <item> empty </item>
+ <item> size </item>
+ <item> rbegin </item>
+ <item> rend </item>
+ <item> const_begin </item>
+ <item> const_end </item>
+ <item> const_rbegin </item>
+ <item> const_rend </item>
+ <item> iterator_range </item>
+ <item> sub_range </item>
+
+</list>
+
+<list name="boost.rational">
+
+ <item> rational </item>
+ <item> rational_cast </item>
+ <item> numerator </item>
+ <item> denominator </item>
+
+</list>
+
+<list name="boost.regex">
+
+</list>
+
+<list name="boost.serialization">
+
+ <item> text_oarchive </item>
+ <item> text_iarchive </item>
+ <item> text_woarchive </item>
+ <item> text_wiarchive </item>
+ <item> binary_oarchive </item>
+ <item> binary_iarchive </item>
+ <item> xml_oarchive </item>
+ <item> xml_iarchive </item>
+ <item> xml_woarchive </item>
+ <item> xml_wiarchive </item>
+ <item> common_iarchive </item>
+
+ <item> archive_flags </item>
+ <item> archive_flags::no_header </item>
+ <item> archive_flags::no_codecvt </item>
+ <item> archive_flags::no_xml_tag_checking </item>
+
+ <item> access </item>
+
+ <item> serialize </item>
+ <item> load </item>
+ <item> save </item>
+
+ <item> base_object </item>
+ <item> split_member </item>
+ <item> split_free </item>
+ <item> load_construct_data </item>
+ <item> save_construct_data </item>
+ <item> register_type </item>
+ <item> void_cast_register </item>
+
+ <item> version_type </item>
+ <item> object_id_type </item>
+ <item> object_id_reference_type </item>
+ <item> class_id_type </item>
+ <item> class_id_optional_type </item>
+ <item> class_id_reference_type </item>
+ <item> tracking_type </item>
+ <item> classname_type </item>
+
+ <item> BOOST_SERIALIZATION_SPLIT_MEMBER </item>
+ <item> BOOST_SERIALIZATION_SPLIT_FREE </item>
+ <item> BOOST_CLASS_EXPORT_GUID </item>
+ <item> BOOST_CLASS_EXPORT </item>
+ <item> BOOST_CLASS_TRACKING </item>
+ <item> BOOST_CLASS_IMPLEMENTATION </item>
+
+</list>
+
+<list name="boost.signals">
+
+ <item> signal </item>
+ <item> connect_position </item>
+ <item> connect_position::at_front </item>
+ <item> connect_position::at_back </item>
+ <item> slot </item>
+ <item> trackable </item>
+ <item> connection </item>
+ <item> scoped_connection </item>
+ <item> visit_each </item>
+ <item> last_value </item>
+ <item> swap </item>
+
+</list>
+
+
+<list name="boost.smart_ptr">
+
+ <item> scoped_ptr </item>
+ <item> scoped_array </item>
+ <item> swap </item>
+
+ <item> weak_ptr </item>
+ <item> make_shared </item>
+
+ <item> shared_ptr_traits </item>
+ <item> static_cast_tag </item>
+ <item> struct const_cast_tag </item>
+ <item> struct dynamic_cast_tag </item>
+ <item> struct polymorphic_cast_tag </item>
+ <item> sp_enable_shared_from_this </item>
+ <item> shared_ptr </item>
+ <item> static_pointer_cast </item>
+ <item> const_pointer_cast </item>
+ <item> dynamic_pointer_cast </item>
+ <item> shared_static_cast </item>
+ <item> shared_dynamic_cast </item>
+ <item> shared_polymorphic_cast </item>
+ <item> shared_polymorphic_downcast </item>
+ <item> get_pointer </item>
+ <item> get_deleter </item>
+
+ <item> shared_array </item>
+
+ <item> intrusive_ptr </item>
+ <item> intrusive_ptr_add_ref </item>
+ <item> intrusive_ptr_release </item>
+
+</list>
+
+<list name="boost.spirit">
+
+</list>
+
+<list name="boost.string_algo">
+
+ <item> to_lower_copy </item>
+ <item> to_lower </item>
+ <item> to_upper_copy </item>
+ <item> to_upper </item>
+ <item> is_classified </item>
+ <item> is_space </item>
+ <item> is_alnum </item>
+ <item> is_alpha </item>
+ <item> is_cntrl </item>
+ <item> is_digit </item>
+ <item> is_graph </item>
+ <item> is_lower </item>
+ <item> is_print </item>
+ <item> is_punct </item>
+ <item> is_upper </item>
+ <item> is_xdigit </item>
+ <item> is_any_of </item>
+ <item> is_from_range</item>
+ <item> is_equal </item>
+
+ <item> FormatterConcept </item>
+ <item> token_compress_mode_type </item>
+
+ <item> erase_range_copy </item>
+ <item> erase_range </item>
+ <item> erase_first_copy </item>
+ <item> erase_first </item>
+ <item> ierase_first_copy </item>
+ <item> ierase_first </item>
+ <item> erase_last_copy </item>
+ <item> erase_last </item>
+ <item> ierase_last_copy </item>
+ <item> ierase_last </item>
+ <item> erase_nth_copy </item>
+ <item> erase_nth </item>
+ <item> ierase_nth_copy </item>
+ <item> ierase_nth </item>
+ <item> erase_all_copy </item>
+ <item> erase_all </item>
+ <item> ierase_all_copy </item>
+ <item> ierase_all </item>
+ <item> erase_head_copy </item>
+ <item> erase_head </item>
+ <item> erase_tail_copy </item>
+ <item> erase_tail </item>
+ <item> find </item>
+ <item> find_first </item>
+ <item> ifind_first </item>
+ <item> find_last </item>
+ <item> ifind_last </item>
+ <item> find_nth </item>
+ <item> ifind_nth </item>
+ <item> find_head </item>
+ <item> find_tail </item>
+ <item> find_token </item>
+ <item> find_format_copy </item>
+ <item> find_format </item>
+ <item> find_format_all_copy </item>
+ <item> find_format_all </item>
+ <item> regex_finder </item>
+ <item> regex_formatter </item>
+ <item> find_iterator </item>
+ <item> split_iterator </item>
+ <item> make_find_iterator </item>
+ <item> make_split_iterator </item>
+ <item> first_finder </item>
+ <item> last_finder </item>
+ <item> nth_finder </item>
+ <item> head_finder </item>
+ <item> tail_finder </item>
+ <item> token_finder </item>
+ <item> range_finder </item>
+ <item> const_formatter </item>
+ <item> identity_formatter </item>
+ <item> empty_formatter </item>
+ <item> starts_with </item>
+ <item> istarts_with </item>
+ <item> ends_with </item>
+ <item> iends_with </item>
+ <item> contains </item>
+ <item> icontains </item>
+ <item> equals </item>
+ <item> iequals </item>
+ <item> all </item>
+ <item> find_regex </item>
+ <item> replace_regex_copy </item>
+ <item> replace_regex </item>
+ <item> replace_all_regex_copy </item>
+ <item> replace_all_regex </item>
+ <item> erase_regex_copy </item>
+ <item> erase_regex </item>
+ <item> erase_all_regex_copy </item>
+ <item> erase_all_regex </item>
+ <item> find_all_regex </item>
+ <item> split_regex </item>
+ <item> regex_finder </item>
+ <item> regex_formatter </item>
+ <item> replace_range_copy </item>
+ <item> replace_range </item>
+ <item> replace_first_copy </item>
+ <item> replace_first </item>
+ <item> ireplace_first_copy </item>
+ <item> ireplace_first </item>
+ <item> replace_last_copy </item>
+ <item> replace_last </item>
+ <item> ireplace_last_copy </item>
+ <item> ireplace_last </item>
+ <item> replace_nth_copy </item>
+ <item> replace_nth </item>
+ <item> ireplace_nth_copy </item>
+ <item> ireplace_nth </item>
+ <item> replace_all_copy </item>
+ <item> replace_all </item>
+ <item> ireplace_all_copy </item>
+ <item> ireplace_all </item>
+ <item> replace_head_copy </item>
+ <item> replace_head </item>
+ <item> replace_tail_copy </item>
+ <item> replace_tail </item>
+
+ <item> has_native_replace </item>
+ <item> has_stable_iterators </item>
+ <item> has_const_time_insert </item>
+ <item> has_const_time_erase </item>
+
+ <item> find_all </item>
+ <item> ifind_all </item>
+ <item> split </item>
+ <item> trim_left_copy_if </item>
+ <item> trim_left_copy </item>
+ <item> trim_left_if </item>
+ <item> trim_left </item>
+ <item> trim_right_copy_if </item>
+ <item> trim_right_copy </item>
+ <item> trim_right_if </item>
+ <item> trim_right </item>
+ <item> trim_copy_if </item>
+ <item> trim_copy </item>
+ <item> trim_if </item>
+ <item> trim </item>
+
+</list>
+
+<list name="boost.thread">
+
+ <item> barrier </item>
+ <item> condition </item>
+ <item> lock_error </item>
+ <item> thread_resource_error </item>
+ <item> mutex </item>
+ <item> try_mutex </item>
+ <item> timed_mutex </item>
+ <item> BOOST_ONCE_INIT </item>
+ <item> call_once </item>
+ <item> recursive_mutex </item>
+ <item> recursive_try_mutex </item>
+ <item> recursive_timed_mutex </item>
+ <item> thread </item>
+ <item> thread_group </item>
+ <item> thread_specific_ptr </item>
+ <item> xtime_clock_types </item>
+ <item> xtime </item>
+ <item> xtime_get </item>
+
+</list>
+
+<list name="boost.timer">
+
+ <item> timer </item>
+ <item> progress_timer </item>
+ <item> progress_display </item>
+
+</list>
+
+<list name="boost.tokenizer">
+
+ <item> tokenizer </item>
+ <item> make_token_iterator </item>
+ <item> token_iterator_generator </item>
+ <item> char_separator </item>
+ <item> escaped_list_separator </item>
+ <item> offset_separator </item>
+
+</list>
+
+<list name="boost.tribool">
+
+ <item> BOOST_TRIBOOL_THIRD_STATE </item>
+ <item> tribool </item>
+ <item> indeterminate </item>
+ <item> indeterminate_name </item>
+ <item> get_default_indeterminate_name </item>
+
+</list>
+
+<list name="boost.tuple">
+
+ <item> tuple </item>
+ <item> make_tuple </item>
+ <item> tie </item>
+ <item> set_open </item>
+ <item> set_close </item>
+ <item> set_delimiter </item>
+ <item> get </item>
+
+</list>
+
+TODO LIST END -->
+
+<!-- Contexts -->
+
+
+
+
+
+<list name="boost.uBLAS">
+
+ <!-- coming soon! -->
+
+</list>
+
+<!--
+<list name="boost.value_initialized">
+
+ <item> value_initialized </item>
+ <item> get </item>
+
+</list>
+
+
+<list name="boost.variant">
+
+ <item> BOOST_VARIANT_LIMIT_TYPES </item>
+ <item> BOOST_VARIANT_ENUM_PARAMS </item>
+ <item> BOOST_VARIANT_ENUM_SHIFTED_PARAMS </item>
+ <item> BOOST_VARIANT_NO_REFERENCE_SUPPORT </item>
+ <item> BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT </item>
+ <item> BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT </item>
+
+ <item> variant </item>
+ <item> make_variant_over </item>
+ <item> swap </item>
+ <item> make_recursive_variant </item>
+ <item> make_recursive_variant_over </item>
+ <item> recursive_wrapper </item>
+ <item> is_recursive_wrapper </item>
+ <item> unwrap_recursive_wrapper </item>
+ <item> apply_visitor_delayed_t </item>
+ <item> apply_visitor </item>
+ <item> bad_get </item>
+ <item> get </item>
+ <item> bad_visit </item>
+ <item> static_visitor </item>
+ <item> visitor_ptr_t </item>
+ <item> visitor_ptr </item>
+
+</list>
+-->
+<list name="boost.wave">
+
+ <!-- maybe later... -->
+
+</list>
+
+
+
+<contexts>
+
+
+<context name="main" attribute="boost.free.function" >
+
+ <keyword attribute="boost.free.function" context="#stay" String="boost.free.function" />
+ <keyword attribute="boost.template.classes" context="#stay" String="boost.template.classes" />
+ <keyword attribute="boost.classes" context="#stay" String="boost.classes" />
+ <keyword attribute="boost.metaprogramming" context="#stay" String="boost.metaprogramming" />
+ <keyword attribute="boost.exception" context="#stay" String="boost.exception" />
+ <keyword attribute="boost.container" context="#stay" String="boost.container" />
+ <keyword attribute="boost.macro" context="#stay" String="boost.macro" />
+ <keyword attribute="boost.object" context="#stay" String="boost.object" />
+ <keyword attribute="boost.fusion.result_of" context="#stay" String="boost.fusion.result_of" />
+ <keyword attribute="boost.concepts.member.functions" context="#stay" String="boost.concepts.member.functions" />
+ <keyword attribute="boost.concepts.free.functions" context="#stay" String="boost.concepts.free.functions" />
+ <keyword attribute="boost.tags" context="#stay" String="boost.tags" />
+ <keyword attribute="boost.member.functions" context="#stay" String="boost.member.functions" />
+ <keyword attribute="boost.constants" context="#stay" String="boost.constants" />
+ <keyword attribute="boost.concepts.member.typedef" context="#stay" String="boost.concepts.member.typedef" />
+ <keyword attribute="boost.namespaces" context="#stay" String="boost.namespaces" />
+
+
+</context>
+
+</contexts>
+
+
+<!--
+ This section defines the colors and format of each type of string parsed
+ Try to use defaults so the user can change it as he wished
+-->
+
+<itemDatas>
+
+ <itemData name="boost.free.function" defStyleNum="dsFunction"/>
+ <itemData name="boost.template.classes" defStyleNum="dsDataType"/>
+ <itemData name="boost.classes" defStyleNum="dsDataType"/>
+ <itemData name="boost.metaprogramming" defStyleNum="dsFunction"/>
+ <itemData name="boost.exception" defStyleNum="dsDataType" color="#0095ff" selColor="#ffffff" bold="1" italic="0"/>
+ <itemData name="boost.container" defStyleNum="dsDataType"/>
+ <itemData name="boost.macro" defStyleNum="dsOthers"/>
+ <itemData name="boost.object" defStyleNum="dsDataType" color="#0095ff" selColor="#ffffff" bold="1" italic="0"/>
+ <itemData name="boost.fusion.result_of" defStyleNum="dsFunction"/>
+ <itemData name="boost.concepts.member.functions" defStyleNum="dsFunction"/>
+ <itemData name="boost.concepts.free.functions" defStyleNum="dsFunction"/>
+ <itemData name="boost.tags" defStyleNum="dsOthers"/>
+ <itemData name="boost.member.functions" defStyleNum="dsFunction"/>
+ <itemData name="boost.constants" defStyleNum="dsKeyword" color="#0095ff" selColor="#ffffff" bold="1" italic="0"/>
+ <itemData name="boost.concepts.member.typedef" defStyleNum="dsDataType"/>
+ <itemData name="boost.namespaces" defStyleNum="dsDataType"/>
+
+ <!--
+ This is an extract from the official Kate page
+ It is leave here as a reference.
+
+ dsNormal used for normal text.
+ dsKeyword used for keywords.
+ dsDataType used for data types.
+ dsDecVal used for decimal values.
+ dsBaseN used for values with a base other than 10.
+ dsFloat used for float values.
+ dsChar used for a character.
+ dsString used for strings.
+ dsComment used for comments.
+ dsOthers used for 'other' things.
+ dsAlert used for warning messages.
+ dsFunction used for function calls.
+ dsRegionMarker used for region markers.
+ dsError used for error highlighting and wrong syntax.
+
+ -->
+</itemDatas>
+
+</highlighting>
+
+<general>
+
+ <keywords casesensitive="1" />
+
+</general>
+
+</language>
+
+
+<!-- [ About the code ]
+
+
+Introduction
+================================================
+This kate syntax files aims to improve boost C++ productivity by providing a
+consitent highligthing framework.
+This files work with kate-part so it can be used in every text procesing application
+of KDE. (KWrite,Kate,Konqueror,KDevelop,etc)
+
+
+Aknowelegments
+=================================================
+
+
+
+Version history
+=================================================
+
+[ 0.1.0 ] Initial beta.
+
+Known bugs
+=================================================
+
+
+Included boost libraries
+=================================================
+
+[ boost.any ]
+Safe, generic container for single values of different value types.
+- Kevlin Henney
+
+[ boost.array ]
+STL compliant container wrapper for arrays of constant size.
+- Nicolai Josuttis.
+
+[ boost.assign ]
+Filling containers with constant or generated data has never been easier.
+- Thorsten Ottosen.
+
+[ boost.bind ]
+Generalized binders for function/object/pointers and member functions.
+- Peter Dimov.
+
+[ boost.call_traits ]
+Defines types for passing parameters.
+- John Maddock, Howard Hinnant, et al.
+
+[ boost.compressed_pair ]
+Empty member optimization.
+- John Maddock, Howard Hinnant, et al.
+
+[ boost.concept_check ]
+Tools for generic programming
+- Jeremy Siek.
+
+[ boost.conversion ]
+Polymorphic and lexical casts
+- Dave Abrahams, Kevlin Henney.
+
+[ boost.crc ]
+Cyclic Redundancy Code
+- Daryle Walker.
+
+[ boost.date_time ]
+Date-Time library.
+- Jeff Garland.
+
+[ boost.dynamic_bitset ]
+A runtime sized version of std::bitset
+- Jeremy Siek, Chuck Allison.
+
+[ boost.enable_if ]
+Selective inclusion of function template overloads
+- Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine.
+
+[ boost.filesystem ]
+Portable paths, iteration over directories, and other useful filesystem operations.
+- Beman Dawes.
+
+[ boost.format ]
+Type-safe 'printf-like' format operations.
+- Samuel Krempp.
+
+[ boost.function ]
+Function object wrappers for deferred calls or callbacks.
+- Doug Gregor.
+
+[ boost.functional ]
+Enhanced function object adaptors.
+- Mark Rodgers.
+
+[ boost.fusion ]
+Fusion between compile and run time
+Joel de Guzman
+
+[ boost.hash ]
+A TR1 hash function object that can be extended to hash user defined types
+- Daniel James.
+
+[ boost.graph ]
+Generic graph components and algorithms
+- Jeremy Siek, University of Notre Dame team.
+
+[ boost.integer ]
+Headers to ease dealing with integral types.
+
+[ boost.interval ]
+Extends the usual arithmetic functions to mathematical intervals
+- Guillaume Melquiond, Herv´ Brönnimann, Sylvain Pion.
+
+[ boost.in_place_factory ]
+Generic in-place construction of contained objects with a variadic argument-list.
+- Fernando Cacciola.
+
+[ boost.io_state_savers ] - Save I/O state to prevent jumbled data
+- Daryle Walker.
+
+[ boost.iostreams ]
+Framework for defining streams, stream buffers and i/o filters.
+- Jonathan Turkanis.
+
+[ boost.iterators ]
+Iterator construction framework, adaptors, concepts, and more.
+- Dave Abrahams, Jeremy Siek, Thomas Witt.
+
+[ boost.lambda ]
+Define small unnamed function objects at the actual call site, and more.
+- Jaakko Järvi, Gary Powell.
+
+[ boost.math ]
+Several contributions in the domain of mathematics.
+
+[ boost.minmax ]
+standard library extensions for simultaneous min/max and min/max element computations,
+- Hervé Brönnimann.
+
+[ boost.mpl ]
+Template metaprogramming framework of compile-time algorithms, sequences and metafunction classes
+- Aleksey Gurtovoy.
+
+[ boost.multi_array ]
+Multidimensional containers and adaptors for arrays of contiguous data
+- Ron Garcia.
+
+[ boost.multi_index ]
+Containers with multiple STL-compatible access interfaces
+- Joaquín M López Muñoz.
+
+[ boost.numeric ]
+Optimized Policy-based Numeric Conversions
+- Fernando Cacciola.
+
+[ boost.operators ]
+Templates ease arithmetic classes and iterators
+- Dave Abrahams, Jeremy Siek.
+
+[ boost.optional ]
+Discriminated-union wrapper for optional values.
+- Fernando Cacciola.
+
+[ boost.parameter ]
+Write functions that accept arguments by name.
+- David Abrahams, Daniel Wallin.
+
+[ boost.pointer_container ]
+Containers for storing heap-allocated polymorphic objects to ease OO-programming.
+- Thorsten Ottosen.
+
+[ boost.pool ]
+Memory pool management
+- Steve Cleary.
+
+[ boost.preprocessor ]
+Preprocessor metaprogramming tools including repetition and recursion.
+- Vesa Karvonen, Paul Mensonides.
+
+[ boost.program_options ]
+Access to configuration data given on command line, in config files and other sources.
+- Vladimir Prus.
+
+[ boost.property_map ]
+Concepts defining interfaces which map key objects to value objects.
+- Jeremy Siek.
+
+[ boost.python ]
+Reflects C++ classes and functions into Python
+- Dave Abrahams.
+
+[ boost.random ]
+A complete system for random number generation
+- Jens Maurer.
+
+[ boost.range ]
+A new infrastructure for generic algorithms that builds on top of the new iterator concepts.
+- Thorsten Ottosen.
+
+[ boost.rational ]
+A rational number class,
+- Paul Moore.
+
+[ boost.ref ]
+A utility library for passing references to generic functions.
+- Jaako Järvi, Peter Dimov, Doug Gregor, Dave Abrahams.
+
+[ boost.regex ]
+Regular expression library.
+- John Maddock.
+
+[ boost.serialization ]
+Serialization for persistence and marshalling.
+- Robert Ramey
+
+[ boost.signals ]
+managed signals & slots callback implementation.
+- Doug Gregor.
+
+[ boost.smart_ptr ]
+Five smart pointer class templates.
+- Greg Colvin, Beman Dawes, Peter Dimov, and Darin Adler.
+
+[ boost.static_assert ]
+Static assertions (compile time assertions).
+- John Maddock.
+
+[ boost.spirit ]
+LL parser framework represents parsers directly as EBNF grammars in inlined C++.
+- Joel de Guzman and team.
+
+[ boost.string_algo ]
+String algorithms library
+- Pavol Droba
+
+[ boost.test ]
+Support for simple program testing, full unit testing, and for program execution monitoring.
+- Gennadiy Rozental.
+
+[ boost.thread ]
+Portable C++ multi-threading.
+- William Kempf.
+
+[ boost.timer ]
+Event timer, progress timer, and progress display classes.
+- Beman Dawes.
+
+[ boost.tokenizer ]
+Break of a string or other character sequence into a series of tokens.
+- John Bandela.
+
+[ boost.tribool ]
+3-state boolean type library.
+- Doug Gregor.
+
+[ boost.tuple ]
+Ease definition of functions returning multiple values, and more.
+- Jaakko Järvi.
+
+[ boost.type_traits ]
+Templates for fundamental properties of types.
+- John Maddock, Steve Cleary, et al.
+
+[ boost.uBLAS ]
+Basic linear algebra for dense, packed and sparse matrices.
+- Joerg Walter, Mathias Koch.
+
+[ boost.utility ]
+Class noncopyable plus checked_delete(), checked_array_delete(), next(), prior() function templates,
+plus base-from-member idiom.
+- Dave Abrahams and others.
+
+[ boost.value_initialized ]
+Wrapper for uniform-syntax value initialization.
+- Fernando Cacciola, based on the original idea of David Abrahams.
+
+[ boost.variant ]
+Safe, generic, stack-based discriminated union container.
+- Eric Friedman, Itay Maman.
+
+[ boost.wave ]
+Preprocessor functionality packed behind an easy to use iterator interface.
+- Hartmut Kaiser
+
+
+-->
+
diff --git a/tools/quickbook/extra/katepart/syntax/boost_hs_cpp.xml b/tools/quickbook/extra/katepart/syntax/boost_hs_cpp.xml
new file mode 100644
index 0000000000..3ec0b91b03
--- /dev/null
+++ b/tools/quickbook/extra/katepart/syntax/boost_hs_cpp.xml
@@ -0,0 +1,471 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE language SYSTEM "language.dtd">
+
+<language
+
+name="c++"
+version="0.1.0"
+kateversion="2.4"
+section="boost::hs"
+extensions="*.cpp;*.hpp;*.h"
+mimetype="allFiles"
+author="Based on the original cpp.xml from katepart, Copyright 2006 -2007 Matias Capeletto, matias.capeletto@gmail.com"
+priority="9"
+license="Distributed under the Boost Software License, Version 1.0.
+http://www.boost.org/LICENSE_1_0.txt"
+
+>
+
+<highlighting>
+
+<!-- Keywords lists -->
+
+<list name="keywords">
+
+ <item> asm </item>
+ <item> break </item>
+ <item> case </item>
+ <item> catch </item>
+ <item> class </item>
+ <item> const_cast </item>
+ <item> continue </item>
+ <item> default </item>
+ <item> delete </item>
+ <item> do </item>
+ <item> dynamic_cast</item>
+ <item> else </item>
+ <item> enum </item>
+ <item> explicit </item>
+ <item> export </item>
+ <item> extern </item>
+ <item> false </item>
+ <item> friend </item>
+ <item> for </item>
+ <item> goto </item>
+ <item> if </item>
+ <item> inline </item>
+ <item> namespace </item>
+ <item> new </item>
+ <item> operator </item>
+ <item> private </item>
+ <item> protected </item>
+ <item> public </item>
+ <item> reinterpret_cast </item>
+ <item> return </item>
+ <item> sizeof </item>
+ <item> static_cast </item>
+ <item> struct </item>
+ <item> switch </item>
+ <item> template </item>
+ <item> this </item>
+ <item> throw </item>
+ <item> true </item>
+ <item> try </item>
+ <item> typedef </item>
+ <item> typeid </item>
+ <item> type_info </item>
+ <item> typename </item>
+ <item> union </item>
+ <item> using </item>
+ <item> virtual </item>
+ <item> while </item>
+ <item> and </item>
+ <item> and_eq </item>
+ <item> bad_cast </item>
+ <item> bad_typeid </item>
+ <item> bitand </item>
+ <item> bitor </item>
+ <item> compl </item>
+ <item> not </item>
+ <item> not_eq </item>
+ <item> or </item>
+ <item> or_eq </item>
+ <item> xor </item>
+ <item> xor_eq </item>
+ <item> except </item>
+ <item> finally </item>
+ <item> xalloc </item>
+
+</list>
+
+<list name="qt_extensions">
+
+ <item> K_DCOP </item>
+ <item> SLOT </item>
+ <item> SIGNAL </item>
+ <item> Q_CLASSINFO </item>
+ <item> Q_ENUMS </item>
+ <item> Q_EXPORT </item>
+ <item> Q_OBJECT </item>
+ <item> Q_OVERRIDE </item>
+ <item> Q_PROPERTY </item>
+ <item> Q_SETS </item>
+ <item> TRUE </item>
+ <item> FALSE </item>
+ <item> connect </item>
+ <item> disconnect </item>
+ <item> emit </item>
+ <item> signals </item>
+ <item> slots </item>
+ <item> foreach </item>
+
+</list>
+
+<list name="types">
+
+ <item> auto </item>
+ <item> bool </item>
+ <item> char </item>
+ <item> const </item>
+ <item> double </item>
+ <item> float </item>
+ <item> int </item>
+ <item> long </item>
+ <item> mutable </item>
+ <item> register </item>
+ <item> short </item>
+ <item> signed </item>
+ <item> static </item>
+ <item> unsigned </item>
+ <item> void </item>
+ <item> volatile </item>
+ <item> uchar </item>
+ <item> uint </item>
+ <item> int8_t </item>
+ <item> int16_t </item>
+ <item> int32_t </item>
+ <item> int64_t </item>
+ <item> uint8_t </item>
+ <item> uint16_t </item>
+ <item> uint32_t </item>
+ <item> uint64_t </item>
+ <item> wchar_t </item>
+
+</list>
+
+<!-- Contexts -->
+
+<contexts>
+
+<context attribute="Normal Text" lineEndContext="#stay" name="Normal">
+
+ <DetectSpaces />
+
+ <IncludeRules context="boost::hs call finder" />
+ <IncludeRules context="preprocessor finder" />
+ <IncludeRules context="keyword finder" />
+ <IncludeRules context="extensions finder" />
+ <IncludeRules context="built in types finder" />
+ <IncludeRules context="##std-c++" />
+ <IncludeRules context="##boost" />
+ <IncludeRules context="character finder" />
+ <IncludeRules context="string finder" />
+
+ <DetectIndentifier />
+
+ <IncludeRules context="number finder" />
+ <IncludeRules context="##Doxygen" />
+ <IncludeRules context="quickbook_import_markup" />
+ <IncludeRules context="comment finder" />
+ <IncludeRules context="region finder" />
+ <IncludeRules context="symbol finder" />
+
+</context>
+
+<!-- String listerals -->
+
+<context attribute="String" name="string finder">
+ <DetectChar attribute="String" context="String" char="&quot;"/>
+</context>
+
+<context attribute="String" lineEndContext="#pop" name="String">
+
+ <LineContinue attribute="String" context="#stay"/>
+ <HlCStringChar attribute="String Char" context="#stay"/>
+ <DetectChar attribute="String" context="#pop" char="&quot;"/>
+
+</context>
+
+<!-- Character literals -->
+
+<context attribute="Character" name="character finder">
+ <HlCChar attribute="Char" context="#stay"/>
+</context>
+
+
+<!-- built in types -->
+
+<context attribute="built in types" name="built in types finder">
+ <keyword attribute="Data Type" context="#stay" String="types" />
+</context>
+
+<!-- extensions -->
+
+<context attribute="Extensions" name="extensions finder">
+ <keyword attribute="Extensions" context="#stay" String="qt_extensions" />
+</context>
+
+<!-- Keywords -->
+
+<context attribute="Keyword" name="keyword finder">
+ <keyword attribute="Keyword" context="#stay" String="keywords" />
+</context>
+
+<!-- Detect number literals -->
+
+<context attribute="Float" name="number finder">
+
+
+ <Float attribute="Float" context="#stay">
+ <AnyChar String="fF" attribute="Float" context="#stay"/>
+ </Float>
+
+ <HlCOct attribute="Octal" context="#stay"/>
+
+ <HlCHex attribute="Hex" context="#stay"/>
+
+ <Int attribute="Decimal" context="#stay">
+
+ <StringDetect attribute="Decimal" context="#stay" String="ULL" insensitive="TRUE"/>
+ <StringDetect attribute="Decimal" context="#stay" String="LUL" insensitive="TRUE"/>
+ <StringDetect attribute="Decimal" context="#stay" String="LLU" insensitive="TRUE"/>
+ <StringDetect attribute="Decimal" context="#stay" String="UL" insensitive="TRUE"/>
+ <StringDetect attribute="Decimal" context="#stay" String="LU" insensitive="TRUE"/>
+ <StringDetect attribute="Decimal" context="#stay" String="LL" insensitive="TRUE"/>
+ <StringDetect attribute="Decimal" context="#stay" String="U" insensitive="TRUE"/>
+ <StringDetect attribute="Decimal" context="#stay" String="L" insensitive="TRUE"/>
+
+ </Int>
+
+</context>
+
+
+<!-- Comments -->
+
+<context attribute="Commnet" name="comment finder">
+ <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
+ <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*" beginRegion="Comment"/>
+</context>
+
+<context attribute="Comment" lineEndContext="#pop" name="Commentar 1">
+ <DetectSpaces />
+ <IncludeRules context="##Alerts" />
+ <DetectIdentifier />
+</context>
+
+<context attribute="Comment" lineEndContext="#stay" name="Commentar 2">
+ <DetectSpaces />
+ <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
+ <IncludeRules context="##Alerts" />
+ <DetectIdentifier />
+</context>
+
+<!-- QuickBook import markups -->
+
+<context attribute="Comment" lineEndContext="#stay" name="Quickbook Commentar 1">
+ <DetectSpaces />
+ <StringDetect attribute="Extensions" context="#pop" String="*/" endRegion="Comment"/>
+ <IncludeRules context="##Alerts" />
+ <DetectIdentifier />
+</context>
+
+<context attribute="Comment" lineEndContext="#stay" name="Quickbook Commentar 2">
+ <DetectSpaces />
+ <StringDetect attribute="Extensions" context="#pop" String="&gt;&gt;*/" endRegion="Comment"/>
+ <IncludeRules context="##Alerts" />
+ <DetectIdentifier />
+</context>
+
+<context attribute="Comment" lineEndContext="#stay" name="Quickbook Commentar 3">
+ <DetectSpaces />
+ <StringDetect attribute="Extensions" context="#pop" String="&gt;*/" endRegion="Comment"/>
+ <IncludeRules context="##Alerts" />
+ <DetectIdentifier />
+</context>
+
+<context name="quickbook_import_markup" attribute="Commnet">
+ <RegExpr attribute="Extensions" context="Commentar 1" String="//\[\s*\w+"/>
+ <StringDetect attribute="Extensions" context="Commentar 1" String="//]"/>
+ <StringDetect attribute="Extensions" context="Commentar 1" String="//`"/>
+ <StringDetect attribute="Extensions" context="Commentar 1" String="//&lt;--"/>
+ <StringDetect attribute="Extensions" context="Commentar 1" String="//--&gt;"/>
+ <StringDetect attribute="Extensions" context="Quickbook Commentar 1" String="/*`" beginRegion="Comment"/>
+ <StringDetect attribute="Extensions" context="Quickbook Commentar 2" String="/*&lt;&lt;" beginRegion="Comment"/>
+ <StringDetect attribute="Extensions" context="Quickbook Commentar 3" String="/*&lt;" beginRegion="Comment"/>
+</context>
+
+
+<!-- Regions -->
+
+<context attribute="Symbol" name="region finder">
+
+ <DetectChar attribute="Symbol" context="#stay" char="{" beginRegion="Brace1" />
+ <DetectChar attribute="Symbol" context="#stay" char="}" endRegion="Brace1" />
+
+</context>
+
+<!-- Other reserved symbols -->
+
+<context attribute="Symbol" name="symbol finder">
+
+ <AnyChar attribute="Symbol" context="#stay" String=":!%&amp;()+,-/.*&lt;=&gt;?[]{|}~^&#59;"/>
+
+</context>
+
+<!-- Preprocessor -->
+
+<context attribute="Preprocessor" name="preprocessor finder">
+
+ <!-- ifdef/ifndef region markers -->
+
+ <RegExpr attribute="Preprocessor" context="Outscoped" String="#\s*if\s+0" beginRegion="Outscoped" firstNonSpace="true" />
+
+ <!-- Enter the preprocessor -->
+
+ <DetectChar attribute="Preprocessor" context="Preprocessor" char="#" firstNonSpace="true" />
+
+</context>
+
+<context attribute="Preprocessor" lineEndContext="#pop" name="Preprocessor">
+
+ <LineContinue attribute="Preprocessor" context="#stay"/>
+ <RegExpr attribute="Preprocessor" context="Define" String="define.*((?=\\))"/>
+ <RegExpr attribute="Preprocessor" context="#stay" String="define.*"/>
+ <RangeDetect attribute="Prep. Lib" context="#stay" char="&quot;" char1="&quot;"/>
+ <RangeDetect attribute="Prep. Lib" context="#stay" char="&lt;" char1="&gt;"/>
+ <IncludeRules context="##Doxygen" />
+ <IncludeRules context="quickbook_import_markup" />
+ <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
+ <Detect2Chars attribute="Comment" context="Commentar/Preprocessor" char="/" char1="*"/>
+
+</context>
+
+<context attribute="Preprocessor" lineEndContext="#pop" name="Define">
+ <LineContinue attribute="Preprocessor" context="#stay"/>
+</context>
+
+<context attribute="Comment" lineEndContext="#stay" name="Commentar/Preprocessor">
+ <DetectSpaces />
+ <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" />
+ <DetectIdentifier />
+</context>
+
+<context attribute="Comment" lineEndContext="#stay" name="Outscoped" >
+ <DetectSpaces />
+ <IncludeRules context="##Alerts" />
+ <DetectIdentifier />
+ <DetectChar attribute="String" context="String" char="&quot;"/>
+ <IncludeRules context="##Doxygen" />
+ <IncludeRules context="quickbook_import_markup" />
+ <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
+ <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*" beginRegion="Comment"/>
+ <RegExpr attribute="Comment" context="Outscoped intern" String="#\s*if" beginRegion="Outscoped" firstNonSpace="true" />
+ <RegExpr attribute="Preprocessor" context="#pop" String="#\s*(endif|else|elif)" endRegion="Outscoped" firstNonSpace="true" />
+</context>
+
+<context attribute="Comment" lineEndContext="#stay" name="Outscoped intern">
+
+ <DetectSpaces />
+ <IncludeRules context="##Alerts" />
+ <DetectIdentifier />
+ <DetectChar attribute="String" context="String" char="&quot;"/>
+ <IncludeRules context="##Doxygen" />
+ <IncludeRules context="quickbook_import_markup" />
+ <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
+ <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*" beginRegion="Comment"/>
+ <RegExpr attribute="Comment" context="Outscoped intern" String="#\s*if" beginRegion="Outscoped" firstNonSpace="true"/>
+ <RegExpr attribute="Comment" context="#pop" String="#\s*endif" endRegion="Outscoped" firstNonSpace="true"/>
+
+</context>
+
+
+<!-- boost::hs -->
+
+<context attribute="Comment" lineEndContext="#pop" name="boost::hs skip line" >
+
+</context>
+
+
+<context attribute="Comment" lineEndContext="#pop#pop" name="boost::hs skip line and pop pop" >
+
+</context>
+
+
+<context attribute="Comment" lineEndContext="boost::hs is off" name="boost::hs has gone off" >
+
+</context>
+
+
+<context attribute="Comment" name="boost::hs call finder">
+
+ <StringDetect attribute="boost::hs" context="boost::hs skip line" String="//boost::hs::begin_region()" beginRegion="boost::hs::Region" firstNonSpace="true" />
+ <StringDetect attribute="boost::hs" context="boost::hs skip line" String="//boost::hs::end_region()" endRegion="boost::hs::Region" firstNonSpace="true" />
+
+ <StringDetect attribute="boost::hs" context="boost::hs has gone off" String="//boost::hs::turn_off()" beginRegion="boost::hs::ScapedRegion" firstNonSpace="true" />
+ <StringDetect attribute="boost::hs" context="boost::hs skip line" String="//boost::hs::turn_on()" firstNonSpace="true" />
+
+</context>
+
+<context attribute="Normal Text" name="boost::hs is off">
+
+ <StringDetect attribute="boost::hs" context="boost::hs skip line and pop pop" String="//boost::hs::turn_off()" endRegion="boost::hs::ScapedRegion" firstNonSpace="true" />
+ <StringDetect attribute="boost::hs" context="#stay" String="//boost::hs::turn_on()" firstNonSpace="true" />
+
+</context>
+
+
+</contexts>
+
+<itemDatas>
+
+ <itemData name="Normal Text" defStyleNum="dsNormal"/>
+ <itemData name="Keyword" defStyleNum="dsKeyword"/>
+ <itemData name="Extensions" defStyleNum="dsKeyword" color="#0095ff" selColor="#ffffff" bold="1" italic="0"/>
+ <itemData name="Data Type" defStyleNum="dsDataType"/>
+ <itemData name="Decimal" defStyleNum="dsDecVal"/>
+ <itemData name="Octal" defStyleNum="dsBaseN"/>
+ <itemData name="Hex" defStyleNum="dsBaseN"/>
+ <itemData name="Float" defStyleNum="dsFloat"/>
+ <itemData name="Char" defStyleNum="dsChar"/>
+ <itemData name="String" defStyleNum="dsString"/>
+ <itemData name="String Char" defStyleNum="dsChar"/>
+ <itemData name="Comment" defStyleNum="dsComment"/>
+ <itemData name="Symbol" defStyleNum="dsNormal"/>
+ <itemData name="Preprocessor" defStyleNum="dsOthers"/>
+ <itemData name="Prep. Lib" defStyleNum="dsOthers"/>
+ <itemData name="boost::hs" defStyleNum="dsOthers"/>
+
+</itemDatas>
+
+</highlighting>
+
+<general>
+
+ <comments>
+
+ <comment name="singleLine" start="//" />
+ <comment name="multiLine" start="/*" end="*/" region="Comment"/>
+
+ </comments>
+
+ <keywords casesensitive="1" />
+
+</general>
+
+</language>
+
+
+<!--
+
+Aknowelegments
+=================================================
+
+Version history
+=================================================
+
+[ 0.1.0 ] Initial beta.
+
+Known bugs
+=================================================
+
+--> \ No newline at end of file
diff --git a/tools/quickbook/extra/katepart/syntax/boost_hs_quickbook.xml b/tools/quickbook/extra/katepart/syntax/boost_hs_quickbook.xml
new file mode 100644
index 0000000000..b043cfbe84
--- /dev/null
+++ b/tools/quickbook/extra/katepart/syntax/boost_hs_quickbook.xml
@@ -0,0 +1,736 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE language SYSTEM "language.dtd">
+<language
+
+name="quickbook"
+version="0.9.4"
+kateversion="2.4"
+section="boost::hs"
+extensions="*.qbk"
+mimetype="allFiles"
+author="Copyright 2006 -2007 Matias Capeletto, matias.capeletto@gmail.com"
+license="Distributed under the Boost Software License, Version 1.0.
+http://www.boost.org/LICENSE_1_0.txt"
+
+>
+
+<highlighting>
+
+<!-- Contexts -->
+
+<contexts>
+
+<!--
+ Main context
+ This is bottom the context, every thing the user type will stack another
+ context. This context is special because some things can only be called
+ from here. (e.g. The quickbook description)
+-->
+
+<context name="c_main" attribute="d_normal" lineEndContext="#stay">
+
+ <IncludeRules context="c_main_before_code" />
+ <IncludeRules context="c_cpp_code_block_finder" />
+ <IncludeRules context="c_main_after_code" />
+ <IncludeRules context="c_normal" />
+
+</context>
+
+<context name="c_main_before_code" attribute="d_normal" lineEndContext="#stay">
+
+ <IncludeRules context="c_sections_finder" />
+ <IncludeRules context="c_predefined_macros" />
+ <IncludeRules context="c_boost::hs call finder" />
+ <IncludeRules context="c_item_list_finder" />
+
+</context>
+
+<context name="c_main_after_code" attribute="d_normal" lineEndContext="#stay">
+
+ <IncludeRules context="c_scape_sequence_finder" />
+ <IncludeRules context="c_headings_finder" />
+ <IncludeRules context="c_includes_finder" />
+ <IncludeRules context="c_macro_definition_finder" />
+ <IncludeRules context="c_template_definition_finder" />
+ <IncludeRules context="c_quickbook_type_finder" />
+ <IncludeRules context="c_text_block_finder" />
+ <IncludeRules context="c_table_finder" />
+ <IncludeRules context="c_variable_list_finder" />
+ <IncludeRules context="c_import_finder" />
+
+</context>
+
+<!-- Common Structures, this constructions can be called in almost every context -->
+
+<context name="c_common_structures" attribute="d_normal" lineEndContext="#stay">
+
+ <DetectSpaces/>
+ <IncludeRules context="c_common_structures_before_code" />
+ <IncludeRules context="c_cpp_inline_code_block_finder" />
+ <IncludeRules context="c_common_structures_after_code" />
+
+</context>
+
+<context name="c_common_structures_before_code" attribute="d_normal" lineEndContext="#stay">
+
+ <DetectSpaces/>
+ <IncludeRules context="c_scape_sequence_finder" />
+ <IncludeRules context="c_predefined_macros" />
+ <IncludeRules context="c_language_finder" />
+ <IncludeRules context="c_comment_finder" />
+ <IncludeRules context="c_boost::hs call finder" />
+ <IncludeRules context="c_no_processing_finder" />
+
+</context>
+
+<context name="c_common_structures_after_code" attribute="d_normal" lineEndContext="#stay">
+
+ <IncludeRules context="c_anchor_finder" />
+ <IncludeRules context="c_image_finder" />
+ <IncludeRules context="c_link_finder" />
+ <IncludeRules context="c_cpp_link_finder" />
+ <IncludeRules context="c_text_format_finder" />
+
+</context>
+
+<!-- Normal contex, defines plain text and look for a structure to appear -->
+
+<context name="c_normal" attribute="d_normal" lineEndContext="#stay">
+
+ <!-- For performance the [endsect] resets the engine -->
+ <StringDetect String="[endsect]" attribute="d_structure" context="#pop#pop#pop#pop#pop" endRegion="r_section"/>
+
+ <IncludeRules context="c_common_structures" />
+ <IncludeRules context="c_simple_text_block_finder" />
+
+</context>
+
+<!-- Inside tables and list, you can not use every construction -->
+
+<context name="c_strict_normal" attribute="d_normal" lineEndContext="#stay">
+
+ <!-- For performance the [endsect] resets the engine -->
+ <StringDetect String="[endsect]" attribute="d_structure" context="#pop#pop#pop#pop#pop" endRegion="r_section"/>
+
+ <IncludeRules context="c_common_structures" />
+
+</context>
+
+<!-- Normal block contexs, this contexts will be stacked so we can know the state -->
+
+<context name="c_normal_block" attribute="d_normal" lineEndContext="#stay">
+ <IncludeRules context="c_normal" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_normal_bold_block" attribute="d_normal_bold" lineEndContext="#stay">
+ <IncludeRules context="c_normal" />
+
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_indirect_normal_block" attribute="d_normal" lineEndContext="#stay">
+ <IncludeRules context="c_normal" />
+
+ <DetectChar char="]" attribute="d_structure" context="#pop#pop" />
+</context>
+
+<context name="c_deep_normal_block" attribute="d_normal" lineEndContext="#stay">
+ <IncludeRules context="c_normal" />
+ <DetectChar char="]" attribute="d_structure" context="#pop#pop#pop" />
+</context>
+
+<context name="c_indirect_normal_bold_block" attribute="d_normal_bold" lineEndContext="#stay">
+ <IncludeRules context="c_normal" />
+
+ <DetectChar char="]" attribute="d_structure" context="#pop#pop" />
+</context>
+
+<!-- Blocks used in macros and templates bodies -->
+
+<context name="c_indirect_main_block" attribute="d_normal" lineEndContext="#stay">
+ <IncludeRules context="c_main" />
+
+ <DetectChar char="]" attribute="d_structure" context="#pop#pop" />
+</context>
+
+<context name="c_deep_main_block" attribute="d_normal" lineEndContext="#stay">
+ <IncludeRules context="c_main" />
+ <DetectChar char="]" attribute="d_structure" context="#pop#pop#pop" />
+</context>
+
+<!-- No processing block -->
+
+<context name="c_no_processing_block" attribute="d_normal" lineEndContext="#stay">
+ <IncludeRules context="c_predefined_macros" />
+ <StringDetect String="'''" attribute="d_structure" context="#pop" endRegion="r_no_processing"/>
+</context>
+
+<context name="c_no_processing_finder" attribute="d_normal" lineEndContext="#stay">
+ <StringDetect String="'''" attribute="d_structure" context="c_no_processing_block" beginRegion="r_no_processing"/>
+</context>
+
+<!-- Items list finder -->
+
+<context name="c_item_list" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="^\s*[\*\#]\s" minimal="true" attribute="d_structure" context="c_item_list"/>
+ <RegExpr String="^." minimal="true" attribute="d_structure" lookAhead="true" context="#pop"/>
+ <IncludeRules context="c_strict_normal" />
+</context>
+
+<context name="c_item_list_finder" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="^\s*[\*\#]\s" minimal="true" attribute="d_structure" context="c_item_list"/>
+</context>
+
+<!-- Code blocks -->
+
+<context name="c_back_to_quickbook_block" attribute="d_normal" lineEndContext="#stay">
+ <Detect2Chars char="`" char1="`" attribute="d_structure" context="#pop" />
+ <IncludeRules context="c_strict_normal" />
+</context>
+
+<context name="c_code_block" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="^[\S]" minimal="true" attribute="d_structure" lookAhead="true" context="#pop" />
+ <Detect2Chars char="`" char1="`" attribute="d_structure" context="c_back_to_quickbook_block" />
+ <IncludeRules context="c_predefined_macros" />
+ <IncludeRules context="##C++" />
+</context>
+
+<context name="c_preformated_code_block" attribute="d_normal" lineEndContext="#stay">
+ <Detect2Chars char="`" char1="`" attribute="d_structure" context="#pop" endRegion="r_code_block" />
+ <IncludeRules context="c_predefined_macros" />
+ <IncludeRules context="##C++" />
+</context>
+
+<context name="c_inline_code_block" attribute="d_normal" lineEndContext="#stay">
+ <DetectChar char="`" attribute="d_structure" context="#pop" />
+ <IncludeRules context="c_predefined_macros" />
+ <IncludeRules context="##C++"/>
+</context>
+
+<context name="c_cpp_code_block_finder" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="^[\s]" minimal="true" attribute="d_structure" context="c_code_block" />
+</context>
+
+<context name="c_cpp_inline_code_block_finder" attribute="d_normal" lineEndContext="#stay">
+ <Detect2Chars char="`" char1="`" attribute="d_structure" context="c_preformated_code_block" beginRegion="r_code_block" />
+ <DetectChar char="`" attribute="d_structure" context="c_inline_code_block" />
+</context>
+
+<context name="c_language_finder" attribute="d_normal" lineEndContext="#stay">
+ <StringDetect String="[c++]" attribute="d_structure" context="#stay" />
+ <StringDetect String="[python]" attribute="d_structure" context="#stay" />
+</context>
+
+<!-- Sections and Headings -->
+
+<context name="c_section_definition" attribute="d_anchor" lineEndContext="#stay">
+ <DetectChar char=" " attribute="d_structure" context="c_indirect_normal_bold_block" />
+</context>
+
+<context name="c_sections_finder" attribute="d_normal" lineEndContext="#stay">
+ <StringDetect String="[section" attribute="d_structure" context="c_section_definition" beginRegion="r_section" />
+ <StringDetect String="[endsect]" attribute="d_structure" context="#pop#pop#pop#pop" endRegion="r_section"/>
+</context>
+
+<context name="c_headings_finder" attribute="d_normal" lineEndContext="#stay">
+ <StringDetect String="[heading" minimal="true" attribute="d_structure" context="c_normal_bold_block" />
+ <RegExpr String="\[h[1-6]\b" minimal="true" attribute="d_structure" context="c_normal_bold_block" />
+</context>
+
+
+<!-- Macros -->
+
+<context name="c_macro_definition" attribute="d_macro" lineEndContext="c_indirect_main_block">
+ <RegExpr String="\s" minimal="true" attribute="d_structure" context="c_indirect_main_block" />
+</context>
+
+<context name="c_predefined_macros" attribute="d_macro">
+ <RegExpr String="[_]{2}[\w_]+[_]{2}" minimal="true" attribute="d_macro" context="#stay" />
+</context>
+
+<context name="c_macro_definition_finder" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="\[def\b[\s]*" attribute="d_structure" context="c_macro_definition" />
+</context>
+
+
+<!-- Templates -->
+
+<context name="c_template_parameters" attribute="d_path" lineEndContext="#stay">
+ <DetectChar char="]" attribute="d_structure" context="c_deep_main_block" />
+</context>
+
+<context name="c_template_definition" attribute="d_macro" lineEndContext="c_indirect_main_block">
+ <DetectChar char="[" attribute="d_structure" context="c_template_parameters" />
+ <RegExpr String="\\\s" minimal="true" attribute="d_structure" context="c_indirect_main_block"/>
+ <RegExpr String="\s" minimal="true" attribute="d_structure" context="c_indirect_main_block" />
+</context>
+
+<context name="c_template_definition_finder" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="\[template\b[\s]*" attribute="d_structure" context="c_template_definition" />
+</context>
+
+<!-- Text format logic -->
+
+<context name="c_text_format_finder" attribute="d_normal">
+ <Detect2Chars char="[" char1="*" attribute="d_structure" context="c_normal_bold" />
+ <Detect2Chars char="[" char1="'" attribute="d_structure" context="c_normal_italic" />
+ <Detect2Chars char="[" char1="_" attribute="d_structure" context="c_normal_underline" />
+ <Detect2Chars char="[" char1="-" attribute="d_structure" context="c_normal_strikeout" />
+ <Detect2Chars char="[" char1="^" attribute="d_structure" context="c_normal_teletype" />
+ <Detect2Chars char="[" char1="~" attribute="d_structure" context="c_normal_replaceable" />
+ <RegExpr String="(?=(^|\W))[\*][\S][^\[\]]*[\S]?[\*](?=($|\W))" minimal="true" attribute="d_normal_bold" context="#stay" />
+ <RegExpr String="(?=(^|\W))[/][\S][^\[\]]*[\S]?[/](?=($|\W))" minimal="true" attribute="d_normal_italic" context="#stay" />
+ <RegExpr String="(?=(^|\W))[_][\S][^\[\]]*[\S]?[_](?=($|\W))" minimal="true" attribute="d_normal_underline" context="#stay" />
+ <RegExpr String="(?=(^|\W))[=][\S][^\[\]]*[\S]?[=](?=($|\W))" minimal="true" attribute="d_normal_teletype" context="#stay" />
+</context>
+
+<context name="c_normal_bold" attribute="d_normal_bold" lineEndContext="#stay">
+ <IncludeRules context="c_common_structures" />
+ <Detect2Chars char="[" char1="*" attribute="d_structure" context="c_normal_bold" />
+ <Detect2Chars char="[" char1="'" attribute="d_structure" context="c_normal_bold_italic" />
+ <Detect2Chars char="[" char1="_" attribute="d_structure" context="c_normal_bold_underline" />
+ <RegExpr String="(?=(^|\W))[/][\S][^\[\]]*[\S]?[/](?=($|\W))" minimal="true" attribute="d_normal_bold_italic" context="#stay" />
+ <RegExpr String="(?=(^|\W))[_][\S][^\[\]]*[\S]?[_](?=($|\W))" minimal="true" attribute="d_normal_bold_underline" context="#stay" />
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_normal_italic" attribute="d_normal_italic" lineEndContext="#stay">
+ <IncludeRules context="c_common_structures" />
+ <Detect2Chars char="[" char1="*" attribute="d_structure" context="c_normal_bold_italic" />
+ <Detect2Chars char="[" char1="_" attribute="d_structure" context="c_normal_italic_underline" />
+ <RegExpr String="(?=(^|\W))[\*][\S][^\[\]]*[\S]?[\*](?=($|\W))" minimal="true" attribute="d_normal_bold_italic" context="#stay" />
+ <RegExpr String="(?=(^|\W))[_][\S][^\[\]]*[\S]?[_](?=($|\W))" minimal="true" attribute="d_normal_italic_underline" context="#stay" />
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_normal_underline" attribute="d_normal_underline" lineEndContext="#stay">
+ <IncludeRules context="c_common_structures" />
+ <Detect2Chars char="[" char1="*" attribute="d_structure" context="c_normal_bold_underline" />
+ <Detect2Chars char="[" char1="'" attribute="d_structure" context="c_normal_italic_underline" />
+ <Detect2Chars char="[" char1="_" attribute="d_structure" context="c_normal_underline" />
+ <RegExpr String="(?=(^|\W))[\*][\S][^\[\]]*[\S]?[\*](?=($|\W))" minimal="true" attribute="d_normal_bold_underline" context="#stay" />
+ <RegExpr String="(?=(^|\W))[/][\S][^\[\]]*[\S]?[/](?=($|\W))" minimal="true" attribute="d_normal_italic_underline" context="#stay" />
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_normal_bold_italic" attribute="d_normal_bold_italic" lineEndContext="#stay">
+ <IncludeRules context="c_common_structures" />
+ <Detect2Chars char="[" char1="*" attribute="d_structure" context="c_normal_bold_italic" />
+ <Detect2Chars char="[" char1="'" attribute="d_structure" context="c_normal_bold_italic" />
+ <Detect2Chars char="[" char1="_" attribute="d_structure" context="c_normal_bold_italic_underline" />
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_normal_bold_underline" attribute="d_normal_bold_underline" lineEndContext="#stay">
+ <IncludeRules context="c_common_structures" />
+ <Detect2Chars char="[" char1="*" attribute="d_structure" context="c_normal_bold_underline" />
+ <Detect2Chars char="[" char1="'" attribute="d_structure" context="c_normal_bold_italic_underline" />
+ <Detect2Chars char="[" char1="_" attribute="d_structure" context="c_normal_bold_underline" />
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_normal_italic_underline" attribute="d_normal_italic_underline" lineEndContext="#stay">
+ <IncludeRules context="c_common_structures" />
+ <Detect2Chars char="[" char1="*" attribute="d_structure" context="c_normal_bold_italic_underline" />
+ <Detect2Chars char="[" char1="'" attribute="d_structure" context="c_normal_italic_underline" />
+ <Detect2Chars char="[" char1="_" attribute="d_structure" context="c_normal_italic_underline" />
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_normal_bold_italic_underline" attribute="d_normal_bold_italic_underline" lineEndContext="#stay">
+ <IncludeRules context="c_common_structures" />
+ <Detect2Chars char="[" char1="*" attribute="d_structure" context="c_normal_bold_italic_underline" />
+ <Detect2Chars char="[" char1="'" attribute="d_structure" context="c_normal_bold_italic_underline" />
+ <Detect2Chars char="[" char1="_" attribute="d_structure" context="c_normal_bold_italic_underline" />
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_normal_strikeout" attribute="d_normal_strikeout" lineEndContext="#stay">
+ <IncludeRules context="c_common_structures" />
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_normal_teletype" attribute="d_normal_teletype" lineEndContext="#stay">
+ <IncludeRules context="c_common_structures" />
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_normal_replaceable" attribute="d_normal_ replaceable" lineEndContext="#stay">
+ <IncludeRules context="c_common_structures" />
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<!-- Links -->
+
+<context name="c_link" attribute="d_anchor" lineEndContext="c_indirect_normal_block">
+ <RegExpr String="\s" minimal="true" attribute="d_structure" context="c_indirect_normal_block" />
+</context>
+
+<context name="c_web_link" attribute="d_path" lineEndContext="c_indirect_normal_block">
+ <RegExpr String="\s" minimal="true" attribute="d_structure" context="c_indirect_normal_block" />
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_link_finder" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="\[link\b[\s]*" attribute="d_structure" context="c_link" />
+ <Detect2Chars char="[" char1="@" attribute="d_structure" context="c_web_link" />
+</context>
+
+<context name="c_cpp_link_finder" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="\[(funcref|classref|memberref|enumref|headerref)\b[\s]*" attribute="d_structure" context="c_link" />
+</context>
+
+<!-- Anchors -->
+
+<context name="c_anchor" attribute="d_anchor" lineEndContext="#stay">
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_anchor_finder" attribute="d_normal" lineEndContext="#stay">
+ <Detect2Chars char="[" char1="#" attribute="d_structure" context="c_anchor" />
+</context>
+
+<!-- Images -->
+
+<context name="c_image" attribute="d_path" lineEndContext="#stay">
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_image_finder" attribute="d_normal" lineEndContext="#stay">
+ <Detect2Chars char="[" char1="$" attribute="d_structure" context="c_image" />
+</context>
+
+<!-- Comments -->
+
+<context name="c_comment" attribute="d_comment" lineEndContext="#stay">
+
+ <!-- For performance the [endsect] resets the engine -->
+ <!-- Is this the best approach here? -->
+ <StringDetect String="[endsect]" attribute="d_structure" context="#pop#pop#pop#pop#pop" endRegion="r_section"/>
+
+ <DetectChar char="[" attribute="d_structure" context="c_comment" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" endRegion="r_comment" />
+</context>
+
+<context name="c_comment_finder" >
+ <Detect2Chars char="[" char1="/" attribute="d_structure" context="c_comment" beginRegion="r_comment" />
+</context>
+
+<!-- Scape sequences -->
+
+<context name="c_scape_sequence_finder" attribute="d_normal" lineEndContext="#stay">
+ <DetectChar char="\" attribute="d_structure" context="c_scape_character" />
+</context>
+
+<context name="c_scape_character" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="." minimal="true" attribute="d_normal" context="#pop" />
+</context>
+
+<!-- Text blocks -->
+
+<context name="c_normal_text_block" attribute="d_normal" lineEndContext="#stay">
+ <IncludeRules context="c_strict_normal" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" endRegion="r_text_block"/>
+</context>
+
+<context name="c_text_block_finder" attribute="d_normal" lineEndContext="#stay">
+ <Detect2Chars char="[" char1=":" attribute="d_structure" context="c_normal_text_block" beginRegion="r_text_block" />
+ <RegExpr String="[\[][\x0022]" minimal="true" attribute="d_structure" context="c_normal_text_block" beginRegion="r_text_block"/>
+ <RegExpr String="\[(pre|footnote|blurb|warning|note|tip|important|pre|caution)(\b|\W|$)" minimal="true" attribute="d_structure" context="c_normal_text_block" beginRegion="r_text_block"/>
+</context>
+
+
+<context name="c_simple_text_block" attribute="d_anchor" lineEndContext="#stay">
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+ <RegExpr String="\s" minimal="true" attribute="d_structure" context="c_indirect_normal_block" />
+</context>
+
+<context name="c_simple_text_block_finder" attribute="d_normal" lineEndContext="#stay">
+ <DetectChar char="[" attribute="d_structure" context="c_simple_text_block" />
+</context>
+
+<!-- Includes -->
+
+<context name="c_included_path" attribute="d_path" lineEndContext="#stay">
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop#pop" />
+</context>
+
+<context name="c_include" attribute="d_anchor" lineEndContext="#stay">
+ <RegExpr String="\s" minimal="true" attribute="d_structure" context="c_included_path" />
+</context>
+
+<context name="c_includes_finder" attribute="d_normal" lineEndContext="#stay">
+ <StringDetect String="[include" attribute="d_structure" context="c_include" />
+ <StringDetect String="[xinclude" attribute="d_structure" context="c_include" />
+</context>
+
+<!-- Import -->
+
+<context name="c_import_path" attribute="d_path" lineEndContext="#stay">
+ <IncludeRules context="c_simple_text_block_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_import_finder" attribute="d_normal" lineEndContext="#stay">
+ <StringDetect String="[import" attribute="d_structure" context="c_import_path" />
+</context>
+
+<!-- Document Type logic -->
+
+<context name="c_quickbook_type_finder" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="\[(book|article|library|chapter|part|appendix|preface|qandadiv|qandaset|reference|set)\b" minimal="true" attribute="d_structure" context="c_documment_definition" beginRegion="r_documment_definition" />
+</context>
+
+<context name="c_documment_definition" attribute="d_normal_bold" lineEndContext="#stay">
+ <IncludeRules context="c_quickbook_attribute_finder" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" endRegion="r_documment_definition"/>
+</context>
+
+<context name="c_quickbook_attribute_finder" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="\[(quickbook|version|id|dirname|copyright|purpose|category|authors|license|source\-mode)\b" minimal="true" attribute="d_structure" context="c_normal_block" />
+
+</context>
+
+<!-- Tables
+
+ [table A Simple Table
+ [[Heading 1] [Heading 2] [Heading 3]]
+ [[R0-C0] [R0-C1] [R0-C2]]
+ [[R1-C0] [R1-C1] [R1-C2]]
+ [[R2-C0] [R2-C1] [R2-C2]]] -->
+
+<context name="c_table" attribute="d_normal_bold" lineEndContext="#stay">
+ <IncludeRules context="c_strict_normal" />
+ <DetectChar char="[" attribute="d_structure" context="c_table_title_row" />
+</context>
+
+<context name="c_table_title_row" attribute="d_nop" lineEndContext="#stay">
+
+ <!-- For performance the [endsect] resets the engine -->
+ <StringDetect String="[endsect]" attribute="d_structure" context="#pop#pop#pop#pop#pop" endRegion="r_section"/>
+
+ <DetectChar char="[" attribute="d_structure" context="c_table_title_cell" />
+ <DetectChar char="]" attribute="d_structure" context="c_table_body" />
+</context>
+
+<context name="c_table_title_cell" attribute="d_table_title_cell" lineEndContext="#stay">
+ <IncludeRules context="c_strict_normal" />
+
+ <DetectChar char="[" attribute="d_structure" context="c_table_cell" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_table_body" attribute="d_nop" lineEndContext="#stay">
+
+ <!-- For performance the [endsect] resets the engine -->
+ <StringDetect String="[endsect]" attribute="d_structure" context="#pop#pop#pop#pop#pop" endRegion="r_section"/>
+
+ <DetectChar char="[" attribute="d_structure" context="c_table_row" />
+ <DetectChar char="]" attribute="d_structure" context="#pop#pop#pop" endRegion="r_table"/>
+</context>
+
+<context name="c_table_row" attribute="d_nop" lineEndContext="#stay">
+
+ <!-- For performance the [endsect] resets the engine -->
+ <StringDetect String="[endsect]" attribute="d_structure" context="#pop#pop#pop#pop#pop" endRegion="r_section"/>
+
+ <DetectChar char="[" attribute="d_structure" context="c_table_cell" />
+
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_table_cell" attribute="d_normal" lineEndContext="#stay">
+ <IncludeRules context="c_normal" />
+ <RegExpr String="Row[\s]+[\d]+[\s]*,[\s]*Col[\s]+[\d]+[\s]*:" minimal="true" attribute="d_structure" context="#stay" />
+ <!--DetectChar char="[" attribute="d_structure" context="c_table_cell" /-->
+ <DetectChar char="]" attribute="d_structure" context="#pop" />
+</context>
+
+<context name="c_table_finder" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="\[table\b" minimal="true" attribute="d_structure" context="c_table" beginRegion="r_table" />
+</context>
+
+<!-- Variable List
+
+ [variablelist A Variable List
+ [[term 1] [The definition of term 1]]
+ [[term 2] [The definition of term 2]]
+ [[term 3] [The definition of term 3]]
+ ]
+ -->
+
+<context name="c_variable_list" attribute="d_normal_bold" lineEndContext="#stay">
+ <IncludeRules context="c_strict_normal" />
+ <DetectChar char="[" attribute="d_structure" context="c_var_list_body_1" />
+ <DetectChar char="]" attribute="d_structure" context="#pop" endRegion="r_variable_list"/>
+</context>
+
+<context name="c_var_list_body_1" attribute="d_nop" lineEndContext="#stay">
+
+ <!-- For performance the [endsect] resets the engine -->
+ <StringDetect String="[endsect]" attribute="d_structure" context="#pop#pop#pop#pop#pop" endRegion="r_section"/>
+
+ <DetectChar char="[" attribute="d_structure" context="c_var_list_element_name" />
+</context>
+
+<context name="c_var_list_body_2" attribute="d_nop" lineEndContext="#stay">
+
+ <!-- For performance the [endsect] resets the engine -->
+ <StringDetect String="[endsect]" attribute="d_structure" context="#pop#pop#pop#pop#pop" endRegion="r_section"/>
+
+ <DetectChar char="[" attribute="d_structure" context="c_var_list_element_info" />
+</context>
+
+<context name="c_var_list_body_3" attribute="d_nop" lineEndContext="#stay">
+ <DetectChar char="]" attribute="d_structure" context="#pop#pop#pop#pop#pop" />
+</context>
+
+<context name="c_var_list_element_name" attribute="d_list_element_name" lineEndContext="#stay">
+ <IncludeRules context="c_normal" />
+ <DetectChar char="]" attribute="d_structure" context="c_var_list_body_2" />
+</context>
+
+<context name="c_var_list_element_info" attribute="d_normal" lineEndContext="#stay">
+ <IncludeRules context="c_normal" />
+ <DetectChar char="]" attribute="d_structure" context="c_var_list_body_3" />
+</context>
+
+<context name="c_variable_list_finder" attribute="d_normal" lineEndContext="#stay">
+ <RegExpr String="\[variablelist\b" minimal="true" attribute="d_structure" context="c_variable_list" beginRegion="r_variable_list" />
+</context>
+
+
+<!--
+ boost::hs
+-->
+
+<context name="c_boost::hs call finder" attribute="d_boost::hs">
+ <StringDetect String="[/boost::hs::turn_off()]" attribute="d_boost::hs" context="c_scape_highlighting" />
+ <StringDetect String="[/boost::hs::turn_on()]" attribute="d_boost::hs" context="#stay" />
+ <StringDetect String="[/boost::hs::begin_region()]" attribute="d_boost::hs" context="#stay" beginRegion="r_boost::hs::region" />
+ <StringDetect String="[/boost::hs::end_region()]" attribute="d_boost::hs" context="#stay" endRegion="r_boost::hs::region" />
+</context>
+
+<context name="c_scape_highlighting" attribute="d_normal" lineEndContext="#stay">
+ <StringDetect String="[/boost::hs::turn_on()]" attribute="d_boost::hs" context="#pop" />
+ <StringDetect String="[/boost::hs::turn_off()]" attribute="d_boost::hs" context="#stay" />
+</context>
+
+</contexts>
+
+<!--
+ This section defines the colors and format of each type of string parsed
+ Try to use defaults so the user can change it as he wished
+-->
+
+<itemDatas>
+
+ <itemData name="d_normal" defStyleNum="dsNormal" />
+
+ <itemData name="d_normal_bold" bold="true" defStyleNum="dsNormal" />
+
+ <itemData name="d_normal_italic" italic="true" defStyleNum="dsNormal" />
+
+ <itemData name="d_normal_underline" underline="true" defStyleNum="dsNormal" />
+
+ <itemData name="d_normal_bold_italic" bold="true" italic="true" defStyleNum="dsNormal" />
+ <itemData name="d_normal_bold_underline" bold="true" underline="true" defStyleNum="dsNormal" />
+
+ <itemData name="d_normal_italic_underline" italic="true" underline="true" defStyleNum="dsNormal" />
+
+ <itemData name="d_normal_bold_italic_underline" bold="true" italic="true" underline="true" defStyleNum="dsNormal" />
+
+ <itemData name="d_normal_strikeout" strikeout="true" defStyleNum="dsNormal" />
+
+ <itemData name="d_normal_teletype" italic="true" defStyleNum="dsNormal" />
+
+ <itemData name="d_normal_replaceable" italic="true" defStyleNum="dsNormal" />
+
+ <itemData name="d_anchor" defStyleNum="dsDataType" />
+
+ <itemData name="d_macro" defStyleNum="dsDataType" />
+
+ <itemData name="d_path" defStyleNum="dsOthers" />
+
+ <itemData name="d_structure" color="#5555FF" defStyleNum="dsNormal" />
+
+ <itemData name="d_comment" defStyleNum="dsComment" />
+
+ <itemData name="d_table_title_cell" color="#000000" bold="true" backgroundColor="#E6E6E6" defStyleNum="dsNormal" />
+
+ <itemData name="d_list_element_name" bold="true" defStyleNum="dsNormal" />
+
+ <itemData name="d_nop" defStyleNum="dsComment" />
+
+ <itemData name="d_boost::hs" defStyleNum="dsFunction" />
+
+</itemDatas>
+
+<!-- Last Part, Give acces to some tools, for example comment/uncomment in edit menu -->
+
+</highlighting>
+
+<general>
+
+ <comments>
+
+ <comment name="multiLine" start="[/" end="]" region="r_comment" />
+
+ </comments>
+
+</general>
+
+</language>
+
+<!--
+
+Aknowelegments
+=================================================
+
+Boost.Quickbook is a poweful C++ documentation tool.
+It is developped by Joel de Guzman and Eric Niebler, I am very thankful they give
+this tool a Boost License and allowed C++ developpers to document their work
+in a easy and fun way.
+Check www.boost.org to get the tool and meet one of the most impressive c++
+library communities in the world.
+
+Version history
+=================================================
+
+[ 0.9.4 ] Add [heading ]
+Add templates
+Add import
+[ 0.9.3 ] "[endsect]" reset the engine to avoid lags in long files
+[ 0.9.2 ] Change file name ( quickbook_sintaxis.xml -> boost::hs::quickbook.xml )
+Change section ( Docs -> boost::hs ),
+Change name ( Boost.Quickbook -> quickbook )
+This changes aims to incorporate a boost kate sintaxis framework in KDE.
+[ 0.9.1 ] Fixed simple formating ( for example: "*this] [that*" is not longer bolded ).
+[ 0.9.0 ] Initial beta, sended to Joel de Guzman and Eric Niebler.
+
+Known bugs
+=================================================
+
+Feedback will be appreciated.
+They are very small and it is very unlikely to encounter one.
+
+* List items * and # are not fully implemented.
+* The line ` \\ C++ comment ` is not working because of Kate C++
+highlight definitions.
+* Python code is not yet supported.
+
+-->
diff --git a/tools/quickbook/extra/katepart/syntax/boost_hs_std.xml b/tools/quickbook/extra/katepart/syntax/boost_hs_std.xml
new file mode 100644
index 0000000000..202d3e560b
--- /dev/null
+++ b/tools/quickbook/extra/katepart/syntax/boost_hs_std.xml
@@ -0,0 +1,620 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE language SYSTEM "language.dtd">
+
+<language
+
+name="std-c++"
+version="0.1.0"
+kateversion="2.4"
+section="boost::hs"
+extensions="*.std"
+mimetype="allFiles"
+author="Copyright 2006 -2007 Matias Capeletto, matias.capeletto@gmail.com"
+priority="9"
+license="Distributed under the Boost Software License, Version 1.0.
+http://www.boost.org/LICENSE_1_0.txt"
+
+>
+
+
+
+<highlighting>
+
+<list name="std.free.function" >
+
+ <!-- std.algorithm -->
+
+ <item> adjacent_find </item>
+ <item> binary_search </item>
+ <item> copy </item>
+ <item> copy_backward </item>
+ <item> count </item>
+ <item> count_if </item>
+ <item> equal </item>
+ <item> equal_range </item>
+ <item> fill </item>
+ <item> fill_n </item>
+ <item> find </item>
+ <item> find_end </item>
+ <item> find_first_of </item>
+ <item> find_if </item>
+ <item> for_each </item>
+ <item> generate </item>
+ <item> generate_n </item>
+ <item> includes </item>
+ <item> inplace_merge </item>
+ <item> iter_swap </item>
+ <item> lexicographical_compare </item>
+ <item> lower_bound </item>
+ <item> make_heap </item>
+ <item> max </item>
+ <item> max_element </item>
+ <item> merge </item>
+ <item> min </item>
+ <item> min_element </item>
+ <item> mismatch </item>
+ <item> next_permutation </item>
+ <item> nth_element </item>
+ <item> partial_sort </item>
+ <item> partial_sort_copy </item>
+ <item> partition </item>
+ <item> pop_heap </item>
+ <item> prev_permutation </item>
+ <item> push_heap </item>
+ <item> random_shuffle </item>
+ <item> remove </item>
+ <item> remove_copy </item>
+ <item> remove_copy_if </item>
+ <item> remove_if </item>
+ <item> replace </item>
+ <item> replace_copy </item>
+ <item> replace_copy_if </item>
+ <item> replace_if </item>
+ <item> reverse </item>
+ <item> reverse_copy </item>
+ <item> rotate </item>
+ <item> rotate_copy </item>
+ <item> search </item>
+ <item> search_n </item>
+ <item> set_difference </item>
+ <item> set_intersection </item>
+ <item> set_symmetric_difference </item>
+ <item> set_union </item>
+ <item> sort </item>
+ <item> sort_heap </item>
+ <item> stable_partition </item>
+ <item> stable_sort </item>
+ <item> swap </item>
+ <item> swap_ranges </item>
+ <item> transform </item>
+ <item> unique </item>
+ <item> unique_copy </item>
+ <item> upper_bound </item>
+
+ <!-- std.assert -->
+
+ <item> assert </item>
+
+ <!-- std.math -->
+
+ <item> abs </item>
+ <item> arg </item>
+ <item> conj </item>
+ <item> cos </item>
+ <item> cosh </item>
+ <item> exp </item>
+ <item> imag </item>
+ <item> log </item>
+ <item> log10 </item>
+ <item> norm </item>
+ <item> polar </item>
+ <item> pow </item>
+ <item> real </item>
+ <item> sin </item>
+ <item> sinh </item>
+ <item> sqrt </item>
+ <item> tan </item>
+ <item> tanh </item>
+ <item> acos </item>
+ <item> asin </item>
+ <item> atan </item>
+ <item> atan2 </item>
+
+ <!-- std.exception -->
+
+ <item> terminate_handler </item>
+ <item> unexpected_handler </item>
+
+ <item> set_terminate </item>
+
+ <item> set_unexpected </item>
+ <item> terminate </item>
+ <item> unexpected </item>
+ <item> uncaught_exception </item>
+
+ <!-- std.iterator -->
+
+ <item> advance </item>
+ <item> distance </item>
+
+ <!-- std.memory -->
+
+ <item> get_temporary_buffer </item>
+ <item> return_temporary_buffer </item>
+ <item> uninitialized_copy </item>
+ <item> uninitialized_fill </item>
+ <item> uninitialized_fill_n </item>
+
+ <!-- std.new -->
+
+ <item> set_new_handler </item>
+
+ <!-- std.numeric -->
+
+ <item> accumulate </item>
+ <item> inner_product </item>
+ <item> partial_sum </item>
+ <item> adjacent_difference </item>
+
+ <!-- std.string -->
+
+ <item> getline </item>
+ <item> swap </item>
+
+ <!-- std.pair -->
+
+ <item> make_pair </item>
+
+ <!-- std.locale -->
+
+ <item> has_facet </item>
+ <item> use_facet </item>
+ <item> isalnum </item>
+ <item> isalpha </item>
+ <item> iscntrl </item>
+ <item> isdigit </item>
+ <item> isgraph </item>
+ <item> islower </item>
+ <item> isprint </item>
+ <item> ispunct </item>
+ <item> isspace </item>
+ <item> isupper </item>
+ <item> isxdigit </item>
+ <item> tolower </item>
+ <item> toupper </item>
+
+</list>
+
+<list name="std.template.classes" >
+
+ <!-- std.complex -->
+
+ <item> complex </item>
+
+ <!-- std_iterator -->
+
+ <item> back_insert_iterator </item>
+ <item> back_inserter </item>
+ <item> front_insert_iterator </item>
+ <item> front_inserter </item>
+ <item> insert_iterator </item>
+ <item> inserter </item>
+ <item> istream_iterator </item>
+ <item> istreambuf_iterator </item>
+ <item> iterator </item>
+ <item> ostream_iterator </item>
+ <item> ostreambuf_iterator </item>
+ <item> reverse_iterator </item>
+
+ <!-- std.memory -->
+
+ <item> allocator </item>
+ <item> raw_storage_iterator </item>
+ <item> auto_ptr </item>
+ <item> auto_ptr_ref </item>
+
+ <!-- std.string -->
+
+ <item> basic_string </item>
+
+ <!-- std.utility -->
+
+ <item> pair </item>
+
+ <!-- std.valarray -->
+
+ <item> gslice_array </item>
+ <item> indirect_array </item>
+ <item> mask_array </item>
+ <item> slice_array </item>
+ <item> valarray </item>
+
+ <!-- std.locale -->
+
+ <item> messages </item>
+ <item> codecvt_byname </item>
+ <item> collate </item>
+ <item> collate_byname </item>
+ <item> ctype </item>
+ <item> ctype_byname </item>
+ <item> messages_byname </item>
+ <item> money_base </item>
+ <item> money_get </item>
+ <item> money_put </item>
+ <item> moneypunct </item>
+ <item> moneypunct_byname </item>
+ <item> num_get </item>
+ <item> num_put </item>
+ <item> numpunct </item>
+ <item> numpunct_byname </item>
+ <item> time_base </item>
+ <item> time_get </item>
+ <item> time_get_byname </item>
+ <item> time_put </item>
+ <item> time_put_byname </item>
+
+ <!-- std.ios -->
+
+ <item> basic_ios </item>
+ <item> fpos </item>
+
+ <!-- std.ios_fwd -->
+
+ <item> istreambuf_iterator </item>
+ <item> ostreambuf_iterator </item>
+ <item> basic_streambuf </item>
+ <item> basic_istream </item>
+ <item> basic_ostream </item>
+ <item> basic_iostream </item>
+ <item> basic_stringbuf </item>
+ <item> basic_istringstream </item>
+ <item> basic_ostringstream </item>
+ <item> basic_stringstream </item>
+ <item> basic_filebuf </item>
+ <item> basic_ifstream </item>
+ <item> basic_ofstream </item>
+ <item> basic_fstream </item>
+
+</list>
+
+
+
+
+<list name="std.classes" >
+
+ <!-- std.iomanip -->
+
+ <item> resetiosflags </item>
+ <item> setiosflags </item>
+ <item> setbase </item>
+
+ <item> setfill </item>
+ <item> setprecision </item>
+ <item> setw </item>
+
+ <!-- std.new -->
+
+ <item> new_handler </item>
+ <item> nothrow_t </item>
+
+ <!-- std.string -->
+
+ <item> string </item>
+ <item> wstring </item>
+
+ <!-- std.valarray -->
+
+ <item> slice </item>
+ <item> gslice </item>
+
+ <!-- std.locale -->
+
+ <item> locale </item>
+ <item> codecvt </item>
+ <item> codecvt_base </item>
+ <item> ctype_base </item>
+ <item> messages_base </item>
+
+ <!-- std.ios -->
+
+ <item> ios_base </item>
+ <item> streamoff </item>
+ <item> streampos </item>
+ <item> streamsize </item>
+ <item> wios </item>
+ <item> wstreampos </item>
+ <item> ios </item>
+
+ <!-- std.ios_fwd -->
+
+ <item> streambuf </item>
+ <item> istream </item>
+ <item> ostream </item>
+ <item> iostream </item>
+ <item> stringbuf </item>
+ <item> istringstream </item>
+ <item> ostringstream </item>
+ <item> stringstream </item>
+ <item> filebuf </item>
+ <item> ifstream </item>
+ <item> ofstream </item>
+ <item> fstream </item>
+ <item> wstreambuf </item>
+ <item> wistream </item>
+ <item> wostream </item>
+ <item> wiostream </item>
+ <item> wstringbuf </item>
+ <item> wistringstream </item>
+ <item> wostringstream </item>
+ <item> wstringstream </item>
+ <item> wfilebuf </item>
+ <item> wifstream </item>
+ <item> wofstream </item>
+ <item> wfstream </item>
+
+</list>
+
+
+<list name="std.exceptions">
+
+ <!-- std.exception -->
+
+ <item> exception </item>
+ <item> bad_exception </item>
+
+ <!-- std.new -->
+
+ <item> bad_alloc </item>
+
+ <!-- std.stdexcept -->
+
+ <item> logic_error </item>
+ <item> domain_error </item>
+ <item> invalid_argument </item>
+ <item> length_error </item>
+ <item> out_of_range </item>
+
+ <item> runtime_error </item>
+ <item> range_error </item>
+ <item> overflow_error </item>
+ <item> underflow_error </item>
+
+ <!-- std.typeinfo -->
+
+ <item> bad_cast </item>
+ <item> bad_typeid </item>
+
+</list>
+
+
+<list name="std.macro" >
+
+ <!-- std.complex -->
+
+ <item> __STD_COMPLEX </item>
+
+</list>
+
+
+
+<list name="std.metaprograming">
+
+ <!-- std.functional -->
+
+ <item> binary_function </item>
+ <item> binary_negate </item>
+ <item> binder1st </item>
+ <item> binder2nd </item>
+ <item> const_mem_fun_t </item>
+ <item> const_mem_fun_ref_t </item>
+ <item> const_mem_fun1_t </item>
+ <item> const_mem_fun1_ref_t </item>
+ <item> divides </item>
+ <item> equal_to </item>
+ <item> greater </item>
+ <item> greater_equal </item>
+ <item> less </item>
+ <item> less_equal </item>
+ <item> logical_and </item>
+ <item> logical_not </item>
+ <item> logical_or </item>
+ <item> mem_fun_t </item>
+ <item> mem_fun_ref_t </item>
+ <item> mem_fun1_t </item>
+ <item> mem_fun1_ref_t </item>
+ <item> minus </item>
+ <item> modulus </item>
+ <item> multiplies </item>
+ <item> negate </item>
+ <item> not_equal_to </item>
+ <item> plus </item>
+ <item> pointer_to_binary_function </item>
+ <item> pointer_to_unary_function </item>
+ <item> unary_function </item>
+ <item> unary_negate </item>
+ <item> bind1st </item>
+ <item> bind2nd </item>
+ <item> mem_fun </item>
+ <item> mem_fun_ref </item>
+ <item> not1 </item>
+ <item> not2 </item>
+ <item> ptr_fun </item>
+
+ <!-- std.limits -->
+
+ <item> numeric_limits </item>
+
+ <!-- std.iterator -->
+
+ <item> iterator_traits </item>
+
+ <!-- std.string -->
+
+ <item> char_traits </item>
+
+ <!-- std.typeinfo -->
+
+ <item> type_info </item>
+
+</list>
+
+<list name="std.object">
+
+ <!-- std.iostream -->
+
+ <item> cin </item>
+ <item> cout </item>
+ <item> cerr </item>
+ <item> clog </item>
+
+ <item> wcin </item>
+ <item> wcout </item>
+ <item> wcerr </item>
+ <item> wclog </item>
+
+ <!-- std.new -->
+
+ <item> nothrow </item>
+
+</list>
+
+
+<list name="std.tags">
+
+ <item> bidirectional_iterator_tag </item>
+ <item> forward_iterator_tag </item>
+ <item> input_iterator_tag </item>
+ <item> output_iterator_tag </item>
+ <item> random_access_iterator_tag </item>
+
+</list>
+
+<list name="std.containers">
+
+ <item> bit_set </item>
+ <item> deque </item>
+ <item> list </item>
+ <item> queue </item>
+ <item> set </item>
+ <item> multiset </item>
+ <item> slist </item>
+ <item> map </item>
+ <item> multimap </item>
+ <item> unordered_map </item>
+ <item> stack </item>
+ <item> vector </item>
+
+</list>
+
+
+
+<list name="std.ios_manipulators">
+
+ <item> boolalpha </item>
+ <item> dec </item>
+ <item> fixed </item>
+ <item> hex </item>
+ <item> internal </item>
+ <item> left </item>
+ <item> noboolalpha </item>
+ <item> noshowbase </item>
+ <item> noshowpoint </item>
+ <item> noshowpos </item>
+ <item> noskipws </item>
+ <item> nounitbuf </item>
+ <item> nouppercase </item>
+ <item> oct </item>
+ <item> right </item>
+ <item> scientific </item>
+ <item> showbase </item>
+ <item> showpoint </item>
+ <item> showpos </item>
+ <item> skipws </item>
+ <item> unitbuf </item>
+ <item> uppercase </item>
+
+</list>
+
+
+<contexts>
+
+ <context name="main" attribute="std.free.function">
+
+ <keyword attribute="std.free.function" context="#stay" String="std.free.function" />
+ <keyword attribute="std.template.classes" context="#stay" String="std.template.classes" />
+ <keyword attribute="std.classes" context="#stay" String="std.classes" />
+ <keyword attribute="std.exceptions" context="#stay" String="std.exceptions" />
+ <keyword attribute="std.macro" context="#stay" String="std.macro" />
+ <keyword attribute="std.metaprogramming" context="#stay" String="std.metaprogramming" />
+ <keyword attribute="std.object" context="#stay" String="std.object" />
+ <keyword attribute="std.tags" context="#stay" String="std.tags" />
+ <keyword attribute="std.containers" context="#stay" String="std.containers" />
+ <keyword attribute="std.ios_manipulators" context="#stay" String="std.ios_manipulators" />
+
+ </context>
+
+</contexts>
+
+<itemDatas>
+
+ <itemData name="std.free.function" defStyleNum="dsFunction"/>
+ <itemData name="std.template.classes" defStyleNum="dsDataType"/>
+ <itemData name="std.classes" defStyleNum="dsDataType"/>
+ <itemData name="std.exceptions" defStyleNum="dsDataType"/>
+ <itemData name="std.macro" defStyleNum="dsOthers"/>
+ <itemData name="std.metaprogramming" defStyleNum="dsFunction"/>
+ <itemData name="std.object" defStyleNum="dsDataType"/>
+ <itemData name="std.tags" defStyleNum="dsOthers"/>
+ <itemData name="std.containers" defStyleNum="dsDataType"/>
+ <itemData name="std.ios_manipulators" defStyleNum="dsFunction"/>
+
+ <!--
+ This is an extract from the official Kate page
+ It is leave here as a reference.
+
+ dsNormal used for normal text.
+ dsKeyword used for keywords.
+ dsDataType used for data types.
+ dsDecVal used for decimal values.
+ dsBaseN used for values with a base other than 10.
+ dsFloat used for float values.
+ dsChar used for a character.
+ dsString used for strings.
+ dsComment used for comments.
+ dsOthers used for 'other' things.
+ dsAlert used for warning messages.
+ dsFunction used for function calls.
+ dsRegionMarker used for region markers.
+ dsError used for error highlighting and wrong syntax.
+
+ -->
+
+</itemDatas>
+
+</highlighting>
+
+<general>
+
+<keywords casesensitive="1" />
+
+</general>
+
+</language>
+
+
+<!--
+
+Aknowelegments
+=================================================
+
+
+
+Version history
+=================================================
+
+[ 0.1.0 ] Initial beta.
+
+Known bugs
+=================================================
+
+-->
diff --git a/tools/quickbook/index.html b/tools/quickbook/index.html
new file mode 100644
index 0000000000..35faddf3b8
--- /dev/null
+++ b/tools/quickbook/index.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <meta http-equiv="refresh" content="0; URL=../../doc/html/quickbook.html">
+ </head>
+ <body>
+ Automatic redirection failed, click this
+ <a href="../../doc/html/quickbook.html">link</a>
+ <p>Copyright&nbsp;Eric Niebler 2005</p>
+ <p>Distributed under the Boost Software License, Version 1.0. (See accompanying file
+ <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at
+ <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>).
+ </p>
+ </body>
+</html>
diff --git a/tools/quickbook/src/Jamfile.v2 b/tools/quickbook/src/Jamfile.v2
new file mode 100644
index 0000000000..9372559492
--- /dev/null
+++ b/tools/quickbook/src/Jamfile.v2
@@ -0,0 +1,60 @@
+#==============================================================================
+# Copyright (c) 2002 2004 2006 Joel de Guzman
+# Copyright (c) 2004 Eric Niebler
+# http://spirit.sourceforge.net/
+#
+# Use, modification and distribution is subject to the Boost Software
+# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+
+project quickbook
+ : requirements
+ <toolset>gcc:<c++-template-depth>300
+ <toolset>darwin:<c++-template-depth>300
+ <toolset>gcc:<cflags>-g0
+ <toolset>darwin:<cflags>-g0
+ <toolset>msvc:<cflags>/wd4709
+ ;
+
+lib shell32 ;
+
+exe quickbook
+ :
+ quickbook.cpp
+ actions.cpp
+ doc_info_actions.cpp
+ actions_class.cpp
+ utils.cpp
+ files.cpp
+ string_ref.cpp
+ input_path.cpp
+ values.cpp
+ id_manager.cpp
+ post_process.cpp
+ collector.cpp
+ template_stack.cpp
+ code_snippet.cpp
+ markups.cpp
+ syntax_highlight.cpp
+ grammar.cpp
+ main_grammar.cpp
+ block_element_grammar.cpp
+ phrase_element_grammar.cpp
+ doc_info_grammar.cpp
+ /boost//program_options
+ /boost//filesystem
+ : #<define>QUICKBOOK_NO_DATES
+ <define>BOOST_FILESYSTEM_NO_DEPRECATED
+ <toolset>msvc:<cxxflags>/wd4355
+ <toolset>msvc:<cxxflags>/wd4511
+ <toolset>msvc:<cxxflags>/wd4512
+ <toolset>msvc:<cxxflags>/wd4701
+ <toolset>msvc:<cxxflags>/wd4702
+ <toolset>msvc:<cxxflags>/wd4244
+ <toolset>msvc:<cxxflags>/wd4267
+ <toolset>msvc:<cxxflags>/wd4800
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <target-os>windows:<library>shell32
+ ;
diff --git a/tools/quickbook/src/actions.cpp b/tools/quickbook/src/actions.cpp
new file mode 100644
index 0000000000..4802893cb1
--- /dev/null
+++ b/tools/quickbook/src/actions.cpp
@@ -0,0 +1,1978 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ Copyright (c) 2005 Thomas Guest
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <numeric>
+#include <functional>
+#include <vector>
+#include <map>
+#include <boost/filesystem/v3/convenience.hpp>
+#include <boost/filesystem/v3/fstream.hpp>
+#include <boost/range/distance.hpp>
+#include <boost/range/algorithm/replace.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/next_prior.hpp>
+#include <boost/foreach.hpp>
+#include "quickbook.hpp"
+#include "actions.hpp"
+#include "utils.hpp"
+#include "files.hpp"
+#include "markups.hpp"
+#include "actions_class.hpp"
+#include "actions_state.hpp"
+#include "grammar.hpp"
+#include "input_path.hpp"
+#include "block_tags.hpp"
+#include "phrase_tags.hpp"
+#include "id_manager.hpp"
+
+namespace quickbook
+{
+ char const* quickbook_get_date = "__quickbook_get_date__";
+ char const* quickbook_get_time = "__quickbook_get_time__";
+
+ unsigned qbk_version_n = 0; // qbk_major_version * 100 + qbk_minor_version
+
+ namespace {
+ void write_anchors(quickbook::actions& actions, collector& tgt)
+ {
+ for(quickbook::actions::string_list::iterator
+ it = actions.anchors.begin(),
+ end = actions.anchors.end();
+ it != end; ++it)
+ {
+ tgt << "<anchor id=\"";
+ detail::print_string(*it, tgt.get());
+ tgt << "\"/>";
+ }
+
+ actions.anchors.clear();
+ }
+
+ std::string add_anchor(quickbook::actions& actions,
+ std::string const& id,
+ id_category::categories category =
+ id_category::explicit_anchor_id)
+ {
+ std::string placeholder = actions.ids.add_anchor(id, category);
+ actions.anchors.push_back(placeholder);
+ return placeholder;
+ }
+ }
+
+ void explicit_list_action(quickbook::actions&, value);
+ void header_action(quickbook::actions&, value);
+ void begin_section_action(quickbook::actions&, value);
+ void end_section_action(quickbook::actions&, value, string_iterator);
+ void block_action(quickbook::actions&, value);
+ void block_empty_action(quickbook::actions&, value);
+ void macro_definition_action(quickbook::actions&, value);
+ void template_body_action(quickbook::actions&, value);
+ void variable_list_action(quickbook::actions&, value);
+ void table_action(quickbook::actions&, value);
+ void xinclude_action(quickbook::actions&, value);
+ void include_action(quickbook::actions&, value, string_iterator);
+ void image_action(quickbook::actions&, value);
+ void anchor_action(quickbook::actions&, value);
+ void link_action(quickbook::actions&, value);
+ void phrase_action(quickbook::actions&, value);
+ void role_action(quickbook::actions&, value);
+ void footnote_action(quickbook::actions&, value);
+ void raw_phrase_action(quickbook::actions&, value);
+ void source_mode_action(quickbook::actions&, value);
+ void do_template_action(quickbook::actions&, value, string_iterator);
+
+ void element_action::operator()(parse_iterator first, parse_iterator) const
+ {
+ value_consumer values = actions.values.release();
+ if(!values.check() || !actions.conditional) return;
+ value v = values.consume();
+ values.finish();
+
+ switch(v.get_tag())
+ {
+ case block_tags::ordered_list:
+ case block_tags::itemized_list:
+ return explicit_list_action(actions, v);
+ case block_tags::generic_heading:
+ case block_tags::heading1:
+ case block_tags::heading2:
+ case block_tags::heading3:
+ case block_tags::heading4:
+ case block_tags::heading5:
+ case block_tags::heading6:
+ return header_action(actions, v);
+ case block_tags::begin_section:
+ return begin_section_action(actions, v);
+ case block_tags::end_section:
+ return end_section_action(actions, v, first.base());
+ case block_tags::blurb:
+ case block_tags::preformatted:
+ case block_tags::blockquote:
+ case block_tags::warning:
+ case block_tags::caution:
+ case block_tags::important:
+ case block_tags::note:
+ case block_tags::tip:
+ case block_tags::block:
+ return block_action(actions,v);
+ case block_tags::hr:
+ return block_empty_action(actions,v);
+ case block_tags::macro_definition:
+ return macro_definition_action(actions,v);
+ case block_tags::template_definition:
+ return template_body_action(actions,v);
+ case block_tags::variable_list:
+ return variable_list_action(actions, v);
+ case block_tags::table:
+ return table_action(actions, v);
+ case block_tags::xinclude:
+ return xinclude_action(actions, v);
+ case block_tags::import:
+ case block_tags::include:
+ return include_action(actions, v, first.base());
+ case phrase_tags::image:
+ return image_action(actions, v);
+ case phrase_tags::anchor:
+ return anchor_action(actions, v);
+ case phrase_tags::url:
+ case phrase_tags::link:
+ case phrase_tags::funcref:
+ case phrase_tags::classref:
+ case phrase_tags::memberref:
+ case phrase_tags::enumref:
+ case phrase_tags::macroref:
+ case phrase_tags::headerref:
+ case phrase_tags::conceptref:
+ case phrase_tags::globalref:
+ return link_action(actions, v);
+ case phrase_tags::bold:
+ case phrase_tags::italic:
+ case phrase_tags::underline:
+ case phrase_tags::teletype:
+ case phrase_tags::strikethrough:
+ case phrase_tags::quote:
+ case phrase_tags::replaceable:
+ return phrase_action(actions, v);
+ case phrase_tags::footnote:
+ return footnote_action(actions, v);
+ case phrase_tags::escape:
+ return raw_phrase_action(actions, v);
+ case phrase_tags::role:
+ return role_action(actions, v);
+ case source_mode_tags::cpp:
+ case source_mode_tags::python:
+ case source_mode_tags::teletype:
+ return source_mode_action(actions, v);
+ case template_tags::template_:
+ return do_template_action(actions, v, first.base());
+ default:
+ break;
+ }
+ }
+
+ void break_action::operator()(parse_iterator first, parse_iterator) const
+ {
+ write_anchors(actions, phrase);
+
+ if(*first == '\\')
+ {
+ detail::outwarn(actions.current_file, first.base())
+ //<< "in column:" << pos.column << ", "
+ << "'\\n' is deprecated, pleases use '[br]' instead" << ".\n";
+ }
+
+ if(!actions.warned_about_breaks)
+ {
+ detail::outwarn(actions.current_file, first.base())
+ << "line breaks generate invalid boostbook "
+ "(will only note first occurrence).\n";
+
+ actions.warned_about_breaks = true;
+ }
+
+ phrase << detail::get_markup(phrase_tags::break_mark).pre;
+ }
+
+ void error_message_action::operator()(parse_iterator first, parse_iterator last) const
+ {
+ file_position const pos = actions.current_file->position_of(first.base());
+
+ std::string value(first, last);
+ std::string formatted_message = message;
+ boost::replace_all(formatted_message, "%s", value);
+ boost::replace_all(formatted_message, "%c",
+ boost::lexical_cast<std::string>(pos.column));
+
+ detail::outerr(actions.current_file->path, pos.line)
+ << detail::utf8(formatted_message) << std::endl;
+ ++actions.error_count;
+ }
+
+ void error_action::operator()(parse_iterator first, parse_iterator /*last*/) const
+ {
+ file_position const pos = actions.current_file->position_of(first.base());
+
+ detail::outerr(actions.current_file->path, pos.line)
+ << "Syntax Error near column " << pos.column << ".\n";
+ ++actions.error_count;
+ }
+
+ void block_action(quickbook::actions& actions, value block)
+ {
+ write_anchors(actions, actions.out);
+
+ detail::markup markup = detail::get_markup(block.get_tag());
+
+ value_consumer values = block;
+ actions.out << markup.pre << values.consume().get_encoded() << markup.post;
+ values.finish();
+ }
+
+ void block_empty_action(quickbook::actions& actions, value block)
+ {
+ write_anchors(actions, actions.out);
+
+ detail::markup markup = detail::get_markup(block.get_tag());
+ actions.out << markup.pre;
+ }
+
+ void phrase_action(quickbook::actions& actions, value phrase)
+ {
+ write_anchors(actions, actions.phrase);
+
+ detail::markup markup = detail::get_markup(phrase.get_tag());
+
+ value_consumer values = phrase;
+ actions.phrase << markup.pre << values.consume().get_encoded() << markup.post;
+ values.finish();
+ }
+
+ void role_action(quickbook::actions& actions, value role)
+ {
+ write_anchors(actions, actions.phrase);
+
+ value_consumer values = role;
+ actions.phrase
+ << "<phrase role=\"";
+ detail::print_string(values.consume().get_quickbook(), actions.phrase.get());
+ actions.phrase
+ << "\">"
+ << values.consume().get_encoded()
+ << "</phrase>";
+ values.finish();
+ }
+
+ void footnote_action(quickbook::actions& actions, value phrase)
+ {
+ write_anchors(actions, actions.phrase);
+
+ value_consumer values = phrase;
+ actions.phrase
+ << "<footnote id=\""
+ << actions.ids.add_id("f", id_category::numbered)
+ << "\"><para>"
+ << values.consume().get_encoded()
+ << "</para></footnote>";
+ values.finish();
+ }
+
+ void raw_phrase_action(quickbook::actions& actions, value phrase)
+ {
+ write_anchors(actions, actions.phrase);
+
+ detail::markup markup = detail::get_markup(phrase.get_tag());
+ actions.phrase << markup.pre << phrase.get_quickbook() << markup.post;
+ }
+
+ void paragraph_action::operator()() const
+ {
+ std::string str;
+ actions.phrase.swap(str);
+
+ std::string::const_iterator
+ pos = str.begin(),
+ end = str.end();
+
+ while(pos != end && cl::space_p.test(*pos)) ++pos;
+
+ if(pos != end) {
+ detail::markup markup = detail::get_markup(block_tags::paragraph);
+ actions.out << markup.pre << str;
+ write_anchors(actions, actions.out);
+ actions.out << markup.post;
+ }
+ }
+
+ void list_item_action::operator()() const
+ {
+ std::string str;
+ actions.phrase.swap(str);
+ actions.out << str;
+ write_anchors(actions, actions.out);
+ }
+
+ void phrase_end_action::operator()() const
+ {
+ write_anchors(actions, actions.phrase);
+ }
+
+ namespace {
+ void write_bridgehead(quickbook::actions& actions, int level,
+ std::string const& str, std::string const& id, bool self_link)
+ {
+ if (self_link && !id.empty())
+ {
+ actions.out << "<bridgehead renderas=\"sect" << level << "\"";
+ actions.out << " id=\"";
+ actions.out << actions.ids.add_id("h", id_category::numbered);
+ actions.out << "\">";
+ actions.out << "<phrase id=\"" << id << "\"/>";
+ actions.out << "<link linkend=\"" << id << "\">";
+ actions.out << str;
+ actions.out << "</link>";
+ actions.out << "</bridgehead>";
+ }
+ else
+ {
+ actions.out << "<bridgehead renderas=\"sect" << level << "\"";
+ if(!id.empty()) actions.out << " id=\"" << id << "\"";
+ actions.out << ">";
+ actions.out << str;
+ actions.out << "</bridgehead>";
+ }
+ }
+ }
+
+ void header_action(quickbook::actions& actions, value heading_list)
+ {
+ value_consumer values = heading_list;
+
+ bool generic = heading_list.get_tag() == block_tags::generic_heading;
+ value element_id = values.optional_consume(general_tags::element_id);
+ value content = values.consume();
+ values.finish();
+
+ int level;
+
+ if (generic)
+ {
+ level = actions.ids.section_level() + 1;
+ // We need to use a heading which is one greater
+ // than the current.
+ if (level > 6 ) // The max is h6, clip it if it goes
+ level = 6; // further than that
+ }
+ else
+ {
+ level = heading_list.get_tag() - block_tags::heading1 + 1;
+ }
+
+ write_anchors(actions, actions.out);
+
+ if (!element_id.empty())
+ {
+ std::string anchor = actions.ids.add_id(
+ element_id.get_quickbook(),
+ id_category::explicit_id);
+
+ write_bridgehead(actions, level,
+ content.get_encoded(), anchor, self_linked_headers);
+ }
+ else if (!generic && actions.ids.compatibility_version() < 103) // version 1.2 and below
+ {
+ // This generates the old id style if both the interpreting
+ // version and the generation version are less then 103u.
+
+ std::string anchor = actions.ids.old_style_id(
+ detail::make_identifier(
+ actions.ids.replace_placeholders_with_unresolved_ids(
+ content.get_encoded())),
+ id_category::generated_heading);
+
+ write_bridgehead(actions, level,
+ content.get_encoded(), anchor, false);
+
+ }
+ else
+ {
+ std::string anchor = actions.ids.add_id(
+ detail::make_identifier(
+ actions.ids.compatibility_version() >= 106 ?
+ content.get_quickbook() :
+ actions.ids.replace_placeholders_with_unresolved_ids(
+ content.get_encoded())
+ ),
+ id_category::generated_heading);
+
+ write_bridgehead(actions, level,
+ content.get_encoded(), anchor, self_linked_headers);
+ }
+ }
+
+ void simple_phrase_action::operator()(char mark) const
+ {
+ write_anchors(actions, out);
+
+ int tag =
+ mark == '*' ? phrase_tags::bold :
+ mark == '/' ? phrase_tags::italic :
+ mark == '_' ? phrase_tags::underline :
+ mark == '=' ? phrase_tags::teletype :
+ 0;
+
+ assert(tag != 0);
+ detail::markup markup = detail::get_markup(tag);
+
+ value_consumer values = actions.values.release();
+ value content = values.consume();
+ values.finish();
+
+ out << markup.pre;
+ out << content.get_encoded();
+ out << markup.post;
+ }
+
+ bool cond_phrase_push::start()
+ {
+ value_consumer values = actions.values.release();
+
+ saved_conditional = actions.conditional;
+
+ if (saved_conditional)
+ {
+ string_ref macro1 = values.consume().get_quickbook();
+ std::string macro(macro1.begin(), macro1.end());
+
+ actions.conditional = find(actions.macro, macro.c_str());
+
+ if (!actions.conditional) {
+ actions.phrase.push();
+ actions.out.push();
+ actions.anchors.swap(anchors);
+ }
+ }
+
+ return true;
+ }
+
+ void cond_phrase_push::cleanup()
+ {
+ if (saved_conditional && !actions.conditional)
+ {
+ actions.phrase.pop();
+ actions.out.pop();
+ actions.anchors.swap(anchors);
+ }
+
+ actions.conditional = saved_conditional;
+ }
+
+ namespace {
+ int indent_length(std::string const& indent)
+ {
+ int length = 0;
+ for(std::string::const_iterator
+ first = indent.begin(), end = indent.end(); first != end; ++first)
+ {
+ switch(*first) {
+ case ' ': ++length; break;
+ // hardcoded tab to 4 for now
+ case '\t': length = ((length + 4) / 4) * 4; break;
+ default: BOOST_ASSERT(false);
+ }
+ }
+
+ return length;
+ }
+ }
+
+ void actions::start_list(char mark)
+ {
+ write_anchors(*this, out);
+ assert(mark == '*' || mark == '#');
+ out << ((mark == '#') ? "<orderedlist>\n" : "<itemizedlist>\n");
+ }
+
+ void actions::end_list(char mark)
+ {
+ write_anchors(*this, out);
+ assert(mark == '*' || mark == '#');
+ out << ((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
+ }
+
+ void actions::start_list_item()
+ {
+ out << "<listitem><simpara>";
+ write_anchors(*this, out);
+ }
+
+ void actions::end_list_item()
+ {
+ write_anchors(*this, out);
+ out << "</simpara></listitem>";
+ }
+
+ void explicit_list_action(quickbook::actions& actions, value list)
+ {
+ write_anchors(actions, actions.out);
+
+ detail::markup markup = detail::get_markup(list.get_tag());
+
+ actions.out << markup.pre;
+
+ BOOST_FOREACH(value item, list)
+ {
+ actions.out << "<listitem>";
+ actions.out << item.get_encoded();
+ actions.out << "</listitem>";
+ }
+
+ actions.out << markup.post;
+ }
+
+ void anchor_action(quickbook::actions& actions, value anchor)
+ {
+ value_consumer values = anchor;
+ value anchor_id = values.consume();
+ // Note: anchor_id is never encoded as boostbook. If it
+ // is encoded, it's just things like escapes.
+ add_anchor(actions, anchor_id.is_encoded() ?
+ anchor_id.get_encoded() : anchor_id.get_quickbook());
+ values.finish();
+ }
+
+ void do_macro_action::operator()(std::string const& str) const
+ {
+ write_anchors(actions, phrase);
+
+ if (str == quickbook_get_date)
+ {
+ char strdate[64];
+ strftime(strdate, sizeof(strdate), "%Y-%b-%d", current_time);
+ phrase << strdate;
+ }
+ else if (str == quickbook_get_time)
+ {
+ char strdate[64];
+ strftime(strdate, sizeof(strdate), "%I:%M:%S %p", current_time);
+ phrase << strdate;
+ }
+ else
+ {
+ phrase << str;
+ }
+ }
+
+ void raw_char_action::operator()(char ch) const
+ {
+ out << ch;
+ }
+
+ void raw_char_action::operator()(parse_iterator first, parse_iterator last) const
+ {
+ while (first != last)
+ out << *first++;
+ }
+
+ void source_mode_action(quickbook::actions& actions, value source_mode)
+ {
+ actions.source_mode = source_mode_tags::name(source_mode.get_tag());
+ }
+
+ void code_action::operator()(parse_iterator first, parse_iterator last) const
+ {
+ bool inline_code = type == inline_ ||
+ (type == inline_block && qbk_version_n < 106u);
+ bool block = type != inline_;
+
+ if (inline_code) {
+ write_anchors(actions, actions.phrase);
+ }
+ else {
+ actions.paragraph();
+ write_anchors(actions, actions.out);
+ }
+
+ std::string str;
+
+ if (block) {
+ // preprocess the code section to remove the initial indentation
+ mapped_file_builder mapped;
+ mapped.start(actions.current_file);
+ mapped.unindent_and_add(first.base(), last.base());
+
+ file_ptr f = mapped.release();
+
+ if (f->source.empty())
+ return; // Nothing left to do here. The program is empty.
+
+ parse_iterator first_(f->source.begin());
+ parse_iterator last_(f->source.end());
+
+ file_ptr saved_file = f;
+ boost::swap(actions.current_file, saved_file);
+
+ // print the code with syntax coloring
+ str = syntax_highlight(first_, last_, actions, actions.source_mode);
+
+ boost::swap(actions.current_file, saved_file);
+ }
+ else {
+ parse_iterator first_(first);
+ str = syntax_highlight(first_, last, actions, actions.source_mode);
+ }
+
+ if (block) {
+ collector& output = inline_code ? actions.phrase : actions.out;
+
+ // We must not place a \n after the <programlisting> tag
+ // otherwise PDF output starts code blocks with a blank line:
+ //
+ output << "<programlisting>";
+ output << str;
+ output << "</programlisting>\n";
+ }
+ else {
+ actions.phrase << "<code>";
+ actions.phrase << str;
+ actions.phrase << "</code>";
+ }
+ }
+
+ void plain_char_action::operator()(char ch) const
+ {
+ write_anchors(actions, phrase);
+
+ detail::print_char(ch, phrase.get());
+ }
+
+ void plain_char_action::operator()(parse_iterator first, parse_iterator last) const
+ {
+ write_anchors(actions, phrase);
+
+ while (first != last)
+ detail::print_char(*first++, phrase.get());
+ }
+
+ void escape_unicode_action::operator()(parse_iterator first, parse_iterator last) const
+ {
+ write_anchors(actions, phrase);
+
+ while(first != last && *first == '0') ++first;
+
+ // Just ignore \u0000
+ // Maybe I should issue a warning?
+ if(first == last) return;
+
+ std::string hex_digits(first, last);
+
+ if(hex_digits.size() == 2 && *first > '0' && *first <= '7') {
+ using namespace std;
+ detail::print_char(strtol(hex_digits.c_str(), 0, 16), phrase.get());
+ }
+ else {
+ phrase << "&#x" << hex_digits << ";";
+ }
+ }
+
+ void write_plain_text(std::ostream& out, value const& v)
+ {
+ if (v.is_encoded())
+ {
+ detail::print_string(v.get_encoded(), out);
+ }
+ else {
+ std::string value = v.get_quickbook();
+ for(std::string::const_iterator
+ first = value.begin(), last = value.end();
+ first != last; ++first)
+ {
+ if (*first == '\\' && ++first == last) break;
+ detail::print_char(*first, out);
+ }
+ }
+ }
+
+ void image_action(quickbook::actions& actions, value image)
+ {
+ write_anchors(actions, actions.phrase);
+
+ // Note: attributes are never encoded as boostbook, if they're
+ // encoded, it's just things like escapes.
+ typedef std::map<std::string, value> attribute_map;
+ attribute_map attributes;
+
+ value_consumer values = image;
+ attributes["fileref"] = values.consume();
+
+ BOOST_FOREACH(value pair_, values)
+ {
+ value_consumer pair = pair_;
+ value name = pair.consume();
+ value value = pair.consume();
+ pair.finish();
+ if(!attributes.insert(std::make_pair(name.get_quickbook(), value)).second)
+ {
+ detail::outwarn(name.get_file(), name.get_position())
+ << "Duplicate image attribute: "
+ << detail::utf8(name.get_quickbook())
+ << std::endl;
+ }
+ }
+
+ values.finish();
+
+ // Find the file basename and extension.
+ //
+ // Not using Boost.Filesystem because I want to stay in UTF-8.
+ // Need to think about uri encoding.
+
+ std::string fileref = attributes["fileref"].is_encoded() ?
+ attributes["fileref"].get_encoded() :
+ attributes["fileref"].get_quickbook();
+
+ // Check for windows paths, then convert.
+ // A bit crude, but there you go.
+
+ if(fileref.find('\\') != std::string::npos)
+ {
+ (qbk_version_n >= 106u ?
+ detail::outerr(attributes["fileref"].get_file(), attributes["fileref"].get_position()) :
+ detail::outwarn(attributes["fileref"].get_file(), attributes["fileref"].get_position()))
+ << "Image path isn't portable: '"
+ << detail::utf8(fileref)
+ << "'"
+ << std::endl;
+ if (qbk_version_n >= 106u) ++actions.error_count;
+ }
+
+ boost::replace(fileref, '\\', '/');
+
+ // Find the file basename and extension.
+ //
+ // Not using Boost.Filesystem because I want to stay in UTF-8.
+ // Need to think about uri encoding.
+
+ std::string::size_type pos;
+ std::string stem, extension;
+
+ pos = fileref.rfind('/');
+ stem = pos == std::string::npos ?
+ fileref :
+ fileref.substr(pos + 1);
+
+ pos = stem.rfind('.');
+ if (pos != std::string::npos)
+ {
+ extension = stem.substr(pos + 1);
+ stem = stem.substr(0, pos);
+ }
+
+ // Extract the alt tag, to use as a text description.
+ // Or if there isn't one, use the stem of the file name.
+
+ attribute_map::iterator alt_pos = attributes.find("alt");
+ quickbook::value alt_text =
+ alt_pos != attributes.end() ? alt_pos->second :
+ qbk_version_n < 106u ? encoded_value(stem) :
+ quickbook::value();
+ attributes.erase("alt");
+
+ if(extension == "svg")
+ {
+ //
+ // SVG's need special handling:
+ //
+ // 1) We must set the "format" attribute, otherwise
+ // HTML generation produces code that will not display
+ // the image at all.
+ // 2) We need to set the "contentwidth" and "contentdepth"
+ // attributes, otherwise the image will be displayed inside
+ // a tiny box with scrollbars (Firefox), or else cropped to
+ // fit in a tiny box (IE7).
+ //
+
+ attributes.insert(attribute_map::value_type("format",
+ encoded_value("SVG")));
+
+ //
+ // Image paths are relative to the html subdirectory:
+ //
+ fs::path img = detail::generic_to_path(fileref);
+ if (!img.has_root_directory())
+ img = quickbook::image_location / img; // relative path
+
+ //
+ // Now load the SVG file:
+ //
+ std::string svg_text;
+ fs::ifstream fs(img);
+ char c;
+ while(fs.get(c) && fs.good())
+ svg_text.push_back(c);
+ //
+ // Extract the svg header from the file:
+ //
+ std::string::size_type a, b;
+ a = svg_text.find("<svg");
+ b = svg_text.find('>', a);
+ svg_text = (a == std::string::npos) ? "" : svg_text.substr(a, b - a);
+ //
+ // Now locate the "width" and "height" attributes
+ // and borrow their values:
+ //
+ a = svg_text.find("width");
+ a = svg_text.find('=', a);
+ a = svg_text.find('\"', a);
+ b = svg_text.find('\"', a + 1);
+ if(a != std::string::npos)
+ {
+ attributes.insert(std::make_pair(
+ "contentwidth", encoded_value(std::string(
+ svg_text.begin() + a + 1, svg_text.begin() + b))
+ ));
+ }
+ a = svg_text.find("height");
+ a = svg_text.find('=', a);
+ a = svg_text.find('\"', a);
+ b = svg_text.find('\"', a + 1);
+ if(a != std::string::npos)
+ {
+ attributes.insert(std::make_pair(
+ "contentdepth", encoded_value(std::string(
+ svg_text.begin() + a + 1, svg_text.begin() + b))
+ ));
+ }
+ }
+
+ actions.phrase << "<inlinemediaobject>";
+
+ actions.phrase << "<imageobject><imagedata";
+
+ BOOST_FOREACH(attribute_map::value_type const& attr, attributes)
+ {
+ actions.phrase << " " << attr.first << "=\"";
+ write_plain_text(actions.phrase.get(), attr.second);
+ actions.phrase << "\"";
+ }
+
+ actions.phrase << "></imagedata></imageobject>";
+
+ // Add a textobject containing the alt tag from earlier.
+ // This will be used for the alt tag in html.
+ if (alt_text.check()) {
+ actions.phrase << "<textobject><phrase>";
+ write_plain_text(actions.phrase.get(), alt_text);
+ actions.phrase << "</phrase></textobject>";
+ }
+
+ actions.phrase << "</inlinemediaobject>";
+ }
+
+ void macro_definition_action(quickbook::actions& actions, quickbook::value macro_definition)
+ {
+ value_consumer values = macro_definition;
+ std::string macro_id = values.consume().get_quickbook();
+ value phrase_value = values.optional_consume();
+ std::string phrase;
+ if (phrase_value.check()) phrase = phrase_value.get_encoded();
+ values.finish();
+
+ std::string* existing_macro =
+ boost::spirit::classic::find(actions.macro, macro_id.c_str());
+ quickbook::ignore_variable(&existing_macro);
+
+ if (existing_macro)
+ {
+ if (qbk_version_n < 106) return;
+
+ // Do this if you're using spirit's TST.
+ //
+ // *existing_macro = phrase;
+ // return;
+ }
+
+ actions.macro.add(
+ macro_id.begin()
+ , macro_id.end()
+ , phrase);
+ }
+
+ void template_body_action(quickbook::actions& actions, quickbook::value template_definition)
+ {
+ value_consumer values = template_definition;
+ std::string identifier = values.consume().get_quickbook();
+
+ std::vector<std::string> template_values;
+ BOOST_FOREACH(value const& p, values.consume()) {
+ template_values.push_back(p.get_quickbook());
+ }
+
+ BOOST_ASSERT(values.check(template_tags::block) || values.check(template_tags::phrase));
+ value body = values.consume();
+ BOOST_ASSERT(!values.check());
+
+ if (!actions.templates.add(
+ template_symbol(
+ identifier,
+ template_values,
+ body,
+ &actions.templates.top_scope())))
+ {
+ detail::outwarn(body.get_file(), body.get_position())
+ << "Template Redefinition: " << detail::utf8(identifier) << std::endl;
+ ++actions.error_count;
+ }
+ }
+
+ namespace
+ {
+ string_iterator find_first_seperator(string_iterator begin, string_iterator end)
+ {
+ if(qbk_version_n < 105) {
+ for(;begin != end; ++begin)
+ {
+ switch(*begin)
+ {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ return begin;
+ default:
+ break;
+ }
+ }
+ }
+ else {
+ unsigned int depth = 0;
+
+ for(;begin != end; ++begin)
+ {
+ switch(*begin)
+ {
+ case '[':
+ ++depth;
+ break;
+ case '\\':
+ if(++begin == end) return begin;
+ break;
+ case ']':
+ if (depth > 0) --depth;
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ if (depth == 0) return begin;
+ default:
+ break;
+ }
+ }
+ }
+
+ return begin;
+ }
+
+ std::pair<string_iterator, string_iterator> find_seperator(string_iterator begin, string_iterator end)
+ {
+ string_iterator first = begin = find_first_seperator(begin, end);
+
+ for(;begin != end; ++begin)
+ {
+ switch(*begin)
+ {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ default:
+ return std::make_pair(first, begin);
+ }
+ }
+
+ return std::make_pair(first, begin);
+ }
+
+ void break_arguments(
+ std::vector<value>& args
+ , std::vector<std::string> const& params
+ , fs::path const& filename
+ )
+ {
+ // Quickbook 1.4-: If there aren't enough parameters seperated by
+ // '..' then seperate the last parameter using
+ // whitespace.
+ // Quickbook 1.5+: If '..' isn't used to seperate the parameters
+ // then use whitespace to separate them
+ // (2 = template name + argument).
+
+ if (qbk_version_n < 105 || args.size() == 1)
+ {
+
+ while (args.size() < params.size())
+ {
+ // Try to break the last argument at the first space found
+ // and push it into the back of args. Do this
+ // recursively until we have all the expected number of
+ // arguments, or if there are no more spaces left.
+
+ value last_arg = args.back();
+ string_iterator begin = last_arg.get_quickbook().begin();
+ string_iterator end = last_arg.get_quickbook().end();
+
+ std::pair<string_iterator, string_iterator> pos =
+ find_seperator(begin, end);
+ if (pos.second == end) break;
+ value new_arg(
+ qbk_value(last_arg.get_file(),
+ pos.second, end, template_tags::phrase));
+
+ args.back() = qbk_value(last_arg.get_file(),
+ begin, pos.first, last_arg.get_tag());
+ args.push_back(new_arg);
+ }
+ }
+ }
+
+ std::pair<bool, std::vector<std::string>::const_iterator>
+ get_arguments(
+ std::vector<value> const& args
+ , std::vector<std::string> const& params
+ , template_scope const& scope
+ , string_iterator first
+ , quickbook::actions& actions
+ )
+ {
+ std::vector<value>::const_iterator arg = args.begin();
+ std::vector<std::string>::const_iterator tpl = params.begin();
+ std::vector<std::string> empty_params;
+
+ // Store each of the argument passed in as local templates:
+ while (arg != args.end())
+ {
+ if (!actions.templates.add(
+ template_symbol(*tpl, empty_params, *arg, &scope)))
+ {
+ detail::outerr(actions.current_file, first)
+ << "Duplicate Symbol Found" << std::endl;
+ ++actions.error_count;
+ return std::make_pair(false, tpl);
+ }
+ ++arg; ++tpl;
+ }
+ return std::make_pair(true, tpl);
+ }
+
+ bool parse_template(
+ value const& content
+ , quickbook::actions& actions
+ )
+ {
+ file_ptr saved_current_file = actions.current_file;
+
+ actions.current_file = content.get_file();
+ string_ref source = content.get_quickbook();
+
+ parse_iterator first(source.begin());
+ parse_iterator last(source.end());
+
+ bool r = cl::parse(first, last,
+ content.get_tag() == template_tags::block ?
+ actions.grammar().block :
+ actions.grammar().inline_phrase
+ ).full;
+
+ boost::swap(actions.current_file, saved_current_file);
+
+ return r;
+ }
+ }
+
+ void call_template(quickbook::actions& actions,
+ template_symbol const* symbol,
+ std::vector<value> const& args,
+ string_iterator first)
+ {
+ // If this template contains already encoded text, then just
+ // write it out, without going through any of the rigamarole.
+
+ if (symbol->content.is_encoded())
+ {
+ if (symbol->content.get_tag() == template_tags::block)
+ {
+ actions.paragraph();
+ actions.out << symbol->content.get_encoded();
+ }
+ else
+ {
+ actions.phrase << symbol->content.get_encoded();
+ }
+
+ return;
+ }
+
+ // The template arguments should have the scope that the template was
+ // called from, not the template's own scope.
+ //
+ // Note that for quickbook 1.4- this value is just ignored when the
+ // arguments are expanded.
+ template_scope const& call_scope = actions.templates.top_scope();
+
+ std::string block;
+ std::string phrase;
+
+ {
+ template_state state(actions);
+ actions.templates.start_template(symbol);
+
+ qbk_version_n = symbol->content.get_file()->version();
+
+ ++actions.template_depth;
+ if (actions.template_depth > actions.max_template_depth)
+ {
+ detail::outerr(actions.current_file, first)
+ << "Infinite loop detected" << std::endl;
+ ++actions.error_count;
+ return;
+ }
+
+ // Store the current section level so that we can ensure that
+ // [section] and [endsect] tags in the template are balanced.
+ actions.min_section_level = actions.ids.section_level();
+
+ ///////////////////////////////////
+ // Prepare the arguments as local templates
+ bool get_arg_result;
+ std::vector<std::string>::const_iterator tpl;
+ boost::tie(get_arg_result, tpl) =
+ get_arguments(args, symbol->params, call_scope, first, actions);
+
+ if (!get_arg_result)
+ {
+ return;
+ }
+
+ ///////////////////////////////////
+ // parse the template body:
+
+ if (!parse_template(symbol->content, actions))
+ {
+ detail::outerr(actions.current_file, first)
+ << "Expanding "
+ << (symbol->content.get_tag() == template_tags::block ? "block" : "phrase")
+ << " template: " << detail::utf8(symbol->identifier) << std::endl
+ << std::endl
+ << "------------------begin------------------" << std::endl
+ << detail::utf8(symbol->content.get_quickbook())
+ << "------------------end--------------------" << std::endl
+ << std::endl;
+ ++actions.error_count;
+ return;
+ }
+
+ if (actions.ids.section_level() != actions.min_section_level)
+ {
+ detail::outerr(actions.current_file, first)
+ << "Mismatched sections in template "
+ << detail::utf8(symbol->identifier)
+ << std::endl;
+ ++actions.error_count;
+ return;
+ }
+
+ actions.out.swap(block);
+ actions.phrase.swap(phrase);
+ }
+
+ if(symbol->content.get_tag() == template_tags::block || !block.empty()) {
+ actions.paragraph(); // For paragraphs before the template call.
+ actions.out << block;
+ actions.phrase << phrase;
+ actions.paragraph();
+ }
+ else {
+ actions.phrase << phrase;
+ }
+ }
+
+ void call_code_snippet(quickbook::actions& actions,
+ template_symbol const* symbol,
+ string_iterator first)
+ {
+ value_consumer values = symbol->content;
+ value content = values.consume(template_tags::block);
+ value callouts = values.consume();
+ values.finish();
+
+ std::vector<std::string> callout_ids;
+ std::vector<value> args;
+ unsigned int size = symbol->params.size();
+ std::string callout_base("c");
+
+ for(unsigned int i = 0; i < size; ++i)
+ {
+ std::string callout_id1 = actions.ids.add_id(callout_base, id_category::numbered);
+ std::string callout_id2 = actions.ids.add_id(callout_base, id_category::numbered);
+
+ std::string code;
+ code += "<co id=\"" + callout_id1 + "\" ";
+ code += "linkends=\"" + callout_id2 + "\" />";
+
+ args.push_back(encoded_value(code, template_tags::phrase));
+ callout_ids.push_back(callout_id1);
+ callout_ids.push_back(callout_id2);
+ }
+
+ // Create a fake symbol for call_template
+ template_symbol t(
+ symbol->identifier,
+ symbol->params,
+ content,
+ symbol->lexical_parent);
+ call_template(actions, &t, args, first);
+
+ std::string block;
+
+ if(!callouts.empty())
+ {
+ block += "<calloutlist>";
+ int i = 0;
+ BOOST_FOREACH(value c, callouts)
+ {
+ std::string callout_id1 = callout_ids[i++];
+ std::string callout_id2 = callout_ids[i++];
+
+ std::string callout_value;
+ {
+ template_state state(actions);
+ ++actions.template_depth;
+
+ bool r = parse_template(c, actions);
+
+ if(!r)
+ {
+ detail::outerr(c.get_file(), c.get_position())
+ << "Expanding callout." << std::endl
+ << "------------------begin------------------" << std::endl
+ << detail::utf8(c.get_quickbook())
+ << std::endl
+ << "------------------end--------------------" << std::endl
+ ;
+ ++actions.error_count;
+ return;
+ }
+
+ actions.out.swap(callout_value);
+ }
+
+ block += "<callout arearefs=\"" + callout_id1 + "\" ";
+ block += "id=\"" + callout_id2 + "\">";
+ block += callout_value;
+ block += "</callout>";
+ }
+ block += "</calloutlist>";
+ }
+
+ actions.out << block;
+ }
+
+ void do_template_action(quickbook::actions& actions, value template_list,
+ string_iterator first)
+ {
+ // Get the arguments
+ value_consumer values = template_list;
+
+ bool template_escape = values.check(template_tags::escape);
+ if(template_escape) values.consume();
+
+ std::string identifier = values.consume(template_tags::identifier).get_quickbook();
+
+ std::vector<value> args;
+
+ BOOST_FOREACH(value arg, values)
+ {
+ args.push_back(arg);
+ }
+
+ values.finish();
+
+ template_symbol const* symbol = actions.templates.find(identifier);
+ BOOST_ASSERT(symbol);
+
+ // Deal with escaped templates.
+
+ if (template_escape)
+ {
+ if (!args.empty())
+ {
+ detail::outerr(actions.current_file, first)
+ << "Arguments for escaped template."
+ <<std::endl;
+ ++actions.error_count;
+ }
+
+ if (symbol->content.is_encoded())
+ {
+ actions.phrase << symbol->content.get_encoded();
+ }
+ else
+ {
+ actions.phrase << symbol->content.get_quickbook();
+
+ /*
+
+ This would surround the escaped template in escape
+ comments to indicate to the post-processor that it
+ isn't quickbook generated markup. But I'm not sure if
+ it would work.
+
+ quickbook::detail::markup escape_markup
+ = detail::get_markup(phrase_tags::escape);
+
+ actions.phrase
+ << escape_markup.pre
+ << symbol->content.get_quickbook()
+ << escape_markup.post
+ ;
+ */
+ }
+
+ return;
+ }
+
+ ///////////////////////////////////
+ // Initialise the arguments
+
+ switch(symbol->content.get_tag())
+ {
+ case template_tags::block:
+ case template_tags::phrase:
+ // Break the arguments for a template
+
+ break_arguments(args, symbol->params, actions.current_file->path);
+
+ if (args.size() != symbol->params.size())
+ {
+ detail::outerr(actions.current_file, first)
+ << "Invalid number of arguments passed. Expecting: "
+ << symbol->params.size()
+ << " argument(s), got: "
+ << args.size()
+ << " argument(s) instead."
+ << std::endl;
+
+ ++actions.error_count;
+ return;
+ }
+
+ call_template(actions, symbol, args, first);
+ break;
+
+ case template_tags::snippet:
+
+ if (!args.empty())
+ {
+ detail::outerr(actions.current_file, first)
+ << "Arguments for code snippet."
+ <<std::endl;
+ ++actions.error_count;
+
+ args.clear();
+ }
+
+ call_code_snippet(actions, symbol, first);
+ break;
+
+ default:
+ assert(0);
+ }
+ }
+
+ void link_action(quickbook::actions& actions, value link)
+ {
+ write_anchors(actions, actions.phrase);
+
+ detail::markup markup = detail::get_markup(link.get_tag());
+
+ value_consumer values = link;
+ value dst_value = values.consume();
+ value content = values.consume();
+ values.finish();
+
+ // Note: dst is never actually encoded as boostbook, which
+ // is why the result is called with 'print_string' later.
+ std::string dst = dst_value.is_encoded() ?
+ dst_value.get_encoded() : dst_value.get_quickbook();
+
+ actions.phrase << markup.pre;
+ detail::print_string(dst, actions.phrase.get());
+ actions.phrase << "\">";
+
+ if (content.empty())
+ detail::print_string(dst, actions.phrase.get());
+ else
+ actions.phrase << content.get_encoded();
+
+ actions.phrase << markup.post;
+ }
+
+ void variable_list_action(quickbook::actions& actions, value variable_list)
+ {
+ write_anchors(actions, actions.out);
+
+ value_consumer values = variable_list;
+ std::string title = values.consume(table_tags::title).get_quickbook();
+
+ actions.out << "<variablelist>\n";
+
+ actions.out << "<title>";
+ detail::print_string(title, actions.out.get());
+ actions.out << "</title>\n";
+
+ BOOST_FOREACH(value_consumer entry, values) {
+ actions.out << "<varlistentry>";
+
+ if(entry.check()) {
+ actions.out << "<term>";
+ actions.out << entry.consume().get_encoded();
+ actions.out << "</term>";
+ }
+
+ if(entry.check()) {
+ actions.out << "<listitem>";
+ BOOST_FOREACH(value phrase, entry) actions.out << phrase.get_encoded();
+ actions.out << "</listitem>";
+ }
+
+ actions.out << "</varlistentry>\n";
+ }
+
+ actions.out << "</variablelist>\n";
+
+ values.finish();
+ }
+
+ void table_action(quickbook::actions& actions, value table)
+ {
+ write_anchors(actions, actions.out);
+
+ value_consumer values = table;
+
+ std::string element_id;
+ if(values.check(general_tags::element_id))
+ element_id = values.consume().get_quickbook();
+
+ value title = values.consume(table_tags::title);
+ bool has_title = !title.empty();
+
+ std::string table_id;
+
+ if (!element_id.empty()) {
+ table_id = actions.ids.add_id(element_id, id_category::explicit_id);
+ }
+ else if (has_title) {
+ if (actions.ids.compatibility_version() >= 105) {
+ table_id = actions.ids.add_id(detail::make_identifier(title.get_quickbook()), id_category::generated);
+ }
+ else {
+ table_id = actions.ids.add_id("t", id_category::numbered);
+ }
+ }
+
+ // Emulating the old behaviour which used the width of the final
+ // row for span_count.
+ int row_count = 0;
+ int span_count = 0;
+
+ value_consumer lookahead = values;
+ BOOST_FOREACH(value row, lookahead) {
+ ++row_count;
+ span_count = boost::distance(row);
+ }
+ lookahead.finish();
+
+ if (has_title)
+ {
+ actions.out << "<table frame=\"all\"";
+ if(!table_id.empty())
+ actions.out << " id=\"" << table_id << "\"";
+ actions.out << ">\n";
+ actions.out << "<title>";
+ if (qbk_version_n < 106u) {
+ detail::print_string(title.get_quickbook(), actions.out.get());
+ }
+ else {
+ actions.out << title.get_encoded();
+ }
+ actions.out << "</title>";
+ }
+ else
+ {
+ actions.out << "<informaltable frame=\"all\"";
+ if(!table_id.empty())
+ actions.out << " id=\"" << table_id << "\"";
+ actions.out << ">\n";
+ }
+
+ actions.out << "<tgroup cols=\"" << span_count << "\">\n";
+
+ if (row_count > 1)
+ {
+ actions.out << "<thead>" << "<row>";
+ BOOST_FOREACH(value cell, values.consume()) {
+ actions.out << "<entry>" << cell.get_encoded() << "</entry>";
+ }
+ actions.out << "</row>\n" << "</thead>\n";
+ }
+
+ actions.out << "<tbody>\n";
+
+ BOOST_FOREACH(value row, values) {
+ actions.out << "<row>";
+ BOOST_FOREACH(value cell, row) {
+ actions.out << "<entry>" << cell.get_encoded() << "</entry>";
+ }
+ actions.out << "</row>\n";
+ }
+
+ values.finish();
+
+ actions.out << "</tbody>\n"
+ << "</tgroup>\n";
+
+ if (has_title)
+ {
+ actions.out << "</table>\n";
+ }
+ else
+ {
+ actions.out << "</informaltable>\n";
+ }
+ }
+
+ void begin_section_action(quickbook::actions& actions, value begin_section_list)
+ {
+ value_consumer values = begin_section_list;
+
+ value element_id = values.optional_consume(general_tags::element_id);
+ value content = values.consume();
+ values.finish();
+
+ std::string full_id = actions.ids.begin_section(
+ !element_id.empty() ?
+ element_id.get_quickbook() :
+ detail::make_identifier(content.get_quickbook()),
+ !element_id.empty() ?
+ id_category::explicit_section_id :
+ id_category::generated_section);
+
+ actions.out << "\n<section id=\"" << full_id << "\">\n";
+ actions.out << "<title>";
+
+ write_anchors(actions, actions.out);
+
+ if (self_linked_headers && actions.ids.compatibility_version() >= 103)
+ {
+ actions.out << "<link linkend=\"" << full_id << "\">"
+ << content.get_encoded()
+ << "</link>"
+ ;
+ }
+ else
+ {
+ actions.out << content.get_encoded();
+ }
+
+ actions.out << "</title>\n";
+ }
+
+ void end_section_action(quickbook::actions& actions, value end_section, string_iterator first)
+ {
+ write_anchors(actions, actions.out);
+
+ if (actions.ids.section_level() <= actions.min_section_level)
+ {
+ file_position const pos = actions.current_file->position_of(first);
+
+ detail::outerr(actions.current_file->path, pos.line)
+ << "Mismatched [endsect] near column " << pos.column << ".\n";
+ ++actions.error_count;
+
+ return;
+ }
+
+ actions.out << "</section>";
+ actions.ids.end_section();
+ }
+
+ void element_id_warning_action::operator()(parse_iterator first, parse_iterator) const
+ {
+ detail::outwarn(actions.current_file, first.base()) << "Empty id.\n";
+ }
+
+ // Not a general purpose normalization function, just
+ // from paths from the root directory. It strips the excess
+ // ".." parts from a path like: "x/../../y", leaving "y".
+ std::vector<fs::path> normalize_path_from_root(fs::path const& path)
+ {
+ assert(!path.has_root_directory() && !path.has_root_name());
+
+ std::vector<fs::path> parts;
+
+ BOOST_FOREACH(fs::path const& part, path)
+ {
+ if (part.empty() || part == ".") {
+ }
+ else if (part == "..") {
+ if (!parts.empty()) parts.pop_back();
+ }
+ else {
+ parts.push_back(part);
+ }
+ }
+
+ return parts;
+ }
+
+ // The relative path from base to path
+ fs::path path_difference(fs::path const& base, fs::path const& path)
+ {
+ fs::path
+ absolute_base = fs::absolute(base),
+ absolute_path = fs::absolute(path);
+
+ // Remove '.', '..' and empty parts from the remaining path
+ std::vector<fs::path>
+ base_parts = normalize_path_from_root(absolute_base.relative_path()),
+ path_parts = normalize_path_from_root(absolute_path.relative_path());
+
+ std::vector<fs::path>::iterator
+ base_it = base_parts.begin(),
+ base_end = base_parts.end(),
+ path_it = path_parts.begin(),
+ path_end = path_parts.end();
+
+ // Build up the two paths in these variables, checking for the first
+ // difference.
+ fs::path
+ base_tmp = absolute_base.root_path(),
+ path_tmp = absolute_path.root_path();
+
+ fs::path result;
+
+ // If they have different roots then there's no relative path so
+ // just build an absolute path.
+ if (!fs::equivalent(base_tmp, path_tmp))
+ {
+ result = path_tmp;
+ }
+ else
+ {
+ // Find the point at which the paths differ
+ for(; base_it != base_end && path_it != path_end; ++base_it, ++path_it)
+ {
+ if(!fs::equivalent(base_tmp /= *base_it, path_tmp /= *path_it))
+ break;
+ }
+
+ // Build a relative path to that point
+ for(; base_it != base_end; ++base_it) result /= "..";
+ }
+
+ // Build the rest of our path
+ for(; path_it != path_end; ++path_it) result /= *path_it;
+
+ return result;
+ }
+
+ fs::path check_path(value const& path, quickbook::actions& actions)
+ {
+ std::string path_text = path.is_encoded() ? path.get_encoded() :
+ path.get_quickbook();
+
+ if(path_text.find('\\') != std::string::npos)
+ {
+ (qbk_version_n >= 106u ?
+ detail::outerr(path.get_file(), path.get_position()) :
+ detail::outwarn(path.get_file(), path.get_position()))
+ << "Path isn't portable: '"
+ << detail::utf8(path_text)
+ << "'"
+ << std::endl;
+ if (qbk_version_n >= 106u) ++actions.error_count;
+ }
+
+ boost::replace(path_text, '\\', '/');
+
+ return detail::generic_to_path(path_text);
+ }
+
+ xinclude_path calculate_xinclude_path(value const& p, quickbook::actions& actions)
+ {
+ fs::path path = check_path(p, actions);
+ fs::path full_path = path;
+
+ // If the path is relative
+ if (!path.has_root_directory())
+ {
+ // Resolve the path from the current file
+ full_path = actions.current_file->path.parent_path() / path;
+
+ // Then calculate relative to the current xinclude_base.
+ path = path_difference(actions.xinclude_base, full_path);
+ }
+
+ return xinclude_path(full_path, detail::escape_uri(detail::path_to_generic(path)));
+ }
+
+ void xinclude_action(quickbook::actions& actions, value xinclude)
+ {
+ write_anchors(actions, actions.out);
+
+ value_consumer values = xinclude;
+ xinclude_path x = calculate_xinclude_path(values.consume(), actions);
+ values.finish();
+
+ actions.out << "\n<xi:include href=\"";
+ detail::print_string(x.uri, actions.out.get());
+ actions.out << "\" />\n";
+ }
+
+ namespace
+ {
+ struct include_search_return
+ {
+ include_search_return(fs::path const& x, fs::path const& y)
+ : filename(x), filename_relative(y) {}
+
+ fs::path filename;
+ fs::path filename_relative;
+ };
+
+ include_search_return include_search(fs::path const& path,
+ quickbook::actions const& actions)
+ {
+ fs::path current = actions.current_file->path.parent_path();
+
+ // If the path is relative, try and resolve it.
+ if (!path.has_root_directory() && !path.has_root_name())
+ {
+ // See if it can be found locally first.
+ if (fs::exists(current / path))
+ {
+ return include_search_return(
+ current / path,
+ actions.filename_relative.parent_path() / path);
+ }
+
+ // Search in each of the include path locations.
+ BOOST_FOREACH(fs::path full, include_path)
+ {
+ full /= path;
+ if (fs::exists(full))
+ {
+ return include_search_return(full, path);
+ }
+ }
+ }
+
+ return include_search_return(path,
+ actions.filename_relative.parent_path() / path);
+ }
+ }
+
+ void load_quickbook(quickbook::actions& actions,
+ include_search_return const& paths,
+ value::tag_type load_type,
+ value const& include_doc_id = value())
+ {
+ assert(load_type == block_tags::include ||
+ load_type == block_tags::import);
+
+ // Check this before qbk_version_n gets changed by the inner file.
+ bool keep_inner_source_mode = (qbk_version_n < 106);
+
+ {
+ // When importing, state doesn't scope templates and macros so that
+ // they're added to the existing scope. It might be better to add
+ // them to a new scope then explicitly import them into the
+ // existing scope.
+ //
+ // For old versions of quickbook, templates aren't scoped by the
+ // file.
+ file_state state(actions,
+ load_type == block_tags::import ? file_state::scope_output :
+ qbk_version_n >= 106u ? file_state::scope_callables :
+ file_state::scope_macros);
+
+ actions.current_file = load(paths.filename); // Throws load_error
+ actions.filename_relative = paths.filename_relative;
+ actions.imported = (load_type == block_tags::import);
+
+ // update the __FILENAME__ macro
+ *boost::spirit::classic::find(actions.macro, "__FILENAME__")
+ = detail::path_to_generic(actions.filename_relative);
+
+ // parse the file
+ quickbook::parse_file(actions, include_doc_id, true);
+
+ // Don't restore source_mode on older versions.
+ if (keep_inner_source_mode) state.source_mode = actions.source_mode;
+ }
+
+ // restore the __FILENAME__ macro
+ *boost::spirit::classic::find(actions.macro, "__FILENAME__")
+ = detail::path_to_generic(actions.filename_relative);
+ }
+
+ void load_source_file(quickbook::actions& actions,
+ include_search_return const& paths,
+ value::tag_type load_type,
+ string_iterator first,
+ value const& include_doc_id = value())
+ {
+ assert(load_type == block_tags::include ||
+ load_type == block_tags::import);
+
+ std::string ext = paths.filename.extension().generic_string();
+ std::vector<template_symbol> storage;
+ // Throws load_error
+ actions.error_count +=
+ load_snippets(paths.filename, storage, ext, load_type);
+
+ if (load_type == block_tags::include)
+ {
+ actions.templates.push();
+ }
+
+ BOOST_FOREACH(template_symbol& ts, storage)
+ {
+ std::string tname = ts.identifier;
+ if (tname != "!")
+ {
+ ts.lexical_parent = &actions.templates.top_scope();
+ if (!actions.templates.add(ts))
+ {
+ detail::outerr(ts.content.get_file(), ts.content.get_position())
+ << "Template Redefinition: " << detail::utf8(tname) << std::endl;
+ ++actions.error_count;
+ }
+ }
+ }
+
+ if (load_type == block_tags::include)
+ {
+ BOOST_FOREACH(template_symbol& ts, storage)
+ {
+ std::string tname = ts.identifier;
+
+ if (tname == "!")
+ {
+ ts.lexical_parent = &actions.templates.top_scope();
+ call_code_snippet(actions, &ts, first);
+ }
+ }
+
+ actions.templates.pop();
+ }
+ }
+
+ void include_action(quickbook::actions& actions, value include, string_iterator first)
+ {
+ write_anchors(actions, actions.out);
+
+ value_consumer values = include;
+ value include_doc_id = values.optional_consume(general_tags::include_id);
+ include_search_return paths = include_search(
+ check_path(values.consume(), actions), actions);
+ values.finish();
+
+ try {
+ if (qbk_version_n >= 106)
+ {
+ if (actions.imported && include.get_tag() == block_tags::include)
+ return;
+
+ std::string ext = paths.filename.extension().generic_string();
+
+ if (ext == ".qbk" || ext == ".quickbook")
+ {
+ load_quickbook(actions, paths, include.get_tag(), include_doc_id);
+ }
+ else
+ {
+ load_source_file(actions, paths, include.get_tag(), first, include_doc_id);
+ }
+ }
+ else
+ {
+ if (include.get_tag() == block_tags::include)
+ {
+ load_quickbook(actions, paths, include.get_tag(), include_doc_id);
+ }
+ else
+ {
+ load_source_file(actions, paths, include.get_tag(), first, include_doc_id);
+ }
+ }
+ }
+ catch (load_error& e) {
+ ++actions.error_count;
+
+ detail::outerr(actions.current_file, first)
+ << "Loading file "
+ << paths.filename
+ << ": "
+ << detail::utf8(e.what())
+ << std::endl;
+ }
+ }
+
+ bool to_value_scoped_action::start(value::tag_type t)
+ {
+ actions.out.push();
+ actions.phrase.push();
+ actions.anchors.swap(saved_anchors);
+ tag = t;
+
+ return true;
+ }
+
+ void to_value_scoped_action::success(parse_iterator first, parse_iterator last)
+ {
+ std::string value;
+
+ if (!actions.out.str().empty())
+ {
+ actions.paragraph();
+ write_anchors(actions, actions.out);
+ actions.out.swap(value);
+ }
+ else
+ {
+ write_anchors(actions, actions.phrase);
+ actions.phrase.swap(value);
+ }
+
+ actions.values.builder.insert(encoded_qbk_value(
+ actions.current_file, first.base(), last.base(), value, tag));
+ }
+
+
+ void to_value_scoped_action::cleanup()
+ {
+ actions.phrase.pop();
+ actions.out.pop();
+ actions.anchors.swap(saved_anchors);
+ }
+}
diff --git a/tools/quickbook/src/actions.hpp b/tools/quickbook/src/actions.hpp
new file mode 100644
index 0000000000..4f67aec09b
--- /dev/null
+++ b/tools/quickbook/src/actions.hpp
@@ -0,0 +1,305 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP
+
+#include <string>
+#include <vector>
+#include "fwd.hpp"
+#include "template_stack.hpp"
+#include "utils.hpp"
+#include "values.hpp"
+#include "scoped.hpp"
+#include "symbols.hpp"
+#include <boost/spirit/include/classic_parser.hpp>
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+
+ extern unsigned qbk_version_n; // qbk_major_version * 100 + qbk_minor_version
+
+ struct quickbook_range : cl::parser<quickbook_range> {
+ quickbook_range(unsigned min_, unsigned max_)
+ : min_(min_), max_(max_) {}
+
+ template <typename ScannerT>
+ typename cl::parser_result<quickbook_range, ScannerT>::type
+ parse(ScannerT const& scan) const
+ {
+ if (qbk_version_n >= min_ && qbk_version_n < max_)
+ {
+ return scan.empty_match();
+ }
+ else
+ {
+ return scan.no_match();
+ }
+ }
+
+ unsigned min_, max_;
+ };
+
+ inline quickbook_range qbk_since(unsigned min_) {
+ return quickbook_range(min_, 999);
+ }
+
+ inline quickbook_range qbk_before(unsigned max_) {
+ return quickbook_range(0, max_);
+ }
+
+ // Throws load_error
+ int load_snippets(fs::path const& file, std::vector<template_symbol>& storage,
+ std::string const& extension, value::tag_type load_type);
+
+ std::string syntax_highlight(
+ parse_iterator first, parse_iterator last,
+ actions& escape_actions,
+ std::string const& source_mode);
+
+ struct xinclude_path {
+ xinclude_path(fs::path& path, std::string const& uri) :
+ path(path), uri(uri) {}
+
+ fs::path path;
+ std::string uri;
+ };
+
+ xinclude_path calculate_xinclude_path(value const&, quickbook::actions&);
+
+ struct error_message_action
+ {
+ // Prints an error message to std::cerr
+
+ error_message_action(quickbook::actions& actions, std::string const& m)
+ : actions(actions)
+ , message(m)
+ {}
+
+ void operator()(parse_iterator, parse_iterator) const;
+
+ quickbook::actions& actions;
+ std::string message;
+ };
+
+ struct error_action
+ {
+ // Prints an error message to std::cerr
+
+ error_action(quickbook::actions& actions)
+ : actions(actions) {}
+
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ error_message_action operator()(std::string const& message)
+ {
+ return error_message_action(actions, message);
+ }
+
+ quickbook::actions& actions;
+ };
+
+ struct element_action
+ {
+ element_action(quickbook::actions& actions)
+ : actions(actions) {}
+
+ void operator()(parse_iterator, parse_iterator) const;
+
+ quickbook::actions& actions;
+ };
+
+ struct paragraph_action
+ {
+ // implicit paragraphs
+ // doesn't output the paragraph if it's only whitespace.
+
+ paragraph_action(
+ quickbook::actions& actions)
+ : actions(actions) {}
+
+ void operator()() const;
+ void operator()(parse_iterator, parse_iterator) const { (*this)(); }
+
+ quickbook::actions& actions;
+ };
+
+ struct list_item_action
+ {
+ // implicit paragraphs
+ // doesn't output the paragraph if it's only whitespace.
+
+ list_item_action(
+ quickbook::actions& actions)
+ : actions(actions) {}
+
+ void operator()() const;
+ void operator()(parse_iterator, parse_iterator) const { (*this)(); }
+
+ quickbook::actions& actions;
+ };
+
+ struct phrase_end_action
+ {
+ phrase_end_action(quickbook::actions& actions) :
+ actions(actions) {}
+
+ void operator()() const;
+ void operator()(parse_iterator, parse_iterator) const { (*this)(); }
+
+ quickbook::actions& actions;
+ };
+
+ struct simple_phrase_action
+ {
+ // Handles simple text formats
+
+ simple_phrase_action(
+ collector& out
+ , quickbook::actions& actions)
+ : out(out)
+ , actions(actions) {}
+
+ void operator()(char) const;
+
+ collector& out;
+ quickbook::actions& actions;
+ };
+
+ struct cond_phrase_push : scoped_action_base
+ {
+ cond_phrase_push(quickbook::actions& x)
+ : actions(x) {}
+
+ bool start();
+ void cleanup();
+
+ quickbook::actions& actions;
+ bool saved_conditional;
+ std::vector<std::string> anchors;
+ };
+
+ extern char const* quickbook_get_date;
+ extern char const* quickbook_get_time;
+
+ struct do_macro_action
+ {
+ // Handles macro substitutions
+
+ do_macro_action(collector& phrase, quickbook::actions& actions)
+ : phrase(phrase)
+ , actions(actions) {}
+
+ void operator()(std::string const& str) const;
+ collector& phrase;
+ quickbook::actions& actions;
+ };
+
+ struct raw_char_action
+ {
+ // Prints a space
+
+ raw_char_action(collector& out)
+ : out(out) {}
+
+ void operator()(char ch) const;
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ collector& out;
+ };
+
+ struct plain_char_action
+ {
+ // Prints a single plain char.
+ // Converts '<' to "&lt;"... etc See utils.hpp
+
+ plain_char_action(collector& phrase, quickbook::actions& actions)
+ : phrase(phrase)
+ , actions(actions) {}
+
+ void operator()(char ch) const;
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ collector& phrase;
+ quickbook::actions& actions;
+ };
+
+ struct escape_unicode_action
+ {
+ escape_unicode_action(collector& phrase, quickbook::actions& actions)
+ : phrase(phrase)
+ , actions(actions) {}
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ collector& phrase;
+ quickbook::actions& actions;
+ };
+
+ struct code_action
+ {
+ enum code_type { block, inline_block, inline_ };
+
+ // Does the actual syntax highlighing of code
+
+ code_action(
+ code_type type
+ , quickbook::actions& actions)
+ : type(type)
+ , actions(actions)
+ {
+ }
+
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ code_type type;
+ quickbook::actions& actions;
+ };
+
+ struct break_action
+ {
+ break_action(collector& phrase, quickbook::actions& actions)
+ : phrase(phrase), actions(actions) {}
+
+ void operator()(parse_iterator f, parse_iterator) const;
+
+ collector& phrase;
+ quickbook::actions& actions;
+ };
+
+ struct element_id_warning_action
+ {
+ element_id_warning_action(quickbook::actions& actions_)
+ : actions(actions_) {}
+
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ quickbook::actions& actions;
+ };
+
+ // Returns the doc_type, or an empty string if there isn't one.
+ std::string pre(quickbook::actions& actions, parse_iterator pos, value include_doc_id, bool nested_file);
+ void post(quickbook::actions& actions, std::string const& doc_type);
+
+ struct to_value_scoped_action : scoped_action_base
+ {
+ to_value_scoped_action(quickbook::actions& actions)
+ : actions(actions) {}
+
+ bool start(value::tag_type = value::default_tag);
+ void success(parse_iterator, parse_iterator);
+ void cleanup();
+
+ quickbook::actions& actions;
+ std::vector<std::string> saved_anchors;
+ value::tag_type tag;
+ };
+}
+
+#endif // BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP
diff --git a/tools/quickbook/src/actions_class.cpp b/tools/quickbook/src/actions_class.cpp
new file mode 100644
index 0000000000..d94706c91a
--- /dev/null
+++ b/tools/quickbook/src/actions_class.cpp
@@ -0,0 +1,136 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ Copyright (c) 2005 Thomas Guest
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "actions_class.hpp"
+#include "actions_state.hpp"
+#include "quickbook.hpp"
+#include "grammar.hpp"
+#include "input_path.hpp"
+
+#if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
+#pragma warning(disable:4355)
+#endif
+
+namespace quickbook
+{
+ actions::actions(fs::path const& filein_, fs::path const& xinclude_base_,
+ string_stream& out_, id_manager& ids)
+ : grammar_()
+
+ , xinclude_base(xinclude_base_)
+
+ , templates()
+ , error_count(0)
+ , anchors()
+ , warned_about_breaks(false)
+ , conditional(true)
+ , ids(ids)
+
+ , imported(false)
+ , macro()
+ , source_mode("c++")
+ , current_file(0)
+ , filename_relative(filein_.filename())
+
+ , template_depth(0)
+ , min_section_level(1)
+
+ , out(out_)
+ , phrase()
+ , values(&current_file)
+
+ , to_value(*this)
+ , scoped_cond_phrase(*this)
+
+ , element(*this)
+ , error(*this)
+ , code(code_action::block, *this)
+ , code_block(code_action::inline_block, *this)
+ , inline_code(code_action::inline_, *this)
+ , paragraph(*this)
+ , list_item(*this)
+ , phrase_end(*this)
+ , raw_char(phrase)
+ , plain_char(phrase, *this)
+ , escape_unicode(phrase, *this)
+
+ , simple_markup(phrase, *this)
+
+ , break_(phrase, *this)
+ , do_macro(phrase, *this)
+
+ , element_id_warning(*this)
+ {
+ // add the predefined macros
+ macro.add
+ ("__DATE__", std::string(quickbook_get_date))
+ ("__TIME__", std::string(quickbook_get_time))
+ ("__FILENAME__", detail::path_to_generic(filename_relative))
+ ;
+
+ boost::scoped_ptr<quickbook_grammar> g(
+ new quickbook_grammar(*this));
+ grammar_.swap(g);
+ }
+
+ quickbook_grammar& actions::grammar() const {
+ return *grammar_;
+ }
+
+ file_state::file_state(actions& a, scope_flags scope)
+ : a(a)
+ , scope(scope)
+ , qbk_version(qbk_version_n)
+ , imported(a.imported)
+ , current_file(a.current_file)
+ , filename_relative(a.filename_relative)
+ , xinclude_base(a.xinclude_base)
+ , source_mode(a.source_mode)
+ , macro()
+ {
+ if (scope & scope_macros) macro = a.macro;
+ if (scope & scope_templates) a.templates.push();
+ if (scope & scope_output) {
+ a.out.push();
+ a.phrase.push();
+ }
+ a.values.builder.save();
+ }
+
+ file_state::~file_state()
+ {
+ a.values.builder.restore();
+ boost::swap(qbk_version_n, qbk_version);
+ boost::swap(a.imported, imported);
+ boost::swap(a.current_file, current_file);
+ boost::swap(a.filename_relative, filename_relative);
+ boost::swap(a.xinclude_base, xinclude_base);
+ boost::swap(a.source_mode, source_mode);
+ if (scope & scope_output) {
+ a.out.pop();
+ a.phrase.pop();
+ }
+ if (scope & scope_templates) a.templates.pop();
+ if (scope & scope_macros) a.macro = macro;
+ }
+
+ template_state::template_state(actions& a)
+ : file_state(a, file_state::scope_all)
+ , template_depth(a.template_depth)
+ , min_section_level(a.min_section_level)
+ {
+ }
+
+ template_state::~template_state()
+ {
+ boost::swap(a.template_depth, template_depth);
+ boost::swap(a.min_section_level, min_section_level);
+ }
+}
diff --git a/tools/quickbook/src/actions_class.hpp b/tools/quickbook/src/actions_class.hpp
new file mode 100644
index 0000000000..979c3ccf67
--- /dev/null
+++ b/tools/quickbook/src/actions_class.hpp
@@ -0,0 +1,107 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_ACTIONS_CLASS_HPP)
+#define BOOST_SPIRIT_ACTIONS_CLASS_HPP
+
+#include <boost/scoped_ptr.hpp>
+#include "actions.hpp"
+#include "parsers.hpp"
+#include "values_parse.hpp"
+#include "collector.hpp"
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+ namespace fs = boost::filesystem;
+
+ struct actions
+ {
+ actions(fs::path const& filein_, fs::path const& xinclude_base, string_stream& out_,
+ id_manager&);
+
+ private:
+ boost::scoped_ptr<quickbook_grammar> grammar_;
+
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // State
+ ///////////////////////////////////////////////////////////////////////////
+
+ typedef std::vector<std::string> string_list;
+
+ static int const max_template_depth = 100;
+
+ // global state
+ fs::path xinclude_base;
+ template_stack templates;
+ int error_count;
+ string_list anchors;
+ bool warned_about_breaks;
+ bool conditional;
+ id_manager& ids;
+
+ // state saved for files and templates.
+ bool imported;
+ string_symbols macro;
+ std::string source_mode;
+ file_ptr current_file;
+ fs::path filename_relative; // for the __FILENAME__ macro.
+ // (relative to the original file
+ // or include path).
+
+ // state saved for templates.
+ int template_depth;
+ int min_section_level;
+
+ // output state - scoped by templates and grammar
+ collector out; // main output stream
+ collector phrase; // phrase output stream
+ value_parser values; // parsed values
+
+ quickbook_grammar& grammar() const;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // actions
+ ///////////////////////////////////////////////////////////////////////////
+
+ void start_list(char mark);
+ void end_list(char mark);
+ void start_list_item();
+ void end_list_item();
+
+ scoped_parser<to_value_scoped_action>
+ to_value;
+ scoped_parser<cond_phrase_push>
+ scoped_cond_phrase;
+
+ element_action element;
+ error_action error;
+
+ code_action code;
+ code_action code_block;
+ code_action inline_code;
+ paragraph_action paragraph;
+ list_item_action list_item;
+ phrase_end_action phrase_end;
+ raw_char_action raw_char;
+ plain_char_action plain_char;
+ escape_unicode_action escape_unicode;
+
+ simple_phrase_action simple_markup;
+
+ break_action break_;
+ do_macro_action do_macro;
+
+ element_id_warning_action element_id_warning;
+ };
+}
+
+#endif // BOOST_SPIRIT_ACTIONS_CLASS_HPP
+
diff --git a/tools/quickbook/src/actions_state.hpp b/tools/quickbook/src/actions_state.hpp
new file mode 100644
index 0000000000..aefa7f99da
--- /dev/null
+++ b/tools/quickbook/src/actions_state.hpp
@@ -0,0 +1,60 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_ACTIONS_STATE_HPP)
+#define BOOST_SPIRIT_ACTIONS_STATE_HPP
+
+#include "actions_class.hpp"
+
+namespace quickbook
+{
+ // State savers
+ //
+ // Defined in actions_class.cpp
+
+ struct file_state
+ {
+ enum scope_flags {
+ scope_none = 0,
+ scope_macros = 1,
+ scope_templates = 2,
+ scope_output = 4,
+ scope_callables = scope_macros + scope_templates,
+ scope_all = scope_callables + scope_output
+ };
+
+ explicit file_state(actions&, scope_flags);
+ ~file_state();
+
+ quickbook::actions& a;
+ scope_flags scope;
+ unsigned qbk_version;
+ bool imported;
+ std::string doc_type;
+ file_ptr current_file;
+ fs::path filename_relative;
+ fs::path xinclude_base;
+ std::string source_mode;
+ string_symbols macro;
+ private:
+ file_state(file_state const&);
+ file_state& operator=(file_state const&);
+ };
+
+ struct template_state : file_state
+ {
+ explicit template_state(actions&);
+ ~template_state();
+
+ int template_depth;
+ int min_section_level;
+ };
+}
+
+#endif // BOOST_SPIRIT_ACTIONS_STATE_HPP
diff --git a/tools/quickbook/src/block_element_grammar.cpp b/tools/quickbook/src/block_element_grammar.cpp
new file mode 100644
index 0000000000..f188e1379f
--- /dev/null
+++ b/tools/quickbook/src/block_element_grammar.cpp
@@ -0,0 +1,320 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "utils.hpp"
+#include "actions_class.hpp"
+#include "grammar_impl.hpp"
+#include "block_tags.hpp"
+#include "template_tags.hpp"
+#include <boost/spirit/include/classic_assign_actor.hpp>
+#include <boost/spirit/include/classic_if.hpp>
+#include <boost/spirit/include/classic_clear_actor.hpp>
+#include <boost/spirit/include/phoenix1_primitives.hpp>
+#include <boost/spirit/include/phoenix1_casts.hpp>
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+ namespace ph = phoenix;
+
+ struct block_element_grammar_local
+ {
+ cl::rule<scanner>
+ heading, inner_block, inner_phrase, def_macro,
+ table, table_title, table_row, variablelist,
+ varlistentry, varlistterm, list, cell,
+ preformatted, begin_section, end_section,
+ xinclude, include, include_filename,
+ template_, template_id, template_formal_arg,
+ template_body, identifier, import,
+ element_id, element_id_1_5, element_id_1_6,
+ same_line;
+ };
+
+ void quickbook_grammar::impl::init_block_elements()
+ {
+ block_element_grammar_local& local = cleanup_.add(
+ new block_element_grammar_local);
+
+ local.element_id =
+ !( ':'
+ >> ( !(qbk_since(105u) >> space)
+ >> (+(cl::alnum_p | '_')) [actions.values.entry(ph::arg1, ph::arg2, general_tags::element_id)]
+ | cl::eps_p [actions.element_id_warning]
+ )
+ )
+ ;
+
+ local.element_id_1_5 =
+ !(qbk_since(105u) >> local.element_id);
+
+ local.element_id_1_6 =
+ !(qbk_since(106u) >> local.element_id);
+
+ elements.add
+ ("section", element_info(element_info::block, &local.begin_section, block_tags::begin_section))
+ ("endsect", element_info(element_info::block, &local.end_section, block_tags::end_section))
+ ;
+
+ local.begin_section =
+ space
+ >> local.element_id
+ >> space
+ >> local.inner_phrase
+ ;
+
+ local.end_section =
+ cl::eps_p
+ ;
+
+ local.heading
+ = space
+ >> local.element_id_1_6
+ >> space
+ >> local.inner_phrase
+ ;
+
+ elements.add
+ ("heading", element_info(element_info::conditional_or_block, &local.heading, block_tags::generic_heading))
+ ("h1", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading1))
+ ("h2", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading2))
+ ("h3", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading3))
+ ("h4", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading4))
+ ("h5", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading5))
+ ("h6", element_info(element_info::conditional_or_block, &local.heading, block_tags::heading6))
+ ;
+
+ elements.add
+ ("blurb", element_info(element_info::nested_block, &local.inner_block, block_tags::blurb))
+ (":", element_info(element_info::nested_block, &local.inner_block, block_tags::blockquote))
+ ("warning", element_info(element_info::nested_block, &local.inner_block, block_tags::warning))
+ ("caution", element_info(element_info::nested_block, &local.inner_block, block_tags::caution))
+ ("important", element_info(element_info::nested_block, &local.inner_block, block_tags::important))
+ ("note", element_info(element_info::nested_block, &local.inner_block, block_tags::note))
+ ("tip", element_info(element_info::nested_block, &local.inner_block, block_tags::tip))
+ ;
+
+ elements.add
+ ("block", element_info(element_info::nested_block, &local.inner_phrase, block_tags::block, 106u))
+ ;
+
+ elements.add
+ ("pre", element_info(element_info::nested_block, &local.preformatted, block_tags::preformatted))
+ ;
+
+ local.preformatted =
+ ( qbk_before(106) >> space
+ | qbk_since(106) >> blank >> !eol
+ )
+ >> actions.to_value()
+ [
+ inside_preformatted
+ ]
+ ;
+
+ elements.add
+ ("def", element_info(element_info::conditional_or_block, &local.def_macro, block_tags::macro_definition))
+ ;
+
+ local.def_macro =
+ space
+ >> macro_identifier [actions.values.entry(ph::arg1, ph::arg2)]
+ >> blank
+ >> local.inner_phrase
+ ;
+
+ local.identifier =
+ (cl::alpha_p | '_') >> *(cl::alnum_p | '_')
+ ;
+
+ local.template_id =
+ local.identifier | (cl::punct_p - (cl::ch_p('[') | ']'))
+ ;
+
+ elements.add
+ ("template", element_info(element_info::conditional_or_block, &local.template_, block_tags::template_definition))
+ ;
+
+ local.template_ =
+ space
+ >> local.template_id [actions.values.entry(ph::arg1, ph::arg2)]
+ >> actions.values.list()[
+ !(
+ space >> '['
+ >> *(
+ space
+ >> local.template_id [actions.values.entry(ph::arg1, ph::arg2)]
+ )
+ >> space >> ']'
+ )
+ ]
+ >> ( cl::eps_p(*cl::blank_p >> cl::eol_p)
+ >> local.template_body [actions.values.entry(ph::arg1, ph::arg2, template_tags::block)]
+ | local.template_body [actions.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
+ )
+ ;
+
+ local.template_body =
+ *(('[' >> local.template_body >> ']') | (cl::anychar_p - ']'))
+ >> cl::eps_p(space >> ']')
+ >> space
+ ;
+
+ elements.add
+ ("variablelist", element_info(element_info::nested_block, &local.variablelist, block_tags::variable_list))
+ ;
+
+ local.variablelist =
+ (cl::eps_p(*cl::blank_p >> cl::eol_p) | space)
+ >> local.table_title
+ >> *local.varlistentry
+ ;
+
+ local.varlistentry =
+ space
+ >> cl::ch_p('[')
+ >> actions.values.list()
+ [
+ (
+ local.varlistterm
+ >> ( +local.cell
+ | cl::eps_p [actions.error]
+ )
+ >> cl::ch_p(']')
+ >> space
+ )
+ | cl::eps_p [actions.error]
+ ]
+ ;
+
+ local.varlistterm =
+ space
+ >> cl::ch_p('[')
+ >> local.inner_phrase
+ >> ( cl::ch_p(']')
+ >> space
+ | cl::eps_p [actions.error]
+ )
+ ;
+
+ elements.add
+ ("table", element_info(element_info::nested_block, &local.table, block_tags::table))
+ ;
+
+ local.same_line = *cl::blank_p >> !(comment >> space);
+
+ local.table =
+ local.same_line
+ >> local.element_id_1_5
+ >> local.same_line
+ >> local.table_title
+ >> *local.table_row
+ ;
+
+ local.table_row =
+ space
+ >> cl::ch_p('[')
+ >>
+ (
+ (
+ actions.values.list(table_tags::row)
+ [ *local.cell
+ ]
+ >> cl::ch_p(']')
+ >> space
+ )
+ | cl::eps_p [actions.error]
+ )
+ ;
+
+ local.table_title =
+ qbk_before(106)
+ >> (*(cl::anychar_p - eol)) [actions.values.entry(ph::arg1, ph::arg2, table_tags::title)]
+ >> (+eol)
+ | qbk_since(106)
+ >> actions.to_value(table_tags::title)
+ [
+ table_title_phrase
+ ]
+ >> space
+ ;
+
+ elements.add
+ ("ordered_list", element_info(element_info::nested_block, &local.list, block_tags::ordered_list, 106))
+ ("itemized_list", element_info(element_info::nested_block, &local.list, block_tags::itemized_list, 106))
+ ;
+
+ local.list = *local.cell;
+
+ local.cell =
+ space
+ >> cl::ch_p('[')
+ >> ( local.inner_block
+ >> cl::ch_p(']')
+ >> space
+ | cl::eps_p [actions.error]
+ )
+ ;
+
+ elements.add
+ ("xinclude", element_info(element_info::conditional_or_block, &local.xinclude, block_tags::xinclude))
+ ("import", element_info(element_info::conditional_or_block, &local.import, block_tags::import))
+ ("include", element_info(element_info::conditional_or_block, &local.include, block_tags::include))
+ ;
+
+ local.xinclude =
+ space
+ >> local.include_filename
+ ;
+
+ local.import =
+ space
+ >> local.include_filename
+ ;
+
+ local.include =
+ space
+ >>
+ !(
+ ':'
+ >> (*((cl::alnum_p | '_') - cl::space_p))
+ [actions.values.entry(ph::arg1, ph::arg2, general_tags::include_id)]
+ >> space
+ )
+ >> local.include_filename
+ ;
+
+ local.include_filename =
+ qbk_before(106u)
+ >> (*(cl::anychar_p - phrase_end)) [actions.values.entry(ph::arg1, ph::arg2)]
+ | qbk_since(106u)
+ >> actions.to_value()
+ [ *( raw_escape
+ | (cl::anychar_p - phrase_end)
+ [actions.raw_char]
+ )
+ ]
+ ;
+
+ local.inner_block =
+ actions.to_value()
+ [
+ inside_paragraph
+ ]
+ ;
+
+ local.inner_phrase =
+ actions.to_value()
+ [
+ paragraph_phrase
+ ]
+ ;
+ }
+}
diff --git a/tools/quickbook/src/block_tags.hpp b/tools/quickbook/src/block_tags.hpp
new file mode 100644
index 0000000000..b01271fc0b
--- /dev/null
+++ b/tools/quickbook/src/block_tags.hpp
@@ -0,0 +1,40 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_SPIRIT_QUICKBOOK_TABLE_TAGS_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_TABLE_TAGS_HPP
+
+#include "value_tags.hpp"
+
+namespace quickbook
+{
+ QUICKBOOK_VALUE_TAGS(block_tags, 0x200,
+ (begin_section)(end_section)
+ (generic_heading)
+ (heading1)(heading2)(heading3)(heading4)(heading5)(heading6)
+ (blurb)(blockquote)(preformatted)
+ (warning)(caution)(important)(note)(tip)(block)
+ (macro_definition)(template_definition)
+ (variable_list)(table)
+ (xinclude)(import)(include)
+ (paragraph)
+ (ordered_list)(itemized_list)
+ (hr)
+ )
+
+ QUICKBOOK_VALUE_TAGS(table_tags, 0x250,
+ (title)(row)
+ )
+
+ QUICKBOOK_VALUE_TAGS(general_tags, 0x300,
+ (element_id)(include_id)(list_indent)(list_mark)
+ )
+
+}
+
+#endif
diff --git a/tools/quickbook/src/cleanup.hpp b/tools/quickbook/src/cleanup.hpp
new file mode 100644
index 0000000000..a03cf4cd2c
--- /dev/null
+++ b/tools/quickbook/src/cleanup.hpp
@@ -0,0 +1,74 @@
+/*=============================================================================
+ Copyright (c) 2010 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+// This header defines a class which can will store pointers and deleters
+// to a number of objects and delete them on exit. Basically stick an
+// object in here, and you can use pointers and references to the object
+// for the cleanup object's lifespan.
+
+#if !defined(BOOST_SPIRIT_QUICKBOOK_CLEANUP_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_CLEANUP_HPP
+
+#include <deque>
+#include <cassert>
+#include <utility>
+
+namespace quickbook
+{
+ namespace detail
+ {
+ template <typename T>
+ void delete_impl(void* ptr) {
+ delete static_cast<T*>(ptr);
+ }
+
+ struct scoped_void
+ {
+ void* ptr_;
+ void (*del_)(void*);
+
+ scoped_void() : ptr_(0), del_(0) {}
+ scoped_void(scoped_void const& src) : ptr_(0), del_(0) {
+ ignore_variable(&src);
+ assert(!src.ptr_);
+ }
+ ~scoped_void() {
+ if(ptr_) del_(ptr_);
+ }
+
+ void store(void* ptr, void (*del)(void* x)) {
+ ptr = ptr_;
+ del = del_;
+ }
+ private:
+ scoped_void& operator=(scoped_void const&);
+ };
+ }
+
+ struct cleanup
+ {
+ cleanup() {}
+
+ template <typename T>
+ T& add(T* new_)
+ {
+ std::auto_ptr<T> obj(new_);
+ cleanup_list_.push_back(detail::scoped_void());
+ cleanup_list_.back().store(obj.release(), &detail::delete_impl<T>);
+
+ return *new_;
+ }
+
+ std::deque<detail::scoped_void> cleanup_list_;
+ private:
+ cleanup& operator=(cleanup const&);
+ cleanup(cleanup const&);
+ };
+}
+
+#endif
diff --git a/tools/quickbook/src/code_snippet.cpp b/tools/quickbook/src/code_snippet.cpp
new file mode 100644
index 0000000000..8d9484cce2
--- /dev/null
+++ b/tools/quickbook/src/code_snippet.cpp
@@ -0,0 +1,600 @@
+/*=============================================================================
+ Copyright (c) 2006 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_actor.hpp>
+#include <boost/spirit/include/classic_confix.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
+#include "block_tags.hpp"
+#include "template_stack.hpp"
+#include "actions.hpp"
+#include "values.hpp"
+#include "files.hpp"
+#include "input_path.hpp"
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+
+ struct code_snippet_actions
+ {
+ code_snippet_actions(std::vector<template_symbol>& storage,
+ file_ptr source_file,
+ char const* source_type)
+ : last_code_pos(source_file->source.begin())
+ , in_code(false)
+ , callout_id(0)
+ , snippet_stack()
+ , storage(storage)
+ , source_file(source_file)
+ , source_type(source_type)
+ , error_count(0)
+ {
+ content.start(source_file);
+ }
+
+ void mark(string_iterator first, string_iterator last);
+ void pass_thru(string_iterator first, string_iterator last);
+ void escaped_comment(string_iterator first, string_iterator last);
+ void start_snippet(string_iterator first, string_iterator last);
+ void start_snippet_impl(std::string const&, string_iterator);
+ void end_snippet(string_iterator first, string_iterator last);
+ void end_snippet_impl(string_iterator);
+ void callout(string_iterator first, string_iterator last);
+ void end_file(string_iterator, string_iterator);
+
+ void append_code(string_iterator first, string_iterator last);
+ void close_code();
+
+ struct snippet_data
+ {
+ snippet_data(std::string const& id, int callout_base_id)
+ : id(id)
+ , callout_base_id(callout_base_id)
+ , start_code(false)
+ {}
+
+ std::string id;
+ int callout_base_id;
+ bool start_code;
+ std::string::const_iterator source_pos;
+ mapped_file_builder::pos start_pos;
+ value_builder callouts;
+ boost::shared_ptr<snippet_data> next;
+ };
+
+ void push_snippet_data(std::string const& id, int callout_base_id,
+ std::string::const_iterator pos)
+ {
+ boost::shared_ptr<snippet_data> new_snippet(
+ new snippet_data(id, callout_base_id));
+ new_snippet->next = snippet_stack;
+ snippet_stack = new_snippet;
+ snippet_stack->start_code = in_code;
+ snippet_stack->source_pos = pos;
+ snippet_stack->start_pos = content.get_pos();
+ }
+
+ boost::shared_ptr<snippet_data> pop_snippet_data()
+ {
+ boost::shared_ptr<snippet_data> snippet(snippet_stack);
+ snippet_stack = snippet->next;
+ snippet->next.reset();
+ return snippet;
+ }
+
+ mapped_file_builder content;
+ std::string::const_iterator mark_begin, mark_end;
+ std::string::const_iterator last_code_pos;
+ bool in_code;
+ int callout_id;
+ boost::shared_ptr<snippet_data> snippet_stack;
+ std::vector<template_symbol>& storage;
+ file_ptr source_file;
+ char const* const source_type;
+ int error_count;
+ };
+
+ struct python_code_snippet_grammar
+ : cl::grammar<python_code_snippet_grammar>
+ {
+ typedef code_snippet_actions actions_type;
+
+ python_code_snippet_grammar(actions_type & actions)
+ : actions(actions)
+ {}
+
+ template <typename Scanner>
+ struct definition
+ {
+ typedef code_snippet_actions actions_type;
+
+ definition(python_code_snippet_grammar const& self)
+ {
+
+ actions_type& actions = self.actions;
+
+ start_ = (*code_elements) [boost::bind(&actions_type::end_file, &actions, _1, _2)]
+ ;
+
+ identifier =
+ (cl::alpha_p | '_') >> *(cl::alnum_p | '_')
+ ;
+
+ code_elements =
+ start_snippet [boost::bind(&actions_type::start_snippet, &actions, _1, _2)]
+ | end_snippet [boost::bind(&actions_type::end_snippet, &actions, _1, _2)]
+ | escaped_comment [boost::bind(&actions_type::escaped_comment, &actions, _1, _2)]
+ | pass_thru_comment [boost::bind(&actions_type::pass_thru, &actions, _1, _2)]
+ | ignore [boost::bind(&actions_type::append_code, &actions, _1, _2)]
+ | cl::anychar_p
+ ;
+
+ start_snippet =
+ *cl::blank_p
+ >> !(cl::eol_p >> *cl::blank_p)
+ >> "#["
+ >> *cl::blank_p
+ >> identifier [boost::bind(&actions_type::mark, &actions, _1, _2)]
+ >> *(cl::anychar_p - cl::eol_p)
+ ;
+
+ end_snippet =
+ *cl::blank_p
+ >> !(cl::eol_p >> *cl::blank_p)
+ >> "#]"
+ >> *(cl::anychar_p - cl::eol_p)
+ ;
+
+ ignore
+ = cl::confix_p(
+ *cl::blank_p >> "#<-",
+ *cl::anychar_p,
+ "#->" >> *cl::blank_p >> (cl::eol_p | cl::end_p)
+ )
+ | cl::confix_p(
+ "\"\"\"<-\"\"\"",
+ *cl::anychar_p,
+ "\"\"\"->\"\"\""
+ )
+ | cl::confix_p(
+ "\"\"\"<-",
+ *cl::anychar_p,
+ "->\"\"\""
+ )
+ ;
+
+ escaped_comment =
+ cl::confix_p(
+ *cl::space_p >> "#`",
+ (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
+ (cl::eol_p | cl::end_p)
+ )
+ | cl::confix_p(
+ *cl::space_p >> "\"\"\"`",
+ (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
+ "\"\"\""
+ )
+ ;
+
+ // Note: Unlike escaped_comment and ignore, this doesn't
+ // swallow preceeding whitespace.
+ pass_thru_comment
+ = "#=" >> (cl::eps_p - '=')
+ >> ( *(cl::anychar_p - cl::eol_p)
+ >> (cl::eol_p | cl::end_p)
+ ) [boost::bind(&actions_type::mark, &actions, _1, _2)]
+ | cl::confix_p(
+ "\"\"\"=" >> (cl::eps_p - '='),
+ (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
+ "\"\"\""
+ )
+ ;
+ }
+
+ cl::rule<Scanner>
+ start_, identifier, code_elements, start_snippet, end_snippet,
+ escaped_comment, pass_thru_comment, ignore;
+
+ cl::rule<Scanner> const&
+ start() const { return start_; }
+ };
+
+ actions_type& actions;
+ };
+
+ struct cpp_code_snippet_grammar
+ : cl::grammar<cpp_code_snippet_grammar>
+ {
+ typedef code_snippet_actions actions_type;
+
+ cpp_code_snippet_grammar(actions_type & actions)
+ : actions(actions)
+ {}
+
+ template <typename Scanner>
+ struct definition
+ {
+ definition(cpp_code_snippet_grammar const& self)
+ {
+ actions_type& actions = self.actions;
+
+ start_ = (*code_elements) [boost::bind(&actions_type::end_file, &actions, _1, _2)]
+ ;
+
+ identifier =
+ (cl::alpha_p | '_') >> *(cl::alnum_p | '_')
+ ;
+
+ code_elements =
+ start_snippet [boost::bind(&actions_type::start_snippet, &actions, _1, _2)]
+ | end_snippet [boost::bind(&actions_type::end_snippet, &actions, _1, _2)]
+ | escaped_comment [boost::bind(&actions_type::escaped_comment, &actions, _1, _2)]
+ | ignore [boost::bind(&actions_type::append_code, &actions, _1, _2)]
+ | pass_thru_comment [boost::bind(&actions_type::pass_thru, &actions, _1, _2)]
+ | line_callout [boost::bind(&actions_type::callout, &actions, _1, _2)]
+ | inline_callout [boost::bind(&actions_type::callout, &actions, _1, _2)]
+ | cl::anychar_p
+ ;
+
+ start_snippet =
+ *cl::blank_p
+ >> !(cl::eol_p >> *cl::blank_p)
+ >> "//["
+ >> *cl::blank_p
+ >> identifier [boost::bind(&actions_type::mark, &actions, _1, _2)]
+ >> *(cl::anychar_p - cl::eol_p)
+ |
+ *cl::blank_p
+ >> cl::eol_p
+ >> *cl::blank_p
+ >> "/*["
+ >> *cl::space_p
+ >> identifier [boost::bind(&actions_type::mark, &actions, _1, _2)]
+ >> *cl::space_p
+ >> "*/"
+ >> *cl::blank_p
+ >> cl::eps_p(cl::eol_p)
+ |
+ "/*["
+ >> *cl::space_p
+ >> identifier [boost::bind(&actions_type::mark, &actions, _1, _2)]
+ >> *cl::space_p
+ >> "*/"
+ ;
+
+ end_snippet =
+ *cl::blank_p
+ >> !(cl::eol_p >> *cl::blank_p)
+ >> "//]"
+ >> *(cl::anychar_p - cl::eol_p)
+ |
+ *cl::blank_p
+ >> cl::eol_p
+ >> *cl::blank_p
+ >> "/*]*/"
+ >> *cl::blank_p
+ >> cl::eps_p(cl::eol_p)
+ |
+ "/*[*/"
+ ;
+
+ inline_callout
+ = cl::confix_p(
+ "/*<" >> *cl::space_p,
+ (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
+ ">*/"
+ )
+ ;
+
+ line_callout
+ = cl::confix_p(
+ "/*<<" >> *cl::space_p,
+ (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
+ ">>*/"
+ )
+ >> *cl::space_p
+ ;
+
+ ignore
+ = cl::confix_p(
+ *cl::blank_p >> "//<-",
+ *cl::anychar_p,
+ "//->"
+ )
+ >> *cl::blank_p
+ >> cl::eol_p
+ | cl::confix_p(
+ "/*<-*/",
+ *cl::anychar_p,
+ "/*->*/"
+ )
+ | cl::confix_p(
+ "/*<-",
+ *cl::anychar_p,
+ "->*/"
+ )
+ ;
+
+ escaped_comment
+ = cl::confix_p(
+ *cl::space_p >> "//`",
+ (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
+ (cl::eol_p | cl::end_p)
+ )
+ | cl::confix_p(
+ *cl::space_p >> "/*`",
+ (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
+ "*/"
+ )
+ ;
+
+ // Note: Unlike escaped_comment and ignore, this doesn't
+ // swallow preceeding whitespace.
+ pass_thru_comment
+ = "//=" >> (cl::eps_p - '=')
+ >> ( *(cl::anychar_p - cl::eol_p)
+ >> (cl::eol_p | cl::end_p)
+ ) [boost::bind(&actions_type::mark, &actions, _1, _2)]
+ | cl::confix_p(
+ "/*=" >> (cl::eps_p - '='),
+ (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
+ "*/"
+ )
+ ;
+ }
+
+ cl::rule<Scanner>
+ start_, identifier, code_elements, start_snippet, end_snippet,
+ escaped_comment, pass_thru_comment, inline_callout, line_callout, ignore;
+
+ cl::rule<Scanner> const&
+ start() const { return start_; }
+ };
+
+ actions_type& actions;
+ };
+
+ int load_snippets(
+ fs::path const& filename
+ , std::vector<template_symbol>& storage // snippets are stored in a
+ // vector of template_symbols
+ , std::string const& extension
+ , value::tag_type load_type)
+ {
+ assert(load_type == block_tags::include ||
+ load_type == block_tags::import);
+
+ bool is_python = extension == ".py";
+ code_snippet_actions a(storage, load(filename, qbk_version_n), is_python ? "[python]" : "[c++]");
+
+ string_iterator first(a.source_file->source.begin());
+ string_iterator last(a.source_file->source.end());
+
+ cl::parse_info<string_iterator> info;
+
+ if(is_python) {
+ info = boost::spirit::classic::parse(first, last, python_code_snippet_grammar(a));
+ }
+ else {
+ info = boost::spirit::classic::parse(first, last, cpp_code_snippet_grammar(a));
+ }
+
+ assert(info.full);
+ return a.error_count;
+ }
+
+ void code_snippet_actions::append_code(string_iterator first, string_iterator last)
+ {
+ assert(last_code_pos <= first);
+
+ if(snippet_stack) {
+ if (last_code_pos != first) {
+ if (!in_code)
+ {
+ content.add("\n\n", last_code_pos);
+ content.add(source_type, last_code_pos);
+ content.add("```\n", last_code_pos);
+
+ in_code = true;
+ }
+
+ content.add(last_code_pos, first);
+ }
+ }
+
+ last_code_pos = last;
+ }
+
+ void code_snippet_actions::close_code()
+ {
+ if (!snippet_stack) return;
+
+ if (in_code)
+ {
+ content.add("\n```\n\n", last_code_pos);
+ in_code = false;
+ }
+ }
+
+ void code_snippet_actions::mark(string_iterator first, string_iterator last)
+ {
+ mark_begin = first;
+ mark_end = last;
+ }
+
+ void code_snippet_actions::pass_thru(string_iterator first, string_iterator last)
+ {
+ if(!snippet_stack) return;
+ append_code(first, last);
+
+ if (!in_code)
+ {
+ content.add("\n\n", first);
+ content.add(source_type, first);
+ content.add("```\n", first);
+ in_code = true;
+ }
+
+ content.add(mark_begin, mark_end);
+ }
+
+ void code_snippet_actions::callout(string_iterator first, string_iterator last)
+ {
+ if(!snippet_stack) return;
+ append_code(first, last);
+
+ if (!in_code)
+ {
+ content.add("\n\n", first);
+ content.add(source_type, first);
+ content.add("```\n", first);
+ in_code = true;
+ }
+
+ content.add(
+ "``[[callout" + boost::lexical_cast<std::string>(callout_id) + "]]``",
+ first);
+
+ snippet_stack->callouts.insert(qbk_value(source_file, mark_begin, mark_end, template_tags::block));
+ ++callout_id;
+ }
+
+ void code_snippet_actions::escaped_comment(string_iterator first, string_iterator last)
+ {
+ append_code(first, last);
+ close_code();
+
+ if (mark_begin != mark_end)
+ {
+ if (!snippet_stack)
+ {
+ start_snippet_impl("!", first);
+ }
+
+ snippet_data& snippet = *snippet_stack;
+
+ content.add("\n", mark_begin);
+ content.unindent_and_add(mark_begin, mark_end);
+
+ if (snippet.id == "!")
+ {
+ end_snippet_impl(last);
+ }
+ }
+ }
+
+ void code_snippet_actions::start_snippet(string_iterator first, string_iterator last)
+ {
+ append_code(first, last);
+ start_snippet_impl(std::string(mark_begin, mark_end), first);
+ }
+
+ void code_snippet_actions::end_snippet(string_iterator first, string_iterator last)
+ {
+ append_code(first, last);
+
+ if(!snippet_stack) {
+ if (qbk_version_n >= 106u) {
+ detail::outerr(source_file, first)
+ << "Mismatched end snippet."
+ << std::endl;
+ ++error_count;
+ }
+ else {
+ detail::outwarn(source_file, first)
+ << "Mismatched end snippet."
+ << std::endl;
+ }
+ return;
+ }
+
+ end_snippet_impl(first);
+ }
+
+ void code_snippet_actions::end_file(string_iterator, string_iterator pos)
+ {
+ append_code(pos, pos);
+ close_code();
+
+ while (snippet_stack) {
+ if (qbk_version_n >= 106u) {
+ detail::outerr(source_file->path)
+ << "Unclosed snippet '"
+ << detail::utf8(snippet_stack->id)
+ << "'"
+ << std::endl;
+ ++error_count;
+ }
+ else {
+ detail::outwarn(source_file->path)
+ << "Unclosed snippet '"
+ << detail::utf8(snippet_stack->id)
+ << "'"
+ << std::endl;
+ }
+
+ end_snippet_impl(pos);
+ }
+ }
+
+ void code_snippet_actions::start_snippet_impl(std::string const& id,
+ string_iterator position)
+ {
+ push_snippet_data(id, callout_id, position);
+ }
+
+ void code_snippet_actions::end_snippet_impl(string_iterator position)
+ {
+ assert(snippet_stack);
+
+ boost::shared_ptr<snippet_data> snippet = pop_snippet_data();
+ value callouts = snippet->callouts.release();
+
+ mapped_file_builder f;
+ f.start(source_file);
+ if (snippet->start_code) {
+ f.add("\n\n", snippet->source_pos);
+ f.add(source_type, snippet->source_pos);
+ f.add("```\n", snippet->source_pos);
+ }
+ f.add(content, snippet->start_pos, content.get_pos());
+ if (in_code) {
+ f.add("\n```\n\n", position);
+ }
+
+ std::vector<std::string> params;
+ int i = 0;
+ for(value::iterator it = callouts.begin(); it != callouts.end(); ++it)
+ {
+ params.push_back("[callout" + boost::lexical_cast<std::string>(snippet->callout_base_id + i) + "]");
+ ++i;
+ }
+
+ file_ptr body = f.release();
+
+ value_builder builder;
+ builder.set_tag(template_tags::snippet);
+ builder.insert(qbk_value(body, body->source.begin(), body->source.end(),
+ template_tags::block));
+ builder.insert(callouts);
+
+ template_symbol symbol(snippet->id, params, builder.release());
+ storage.push_back(symbol);
+
+ // Copy the snippet's callouts to its parent
+
+ if(snippet_stack)
+ {
+ snippet_stack->callouts.extend(callouts);
+ }
+ }
+}
diff --git a/tools/quickbook/src/collector.cpp b/tools/quickbook/src/collector.cpp
new file mode 100644
index 0000000000..fb2daec901
--- /dev/null
+++ b/tools/quickbook/src/collector.cpp
@@ -0,0 +1,67 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "collector.hpp"
+#include <boost/assert.hpp>
+
+namespace quickbook
+{
+ string_stream::string_stream()
+ : buffer_ptr(new std::string())
+ , stream_ptr(new ostream(boost::iostreams::back_inserter(*buffer_ptr.get())))
+ {}
+
+ string_stream::string_stream(string_stream const& other)
+ : buffer_ptr(other.buffer_ptr)
+ , stream_ptr(other.stream_ptr)
+ {}
+
+ string_stream&
+ string_stream::operator=(string_stream const& other)
+ {
+ buffer_ptr = other.buffer_ptr;
+ stream_ptr = other.stream_ptr;
+ return *this;
+ }
+
+ collector::collector()
+ : main(default_)
+ , top(default_)
+ {
+ }
+
+ collector::collector(string_stream& out)
+ : main(out)
+ , top(out)
+ {
+ }
+
+ collector::~collector()
+ {
+ BOOST_ASSERT(streams.empty()); // assert there are no more pushes than pops!!!
+ }
+
+ void
+ collector::push()
+ {
+ streams.push(string_stream());
+ top = boost::ref(streams.top());
+ }
+
+ void
+ collector::pop()
+ {
+ BOOST_ASSERT(!streams.empty());
+ streams.pop();
+
+ if (streams.empty())
+ top = boost::ref(main);
+ else
+ top = boost::ref(streams.top());
+ }
+}
diff --git a/tools/quickbook/src/collector.hpp b/tools/quickbook/src/collector.hpp
new file mode 100644
index 0000000000..a3b98e2702
--- /dev/null
+++ b/tools/quickbook/src/collector.hpp
@@ -0,0 +1,123 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_QUICKBOOK_COLLECTOR_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_COLLECTOR_HPP
+
+#include <string>
+#include <stack>
+#include <boost/ref.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/iostreams/device/back_inserter.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+
+namespace quickbook
+{
+ struct string_stream
+ {
+ typedef boost::iostreams::filtering_ostream ostream;
+
+ string_stream();
+ string_stream(string_stream const& other);
+ string_stream& operator=(string_stream const& other);
+
+ std::string const& str() const
+ {
+ stream_ptr->flush();
+ return *buffer_ptr.get();
+ }
+
+ std::ostream& get() const
+ {
+ return *stream_ptr.get();
+ }
+
+ void clear()
+ {
+ buffer_ptr->clear();
+ }
+
+ void swap(std::string& other)
+ {
+ stream_ptr->flush();
+ std::swap(other, *buffer_ptr.get());
+ }
+
+ void append(std::string const& other)
+ {
+ stream_ptr->flush();
+ *buffer_ptr.get() += other;
+ }
+
+ private:
+
+ boost::shared_ptr<std::string> buffer_ptr;
+ boost::shared_ptr<ostream> stream_ptr;
+ };
+
+ struct collector : boost::noncopyable
+ {
+ collector();
+ collector(string_stream& out);
+ ~collector();
+
+ void push();
+ void pop();
+
+ std::ostream& get() const
+ {
+ return top.get().get();
+ }
+
+ std::string const& str() const
+ {
+ return top.get().str();
+ }
+
+ void clear()
+ {
+ top.get().clear();
+ }
+
+ void swap(std::string& other)
+ {
+ top.get().swap(other);
+ }
+
+ void append(std::string const& other)
+ {
+ top.get().append(other);
+ }
+
+ private:
+
+ std::stack<string_stream> streams;
+ boost::reference_wrapper<string_stream> main;
+ boost::reference_wrapper<string_stream> top;
+ string_stream default_;
+ };
+
+ template <typename T>
+ inline collector&
+ operator<<(collector& out, T const& val)
+ {
+ out.get() << val;
+ return out;
+ }
+
+ inline collector&
+ operator<<(collector& out, std::string const& val)
+ {
+ out.append(val);
+ return out;
+ }
+}
+
+#endif // BOOST_SPIRIT_QUICKBOOK_COLLECTOR_HPP
+
diff --git a/tools/quickbook/src/doc_info_actions.cpp b/tools/quickbook/src/doc_info_actions.cpp
new file mode 100644
index 0000000000..e23466fd3d
--- /dev/null
+++ b/tools/quickbook/src/doc_info_actions.cpp
@@ -0,0 +1,559 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ Copyright (c) 2005 Thomas Guest
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <sstream>
+#include <boost/bind.hpp>
+#include <boost/algorithm/string/join.hpp>
+#include <boost/foreach.hpp>
+#include <boost/filesystem/v3/operations.hpp>
+#include "quickbook.hpp"
+#include "utils.hpp"
+#include "files.hpp"
+#include "input_path.hpp"
+#include "actions_class.hpp"
+#include "doc_info_tags.hpp"
+#include "id_manager.hpp"
+
+namespace quickbook
+{
+ static void write_document_title(collector& out, value const& title, value const& version);
+
+ static std::string doc_info_output(value const& p, unsigned version)
+ {
+ if (qbk_version_n < version) {
+ std::string value = p.get_quickbook();
+ value.erase(value.find_last_not_of(" \t") + 1);
+ return value;
+ }
+ else {
+ return p.get_encoded();
+ }
+ }
+
+ // Each docinfo attribute is stored in a value list, these are then stored
+ // in a sorted value list. The following convenience methods extract all the
+ // values for an attribute tag.
+
+ // Expecting at most one attribute, with several values in the list.
+ value consume_list(value_consumer& c, value::tag_type tag,
+ std::vector<std::string>* duplicates)
+ {
+ value p;
+
+ int count = 0;
+ while(c.check(tag)) {
+ p = c.consume();
+ ++count;
+ }
+
+ if(count > 1) duplicates->push_back(doc_info_attributes::name(tag));
+
+ return p;
+ }
+
+ // Expecting at most one attribute, with a single value, so extract that
+ // immediately.
+ value consume_value_in_list(value_consumer& c, value::tag_type tag,
+ std::vector<std::string>* duplicates)
+ {
+ value l = consume_list(c, tag, duplicates);
+ if(l.empty()) return l;
+
+ assert(l.is_list());
+ value_consumer c2 = l;
+ value p = c2.consume();
+ c2.finish();
+
+ return p;
+ }
+
+ // Any number of attributes, so stuff them into a vector.
+ std::vector<value> consume_multiple_lists(value_consumer& c, value::tag_type tag)
+ {
+ std::vector<value> values;
+
+ while(c.check(tag)) {
+ values.push_back(c.consume());
+ }
+
+ return values;
+ }
+
+ unsigned get_version(quickbook::actions& actions, bool using_docinfo,
+ value version)
+ {
+ unsigned result = 0;
+
+ if (!version.empty()) {
+ value_consumer version_values(version);
+ bool before_docinfo = version_values.optional_consume(
+ doc_info_tags::before_docinfo).check();
+ int major_verison = version_values.consume().get_int();
+ int minor_verison = version_values.consume().get_int();
+ version_values.finish();
+
+ if (before_docinfo || using_docinfo) {
+ result = ((unsigned) major_verison * 100) +
+ (unsigned) minor_verison;
+
+ if(result < 100 || result > 106)
+ {
+ detail::outerr(actions.current_file->path)
+ << "Unknown version: "
+ << major_verison
+ << "."
+ << minor_verison
+ << std::endl;
+ ++actions.error_count;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ std::string pre(quickbook::actions& actions, parse_iterator pos,
+ value include_doc_id, bool nested_file)
+ {
+ // The doc_info in the file has been parsed. Here's what we'll do
+ // *before* anything else.
+ //
+ // If there isn't a doc info block, then values will be empty, so most
+ // of the following code won't actually do anything.
+
+ value_consumer values = actions.values.release();
+
+ // Skip over invalid attributes
+
+ while (values.check(value::default_tag)) values.consume();
+
+ bool use_doc_info = false;
+ std::string doc_type;
+ value doc_title;
+
+ if (values.check(doc_info_tags::type))
+ {
+ doc_type = values.consume(doc_info_tags::type).get_quickbook();
+ doc_title = values.consume(doc_info_tags::title);
+ use_doc_info = !nested_file || qbk_version_n >= 106u;
+ }
+ else
+ {
+ if (!nested_file)
+ {
+ detail::outerr(actions.current_file, pos.base())
+ << "No doc_info block."
+ << std::endl;
+
+ ++actions.error_count;
+
+ // Create a fake document info block in order to continue.
+ doc_type = "article";
+ doc_title = qbk_value(actions.current_file,
+ pos.base(), pos.base(),
+ doc_info_tags::type);
+ use_doc_info = true;
+ }
+ }
+
+ std::vector<std::string> duplicates;
+
+ value qbk_version = consume_list(values, doc_attributes::qbk_version, &duplicates);
+ value compatibility_mode = consume_list(values, doc_attributes::compatibility_mode, &duplicates);
+ consume_multiple_lists(values, doc_attributes::source_mode);
+
+ value id = consume_value_in_list(values, doc_info_attributes::id, &duplicates);
+ value dirname = consume_value_in_list(values, doc_info_attributes::dirname, &duplicates);
+ value last_revision = consume_value_in_list(values, doc_info_attributes::last_revision, &duplicates);
+ value purpose = consume_value_in_list(values, doc_info_attributes::purpose, &duplicates);
+ std::vector<value> categories = consume_multiple_lists(values, doc_info_attributes::category);
+ value lang = consume_value_in_list(values, doc_info_attributes::lang, &duplicates);
+ value version = consume_value_in_list(values, doc_info_attributes::version, &duplicates);
+ std::vector<value> authors = consume_multiple_lists(values, doc_info_attributes::authors);
+ std::vector<value> copyrights = consume_multiple_lists(values, doc_info_attributes::copyright);
+ value license = consume_value_in_list(values, doc_info_attributes::license, &duplicates);
+ std::vector<value> biblioids = consume_multiple_lists(values, doc_info_attributes::biblioid);
+ value xmlbase = consume_value_in_list(values, doc_info_attributes::xmlbase, &duplicates);
+
+ values.finish();
+
+ if(!duplicates.empty())
+ {
+ detail::outwarn(actions.current_file->path)
+ << (duplicates.size() > 1 ?
+ "Duplicate attributes" : "Duplicate attribute")
+ << ":" << detail::utf8(boost::algorithm::join(duplicates, ", "))
+ << "\n"
+ ;
+ }
+
+ std::string include_doc_id_, id_;
+
+ if (!include_doc_id.empty())
+ include_doc_id_ = include_doc_id.get_quickbook();
+ if (!id.empty())
+ id_ = id.get_quickbook();
+
+ // Quickbook version
+
+ unsigned new_version = get_version(actions, use_doc_info, qbk_version);
+
+ if (new_version != qbk_version_n && new_version == 106)
+ {
+ detail::outwarn(actions.current_file->path)
+ << "Quickbook 1.6 is still under development and is "
+ "likely to change in the future." << std::endl;
+ }
+
+ if (new_version) {
+ qbk_version_n = new_version;
+ }
+ else if (use_doc_info) {
+ // hard code quickbook version to v1.1
+ qbk_version_n = 101;
+ detail::outwarn(actions.current_file, pos.base())
+ << "Quickbook version undefined. "
+ "Version 1.1 is assumed" << std::endl;
+ }
+
+ actions.current_file->version(qbk_version_n);
+
+ // Compatibility Version
+
+ unsigned compatibility_version =
+ get_version(actions, use_doc_info, compatibility_mode);
+
+ if (!compatibility_version) {
+ compatibility_version = use_doc_info ?
+ qbk_version_n : actions.ids.compatibility_version();
+ }
+
+ // Start file, finish here if not generating document info.
+
+ if (!use_doc_info)
+ {
+ actions.ids.start_file(compatibility_version, include_doc_id_, id_,
+ doc_title);
+ return "";
+ }
+
+ std::string id_placeholder =
+ actions.ids.start_file_with_docinfo(
+ compatibility_version, include_doc_id_, id_, doc_title);
+
+ // Make sure we really did have a document info block.
+
+ assert(doc_title.check() && !doc_type.empty());
+
+ // Set xmlbase
+
+ std::string xmlbase_value;
+
+ if (!xmlbase.empty())
+ {
+ xinclude_path x = calculate_xinclude_path(xmlbase, actions);
+
+ if (!fs::is_directory(x.path))
+ {
+ detail::outerr(xmlbase.get_file(), xmlbase.get_position())
+ << "xmlbase \""
+ << detail::utf8(xmlbase.get_quickbook())
+ << "\" isn't a directory."
+ << std::endl;
+
+ ++actions.error_count;
+ }
+ else
+ {
+ xmlbase_value = x.uri;
+ actions.xinclude_base = x.path;
+ }
+ }
+
+ // Warn about invalid fields
+
+ if (doc_type != "library")
+ {
+ std::vector<std::string> invalid_attributes;
+
+ if (!purpose.empty())
+ invalid_attributes.push_back("purpose");
+
+ if (!categories.empty())
+ invalid_attributes.push_back("category");
+
+ if (!dirname.empty())
+ invalid_attributes.push_back("dirname");
+
+ if(!invalid_attributes.empty())
+ {
+ detail::outwarn(actions.current_file->path)
+ << (invalid_attributes.size() > 1 ?
+ "Invalid attributes" : "Invalid attribute")
+ << " for '" << detail::utf8(doc_type) << " document info': "
+ << detail::utf8(boost::algorithm::join(invalid_attributes, ", "))
+ << "\n"
+ ;
+ }
+ }
+
+ // Write out header
+
+ if (!nested_file)
+ {
+ actions.out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ << "<!DOCTYPE "
+ << doc_type
+ << " PUBLIC \"-//Boost//DTD BoostBook XML V1.0//EN\"\n"
+ << " \"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd\">\n"
+ ;
+ }
+
+ actions.out << '<' << doc_type << "\n"
+ << " id=\""
+ << id_placeholder
+ << "\"\n";
+
+ if(!lang.empty())
+ {
+ actions.out << " lang=\""
+ << doc_info_output(lang, 106)
+ << "\"\n";
+ }
+
+ if(doc_type == "library" && !doc_title.empty())
+ {
+ actions.out << " name=\"" << doc_info_output(doc_title, 106) << "\"\n";
+ }
+
+ // Set defaults for dirname + last_revision
+
+ if (!dirname.empty() || doc_type == "library")
+ {
+ actions.out << " dirname=\"";
+ if (!dirname.empty()) {
+ actions.out << doc_info_output(dirname, 106);
+ }
+ else if (!id_.empty()) {
+ actions.out << id_;
+ }
+ else if (!include_doc_id_.empty()) {
+ actions.out << include_doc_id_;
+ }
+ else if (!doc_title.empty()) {
+ actions.out << detail::make_identifier(doc_title.get_quickbook());
+ }
+ else {
+ actions.out << "library";
+ }
+
+ actions.out << "\"\n";
+ }
+
+ actions.out << " last-revision=\"";
+ if (!last_revision.empty())
+ {
+ actions.out << doc_info_output(last_revision, 106);
+ }
+ else
+ {
+ // default value for last-revision is now
+
+ char strdate[64];
+ strftime(
+ strdate, sizeof(strdate),
+ (debug_mode ?
+ "DEBUG MODE Date: %Y/%m/%d %H:%M:%S $" :
+ "$" /* prevent CVS substitution */ "Date: %Y/%m/%d %H:%M:%S $"),
+ current_gm_time
+ );
+
+ actions.out << strdate;
+ }
+
+ actions.out << "\" \n";
+
+ if (!xmlbase.empty())
+ {
+ actions.out << " xml:base=\""
+ << xmlbase_value
+ << "\"\n";
+ }
+
+ actions.out << " xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n";
+
+ std::ostringstream tmp;
+
+ if(!authors.empty())
+ {
+ tmp << " <authorgroup>\n";
+ BOOST_FOREACH(value_consumer author_values, authors)
+ {
+ while (author_values.check()) {
+ value surname = author_values.consume(doc_info_tags::author_surname);
+ value first = author_values.consume(doc_info_tags::author_first);
+
+ tmp << " <author>\n"
+ << " <firstname>"
+ << doc_info_output(first, 106)
+ << "</firstname>\n"
+ << " <surname>"
+ << doc_info_output(surname, 106)
+ << "</surname>\n"
+ << " </author>\n";
+ }
+ }
+ tmp << " </authorgroup>\n";
+ }
+
+ BOOST_FOREACH(value_consumer copyright, copyrights)
+ {
+ while(copyright.check())
+ {
+ tmp << "\n" << " <copyright>\n";
+
+ while(copyright.check(doc_info_tags::copyright_year))
+ {
+ value year_start_value = copyright.consume();
+ int year_start = year_start_value.get_int();
+ int year_end =
+ copyright.check(doc_info_tags::copyright_year_end) ?
+ copyright.consume().get_int() :
+ year_start;
+
+ if (year_end < year_start) {
+ ++actions.error_count;
+
+ detail::outerr(actions.current_file, copyright.begin()->get_position())
+ << "Invalid year range: "
+ << year_start
+ << "-"
+ << year_end
+ << "."
+ << std::endl;
+ }
+
+ for(; year_start <= year_end; ++year_start)
+ tmp << " <year>" << year_start << "</year>\n";
+ }
+
+ tmp << " <holder>"
+ << doc_info_output(copyright.consume(doc_info_tags::copyright_name), 106)
+ << "</holder>\n"
+ << " </copyright>\n"
+ << "\n"
+ ;
+ }
+ }
+
+ if (!license.empty())
+ {
+ tmp << " <legalnotice id=\""
+ << actions.ids.add_id("legal", id_category::generated)
+ << "\">\n"
+ << " <para>\n"
+ << " " << doc_info_output(license, 103) << "\n"
+ << " </para>\n"
+ << " </legalnotice>\n"
+ << "\n"
+ ;
+ }
+
+ if (!purpose.empty())
+ {
+ tmp << " <" << doc_type << "purpose>\n"
+ << " " << doc_info_output(purpose, 103)
+ << " </" << doc_type << "purpose>\n"
+ << "\n"
+ ;
+ }
+
+ BOOST_FOREACH(value_consumer values, categories) {
+ value category = values.optional_consume();
+ if(!category.empty()) {
+ tmp << " <" << doc_type << "category name=\"category:"
+ << doc_info_output(category, 106)
+ << "\"></" << doc_type << "category>\n"
+ << "\n"
+ ;
+ }
+ values.finish();
+ }
+
+ BOOST_FOREACH(value_consumer biblioid, biblioids)
+ {
+ value class_ = biblioid.consume(doc_info_tags::biblioid_class);
+ value value_ = biblioid.consume(doc_info_tags::biblioid_value);
+
+ tmp << " <biblioid class=\""
+ << class_.get_quickbook()
+ << "\">"
+ << doc_info_output(value_, 106)
+ << "</biblioid>"
+ << "\n"
+ ;
+ biblioid.finish();
+ }
+
+ if(doc_type != "library") {
+ write_document_title(actions.out, doc_title, version);
+ }
+
+ std::string docinfo = tmp.str();
+ if(!docinfo.empty())
+ {
+ actions.out << " <" << doc_type << "info>\n"
+ << docinfo
+ << " </" << doc_type << "info>\n"
+ << "\n"
+ ;
+ }
+
+ if(doc_type == "library") {
+ write_document_title(actions.out, doc_title, version);
+ }
+
+ return doc_type;
+ }
+
+ void post(quickbook::actions& actions, std::string const& doc_type)
+ {
+ // We've finished generating our output. Here's what we'll do
+ // *after* everything else.
+
+ // Close any open sections.
+ if (!doc_type.empty() && actions.ids.section_level() > 1) {
+ detail::outwarn(actions.current_file->path)
+ << "Missing [endsect] detected at end of file."
+ << std::endl;
+
+ while(actions.ids.section_level() > 1) {
+ actions.out << "</section>";
+ actions.ids.end_section();
+ }
+ }
+
+ actions.ids.end_file();
+ if (!doc_type.empty()) actions.out << "\n</" << doc_type << ">\n\n";
+ }
+
+ static void write_document_title(collector& out, value const& title, value const& version)
+ {
+ if (!title.empty())
+ {
+ out << " <title>"
+ << doc_info_output(title, 106);
+ if (!version.empty()) {
+ out << ' ' << doc_info_output(version, 106);
+ }
+ out<< "</title>\n\n\n";
+ }
+ }
+}
diff --git a/tools/quickbook/src/doc_info_grammar.cpp b/tools/quickbook/src/doc_info_grammar.cpp
new file mode 100644
index 0000000000..26418eec48
--- /dev/null
+++ b/tools/quickbook/src/doc_info_grammar.cpp
@@ -0,0 +1,289 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include <map>
+#include <boost/foreach.hpp>
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_actor.hpp>
+#include <boost/spirit/include/classic_loops.hpp>
+#include <boost/spirit/include/classic_symbols.hpp>
+#include <boost/spirit/include/classic_chset.hpp>
+#include <boost/spirit/include/classic_numerics.hpp>
+#include <boost/spirit/include/phoenix1_primitives.hpp>
+#include <boost/spirit/include/phoenix1_operators.hpp>
+#include "grammar_impl.hpp"
+#include "actions_class.hpp"
+#include "doc_info_tags.hpp"
+#include "phrase_tags.hpp"
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+
+ struct attribute_info
+ {
+ attribute_info(value::tag_type t, cl::rule<scanner>* r)
+ : tag(t), rule(r)
+ {}
+
+ value::tag_type tag;
+ cl::rule<scanner>* rule;
+ };
+
+ struct doc_info_grammar_local
+ {
+ struct assign_attribute_type
+ {
+ assign_attribute_type(doc_info_grammar_local& l)
+ : l(l)
+ {}
+
+ void operator()(value::tag_type& t) const {
+ l.attribute_rule = *l.attribute_rules[t];
+ l.attribute_tag = t;
+ }
+
+ doc_info_grammar_local& l;
+ };
+
+ struct fallback_attribute_type
+ {
+ fallback_attribute_type(doc_info_grammar_local& l)
+ : l(l)
+ {}
+
+ void operator()(parse_iterator, parse_iterator) const {
+ l.attribute_rule = l.doc_fallback;
+ l.attribute_tag = value::default_tag;
+ }
+
+ doc_info_grammar_local& l;
+ };
+
+ cl::rule<scanner>
+ doc_info_block, doc_attribute, doc_info_attribute,
+ doc_title, doc_simple, doc_phrase, doc_fallback,
+ doc_authors, doc_author,
+ doc_copyright, doc_copyright_holder,
+ doc_source_mode, doc_biblioid, doc_compatibility_mode,
+ quickbook_version, char_;
+ cl::uint_parser<int, 10, 4, 4> doc_copyright_year;
+ cl::symbols<> doc_types;
+ cl::symbols<value::tag_type> doc_info_attributes;
+ cl::symbols<value::tag_type> doc_attributes;
+ std::map<value::tag_type, cl::rule<scanner>* > attribute_rules;
+ value::tag_type attribute_tag;
+ cl::rule<scanner> attribute_rule;
+ assign_attribute_type assign_attribute;
+ fallback_attribute_type fallback_attribute;
+
+ doc_info_grammar_local()
+ : assign_attribute(*this)
+ , fallback_attribute(*this)
+ {}
+
+ bool source_mode_unset;
+ };
+
+ void quickbook_grammar::impl::init_doc_info()
+ {
+ doc_info_grammar_local& local = cleanup_.add(
+ new doc_info_grammar_local);
+
+ typedef cl::uint_parser<int, 10, 1, 2> uint2_t;
+
+ local.doc_types =
+ "book", "article", "library", "chapter", "part"
+ , "appendix", "preface", "qandadiv", "qandaset"
+ , "reference", "set"
+ ;
+
+ BOOST_FOREACH(value::tag_type t, doc_attributes::tags()) {
+ local.doc_attributes.add(doc_attributes::name(t), t);
+ local.doc_info_attributes.add(doc_attributes::name(t), t);
+ }
+
+ BOOST_FOREACH(value::tag_type t, doc_info_attributes::tags()) {
+ local.doc_info_attributes.add(doc_info_attributes::name(t), t);
+ }
+
+ doc_info_details =
+ space [ph::var(local.source_mode_unset) = true]
+ >> *( local.doc_attribute
+ >> space
+ )
+ >> !local.doc_info_block
+ ;
+
+ local.doc_info_block =
+ '['
+ >> space
+ >> (local.doc_types >> cl::eps_p)
+ [actions.values.entry(ph::arg1, ph::arg2, doc_info_tags::type)]
+ >> hard_space
+ >> actions.to_value(doc_info_tags::title)
+ [ *( ~cl::eps_p(blank >> (cl::ch_p('[') | ']' | cl::eol_p))
+ >> local.char_
+ )
+ // Include 'blank' here so that it will be included in
+ // id generation.
+ >> blank
+ ]
+ >> space
+ >> !(qbk_since(106u) >> cl::eps_p(ph::var(local.source_mode_unset))
+ [cl::assign_a(actions.source_mode, "c++")]
+ )
+ >> (*( local.doc_info_attribute
+ >> space
+ )) [actions.values.sort()]
+ >> ( ']'
+ >> (+eol | cl::end_p)
+ | cl::eps_p [actions.error]
+ )
+ ;
+
+ local.doc_attribute =
+ '['
+ >> space
+ >> local.doc_attributes [local.assign_attribute]
+ >> hard_space
+ >> actions.values.list(ph::var(local.attribute_tag))
+ [ cl::eps_p [actions.values.entry(ph::arg1, ph::arg2, doc_info_tags::before_docinfo)]
+ >> local.attribute_rule
+ ]
+ >> space
+ >> ']'
+ ;
+
+ local.doc_info_attribute =
+ '['
+ >> space
+ >> ( local.doc_info_attributes
+ [local.assign_attribute]
+ | (+(cl::alnum_p | '_' | '-'))
+ [local.fallback_attribute]
+ [actions.error("Unrecognized document attribute: '%s'.")]
+ )
+ >> hard_space
+ >> actions.values.list(ph::var(local.attribute_tag))
+ [local.attribute_rule]
+ >> space
+ >> ']'
+ ;
+
+ local.doc_fallback = actions.to_value() [
+ *(~cl::eps_p(']') >> local.char_)
+ ];
+
+ // Document Attributes
+
+ local.quickbook_version =
+ cl::uint_p [actions.values.entry(ph::arg1)]
+ >> '.'
+ >> uint2_t() [actions.values.entry(ph::arg1)]
+ ;
+
+ local.attribute_rules[doc_attributes::qbk_version] = &local.quickbook_version;
+
+ local.doc_compatibility_mode =
+ cl::uint_p [actions.values.entry(ph::arg1)]
+ >> '.'
+ >> uint2_t() [actions.values.entry(ph::arg1)]
+ ;
+
+ local.attribute_rules[doc_attributes::compatibility_mode] = &local.doc_compatibility_mode;
+
+ local.doc_source_mode =
+ (
+ cl::str_p("c++")
+ | "python"
+ | "teletype"
+ ) [cl::assign_a(actions.source_mode)]
+ [ph::var(local.source_mode_unset) = false]
+ ;
+
+ local.attribute_rules[doc_attributes::source_mode] = &local.doc_source_mode;
+
+ // Document Info Attributes
+
+ local.doc_simple = actions.to_value() [*(~cl::eps_p(']') >> local.char_)];
+ local.attribute_rules[doc_info_attributes::version] = &local.doc_simple;
+ local.attribute_rules[doc_info_attributes::id] = &local.doc_simple;
+ local.attribute_rules[doc_info_attributes::dirname] = &local.doc_simple;
+ local.attribute_rules[doc_info_attributes::category] = &local.doc_simple;
+ local.attribute_rules[doc_info_attributes::last_revision] = &local.doc_simple;
+ local.attribute_rules[doc_info_attributes::lang] = &local.doc_simple;
+ local.attribute_rules[doc_info_attributes::xmlbase] = &local.doc_simple;
+
+ local.doc_copyright_holder
+ = *( ~cl::eps_p
+ ( ']'
+ | ',' >> space >> local.doc_copyright_year
+ )
+ >> local.char_
+ );
+
+ local.doc_copyright =
+ *( +( local.doc_copyright_year
+ [actions.values.entry(ph::arg1, doc_info_tags::copyright_year)]
+ >> space
+ >> !( '-'
+ >> space
+ >> local.doc_copyright_year
+ [actions.values.entry(ph::arg1, doc_info_tags::copyright_year_end)]
+ >> space
+ )
+ >> !cl::ch_p(',')
+ >> space
+ )
+ >> actions.to_value(doc_info_tags::copyright_name) [ local.doc_copyright_holder ]
+ >> !cl::ch_p(',')
+ >> space
+ )
+ ;
+
+ local.attribute_rules[doc_info_attributes::copyright] = &local.doc_copyright;
+
+ local.doc_phrase = actions.to_value() [ nested_phrase ];
+ local.attribute_rules[doc_info_attributes::purpose] = &local.doc_phrase;
+ local.attribute_rules[doc_info_attributes::license] = &local.doc_phrase;
+
+ local.doc_author =
+ '['
+ >> space
+ >> actions.to_value(doc_info_tags::author_surname)
+ [*(~cl::eps_p(',') >> local.char_)]
+ >> ',' >> space
+ >> actions.to_value(doc_info_tags::author_first)
+ [*(~cl::eps_p(']') >> local.char_)]
+ >> ']'
+ ;
+
+ local.doc_authors =
+ *( local.doc_author
+ >> space
+ >> !(cl::ch_p(',') >> space)
+ )
+ ;
+
+ local.attribute_rules[doc_info_attributes::authors] = &local.doc_authors;
+
+ local.doc_biblioid =
+ (+cl::alnum_p) [actions.values.entry(ph::arg1, ph::arg2, doc_info_tags::biblioid_class)]
+ >> hard_space
+ >> actions.to_value(doc_info_tags::biblioid_value)
+ [+(~cl::eps_p(']') >> local.char_)]
+ ;
+
+ local.attribute_rules[doc_info_attributes::biblioid] = &local.doc_biblioid;
+
+ local.char_ = escape | cl::anychar_p[actions.plain_char];
+ }
+}
diff --git a/tools/quickbook/src/doc_info_tags.hpp b/tools/quickbook/src/doc_info_tags.hpp
new file mode 100644
index 0000000000..4caea3317c
--- /dev/null
+++ b/tools/quickbook/src/doc_info_tags.hpp
@@ -0,0 +1,48 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_SPIRIT_QUICKBOOK_DOC_INFO_TAGS_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_DOC_INFO_TAGS_HPP
+
+#include "value_tags.hpp"
+
+namespace quickbook
+{
+ QUICKBOOK_VALUE_TAGS(doc_info_tags, 0x400,
+ (before_docinfo)
+ (type)
+ (title)
+ (author_surname)(author_first)
+ (copyright_year)(copyright_year_end)(copyright_name)
+ (license)
+ (biblioid_class)(biblioid_value)
+ )
+
+ QUICKBOOK_VALUE_NAMED_TAGS(doc_attributes, 0x440,
+ ((qbk_version)("quickbook"))
+ ((compatibility_mode)("compatibility-mode"))
+ ((source_mode)("source-mode"))
+ )
+
+ QUICKBOOK_VALUE_NAMED_TAGS(doc_info_attributes, 0x450,
+ ((id)("id"))
+ ((dirname)("dirname"))
+ ((last_revision)("last-revision"))
+ ((purpose)("purpose"))
+ ((category)("category"))
+ ((lang)("lang"))
+ ((version)("version"))
+ ((authors)("authors"))
+ ((copyright)("copyright"))
+ ((license)("license"))
+ ((biblioid)("biblioid"))
+ ((xmlbase)("xmlbase"))
+ )
+}
+
+#endif
diff --git a/tools/quickbook/src/files.cpp b/tools/quickbook/src/files.cpp
new file mode 100644
index 0000000000..ce63c84eb2
--- /dev/null
+++ b/tools/quickbook/src/files.cpp
@@ -0,0 +1,507 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "files.hpp"
+#include <boost/filesystem/v3/fstream.hpp>
+#include <boost/unordered_map.hpp>
+#include <boost/range/algorithm/upper_bound.hpp>
+#include <boost/range/algorithm/transform.hpp>
+#include <fstream>
+#include <iterator>
+
+namespace quickbook
+{
+ namespace
+ {
+ boost::unordered_map<fs::path, file_ptr> files;
+ }
+
+ // Read the first few bytes in a file to see it starts with a byte order
+ // mark. If it doesn't, then write the characters we've already read in.
+ // Although, given how UTF-8 works, if we've read anything in, the files
+ // probably broken.
+
+ template <typename InputIterator, typename OutputIterator>
+ bool check_bom(InputIterator& begin, InputIterator end,
+ OutputIterator out, char const* chars, int length)
+ {
+ char const* ptr = chars;
+
+ while(begin != end && *begin == *ptr) {
+ ++begin;
+ ++ptr;
+ --length;
+ if(length == 0) return true;
+ }
+
+ // Failed to match, so write the skipped characters to storage:
+ while(chars != ptr) *out++ = *chars++;
+
+ return false;
+ }
+
+ template <typename InputIterator, typename OutputIterator>
+ std::string read_bom(InputIterator& begin, InputIterator end,
+ OutputIterator out)
+ {
+ if(begin == end) return "";
+
+ const char* utf8 = "\xef\xbb\xbf" ;
+ const char* utf32be = "\0\0\xfe\xff";
+ const char* utf32le = "\xff\xfe\0\0";
+
+ unsigned char c = *begin;
+ switch(c)
+ {
+ case 0xEF: { // UTF-8
+ return check_bom(begin, end, out, utf8, 3) ? "UTF-8" : "";
+ }
+ case 0xFF: // UTF-16/UTF-32 little endian
+ return !check_bom(begin, end, out, utf32le, 2) ? "" :
+ check_bom(begin, end, out, utf32le + 2, 2) ? "UTF-32" : "UTF-16";
+ case 0: // UTF-32 big endian
+ return check_bom(begin, end, out, utf32be, 4) ? "UTF-32" : "";
+ case 0xFE: // UTF-16 big endian
+ return check_bom(begin, end, out, utf32be + 2, 2) ? "UTF-16" : "";
+ default:
+ return "";
+ }
+ }
+
+ // Copy a string, converting mac and windows style newlines to unix
+ // newlines.
+
+ template <typename InputIterator, typename OutputIterator>
+ void normalize(InputIterator begin, InputIterator end,
+ OutputIterator out)
+ {
+ std::string encoding = read_bom(begin, end, out);
+
+ if(encoding != "UTF-8" && encoding != "")
+ throw load_error(encoding +
+ " is not supported. Please use UTF-8.");
+
+ while(begin != end) {
+ if(*begin == '\r') {
+ *out++ = '\n';
+ ++begin;
+ if(begin != end && *begin == '\n') ++begin;
+ }
+ else {
+ *out++ = *begin++;
+ }
+ }
+ }
+
+ file_ptr load(fs::path const& filename, unsigned qbk_version)
+ {
+ boost::unordered_map<fs::path, file_ptr>::iterator pos
+ = files.find(filename);
+
+ if (pos == files.end())
+ {
+ fs::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ throw load_error("Could not open input file.");
+
+ // Turn off white space skipping on the stream
+ in.unsetf(std::ios::skipws);
+
+ std::string source;
+ normalize(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(source));
+
+ if (in.bad())
+ throw load_error("Error reading input file.");
+
+ bool inserted;
+
+ boost::tie(pos, inserted) = files.emplace(
+ filename, new file(filename, source, qbk_version));
+
+ assert(inserted);
+ }
+
+ return pos->second;
+ }
+
+ file_position relative_position(
+ std::string::const_iterator begin,
+ std::string::const_iterator iterator)
+ {
+ file_position pos;
+ std::string::const_iterator line_begin = begin;
+
+ while (begin != iterator)
+ {
+ if (*begin == '\r')
+ {
+ ++begin;
+ ++pos.line;
+ line_begin = begin;
+ }
+ else if (*begin == '\n')
+ {
+ ++begin;
+ ++pos.line;
+ line_begin = begin;
+ if (begin == iterator) break;
+ if (*begin == '\r')
+ {
+ ++begin;
+ line_begin = begin;
+ }
+ }
+ else
+ {
+ ++begin;
+ }
+ }
+
+ pos.column = iterator - line_begin + 1;
+ return pos;
+ }
+
+ file_position file::position_of(std::string::const_iterator iterator) const
+ {
+ return relative_position(source.begin(), iterator);
+ }
+
+ // Mapped files.
+
+ struct mapped_file_section
+ {
+ enum section_types {
+ normal,
+ empty,
+ indented
+ };
+
+ std::string::size_type original_pos;
+ std::string::size_type our_pos;
+ section_types section_type;
+
+ mapped_file_section(
+ std::string::size_type original_pos,
+ std::string::size_type our_pos,
+ section_types section_type = normal) :
+ original_pos(original_pos), our_pos(our_pos), section_type(section_type) {}
+
+ std::string::size_type to_original_pos(std::string::size_type pos)
+ {
+ switch (section_type) {
+ case normal:
+ return pos - our_pos + original_pos;
+ case empty:
+ return original_pos;
+ case indented:
+ // Indented doesn't really work, but that's okay because we
+ // currently don't break up indented code.
+ assert(pos == our_pos);
+ return pos - our_pos + original_pos;
+ default:
+ assert(false);
+ return original_pos;
+ }
+ }
+
+ // If 'to_original_pos' worked for indented blocks, this wouldn't
+ // be necessary.
+ file_position calculate_position(
+ file_position const& original,
+ file_position const& relative) const
+ {
+ switch (section_type) {
+ case normal:
+ return file_position(
+ original.line + relative.line - 1,
+ relative.line == 1 ?
+ original.column + relative.column - 1 :
+ relative.column);
+ case empty:
+ return original;
+ case indented:
+ return file_position(
+ original.line + relative.line - 1,
+ original.column + relative.column - 1);
+ default:
+ assert(false);
+ return file_position();
+ }
+ }
+ };
+
+ struct mapped_section_original_cmp
+ {
+ bool operator()(mapped_file_section const& x,
+ mapped_file_section const& y)
+ {
+ return x.original_pos < y.original_pos;
+ }
+
+ bool operator()(mapped_file_section const& x,
+ std::string::size_type const& y)
+ {
+ return x.original_pos < y;
+ }
+
+ bool operator()(std::string::size_type const& x,
+ mapped_file_section const& y)
+ {
+ return x < y.original_pos;
+ }
+ };
+
+ struct mapped_section_pos_cmp
+ {
+ bool operator()(mapped_file_section const& x,
+ mapped_file_section const& y)
+ {
+ return x.our_pos < y.our_pos;
+ }
+
+ bool operator()(mapped_file_section const& x,
+ std::string::size_type const& y)
+ {
+ return x.our_pos < y;
+ }
+
+ bool operator()(std::string::size_type const& x,
+ mapped_file_section const& y)
+ {
+ return x < y.our_pos;
+ }
+ };
+
+ struct mapped_file : file
+ {
+ mapped_file(file_ptr original) :
+ file(original->path, std::string(), original->version()),
+ original(original), mapped_sections() {}
+
+ file_ptr original;
+ std::vector<mapped_file_section> mapped_sections;
+
+ void add_empty_mapped_file_section(std::string::const_iterator pos) {
+ std::string::size_type original_pos =
+ pos - original->source.begin();
+
+ if (mapped_sections.empty() ||
+ mapped_sections.back().section_type !=
+ mapped_file_section::empty ||
+ mapped_sections.back().original_pos != original_pos)
+ {
+ mapped_sections.push_back(mapped_file_section(
+ original_pos, source.size(),
+ mapped_file_section::empty));
+ }
+ }
+
+ void add_mapped_file_section(std::string::const_iterator pos) {
+ mapped_sections.push_back(mapped_file_section(
+ pos - original->source.begin(), source.size()));
+ }
+
+ void add_indented_mapped_file_section(std::string::const_iterator pos) {
+ mapped_sections.push_back(mapped_file_section(
+ pos - original->source.begin(), source.size(),
+ mapped_file_section::indented));
+ }
+
+ virtual file_position position_of(std::string::const_iterator) const;
+ };
+
+ namespace {
+ std::list<mapped_file> mapped_files;
+ }
+
+ struct mapped_file_builder_data
+ {
+ mapped_file_builder_data() { reset(); }
+ void reset() { new_file.reset(); }
+
+ boost::intrusive_ptr<mapped_file> new_file;
+ };
+
+ mapped_file_builder::mapped_file_builder() : data(0) {}
+ mapped_file_builder::~mapped_file_builder() { delete data; }
+
+ void mapped_file_builder::start(file_ptr f)
+ {
+ if (!data) {
+ data = new mapped_file_builder_data;
+ }
+
+ assert(!data->new_file);
+ data->new_file = new mapped_file(f);
+ }
+
+ file_ptr mapped_file_builder::release()
+ {
+ file_ptr r = data->new_file;
+ data->reset();
+ return r;
+ }
+
+ void mapped_file_builder::clear()
+ {
+ data->reset();
+ }
+
+ bool mapped_file_builder::empty() const
+ {
+ return data->new_file->source.empty();
+ }
+
+ mapped_file_builder::pos mapped_file_builder::get_pos() const
+ {
+ return data->new_file->source.size();
+ }
+
+ void mapped_file_builder::add(char const* x, iterator pos)
+ {
+ data->new_file->add_empty_mapped_file_section(pos);
+ data->new_file->source.append(x);
+ }
+
+ void mapped_file_builder::add(std::string const& x, iterator pos)
+ {
+ data->new_file->add_empty_mapped_file_section(pos);
+ data->new_file->source.append(x);
+ }
+
+ void mapped_file_builder::add(iterator begin, iterator end)
+ {
+ data->new_file->add_mapped_file_section(begin);
+ data->new_file->source.append(begin, end);
+ }
+
+ void mapped_file_builder::add(mapped_file_builder const& x)
+ {
+ add(x, 0, x.data->new_file->source.size());
+ }
+
+ void mapped_file_builder::add(mapped_file_builder const& x,
+ pos begin, pos end)
+ {
+ assert(data->new_file->original == x.data->new_file->original);
+ assert(begin <= x.data->new_file->source.size());
+ assert(end <= x.data->new_file->source.size());
+
+ if (begin != end)
+ {
+ std::vector<mapped_file_section>::iterator start =
+ boost::upper_bound(x.data->new_file->mapped_sections,
+ begin, mapped_section_pos_cmp());
+ assert(start != x.data->new_file->mapped_sections.begin());
+ --start;
+
+ std::string::size_type size = data->new_file->source.size();
+
+ data->new_file->mapped_sections.push_back(mapped_file_section(
+ start->to_original_pos(begin), size,
+ start->section_type));
+
+ for (++start; start != x.data->new_file->mapped_sections.end() &&
+ start->our_pos < end; ++start)
+ {
+ data->new_file->mapped_sections.push_back(mapped_file_section(
+ start->original_pos, start->our_pos - begin + size,
+ start->section_type));
+ }
+
+ data->new_file->source.append(
+ x.data->new_file->source.begin() + begin,
+ x.data->new_file->source.begin() + end);
+ }
+ }
+
+ void mapped_file_builder::unindent_and_add(iterator begin, iterator end)
+ {
+ std::string program(begin, end);
+
+ // Erase leading blank lines and newlines:
+ std::string::size_type start = program.find_first_not_of(" \t");
+ if (start != std::string::npos &&
+ (program[start] == '\r' || program[start] == '\n'))
+ {
+ program.erase(0, start);
+ }
+ start = program.find_first_not_of("\r\n");
+ program.erase(0, start);
+
+ if (program.size() == 0)
+ return; // nothing left to do
+
+ // Get the first line indent
+ std::string::size_type indent = program.find_first_not_of(" \t");
+ std::string::size_type pos = 0;
+ if (std::string::npos == indent)
+ {
+ // Nothing left to do here. The code is empty (just spaces).
+ // We clear the program to signal the caller that it is empty
+ // and return early.
+ program.clear();
+ return;
+ }
+
+ // Calculate the minimum indent from the rest of the lines
+ do
+ {
+ pos = program.find_first_not_of("\r\n", pos);
+ if (std::string::npos == pos)
+ break;
+
+ std::string::size_type n = program.find_first_not_of(" \t", pos);
+ if (n != std::string::npos)
+ {
+ char ch = program[n];
+ if (ch != '\r' && ch != '\n') // ignore empty lines
+ indent = (std::min)(indent, n-pos);
+ }
+ }
+ while (std::string::npos != (pos = program.find_first_of("\r\n", pos)));
+
+ // Trim white spaces from column 0..indent
+ pos = 0;
+ program.erase(0, indent);
+ while (std::string::npos != (pos = program.find_first_of("\r\n", pos)))
+ {
+ if (std::string::npos == (pos = program.find_first_not_of("\r\n", pos)))
+ {
+ break;
+ }
+
+ std::string::size_type next = program.find_first_of("\r\n", pos);
+ program.erase(pos, (std::min)(indent, next-pos));
+ }
+
+ data->new_file->add_indented_mapped_file_section(begin + indent);
+ data->new_file->source.append(program);
+ }
+
+ file_position mapped_file::position_of(std::string::const_iterator pos) const
+ {
+ std::vector<mapped_file_section>::const_iterator section =
+ boost::upper_bound(mapped_sections,
+ std::string::size_type(pos - source.begin()),
+ mapped_section_pos_cmp());
+ assert(section != mapped_sections.begin());
+ --section;
+
+ return section->calculate_position(
+ original->position_of(
+ original->source.begin() + section->original_pos),
+ relative_position(source.begin() + section->our_pos, pos)
+ );
+ }
+}
diff --git a/tools/quickbook/src/files.hpp b/tools/quickbook/src/files.hpp
new file mode 100644
index 0000000000..1b0ef282b0
--- /dev/null
+++ b/tools/quickbook/src/files.hpp
@@ -0,0 +1,112 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_QUICKBOOK_FILES_HPP)
+#define BOOST_QUICKBOOK_FILES_HPP
+
+#include <string>
+#include <boost/filesystem/v3/path.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <stdexcept>
+#include <cassert>
+#include "intrusive_base.hpp"
+
+namespace quickbook {
+
+ namespace fs = boost::filesystem;
+
+ struct file;
+ typedef boost::intrusive_ptr<file> file_ptr;
+
+ struct file_position
+ {
+ file_position() : line(1), column(1) {}
+ file_position(int l, int c) : line(l), column(c) {}
+
+ int line;
+ int column;
+ };
+
+ struct file : intrusive_base<file>
+ {
+ fs::path const path;
+ std::string source;
+ private:
+ unsigned qbk_version;
+ public:
+
+ file(fs::path const& path, std::string const& source,
+ unsigned qbk_version) :
+ path(path), source(source), qbk_version(qbk_version)
+ {}
+
+ virtual ~file() {}
+
+ unsigned version() const {
+ assert(qbk_version);
+ return qbk_version;
+ }
+
+ void version(unsigned v) {
+ // Check that either version hasn't been set, or it was
+ // previously set to the same version (because the same
+ // file has been loaded twice).
+ assert(!qbk_version || qbk_version == v);
+ qbk_version = v;
+ }
+
+ virtual file_position position_of(std::string::const_iterator) const;
+ };
+
+ // If version isn't supplied then it must be set later.
+ file_ptr load(fs::path const& filename,
+ unsigned qbk_version = 0);
+
+ struct load_error : std::runtime_error
+ {
+ explicit load_error(std::string const& arg)
+ : std::runtime_error(arg) {}
+ };
+
+ // Interface for creating fake files which are mapped to
+ // real files, so that the position can be found later.
+
+ struct mapped_file_builder_data;
+
+ struct mapped_file_builder
+ {
+ typedef std::string::const_iterator iterator;
+ typedef std::string::size_type pos;
+
+ mapped_file_builder();
+ ~mapped_file_builder();
+
+ void start(file_ptr);
+ file_ptr release();
+ void clear();
+
+ bool empty() const;
+ pos get_pos() const;
+
+ void add(char const*, iterator);
+ void add(std::string const&, iterator);
+ void add(iterator, iterator);
+ void add(mapped_file_builder const&);
+ void add(mapped_file_builder const&, pos, pos);
+ void unindent_and_add(iterator, iterator);
+ private:
+ mapped_file_builder_data* data;
+
+ mapped_file_builder(mapped_file_builder const&);
+ mapped_file_builder& operator=(mapped_file_builder const&);
+ };
+}
+
+#endif // BOOST_QUICKBOOK_FILES_HPP
diff --git a/tools/quickbook/src/fwd.hpp b/tools/quickbook/src/fwd.hpp
new file mode 100644
index 0000000000..7995c14097
--- /dev/null
+++ b/tools/quickbook/src/fwd.hpp
@@ -0,0 +1,33 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ Copyright (c) 2010 Daniel James
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_FWD_HPP)
+#define BOOST_SPIRIT_FWD_HPP
+
+#include "iterator.hpp"
+#include <boost/intrusive_ptr.hpp>
+
+namespace quickbook
+{
+ struct actions;
+ struct quickbook_grammar;
+ struct collector;
+ struct id_manager;
+ struct section_info;
+ struct file;
+ typedef boost::intrusive_ptr<file> file_ptr;
+
+ typedef std::string::const_iterator string_iterator;
+ typedef lookback_iterator<string_iterator> parse_iterator;
+
+ inline void ignore_variable(void const*) {}
+}
+
+#endif
diff --git a/tools/quickbook/src/grammar.cpp b/tools/quickbook/src/grammar.cpp
new file mode 100644
index 0000000000..a0e2e57887
--- /dev/null
+++ b/tools/quickbook/src/grammar.cpp
@@ -0,0 +1,39 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ Copyright (c) 2010 Daniel James
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "grammar_impl.hpp"
+
+namespace quickbook
+{
+ quickbook_grammar::quickbook_grammar(quickbook::actions& a)
+ : impl_(new impl(a))
+ , command_line_macro(impl_->command_line, "command_line_macro")
+ , inline_phrase(impl_->inline_phrase, "inline_phrase")
+ , phrase(impl_->phrase_start, "phrase")
+ , block(impl_->block_start, "block")
+ , doc_info(impl_->doc_info_details, "doc_info")
+ {
+ }
+
+ quickbook_grammar::~quickbook_grammar()
+ {
+ }
+
+ quickbook_grammar::impl::impl(quickbook::actions& a)
+ : actions(a)
+ , cleanup_()
+ {
+ init_main();
+ init_block_elements();
+ init_phrase_elements();
+ init_doc_info();
+ }
+}
diff --git a/tools/quickbook/src/grammar.hpp b/tools/quickbook/src/grammar.hpp
new file mode 100644
index 0000000000..73aae4a26c
--- /dev/null
+++ b/tools/quickbook/src/grammar.hpp
@@ -0,0 +1,70 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_QUICKBOOK_GRAMMARS_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_GRAMMARS_HPP
+
+#include <boost/spirit/include/classic_core.hpp>
+#include "fwd.hpp"
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+
+ // The spirit scanner for explicitly instantiating grammars. This is a
+ // spirit implementation detail, but since classic is no longer under
+ // development, it won't change. And spirit 2 won't require such a hack.
+
+ typedef cl::scanner<parse_iterator, cl::scanner_policies <
+ cl::iteration_policy, cl::match_policy, cl::action_policy> > scanner;
+
+ template <typename Scanner>
+ struct Scanner_must_be_the_quickbook_scanner_typedef;
+ template <>
+ struct Scanner_must_be_the_quickbook_scanner_typedef<scanner> {};
+
+ struct grammar
+ : public cl::grammar<grammar>
+ {
+ grammar(cl::rule<scanner> const& start_rule, char const* /* name */)
+ : start_rule(start_rule) {}
+
+ template <typename Scanner>
+ struct definition :
+ Scanner_must_be_the_quickbook_scanner_typedef<Scanner>
+ {
+ definition(grammar const& self) : start_rule(self.start_rule) {}
+ cl::rule<scanner> const& start() const { return start_rule; }
+ cl::rule<scanner> const& start_rule;
+ };
+
+ cl::rule<scanner> const& start_rule;
+ };
+
+ struct quickbook_grammar
+ {
+ public:
+ struct impl;
+
+ private:
+ boost::scoped_ptr<impl> impl_;
+
+ public:
+ grammar command_line_macro;
+ grammar inline_phrase;
+ grammar phrase;
+ grammar block;
+ grammar doc_info;
+
+ quickbook_grammar(quickbook::actions&);
+ ~quickbook_grammar();
+ };
+}
+
+#endif
diff --git a/tools/quickbook/src/grammar_impl.hpp b/tools/quickbook/src/grammar_impl.hpp
new file mode 100644
index 0000000000..c968111b8c
--- /dev/null
+++ b/tools/quickbook/src/grammar_impl.hpp
@@ -0,0 +1,106 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ Copyright (c) 2010 Daniel James
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_QUICKBOOK_GRAMMARS_IMPL_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_GRAMMARS_IMPL_HPP
+
+#include "grammar.hpp"
+#include "cleanup.hpp"
+#include "values.hpp"
+#include <boost/spirit/include/classic_symbols.hpp>
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+
+ struct element_info
+ {
+ enum type_enum {
+ nothing = 0,
+ block = 1,
+ conditional_or_block = 2,
+ nested_block = 4,
+ phrase = 8,
+ maybe_block = 16
+ };
+
+ enum context {
+ in_phrase = phrase | maybe_block,
+ in_nested_block = phrase | maybe_block | nested_block,
+ in_conditional = phrase | maybe_block | nested_block | conditional_or_block,
+ in_block = phrase | maybe_block | nested_block | conditional_or_block | block,
+ only_nested_block = nested_block,
+ only_block = nested_block | conditional_or_block | block,
+ only_contextual_block = maybe_block | nested_block | conditional_or_block | block
+ };
+
+ element_info()
+ : type(nothing), rule(), tag(0) {}
+
+ element_info(
+ type_enum t,
+ cl::rule<scanner>* r,
+ value::tag_type tag = value::default_tag,
+ unsigned int v = 0)
+ : type(t), rule(r), tag(tag), qbk_version(v) {}
+
+ type_enum type;
+ cl::rule<scanner>* rule;
+ value::tag_type tag;
+ unsigned int qbk_version;
+ };
+
+ struct quickbook_grammar::impl
+ {
+ quickbook::actions& actions;
+ cleanup cleanup_;
+
+ // Main Grammar
+ cl::rule<scanner> block_start;
+ cl::rule<scanner> phrase_start;
+ cl::rule<scanner> nested_phrase;
+ cl::rule<scanner> inline_phrase;
+ cl::rule<scanner> paragraph_phrase;
+ cl::rule<scanner> extended_phrase;
+ cl::rule<scanner> table_title_phrase;
+ cl::rule<scanner> inside_preformatted;
+ cl::rule<scanner> inside_paragraph;
+ cl::rule<scanner> command_line;
+ cl::rule<scanner> escape;
+ cl::rule<scanner> raw_escape;
+
+ // Miscellaneous stuff
+ cl::rule<scanner> hard_space;
+ cl::rule<scanner> space;
+ cl::rule<scanner> blank;
+ cl::rule<scanner> eol;
+ cl::rule<scanner> phrase_end;
+ cl::rule<scanner> comment;
+ cl::rule<scanner> line_comment;
+ cl::rule<scanner> macro_identifier;
+
+ // Element Symbols
+ cl::symbols<element_info> elements;
+
+ // Doc Info
+ cl::rule<scanner> doc_info_details;
+
+ impl(quickbook::actions&);
+
+ private:
+
+ void init_main();
+ void init_block_elements();
+ void init_phrase_elements();
+ void init_doc_info();
+ };
+}
+
+#endif // BOOST_SPIRIT_QUICKBOOK_GRAMMARS_HPP
diff --git a/tools/quickbook/src/id_manager.cpp b/tools/quickbook/src/id_manager.cpp
new file mode 100644
index 0000000000..32e537df71
--- /dev/null
+++ b/tools/quickbook/src/id_manager.cpp
@@ -0,0 +1,1141 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "id_manager.hpp"
+#include "utils.hpp"
+#include "string_ref.hpp"
+#include "intrusive_base.hpp"
+#include <boost/intrusive_ptr.hpp>
+#include <boost/unordered_map.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/range/algorithm.hpp>
+#include <boost/foreach.hpp>
+#include <deque>
+#include <vector>
+#include <cctype>
+
+namespace quickbook
+{
+ // TODO: This should possibly try to make ids are generated:
+ // http://www.w3.org/TR/REC-xml/#NT-NameStartChar
+
+ //
+ // Forward declarations
+ //
+
+ struct id_placeholder;
+ struct id_data;
+ std::string replace_ids(id_state& state, std::string const& xml,
+ bool use_resolved_ids = true);
+ std::string process_ids(id_state&, std::string const&);
+
+ static const std::size_t max_size = 32;
+
+ //
+ // id_placeholder
+ //
+
+ struct id_placeholder
+ {
+ enum state_enum { child, unresolved, resolved, generated };
+
+ unsigned index; // The poisition in the placeholder deque.
+ state_enum generation_state;
+ // Placeholder's position in generation
+ // process.
+ std::string unresolved_id;
+ // The id that would be generated without any
+ // duplicate handling.
+ std::string id; // The id so far.
+ id_placeholder* parent; // Placeholder of the parent id.
+ // Only when generation_state == child
+ id_category category;
+ unsigned num_dots; // Number of dots in the id.
+ // Normally equal to the section level.
+ unsigned order; // Order of the placeholders in the generated
+ // xml. Stored because it can be slightly
+ // different to the order they're generated
+ // in. e.g. for nested tables the cells
+ // are processed before the title id.
+ // Only set when processing ids.
+ id_data* data; // Assigned data shared by duplicate ids
+ // used to detect them. Only when
+ // generation_state == resolved
+
+ id_placeholder(
+ unsigned index,
+ std::string const& id,
+ id_category category,
+ id_placeholder* parent_ = 0)
+ : index(index),
+ generation_state(parent_ ? child : unresolved),
+ unresolved_id(parent_ ? parent_->unresolved_id + '.' + id : id),
+ id(id),
+ parent(parent_),
+ category(category),
+ num_dots(boost::range::count(id, '.') +
+ (parent_ ? parent_->num_dots + 1 : 0)),
+ order(0),
+ data(0)
+ {
+ }
+
+ std::string to_string()
+ {
+ return '$' + boost::lexical_cast<std::string>(index);
+ }
+
+ bool check_state() const
+ {
+ return (
+ (generation_state == child) == (bool) parent &&
+ (generation_state == resolved) == (bool) data);
+ }
+
+ bool check_state(state_enum s) const
+ {
+ return s == generation_state && check_state();
+ }
+ };
+
+ //
+ // id_state
+ //
+
+ struct file_info;
+ struct doc_info;
+ struct section_info;
+
+ struct id_state
+ {
+ boost::intrusive_ptr<file_info> current_file;
+ std::deque<id_placeholder> placeholders;
+
+ // Placeholder methods
+
+ id_placeholder* add_placeholder(
+ std::string const&, id_category, id_placeholder* parent = 0);
+
+ id_placeholder* get_placeholder(string_ref);
+
+ // Events
+
+ id_placeholder* start_file(
+ unsigned compatibility_version,
+ bool document_root,
+ std::string const& include_doc_id,
+ std::string const& id,
+ value const& title);
+
+ void end_file();
+
+ id_placeholder* add_id(
+ std::string const& id,
+ id_category category);
+ id_placeholder* old_style_id(
+ std::string const& id,
+ id_category category);
+ id_placeholder* begin_section(
+ std::string const& id,
+ id_category category);
+ void end_section();
+
+private:
+ id_placeholder* add_id_to_section(
+ std::string const& id,
+ id_category category,
+ boost::intrusive_ptr<section_info> const& section);
+ id_placeholder* create_new_section(
+ std::string const& id,
+ id_category category);
+
+ void switch_section(id_placeholder*);
+ void reswitch_sections(boost::intrusive_ptr<section_info> const&,
+ boost::intrusive_ptr<section_info> const&);
+ void restore_section();
+ };
+
+ struct file_info : intrusive_base<file_info>
+ {
+ boost::intrusive_ptr<file_info> parent;
+ boost::intrusive_ptr<doc_info> document;
+
+ bool document_root; // !parent || document != parent->document
+ unsigned compatibility_version;
+ boost::intrusive_ptr<section_info> switched_section;
+ id_placeholder* original_placeholder;
+
+ // The 1.1-1.5 document id would actually change per file due to
+ // explicit ids in includes and a bug which would sometimes use the
+ // document title instead of the id.
+ std::string doc_id_1_1;
+
+ file_info(boost::intrusive_ptr<file_info> const& parent,
+ unsigned compatibility_version) :
+ parent(parent), document(parent->document), document_root(false),
+ compatibility_version(compatibility_version),
+ switched_section(), original_placeholder()
+ {}
+
+ file_info(boost::intrusive_ptr<file_info> const& parent,
+ boost::intrusive_ptr<doc_info> const& document,
+ unsigned compatibility_version) :
+ parent(parent), document(document), document_root(true),
+ compatibility_version(compatibility_version),
+ switched_section(), original_placeholder()
+ {}
+ };
+
+ struct doc_info : intrusive_base<doc_info>
+ {
+ boost::intrusive_ptr<section_info> current_section;
+ std::string last_title_1_1;
+ std::string section_id_1_1;
+
+ doc_info() :
+ current_section(), last_title_1_1(), section_id_1_1()
+ {}
+ };
+
+ struct section_info : intrusive_base<section_info>
+ {
+ boost::intrusive_ptr<section_info> parent;
+ unsigned compatibility_version;
+ unsigned level;
+ std::string id_1_1;
+ id_placeholder* placeholder_1_6;
+
+ section_info(boost::intrusive_ptr<section_info> const& parent,
+ unsigned compatibility_version, std::string const& id) :
+ parent(parent), compatibility_version(compatibility_version),
+ level(parent ? parent->level + 1 : 1),
+ id_1_1(), placeholder_1_6(0)
+ {
+ if (parent && compatibility_version < 106u) {
+ id_1_1 = parent->id_1_1;
+ if (!id_1_1.empty() && !id.empty())
+ id_1_1 += ".";
+ id_1_1 += id;
+ }
+ }
+ };
+
+ //
+ // id_manager
+ //
+
+ id_manager::id_manager()
+ : state(new id_state)
+ {
+ }
+
+ id_manager::~id_manager() {}
+
+ void id_manager::start_file(
+ unsigned compatibility_version,
+ std::string const& include_doc_id,
+ std::string const& id,
+ value const& title)
+ {
+ state->start_file(compatibility_version, false, include_doc_id, id, title);
+ }
+
+ std::string id_manager::start_file_with_docinfo(
+ unsigned compatibility_version,
+ std::string const& include_doc_id,
+ std::string const& id,
+ value const& title)
+ {
+ return state->start_file(compatibility_version, true, include_doc_id,
+ id, title)->to_string();
+ }
+
+ void id_manager::end_file()
+ {
+ state->end_file();
+ }
+
+ std::string id_manager::begin_section(std::string const& id,
+ id_category category)
+ {
+ return state->begin_section(id, category)->to_string();
+ }
+
+ void id_manager::end_section()
+ {
+ return state->end_section();
+ }
+
+ int id_manager::section_level() const
+ {
+ return state->current_file->document->current_section->level;
+ }
+
+ std::string id_manager::old_style_id(std::string const& id, id_category category)
+ {
+ return state->old_style_id(id, category)->to_string();
+ }
+
+ std::string id_manager::add_id(std::string const& id, id_category category)
+ {
+ return state->add_id(id, category)->to_string();
+ }
+
+ std::string id_manager::add_anchor(std::string const& id, id_category category)
+ {
+ return state->add_placeholder(id, category)->to_string();
+ }
+
+ std::string id_manager::replace_placeholders_with_unresolved_ids(
+ std::string const& xml) const
+ {
+ return replace_ids(*state, xml, false);
+ }
+
+ std::string id_manager::replace_placeholders(std::string const& xml) const
+ {
+ assert(!state->current_file);
+ return process_ids(*state, xml);
+ }
+
+ unsigned id_manager::compatibility_version() const
+ {
+ return state->current_file->compatibility_version;
+ }
+
+ //
+ // normalize_id
+ //
+ // Normalizes generated ids.
+ //
+
+ namespace
+ {
+ std::string normalize_id(
+ std::string src_id,
+ std::size_t prefix = 0,
+ std::size_t size = max_size)
+ {
+ std::string id;
+ id.swap(src_id);
+
+ std::size_t src = prefix;
+ std::size_t dst = prefix;
+ size += prefix;
+
+ if (src >= id.length()) {
+ return id;
+ }
+
+ while (src < id.length() && id[src] == '_') {
+ ++src;
+ }
+
+ if (src >= id.length()) {
+ id += '_';
+ return id;
+ }
+
+ while (src < id.length() && dst < size) {
+ if (id[src] == '_') {
+ do {
+ ++src;
+ } while(src < id.length() && id[src] == '_');
+
+ if (src < id.length()) id[dst++] = '_';
+ }
+ else {
+ id[dst++] = id[src++];
+ }
+ }
+
+ id.erase(dst);
+
+ return id;
+ }
+ }
+
+ //
+ // id_state
+ //
+
+ id_placeholder* id_state::add_placeholder(
+ std::string const& id, id_category category,
+ id_placeholder* parent)
+ {
+ placeholders.push_back(id_placeholder(
+ placeholders.size(), id, category, parent));
+ return &placeholders.back();
+ }
+
+ id_placeholder* id_state::get_placeholder(string_ref value)
+ {
+ // If this isn't a placeholder id.
+ if (value.size() <= 1 || *value.begin() != '$')
+ return 0;
+
+ unsigned index = boost::lexical_cast<int>(std::string(
+ value.begin() + 1, value.end()));
+
+ return &placeholders.at(index);
+ }
+
+ void id_state::switch_section(id_placeholder* p)
+ {
+ assert(!current_file->original_placeholder);
+ current_file->switched_section = current_file->document->current_section;
+ current_file->original_placeholder = current_file->switched_section->placeholder_1_6;
+ current_file->switched_section->placeholder_1_6 = p;
+ }
+
+ void id_state::reswitch_sections(
+ boost::intrusive_ptr<section_info> const& popped_section,
+ boost::intrusive_ptr<section_info> const& parent_section)
+ {
+ boost::intrusive_ptr<file_info> file = current_file;
+ boost::intrusive_ptr<file_info> first_switched_file;
+
+ for (;;) {
+ if (file->switched_section == popped_section)
+ {
+ first_switched_file = file;
+ file->switched_section = parent_section;
+ }
+
+ if (file->document_root) break;
+ file = file->parent;
+ }
+
+ if (first_switched_file) {
+ first_switched_file->original_placeholder =
+ parent_section->placeholder_1_6;
+ parent_section->placeholder_1_6 =
+ popped_section->placeholder_1_6;
+ }
+ }
+
+ void id_state::restore_section()
+ {
+ if (current_file->original_placeholder) {
+ current_file->switched_section->placeholder_1_6 =
+ current_file->original_placeholder;
+ }
+ }
+
+ id_placeholder* id_state::start_file(
+ unsigned compatibility_version,
+ bool document_root,
+ std::string const& include_doc_id,
+ std::string const& id,
+ value const& title)
+ {
+ // Create new file
+
+ boost::intrusive_ptr<file_info> parent = current_file;
+
+ if (document_root) {
+ current_file = new file_info(parent, new doc_info(),
+ compatibility_version);
+ }
+ else {
+ current_file =
+ new file_info(parent, compatibility_version);
+ }
+
+ // Choose specified id to use. Prefer 'include_doc_id' (the id
+ // specified in an 'include' element) unless backwards compatibility
+ // is required.
+
+ std::string initial_doc_id;
+
+ if (document_root ||
+ compatibility_version >= 106u ||
+ (parent && parent->compatibility_version >= 106u)) {
+ initial_doc_id = !include_doc_id.empty() ? include_doc_id : id;
+ }
+ else {
+ initial_doc_id = !id.empty() ? id : include_doc_id;
+ }
+
+ // Set variables used for backwards compatible id generation.
+ // They're a bit odd because of old bugs.
+
+ if (document_root || compatibility_version < 106u) {
+ // Note: this is done for older versions even if docinfo is
+ // otherwise ignored.
+
+ if (title.check())
+ current_file->document->last_title_1_1 =
+ title.get_quickbook();
+
+ current_file->doc_id_1_1 = !initial_doc_id.empty() ? initial_doc_id :
+ detail::make_identifier(current_file->document->last_title_1_1);
+ }
+ else if (parent) {
+ current_file->doc_id_1_1 = parent->doc_id_1_1;
+ }
+
+ if (document_root) {
+ if (!initial_doc_id.empty()) {
+ return create_new_section(id, id_category::explicit_section_id);
+ }
+ else if (!title.empty()) {
+ return create_new_section(
+ detail::make_identifier(title.get_quickbook()),
+ id_category::generated_doc);
+ }
+ else if (compatibility_version >= 106u) {
+ return create_new_section("doc", id_category::numbered);
+ }
+ else {
+ return create_new_section("", id_category::generated_doc);
+ }
+ }
+ else {
+ // If an id was set for the file, then switch the current section
+ // with a new section with this id. This will be maintained in
+ // 'end_section' if the current section ends, and then the original
+ // section restored in 'end_file'
+
+ if (compatibility_version >= 106u && !initial_doc_id.empty()) {
+ switch_section(add_id_to_section(initial_doc_id,
+ id_category::explicit_section_id,
+ boost::intrusive_ptr<section_info>()));
+ }
+
+ return 0;
+ }
+ }
+
+ void id_state::end_file()
+ {
+ restore_section();
+ current_file = current_file->parent;
+ }
+
+ id_placeholder* id_state::add_id(
+ std::string const& id,
+ id_category category)
+ {
+ return add_id_to_section(id, category,
+ current_file->document->current_section);
+ }
+
+ id_placeholder* id_state::add_id_to_section(
+ std::string const& id,
+ id_category category,
+ boost::intrusive_ptr<section_info> const& section)
+ {
+ std::string id_part = id;
+
+ // Note: Normalizing id according to file compatibility version, but
+ // adding to section according to section compatibility version.
+
+ if (current_file->compatibility_version >= 106u &&
+ category.c < id_category::explicit_id) {
+ id_part = normalize_id(id);
+ }
+
+ if(!section || section->compatibility_version >= 106u) {
+ return add_placeholder(id_part, category,
+ section ? section->placeholder_1_6 : 0);
+ }
+ else {
+ std::string const& qualified_id = section->id_1_1;
+
+ std::string new_id;
+ if (!section->placeholder_1_6)
+ new_id = current_file->doc_id_1_1;
+ if (!new_id.empty() && !qualified_id.empty()) new_id += '.';
+ new_id += qualified_id;
+ if (!new_id.empty() && !id_part.empty()) new_id += '.';
+ new_id += id_part;
+
+ return add_placeholder(new_id, category,
+ section->placeholder_1_6);
+ }
+ }
+
+ id_placeholder* id_state::old_style_id(
+ std::string const& id,
+ id_category category)
+ {
+ return current_file->compatibility_version < 103u ?
+ add_placeholder(
+ current_file->document->section_id_1_1 + "." + id, category) :
+ add_id(id, category);
+ }
+
+ id_placeholder* id_state::begin_section(
+ std::string const& id,
+ id_category category)
+ {
+ current_file->document->section_id_1_1 = id;
+ return create_new_section(id, category);
+ }
+
+ id_placeholder* id_state::create_new_section(
+ std::string const& id,
+ id_category category)
+ {
+ boost::intrusive_ptr<section_info> parent =
+ current_file->document->current_section;
+
+ boost::intrusive_ptr<section_info> new_section =
+ new section_info(parent, current_file->compatibility_version, id);
+
+ id_placeholder* p;
+
+ if (new_section->compatibility_version >= 106u) {
+ p = add_id_to_section(id, category, parent);
+ new_section->placeholder_1_6 = p;
+ }
+ else if (new_section->compatibility_version >= 103u) {
+ if (parent)
+ new_section->placeholder_1_6 = parent->placeholder_1_6;
+
+ std::string new_id;
+ if (!new_section->placeholder_1_6) {
+ new_id = current_file->doc_id_1_1;
+ if (!new_section->id_1_1.empty()) new_id += '.';
+ }
+ new_id += new_section->id_1_1;
+
+ p = add_placeholder(new_id, category,
+ new_section->placeholder_1_6);
+ }
+ else {
+ if (parent)
+ new_section->placeholder_1_6 = parent->placeholder_1_6;
+
+ std::string new_id;
+ if (parent && !new_section->placeholder_1_6)
+ new_id = current_file->doc_id_1_1 + '.';
+
+ new_id += id;
+
+ p = add_placeholder(new_id, category,
+ new_section->placeholder_1_6);
+ }
+
+ current_file->document->current_section = new_section;
+
+ return p;
+ }
+
+ void id_state::end_section()
+ {
+ boost::intrusive_ptr<section_info> popped_section =
+ current_file->document->current_section;
+ current_file->document->current_section = popped_section->parent;
+
+ reswitch_sections(popped_section, popped_section->parent);
+ }
+
+ //
+ // Xml subset parser used for finding id values.
+ //
+ // I originally tried to integrate this into the post processor
+ // but that proved tricky. Alternatively it could use a proper
+ // xml parser, but I want this to be able to survive badly
+ // marked up escapes.
+ //
+
+ struct xml_processor
+ {
+ xml_processor();
+
+ std::vector<std::string> id_attributes;
+
+ struct callback {
+ virtual void start(string_ref) {}
+ virtual void id_value(string_ref) {}
+ virtual void finish(string_ref) {}
+ virtual ~callback() {}
+ };
+
+ void parse(std::string const&, callback&);
+ };
+
+ namespace
+ {
+ char const* id_attributes_[] =
+ {
+ "id",
+ "linkend",
+ "linkends",
+ "arearefs"
+ };
+ }
+
+ xml_processor::xml_processor()
+ {
+ static int const n_id_attributes = sizeof(id_attributes_)/sizeof(char const*);
+ for (int i = 0; i != n_id_attributes; ++i)
+ {
+ id_attributes.push_back(id_attributes_[i]);
+ }
+
+ boost::sort(id_attributes);
+ }
+
+ template <typename Iterator>
+ bool read(Iterator& it, Iterator end, char const* text)
+ {
+ for(Iterator it2 = it;; ++it2, ++text) {
+ if (!*text) {
+ it = it2;
+ return true;
+ }
+
+ if (it2 == end || *it2 != *text)
+ return false;
+ }
+ }
+
+ template <typename Iterator>
+ void read_past(Iterator& it, Iterator end, char const* text)
+ {
+ while (it != end && !read(it, end, text)) ++it;
+ }
+
+ bool find_char(char const* text, char c)
+ {
+ for(;*text; ++text)
+ if (c == *text) return true;
+ return false;
+ }
+
+ template <typename Iterator>
+ void read_some_of(Iterator& it, Iterator end, char const* text)
+ {
+ while(it != end && find_char(text, *it)) ++it;
+ }
+
+ template <typename Iterator>
+ void read_to_one_of(Iterator& it, Iterator end, char const* text)
+ {
+ while(it != end && !find_char(text, *it)) ++it;
+ }
+
+ void xml_processor::parse(std::string const& source, callback& c)
+ {
+ typedef std::string::const_iterator iterator;
+
+ string_ref source_ref(source.begin(), source.end());
+ c.start(source_ref);
+
+ iterator it = source_ref.begin(), end = source_ref.end();
+
+ for(;;)
+ {
+ read_past(it, end, "<");
+ if (it == end) break;
+
+ if (read(it, end, "!--quickbook-escape-prefix-->"))
+ {
+ read_past(it, end, "<!--quickbook-escape-postfix-->");
+ continue;
+ }
+
+ switch(*it)
+ {
+ case '?':
+ ++it;
+ read_past(it, end, "?>");
+ break;
+
+ case '!':
+ if (read(it, end, "!--"))
+ read_past(it, end, "-->");
+ else
+ read_past(it, end, ">");
+ break;
+
+ default:
+ if ((*it >= 'a' && *it <= 'z') ||
+ (*it >= 'A' && *it <= 'Z') ||
+ *it == '_' || *it == ':')
+ {
+ read_to_one_of(it, end, " \t\n\r>");
+
+ for (;;) {
+ read_some_of(it, end, " \t\n\r");
+ iterator name_start = it;
+ read_to_one_of(it, end, "= \t\n\r>");
+ if (it == end || *it == '>') break;
+ string_ref name(name_start, it);
+ ++it;
+
+ read_some_of(it, end, "= \t\n\r");
+ if (it == end || (*it != '"' && *it != '\'')) break;
+
+ char delim = *it;
+ ++it;
+
+ iterator value_start = it;
+
+ it = std::find(it, end, delim);
+ if (it == end) break;
+ string_ref value(value_start, it);
+ ++it;
+
+ if (boost::find(id_attributes, name)
+ != id_attributes.end())
+ {
+ c.id_value(value);
+ }
+ }
+ }
+ else
+ {
+ read_past(it, end, ">");
+ }
+ }
+ }
+
+ c.finish(source_ref);
+ }
+
+ //
+ // process_ids
+ //
+
+ //
+ // Data used for generating placeholders that have duplicates.
+ //
+
+ struct id_generation_data : intrusive_base<id_generation_data>
+ {
+ id_generation_data(std::string const& src_id)
+ : child_start(src_id.rfind('.') + 1),
+ id(normalize_id(src_id, child_start, max_size - 1)),
+ // 'max_size - 1' leaves a character to append
+ // a number.
+ count(0)
+ {
+ if (std::isdigit(id[id.length() - 1]))
+ {
+ if (child_length() < max_size - 1)
+ id += '_';
+ else
+ reduce_id();
+ }
+ }
+
+ void reduce_id()
+ {
+ assert(id.length() > child_start);
+ std::size_t length = id.length() - 1;
+ while(length > child_start && std::isdigit(id[length - 1])) --length;
+ id.erase(length);
+ count = 0;
+ }
+
+ std::size_t child_length() const
+ {
+ return id.length() - child_start;
+ }
+
+ std::size_t child_start;
+ std::string id;
+ int count;
+ };
+
+ // Created for all desired ids, either when resolving an id or due to
+ // generating a new id to avoid duplicates.
+ struct id_data
+ {
+ id_data()
+ : category(id_category::numbered),
+ used(false),
+ generation_data()
+ {}
+
+ void update_category(id_category c)
+ {
+ if (c.c > category.c) category = c;
+ }
+
+ id_category category; // The highest priority category of the
+ // placeholders that want to use this id.
+ bool used; // Whether this id has been used.
+ boost::intrusive_ptr<id_generation_data> generation_data;
+ // If a duplicates are found, this is
+ // created to generate new ids.
+ //
+ // Many to one relationship, because truncation
+ // can lead to different ids contending for the
+ // same id prefix.
+ };
+
+ typedef boost::unordered_map<std::string, id_data> allocated_ids;
+ typedef std::vector<id_placeholder*> placeholder_index;
+
+ placeholder_index index_placeholders(id_state&, std::string const& xml);
+ void resolve_id(id_placeholder&, allocated_ids&);
+ void generate_id(id_placeholder&, allocated_ids&);
+
+ std::string process_ids(id_state& state, std::string const& xml)
+ {
+ placeholder_index placeholders = index_placeholders(state, xml);
+
+ typedef std::vector<id_placeholder*>::iterator iterator;
+
+ iterator it = placeholders.begin(),
+ end = placeholders.end();
+
+ // Placeholder ids are processed in blocks of ids with
+ // an equal number of dots.
+ while (it != end) {
+ unsigned num_dots = (*it)->num_dots;
+
+ // ids can't clash with ids at a different num_dots, so
+ // this only needs to track the id generation data
+ // for a single num_dots at a time.
+ allocated_ids ids;
+
+ iterator it2 = it;
+ do {
+ resolve_id(**it2++, ids);
+ } while(it2 != end && (*it2)->num_dots == num_dots);
+
+ do {
+ generate_id(**it++, ids);
+ } while(it != it2);
+ }
+
+ return replace_ids(state, xml);
+ }
+
+ //
+ // index_placeholders
+ //
+ // Create a sorted index of the placeholders, in order
+ // to make numbering duplicates easy. A total order.
+ //
+
+ struct placeholder_compare
+ {
+ bool operator()(id_placeholder* x, id_placeholder* y) const
+ {
+ bool x_explicit = x->category.c >= id_category::explicit_id;
+ bool y_explicit = y->category.c >= id_category::explicit_id;
+
+ return
+ x->num_dots < y->num_dots ? true :
+ x->num_dots > y->num_dots ? false :
+ x_explicit > y_explicit ? true :
+ x_explicit < y_explicit ? false :
+ x->order < y->order;
+ }
+ };
+
+ struct number_placeholders_callback : xml_processor::callback
+ {
+ id_state& state;
+ unsigned count;
+
+ number_placeholders_callback(id_state& state)
+ : state(state),
+ count(0)
+ {}
+
+ void id_value(string_ref value)
+ {
+ id_placeholder* p = state.get_placeholder(value);
+ number(p);
+ }
+
+ void number(id_placeholder* p)
+ {
+ if (p && !p->order) {
+ number(p->parent);
+ p->order = ++count;
+ }
+ }
+ };
+
+ placeholder_index index_placeholders(
+ id_state& state,
+ std::string const& xml)
+ {
+ xml_processor processor;
+ number_placeholders_callback callback(state);
+ processor.parse(xml, callback);
+
+ placeholder_index sorted_placeholders;
+ sorted_placeholders.reserve(state.placeholders.size());
+ BOOST_FOREACH(id_placeholder& p, state.placeholders)
+ if (p.order) sorted_placeholders.push_back(&p);
+ boost::sort(sorted_placeholders, placeholder_compare());
+
+ return sorted_placeholders;
+ }
+
+ //
+ // resolve_id
+ //
+ // Convert child ids to full ids, and add to the
+ // allocated ids (although not yet set in stone because
+ // there might be duplicates).
+ //
+ // Note that the parent ids has to be generated before resolving
+ // the child id.
+ //
+
+ void resolve_id(id_placeholder& p, allocated_ids& ids)
+ {
+ if (p.generation_state == id_placeholder::child)
+ {
+ assert(p.check_state());
+
+ assert(p.parent->check_state(id_placeholder::generated));
+
+ p.id = p.parent->id + "." + p.id;
+ p.generation_state = id_placeholder::unresolved;
+ p.parent = 0;
+ }
+
+ assert(p.check_state(id_placeholder::unresolved));
+
+ id_data& data = ids.emplace(p.id, id_data()).first->second;
+ data.update_category(p.category);
+
+ p.data = &data;
+ p.generation_state = id_placeholder::resolved;
+ }
+
+ //
+ // generate_id
+ //
+ // Finally generate the final id.
+ //
+
+ void register_generation_data(id_placeholder&, allocated_ids&);
+
+ void generate_id(id_placeholder& p, allocated_ids& ids)
+ {
+ assert(p.check_state(id_placeholder::resolved));
+
+ // If the placeholder id is available, then update data
+ // and return.
+ if (p.category == p.data->category && !p.data->used &&
+ p.category.c != id_category::numbered)
+ {
+ p.data->used = true;
+ p.generation_state = id_placeholder::generated;
+ p.data = 0;
+ return;
+ }
+
+ if (!p.data->generation_data)
+ {
+ p.data->generation_data.reset(new id_generation_data(p.id));
+ register_generation_data(p, ids);
+ }
+
+ // Loop until an available id is found.
+ for(;;)
+ {
+ id_generation_data& generation_data = *p.data->generation_data;
+
+ std::string postfix =
+ boost::lexical_cast<std::string>(generation_data.count++);
+
+ if (generation_data.child_length() + postfix.length() > max_size) {
+ // The resulting id is too long, so move to a shorter id.
+ generation_data.reduce_id();
+ register_generation_data(p, ids);
+ }
+ else {
+ std::string id = generation_data.id + postfix;
+
+ if (ids.find(id) == ids.end()) {
+ p.id.swap(id);
+ p.generation_state = id_placeholder::generated;
+ p.data = 0;
+ return;
+ }
+ }
+ }
+ }
+
+ // Every time the generation id is changed, this is called to
+ // check if that id is already in use.
+ void register_generation_data(id_placeholder& p, allocated_ids& ids)
+ {
+ std::string const& id = p.data->generation_data->id;
+
+ id_data& new_data = ids.emplace(id, id_data()).first->second;
+
+ // If there is already generation_data for the new id then use that.
+ // Otherwise use the placeholder's existing generation_data.
+ if (new_data.generation_data)
+ p.data->generation_data = new_data.generation_data;
+ else
+ new_data.generation_data = p.data->generation_data;
+ }
+
+ //
+ // replace_ids
+ //
+ // Return a copy of the xml with all the placeholders replaced by
+ // generated_ids.
+ //
+
+ struct replace_ids_callback : xml_processor::callback
+ {
+ id_state& state;
+ bool use_resolved_ids;
+ std::string::const_iterator source_pos;
+ std::string result;
+
+ replace_ids_callback(id_state& state, bool resolved)
+ : state(state),
+ use_resolved_ids(resolved),
+ source_pos(),
+ result()
+ {}
+
+ void start(string_ref xml)
+ {
+ source_pos = xml.begin();
+ }
+
+ void id_value(string_ref value)
+ {
+ if (id_placeholder* p = state.get_placeholder(value))
+ {
+ assert(!use_resolved_ids ||
+ p->check_state(id_placeholder::generated));
+ std::string const& id = use_resolved_ids ?
+ p->id : p->unresolved_id;
+
+ result.append(source_pos, value.begin());
+ result.append(id.begin(), id.end());
+ source_pos = value.end();
+ }
+ }
+
+ void finish(string_ref xml)
+ {
+ result.append(source_pos, xml.end());
+ source_pos = xml.end();
+ }
+ };
+
+ std::string replace_ids(id_state& state, std::string const& xml,
+ bool use_unresolved_ids)
+ {
+ xml_processor processor;
+ replace_ids_callback callback(state, use_unresolved_ids);
+ processor.parse(xml, callback);
+ return callback.result;
+ }
+}
diff --git a/tools/quickbook/src/id_manager.hpp b/tools/quickbook/src/id_manager.hpp
new file mode 100644
index 0000000000..e071241773
--- /dev/null
+++ b/tools/quickbook/src/id_manager.hpp
@@ -0,0 +1,86 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_QUICKBOOK_ID_MANAGER_HPP)
+#define BOOST_QUICKBOOK_ID_MANAGER_HPP
+
+#include <boost/scoped_ptr.hpp>
+#include <string>
+#include "values.hpp"
+
+namespace quickbook
+{
+ // id_category
+ //
+ // Higher categories get priority over lower ones.
+
+ struct id_category
+ {
+ enum categories
+ {
+ default_category = 0,
+ numbered, // Just used to avoid random docbook ids
+ generated, // Generated ids for other elements.
+ generated_heading, // Generated ids for headings.
+ generated_section, // Generated ids for sections.
+ generated_doc, // Generated ids for document.
+ explicit_id, // Explicitly given by user
+ explicit_section_id,
+ explicit_anchor_id
+ };
+
+ id_category() : c(default_category) {}
+ id_category(categories c) : c(c) {}
+ explicit id_category(int c) : c(categories(c)) {}
+
+ bool operator==(id_category rhs) const { return c == rhs.c; }
+
+ categories c;
+ };
+
+ struct id_state;
+ struct section_manager;
+
+ struct id_manager
+ {
+ id_manager();
+ ~id_manager();
+
+ std::string start_file_with_docinfo(
+ unsigned compatibility_version,
+ std::string const& include_doc_id,
+ std::string const& id,
+ value const& title);
+
+ void start_file(
+ unsigned compatibility_version,
+ std::string const& include_doc_id,
+ std::string const& id,
+ value const& title);
+
+ void end_file();
+
+ std::string begin_section(std::string const&, id_category);
+ void end_section();
+ int section_level() const;
+
+ std::string old_style_id(std::string const&, id_category);
+ std::string add_id(std::string const&, id_category);
+ std::string add_anchor(std::string const&, id_category);
+
+ std::string replace_placeholders_with_unresolved_ids(
+ std::string const&) const;
+ std::string replace_placeholders(std::string const&) const;
+
+ unsigned compatibility_version() const;
+ private:
+ boost::scoped_ptr<id_state> state;
+ };
+}
+
+#endif
diff --git a/tools/quickbook/src/input_path.cpp b/tools/quickbook/src/input_path.cpp
new file mode 100644
index 0000000000..4523ac6f22
--- /dev/null
+++ b/tools/quickbook/src/input_path.cpp
@@ -0,0 +1,257 @@
+/*=============================================================================
+ Copyright (c) 2009 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include <boost/program_options.hpp>
+#include <iostream>
+#include "input_path.hpp"
+#include "utils.hpp"
+#include "files.hpp"
+
+#if QUICKBOOK_WIDE_PATHS || QUICKBOOK_WIDE_STREAMS
+#include <boost/scoped_ptr.hpp>
+#include <windows.h>
+#include <io.h>
+#include <fcntl.h>
+#endif
+
+#if QUICKBOOK_CYGWIN_PATHS
+#include <boost/scoped_array.hpp>
+#include <boost/program_options/errors.hpp>
+#include <sys/cygwin.h>
+#endif
+
+namespace quickbook {
+ extern bool ms_errors;
+}
+
+namespace quickbook {
+namespace detail {
+
+// This is used for converting paths to UTF-8 on cygin.
+// Might be better not to use a windows
+#if QUICKBOOK_WIDE_PATHS || QUICKBOOK_WIDE_STREAMS
+ namespace {
+ std::string to_utf8(std::wstring const& x)
+ {
+ int buffer_count = WideCharToMultiByte(CP_UTF8, 0, x.c_str(), -1, 0, 0, 0, 0);
+
+ if (!buffer_count)
+ throw conversion_error("Error converting wide string to utf-8.");
+
+ boost::scoped_ptr<char> buffer(new char[buffer_count]);
+
+ if (!WideCharToMultiByte(CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count, 0, 0))
+ throw conversion_error("Error converting wide string to utf-8.");
+
+ return std::string(buffer.get());
+ }
+
+ std::wstring from_utf8(std::string const& x)
+ {
+ int buffer_count = MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, 0, 0);
+
+ if (!buffer_count)
+ throw conversion_error("Error converting utf-8 to wide string.");
+
+ boost::scoped_ptr<wchar_t> buffer(new wchar_t[buffer_count]);
+
+ if (!MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count))
+ throw conversion_error("Error converting utf-8 to wide string.");
+
+ return std::wstring(buffer.get());
+ }
+ }
+#endif
+
+#if QUICKBOOK_WIDE_PATHS
+ std::string input_to_utf8(input_string const& x)
+ {
+ return to_utf8(x);
+ }
+#else
+ std::string input_to_utf8(input_string const& x)
+ {
+ return x;
+ }
+#endif
+
+#if QUICKBOOK_WIDE_PATHS
+ fs::path generic_to_path(std::string const& x)
+ {
+ return fs::path(from_utf8(x));
+ }
+
+ std::string path_to_generic(fs::path const& x)
+ {
+ return to_utf8(x.generic_wstring());
+ }
+#else
+ fs::path generic_to_path(std::string const& x)
+ {
+ return fs::path(x);
+ }
+
+ std::string path_to_generic(fs::path const& x)
+ {
+ return x.generic_string();
+ }
+
+#endif
+
+#if QUICKBOOK_CYGWIN_PATHS
+ fs::path input_to_path(input_string const& path)
+ {
+ cygwin_conv_path_t flags = CCP_POSIX_TO_WIN_W | CCP_RELATIVE;
+
+ ssize_t size = cygwin_conv_path(flags, path.c_str(), NULL, 0);
+
+ if (size < 0)
+ throw conversion_error("Error converting cygwin path to windows.");
+
+ boost::scoped_array<char> result(new char[size]);
+ void* ptr = result.get();
+
+ if(cygwin_conv_path(flags, path.c_str(), ptr, size))
+ throw conversion_error("Error converting cygwin path to windows.");
+
+ return fs::path(static_cast<wchar_t*>(ptr));
+ }
+
+ stream_string path_to_stream(fs::path const& path)
+ {
+ cygwin_conv_path_t flags = CCP_WIN_W_TO_POSIX | CCP_RELATIVE;
+
+ ssize_t size = cygwin_conv_path(flags, path.native().c_str(), NULL, 0);
+
+ if (size < 0)
+ throw conversion_error("Error converting windows path to cygwin.");
+
+ boost::scoped_array<char> result(new char[size]);
+
+ if(cygwin_conv_path(flags, path.native().c_str(), result.get(), size))
+ throw conversion_error("Error converting windows path to cygwin.");
+
+ return std::string(result.get());
+ }
+#else
+ fs::path input_to_path(input_string const& path)
+ {
+ return fs::path(path);
+ }
+
+#if QUICKBOOK_WIDE_PATHS && !QUICKBOOK_WIDE_STREAMS
+ stream_string path_to_stream(fs::path const& path)
+ {
+ return path.string();
+ }
+#else
+ stream_string path_to_stream(fs::path const& path)
+ {
+ return path.native();
+ }
+#endif
+
+#endif // QUICKBOOK_CYGWIN_PATHS
+
+#if QUICKBOOK_WIDE_STREAMS
+
+ void initialise_output()
+ {
+ if (_isatty(_fileno(stdout))) _setmode(_fileno(stdout), _O_U16TEXT);
+ if (_isatty(_fileno(stderr))) _setmode(_fileno(stderr), _O_U16TEXT);
+ }
+
+ void write_utf8(ostream& out, std::string const& x)
+ {
+ out << from_utf8(x);
+ }
+
+ ostream& out()
+ {
+ return std::wcout;
+ }
+
+ namespace
+ {
+ inline ostream& error_stream()
+ {
+ return std::wcerr;
+ }
+ }
+
+#else
+
+ void initialise_output()
+ {
+ }
+
+ void write_utf8(ostream& out, std::string const& x)
+ {
+ out << x;
+ }
+
+ ostream& out()
+ {
+ return std::cout;
+ }
+
+ namespace
+ {
+ inline ostream& error_stream()
+ {
+ return std::clog;
+ }
+ }
+
+#endif
+
+ ostream& outerr()
+ {
+ return error_stream() << "Error: ";
+ }
+
+ ostream& outerr(fs::path const& file, int line)
+ {
+ if (line >= 0)
+ {
+ if (ms_errors)
+ return error_stream() << path_to_stream(file) << "(" << line << "): error: ";
+ else
+ return error_stream() << path_to_stream(file) << ":" << line << ": error: ";
+ }
+ else
+ {
+ return error_stream() << path_to_stream(file) << ": error: ";
+ }
+ }
+
+ ostream& outerr(file_ptr const& f, string_iterator pos)
+ {
+ return outerr(f->path, f->position_of(pos).line);
+ }
+
+ ostream& outwarn(fs::path const& file, int line)
+ {
+ if (line >= 0)
+ {
+ if (ms_errors)
+ return error_stream() << path_to_stream(file) << "(" << line << "): warning: ";
+ else
+ return error_stream() << path_to_stream(file) << ":" << line << ": warning: ";
+ }
+ else
+ {
+ return error_stream() << path_to_stream(file) << ": warning: ";
+ }
+ }
+
+ ostream& outwarn(file_ptr const& f, string_iterator pos)
+ {
+ return outwarn(f->path, f->position_of(pos).line);
+ }
+}}
diff --git a/tools/quickbook/src/input_path.hpp b/tools/quickbook/src/input_path.hpp
new file mode 100644
index 0000000000..a23474d3e1
--- /dev/null
+++ b/tools/quickbook/src/input_path.hpp
@@ -0,0 +1,123 @@
+/*=============================================================================
+ Copyright (c) 2009 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_QUICKBOOK_DETAIL_INPUT_PATH_HPP)
+#define BOOST_QUICKBOOK_DETAIL_INPUT_PATH_HPP
+
+#include <boost/config.hpp>
+#include <boost/filesystem/v3/path.hpp>
+#include <string>
+#include <stdexcept>
+#include <iostream>
+#include "fwd.hpp"
+
+#if defined(__cygwin__) || defined(__CYGWIN__)
+# define QUICKBOOK_CYGWIN_PATHS 1
+#elif defined(_WIN32)
+# define QUICKBOOK_WIDE_PATHS 1
+# if defined(BOOST_MSVC) && BOOST_MSVC >= 1400
+# define QUICKBOOK_WIDE_STREAMS 1
+# endif
+#endif
+
+#if !defined(QUICKBOOK_WIDE_PATHS)
+#define QUICKBOOK_WIDE_PATHS 0
+#endif
+
+#if !defined(QUICKBOOK_WIDE_STREAMS)
+#define QUICKBOOK_WIDE_STREAMS 0
+#endif
+
+#if !defined(QUICKBOOK_CYGWIN_PATHS)
+#define QUICKBOOK_CYGWIN_PATHS 0
+#endif
+
+namespace quickbook
+{
+ namespace fs = boost::filesystem;
+
+ namespace detail
+ {
+ struct conversion_error : std::runtime_error
+ {
+ conversion_error(char const* m) : std::runtime_error(m) {}
+ };
+
+ // 'generic': Paths in quickbook source and the generated boostbook.
+ // Always UTF-8.
+ // 'input': Paths (or other parameters) from the command line and
+ // possibly other sources in the future. Wide strings on
+ // normal windows, UTF-8 for cygwin and other platforms
+ // (hopefully).
+ // 'stream': Strings to be written to a stream.
+ // 'path': Stored as a boost::filesystem::path. Since
+ // Boost.Filesystem doesn't support cygwin, this
+ // is always wide on windows. UTF-8 on other
+ // platforms (again, hopefully).
+
+#if QUICKBOOK_WIDE_PATHS
+ typedef std::wstring input_string;
+#else
+ typedef std::string input_string;
+#endif
+
+#if QUICKBOOK_WIDE_STREAMS
+ typedef std::wostream ostream;
+ typedef std::wstring stream_string;
+#else
+ typedef std::ostream ostream;
+ typedef std::string stream_string;
+#endif
+
+ std::string input_to_utf8(input_string const&);
+ fs::path input_to_path(input_string const&);
+ stream_string path_to_stream(fs::path const&);
+
+ std::string path_to_generic(fs::path const&);
+ fs::path generic_to_path(std::string const&);
+
+ void initialise_output();
+
+ ostream& out();
+
+ // Preformats an error/warning message so that it can be parsed by
+ // common IDEs. Uses the ms_errors global to determine if VS format
+ // or GCC format. Returns the stream to continue ouput of the verbose
+ // error message.
+ ostream& outerr();
+ ostream& outerr(fs::path const& file, int line = -1);
+ ostream& outwarn(fs::path const& file, int line = -1);
+ ostream& outerr(file_ptr const&, string_iterator);
+ ostream& outwarn(file_ptr const&, string_iterator);
+
+ struct utf8_proxy
+ {
+ std::string value;
+
+ explicit utf8_proxy(std::string const& v) : value(v) {}
+ };
+
+ void write_utf8(ostream& out, std::string const&);
+
+ inline ostream& operator<<(ostream& out, utf8_proxy const& p) {
+ write_utf8(out, p.value);
+ return out;
+ }
+
+ inline utf8_proxy utf8(std::string const& value) {
+ return utf8_proxy(value);
+ }
+
+ template <typename It>
+ inline utf8_proxy utf8(It begin, It end) {
+ return utf8_proxy(std::string(begin, end));
+ }
+ }
+}
+
+#endif
diff --git a/tools/quickbook/src/intrusive_base.hpp b/tools/quickbook/src/intrusive_base.hpp
new file mode 100644
index 0000000000..702c13d0b9
--- /dev/null
+++ b/tools/quickbook/src/intrusive_base.hpp
@@ -0,0 +1,36 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_QUICKBOOK_INTRUSIVE_BASE_HPP)
+#define BOOST_QUICKBOOK_INTRUSIVE_BASE_HPP
+
+namespace quickbook
+{
+ //
+ // instructive_base
+ //
+
+ template <typename T>
+ struct intrusive_base
+ {
+ intrusive_base() : ref_count_(0) {}
+ intrusive_base(intrusive_base const&) : ref_count_(0) {}
+ intrusive_base& operator=(intrusive_base const&) { return *this; }
+ ~intrusive_base() { assert(!ref_count_); }
+
+ friend void intrusive_ptr_add_ref(T* ptr)
+ { ++ptr->ref_count_; }
+
+ friend void intrusive_ptr_release(T* ptr)
+ { if(--ptr->ref_count_ == 0) delete ptr; }
+ private:
+ unsigned ref_count_;
+ };
+}
+
+#endif
diff --git a/tools/quickbook/src/iterator.hpp b/tools/quickbook/src/iterator.hpp
new file mode 100644
index 0000000000..5897664d2d
--- /dev/null
+++ b/tools/quickbook/src/iterator.hpp
@@ -0,0 +1,69 @@
+/*=============================================================================
+ Copyright (c) 2010 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_SPIRIT_QUICKBOOK_ITERATOR_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_ITERATOR_HPP
+
+#include <boost/operators.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <iterator>
+
+namespace quickbook
+{
+ template <typename Iterator>
+ struct lookback_iterator
+ : boost::forward_iterator_helper<
+ lookback_iterator<Iterator>,
+ typename boost::iterator_value<Iterator>::type,
+ typename boost::iterator_difference<Iterator>::type,
+ typename boost::iterator_pointer<Iterator>::type,
+ typename boost::iterator_reference<Iterator>::type
+ >
+ {
+ lookback_iterator() {}
+ explicit lookback_iterator(Iterator base)
+ : original_(base), base_(base) {}
+
+ friend bool operator==(
+ lookback_iterator const& x,
+ lookback_iterator const& y)
+ {
+ return x.base_ == y.base_;
+ }
+
+ lookback_iterator& operator++()
+ {
+ ++base_;
+ return *this;
+ }
+
+ typename boost::iterator_reference<Iterator>::type operator*() const
+ {
+ return *base_;
+ }
+
+ Iterator base() const {
+ return base_;
+ }
+
+ typedef boost::iterator_range<std::reverse_iterator<Iterator> >
+ lookback_range;
+
+ lookback_range lookback() const
+ {
+ return lookback_range(base_, original_);
+ }
+
+ private:
+ Iterator original_;
+ Iterator base_;
+ };
+}
+
+#endif
diff --git a/tools/quickbook/src/main_grammar.cpp b/tools/quickbook/src/main_grammar.cpp
new file mode 100644
index 0000000000..1ec2ff9ca8
--- /dev/null
+++ b/tools/quickbook/src/main_grammar.cpp
@@ -0,0 +1,933 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "grammar_impl.hpp"
+#include "actions_class.hpp"
+#include "utils.hpp"
+#include "template_tags.hpp"
+#include "block_tags.hpp"
+#include "phrase_tags.hpp"
+#include "parsers.hpp"
+#include "scoped.hpp"
+#include "input_path.hpp"
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_chset.hpp>
+#include <boost/spirit/include/classic_if.hpp>
+#include <boost/spirit/include/classic_loops.hpp>
+#include <boost/spirit/include/classic_attribute.hpp>
+#include <boost/spirit/include/classic_lazy.hpp>
+#include <boost/spirit/include/phoenix1_primitives.hpp>
+#include <boost/range/algorithm/find_first_of.hpp>
+#include <boost/range/as_literal.hpp>
+
+#include <iostream>
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+
+ struct list_stack_item {
+ bool root; // Is this the root of the context
+ // (e.g. top, template, table cell etc.)
+ unsigned int indent; // Indent of list marker
+ // (or paragraph if not in a list)
+ unsigned int indent2; // Indent of paragraph
+ char mark; // List mark, '\0' if not in a list.
+
+ // Example of inside a list:
+ //
+ // |indent
+ // * List item
+ // |indent2
+
+ list_stack_item() :
+ root(true), indent(0), indent2(0), mark('\0') {}
+
+ list_stack_item(char mark, unsigned int indent, unsigned int indent2) :
+ root(false), indent(indent), indent2(indent2), mark(mark)
+ {}
+
+ };
+
+ struct block_types {
+ enum values {
+ none, code, list, paragraph
+ };
+ };
+
+ template <typename T>
+ struct member_action
+ {
+ typedef void(T::*member_function)(parse_iterator, parse_iterator);
+
+ T& l;
+ member_function mf;
+
+ member_action(T& l, member_function mf) : l(l), mf(mf) {}
+
+ void operator()(parse_iterator first, parse_iterator last) const {
+ (l.*mf)(first, last);
+ }
+ };
+
+ struct main_grammar_local
+ {
+ ////////////////////////////////////////////////////////////////////////
+ // Local actions
+
+ void start_blocks_impl(parse_iterator first, parse_iterator last);
+ void end_blocks_impl(parse_iterator first, parse_iterator last);
+ void check_indentation_impl(parse_iterator first, parse_iterator last);
+ void check_code_block_impl(parse_iterator first, parse_iterator last);
+ void plain_block(string_iterator first, string_iterator last);
+ void list_block(string_iterator first, string_iterator mark_pos,
+ string_iterator last);
+ void clear_stack();
+
+ struct process_element_impl : scoped_action_base {
+ process_element_impl(main_grammar_local& l)
+ : l(l) {}
+
+ bool start()
+ {
+ if (!(l.info.type & l.element.context()) ||
+ qbk_version_n < l.info.qbk_version)
+ return false;
+
+ info_ = l.info;
+
+ if (info_.type != element_info::phrase &&
+ info_.type != element_info::maybe_block)
+ l.actions_.paragraph();
+
+ l.actions_.values.builder.reset();
+
+ return true;
+ }
+
+ template <typename ResultT, typename ScannerT>
+ bool result(ResultT result, ScannerT const& scan)
+ {
+ if (result || info_.type & element_info::in_phrase)
+ return result;
+
+ l.actions_.error(scan.first, scan.first);
+ return true;
+ }
+
+ void success(parse_iterator, parse_iterator) { l.element_type = info_.type; }
+ void failure() { l.element_type = element_info::nothing; }
+
+ main_grammar_local& l;
+ element_info info_;
+ };
+
+ struct in_list_impl {
+ main_grammar_local& l;
+
+ in_list_impl(main_grammar_local& l) :
+ l(l) {}
+
+ bool operator()() const {
+ return !l.list_stack.top().root;
+ }
+ };
+
+ struct set_no_eols_scoped : scoped_action_base
+ {
+ set_no_eols_scoped(main_grammar_local& l)
+ : l(l) {}
+
+ bool start() {
+ saved_no_eols = l.no_eols;
+ l.no_eols = false;
+
+ return true;
+ }
+
+ void cleanup() {
+ l.no_eols = saved_no_eols;
+ }
+
+ main_grammar_local& l;
+ bool saved_no_eols;
+ };
+
+ ////////////////////////////////////////////////////////////////////////
+ // Local members
+
+ cl::rule<scanner>
+ top_level, indent_check,
+ paragraph_separator,
+ code, code_line, blank_line, hr,
+ inline_code,
+ template_,
+ code_block, macro,
+ template_args,
+ template_args_1_4, template_arg_1_4,
+ template_inner_arg_1_4, brackets_1_4,
+ template_args_1_5, template_arg_1_5, template_arg_1_5_content,
+ template_inner_arg_1_5, brackets_1_5,
+ break_,
+ command_line_macro_identifier,
+ dummy_block, line_dummy_block, square_brackets
+ ;
+
+ struct simple_markup_closure
+ : cl::closure<simple_markup_closure, char>
+ {
+ member1 mark;
+ };
+
+ struct block_item_closure : cl::closure<block_item_closure, bool>
+ {
+ member1 still_in_block;
+ };
+
+ struct context_closure : cl::closure<context_closure, element_info::context>
+ {
+ member1 context;
+ };
+
+ cl::rule<scanner, simple_markup_closure::context_t> simple_markup;
+ cl::rule<scanner> simple_markup_end;
+
+ cl::rule<scanner, block_item_closure::context_t> paragraph;
+ cl::rule<scanner, context_closure::context_t> paragraph_item;
+ cl::rule<scanner, block_item_closure::context_t> list;
+ cl::rule<scanner, context_closure::context_t> list_item;
+ cl::rule<scanner, context_closure::context_t> common;
+ cl::rule<scanner, context_closure::context_t> element;
+
+ // state
+ std::stack<list_stack_item> list_stack;
+ unsigned int list_indent;
+ bool no_eols;
+
+ // transitory state
+ block_types::values block_type;
+ element_info info;
+ element_info::type_enum element_type;
+
+ // actions
+ quickbook::actions& actions_;
+ member_action<main_grammar_local> check_indentation;
+ member_action<main_grammar_local> check_code_block;
+ member_action<main_grammar_local> start_blocks;
+ member_action<main_grammar_local> end_blocks;
+ in_list_impl in_list;
+ scoped_parser<process_element_impl> process_element;
+ scoped_parser<set_no_eols_scoped> scoped_no_eols;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Local constructor
+
+ main_grammar_local(quickbook::actions& actions)
+ : list_stack()
+ , list_indent(0)
+ , no_eols(true)
+ , actions_(actions)
+ , check_indentation(*this, &main_grammar_local::check_indentation_impl)
+ , check_code_block(*this, &main_grammar_local::check_indentation_impl)
+ , start_blocks(*this, &main_grammar_local::start_blocks_impl)
+ , end_blocks(*this, &main_grammar_local::end_blocks_impl)
+ , in_list(*this)
+ , process_element(*this)
+ , scoped_no_eols(*this)
+ {}
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Local grammar
+
+ void quickbook_grammar::impl::init_main()
+ {
+ main_grammar_local& local = cleanup_.add(
+ new main_grammar_local(actions));
+
+ // phrase/phrase_start is used for an entirely self-contained
+ // phrase. For example, any remaining anchors are written out
+ // at the end instead of being saved for any following content.
+ phrase_start =
+ inline_phrase [actions.phrase_end]
+ ;
+
+ // nested_phrase is used for a phrase nested inside square
+ // brackets.
+ nested_phrase =
+ actions.values.save()
+ [ *( ~cl::eps_p(']')
+ >> local.common(element_info::in_phrase)
+ )
+ ]
+ ;
+
+ // paragraph_phrase is like a nested_phrase but is also terminated
+ // by a paragraph end.
+ paragraph_phrase =
+ actions.values.save()
+ [ *( ~cl::eps_p(phrase_end)
+ >> local.common(element_info::in_phrase)
+ )
+ ]
+ ;
+
+ // extended_phrase is like a paragraph_phrase but allows some block
+ // elements.
+ extended_phrase =
+ actions.values.save()
+ [ *( ~cl::eps_p(phrase_end)
+ >> local.common(element_info::in_conditional)
+ )
+ ]
+ ;
+
+ // inline_phrase is used a phrase that isn't nested inside
+ // brackets, but is not self contained. An example of this
+ // is expanding a template, which is parsed separately but
+ // is part of the paragraph that contains it.
+ inline_phrase =
+ actions.values.save()
+ [ *local.common(element_info::in_phrase)
+ ]
+ ;
+
+ table_title_phrase =
+ actions.values.save()
+ [ *( ~cl::eps_p(space >> (']' | '[' >> space >> '['))
+ >> local.common(element_info::in_phrase)
+ )
+ ]
+ ;
+
+ inside_preformatted =
+ local.scoped_no_eols()
+ [ paragraph_phrase
+ ]
+ ;
+
+ // Top level blocks
+ block_start =
+ (*eol) [local.start_blocks]
+ >> (*local.top_level) [local.end_blocks]
+ ;
+
+ local.top_level =
+ cl::eps_p(local.indent_check)
+ >> ( cl::eps_p(ph::var(local.block_type) == block_types::code)
+ >> local.code
+ | cl::eps_p(ph::var(local.block_type) == block_types::list)
+ >> local.list
+ | cl::eps_p(ph::var(local.block_type) == block_types::paragraph)
+ >> ( local.hr
+ | local.paragraph
+ )
+ )
+ >> *eol
+ ;
+
+ local.indent_check =
+ ( *cl::blank_p
+ >> !( (cl::ch_p('*') | '#')
+ >> *cl::blank_p)
+ ) [local.check_indentation]
+ ;
+
+ local.paragraph =
+ cl::eps_p [local.paragraph.still_in_block = true]
+ >> local.paragraph_item(element_info::only_contextual_block)
+ >> *( cl::eps_p(local.paragraph.still_in_block)
+ >> local.paragraph_item(element_info::only_block)
+ )
+ >> cl::eps_p [actions.paragraph]
+ ;
+
+ local.paragraph_item =
+ local.element(local.paragraph_item.context)
+ >> !eol [local.paragraph.still_in_block = false]
+ | local.paragraph_separator [local.paragraph.still_in_block = false]
+ | local.common(element_info::in_phrase)
+ ;
+
+ local.list =
+ *cl::blank_p
+ >> (cl::ch_p('*') | '#')
+ >> (*cl::blank_p) [local.list.still_in_block = true]
+ >> *( cl::eps_p(local.list.still_in_block)
+ >> local.list_item(element_info::only_block)
+ )
+ >> cl::eps_p [actions.list_item]
+ ;
+
+ local.list_item =
+ local.element(local.list_item.context)
+ >> !eol [local.list.still_in_block = false]
+ | local.paragraph_separator [local.list.still_in_block = false]
+ | local.common(element_info::in_phrase)
+ ;
+
+ local.paragraph_separator =
+ cl::eol_p
+ >> cl::eps_p
+ ( *cl::blank_p
+ >> ( cl::eol_p
+ | cl::end_p
+ | cl::eps_p(local.in_list) >> (cl::ch_p('*') | '#')
+ )
+ )
+ >> *eol
+ ;
+
+ // Blocks contains within an element, e.g. a table cell or a footnote.
+ inside_paragraph =
+ actions.values.save()
+ [ *( local.paragraph_separator [actions.paragraph]
+ >> *eol
+ | ~cl::eps_p(']')
+ >> local.common(element_info::in_nested_block)
+ )
+ ] [actions.paragraph]
+ ;
+
+ local.hr =
+ cl::str_p("----")
+ >> actions.values.list(block_tags::hr)
+ [ ( qbk_since(106u)
+ >> *(line_comment | (cl::anychar_p - (cl::eol_p | '[' | ']')))
+ | qbk_before(106u)
+ >> *(line_comment | (cl::anychar_p - (cl::eol_p | "[/")))
+ )
+ >> *eol
+ ] [actions.element]
+ ;
+
+ local.element
+ = '['
+ >> ( cl::eps_p(cl::punct_p)
+ >> elements [ph::var(local.info) = ph::arg1]
+ | elements [ph::var(local.info) = ph::arg1]
+ >> (cl::eps_p - (cl::alnum_p | '_'))
+ )
+ >> local.process_element()
+ [ actions.values.list(ph::var(local.info.tag))
+ [ cl::lazy_p(*ph::var(local.info.rule))
+ >> space
+ >> ']'
+ ] [actions.element]
+ ]
+ ;
+
+ local.code =
+ (
+ local.code_line
+ >> *(*local.blank_line >> local.code_line)
+ ) [actions.code]
+ >> *eol
+ ;
+
+ local.code_line =
+ ( *cl::blank_p
+ >> ~cl::eps_p(cl::eol_p)
+ ) [local.check_code_block]
+ >> cl::eps_p(ph::var(local.block_type) == block_types::code)
+ >> *(cl::anychar_p - cl::eol_p)
+ >> (cl::eol_p | cl::end_p)
+ ;
+
+ local.blank_line =
+ *cl::blank_p >> cl::eol_p
+ ;
+
+ local.common =
+ local.macro
+ | local.element(local.common.context)
+ | local.template_
+ | local.break_
+ | local.code_block
+ | local.inline_code
+ | local.simple_markup
+ | escape
+ | comment
+ | qbk_since(106u) >> local.square_brackets
+ | cl::space_p [actions.raw_char]
+ | cl::anychar_p [actions.plain_char]
+ ;
+
+ local.square_brackets =
+ ( cl::ch_p('[') [actions.plain_char]
+ >> paragraph_phrase
+ >> ( cl::ch_p(']') [actions.plain_char]
+ | cl::eps_p [actions.error("Missing close bracket")]
+ )
+ | cl::ch_p(']') [actions.plain_char]
+ >> cl::eps_p [actions.error("Mismatched close bracket")]
+ )
+ ;
+
+ local.macro =
+ cl::eps_p
+ ( ( actions.macro
+ >> ~cl::eps_p(cl::alpha_p | '_')
+ // must not be followed by alpha or underscore
+ )
+ & macro_identifier // must be a valid macro for the current version
+ )
+ >> actions.macro [actions.do_macro]
+ ;
+
+ local.template_ =
+ ( '['
+ >> space
+ >> actions.values.list(template_tags::template_)
+ [ !cl::str_p("`") [actions.values.entry(ph::arg1, ph::arg2, template_tags::escape)]
+ >> ( cl::eps_p(cl::punct_p)
+ >> actions.templates.scope [actions.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
+ | actions.templates.scope [actions.values.entry(ph::arg1, ph::arg2, template_tags::identifier)]
+ >> cl::eps_p(hard_space)
+ )
+ >> space
+ >> !local.template_args
+ >> ']'
+ ]
+ ) [actions.element]
+ ;
+
+ local.template_args =
+ qbk_since(105u) >> local.template_args_1_5
+ | qbk_before(105u) >> local.template_args_1_4
+ ;
+
+ local.template_args_1_4 = local.template_arg_1_4 >> *(".." >> local.template_arg_1_4);
+
+ local.template_arg_1_4 =
+ ( cl::eps_p(*cl::blank_p >> cl::eol_p)
+ >> local.template_inner_arg_1_4 [actions.values.entry(ph::arg1, ph::arg2, template_tags::block)]
+ | local.template_inner_arg_1_4 [actions.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
+ )
+ ;
+
+ local.template_inner_arg_1_4 =
+ +(local.brackets_1_4 | (cl::anychar_p - (cl::str_p("..") | ']')))
+ ;
+
+ local.brackets_1_4 =
+ '[' >> local.template_inner_arg_1_4 >> ']'
+ ;
+
+ local.template_args_1_5 = local.template_arg_1_5 >> *(".." >> local.template_arg_1_5);
+
+ local.template_arg_1_5 =
+ ( cl::eps_p(*cl::blank_p >> cl::eol_p)
+ >> local.template_arg_1_5_content [actions.values.entry(ph::arg1, ph::arg2, template_tags::block)]
+ | local.template_arg_1_5_content [actions.values.entry(ph::arg1, ph::arg2, template_tags::phrase)]
+ )
+ ;
+
+ local.template_arg_1_5_content =
+ +(local.brackets_1_5 | ('\\' >> cl::anychar_p) | (cl::anychar_p - (cl::str_p("..") | '[' | ']')))
+ ;
+
+ local.template_inner_arg_1_5 =
+ +(local.brackets_1_5 | ('\\' >> cl::anychar_p) | (cl::anychar_p - (cl::str_p('[') | ']')))
+ ;
+
+ local.brackets_1_5 =
+ '[' >> local.template_inner_arg_1_5 >> ']'
+ ;
+
+ local.break_
+ = ( '['
+ >> space
+ >> "br"
+ >> space
+ >> ']'
+ ) [actions.break_]
+ ;
+
+ local.inline_code =
+ '`' >>
+ (
+ *(cl::anychar_p -
+ ( '`'
+ | (cl::eol_p >> *cl::blank_p >> cl::eol_p)
+ // Make sure that we don't go
+ ) // past a single block
+ ) >> cl::eps_p('`')
+ ) [actions.inline_code]
+ >> '`'
+ ;
+
+ local.code_block =
+ "```"
+ >> ~cl::eps_p("`")
+ >> *(*cl::blank_p >> cl::eol_p)
+ >> ( *( "````" >> *cl::ch_p('`')
+ | ( cl::anychar_p
+ - (*cl::space_p >> "```" >> ~cl::eps_p("`"))
+ )
+ )
+ >> !(*cl::blank_p >> cl::eol_p)
+ ) [actions.code_block]
+ >> ( *cl::space_p >> "```"
+ | cl::eps_p [actions.error("Unfinished code block")]
+ )
+ | "``"
+ >> ~cl::eps_p("`")
+ >> *(*cl::blank_p >> cl::eol_p)
+ >> ( *( "```" >> *cl::ch_p('`')
+ | ( cl::anychar_p
+ - (*cl::space_p >> "``" >> ~cl::eps_p("`"))
+ )
+ )
+ >> !(*cl::blank_p >> cl::eol_p)
+ ) [actions.code_block]
+ >> ( *cl::space_p >> "``"
+ | cl::eps_p [actions.error("Unfinished code block")]
+ )
+ ;
+
+ local.simple_markup =
+ cl::chset<>("*/_=") [local.simple_markup.mark = ph::arg1]
+ >> cl::eps_p(cl::graph_p) // graph_p must follow first mark
+ >> lookback
+ [ cl::anychar_p // skip back over the markup
+ >> ~cl::eps_p(cl::f_ch_p(local.simple_markup.mark))
+ // first mark not be preceeded by
+ // the same character.
+ >> (cl::space_p | cl::punct_p | cl::end_p)
+ // first mark must be preceeded
+ // by space or punctuation or the
+ // mark character or a the start.
+ ]
+ >> actions.values.save()
+ [
+ actions.to_value()
+ [
+ cl::eps_p((actions.macro & macro_identifier) >> local.simple_markup_end)
+ >> actions.macro [actions.do_macro]
+ | ~cl::eps_p(cl::f_ch_p(local.simple_markup.mark))
+ >> +( ~cl::eps_p
+ ( lookback [~cl::f_ch_p(local.simple_markup.mark)]
+ >> local.simple_markup_end
+ )
+ >> cl::anychar_p [actions.plain_char]
+ )
+ ]
+ >> cl::f_ch_p(local.simple_markup.mark)
+ [actions.simple_markup]
+ ]
+ ;
+
+ local.simple_markup_end
+ = ( lookback[cl::graph_p] // final mark must be preceeded by
+ // graph_p
+ >> cl::f_ch_p(local.simple_markup.mark)
+ >> ~cl::eps_p(cl::f_ch_p(local.simple_markup.mark))
+ // final mark not be followed by
+ // the same character.
+ >> (cl::space_p | cl::punct_p | cl::end_p)
+ // final mark must be followed by
+ // space or punctuation
+ )
+ | '['
+ | "'''"
+ | '`'
+ | phrase_end
+ ;
+
+ escape =
+ cl::str_p("\\n") [actions.break_]
+ | cl::str_p("\\ ") // ignore an escaped space
+ | '\\' >> cl::punct_p [actions.plain_char]
+ | "\\u" >> cl::repeat_p(4) [cl::chset<>("0-9a-fA-F")]
+ [actions.escape_unicode]
+ | "\\U" >> cl::repeat_p(8) [cl::chset<>("0-9a-fA-F")]
+ [actions.escape_unicode]
+ | ("'''" >> !eol)
+ >> actions.values.save()
+ [ (*(cl::anychar_p - "'''")) [actions.values.entry(ph::arg1, ph::arg2, phrase_tags::escape)]
+ >> ( cl::str_p("'''")
+ | cl::eps_p [actions.error("Unclosed boostbook escape.")]
+ ) [actions.element]
+ ]
+ ;
+
+ raw_escape =
+ cl::str_p("\\n") [actions.error("Newlines invalid here.")]
+ | cl::str_p("\\ ") // ignore an escaped space
+ | '\\' >> cl::punct_p [actions.raw_char]
+ | "\\u" >> cl::repeat_p(4) [cl::chset<>("0-9a-fA-F")]
+ [actions.escape_unicode]
+ | "\\U" >> cl::repeat_p(8) [cl::chset<>("0-9a-fA-F")]
+ [actions.escape_unicode]
+ | ('\\' >> cl::anychar_p) [actions.error("Invalid escape.")]
+ [actions.raw_char]
+ | ("'''" >> !eol) [actions.error("Boostbook escape invalid here.")]
+ >> (*(cl::anychar_p - "'''"))
+ >> ( cl::str_p("'''")
+ | cl::eps_p [actions.error("Unclosed boostbook escape.")]
+ ) [actions.element]
+ ;
+
+ //
+ // Command line
+ //
+
+ command_line =
+ actions.values.list(block_tags::macro_definition)
+ [ *cl::space_p
+ >> local.command_line_macro_identifier
+ [actions.values.entry(ph::arg1, ph::arg2)]
+ >> *cl::space_p
+ >> !( '='
+ >> *cl::space_p
+ >> actions.to_value() [ inline_phrase ]
+ >> *cl::space_p
+ )
+ >> cl::end_p
+ ] [actions.element]
+ ;
+
+ local.command_line_macro_identifier =
+ qbk_since(106u)
+ >> +(cl::anychar_p - (cl::space_p | '[' | '\\' | ']' | '='))
+ | +(cl::anychar_p - (cl::space_p | ']' | '='))
+ ;
+
+ // Miscellaneous stuff
+
+ // Follows an alphanumeric identifier - ensures that it doesn't
+ // match an empty space in the middle of the identifier.
+ hard_space =
+ (cl::eps_p - (cl::alnum_p | '_')) >> space
+ ;
+
+ space =
+ *(cl::space_p | comment)
+ ;
+
+ blank =
+ *(cl::blank_p | comment)
+ ;
+
+ eol = blank >> cl::eol_p
+ ;
+
+ phrase_end =
+ ']'
+ | cl::eps_p(ph::var(local.no_eols))
+ >> cl::eol_p >> *cl::blank_p >> cl::eol_p
+ ; // Make sure that we don't go
+ // past a single block, except
+ // when preformatted.
+
+ comment =
+ "[/" >> *(local.dummy_block | (cl::anychar_p - ']')) >> ']'
+ ;
+
+ local.dummy_block =
+ '[' >> *(local.dummy_block | (cl::anychar_p - ']')) >> ']'
+ ;
+
+ line_comment =
+ "[/" >> *(local.line_dummy_block | (cl::anychar_p - (cl::eol_p | ']'))) >> ']'
+ ;
+
+ local.line_dummy_block =
+ '[' >> *(local.line_dummy_block | (cl::anychar_p - (cl::eol_p | ']'))) >> ']'
+ ;
+
+ macro_identifier =
+ qbk_since(106u)
+ >> +(cl::anychar_p - (cl::space_p | '[' | '\\' | ']'))
+ | qbk_before(106u)
+ >> +(cl::anychar_p - (cl::space_p | ']'))
+ ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Indentation Handling
+
+ template <typename Iterator>
+ int indent_length(Iterator first, Iterator end)
+ {
+ int length = 0;
+ for(; first != end; ++first)
+ {
+ if (*first == '\t') {
+ // hardcoded tab to 4 for now
+ length = length + 4 - (length % 4);
+ }
+ else {
+ ++length;
+ }
+ }
+
+ return length;
+ }
+
+ void main_grammar_local::start_blocks_impl(parse_iterator, parse_iterator)
+ {
+ list_stack.push(list_stack_item());
+ }
+
+ void main_grammar_local::end_blocks_impl(parse_iterator, parse_iterator)
+ {
+ clear_stack();
+ list_stack.pop();
+ }
+
+ void main_grammar_local::check_indentation_impl(parse_iterator first_, parse_iterator last_)
+ {
+ string_iterator first = first_.base();
+ string_iterator last = last_.base();
+ string_iterator mark_pos = boost::find_first_of(
+ boost::make_iterator_range(first, last),
+ boost::as_literal("#*"));
+
+ if (mark_pos == last) {
+ plain_block(first, last);
+ }
+ else {
+ list_block(first, mark_pos, last);
+ }
+ }
+
+ void main_grammar_local::check_code_block_impl(parse_iterator first, parse_iterator last)
+ {
+ unsigned int new_indent = indent_length(first.base(), last.base());
+
+ block_type = (new_indent > list_stack.top().indent2) ?
+ block_types::code : block_types::none;
+ }
+
+ void main_grammar_local::plain_block(string_iterator first, string_iterator last)
+ {
+ if (qbk_version_n >= 106u) {
+ unsigned int new_indent = indent_length(first, last);
+
+ if (new_indent > list_stack.top().indent2) {
+ block_type = block_types::code;
+ }
+ else {
+ while (!list_stack.top().root && new_indent < list_stack.top().indent)
+ {
+ actions_.end_list_item();
+ actions_.end_list(list_stack.top().mark);
+ list_stack.pop();
+ list_indent = list_stack.top().indent;
+ }
+
+ if (!list_stack.top().root && new_indent == list_stack.top().indent)
+ {
+ // If the paragraph is aligned with the list item's marker,
+ // then end the current list item if that's aligned (or to
+ // the left of) the parent's paragraph.
+ //
+ // i.e.
+ //
+ // * Level 1
+ // * Level 2
+ //
+ // Still Level 2
+ //
+ // vs.
+ //
+ // * Level 1
+ // * Level 2
+ //
+ // Back to Level 1
+
+ list_stack_item save = list_stack.top();
+ list_stack.pop();
+
+ assert(list_stack.top().root ?
+ new_indent >= list_stack.top().indent :
+ new_indent > list_stack.top().indent);
+
+ if (new_indent <= list_stack.top().indent2) {
+ actions_.end_list_item();
+ actions_.end_list(save.mark);
+ list_indent = list_stack.top().indent;
+ }
+ else {
+ list_stack.push(save);
+ }
+ }
+
+ block_type = block_types::paragraph;
+ }
+ }
+ else {
+ clear_stack();
+
+ if (last == first)
+ block_type = block_types::paragraph;
+ else
+ block_type = block_types::code;
+ }
+ }
+
+ void main_grammar_local::list_block(string_iterator first, string_iterator mark_pos,
+ string_iterator last)
+ {
+ unsigned int new_indent = indent_length(first, mark_pos);
+ unsigned int new_indent2 = indent_length(first, last);
+ char mark = *mark_pos;
+
+ if (list_stack.top().root && new_indent > 0) {
+ block_type = block_types::code;
+ return;
+ }
+
+ if (list_stack.top().root || new_indent > list_indent) {
+ list_stack.push(list_stack_item(mark, new_indent, new_indent2));
+ actions_.start_list(mark);
+ }
+ else if (new_indent == list_indent) {
+ actions_.end_list_item();
+ }
+ else {
+ // This should never reach root, since the first list
+ // has indentation 0.
+ while(!list_stack.top().root && new_indent < list_stack.top().indent)
+ {
+ actions_.end_list_item();
+ actions_.end_list(list_stack.top().mark);
+ list_stack.pop();
+ }
+
+ actions_.end_list_item();
+ }
+
+ list_indent = new_indent;
+
+ if (mark != list_stack.top().mark)
+ {
+ detail::outerr(actions_.current_file, first)
+ << "Illegal change of list style.\n";
+ detail::outwarn(actions_.current_file, first)
+ << "Ignoring change of list style." << std::endl;
+ ++actions_.error_count;
+ }
+
+ actions_.start_list_item();
+ block_type = block_types::list;
+ }
+
+ void main_grammar_local::clear_stack()
+ {
+ while (!list_stack.top().root) {
+ actions_.end_list_item();
+ actions_.end_list(list_stack.top().mark);
+ list_stack.pop();
+ }
+ }
+}
diff --git a/tools/quickbook/src/markups.cpp b/tools/quickbook/src/markups.cpp
new file mode 100644
index 0000000000..558848444b
--- /dev/null
+++ b/tools/quickbook/src/markups.cpp
@@ -0,0 +1,78 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "quickbook.hpp"
+#include "markups.hpp"
+#include "block_tags.hpp"
+#include "phrase_tags.hpp"
+#include <boost/foreach.hpp>
+#include <ostream>
+#include <map>
+
+namespace quickbook
+{
+ namespace detail
+ {
+ std::map<value::tag_type, markup> markups;
+
+ void initialise_markups()
+ {
+ markup init_markups[] = {
+ { block_tags::paragraph, "<para>\n", "</para>\n" },
+ { block_tags::blurb, "<sidebar role=\"blurb\">\n", "</sidebar>\n" },
+ { block_tags::blockquote, "<blockquote>", "</blockquote>" },
+ { block_tags::preformatted, "<programlisting>", "</programlisting>" },
+ { block_tags::warning, "<warning>", "</warning>" },
+ { block_tags::caution, "<caution>", "</caution>" },
+ { block_tags::important, "<important>", "</important>" },
+ { block_tags::note, "<note>", "</note>" },
+ { block_tags::tip, "<tip>", "</tip>" },
+ { block_tags::block, "", "" },
+ { block_tags::ordered_list, "<orderedlist>", "</orderedlist>" },
+ { block_tags::itemized_list, "<itemizedlist>", "</itemizedlist>" },
+ { block_tags::hr, "<para/>", 0 },
+ { phrase_tags::url, "<ulink url=\"", "</ulink>" },
+ { phrase_tags::link, "<link linkend=\"", "</link>" },
+ { phrase_tags::funcref, "<functionname alt=\"", "</functionname>" },
+ { phrase_tags::classref, "<classname alt=\"", "</classname>" },
+ { phrase_tags::memberref, "<methodname alt=\"", "</methodname>" },
+ { phrase_tags::enumref, "<enumname alt=\"", "</enumname>" },
+ { phrase_tags::macroref, "<macroname alt=\"", "</macroname>" },
+ { phrase_tags::headerref, "<headername alt=\"", "</headername>" },
+ { phrase_tags::conceptref, "<conceptname alt=\"", "</conceptname>" },
+ { phrase_tags::globalref, "<globalname alt=\"", "</globalname>" },
+ { phrase_tags::bold, "<emphasis role=\"bold\">", "</emphasis>" },
+ { phrase_tags::italic, "<emphasis>", "</emphasis>" },
+ { phrase_tags::underline, "<emphasis role=\"underline\">", "</emphasis>" },
+ { phrase_tags::teletype, "<literal>", "</literal>" },
+ { phrase_tags::strikethrough, "<emphasis role=\"strikethrough\">", "</emphasis>" },
+ { phrase_tags::quote, "<quote>", "</quote>" },
+ { phrase_tags::replaceable, "<replaceable>", "</replaceable>" },
+ { phrase_tags::escape, "<!--quickbook-escape-prefix-->", "<!--quickbook-escape-postfix-->" },
+ { phrase_tags::break_mark, "<sbr/>\n", 0 }
+ };
+
+ BOOST_FOREACH(markup m, init_markups)
+ {
+ markups[m.tag] = m;
+ }
+ }
+
+ markup const& get_markup(value::tag_type t)
+ {
+ return markups[t];
+ }
+
+ std::ostream& operator<<(std::ostream& out, markup const& m)
+ {
+ return out<<"{"<<m.tag<<": \""<<m.pre<<"\", \""<<m.post<<"\"}";
+ }
+ }
+}
diff --git a/tools/quickbook/src/markups.hpp b/tools/quickbook/src/markups.hpp
new file mode 100644
index 0000000000..0779b7e40a
--- /dev/null
+++ b/tools/quickbook/src/markups.hpp
@@ -0,0 +1,32 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MARKUPS_HPP)
+#define BOOST_SPIRIT_MARKUPS_HPP
+
+#include <iosfwd>
+#include "values.hpp"
+
+namespace quickbook
+{
+ namespace detail
+ {
+ struct markup {
+ value::tag_type tag;
+ char const* pre;
+ char const* post;
+ };
+
+ markup const& get_markup(value::tag_type);
+ std::ostream& operator<<(std::ostream&, markup const&);
+ }
+}
+
+#endif // BOOST_SPIRIT_MARKUPS_HPP
+
diff --git a/tools/quickbook/src/parsers.hpp b/tools/quickbook/src/parsers.hpp
new file mode 100644
index 0000000000..19d385de5e
--- /dev/null
+++ b/tools/quickbook/src/parsers.hpp
@@ -0,0 +1,257 @@
+/*=============================================================================
+ Copyright (c) 2010-2011 Daniel James
+ Copyright (c) 2003 Martin Wille
+ http://spirit.sourceforge.net/
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ =============================================================================*/
+
+// Some custom parsers for use in quickbook.
+
+#ifndef BOOST_QUICKBOOK_PARSERS_HPP
+#define BOOST_QUICKBOOK_PARSERS_HPP
+
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_nil.hpp>
+#include <boost/spirit/include/phoenix1_primitives.hpp>
+#include <boost/spirit/include/phoenix1_tuples.hpp>
+#include <boost/spirit/include/phoenix1_binders.hpp>
+
+namespace quickbook {
+ namespace cl = boost::spirit::classic;
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // scoped_parser<Impl>
+ //
+ // Impl is a struct with the methods:
+ //
+ // void start();
+ // void success(parse_iterator, parse_iterator);
+ // void failure();
+ // void cleanup();
+ //
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Impl, typename Arguments, typename ParserT>
+ struct scoped_parser_impl
+ : public cl::unary< ParserT, cl::parser< scoped_parser_impl<Impl, Arguments, ParserT> > >
+ {
+ typedef scoped_parser_impl<Impl, Arguments, ParserT> self_t;
+ typedef cl::unary< ParserT, cl::parser< scoped_parser_impl<Impl, Arguments, ParserT> > > base_t;
+
+ template <typename ScannerT>
+ struct result { typedef cl::match<> type; };
+
+ scoped_parser_impl(
+ Impl const& impl,
+ Arguments const& arguments,
+ ParserT const &p)
+ : base_t(p)
+ , impl_(impl)
+ , arguments_(arguments)
+ {}
+
+ struct scoped
+ {
+ explicit scoped(Impl const& impl)
+ : impl_(impl)
+ , in_progress_(false)
+ {}
+
+ typedef phoenix::tuple_index<0> t0;
+ typedef phoenix::tuple_index<1> t1;
+
+ bool start(phoenix::tuple<> const&)
+ {
+ in_progress_ = impl_.start();
+ return in_progress_;
+ }
+
+ template <typename Arg1>
+ bool start(phoenix::tuple<Arg1> const& x)
+ {
+ in_progress_ = phoenix::bind(&Impl::start)(phoenix::var(impl_), x[t0()])();
+ return in_progress_;
+ }
+
+ template <typename Arg1, typename Arg2>
+ bool start(phoenix::tuple<Arg1, Arg2> const& x)
+ {
+ in_progress_ = phoenix::bind(&Impl::start)(phoenix::var(impl_), x[t0()], x[t1()])();
+ return in_progress_;
+ }
+
+ void success(parse_iterator f, parse_iterator l)
+ {
+ in_progress_ = false;
+ impl_.success(f, l);
+ }
+
+ void failure()
+ {
+ in_progress_ = false;
+ impl_.failure();
+ }
+
+ ~scoped()
+ {
+ if (in_progress_) impl_.failure();
+ impl_.cleanup();
+ }
+
+ Impl impl_;
+ bool in_progress_;
+ };
+
+ template <typename ScannerT>
+ typename result<ScannerT>::type parse(ScannerT const &scan) const
+ {
+ typedef typename ScannerT::iterator_t iterator_t;
+ iterator_t save = scan.first;
+
+ scoped scope(impl_);
+ if (!scope.start(arguments_))
+ return scan.no_match();
+
+ typename cl::parser_result<ParserT, ScannerT>::type result
+ = this->subject().parse(scan);
+
+ bool success = scope.impl_.result(result, scan);
+
+ if (success) {
+ scope.success(save, scan.first);
+
+ if (result) {
+ return scan.create_match(result.length(), cl::nil_t(), save, scan.first);
+ }
+ else {
+ return scan.create_match(scan.first.base() - save.base(), cl::nil_t(), save, scan.first);
+ }
+ }
+ else {
+ scope.failure();
+ return scan.no_match();
+ }
+ }
+
+ Impl impl_;
+ Arguments arguments_;
+ };
+
+ template <typename Impl, typename Arguments>
+ struct scoped_parser_gen
+ {
+ explicit scoped_parser_gen(Impl impl, Arguments const& arguments)
+ : impl_(impl), arguments_(arguments) {}
+
+ template<typename ParserT>
+ scoped_parser_impl
+ <
+ Impl,
+ Arguments,
+ typename cl::as_parser<ParserT>::type
+ >
+ operator[](ParserT const &p) const
+ {
+ typedef cl::as_parser<ParserT> as_parser_t;
+ typedef typename as_parser_t::type parser_t;
+
+ return scoped_parser_impl<Impl, Arguments, parser_t>
+ (impl_, arguments_, p);
+ }
+
+ Impl impl_;
+ Arguments arguments_;
+ };
+
+ template <typename Impl>
+ struct scoped_parser
+ {
+ scoped_parser(Impl const& impl)
+ : impl_(impl) {}
+
+ scoped_parser_gen<Impl, phoenix::tuple<> >
+ operator()() const
+ {
+ typedef phoenix::tuple<> tuple;
+ return scoped_parser_gen<Impl, tuple>(impl_, tuple());
+ }
+
+ template <typename Arg1>
+ scoped_parser_gen<Impl, phoenix::tuple<Arg1> >
+ operator()(Arg1 x1) const
+ {
+ typedef phoenix::tuple<Arg1> tuple;
+ return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1));
+ }
+
+ template <typename Arg1, typename Arg2>
+ scoped_parser_gen<Impl, phoenix::tuple<Arg1, Arg2> >
+ operator()(Arg1 x1, Arg2 x2) const
+ {
+ typedef phoenix::tuple<Arg1, Arg2> tuple;
+ return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1, x2));
+ }
+
+ Impl impl_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // Lookback parser
+ //
+ // usage: lookback[body]
+ //
+ // Requires that iterator has typedef 'lookback_range' and function
+ // 'lookback' returning a 'lookback_range'.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename ParserT>
+ struct lookback_parser
+ : public cl::unary< ParserT, cl::parser< lookback_parser<ParserT> > >
+ {
+ typedef lookback_parser<ParserT> self_t;
+ typedef cl::unary< ParserT, cl::parser< lookback_parser<ParserT> > > base_t;
+
+ template <typename ScannerT>
+ struct result
+ {
+ typedef typename cl::parser_result<ParserT, ScannerT>::type type;
+ };
+
+ lookback_parser(ParserT const& p)
+ : base_t(p)
+ {}
+
+ template <typename ScannerT>
+ typename result<ScannerT>::type parse(ScannerT const &scan) const
+ {
+ typedef typename ScannerT::iterator_t::lookback_range::iterator iterator_t;
+ typedef cl::scanner<iterator_t, typename ScannerT::policies_t> scanner_t;
+
+ iterator_t begin = scan.first.lookback().begin();
+ scanner_t lookback_scan(begin, scan.first.lookback().end(), scan);
+
+ if (this->subject().parse(lookback_scan))
+ return scan.empty_match();
+ else
+ return scan.no_match();
+ }
+ };
+
+ struct lookback_gen
+ {
+ template <typename ParserT>
+ lookback_parser<ParserT> operator[](ParserT const& p) const
+ {
+ return lookback_parser<ParserT>(p);
+ }
+ };
+
+ lookback_gen const lookback = lookback_gen();
+}
+
+#endif // BOOST_QUICKBOOK_SCOPED_BLOCK_HPP
diff --git a/tools/quickbook/src/phrase_element_grammar.cpp b/tools/quickbook/src/phrase_element_grammar.cpp
new file mode 100644
index 0000000000..7a4e3c0a09
--- /dev/null
+++ b/tools/quickbook/src/phrase_element_grammar.cpp
@@ -0,0 +1,184 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "grammar_impl.hpp"
+#include "actions_class.hpp"
+#include "utils.hpp"
+#include "phrase_tags.hpp"
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_assign_actor.hpp>
+#include <boost/spirit/include/classic_clear_actor.hpp>
+#include <boost/spirit/include/classic_if.hpp>
+#include <boost/spirit/include/phoenix1_primitives.hpp>
+#include <boost/spirit/include/phoenix1_casts.hpp>
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+
+ struct phrase_element_grammar_local
+ {
+ cl::rule<scanner>
+ image, anchor, link, empty, cond_phrase, inner_phrase,
+ role
+ ;
+ };
+
+ void quickbook_grammar::impl::init_phrase_elements()
+ {
+ phrase_element_grammar_local& local = cleanup_.add(
+ new phrase_element_grammar_local);
+
+ elements.add
+ ("?", element_info(element_info::phrase, &local.cond_phrase))
+ ;
+
+ local.cond_phrase =
+ blank
+ >> macro_identifier [actions.values.entry(ph::arg1, ph::arg2)]
+ >> actions.scoped_cond_phrase()
+ [extended_phrase]
+ ;
+
+ elements.add
+ ("$", element_info(element_info::phrase, &local.image, phrase_tags::image))
+ ;
+
+ // Note that the attribute values here are encoded in plain text not
+ // boostbook.
+ local.image =
+ qbk_since(105u)
+ >> blank
+ >> ( qbk_before(106u)
+ >> (+(
+ *cl::space_p
+ >> +(cl::anychar_p - (cl::space_p | phrase_end | '['))
+ )) [actions.values.entry(ph::arg1, ph::arg2)]
+ | qbk_since(106u)
+ >> actions.to_value()
+ [ +( raw_escape
+ | (+cl::space_p >> ~cl::eps_p(phrase_end | '['))
+ [actions.raw_char]
+ | (cl::anychar_p - (cl::space_p | phrase_end | '['))
+ [actions.raw_char]
+ )
+ ]
+ )
+ >> hard_space
+ >> *actions.values.list()
+ [ '['
+ >> (*(cl::alnum_p | '_'))
+ [actions.values.entry(ph::arg1, ph::arg2)]
+ >> space
+ >> ( qbk_before(106u)
+ >> (*(cl::anychar_p - (phrase_end | '[')))
+ [actions.values.entry(ph::arg1, ph::arg2)]
+ | qbk_since(106u)
+ >> actions.to_value()
+ [ *( raw_escape
+ | (cl::anychar_p - (phrase_end | '['))
+ [actions.raw_char]
+ )
+ ]
+ )
+ >> ']'
+ >> space
+ ]
+ >> cl::eps_p(']')
+ | qbk_before(105u)
+ >> blank
+ >> (*(cl::anychar_p - phrase_end)) [actions.values.entry(ph::arg1, ph::arg2)]
+ >> cl::eps_p(']')
+ ;
+
+ elements.add
+ ("@", element_info(element_info::phrase, &local.link, phrase_tags::url))
+ ("link", element_info(element_info::phrase, &local.link, phrase_tags::link))
+ ("funcref", element_info(element_info::phrase, &local.link, phrase_tags::funcref))
+ ("classref", element_info(element_info::phrase, &local.link, phrase_tags::classref))
+ ("memberref", element_info(element_info::phrase, &local.link, phrase_tags::memberref))
+ ("enumref", element_info(element_info::phrase, &local.link, phrase_tags::enumref))
+ ("macroref", element_info(element_info::phrase, &local.link, phrase_tags::macroref))
+ ("headerref", element_info(element_info::phrase, &local.link, phrase_tags::headerref))
+ ("conceptref", element_info(element_info::phrase, &local.link, phrase_tags::conceptref))
+ ("globalref", element_info(element_info::phrase, &local.link, phrase_tags::globalref))
+ ;
+
+ local.link =
+ space
+ >> ( qbk_before(106u)
+ >> (*(cl::anychar_p - (']' | space)))
+ [actions.values.entry(ph::arg1, ph::arg2)]
+ | qbk_since(106u)
+ >> actions.to_value()
+ [ *( raw_escape
+ | (cl::anychar_p - (']' | space))
+ [actions.raw_char]
+ )
+ ]
+ )
+ >> hard_space
+ >> local.inner_phrase
+ ;
+
+ elements.add
+ ("#", element_info(element_info::maybe_block, &local.anchor, phrase_tags::anchor))
+ ;
+
+ local.anchor =
+ blank
+ >> ( qbk_before(106u)
+ >> (*(cl::anychar_p - phrase_end)) [actions.values.entry(ph::arg1, ph::arg2)]
+ | qbk_since(106u)
+ >> actions.to_value()
+ [ *( raw_escape
+ | (cl::anychar_p - phrase_end)
+ [actions.raw_char]
+ )
+ ]
+ )
+ ;
+
+ elements.add
+ ("*", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::bold))
+ ("'", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::italic))
+ ("_", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::underline))
+ ("^", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::teletype))
+ ("-", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::strikethrough))
+ ("\"", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::quote))
+ ("~", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::replaceable))
+ ("footnote", element_info(element_info::phrase, &local.inner_phrase, phrase_tags::footnote))
+ ;
+
+ elements.add
+ ("c++", element_info(element_info::phrase, &local.empty, source_mode_tags::cpp))
+ ("python", element_info(element_info::phrase, &local.empty, source_mode_tags::python))
+ ("teletype", element_info(element_info::phrase, &local.empty, source_mode_tags::teletype))
+ ;
+
+ elements.add
+ ("role", element_info(element_info::phrase, &local.role, phrase_tags::role, 106u))
+ ;
+
+ local.role
+ = space
+ >> (+(cl::alnum_p | '_')) [actions.values.entry(ph::arg1, ph::arg2)]
+ >> hard_space
+ >> local.inner_phrase
+ ;
+
+ local.empty = cl::eps_p;
+
+ local.inner_phrase =
+ blank
+ >> actions.to_value() [ paragraph_phrase ]
+ ;
+ }
+}
diff --git a/tools/quickbook/src/phrase_tags.hpp b/tools/quickbook/src/phrase_tags.hpp
new file mode 100644
index 0000000000..bf9b754b6c
--- /dev/null
+++ b/tools/quickbook/src/phrase_tags.hpp
@@ -0,0 +1,35 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_SPIRIT_QUICKBOOK_PHRASE_TAGS_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_PHRASE_TAGS_HPP
+
+#include "value_tags.hpp"
+
+namespace quickbook
+{
+ QUICKBOOK_VALUE_TAGS(phrase_tags, 0x500,
+ (image)
+ (url)(link)(anchor)
+ (funcref)(classref)(memberref)(enumref)
+ (macroref)(headerref)(conceptref)(globalref)
+ (bold)(italic)(underline)(teletype)(strikethrough)(quote)(replaceable)
+ (footnote)
+ (escape)
+ (break_mark)
+ (role)
+ )
+
+ QUICKBOOK_VALUE_NAMED_TAGS(source_mode_tags, 0x550,
+ ((cpp)("c++"))
+ ((python)("python"))
+ ((teletype)("teletype"))
+ )
+}
+
+#endif
diff --git a/tools/quickbook/src/post_process.cpp b/tools/quickbook/src/post_process.cpp
new file mode 100644
index 0000000000..fac6c13dfa
--- /dev/null
+++ b/tools/quickbook/src/post_process.cpp
@@ -0,0 +1,457 @@
+/*=============================================================================
+ Copyright (c) 2005 2006 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "post_process.hpp"
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/bind.hpp>
+#include <set>
+#include <stack>
+#include <cctype>
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+ typedef std::string::const_iterator iter_type;
+
+ struct printer
+ {
+ printer(std::string& out, int& current_indent, int linewidth)
+ : prev(0), out(out), current_indent(current_indent) , column(0)
+ , in_string(false), linewidth(linewidth) {}
+
+ void indent()
+ {
+ BOOST_ASSERT(current_indent >= 0); // this should not happen!
+ for (int i = 0; i < current_indent; ++i)
+ out += ' ';
+ column = current_indent;
+ }
+
+ void trim_spaces()
+ {
+ out.erase(out.find_last_not_of(' ')+1); // trim trailing spaces
+ }
+
+ void break_line()
+ {
+ trim_spaces();
+ out += '\n';
+ indent();
+ }
+
+ bool line_is_empty() const
+ {
+ for (iter_type i = out.end()-(column-current_indent); i != out.end(); ++i)
+ {
+ if (*i != ' ')
+ return false;
+ }
+ return true;
+ }
+
+ void align_indent()
+ {
+ // make sure we are at the proper indent position
+ if (column != current_indent)
+ {
+ if (column > current_indent)
+ {
+ if (line_is_empty())
+ {
+ // trim just enough trailing spaces down to current_indent position
+ out.erase(out.end()-(column-current_indent), out.end());
+ column = current_indent;
+ }
+ else
+ {
+ // nope, line is not empty. do a hard CR
+ break_line();
+ }
+ }
+ else
+ {
+ // will this happen? (i.e. column <= current_indent)
+ while (column != current_indent)
+ {
+ out += ' ';
+ ++column;
+ }
+ }
+ }
+ }
+
+ void print(char ch)
+ {
+ // Print a char. Attempt to break the line if we are exceeding
+ // the target linewidth. The linewidth is not an absolute limit.
+ // There are many cases where a line will exceed the linewidth
+ // and there is no way to properly break the line. Preformatted
+ // code that exceeds the linewidth are examples. We cannot break
+ // preformatted code. We shall not attempt to be very strict with
+ // line breaking. What's more important is to have a reproducable
+ // output (i.e. processing two logically equivalent xml files
+ // results in two lexically equivalent xml files). *** pretty
+ // formatting is a secondary goal ***
+
+ // Strings will occur only in tag attributes. Normal content
+ // will have &quot; instead. We shall deal only with tag
+ // attributes here.
+ if (ch == '"')
+ in_string = !in_string; // don't break strings!
+
+ if (!in_string && std::isspace(static_cast<unsigned char>(ch)))
+ {
+ // we can break spaces if they are not inside strings
+ if (!std::isspace(static_cast<unsigned char>(prev)))
+ {
+ if (column >= linewidth)
+ {
+ break_line();
+ if (column == 0 && ch == ' ')
+ {
+ ++column;
+ out += ' ';
+ }
+ }
+ else
+ {
+ ++column;
+ out += ' ';
+ }
+ }
+ }
+ else
+ {
+ // we can break tag boundaries and stuff after
+ // delimiters if they are not inside strings
+ // and *only-if* the preceding char is a space
+ if (!in_string
+ && column >= linewidth
+ && (ch == '<' && std::isspace(static_cast<unsigned char>(prev))))
+ break_line();
+ out += ch;
+ ++column;
+ }
+
+ prev = ch;
+ }
+
+ void
+ print(iter_type f, iter_type l)
+ {
+ for (iter_type i = f; i != l; ++i)
+ print(*i);
+ }
+
+ void
+ print_tag(iter_type f, iter_type l, bool is_flow_tag)
+ {
+ if (is_flow_tag)
+ {
+ print(f, l);
+ }
+ else
+ {
+ // This is not a flow tag, so, we're going to do a
+ // carriage return anyway. Let us remove extra right
+ // spaces.
+ std::string str(f, l);
+ BOOST_ASSERT(f != l); // this should not happen
+ iter_type i = str.end();
+ while (i != str.begin() && std::isspace(static_cast<unsigned char>(*(i-1))))
+ --i;
+ print(str.begin(), i);
+ }
+ }
+
+ char prev;
+ std::string& out;
+ int& current_indent;
+ int column;
+ bool in_string;
+ int linewidth;
+ };
+
+ char const* block_tags_[] =
+ {
+ "author"
+ , "blockquote"
+ , "bridgehead"
+ , "callout"
+ , "calloutlist"
+ , "caution"
+ , "copyright"
+ , "entry"
+ , "important"
+ , "informaltable"
+ , "itemizedlist"
+ , "legalnotice"
+ , "listitem"
+ , "note"
+ , "orderedlist"
+ , "para"
+ , "row"
+ , "section"
+ , "simpara"
+ , "table"
+ , "tbody"
+ , "textobject"
+ , "tgroup"
+ , "thead"
+ , "tip"
+ , "variablelist"
+ , "varlistentry"
+ , "warning"
+ , "xml"
+ , "xi:include"
+ };
+
+ char const* doc_types_[] =
+ {
+ "book"
+ , "article"
+ , "library"
+ , "chapter"
+ , "part"
+ , "appendix"
+ , "preface"
+ , "qandadiv"
+ , "qandaset"
+ , "reference"
+ , "set"
+ };
+
+ struct tidy_compiler
+ {
+ tidy_compiler(std::string& out, int linewidth)
+ : out(out), current_indent(0), printer_(out, current_indent, linewidth)
+ {
+ static int const n_block_tags = sizeof(block_tags_)/sizeof(char const*);
+ for (int i = 0; i != n_block_tags; ++i)
+ {
+ block_tags.insert(block_tags_[i]);
+ }
+
+ static int const n_doc_types = sizeof(doc_types_)/sizeof(char const*);
+ for (int i = 0; i != n_doc_types; ++i)
+ {
+ block_tags.insert(doc_types_[i]);
+ block_tags.insert(doc_types_[i] + std::string("info"));
+ block_tags.insert(doc_types_[i] + std::string("purpose"));
+ }
+ }
+
+ bool is_flow_tag(std::string const& tag)
+ {
+ return block_tags.find(tag) == block_tags.end();
+ }
+
+ std::set<std::string> block_tags;
+ std::stack<std::string> tags;
+ std::string& out;
+ int current_indent;
+ printer printer_;
+ std::string current_tag;
+ };
+
+ struct tidy_grammar : cl::grammar<tidy_grammar>
+ {
+ tidy_grammar(tidy_compiler& state, int indent)
+ : state(state), indent(indent) {}
+
+ template <typename Scanner>
+ struct definition
+ {
+ definition(tidy_grammar const& self)
+ {
+ tag = (cl::lexeme_d[+(cl::alpha_p | '_' | ':')]) [boost::bind(&tidy_grammar::do_tag, &self, _1, _2)];
+
+ code =
+ "<programlisting>"
+ >> *(cl::anychar_p - "</programlisting>")
+ >> "</programlisting>"
+ ;
+
+ // What's the business of cl::lexeme_d['>' >> *cl::space_p]; ?
+ // It is there to preserve the space after the tag that is
+ // otherwise consumed by the cl::space_p skipper.
+
+ escape =
+ cl::str_p("<!--quickbook-escape-prefix-->") >>
+ (*(cl::anychar_p - cl::str_p("<!--quickbook-escape-postfix-->")))
+ [
+ boost::bind(&tidy_grammar::do_escape, &self, _1, _2)
+ ]
+ >> cl::lexeme_d
+ [
+ cl::str_p("<!--quickbook-escape-postfix-->") >>
+ (*cl::space_p)
+ [
+ boost::bind(&tidy_grammar::do_escape_post, &self, _1, _2)
+ ]
+ ]
+ ;
+
+ start_tag = '<' >> tag >> *(cl::anychar_p - '>') >> cl::lexeme_d['>' >> *cl::space_p];
+ start_end_tag =
+ '<' >> tag >> *(cl::anychar_p - ("/>" | cl::ch_p('>'))) >> cl::lexeme_d["/>" >> *cl::space_p]
+ | "<?" >> tag >> *(cl::anychar_p - '?') >> cl::lexeme_d["?>" >> *cl::space_p]
+ | "<!--" >> *(cl::anychar_p - "-->") >> cl::lexeme_d["-->" >> *cl::space_p]
+ | "<!" >> tag >> *(cl::anychar_p - '>') >> cl::lexeme_d['>' >> *cl::space_p]
+ ;
+ content = cl::lexeme_d[ +(cl::anychar_p - '<') ];
+ end_tag = "</" >> +(cl::anychar_p - '>') >> cl::lexeme_d['>' >> *cl::space_p];
+
+ markup =
+ escape
+ | code [boost::bind(&tidy_grammar::do_code, &self, _1, _2)]
+ | start_end_tag [boost::bind(&tidy_grammar::do_start_end_tag, &self, _1, _2)]
+ | start_tag [boost::bind(&tidy_grammar::do_start_tag, &self, _1, _2)]
+ | end_tag [boost::bind(&tidy_grammar::do_end_tag, &self, _1, _2)]
+ | content [boost::bind(&tidy_grammar::do_content, &self, _1, _2)]
+ ;
+
+ tidy = +markup;
+ }
+
+ cl::rule<Scanner> const&
+ start() { return tidy; }
+
+ cl::rule<Scanner>
+ tidy, tag, start_tag, start_end_tag,
+ content, end_tag, markup, code, escape;
+ };
+
+ void do_escape_post(iter_type f, iter_type l) const
+ {
+ for (iter_type i = f; i != l; ++i)
+ state.out += *i;
+ }
+
+ void do_escape(iter_type f, iter_type l) const
+ {
+ while (f != l && std::isspace(*f))
+ ++f;
+ for (iter_type i = f; i != l; ++i)
+ state.out += *i;
+ }
+
+ void do_code(iter_type f, iter_type l) const
+ {
+ state.printer_.trim_spaces();
+ if (state.out[state.out.size() - 1] != '\n')
+ state.out += '\n';
+ // print the string taking care of line
+ // ending CR/LF platform issues
+ for (iter_type i = f; i != l; ++i)
+ {
+ if (*i == '\n')
+ {
+ state.printer_.trim_spaces();
+ state.out += '\n';
+ ++i;
+ if (i != l && *i != '\r')
+ state.out += *i;
+ }
+ else if (*i == '\r')
+ {
+ state.printer_.trim_spaces();
+ state.out += '\n';
+ ++i;
+ if (i != l && *i != '\n')
+ state.out += *i;
+ }
+ else
+ {
+ state.out += *i;
+ }
+ }
+ state.out += '\n';
+ state.printer_.indent();
+ }
+
+ void do_tag(iter_type f, iter_type l) const
+ {
+ state.current_tag = std::string(f, l);
+ }
+
+ void do_start_end_tag(iter_type f, iter_type l) const
+ {
+ bool is_flow_tag = state.is_flow_tag(state.current_tag);
+ if (!is_flow_tag)
+ state.printer_.align_indent();
+ state.printer_.print_tag(f, l, is_flow_tag);
+ if (!is_flow_tag)
+ state.printer_.break_line();
+ }
+
+ void do_start_tag(iter_type f, iter_type l) const
+ {
+ state.tags.push(state.current_tag);
+ bool is_flow_tag = state.is_flow_tag(state.current_tag);
+ if (!is_flow_tag)
+ state.printer_.align_indent();
+ state.printer_.print_tag(f, l, is_flow_tag);
+ if (!is_flow_tag)
+ {
+ state.current_indent += indent;
+ state.printer_.break_line();
+ }
+ }
+
+ void do_content(iter_type f, iter_type l) const
+ {
+ state.printer_.print(f, l);
+ }
+
+ void do_end_tag(iter_type f, iter_type l) const
+ {
+ if (state.tags.empty())
+ throw quickbook::post_process_failure("Mismatched tags.");
+
+ bool is_flow_tag = state.is_flow_tag(state.tags.top());
+ if (!is_flow_tag)
+ {
+ state.current_indent -= indent;
+ state.printer_.align_indent();
+ }
+ state.printer_.print_tag(f, l, is_flow_tag);
+ if (!is_flow_tag)
+ state.printer_.break_line();
+ state.tags.pop();
+ }
+
+ tidy_compiler& state;
+ int indent;
+ };
+
+ std::string post_process(
+ std::string const& in
+ , int indent
+ , int linewidth)
+ {
+ if (indent == -1)
+ indent = 2; // set default to 2
+ if (linewidth == -1)
+ linewidth = 80; // set default to 80
+
+ std::string tidy;
+ tidy_compiler state(tidy, linewidth);
+ tidy_grammar g(state, indent);
+ cl::parse_info<iter_type> r = parse(in.begin(), in.end(), g, cl::space_p);
+ if (r.full)
+ {
+ return tidy;
+ }
+ else
+ {
+ throw quickbook::post_process_failure("Post Processing Failed.");
+ }
+ }
+}
+
diff --git a/tools/quickbook/src/post_process.hpp b/tools/quickbook/src/post_process.hpp
new file mode 100644
index 0000000000..81f282b7a6
--- /dev/null
+++ b/tools/quickbook/src/post_process.hpp
@@ -0,0 +1,31 @@
+/*=============================================================================
+ Copyright (c) 2005 2006 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP
+
+#include <string>
+#include <stdexcept>
+
+namespace quickbook
+{
+ std::string post_process(
+ std::string const& in
+ , int indent = -1
+ , int linewidth = -1);
+
+ struct post_process_failure : public std::runtime_error
+ {
+ public:
+ explicit post_process_failure(std::string const& error)
+ : std::runtime_error(error) {}
+ };
+}
+
+#endif // BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP
+
diff --git a/tools/quickbook/src/quickbook.cpp b/tools/quickbook/src/quickbook.cpp
new file mode 100644
index 0000000000..fc197b58c7
--- /dev/null
+++ b/tools/quickbook/src/quickbook.cpp
@@ -0,0 +1,476 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "grammar.hpp"
+#include "quickbook.hpp"
+#include "actions_class.hpp"
+#include "post_process.hpp"
+#include "utils.hpp"
+#include "files.hpp"
+#include "input_path.hpp"
+#include "id_manager.hpp"
+#include <boost/program_options.hpp>
+#include <boost/filesystem/v3/path.hpp>
+#include <boost/filesystem/v3/operations.hpp>
+#include <boost/filesystem/v3/fstream.hpp>
+#include <boost/range/algorithm.hpp>
+#include <boost/ref.hpp>
+#include <boost/version.hpp>
+
+#include <stdexcept>
+#include <vector>
+#include <iterator>
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <shellapi.h>
+#endif
+
+#if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
+#pragma warning(disable:4355)
+#endif
+
+#define QUICKBOOK_VERSION "Quickbook Version 1.5.7"
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+ namespace fs = boost::filesystem;
+
+ tm* current_time; // the current time
+ tm* current_gm_time; // the current UTC time
+ bool debug_mode; // for quickbook developers only
+ bool self_linked_headers;
+ bool ms_errors = false; // output errors/warnings as if for VS
+ std::vector<fs::path> include_path;
+ std::vector<std::string> preset_defines;
+ fs::path image_location;
+
+ static void set_macros(actions& actor)
+ {
+ for(std::vector<std::string>::const_iterator
+ it = preset_defines.begin(),
+ end = preset_defines.end();
+ it != end; ++it)
+ {
+ parse_iterator first(it->begin());
+ parse_iterator last(it->end());
+
+ cl::parse_info<parse_iterator> info =
+ cl::parse(first, last, actor.grammar().command_line_macro);
+
+ if (!info.full) {
+ detail::outerr()
+ << "Error parsing command line definition: '"
+ << detail::utf8(*it)
+ << "'"
+ << std::endl;
+ ++actor.error_count;
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // Parse a file
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ void parse_file(actions& actor, value include_doc_id, bool nested_file)
+ {
+ parse_iterator first(actor.current_file->source.begin());
+ parse_iterator last(actor.current_file->source.end());
+
+ cl::parse_info<parse_iterator> info = cl::parse(first, last, actor.grammar().doc_info);
+ assert(info.hit);
+
+ if (!actor.error_count)
+ {
+ parse_iterator pos = info.stop;
+ std::string doc_type = pre(actor, pos, include_doc_id, nested_file);
+
+ info = cl::parse(info.hit ? info.stop : first, last, actor.grammar().block);
+
+ post(actor, doc_type);
+
+ if (!info.full)
+ {
+ file_position const& pos = actor.current_file->position_of(info.stop.base());
+ detail::outerr(actor.current_file->path, pos.line)
+ << "Syntax Error near column " << pos.column << ".\n";
+ ++actor.error_count;
+ }
+ }
+ }
+
+ static int
+ parse_document(
+ fs::path const& filein_
+ , fs::path const& fileout_
+ , fs::path const& xinclude_base_
+ , int indent
+ , int linewidth
+ , bool pretty_print)
+ {
+ string_stream buffer;
+ id_manager ids;
+
+ int result = 0;
+
+ try {
+ actions actor(filein_, xinclude_base_, buffer, ids);
+ set_macros(actor);
+
+ if (actor.error_count == 0) {
+ actor.current_file = load(filein_); // Throws load_error
+
+ parse_file(actor);
+
+ if(actor.error_count) {
+ detail::outerr()
+ << "Error count: " << actor.error_count << ".\n";
+ }
+ }
+
+ result = actor.error_count ? 1 : 0;
+ }
+ catch (load_error& e) {
+ detail::outerr(filein_) << detail::utf8(e.what()) << std::endl;
+ result = 1;
+ }
+
+ if (result == 0)
+ {
+ std::string stage2 = ids.replace_placeholders(buffer.str());
+
+ fs::ofstream fileout(fileout_);
+
+ if (fileout.fail()) {
+ ::quickbook::detail::outerr()
+ << "Error opening output file "
+ << fileout_
+ << std::endl;
+
+ return 1;
+ }
+
+ if (pretty_print)
+ {
+ try
+ {
+ fileout << post_process(stage2, indent, linewidth);
+ }
+ catch (quickbook::post_process_failure&)
+ {
+ // fallback!
+ ::quickbook::detail::outerr()
+ << "Post Processing Failed."
+ << std::endl;
+ fileout << stage2;
+ return 1;
+ }
+ }
+ else
+ {
+ fileout << stage2;
+ }
+
+ if (fileout.fail()) {
+ ::quickbook::detail::outerr()
+ << "Error writing to output file "
+ << fileout_
+ << std::endl;
+
+ return 1;
+ }
+ }
+
+ return result;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Main program
+//
+///////////////////////////////////////////////////////////////////////////
+int
+main(int argc, char* argv[])
+{
+ try
+ {
+ namespace fs = boost::filesystem;
+ namespace po = boost::program_options;
+
+ using boost::program_options::options_description;
+ using boost::program_options::variables_map;
+ using boost::program_options::store;
+ using boost::program_options::parse_command_line;
+ using boost::program_options::wcommand_line_parser;
+ using boost::program_options::command_line_parser;
+ using boost::program_options::notify;
+ using boost::program_options::positional_options_description;
+
+ using quickbook::detail::input_string;
+
+ // First thing, the filesystem should record the current working directory.
+ fs::initial_path<fs::path>();
+
+ // Various initialisation methods
+ quickbook::detail::initialise_output();
+ quickbook::detail::initialise_markups();
+
+ options_description desc("Allowed options");
+ options_description hidden("Hidden options");
+ options_description all("All options");
+
+#if QUICKBOOK_WIDE_PATHS
+#define PO_VALUE po::wvalue
+#else
+#define PO_VALUE po::value
+#endif
+
+ desc.add_options()
+ ("help", "produce help message")
+ ("version", "print version string")
+ ("no-pretty-print", "disable XML pretty printing")
+ ("no-self-linked-headers", "stop headers linking to themselves")
+ ("indent", PO_VALUE<int>(), "indent spaces")
+ ("linewidth", PO_VALUE<int>(), "line width")
+ ("input-file", PO_VALUE<input_string>(), "input file")
+ ("output-file", PO_VALUE<input_string>(), "output file")
+ ("debug", "debug mode (for developers)")
+ ("ms-errors", "use Microsoft Visual Studio style error & warn message format")
+ ("include-path,I", PO_VALUE< std::vector<input_string> >(), "include path")
+ ("define,D", PO_VALUE< std::vector<input_string> >(), "define macro")
+ ("image-location", PO_VALUE<input_string>(), "image location")
+ ;
+
+ hidden.add_options()
+ ("expect-errors",
+ "Succeed if the input file contains a correctly handled "
+ "error, fail otherwise.")
+ ("xinclude-base", PO_VALUE<input_string>(),
+ "Generate xincludes as if generating for this target "
+ "directory.")
+ ;
+
+ all.add(desc).add(hidden);
+
+ positional_options_description p;
+ p.add("input-file", -1);
+
+ variables_map vm;
+ int indent = -1;
+ int linewidth = -1;
+ bool pretty_print = true;
+
+#if QUICKBOOK_WIDE_PATHS
+ quickbook::ignore_variable(&argc);
+ quickbook::ignore_variable(&argv);
+
+ int wide_argc;
+ LPWSTR* wide_argv = CommandLineToArgvW(GetCommandLineW(), &wide_argc);
+ if (!wide_argv)
+ {
+ quickbook::detail::outerr() << "Error getting argument values." << std::endl;
+ return 1;
+ }
+
+ store(
+ wcommand_line_parser(wide_argc, wide_argv)
+ .options(all)
+ .positional(p)
+ .run(), vm);
+
+ LocalFree(wide_argv);
+#else
+ store(command_line_parser(argc, argv)
+ .options(all)
+ .positional(p)
+ .run(), vm);
+#endif
+
+ notify(vm);
+
+ bool expect_errors = vm.count("expect-errors");
+ int error_count = 0;
+
+ if (vm.count("help"))
+ {
+ std::ostringstream description_text;
+ description_text << desc;
+
+ quickbook::detail::out()
+ << quickbook::detail::utf8(description_text.str()) << "\n";
+
+ return 0;
+ }
+
+ if (vm.count("version"))
+ {
+ std::string boost_version = BOOST_LIB_VERSION;
+ boost::replace(boost_version, '_', '.');
+
+ quickbook::detail::out()
+ << QUICKBOOK_VERSION
+ << " (Boost "
+ << quickbook::detail::utf8(boost_version)
+ << ")"
+ << std::endl;
+ return 0;
+ }
+
+ if (vm.count("ms-errors"))
+ quickbook::ms_errors = true;
+
+ if (vm.count("no-pretty-print"))
+ pretty_print = false;
+
+ quickbook::self_linked_headers = !vm.count("no-self-link-headers");
+
+ if (vm.count("indent"))
+ indent = vm["indent"].as<int>();
+
+ if (vm.count("linewidth"))
+ linewidth = vm["linewidth"].as<int>();
+
+ if (vm.count("debug"))
+ {
+ static tm timeinfo;
+ timeinfo.tm_year = 2000 - 1900;
+ timeinfo.tm_mon = 12 - 1;
+ timeinfo.tm_mday = 20;
+ timeinfo.tm_hour = 12;
+ timeinfo.tm_min = 0;
+ timeinfo.tm_sec = 0;
+ timeinfo.tm_isdst = -1;
+ mktime(&timeinfo);
+ quickbook::current_time = &timeinfo;
+ quickbook::current_gm_time = &timeinfo;
+ quickbook::debug_mode = true;
+ }
+ else
+ {
+ time_t t = std::time(0);
+ static tm lt = *localtime(&t);
+ static tm gmt = *gmtime(&t);
+ quickbook::current_time = &lt;
+ quickbook::current_gm_time = &gmt;
+ quickbook::debug_mode = false;
+ }
+
+ quickbook::include_path.clear();
+ if (vm.count("include-path"))
+ {
+ boost::transform(
+ vm["include-path"].as<std::vector<input_string> >(),
+ std::back_inserter(quickbook::include_path),
+ quickbook::detail::input_to_path);
+ }
+
+ quickbook::preset_defines.clear();
+ if (vm.count("define"))
+ {
+ boost::transform(
+ vm["define"].as<std::vector<input_string> >(),
+ std::back_inserter(quickbook::preset_defines),
+ quickbook::detail::input_to_utf8);
+ }
+
+ if (vm.count("input-file"))
+ {
+ fs::path filein = quickbook::detail::input_to_path(
+ vm["input-file"].as<input_string>());
+ fs::path fileout;
+
+ if (vm.count("output-file"))
+ {
+ fileout = quickbook::detail::input_to_path(
+ vm["output-file"].as<input_string>());
+ }
+ else
+ {
+ fileout = filein;
+ fileout.replace_extension(".xml");
+ }
+
+ fs::path xinclude_base;
+ if (vm.count("xinclude-base"))
+ {
+ xinclude_base = quickbook::detail::input_to_path(
+ vm["xinclude-base"].as<input_string>());
+ }
+ else
+ {
+ xinclude_base = fileout.parent_path();
+ if (xinclude_base.empty())
+ xinclude_base = ".";
+ }
+
+ if (!fs::is_directory(xinclude_base))
+ {
+ quickbook::detail::outerr()
+ << (vm.count("xinclude-base") ?
+ "xinclude-base is not a directory" :
+ "parent directory not found for output file");
+ ++error_count;
+ }
+
+ if (vm.count("image-location"))
+ {
+ quickbook::image_location = quickbook::detail::input_to_path(
+ vm["image-location"].as<input_string>());
+ }
+ else
+ {
+ quickbook::image_location = filein.parent_path() / "html";
+ }
+
+ quickbook::detail::out() << "Generating Output File: "
+ << quickbook::detail::path_to_stream(fileout)
+ << std::endl;
+
+ if (!error_count)
+ error_count += quickbook::parse_document(filein, fileout, xinclude_base, indent, linewidth, pretty_print);
+
+ if (expect_errors)
+ {
+ if (!error_count) quickbook::detail::outerr() << "No errors detected for --expect-errors." << std::endl;
+ return !error_count;
+ }
+ else
+ {
+ return error_count;
+ }
+ }
+ else
+ {
+ std::ostringstream description_text;
+ description_text << desc;
+
+ quickbook::detail::outerr() << "No filename given\n\n"
+ << quickbook::detail::utf8(description_text.str()) << std::endl;
+ return 1;
+ }
+ }
+
+ catch(std::exception& e)
+ {
+ quickbook::detail::outerr() << quickbook::detail::utf8(e.what()) << "\n";
+ return 1;
+ }
+
+ catch(...)
+ {
+ quickbook::detail::outerr() << "Exception of unknown type caught\n";
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/tools/quickbook/src/quickbook.hpp b/tools/quickbook/src/quickbook.hpp
new file mode 100644
index 0000000000..265bc7ee53
--- /dev/null
+++ b/tools/quickbook/src/quickbook.hpp
@@ -0,0 +1,46 @@
+/*=============================================================================
+ Copyright (c) 2009 Daniel James
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_SPIRIT_QUICKBOOK_QUICKBOOK_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_QUICKBOOK_HPP
+
+#include <time.h>
+#include <vector>
+#include <string>
+#include <boost/filesystem/v3/path.hpp>
+#include "fwd.hpp"
+#include "values.hpp"
+
+namespace quickbook
+{
+ namespace fs = boost::filesystem;
+
+ extern tm* current_time; // the current time
+ extern tm* current_gm_time; // the current UTC time
+ extern bool debug_mode;
+ extern bool self_linked_headers;
+ extern std::vector<fs::path> include_path;
+ extern std::vector<std::string> preset_defines;
+ extern fs::path image_location;
+
+ void parse_file(actions& actor,
+ value include_doc_id = value(),
+ bool nested_file = false);
+ // Some initialisation methods
+ //
+ // Declared here to avoid including other headers
+ namespace detail
+ {
+ void initialise_markups();
+ }
+}
+
+#endif
diff --git a/tools/quickbook/src/scoped.hpp b/tools/quickbook/src/scoped.hpp
new file mode 100644
index 0000000000..4acbb42816
--- /dev/null
+++ b/tools/quickbook/src/scoped.hpp
@@ -0,0 +1,32 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_QUICKBOOK_SCOPED_HPP)
+#define BOOST_QUICKBOOK_SCOPED_HPP
+
+#include <cassert>
+
+namespace quickbook {
+
+ struct scoped_action_base
+ {
+ bool start() { return true; }
+ template <typename Iterator>
+ void success(Iterator, Iterator) {}
+ void failure() {}
+ void cleanup() {}
+
+ template <typename ResultT, typename ScannerT>
+ bool result(ResultT result, ScannerT const&)
+ {
+ return result;
+ }
+ };
+}
+
+#endif
diff --git a/tools/quickbook/src/string_ref.cpp b/tools/quickbook/src/string_ref.cpp
new file mode 100644
index 0000000000..b4775576da
--- /dev/null
+++ b/tools/quickbook/src/string_ref.cpp
@@ -0,0 +1,30 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "string_ref.hpp"
+#include <boost/range/algorithm/equal.hpp>
+#include <boost/range/algorithm/lexicographical_compare.hpp>
+#include <ostream>
+
+namespace quickbook
+{
+ bool operator==(string_ref const& x, string_ref const& y)
+ {
+ return boost::equal(x, y);
+ }
+
+ bool operator<(string_ref const& x, string_ref const& y)
+ {
+ return boost::lexicographical_compare(x, y);
+ }
+
+ std::ostream& operator<<(std::ostream& out, string_ref const& x)
+ {
+ return out.write(&*x.begin(), x.end() - x.begin());
+ }
+}
diff --git a/tools/quickbook/src/string_ref.hpp b/tools/quickbook/src/string_ref.hpp
new file mode 100644
index 0000000000..b712006790
--- /dev/null
+++ b/tools/quickbook/src/string_ref.hpp
@@ -0,0 +1,78 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_QUICKBOOK_STRING_REF_HPP)
+#define BOOST_QUICKBOOK_STRING_REF_HPP
+
+#include <boost/operators.hpp>
+#include <string>
+#include <iosfwd>
+
+namespace quickbook
+{
+ struct string_ref
+ : boost::less_than_comparable<string_ref,
+ boost::less_than_comparable<string_ref, std::string,
+ boost::equality_comparable<string_ref,
+ boost::equality_comparable<string_ref, std::string> > > >
+ {
+ public:
+ typedef std::string::const_iterator iterator;
+ typedef std::string::const_iterator const_iterator;
+
+ private:
+ iterator begin_, end_;
+
+ public:
+ string_ref() : begin_(), end_() {}
+
+ explicit string_ref(iterator b, iterator e)
+ : begin_(b), end_(e) {}
+
+ explicit string_ref(std::string const& x)
+ : begin_(x.begin()), end_(x.end()) {}
+
+ operator std::string() const {
+ return std::string(begin_, end_);
+ }
+
+ iterator begin() const { return begin_; }
+ iterator end() const { return end_; }
+
+ std::size_t size() const
+ {
+ return static_cast<std::size_t>(end_ - begin_);
+ }
+
+ bool empty() const
+ {
+ return begin_ == end_;
+ }
+ };
+
+ bool operator==(string_ref const& x, string_ref const& y);
+ bool operator<(string_ref const& x, string_ref const& y);
+ std::ostream& operator<<(std::ostream&, string_ref const& x);
+
+ inline bool operator==(string_ref const& x, std::string const& y)
+ {
+ return x == string_ref(y);
+ }
+
+ inline bool operator<(string_ref const& x, std::string const& y)
+ {
+ return x < string_ref(y);
+ }
+
+ inline bool operator>(string_ref const& x, std::string const& y)
+ {
+ return x > string_ref(y);
+ }
+}
+
+#endif
diff --git a/tools/quickbook/src/symbols.hpp b/tools/quickbook/src/symbols.hpp
new file mode 100644
index 0000000000..a514f37747
--- /dev/null
+++ b/tools/quickbook/src/symbols.hpp
@@ -0,0 +1,213 @@
+/*=============================================================================
+ Copyright (c) 2001-2003 Joel de Guzman
+ Copyright (c) 2011 Daniel James
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#ifndef QUICKBOOK_SYMBOLS_IPP
+#define QUICKBOOK_SYMBOLS_IPP
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/home/classic/symbols.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+namespace quickbook
+{
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// tst class
+//
+// This it the Ternary Search Tree from
+// <boost/spirit/home/classic/symbols/impl/tst.ipp> adapted to be cheap
+// to copy.
+//
+// Ternary Search Tree implementation. The data structure is faster than
+// hashing for many typical search problems especially when the search
+// interface is iterator based. Searching for a string of length k in a
+// ternary search tree with n strings will require at most O(log n+k)
+// character comparisons. TSTs are many times faster than hash tables
+// for unsuccessful searches since mismatches are discovered earlier
+// after examining only a few characters. Hash tables always examine an
+// entire key when searching.
+//
+// For details see http://www.cs.princeton.edu/~rs/strings/.
+//
+// *** This is a low level class and is
+// not meant for public consumption ***
+//
+///////////////////////////////////////////////////////////////////////////////
+
+ template <typename T, typename CharT>
+ struct tst_node
+ {
+ tst_node(CharT value_)
+ : reference_count(0)
+ , left()
+ , middle()
+ , right()
+ , data()
+ , value(value_)
+ {
+ }
+
+ tst_node(tst_node const& other)
+ : reference_count(0)
+ , left(other.left)
+ , middle(other.middle)
+ , right(other.right)
+ , data(other.data ? new T(*other.data) : 0)
+ , value(other.value)
+ {
+ }
+
+ // If you fancy a slight improvement in memory use,
+ // reference_count + value could probably be packed
+ // in the space for a single int.
+ int reference_count;
+ boost::intrusive_ptr<tst_node> left;
+ boost::intrusive_ptr<tst_node> middle;
+ boost::intrusive_ptr<tst_node> right;
+ boost::scoped_ptr<T> data;
+ CharT value;
+ private:
+ tst_node& operator=(tst_node const&);
+ };
+
+ template <typename T, typename CharT>
+ void intrusive_ptr_add_ref(tst_node<T, CharT>* ptr)
+ { ++ptr->reference_count; }
+
+ template <typename T, typename CharT>
+ void intrusive_ptr_release(tst_node<T, CharT>* ptr)
+ { if(--ptr->reference_count == 0) delete ptr; }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename T, typename CharT>
+ class tst
+ {
+ typedef tst_node<T, CharT> node_t;
+ typedef boost::intrusive_ptr<node_t> node_ptr;
+ node_ptr root;
+
+ public:
+
+ struct search_info
+ {
+ T* data;
+ std::size_t length;
+ };
+
+ void swap(tst& other)
+ {
+ root.swap(other.root);
+ }
+
+ // Adds symbol to ternary search tree.
+ // If it already exists, then replace it with new value.
+ //
+ // pre: first != last
+ template <typename IteratorT>
+ T* add(IteratorT first, IteratorT const& last, T const& data)
+ {
+ assert (first != last);
+
+ node_ptr* np = &root;
+ CharT ch = *first;
+
+ for(;;)
+ {
+ if (!*np)
+ {
+ *np = new node_t(ch);
+ }
+ else if ((*np)->reference_count > 1)
+ {
+ *np = new node_t(**np);
+ }
+
+ if (ch < (*np)->value)
+ {
+ np = &(*np)->left;
+ }
+ else if (ch == (*np)->value)
+ {
+ ++first;
+ if (first == last) break;
+ ch = *first;
+ np = &(*np)->middle;
+ }
+ else
+ {
+ np = &(*np)->right;
+ }
+ }
+
+ boost::scoped_ptr<T> new_data(new T(data));
+ boost::swap((*np)->data, new_data);
+ return (*np)->data.get();
+ }
+
+ template <typename ScannerT>
+ search_info find(ScannerT const& scan) const
+ {
+ search_info result = { 0, 0 };
+ if (scan.at_end()) {
+ return result;
+ }
+
+ typedef typename ScannerT::iterator_t iterator_t;
+ node_ptr np = root;
+ CharT ch = *scan;
+ iterator_t latest = scan.first;
+ std::size_t length = 0;
+
+ while (np)
+ {
+ if (ch < np->value) // => go left!
+ {
+ np = np->left;
+ }
+ else if (ch == np->value) // => go middle!
+ {
+ ++scan;
+ ++length;
+
+ // Found a potential match.
+ if (np->data.get())
+ {
+ result.data = np->data.get();
+ result.length = length;
+ latest = scan.first;
+ }
+
+ if (scan.at_end()) break;
+ ch = *scan;
+ np = np->middle;
+ }
+ else // (ch > np->value) => go right!
+ {
+ np = np->right;
+ }
+ }
+
+ scan.first = latest;
+ return result;
+ }
+ };
+
+ typedef boost::spirit::classic::symbols<
+ std::string,
+ char,
+ quickbook::tst<std::string, char>
+ > string_symbols;
+} // namespace quickbook
+
+#endif
diff --git a/tools/quickbook/src/syntax_highlight.cpp b/tools/quickbook/src/syntax_highlight.cpp
new file mode 100644
index 0000000000..2e790f5bb1
--- /dev/null
+++ b/tools/quickbook/src/syntax_highlight.cpp
@@ -0,0 +1,569 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_confix.hpp>
+#include <boost/spirit/include/classic_chset.hpp>
+#include <boost/spirit/include/classic_symbols.hpp>
+#include <boost/spirit/include/classic_loops.hpp>
+#include "grammar.hpp"
+#include "grammar_impl.hpp" // Just for context stuff. Should move?
+#include "actions_class.hpp"
+#include "files.hpp"
+#include "input_path.hpp"
+
+namespace quickbook
+{
+ namespace cl = boost::spirit::classic;
+
+ // quickbook::actions is used in a few places here, as 'escape_actions'.
+ // It's named differently to distinguish it from the syntax highlighting
+ // actions, declared below.
+
+ // Syntax Highlight Actions
+
+ struct span
+ {
+ // Decorates c++ code fragments
+
+ span(char const* name, collector& out)
+ : name(name), out(out) {}
+
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ char const* name;
+ collector& out;
+ };
+
+ struct span_start
+ {
+ span_start(char const* name, collector& out)
+ : name(name), out(out) {}
+
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ char const* name;
+ collector& out;
+ };
+
+ struct span_end
+ {
+ span_end(collector& out)
+ : out(out) {}
+
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ collector& out;
+ };
+
+ struct unexpected_char
+ {
+ // Handles unexpected chars in c++ syntax
+
+ unexpected_char(
+ collector& out
+ , quickbook::actions& escape_actions)
+ : out(out)
+ , escape_actions(escape_actions) {}
+
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ collector& out;
+ quickbook::actions& escape_actions;
+ };
+
+ struct plain_char
+ {
+ // Prints a single plain char.
+ // Converts '<' to "&lt;"... etc See utils.hpp
+
+ plain_char(collector& out)
+ : out(out) {}
+
+ void operator()(char ch) const;
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ collector& out;
+ };
+
+ struct pre_escape_back
+ {
+ // Escapes back from code to quickbook (Pre)
+
+ pre_escape_back(actions& escape_actions)
+ : escape_actions(escape_actions) {}
+
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ actions& escape_actions;
+ };
+
+ struct post_escape_back
+ {
+ // Escapes back from code to quickbook (Post)
+
+ post_escape_back(collector& out, actions& escape_actions)
+ : out(out), escape_actions(escape_actions) {}
+
+ void operator()(parse_iterator first, parse_iterator last) const;
+
+ collector& out;
+ actions& escape_actions;
+ };
+
+ void span::operator()(parse_iterator first, parse_iterator last) const
+ {
+ out << "<phrase role=\"" << name << "\">";
+ while (first != last)
+ detail::print_char(*first++, out.get());
+ out << "</phrase>";
+ }
+
+ void span_start::operator()(parse_iterator first, parse_iterator last) const
+ {
+ out << "<phrase role=\"" << name << "\">";
+ while (first != last)
+ detail::print_char(*first++, out.get());
+ }
+
+ void span_end::operator()(parse_iterator first, parse_iterator last) const
+ {
+ while (first != last)
+ detail::print_char(*first++, out.get());
+ out << "</phrase>";
+ }
+
+ void unexpected_char::operator()(parse_iterator first, parse_iterator last) const
+ {
+ file_position const pos = escape_actions.current_file->position_of(first.base());
+
+ detail::outwarn(escape_actions.current_file->path, pos.line)
+ << "in column:" << pos.column
+ << ", unexpected character: " << detail::utf8(first, last)
+ << "\n";
+
+ // print out an unexpected character
+ out << "<phrase role=\"error\">";
+ while (first != last)
+ detail::print_char(*first++, out.get());
+ out << "</phrase>";
+ }
+
+ void plain_char::operator()(char ch) const
+ {
+ detail::print_char(ch, out.get());
+ }
+
+ void plain_char::operator()(parse_iterator first, parse_iterator last) const
+ {
+ while (first != last)
+ detail::print_char(*first++, out.get());
+ }
+
+ void pre_escape_back::operator()(parse_iterator, parse_iterator) const
+ {
+ escape_actions.phrase.push(); // save the stream
+ }
+
+ void post_escape_back::operator()(parse_iterator, parse_iterator) const
+ {
+ out << escape_actions.phrase.str();
+ escape_actions.phrase.pop(); // restore the stream
+ }
+
+ // Syntax
+
+ struct keywords_holder
+ {
+ cl::symbols<> cpp, python;
+
+ keywords_holder()
+ {
+ cpp
+ = "and_eq", "and", "asm", "auto", "bitand", "bitor",
+ "bool", "break", "case", "catch", "char", "class",
+ "compl", "const_cast", "const", "continue", "default",
+ "delete", "do", "double", "dynamic_cast", "else",
+ "enum", "explicit", "export", "extern", "false",
+ "float", "for", "friend", "goto", "if", "inline",
+ "int", "long", "mutable", "namespace", "new", "not_eq",
+ "not", "operator", "or_eq", "or", "private",
+ "protected", "public", "register", "reinterpret_cast",
+ "return", "short", "signed", "sizeof", "static",
+ "static_cast", "struct", "switch", "template", "this",
+ "throw", "true", "try", "typedef", "typeid",
+ "typename", "union", "unsigned", "using", "virtual",
+ "void", "volatile", "wchar_t", "while", "xor_eq", "xor"
+ ;
+
+ python
+ =
+ "and", "del", "for", "is", "raise",
+ "assert", "elif", "from", "lambda", "return",
+ "break", "else", "global", "not", "try",
+ "class", "except", "if", "or", "while",
+ "continue", "exec", "import", "pass", "yield",
+ "def", "finally", "in", "print",
+
+ // Technically "as" and "None" are not yet keywords (at Python
+ // 2.4). They are destined to become keywords, and we treat them
+ // as such for syntax highlighting purposes.
+
+ "as", "None"
+ ;
+ }
+ };
+
+ namespace {
+ keywords_holder keywords;
+ }
+
+ // Grammar for C++ highlighting
+ struct cpp_highlight
+ : public cl::grammar<cpp_highlight>
+ {
+ cpp_highlight(collector& out, actions& escape_actions)
+ : out(out), escape_actions(escape_actions) {}
+
+ template <typename Scanner>
+ struct definition
+ {
+ definition(cpp_highlight const& self)
+ : g(self.escape_actions.grammar())
+ {
+ program
+ =
+ *( (+cl::space_p) [plain_char(self.out)]
+ | macro
+ | escape
+ | preprocessor [span("preprocessor", self.out)]
+ | comment
+ | keyword [span("keyword", self.out)]
+ | identifier [span("identifier", self.out)]
+ | special [span("special", self.out)]
+ | string_ [span("string", self.out)]
+ | char_ [span("char", self.out)]
+ | number [span("number", self.out)]
+ | cl::repeat_p(1)[cl::anychar_p]
+ [unexpected_char(self.out, self.escape_actions)]
+ )
+ ;
+
+ macro =
+ // must not be followed by alpha or underscore
+ cl::eps_p(self.escape_actions.macro
+ >> (cl::eps_p - (cl::alpha_p | '_')))
+ >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)]
+ ;
+
+ escape =
+ cl::str_p("``") [pre_escape_back(self.escape_actions)]
+ >>
+ (
+ (
+ (
+ (+(cl::anychar_p - "``") >> cl::eps_p("``"))
+ & g.phrase
+ )
+ >> cl::str_p("``")
+ )
+ |
+ (
+ cl::eps_p [self.escape_actions.error]
+ >> *cl::anychar_p
+ )
+ ) [post_escape_back(self.out, self.escape_actions)]
+ ;
+
+ preprocessor
+ = '#' >> *cl::space_p >> ((cl::alpha_p | '_') >> *(cl::alnum_p | '_'))
+ ;
+
+ comment
+ = cl::str_p("//") [span_start("comment", self.out)]
+ >> *( escape
+ | (+(cl::anychar_p - (cl::eol_p | "``")))
+ [plain_char(self.out)]
+ )
+ >> cl::eps_p [span_end(self.out)]
+ | cl::str_p("/*") [span_start("comment", self.out)]
+ >> *( escape
+ | (+(cl::anychar_p - (cl::str_p("*/") | "``")))
+ [plain_char(self.out)]
+ )
+ >> (!cl::str_p("*/")) [span_end(self.out)]
+ ;
+
+ keyword
+ = keywords.cpp >> (cl::eps_p - (cl::alnum_p | '_'))
+ ; // make sure we recognize whole words only
+
+ special
+ = +cl::chset_p("~!%^&*()+={[}]:;,<.>?/|\\-")
+ ;
+
+ string_char = ('\\' >> cl::anychar_p) | (cl::anychar_p - '\\');
+
+ string_
+ = !cl::as_lower_d['l'] >> cl::confix_p('"', *string_char, '"')
+ ;
+
+ char_
+ = !cl::as_lower_d['l'] >> cl::confix_p('\'', *string_char, '\'')
+ ;
+
+ number
+ = (
+ cl::as_lower_d["0x"] >> cl::hex_p
+ | '0' >> cl::oct_p
+ | cl::real_p
+ )
+ >> *cl::as_lower_d[cl::chset_p("ldfu")]
+ ;
+
+ identifier
+ = (cl::alpha_p | '_') >> *(cl::alnum_p | '_')
+ ;
+ }
+
+ cl::rule<Scanner>
+ program, macro, preprocessor, comment, special, string_,
+ char_, number, identifier, keyword, escape,
+ string_char;
+
+ quickbook_grammar& g;
+
+ cl::rule<Scanner> const&
+ start() const { return program; }
+ };
+
+ collector& out;
+ actions& escape_actions;
+ };
+
+ // Grammar for Python highlighting
+ // See also: The Python Reference Manual
+ // http://docs.python.org/ref/ref.html
+ struct python_highlight
+ : public cl::grammar<python_highlight>
+ {
+ python_highlight(collector& out, actions& escape_actions)
+ : out(out), escape_actions(escape_actions) {}
+
+ template <typename Scanner>
+ struct definition
+ {
+ definition(python_highlight const& self)
+ : g(self.escape_actions.grammar())
+ {
+ program
+ =
+ *( (+cl::space_p) [plain_char(self.out)]
+ | macro
+ | escape
+ | comment
+ | keyword [span("keyword", self.out)]
+ | identifier [span("identifier", self.out)]
+ | special [span("special", self.out)]
+ | string_ [span("string", self.out)]
+ | number [span("number", self.out)]
+ | cl::repeat_p(1)[cl::anychar_p]
+ [unexpected_char(self.out, self.escape_actions)]
+ )
+ ;
+
+ macro =
+ // must not be followed by alpha or underscore
+ cl::eps_p(self.escape_actions.macro
+ >> (cl::eps_p - (cl::alpha_p | '_')))
+ >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)]
+ ;
+
+ escape =
+ cl::str_p("``") [pre_escape_back(self.escape_actions)]
+ >>
+ (
+ (
+ (
+ (+(cl::anychar_p - "``") >> cl::eps_p("``"))
+ & g.phrase
+ )
+ >> cl::str_p("``")
+ )
+ |
+ (
+ cl::eps_p [self.escape_actions.error]
+ >> *cl::anychar_p
+ )
+ ) [post_escape_back(self.out, self.escape_actions)]
+ ;
+
+ comment
+ = cl::str_p("#") [span_start("comment", self.out)]
+ >> *( escape
+ | (+(cl::anychar_p - (cl::eol_p | "``")))
+ [plain_char(self.out)]
+ )
+ >> cl::eps_p [span_end(self.out)]
+ ;
+
+ keyword
+ = keywords.python >> (cl::eps_p - (cl::alnum_p | '_'))
+ ; // make sure we recognize whole words only
+
+ special
+ = +cl::chset_p("~!%^&*()+={[}]:;,<.>/|\\-")
+ ;
+
+ string_prefix
+ = cl::as_lower_d[cl::str_p("u") >> ! cl::str_p("r")]
+ ;
+
+ string_
+ = ! string_prefix >> (long_string | short_string)
+ ;
+
+ string_char = ('\\' >> cl::anychar_p) | (cl::anychar_p - '\\');
+
+ short_string
+ = cl::confix_p('\'', * string_char, '\'') |
+ cl::confix_p('"', * string_char, '"')
+ ;
+
+ long_string
+ // Note: the "cl::str_p" on the next two lines work around
+ // an INTERNAL COMPILER ERROR when using VC7.1
+ = cl::confix_p(cl::str_p("'''"), * string_char, "'''") |
+ cl::confix_p(cl::str_p("\"\"\""), * string_char, "\"\"\"")
+ ;
+
+ number
+ = (
+ cl::as_lower_d["0x"] >> cl::hex_p
+ | '0' >> cl::oct_p
+ | cl::real_p
+ )
+ >> *cl::as_lower_d[cl::chset_p("lj")]
+ ;
+
+ identifier
+ = (cl::alpha_p | '_') >> *(cl::alnum_p | '_')
+ ;
+ }
+
+ cl::rule<Scanner>
+ program, macro, comment, special, string_, string_prefix,
+ short_string, long_string, number, identifier, keyword,
+ escape, string_char;
+
+ quickbook_grammar& g;
+
+ cl::rule<Scanner> const&
+ start() const { return program; }
+ };
+
+ collector& out;
+ actions& escape_actions;
+ };
+
+ // Grammar for plain text (no actual highlighting)
+ struct teletype_highlight
+ : public cl::grammar<teletype_highlight>
+ {
+ teletype_highlight(collector& out, actions& escape_actions)
+ : out(out), escape_actions(escape_actions) {}
+
+ template <typename Scanner>
+ struct definition
+ {
+ definition(teletype_highlight const& self)
+ : g(self.escape_actions.grammar())
+ {
+ program
+ =
+ *( macro
+ | escape
+ | cl::repeat_p(1)[cl::anychar_p] [plain_char(self.out)]
+ )
+ ;
+
+ macro =
+ // must not be followed by alpha or underscore
+ cl::eps_p(self.escape_actions.macro
+ >> (cl::eps_p - (cl::alpha_p | '_')))
+ >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)]
+ ;
+
+ escape =
+ cl::str_p("``") [pre_escape_back(self.escape_actions)]
+ >>
+ (
+ (
+ (
+ (+(cl::anychar_p - "``") >> cl::eps_p("``"))
+ & g.phrase
+ )
+ >> cl::str_p("``")
+ )
+ |
+ (
+ cl::eps_p [self.escape_actions.error]
+ >> *cl::anychar_p
+ )
+ ) [post_escape_back(self.out, self.escape_actions)]
+ ;
+ }
+
+ cl::rule<Scanner> program, macro, escape;
+
+ quickbook_grammar& g;
+
+ cl::rule<Scanner> const&
+ start() const { return program; }
+ };
+
+ collector& out;
+ actions& escape_actions;
+ };
+
+ std::string syntax_highlight(
+ parse_iterator first,
+ parse_iterator last,
+ actions& escape_actions,
+ std::string const& source_mode)
+ {
+ quickbook::collector temp;
+
+ // print the code with syntax coloring
+ if (source_mode == "c++")
+ {
+ cpp_highlight cpp_p(temp, escape_actions);
+ boost::spirit::classic::parse(first, last, cpp_p);
+ }
+ else if (source_mode == "python")
+ {
+ python_highlight python_p(temp, escape_actions);
+ boost::spirit::classic::parse(first, last, python_p);
+ }
+ else if (source_mode == "teletype")
+ {
+ teletype_highlight teletype_p(temp, escape_actions);
+ boost::spirit::classic::parse(first, last, teletype_p);
+ }
+ else
+ {
+ BOOST_ASSERT(0);
+ }
+
+ std::string str;
+ temp.swap(str);
+
+ return str;
+ }
+}
diff --git a/tools/quickbook/src/template_stack.cpp b/tools/quickbook/src/template_stack.cpp
new file mode 100644
index 0000000000..fba72558e1
--- /dev/null
+++ b/tools/quickbook/src/template_stack.cpp
@@ -0,0 +1,119 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include <cassert>
+#include "template_stack.hpp"
+#include "files.hpp"
+
+#ifdef BOOST_MSVC
+#pragma warning(disable : 4355)
+#endif
+
+namespace quickbook
+{
+ template_symbol::template_symbol(
+ std::string const& identifier,
+ std::vector<std::string> const& params,
+ value const& content,
+ template_scope const* lexical_parent)
+ : identifier(identifier)
+ , params(params)
+ , content(content)
+ , lexical_parent(lexical_parent)
+ {
+ assert(content.get_tag() == template_tags::block ||
+ content.get_tag() == template_tags::phrase ||
+ content.get_tag() == template_tags::snippet);
+ }
+
+ template_stack::template_stack()
+ : scope(template_stack::parser(*this))
+ , scopes()
+ , parent_1_4(0)
+ {
+ scopes.push_front(template_scope());
+ parent_1_4 = &scopes.front();
+ }
+
+ template_symbol* template_stack::find(std::string const& symbol) const
+ {
+ for (template_scope const* i = &*scopes.begin(); i; i = i->parent_scope)
+ {
+ if (template_symbol* ts = boost::spirit::classic::find(i->symbols, symbol.c_str()))
+ return ts;
+ }
+ return 0;
+ }
+
+ template_symbol* template_stack::find_top_scope(std::string const& symbol) const
+ {
+ return boost::spirit::classic::find(scopes.front().symbols, symbol.c_str());
+ }
+
+ template_symbols const& template_stack::top() const
+ {
+ BOOST_ASSERT(!scopes.empty());
+ return scopes.front().symbols;
+ }
+
+ template_scope const& template_stack::top_scope() const
+ {
+ BOOST_ASSERT(!scopes.empty());
+ return scopes.front();
+ }
+
+ bool template_stack::add(template_symbol const& ts)
+ {
+ BOOST_ASSERT(!scopes.empty());
+ BOOST_ASSERT(ts.lexical_parent);
+
+ if (this->find_top_scope(ts.identifier)) {
+ return false;
+ }
+
+ boost::spirit::classic::add(scopes.front().symbols,
+ ts.identifier.c_str(), ts);
+
+ return true;
+ }
+
+ void template_stack::push()
+ {
+ template_scope const& old_front = scopes.front();
+ scopes.push_front(template_scope());
+ scopes.front().parent_1_4 = parent_1_4;
+ scopes.front().parent_scope = &old_front;
+ parent_1_4 = &scopes.front();
+ }
+
+ void template_stack::pop()
+ {
+ parent_1_4 = scopes.front().parent_1_4;
+ scopes.pop_front();
+ }
+
+ void template_stack::start_template(template_symbol const* symbol)
+ {
+ // Quickbook 1.4-: When expanding the template continue to use the
+ // current scope (the dynamic scope).
+ // Quickbook 1.5+: Use the scope the template was defined in
+ // (the static scope).
+ if (symbol->content.get_file()->version() >= 105u)
+ {
+ parent_1_4 = scopes.front().parent_1_4;
+ scopes.front().parent_scope = symbol->lexical_parent;
+ }
+ else
+ {
+ scopes.front().parent_scope = scopes.front().parent_1_4;
+ }
+ }
+}
+
+
diff --git a/tools/quickbook/src/template_stack.hpp b/tools/quickbook/src/template_stack.hpp
new file mode 100644
index 0000000000..03c69cf463
--- /dev/null
+++ b/tools/quickbook/src/template_stack.hpp
@@ -0,0 +1,126 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP
+
+#include <string>
+#include <deque>
+#include <vector>
+#include <cassert>
+#include <boost/tuple/tuple.hpp>
+#include <boost/assert.hpp>
+#include <boost/spirit/include/classic_functor_parser.hpp>
+#include <boost/spirit/include/classic_symbols.hpp>
+#include <boost/next_prior.hpp>
+#include <boost/filesystem/path.hpp>
+#include "fwd.hpp"
+#include "values.hpp"
+#include "template_tags.hpp"
+
+namespace quickbook
+{
+ namespace fs = boost::filesystem;
+
+ struct template_scope;
+
+ struct template_symbol
+ {
+ template_symbol(
+ std::string const& identifier,
+ std::vector<std::string> const& params,
+ value const& content,
+ template_scope const* parent = 0);
+
+ std::string identifier;
+ std::vector<std::string> params;
+ value content;
+
+ template_scope const* lexical_parent;
+ };
+
+ typedef boost::spirit::classic::symbols<template_symbol> template_symbols;
+
+ // template scope
+ //
+ // 1.4-: parent_scope is the previous scope on the dynamic
+ // lookup chain. This moves up the stack skipping
+ // 1.5 templates (but not 1.5 included files).
+ // 1.5+: parent_scope is the template's lexical parent.
+ //
+ // This means that a search along the parent_scope chain will follow the
+ // correct lookup chain for that version of quickboook.
+ //
+ // symbols contains the templates defined in this scope.
+
+ struct template_scope
+ {
+ template_scope() : parent_scope(), parent_1_4() {}
+ template_scope const* parent_scope;
+ template_scope const* parent_1_4;
+ template_symbols symbols;
+ };
+
+ struct template_stack
+ {
+ typedef std::deque<template_scope> deque;
+
+ struct parser
+ {
+ typedef boost::spirit::classic::nil_t result_t;
+
+ parser(template_stack& ts)
+ : ts(ts) {}
+
+ template <typename Scanner>
+ std::ptrdiff_t
+ operator()(Scanner const& scan, result_t) const
+ {
+ // search all scopes for the longest matching symbol.
+ typename Scanner::iterator_t f = scan.first;
+ std::ptrdiff_t len = -1;
+ for (template_scope const* i = &*ts.scopes.begin(); i; i = i->parent_scope)
+ {
+ boost::spirit::classic::match<> m = i->symbols.parse(scan);
+ if (m.length() > len)
+ len = m.length();
+ scan.first = f;
+ }
+ if (len >= 0)
+ scan.first = boost::next(f, len);
+ return len;
+ }
+
+ template_stack& ts;
+ };
+
+ template_stack();
+ template_symbol* find(std::string const& symbol) const;
+ template_symbol* find_top_scope(std::string const& symbol) const;
+ template_symbols const& top() const;
+ template_scope const& top_scope() const;
+ // Add the given template symbol to the current scope.
+ // If it doesn't have a scope, sets the symbol's scope to the current scope.
+ bool add(template_symbol const&);
+ void push();
+ void pop();
+
+ void start_template(template_symbol const*);
+
+ boost::spirit::classic::functor_parser<parser> scope;
+
+ private:
+
+ friend struct parser;
+ deque scopes;
+ template_scope const* parent_1_4;
+ };
+}
+
+#endif // BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP
+
diff --git a/tools/quickbook/src/template_tags.hpp b/tools/quickbook/src/template_tags.hpp
new file mode 100644
index 0000000000..a47158dae6
--- /dev/null
+++ b/tools/quickbook/src/template_tags.hpp
@@ -0,0 +1,26 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_SPIRIT_QUICKBOOK_TEMPLATE_TAGS_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_TEMPLATE_TAGS_HPP
+
+#include "value_tags.hpp"
+
+namespace quickbook
+{
+ QUICKBOOK_VALUE_TAGS(template_tags, 0x100,
+ (template_)
+ (escape)
+ (identifier)
+ (block)
+ (phrase)
+ (snippet)
+ )
+}
+
+#endif
diff --git a/tools/quickbook/src/utils.cpp b/tools/quickbook/src/utils.cpp
new file mode 100644
index 0000000000..0defe6d182
--- /dev/null
+++ b/tools/quickbook/src/utils.cpp
@@ -0,0 +1,84 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "utils.hpp"
+
+#include <cctype>
+#include <cstring>
+#include <map>
+
+namespace quickbook { namespace detail
+{
+ void print_char(char ch, std::ostream& out)
+ {
+ switch (ch)
+ {
+ case '<': out << "&lt;"; break;
+ case '>': out << "&gt;"; break;
+ case '&': out << "&amp;"; break;
+ case '"': out << "&quot;"; break;
+ default: out << ch; break;
+ // note &apos; is not included. see the curse of apos:
+ // http://fishbowl.pastiche.org/2003/07/01/the_curse_of_apos
+ }
+ }
+
+ void print_string(std::basic_string<char> const& str, std::ostream& out)
+ {
+ for (std::string::const_iterator cur = str.begin();
+ cur != str.end(); ++cur)
+ {
+ print_char(*cur, out);
+ }
+ }
+
+ char filter_identifier_char(char ch)
+ {
+ if (!std::isalnum(static_cast<unsigned char>(ch)))
+ ch = '_';
+ return static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
+ }
+
+ std::string escape_uri(std::string uri)
+ {
+ for (std::string::size_type n = 0; n < uri.size(); ++n)
+ {
+ static char const mark[] = "-_.!~*'()?\\/";
+ if((!std::isalnum(static_cast<unsigned char>(uri[n])) || 127 < static_cast<unsigned char>(uri[n]))
+ && 0 == std::strchr(mark, uri[n]))
+ {
+ static char const hex[] = "0123456789abcdef";
+ char escape[] = { hex[uri[n] / 16], hex[uri[n] % 16] };
+ uri.insert(n + 1, escape, 2);
+ uri[n] = '%';
+ n += 2;
+ }
+ }
+ return uri;
+ }
+
+ file_type get_file_type(std::string const& extension)
+ {
+ static std::map<std::string, file_type> ftypes;
+ if (ftypes.empty())
+ {
+ // init the map of types
+ ftypes["cpp"] = cpp_file;
+ ftypes["hpp"] = cpp_file;
+ ftypes["h"] = cpp_file;
+ ftypes["c"] = cpp_file;
+ ftypes["cxx"] = cpp_file;
+ ftypes["hxx"] = cpp_file;
+ ftypes["ipp"] = cpp_file;
+ ftypes["py"] = python_file;
+ }
+ return ftypes[extension];
+ }
+
+}}
diff --git a/tools/quickbook/src/utils.hpp b/tools/quickbook/src/utils.hpp
new file mode 100644
index 0000000000..e7afa05e1b
--- /dev/null
+++ b/tools/quickbook/src/utils.hpp
@@ -0,0 +1,50 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 2006 Joel de Guzman
+ Copyright (c) 2004 Eric Niebler
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_QUICKBOOK_UTILS_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_UTILS_HPP
+
+#include <string>
+#include <ostream>
+#include <boost/range/algorithm_ext/push_back.hpp>
+#include <boost/range/adaptor/transformed.hpp>
+
+namespace quickbook { namespace detail {
+ void print_char(char ch, std::ostream& out);
+ void print_string(std::basic_string<char> const& str, std::ostream& out);
+ char filter_identifier_char(char ch);
+
+ template <typename Range>
+ inline std::string
+ make_identifier(Range const& range)
+ {
+ std::string out_name;
+
+ boost::push_back(out_name,
+ range | boost::adaptors::transformed(filter_identifier_char));
+
+ return out_name;
+ }
+
+ std::string escape_uri(std::string uri);
+
+ // given a file extension, return the type of the source file
+ // we'll have an internal database for known file types.
+
+ enum file_type
+ {
+ cpp_file
+ , python_file
+ };
+
+ file_type get_file_type(std::string const& extension);
+}}
+
+#endif // BOOST_SPIRIT_QUICKBOOK_UTILS_HPP
+
diff --git a/tools/quickbook/src/value_tags.hpp b/tools/quickbook/src/value_tags.hpp
new file mode 100644
index 0000000000..ec3312c1ca
--- /dev/null
+++ b/tools/quickbook/src/value_tags.hpp
@@ -0,0 +1,73 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_SPIRIT_QUICKBOOK_VALUES_TAGS_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_VALUES_TAGS_HPP
+
+#include <boost/preprocessor/stringize.hpp>
+#include <boost/preprocessor/seq/enum.hpp>
+#include <boost/preprocessor/seq/for_each.hpp>
+#include <boost/preprocessor/seq/elem.hpp>
+#include <boost/range/irange.hpp>
+#include <cassert>
+
+#define QUICKBOOK_VALUE_TAGS(tags_name, start_index, values) \
+ struct tags_name { \
+ enum tags_name##_enum { \
+ previous_index = start_index - 1, \
+ BOOST_PP_SEQ_ENUM(values), \
+ end_index \
+ }; \
+ \
+ static char const* name(int value) { \
+ switch(value) {\
+ case 0: \
+ return "null"; \
+ BOOST_PP_SEQ_FOR_EACH(QUICKBOOK_VALUE_CASE, _, values) \
+ default: \
+ assert(false); return ""; \
+ }; \
+ } \
+ \
+ typedef boost::integer_range<int> range_type; \
+ static range_type tags() { return boost::irange(start_index, (int) end_index); } \
+ };
+
+#define QUICKBOOK_VALUE_CASE(r, _, value) \
+ case value: return BOOST_PP_STRINGIZE(value);
+
+#define QUICKBOOK_VALUE_NAMED_TAGS(tags_name, start_index, values) \
+ struct tags_name { \
+ enum tags_name##_enum { \
+ previous_index = start_index - 1 \
+ BOOST_PP_SEQ_FOR_EACH(QUICKBOOK_VALUE_NAMED_ENUM, _, values), \
+ end_index \
+ }; \
+ \
+ static char const* name(int value) { \
+ switch(value) {\
+ case 0: \
+ return "null"; \
+ BOOST_PP_SEQ_FOR_EACH(QUICKBOOK_VALUE_NAMED_CASE, _, values) \
+ default: \
+ assert(false); return ""; \
+ }; \
+ } \
+ \
+ typedef boost::integer_range<int> range_type; \
+ static range_type tags() { return boost::irange(start_index, (int) end_index); } \
+ };
+
+#define QUICKBOOK_VALUE_NAMED_ENUM(r, _, value) \
+ , BOOST_PP_SEQ_ELEM(0, value)
+
+#define QUICKBOOK_VALUE_NAMED_CASE(r, _, value) \
+ case BOOST_PP_SEQ_ELEM(0, value): return BOOST_PP_SEQ_ELEM(1, value);
+
+
+#endif
diff --git a/tools/quickbook/src/values.cpp b/tools/quickbook/src/values.cpp
new file mode 100644
index 0000000000..7c3521d50b
--- /dev/null
+++ b/tools/quickbook/src/values.cpp
@@ -0,0 +1,853 @@
+/*=============================================================================
+ Copyright (c) 2010-2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "values.hpp"
+#include "files.hpp"
+#include <boost/current_function.hpp>
+#include <boost/lexical_cast.hpp>
+
+#define UNDEFINED_ERROR() \
+ throw value_undefined_method( \
+ std::string(BOOST_CURRENT_FUNCTION) +\
+ " not defined for " + \
+ this->type_name() + \
+ " values." \
+ );
+
+namespace quickbook
+{
+ ////////////////////////////////////////////////////////////////////////////
+ // Value Error
+
+ struct value_undefined_method : value_error
+ {
+ value_undefined_method(std::string const&);
+ };
+
+ value_error::value_error(std::string const& x)
+ : std::logic_error(x) {}
+
+ value_undefined_method::value_undefined_method(std::string const& x)
+ : value_error(x) {}
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Node
+
+ namespace detail
+ {
+ value_node::value_node(tag_type t)
+ : ref_count_(0), tag_(t), next_() {
+ }
+
+ value_node::~value_node() {
+ }
+
+ file_ptr value_node::get_file() const { UNDEFINED_ERROR(); }
+ string_iterator value_node::get_position() const { UNDEFINED_ERROR(); }
+ int value_node::get_int() const { UNDEFINED_ERROR(); }
+ string_ref value_node::get_quickbook() const { UNDEFINED_ERROR(); }
+ std::string value_node::get_encoded() const { UNDEFINED_ERROR(); }
+ value_node* value_node::get_list() const { UNDEFINED_ERROR(); }
+
+ bool value_node::empty() const { return false; }
+ bool value_node::check() const { return true; }
+ bool value_node::is_list() const { return false; }
+ bool value_node::is_encoded() const { return false; }
+ bool value_node::equals(value_node*) const { UNDEFINED_ERROR(); }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // List end value
+ //
+ // A special value for marking the end of lists.
+
+ namespace detail
+ {
+ struct value_list_end_impl : public value_node
+ {
+ static value_list_end_impl instance;
+ private:
+ value_list_end_impl()
+ : value_node(value::default_tag)
+ {
+ intrusive_ptr_add_ref(&instance);
+ next_ = this;
+ }
+
+ virtual char const* type_name() const { return "list end"; }
+ virtual value_node* clone() const { UNDEFINED_ERROR(); }
+
+ virtual bool equals(value_node* other) const
+ { return this == other; }
+
+ bool empty() const { UNDEFINED_ERROR(); }
+ bool check() const { UNDEFINED_ERROR(); }
+ bool is_list() const { UNDEFINED_ERROR(); }
+ bool is_encoded() const { UNDEFINED_ERROR(); }
+ };
+
+ value_list_end_impl value_list_end_impl::instance;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Empty/nil values
+ //
+ // (nil is just a special case of empty, don't be mislead by the name
+ // the type is not important).
+
+ namespace detail
+ {
+ struct empty_value_impl : public value_node
+ {
+ static value_node* new_(value::tag_type t);
+
+ protected:
+ explicit empty_value_impl(value::tag_type t)
+ : value_node(t) {}
+
+ private:
+ char const* type_name() const { return "empty"; }
+
+ virtual value_node* clone() const
+ { return new empty_value_impl(tag_); }
+
+ virtual bool empty() const
+ { return true; }
+
+ virtual bool check() const
+ { return false; }
+
+ virtual bool equals(value_node* other) const
+ { return !other->check(); }
+
+ friend value quickbook::empty_value(value::tag_type);
+ };
+
+ struct value_nil_impl : public empty_value_impl
+ {
+ static value_nil_impl instance;
+ private:
+ value_nil_impl()
+ : empty_value_impl(value::default_tag)
+ {
+ intrusive_ptr_add_ref(&instance);
+ next_ = &value_list_end_impl::instance;
+ }
+ };
+
+ value_nil_impl value_nil_impl::instance;
+
+ value_node* empty_value_impl::new_(value::tag_type t) {
+ // The return value from this function is always placed in an
+ // intrusive_ptr which will manage the memory correctly.
+ // Note that value_nil_impl increments its reference count
+ // in its constructor, so that it will never be deleted by the
+ // intrusive pointer.
+
+ if (t == value::default_tag)
+ return &value_nil_impl::instance;
+ else
+ return new empty_value_impl(t);
+ }
+ }
+
+ value empty_value(value::tag_type t)
+ {
+ return value(detail::empty_value_impl::new_(t));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // value_counted
+
+ namespace detail
+ {
+ value_counted::value_counted()
+ : value_base(&value_nil_impl::instance)
+ {
+ // Even though empty is not on the heap, its reference
+ // counter needs to be incremented so that the destructor
+ // doesn't try to delete it.
+
+ intrusive_ptr_add_ref(value_);
+ }
+
+ value_counted::value_counted(value_counted const& x)
+ : value_base(x)
+ {
+ intrusive_ptr_add_ref(value_);
+ }
+
+ value_counted::value_counted(value_base const& x)
+ : value_base(x)
+ {
+ intrusive_ptr_add_ref(value_);
+ }
+
+ value_counted::value_counted(value_node* x)
+ : value_base(x)
+ {
+ intrusive_ptr_add_ref(value_);
+ }
+
+ value_counted::~value_counted()
+ {
+ intrusive_ptr_release(value_);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // value
+
+ value::value()
+ : detail::value_counted()
+ {
+ }
+
+ value::value(value const& x)
+ : detail::value_counted(x)
+ {
+ }
+
+ value::value(detail::value_base const& x)
+ : detail::value_counted(x)
+ {
+ }
+
+ value::value(detail::value_node* x)
+ : detail::value_counted(x)
+ {
+ }
+
+ value& value::operator=(value x)
+ {
+ swap(x);
+ return *this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Integers
+
+ namespace detail
+ {
+ struct int_value_impl : public value_node
+ {
+ public:
+ explicit int_value_impl(int, value::tag_type);
+ private:
+ char const* type_name() const { return "integer"; }
+ virtual value_node* clone() const;
+ virtual int get_int() const;
+ virtual std::string get_encoded() const;
+ virtual bool empty() const;
+ virtual bool is_encoded() const;
+ virtual bool equals(value_node*) const;
+
+ int value_;
+ };
+
+ int_value_impl::int_value_impl(int v, value::tag_type t)
+ : value_node(t)
+ , value_(v)
+ {}
+
+ value_node* int_value_impl::clone() const
+ {
+ return new int_value_impl(value_, tag_);
+ }
+
+ int int_value_impl::get_int() const
+ {
+ return value_;
+ }
+
+ std::string int_value_impl::get_encoded() const
+ {
+ return boost::lexical_cast<std::string>(value_);
+ }
+
+ bool int_value_impl::empty() const
+ {
+ return false;
+ }
+
+ bool int_value_impl::is_encoded() const
+ {
+ return true;
+ }
+
+ bool int_value_impl::equals(value_node* other) const {
+ try {
+ return value_ == other->get_int();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+ }
+ }
+
+ value int_value(int v, value::tag_type t)
+ {
+ return value(new detail::int_value_impl(v, t));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Strings
+
+ namespace detail
+ {
+ struct encoded_value_impl : public value_node
+ {
+ public:
+ explicit encoded_value_impl(std::string const&, value::tag_type);
+ private:
+ char const* type_name() const { return "encoded text"; }
+
+ virtual ~encoded_value_impl();
+ virtual value_node* clone() const;
+ virtual std::string get_encoded() const;
+ virtual bool empty() const;
+ virtual bool is_encoded() const;
+ virtual bool equals(value_node*) const;
+
+ std::string value_;
+ };
+
+ struct qbk_value_impl : public value_node
+ {
+ public:
+ explicit qbk_value_impl(
+ file_ptr const&,
+ string_iterator begin,
+ string_iterator end,
+ value::tag_type);
+ private:
+ char const* type_name() const { return "quickbook"; }
+
+ virtual ~qbk_value_impl();
+ virtual value_node* clone() const;
+ virtual file_ptr get_file() const;
+ virtual string_iterator get_position() const;
+ virtual string_ref get_quickbook() const;
+ virtual bool empty() const;
+ virtual bool equals(value_node*) const;
+
+ file_ptr file_;
+ string_iterator begin_;
+ string_iterator end_;
+ };
+
+ struct encoded_qbk_value_impl : public value_node
+ {
+ private:
+ char const* type_name() const { return "encoded text with quickbook reference"; }
+
+ encoded_qbk_value_impl(file_ptr const&,
+ string_iterator, string_iterator,
+ std::string const&, value::tag_type);
+
+ virtual ~encoded_qbk_value_impl();
+ virtual value_node* clone() const;
+ virtual file_ptr get_file() const;
+ virtual string_iterator get_position() const;
+ virtual string_ref get_quickbook() const;
+ virtual std::string get_encoded() const;
+ virtual bool empty() const;
+ virtual bool is_encoded() const;
+ virtual bool equals(value_node*) const;
+
+ file_ptr file_;
+ string_iterator begin_;
+ string_iterator end_;
+ std::string encoded_value_;
+
+ friend quickbook::value quickbook::encoded_qbk_value(
+ file_ptr const&, string_iterator, string_iterator,
+ std::string const&, quickbook::value::tag_type);
+ };
+
+ // encoded_value_impl
+
+ encoded_value_impl::encoded_value_impl(
+ std::string const& val,
+ value::tag_type tag
+ )
+ : value_node(tag), value_(val)
+ {
+ }
+
+ encoded_value_impl::~encoded_value_impl()
+ {
+ }
+
+ value_node* encoded_value_impl::clone() const
+ {
+ return new encoded_value_impl(value_, tag_);
+ }
+
+ std::string encoded_value_impl::get_encoded() const
+ { return value_; }
+
+ bool encoded_value_impl::empty() const
+ { return value_.empty(); }
+
+ bool encoded_value_impl::is_encoded() const
+ { return true; }
+
+ bool encoded_value_impl::equals(value_node* other) const {
+ try {
+ return value_ == other->get_encoded();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+ }
+
+ // qbk_value_impl
+
+ qbk_value_impl::qbk_value_impl(
+ file_ptr const& f,
+ string_iterator begin,
+ string_iterator end,
+ value::tag_type tag
+ ) : value_node(tag), file_(f), begin_(begin), end_(end)
+ {
+ }
+
+ qbk_value_impl::~qbk_value_impl()
+ {
+ }
+
+ value_node* qbk_value_impl::clone() const
+ {
+ return new qbk_value_impl(file_, begin_, end_, tag_);
+ }
+
+ file_ptr qbk_value_impl::get_file() const
+ { return file_; }
+
+ string_iterator qbk_value_impl::get_position() const
+ { return begin_; }
+
+ string_ref qbk_value_impl::get_quickbook() const
+ { return string_ref(begin_, end_); }
+
+ bool qbk_value_impl::empty() const
+ { return begin_ == end_; }
+
+ bool qbk_value_impl::equals(value_node* other) const {
+ try {
+ return this->get_quickbook() == other->get_quickbook();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+ }
+
+ // encoded_qbk_value_impl
+
+ encoded_qbk_value_impl::encoded_qbk_value_impl(
+ file_ptr const& f,
+ string_iterator begin,
+ string_iterator end,
+ std::string const& encoded,
+ value::tag_type tag)
+ : value_node(tag)
+ , file_(f)
+ , begin_(begin)
+ , end_(end)
+ , encoded_value_(encoded)
+
+ {
+ }
+
+ encoded_qbk_value_impl::~encoded_qbk_value_impl()
+ {
+ }
+
+ value_node* encoded_qbk_value_impl::clone() const
+ {
+ return new encoded_qbk_value_impl(
+ file_, begin_, end_, encoded_value_, tag_);
+ }
+
+ file_ptr encoded_qbk_value_impl::get_file() const
+ { return file_; }
+
+ string_iterator encoded_qbk_value_impl::get_position() const
+ { return begin_; }
+
+ string_ref encoded_qbk_value_impl::get_quickbook() const
+ { return string_ref(begin_, end_); }
+
+ std::string encoded_qbk_value_impl::get_encoded() const
+ { return encoded_value_; }
+
+ // Should this test the quickbook, the boostbook or both?
+ bool encoded_qbk_value_impl::empty() const
+ { return encoded_value_.empty(); }
+
+ bool encoded_qbk_value_impl::is_encoded() const
+ { return true; }
+
+ bool encoded_qbk_value_impl::equals(value_node* other) const {
+ try {
+ return this->get_quickbook() == other->get_quickbook();
+ }
+ catch(value_undefined_method&) {}
+
+ try {
+ return this->get_encoded() == other->get_encoded();
+ }
+ catch(value_undefined_method&) {}
+
+ return false;
+ }
+ }
+
+ value qbk_value(file_ptr const& f, string_iterator x, string_iterator y, value::tag_type t)
+ {
+ return value(new detail::qbk_value_impl(f, x, y, t));
+ }
+
+ value encoded_value(std::string const& x, value::tag_type t)
+ {
+ return value(new detail::encoded_value_impl(x, t));
+ }
+
+ value encoded_qbk_value(
+ file_ptr const& f, string_iterator x, string_iterator y,
+ std::string const& z, value::tag_type t)
+ {
+ return value(new detail::encoded_qbk_value_impl(f,x,y,z,t));
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // List methods
+
+ namespace detail
+ {
+ namespace {
+ value_node** list_ref_back(value_node**);
+ void list_ref(value_node*);
+ void list_unref(value_node*);
+ value_node** merge_sort(value_node**);
+ value_node** merge_sort(value_node**, int);
+ value_node** merge(value_node**, value_node**, value_node**);
+ void rotate(value_node**, value_node**, value_node**);
+
+ value_node** list_ref_back(value_node** back)
+ {
+ while(*back != &value_list_end_impl::instance) {
+ intrusive_ptr_add_ref(*back);
+ back = &(*back)->next_;
+ }
+
+ return back;
+ }
+
+ void list_ref(value_node* ptr)
+ {
+ while(ptr != &value_list_end_impl::instance) {
+ intrusive_ptr_add_ref(ptr);
+ ptr = ptr->next_;
+ }
+ }
+
+ void list_unref(value_node* ptr)
+ {
+ while(ptr != &value_list_end_impl::instance) {
+ value_node* next = ptr->next_;
+ intrusive_ptr_release(ptr);
+ ptr = next;
+ }
+ }
+
+ value_node** merge_sort(value_node** l)
+ {
+ if(*l == &value_list_end_impl::instance)
+ return l;
+ else
+ return merge_sort(l, 9999);
+ }
+
+ value_node** merge_sort(value_node** l, int recurse_limit)
+ {
+ value_node** p = &(*l)->next_;
+ for(int count = 0;
+ count < recurse_limit && *p != &value_list_end_impl::instance;
+ ++count)
+ {
+ p = merge(l, p, merge_sort(p, count));
+ }
+ return p;
+ }
+
+ value_node** merge(
+ value_node** first, value_node** second, value_node** third)
+ {
+ for(;;) {
+ for(;;) {
+ if(first == second) return third;
+ if((*second)->tag_ < (*first)->tag_) break;
+ first = &(*first)->next_;
+ }
+
+ rotate(first, second, third);
+ first = &(*first)->next_;
+
+ // Since the two ranges were just swapped, the order is now:
+ // first...third...second
+ //
+ // Also, that since the second section of the list was
+ // originally before the first, if the heads are equal
+ // we need to swap to maintain the order.
+
+ for(;;) {
+ if(first == third) return second;
+ if((*third)->tag_ <= (*first)->tag_) break;
+ first = &(*first)->next_;
+ }
+
+ rotate(first, third, second);
+ first = &(*first)->next_;
+ }
+ }
+
+ void rotate(value_node** first, value_node** second, value_node** third)
+ {
+ value_node* tmp = *first;
+ *first = *second;
+ *second = *third;
+ *third = tmp;
+ //if(*second != &value_list_end_impl::instance) back = second;
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Lists
+
+ namespace detail
+ {
+ struct value_list_impl : public value_node
+ {
+ value_list_impl(value::tag_type);
+ value_list_impl(value_list_builder&, value::tag_type);
+ private:
+ value_list_impl(value_list_impl const&);
+
+ char const* type_name() const { return "list"; }
+
+ virtual ~value_list_impl();
+ virtual value_node* clone() const;
+ virtual bool empty() const;
+ virtual bool equals(value_node*) const;
+
+ virtual bool is_list() const;
+ virtual value_node* get_list() const;
+
+ value_node* head_;
+ };
+
+ value_list_impl::value_list_impl(value::tag_type tag)
+ : value_node(tag), head_(&value_list_end_impl::instance)
+ {}
+
+ value_list_impl::value_list_impl(value_list_builder& builder,
+ value::tag_type tag)
+ : value_node(tag), head_(builder.release())
+ {
+ }
+
+ value_list_impl::value_list_impl(value_list_impl const& x)
+ : value_node(x.tag_), head_(x.head_)
+ {
+ list_ref(head_);
+ }
+
+ value_list_impl::~value_list_impl()
+ {
+ list_unref(head_);
+ }
+
+ value_node* value_list_impl::clone() const
+ {
+ return new value_list_impl(*this);
+ }
+
+ bool value_list_impl::empty() const
+ {
+ return head_ == &value_list_end_impl::instance;
+ }
+
+ bool value_list_impl::is_list() const
+ {
+ return true;
+ }
+
+ value_node* value_list_impl::get_list() const
+ {
+ return head_;
+ }
+
+ bool value_list_impl::equals(value_node* other) const {
+ value_node* x1;
+
+ try {
+ x1 = other->get_list();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+
+ for(value_node *x2 = head_; x1 != x2; x1 = x1->next_, x2 = x2->next_)
+ {
+ if (x2 == &value_list_end_impl::instance ||
+ !x1->equals(x2)) return false;
+ }
+
+ return true;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // List builder
+
+ namespace detail
+ {
+ // value_list_builder
+
+ value_list_builder::value_list_builder()
+ : head_(&value_list_end_impl::instance)
+ , back_(&head_)
+ {}
+
+ value_list_builder::value_list_builder(value_node* ptr)
+ : head_(ptr)
+ , back_(list_ref_back(&head_))
+ {}
+
+ value_list_builder::~value_list_builder()
+ {
+ list_unref(head_);
+ }
+
+ void value_list_builder::swap(value_list_builder& other) {
+ std::swap(head_, other.head_);
+ std::swap(back_, other.back_);
+ if(back_ == &other.head_) back_ = &head_;
+ if(other.back_ == &head_) other.back_ = &other.head_;
+ }
+
+ value_node* value_list_builder::release() {
+ value_node* r = head_;
+ head_ = &value_list_end_impl::instance;
+ back_ = &head_;
+ return r;
+ }
+
+ void value_list_builder::append(value_node* item)
+ {
+ if(item->next_) item = item->clone();
+ intrusive_ptr_add_ref(item);
+ item->next_ = *back_;
+ *back_ = item;
+ back_ = &item->next_;
+ }
+
+ void value_list_builder::sort()
+ {
+ back_ = merge_sort(&head_);
+ assert(*back_ == &value_list_end_impl::instance);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Value builder
+
+ value_builder::value_builder()
+ : current()
+ , list_tag(value::default_tag)
+ , saved()
+ {
+ }
+
+ void value_builder::swap(value_builder& other) {
+ current.swap(other.current);
+ std::swap(list_tag, other.list_tag);
+ saved.swap(other.saved);
+ }
+
+ void value_builder::save() {
+ boost::scoped_ptr<value_builder> store(new value_builder);
+ swap(*store);
+ saved.swap(store);
+ }
+
+ void value_builder::restore() {
+ boost::scoped_ptr<value_builder> store;
+ store.swap(saved);
+ swap(*store);
+ }
+
+ value value_builder::release() {
+ return value(new detail::value_list_impl(current, list_tag));
+ }
+
+ void value_builder::reset() {
+ detail::value_list_builder new_builder;
+ current.swap(new_builder);
+ list_tag = value::default_tag;
+ }
+
+ void value_builder::set_tag(value::tag_type tag) {
+ list_tag = tag;
+ }
+
+ void value_builder::insert(value const& item) {
+ current.append(item.value_);
+ }
+
+ void value_builder::extend(value const& list) {
+ for (value::iterator begin = list.begin(), end = list.end();
+ begin != end; ++begin)
+ {
+ insert(*begin);
+ }
+ }
+
+ void value_builder::start_list(value::tag_type tag) {
+ value::tag_type saved_tag = tag;
+ save();
+ list_tag = saved_tag;
+ }
+
+ void value_builder::finish_list() {
+ value list = release();
+ restore();
+ insert(list);
+ }
+
+ void value_builder::clear_list() {
+ restore();
+ }
+
+ void value_builder::sort_list()
+ {
+ current.sort();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Iterator
+
+ namespace detail
+ {
+ value::iterator::iterator()
+ : ptr_(&value_list_end_impl::instance) {}
+ }
+}
diff --git a/tools/quickbook/src/values.hpp b/tools/quickbook/src/values.hpp
new file mode 100644
index 0000000000..2380b0d5dc
--- /dev/null
+++ b/tools/quickbook/src/values.hpp
@@ -0,0 +1,409 @@
+/*=============================================================================
+ Copyright (c) 2010-2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+// An easy way to store data parsed for quickbook.
+
+#if !defined(BOOST_SPIRIT_QUICKBOOK_VALUES_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_VALUES_HPP
+
+#include <utility>
+#include <string>
+#include <cassert>
+#include <boost/scoped_ptr.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <stdexcept>
+#include "fwd.hpp"
+#include "string_ref.hpp"
+#include "files.hpp"
+
+namespace quickbook
+{
+ struct value;
+ struct value_builder;
+ struct value_error;
+
+ namespace detail
+ {
+ ////////////////////////////////////////////////////////////////////////
+ // Node
+
+ struct value_node
+ {
+ private:
+ value_node(value_node const&);
+ value_node& operator=(value_node const&);
+
+ public:
+ typedef int tag_type;
+
+ protected:
+ explicit value_node(tag_type);
+ virtual ~value_node();
+
+ public:
+ virtual char const* type_name() const = 0;
+ virtual value_node* clone() const = 0;
+
+ virtual file_ptr get_file() const;
+ virtual string_iterator get_position() const;
+ virtual string_ref get_quickbook() const;
+ virtual std::string get_encoded() const;
+ virtual int get_int() const;
+
+ virtual bool check() const;
+ virtual bool empty() const;
+ virtual bool is_encoded() const;
+ virtual bool is_list() const;
+ virtual bool equals(value_node*) const;
+
+ virtual value_node* get_list() const;
+
+ int ref_count_;
+ const tag_type tag_;
+ value_node* next_;
+
+ friend void intrusive_ptr_add_ref(value_node* ptr)
+ { ++ptr->ref_count_; }
+ friend void intrusive_ptr_release(value_node* ptr)
+ { if(--ptr->ref_count_ == 0) delete ptr; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////
+ // Value base
+ //
+ // This defines most of the public methods for value.
+ // 'begin' and 'end' are defined with the iterators later.
+
+ struct value_base
+ {
+ public:
+ struct iterator;
+
+ typedef iterator const_iterator;
+ typedef value_node::tag_type tag_type;
+ enum { default_tag = 0 };
+
+ protected:
+ explicit value_base(value_node* base)
+ : value_(base)
+ {
+ assert(value_);
+ }
+
+ ~value_base() {}
+
+ void swap(value_base& x) { std::swap(value_, x.value_); }
+ public:
+ bool check() const { return value_->check(); }
+ bool empty() const { return value_->empty(); }
+ bool is_encoded() const { return value_->is_encoded(); }
+ bool is_list() const { return value_->is_list(); }
+
+ iterator begin() const;
+ iterator end() const;
+
+ // Item accessors
+ int get_tag() const { return value_->tag_; }
+ file_ptr get_file() const
+ { return value_->get_file(); }
+ string_iterator get_position() const
+ { return value_->get_position(); }
+ string_ref get_quickbook() const
+ { return value_->get_quickbook(); }
+ std::string get_encoded() const
+ { return value_->get_encoded(); }
+ int get_int() const
+ { return value_->get_int(); }
+
+ // Equality is pretty inefficient. Not really designed for anything
+ // more than testing purposes.
+ friend bool operator==(value_base const& x, value_base const& y)
+ { return x.value_->equals(y.value_); }
+
+ protected:
+ value_node* value_;
+
+ // value_builder needs to access 'value_' to get the node
+ // from a value.
+ friend struct quickbook::value_builder;
+ };
+
+ ////////////////////////////////////////////////////////////////////////
+ // Reference and proxy values for use in iterators
+
+ struct value_ref : public value_base
+ {
+ public:
+ explicit value_ref(value_node* base) : value_base(base) {}
+ };
+
+ struct value_proxy : public value_base
+ {
+ public:
+ explicit value_proxy(value_node* base) : value_base(base) {}
+ value_proxy* operator->() { return this; }
+ value_ref operator*() const { return value_ref(value_); }
+ };
+
+ ////////////////////////////////////////////////////////////////////////
+ // Iterators
+
+ struct value_base::iterator
+ : public boost::forward_iterator_helper<
+ iterator, value, int, value_proxy, value_ref>
+ {
+ public:
+ iterator();
+ explicit iterator(value_node* p) : ptr_(p) {}
+ friend bool operator==(iterator x, iterator y)
+ { return x.ptr_ == y.ptr_; }
+ iterator& operator++() { ptr_ = ptr_->next_; return *this; }
+ value_ref operator*() const { return value_ref(ptr_); }
+ value_proxy operator->() const { return value_proxy(ptr_); }
+ private:
+ value_node* ptr_;
+ };
+
+ inline value_base::iterator value_base::begin() const
+ {
+ return iterator(value_->get_list());
+ }
+
+ inline value_base::iterator value_base::end() const
+ {
+ return iterator();
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Reference counting for values
+
+ struct value_counted : public value_base
+ {
+ value_counted& operator=(value_counted const&);
+ protected:
+ value_counted();
+ value_counted(value_counted const&);
+ value_counted(value_base const&);
+ value_counted(value_node*);
+ ~value_counted();
+ };
+
+ ////////////////////////////////////////////////////////////////////////
+ // List builder
+ //
+ // Values are immutable, so this class is used to build a list of
+ // value nodes before constructing the value.
+
+ struct value_list_builder {
+ value_list_builder(value_list_builder const&);
+ value_list_builder& operator=(value_list_builder const&);
+ public:
+ value_list_builder();
+ value_list_builder(value_node*);
+ ~value_list_builder();
+ void swap(value_list_builder& b);
+ value_node* release();
+
+ void append(value_node*);
+ void sort();
+ private:
+ value_node* head_;
+ value_node** back_;
+ };
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Value
+ //
+ // Most of the methods are in value_base.
+
+ struct value : public detail::value_counted
+ {
+ public:
+ value();
+ value(value const&);
+ value(detail::value_base const&);
+ explicit value(detail::value_node*);
+ value& operator=(value);
+ void swap(value& x) { detail::value_counted::swap(x); }
+ };
+
+ // Empty
+ value empty_value(value::tag_type = value::default_tag);
+
+ // Integers
+ value int_value(int, value::tag_type = value::default_tag);
+
+ // String types
+
+ // Quickbook strings contain a reference to the original quickbook source.
+ value qbk_value(file_ptr const&, string_iterator, string_iterator,
+ value::tag_type = value::default_tag);
+
+ // Encoded strings are either plain text or boostbook.
+ value encoded_value(std::string const&,
+ value::tag_type = value::default_tag);
+
+ // An encoded quickbook string is an encoded string that contains a
+ // reference to the quickbook source it was generated from.
+ value encoded_qbk_value(file_ptr const&, string_iterator, string_iterator,
+ std::string const&, value::tag_type = value::default_tag);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Value Builder
+ //
+ // Used to incrementally build a valueeter tree.
+
+ struct value_builder {
+ public:
+ value_builder();
+ void swap(value_builder& b);
+
+ void save();
+ void restore();
+
+ value release();
+
+ void reset();
+ void set_tag(value::tag_type);
+ void insert(value const&);
+ void extend(value const&);
+
+ void start_list(value::tag_type = value::default_tag);
+ void finish_list();
+ void clear_list();
+ void sort_list();
+
+ private:
+ detail::value_list_builder current;
+ value::tag_type list_tag;
+ boost::scoped_ptr<value_builder> saved;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Value Error
+ //
+
+ struct value_error : public std::logic_error
+ {
+ public:
+ explicit value_error(std::string const&);
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Value Consumer
+ //
+ // Convenience class for unpacking value values.
+
+ struct value_consumer {
+ public:
+ struct iterator
+ : public boost::input_iterator_helper<iterator,
+ boost::iterator_value<value::iterator>::type,
+ boost::iterator_difference<value::iterator>::type,
+ boost::iterator_pointer<value::iterator>::type,
+ boost::iterator_reference<value::iterator>::type>
+ {
+ public:
+ iterator();
+ explicit iterator(value::iterator* p) : ptr_(p) {}
+ friend bool operator==(iterator x, iterator y)
+ { return *x.ptr_ == *y.ptr_; }
+ iterator& operator++() { ++*ptr_; return *this; }
+ reference operator*() const { return **ptr_; }
+ pointer operator->() const { return ptr_->operator->(); }
+ private:
+ value::iterator* ptr_;
+ };
+
+ typedef iterator const_iterator;
+ typedef iterator::reference reference;
+
+ value_consumer(value const& x)
+ : list_(x)
+ , pos_(x.begin())
+ , end_(x.end())
+ {}
+
+ value_consumer(reference x)
+ : list_(x)
+ , pos_(x.begin())
+ , end_(x.end())
+ {}
+
+ reference consume()
+ {
+ assert_check();
+ return *pos_++;
+ }
+
+ reference consume(value::tag_type t)
+ {
+ assert_check(t);
+ return *pos_++;
+ }
+
+ value optional_consume()
+ {
+ if(check()) {
+ return *pos_++;
+ }
+ else {
+ return value();
+ }
+ }
+
+ value optional_consume(value::tag_type t)
+ {
+ if(check(t)) {
+ return *pos_++;
+ }
+ else {
+ return value();
+ }
+ }
+
+ bool check() const
+ {
+ return pos_ != end_;
+ }
+
+ bool check(value::tag_type t) const
+ {
+ return pos_ != end_ && t == pos_->get_tag();
+ }
+
+ void finish() const
+ {
+ if (pos_ != end_)
+ throw value_error("Not all values handled.");
+ }
+
+ iterator begin() { return iterator(&pos_); }
+ iterator end() { return iterator(&end_); }
+ private:
+
+ void assert_check() const
+ {
+ if (pos_ == end_)
+ throw value_error("Attempt to read past end of value list.");
+ }
+
+ void assert_check(value::tag_type t) const
+ {
+ assert_check();
+ if (t != pos_->get_tag())
+ throw value_error("Incorrect value tag.");
+ }
+
+ value list_;
+ value::iterator pos_, end_;
+ };
+}
+
+#endif
diff --git a/tools/quickbook/src/values_parse.hpp b/tools/quickbook/src/values_parse.hpp
new file mode 100644
index 0000000000..8d16b53d40
--- /dev/null
+++ b/tools/quickbook/src/values_parse.hpp
@@ -0,0 +1,113 @@
+/*=============================================================================
+ Copyright (c) 2010-2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(BOOST_SPIRIT_QUICKBOOK_VALUES_PARSE_HPP)
+#define BOOST_SPIRIT_QUICKBOOK_VALUES_PARSE_HPP
+
+#include "values.hpp"
+#include "parsers.hpp"
+#include "scoped.hpp"
+#include <boost/spirit/include/phoenix1_functions.hpp>
+
+#include <iostream>
+
+namespace quickbook {
+ namespace ph = phoenix;
+
+ struct value_builder_save : scoped_action_base
+ {
+ value_builder_save(value_builder& builder) : builder(builder) {}
+
+ bool start()
+ {
+ builder.save();
+ return true;
+ }
+
+ void cleanup() { builder.restore(); }
+
+ value_builder& builder;
+ };
+
+ struct value_builder_list : scoped_action_base
+ {
+ value_builder_list(value_builder& builder) : builder(builder) {}
+
+ bool start(value::tag_type tag = value::default_tag)
+ {
+ builder.start_list(tag);
+ return true;
+ }
+
+ void success(parse_iterator, parse_iterator) { builder.finish_list(); }
+ void failure() { builder.clear_list(); }
+
+ value_builder& builder;
+ };
+
+ struct value_entry
+ {
+ template <typename Arg1, typename Arg2 = void, typename Arg3 = void, typename Arg4 = void>
+ struct result {
+ typedef void type;
+ };
+
+ value_entry(value_builder& b, file_ptr* current_file)
+ : b(b), current_file(current_file) {}
+
+ void operator()(parse_iterator begin, parse_iterator end,
+ value::tag_type tag = value::default_tag) const
+ {
+ b.insert(qbk_value(*current_file, begin.base(), end.base(), tag));
+ }
+
+ void operator()(int v,
+ value::tag_type tag = value::default_tag) const
+ {
+ b.insert(int_value(v, tag));
+ }
+
+ value_builder& b;
+ file_ptr* current_file;
+ };
+
+ struct value_sort
+ {
+ typedef void result_type;
+
+ value_sort(value_builder& b)
+ : b(b) {}
+
+ void operator()() const {
+ b.sort_list();
+ }
+
+ value_builder& b;
+ };
+
+ struct value_parser
+ {
+ value_parser(file_ptr* current_file)
+ : builder()
+ , save(builder)
+ , list(builder)
+ , entry(value_entry(builder, current_file))
+ , sort(builder)
+ {}
+
+ value release() { return builder.release(); }
+
+ value_builder builder;
+ scoped_parser<value_builder_save> save;
+ scoped_parser<value_builder_list> list;
+ ph::function<value_entry> entry;
+ ph::function<value_sort> sort;
+ };
+}
+
+#endif
diff --git a/tools/quickbook/test/Jamfile.v2 b/tools/quickbook/test/Jamfile.v2
new file mode 100644
index 0000000000..fca35b5be4
--- /dev/null
+++ b/tools/quickbook/test/Jamfile.v2
@@ -0,0 +1,115 @@
+#
+# Copyright (c) 2005 João Abecasis
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+project test
+ : requirements
+ <toolset>msvc:<debug-symbols>off
+ ;
+
+build-project doc-info ;
+build-project unit ;
+build-project command-line ;
+build-project snippets ;
+build-project "include" ;
+build-project versions ;
+build-project xinclude ;
+
+import quickbook-testing : quickbook-test quickbook-error-test ;
+
+test-suite quickbook.test :
+ [ quickbook-test anchor-1_1 ]
+ [ quickbook-test anchor-1_6 ]
+ [ quickbook-test blocks-1_5 ]
+ [ quickbook-test callouts-1_5 ]
+ [ quickbook-test code-1_1 ]
+ [ quickbook-test code-1_5 ]
+ [ quickbook-test code_cpp-1_5 ]
+ [ quickbook-error-test code_cpp_mismatched_escape-1_4-fail ]
+ [ quickbook-test code_python-1_5 ]
+ [ quickbook-error-test code_python_mismatched_escape-1_4-fail ]
+ [ quickbook-test code_snippet-1_1 ]
+ [ quickbook-test code_teletype-1_5 ]
+ [ quickbook-test command_line_macro-1_1 : : :
+ <quickbook-test-define>__macro__=*bold*
+ <quickbook-test-define>__empty__ ]
+ [ quickbook-error-test command_line_macro-1_1-invalid :
+ command_line_macro-1_1.quickbook :
+ <testing.arg>-Dsomething[] ]
+ [ quickbook-test cond_phrase-1_5 ]
+ [ quickbook-test elements-1_5 ]
+ [ quickbook-test elements-1_6 ]
+ [ quickbook-test escape-1_1 ]
+ [ quickbook-test escape-1_6 ]
+ [ quickbook-error-test escape-mismatched-1_5-fail ]
+ [ quickbook-test heading-1_1 ]
+ [ quickbook-test heading-1_3 ]
+ [ quickbook-test heading-1_5 ]
+ [ quickbook-test heading-1_6 ]
+ [ quickbook-error-test heading_unclosed-1_4-fail ]
+ [ quickbook-test hr-1_5 ]
+ [ quickbook-test hr-1_6 ]
+ [ quickbook-test identifier-1_5 ]
+ [ quickbook-test identifier-1_6 ]
+ [ quickbook-test image-1_5 ]
+ [ quickbook-test image-1_6 ]
+ [ quickbook-error-test import-1_1-fail ]
+ [ quickbook-error-test include-1_1-fail ]
+ [ quickbook-test include-1_5 ]
+ [ quickbook-test include-1_6 ]
+ [ quickbook-test include2-1_6 ]
+ [ quickbook-error-test include_win_path-1_6-fail ]
+ [ quickbook-test link-1_1 ]
+ [ quickbook-test link-1_6 ]
+ [ quickbook-test list_test-1_5 ]
+ [ quickbook-test list_test-1_6 ]
+ [ quickbook-test macro-1_5 ]
+ [ quickbook-test macro-1_6 ]
+ [ quickbook-error-test mismatched_brackets-1_1-fail ]
+ [ quickbook-test mismatched_brackets1-1_1 ]
+ [ quickbook-test mismatched_brackets2-1_1 ]
+ [ quickbook-test newline-1_1 ]
+ [ quickbook-test para_test-1_5 ]
+ [ quickbook-error-test post_process-fail ]
+ [ quickbook-test preformatted-1_1 ]
+ [ quickbook-test preformatted-1_6 ]
+ [ quickbook-test role-1_6 ]
+ [ quickbook-test section-1_4 ]
+ [ quickbook-test section-1_5-unclosed ]
+ [ quickbook-test section-1_5 ]
+ [ quickbook-test simple_markup-1_5 ]
+ [ quickbook-test svg-1_1 ]
+ [ quickbook-test table-1_3 ]
+ [ quickbook-test table-1_5 ]
+ [ quickbook-test table-1_6 ]
+ [ quickbook-error-test template_arguments1-1_1-fail ]
+ [ quickbook-error-test template_arguments2-1_1-fail ]
+ [ quickbook-error-test template_arguments3-1_1-fail ]
+ [ quickbook-test template_section-1_5 ]
+ [ quickbook-error-test template_section1-1_5-fail ]
+ [ quickbook-error-test template_section2-1_5-fail ]
+ [ quickbook-error-test template_section3-1_5-fail ]
+ [ quickbook-test templates-1_3 ]
+ [ quickbook-test templates-1_4 ]
+ [ quickbook-test templates-1_5 ]
+ [ quickbook-test unicode_escape-1_5 ]
+ [ quickbook-test unmatched_element-1_5 ]
+ [ quickbook-test unmatched_element-1_6 ]
+ [ quickbook-error-test utf16be_bom-1_5-fail ]
+ [ quickbook-error-test utf16le_bom-1_5-fail ]
+ [ quickbook-test utf8-1_5 ]
+ [ quickbook-test utf8_bom-1_5 ]
+ [ quickbook-error-test variablelist-1_5-fail ]
+ [ quickbook-test variablelist-1_5 ]
+ [ quickbook-error-test version-0_1-fail ]
+ [ quickbook-error-test version-1_7-fail ]
+ [ quickbook-error-test version-2_0-fail ]
+ [ quickbook-test xml_escape-1_2 ]
+ [ quickbook-test xml_escape-1_5 ]
+
+ [ quickbook-test quickbook_manual-1_4 ]
+ ;
diff --git a/tools/quickbook/test/anchor-1_1.gold b/tools/quickbook/test/anchor-1_1.gold
new file mode 100644
index 0000000000..e0b8209719
--- /dev/null
+++ b/tools/quickbook/test/anchor-1_1.gold
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="anchor_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Anchor Test</title>
+ <section id="anchor_test.anchors">
+ <title>Anchors</title>
+ <para>
+ <anchor id="a1"/>A paragraph containing several anchors. <anchor id="a2"/>We
+ want to make sure they appear in the correct place. <anchor id="a3"/>
+ </para>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h0">
+ <phrase id="anchor_test.anchors.this_heading_shouldn_t_pick_up_the_previous_anchor"/><link
+ linkend="anchor_test.anchors.this_heading_shouldn_t_pick_up_the_previous_anchor">This
+ heading shouldn't pick up the previous anchor</link>
+ </bridgehead>
+ <anchor id="a4"/>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h1">
+ <phrase id="anchor_test.anchors.this_heading_should_pick_up_the_previous_anchor"/><link
+ linkend="anchor_test.anchors.this_heading_should_pick_up_the_previous_anchor">This
+ heading should pick up the previous anchor</link>
+ </bridgehead>
+ <anchor id="a5"/>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h2">
+ <phrase id="anchor_test.anchors.and_this_one"/><link linkend="anchor_test.anchors.and_this_one">And
+ this one</link>
+ </bridgehead>
+ <anchor id="a6"/>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h3">
+ <phrase id="anchor_test.anchors.also_this_one"/><link linkend="anchor_test.anchors.also_this_one">Also
+ this one</link>
+ </bridgehead>
+ <anchor id="a7"/>
+ <bridgehead renderas="sect3" id="anchors.finally_this">
+ Finally this
+ </bridgehead>
+ <anchor id="a8"/>
+ </section>
+ <section id="anchor_test.section_anchor">
+ <title><anchor id="a9"/>Section Anchor</title>
+ <section id="anchor_test.nested_section">
+ <title><anchor id="a10"/>Nested Section</title>
+ </section>
+ <anchor id="a11"/>
+ </section>
+ <section id="anchor_test.conditional_section_anchor">
+ <title><anchor id="a12"/>Conditional Section Anchor</title>
+ </section>
+ <section id="anchor_test.lists">
+ <title>Lists</title> <anchor id="a14"/>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Item 1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Item 2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Nested List <anchor id="a15"/>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Nested Item 1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Nested Item 2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <anchor id="a16"/>Nested Item 3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Item 3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="anchor_test.anchors_in_templates">
+ <title>Anchors in templates</title>
+ <para>
+ <anchor id="t1"/>Some text.
+ </para>
+ <para>
+ <anchor id="t2"/>Text content
+ </para>
+ </section>
+ <section id="anchor_test.anchors_in_syntax_highlighted_code">
+ <title>Anchors in syntax highlighted code</title>
+<programlisting><phrase role="keyword">int</phrase> <anchor id="s1"/><phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase>
+</programlisting>
+ </section>
+ <section id="anchor_test.nested_anchors">
+ <title>Nested anchors</title>
+ <table frame="all" id="anchor_test.nested_anchors.t0">
+ <title>Table with anchors</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <anchor id="table1"/>Cell 1
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <anchor id="table2"/>Cell 2
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Cell 3<anchor id="table3"/>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+</article>
diff --git a/tools/quickbook/test/anchor-1_1.quickbook b/tools/quickbook/test/anchor-1_1.quickbook
new file mode 100644
index 0000000000..0e8934ee06
--- /dev/null
+++ b/tools/quickbook/test/anchor-1_1.quickbook
@@ -0,0 +1,80 @@
+[article Anchor Test]
+
+[section Anchors]
+
+[#a1] A paragraph containing several anchors. [#a2] We want to make sure
+they appear in the correct place. [#a3]
+
+[heading This heading shouldn't pick up the previous anchor]
+
+[#a4]
+
+[heading This heading should pick up the previous anchor]
+
+[#a5]
+[heading And this one]
+
+[#a6][heading Also this one]
+
+[#a7][h3 Finally this]
+
+[#a8]
+
+[endsect]
+
+[#a9]
+[section Section Anchor]
+[#a10][section Nested Section]
+[endsect]
+[/ This anchor is invalid, I'm not sure what to do with it]
+[#a11]
+[endsect]
+
+[#a12][?__not_defined__ #a13]
+[section Conditional Section Anchor]
+[endsect]
+
+[section Lists]
+
+[#a14]
+* Item 1
+* Item 2
+* Nested List
+ [#a15]
+ * Nested Item 1
+ * Nested Item 2
+ * [#a16] Nested Item 3
+* Item 3
+
+[endsect]
+
+[section Anchors in templates]
+
+[template anchor1[][#t1]]
+[template para[] Text content]
+
+[anchor1]
+
+Some text.
+
+[#t2]
+
+[para]
+
+[endsect]
+
+[section Anchors in syntax highlighted code]
+
+ int ``[#s1]``main() {}
+
+[endsect]
+
+[section Nested anchors]
+
+[table Table with anchors
+ [[Heading]]
+ [[[#table1]Cell 1]]
+ [[[#table2] Cell 2]]
+ [[Cell 3[#table3]]]
+]
+[endsect]
diff --git a/tools/quickbook/test/anchor-1_6.gold b/tools/quickbook/test/anchor-1_6.gold
new file mode 100644
index 0000000000..5d056f2dbf
--- /dev/null
+++ b/tools/quickbook/test/anchor-1_6.gold
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="anchor_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Anchor Test</title>
+ <section id="anchor_test.anchors">
+ <title><link linkend="anchor_test.anchors">Anchors</link></title>
+ <para>
+ <anchor id="a1"/>A paragraph containing several anchors. <anchor id="a2"/>We
+ want to make sure they appear in the correct place. <anchor id="a3"/>
+ </para>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h0">
+ <phrase id="anchor_test.anchors.this_heading_shouldn_t_pick_up_t"/><link linkend="anchor_test.anchors.this_heading_shouldn_t_pick_up_t">This
+ heading shouldn't pick up the previous anchor</link>
+ </bridgehead>
+ <anchor id="a4"/>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h1">
+ <phrase id="anchor_test.anchors.this_heading_should_pick_up_the_"/><link linkend="anchor_test.anchors.this_heading_should_pick_up_the_">This
+ heading should pick up the previous anchor</link>
+ </bridgehead>
+ <anchor id="a5"/>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h2">
+ <phrase id="anchor_test.anchors.and_this_one"/><link linkend="anchor_test.anchors.and_this_one">And
+ this one</link>
+ </bridgehead>
+ <anchor id="a6"/>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h3">
+ <phrase id="anchor_test.anchors.also_this_one"/><link linkend="anchor_test.anchors.also_this_one">Also
+ this one</link>
+ </bridgehead>
+ <anchor id="a7"/>
+ <bridgehead renderas="sect3" id="anchor_test.anchors.h4">
+ <phrase id="anchor_test.anchors.finally_this"/><link linkend="anchor_test.anchors.finally_this">Finally
+ this</link>
+ </bridgehead>
+ <anchor id="a8"/>
+ </section>
+ <section id="anchor_test.section_anchor">
+ <title><anchor id="a9"/><link linkend="anchor_test.section_anchor">Section Anchor</link></title>
+ <section id="anchor_test.section_anchor.nested_section">
+ <title><anchor id="a10"/><link linkend="anchor_test.section_anchor.nested_section">Nested
+ Section</link></title>
+ </section>
+ <anchor id="a11"/>
+ </section>
+ <section id="anchor_test.conditional_section_anchor">
+ <title><anchor id="a12"/><link linkend="anchor_test.conditional_section_anchor">Conditional
+ Section Anchor</link></title>
+ </section>
+ <section id="anchor_test.lists">
+ <title><link linkend="anchor_test.lists">Lists</link></title> <anchor id="a14"/>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Item 1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Item 2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Nested List <anchor id="a15"/>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Nested Item 1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Nested Item 2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <anchor id="a16"/>Nested Item 3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Item 3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="anchor_test.anchors_in_templates">
+ <title><link linkend="anchor_test.anchors_in_templates">Anchors in templates</link></title>
+ <para>
+ <anchor id="t1"/>Some text.
+ </para>
+ <para>
+ <anchor id="t2"/>Text content
+ </para>
+ </section>
+ <section id="anchor_test.anchors_in_syntax_highlighted_co">
+ <title><link linkend="anchor_test.anchors_in_syntax_highlighted_co">Anchors in
+ syntax highlighted code</link></title>
+<programlisting><phrase role="keyword">int</phrase> <anchor id="s1"/><phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase>
+</programlisting>
+ </section>
+ <section id="anchor_test.nested_anchors">
+ <title><link linkend="anchor_test.nested_anchors">Nested anchors</link></title>
+ <table frame="all" id="anchor_test.nested_anchors.table_with_anchors">
+ <title>Table with anchors</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <anchor id="table1"/>Cell 1
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <anchor id="table2"/>Cell 2
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Cell 3<anchor id="table3"/>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="anchor_test.anchors_with_escapes">
+ <title><link linkend="anchor_test.anchors_with_escapes">Anchors with escapes</link></title>
+ <anchor id="[oddid]"/>
+ </section>
+</article>
diff --git a/tools/quickbook/test/anchor-1_6.quickbook b/tools/quickbook/test/anchor-1_6.quickbook
new file mode 100644
index 0000000000..8d4a7b34e1
--- /dev/null
+++ b/tools/quickbook/test/anchor-1_6.quickbook
@@ -0,0 +1,88 @@
+[article Anchor Test
+[quickbook 1.6]
+]
+
+[section Anchors]
+
+[#a1] A paragraph containing several anchors. [#a2] We want to make sure
+they appear in the correct place. [#a3]
+
+[heading This heading shouldn't pick up the previous anchor]
+
+[#a4]
+
+[heading This heading should pick up the previous anchor]
+
+[#a5]
+[heading And this one]
+
+[#a6][heading Also this one]
+
+[#a7][h3 Finally this]
+
+[#a8]
+
+[endsect]
+
+[#a9]
+[section Section Anchor]
+[#a10][section Nested Section]
+[endsect]
+[/ This anchor is invalid, I'm not sure what to do with it]
+[#a11]
+[endsect]
+
+[#a12][?__not_defined__ #a13]
+[section Conditional Section Anchor]
+[endsect]
+
+[section Lists]
+
+[#a14]
+* Item 1
+* Item 2
+* Nested List
+ [#a15]
+ * Nested Item 1
+ * Nested Item 2
+ * [#a16] Nested Item 3
+* Item 3
+
+[endsect]
+
+[section Anchors in templates]
+
+[template anchor1[][#t1]]
+[template para[] Text content]
+
+[anchor1]
+
+Some text.
+
+[#t2]
+
+[para]
+
+[endsect]
+
+[section Anchors in syntax highlighted code]
+
+ int ``[#s1]``main() {}
+
+[endsect]
+
+[section Nested anchors]
+
+[table Table with anchors
+ [[Heading]]
+ [[[#table1]Cell 1]]
+ [[[#table2] Cell 2]]
+ [[Cell 3[#table3]]]
+]
+[endsect]
+
+[section Anchors with escapes]
+
+[#\[oddid\]]
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/blocks-1_5.gold b/tools/quickbook/test/blocks-1_5.gold
new file mode 100644
index 0000000000..2d7370be68
--- /dev/null
+++ b/tools/quickbook/test/blocks-1_5.gold
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="various_blocks" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Various blocks</title>
+ <bridgehead renderas="sect2" id="various_blocks.h0">
+ <phrase id="various_blocks.blockquotes"/><link linkend="various_blocks.blockquotes">Blockquotes</link>
+ </bridgehead>
+ <para>
+ Here's a blockquote:
+ </para>
+ <blockquote>
+ <para>
+ Blockquote.
+ </para>
+ </blockquote>
+ <para>
+ And another:
+ </para>
+ <blockquote>
+ <para>
+ Blockquote first paragraph.
+ </para>
+ <para>
+ Blockquote second paragraph.
+ </para>
+ </blockquote>
+ <bridgehead renderas="sect2" id="various_blocks.h1">
+ <phrase id="various_blocks.admonitions"/><link linkend="various_blocks.admonitions">Admonitions</link>
+ </bridgehead>
+ <warning>
+ <para>
+ Warning
+ </para>
+ </warning>
+ <caution>
+ <para>
+ Caution
+ </para>
+ </caution>
+ <important>
+ <para>
+ Important
+ </para>
+ </important>
+ <note>
+ <para>
+ Note
+ </para>
+ </note>
+ <tip>
+ <para>
+ Tip
+ </para>
+ </tip>
+ <warning>
+ <para>
+ Warning first paragraph.
+ </para>
+ <para>
+ Warning second paragraph.
+ </para>
+ </warning>
+ <bridgehead renderas="sect2" id="various_blocks.h2">
+ <phrase id="various_blocks.blurb"/><link linkend="various_blocks.blurb">Blurb</link>
+ </bridgehead>
+ <sidebar role="blurb">
+ <para>
+ Blurb
+ </para>
+ </sidebar>
+ <bridgehead renderas="sect2" id="various_blocks.h3">
+ <phrase id="various_blocks.inline_blocks"/><link linkend="various_blocks.inline_blocks">Inline
+ blocks</link>
+ </bridgehead>
+ <blockquote>
+ <para>
+ Blockquote containing a footnote<footnote id="various_blocks.f0">
+ <para>
+ Here it is!
+ </para>
+ </footnote>.
+ </para>
+ </blockquote>
+ <para>
+ [tipping point]
+ </para>
+ <para>
+ Multiple paragraphs because of the inline blocks.
+ </para>
+ <warning>
+ <para>
+ Warning
+ </para>
+ </warning>
+ <para>
+ This line should appear as a separate paragraph.
+ </para>
+ <warning>
+ <para>
+ Warning
+ </para>
+ </warning>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ This should be a list item because it's preceded by block markup.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+</article>
diff --git a/tools/quickbook/test/blocks-1_5.quickbook b/tools/quickbook/test/blocks-1_5.quickbook
new file mode 100644
index 0000000000..2632a0fd62
--- /dev/null
+++ b/tools/quickbook/test/blocks-1_5.quickbook
@@ -0,0 +1,46 @@
+[article Various blocks
+[quickbook 1.5]
+]
+
+[heading Blockquotes]
+
+Here's a blockquote:
+
+[:Blockquote.]
+
+And another:
+
+[:
+Blockquote first paragraph.
+
+Blockquote second paragraph.
+]
+
+[heading Admonitions]
+
+[warning Warning]
+[caution Caution]
+[important Important]
+[note Note]
+[tip Tip]
+
+[warning Warning first paragraph.
+
+Warning second paragraph.]
+
+[heading Blurb]
+
+[blurb Blurb]
+
+[heading Inline blocks]
+
+[: Blockquote containing a footnote[footnote Here it is!].]
+
+[/ Unfortunately footnotes currently can't contain blocks.]
+
+[/ Quickbook shouldn't think that this is a tip]
+[tipping point]
+
+Multiple paragraphs because of the inline blocks. [warning Warning] This
+line should appear as a separate paragraph.[warning Warning]
+* This should be a list item because it's preceded by block markup. \ No newline at end of file
diff --git a/tools/quickbook/test/callouts-1_5.gold b/tools/quickbook/test/callouts-1_5.gold
new file mode 100644
index 0000000000..5b66c9933e
--- /dev/null
+++ b/tools/quickbook/test/callouts-1_5.gold
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="callout_tests" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Callout Tests</title>
+ <para>
+ Example 1:
+ </para>
+ <para>
+ Now we can define a function that simulates an ordinary six-sided die.
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.c0" linkends="callout_tests.c1" />
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.c0" id="callout_tests.c1">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 2:
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.c2" linkends="callout_tests.c3" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.c2" id="callout_tests.c3">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 3:
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.c4" linkends="callout_tests.c5" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.c4" id="callout_tests.c5">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 3 (again!):
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.c6" linkends="callout_tests.c7" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.c6" id="callout_tests.c7">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 4:
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.c8" linkends="callout_tests.c9" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+ <co id="callout_tests.c10" linkends="callout_tests.c11" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.c12" linkends="callout_tests.c13" />
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.c8" id="callout_tests.c9">
+ <para>
+ callout 1
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.c10" id="callout_tests.c11">
+ <para>
+ callout 2
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.c12" id="callout_tests.c13">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+ <para>
+<programlisting><co id="callout_tests.c14" linkends="callout_tests.c15" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.c16" linkends="callout_tests.c17" />
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.c14" id="callout_tests.c15">
+ <para>
+ callout 2
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.c16" id="callout_tests.c17">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+ <section id="callout_tests.test_section">
+ <title><link linkend="callout_tests.test_section">Try callouts in a section</link></title>
+ <para>
+ Example 1:
+ </para>
+ <para>
+ Now we can define a function that simulates an ordinary six-sided die.
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.test_section.c0" linkends="callout_tests.test_section.c1" />
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c0" id="callout_tests.test_section.c1">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 2:
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.test_section.c2" linkends="callout_tests.test_section.c3" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c2" id="callout_tests.test_section.c3">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 3:
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.test_section.c4" linkends="callout_tests.test_section.c5" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c4" id="callout_tests.test_section.c5">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 3 (again!):
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.test_section.c6" linkends="callout_tests.test_section.c7" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c6" id="callout_tests.test_section.c7">
+ <important>
+ <para>
+ test
+ </para>
+ </important>
+ </callout>
+ </calloutlist>
+ <para>
+ Example 4:
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests.test_section.c8" linkends="callout_tests.test_section.c9" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+ <co id="callout_tests.test_section.c10" linkends="callout_tests.test_section.c11" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.test_section.c12" linkends="callout_tests.test_section.c13" />
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c8" id="callout_tests.test_section.c9">
+ <para>
+ callout 1
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.test_section.c10" id="callout_tests.test_section.c11">
+ <para>
+ callout 2
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.test_section.c12" id="callout_tests.test_section.c13">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+ <para>
+<programlisting><co id="callout_tests.test_section.c14" linkends="callout_tests.test_section.c15" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests.test_section.c16" linkends="callout_tests.test_section.c17" />
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests.test_section.c14" id="callout_tests.test_section.c15">
+ <para>
+ callout 2
+ </para>
+ </callout>
+ <callout arearefs="callout_tests.test_section.c16" id="callout_tests.test_section.c17">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+ </section>
+</article>
diff --git a/tools/quickbook/test/callouts-1_5.quickbook b/tools/quickbook/test/callouts-1_5.quickbook
new file mode 100644
index 0000000000..b17e90489c
--- /dev/null
+++ b/tools/quickbook/test/callouts-1_5.quickbook
@@ -0,0 +1,51 @@
+[article Callout Tests
+ [quickbook 1.5]
+]
+
+[import callouts.cpp]
+
+Example 1:
+
+[example1]
+
+Example 2:
+
+[example2]
+
+Example 3:
+
+[example3]
+
+Example 3 (again!):
+
+[example3]
+
+Example 4:
+
+[example4]
+[example4a]
+
+[section:test_section Try callouts in a section]
+
+Example 1:
+
+[example1]
+
+Example 2:
+
+[example2]
+
+Example 3:
+
+[example3]
+
+Example 3 (again!):
+
+[example3]
+
+Example 4:
+
+[example4]
+[example4a]
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/callouts.cpp b/tools/quickbook/test/callouts.cpp
new file mode 100644
index 0000000000..82981e7159
--- /dev/null
+++ b/tools/quickbook/test/callouts.cpp
@@ -0,0 +1,50 @@
+
+// Copyright 2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
+
+/*< This shouldn't be used. >*/
+
+//[ example1
+
+/*`
+ Now we can define a function that simulates an ordinary
+ six-sided die.
+*/
+int roll_die() {
+ boost::uniform_int<> dist(1, 6); /*< create a uniform_int distribution >*/
+}
+
+//]
+
+//[ example2
+
+int roll_die() {
+ /*<< [important test] >>*/
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+}
+
+//]
+
+//[ example3
+
+int roll_die() {
+ /*<< [important test]
+ >>*/
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+}
+
+//]
+
+//[ example4
+
+int roll_die() {
+ /*<< callout 1 >>*/
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+//[ example4a
+ /*<< callout 2 >>*/
+ boost::uniform_int<> dist(1, 6); /*< create a uniform_int distribution >*/
+//]
+}
+
+//]
diff --git a/tools/quickbook/test/code-1_1.gold b/tools/quickbook/test/code-1_1.gold
new file mode 100644
index 0000000000..d7382593b3
--- /dev/null
+++ b/tools/quickbook/test/code-1_1.gold
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="code_block" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Code Block</title>
+ <section id="code_block.test_1">
+ <title>Test 1</title>
+ <para>
+ A code block with proper indentation ;-)
+ </para>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">iostream</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;Hello, World!&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </section>
+ <section id="code_block.test_2">
+ <title>Test 2</title>
+ <para>
+ A code block with proper indentation ;-)
+ </para>
+ <para>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">iostream</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;Hello, World!&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ </section>
+ <section id="code_block.test_3">
+ <title>Test 3</title>
+ <para>
+<programlisting><phrase role="keyword">print</phrase> <phrase role="string">&quot;\xfabln\xeck&quot;</phrase>
+</programlisting>
+ </para>
+ </section>
+ <section id="code_block.test_4">
+ <title>Test 4</title>
+ <para>
+ This isn't valid C++ but I think we should accept it;
+ </para>
+ <para>
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase><phrase role="special">&lt;&lt;</phrase><phrase role="string">&quot;\xfabln\xeck&quot;</phrase><phrase role="special">&lt;&lt;</phrase><phrase role="string">&quot;\n&quot;</phrase><phrase role="special">;</phrase>
+</programlisting>
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/code-1_1.quickbook b/tools/quickbook/test/code-1_1.quickbook
new file mode 100644
index 0000000000..8c800911a9
--- /dev/null
+++ b/tools/quickbook/test/code-1_1.quickbook
@@ -0,0 +1,51 @@
+[article Code Block]
+
+[section Test 1]
+
+A code block with proper indentation ;-)
+
+ #include <iostream>
+
+ int main()
+ {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+
+[endsect]
+
+[section Test 2]
+
+A code block with proper indentation ;-)
+
+``
+ #include <iostream>
+
+ int main()
+ {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+``
+
+[endsect]
+
+[section Test 3]
+
+[python]
+``
+ print "\xfabln\xeck"
+``
+
+[endsect]
+
+[section Test 4]
+
+This isn't valid C++ but I think we should accept it;
+
+[c++]
+``
+ std::cout<<"\xfabln\xeck"<<"\n";
+``
+
+[endsect]
diff --git a/tools/quickbook/test/code-1_5.gold b/tools/quickbook/test/code-1_5.gold
new file mode 100644
index 0000000000..8ca2281263
--- /dev/null
+++ b/tools/quickbook/test/code-1_5.gold
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="indented_code_blocks" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Indented code blocks</title>
+ <para>
+ In a paragraph. Still in a paragraph.
+ </para>
+<programlisting>In a code block.
+</programlisting>
+ <para>
+ Back in a paragraph.
+ </para>
+<programlisting> Code block line 1.
+Code block line 2.
+ Code block line 3.
+</programlisting>
+ <para>
+ Paragraph.
+ </para>
+<programlisting>Code block with no trailing blank lines.
+</programlisting>
+ <para>
+ Paragraph.
+ </para>
+ <bridgehead renderas="sect2" id="indented_code_blocks.h0">
+ <phrase id="indented_code_blocks.code_blocks_separated_by_comment"/><link linkend="indented_code_blocks.code_blocks_separated_by_comment">Code
+ blocks separated by comment</link>
+ </bridgehead>
+<programlisting>First code block.
+</programlisting>
+<programlisting>Second code block.
+[/ Comment in second code block]
+Still second code block.
+[/ Comment trailing second code block]
+</programlisting>
+</article>
diff --git a/tools/quickbook/test/code-1_5.quickbook b/tools/quickbook/test/code-1_5.quickbook
new file mode 100644
index 0000000000..de377a64fe
--- /dev/null
+++ b/tools/quickbook/test/code-1_5.quickbook
@@ -0,0 +1,29 @@
+[article Indented code blocks
+ [quickbook 1.5]
+ [source-mode teletype]
+]
+
+In a paragraph.
+ Still in a paragraph.
+
+ In a code block.
+
+Back in a paragraph.
+
+ Code block line 1.
+ Code block line 2.
+ Code block line 3.
+
+Paragraph.
+
+ Code block with no trailing blank lines.
+Paragraph.
+
+[heading Code blocks separated by comment]
+
+ First code block.
+[/ Comment]
+ Second code block.
+ [/ Comment in second code block]
+ Still second code block.
+ [/ Comment trailing second code block]
diff --git a/tools/quickbook/test/code_cpp-1_5.gold b/tools/quickbook/test/code_cpp-1_5.gold
new file mode 100644
index 0000000000..be33bfdfd3
--- /dev/null
+++ b/tools/quickbook/test/code_cpp-1_5.gold
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="c___code_blocks" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>C++ Code Blocks</title>
+<programlisting><phrase role="comment">// No escape</phrase>
+<phrase role="comment">/* No escape */</phrase>
+<phrase role="comment">/* No escape
+ * with newlines
+ */</phrase>
+<phrase role="comment">// In Header: &lt;<ulink url="boost:/boost/optional/optional.hpp">boost/optional/optional.hpp</ulink>&gt;</phrase>
+<phrase role="comment">/* In Header: &lt;<ulink url="boost:/boost/optional/optional.hpp">boost/optional/optional.hpp</ulink>&gt; */</phrase>
+<phrase role="comment">/* Multiple escapes: <emphasis>italic</emphasis>
+ * <emphasis role="underline">underline</emphasis><emphasis role="bold">bold</emphasis>
+ */</phrase>
+</programlisting>
+ <para>
+ A badly formed comment:
+ </para>
+<programlisting><phrase role="comment">/* Oh dear
+</phrase></programlisting>
+ <para>
+ A badly formed comment with an escape:
+ </para>
+<programlisting><phrase role="comment">/* Oh dear <emphasis role="bold">bold</emphasis>
+</phrase></programlisting>
+</article>
diff --git a/tools/quickbook/test/code_cpp-1_5.quickbook b/tools/quickbook/test/code_cpp-1_5.quickbook
new file mode 100644
index 0000000000..be8043a018
--- /dev/null
+++ b/tools/quickbook/test/code_cpp-1_5.quickbook
@@ -0,0 +1,22 @@
+[article C++ Code Blocks
+[quickbook 1.5]
+]
+
+ // No escape
+ /* No escape */
+ /* No escape
+ * with newlines
+ */
+ // In Header: <``[@boost:/boost/optional/optional.hpp boost/optional/optional.hpp]``>
+ /* In Header: <``[@boost:/boost/optional/optional.hpp boost/optional/optional.hpp]``> */
+ /* Multiple escapes: ``/italic/``
+ * ``_underline_````*bold*``
+ */
+
+A badly formed comment:
+
+ /* Oh dear
+
+A badly formed comment with an escape:
+
+ /* Oh dear ``*bold*``
diff --git a/tools/quickbook/test/code_cpp_mismatched_escape-1_4-fail.quickbook b/tools/quickbook/test/code_cpp_mismatched_escape-1_4-fail.quickbook
new file mode 100644
index 0000000000..d5d332c17f
--- /dev/null
+++ b/tools/quickbook/test/code_cpp_mismatched_escape-1_4-fail.quickbook
@@ -0,0 +1,5 @@
+[article Odd code markup. [quickbook 1.4] ]
+
+[c++]
+
+ `` int main() {}
diff --git a/tools/quickbook/test/code_python-1_5.gold b/tools/quickbook/test/code_python-1_5.gold
new file mode 100644
index 0000000000..239d1470ab
--- /dev/null
+++ b/tools/quickbook/test/code_python-1_5.gold
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="python_code_blocks" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Python Code Blocks</title>
+<programlisting><phrase role="comment"># No escape</phrase>
+<phrase role="comment"># Escape: <emphasis role="bold">bold</emphasis></phrase>
+<phrase role="comment"># Escape: <emphasis role="underline">underline</emphasis><emphasis>italic</emphasis></phrase>
+</programlisting>
+</article>
diff --git a/tools/quickbook/test/code_python-1_5.quickbook b/tools/quickbook/test/code_python-1_5.quickbook
new file mode 100644
index 0000000000..45e700ecb6
--- /dev/null
+++ b/tools/quickbook/test/code_python-1_5.quickbook
@@ -0,0 +1,8 @@
+[article Python Code Blocks
+[quickbook 1.5]
+[source-mode python]
+]
+
+ # No escape
+ # Escape: ``*bold*``
+ # Escape: ``_underline_````/italic/``
diff --git a/tools/quickbook/test/code_python_mismatched_escape-1_4-fail.quickbook b/tools/quickbook/test/code_python_mismatched_escape-1_4-fail.quickbook
new file mode 100644
index 0000000000..e93cf13f17
--- /dev/null
+++ b/tools/quickbook/test/code_python_mismatched_escape-1_4-fail.quickbook
@@ -0,0 +1,5 @@
+[article Odd code markup. [quickbook 1.4] ]
+
+[python]
+
+ print "Hello World." ``
diff --git a/tools/quickbook/test/code_snippet-1_1.gold b/tools/quickbook/test/code_snippet-1_1.gold
new file mode 100644
index 0000000000..1badf4babc
--- /dev/null
+++ b/tools/quickbook/test/code_snippet-1_1.gold
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="code_snippets" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Code Snippets</title>
+ <section id="code_snippets.a_code_snippet">
+ <title>A code snippet</title>
+ <para>
+ Code snippets inlined in text, as in <code><phrase role="keyword">namespace</phrase>
+ <phrase role="identifier">quickbook</phrase> <phrase role="special">{</phrase>
+ <phrase role="keyword">static</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="keyword">int</phrase> <phrase role="identifier">value</phrase>
+ <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase></code>, should be properly formatted and
+ not glued to the surrounding text.
+ </para>
+ <para>
+ There shoud be no spacees around (<code><phrase role="keyword">this</phrase></code>),
+ and spaces around <code><phrase role="keyword">this</phrase></code> code.
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/code_snippet-1_1.quickbook b/tools/quickbook/test/code_snippet-1_1.quickbook
new file mode 100644
index 0000000000..875162708c
--- /dev/null
+++ b/tools/quickbook/test/code_snippet-1_1.quickbook
@@ -0,0 +1,12 @@
+[article Code Snippets
+]
+
+[section A code snippet]
+
+Code snippets inlined in text, as in `namespace quickbook { static const int
+value = 0; }`, should be properly formatted and not glued to the surrounding
+text.
+
+There shoud be no spacees around (`this`), and spaces around `this` code.
+
+[endsect]
diff --git a/tools/quickbook/test/code_teletype-1_5.gold b/tools/quickbook/test/code_teletype-1_5.gold
new file mode 100644
index 0000000000..e36fb11bbc
--- /dev/null
+++ b/tools/quickbook/test/code_teletype-1_5.gold
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="code_block_teletype_1" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Code Block Teletype 1</title>
+ <section id="code_block_teletype_1.a_code_block">
+ <title><link linkend="code_block_teletype_1.a_code_block">A code block</link></title>
+<programlisting>Just some plain text.
+With some <emphasis role="bold">quickbook</emphasis> thrown in?
+</programlisting>
+ </section>
+</article>
diff --git a/tools/quickbook/test/code_teletype-1_5.quickbook b/tools/quickbook/test/code_teletype-1_5.quickbook
new file mode 100644
index 0000000000..841de3e545
--- /dev/null
+++ b/tools/quickbook/test/code_teletype-1_5.quickbook
@@ -0,0 +1,13 @@
+[article Code Block Teletype 1
+ [quickbook 1.5]
+ [source-mode teletype]
+]
+
+[section A code block]
+
+[def __text__ text]
+
+ Just some plain __text__.
+ ``With some *quickbook* thrown in?``
+
+[endsect]
diff --git a/tools/quickbook/test/command-line/Jamfile.v2 b/tools/quickbook/test/command-line/Jamfile.v2
new file mode 100644
index 0000000000..052ec82afb
--- /dev/null
+++ b/tools/quickbook/test/command-line/Jamfile.v2
@@ -0,0 +1,28 @@
+
+#
+# Copyright (c) 2011 Daniel James
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+project quickook/tests/command-line ;
+
+import quickbook-testing : quickbook-test quickbook-fail-test quickbook-error-test ;
+
+test-suite command-line.test :
+ # Check that expect-errors works as advertised.
+ [ quickbook-fail-test error-fail : : <testing.arg>--expect-errors ]
+ [ quickbook-error-test error1 ]
+ [ quickbook-error-test error2 ]
+
+ [ quickbook-error-test
+ non_existent_output :
+ basic-1_6.quickbook :
+ <testing.arg>--output-file=non-existent/basic.xml ]
+ [ quickbook-error-test
+ output_nested_in_file :
+ basic-1_6.quickbook :
+ <testing.arg>--output-file=basic-1_6.quickbook/basic.xml ]
+ ; \ No newline at end of file
diff --git a/tools/quickbook/test/command-line/basic-1_6.quickbook b/tools/quickbook/test/command-line/basic-1_6.quickbook
new file mode 100644
index 0000000000..fa8c8a693b
--- /dev/null
+++ b/tools/quickbook/test/command-line/basic-1_6.quickbook
@@ -0,0 +1,5 @@
+[article Basic quickbook file
+[quickbook 1.5]
+]
+
+Just used for running command line tests. \ No newline at end of file
diff --git a/tools/quickbook/test/command-line/error-fail.quickbook b/tools/quickbook/test/command-line/error-fail.quickbook
new file mode 100644
index 0000000000..835f01ad57
--- /dev/null
+++ b/tools/quickbook/test/command-line/error-fail.quickbook
@@ -0,0 +1,5 @@
+[article Valid file to just that expect errors fails
+[quickbook 1.5]
+]
+
+No errors. \ No newline at end of file
diff --git a/tools/quickbook/test/command-line/error1.quickbook b/tools/quickbook/test/command-line/error1.quickbook
new file mode 100644
index 0000000000..5f76a444e8
--- /dev/null
+++ b/tools/quickbook/test/command-line/error1.quickbook
@@ -0,0 +1,3 @@
+[article A file with an error in the docinfo
+[quickbook 0.8]
+]
diff --git a/tools/quickbook/test/command-line/error2.quickbook b/tools/quickbook/test/command-line/error2.quickbook
new file mode 100644
index 0000000000..2eea16285c
--- /dev/null
+++ b/tools/quickbook/test/command-line/error2.quickbook
@@ -0,0 +1,7 @@
+[article A file with an error in the body
+[quickbook 1.5]
+]
+
+[table
+[x]
+] \ No newline at end of file
diff --git a/tools/quickbook/test/command_line_macro-1_1.gold b/tools/quickbook/test/command_line_macro-1_1.gold
new file mode 100644
index 0000000000..423b5cbba3
--- /dev/null
+++ b/tools/quickbook/test/command_line_macro-1_1.gold
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="command_line_macro" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Command Line Macro</title>
+ <para>
+ <emphasis role="bold">bold</emphasis>
+ </para>
+ <para>
+ empty is defined
+ </para>
+</article>
diff --git a/tools/quickbook/test/command_line_macro-1_1.quickbook b/tools/quickbook/test/command_line_macro-1_1.quickbook
new file mode 100644
index 0000000000..5b19fc0066
--- /dev/null
+++ b/tools/quickbook/test/command_line_macro-1_1.quickbook
@@ -0,0 +1,10 @@
+[article Command Line Macro
+]
+
+[/ This test relies on __macro__ being defined at the command line.]
+
+__macro__
+
+__empty__
+
+[?__empty__ empty is defined] \ No newline at end of file
diff --git a/tools/quickbook/test/cond_phrase-1_5.gold b/tools/quickbook/test/cond_phrase-1_5.gold
new file mode 100644
index 0000000000..95a1d35d75
--- /dev/null
+++ b/tools/quickbook/test/cond_phrase-1_5.gold
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="coniditional_phrase_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Coniditional Phrase Test</title>
+ <para>
+ This should show
+ </para>
+ <para>
+ The should be no space inserted.
+ </para>
+ <para>
+ <emphasis role="bold">Bold text</emphasis>
+ </para>
+</article>
diff --git a/tools/quickbook/test/cond_phrase-1_5.quickbook b/tools/quickbook/test/cond_phrase-1_5.quickbook
new file mode 100644
index 0000000000..e158a251b5
--- /dev/null
+++ b/tools/quickbook/test/cond_phrase-1_5.quickbook
@@ -0,0 +1,12 @@
+[article Coniditional Phrase Test
+ [quickbook 1.5]
+]
+
+[def __defined__]
+
+[? __defined__ This should show]
+[? __undefined__ This should not show]
+
+The should be no sp[?__undefined__ just some junk]ace inserted.
+
+[? __defined__ [*Bold text]] \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/Jamfile.v2 b/tools/quickbook/test/doc-info/Jamfile.v2
new file mode 100644
index 0000000000..f7d262c050
--- /dev/null
+++ b/tools/quickbook/test/doc-info/Jamfile.v2
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2005 João Abecasis
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+project quickook/tests/doc-info ;
+
+import quickbook-testing : quickbook-test quickbook-error-test ;
+
+test-suite quickbook.test :
+ [ quickbook-test escape-1.6 ]
+ [ quickbook-test encode-1.5 ]
+ [ quickbook-test author1 ]
+ [ quickbook-test author2 ]
+ [ quickbook-test empty-attributes ]
+ [ quickbook-test duplicates-1.1 ]
+ [ quickbook-test duplicates-1.5 ]
+ [ quickbook-test source-mode-1.4 ]
+ [ quickbook-test source-mode-1.5 ]
+ [ quickbook-test source-mode-1.6 ]
+ [ quickbook-test copyright1 ]
+ [ quickbook-error-test copyright-fail1 ]
+ [ quickbook-error-test copyright-fail2 ]
+ [ quickbook-test id1-1.5 ]
+ [ quickbook-test title_trailing_space-1_1 ]
+ [ quickbook-test title_trailing_space-1_6 ]
+ [ quickbook-test empty_title-1_1 ]
+ [ quickbook-test empty_title-1_5 ]
+ [ quickbook-test empty_title-1_6 ]
+ [ quickbook-error-test missing_doc_info-1_6-fail ]
+ ;
diff --git a/tools/quickbook/test/doc-info/author1.gold b/tools/quickbook/test/doc-info/author1.gold
new file mode 100644
index 0000000000..613fa83eff
--- /dev/null
+++ b/tools/quickbook/test/doc-info/author1.gold
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE appendix PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<appendix id="document_information_4" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Document Information 4</title>
+ <appendixinfo>
+ <authorgroup>
+ <author>
+ <firstname>Joe</firstname> <surname>Blow</surname>
+ </author>
+ </authorgroup>
+ </appendixinfo>
+</appendix>
diff --git a/tools/quickbook/test/doc-info/author1.quickbook b/tools/quickbook/test/doc-info/author1.quickbook
new file mode 100644
index 0000000000..4505b4091e
--- /dev/null
+++ b/tools/quickbook/test/doc-info/author1.quickbook
@@ -0,0 +1,5 @@
+[appendix Document Information 4
+[quickbook 1.5]
+[authors [Blow, Joe]]
+]
+[/ Some comment] \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/author2.gold b/tools/quickbook/test/doc-info/author2.gold
new file mode 100644
index 0000000000..766d8f68b2
--- /dev/null
+++ b/tools/quickbook/test/doc-info/author2.gold
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<chapter id="document_information_4" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Document Information 4</title>
+ <chapterinfo>
+ <authorgroup>
+ <author>
+ <firstname>Joe</firstname> <surname>Blow</surname>
+ </author>
+ <author>
+ <firstname>Jane</firstname> <surname>Doe</surname>
+ </author>
+ <author>
+ <firstname>John</firstname> <surname>Coe</surname>
+ </author>
+ </authorgroup>
+ </chapterinfo>
+</chapter>
diff --git a/tools/quickbook/test/doc-info/author2.quickbook b/tools/quickbook/test/doc-info/author2.quickbook
new file mode 100644
index 0000000000..c4737e0acb
--- /dev/null
+++ b/tools/quickbook/test/doc-info/author2.quickbook
@@ -0,0 +1,4 @@
+[chapter Document Information 4
+[quickbook 1.5]
+[authors [Blow, Joe], [Doe, Jane] [Coe, John]]
+] \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/copyright-fail1.quickbook b/tools/quickbook/test/doc-info/copyright-fail1.quickbook
new file mode 100644
index 0000000000..20738cb919
--- /dev/null
+++ b/tools/quickbook/test/doc-info/copyright-fail1.quickbook
@@ -0,0 +1,4 @@
+[article Invalid copyright years
+[quickbook 1.5]
+[copyright 2010-2001 Timequake man]
+] \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/copyright-fail2.quickbook b/tools/quickbook/test/doc-info/copyright-fail2.quickbook
new file mode 100644
index 0000000000..607c3a7895
--- /dev/null
+++ b/tools/quickbook/test/doc-info/copyright-fail2.quickbook
@@ -0,0 +1,6 @@
+[article Invalid copyright
+[quickbook 1.5]
+[copyright No year]
+]
+
+Maybe this should pass? \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/copyright1.gold b/tools/quickbook/test/doc-info/copyright1.gold
new file mode 100644
index 0000000000..3c6d40668e
--- /dev/null
+++ b/tools/quickbook/test/doc-info/copyright1.gold
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="copyright_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Copyright Test</title>
+ <articleinfo>
+ <copyright>
+ <year>1963</year> <year>1964</year> <year>1965</year> <holder>Jane Doe</holder>
+ </copyright>
+ <copyright>
+ <year>2018</year> <holder>Joe Blow, John Coe</holder>
+ </copyright>
+ <copyright>
+ <year>1977</year> <year>1985</year> <holder>Someone else</holder>
+ </copyright>
+ </articleinfo>
+</article>
diff --git a/tools/quickbook/test/doc-info/copyright1.quickbook b/tools/quickbook/test/doc-info/copyright1.quickbook
new file mode 100644
index 0000000000..4dff125fe1
--- /dev/null
+++ b/tools/quickbook/test/doc-info/copyright1.quickbook
@@ -0,0 +1,5 @@
+[article Copyright Test
+[quickbook 1.5]
+[copyright 1963-1965 Jane Doe, 2018 Joe Blow, John Coe]
+[copyright 1977,1985 Someone else]
+] \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/duplicates-1.1.gold b/tools/quickbook/test/doc-info/duplicates-1.1.gold
new file mode 100644
index 0000000000..7ff1fa4b94
--- /dev/null
+++ b/tools/quickbook/test/doc-info/duplicates-1.1.gold
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<library id="thing2" name="Duplicates 1.1" dirname="thing2" last-revision="Tomorrow"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <libraryinfo>
+ <authorgroup>
+ <author>
+ <firstname>Joe</firstname> <surname>Blow</surname>
+ </author>
+ <author>
+ <firstname>Jane</firstname> <surname>Doe</surname>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2018</year> <holder>Joe Blow</holder>
+ </copyright>
+ <copyright>
+ <year>1963</year> <holder>Jane Doe</holder>
+ </copyright>
+ <legalnotice id="thing2.legal">
+ <para>
+ Public Domain
+ </para>
+ </legalnotice>
+ <librarypurpose>
+ Another Duplicate
+ </librarypurpose>
+ <librarycategory name="category:Category 1"></librarycategory> <librarycategory
+ name="category:Category 2"></librarycategory>
+ </libraryinfo>
+ <title>Duplicates 1.1 2</title>
+ <para>
+ Content
+ </para>
+</library>
diff --git a/tools/quickbook/test/doc-info/duplicates-1.1.quickbook b/tools/quickbook/test/doc-info/duplicates-1.1.quickbook
new file mode 100644
index 0000000000..d5daa2158c
--- /dev/null
+++ b/tools/quickbook/test/doc-info/duplicates-1.1.quickbook
@@ -0,0 +1,23 @@
+[library Duplicates 1.1
+
+[id thing1]
+[id thing2]
+[dirname thing1]
+[dirname thing2]
+[last-revision Yesterday]
+[last-revision Tomorrow]
+[purpose Test Duplicates]
+[purpose Another Duplicate]
+[category Category 1]
+[category Category 2]
+[version 1]
+[version 2]
+[authors [Blow, Joe]]
+[authors [Doe, Jane]]
+[copyright 2018 Joe Blow]
+[copyright 1963 Jane Doe]
+[license Some license]
+[license Public Domain]
+]
+
+Content \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/duplicates-1.5.gold b/tools/quickbook/test/doc-info/duplicates-1.5.gold
new file mode 100644
index 0000000000..71a58a8d10
--- /dev/null
+++ b/tools/quickbook/test/doc-info/duplicates-1.5.gold
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="thing2" lang="de" dirname="thing2" last-revision="Tomorrow" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Duplicates 1.5 2</title>
+ <articleinfo>
+ <authorgroup>
+ <author>
+ <firstname>Joe</firstname> <surname>Blow</surname>
+ </author>
+ <author>
+ <firstname>Jane</firstname> <surname>Doe</surname>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2018</year> <holder>Joe Blow</holder>
+ </copyright>
+ <copyright>
+ <year>1963</year> <holder>Jane Doe</holder>
+ </copyright>
+ <legalnotice id="thing2.legal">
+ <para>
+ Public Domain
+ </para>
+ </legalnotice>
+ <articlepurpose>
+ Another Duplicate
+ </articlepurpose>
+ <articlecategory name="category:Category 1"></articlecategory> <articlecategory
+ name="category:Category 2"></articlecategory> <biblioid class="uri">http://www.boost.org/tools/quickbook/test/doc-info-2.quickbook</biblioid>
+ <biblioid class="isbn">0-937383-18-X</biblioid>
+ </articleinfo>
+</article>
diff --git a/tools/quickbook/test/doc-info/duplicates-1.5.quickbook b/tools/quickbook/test/doc-info/duplicates-1.5.quickbook
new file mode 100644
index 0000000000..99e681aba3
--- /dev/null
+++ b/tools/quickbook/test/doc-info/duplicates-1.5.quickbook
@@ -0,0 +1,26 @@
+[article Duplicates 1.5
+[quickbook 1.5]
+
+[id thing1]
+[id thing2]
+[dirname thing1]
+[dirname thing2]
+[last-revision Yesterday]
+[last-revision Tomorrow]
+[purpose Test Duplicates]
+[purpose Another Duplicate]
+[category Category 1]
+[category Category 2]
+[lang en]
+[lang de]
+[version 1]
+[version 2]
+[authors [Blow, Joe]]
+[authors [Doe, Jane]]
+[copyright 2018 Joe Blow]
+[copyright 1963 Jane Doe]
+[license Some license]
+[license Public Domain]
+[biblioid uri http://www.boost.org/tools/quickbook/test/doc-info-2.quickbook]
+[biblioid isbn 0-937383-18-X]
+]
diff --git a/tools/quickbook/test/doc-info/empty-attributes.gold b/tools/quickbook/test/doc-info/empty-attributes.gold
new file mode 100644
index 0000000000..a7f05f756b
--- /dev/null
+++ b/tools/quickbook/test/doc-info/empty-attributes.gold
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<library id="empty_attributes" name="Empty Attributes" dirname="empty_attributes"
+last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <libraryinfo>
+ <authorgroup>
+ <author>
+ <firstname></firstname> <surname></surname>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2011</year> <holder></holder>
+ </copyright>
+ </libraryinfo>
+ <title>Empty Attributes</title>
+ <para>
+ <literal>biblioid</literal> and <literal>source-mode</literal> can't be empty.
+ </para>
+</library>
diff --git a/tools/quickbook/test/doc-info/empty-attributes.quickbook b/tools/quickbook/test/doc-info/empty-attributes.quickbook
new file mode 100644
index 0000000000..a31dc71998
--- /dev/null
+++ b/tools/quickbook/test/doc-info/empty-attributes.quickbook
@@ -0,0 +1,16 @@
+[library Empty Attributes
+[version]
+[id]
+[dirname]
+[copyright]
+[copyright 2011]
+[purpose]
+[category]
+[authors]
+[authors [,]]
+[license]
+[last-revision]
+[lang]
+]
+
+=biblioid= and =source-mode= can't be empty.
diff --git a/tools/quickbook/test/doc-info/empty_title-1_1.gold b/tools/quickbook/test/doc-info/empty_title-1_1.gold
new file mode 100644
index 0000000000..01bc60673d
--- /dev/null
+++ b/tools/quickbook/test/doc-info/empty_title-1_1.gold
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <section id=".test">
+ <title>Test</title>
+ <para>
+ Hello
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/doc-info/empty_title-1_1.quickbook b/tools/quickbook/test/doc-info/empty_title-1_1.quickbook
new file mode 100644
index 0000000000..45769a983f
--- /dev/null
+++ b/tools/quickbook/test/doc-info/empty_title-1_1.quickbook
@@ -0,0 +1,8 @@
+[article
+]
+
+[section Test]
+
+Hello
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/empty_title-1_5.gold b/tools/quickbook/test/doc-info/empty_title-1_5.gold
new file mode 100644
index 0000000000..034482798f
--- /dev/null
+++ b/tools/quickbook/test/doc-info/empty_title-1_5.gold
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <section id=".test">
+ <title><link linkend=".test">Test</link></title>
+ <para>
+ Hello
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/doc-info/empty_title-1_5.quickbook b/tools/quickbook/test/doc-info/empty_title-1_5.quickbook
new file mode 100644
index 0000000000..99cbf6b797
--- /dev/null
+++ b/tools/quickbook/test/doc-info/empty_title-1_5.quickbook
@@ -0,0 +1,7 @@
+[article
+[quickbook 1.5]
+]
+
+[section Test]
+Hello
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/empty_title-1_6.gold b/tools/quickbook/test/doc-info/empty_title-1_6.gold
new file mode 100644
index 0000000000..1dce22ef0c
--- /dev/null
+++ b/tools/quickbook/test/doc-info/empty_title-1_6.gold
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="doc0" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+</article>
diff --git a/tools/quickbook/test/doc-info/empty_title-1_6.quickbook b/tools/quickbook/test/doc-info/empty_title-1_6.quickbook
new file mode 100644
index 0000000000..bf310afd3a
--- /dev/null
+++ b/tools/quickbook/test/doc-info/empty_title-1_6.quickbook
@@ -0,0 +1 @@
+[quickbook 1.6][article] \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/encode-1.5.gold b/tools/quickbook/test/doc-info/encode-1.5.gold
new file mode 100644
index 0000000000..83870c7c98
--- /dev/null
+++ b/tools/quickbook/test/doc-info/encode-1.5.gold
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<library id="karel_vom__xe1___x10d_ka_and_tom__xe1___x161__martin__xed_k" name="Karel Vom&#xE1;&#x10D;ka and Tom&#xE1;&#x161; Martin&#xED;k"
+dirname="karel_vom__xe1___x10d_ka_and_tom__xe1___x161__martin__xed_k" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <libraryinfo>
+ <authorgroup>
+ <author>
+ <firstname>Matti</firstname> <surname>Meik&#xE4;l&#xE4;inen</surname>
+ </author>
+ <author>
+ <firstname>Pero</firstname> <surname>Peri&#x107;</surname>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2010</year> <holder>Me&#xF0;al-J&#xF3;n and J&#xF3;na J&#xF3;nsd&#xF3;ttir</holder>
+ </copyright>
+ <librarypurpose>
+ Inline code test: <code>1 + 2</code>
+ </librarypurpose>
+ <librarycategory name="category:tests"></librarycategory> <librarycategory name="category:irrelevance"></librarycategory>
+ <biblioid class="uri">http://www.boost.org/tools/quickbook/test/doc-info-2.quickbook</biblioid>
+ <biblioid class="isbn">0-937383-18-X</biblioid>
+ </libraryinfo>
+ <title>Karel Vom&#xE1;&#x10D;ka and Tom&#xE1;&#x161; Martin&#xED;k</title>
+</library>
diff --git a/tools/quickbook/test/doc-info/encode-1.5.quickbook b/tools/quickbook/test/doc-info/encode-1.5.quickbook
new file mode 100644
index 0000000000..c1928c6a87
--- /dev/null
+++ b/tools/quickbook/test/doc-info/encode-1.5.quickbook
@@ -0,0 +1,14 @@
+[library Karel Vom&#xE1;&#x10D;ka and Tom&#xE1;&#x161; Martin&#xED;k
+[quickbook 1.5]
+[authors [Meik&#xE4;l&#xE4;inen, Matti],[Peri&#x107;, Pero]]
+[copyright 2010 Me&#xF0;al-J&#xF3;n and J&#xF3;na J&#xF3;nsd&#xF3;ttir]
+[source-mode teletype]
+[purpose Inline code test: `1 + 2`]
+[category tests]
+[category irrelevance]
+[/ [category commented out] ]
+[biblioid uri http://www.boost.org/tools/quickbook/test/doc-info-2.quickbook]
+[biblioid isbn 0-937383-18-X]
+]
+
+[/ Some comment]
diff --git a/tools/quickbook/test/doc-info/escape-1.6.gold b/tools/quickbook/test/doc-info/escape-1.6.gold
new file mode 100644
index 0000000000..630398679b
--- /dev/null
+++ b/tools/quickbook/test/doc-info/escape-1.6.gold
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="karel_vom_u00e1_u010dka_and_tom_" lang="en" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Karel Vom&#xE1;&#x10D;ka and Tom&#xE1;&#x161; Martin&#xED;k</title>
+ <articleinfo>
+ <authorgroup>
+ <author>
+ <firstname>Matti</firstname> <surname>Meik&#xE4;l&#xE4;inen</surname>
+ </author>
+ <author>
+ <firstname>Pero</firstname> <surname>Peri&#x107;</surname>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2010</year> <holder>Me&#xF0;al-J&#xF3;n and J&#xF3;na J&#xF3;nsd&#xF3;ttir</holder>
+ </copyright>
+ <articlepurpose>
+ Inline code test: <code>1 + 2</code>
+ </articlepurpose>
+ <articlecategory name="category:tests"></articlecategory> <articlecategory name="category:irrelevance"></articlecategory>
+ <biblioid class="uri">http://www.boost.org/tools/quickbook/test/doc-info-1.quickbook</biblioid>
+ </articleinfo>
+</article>
diff --git a/tools/quickbook/test/doc-info/escape-1.6.quickbook b/tools/quickbook/test/doc-info/escape-1.6.quickbook
new file mode 100644
index 0000000000..7ae3e70032
--- /dev/null
+++ b/tools/quickbook/test/doc-info/escape-1.6.quickbook
@@ -0,0 +1,12 @@
+[article Karel Vom\u00E1\u010Dka and Tom\u00E1\u0161 Martin\u00EDk
+[quickbook 1.6]
+[authors [Meik\u00E4l\u00E4inen, Matti][Peri\u0107, Pero]]
+[copyright 2010 Me\u00F0al-J\u00F3n and J\u00F3na J\u00F3nsd\u00F3ttir]
+[source-mode teletype]
+[purpose Inline code test: `1 + 2`]
+[category tests]
+[category irrelevance]
+[/ [category commented out] ]
+[biblioid uri http://www.boost.org/tools/quickbook/test/doc-info-1.quickbook]
+[lang en]
+]
diff --git a/tools/quickbook/test/doc-info/id1-1.5.gold b/tools/quickbook/test/doc-info/id1-1.5.gold
new file mode 100644
index 0000000000..5b55391e2b
--- /dev/null
+++ b/tools/quickbook/test/doc-info/id1-1.5.gold
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="missing_id_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Missing Id test</title>
+ <section id="missing_id_test.missing_id_test_1">
+ <title><link linkend="missing_id_test.missing_id_test_1">Missing Id test 1</link></title>
+ </section>
+ <section id="missing_id_test.no_docinfo_test_1">
+ <title><link linkend="missing_id_test.no_docinfo_test_1">No docinfo test 1</link></title>
+ </section>
+ <section id="missing_id_test.missing_id_test_2">
+ <title><link linkend="missing_id_test.missing_id_test_2">Missing Id test 2</link></title>
+ </section>
+ <section id="docinfo_no_id.docinfo_no_id_1">
+ <title><link linkend="docinfo_no_id.docinfo_no_id_1">Docinfo no id 1</link></title>
+ </section>
+ <section id="missing_id_test.missing_id_test_3">
+ <title><link linkend="missing_id_test.missing_id_test_3">Missing Id test 3</link></title>
+ </section>
+ <section id="docinfo_no_id.no_docinfo_test_1">
+ <title><link linkend="docinfo_no_id.no_docinfo_test_1">No docinfo test 1</link></title>
+ </section>
+ <section id="missing_id_test.missing_id_test_4">
+ <title><link linkend="missing_id_test.missing_id_test_4">Missing Id test 4</link></title>
+ </section>
+</article>
diff --git a/tools/quickbook/test/doc-info/id1-1.5.quickbook b/tools/quickbook/test/doc-info/id1-1.5.quickbook
new file mode 100644
index 0000000000..c7065d0c50
--- /dev/null
+++ b/tools/quickbook/test/doc-info/id1-1.5.quickbook
@@ -0,0 +1,21 @@
+[article Missing Id test
+[quickbook 1.5]
+]
+
+[section Missing Id test 1]
+[endsect]
+
+[include id1-no-docinfo.quickbook]
+
+[section Missing Id test 2]
+[endsect]
+
+[include id1-docinfo-no-id.quickbook]
+
+[section Missing Id test 3]
+[endsect]
+
+[include id1-no-docinfo.quickbook]
+
+[section Missing Id test 4]
+[endsect]
diff --git a/tools/quickbook/test/doc-info/id1-docinfo-no-id.quickbook b/tools/quickbook/test/doc-info/id1-docinfo-no-id.quickbook
new file mode 100644
index 0000000000..d5e9548260
--- /dev/null
+++ b/tools/quickbook/test/doc-info/id1-docinfo-no-id.quickbook
@@ -0,0 +1,5 @@
+[article Docinfo no id
+]
+
+[section Docinfo no id 1]
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/id1-no-docinfo.quickbook b/tools/quickbook/test/doc-info/id1-no-docinfo.quickbook
new file mode 100644
index 0000000000..4dbaf2dead
--- /dev/null
+++ b/tools/quickbook/test/doc-info/id1-no-docinfo.quickbook
@@ -0,0 +1,2 @@
+[section No docinfo test 1]
+[endsect]
diff --git a/tools/quickbook/test/doc-info/missing_doc_info-1_6-fail.quickbook b/tools/quickbook/test/doc-info/missing_doc_info-1_6-fail.quickbook
new file mode 100644
index 0000000000..6f0b2cdbe3
--- /dev/null
+++ b/tools/quickbook/test/doc-info/missing_doc_info-1_6-fail.quickbook
@@ -0,0 +1,3 @@
+[quickbook 1.6]
+
+Hello!
diff --git a/tools/quickbook/test/doc-info/source-mode-1.4.gold b/tools/quickbook/test/doc-info/source-mode-1.4.gold
new file mode 100644
index 0000000000..f7fea9a71b
--- /dev/null
+++ b/tools/quickbook/test/doc-info/source-mode-1.4.gold
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="c___test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>C++ test</title>
+ <articleinfo>
+ <legalnotice id="c___test.legal">
+ <para>
+ <code><phrase role="keyword">def</phrase> <phrase role="identifier">foo</phrase><phrase
+ role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">):</phrase>
+ <phrase role="keyword">print</phrase> <phrase role="string">&quot;Hello&quot;</phrase></code>
+ </para>
+ </legalnotice>
+ <articlepurpose>
+ <code><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase
+ role="special">()</phrase> <phrase role="special">{}</phrase></code>
+ </articlepurpose>
+ </articleinfo>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ </para>
+ <para>
+<programlisting><phrase role="keyword">def</phrase> <phrase role="identifier">foo</phrase><phrase role="special">():</phrase></programlisting>
+ </para>
+ <para>
+<programlisting><phrase role="keyword">def</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">):</phrase></programlisting>
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ </para>
+</article>
diff --git a/tools/quickbook/test/doc-info/source-mode-1.4.quickbook b/tools/quickbook/test/doc-info/source-mode-1.4.quickbook
new file mode 100644
index 0000000000..a04bca741a
--- /dev/null
+++ b/tools/quickbook/test/doc-info/source-mode-1.4.quickbook
@@ -0,0 +1,17 @@
+[article C++ test
+[quickbook 1.5]
+[source-mode python]
+[license `def foo(x): print "Hello"`]
+[source-mode c++]
+[purpose `int main() {}`]
+]
+
+```int main() {}```
+
+[include source-mode-python-include.quickbook]
+
+```def foo(x):```
+
+[include source-mode-cpp-include.quickbook]
+
+```int main() {}```
diff --git a/tools/quickbook/test/doc-info/source-mode-1.5.gold b/tools/quickbook/test/doc-info/source-mode-1.5.gold
new file mode 100644
index 0000000000..340c5d2e9b
--- /dev/null
+++ b/tools/quickbook/test/doc-info/source-mode-1.5.gold
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="c___test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>C++ test</title>
+ <articleinfo>
+ <legalnotice id="c___test.legal">
+ <para>
+ <code><phrase role="keyword">def</phrase> <phrase role="identifier">foo</phrase><phrase
+ role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">):</phrase>
+ <phrase role="keyword">print</phrase> <phrase role="string">&quot;Hello&quot;</phrase></code>
+ </para>
+ </legalnotice>
+ <articlepurpose>
+ <code>This shouldn't be highlighted</code>
+ </articlepurpose>
+ </articleinfo>
+ <para>
+<programlisting>This shouldn't be highlighted.</programlisting>
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ </para>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ </para>
+ <para>
+<programlisting><phrase role="keyword">def</phrase> <phrase role="identifier">foo</phrase><phrase role="special">():</phrase></programlisting>
+ </para>
+ <para>
+<programlisting><phrase role="keyword">def</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">):</phrase></programlisting>
+ </para>
+ <para>
+<programlisting>This shouldn't be highlighted</programlisting>
+ </para>
+ <para>
+<programlisting>This shouldn't be highlighted.</programlisting>
+ </para>
+</article>
diff --git a/tools/quickbook/test/doc-info/source-mode-1.5.quickbook b/tools/quickbook/test/doc-info/source-mode-1.5.quickbook
new file mode 100644
index 0000000000..78e20b7c0e
--- /dev/null
+++ b/tools/quickbook/test/doc-info/source-mode-1.5.quickbook
@@ -0,0 +1,21 @@
+[article C++ test
+[quickbook 1.5]
+[source-mode python]
+[license `def foo(x): print "Hello"`]
+[source-mode teletype]
+[purpose `This shouldn't be highlighted`]
+]
+
+```This shouldn't be highlighted.```
+
+[include source-mode-cpp-include.quickbook]
+
+```int main() {}```
+
+[include source-mode-python-include.quickbook]
+
+```def foo(x):```
+
+[include source-mode-teletype-include.quickbook]
+
+```This shouldn't be highlighted.```
diff --git a/tools/quickbook/test/doc-info/source-mode-1.6.gold b/tools/quickbook/test/doc-info/source-mode-1.6.gold
new file mode 100644
index 0000000000..02496673aa
--- /dev/null
+++ b/tools/quickbook/test/doc-info/source-mode-1.6.gold
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="c_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>C++ test</title>
+ <articleinfo>
+ <legalnotice id="c_test.legal">
+ <para>
+ <code><phrase role="keyword">def</phrase> <phrase role="identifier">foo</phrase><phrase
+ role="special">(</phrase><phrase role="identifier">x</phrase><phrase role="special">):</phrase>
+ <phrase role="keyword">print</phrase> <phrase role="string">&quot;Hello&quot;</phrase></code>
+ </para>
+ </legalnotice>
+ <articlepurpose>
+ <code>This shouldn't be highlighted</code>
+ </articlepurpose>
+ </articleinfo>
+<programlisting>This shouldn't be highlighted.</programlisting>
+ <article id="c___source_mode_include" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>C++ source mode include</title>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ </para>
+ </article>
+<programlisting>This shouldn't be highlighted.</programlisting>
+ <article id="python_source_mode_include" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Python source mode include</title>
+ <para>
+<programlisting><phrase role="keyword">def</phrase> <phrase role="identifier">foo</phrase><phrase role="special">():</phrase></programlisting>
+ </para>
+ </article>
+<programlisting>This shouldn't be highlighted.</programlisting>
+ <article id="teletype_source_mode_include" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Teletype source mode include</title>
+ <para>
+<programlisting>This shouldn't be highlighted</programlisting>
+ </para>
+ </article>
+<programlisting>This shouldn't be highlighted.</programlisting>
+</article>
diff --git a/tools/quickbook/test/doc-info/source-mode-1.6.quickbook b/tools/quickbook/test/doc-info/source-mode-1.6.quickbook
new file mode 100644
index 0000000000..02f7ee4c48
--- /dev/null
+++ b/tools/quickbook/test/doc-info/source-mode-1.6.quickbook
@@ -0,0 +1,21 @@
+[article C++ test
+[quickbook 1.6]
+[source-mode python]
+[license `def foo(x): print "Hello"`]
+[source-mode teletype]
+[purpose `This shouldn't be highlighted`]
+]
+
+```This shouldn't be highlighted.```
+
+[include source-mode-cpp-include.quickbook]
+
+```This shouldn't be highlighted.```
+
+[include source-mode-python-include.quickbook]
+
+```This shouldn't be highlighted.```
+
+[include source-mode-teletype-include.quickbook]
+
+```This shouldn't be highlighted.```
diff --git a/tools/quickbook/test/doc-info/source-mode-cpp-include.quickbook b/tools/quickbook/test/doc-info/source-mode-cpp-include.quickbook
new file mode 100644
index 0000000000..1ff2b94cd3
--- /dev/null
+++ b/tools/quickbook/test/doc-info/source-mode-cpp-include.quickbook
@@ -0,0 +1,4 @@
+[source-mode c++]
+[article C++ source mode include]
+
+```int main() {}``` \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/source-mode-python-include.quickbook b/tools/quickbook/test/doc-info/source-mode-python-include.quickbook
new file mode 100644
index 0000000000..31ac531d0f
--- /dev/null
+++ b/tools/quickbook/test/doc-info/source-mode-python-include.quickbook
@@ -0,0 +1,5 @@
+[article Python source mode include
+[source-mode python]
+]
+
+```def foo():``` \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/source-mode-teletype-include.quickbook b/tools/quickbook/test/doc-info/source-mode-teletype-include.quickbook
new file mode 100644
index 0000000000..c7908fb76e
--- /dev/null
+++ b/tools/quickbook/test/doc-info/source-mode-teletype-include.quickbook
@@ -0,0 +1,5 @@
+[article Teletype source mode include
+[source-mode teletype]
+]
+
+```This shouldn't be highlighted``` \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/title_trailing_space-1_1.gold b/tools/quickbook/test/doc-info/title_trailing_space-1_1.gold
new file mode 100644
index 0000000000..17e4add733
--- /dev/null
+++ b/tools/quickbook/test/doc-info/title_trailing_space-1_1.gold
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="trailing_space_____" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Trailing Space</title>
+ <section id="trailing_space_____.body">
+ <title>Body</title>
+ </section>
+</article>
diff --git a/tools/quickbook/test/doc-info/title_trailing_space-1_1.quickbook b/tools/quickbook/test/doc-info/title_trailing_space-1_1.quickbook
new file mode 100644
index 0000000000..27305f719d
--- /dev/null
+++ b/tools/quickbook/test/doc-info/title_trailing_space-1_1.quickbook
@@ -0,0 +1,5 @@
+[article Trailing Space ]
+
+[section Body]
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/doc-info/title_trailing_space-1_6.gold b/tools/quickbook/test/doc-info/title_trailing_space-1_6.gold
new file mode 100644
index 0000000000..45231b6d11
--- /dev/null
+++ b/tools/quickbook/test/doc-info/title_trailing_space-1_6.gold
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="trailing_space" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Trailing Space</title>
+ <section id="trailing_space.body">
+ <title><link linkend="trailing_space.body">Body</link></title>
+ </section>
+</article>
diff --git a/tools/quickbook/test/doc-info/title_trailing_space-1_6.quickbook b/tools/quickbook/test/doc-info/title_trailing_space-1_6.quickbook
new file mode 100644
index 0000000000..b1b8cd5d25
--- /dev/null
+++ b/tools/quickbook/test/doc-info/title_trailing_space-1_6.quickbook
@@ -0,0 +1,5 @@
+[article Trailing Space [quickbook 1.6]]
+
+[section Body]
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/elements-1_5.gold b/tools/quickbook/test/elements-1_5.gold
new file mode 100644
index 0000000000..e5bb24a277
--- /dev/null
+++ b/tools/quickbook/test/elements-1_5.gold
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="1_5_elements" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>1.5 Elements</title>
+ <para>
+ [ordered_list [item1][item2]]
+ </para>
+ <para>
+ [itemized_list [item1][item2]]
+ </para>
+ <para>
+ [block<simplesect><title>A <emphasis role="bold">simplesect</emphasis>!</title>]
+ </para>
+ <para>
+ [block</simplesect>]
+ </para>
+</article>
diff --git a/tools/quickbook/test/elements-1_5.quickbook b/tools/quickbook/test/elements-1_5.quickbook
new file mode 100644
index 0000000000..df8f10aa7e
--- /dev/null
+++ b/tools/quickbook/test/elements-1_5.quickbook
@@ -0,0 +1,13 @@
+[article 1.5 Elements
+[quickbook 1.5]
+]
+
+[/ elements from 1.6]
+
+[ordered_list [item1][item2]]
+
+[itemized_list [item1][item2]]
+
+[block'''<simplesect><title>'''A *simplesect*!'''</title>''']
+
+[block'''</simplesect>'''] \ No newline at end of file
diff --git a/tools/quickbook/test/elements-1_6.gold b/tools/quickbook/test/elements-1_6.gold
new file mode 100644
index 0000000000..bc9ee06f31
--- /dev/null
+++ b/tools/quickbook/test/elements-1_6.gold
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="1_6_elements" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>1.6 Elements</title>
+ <orderedlist>
+ <listitem>
+ <para>
+ item1
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ item2
+ </para>
+ </listitem>
+ </orderedlist>
+ <itemizedlist>
+ <listitem>
+ <para>
+ item1
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ item2
+ </para>
+ </listitem>
+ </itemizedlist>
+ <simplesect><title>A <emphasis role="bold">simplesect</emphasis>!</title></simplesect>
+
+</article>
diff --git a/tools/quickbook/test/elements-1_6.quickbook b/tools/quickbook/test/elements-1_6.quickbook
new file mode 100644
index 0000000000..68372d1238
--- /dev/null
+++ b/tools/quickbook/test/elements-1_6.quickbook
@@ -0,0 +1,13 @@
+[article 1.6 Elements
+[quickbook 1.6]
+]
+
+[/ elements from 1.6]
+
+[ordered_list [item1][item2]]
+
+[itemized_list [item1][item2]]
+
+[block'''<simplesect><title>'''A *simplesect*!'''</title>''']
+
+[block'''</simplesect>'''] \ No newline at end of file
diff --git a/tools/quickbook/test/empty.qbk b/tools/quickbook/test/empty.qbk
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/quickbook/test/empty.qbk
diff --git a/tools/quickbook/test/escape-1_1.gold b/tools/quickbook/test/escape-1_1.gold
new file mode 100644
index 0000000000..0c600e0dcb
--- /dev/null
+++ b/tools/quickbook/test/escape-1_1.gold
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="escape" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Escape</title>
+ <section id="escape.escape">
+ <title>Escape</title>
+ <para>
+ <emphasis>Da do do do. Da da da da. That's all I have to say to you.</emphasis>
+ </para>
+ <para>
+ This letter &#x3B1; should have a space either side of it.
+ </para>
+ <para>
+ These should be properly encoded: &gt; &lt; &quot;
+ </para>
+ <para>
+ This <link linkend="$0">link</link> shouldn't be changed.
+ </para>
+ <para>
+ Some other problematic links:
+<link linkend="$157">one</link>,
+<link linkend="$-256">two</link>,
+<link linkend="$text">three</link>.
+ </para>
+ <para>
+ <emphasis>This will be escaped</emphasis>
+ </para>
+ <para>
+ \[ generates [. \] generates ].
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/escape-1_1.quickbook b/tools/quickbook/test/escape-1_1.quickbook
new file mode 100644
index 0000000000..3536ae5d5d
--- /dev/null
+++ b/tools/quickbook/test/escape-1_1.quickbook
@@ -0,0 +1,34 @@
+[article Escape
+]
+
+[section Escape]
+
+'''
+<emphasis>Da do do do. Da da da da. That's all I have to say to you.</emphasis>
+'''
+
+This letter '''&#x3B1;''' should have a space either side of it.
+
+These should be properly encoded: \> \< \"
+
+[/ The following tests are based on internal knowledge of
+ how quickbook's id generator works. They make sure it
+ doesn't mess up escaped docbook. ]
+
+'''This <link linkend="$0">link</link> shouldn't be changed.'''
+
+'''
+Some other problematic links:
+<link linkend="$157">one</link>,
+<link linkend="$-256">two</link>,
+<link linkend="$text">three</link>.
+'''
+
+[template escapedtemplate <emphasis>This will be escaped</emphasis>]
+
+[`escapedtemplate]
+
+\\\[ generates \[.
+\\\] generates \].
+
+[endsect]
diff --git a/tools/quickbook/test/escape-1_6.gold b/tools/quickbook/test/escape-1_6.gold
new file mode 100644
index 0000000000..54056a7d8e
--- /dev/null
+++ b/tools/quickbook/test/escape-1_6.gold
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="escape" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Escape</title>
+ <section id="escape.escape">
+ <title><link linkend="escape.escape">Escape</link></title>
+ <para>
+ <emphasis>Da do do do. Da da da da. That's all I have to say to you.</emphasis>
+ </para>
+ <para>
+ This letter &#x3B1; should have a space either side of it.
+ </para>
+ <para>
+ These should be properly encoded: &gt; &lt; &quot;
+ </para>
+ <para>
+ This <link linkend="$0">link</link> shouldn't be changed.
+ </para>
+ <para>
+ Some other problematic links:
+<link linkend="$157">one</link>,
+<link linkend="$-256">two</link>,
+<link linkend="$text">three</link>.
+ </para>
+ <para>
+ <emphasis>This will be escaped</emphasis>
+ </para>
+ <para>
+ \[ generates [. \] generates ].
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/escape-1_6.quickbook b/tools/quickbook/test/escape-1_6.quickbook
new file mode 100644
index 0000000000..0df9038084
--- /dev/null
+++ b/tools/quickbook/test/escape-1_6.quickbook
@@ -0,0 +1,35 @@
+[article Escape
+[quickbook 1.6]
+]
+
+[section Escape]
+
+'''
+<emphasis>Da do do do. Da da da da. That's all I have to say to you.</emphasis>
+'''
+
+This letter '''&#x3B1;''' should have a space either side of it.
+
+These should be properly encoded: \> \< \"
+
+[/ The following tests are based on internal knowledge of
+ how quickbook's id generator works. They make sure it
+ doesn't mess up escaped docbook. ]
+
+'''This <link linkend="$0">link</link> shouldn't be changed.'''
+
+'''
+Some other problematic links:
+<link linkend="$157">one</link>,
+<link linkend="$-256">two</link>,
+<link linkend="$text">three</link>.
+'''
+
+[template escapedtemplate <emphasis>This will be escaped</emphasis>]
+
+[`escapedtemplate]
+
+\\\[ generates \[.
+\\\] generates \].
+
+[endsect]
diff --git a/tools/quickbook/test/escape-mismatched-1_5-fail.quickbook b/tools/quickbook/test/escape-mismatched-1_5-fail.quickbook
new file mode 100644
index 0000000000..1f9d0c0a4b
--- /dev/null
+++ b/tools/quickbook/test/escape-mismatched-1_5-fail.quickbook
@@ -0,0 +1,5 @@
+[article Badly escaped boostbook
+[quickbook 1.5]
+]
+
+'''<emphasis>something</emphasis> \ No newline at end of file
diff --git a/tools/quickbook/test/heading-1_1.gold b/tools/quickbook/test/heading-1_1.gold
new file mode 100644
index 0000000000..334d20bc19
--- /dev/null
+++ b/tools/quickbook/test/heading-1_1.gold
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="heading_test_1_1" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Heading Test 1.1</title>
+ <bridgehead renderas="sect2" id="heading_test_1_1.h0">
+ <phrase id="heading_test_1_1.generic_header"/><link linkend="heading_test_1_1.generic_header">Generic
+ header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id=".level_1">
+ Level 1
+ </bridgehead>
+ <bridgehead renderas="sect2" id=".level_2">
+ Level 2
+ </bridgehead>
+ <bridgehead renderas="sect3" id=".level_3">
+ Level 3
+ </bridgehead>
+ <bridgehead renderas="sect4" id=".level_4">
+ Level 4
+ </bridgehead>
+ <bridgehead renderas="sect5" id=".level_5">
+ Level 5
+ </bridgehead>
+ <bridgehead renderas="sect6" id=".level_6">
+ Level 6
+ </bridgehead>
+ <bridgehead renderas="sect1" id="._emphasis_role__bold__bold__emphasis_">
+ <emphasis role="bold">Bold</emphasis>
+ </bridgehead>
+ <bridgehead renderas="sect1" id=".comment">
+ Comment
+ </bridgehead>
+ <bridgehead renderas="sect1" id="._notanid">
+ :notanid
+ </bridgehead>
+ <bridgehead renderas="sect1" id="._also_not_an_id">
+ :also not an id
+ </bridgehead>
+ <bridgehead renderas="sect1" id="._anchor_id__anchor___anchor_heading">
+ <anchor id="anchor"/>Anchor heading
+ </bridgehead>
+ <bridgehead renderas="sect1" id="._link_linkend__anchor__link_heading__link_">
+ <link linkend="anchor">Link heading</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id=".h1">
+ H1
+ </bridgehead>
+ <section id="heading_test_1_1.s1">
+ <title>S1</title>
+ <bridgehead renderas="sect2" id="s1.h2">
+ H2
+ </bridgehead>
+ <section id="heading_test_1_1.s2">
+ <title>S2</title>
+ <bridgehead renderas="sect3" id="s2.h3">
+ H3
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect3" id="heading_test_1_1.s1.h0">
+ <phrase id="heading_test_1_1.s1.h4"/><link linkend="heading_test_1_1.s1.h4">H4</link>
+ </bridgehead>
+ <section id="heading_test_1_1.s3">
+ <title>S3</title>
+ <bridgehead renderas="sect3" id="s3.h5">
+ H5
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect3" id="heading_test_1_1.s1.h1">
+ <phrase id="heading_test_1_1.s1.h6"/><link linkend="heading_test_1_1.s1.h6">H6</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect1" id="s3.h7">
+ H7
+ </bridgehead>
+</article>
diff --git a/tools/quickbook/test/heading-1_1.quickbook b/tools/quickbook/test/heading-1_1.quickbook
new file mode 100644
index 0000000000..f7b2286f42
--- /dev/null
+++ b/tools/quickbook/test/heading-1_1.quickbook
@@ -0,0 +1,55 @@
+[article Heading Test 1.1]
+
+[/ Basic headers ]
+
+[heading Generic header]
+[h1 Level 1]
+[h2 Level 2]
+[h3 Level 3]
+[h4 Level 4]
+[h5 Level 5]
+[h6 Level 6]
+
+[/ Test how heading ids are generated when different types of markup are present]
+
+[h1 *Bold*]
+[h1 [/]Comment[/]]
+
+[/ Headings that look like ids]
+
+[h1:notanid]
+[h1:also not an id]
+
+[/ Test how ids are generated for headings containing things like anchors
+ and links ]
+
+[h1 [#anchor]Anchor heading]
+[h1 [link anchor Link heading]]
+
+[/ Test how heading ids are generated inside sections]
+
+[h1 H1]
+
+[section:s1 S1]
+
+[h2 H2]
+
+[section:s2 S2]
+
+[h3 H3]
+
+[endsect]
+
+[heading H4]
+
+[section:s3 S3]
+
+[h3 H5]
+
+[endsect]
+
+[heading H6]
+
+[endsect]
+
+[h1 H7]
diff --git a/tools/quickbook/test/heading-1_3.gold b/tools/quickbook/test/heading-1_3.gold
new file mode 100644
index 0000000000..f883a60375
--- /dev/null
+++ b/tools/quickbook/test/heading-1_3.gold
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="header" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Header</title>
+ <bridgehead renderas="sect2" id="header.h0">
+ <phrase id="header.header_test"/><link linkend="header.header_test">Header Test</link>
+ </bridgehead>
+ <para>
+ Testing headers without sections.
+ </para>
+ <bridgehead renderas="sect2" id="header.h1">
+ <phrase id="header._not_an_id"/><link linkend="header._not_an_id">:Not an Id</link>
+ </bridgehead>
+ <para>
+ Paragraph.
+ </para>
+ <bridgehead renderas="sect3" id="header.h2">
+ <phrase id="header._not_an_id_again"/><link linkend="header._not_an_id_again">:Not
+ an Id again</link>
+ </bridgehead>
+ <para>
+ Paragraph.
+ </para>
+</article>
diff --git a/tools/quickbook/test/heading-1_3.quickbook b/tools/quickbook/test/heading-1_3.quickbook
new file mode 100644
index 0000000000..19de3a49a0
--- /dev/null
+++ b/tools/quickbook/test/heading-1_3.quickbook
@@ -0,0 +1,16 @@
+[article Header
+ [quickbook 1.3]
+ [id header]
+]
+
+[heading Header Test]
+
+Testing headers without sections.
+
+[heading:Not an Id]
+
+Paragraph.
+
+[h3:Not an Id again]
+
+Paragraph. \ No newline at end of file
diff --git a/tools/quickbook/test/heading-1_5.gold b/tools/quickbook/test/heading-1_5.gold
new file mode 100644
index 0000000000..03fe464912
--- /dev/null
+++ b/tools/quickbook/test/heading-1_5.gold
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="heading_test_1_5" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Heading Test 1.5</title>
+ <bridgehead renderas="sect2" id="heading_test_1_5.h0">
+ <phrase id="heading_test_1_5.generic_header"/><link linkend="heading_test_1_5.generic_header">Generic
+ header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_5.h2">
+ <phrase id="heading_test_1_5.level_1"/><link linkend="heading_test_1_5.level_1">Level
+ 1</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="heading_test_1_5.h3">
+ <phrase id="heading_test_1_5.level_2"/><link linkend="heading_test_1_5.level_2">Level
+ 2</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="heading_test_1_5.h4">
+ <phrase id="heading_test_1_5.level_3"/><link linkend="heading_test_1_5.level_3">Level
+ 3</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="heading_test_1_5.h5">
+ <phrase id="heading_test_1_5.level_4"/><link linkend="heading_test_1_5.level_4">Level
+ 4</link>
+ </bridgehead>
+ <bridgehead renderas="sect5" id="heading_test_1_5.h6">
+ <phrase id="heading_test_1_5.level_5"/><link linkend="heading_test_1_5.level_5">Level
+ 5</link>
+ </bridgehead>
+ <bridgehead renderas="sect6" id="heading_test_1_5.h8">
+ <phrase id="heading_test_1_5.level_6"/><link linkend="heading_test_1_5.level_6">Level
+ 6</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_5.h9">
+ <phrase id="heading_test_1_5._emphasis_role__bold__bold__emphasis_"/><link linkend="heading_test_1_5._emphasis_role__bold__bold__emphasis_"><emphasis
+ role="bold">Bold</emphasis></link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_5.h10">
+ <phrase id="heading_test_1_5.comment"/><link linkend="heading_test_1_5.comment">Comment</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_5.h11">
+ <phrase id="heading_test_1_5._notanid"/><link linkend="heading_test_1_5._notanid">:notanid</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_5.h12">
+ <phrase id="heading_test_1_5._also_not_an_id"/><link linkend="heading_test_1_5._also_not_an_id">:also
+ not an id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_5.h13">
+ <phrase id="heading_test_1_5._anchor_id__anchor___anchor_heading"/><link linkend="heading_test_1_5._anchor_id__anchor___anchor_heading"><anchor
+ id="anchor"/>Anchor heading</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_5.h14">
+ <phrase id="heading_test_1_5._link_linkend__anchor__link_heading__link_"/><link
+ linkend="heading_test_1_5._link_linkend__anchor__link_heading__link_"><link linkend="anchor">Link
+ heading</link></link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="heading_test_1_5.h15">
+ <phrase id="heading_test_1_5.h1"/><link linkend="heading_test_1_5.h1">H1</link>
+ </bridgehead>
+ <section id="heading_test_1_5.s1">
+ <title><link linkend="heading_test_1_5.s1">S1</link></title>
+ <bridgehead renderas="sect2" id="heading_test_1_5.s1.h0">
+ <phrase id="heading_test_1_5.s1.h2"/><link linkend="heading_test_1_5.s1.h2">H2</link>
+ </bridgehead>
+ <section id="heading_test_1_5.s1.s2">
+ <title><link linkend="heading_test_1_5.s1.s2">S2</link></title>
+ <bridgehead renderas="sect3" id="heading_test_1_5.s1.s2.h0">
+ <phrase id="heading_test_1_5.s1.s2.h3"/><link linkend="heading_test_1_5.s1.s2.h3">H3</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect2" id="heading_test_1_5.s1.h1">
+ <phrase id="heading_test_1_5.s1.h4"/><link linkend="heading_test_1_5.s1.h4">H4</link>
+ </bridgehead>
+ <section id="heading_test_1_5.s1.s3">
+ <title><link linkend="heading_test_1_5.s1.s3">S3</link></title>
+ <bridgehead renderas="sect4" id="heading_test_1_5.s1.s3.h0">
+ <phrase id="heading_test_1_5.s1.s3.h5"/><link linkend="heading_test_1_5.s1.s3.h5">H5</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect2" id="heading_test_1_5.s1.h3">
+ <phrase id="heading_test_1_5.s1.h6"/><link linkend="heading_test_1_5.s1.h6">H6</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect1" id="heading_test_1_5.h16">
+ <phrase id="heading_test_1_5.h7"/><link linkend="heading_test_1_5.h7">H7</link>
+ </bridgehead>
+</article>
diff --git a/tools/quickbook/test/heading-1_5.quickbook b/tools/quickbook/test/heading-1_5.quickbook
new file mode 100644
index 0000000000..572b184cd8
--- /dev/null
+++ b/tools/quickbook/test/heading-1_5.quickbook
@@ -0,0 +1,57 @@
+[article Heading Test 1.5
+[quickbook 1.5]
+]
+
+[/ Basic headers ]
+
+[heading Generic header]
+[h1 Level 1]
+[h2 Level 2]
+[h3 Level 3]
+[h4 Level 4]
+[h5 Level 5]
+[h6 Level 6]
+
+[/ Test how heading ids are generated when different types of markup are present]
+
+[h1 *Bold*]
+[h1 [/]Comment[/]]
+
+[/ Headings that look like ids]
+
+[h1:notanid]
+[h1:also not an id]
+
+[/ Test how ids are generated for headings containing things like anchors
+ and links ]
+
+[h1 [#anchor]Anchor heading]
+[h1 [link anchor Link heading]]
+
+[/ Test how heading ids are generated inside sections]
+
+[heading H1]
+
+[section:s1 S1]
+
+[h2 H2]
+
+[section:s2 S2]
+
+[h3 H3]
+
+[endsect]
+
+[h2 H4]
+
+[section:s3 S3]
+
+[heading H5]
+
+[endsect]
+
+[h2 H6]
+
+[endsect]
+
+[h1 H7]
diff --git a/tools/quickbook/test/heading-1_6.gold b/tools/quickbook/test/heading-1_6.gold
new file mode 100644
index 0000000000..008115d724
--- /dev/null
+++ b/tools/quickbook/test/heading-1_6.gold
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="heading_test_1_6" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Heading Test 1.6</title>
+ <bridgehead renderas="sect2" id="heading_test_1_6.h0">
+ <phrase id="heading_test_1_6.generic_header"/><link linkend="heading_test_1_6.generic_header">Generic
+ header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_6.h2">
+ <phrase id="heading_test_1_6.level_1"/><link linkend="heading_test_1_6.level_1">Level
+ 1</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="heading_test_1_6.h3">
+ <phrase id="heading_test_1_6.level_2"/><link linkend="heading_test_1_6.level_2">Level
+ 2</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="heading_test_1_6.h4">
+ <phrase id="heading_test_1_6.level_3"/><link linkend="heading_test_1_6.level_3">Level
+ 3</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="heading_test_1_6.h5">
+ <phrase id="heading_test_1_6.level_4"/><link linkend="heading_test_1_6.level_4">Level
+ 4</link>
+ </bridgehead>
+ <bridgehead renderas="sect5" id="heading_test_1_6.h6">
+ <phrase id="heading_test_1_6.level_5"/><link linkend="heading_test_1_6.level_5">Level
+ 5</link>
+ </bridgehead>
+ <bridgehead renderas="sect6" id="heading_test_1_6.h8">
+ <phrase id="heading_test_1_6.level_6"/><link linkend="heading_test_1_6.level_6">Level
+ 6</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_6.h9">
+ <phrase id="heading_test_1_6.bold"/><link linkend="heading_test_1_6.bold"><emphasis
+ role="bold">Bold</emphasis></link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_6.h10">
+ <phrase id="heading_test_1_6.comment"/><link linkend="heading_test_1_6.comment">Comment</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_6.h11">
+ <phrase id="heading_test_1_6.anchor_anchor_heading"/><link linkend="heading_test_1_6.anchor_anchor_heading"><anchor
+ id="anchor"/>Anchor heading</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_6.h12">
+ <phrase id="heading_test_1_6.link_anchor_link_heading"/><link linkend="heading_test_1_6.link_anchor_link_heading"><link
+ linkend="anchor">Link heading</link></link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_6.h13">
+ <phrase id="heading_test_1_6.h1"/><link linkend="heading_test_1_6.h1">H1</link>
+ </bridgehead>
+ <section id="heading_test_1_6.s1">
+ <title><link linkend="heading_test_1_6.s1">S1</link></title>
+ <bridgehead renderas="sect3" id="heading_test_1_6.s1.h0">
+ <phrase id="heading_test_1_6.s1.h2"/><link linkend="heading_test_1_6.s1.h2">H2</link>
+ </bridgehead>
+ <section id="heading_test_1_6.s1.s2">
+ <title><link linkend="heading_test_1_6.s1.s2">S2</link></title>
+ <bridgehead renderas="sect3" id="heading_test_1_6.s1.s2.h0">
+ <phrase id="heading_test_1_6.s1.s2.h3"/><link linkend="heading_test_1_6.s1.s2.h3">H3</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect2" id="heading_test_1_6.s1.h1">
+ <phrase id="heading_test_1_6.s1.h4"/><link linkend="heading_test_1_6.s1.h4">H4</link>
+ </bridgehead>
+ <section id="heading_test_1_6.s1.s3">
+ <title><link linkend="heading_test_1_6.s1.s3">S3</link></title>
+ <bridgehead renderas="sect4" id="heading_test_1_6.s1.s3.h0">
+ <phrase id="heading_test_1_6.s1.s3.h5"/><link linkend="heading_test_1_6.s1.s3.h5">H5</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect2" id="heading_test_1_6.s1.h3">
+ <phrase id="heading_test_1_6.s1.h6"/><link linkend="heading_test_1_6.s1.h6">H6</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect1" id="heading_test_1_6.h14">
+ <phrase id="heading_test_1_6.h7"/><link linkend="heading_test_1_6.h7">H7</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="heading_test_1_6.h15">
+ <phrase id="heading_test_1_6.a1"/><link linkend="heading_test_1_6.a1">H1</link>
+ </bridgehead>
+ <section id="heading_test_1_6.s1_0">
+ <title><link linkend="heading_test_1_6.s1_0">S1</link></title>
+ <bridgehead renderas="sect2" id="heading_test_1_6.s1_0.h0">
+ <phrase id="heading_test_1_6.s1_0.a2"/><link linkend="heading_test_1_6.s1_0.a2">H2</link>
+ </bridgehead>
+ <section id="heading_test_1_6.s1_0.s2">
+ <title><link linkend="heading_test_1_6.s1_0.s2">S2</link></title>
+ <bridgehead renderas="sect3" id="heading_test_1_6.s1_0.s2.h0">
+ <phrase id="heading_test_1_6.s1_0.s2.a3"/><link linkend="heading_test_1_6.s1_0.s2.a3">H3</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect2" id="heading_test_1_6.s1_0.h1">
+ <phrase id="heading_test_1_6.s1_0.a4"/><link linkend="heading_test_1_6.s1_0.a4">H4</link>
+ </bridgehead>
+ <section id="heading_test_1_6.s1_0.s3">
+ <title><link linkend="heading_test_1_6.s1_0.s3">S3</link></title>
+ <bridgehead renderas="sect3" id="heading_test_1_6.s1_0.s3.h0">
+ <phrase id="heading_test_1_6.s1_0.s3.a5"/><link linkend="heading_test_1_6.s1_0.s3.a5">H5</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect3" id="heading_test_1_6.s1_0.h2">
+ <phrase id="heading_test_1_6.s1_0.a6"/><link linkend="heading_test_1_6.s1_0.a6">H6</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect1" id="heading_test_1_6.h16">
+ <phrase id="heading_test_1_6.a7"/><link linkend="heading_test_1_6.a7">H7</link>
+ </bridgehead>
+</article>
diff --git a/tools/quickbook/test/heading-1_6.quickbook b/tools/quickbook/test/heading-1_6.quickbook
new file mode 100644
index 0000000000..b8f6686945
--- /dev/null
+++ b/tools/quickbook/test/heading-1_6.quickbook
@@ -0,0 +1,80 @@
+[article Heading Test 1.6
+[quickbook 1.6]
+]
+
+[/ Basic headers ]
+
+[heading Generic header]
+[h1 Level 1]
+[h2 Level 2]
+[h3 Level 3]
+[h4 Level 4]
+[h5 Level 5]
+[h6 Level 6]
+
+[/ Test how heading ids are generated when different types of markup are present]
+
+[h1 *Bold*]
+[h1 [/]Comment[/]]
+
+[/ Test how ids are generated for headings containing things like anchors
+ and links ]
+
+[h1 [#anchor]Anchor heading]
+[h1 [link anchor Link heading]]
+
+[/ Test how heading ids are generated inside sections]
+
+[h1 H1]
+
+[section:s1 S1]
+
+[heading H2]
+
+[section:s2 S2]
+
+[h3 H3]
+
+[endsect]
+
+[h2 H4]
+
+[section:s3 S3]
+
+[heading H5]
+
+[endsect]
+
+[h2 H6]
+
+[endsect]
+
+[h1 H7]
+
+[/ Repeat with explicit ids]
+
+[h1:a1 H1]
+
+[section:s1 S1]
+
+[h2:a2 H2]
+
+[section:s2 S2]
+
+[h3:a3 H3]
+
+[endsect]
+
+[h2:a4 H4]
+
+[section:s3 S3]
+
+[h3:a5 H5]
+
+[endsect]
+
+[heading:a6 H6]
+
+[endsect]
+
+[h1:a7 H7]
diff --git a/tools/quickbook/test/heading_unclosed-1_4-fail.quickbook b/tools/quickbook/test/heading_unclosed-1_4-fail.quickbook
new file mode 100644
index 0000000000..79bf3d79af
--- /dev/null
+++ b/tools/quickbook/test/heading_unclosed-1_4-fail.quickbook
@@ -0,0 +1,3 @@
+[article Parse error [quickbook 1.4]]
+
+[heading Incomplete heading
diff --git a/tools/quickbook/test/hr-1_5.gold b/tools/quickbook/test/hr-1_5.gold
new file mode 100644
index 0000000000..8da9aa4d0f
--- /dev/null
+++ b/tools/quickbook/test/hr-1_5.gold
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="horizontal_rule" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Horizontal Rule</title>
+ <para/>
+ <para>
+ This should be displayed.
+ </para>
+ <para/>
+ <para/>
+ <para>
+ * This shouldn't be a list
+ </para>
+ <para/>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ This should be a list
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para/>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ This should be a list
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para/>
+ <para/>
+ <para/>
+</article>
diff --git a/tools/quickbook/test/hr-1_5.quickbook b/tools/quickbook/test/hr-1_5.quickbook
new file mode 100644
index 0000000000..27df9f5370
--- /dev/null
+++ b/tools/quickbook/test/hr-1_5.quickbook
@@ -0,0 +1,27 @@
+[article Horizontal Rule
+[quickbook 1.5]
+]
+
+---- [/
+This should be a comment.
+] This should be displayed.
+
+---- [/ ] This shouldn't be displayed.
+
+---- [/
+This should be a comment.
+] * This shouldn't be a list
+
+---- [/
+This should be a comment.
+]
+* This should be a list
+
+---- [/ This should be a comment]
+* This should be a list
+
+---- [* This shouldn't be displayed.]
+
+---- This doesn't have an open bracket.]
+
+---- [ This doesn't have a close bracket.
diff --git a/tools/quickbook/test/hr-1_6.gold b/tools/quickbook/test/hr-1_6.gold
new file mode 100644
index 0000000000..b9ef17a472
--- /dev/null
+++ b/tools/quickbook/test/hr-1_6.gold
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="horizontal_rule" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Horizontal Rule</title>
+ <para/>
+ <para>
+ This should be displayed.
+ </para>
+ <para/>
+ <para/>
+ <para>
+ * This shouldn't be a list
+ </para>
+ <para/>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ This should be a list
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para/>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ This should be a list
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para/>
+ <para>
+ <emphasis role="bold">This should be displayed. Maybe that's wrong?</emphasis>
+ </para>
+ <para/>
+ <para>
+ Odd way to get text displayed.
+ </para>
+</article>
diff --git a/tools/quickbook/test/hr-1_6.quickbook b/tools/quickbook/test/hr-1_6.quickbook
new file mode 100644
index 0000000000..0ed38c93ea
--- /dev/null
+++ b/tools/quickbook/test/hr-1_6.quickbook
@@ -0,0 +1,26 @@
+[article Horizontal Rule
+[quickbook 1.6]
+]
+
+---- [/
+This should be a comment.
+] This should be displayed.
+
+---- [/ ] This shouldn't be displayed.
+
+---- [/
+This should be a comment.
+] * This shouldn't be a list
+
+---- [/
+This should be a comment.
+]
+* This should be a list
+
+---- [/ This should be a comment]
+* This should be a list
+
+---- [* This should be displayed. Maybe that's wrong?]
+
+[template nothing]
+---- [nothing] Odd way to get text displayed.
diff --git a/tools/quickbook/test/html/images/open_clipart_library_logo.svg b/tools/quickbook/test/html/images/open_clipart_library_logo.svg
new file mode 100644
index 0000000000..9a4521f3a5
--- /dev/null
+++ b/tools/quickbook/test/html/images/open_clipart_library_logo.svg
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ x="0.00000000"
+ y="0.00000000"
+ id="svg6221"
+ width="745.60706"
+ height="513.25690"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ sodipodi:docname="Open_Clipart_Library_logo.svg">
+ <sodipodi:namedview
+ inkscape:cy="893.36713"
+ inkscape:cx="305.25953"
+ inkscape:zoom="0.86831670"
+ inkscape:window-height="913"
+ inkscape:window-width="1272"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:window-x="0"
+ inkscape:window-y="30"
+ inkscape:current-layer="svg6221" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Open Clip Art Logo</dc:title>
+ <dc:date>10-01-2004</dc:date>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Andreas Nilsson</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <cc:license
+ rdf:resource="http://web.resource.org/cc/PublicDomain" />
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title>Jon Phillips, Tobias Jakobs</dc:title>
+ </cc:Agent>
+ </dc:contributor>
+ <dc:description>This is one version of the official Open Clip Art Library logo.</dc:description>
+ <dc:subject>logo, open clip art library logo, logotype</dc:subject>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://web.resource.org/cc/PublicDomain">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3" />
+ <path
+ d="M 405.82430,48.494855 C 396.10958,45.870336 386.13966,51.583653 383.51514,61.298370 L 298.15838,376.92441 C 295.53385,386.63914 301.24717,396.41506 310.96188,399.03957 L 626.58791,484.39635 C 636.30255,487.02086 646.27253,481.30755 648.89705,471.59283 L 734.25375,155.96679 C 735.49097,151.38725 734.71475,146.85751 732.70181,142.96928 L 732.70181,142.77528 L 732.50782,142.38730 L 732.50782,142.19331 C 732.46276,142.11490 732.36008,142.07704 732.31383,141.99931 L 717.76438,111.93045 L 651.80695,114.84034 L 405.82430,48.494855 z "
+ style="fill:#000000;fill-opacity:0.20000000;fill-rule:evenodd;stroke:none;stroke-width:1.6789947;stroke-miterlimit:4.0000000;stroke-opacity:0.20000000"
+ id="rect6080" />
+ <rect
+ width="363.28452"
+ height="363.28452"
+ rx="2.9260478"
+ ry="2.9260478"
+ x="363.42282"
+ y="-78.837021"
+ transform="matrix(0.965391,0.260807,-0.260807,0.965391,0.000000,0.000000)"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#ffffff;stroke-width:7.7597070;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ id="rect911" />
+ <rect
+ width="288.49521"
+ height="288.49521"
+ rx="2.3236644"
+ ry="2.3236644"
+ x="398.72931"
+ y="-39.355053"
+ transform="matrix(0.965391,0.260807,-0.260807,0.965391,0.000000,0.000000)"
+ style="fill:#f3e533;fill-opacity:1.0000000;fill-rule:evenodd;stroke-width:0.79413080pt"
+ id="rect912" />
+ <path
+ d="M 552.48969,32.227283 L 486.13725,53.566475 L 486.71922,53.760468 L 235.30476,53.760468 C 225.24184,53.760468 217.26344,61.738811 217.26344,71.801785 L 217.26344,398.87339 C 217.26344,408.93643 225.24178,416.91471 235.30476,416.91471 L 562.37636,416.91471 C 572.43940,416.91471 580.41768,408.93637 580.41768,398.87339 L 580.41768,71.801785 C 580.41768,66.612962 578.25806,62.108236 574.79189,58.804276 L 552.48969,32.227283 z "
+ style="fill:#000000;fill-opacity:0.20000000;fill-rule:evenodd;stroke:none;stroke-width:1.6789950;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ id="rect6079" />
+ <rect
+ width="363.28418"
+ height="363.28418"
+ rx="2.9260466"
+ ry="2.9260466"
+ x="192.47523"
+ y="30.531385"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#ffffff;stroke-width:7.7597060;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ id="rect913" />
+ <rect
+ width="288.49512"
+ height="288.49512"
+ rx="2.3236635"
+ ry="2.3236635"
+ x="227.78207"
+ y="70.013809"
+ style="fill:#ff7f00;fill-rule:evenodd;stroke-width:0.79413080pt"
+ id="rect914" />
+ <path
+ d="M 348.20848,28.541423 L 291.17463,66.563983 L 305.14211,68.115925 L 55.667554,157.15854 C 46.188236,160.53570 41.232826,170.76437 44.609974,180.24367 L 138.89040,445.04365 L 132.29465,444.84966 L 128.02682,485.39411 L 163.52746,498.58561 L 163.91546,498.58561 C 168.05181,500.44490 172.88654,501.00342 177.49494,499.36159 L 485.55528,389.56176 C 495.03452,386.18460 499.79600,375.76200 496.41886,366.28264 L 386.81301,58.416291 C 385.25785,54.051177 382.02384,50.975478 378.27734,48.910652 L 348.20848,28.541423 z "
+ style="fill:#000000;fill-opacity:0.20000000;fill-rule:evenodd;stroke:none;stroke-width:1.2500002;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ id="rect6078" />
+ <rect
+ width="363.28326"
+ height="363.28326"
+ rx="2.9260383"
+ ry="2.9260383"
+ x="-41.716114"
+ y="142.20343"
+ transform="matrix(0.942003,-0.335604,0.335604,0.942003,0.000000,0.000000)"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#ffffff;stroke-width:7.7596951;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ id="rect915" />
+ <rect
+ width="288.49469"
+ height="288.49469"
+ rx="2.3236592"
+ ry="2.3236592"
+ x="-6.4090877"
+ y="181.68738"
+ transform="matrix(0.942003,-0.335604,0.335604,0.942003,0.000000,0.000000)"
+ style="fill:#bf0000;fill-rule:evenodd;stroke-width:0.79413080pt"
+ id="rect916" />
+</svg>
diff --git a/tools/quickbook/test/identifier-1_5.gold b/tools/quickbook/test/identifier-1_5.gold
new file mode 100644
index 0000000000..0e3557b0a3
--- /dev/null
+++ b/tools/quickbook/test/identifier-1_5.gold
@@ -0,0 +1,610 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="identifiers_in_quickbook_1_5" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Identifiers in quickbook 1.5</title>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h0">
+ <phrase id="identifiers_in_quickbook_1_5.test_heading_with__code__phrase_role__identifier__code__phrase___code_"/><link
+ linkend="identifiers_in_quickbook_1_5.test_heading_with__code__phrase_role__identifier__code__phrase___code_">Test
+ heading with <code><phrase role="identifier">code</phrase></code></link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h1">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10_0"/><link linkend="identifiers_in_quickbook_1_5.identifier_10_0">Identifier
+ 10</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h2">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10_1"/><link linkend="identifiers_in_quickbook_1_5.identifier_10_1">Identifier
+ 10</link>
+ </bridgehead>
+ <table frame="all" id="identifiers_in_quickbook_1_5.identifier_10_2">
+ <title>Identifier 10</title>
+ <tgroup cols="1">
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h3">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_duplicate_it_by_having_several_headers"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_duplicate_it_by_having_several_headers">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h4">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d0"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d0">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h5">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_duplicate_it_by_having_lots_of_headers"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_duplicate_it_by_having_lots_of_headers">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h6">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d1"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d1">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h7">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d2"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d2">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h8">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d3"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d3">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h9">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d5"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d5">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h10">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d6"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d6">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h11">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d7"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d7">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h12">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_duplicate_it_by_having_too_many_headers"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_duplicate_it_by_having_too_many_headers">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h13">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d8"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d8">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h14">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d9"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d9">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h15">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_0"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_0">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h16">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_1"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_1">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h17">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_2"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_2">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h18">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_3"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_3">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h19">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_4"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_4">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h20">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_5"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_5">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h21">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_6"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_6">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h22">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_7"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_7">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h23">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_8"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_8">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h24">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_9"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_9">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h25">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_10"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_10">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h26">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_11"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_11">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h27">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_12"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_12">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h28">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_13"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_13">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h29">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_14"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_14">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h30">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_16"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_16">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h31">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_17"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_17">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h32">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_18"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_18">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h33">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_19"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_19">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h34">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_20"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_20">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h35">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_21"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_21">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h36">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_22"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_22">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h37">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_23"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_23">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h38">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_24"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_24">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h39">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_25"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_25">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h40">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_26"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_26">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h41">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_duplicate_it_by_having_even_more_headers"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_duplicate_it_by_having_even_more_headers">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h42">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_27"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_27">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h43">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_28"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_28">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h44">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_29"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_29">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h45">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d4"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_d4">Generate
+ a really long id and d4</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h46">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_15"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_15">Generate
+ a really long id and 15</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h47">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_30"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_30">Generate
+ a really long id and d4</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h48">
+ <phrase id="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_31"/><link
+ linkend="identifiers_in_quickbook_1_5.generate_a_really_long_id_and_31">Generate
+ a really long id and 15</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h49">
+ <phrase id="identifiers_in_quickbook_1_5.a2345678901234567890123456789012"/><link
+ linkend="identifiers_in_quickbook_1_5.a2345678901234567890123456789012">a2345678901234567890123456789012</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h50">
+ <phrase id="identifiers_in_quickbook_1_5.a0"/><link linkend="identifiers_in_quickbook_1_5.a0">a2345678901234567890123456789012</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h51">
+ <phrase id="identifiers_in_quickbook_1_5.abcdefghijklmnopqrstuvwxyzabcdef"/><link
+ linkend="identifiers_in_quickbook_1_5.abcdefghijklmnopqrstuvwxyzabcdef">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h52">
+ <phrase id="identifiers_in_quickbook_1_5.abcdefghijklmnopqrstuvwxyzabcde0"/><link
+ linkend="identifiers_in_quickbook_1_5.abcdefghijklmnopqrstuvwxyzabcde0">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h53">
+ <phrase id="identifiers_in_quickbook_1_5.abcdefghijklmnopqrstuvwxyzabcde1"/><link
+ linkend="identifiers_in_quickbook_1_5.abcdefghijklmnopqrstuvwxyzabcde1">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h54">
+ <phrase id="identifiers_in_quickbook_1_5.abcdefghijklmnopqrstuvwxyzabcde2"/><link
+ linkend="identifiers_in_quickbook_1_5.abcdefghijklmnopqrstuvwxyzabcde2">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h55">
+ <phrase id="identifiers_in_quickbook_1_5.markup_in__code__phrase_role__identifier__heading__phrase___code___in__emphasis_role__bold__order__emphasis__to_test_normalization"/><link
+ linkend="identifiers_in_quickbook_1_5.markup_in__code__phrase_role__identifier__heading__phrase___code___in__emphasis_role__bold__order__emphasis__to_test_normalization">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h56">
+ <phrase id="identifiers_in_quickbook_1_5.markup_in_code_phrase_role_iden0"/><link
+ linkend="identifiers_in_quickbook_1_5.markup_in_code_phrase_role_iden0">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_5.h57">
+ <phrase id="identifiers_in_quickbook_1_5.markup_in_code_phrase_role_iden1"/><link
+ linkend="identifiers_in_quickbook_1_5.markup_in_code_phrase_role_iden1">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <section id="identifiers_in_quickbook_1_5.identifier_10">
+ <title><link linkend="identifiers_in_quickbook_1_5.identifier_10">Identifier
+ 10</link></title>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h0">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_duplicate_it_by_having_several_headers"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_duplicate_it_by_having_several_headers">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h1">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d0"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d0">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h2">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_duplicate_it_by_having_lots_of_headers"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_duplicate_it_by_having_lots_of_headers">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h4">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d1"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d1">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h5">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d2"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d2">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h6">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d3"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d3">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h7">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d5"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d5">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h8">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d6"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d6">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h9">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d7"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d7">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h10">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_duplicate_it_by_having_too_many_headers"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_duplicate_it_by_having_too_many_headers">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h11">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d8"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d8">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h12">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d9"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d9">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h13">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_0"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_0">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h14">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_1"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_1">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h15">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_2"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_2">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h16">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_3"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_3">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h17">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_4"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_4">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h18">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_5"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_5">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h19">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_6"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_6">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h20">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_7"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_7">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h21">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_8"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_8">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h22">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_9"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_9">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h23">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_10"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_10">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h24">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_11"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_11">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h25">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_12"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_12">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h26">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_13"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_13">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h27">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_14"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_14">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h28">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_16"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_16">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h29">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_17"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_17">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h30">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_18"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_18">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h31">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_19"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_19">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h32">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_20"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_20">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h33">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_21"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_21">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h34">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_22"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_22">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h35">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_23"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_23">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h36">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_24"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_24">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h37">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_25"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_25">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h38">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_26"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_26">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h39">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_duplicate_it_by_having_even_more_headers"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_duplicate_it_by_having_even_more_headers">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h40">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_27"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_27">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h41">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_28"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_28">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h42">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_29"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_29">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h43">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d4"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_d4">Generate
+ a really long id and d4</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h44">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_15"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_15">Generate
+ a really long id and 15</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h45">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_30"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_30">Generate
+ a really long id and d4</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h46">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_31"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.generate_a_really_long_id_and_31">Generate
+ a really long id and 15</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h47">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.a2345678901234567890123456789012"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.a2345678901234567890123456789012">a2345678901234567890123456789012</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h48">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.a0"/><link linkend="identifiers_in_quickbook_1_5.identifier_10.a0">a2345678901234567890123456789012</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h49">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.abcdefghijklmnopqrstuvwxyzabcdef"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.abcdefghijklmnopqrstuvwxyzabcdef">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h50">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.abcdefghijklmnopqrstuvwxyzabcde0"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.abcdefghijklmnopqrstuvwxyzabcde0">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h51">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.abcdefghijklmnopqrstuvwxyzabcde1"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.abcdefghijklmnopqrstuvwxyzabcde1">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h52">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.abcdefghijklmnopqrstuvwxyzabcde2"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.abcdefghijklmnopqrstuvwxyzabcde2">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h53">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.markup_in__code__phrase_role__identifier__heading__phrase___code___in__emphasis_role__bold__order__emphasis__to_test_normalization"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.markup_in__code__phrase_role__identifier__heading__phrase___code___in__emphasis_role__bold__order__emphasis__to_test_normalization">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h54">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.markup_in_code_phrase_role_iden0"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.markup_in_code_phrase_role_iden0">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.identifier_10.h55">
+ <phrase id="identifiers_in_quickbook_1_5.identifier_10.markup_in_code_phrase_role_iden1"/><link
+ linkend="identifiers_in_quickbook_1_5.identifier_10.markup_in_code_phrase_role_iden1">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <table frame="all" id="identifiers_in_quickbook_1_5.identifier_10.h3">
+ <title>h3</title>
+ <tgroup cols="1">
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="identifiers_in_quickbook_1_5.identifier_10.h3_0">
+ <title>h3</title>
+ <tgroup cols="1">
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="identifiers_in_quickbook_1_5.punctuation___stuff">
+ <title><link linkend="identifiers_in_quickbook_1_5.punctuation___stuff">Punctuation
+ &amp; stuff</link></title>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.punctuation___stuff.h0">
+ <phrase id="identifiers_in_quickbook_1_5.punctuation___stuff.a___b"/><link
+ linkend="identifiers_in_quickbook_1_5.punctuation___stuff.a___b">A + B</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_5.punctuation___stuff.h1">
+ <phrase id="identifiers_in_quickbook_1_5.punctuation___stuff.a_b0"/><link linkend="identifiers_in_quickbook_1_5.punctuation___stuff.a_b0">A
+ + B</link>
+ </bridgehead>
+ </section>
+</article>
diff --git a/tools/quickbook/test/identifier-1_5.quickbook b/tools/quickbook/test/identifier-1_5.quickbook
new file mode 100644
index 0000000000..882d5df235
--- /dev/null
+++ b/tools/quickbook/test/identifier-1_5.quickbook
@@ -0,0 +1,148 @@
+[article Identifiers in quickbook 1.5
+ [quickbook 1.5]
+]
+
+[heading Test heading with `code`]
+
+[heading Identifier 10]
+[heading Identifier 10]
+[table Identifier 10
+[[]]
+]
+
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having several headers]
+
+[heading Generate a really long id and d4]
+[heading Generate a really long id and 15]
+[heading Generate a really long id and d4]
+[heading Generate a really long id and 15]
+
+[heading a2345678901234567890123456789012]
+[heading a2345678901234567890123456789012]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+
+[heading Markup in `heading` in *order* to test normalization]
+[heading Markup in `heading` in *order* to test normalization]
+[heading Markup in `heading` in *order* to test normalization]
+
+[section Identifier 10]
+
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having several headers]
+
+[heading Generate a really long id and d4]
+[heading Generate a really long id and 15]
+[heading Generate a really long id and d4]
+[heading Generate a really long id and 15]
+
+[heading a2345678901234567890123456789012]
+[heading a2345678901234567890123456789012]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+
+[heading Markup in `heading` in *order* to test normalization]
+[heading Markup in `heading` in *order* to test normalization]
+[heading Markup in `heading` in *order* to test normalization]
+
+[table h3
+[[]]
+]
+
+[table h3
+[[]]
+]
+
+[endsect]
+
+[section Punctuation & stuff]
+
+[heading A + B]
+[heading A + B]
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/identifier-1_6.gold b/tools/quickbook/test/identifier-1_6.gold
new file mode 100644
index 0000000000..3872041222
--- /dev/null
+++ b/tools/quickbook/test/identifier-1_6.gold
@@ -0,0 +1,609 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="identifiers_in_quickbook_1_6" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Identifiers in quickbook 1.6</title>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h0">
+ <phrase id="identifiers_in_quickbook_1_6.test_heading_with_code"/><link linkend="identifiers_in_quickbook_1_6.test_heading_with_code">Test
+ heading with <code><phrase role="identifier">code</phrase></code></link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h1">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10_0"/><link linkend="identifiers_in_quickbook_1_6.identifier_10_0">Identifier
+ 10</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h2">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10_1"/><link linkend="identifiers_in_quickbook_1_6.identifier_10_1">Identifier
+ 10</link>
+ </bridgehead>
+ <table frame="all" id="identifiers_in_quickbook_1_6.identifier_10_2">
+ <title>Identifier 10</title>
+ <tgroup cols="1">
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h3">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_du"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_du">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h4">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d0"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d0">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h5">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d1"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d1">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h6">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d2"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d2">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h7">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d3"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d3">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h8">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d5"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d5">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h9">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d6"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d6">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h10">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d7"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d7">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h11">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d8"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d8">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h12">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d9"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d9">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h13">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_0"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_0">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h14">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_1"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_1">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h15">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_2"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_2">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h16">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_3"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_3">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h17">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_4"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_4">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h18">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_5"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_5">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h19">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_6"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_6">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h20">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_7"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_7">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h21">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_8"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_8">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h22">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_9"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_9">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h23">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_10"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_10">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h24">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_11"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_11">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h25">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_12"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_12">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h26">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_13"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_13">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h27">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_14"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_14">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h28">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_16"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_16">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h29">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_17"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_17">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h30">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_18"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_18">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h31">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_19"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_19">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h32">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_20"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_20">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h33">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_21"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_21">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h34">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_22"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_22">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h35">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_23"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_23">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h36">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_24"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_24">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h37">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_25"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_25">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h38">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_26"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_26">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h39">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_27"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_27">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h40">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_28"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_28">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h41">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_29"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_29">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h42">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_30"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_30">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h43">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_31"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_31">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h44">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_32"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_32">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h45">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d4"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_d4">Generate
+ a really long id and d4</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h46">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_15"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_15">Generate
+ a really long id and 15</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h47">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_33"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_33">Generate
+ a really long id and d4</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h48">
+ <phrase id="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_34"/><link
+ linkend="identifiers_in_quickbook_1_6.generate_a_really_long_id_and_34">Generate
+ a really long id and 15</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h49">
+ <phrase id="identifiers_in_quickbook_1_6.a2345678901234567890123456789012"/><link
+ linkend="identifiers_in_quickbook_1_6.a2345678901234567890123456789012">a2345678901234567890123456789012</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h50">
+ <phrase id="identifiers_in_quickbook_1_6.a0"/><link linkend="identifiers_in_quickbook_1_6.a0">a2345678901234567890123456789012</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h51">
+ <phrase id="identifiers_in_quickbook_1_6.abcdefghijklmnopqrstuvwxyzabcdef"/><link
+ linkend="identifiers_in_quickbook_1_6.abcdefghijklmnopqrstuvwxyzabcdef">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h52">
+ <phrase id="identifiers_in_quickbook_1_6.abcdefghijklmnopqrstuvwxyzabcde0"/><link
+ linkend="identifiers_in_quickbook_1_6.abcdefghijklmnopqrstuvwxyzabcde0">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h53">
+ <phrase id="identifiers_in_quickbook_1_6.abcdefghijklmnopqrstuvwxyzabcde1"/><link
+ linkend="identifiers_in_quickbook_1_6.abcdefghijklmnopqrstuvwxyzabcde1">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h54">
+ <phrase id="identifiers_in_quickbook_1_6.abcdefghijklmnopqrstuvwxyzabcde2"/><link
+ linkend="identifiers_in_quickbook_1_6.abcdefghijklmnopqrstuvwxyzabcde2">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h55">
+ <phrase id="identifiers_in_quickbook_1_6.markup_in_heading_in_order_to_te"/><link
+ linkend="identifiers_in_quickbook_1_6.markup_in_heading_in_order_to_te">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h56">
+ <phrase id="identifiers_in_quickbook_1_6.markup_in_heading_in_order_to_t0"/><link
+ linkend="identifiers_in_quickbook_1_6.markup_in_heading_in_order_to_t0">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="identifiers_in_quickbook_1_6.h57">
+ <phrase id="identifiers_in_quickbook_1_6.markup_in_heading_in_order_to_t1"/><link
+ linkend="identifiers_in_quickbook_1_6.markup_in_heading_in_order_to_t1">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <section id="identifiers_in_quickbook_1_6.identifier_10">
+ <title><link linkend="identifiers_in_quickbook_1_6.identifier_10">Identifier
+ 10</link></title>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h0">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_du"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_du">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h1">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d0"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d0">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h2">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d1"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d1">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h4">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d2"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d2">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h5">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d3"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d3">Generate
+ a really long id and duplicate it by having lots of headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h6">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d5"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d5">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h7">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d6"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d6">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h8">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d7"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d7">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h9">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d8"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d8">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h10">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d9"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d9">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h11">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_0"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_0">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h12">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_1"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_1">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h13">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_2"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_2">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h14">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_3"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_3">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h15">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_4"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_4">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h16">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_5"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_5">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h17">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_6"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_6">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h18">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_7"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_7">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h19">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_8"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_8">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h20">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_9"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_9">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h21">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_10"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_10">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h22">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_11"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_11">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h23">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_12"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_12">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h24">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_13"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_13">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h25">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_14"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_14">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h26">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_16"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_16">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h27">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_17"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_17">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h28">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_18"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_18">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h29">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_19"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_19">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h30">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_20"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_20">Generate
+ a really long id and duplicate it by having too many headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h31">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_21"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_21">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h32">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_22"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_22">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h33">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_23"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_23">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h34">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_24"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_24">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h35">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_25"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_25">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h36">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_26"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_26">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h37">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_27"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_27">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h38">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_28"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_28">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h39">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_29"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_29">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h40">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_30"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_30">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h41">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_31"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_31">Generate
+ a really long id and duplicate it by having even more headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h42">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_32"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_32">Generate
+ a really long id and duplicate it by having several headers</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h43">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d4"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_d4">Generate
+ a really long id and d4</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h44">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_15"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_15">Generate
+ a really long id and 15</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h45">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_33"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_33">Generate
+ a really long id and d4</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h46">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_34"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.generate_a_really_long_id_and_34">Generate
+ a really long id and 15</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h47">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.a2345678901234567890123456789012"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.a2345678901234567890123456789012">a2345678901234567890123456789012</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h48">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.a0"/><link linkend="identifiers_in_quickbook_1_6.identifier_10.a0">a2345678901234567890123456789012</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h49">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.abcdefghijklmnopqrstuvwxyzabcdef"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.abcdefghijklmnopqrstuvwxyzabcdef">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h50">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.abcdefghijklmnopqrstuvwxyzabcde0"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.abcdefghijklmnopqrstuvwxyzabcde0">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h51">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.abcdefghijklmnopqrstuvwxyzabcde1"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.abcdefghijklmnopqrstuvwxyzabcde1">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h52">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.abcdefghijklmnopqrstuvwxyzabcde2"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.abcdefghijklmnopqrstuvwxyzabcde2">abcdefghijklmnopqrstuvwxyzabcdef</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h53">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.markup_in_heading_in_order_to_te"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.markup_in_heading_in_order_to_te">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h54">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.markup_in_heading_in_order_to_t0"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.markup_in_heading_in_order_to_t0">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.identifier_10.h55">
+ <phrase id="identifiers_in_quickbook_1_6.identifier_10.markup_in_heading_in_order_to_t1"/><link
+ linkend="identifiers_in_quickbook_1_6.identifier_10.markup_in_heading_in_order_to_t1">Markup
+ in <code><phrase role="identifier">heading</phrase></code> in <emphasis role="bold">order</emphasis>
+ to test normalization</link>
+ </bridgehead>
+ <table frame="all" id="identifiers_in_quickbook_1_6.identifier_10.h3">
+ <title>h3</title>
+ <tgroup cols="1">
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="identifiers_in_quickbook_1_6.identifier_10.h3_0">
+ <title>h3</title>
+ <tgroup cols="1">
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="identifiers_in_quickbook_1_6.punctuation_stuff">
+ <title><link linkend="identifiers_in_quickbook_1_6.punctuation_stuff">Punctuation
+ &amp; stuff</link></title>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.punctuation_stuff.h0">
+ <phrase id="identifiers_in_quickbook_1_6.punctuation_stuff.a_b"/><link linkend="identifiers_in_quickbook_1_6.punctuation_stuff.a_b">A
+ + B</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="identifiers_in_quickbook_1_6.punctuation_stuff.h1">
+ <phrase id="identifiers_in_quickbook_1_6.punctuation_stuff.a_b0"/><link linkend="identifiers_in_quickbook_1_6.punctuation_stuff.a_b0">A
+ + B</link>
+ </bridgehead>
+ </section>
+</article>
diff --git a/tools/quickbook/test/identifier-1_6.quickbook b/tools/quickbook/test/identifier-1_6.quickbook
new file mode 100644
index 0000000000..1bbf0a1c4e
--- /dev/null
+++ b/tools/quickbook/test/identifier-1_6.quickbook
@@ -0,0 +1,148 @@
+[article Identifiers in quickbook 1.6
+ [quickbook 1.6]
+]
+
+[heading Test heading with `code`]
+
+[heading Identifier 10]
+[heading Identifier 10]
+[table Identifier 10
+[[]]
+]
+
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having several headers]
+
+[heading Generate a really long id and d4]
+[heading Generate a really long id and 15]
+[heading Generate a really long id and d4]
+[heading Generate a really long id and 15]
+
+[heading a2345678901234567890123456789012]
+[heading a2345678901234567890123456789012]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+
+[heading Markup in `heading` in *order* to test normalization]
+[heading Markup in `heading` in *order* to test normalization]
+[heading Markup in `heading` in *order* to test normalization]
+
+[section Identifier 10]
+
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having lots of headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having too many headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having several headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having even more headers]
+[heading Generate a really long id and duplicate it by having several headers]
+
+[heading Generate a really long id and d4]
+[heading Generate a really long id and 15]
+[heading Generate a really long id and d4]
+[heading Generate a really long id and 15]
+
+[heading a2345678901234567890123456789012]
+[heading a2345678901234567890123456789012]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+[heading abcdefghijklmnopqrstuvwxyzabcdef]
+
+[heading Markup in `heading` in *order* to test normalization]
+[heading Markup in `heading` in *order* to test normalization]
+[heading Markup in `heading` in *order* to test normalization]
+
+[table h3
+[[]]
+]
+
+[table h3
+[[]]
+]
+
+[endsect]
+
+[section Punctuation & stuff]
+
+[heading A + B]
+[heading A + B]
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/image-1_5.gold b/tools/quickbook/test/image-1_5.gold
new file mode 100644
index 0000000000..6364ded61d
--- /dev/null
+++ b/tools/quickbook/test/image-1_5.gold
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="images_1_5" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Images 1.5</title>
+ <para>
+ <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>test</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test this.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>test this</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test&amp;this.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>test&amp;this</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test.gif"
+ height="10cm" width="10cm"></imagedata></imageobject>
+ <textobject>
+ <phrase>test</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>Foo</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>Foobie foobie foo</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>Foo &amp; bar</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test.gif"
+ height="10cm" width="10cm"></imagedata></imageobject>
+ <textobject>
+ <phrase>Foo</phrase>
+ </textobject>
+ </inlinemediaobject>
+ </para>
+ <para>
+ <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>test</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>test</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>comment</phrase>
+ </textobject>
+ </inlinemediaobject>
+ </para>
+ <para>
+ <inlinemediaobject><imageobject><imagedata fileref="test.gif" height="10cm" width="10cm"></imagedata></imageobject>
+ <textobject>
+ <phrase>test</phrase>
+ </textobject>
+ </inlinemediaobject>
+ </para>
+</article>
diff --git a/tools/quickbook/test/image-1_5.quickbook b/tools/quickbook/test/image-1_5.quickbook
new file mode 100644
index 0000000000..0774fd4471
--- /dev/null
+++ b/tools/quickbook/test/image-1_5.quickbook
@@ -0,0 +1,19 @@
+[article Images 1.5
+ [quickbook 1.5]
+]
+
+[$test.gif]
+[$test this.gif]
+[$test&this.gif]
+[$test.gif [width 10cm] [height 10cm]]
+[$test.gif [alt Foo]]
+[$test.gif [alt Foobie foobie foo]]
+[$test.gif [alt Foo & bar]]
+[$test.gif [alt Foo] [width 10cm] [height 10cm]]
+
+[$ [/comment] test.gif ]
+[$ [/comment] test.gif [/comment] ]
+[$ [/comment] test.gif [/comment] [alt comment] ]
+
+[/ This should warn about repeated attribute and then ignore it. ]
+[$test.gif [width 10cm] [height 10cm] [width 20cm]]
diff --git a/tools/quickbook/test/image-1_6.gold b/tools/quickbook/test/image-1_6.gold
new file mode 100644
index 0000000000..31eaee11e6
--- /dev/null
+++ b/tools/quickbook/test/image-1_6.gold
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="images_1_6" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Images 1.6</title>
+ <para>
+ <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject></inlinemediaobject>
+ <inlinemediaobject><imageobject><imagedata fileref="test this.gif"></imagedata></imageobject></inlinemediaobject>
+ <inlinemediaobject><imageobject><imagedata fileref="test&amp;this.gif"></imagedata></imageobject></inlinemediaobject>
+ <inlinemediaobject><imageobject><imagedata fileref="test.gif" height="10cm" width="10cm"></imagedata></imageobject></inlinemediaobject>
+ <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>Foo</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>Foobie foobie foo</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>Foo &amp; bar</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test.gif"
+ height="10cm" width="10cm"></imagedata></imageobject>
+ <textobject>
+ <phrase>Foo</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="test.gif"
+ height="10cm" width="10cm"></imagedata></imageobject>
+ <textobject>
+ <phrase>Foo[]</phrase>
+ </textobject>
+ </inlinemediaobject>
+ </para>
+ <para>
+ <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject></inlinemediaobject>
+ <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject></inlinemediaobject>
+ <inlinemediaobject><imageobject><imagedata fileref="test.gif"></imagedata></imageobject>
+ <textobject>
+ <phrase>comment</phrase>
+ </textobject>
+ </inlinemediaobject>
+ </para>
+ <para>
+ <inlinemediaobject><imageobject><imagedata fileref="test.gif" height="10cm" width="10cm"></imagedata></imageobject></inlinemediaobject>
+ </para>
+</article>
diff --git a/tools/quickbook/test/image-1_6.quickbook b/tools/quickbook/test/image-1_6.quickbook
new file mode 100644
index 0000000000..1bd3883989
--- /dev/null
+++ b/tools/quickbook/test/image-1_6.quickbook
@@ -0,0 +1,20 @@
+[article Images 1.6
+ [quickbook 1.6]
+]
+
+[$test.gif]
+[$test this.gif]
+[$test&this.gif]
+[$test.gif [width 10cm] [height 10cm]]
+[$test.gif [alt Foo]]
+[$test.gif [alt Foobie foobie foo]]
+[$test.gif [alt Foo & bar]]
+[$test.gif [alt Foo] [width 10cm] [height 10cm]]
+[$test.gif [alt Foo\[\]] [width 10cm] [height 10cm]]
+
+[$ [/comment] test.gif ]
+[$ [/comment] test.gif [/comment] ]
+[$ [/comment] test.gif [/comment] [alt comment] ]
+
+[/ This should warn about repeated attribute and then ignore it. ]
+[$test.gif [width 10cm] [height 10cm] [width 20cm]]
diff --git a/tools/quickbook/test/import-1_1-fail.quickbook b/tools/quickbook/test/import-1_1-fail.quickbook
new file mode 100644
index 0000000000..ea60df84f2
--- /dev/null
+++ b/tools/quickbook/test/import-1_1-fail.quickbook
@@ -0,0 +1,8 @@
+[article Expect import Fail
+]
+
+[section Failure]
+
+[import this-is-not-a-file.cpp]
+
+[endsect]
diff --git a/tools/quickbook/test/include-1_1-fail.quickbook b/tools/quickbook/test/include-1_1-fail.quickbook
new file mode 100644
index 0000000000..adb990e59b
--- /dev/null
+++ b/tools/quickbook/test/include-1_1-fail.quickbook
@@ -0,0 +1,8 @@
+[article Expect xinclude Fail
+]
+
+[section Failure]
+
+[include this-is-not-a-file.qbk]
+
+[endsect]
diff --git a/tools/quickbook/test/include-1_5.gold b/tools/quickbook/test/include-1_5.gold
new file mode 100644
index 0000000000..f8a347e2e9
--- /dev/null
+++ b/tools/quickbook/test/include-1_5.gold
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include-test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include Test</title>
+ <section id="include_test_sub_document.test">
+ <title><link linkend="include_test_sub_document.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+ <section id="foo.test">
+ <title><link linkend="foo.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+ <para>
+ Just trying including in a conditional macro.
+ </para>
+ <section id="foo2.test">
+ <title><link linkend="foo2.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+ <para>
+ With some text around it.
+ </para>
+</article>
diff --git a/tools/quickbook/test/include-1_5.quickbook b/tools/quickbook/test/include-1_5.quickbook
new file mode 100644
index 0000000000..849d19ceca
--- /dev/null
+++ b/tools/quickbook/test/include-1_5.quickbook
@@ -0,0 +1,17 @@
+[article Include Test
+ [quickbook 1.5]
+ [id include-test]
+]
+
+[include include_sub-1_5.qbk]
+[include .\include_sub.qbk]
+[include:foo include_sub.qbk]
+[include empty.qbk]
+
+[def __defined__]
+
+[? __undefined__ [include:foo1 include_sub.qbk] ]
+[? __undefined__ [include:foo1 not_a_file.qbk] ]
+[? __defined__
+ Just trying including in a conditional macro. [include:foo2 include_sub.qbk]
+ With some text around it.]
diff --git a/tools/quickbook/test/include-1_6.gold b/tools/quickbook/test/include-1_6.gold
new file mode 100644
index 0000000000..f5b5af358a
--- /dev/null
+++ b/tools/quickbook/test/include-1_6.gold
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include-test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include Test</title>
+ <section id="include-test.test">
+ <title><link linkend="include-test.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+ <section id="foo.test">
+ <title><link linkend="foo.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+ <para>
+ Just trying including in a conditional macro.
+ </para>
+ <section id="foo2.test">
+ <title><link linkend="foo2.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+ <para>
+ With some text around it.
+ </para>
+</article>
diff --git a/tools/quickbook/test/include-1_6.quickbook b/tools/quickbook/test/include-1_6.quickbook
new file mode 100644
index 0000000000..00d6033e3b
--- /dev/null
+++ b/tools/quickbook/test/include-1_6.quickbook
@@ -0,0 +1,15 @@
+[article Include Test
+ [quickbook 1.6]
+ [id include-test]
+]
+
+[include include_sub.qbk]
+[include:foo include_sub.qbk]
+
+[def __defined__]
+
+[? __undefined__ [include:foo1 include_sub.qbk] ]
+[? __undefined__ [include:foo1 not-a-file.qbk] ]
+[? __defined__
+ Just trying including in a conditional macro. [include:foo2 include_sub.qbk]
+ With some text around it.]
diff --git a/tools/quickbook/test/include/Jamfile.v2 b/tools/quickbook/test/include/Jamfile.v2
new file mode 100644
index 0000000000..3ab39b201a
--- /dev/null
+++ b/tools/quickbook/test/include/Jamfile.v2
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2011 Daniel James
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+project test/includes
+ : requirements
+ <toolset>msvc:<debug-symbols>off
+ ;
+
+import quickbook-testing : quickbook-test quickbook-error-test ;
+
+test-suite quickbook.test :
+ [ quickbook-test import-basic-1.6 ]
+ [ quickbook-test filename ]
+ [ quickbook-test filename-path : : : <quickbook-test-include>sub ]
+ [ quickbook-test doc-title1-1.5 ]
+ [ quickbook-test doc-title1a-1.5 ]
+ [ quickbook-test section ]
+ [ quickbook-test section-unclosed ]
+ [ quickbook-test templates-1.5 ]
+ [ quickbook-test templates-1.6 ]
+ [ quickbook-test macros-1.5 ]
+ [ quickbook-test macros-1.6 ]
+ [ quickbook-test code-import ]
+ [ quickbook-test code-include ]
+ [ quickbook-test include-id-1.5 ]
+ [ quickbook-test include-id-1.6 ]
+ [ quickbook-test include_id_unbalanced-1_6 ]
+ [ quickbook-error-test section-fail1 ]
+ [ quickbook-error-test section-fail2 ]
+ [ quickbook-test in_section-1_5 ]
+ [ quickbook-test in_section-1_6 ]
+ [ quickbook-test compatibility-1_1 ]
+ [ quickbook-test compatibility-1_5 ]
+ [ quickbook-test compatibility-1_6 ]
+ [ quickbook-test source_mode-1_5 ]
+ [ quickbook-test source_mode-1_6 ]
+ [ quickbook-test nested_compatibility-1_5 ]
+ [ quickbook-test nested_compatibility-1_6 ]
+ ;
diff --git a/tools/quickbook/test/include/code-import.gold b/tools/quickbook/test/include/code-import.gold
new file mode 100644
index 0000000000..12089ece2b
--- /dev/null
+++ b/tools/quickbook/test/include/code-import.gold
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="import" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Import</title>
+ <para>
+ This is the <emphasis role="bold"><emphasis>foo</emphasis></emphasis> function.
+ </para>
+ <para>
+ This description can have paragraphs...
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ lists
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ etc.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ And any quickbook block markup.
+ </para>
+ <para>
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">foo</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">// return 'em, foo man!</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="string">&quot;foo&quot;</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <para>
+ This is the Python <emphasis role="bold"><emphasis>foo</emphasis></emphasis>
+ function.
+ </para>
+ <para>
+ This description can have paragraphs...
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ lists
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ etc.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ And any quickbook block markup.
+ </para>
+ <para>
+<programlisting><phrase role="keyword">def</phrase> <phrase role="identifier">foo</phrase><phrase role="special">():</phrase>
+ <phrase role="comment"># return 'em, foo man!</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="string">&quot;foo&quot;</phrase>
+</programlisting>
+ </para>
+ <para>
+ This is the C <emphasis role="bold"><emphasis>foo</emphasis></emphasis> function.
+ </para>
+ <para>
+ This description can have paragraphs...
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ lists
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ etc.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ And any quickbook block markup.
+ </para>
+ <para>
+<programlisting><phrase role="keyword">char</phrase><phrase role="special">*</phrase> <phrase role="identifier">foo</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">// return 'em, foo man!</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="string">&quot;foo&quot;</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <para>
+<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">x</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+
+ <co id="import.c0" linkends="import.c1" /><phrase role="identifier">x</phrase><phrase role="special">()</phrase> <phrase role="special">:</phrase> <phrase role="identifier">n</phrase><phrase role="special">(</phrase><phrase role="number">0</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="special">}</phrase>
+
+ <co id="import.c2" linkends="import.c3" /><phrase role="special">~</phrase><phrase role="identifier">x</phrase><phrase role="special">()</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="special">}</phrase>
+
+ <co id="import.c4" linkends="import.c5" /><phrase role="keyword">int</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">n</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+
+ <co id="import.c6" linkends="import.c7" /><phrase role="keyword">void</phrase> <phrase role="identifier">set</phrase><phrase role="special">(</phrase><phrase role="keyword">int</phrase> <phrase role="identifier">n_</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="identifier">n</phrase> <phrase role="special">=</phrase> <phrase role="identifier">n_</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="import.c0" id="import.c1">
+ <para>
+ Constructor
+ </para>
+ </callout>
+ <callout arearefs="import.c2" id="import.c3">
+ <para>
+ Destructor
+ </para>
+ </callout>
+ <callout arearefs="import.c4" id="import.c5">
+ <para>
+ Get the <code><phrase role="identifier">n</phrase></code> member variable
+ </para>
+ </callout>
+ <callout arearefs="import.c6" id="import.c7">
+ <para>
+ Set the <code><phrase role="identifier">n</phrase></code> member variable
+ </para>
+ </callout>
+ </calloutlist>
+</article>
diff --git a/tools/quickbook/test/include/code-import.quickbook b/tools/quickbook/test/include/code-import.quickbook
new file mode 100644
index 0000000000..70faf07769
--- /dev/null
+++ b/tools/quickbook/test/include/code-import.quickbook
@@ -0,0 +1,13 @@
+[article Import]
+
+[import ../stub.c]
+[import ../stub.py]
+[import ../stub.cpp]
+
+[foo]
+
+[foo_py]
+
+[foo_c]
+
+[class_] \ No newline at end of file
diff --git a/tools/quickbook/test/include/code-include.gold b/tools/quickbook/test/include/code-include.gold
new file mode 100644
index 0000000000..dfa697fd8b
--- /dev/null
+++ b/tools/quickbook/test/include/code-include.gold
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include</title>
+ <para>
+ This should appear when <literal>stub.c</literal> is included.
+ </para>
+ <para>
+ This is the C <emphasis role="bold"><emphasis>foo</emphasis></emphasis> function.
+ </para>
+ <para>
+ This description can have paragraphs...
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ lists
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ etc.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ And any quickbook block markup.
+ </para>
+<programlisting><phrase role="keyword">char</phrase><phrase role="special">*</phrase> <phrase role="identifier">foo</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">// return 'em, foo man!</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="string">&quot;foo&quot;</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ <para>
+ This should appear when <literal>stub.py</literal> is included.
+ </para>
+ <para>
+ This should appear when <literal>stub.cpp</literal> is included.
+ </para>
+ <para>
+ [foo]
+ </para>
+ <para>
+ [foo_py]
+ </para>
+ <para>
+ [foo_c]
+ </para>
+</article>
diff --git a/tools/quickbook/test/include/code-include.quickbook b/tools/quickbook/test/include/code-include.quickbook
new file mode 100644
index 0000000000..8a47538f16
--- /dev/null
+++ b/tools/quickbook/test/include/code-include.quickbook
@@ -0,0 +1,16 @@
+[article Include
+[quickbook 1.6]
+]
+
+[include ../stub.c]
+[include ../stub.py]
+[include ../stub.cpp]
+
+[/ These shouldn't expand ]
+
+[foo]
+
+[foo_py]
+
+[foo_c]
+
diff --git a/tools/quickbook/test/include/compatibility-1_1.gold b/tools/quickbook/test/include/compatibility-1_1.gold
new file mode 100644
index 0000000000..961d6aa512
--- /dev/null
+++ b/tools/quickbook/test/include/compatibility-1_1.gold
@@ -0,0 +1,362 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="compatibility" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Test Compatibility Mode</title>
+ <section id="compatibility.collision">
+ <title>Outer</title>
+ <section id="test_compatibility_mode.inner">
+ <title>Inner</title>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h0">
+ <phrase id="test_compatibility_mode.collision.inner.header"/><link linkend="test_compatibility_mode.collision.inner.header">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="inner.heading1">
+ Heading1
+ </bridgehead>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h1">
+ <phrase id="test_compatibility_mode.collision.inner.x1"/><link linkend="test_compatibility_mode.collision.inner.x1">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="test_compatibility_mode.collision.inner.h2">
+ <phrase id="test_compatibility_mode.collision.inner.x2"/><link linkend="test_compatibility_mode.collision.inner.x2">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="test_compatibility_mode.collision.inner.withid">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="test_compatibility_mode.collision.inner.t0">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="test_compatibility_mode.collision.inner.x">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="test_compatibility_mode.x">
+ <title>Inner with id</title>
+ </section>
+ </section>
+ <section id="compatibility.collision0">
+ <title>Include compatibility 1.1</title>
+ <section id="test_compatibility_mode.inner0">
+ <title>Inner</title>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h3">
+ <phrase id="test_compatibility_mode.collision.inner.header0"/><link linkend="test_compatibility_mode.collision.inner.header0">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="inner.heading1_0">
+ Heading1
+ </bridgehead>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h4">
+ <phrase id="test_compatibility_mode.collision.inner.x1_0"/><link linkend="test_compatibility_mode.collision.inner.x1_0">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="test_compatibility_mode.collision.inner.h5">
+ <phrase id="test_compatibility_mode.collision.inner.x2_0"/><link linkend="test_compatibility_mode.collision.inner.x2_0">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="test_compatibility_mode.collision.inner.withid0">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="test_compatibility_mode.collision.inner.t1">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="test_compatibility_mode.collision.inner.x0">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="test_compatibility_mode.x0">
+ <title>Inner with id</title>
+ </section>
+ </section>
+ <section id="compatibility.collision1">
+ <title>Include compatibility 1.5</title>
+ <section id="test_compatibility_mode.collision.inner">
+ <title><link linkend="test_compatibility_mode.collision.inner">Inner</link></title>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h6">
+ <phrase id="test_compatibility_mode.collision.inner.header1"/><link linkend="test_compatibility_mode.collision.inner.header1">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="test_compatibility_mode.collision.inner.h7">
+ <phrase id="test_compatibility_mode.collision.inner.heading1"/><link linkend="test_compatibility_mode.collision.inner.heading1">Heading1</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h8">
+ <phrase id="test_compatibility_mode.collision.inner.x1_1"/><link linkend="test_compatibility_mode.collision.inner.x1_1">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="test_compatibility_mode.collision.inner.h9">
+ <phrase id="test_compatibility_mode.collision.inner.x2_1"/><link linkend="test_compatibility_mode.collision.inner.x2_1">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="test_compatibility_mode.collision.inner.withid1">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="test_compatibility_mode.collision.inner.with_title">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="test_compatibility_mode.collision.inner.x3">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="test_compatibility_mode.collision.x">
+ <title><link linkend="test_compatibility_mode.collision.x">Inner with id</link></title>
+ </section>
+ </section>
+ <section id="compatibility.collision2">
+ <title>Include compatibility 1.6</title>
+ <section id="compatibility.collision.inner">
+ <title><link linkend="compatibility.collision.inner">Inner</link></title>
+ <bridgehead renderas="sect4" id="compatibility.collision.inner.h0">
+ <phrase id="compatibility.collision.inner.header"/><link linkend="compatibility.collision.inner.header">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="compatibility.collision.inner.h1">
+ <phrase id="compatibility.collision.inner.heading1"/><link linkend="compatibility.collision.inner.heading1">Heading1</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="compatibility.collision.inner.h2">
+ <phrase id="compatibility.collision.inner.x1"/><link linkend="compatibility.collision.inner.x1">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="compatibility.collision.inner.h3">
+ <phrase id="compatibility.collision.inner.x2"/><link linkend="compatibility.collision.inner.x2">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="compatibility.collision.inner.withid">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="compatibility.collision.inner.with_title">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="compatibility.collision.inner.x">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="compatibility.collision.x">
+ <title><link linkend="compatibility.collision.x">Inner with id</link></title>
+ </section>
+ </section>
+</article>
diff --git a/tools/quickbook/test/include/compatibility-1_1.quickbook b/tools/quickbook/test/include/compatibility-1_1.quickbook
new file mode 100644
index 0000000000..ec5d62f55b
--- /dev/null
+++ b/tools/quickbook/test/include/compatibility-1_1.quickbook
@@ -0,0 +1,18 @@
+[article Test Compatibility Mode
+[quickbook 1.6]
+[compatibility-mode 1.1]
+[id compatibility]
+]
+
+[section:collision Outer]
+[include compatibility-inc.qbk]
+[endsect]
+[section:collision Include compatibility 1.1]
+[include compatibility-inc_1_1.qbk]
+[endsect]
+[section:collision Include compatibility 1.5]
+[include compatibility-inc_1_5.qbk]
+[endsect]
+[section:collision Include compatibility 1.6]
+[include compatibility-inc_1_6.qbk]
+[endsect]
diff --git a/tools/quickbook/test/include/compatibility-1_5.gold b/tools/quickbook/test/include/compatibility-1_5.gold
new file mode 100644
index 0000000000..79245caf1c
--- /dev/null
+++ b/tools/quickbook/test/include/compatibility-1_5.gold
@@ -0,0 +1,362 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="compatibility" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Test Compatibility Mode</title>
+ <section id="compatibility.collision">
+ <title><link linkend="compatibility.collision">Outer</link></title>
+ <section id="test_compatibility_mode.collision.inner">
+ <title><link linkend="test_compatibility_mode.collision.inner">Inner</link></title>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h0">
+ <phrase id="test_compatibility_mode.collision.inner.header"/><link linkend="test_compatibility_mode.collision.inner.header">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="test_compatibility_mode.collision.inner.h1">
+ <phrase id="test_compatibility_mode.collision.inner.heading1"/><link linkend="test_compatibility_mode.collision.inner.heading1">Heading1</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h2">
+ <phrase id="test_compatibility_mode.collision.inner.x1"/><link linkend="test_compatibility_mode.collision.inner.x1">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="test_compatibility_mode.collision.inner.h3">
+ <phrase id="test_compatibility_mode.collision.inner.x2"/><link linkend="test_compatibility_mode.collision.inner.x2">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="test_compatibility_mode.collision.inner.withid">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="test_compatibility_mode.collision.inner.with_title">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="test_compatibility_mode.collision.inner.x">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="test_compatibility_mode.collision.x">
+ <title><link linkend="test_compatibility_mode.collision.x">Inner with id</link></title>
+ </section>
+ </section>
+ <section id="compatibility.collision0">
+ <title><link linkend="compatibility.collision0">Include compatibility 1.1</link></title>
+ <section id="test_compatibility_mode.inner">
+ <title>Inner</title>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h4">
+ <phrase id="test_compatibility_mode.collision.inner.header0"/><link linkend="test_compatibility_mode.collision.inner.header0">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="inner.heading1">
+ Heading1
+ </bridgehead>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h5">
+ <phrase id="test_compatibility_mode.collision.inner.x1_0"/><link linkend="test_compatibility_mode.collision.inner.x1_0">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="test_compatibility_mode.collision.inner.h6">
+ <phrase id="test_compatibility_mode.collision.inner.x2_0"/><link linkend="test_compatibility_mode.collision.inner.x2_0">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="test_compatibility_mode.collision.inner.withid0">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="test_compatibility_mode.collision.inner.t0">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="test_compatibility_mode.collision.inner.x0">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="test_compatibility_mode.x">
+ <title>Inner with id</title>
+ </section>
+ </section>
+ <section id="compatibility.collision1">
+ <title><link linkend="compatibility.collision1">Include compatibility 1.5</link></title>
+ <section id="test_compatibility_mode.collision.inner0">
+ <title><link linkend="test_compatibility_mode.collision.inner0">Inner</link></title>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h7">
+ <phrase id="test_compatibility_mode.collision.inner.header1"/><link linkend="test_compatibility_mode.collision.inner.header1">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="test_compatibility_mode.collision.inner.h8">
+ <phrase id="test_compatibility_mode.collision.inner.heading1_0"/><link linkend="test_compatibility_mode.collision.inner.heading1_0">Heading1</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="test_compatibility_mode.collision.inner.h9">
+ <phrase id="test_compatibility_mode.collision.inner.x1_1"/><link linkend="test_compatibility_mode.collision.inner.x1_1">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="test_compatibility_mode.collision.inner.h10">
+ <phrase id="test_compatibility_mode.collision.inner.x2_1"/><link linkend="test_compatibility_mode.collision.inner.x2_1">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="test_compatibility_mode.collision.inner.withid1">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="test_compatibility_mode.collision.inner.with_title0">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="test_compatibility_mode.collision.inner.x3">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="test_compatibility_mode.collision.x0">
+ <title><link linkend="test_compatibility_mode.collision.x0">Inner with id</link></title>
+ </section>
+ </section>
+ <section id="compatibility.collision2">
+ <title><link linkend="compatibility.collision2">Include compatibility 1.6</link></title>
+ <section id="compatibility.collision.inner">
+ <title><link linkend="compatibility.collision.inner">Inner</link></title>
+ <bridgehead renderas="sect4" id="compatibility.collision.inner.h0">
+ <phrase id="compatibility.collision.inner.header"/><link linkend="compatibility.collision.inner.header">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="compatibility.collision.inner.h1">
+ <phrase id="compatibility.collision.inner.heading1"/><link linkend="compatibility.collision.inner.heading1">Heading1</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="compatibility.collision.inner.h2">
+ <phrase id="compatibility.collision.inner.x1"/><link linkend="compatibility.collision.inner.x1">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="compatibility.collision.inner.h3">
+ <phrase id="compatibility.collision.inner.x2"/><link linkend="compatibility.collision.inner.x2">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="compatibility.collision.inner.withid">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="compatibility.collision.inner.with_title">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="compatibility.collision.inner.x">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="compatibility.collision.x">
+ <title><link linkend="compatibility.collision.x">Inner with id</link></title>
+ </section>
+ </section>
+</article>
diff --git a/tools/quickbook/test/include/compatibility-1_5.quickbook b/tools/quickbook/test/include/compatibility-1_5.quickbook
new file mode 100644
index 0000000000..c16ddac5e9
--- /dev/null
+++ b/tools/quickbook/test/include/compatibility-1_5.quickbook
@@ -0,0 +1,18 @@
+[article Test Compatibility Mode
+[compatibility-mode 1.5]
+[id compatibility]
+[quickbook 1.6]
+]
+
+[section:collision Outer]
+[include compatibility-inc.qbk]
+[endsect]
+[section:collision Include compatibility 1.1]
+[include compatibility-inc_1_1.qbk]
+[endsect]
+[section:collision Include compatibility 1.5]
+[include compatibility-inc_1_5.qbk]
+[endsect]
+[section:collision Include compatibility 1.6]
+[include compatibility-inc_1_6.qbk]
+[endsect]
diff --git a/tools/quickbook/test/include/compatibility-1_6.gold b/tools/quickbook/test/include/compatibility-1_6.gold
new file mode 100644
index 0000000000..b3e51277f4
--- /dev/null
+++ b/tools/quickbook/test/include/compatibility-1_6.gold
@@ -0,0 +1,362 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="compatibility" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Test Compatibility Mode</title>
+ <section id="compatibility.collision">
+ <title><link linkend="compatibility.collision">Outer</link></title>
+ <section id="compatibility.collision.inner">
+ <title><link linkend="compatibility.collision.inner">Inner</link></title>
+ <bridgehead renderas="sect4" id="compatibility.collision.inner.h0">
+ <phrase id="compatibility.collision.inner.header"/><link linkend="compatibility.collision.inner.header">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="compatibility.collision.inner.h1">
+ <phrase id="compatibility.collision.inner.heading1"/><link linkend="compatibility.collision.inner.heading1">Heading1</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="compatibility.collision.inner.h2">
+ <phrase id="compatibility.collision.inner.x1"/><link linkend="compatibility.collision.inner.x1">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="compatibility.collision.inner.h3">
+ <phrase id="compatibility.collision.inner.x2"/><link linkend="compatibility.collision.inner.x2">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="compatibility.collision.inner.withid">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="compatibility.collision.inner.with_title">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="compatibility.collision.inner.x">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="compatibility.collision.x">
+ <title><link linkend="compatibility.collision.x">Inner with id</link></title>
+ </section>
+ </section>
+ <section id="compatibility.collision0">
+ <title><link linkend="compatibility.collision0">Include compatibility 1.1</link></title>
+ <section id="compatibility.collision0.inner">
+ <title>Inner</title>
+ <bridgehead renderas="sect4" id="compatibility.collision0.inner.h0">
+ <phrase id="compatibility.collision0.inner.header"/><link linkend="compatibility.collision0.inner.header">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="inner.heading1">
+ Heading1
+ </bridgehead>
+ <bridgehead renderas="sect4" id="compatibility.collision0.inner.h1">
+ <phrase id="compatibility.collision0.inner.x1"/><link linkend="compatibility.collision0.inner.x1">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="compatibility.collision0.inner.h2">
+ <phrase id="compatibility.collision0.inner.x2"/><link linkend="compatibility.collision0.inner.x2">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="compatibility.collision0.inner.withid">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="compatibility.collision0.inner.t0">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="compatibility.collision0.inner.x">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="compatibility.collision0.x">
+ <title>Inner with id</title>
+ </section>
+ </section>
+ <section id="compatibility.collision1">
+ <title><link linkend="compatibility.collision1">Include compatibility 1.5</link></title>
+ <section id="compatibility.collision1.inner">
+ <title><link linkend="compatibility.collision1.inner">Inner</link></title>
+ <bridgehead renderas="sect4" id="compatibility.collision1.inner.h0">
+ <phrase id="compatibility.collision1.inner.header"/><link linkend="compatibility.collision1.inner.header">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="compatibility.collision1.inner.h1">
+ <phrase id="compatibility.collision1.inner.heading1"/><link linkend="compatibility.collision1.inner.heading1">Heading1</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="compatibility.collision1.inner.h2">
+ <phrase id="compatibility.collision1.inner.x1"/><link linkend="compatibility.collision1.inner.x1">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="compatibility.collision1.inner.h3">
+ <phrase id="compatibility.collision1.inner.x2"/><link linkend="compatibility.collision1.inner.x2">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="compatibility.collision1.inner.withid">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="compatibility.collision1.inner.with_title">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="compatibility.collision1.inner.x">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="compatibility.collision1.x">
+ <title><link linkend="compatibility.collision1.x">Inner with id</link></title>
+ </section>
+ </section>
+ <section id="compatibility.collision2">
+ <title><link linkend="compatibility.collision2">Include compatibility 1.6</link></title>
+ <section id="compatibility.collision2.inner">
+ <title><link linkend="compatibility.collision2.inner">Inner</link></title>
+ <bridgehead renderas="sect4" id="compatibility.collision2.inner.h0">
+ <phrase id="compatibility.collision2.inner.header"/><link linkend="compatibility.collision2.inner.header">Header</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="compatibility.collision2.inner.h1">
+ <phrase id="compatibility.collision2.inner.heading1"/><link linkend="compatibility.collision2.inner.heading1">Heading1</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="compatibility.collision2.inner.h2">
+ <phrase id="compatibility.collision2.inner.x1"/><link linkend="compatibility.collision2.inner.x1">Header
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect1" id="compatibility.collision2.inner.h3">
+ <phrase id="compatibility.collision2.inner.x2"/><link linkend="compatibility.collision2.inner.x2">Heading1
+ with id</link>
+ </bridgehead>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="compatibility.collision2.inner.withid">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="compatibility.collision2.inner.with_title">
+ <title>With Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="compatibility.collision2.inner.x">
+ <title>Id and Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="compatibility.collision2.x">
+ <title><link linkend="compatibility.collision2.x">Inner with id</link></title>
+ </section>
+ </section>
+</article>
diff --git a/tools/quickbook/test/include/compatibility-1_6.quickbook b/tools/quickbook/test/include/compatibility-1_6.quickbook
new file mode 100644
index 0000000000..276674afca
--- /dev/null
+++ b/tools/quickbook/test/include/compatibility-1_6.quickbook
@@ -0,0 +1,17 @@
+[article Test Compatibility Mode
+[id compatibility]
+[quickbook 1.6]
+]
+
+[section:collision Outer]
+[include compatibility-inc.qbk]
+[endsect]
+[section:collision Include compatibility 1.1]
+[include compatibility-inc_1_1.qbk]
+[endsect]
+[section:collision Include compatibility 1.5]
+[include compatibility-inc_1_5.qbk]
+[endsect]
+[section:collision Include compatibility 1.6]
+[include compatibility-inc_1_6.qbk]
+[endsect]
diff --git a/tools/quickbook/test/include/compatibility-inc.qbk b/tools/quickbook/test/include/compatibility-inc.qbk
new file mode 100644
index 0000000000..66fbb54eee
--- /dev/null
+++ b/tools/quickbook/test/include/compatibility-inc.qbk
@@ -0,0 +1,31 @@
+[section Inner]
+
+[heading Header]
+
+[h1 Heading1]
+
+[heading:x1 Header with id]
+
+[h1:x2 Heading1 with id]
+
+[table
+[[]][[]]
+]
+
+[table:withid
+[[]][[]]
+]
+
+[table With Title
+[[]][[]]
+]
+
+[table:x Id and Title
+[[]][[]]
+]
+
+
+[endsect]
+
+[section:x Inner with id]
+[endsect]
diff --git a/tools/quickbook/test/include/compatibility-inc_1_1.qbk b/tools/quickbook/test/include/compatibility-inc_1_1.qbk
new file mode 100644
index 0000000000..89b4d6554a
--- /dev/null
+++ b/tools/quickbook/test/include/compatibility-inc_1_1.qbk
@@ -0,0 +1,33 @@
+[compatibility-mode 1.1]
+
+[section Inner]
+
+[heading Header]
+
+[h1 Heading1]
+
+[heading:x1 Header with id]
+
+[h1:x2 Heading1 with id]
+
+[table
+[[]][[]]
+]
+
+[table:withid
+[[]][[]]
+]
+
+[table With Title
+[[]][[]]
+]
+
+[table:x Id and Title
+[[]][[]]
+]
+
+
+[endsect]
+
+[section:x Inner with id]
+[endsect]
diff --git a/tools/quickbook/test/include/compatibility-inc_1_5.qbk b/tools/quickbook/test/include/compatibility-inc_1_5.qbk
new file mode 100644
index 0000000000..5551da5b37
--- /dev/null
+++ b/tools/quickbook/test/include/compatibility-inc_1_5.qbk
@@ -0,0 +1,33 @@
+[compatibility-mode 1.5]
+
+[section Inner]
+
+[heading Header]
+
+[h1 Heading1]
+
+[heading:x1 Header with id]
+
+[h1:x2 Heading1 with id]
+
+[table
+[[]][[]]
+]
+
+[table:withid
+[[]][[]]
+]
+
+[table With Title
+[[]][[]]
+]
+
+[table:x Id and Title
+[[]][[]]
+]
+
+
+[endsect]
+
+[section:x Inner with id]
+[endsect]
diff --git a/tools/quickbook/test/include/compatibility-inc_1_6.qbk b/tools/quickbook/test/include/compatibility-inc_1_6.qbk
new file mode 100644
index 0000000000..61f3c7bcd1
--- /dev/null
+++ b/tools/quickbook/test/include/compatibility-inc_1_6.qbk
@@ -0,0 +1,33 @@
+[compatibility-mode 1.6]
+
+[section Inner]
+
+[heading Header]
+
+[h1 Heading1]
+
+[heading:x1 Header with id]
+
+[h1:x2 Heading1 with id]
+
+[table
+[[]][[]]
+]
+
+[table:withid
+[[]][[]]
+]
+
+[table With Title
+[[]][[]]
+]
+
+[table:x Id and Title
+[[]][[]]
+]
+
+
+[endsect]
+
+[section:x Inner with id]
+[endsect]
diff --git a/tools/quickbook/test/include/doc-title1-1.5.gold b/tools/quickbook/test/include/doc-title1-1.5.gold
new file mode 100644
index 0000000000..f2fb5321d6
--- /dev/null
+++ b/tools/quickbook/test/include/doc-title1-1.5.gold
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="doc_title_1" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Doc Title 1</title>
+ <bridgehead renderas="sect2" id="doc_title_1.h0">
+ <phrase id="doc_title_1.a1"/><link linkend="doc_title_1.a1">a1</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc_title_1.h1">
+ <phrase id="doc_title_1.inc1"/><link linkend="doc_title_1.inc1">inc1</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc_title_1.h2">
+ <phrase id="doc_title_1.a2"/><link linkend="doc_title_1.a2">a2</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc_title_1_inc2.h0">
+ <phrase id="doc_title_1_inc2.inc2"/><link linkend="doc_title_1_inc2.inc2">inc2</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc_title_1.h3">
+ <phrase id="doc_title_1.a3"/><link linkend="doc_title_1.a3">a3</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc_title_1_inc2.h1">
+ <phrase id="doc_title_1_inc2.inc3"/><link linkend="doc_title_1_inc2.inc3">inc3</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc_title_1.h4">
+ <phrase id="doc_title_1.a4"/><link linkend="doc_title_1.a4">a4</link>
+ </bridgehead>
+</article>
diff --git a/tools/quickbook/test/include/doc-title1-1.5.quickbook b/tools/quickbook/test/include/doc-title1-1.5.quickbook
new file mode 100644
index 0000000000..ec7a56c86a
--- /dev/null
+++ b/tools/quickbook/test/include/doc-title1-1.5.quickbook
@@ -0,0 +1,27 @@
+[article Doc Title 1
+[quickbook 1.5]
+]
+
+[/ Doc Titles for included files is a little odd. You generally don't see
+ titles in them, the only way to detect them is through the generated ids.
+ So that's what this test is for.
+
+ The second include has a title, because that isn't scoped by file it will
+ continue to be used to generated ids for the following included files -
+ but not in this document as the document id for the file is generated
+ for the whole file at the start.
+ ]
+
+[heading a1]
+
+[include doc-title1-inc1.quickbook]
+
+[heading a2]
+
+[include doc-title1-inc2.quickbook]
+
+[heading a3]
+
+[include doc-title1-inc3.quickbook]
+
+[heading a4]
diff --git a/tools/quickbook/test/include/doc-title1-inc1.quickbook b/tools/quickbook/test/include/doc-title1-inc1.quickbook
new file mode 100644
index 0000000000..e17ad31d8b
--- /dev/null
+++ b/tools/quickbook/test/include/doc-title1-inc1.quickbook
@@ -0,0 +1 @@
+[heading inc1]
diff --git a/tools/quickbook/test/include/doc-title1-inc2.quickbook b/tools/quickbook/test/include/doc-title1-inc2.quickbook
new file mode 100644
index 0000000000..e8b18d37ba
--- /dev/null
+++ b/tools/quickbook/test/include/doc-title1-inc2.quickbook
@@ -0,0 +1,4 @@
+[article Doc Title 1 Inc2
+]
+
+[heading inc2]
diff --git a/tools/quickbook/test/include/doc-title1-inc3.quickbook b/tools/quickbook/test/include/doc-title1-inc3.quickbook
new file mode 100644
index 0000000000..501e3320b9
--- /dev/null
+++ b/tools/quickbook/test/include/doc-title1-inc3.quickbook
@@ -0,0 +1 @@
+[heading inc3]
diff --git a/tools/quickbook/test/include/doc-title1a-1.5.gold b/tools/quickbook/test/include/doc-title1a-1.5.gold
new file mode 100644
index 0000000000..0ee226e9e5
--- /dev/null
+++ b/tools/quickbook/test/include/doc-title1a-1.5.gold
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="doc-title" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Doc Title 1a</title>
+ <bridgehead renderas="sect2" id="doc-title.h0">
+ <phrase id="doc-title.a1"/><link linkend="doc-title.a1">a1</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc_title_1a.h0">
+ <phrase id="doc_title_1a.inc1"/><link linkend="doc_title_1a.inc1">inc1</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc-title.h1">
+ <phrase id="doc-title.a2"/><link linkend="doc-title.a2">a2</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc_title_1_inc2.h0">
+ <phrase id="doc_title_1_inc2.inc2"/><link linkend="doc_title_1_inc2.inc2">inc2</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc-title.h2">
+ <phrase id="doc-title.a3"/><link linkend="doc-title.a3">a3</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc_title_1_inc2.h1">
+ <phrase id="doc_title_1_inc2.inc3"/><link linkend="doc_title_1_inc2.inc3">inc3</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="doc-title.h3">
+ <phrase id="doc-title.a4"/><link linkend="doc-title.a4">a4</link>
+ </bridgehead>
+</article>
diff --git a/tools/quickbook/test/include/doc-title1a-1.5.quickbook b/tools/quickbook/test/include/doc-title1a-1.5.quickbook
new file mode 100644
index 0000000000..dc12d5cb78
--- /dev/null
+++ b/tools/quickbook/test/include/doc-title1a-1.5.quickbook
@@ -0,0 +1,20 @@
+[article Doc Title 1a
+[quickbook 1.5]
+[id doc-title]
+]
+
+[/ A repeat of doc-title1, but with an explicit id. ]
+
+[heading a1]
+
+[include doc-title1-inc1.quickbook]
+
+[heading a2]
+
+[include doc-title1-inc2.quickbook]
+
+[heading a3]
+
+[include doc-title1-inc3.quickbook]
+
+[heading a4]
diff --git a/tools/quickbook/test/include/filename-path.gold b/tools/quickbook/test/include/filename-path.gold
new file mode 100644
index 0000000000..f77ab84a86
--- /dev/null
+++ b/tools/quickbook/test/include/filename-path.gold
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="filename_test_with_include_path" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Filename test with include path</title>
+ <para>
+ filename-path.quickbook
+ </para>
+ <para>
+ filename_include1.quickbook
+ </para>
+ <para>
+ ../filename_include2.quickbook
+ </para>
+ <para>
+ filename_include2.quickbook
+ </para>
+</article>
diff --git a/tools/quickbook/test/include/filename-path.quickbook b/tools/quickbook/test/include/filename-path.quickbook
new file mode 100644
index 0000000000..6121df5c5b
--- /dev/null
+++ b/tools/quickbook/test/include/filename-path.quickbook
@@ -0,0 +1,9 @@
+[article Filename test with include path
+[quickbook 1.5]
+]
+
+__FILENAME__
+
+[include filename_include1.quickbook]
+
+[include filename_include2.quickbook] \ No newline at end of file
diff --git a/tools/quickbook/test/include/filename.gold b/tools/quickbook/test/include/filename.gold
new file mode 100644
index 0000000000..3e895eb4e6
--- /dev/null
+++ b/tools/quickbook/test/include/filename.gold
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="filename_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Filename Test</title>
+ <para>
+ filename.quickbook
+ </para>
+ <para>
+ sub/filename_include1.quickbook
+ </para>
+ <para>
+ sub/../filename_include2.quickbook
+ </para>
+ <para>
+ filename_include2.quickbook
+ </para>
+</article>
diff --git a/tools/quickbook/test/include/filename.quickbook b/tools/quickbook/test/include/filename.quickbook
new file mode 100644
index 0000000000..37ff37b5cc
--- /dev/null
+++ b/tools/quickbook/test/include/filename.quickbook
@@ -0,0 +1,9 @@
+[article Filename Test
+[quickbook 1.5]
+]
+
+__FILENAME__
+
+[include sub/filename_include1.quickbook]
+
+[include filename_include2.quickbook]
diff --git a/tools/quickbook/test/include/filename_include2.quickbook b/tools/quickbook/test/include/filename_include2.quickbook
new file mode 100644
index 0000000000..f9d479a939
--- /dev/null
+++ b/tools/quickbook/test/include/filename_include2.quickbook
@@ -0,0 +1 @@
+__FILENAME__ \ No newline at end of file
diff --git a/tools/quickbook/test/include/import-basic-1.6.gold b/tools/quickbook/test/include/import-basic-1.6.gold
new file mode 100644
index 0000000000..706589aef0
--- /dev/null
+++ b/tools/quickbook/test/include/import-basic-1.6.gold
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="import-1.6" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Import Quickbook Test</title>
+ <para>
+ Macro 1: import-basic-inc1.quickbook Template 1: import-basic-1.6.quickbook
+ </para>
+ <para>
+ Macro 2: import-basic-inc2.quickbook Template 2: import-basic-1.6.quickbook
+ </para>
+</article>
diff --git a/tools/quickbook/test/include/import-basic-1.6.quickbook b/tools/quickbook/test/include/import-basic-1.6.quickbook
new file mode 100644
index 0000000000..934db6a9ed
--- /dev/null
+++ b/tools/quickbook/test/include/import-basic-1.6.quickbook
@@ -0,0 +1,12 @@
+[article Import Quickbook Test
+[quickbook 1.6]
+[id import-1.6]
+]
+
+[import import-basic-inc1.quickbook]
+
+macro1 [template1]
+
+[import import-basic-inc2.quickbook]
+
+macro2 [template2]
diff --git a/tools/quickbook/test/include/import-basic-inc1.quickbook b/tools/quickbook/test/include/import-basic-inc1.quickbook
new file mode 100644
index 0000000000..4699228455
--- /dev/null
+++ b/tools/quickbook/test/include/import-basic-inc1.quickbook
@@ -0,0 +1,4 @@
+This shouldn't show: __FILENAME__
+
+[def macro1 Macro 1: __FILENAME__]
+[template template1 Template 1: __FILENAME__] \ No newline at end of file
diff --git a/tools/quickbook/test/include/import-basic-inc2.quickbook b/tools/quickbook/test/include/import-basic-inc2.quickbook
new file mode 100644
index 0000000000..0cbaaa11d6
--- /dev/null
+++ b/tools/quickbook/test/include/import-basic-inc2.quickbook
@@ -0,0 +1,10 @@
+[article Macro import.
+[quickbook 1.6]
+]
+
+[/ TOOD: Should I have a special docinfo type for this kind of thing? ]
+
+This shouldn't show: __FILENAME__
+
+[def macro2 Macro 2: __FILENAME__]
+[template template2 Template 2: __FILENAME__] \ No newline at end of file
diff --git a/tools/quickbook/test/include/in_section-1_5.gold b/tools/quickbook/test/include/in_section-1_5.gold
new file mode 100644
index 0000000000..1dfeaff908
--- /dev/null
+++ b/tools/quickbook/test/include/in_section-1_5.gold
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include_in_section_1_5" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include in section 1.5</title>
+ <section id="include_in_section_1_5.container">
+ <title><link linkend="include_in_section_1_5.container">Container</link></title>
+ <bridgehead renderas="sect1" id="include_in_section_include_1.container.h0">
+ <phrase id="include_in_section_include_1.container.test1"/><link linkend="include_in_section_include_1.container.test1">Test1</link>
+ </bridgehead>
+ <section id="include_in_section_include_1.container.inner">
+ <title><link linkend="include_in_section_include_1.container.inner"></link></title>
+ <bridgehead renderas="sect1" id="include_in_section_include_1.container.inner.h0">
+ <phrase id="include_in_section_include_1.container.inner.test2"/><link linkend="include_in_section_include_1.container.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect1" id="section_include.container.h0">
+ <phrase id="section_include.container.test1"/><link linkend="section_include.container.test1">Test1</link>
+ </bridgehead>
+ <section id="section_include.container.inner">
+ <title><link linkend="section_include.container.inner"></link></title>
+ <bridgehead renderas="sect1" id="section_include.container.inner.h0">
+ <phrase id="section_include.container.inner.test2"/><link linkend="section_include.container.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ </section>
+ <bridgehead renderas="sect1" id="include_in_section_include_1.h0">
+ <phrase id="include_in_section_include_1.test1"/><link linkend="include_in_section_include_1.test1">Test1</link>
+ </bridgehead>
+ <section id="include_in_section_include_1.inner">
+ <title><link linkend="include_in_section_include_1.inner"></link></title>
+ <bridgehead renderas="sect1" id="include_in_section_include_1.inner.h0">
+ <phrase id="include_in_section_include_1.inner.test2"/><link linkend="include_in_section_include_1.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect1" id="section_include.h0">
+ <phrase id="section_include.test1"/><link linkend="section_include.test1">Test1</link>
+ </bridgehead>
+ <section id="section_include.inner">
+ <title><link linkend="section_include.inner"></link></title>
+ <bridgehead renderas="sect1" id="section_include.inner.h0">
+ <phrase id="section_include.inner.test2"/><link linkend="section_include.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ <section id="include_in_section_1_5.container2">
+ <title><link linkend="include_in_section_1_5.container2">Container2</link></title>
+ <bridgehead renderas="sect1" id="include_in_section_include_1.container2.h0">
+ <phrase id="include_in_section_include_1.container2.test1"/><link linkend="include_in_section_include_1.container2.test1">Test1</link>
+ </bridgehead>
+ <section id="include_in_section_include_1.container2.inner">
+ <title><link linkend="include_in_section_include_1.container2.inner"></link></title>
+ <bridgehead renderas="sect1" id="include_in_section_include_1.container2.inner.h0">
+ <phrase id="include_in_section_include_1.container2.inner.test2"/><link linkend="include_in_section_include_1.container2.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect1" id="section_include.container2.h0">
+ <phrase id="section_include.container2.test1"/><link linkend="section_include.container2.test1">Test1</link>
+ </bridgehead>
+ <section id="section_include.container2.inner">
+ <title><link linkend="section_include.container2.inner"></link></title>
+ <bridgehead renderas="sect1" id="section_include.container2.inner.h0">
+ <phrase id="section_include.container2.inner.test2"/><link linkend="section_include.container2.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ </section>
+</article>
diff --git a/tools/quickbook/test/include/in_section-1_5.quickbook b/tools/quickbook/test/include/in_section-1_5.quickbook
new file mode 100644
index 0000000000..9cd15f61d9
--- /dev/null
+++ b/tools/quickbook/test/include/in_section-1_5.quickbook
@@ -0,0 +1,16 @@
+[article Include in section 1.5
+[quickbook 1.5]
+]
+
+[section:container Container]
+[include in_section-include1.qbk]
+[include in_section-include2.qbk]
+[endsect]
+
+[include in_section-include1.qbk]
+[include in_section-include2.qbk]
+
+[section:container2 Container2]
+[include in_section-include1.qbk]
+[include in_section-include2.qbk]
+[endsect]
diff --git a/tools/quickbook/test/include/in_section-1_6.gold b/tools/quickbook/test/include/in_section-1_6.gold
new file mode 100644
index 0000000000..7601df44f7
--- /dev/null
+++ b/tools/quickbook/test/include/in_section-1_6.gold
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include_in_section_1_6" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include in section 1.6</title>
+ <section id="include_in_section_1_6.container">
+ <title><link linkend="include_in_section_1_6.container">Container</link></title>
+ <article id="include_in_section_include_1" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include in section include 1</title>
+ <bridgehead renderas="sect1" id="include_in_section_include_1.h0">
+ <phrase id="include_in_section_include_1.test1"/><link linkend="include_in_section_include_1.test1">Test1</link>
+ </bridgehead>
+ <section id="include_in_section_include_1.inner">
+ <title><link linkend="include_in_section_include_1.inner"></link></title>
+ <bridgehead renderas="sect1" id="include_in_section_include_1.inner.h0">
+ <phrase id="include_in_section_include_1.inner.test2"/><link linkend="include_in_section_include_1.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ </article>
+ <article id="section_include" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include in section include 2</title>
+ <bridgehead renderas="sect1" id="section_include.h0">
+ <phrase id="section_include.test1"/><link linkend="section_include.test1">Test1</link>
+ </bridgehead>
+ <section id="section_include.inner">
+ <title><link linkend="section_include.inner"></link></title>
+ <bridgehead renderas="sect1" id="section_include.inner.h0">
+ <phrase id="section_include.inner.test2"/><link linkend="section_include.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ </article>
+ </section>
+ <article id="include_in_section_include_1_0" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include in section include 1</title>
+ <bridgehead renderas="sect1" id="include_in_section_include_1_0.h0">
+ <phrase id="include_in_section_include_1_0.test1"/><link linkend="include_in_section_include_1_0.test1">Test1</link>
+ </bridgehead>
+ <section id="include_in_section_include_1_0.inner">
+ <title><link linkend="include_in_section_include_1_0.inner"></link></title>
+ <bridgehead renderas="sect1" id="include_in_section_include_1_0.inner.h0">
+ <phrase id="include_in_section_include_1_0.inner.test2"/><link linkend="include_in_section_include_1_0.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ </article>
+ <article id="section_include0" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include in section include 2</title>
+ <bridgehead renderas="sect1" id="section_include0.h0">
+ <phrase id="section_include0.test1"/><link linkend="section_include0.test1">Test1</link>
+ </bridgehead>
+ <section id="section_include0.inner">
+ <title><link linkend="section_include0.inner"></link></title>
+ <bridgehead renderas="sect1" id="section_include0.inner.h0">
+ <phrase id="section_include0.inner.test2"/><link linkend="section_include0.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ </article>
+ <section id="include_in_section_1_6.container2">
+ <title><link linkend="include_in_section_1_6.container2">Container2</link></title>
+ <article id="include_in_section_include_1_1" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include in section include 1</title>
+ <bridgehead renderas="sect1" id="include_in_section_include_1_1.h0">
+ <phrase id="include_in_section_include_1_1.test1"/><link linkend="include_in_section_include_1_1.test1">Test1</link>
+ </bridgehead>
+ <section id="include_in_section_include_1_1.inner">
+ <title><link linkend="include_in_section_include_1_1.inner"></link></title>
+ <bridgehead renderas="sect1" id="include_in_section_include_1_1.inner.h0">
+ <phrase id="include_in_section_include_1_1.inner.test2"/><link linkend="include_in_section_include_1_1.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ </article>
+ <article id="section_include1" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include in section include 2</title>
+ <bridgehead renderas="sect1" id="section_include1.h0">
+ <phrase id="section_include1.test1"/><link linkend="section_include1.test1">Test1</link>
+ </bridgehead>
+ <section id="section_include1.inner">
+ <title><link linkend="section_include1.inner"></link></title>
+ <bridgehead renderas="sect1" id="section_include1.inner.h0">
+ <phrase id="section_include1.inner.test2"/><link linkend="section_include1.inner.test2">Test2</link>
+ </bridgehead>
+ </section>
+ </article>
+ </section>
+</article>
diff --git a/tools/quickbook/test/include/in_section-1_6.quickbook b/tools/quickbook/test/include/in_section-1_6.quickbook
new file mode 100644
index 0000000000..45be4411b1
--- /dev/null
+++ b/tools/quickbook/test/include/in_section-1_6.quickbook
@@ -0,0 +1,16 @@
+[article Include in section 1.6
+[quickbook 1.6]
+]
+
+[section:container Container]
+[include in_section-include1.qbk]
+[include in_section-include2.qbk]
+[endsect]
+
+[include in_section-include1.qbk]
+[include in_section-include2.qbk]
+
+[section:container2 Container2]
+[include in_section-include1.qbk]
+[include in_section-include2.qbk]
+[endsect]
diff --git a/tools/quickbook/test/include/in_section-include1.qbk b/tools/quickbook/test/include/in_section-include1.qbk
new file mode 100644
index 0000000000..f8fab4d12a
--- /dev/null
+++ b/tools/quickbook/test/include/in_section-include1.qbk
@@ -0,0 +1,11 @@
+[article Include in section include 1
+[quickbook 1.6]
+]
+
+[h1 Test1]
+
+[section:inner]
+
+[h1 Test2]
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/include/in_section-include2.qbk b/tools/quickbook/test/include/in_section-include2.qbk
new file mode 100644
index 0000000000..9d8ee51698
--- /dev/null
+++ b/tools/quickbook/test/include/in_section-include2.qbk
@@ -0,0 +1,12 @@
+[article Include in section include 2
+[quickbook 1.6]
+[id section_include]
+]
+
+[h1 Test1]
+
+[section:inner]
+
+[h1 Test2]
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/include/include-id-1.5.gold b/tools/quickbook/test/include/include-id-1.5.gold
new file mode 100644
index 0000000000..4944d08d45
--- /dev/null
+++ b/tools/quickbook/test/include/include-id-1.5.gold
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include_id_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include Id Test</title>
+ <bridgehead renderas="sect2" id="a.h0">
+ <phrase id="a.simple_include"/><link linkend="a.simple_include">Simple include</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="b.h0">
+ <phrase id="b.simple_include"/><link linkend="b.simple_include">Simple include</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="c.h0">
+ <phrase id="c.title__no_id"/><link linkend="c.title__no_id">Title, no id</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="d.h0">
+ <phrase id="d.title__no_id"/><link linkend="d.title__no_id">Title, no id</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="with-id.h0">
+ <phrase id="with-id.title_with_id"/><link linkend="with-id.title_with_id">Title
+ with id</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="with-id.h1">
+ <phrase id="with-id.title_with_id0"/><link linkend="with-id.title_with_id0">Title
+ with id</link>
+ </bridgehead>
+</article>
diff --git a/tools/quickbook/test/include/include-id-1.5.quickbook b/tools/quickbook/test/include/include-id-1.5.quickbook
new file mode 100644
index 0000000000..dd4b50ad36
--- /dev/null
+++ b/tools/quickbook/test/include/include-id-1.5.quickbook
@@ -0,0 +1,10 @@
+[article Include Id Test
+[quickbook 1.5]
+]
+
+[include:a include-id-inc1.quickbook]
+[include:b include-id-inc1.quickbook]
+[include:c include-id-inc2.quickbook]
+[include:d include-id-inc2.quickbook]
+[include:e include-id-inc3.quickbook]
+[include:f include-id-inc3.quickbook]
diff --git a/tools/quickbook/test/include/include-id-1.6.gold b/tools/quickbook/test/include/include-id-1.6.gold
new file mode 100644
index 0000000000..1f4cb881fc
--- /dev/null
+++ b/tools/quickbook/test/include/include-id-1.6.gold
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include_id_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include Id Test</title>
+ <bridgehead renderas="sect2" id="a.h0">
+ <phrase id="a.simple_include"/><link linkend="a.simple_include">Simple include</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="b.h0">
+ <phrase id="b.simple_include"/><link linkend="b.simple_include">Simple include</link>
+ </bridgehead>
+ <article id="c" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include without id</title>
+ <bridgehead renderas="sect2" id="c.h0">
+ <phrase id="c.title__no_id"/><link linkend="c.title__no_id">Title, no id</link>
+ </bridgehead>
+ </article>
+ <article id="d" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include without id</title>
+ <bridgehead renderas="sect2" id="d.h0">
+ <phrase id="d.title__no_id"/><link linkend="d.title__no_id">Title, no id</link>
+ </bridgehead>
+ </article>
+ <article id="e" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include with id</title>
+ <bridgehead renderas="sect2" id="e.h0">
+ <phrase id="e.title_with_id"/><link linkend="e.title_with_id">Title with id</link>
+ </bridgehead>
+ </article>
+ <article id="f" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include with id</title>
+ <bridgehead renderas="sect2" id="f.h0">
+ <phrase id="f.title_with_id"/><link linkend="f.title_with_id">Title with id</link>
+ </bridgehead>
+ </article>
+</article>
diff --git a/tools/quickbook/test/include/include-id-1.6.quickbook b/tools/quickbook/test/include/include-id-1.6.quickbook
new file mode 100644
index 0000000000..d7d5318cd3
--- /dev/null
+++ b/tools/quickbook/test/include/include-id-1.6.quickbook
@@ -0,0 +1,10 @@
+[article Include Id Test
+[quickbook 1.6]
+]
+
+[include:a include-id-inc1.quickbook]
+[include:b include-id-inc1.quickbook]
+[include:c include-id-inc2.quickbook]
+[include:d include-id-inc2.quickbook]
+[include:e include-id-inc3.quickbook]
+[include:f include-id-inc3.quickbook]
diff --git a/tools/quickbook/test/include/include-id-inc1.quickbook b/tools/quickbook/test/include/include-id-inc1.quickbook
new file mode 100644
index 0000000000..63a761d569
--- /dev/null
+++ b/tools/quickbook/test/include/include-id-inc1.quickbook
@@ -0,0 +1 @@
+[heading Simple include]
diff --git a/tools/quickbook/test/include/include-id-inc2.quickbook b/tools/quickbook/test/include/include-id-inc2.quickbook
new file mode 100644
index 0000000000..a7dbef41b6
--- /dev/null
+++ b/tools/quickbook/test/include/include-id-inc2.quickbook
@@ -0,0 +1,5 @@
+[article Include without id
+[quickbook 1.5]
+]
+
+[heading Title, no id]
diff --git a/tools/quickbook/test/include/include-id-inc3.quickbook b/tools/quickbook/test/include/include-id-inc3.quickbook
new file mode 100644
index 0000000000..2bd2398254
--- /dev/null
+++ b/tools/quickbook/test/include/include-id-inc3.quickbook
@@ -0,0 +1,6 @@
+[article Include with id
+[quickbook 1.5]
+[id with-id]
+]
+
+[heading Title with id]
diff --git a/tools/quickbook/test/include/include_id_unbalanced-1_6.gold b/tools/quickbook/test/include/include_id_unbalanced-1_6.gold
new file mode 100644
index 0000000000..ede21ccbba
--- /dev/null
+++ b/tools/quickbook/test/include/include_id_unbalanced-1_6.gold
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="unbalanced" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Test include ids with unbalanced sections</title>
+ <section id="include1.inc1">
+ <title><link linkend="include1.inc1">Include 1</link></title>
+ <bridgehead renderas="sect3" id="include1.inc1.h0">
+ <phrase id="include1.inc1.inc1_1"/><link linkend="include1.inc1.inc1_1">Heading
+ 1</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="include1a.h0">
+ <phrase id="include1a.inc1a_1"/><link linkend="include1a.inc1a_1">Heading 1</link>
+ </bridgehead>
+ <section id="include1a.inc1a">
+ <title><link linkend="include1a.inc1a">Include 1a</link></title>
+ <bridgehead renderas="sect4" id="include1a.inc1a.h0">
+ <phrase id="include1a.inc1a.inc1a_2"/><link linkend="include1a.inc1a.inc1a_2">Heading
+ 2</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="include1a.inc1a.h1">
+ <phrase id="include1a.inc1a.inc1_2"/><link linkend="include1a.inc1a.inc1_2">Heading
+ 2</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="include1a.inc1a.h2">
+ <phrase id="include1a.inc1a.x1"/><link linkend="include1a.inc1a.x1">X1</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect3" id="include1.inc1.h1">
+ <phrase id="include1.inc1.x2"/><link linkend="include1.inc1.x2">X2</link>
+ </bridgehead>
+ </section>
+ <section id="unbalanced.sect1">
+ <title><link linkend="unbalanced.sect1">Section 1</link></title>
+ <bridgehead renderas="sect3" id="unbalanced.sect1.h0">
+ <phrase id="unbalanced.sect1.x1"/><link linkend="unbalanced.sect1.x1">X1</link>
+ </bridgehead>
+ <section id="unbalanced.sect1.sect2">
+ <title><link linkend="unbalanced.sect1.sect2">Section 2</link></title>
+ <bridgehead renderas="sect4" id="unbalanced.sect1.sect2.h0">
+ <phrase id="unbalanced.sect1.sect2.x2"/><link linkend="unbalanced.sect1.sect2.x2">X2</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="include2.h0">
+ <phrase id="include2.inc2_1"/><link linkend="include2.inc2_1">Heading 1</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect3" id="include2.h1">
+ <phrase id="include2.inc2_2"/><link linkend="include2.inc2_2">Heading 2</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="include2a.h0">
+ <phrase id="include2a.inc2a_1"/><link linkend="include2a.inc2a_1">Heading 1</link>
+ </bridgehead>
+ </section>
+ <bridgehead renderas="sect2" id="include2a.h1">
+ <phrase id="include2a.inc2a_2"/><link linkend="include2a.inc2a_2">Heading 2</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="include2.h2">
+ <phrase id="include2.inc2_3"/><link linkend="include2.inc2_3">Heading 3</link>
+ </bridgehead>
+</article>
diff --git a/tools/quickbook/test/include/include_id_unbalanced-1_6.quickbook b/tools/quickbook/test/include/include_id_unbalanced-1_6.quickbook
new file mode 100644
index 0000000000..0b299a606b
--- /dev/null
+++ b/tools/quickbook/test/include/include_id_unbalanced-1_6.quickbook
@@ -0,0 +1,19 @@
+[quickbook 1.6]
+[article Test include ids with unbalanced sections
+ [id unbalanced]
+]
+
+[/ Sections start in included files ]
+
+[include:include1 include_id_unbalanced-inc1.qbk]
+[heading:x1 X1]
+[endsect]
+[heading:x2 X2]
+[endsect]
+
+[/ Sections end in included files ]
+[section:sect1 Section 1]
+[heading:x1 X1]
+[section:sect2 Section 2]
+[heading:x2 X2]
+[include:include2 include_id_unbalanced-inc2.qbk]
diff --git a/tools/quickbook/test/include/include_id_unbalanced-inc1.qbk b/tools/quickbook/test/include/include_id_unbalanced-inc1.qbk
new file mode 100644
index 0000000000..3170f2601d
--- /dev/null
+++ b/tools/quickbook/test/include/include_id_unbalanced-inc1.qbk
@@ -0,0 +1,4 @@
+[section:inc1 Include 1]
+[heading:inc1_1 Heading 1]
+[include:include1a include_id_unbalanced-inc1a.qbk]
+[heading:inc1_2 Heading 2]
diff --git a/tools/quickbook/test/include/include_id_unbalanced-inc1a.qbk b/tools/quickbook/test/include/include_id_unbalanced-inc1a.qbk
new file mode 100644
index 0000000000..1bc46b4f57
--- /dev/null
+++ b/tools/quickbook/test/include/include_id_unbalanced-inc1a.qbk
@@ -0,0 +1,3 @@
+[heading:inc1a_1 Heading 1]
+[section:inc1a Include 1a]
+[heading:inc1a_2 Heading 2]
diff --git a/tools/quickbook/test/include/include_id_unbalanced-inc2.qbk b/tools/quickbook/test/include/include_id_unbalanced-inc2.qbk
new file mode 100644
index 0000000000..b71932423a
--- /dev/null
+++ b/tools/quickbook/test/include/include_id_unbalanced-inc2.qbk
@@ -0,0 +1,5 @@
+[heading:inc2_1 Heading 1]
+[endsect]
+[heading:inc2_2 Heading 2]
+[include:include2a include_id_unbalanced-inc2a.qbk]
+[heading:inc2_3 Heading 3]
diff --git a/tools/quickbook/test/include/include_id_unbalanced-inc2a.qbk b/tools/quickbook/test/include/include_id_unbalanced-inc2a.qbk
new file mode 100644
index 0000000000..780fb40572
--- /dev/null
+++ b/tools/quickbook/test/include/include_id_unbalanced-inc2a.qbk
@@ -0,0 +1,3 @@
+[heading:inc2a_1 Heading 1]
+[endsect]
+[heading:inc2a_2 Heading 2]
diff --git a/tools/quickbook/test/include/macros-1.5.gold b/tools/quickbook/test/include/macros-1.5.gold
new file mode 100644
index 0000000000..d5e8a5193f
--- /dev/null
+++ b/tools/quickbook/test/include/macros-1.5.gold
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="macros_test_1_5" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Macros Test 1.5</title>
+ <para>
+ Foo:macros-inc1.quickbook
+ </para>
+ <para>
+ Defined conditional phrase.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ __foo__
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Defined template:macros-1.5.quickbook
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ __defined_macro__
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ [not_defined_template]
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <emphasis role="underline">_not_defined_macro__</emphasis>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+</article>
diff --git a/tools/quickbook/test/include/macros-1.5.quickbook b/tools/quickbook/test/include/macros-1.5.quickbook
new file mode 100644
index 0000000000..a63a1f0ca4
--- /dev/null
+++ b/tools/quickbook/test/include/macros-1.5.quickbook
@@ -0,0 +1,13 @@
+[article Macros Test 1.5
+[quickbook 1.5]
+]
+
+[def __defined__]
+
+[include macros-inc1.quickbook]
+
+* __foo__
+* [defined_template]
+* __defined_macro__
+* [not_defined_template]
+* [__not_defined_macro__]
diff --git a/tools/quickbook/test/include/macros-1.6.gold b/tools/quickbook/test/include/macros-1.6.gold
new file mode 100644
index 0000000000..ec93c05c18
--- /dev/null
+++ b/tools/quickbook/test/include/macros-1.6.gold
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="macros_test_1_6" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Macros Test 1.6</title>
+ <para>
+ Foo:macros-inc1.quickbook
+ </para>
+ <para>
+ Defined conditional phrase.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ __foo__
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ [defined_template]
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ __defined_macro__
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ [not_defined_template]
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <emphasis role="underline">_not_defined_macro__</emphasis>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Foo:macros-inc1.quickbook
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Defined template:macros-1.6.quickbook
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Defined macro:macros-inc1.quickbook
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ [not_defined_template]
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <emphasis role="underline">_not_defined_macro__</emphasis>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+</article>
diff --git a/tools/quickbook/test/include/macros-1.6.quickbook b/tools/quickbook/test/include/macros-1.6.quickbook
new file mode 100644
index 0000000000..5355c090e5
--- /dev/null
+++ b/tools/quickbook/test/include/macros-1.6.quickbook
@@ -0,0 +1,21 @@
+[article Macros Test 1.6
+[quickbook 1.6]
+]
+
+[def __defined__]
+
+[include macros-inc1.quickbook]
+
+* __foo__
+* [defined_template]
+* __defined_macro__
+* [not_defined_template]
+* [__not_defined_macro__]
+
+[import macros-inc1.quickbook]
+
+* __foo__
+* [defined_template]
+* __defined_macro__
+* [not_defined_template]
+* [__not_defined_macro__]
diff --git a/tools/quickbook/test/include/macros-inc1.quickbook b/tools/quickbook/test/include/macros-inc1.quickbook
new file mode 100644
index 0000000000..f8b6f25bc5
--- /dev/null
+++ b/tools/quickbook/test/include/macros-inc1.quickbook
@@ -0,0 +1,15 @@
+[def __foo__ Foo:__FILENAME__]
+
+__foo__
+
+[?__defined__
+Defined conditional phrase.
+[template defined_template Defined template:__FILENAME__]
+[def __defined_macro__ Defined macro:__FILENAME__]
+]
+
+[?__not_defined__
+Not defined conditional phrase.
+[template not_defined_template Not defined template:__FILENAME__]
+[def __not_defined_macro__ Not defined macro:__FILENAME__]
+] \ No newline at end of file
diff --git a/tools/quickbook/test/include/nested_compatibility-1_5.gold b/tools/quickbook/test/include/nested_compatibility-1_5.gold
new file mode 100644
index 0000000000..92c948a14b
--- /dev/null
+++ b/tools/quickbook/test/include/nested_compatibility-1_5.gold
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="nested_compatibility_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Nested Compatibility Test</title>
+ <section id="nested_compatibility_test.duplicate_name">
+ <title><link linkend="nested_compatibility_test.duplicate_name">Duplicate Name</link></title>
+ <section id="nested_compatibility_test.duplicate_name.nested">
+ <title><link linkend="nested_compatibility_test.duplicate_name.nested">Nested
+ Section 1.5</link></title>
+ <bridgehead renderas="sect4" id="nested_compatibility_test.duplicate_name.nested.h0">
+ <phrase id="nested_compatibility_test.duplicate_name.nested.nested_heading_1_5"/><link
+ linkend="nested_compatibility_test.duplicate_name.nested.nested_heading_1_5">Nested
+ Heading 1.5</link>
+ </bridgehead>
+ </section>
+ <section id="nested_compatibility_test.duplicate_name.nested0">
+ <title><link linkend="nested_compatibility_test.duplicate_name.nested0">Nested
+ Section 1.6</link></title>
+ <bridgehead renderas="sect4" id="nested_compatibility_test.duplicate_name.nested0.h0">
+ <phrase id="nested_compatibility_test.duplicate_name.nested0.nested_heading_1_6"/><link
+ linkend="nested_compatibility_test.duplicate_name.nested0.nested_heading_1_6">Nested
+ Heading 1.6</link>
+ </bridgehead>
+ </section>
+ </section>
+ <section id="nested_compatibility_test.duplicate_name0">
+ <title><link linkend="nested_compatibility_test.duplicate_name0">Duplicate Name</link></title>
+ <section id="nested_compatibility_test.duplicate_name.nested1">
+ <title><link linkend="nested_compatibility_test.duplicate_name.nested1">Nested
+ Section 1.5</link></title>
+ <bridgehead renderas="sect4" id="nested_compatibility_test.duplicate_name.nested.h1">
+ <phrase id="nested_compatibility_test.duplicate_name.nested.nested_heading_1_5_0"/><link
+ linkend="nested_compatibility_test.duplicate_name.nested.nested_heading_1_5_0">Nested
+ Heading 1.5</link>
+ </bridgehead>
+ </section>
+ <section id="nested_compatibility_test.duplicate_name.nested2">
+ <title><link linkend="nested_compatibility_test.duplicate_name.nested2">Nested
+ Section 1.6</link></title>
+ <bridgehead renderas="sect4" id="nested_compatibility_test.duplicate_name.nested2.h0">
+ <phrase id="nested_compatibility_test.duplicate_name.nested2.nested_heading_1_6"/><link
+ linkend="nested_compatibility_test.duplicate_name.nested2.nested_heading_1_6">Nested
+ Heading 1.6</link>
+ </bridgehead>
+ </section>
+ </section>
+</article>
diff --git a/tools/quickbook/test/include/nested_compatibility-1_5.quickbook b/tools/quickbook/test/include/nested_compatibility-1_5.quickbook
new file mode 100644
index 0000000000..8276715faf
--- /dev/null
+++ b/tools/quickbook/test/include/nested_compatibility-1_5.quickbook
@@ -0,0 +1,12 @@
+[quickbook 1.5]
+[article Nested Compatibility Test]
+
+[section Duplicate Name]
+[include nested_compatibility_inc-1_5.qbk]
+[include nested_compatibility_inc-1_6.qbk]
+[endsect]
+
+[section Duplicate Name]
+[include nested_compatibility_inc-1_5.qbk]
+[include nested_compatibility_inc-1_6.qbk]
+[endsect]
diff --git a/tools/quickbook/test/include/nested_compatibility-1_6.gold b/tools/quickbook/test/include/nested_compatibility-1_6.gold
new file mode 100644
index 0000000000..af09a9e87b
--- /dev/null
+++ b/tools/quickbook/test/include/nested_compatibility-1_6.gold
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="nested_compatibility_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Nested Compatibility Test</title>
+ <section id="nested_compatibility_test.duplicate_name">
+ <title><link linkend="nested_compatibility_test.duplicate_name">Duplicate Name</link></title>
+ <section id="nested_compatibility_test.duplicate_name.nested">
+ <title><link linkend="nested_compatibility_test.duplicate_name.nested">Nested
+ Section 1.5</link></title>
+ <bridgehead renderas="sect4" id="nested_compatibility_test.duplicate_name.nested.h0">
+ <phrase id="nested_compatibility_test.duplicate_name.nested.nested_heading_1_5"/><link
+ linkend="nested_compatibility_test.duplicate_name.nested.nested_heading_1_5">Nested
+ Heading 1.5</link>
+ </bridgehead>
+ </section>
+ <section id="nested_compatibility_test.duplicate_name.nested0">
+ <title><link linkend="nested_compatibility_test.duplicate_name.nested0">Nested
+ Section 1.6</link></title>
+ <bridgehead renderas="sect4" id="nested_compatibility_test.duplicate_name.nested0.h0">
+ <phrase id="nested_compatibility_test.duplicate_name.nested0.nested_heading_1_6"/><link
+ linkend="nested_compatibility_test.duplicate_name.nested0.nested_heading_1_6">Nested
+ Heading 1.6</link>
+ </bridgehead>
+ </section>
+ </section>
+ <section id="nested_compatibility_test.duplicate_name0">
+ <title><link linkend="nested_compatibility_test.duplicate_name0">Duplicate Name</link></title>
+ <section id="nested_compatibility_test.duplicate_name0.nested">
+ <title><link linkend="nested_compatibility_test.duplicate_name0.nested">Nested
+ Section 1.5</link></title>
+ <bridgehead renderas="sect4" id="nested_compatibility_test.duplicate_name0.nested.h0">
+ <phrase id="nested_compatibility_test.duplicate_name0.nested.nested_heading_1_5"/><link
+ linkend="nested_compatibility_test.duplicate_name0.nested.nested_heading_1_5">Nested
+ Heading 1.5</link>
+ </bridgehead>
+ </section>
+ <section id="nested_compatibility_test.duplicate_name0.nested0">
+ <title><link linkend="nested_compatibility_test.duplicate_name0.nested0">Nested
+ Section 1.6</link></title>
+ <bridgehead renderas="sect4" id="nested_compatibility_test.duplicate_name0.nested0.h0">
+ <phrase id="nested_compatibility_test.duplicate_name0.nested0.nested_heading_1_6"/><link
+ linkend="nested_compatibility_test.duplicate_name0.nested0.nested_heading_1_6">Nested
+ Heading 1.6</link>
+ </bridgehead>
+ </section>
+ </section>
+</article>
diff --git a/tools/quickbook/test/include/nested_compatibility-1_6.quickbook b/tools/quickbook/test/include/nested_compatibility-1_6.quickbook
new file mode 100644
index 0000000000..72c4b65512
--- /dev/null
+++ b/tools/quickbook/test/include/nested_compatibility-1_6.quickbook
@@ -0,0 +1,12 @@
+[quickbook 1.6]
+[article Nested Compatibility Test]
+
+[section Duplicate Name]
+[include nested_compatibility_inc-1_5.qbk]
+[include nested_compatibility_inc-1_6.qbk]
+[endsect]
+
+[section Duplicate Name]
+[include nested_compatibility_inc-1_5.qbk]
+[include nested_compatibility_inc-1_6.qbk]
+[endsect]
diff --git a/tools/quickbook/test/include/nested_compatibility_inc-1_5.qbk b/tools/quickbook/test/include/nested_compatibility_inc-1_5.qbk
new file mode 100644
index 0000000000..3c79855a49
--- /dev/null
+++ b/tools/quickbook/test/include/nested_compatibility_inc-1_5.qbk
@@ -0,0 +1,5 @@
+[compatibility-mode 1.5]
+
+[section:nested Nested Section 1.5]
+[heading Nested Heading 1.5]
+[endsect]
diff --git a/tools/quickbook/test/include/nested_compatibility_inc-1_6.qbk b/tools/quickbook/test/include/nested_compatibility_inc-1_6.qbk
new file mode 100644
index 0000000000..d0790840cd
--- /dev/null
+++ b/tools/quickbook/test/include/nested_compatibility_inc-1_6.qbk
@@ -0,0 +1,5 @@
+[compatibility-mode 1.6]
+
+[section:nested Nested Section 1.6]
+[heading Nested Heading 1.6]
+[endsect]
diff --git a/tools/quickbook/test/include/section-fail1.quickbook b/tools/quickbook/test/include/section-fail1.quickbook
new file mode 100644
index 0000000000..ea75783e0c
--- /dev/null
+++ b/tools/quickbook/test/include/section-fail1.quickbook
@@ -0,0 +1,6 @@
+[article Include Section Test
+[quickbook 1.5]
+]
+
+[include section-inc2.quickbook]
+[include section-inc1.quickbook]
diff --git a/tools/quickbook/test/include/section-fail2.quickbook b/tools/quickbook/test/include/section-fail2.quickbook
new file mode 100644
index 0000000000..26a481104c
--- /dev/null
+++ b/tools/quickbook/test/include/section-fail2.quickbook
@@ -0,0 +1,5 @@
+[article Include Section Test
+[quickbook 1.5]
+]
+
+[include section-inc2.quickbook]
diff --git a/tools/quickbook/test/include/section-inc1.quickbook b/tools/quickbook/test/include/section-inc1.quickbook
new file mode 100644
index 0000000000..9c3fdd8248
--- /dev/null
+++ b/tools/quickbook/test/include/section-inc1.quickbook
@@ -0,0 +1 @@
+[section Mulitple file section]
diff --git a/tools/quickbook/test/include/section-inc2.quickbook b/tools/quickbook/test/include/section-inc2.quickbook
new file mode 100644
index 0000000000..8acc6a502b
--- /dev/null
+++ b/tools/quickbook/test/include/section-inc2.quickbook
@@ -0,0 +1 @@
+[endsect]
diff --git a/tools/quickbook/test/include/section-unclosed.gold b/tools/quickbook/test/include/section-unclosed.gold
new file mode 100644
index 0000000000..bea5cea672
--- /dev/null
+++ b/tools/quickbook/test/include/section-unclosed.gold
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include_section_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include Section Test</title>
+ <section id="include_section_test.mulitple_file_section">
+ <title><link linkend="include_section_test.mulitple_file_section">Mulitple file
+ section</link></title>
+ </section>
+</article>
diff --git a/tools/quickbook/test/include/section-unclosed.quickbook b/tools/quickbook/test/include/section-unclosed.quickbook
new file mode 100644
index 0000000000..290cd16333
--- /dev/null
+++ b/tools/quickbook/test/include/section-unclosed.quickbook
@@ -0,0 +1,5 @@
+[article Include Section Test
+[quickbook 1.5]
+]
+
+[include section-inc1.quickbook]
diff --git a/tools/quickbook/test/include/section.gold b/tools/quickbook/test/include/section.gold
new file mode 100644
index 0000000000..bea5cea672
--- /dev/null
+++ b/tools/quickbook/test/include/section.gold
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include_section_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include Section Test</title>
+ <section id="include_section_test.mulitple_file_section">
+ <title><link linkend="include_section_test.mulitple_file_section">Mulitple file
+ section</link></title>
+ </section>
+</article>
diff --git a/tools/quickbook/test/include/section.quickbook b/tools/quickbook/test/include/section.quickbook
new file mode 100644
index 0000000000..a570b35243
--- /dev/null
+++ b/tools/quickbook/test/include/section.quickbook
@@ -0,0 +1,6 @@
+[article Include Section Test
+[quickbook 1.5]
+]
+
+[include section-inc1.quickbook]
+[include section-inc2.quickbook]
diff --git a/tools/quickbook/test/include/source_mode-1_5.gold b/tools/quickbook/test/include/source_mode-1_5.gold
new file mode 100644
index 0000000000..4fbee6f63a
--- /dev/null
+++ b/tools/quickbook/test/include/source_mode-1_5.gold
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="souce_mode_include_" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Souce Mode Include</title>
+<programlisting>void main() {}</programlisting>
+</article>
diff --git a/tools/quickbook/test/include/source_mode-1_5.quickbook b/tools/quickbook/test/include/source_mode-1_5.quickbook
new file mode 100644
index 0000000000..24e52a01b9
--- /dev/null
+++ b/tools/quickbook/test/include/source_mode-1_5.quickbook
@@ -0,0 +1,3 @@
+[article Souce Mode Include [source-mode teletype][quickbook 1.5]]
+
+[include source_mode-inc1.qbk] \ No newline at end of file
diff --git a/tools/quickbook/test/include/source_mode-1_6.gold b/tools/quickbook/test/include/source_mode-1_6.gold
new file mode 100644
index 0000000000..6d20203e66
--- /dev/null
+++ b/tools/quickbook/test/include/source_mode-1_6.gold
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="souce_mode_include" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Souce Mode Include</title>
+ <article id="source_include_with_no_source_mode" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Source include with no source-mode</title>
+<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ </article>
+</article>
diff --git a/tools/quickbook/test/include/source_mode-1_6.quickbook b/tools/quickbook/test/include/source_mode-1_6.quickbook
new file mode 100644
index 0000000000..9eb81d9401
--- /dev/null
+++ b/tools/quickbook/test/include/source_mode-1_6.quickbook
@@ -0,0 +1,4 @@
+[source-mode teletype][quickbook 1.6]
+[article Souce Mode Include]
+
+[include source_mode-inc1.qbk] \ No newline at end of file
diff --git a/tools/quickbook/test/include/source_mode-inc1.qbk b/tools/quickbook/test/include/source_mode-inc1.qbk
new file mode 100644
index 0000000000..3cefbe6bc7
--- /dev/null
+++ b/tools/quickbook/test/include/source_mode-inc1.qbk
@@ -0,0 +1,3 @@
+[article Source include with no source-mode]
+
+ void main() {} \ No newline at end of file
diff --git a/tools/quickbook/test/include/sub/filename_include1.quickbook b/tools/quickbook/test/include/sub/filename_include1.quickbook
new file mode 100644
index 0000000000..6c57614d52
--- /dev/null
+++ b/tools/quickbook/test/include/sub/filename_include1.quickbook
@@ -0,0 +1,3 @@
+__FILENAME__
+
+[include ../filename_include2.quickbook] \ No newline at end of file
diff --git a/tools/quickbook/test/include/templates-1.5.gold b/tools/quickbook/test/include/templates-1.5.gold
new file mode 100644
index 0000000000..7d7e5dd60e
--- /dev/null
+++ b/tools/quickbook/test/include/templates-1.5.gold
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="templates_1_5" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Templates 1.5</title>
+ <para>
+ Inline:templates-inc1.quickbook
+ </para>
+ <para>
+ Foo:templates-1.5.quickbook
+ </para>
+</article>
diff --git a/tools/quickbook/test/include/templates-1.5.quickbook b/tools/quickbook/test/include/templates-1.5.quickbook
new file mode 100644
index 0000000000..5104ae6fa8
--- /dev/null
+++ b/tools/quickbook/test/include/templates-1.5.quickbook
@@ -0,0 +1,7 @@
+[article Templates 1.5
+[quickbook 1.5]
+]
+
+[include templates-inc1.quickbook]
+
+[foo] \ No newline at end of file
diff --git a/tools/quickbook/test/include/templates-1.6.gold b/tools/quickbook/test/include/templates-1.6.gold
new file mode 100644
index 0000000000..4e37e5e64d
--- /dev/null
+++ b/tools/quickbook/test/include/templates-1.6.gold
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="templates_1_6" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Templates 1.6</title>
+ <para>
+ Inline:templates-inc1.quickbook
+ </para>
+ <para>
+ [foo]
+ </para>
+ <para>
+ Foo:templates-1.6.quickbook
+ </para>
+</article>
diff --git a/tools/quickbook/test/include/templates-1.6.quickbook b/tools/quickbook/test/include/templates-1.6.quickbook
new file mode 100644
index 0000000000..77d821e4c3
--- /dev/null
+++ b/tools/quickbook/test/include/templates-1.6.quickbook
@@ -0,0 +1,11 @@
+[article Templates 1.6
+[quickbook 1.6]
+]
+
+[include templates-inc1.quickbook]
+
+[foo]
+
+[import templates-inc1.quickbook]
+
+[foo]
diff --git a/tools/quickbook/test/include/templates-inc1.quickbook b/tools/quickbook/test/include/templates-inc1.quickbook
new file mode 100644
index 0000000000..70574627c7
--- /dev/null
+++ b/tools/quickbook/test/include/templates-inc1.quickbook
@@ -0,0 +1,4 @@
+Inline:__FILENAME__
+
+[template foo Foo:__FILENAME__]
+
diff --git a/tools/quickbook/test/include2-1_6.gold b/tools/quickbook/test/include2-1_6.gold
new file mode 100644
index 0000000000..f46759b78c
--- /dev/null
+++ b/tools/quickbook/test/include2-1_6.gold
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include-test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include Test</title>
+ <article id="include-sub" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include Test Sub Document</title>
+ </article>
+ <section id="include-test.test">
+ <title><link linkend="include-test.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+ <section id="foo.test">
+ <title><link linkend="foo.test">Test</link></title>
+ <para>
+ Just testing.
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/include2-1_6.quickbook b/tools/quickbook/test/include2-1_6.quickbook
new file mode 100644
index 0000000000..be78fcc7fd
--- /dev/null
+++ b/tools/quickbook/test/include2-1_6.quickbook
@@ -0,0 +1,8 @@
+[article Include Test
+ [quickbook 1.6]
+ [id include-test]
+]
+
+[include include_sub-1_5.qbk]
+[include include_sub.qbk]
+[include:foo include_sub.qbk]
diff --git a/tools/quickbook/test/include_sub-1_5.qbk b/tools/quickbook/test/include_sub-1_5.qbk
new file mode 100644
index 0000000000..1dcbff9ff4
--- /dev/null
+++ b/tools/quickbook/test/include_sub-1_5.qbk
@@ -0,0 +1,6 @@
+[article Include Test Sub Document
+ [quickbook 1.5]
+ [id include-sub]
+]
+
+[/ Empty. Shouldn't really need this comment.]
diff --git a/tools/quickbook/test/include_sub.qbk b/tools/quickbook/test/include_sub.qbk
new file mode 100644
index 0000000000..1fa61608b8
--- /dev/null
+++ b/tools/quickbook/test/include_sub.qbk
@@ -0,0 +1,9 @@
+[/ I'm trying not to break existing behaviour even when buggy.
+ In this case, this section will get an id using the title from
+ the previous 'include'.]
+
+[section:test Test]
+
+Just testing.
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/include_win_path-1_6-fail.quickbook b/tools/quickbook/test/include_win_path-1_6-fail.quickbook
new file mode 100644
index 0000000000..2e25423fd1
--- /dev/null
+++ b/tools/quickbook/test/include_win_path-1_6-fail.quickbook
@@ -0,0 +1,5 @@
+[article Include fail for windows path.
+[quickbook 1.6]
+]
+
+[include .\empty.qbk]
diff --git a/tools/quickbook/test/link-1_1.gold b/tools/quickbook/test/link-1_1.gold
new file mode 100644
index 0000000000..70fd440f1e
--- /dev/null
+++ b/tools/quickbook/test/link-1_1.gold
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="link_tests" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Link tests</title>
+ <section id="link_tests.different_types_of_links">
+ <title>Different types of links</title>
+ <para>
+ <ulink url="http://www.boost.org/">http://www.boost.org/</ulink> <ulink url="http://www.boost.org/">Boost</ulink>
+ <link linkend="link-id">link-id</link> <link linkend="link-id">Link Text</link>
+ <anchor id="link-id"/><functionname alt="foo">foo</functionname> <functionname
+ alt="foo">link text</functionname> <classname alt="foo">foo</classname> <classname
+ alt="foo">link text</classname> <methodname alt="foo">foo</methodname> <methodname
+ alt="foo">link text</methodname> <enumname alt="foo">foo</enumname> <enumname
+ alt="foo">link text</enumname> <macroname alt="foo">foo</macroname> <macroname
+ alt="foo">link text</macroname> <headername alt="foo">foo</headername> <headername
+ alt="foo">link text</headername> <conceptname alt="foo">foo</conceptname>
+ <conceptname alt="foo">link text</conceptname> <globalname alt="foo">foo</globalname>
+ <globalname alt="foo">link text</globalname>
+ </para>
+ <para>
+ <link linkend="link">description</link>
+ </para>
+ </section>
+ <section id="link_tests.side_by_side_links">
+ <title>Side-by-side links</title>
+ <para>
+ <link linkend="x">x</link> and <link linkend="y">y</link> are two distinct
+ links, which should be separated by whitespace when they appear together as
+ in <link linkend="x">x</link> <link linkend="y">y</link>. Also in <link linkend="x">x</link>
+ <link linkend="y">y</link>, and in <link linkend="x">x</link> <link linkend="y">y</link>
+ as well.
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/link-1_1.quickbook b/tools/quickbook/test/link-1_1.quickbook
new file mode 100644
index 0000000000..2ddb0bf218
--- /dev/null
+++ b/tools/quickbook/test/link-1_1.quickbook
@@ -0,0 +1,41 @@
+[article Link tests
+]
+
+[section Different types of links]
+
+[@http://www.boost.org/]
+[@ http://www.boost.org/ Boost]
+[link link-id]
+[link link-id Link Text]
+[#link-id]
+[funcref foo]
+[funcref foo link text]
+[classref foo]
+[classref foo link text]
+[memberref foo]
+[memberref foo link text]
+[enumref foo]
+[enumref foo link text]
+[macroref foo]
+[macroref foo link text]
+[headerref foo]
+[headerref foo link text]
+[conceptref foo]
+[conceptref foo link text]
+[globalref foo]
+[globalref foo link text]
+
+[link link[/ comment]description]
+
+[endsect]
+
+[section Side-by-side links]
+
+[link x] and [link y] are two distinct links, which should be separated by
+whitespace when they appear together as in [link x] [link y]. Also in [link x]
+[link y], and in
+[link x]
+[link y]
+as well.
+
+[endsect]
diff --git a/tools/quickbook/test/link-1_6.gold b/tools/quickbook/test/link-1_6.gold
new file mode 100644
index 0000000000..05af56162a
--- /dev/null
+++ b/tools/quickbook/test/link-1_6.gold
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="link_tests" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Link tests</title>
+ <section id="link_tests.different_types_of_links">
+ <title><link linkend="link_tests.different_types_of_links">Different types of
+ links</link></title>
+ <para>
+ <ulink url="http://www.boost.org/">http://www.boost.org/</ulink> <ulink url="http://www.boost.org/">Boost</ulink>
+ <link linkend="link-id">link-id</link> <link linkend="link-id">Link Text</link>
+ <anchor id="link-id"/><functionname alt="foo">foo</functionname> <functionname
+ alt="foo">link text</functionname> <classname alt="foo">foo</classname> <classname
+ alt="foo">link text</classname> <methodname alt="foo">foo</methodname> <methodname
+ alt="foo">link text</methodname> <enumname alt="foo">foo</enumname> <enumname
+ alt="foo">link text</enumname> <macroname alt="foo">foo</macroname> <macroname
+ alt="foo">link text</macroname> <headername alt="foo">foo</headername> <headername
+ alt="foo">link text</headername> <conceptname alt="foo">foo</conceptname>
+ <conceptname alt="foo">link text</conceptname> <globalname alt="foo">foo</globalname>
+ <globalname alt="foo">link text</globalname>
+ </para>
+ <para>
+ <link linkend="link">description</link>
+ </para>
+ <para>
+ <link linkend="link[Hello]">description</link>
+ </para>
+ </section>
+ <section id="link_tests.side_by_side_links">
+ <title><link linkend="link_tests.side_by_side_links">Side-by-side links</link></title>
+ <para>
+ <link linkend="x">x</link> and <link linkend="y">y</link> are two distinct
+ links, which should be separated by whitespace when they appear together as
+ in <link linkend="x">x</link> <link linkend="y">y</link>. Also in <link linkend="x">x</link>
+ <link linkend="y">y</link>, and in <link linkend="x">x</link> <link linkend="y">y</link>
+ as well.
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/link-1_6.quickbook b/tools/quickbook/test/link-1_6.quickbook
new file mode 100644
index 0000000000..28e99dbfd0
--- /dev/null
+++ b/tools/quickbook/test/link-1_6.quickbook
@@ -0,0 +1,45 @@
+[article Link tests
+[quickbook 1.6]
+]
+
+[section Different types of links]
+
+[@http://www.boost.org/]
+[@ http://www.boost.org/ Boost]
+[link link-id]
+[link link-id Link Text]
+[#link-id]
+[funcref foo]
+[funcref foo link text]
+[classref foo]
+[classref foo link text]
+[memberref foo]
+[memberref foo link text]
+[enumref foo]
+[enumref foo link text]
+[macroref foo]
+[macroref foo link text]
+[headerref foo]
+[headerref foo link text]
+[conceptref foo]
+[conceptref foo link text]
+[globalref foo]
+[globalref foo link text]
+
+[link link[/ comment]description]
+
+[link link\[Hello\] description]
+
+
+[endsect]
+
+[section Side-by-side links]
+
+[link x] and [link y] are two distinct links, which should be separated by
+whitespace when they appear together as in [link x] [link y]. Also in [link x]
+[link y], and in
+[link x]
+[link y]
+as well.
+
+[endsect]
diff --git a/tools/quickbook/test/list_test-1_5.gold b/tools/quickbook/test/list_test-1_5.gold
new file mode 100644
index 0000000000..a1b44d829e
--- /dev/null
+++ b/tools/quickbook/test/list_test-1_5.gold
@@ -0,0 +1,386 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="list_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>List Test</title>
+ <para>
+ Simple list:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Simple list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Two level list:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Two level list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Three level list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ C
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ D
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ E
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ F
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ G
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ H
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Three level list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <orderedlist>
+ <listitem>
+ <simpara>
+ C
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ D
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ G
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ H
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Inconsistent Indentation:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A1
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ B1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B2
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ C1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ C2
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B3
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B4
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B5
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ C3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B6
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Markup in list:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ <emphasis role="bold">Bold</emphasis>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <emphasis role="bold">Bold</emphasis>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <quote>Quoted</quote>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <footnote id="list_test.f0">
+ <para>
+ Footnote
+ </para>
+ </footnote>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Don't end list with comment 1:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A3
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A4
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Don't end list with comment 2:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A1
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ B1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <section id="list_test.list_immediately_following_markup">
+ <title><link linkend="list_test.list_immediately_following_markup">List immediately
+ following markup</link></title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ One
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Two
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Three
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+</article>
diff --git a/tools/quickbook/test/list_test-1_5.quickbook b/tools/quickbook/test/list_test-1_5.quickbook
new file mode 100644
index 0000000000..ab78e6f588
--- /dev/null
+++ b/tools/quickbook/test/list_test-1_5.quickbook
@@ -0,0 +1,100 @@
+[article List Test
+[quickbook 1.5]
+]
+
+Simple list:
+
+* A
+* B
+
+Simple list:
+
+#A
+#B
+
+Two level list:
+
+* A
+ * A
+ * B
+* B
+ * A
+ * B
+
+Two level list:
+
+# A
+ * A
+ * B
+# B
+ * A
+ * B
+
+Three level list:
+
+# A
+ * A
+ * B
+ * C
+ * D
+ * E
+ * F
+ * G
+ * H
+
+Three level list:
+
+# A
+ * A
+ * B
+ # C
+ # D
+# G
+# H
+
+Inconsistent Indentation:
+
+* A1
+ * B1
+ * B2
+ * C1
+ * C2
+ * B3
+ * B4
+ * B5
+ * C3
+ * B6
+ * A2
+* A3
+
+Markup in list:
+
+* *Bold*
+* [*Bold]
+* ["Quoted]
+* [footnote Footnote]
+
+Don't end list with comment 1:
+
+* A1
+* A2
+
+[/ End list?]
+* A3
+* A4
+
+Don't end list with comment 2:
+
+* A1
+ * B1
+
+[/ End list?]
+ * B2
+ * B3
+
+[section List immediately following markup]
+* One
+* Two
+* Three
+
+[endsect]
diff --git a/tools/quickbook/test/list_test-1_6.gold b/tools/quickbook/test/list_test-1_6.gold
new file mode 100644
index 0000000000..223509a590
--- /dev/null
+++ b/tools/quickbook/test/list_test-1_6.gold
@@ -0,0 +1,476 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="list_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>List Test</title>
+ <para>
+ Simple list:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Simple list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Two level list:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Two level list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Three level list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ C
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ D
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ E
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ F
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ G
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ H
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Three level list:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B
+ <orderedlist>
+ <listitem>
+ <simpara>
+ C
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ D
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ G
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ H
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ Inconsistent Indentation:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A1
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ B1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B2
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ C1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ C2
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B3
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B4
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B5
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ C3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B6
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Markup in list:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ <emphasis role="bold">Bold</emphasis>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <emphasis role="bold">Bold</emphasis>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <quote>Quoted</quote>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <footnote id="list_test.f0">
+ <para>
+ Footnote
+ </para>
+ </footnote>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ Cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <bridgehead renderas="sect2" id="list_test.h0">
+ <phrase id="list_test.the_heading_for_a_list_item"/><link linkend="list_test.the_heading_for_a_list_item">The
+ heading for a list item</link>
+ </bridgehead>
+ <para>
+ The content of the list item.
+ </para>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Don't end list with comment 1:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A3
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A4
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Don't end list with comment 2:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A1
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ B1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B2
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B3
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <section id="list_test.list_immediately_following_marku">
+ <title><link linkend="list_test.list_immediately_following_marku">List immediately
+ following markup</link></title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ One
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Two
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Three
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="list_test.paragraphs_in_list_items">
+ <title><link linkend="list_test.paragraphs_in_list_items">Paragraphs in list
+ items</link></title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ A1
+ <para>
+ A2
+ </para>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ B1
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ C1
+ <para>
+ C2
+ </para>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ B2
+ </para>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ D1
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ E1
+ <para>
+ E2
+ </para>
+ <para>
+ E3
+ </para>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ D2
+ </para>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+</article>
diff --git a/tools/quickbook/test/list_test-1_6.quickbook b/tools/quickbook/test/list_test-1_6.quickbook
new file mode 100644
index 0000000000..fd01b389d5
--- /dev/null
+++ b/tools/quickbook/test/list_test-1_6.quickbook
@@ -0,0 +1,128 @@
+[article List Test
+[quickbook 1.6]
+]
+
+Simple list:
+
+* A
+* B
+
+Simple list:
+
+#A
+#B
+
+Two level list:
+
+* A
+ * A
+ * B
+* B
+ * A
+ * B
+
+Two level list:
+
+# A
+ * A
+ * B
+# B
+ * A
+ * B
+
+Three level list:
+
+# A
+ * A
+ * B
+ * C
+ * D
+ * E
+ * F
+ * G
+ * H
+
+Three level list:
+
+# A
+ * A
+ * B
+ # C
+ # D
+# G
+# H
+
+Inconsistent Indentation:
+
+* A1
+ * B1
+ * B2
+ * C1
+ * C2
+ * B3
+ * B4
+ * B5
+ * C3
+ * B6
+ * A2
+* A3
+
+Markup in list:
+
+* *Bold*
+* [*Bold]
+* ["Quoted]
+* [footnote Footnote]
+* [table [[Heading]][[Cell]]]
+* [heading The heading for a list item]
+
+ The content of the list item.
+
+Don't end list with comment 1:
+
+* A1
+* A2
+
+[/ End list?]
+* A3
+* A4
+
+Don't end list with comment 2:
+
+* A1
+ * B1
+
+[/ End list?]
+ * B2
+ * B3
+
+[section List immediately following markup]
+* One
+* Two
+* Three
+
+[endsect]
+
+[section Paragraphs in list items]
+
+* A1
+
+ A2
+
+* B1
+ * C1
+
+ C2
+
+ B2
+
+* D1
+ * E1
+
+ E2
+
+ E3
+
+ D2
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/macro-1_5.gold b/tools/quickbook/test/macro-1_5.gold
new file mode 100644
index 0000000000..aec771a0cc
--- /dev/null
+++ b/tools/quickbook/test/macro-1_5.gold
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="macro_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Macro Test</title>
+ <para>
+ 1
+ </para>
+ <para>
+ 2
+ </para>
+ <para>
+ two
+ </para>
+ <para>
+ 1
+ </para>
+ <para>
+ 1
+ </para>
+ <para>
+ 1
+ </para>
+ <para>
+ 1 2
+ </para>
+</article>
diff --git a/tools/quickbook/test/macro-1_5.quickbook b/tools/quickbook/test/macro-1_5.quickbook
new file mode 100644
index 0000000000..165ad1b927
--- /dev/null
+++ b/tools/quickbook/test/macro-1_5.quickbook
@@ -0,0 +1,34 @@
+[article Macro Test
+[quickbook 1.5]
+]
+
+[def one 1]
+
+one
+
+[template foo[]
+
+[def two 2]
+two
+]
+
+[foo]
+two [/This shouldn't expand]
+
+
+[def __foo__ 1]
+[def __foo__ 2]
+__foo__
+
+[template foo2[]
+[def __foo__ 3]
+__foo__
+]
+
+[foo2]
+__foo__
+
+[def __crazy[macro__ 1]
+[def __crazy\macro__ 2]
+__crazy[macro__
+__crazy\macro__ \ No newline at end of file
diff --git a/tools/quickbook/test/macro-1_6.gold b/tools/quickbook/test/macro-1_6.gold
new file mode 100644
index 0000000000..291ddf1f98
--- /dev/null
+++ b/tools/quickbook/test/macro-1_6.gold
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="macro_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Macro Test</title>
+ <para>
+ 1
+ </para>
+ <para>
+ 2
+ </para>
+ <para>
+ two
+ </para>
+ <para>
+ 2
+ </para>
+ <para>
+ 3
+ </para>
+ <para>
+ 2
+ </para>
+ <para>
+ [1] \m2
+ </para>
+</article>
diff --git a/tools/quickbook/test/macro-1_6.quickbook b/tools/quickbook/test/macro-1_6.quickbook
new file mode 100644
index 0000000000..43f8cbc0af
--- /dev/null
+++ b/tools/quickbook/test/macro-1_6.quickbook
@@ -0,0 +1,34 @@
+[article Macro Test
+[quickbook 1.6]
+]
+
+[def one 1]
+
+one
+
+[template foo[]
+
+[def two 2]
+two
+]
+
+[foo]
+two [/This shouldn't expand]
+
+
+[def __foo__ 1]
+[def __foo__ 2]
+__foo__
+
+[template foo2[]
+[def __foo__ 3]
+__foo__
+]
+
+[foo2]
+__foo__
+
+[def __crazy[1]]
+[def __crazy2\m2]
+__crazy
+__crazy2 \ No newline at end of file
diff --git a/tools/quickbook/test/mismatched_brackets-1_1-fail.quickbook b/tools/quickbook/test/mismatched_brackets-1_1-fail.quickbook
new file mode 100644
index 0000000000..e3db0daa2d
--- /dev/null
+++ b/tools/quickbook/test/mismatched_brackets-1_1-fail.quickbook
@@ -0,0 +1,5 @@
+[article Mismatched brackets]
+
+[template foo Oops]
+[template blah Eek
+[foo]
diff --git a/tools/quickbook/test/mismatched_brackets1-1_1.gold b/tools/quickbook/test/mismatched_brackets1-1_1.gold
new file mode 100644
index 0000000000..f6fbff4972
--- /dev/null
+++ b/tools/quickbook/test/mismatched_brackets1-1_1.gold
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="mismatched_brackets" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Mismatched brackets</title>
+ <para>
+ [foo
+ </para>
+ <para>
+ Eek
+ </para>
+</article>
diff --git a/tools/quickbook/test/mismatched_brackets1-1_1.quickbook b/tools/quickbook/test/mismatched_brackets1-1_1.quickbook
new file mode 100644
index 0000000000..a0cfb77b36
--- /dev/null
+++ b/tools/quickbook/test/mismatched_brackets1-1_1.quickbook
@@ -0,0 +1,7 @@
+[article Mismatched brackets]
+
+[template foo Oops]
+
+[foo
+[template blah Eek]
+[blah] \ No newline at end of file
diff --git a/tools/quickbook/test/mismatched_brackets2-1_1.gold b/tools/quickbook/test/mismatched_brackets2-1_1.gold
new file mode 100644
index 0000000000..bdbb114c74
--- /dev/null
+++ b/tools/quickbook/test/mismatched_brackets2-1_1.gold
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="mismatched_brackets" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Mismatched brackets</title>
+ <para>
+ [foo Eek
+ </para>
+</article>
diff --git a/tools/quickbook/test/mismatched_brackets2-1_1.quickbook b/tools/quickbook/test/mismatched_brackets2-1_1.quickbook
new file mode 100644
index 0000000000..271fee8af3
--- /dev/null
+++ b/tools/quickbook/test/mismatched_brackets2-1_1.quickbook
@@ -0,0 +1,7 @@
+[article Mismatched brackets]
+
+[template foo Oops]
+[template blah Eek]
+
+[foo
+[blah] \ No newline at end of file
diff --git a/tools/quickbook/test/newline-1_1.gold b/tools/quickbook/test/newline-1_1.gold
new file mode 100644
index 0000000000..716acca125
--- /dev/null
+++ b/tools/quickbook/test/newline-1_1.gold
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="test_newlines" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Test newlines</title>
+ <para>
+ Line 1<sbr/> Line 2
+ </para>
+ <blockquote>
+ <para>
+ <quote>It is better to be approximately right than exactly wrong.</quote><sbr/>
+ <emphasis>-- Old adage</emphasis>
+ </para>
+ </blockquote>
+ <para>
+ Line 1<sbr/> Line 2
+ </para>
+ <blockquote>
+ <para>
+ <quote>It is better to be approximately right than exactly wrong.</quote><sbr/>
+ <emphasis>-- Old adage</emphasis>
+ </para>
+ </blockquote>
+</article>
diff --git a/tools/quickbook/test/newline-1_1.quickbook b/tools/quickbook/test/newline-1_1.quickbook
new file mode 100644
index 0000000000..6476f6a409
--- /dev/null
+++ b/tools/quickbook/test/newline-1_1.quickbook
@@ -0,0 +1,10 @@
+[article Test newlines
+]
+
+Line 1\nLine 2
+
+[:["It is better to be approximately right than exactly wrong.]\n['-- Old adage]]
+
+Line 1[br]Line 2
+
+[:["It is better to be approximately right than exactly wrong.][br]['-- Old adage]] \ No newline at end of file
diff --git a/tools/quickbook/test/para_test-1_5.gold b/tools/quickbook/test/para_test-1_5.gold
new file mode 100644
index 0000000000..1a8f17d6a1
--- /dev/null
+++ b/tools/quickbook/test/para_test-1_5.gold
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="paragraph_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Paragraph Test</title>
+ <section id="paragraph_test.some_paragraphs">
+ <title><link linkend="paragraph_test.some_paragraphs">Some Paragraphs</link></title>
+ <para>
+ Shouldn't be a code block.
+ </para>
+ <para>
+ <emphasis role="bold">Should be bold</emphasis>.
+ </para>
+ <para>
+ Should be a single paragraph.
+ </para>
+ <para>
+ Single paragraph.
+ </para>
+ <para>
+ Single paragraph.
+ </para>
+ <para>
+ Single paragraph.
+ </para>
+ <para>
+ Single paragraph.
+ </para>
+ <para>
+ Lots of newlines round this paragraph.
+ </para>
+ <para>
+ Last paragraph.
+ </para>
+ </section>
+ <section id="paragraph_test.inside___breaking_comment__blocks">
+ <title><link linkend="paragraph_test.inside___breaking_comment__blocks">Inside
+ blocks</link></title>
+ <variablelist>
+ <title></title>
+ <varlistentry>
+ <term>Paragraphs</term>
+ <listitem>
+ <para>
+ Shouldn't be a code block.
+ </para>
+ <para>
+ <emphasis role="bold">Should be bold</emphasis>.
+ </para>
+ <para>
+ Should be a single paragraph.
+ </para>
+ <para>
+ Single paragraph.
+ </para>
+ <para>
+ Single paragraph.
+ </para>
+ <para>
+ Single paragraph.
+ </para>
+ <para>
+ Single paragraph.
+ </para>
+ <para>
+ Lots of newlines round this paragraph.
+ </para>
+ <para>
+ Last paragraph.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+</article>
diff --git a/tools/quickbook/test/para_test-1_5.quickbook b/tools/quickbook/test/para_test-1_5.quickbook
new file mode 100644
index 0000000000..8a099bce55
--- /dev/null
+++ b/tools/quickbook/test/para_test-1_5.quickbook
@@ -0,0 +1,81 @@
+[article Paragraph Test
+ [quickbook 1.5]
+]
+
+[section Some Paragraphs]
+
+[/ Leading comment ] Shouldn't be a code block.
+
+[/ Leading comment ]*Should be bold*.
+
+Should be a
+[/ Breaking comment]
+single paragraph.
+
+Single paragraph.
+[/ Breaking comment]
+
+Single paragraph.
+
+[/ Breaking comment]
+Single paragraph.
+
+Single paragraph.[/ Trailing comment]
+
+
+
+
+
+
+Lots of newlines round this paragraph.
+
+
+
+
+
+
+
+
+Last paragraph.[endsect]
+
+[section Inside
+[/Breaking comment]
+blocks]
+
+[variablelist
+[[Paragraphs][
+[/ Leading comment ] Shouldn't be a code block.
+
+[/ Leading comment ]*Should be bold*.
+
+Should be a
+[/ Breaking comment]
+single paragraph.
+
+Single paragraph.
+[/ Breaking comment]
+
+Single paragraph.
+
+[/ Breaking comment]
+Single paragraph.
+
+Single paragraph.[/ Trailing comment]
+
+
+
+
+
+
+Lots of newlines round this paragraph.
+
+
+
+
+
+
+
+
+Last paragraph.]]]
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/post_process-fail.quickbook b/tools/quickbook/test/post_process-fail.quickbook
new file mode 100644
index 0000000000..994a63574e
--- /dev/null
+++ b/tools/quickbook/test/post_process-fail.quickbook
@@ -0,0 +1,3 @@
+[article Fail post process due to invalid embedded xml [quickbook 1.4] ]
+
+Invalid xml follows: '''<!--quickbook-escape-postfix--><>'''
diff --git a/tools/quickbook/test/preformatted-1_1.gold b/tools/quickbook/test/preformatted-1_1.gold
new file mode 100644
index 0000000000..a92b3f55ab
--- /dev/null
+++ b/tools/quickbook/test/preformatted-1_1.gold
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="preformatted" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Preformatted</title>
+ <section id="preformatted.preformatted">
+ <title>Preformatted</title>
+ <para>
+ Here's the ubiquitous <emphasis>Hello World</emphasis> program in C++.
+ </para>
+<programlisting>#include &lt;iostream&gt;
+
+int main()
+{
+ std::cout &lt;&lt; &quot;Hello, World!&quot; &lt;&lt; std::endl;
+ return 0;
+}
+</programlisting>
+ <para>
+ The code should appear as a single block of code in a monospaced font and with
+ no syntax highlighting. The fifth and sixth lines should appear indented to
+ the right, aligning under <code><phrase role="identifier">main</phrase></code>,
+ on line 3.
+ </para>
+ <para>
+ Here's a one line function definitition:
+ </para>
+<programlisting>void something(); </programlisting>
+ <para>
+ .
+ </para>
+ <para>
+ And some indented code:
+ </para>
+<programlisting>void go()
+ {
+ }
+</programlisting>
+ </section>
+</article>
diff --git a/tools/quickbook/test/preformatted-1_1.quickbook b/tools/quickbook/test/preformatted-1_1.quickbook
new file mode 100644
index 0000000000..e41f83b5da
--- /dev/null
+++ b/tools/quickbook/test/preformatted-1_1.quickbook
@@ -0,0 +1,32 @@
+[article Preformatted
+]
+
+[section Preformatted]
+
+Here's the ubiquitous /Hello World/ program in C++.
+
+[pre
+#include <iostream>
+
+int main()
+{
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+}
+]
+
+The code should appear as a single block of code in a monospaced font and with
+no syntax highlighting. The fifth and sixth lines should appear indented to the
+right, aligning under `main`, on line 3.
+
+Here's a one line function definitition: [pre void something(); ].
+
+And some indented code:
+
+[pre
+ void go()
+ {
+ }
+]
+
+[endsect]
diff --git a/tools/quickbook/test/preformatted-1_6.gold b/tools/quickbook/test/preformatted-1_6.gold
new file mode 100644
index 0000000000..46a90c98e7
--- /dev/null
+++ b/tools/quickbook/test/preformatted-1_6.gold
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="preformatted" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Preformatted</title>
+ <section id="preformatted.preformatted">
+ <title><link linkend="preformatted.preformatted">Preformatted</link></title>
+ <para>
+ Here's the ubiquitous <emphasis>Hello World</emphasis> program in C++.
+ </para>
+<programlisting>#include &lt;iostream&gt;
+
+int main()
+{
+ std::cout &lt;&lt; &quot;Hello, World!&quot; &lt;&lt; std::endl;
+ return 0;
+}
+</programlisting>
+ <para>
+ The code should appear as a single block of code in a monospaced font and with
+ no syntax highlighting. The fifth and sixth lines should appear indented to
+ the right, aligning under <code><phrase role="identifier">main</phrase></code>,
+ on line 3.
+ </para>
+ <para>
+ Here's a one line function definitition:
+ </para>
+<programlisting>void something(); </programlisting>
+ <para>
+ .
+ </para>
+ <para>
+ And some indented code:
+ </para>
+<programlisting> void go()
+ {
+ }
+</programlisting>
+ </section>
+</article>
diff --git a/tools/quickbook/test/preformatted-1_6.quickbook b/tools/quickbook/test/preformatted-1_6.quickbook
new file mode 100644
index 0000000000..25c6bc5c55
--- /dev/null
+++ b/tools/quickbook/test/preformatted-1_6.quickbook
@@ -0,0 +1,33 @@
+[article Preformatted
+[quickbook 1.6]
+]
+
+[section Preformatted]
+
+Here's the ubiquitous /Hello World/ program in C++.
+
+[pre
+#include <iostream>
+
+int main()
+{
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+}
+]
+
+The code should appear as a single block of code in a monospaced font and with
+no syntax highlighting. The fifth and sixth lines should appear indented to the
+right, aligning under `main`, on line 3.
+
+Here's a one line function definitition: [pre void something(); ].
+
+And some indented code:
+
+[pre
+ void go()
+ {
+ }
+]
+
+[endsect]
diff --git a/tools/quickbook/test/quickbook-testing.jam b/tools/quickbook/test/quickbook-testing.jam
new file mode 100644
index 0000000000..614facec5d
--- /dev/null
+++ b/tools/quickbook/test/quickbook-testing.jam
@@ -0,0 +1,141 @@
+#
+# Copyright (c) 2005 João Abecasis
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+import feature ;
+import generators ;
+import modules ;
+import project ;
+import targets ;
+import testing ;
+import toolset ;
+import type ;
+
+feature.feature quickbook-testing.quickbook-command : : free dependency ;
+feature.feature <quickbook-test-define> : : free ;
+feature.feature <quickbook-test-include> : : free path ;
+feature.feature <quickbook-xinclude-base> : : free ;
+
+type.register QUICKBOOK_INPUT : quickbook ;
+type.register QUICKBOOK_OUTPUT ;
+
+generators.register-standard quickbook-testing.process-quickbook : QUICKBOOK_INPUT : QUICKBOOK_OUTPUT ;
+
+################################################################################
+#
+# quickbook-test - generates a test for quickbook itself. A quickbook-test is
+# actually made up of two tests:
+# $(target-name).boostbook :
+# generate boostbook from $(input) or $(target-name).quickbook
+#
+# $(target-name):
+# compare generated boostbook to $(reference-output) or
+# $(input).gold or $(target-name).gold
+#
+rule quickbook-test ( target-name : input ? : reference-output ? : requirements * )
+{
+ input ?= $(target-name).quickbook ;
+ reference-output ?= $(input:S=.gold) ;
+
+ local project = [ project.current ] ;
+
+ local boost-root = [ modules.peek : BOOST_ROOT ] ;
+
+ local t =
+ [ targets.create-typed-target QUICKBOOK_OUTPUT
+ : $(project)
+ : $(target-name).boostbook
+ : $(input)
+ : $(requirements)
+ <location-prefix>$(target-name).test
+ <quickbook-testing.quickbook-command>$(boost-root)/tools/quickbook/src//quickbook
+ ]
+
+ [ targets.create-typed-target RUN
+ : $(project)
+ : $(target-name)
+ : $(boost-root)/tools/quickbook/test/src//line-compare-tool
+ : $(requirements)
+ <location-prefix>$(target-name).test
+ <testing.input-file>$(reference-output)
+ <testing.input-file>$(target-name).boostbook
+ <preserve-test-targets>on
+ ]
+ ;
+
+ modules.poke testing : .all-tests : \$\(all-tests\) $(t) ;
+
+ return $(t) ;
+}
+
+rule quickbook-fail-test ( target-name : input ? : requirements * )
+{
+ input ?= $(target-name).quickbook ;
+
+ local project = [ project.current ] ;
+
+ local boost-root = [ modules.peek : BOOST_ROOT ] ;
+
+ local t =
+ [ targets.create-typed-target RUN_FAIL
+ : $(project)
+ : $(target-name)
+ : $(boost-root)/tools/quickbook/src//quickbook
+ : $(requirements)
+ <testing.input-file>$(input)
+ <preserve-test-targets>on
+ <dependency>$(input)
+ ]
+ ;
+
+ modules.poke testing : .all-tests : \$\(all-tests\) $(t) ;
+
+ return $(t) ;
+}
+
+rule quickbook-error-test ( target-name : input ? : requirements * )
+{
+ input ?= $(target-name).quickbook ;
+
+ local project = [ project.current ] ;
+
+ local boost-root = [ modules.peek : BOOST_ROOT ] ;
+
+ local t =
+ [ targets.create-typed-target RUN
+ : $(project)
+ : $(target-name)
+ : $(boost-root)/tools/quickbook/src//quickbook
+ : $(requirements)
+ <testing.input-file>$(input)
+ <testing.arg>--expect-errors
+ <preserve-test-targets>on
+ <dependency>$(input)
+ ]
+ ;
+
+ modules.poke testing : .all-tests : \$\(all-tests\) $(t) ;
+
+ return $(t) ;
+}
+
+################################################################################
+toolset.flags quickbook-testing.process-quickbook quickbook-command <quickbook-testing.quickbook-command> ;
+toolset.flags quickbook-testing.process-quickbook QB-DEFINES <quickbook-test-define> ;
+toolset.flags quickbook-testing.process-quickbook XINCLUDE <quickbook-xinclude-base> ;
+toolset.flags quickbook-testing.process-quickbook INCLUDES <quickbook-test-include> ;
+
+rule process-quickbook ( target : source : properties * )
+{
+ DEPENDS $(target) : [ on $(target) return $(quickbook-command) ] ;
+}
+
+actions process-quickbook bind quickbook-command
+{
+ $(quickbook-command) $(>) --output-file=$(<) --debug -D"$(QB-DEFINES)" -I"$(INCLUDES)" --xinclude-base="$(XINCLUDE)"
+}
+
diff --git a/tools/quickbook/test/quickbook_manual-1_4.gold b/tools/quickbook/test/quickbook_manual-1_4.gold
new file mode 100644
index 0000000000..86d2eda663
--- /dev/null
+++ b/tools/quickbook/test/quickbook_manual-1_4.gold
@@ -0,0 +1,3945 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="quickbook" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Quickbook 1.4</title>
+ <articleinfo>
+ <authorgroup>
+ <author>
+ <firstname>Joel</firstname> <surname>de Guzman</surname>
+ </author>
+ <author>
+ <firstname>Eric</firstname> <surname>Niebler</surname>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2002</year> <year>2004</year> <year>2006</year> <holder>Joel de Guzman,
+ Eric Niebler</holder>
+ </copyright>
+ <legalnotice id="quickbook.legal">
+ <para>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
+ </para>
+ </legalnotice>
+ <articlepurpose>
+ <emphasis>WikiWiki</emphasis> style documentation tool
+ </articlepurpose>
+ </articleinfo>
+ <section id="quickbook.intro">
+ <title><link linkend="quickbook.intro">Introduction</link></title>
+ <blockquote>
+ <para>
+ <emphasis role="bold"><emphasis><quote>Why program by hand in five days what
+ you can spend five years of your life automating?</quote></emphasis></emphasis>
+ </para>
+ <para>
+ -- Terrence Parr, author ANTLR/PCCTS
+ </para>
+ </blockquote>
+ <para>
+ Well, QuickBook started as a weekend hack. It was originally intended to be
+ a sample application using <ulink url="http://spirit.sourceforge.net">Spirit</ulink>.
+ What is it? What you are viewing now, this documentation, is autogenerated
+ by QuickBook. These files were generated from one master:
+ </para>
+ <blockquote>
+ <para>
+ <ulink url="../quickbook.qbk">quickbook.qbk</ulink>
+ </para>
+ </blockquote>
+ <para>
+ Originally named QuickDoc, this funky tool that never dies evolved into a funkier
+ tool thanks to Eric Niebler who resurrected the project making it generate
+ <ulink url="http://www.boost.org/doc/html/boostbook.html">BoostBook</ulink>
+ instead of HTML. The <ulink url="http://www.boost.org/doc/html/boostbook.html">BoostBook</ulink>
+ documentation format is an extension of <ulink url="http://www.docbook.org/">DocBook</ulink>,
+ an SGML or XML based format for describing documentation.
+ </para>
+ <para>
+ QuickBook is a WikiWiki style documentation tool geared towards C++ documentation
+ using simple rules and markup for simple formatting tasks. QuickBook extends
+ the WikiWiki concept. Like the WikiWiki, QuickBook documents are simple text
+ files. A single QuickBook document can generate a fully linked set of nice
+ HTML and PostScript/PDF documents complete with images and syntax- colorized
+ source code.
+ </para>
+ <para>
+ Features include:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ generate <ulink url="http://www.boost.org/doc/html/boostbook.html">BoostBook</ulink>
+ xml, to generate HTML, PostScript and PDF
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ simple markup to link to Doxygen-generated entities
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ macro system for simple text substitution
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ simple markup for italics, bold, preformatted, blurbs, code samples, tables,
+ URLs, anchors, images, etc.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ automatic syntax coloring of code samples
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ CSS support
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="quickbook.change_log">
+ <title><link linkend="quickbook.change_log">Change Log</link></title>
+ <bridgehead renderas="sect3" id="quickbook.change_log.h0">
+ <phrase id="quickbook.change_log.version_1_3"/><link linkend="quickbook.change_log.version_1_3">Version
+ 1.3</link>
+ </bridgehead>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Quickbook file inclusion [include].
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Better xml output (pretty layout). Check out the generated XML.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Regression testing facility: to make sure your document will always be
+ compatible (full backward compatibility) regardless of changes to QuickBook.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Code cleanup and refactoring.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Allow phrase markup in the doc-info.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Preformatted code blocks via ``code`` (double ticks) allows code in tables
+ and lists, for example.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Quickbook versioning; allows full backward compatibility. You have to add
+ [quickbook 1.3] to the doc-info header to enable the new features. Without
+ this, QuickBook will assume that the document is a pre-1.3 document.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Better (intuitive) paragraph termination. Some markups may terminate a
+ paragraph. Example:
+<programlisting><phrase role="special">[</phrase><phrase role="identifier">section</phrase> <phrase role="identifier">x</phrase><phrase role="special">]</phrase>
+<phrase role="identifier">blah</phrase><phrase role="special">...</phrase>
+<phrase role="special">[</phrase><phrase role="identifier">endsect</phrase><phrase role="special">]</phrase></programlisting>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Fully qualified section and headers. Subsection names are concatenated
+ to the ID to avoid clashing. Example: <code><phrase role="identifier">doc_name</phrase><phrase
+ role="special">.</phrase><phrase role="identifier">sect_name</phrase><phrase
+ role="special">.</phrase><phrase role="identifier">sub_sect_name</phrase><phrase
+ role="special">.</phrase><phrase role="identifier">sub_sub_sect_name</phrase></code>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Better &amp;nbsp; and whitespace handling in code snippets.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ [xinclude] fixes up the relative path to the target XML file when input_directory
+ is not the same as the output_directory.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Allow untitled tables.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Allow phrase markups in section titles.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Allow escaping back to QuickBook from code, code blocks and inline code.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Footnotes, with the [footnote This is the footnote] syntax.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Post-processor bug fix for escaped XML code that it does not recognize.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Replaceable, with the [~replacement] syntax.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Generic Headers
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Code changes to allow full recursion (i.e. Collectors and push/pop functions)
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Various code cleanup/maintenance
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Templates!
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ [conceptref] for referencing BoostBook &lt;concept&gt; entities.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Allow escape of spaces. The escaped space is removed from the output. Syntax:
+ <code><phrase role="special">\</phrase> </code>.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Nested comments are now allowed.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Quickbook blocks can nest inside comments.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <link linkend="quickbook.syntax.block.import">Import</link> facility.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Callouts on imported code
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Simple markups can now span a whole block.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <link linkend="quickbook.syntax.block.blurbs">Blurbs</link>, <link linkend="quickbook.syntax.block.admonitions">Admonitions</link>
+ and table cells (see <link linkend="quickbook.syntax.block.tables">Tables</link>)
+ may now contain paragraphs.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <code><phrase role="special">\</phrase><phrase role="identifier">n</phrase></code>
+ and <code><phrase role="special">[</phrase><phrase role="identifier">br</phrase><phrase
+ role="special">]</phrase></code> are now deprecated.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="quickbook.syntax">
+ <title><link linkend="quickbook.syntax">Syntax Summary</link></title>
+ <para>
+ A QuickBook document is composed of one or more blocks. An example of a block
+ is the paragraph or a C++ code snippet. Some blocks have special mark-ups.
+ Blocks, except code snippets which have their own grammar (C++ or Python),
+ are composed of one or more phrases. A phrase can be a simple contiguous run
+ of characters. Phrases can have special mark-ups. Marked up phrases can recursively
+ contain other phrases, but cannot contain blocks. A terminal is a self contained
+ block-level or phrase-level element that does not nest anything.
+ </para>
+ <para>
+ Blocks, in general, are delimited by two end-of-lines (the block terminator).
+ Phrases in each block cannot contain a block terminator. This way, syntax errors
+ such as un-matched closing brackets do not go haywire and corrupt anything
+ past a single block.
+ </para>
+ <section id="quickbook.syntax.comments">
+ <title><link linkend="quickbook.syntax.comments">Comments</link></title>
+ <para>
+ Can be placed anywhere.
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[/ comment (no output generated) ]<!--quickbook-escape-postfix-->
+</programlisting>
+<programlisting><!--quickbook-escape-prefix-->[/ comments can be nested [/ some more here] ]<!--quickbook-escape-postfix-->
+</programlisting>
+<programlisting><!--quickbook-escape-prefix-->[/ Quickbook blocks can nest inside comments. [*Comment this out too!] ]<!--quickbook-escape-postfix-->
+</programlisting>
+ </section>
+ <section id="quickbook.syntax.phrase">
+ <title><link linkend="quickbook.syntax.phrase">Phrase Level Elements</link></title>
+ <section id="quickbook.syntax.phrase.font_styles">
+ <title><link linkend="quickbook.syntax.phrase.font_styles">Font Styles</link></title>
+<programlisting><!--quickbook-escape-prefix-->['italic], [*bold], [_underline], [^teletype], [-strikethrough]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <para>
+ <emphasis>italic</emphasis>, <emphasis role="bold">bold</emphasis>, <emphasis
+ role="underline">underline</emphasis>, <literal>teletype</literal>, <emphasis
+ role="strikethrough">strikethrough</emphasis>
+ </para>
+ <para>
+ Like all non-terminal phrase level elements, this can of course be nested:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[*['bold-italic]]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <para>
+ <emphasis role="bold"><emphasis>bold-italic</emphasis></emphasis>
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.replaceable">
+ <title><link linkend="quickbook.syntax.phrase.replaceable">Replaceable</link></title>
+ <para>
+ When you want content that may or must be replaced by the user, use the
+ syntax:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[~replacement]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ This will generate:
+ </para>
+ <para>
+ <replaceable>replacement</replaceable>
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.quotations">
+ <title><link linkend="quickbook.syntax.phrase.quotations">Quotations</link></title>
+<programlisting><!--quickbook-escape-prefix-->["A question that sometimes drives me hazy: am I or are the others crazy?]--Einstein
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <para>
+ <quote>A question that sometimes drives me hazy: am I or are the others
+ crazy?</quote>--Einstein
+ </para>
+ <para>
+ Note the proper left and right quote marks. Also, while you can simply
+ use ordinary quote marks like &quot;quoted&quot;, our quotation, above,
+ will generate correct DocBook quotations (e.g. &lt;quote&gt;quoted&lt;/quote&gt;).
+ </para>
+ <para>
+ Like all phrase elements, quotations may be nested. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->["Here's the rule for bargains: ["Do other men, for they would do you.] That's
+the true business precept.]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <para>
+ <quote>Here's the rule for bargains: <quote>Do other men, for they would
+ do you.</quote> That's the true business precept.</quote>
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.simple_formatting">
+ <title><link linkend="quickbook.syntax.phrase.simple_formatting">Simple formatting</link></title>
+ <para>
+ Simple markup for formatting text, common in many applications, is now
+ supported:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->/italic/, *bold*, _underline_, =teletype=
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <para>
+ <emphasis>italic</emphasis>, <emphasis role="bold">bold</emphasis>, <emphasis
+ role="underline">underline</emphasis>, <literal>teletype</literal>
+ </para>
+ <para>
+ Unlike QuickBook's standard formatting scheme, the rules for simpler alternatives
+ are much stricter<footnote id="quickbook.syntax.phrase.simple_formatting.f0">
+ <para>
+ Thanks to David Barrett, author of <ulink url="http://quinthar.com/qwikiwiki/index.php?page=Home">Qwiki</ulink>,
+ for sharing these samples and teaching me these obscure formatting rules.
+ I wasn't sure at all if <ulink url="http://spirit.sourceforge.net">Spirit</ulink>,
+ being more or less a formal EBNF parser, can handle the context sensitivity
+ and ambiguity.
+ </para>
+ </footnote>.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Simple markups cannot nest. You can combine a simple markup with a
+ nestable markup.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Simple markups cannot contain any other form of quickbook markup.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A non-space character must follow the leading markup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A non-space character must precede the trailing markup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A space or a punctuation must follow the trailing markup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ If the matching markup cannot be found within a block, the formatting
+ will not be applied. This is to ensure that un-matched formatting markups,
+ which can be a common mistake, does not corrupt anything past a single
+ block. We do not want the rest of the document to be rendered bold
+ just because we forgot a trailing '*'. A single block is terminated
+ by two end of lines or the close bracket: ']'.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A line starting with the star will be interpreted as an unordered list.
+ See <link linkend="quickbook.syntax.block.lists.unordered_lists">Unordered
+ lists</link>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <table frame="all" id="quickbook.syntax.phrase.simple_formatting.t0">
+ <title>More Formatting Samples</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Markup
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Result
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ <literal>*Bold*</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <emphasis role="bold">Bold</emphasis>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>*Is bold*</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <emphasis role="bold">Is bold</emphasis>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>* Not bold* *Not bold * * Not bold *</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ * Not bold* *Not bold * * Not bold *
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>This*Isn't*Bold (no bold)</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ This*Isn't*Bold (no bold)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>(*Bold Inside*) (parenthesis not bold)</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ (<emphasis role="bold">Bold Inside</emphasis>) (parenthesis not
+ bold)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>*(Bold Outside)* (parenthesis bold)</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <emphasis role="bold">(Bold Outside)</emphasis> (parenthesis
+ bold)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>3*4*5 = 60 (no bold)</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ 3*4*5 = 60 (no bold)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>3 * 4 * 5 = 60 (no bold)</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ 3 * 4 * 5 = 60 (no bold)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>3 *4* 5 = 60 (4 is bold)</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ 3 <emphasis role="bold">4</emphasis> 5 = 60 (4 is bold)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>*This is bold* this is not *but this is*</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <emphasis role="bold">This is bold</emphasis> this is not <emphasis
+ role="bold">but this is</emphasis>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>*This is bold*.</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <emphasis role="bold">This is bold</emphasis>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>*B*. (bold B)</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <emphasis role="bold">B</emphasis>. (bold B)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>['*Bold-Italic*]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <emphasis><emphasis role="bold">Bold-Italic</emphasis></emphasis>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>*side-by*/-side/</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <emphasis role="bold">side-by</emphasis><emphasis>-side</emphasis>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ As mentioned, simple markups cannot go past a single block. The text from
+ &quot;have&quot; to &quot;full&quot; in the following paragraph will be
+ rendered as bold:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->Baa baa black sheep, *have you any wool?
+Yes sir, yes sir, three bags full!*
+One for the master, one for the dame,
+And one for the little boy who lives down the lane.
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Baa baa black sheep, <emphasis role="bold">have you any wool? Yes sir,
+ yes sir, three bags full!</emphasis> One for the master, one for the dame,
+ And one for the little boy who lives down the lane.
+ </para>
+ <para>
+ But in the following paragraph, bold is not applied:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->Baa baa black sheep, *have you any wool?
+Yes sir, yes sir, three bags full!
+One for the master, one for the dame,
+And one for the little boy who lives down the lane.
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Baa baa black sheep, *have you any wool? Yes sir, yes sir, three bags full!
+ One for the master, one for the dame, And one for the little boy who lives
+ down the lane.
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.inline_code">
+ <title><link linkend="quickbook.syntax.phrase.inline_code">Inline code</link></title>
+ <para>
+ Inlining code in paragraphs is quite common when writing C++ documentation.
+ We provide a very simple markup for this. For example, this:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->This text has inlined code `int main() { return 0; }` in it.
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <para>
+ This text has inlined code <code><phrase role="keyword">int</phrase> <phrase
+ role="identifier">main</phrase><phrase role="special">()</phrase> <phrase
+ role="special">{</phrase> <phrase role="keyword">return</phrase> <phrase
+ role="number">0</phrase><phrase role="special">;</phrase> <phrase role="special">}</phrase></code>
+ in it. The code will be syntax highlighted.
+ </para>
+ <note>
+ <para>
+ We simply enclose the code with the tick: <literal>"`"</literal>, not the
+ single quote: <code><phrase role="string">&quot;'&quot;</phrase></code>.
+ Note too that <literal>`some code`</literal> is preferred over <literal>[^some code]</literal>.
+ </para>
+ </note>
+ </section>
+ <section id="quickbook.syntax.phrase.code_blocks">
+ <title><link linkend="quickbook.syntax.phrase.code_blocks">Code blocks</link></title>
+ <para>
+ Preformatted code simply starts with a space or a tab (See <link linkend="quickbook.syntax.block.code">Code</link>).
+ However, such a simple syntax cannot be used as phrase elements in lists
+ (See <link linkend="quickbook.syntax.block.lists.ordered_lists">Ordered
+ lists</link> and <link linkend="quickbook.syntax.block.lists.unordered_lists">Unordered
+ lists</link>), tables (See <link linkend="quickbook.syntax.block.tables">Tables</link>),
+ etc. Inline code (see above) can. The problem is, inline code does not
+ allow formatting with newlines, spaces, and tabs. These are lost.
+ </para>
+ <para>
+ We provide a phrase level markup that is a mix between the two. By using
+ the double-tick, instead of the single-tick, we are telling QuickBook to
+ use preformatted blocks of code. Example:
+ </para>
+<programlisting>``
+ #include &lt;iostream&gt;
+
+ int main()
+ {
+ std::cout &lt;&lt; &quot;Hello, World!&quot; &lt;&lt; std::endl;
+ return 0;
+ }
+``
+</programlisting>
+ <para>
+ will generate:
+ </para>
+ <para>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">iostream</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;Hello, World!&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.source_mode">
+ <title><link linkend="quickbook.syntax.phrase.source_mode">Source Mode</link></title>
+ <para>
+ If a document contains more than one type of source code then the source
+ mode may be changed dynamically as the document is processed. All QuickBook
+ documents are initially in C++ mode by default, though an alternative initial
+ value may be set in the <link linkend="quickbook.syntax.block.document">Document</link>
+ section.
+ </para>
+ <para>
+ To change the source mode, use the <literal>[source-mode]</literal> markup,
+ where <literal>source-mode</literal> is one of the supported modes. For
+ example, this:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->Python's [python] `import` is rather like C++'s [c++] `#include`. A
+C++ comment `// looks like this` whereas a Python comment [python]
+`# looks like this`.
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <para>
+ Python's <code><phrase role="keyword">import</phrase></code> is rather
+ like C++'s <code><phrase role="preprocessor">#include</phrase></code>.
+ A C++ comment <code><phrase role="comment">// looks like this</phrase></code>
+ whereas a Python comment <code><phrase role="comment">#looks like this</phrase></code>.
+ </para>
+ <table frame="all" id="quickbook.syntax.phrase.source_mode.t0">
+ <title>Supported Source Modes</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Mode
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Source Mode Markup
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ C++
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[c++]</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Python
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[python]</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <note>
+ <para>
+ The source mode strings are lowercase.
+ </para>
+ </note>
+ </section>
+ <section id="quickbook.syntax.phrase.line_break">
+ <title><link linkend="quickbook.syntax.phrase.line_break">line-break</link></title>
+<programlisting><!--quickbook-escape-prefix-->[br]
+<!--quickbook-escape-postfix--></programlisting>
+ <warning>
+ <para>
+ <code><phrase role="special">[</phrase><phrase role="identifier">br</phrase><phrase
+ role="special">]</phrase></code> is now deprecated. <link linkend="quickbook.syntax.block.blurbs">Blurbs</link>,
+ <link linkend="quickbook.syntax.block.admonitions">Admonitions</link>
+ and table cells (see <link linkend="quickbook.syntax.block.tables">Tables</link>)
+ may now contain paragraphs.
+ </para>
+ </warning>
+ </section>
+ <section id="quickbook.syntax.phrase.anchors">
+ <title><link linkend="quickbook.syntax.phrase.anchors">Anchors</link></title>
+<programlisting><!--quickbook-escape-prefix-->[#named_anchor]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ A named anchor is a hook that can be referenced by a link elsewhere in
+ the document. You can then reference an anchor with <literal>[link named_anchor
+Some link text]</literal>.
+ See <link linkend="quickbook.syntax.phrase.anchor_links">Anchor links</link>,
+ <link linkend="quickbook.syntax.block.section">Section</link> and <link
+ linkend="quickbook.syntax.block.headings">Heading</link>.
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.links">
+ <title><link linkend="quickbook.syntax.phrase.links">Links</link></title>
+<programlisting><!--quickbook-escape-prefix-->[@http://www.boost.org this is [*boost's] website....]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <para>
+ <ulink url="http://www.boost.org">this is <emphasis role="bold">boost's</emphasis>
+ website....</ulink>
+ </para>
+ <para>
+ URL links where the link text is the link itself is common. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->see http://spirit.sourceforge.net/
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ so, when the text is absent in a link markup, the URL is assumed. Example:
+ </para>
+<programlisting>see <!--quickbook-escape-prefix-->[@http://spirit.sourceforge.net/]<!--quickbook-escape-postfix-->
+</programlisting>
+ <para>
+ will generate:
+ </para>
+ <para>
+ see <ulink url="http://spirit.sourceforge.net/">http://spirit.sourceforge.net/</ulink>
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.anchor_links">
+ <title><link linkend="quickbook.syntax.phrase.anchor_links">Anchor links</link></title>
+ <para>
+ You can link within a document using:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[link section_id.normalized_header_text The link text]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ See sections <link linkend="quickbook.syntax.block.section">Section</link>
+ and <link linkend="quickbook.syntax.block.headings">Heading</link> for
+ more info.
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.refentry_links">
+ <title><link linkend="quickbook.syntax.phrase.refentry_links">refentry links</link></title>
+ <para>
+ In addition, you can link internally to an XML refentry like:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[link xml.refentry The link text]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ This gets converted into <literal>&lt;link linkend=&quot;xml.refentry&quot;&gt;The
+ link text&lt;/link&gt;</literal>.
+ </para>
+ <para>
+ Like URLs, the link text is optional. If this is not present, the link
+ text will automatically be the refentry. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[link xml.refentry]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ This gets converted into <literal>&lt;link linkend=&quot;xml.refentry&quot;&gt;xml.refentry&lt;/link&gt;</literal>.
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.code_links">
+ <title><link linkend="quickbook.syntax.phrase.code_links">Code Links</link></title>
+ <para>
+ If you want to link to a function, class, member, enum, concept or header
+ in the reference section, you can use:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[funcref fully::qualified::function_name The link text]
+[classref fully::qualified::class_name The link text]
+[memberref fully::qualified::member_name The link text]
+[enumref fully::qualified::enum_name The link text]
+[macroref MACRO_NAME The link text]
+[conceptref ConceptName The link text]
+[headerref path/to/header.hpp The link text]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Again, the link text is optional. If this is not present, the link text
+ will automatically be the function, class, member, enum, macro, concept
+ or header. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[classref boost::bar::baz]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ would have &quot;boost::bar::baz&quot; as the link text.
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.escape">
+ <title><link linkend="quickbook.syntax.phrase.escape">Escape</link></title>
+ <para>
+ The escape mark-up is used when we don't want to do any processing.
+ </para>
+<programlisting>'''
+escape (no processing/formatting)
+'''
+</programlisting>
+ <para>
+ Escaping allows us to pass XML markup to <ulink url="http://www.boost.org/doc/html/boostbook.html">BoostBook</ulink>
+ or <ulink url="http://www.docbook.org/">DocBook</ulink>. For example:
+ </para>
+<programlisting>'''
+&lt;emphasis role=&quot;bold&quot;&gt;This is direct XML markup&lt;/emphasis&gt;
+'''
+</programlisting>
+ <para>
+ <emphasis role="bold">This is direct XML markup</emphasis>
+ </para>
+ <important>
+ <para>
+ Be careful when using the escape. The text must conform to <ulink url="http://www.boost.org/doc/html/boostbook.html">BoostBook</ulink>/<ulink
+ url="http://www.docbook.org/">DocBook</ulink> syntax.
+ </para>
+ </important>
+ </section>
+ <section id="quickbook.syntax.phrase.single_char_escape">
+ <title><link linkend="quickbook.syntax.phrase.single_char_escape">Single
+ char escape</link></title>
+ <para>
+ The backslash may be used to escape a single punctuation character. The
+ punctuation immediately after the backslash is passed without any processing.
+ This is useful when we need to escape QuickBook punctuations such as <code><phrase
+ role="special">[</phrase></code> and <code><phrase role="special">]</phrase></code>.
+ For example, how do you escape the triple quote? Simple: <literal>\'\'\'</literal>
+ </para>
+ <para>
+ <code><phrase role="special">\</phrase><phrase role="identifier">n</phrase></code>
+ has a special meaning. It is used to generate line breaks.
+ </para>
+ <warning>
+ <para>
+ <code><phrase role="special">\</phrase><phrase role="identifier">n</phrase></code>
+ and <code><phrase role="special">[</phrase><phrase role="identifier">br</phrase><phrase
+ role="special">]</phrase></code> are now deprecated. <link linkend="quickbook.syntax.block.blurbs">Blurbs</link>,
+ <link linkend="quickbook.syntax.block.admonitions">Admonitions</link>
+ and table cells (see <link linkend="quickbook.syntax.block.tables">Tables</link>)
+ may now contain paragraphs.
+ </para>
+ </warning>
+ <para>
+ The escaped space: <code><phrase role="special">\</phrase> </code> also
+ has a special meaning. The escaped space is removed from the output.
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.images">
+ <title><link linkend="quickbook.syntax.phrase.images">Images</link></title>
+<programlisting><!--quickbook-escape-prefix-->[$image.jpg]
+<!--quickbook-escape-postfix--></programlisting>
+ </section>
+ <section id="quickbook.syntax.phrase.footnotes">
+ <title><link linkend="quickbook.syntax.phrase.footnotes">Footnotes</link></title>
+ <para>
+ As of version 1.3, QuickBook supports footnotes. Just put the text of the
+ footnote in a <code><phrase role="special">[</phrase><phrase role="identifier">footnote</phrase><phrase
+ role="special">]</phrase></code> block, and the text will be put at the
+ bottom of the current page. For example, this:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[footnote A sample footnote]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate this<footnote id="quickbook.syntax.phrase.footnotes.f0">
+ <para>
+ A sample footnote
+ </para>
+ </footnote>.
+ </para>
+ <section id="quickbook.syntax.phrase.footnotes.macro_expansion">
+ <title><link linkend="quickbook.syntax.phrase.footnotes.macro_expansion">Macro
+ Expansion</link></title>
+<programlisting><!--quickbook-escape-prefix-->__a_macro_identifier__
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ See <link linkend="quickbook.syntax.block.macros">Macros</link> for details.
+ </para>
+ </section>
+ <section id="quickbook.syntax.phrase.footnotes.template_expansion">
+ <title><link linkend="quickbook.syntax.phrase.footnotes.template_expansion">Template
+ Expansion</link></title>
+<programlisting><!--quickbook-escape-prefix-->[a_template_identifier]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ See <link linkend="quickbook.syntax.block.templates">Templates</link>
+ for details.
+ </para>
+ </section>
+ </section>
+ </section>
+ <section id="quickbook.syntax.block">
+ <title><link linkend="quickbook.syntax.block">Block Level Elements</link></title>
+ <section id="quickbook.syntax.block.document">
+ <title><link linkend="quickbook.syntax.block.document">Document</link></title>
+ <para>
+ Every document must begin with a Document Info section, which should look
+ like this:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[document-type The Document Title
+ [quickbook 1.3]
+ [version 1.0]
+ [id the_document_name]
+ [dirname the_document_dir]
+ [copyright 2000 2002 2003 Joe Blow, Jane Doe]
+ [purpose The document's reason for being]
+ [category The document's category]
+ [authors [Blow, Joe], [Doe, Jane]]
+ [license The document's license]
+ [source-mode source-type]
+]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Where document-type is one of:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ book
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ article
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ library
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ chapter
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ part
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ appendix
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ preface
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ qandadiv
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ qandaset
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ reference
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ set
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ quickbook 1.3 declares the version of quickbook the document is written
+ for. In its absence, version 1.1 is assumed.
+ </para>
+ <para>
+ <literal>version</literal>, <literal>id</literal>, <literal>dirname</literal>,
+ <literal>copyright</literal>, <literal>purpose</literal>, <literal>category</literal>,
+ <literal>authors</literal>, <literal>license</literal>, <literal>last-revision</literal>
+ and <literal>source-mode</literal> are optional information.
+ </para>
+ <para>
+ <literal>source-type</literal> is a lowercase string setting the initial
+ <link linkend="quickbook.syntax.phrase.source_mode">Source Mode</link>.
+ If the <literal>source-mode</literal> field is omitted, a default value
+ of <literal>c++</literal> will be used.
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.section">
+ <title><link linkend="quickbook.syntax.block.section">Section</link></title>
+ <para>
+ Starting a new section is accomplished with:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[section:id The Section Title]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ where <emphasis>id</emphasis> is optional. id will be the filename of the
+ generated section. If it is not present, &quot;The Section Title&quot;
+ will be normalized and become the id. Valid characters are <literal>a-Z</literal>,
+ <literal>A-Z</literal>, <literal>0-9</literal> and <literal>_</literal>.
+ All non-valid characters are converted to underscore and all upper-case
+ are converted to lower case. Thus: &quot;The Section Title&quot; will be
+ normalized to &quot;the_section_title&quot;.
+ </para>
+ <para>
+ End a section with:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[endsect]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Sections can nest, and that results in a hierarchy in the table of contents.
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.xinclude">
+ <title><link linkend="quickbook.syntax.block.xinclude">xinclude</link></title>
+ <para>
+ You can include another XML file with:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[xinclude file.xml]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ This is useful when file.xml has been generated by Doxygen and contains
+ your reference section.
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.paragraphs">
+ <title><link linkend="quickbook.syntax.block.paragraphs">Paragraphs</link></title>
+ <para>
+ Paragraphs start left-flushed and are terminated by two or more newlines.
+ No markup is needed for paragraphs. QuickBook automatically detects paragraphs
+ from the context. Block markups [section, endsect, h1, h2, h3, h4, h5,
+ h6, blurb, (block-quote) ':', pre, def, table and include ] may also terminate
+ a paragraph.
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.lists">
+ <title><link linkend="quickbook.syntax.block.lists">Lists</link></title>
+ <section id="quickbook.syntax.block.lists.ordered_lists">
+ <title><link linkend="quickbook.syntax.block.lists.ordered_lists">Ordered
+ lists</link></title>
+<programlisting># One
+# Two
+# Three
+</programlisting>
+ <para>
+ will generate:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ One
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Two
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Three
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </section>
+ <section id="quickbook.syntax.block.lists.list_hierarchies">
+ <title><link linkend="quickbook.syntax.block.lists.list_hierarchies">List
+ Hierarchies</link></title>
+ <para>
+ List hierarchies are supported. Example:
+ </para>
+<programlisting># One
+# Two
+# Three
+ # Three.a
+ # Three.b
+ # Three.c
+# Four
+ # Four.a
+ # Four.a.i
+ # Four.a.ii
+# Five
+</programlisting>
+ <para>
+ will generate:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ One
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Two
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Three
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Three.a
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Three.b
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Three.c
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Fourth
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Four.a
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Four.a.i
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Four.a.ii
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Five
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </section>
+ <section id="quickbook.syntax.block.lists.long_list_lines">
+ <title><link linkend="quickbook.syntax.block.lists.long_list_lines">Long
+ List Lines</link></title>
+ <para>
+ Long lines will be wrapped appropriately. Example:
+ </para>
+<programlisting># A short item.
+# A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+# A short item.
+</programlisting>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ A short item.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A very long item. A very long item. A very long item. A very long
+ item. A very long item. A very long item. A very long item. A very
+ long item. A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item. A very long
+ item.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A short item.
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </section>
+ <section id="quickbook.syntax.block.lists.unordered_lists">
+ <title><link linkend="quickbook.syntax.block.lists.unordered_lists">Unordered
+ lists</link></title>
+<programlisting><!--quickbook-escape-prefix-->* First
+* Second
+* Third
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ First
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Second
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Third
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="quickbook.syntax.block.lists.mixed_lists">
+ <title><link linkend="quickbook.syntax.block.lists.mixed_lists">Mixed lists</link></title>
+ <para>
+ Mixed lists (ordered and unordered) are supported. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix--># One
+# Two
+# Three
+ * Three.a
+ * Three.b
+ * Three.c
+# Four
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ One
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Two
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Three
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Three.a
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Three.b
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Three.c
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Four
+ </simpara>
+ </listitem>
+ </orderedlist>
+ <para>
+ And...
+ </para>
+<programlisting><!--quickbook-escape-prefix--># 1
+ * 1.a
+ # 1.a.1
+ # 1.a.2
+ * 1.b
+# 2
+ * 2.a
+ * 2.b
+ # 2.b.1
+ # 2.b.2
+ * 2.b.2.a
+ * 2.b.2.b
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ 1
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ 1.a
+ <orderedlist>
+ <listitem>
+ <simpara>
+ 1.a.1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ 1.a.2
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ 1.b
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ 2
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ 2.a
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ 2.b
+ <orderedlist>
+ <listitem>
+ <simpara>
+ 2.b.1
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ 2.b.2
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ 2.b.2.a
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ 2.b.2.b
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </section>
+ </section>
+ <section id="quickbook.syntax.block.code">
+ <title><link linkend="quickbook.syntax.block.code">Code</link></title>
+ <para>
+ Preformatted code starts with a space or a tab. The code will be syntax
+ highlighted according to the current <link linkend="quickbook.syntax.phrase.source_mode">Source
+ Mode</link>:
+ </para>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">iostream</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">// Sample code</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;Hello, World\n&quot;</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+<programlisting><phrase role="keyword">import</phrase> <phrase role="identifier">cgi</phrase>
+
+<phrase role="keyword">def</phrase> <phrase role="identifier">cookForHtml</phrase><phrase role="special">(</phrase><phrase role="identifier">text</phrase><phrase role="special">):</phrase>
+ <phrase role="string">'''&quot;Cooks&quot; the input text for HTML.'''</phrase>
+
+ <phrase role="keyword">return</phrase> <phrase role="identifier">cgi</phrase><phrase role="special">.</phrase><phrase role="identifier">escape</phrase><phrase role="special">(</phrase><phrase role="identifier">text</phrase><phrase role="special">)</phrase>
+</programlisting>
+ <para>
+ Macros that are already defined are expanded in source code. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[def __array__ [@http://www.boost.org/doc/html/array/reference.html array]]
+[def __boost__ [@http://www.boost.org/libs/libraries.htm boost]]
+
+ using __boost__::__array__;
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Generates:
+ </para>
+<programlisting><phrase role="keyword">using</phrase> <ulink url="http://www.boost.org/libs/libraries.htm">boost</ulink><phrase role="special">::</phrase><ulink url="http://www.boost.org/doc/html/array/reference.html">array</ulink><phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="quickbook.syntax.block.escape_back">
+ <title><link linkend="quickbook.syntax.block.escape_back">Escaping Back To
+ QuickBook</link></title>
+ <para>
+ Inside code, code blocks and inline code, QuickBook does not allow any
+ markup to avoid conflicts with the target syntax (e.g. c++). In case you
+ need to switch back to QuickBook markup inside code, you can do so using
+ a language specific <emphasis>escape-back</emphasis> delimiter. In C++
+ and Python, the delimiter is the double tick (back-quote): &quot;``&quot;
+ and &quot;``&quot;. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->void ``[@http://en.wikipedia.org/wiki/Foo#Foo.2C_Bar_and_Baz foo]``()
+{
+}
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Will generate:
+ </para>
+<programlisting><phrase role="keyword">void</phrase> <ulink url="http://en.wikipedia.org/wiki/Foo#Foo.2C_Bar_and_Baz">foo</ulink><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ <para>
+ When escaping from code to QuickBook, only phrase level markups are allowed.
+ Block level markups like lists, tables etc. are not allowed.
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.preformatted">
+ <title><link linkend="quickbook.syntax.block.preformatted">Preformatted</link></title>
+ <para>
+ Sometimes, you don't want some preformatted text to be parsed as C++. In
+ such cases, use the <literal>[pre ... ]</literal> markup block.
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[pre
+
+ Some *preformatted* text Some *preformatted* text
+
+ Some *preformatted* text Some *preformatted* text
+
+ Some *preformatted* text Some *preformatted* text
+
+]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Spaces, tabs and newlines are rendered as-is. Unlike all quickbook block
+ level markup, pre (and Code) are the only ones that allow multiple newlines.
+ The markup above will generate:
+ </para>
+<programlisting>Some <emphasis role="bold">preformatted</emphasis> text Some <emphasis role="bold">preformatted</emphasis> text
+
+ Some <emphasis role="bold">preformatted</emphasis> text Some <emphasis role="bold">preformatted</emphasis> text
+
+ Some <emphasis role="bold">preformatted</emphasis> text Some <emphasis role="bold">preformatted</emphasis> text
+
+</programlisting>
+ <para>
+ Notice that unlike Code, phrase markup such as font style is still permitted
+ inside <literal>pre</literal> blocks.
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.blockquote">
+ <title><link linkend="quickbook.syntax.block.blockquote">Blockquote</link></title>
+<programlisting><!--quickbook-escape-prefix-->[:sometext...]<!--quickbook-escape-postfix-->
+</programlisting>
+ <blockquote>
+ <para>
+ Indents the paragraph. This applies to one paragraph only.
+ </para>
+ </blockquote>
+ </section>
+ <section id="quickbook.syntax.block.admonitions">
+ <title><link linkend="quickbook.syntax.block.admonitions">Admonitions</link></title>
+<programlisting><!--quickbook-escape-prefix-->[note This is a note]
+[tip This is a tip]
+[important This is important]
+[caution This is a caution]
+[warning This is a warning]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ generates <ulink url="http://www.docbook.org/">DocBook</ulink> admonitions:
+ </para>
+ <note>
+ <para>
+ This is a note
+ </para>
+ </note>
+ <tip>
+ <para>
+ This is a tip
+ </para>
+ </tip>
+ <important>
+ <para>
+ This is important
+ </para>
+ </important>
+ <caution>
+ <para>
+ This is a caution
+ </para>
+ </caution>
+ <warning>
+ <para>
+ This is a warning
+ </para>
+ </warning>
+ <para>
+ These are the only admonitions supported by <ulink url="http://www.docbook.org/">DocBook</ulink>.
+ So, for example <literal>[information This is some information]</literal>
+ is unlikely to produce the desired effect.
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.headings">
+ <title><link linkend="quickbook.syntax.block.headings">Headings</link></title>
+<programlisting><!--quickbook-escape-prefix-->[h1 Heading 1]
+[h2 Heading 2]
+[h3 Heading 3]
+[h4 Heading 4]
+[h5 Heading 5]
+[h6 Heading 6]
+<!--quickbook-escape-postfix--></programlisting>
+ <bridgehead renderas="sect1" id="quickbook.syntax.block.headings.h0">
+ <phrase id="quickbook.syntax.block.headings.heading_1"/><link linkend="quickbook.syntax.block.headings.heading_1">Heading
+ 1</link>
+ </bridgehead>
+ <bridgehead renderas="sect2" id="quickbook.syntax.block.headings.h1">
+ <phrase id="quickbook.syntax.block.headings.heading_2"/><link linkend="quickbook.syntax.block.headings.heading_2">Heading
+ 2</link>
+ </bridgehead>
+ <bridgehead renderas="sect3" id="quickbook.syntax.block.headings.h2">
+ <phrase id="quickbook.syntax.block.headings.heading_3"/><link linkend="quickbook.syntax.block.headings.heading_3">Heading
+ 3</link>
+ </bridgehead>
+ <bridgehead renderas="sect4" id="quickbook.syntax.block.headings.h3">
+ <phrase id="quickbook.syntax.block.headings.heading_4"/><link linkend="quickbook.syntax.block.headings.heading_4">Heading
+ 4</link>
+ </bridgehead>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.headings.h4">
+ <phrase id="quickbook.syntax.block.headings.heading_5"/><link linkend="quickbook.syntax.block.headings.heading_5">Heading
+ 5</link>
+ </bridgehead>
+ <bridgehead renderas="sect6" id="quickbook.syntax.block.headings.h5">
+ <phrase id="quickbook.syntax.block.headings.heading_6"/><link linkend="quickbook.syntax.block.headings.heading_6">Heading
+ 6</link>
+ </bridgehead>
+ <para>
+ Headings 1-3 [h1 h2 and h3] will automatically have anchors with normalized
+ names with <literal>name=&quot;section_id.normalized_header_text&quot;</literal>
+ (i.e. valid characters are <literal>a-z</literal>, <literal>A-Z</literal>,
+ <literal>0-9</literal> and <literal>_</literal>. All non-valid characters
+ are converted to underscore and all upper-case are converted to lower-case.
+ For example: Heading 1 in section Section 2 will be normalized to <literal>section_2.heading_1</literal>).
+ You can use:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[link section_id.normalized_header_text The link text]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ to link to them. See <link linkend="quickbook.syntax.phrase.anchor_links">Anchor
+ links</link> and <link linkend="quickbook.syntax.block.section">Section</link>
+ for more info.
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.generic_heading">
+ <title><link linkend="quickbook.syntax.block.generic_heading">Generic Heading</link></title>
+ <para>
+ In cases when you don't want to care about the heading level (1 to 6),
+ you can use the <emphasis>Generic Heading</emphasis>:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[heading Heading]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ The <emphasis>Generic Heading</emphasis> assumes the level, plus one, of
+ the innermost section where it is placed. For example, if it is placed
+ in the outermost section, then, it assumes <emphasis>h2</emphasis>.
+ </para>
+ <para>
+ Headings are often used as an alternative to sections. It is used particularly
+ if you do not want to start a new section. In many cases, however, headings
+ in a particular section is just flat. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[section A]
+[h2 X]
+[h2 Y]
+[h2 Z]
+[endsect]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Here we use h2 assuming that section A is the outermost level. If it is
+ placed in an inner level, you'll have to use h3, h4, etc. depending on
+ where the section is. In general, it is the section level plus one. It
+ is rather tedious, however, to scan the section level everytime. If you
+ rewrite the example above as shown below, this will be automatic:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[section A]
+[heading X]
+[heading Y]
+[heading Z]
+[endsect]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ They work well regardless where you place them. You can rearrange sections
+ at will without any extra work to ensure correct heading levels. In fact,
+ with <emphasis>section</emphasis> and <emphasis>heading</emphasis>, you
+ have all you need. <emphasis>h1</emphasis>..<emphasis>h6</emphasis> becomes
+ redundant. <emphasis>h1</emphasis>..<emphasis>h6</emphasis> might be deprecated
+ in the future.
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.macros">
+ <title><link linkend="quickbook.syntax.block.macros">Macros</link></title>
+<programlisting><!--quickbook-escape-prefix-->[def macro_identifier some text]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ When a macro is defined, the identifier replaces the text anywhere in the
+ file, in paragraphs, in markups, etc. macro_identifier is a string of non-
+ white space characters except ']'. A macro may not follow an alphabetic
+ character or the underscore. The replacement text can be any phrase (even
+ marked up). Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[def sf_logo [$http://sourceforge.net/sflogo.php?group_id=28447&amp;type=1]]
+sf_logo
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Now everywhere the sf_logo is placed, the picture will be inlined.
+ </para>
+ <para>
+ <inlinemediaobject><imageobject><imagedata fileref="http://sourceforge.net/sflogo.php?group_id=28447&amp;type=1"></imagedata></imageobject>
+ <textobject>
+ <phrase>sflogo</phrase>
+ </textobject>
+ </inlinemediaobject>
+ </para>
+ <tip>
+ <para>
+ It's a good idea to use macro identifiers that are distinguishable. For
+ instance, in this document, macro identifiers have two leading and trailing
+ underscores (e.g. <literal>__spirit__</literal>). The reason is to avoid unwanted
+ macro replacement.
+ </para>
+ </tip>
+ <para>
+ Links (URLS) and images are good candidates for macros. <emphasis role="bold">1</emphasis>)
+ They tend to change a lot. It is a good idea to place all links and images
+ in one place near the top to make it easy to make changes. <emphasis role="bold">2</emphasis>)
+ The syntax is not pretty. It's easier to read and write, e.g. <literal>__spirit__</literal>
+ than <literal>[@http://spirit.sourceforge.net Spirit]</literal>.
+ </para>
+ <para>
+ Some more examples:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[def :-) [$theme/smiley.png]]
+[def __spirit__ [@http://spirit.sourceforge.net Spirit]]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ (See <link linkend="quickbook.syntax.phrase.images">Images</link> and
+ <link linkend="quickbook.syntax.phrase.links">Links</link>)
+ </para>
+ <para>
+ Invoking these macros:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->Hi __spirit__ :-)
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate this:
+ </para>
+ <para>
+ Hi <ulink url="http://spirit.sourceforge.net">Spirit</ulink> <inlinemediaobject><imageobject><imagedata
+ fileref="images/smiley.png"></imagedata></imageobject>
+ <textobject>
+ <phrase>smiley</phrase>
+ </textobject>
+ </inlinemediaobject>
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.predefined_macros">
+ <title><link linkend="quickbook.syntax.block.predefined_macros">Predefined
+ Macros</link></title>
+ <para>
+ Quickbook has some predefined macros that you can already use.
+ </para>
+ <table frame="all" id="quickbook.syntax.block.predefined_macros.t0">
+ <title>Predefined Macros</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Macro
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Meaning
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Example
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ __DATE__
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Today's date
+ </para>
+ </entry>
+ <entry>
+ <para>
+ 2000-Dec-20
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ __TIME__
+ </para>
+ </entry>
+ <entry>
+ <para>
+ The current time
+ </para>
+ </entry>
+ <entry>
+ <para>
+ 12:00:00 PM
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ __FILENAME__
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Quickbook source filename
+ </para>
+ </entry>
+ <entry>
+ <para>
+ quickbook_manual-1_4.quickbook
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="quickbook.syntax.block.templates">
+ <title><link linkend="quickbook.syntax.block.templates">Templates</link></title>
+ <para>
+ Templates provide a more versatile text substitution mechanism. Templates
+ come in handy when you need to create parameterizable, multi-line, boilerplate
+ text that you specify once and expand many times. Templates accept one
+ or more arguments. These arguments act like place-holders for text replacement.
+ Unlike simple macros, which are limited to phrase level markup, templates
+ can contain block level markup (e.g. paragraphs, code blocks and tables).
+ </para>
+ <para>
+ Example template:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[template person[name age what]
+
+Hi, my name is [name]. I am [age] years old. I am a [what].
+
+]
+<!--quickbook-escape-postfix--></programlisting>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.h0">
+ <phrase id="quickbook.syntax.block.templates.template_identifier"/><link
+ linkend="quickbook.syntax.block.templates.template_identifier">Template
+ Identifier</link>
+ </bridgehead>
+ <para>
+ Template identifiers can either consist of:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ An initial alphabetic character or the underscore, followed by zero
+ or more alphanumeric characters or the underscore. This is similar
+ to your typical C/C++ identifier.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ A single character punctuation (a non-alphanumeric printable character)
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.h1">
+ <phrase id="quickbook.syntax.block.templates.formal_template_arguments"/><link
+ linkend="quickbook.syntax.block.templates.formal_template_arguments">Formal
+ Template Arguments</link>
+ </bridgehead>
+ <para>
+ Template formal arguments are identifiers consisting of an initial alphabetic
+ character or the underscore, followed by zero or more alphanumeric characters
+ or the underscore. This is similar to your typical C/C++ identifier.
+ </para>
+ <para>
+ A template formal argument temporarily hides a template of the same name
+ at the point where the <link linkend="quickbook.syntax.block.templates.template_expansion">template
+ is expanded</link>. Note that the body of the <literal>person</literal>
+ template above refers to <literal>name</literal> <literal>age</literal>
+ and <literal>what</literal> as <literal>[name]</literal> <literal>[age]</literal>
+ and <literal>[what]</literal>. <literal>name</literal> <literal>age</literal>
+ and <literal>what</literal> are actually templates that exist in the duration
+ of the template call.
+ </para>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.h2">
+ <phrase id="quickbook.syntax.block.templates.template_body"/><link linkend="quickbook.syntax.block.templates.template_body">Template
+ Body</link>
+ </bridgehead>
+ <para>
+ The template body can be just about any QuickBook block or phrase. There
+ are actually two forms. Templates may be phrase or block level. Phrase
+ templates are of the form:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[template sample[arg1 arg2...argN] replacement text... ]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Block templates are of the form:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[template sample[arg1 arg2...argN]
+replacement text...
+]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ The basic rule is as follows: if a newline immediately follows the argument
+ list, then it is a block template, otherwise, it is a phrase template.
+ Phrase templates are typically expanded as part of phrases. Like macros,
+ block level elements are not allowed in phrase templates.
+ </para>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.h3">
+ <phrase id="quickbook.syntax.block.templates.template_expansion"/><link
+ linkend="quickbook.syntax.block.templates.template_expansion">Template
+ Expansion</link>
+ </bridgehead>
+ <para>
+ You expand a template this way:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[template_identifier arg1..arg2..arg3]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ At template expansion, you supply the actual arguments. The template will
+ be expanded with your supplied arguments. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[person James Bond..39..Spy]
+[person Santa Clause..87..Big Red Fatso]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Which will expand to:
+ </para>
+ <para>
+ Hi, my name is James Bond. I am 39 years old. I am a Spy.
+ </para>
+ <para>
+ Hi, my name is Santa Clause. I am 87 years old. I am a Big Red Fatso.
+ </para>
+ <caution>
+ <para>
+ A word of caution: Templates are recursive. A template can call another
+ template or even itself, directly or indirectly. There are no control
+ structures in QuickBook (yet) so this will always mean infinite recursion.
+ QuickBook can detect this situation and report an error if recursion
+ exceeds a certain limit.
+ </para>
+ </caution>
+ <para>
+ Each actual argument can be a word, a text fragment or just about any
+ <link linkend="quickbook.syntax.phrase">QuickBook phrase</link>. Arguments
+ are separated by the double dot <literal>&quot;..&quot;</literal> and terminated
+ by the close parenthesis.
+ </para>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.h4">
+ <phrase id="quickbook.syntax.block.templates.nullary_templates"/><link
+ linkend="quickbook.syntax.block.templates.nullary_templates">Nullary Templates</link>
+ </bridgehead>
+ <para>
+ Nullary templates look and act like simple macros. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[template alpha[]&apos;&apos;&apos;&amp;#945;&apos;&apos;&apos;]
+[template beta[]&apos;&apos;&apos;&amp;#946;&apos;&apos;&apos;]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Expanding:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->Some squigles...[*[alpha][beta]]<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ We have:
+ </para>
+ <para>
+ Some squiggles...<emphasis role="bold">&#945;&#946;</emphasis>
+ </para>
+ <para>
+ The difference with macros are
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ The explicit <link linkend="quickbook.syntax.block.templates.template_expansion">template
+ expansion syntax</link>. This is an advantage because, now, we don't
+ have to use obscure naming conventions like double underscores (e.g.
+ __alpha__) to avoid unwanted macro replacement.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The template is expanded at the point where it is invoked. A macro
+ is expanded immediately at its point of declaration. This is subtle
+ and can cause a slight difference in behavior especially if you refer
+ to other macros and templates in the body.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The empty brackets after the template identifier (<literal>alpha[]</literal>)
+ indicates no arguments. If the template body does not look like a template
+ argument list, we can elide the empty brackets. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[template aristotle_quote Aristotle: [*['Education is the best provision
+for the journey to old age.]]]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Expanding:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->Here's a quote from [aristotle_quote].
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ We have:
+ </para>
+ <para>
+ Here's a quote from Aristotle: <emphasis role="bold"><emphasis>Education
+ is the best provision for the journey to old age.</emphasis></emphasis>.
+ </para>
+ <para>
+ The disadvantage is that you can't avoid the space between the template
+ identifier, <code><phrase role="identifier">aristotle_quote</phrase></code>,
+ and the template body &quot;Aristotle...&quot;. This space will be part
+ of the template body. If that space is unwanted, use empty brackets or
+ use the space escape: &quot;<code><phrase role="special">\</phrase> </code>&quot;.
+ Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[template tag\ _tag]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Then expanding:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->`struct` x[tag];
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ We have:
+ </para>
+ <para>
+ <code><phrase role="keyword">struct</phrase></code> x_tag;
+ </para>
+ <para>
+ You have a couple of ways to do it. I personally prefer the explicit empty
+ brackets, though.
+ </para>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.h5">
+ <phrase id="quickbook.syntax.block.templates.simple_arguments"/><link linkend="quickbook.syntax.block.templates.simple_arguments">Simple
+ Arguments</link>
+ </bridgehead>
+ <para>
+ As mentioned, arguments are separated by the double dot <literal>&quot;..&quot;</literal>.
+ If there are less arguments passed than expected, QuickBook attempts to
+ break the last argument into two or more arguments following this logic:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Break the last argument into two, at the first space found (<literal>'',
+ '\n', \t' or '\r'</literal>).
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Repeat until there are enough arguments or if there are no more spaces
+ found (in which case, an error is reported).
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ For example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[template simple[a b c d] [a][b][c][d]]
+[simple w x y z]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will produce:
+ </para>
+ <para>
+ wxyz
+ </para>
+ <para>
+ &quot;w x y z&quot; is initially treated as a single argument because we
+ didn't supply any <literal>&quot;..&quot;</literal> separators. However,
+ since <literal>simple</literal> expects 4 arguments, &quot;w x y z&quot;
+ is broken down iteratively (applying the logic above) until we have &quot;w&quot;,
+ &quot;x&quot;, &quot;y&quot; and &quot;z&quot;.
+ </para>
+ <para>
+ QuickBook only tries to get the arguments it needs. For example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[simple w x y z trail]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will produce:
+ </para>
+ <para>
+ wxyz trail
+ </para>
+ <para>
+ The arguments being: &quot;w&quot;, &quot;x&quot;, &quot;y&quot; and &quot;z
+ trail&quot;.
+ </para>
+ <para>
+ It should be obvious now that for simple arguments with no spaces, we can
+ get by without separating the arguments with <literal>&quot;..&quot;</literal>
+ separators. It is possible to combine <literal>&quot;..&quot;</literal>
+ separators with the argument passing simplification presented above. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[simple what do you think ..m a n?]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will produce:
+ </para>
+ <para>
+ what do you think man?
+ </para>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.templates.h6">
+ <phrase id="quickbook.syntax.block.templates.punctuation_templates"/><link
+ linkend="quickbook.syntax.block.templates.punctuation_templates">Punctuation
+ Templates</link>
+ </bridgehead>
+ <para>
+ With templates, one of our objectives is to allow us to rewrite QuickBook
+ in QuickBook (as a qbk library). For that to happen, we need to accommodate
+ single character punctuation templates which are fairly common in QuickBook.
+ You might have noticed that single character punctuations are allowed as
+ <link linkend="quickbook.syntax.block.templates.template_identifier">template
+ identifiers</link>. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[template ![bar] <!--quickbook-escape-postfix-->&lt;hey&gt;<!--quickbook-escape-prefix-->[bar]<!--quickbook-escape-postfix-->&lt;/hey&gt;<!--quickbook-escape-prefix-->]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ Now, expanding this:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[!baz]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ We will have:
+ </para>
+<programlisting>&lt;hey&gt;baz&lt;/hey&gt;
+</programlisting>
+ </section>
+ <section id="quickbook.syntax.block.blurbs">
+ <title><link linkend="quickbook.syntax.block.blurbs">Blurbs</link></title>
+<programlisting><!--quickbook-escape-prefix-->[blurb :-) [*An eye catching advertisement or note...]
+
+ __spirit__ is an object-oriented recursive-descent parser generator framework
+ implemented using template meta-programming techniques. Expression templates
+ allow us to approximate the syntax of Extended Backus-Normal Form (EBNF)
+ completely in C++.
+]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate this:
+ </para>
+ <sidebar role="blurb">
+ <para>
+ <inlinemediaobject><imageobject><imagedata fileref="images/smiley.png"></imagedata></imageobject>
+ <textobject>
+ <phrase>smiley</phrase>
+ </textobject>
+ </inlinemediaobject> <emphasis role="bold">An eye catching advertisement
+ or note...</emphasis>
+ </para>
+ <para>
+ <ulink url="http://spirit.sourceforge.net">Spirit</ulink> is an object-oriented
+ recursive-descent parser generator framework implemented using template
+ meta-programming techniques. Expression templates allow us to approximate
+ the syntax of Extended Backus-Normal Form (EBNF) completely in C++.
+ </para>
+ </sidebar>
+ <note>
+ <para>
+ Prefer <link linkend="quickbook.syntax.block.admonitions">admonitions</link>
+ wherever appropriate.
+ </para>
+ </note>
+ </section>
+ <section id="quickbook.syntax.block.tables">
+ <title><link linkend="quickbook.syntax.block.tables">Tables</link></title>
+<programlisting><!--quickbook-escape-prefix-->[table A Simple Table
+ [[Heading 1] [Heading 2] [Heading 3]]
+ [[R0-C0] [R0-C1] [R0-C2]]
+ [[R1-C0] [R1-C1] [R1-C2]]
+ [[R2-C0] [R2-C1] [R2-C2]]
+]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <table frame="all" id="quickbook.syntax.block.tables.t0">
+ <title>A Simple Table</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading 1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Heading 2
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Heading 3
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ R0-C0
+ </para>
+ </entry>
+ <entry>
+ <para>
+ R0-C1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ R0-C2
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ R2-C0
+ </para>
+ </entry>
+ <entry>
+ <para>
+ R2-C1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ R2-C2
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ R3-C0
+ </para>
+ </entry>
+ <entry>
+ <para>
+ R3-C1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ R3-C2
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ The table title is optional. The first row of the table is automatically
+ treated as the table header; that is, it is wrapped in <literal>&lt;thead&gt;...&lt;/thead&gt;</literal>
+ XML tags. Note that unlike the original QuickDoc, the columns are nested
+ in [ cells... ]. The syntax is free-format and allows big cells to be formatted
+ nicely. Example:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[table Table with fat cells
+ [[Heading 1] [Heading 2]]
+ [
+ [Row 0, Col 0: a small cell]
+ [
+ Row 0, Col 1: a big fat cell with paragraphs
+
+ Boost provides free peer-reviewed portable C++ source libraries.
+
+ We emphasize libraries that work well with the C++ Standard Library.
+ Boost libraries are intended to be widely useful, and usable across
+ a broad spectrum of applications. The Boost license encourages both
+ commercial and non-commercial use.
+ ]
+ ]
+ [
+ [Row 1, Col 0: a small cell]
+ [Row 1, Col 1: a small cell]
+ ]
+]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ and thus:
+ </para>
+ <table frame="all" id="quickbook.syntax.block.tables.t1">
+ <title>Table with fat cells</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading 1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Heading 2
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ Row 0, Col 0: a small cell
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Row 0, Col 1: a big fat cell with paragraphs
+ </para>
+ <para>
+ Boost provides free peer-reviewed portable C++ source libraries.
+ </para>
+ <para>
+ We emphasize libraries that work well with the C++ Standard Library.
+ Boost libraries are intended to be widely useful, and usable
+ across a broad spectrum of applications. The Boost license encourages
+ both commercial and non-commercial use.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Row 1, Col 0: a small cell
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Row 1, Col 1: a small cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ Here's how to have preformatted blocks of code in a table cell:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[table Table with code
+ [[Comment] [Code]]
+ [
+ [My first program]
+ [<!--quickbook-escape-postfix-->``
+ #include &lt;iostream&gt;
+
+ int main()
+ {
+ std::cout &lt;&lt; &quot;Hello, World!&quot; &lt;&lt; std::endl;
+ return 0;
+ }
+ ``<!--quickbook-escape-prefix-->]
+ ]
+]
+<!--quickbook-escape-postfix--></programlisting>
+ <table frame="all" id="quickbook.syntax.block.tables.t2">
+ <title>Table with code</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Comment
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Code
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ My first program
+ </para>
+ </entry>
+ <entry>
+ <para>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">iostream</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;Hello, World!&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="quickbook.syntax.block.variable_lists">
+ <title><link linkend="quickbook.syntax.block.variable_lists">Variable Lists</link></title>
+<programlisting><!--quickbook-escape-prefix-->[variablelist A Variable List
+ [[term 1] [The definition of term 1]]
+ [[term 2] [The definition of term 2]]
+ [[term 3] [The definition of term 3]]
+]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ will generate:
+ </para>
+ <variablelist>
+ <title>A Variable List</title>
+ <varlistentry>
+ <term>term 1</term>
+ <listitem>
+ <para>
+ The definition of term 1
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>term 2</term>
+ <listitem>
+ <para>
+ The definition of term 2
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>term 3</term>
+ <listitem>
+ <para>
+ The definition of term 3
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <para>
+ The rules for variable lists are the same as for tables, except that only
+ 2 &quot;columns&quot; are allowed. The first column contains the terms,
+ and the second column contains the definitions. Those familiar with HTML
+ will recognize this as a &quot;definition list&quot;.
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.include">
+ <title><link linkend="quickbook.syntax.block.include">Include</link></title>
+ <para>
+ You can include one QuickBook file from another. The syntax is simply:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[include someother.qbk]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ The included file will be processed as if it had been cut and pasted into
+ the current document, with the following exceptions:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ The __FILENAME__ predefined macro will reflect the name of the file currently being
+ processed.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Any macros defined in the included file are scoped to that file.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The <literal>[include]</literal> directive lets you specify a document
+ id to use for the included file. When this id is not explicitly specified,
+ the id defaults to the filename (&quot;someother&quot;, in the example
+ above). You can specify the id like this:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[include:someid someother.qbk]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ All auto-generated anchors will use the document id as a unique prefix.
+ So for instance, if there is a top section in someother.qbk named &quot;Intro&quot;,
+ the named anchor for that section will be &quot;someid.intro&quot;, and
+ you can link to it with <literal>[link someid.intro The Intro]</literal>.
+ </para>
+ </section>
+ <section id="quickbook.syntax.block.import">
+ <title><link linkend="quickbook.syntax.block.import">Import</link></title>
+ <para>
+ When documenting code, you'd surely need to present code from actual source
+ files. While it is possible to copy some code and paste them in your QuickBook
+ file, doing so is error prone and the extracted code in the documentation
+ tends to get out of sync with the actual code as the code evolves. The
+ problem, as always, is that once documentation is written, the tendency
+ is for the docs to languish in the archives without maintenance.
+ </para>
+ <para>
+ QuickBook's import facility provides a nice solution.
+ </para>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.import.h0">
+ <phrase id="quickbook.syntax.block.import.example"/><link linkend="quickbook.syntax.block.import.example">Example</link>
+ </bridgehead>
+ <para>
+ You can effortlessly import code snippets from source code into your QuickBook.
+ The following illustrates how this is done:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[import ../test/stub.cpp]
+[foo]
+[bar]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ The first line:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[import ../test/stub.cpp]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ collects specially marked-up code snippets from <ulink url="../../test/stub.cpp">stub.cpp</ulink>
+ and places them in your QuickBook file as virtual templates. Each of the
+ specially marked-up code snippets has a name (e.g. <code><phrase role="identifier">foo</phrase></code>
+ and <code><phrase role="identifier">bar</phrase></code> in the example
+ above). This shall be the template identifier for that particular code
+ snippet. The second and third line above does the actual template expansion:
+ </para>
+<programlisting><!--quickbook-escape-prefix-->[foo]
+[bar]
+<!--quickbook-escape-postfix--></programlisting>
+ <para>
+ And the result is:
+ </para>
+ <para>
+ This is the <emphasis role="bold"><emphasis>foo</emphasis></emphasis> function.
+ </para>
+ <para>
+ This description can have paragraphs...
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ lists
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ etc.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ And any quickbook block markup.
+ </para>
+ <para>
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">foo</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">// return 'em, foo man!</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="string">&quot;foo&quot;</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <para>
+ This is the <emphasis role="bold"><emphasis>bar</emphasis></emphasis> function
+ </para>
+ <para>
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">bar</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="comment">// return 'em, bar man!</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="string">&quot;bar&quot;</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <para>
+ Some trailing text here
+ </para>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.import.h1">
+ <phrase id="quickbook.syntax.block.import.code_snippet_markup"/><link linkend="quickbook.syntax.block.import.code_snippet_markup">Code
+ Snippet Markup</link>
+ </bridgehead>
+ <para>
+ Note how the code snippets in <ulink url="../../test/stub.cpp">stub.cpp</ulink>
+ get marked up. We use distinguishable comments following the form:
+ </para>
+<programlisting><phrase role="comment">//[id</phrase>
+<phrase role="identifier">some</phrase> <phrase role="identifier">code</phrase> <phrase role="identifier">here</phrase>
+<phrase role="comment">//]</phrase>
+</programlisting>
+ <para>
+ The first comment line above initiates a named code-snippet. This prefix
+ will not be visible in quickbook. The entire code-snippet in between <code><phrase
+ role="comment">//[id</phrase></code> and <code><phrase role="comment">//]</phrase></code>
+ will be inserted as a template in quickbook with name <emphasis><emphasis>id</emphasis></emphasis>.
+ The comment <code><phrase role="comment">//]</phrase></code> ends a code-snippet
+ This too will not be visible in quickbook.
+ </para>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.import.h2">
+ <phrase id="quickbook.syntax.block.import.special_comments"/><link linkend="quickbook.syntax.block.import.special_comments">Special
+ Comments</link>
+ </bridgehead>
+ <para>
+ Special comments of the form:
+ </para>
+<programlisting><phrase role="comment">//` some [*quickbook] markup here</phrase>
+</programlisting>
+ <para>
+ and:
+ </para>
+<programlisting><phrase role="comment">/*` some [*quickbook] markup here */</phrase>
+</programlisting>
+ <para>
+ will be parsed by QuickBook. This can contain quickbook <emphasis>blocks</emphasis>
+ (e.g. sections, paragraphs, tables, etc). In the first case, the initial
+ slash-slash, tick and white-space shall be ignored. In the second, the
+ initial slash-star-tick and the final star-slash shall be ignored.
+ </para>
+ <bridgehead renderas="sect5" id="quickbook.syntax.block.import.h3">
+ <phrase id="quickbook.syntax.block.import.callouts"/><link linkend="quickbook.syntax.block.import.callouts">Callouts</link>
+ </bridgehead>
+ <para>
+ Special comments of the form:
+ </para>
+<programlisting><phrase role="comment">/*&lt; some [*quickbook] markup here &gt;*/</phrase>
+</programlisting>
+ <para>
+ will be regarded as callouts. These will be collected, numbered and rendered
+ as a &quot;callout bug&quot; (a small icon with a number). After the whole
+ snippet is parsed, the callout list is generated. See <ulink url="http://www.docbook.org/tdg/en/html/callout.html">Callouts</ulink>
+ for details. Example:
+ </para>
+ <para>
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">foo_bar</phrase><phrase role="special">()</phrase> <co id="quickbook.syntax.block.import.c0" linkends="quickbook.syntax.block.import.c1" />
+<phrase role="special">{</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="string">&quot;foo-bar&quot;</phrase><phrase role="special">;</phrase> <co id="quickbook.syntax.block.import.c2" linkends="quickbook.syntax.block.import.c3" />
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="quickbook.syntax.block.import.c0" id="quickbook.syntax.block.import.c1">
+ <para>
+ The <emphasis>Mythical</emphasis> FooBar. See <ulink url="http://en.wikipedia.org/wiki/Foobar">Foobar
+ for details</ulink>
+ </para>
+ </callout>
+ <callout arearefs="quickbook.syntax.block.import.c2" id="quickbook.syntax.block.import.c3">
+ <para>
+ return 'em, foo-bar man!
+ </para>
+ </callout>
+ </calloutlist>
+ <para>
+ Checkout <ulink url="../../test/stub.cpp">stub.cpp</ulink> to see the actual
+ code.
+ </para>
+ </section>
+ </section>
+ </section>
+ <section id="quickbook.install">
+ <title><link linkend="quickbook.install">Installation and configuration</link></title>
+ <para>
+ This section provides some guidelines on how to install and configure BoostBook
+ and Quickbook under several operating systems.
+ </para>
+ <para>
+ Before continuing, it is very important that you keep this in mind: if you
+ try to build some documents and the process breaks due to misconfiguration,
+ be absolutely sure to delete any <code><phrase role="identifier">bin</phrase></code>
+ and <code><phrase role="identifier">bin</phrase><phrase role="special">.</phrase><phrase
+ role="identifier">v2</phrase></code> directories generated by the build before
+ trying again. Otherwise your configuration fixes will not take any effect.
+ </para>
+ <section id="quickbook.install.windows">
+ <title><link linkend="quickbook.install.windows">Windows 2000, XP, 2003, Vista</link></title>
+ <blockquote>
+ <para>
+ <emphasis>Section contributed by Julio M. Merino Vidal</emphasis>
+ </para>
+ </blockquote>
+ <para>
+ The following instructions apply to any Windows system based on Windows 2000,
+ including Windows XP, Windows 2003 Server and Windows Vista. The paths shown
+ below are taken from a Windows Vista machine; you will need to adjust them
+ to match your system in case you are running an older version.
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ First of all you need to have a copy of <code><phrase role="identifier">xsltproc</phrase></code>
+ for Windows. There are many ways to get this tool, but to keep things
+ simple, use the <ulink url="http://www.zlatkovic.com/pub/libxml/">binary
+ packages</ulink> made by Igor Zlatkovic. At the very least, you need
+ to download the following packages: <code><phrase role="identifier">iconv</phrase></code>,
+ <code><phrase role="identifier">zlib</phrase></code>, <code><phrase role="identifier">libxml2</phrase></code>
+ and <code><phrase role="identifier">libxslt</phrase></code>.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Unpack all these packages in the same directory so that you get unique
+ <code><phrase role="identifier">bin</phrase></code>, <code><phrase role="identifier">include</phrase></code>
+ and <code><phrase role="identifier">lib</phrase></code> directories within
+ the hierarchy. These instructions use <code><phrase role="identifier">C</phrase><phrase
+ role="special">:\</phrase><phrase role="identifier">Users</phrase><phrase
+ role="special">\</phrase><phrase role="identifier">example</phrase><phrase
+ role="special">\</phrase><phrase role="identifier">Documents</phrase><phrase
+ role="special">\</phrase><phrase role="identifier">boost</phrase><phrase
+ role="special">\</phrase><phrase role="identifier">xml</phrase></code>
+ as the root for all files.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ From the command line, go to the <code><phrase role="identifier">bin</phrase></code>
+ directory and launch <code><phrase role="identifier">xsltproc</phrase><phrase
+ role="special">.</phrase><phrase role="identifier">exe</phrase></code>
+ to ensure it works. You should get usage information on screen.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Download <ulink url="http://www.docbook.org/xml/4.2/docbook-xml-4.2.zip">Docbook
+ XML 4.2</ulink> and unpack it in the same directory used above. That
+ is: <code><phrase role="identifier">C</phrase><phrase role="special">:\</phrase><phrase
+ role="identifier">Users</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">example</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">Documents</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">boost</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">xml</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">docbook</phrase><phrase role="special">-</phrase><phrase
+ role="identifier">xml</phrase></code>.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Download the latest <ulink url="http://sourceforge.net/project/showfiles.php?group_id=21935&amp;package_id=16608">Docbook
+ XSL</ulink> version and unpack it, again in the same directory used before.
+ To make things easier, rename the directory created during the extraction
+ to <code><phrase role="identifier">docbook</phrase><phrase role="special">-</phrase><phrase
+ role="identifier">xsl</phrase></code> (bypassing the version name):
+ <code><phrase role="identifier">C</phrase><phrase role="special">:\</phrase><phrase
+ role="identifier">Users</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">example</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">Documents</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">boost</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">xml</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">docbook</phrase><phrase role="special">-</phrase><phrase
+ role="identifier">xsl</phrase></code>.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Add the following to your <code><phrase role="identifier">user</phrase><phrase
+ role="special">-</phrase><phrase role="identifier">config</phrase><phrase
+ role="special">.</phrase><phrase role="identifier">jam</phrase></code>
+ file, which should live in your home directory (<code><phrase role="special">%</phrase><phrase
+ role="identifier">HOMEDRIVE</phrase><phrase role="special">%%</phrase><phrase
+ role="identifier">HOMEPATH</phrase><phrase role="special">%</phrase></code>).
+ You must already have it somewhere or otherwise you could not be building
+ Boost (i.e. missing tools configuration).
+ </simpara>
+ </listitem>
+ </orderedlist>
+<programlisting><phrase role="identifier">using</phrase> <phrase role="identifier">xsltproc</phrase>
+ <phrase role="special">:</phrase> <phrase role="string">&quot;C:/Users/example/Documents/boost/xml/bin/xsltproc.exe&quot;</phrase>
+ <phrase role="special">;</phrase>
+
+<phrase role="identifier">using</phrase> <phrase role="identifier">boostbook</phrase>
+ <phrase role="special">:</phrase> <phrase role="string">&quot;C:/Users/example/Documents/boost/xml/docbook-xsl&quot;</phrase>
+ <phrase role="special">:</phrase> <phrase role="string">&quot;C:/Users/example/Documents/boost/xml/docbook-xml&quot;</phrase>
+ <phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ The above steps are enough to get a functional BoostBook setup. Quickbook
+ will be automatically built when needed. If you want to avoid these rebuilds:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Go to Quickbook's source directory (<code><phrase role="identifier">BOOST_ROOT</phrase><phrase
+ role="special">\</phrase><phrase role="identifier">tools</phrase><phrase
+ role="special">\</phrase><phrase role="identifier">quickbook</phrase></code>).
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Build the utility by issuing <code><phrase role="identifier">bjam</phrase>
+ <phrase role="special">--</phrase><phrase role="identifier">v2</phrase></code>.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Copy the resulting <code><phrase role="identifier">quickbook</phrase><phrase
+ role="special">.</phrase><phrase role="identifier">exe</phrase></code>
+ binary (located under the <code><phrase role="identifier">BOOST_ROOT</phrase><phrase
+ role="special">\</phrase><phrase role="identifier">bin</phrase><phrase
+ role="special">.</phrase><phrase role="identifier">v2</phrase></code>
+ hierarchy) to a safe place. Following our previous example, you can install
+ it into: <code><phrase role="identifier">C</phrase><phrase role="special">:\</phrase><phrase
+ role="identifier">Users</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">example</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">Documents</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">boost</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">xml</phrase><phrase role="special">\</phrase><phrase
+ role="identifier">bin</phrase></code>.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Add the following to your <code><phrase role="identifier">user</phrase><phrase
+ role="special">-</phrase><phrase role="identifier">config</phrase><phrase
+ role="special">.</phrase><phrase role="identifier">jam</phrase></code>
+ file:
+ </simpara>
+ </listitem>
+ </orderedlist>
+<programlisting><phrase role="identifier">using</phrase> <phrase role="identifier">quickbook</phrase>
+ <phrase role="special">:</phrase> <phrase role="string">&quot;C:/Users/example/Documents/boost/xml/bin/quickbook.exe&quot;</phrase>
+ <phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ <section id="quickbook.install.linux">
+ <title><link linkend="quickbook.install.linux">Debian, Ubuntu</link></title>
+ <para>
+ The following instructions apply to Debian and its derivatives. They are
+ based on a Ubuntu Edgy install but should work on other Debian based systems.
+ </para>
+ <para>
+ First install the <code><phrase role="identifier">bjam</phrase></code>,
+ <code><phrase role="identifier">xsltproc</phrase></code>, <code><phrase role="identifier">docbook</phrase><phrase
+ role="special">-</phrase><phrase role="identifier">xsl</phrase></code> and
+ <code><phrase role="identifier">docbook</phrase><phrase role="special">-</phrase><phrase
+ role="identifier">xml</phrase></code> packages. For example, using <code><phrase
+ role="identifier">apt</phrase><phrase role="special">-</phrase><phrase role="identifier">get</phrase></code>:
+ </para>
+<programlisting><phrase role="identifier">sudo</phrase> <phrase role="identifier">apt</phrase><phrase role="special">-</phrase><phrase role="identifier">get</phrase> <phrase role="identifier">install</phrase> <phrase role="identifier">xsltprc</phrase> <phrase role="identifier">docbook</phrase><phrase role="special">-</phrase><phrase role="identifier">xsl</phrase> <phrase role="identifier">docbook</phrase><phrase role="special">-</phrase><phrase role="identifier">xml</phrase>
+</programlisting>
+ <para>
+ If you're planning on building boost's documentation, you'll also need to
+ install the <code><phrase role="identifier">doxygen</phrase></code> package
+ as well.
+ </para>
+ <para>
+ Next, we need to configure Boost Build to compile BoostBook files. Add the
+ following to your <code><phrase role="identifier">user</phrase><phrase role="special">-</phrase><phrase
+ role="identifier">config</phrase><phrase role="special">.</phrase><phrase
+ role="identifier">jam</phrase></code> file, which should be in your home
+ directory. If you don't have one, create a file containing this text. For
+ more information on setting up <code><phrase role="identifier">user</phrase><phrase
+ role="special">-</phrase><phrase role="identifier">config</phrase><phrase
+ role="special">.</phrase><phrase role="identifier">jam</phrase></code>, see
+ the <ulink url="http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html">Boost
+ Build documentation</ulink>.
+ </para>
+<programlisting><phrase role="identifier">using</phrase> <phrase role="identifier">xsltproc</phrase> <phrase role="special">;</phrase>
+
+<phrase role="identifier">using</phrase> <phrase role="identifier">boostbook</phrase>
+ <phrase role="special">:</phrase> <phrase role="special">/</phrase><phrase role="identifier">usr</phrase><phrase role="special">/</phrase><phrase role="identifier">share</phrase><phrase role="special">/</phrase><phrase role="identifier">xml</phrase><phrase role="special">/</phrase><phrase role="identifier">docbook</phrase><phrase role="special">/</phrase><phrase role="identifier">stylesheet</phrase><phrase role="special">/</phrase><phrase role="identifier">nwalsh</phrase>
+ <phrase role="special">:</phrase> <phrase role="special">/</phrase><phrase role="identifier">usr</phrase><phrase role="special">/</phrase><phrase role="identifier">share</phrase><phrase role="special">/</phrase><phrase role="identifier">xml</phrase><phrase role="special">/</phrase><phrase role="identifier">docbook</phrase><phrase role="special">/</phrase><phrase role="identifier">schema</phrase><phrase role="special">/</phrase><phrase role="identifier">dtd</phrase><phrase role="special">/</phrase><phrase role="number">4.2</phrase>
+ <phrase role="special">;</phrase>
+
+<phrase role="comment"># Remove this line if you're not using doxygen</phrase>
+<phrase role="identifier">using</phrase> <phrase role="identifier">doxygen</phrase> <phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ The above steps are enough to get a functional BoostBook setup. Quickbook
+ will be automatically built when needed. If you want to avoid these rebuilds:
+ </para>
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Go to Quickbook's source directory (<code><phrase role="identifier">BOOST_ROOT</phrase><phrase
+ role="special">/</phrase><phrase role="identifier">tools</phrase><phrase
+ role="special">/</phrase><phrase role="identifier">quickbook</phrase></code>).
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Build the utility by issuing <code><phrase role="identifier">bjam</phrase>
+ <phrase role="special">--</phrase><phrase role="identifier">v2</phrase></code>.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Copy the resulting <code><phrase role="identifier">quickbook</phrase></code>
+ binary (located under the <code><phrase role="identifier">BOOST_ROOT</phrase><phrase
+ role="special">/</phrase><phrase role="identifier">bin</phrase><phrase
+ role="special">.</phrase><phrase role="identifier">v2</phrase></code>
+ hierarchy) to a safe place. The traditional location is <code><phrase
+ role="special">/</phrase><phrase role="identifier">usr</phrase><phrase
+ role="special">/</phrase><phrase role="identifier">local</phrase><phrase
+ role="special">/</phrase><phrase role="identifier">bin</phrase></code>.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Add the following to your <code><phrase role="identifier">user</phrase><phrase
+ role="special">-</phrase><phrase role="identifier">config</phrase><phrase
+ role="special">.</phrase><phrase role="identifier">jam</phrase></code>
+ file, using the full path of the quickbook executable:
+ </simpara>
+ </listitem>
+ </orderedlist>
+<programlisting><phrase role="identifier">using</phrase> <phrase role="identifier">quickbook</phrase>
+ <phrase role="special">:</phrase> <phrase role="special">/</phrase><phrase role="identifier">usr</phrase><phrase role="special">/</phrase><phrase role="identifier">local</phrase><phrase role="special">/</phrase><phrase role="identifier">bin</phrase><phrase role="special">/</phrase><phrase role="identifier">quickbook</phrase>
+ <phrase role="special">;</phrase>
+</programlisting>
+ </section>
+ </section>
+ <section id="quickbook.editors">
+ <title><link linkend="quickbook.editors">Editor Support</link></title>
+ <para>
+ Editing quickbook files is usually done with text editors both simple and powerful.
+ The following sections list the settings for some editors which can help make
+ editing quickbook files a bit easier.
+ </para>
+ <sidebar role="blurb">
+ <para>
+ <inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject>
+ <textobject>
+ <phrase>note</phrase>
+ </textobject>
+ </inlinemediaobject> You may submit your settings, tips, and suggestions to
+ the authors, or through the <ulink url="https://lists.sourceforge.net/lists/listinfo/boost-">docs
+ Boost Docs mailing list</ulink>.
+ </para>
+ </sidebar>
+ <section id="quickbook.editors.scite">
+ <title><link linkend="quickbook.editors.scite">Scintilla Text Editor</link></title>
+ <blockquote>
+ <para>
+ <emphasis>Section contributed by Dean Michael Berris</emphasis>
+ </para>
+ </blockquote>
+ <para>
+ The Scintilla Text Editor (SciTE) is a free source code editor for Win32
+ and X. It uses the SCIntilla source code editing component.
+ </para>
+ <sidebar role="blurb">
+ <para>
+ <inlinemediaobject><imageobject><imagedata fileref="images/tip.png"></imagedata></imageobject>
+ <textobject>
+ <phrase>tip</phrase>
+ </textobject>
+ </inlinemediaobject> SciTE can be downloaded from <ulink url="http://www.scintilla.org/SciTE.html">http://www.scintilla.org/SciTE.html</ulink>
+ </para>
+ </sidebar>
+ <para>
+ You can use the following settings to highlight quickbook tags when editing
+ quickbook files.
+ </para>
+<programlisting><!--quickbook-escape-prefix-->qbk=*.qbk
+lexer.*.qbk=props
+use.tabs.$(qbk)=0
+tab.size.$(qbk)=4
+indent.size.$(qbk)=4
+style.props.32=$(font.base)
+comment.stream.start.props=[/
+comment.stream.end.props=]
+comment.box.start.props=[/
+comment.box.middle.props=
+comment.box.end.props=]
+<!--quickbook-escape-postfix--></programlisting>
+ <sidebar role="blurb">
+ <para>
+ <inlinemediaobject><imageobject><imagedata fileref="images/note.png"></imagedata></imageobject>
+ <textobject>
+ <phrase>note</phrase>
+ </textobject>
+ </inlinemediaobject> Thanks to Rene Rivera for the above SciTE settings.
+ </para>
+ </sidebar>
+ </section>
+ </section>
+ <section id="quickbook.faq">
+ <title><link linkend="quickbook.faq">Frequently Asked Questions</link></title>
+ <bridgehead renderas="sect3" id="quickbook.faq.h0">
+ <phrase id="quickbook.faq.can_i_use_quickbook_for_non_boost_documentation_"/><link
+ linkend="quickbook.faq.can_i_use_quickbook_for_non_boost_documentation_">Can
+ I use QuickBook for non-Boost documentation?</link>
+ </bridgehead>
+ <para>
+ QuickBook can be used for non-Boost documentation with a little extra work.
+ </para>
+ <blockquote>
+ <para>
+ <emphasis>Faq contributed by Michael Marcin</emphasis>
+ </para>
+ </blockquote>
+ <para>
+ When building HTML documentation with BoostBook a Boost C++ Libraries header
+ is added to the files. When using QuickBook to document projects outside of
+ Boost this is not desirable. This behavior can be overridden at the BoostBook
+ level by specifying some XSLT options. When using Boost Build version 2 (BBv2)
+ this can be achieved by adding parameters to the BoostBook target declaration.
+ </para>
+ <para>
+ For example:
+ </para>
+<programlisting>using quickbook ;
+
+xml my_doc : my_doc.qbk ;
+
+boostbook standalone
+ :
+ my_doc
+ :
+ &lt;xsl:param&gt;boost.image.src=images/my_project_logo.png
+ &lt;xsl:param&gt;boost.image.alt=&quot;\&quot;My Project\&quot;&quot;
+ &lt;xsl:param&gt;boost.image.w=100
+ &lt;xsl:param&gt;boost.image.h=50
+ &lt;xsl:param&gt;nav.layout=none
+ ;
+</programlisting>
+ </section>
+ <section id="quickbook.ref">
+ <title><link linkend="quickbook.ref">Quick Reference</link></title>
+ <para>
+ [cpp]
+ </para>
+ <table frame="all" id="quickbook.ref.t0">
+ <title>Syntax Compendium</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ To do this...
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Use this...
+ </para>
+ </entry>
+ <entry>
+ <para>
+ See this...
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ comment
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[/ some comment]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.comments">Comments</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <emphasis>italics</emphasis>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>['italics] or /italics/</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.font_styles">Font Styles</link>
+ and <link linkend="quickbook.syntax.phrase.simple_formatting">Simple
+ formatting</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <emphasis role="bold">bold</emphasis>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[*bold] or *bold*</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.font_styles">Font Styles</link>
+ and <link linkend="quickbook.syntax.phrase.simple_formatting">Simple
+ formatting</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <emphasis role="underline">underline</emphasis>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[_underline] or _underline_</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.font_styles">Font Styles</link>
+ and <link linkend="quickbook.syntax.phrase.simple_formatting">Simple
+ formatting</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <literal>teletype</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[^teletype] or =teletype=</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.font_styles">Font Styles</link>
+ and <link linkend="quickbook.syntax.phrase.simple_formatting">Simple
+ formatting</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <emphasis role="strikethrough">strikethrough</emphasis>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[-strikethrough]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.font_styles">Font Styles</link>
+ and <link linkend="quickbook.syntax.phrase.simple_formatting">Simple
+ formatting</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ <replaceable>replaceable</replaceable>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[~replaceable]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.replaceable">Replaceble</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ source mode
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[c++]</literal> or <literal>[python]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.source_mode">Source Mode</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ inline code
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>`int main();`</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.inline_code">Inline code</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ code block
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>``int main();``</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.code">Code</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ code escape
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>``from c++ to QuickBook``</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.escape_back">Escaping Back
+ To QuickBook</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ line break
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[br] or \n</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.line_break">line-break</link>
+ <emphasis role="bold">DEPRECATED</emphasis>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ anchor
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[#anchor]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.anchors">Anchors</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ link
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[@http://www.boost.org Boost]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.links">Links</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ anchor link
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[link section.anchor Link text]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.anchor_links">Anchor links</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ refentry link
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[link xml.refentry Link text]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.refentry_links">refentry links</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ function link
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[funcref fully::qualified::function_name Link text]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.code_links">function, class,
+ member, enum, macro, concept or header links</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ class link
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[classref fully::qualified::class_name Link text]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.code_links">function, class,
+ member, enum, macro, concept or header links</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ member link
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[memberref fully::qualified::member_name Link text]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.code_links">function, class,
+ member, enum, macro, concept or header links</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ enum link
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[enumref fully::qualified::enum_name Link text]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.code_links">function, class,
+ member, enum, macro, concept or header links</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ macro link
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[macroref MACRO_NAME Link text]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.code_links">function, class,
+ member, enum, macro, concept or header links</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ concept link
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[conceptref ConceptName Link text]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.code_links">function, class,
+ member, enum, macro, concept or header links</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ header link
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[headerref path/to/header.hpp Link text]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.code_links">function, class,
+ member, enum, macro, concept or header links</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ escape
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>'''escaped text (no processing/formatting)'''</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.escape">Escape</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ single char escape
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>\c</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.single_char_escape">Single
+ char escape</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ images
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[$image.jpg]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.phrase.images">Images</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ begin section
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[section The Section Title]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.section">Section</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ end section
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[endsect]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.section">Section</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ paragraph
+ </para>
+ </entry>
+ <entry>
+ <para>
+ No markup. Paragraphs start left-flushed and are terminated by two
+ or more newlines.
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.paragraphs">Paragraphs</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ ordered list
+ </para>
+ </entry>
+ <entry>
+<programlisting><!--quickbook-escape-prefix--># one
+# two
+# three
+<!--quickbook-escape-postfix--></programlisting>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.lists.ordered_lists">Ordered
+ lists</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ unordered list
+ </para>
+ </entry>
+ <entry>
+<programlisting><!--quickbook-escape-prefix-->* one
+* two
+* three
+<!--quickbook-escape-postfix--></programlisting>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.lists.unordered_lists">Unordered
+ lists</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ code
+ </para>
+ </entry>
+ <entry>
+ <para>
+ No markup. Preformatted code starts with a space or a tab.
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.code">Code</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ preformatted
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[pre preformatted]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.preformatted">Preformatted</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ block quote
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[:sometext...]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.blockquote">Blockquote</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ heading 1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[h1 Heading 1]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.headings">Heading</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ heading 2
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[h2 Heading 2]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.headings">Heading</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ heading 3
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[h3 Heading 3]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.headings">Heading</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ heading 4
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[h4 Heading 4]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.headings">Heading</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ heading 5
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[h5 Heading 5]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.headings">Heading</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ heading 6
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[h6 Heading 6]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.headings">Heading</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ macro
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[def macro_identifier some text]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.macros">Macros</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ template
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[template[a b] [a] body [b]]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.templates">Templates</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ blurb
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[blurb advertisement or note...]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.blurbs">Blurbs</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ admonition
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[warning Warning text...]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.admonitions">Admonitions</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ table
+ </para>
+ </entry>
+ <entry>
+<programlisting><!--quickbook-escape-prefix-->[table Title
+[[a][b][c]]
+[[a][b][c]]
+]
+<!--quickbook-escape-postfix--></programlisting>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.tables">Tables</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ variablelist
+ </para>
+ </entry>
+ <entry>
+<programlisting><!--quickbook-escape-prefix-->[variablelist Title
+[[a][b]]
+[[a][b]]
+]
+<!--quickbook-escape-postfix--></programlisting>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.variable_lists">Variable Lists</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ include
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <literal>[include someother.qbk]</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>
+ <link linkend="quickbook.syntax.block.include">Include</link>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+</article>
diff --git a/tools/quickbook/test/quickbook_manual-1_4.quickbook b/tools/quickbook/test/quickbook_manual-1_4.quickbook
new file mode 100644
index 0000000000..00fc9caa15
--- /dev/null
+++ b/tools/quickbook/test/quickbook_manual-1_4.quickbook
@@ -0,0 +1,1981 @@
+[article Quickbook
+ [quickbook 1.4]
+ [version 1.4]
+ [authors [de Guzman, Joel], [Niebler, Eric]]
+ [copyright 2002 2004 2006 Joel de Guzman, Eric Niebler]
+ [purpose /WikiWiki/ style documentation tool]
+ [license
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ [@http://www.boost.org/LICENSE_1_0.txt])
+ ]
+]
+
+[/ QuickBook Document version 1.3 ]
+[/ Sept 24, 2002 ]
+[/ Sept 2, 2004 ]
+[/ Feb 14, 2005 ]
+[/ Sept 13, 2005 ]
+
+[/ Some links]
+
+[def __note__ [$images/note.png]]
+[def __alert__ [$images/alert.png]]
+[def __tip__ [$images/tip.png]]
+[def :-) [$images/smiley.png]]
+[def __spirit__ [@http://spirit.sourceforge.net Spirit]]
+[def __boostbook__ [@http://www.boost.org/doc/html/boostbook.html BoostBook]]
+[def __docbook__ [@http://www.docbook.org/ DocBook]]
+
+[def __comments__ [link quickbook.syntax.comments Comments]]
+
+[def __font_styles__ [link quickbook.syntax.phrase.font_styles Font Styles]]
+[def __quotations__ [link quickbook.syntax.phrase.quotations Quotations]]
+[def __replaceable__ [link quickbook.syntax.phrase.replaceable Replaceble]]
+[def __simple_formatting__ [link quickbook.syntax.phrase.simple_formatting Simple formatting]]
+[def __inline_code__ [link quickbook.syntax.phrase.inline_code Inline code]]
+[def __code_blocks__ [link quickbook.syntax.phrase.code_blocks Code blocks]]
+[def __source_mode__ [link quickbook.syntax.phrase.source_mode Source Mode]]
+[def __line_break__ [link quickbook.syntax.phrase.line_break line-break]]
+[def __anchors__ [link quickbook.syntax.phrase.anchors Anchors]]
+[def __links__ [link quickbook.syntax.phrase.links Links]]
+[def __anchor_links__ [link quickbook.syntax.phrase.anchor_links Anchor links]]
+[def __refentry_links__ [link quickbook.syntax.phrase.refentry_links refentry links]]
+[def __code_links__ [link quickbook.syntax.phrase.code_links function, class, member, enum, macro, concept or header links]]
+[def __escape__ [link quickbook.syntax.phrase.escape Escape]]
+[def __single_char_escape__ [link quickbook.syntax.phrase.single_char_escape Single char escape]]
+[def __images__ [link quickbook.syntax.phrase.images Images]]
+
+[def __document__ [link quickbook.syntax.block.document Document]]
+[def __section__ [link quickbook.syntax.block.section Section]]
+[def __xinclude__ [link quickbook.syntax.block.xinclude xinclude]]
+[def __paragraphs__ [link quickbook.syntax.block.paragraphs Paragraphs]]
+[def __ordered_lists__ [link quickbook.syntax.block.lists.ordered_lists Ordered lists]]
+[def __list_hierarchies__ [link quickbook.syntax.block.lists.list_hierarchies List Hierarchies]]
+[def __long_list_lines__ [link quickbook.syntax.block.lists.long_list_lines Long List Lines]]
+[def __unordered_lists__ [link quickbook.syntax.block.lists.unordered_lists Unordered lists]]
+[def __mixed_lists__ [link quickbook.syntax.block.lists.mixed_lists Mixed lists]]
+[def __code__ [link quickbook.syntax.block.code Code]]
+[def __escape_back__ [link quickbook.syntax.block.escape_back Escaping Back To QuickBook]]
+[def __preformatted__ [link quickbook.syntax.block.preformatted Preformatted]]
+[def __blockquote__ [link quickbook.syntax.block.blockquote Blockquote]]
+[def __heading__ [link quickbook.syntax.block.headings Heading]]
+[def __macros__ [link quickbook.syntax.block.macros Macros]]
+[def __templates__ [link quickbook.syntax.block.templates Templates]]
+[def __predefined_macros__ [link quickbook.syntax.block.predefined_macros Predefined Macros]]
+[def __blurbs__ [link quickbook.syntax.block.blurbs Blurbs]]
+[def __admonitions__ [link quickbook.syntax.block.admonitions Admonitions]]
+[def __tables__ [link quickbook.syntax.block.tables Tables]]
+[def __variable_lists__ [link quickbook.syntax.block.variable_lists Variable Lists]]
+[def __include__ [link quickbook.syntax.block.include Include]]
+[def __import__ [link quickbook.syntax.block.import Import]]
+
+[section:intro Introduction]
+
+[:[*['["Why program by hand in five days what you can spend five years of your
+life automating?]]]
+
+-- Terrence Parr, author ANTLR/PCCTS
+]
+
+Well, QuickBook started as a weekend hack. It was originally intended to be a
+sample application using __spirit__. What is it? What you are viewing now, this
+documentation, is autogenerated by QuickBook. These files were generated from
+one master:
+
+[:[@../quickbook.qbk quickbook.qbk]]
+
+Originally named QuickDoc, this funky tool that never dies evolved into a
+funkier tool thanks to Eric Niebler who resurrected the project making it
+generate __boostbook__ instead of HTML. The __boostbook__ documentation format
+is an extension of __docbook__, an SGML or XML based format for describing
+documentation.
+
+QuickBook is a WikiWiki style documentation tool geared towards C++
+documentation using simple rules and markup for simple formatting tasks.
+QuickBook extends the WikiWiki concept. Like the WikiWiki, QuickBook documents are
+simple text files. A single QuickBook document can generate a fully linked set
+of nice HTML and PostScript/PDF documents complete with images and syntax-
+colorized source code.
+
+Features include:
+
+* generate __boostbook__ xml, to generate HTML, PostScript and PDF
+* simple markup to link to Doxygen-generated entities
+* macro system for simple text substitution
+* simple markup for italics, bold, preformatted, blurbs, code samples,
+ tables, URLs, anchors, images, etc.
+* automatic syntax coloring of code samples
+* CSS support
+
+[endsect]
+
+[section:change_log Change Log]
+
+[h3 Version 1.3]
+
+* Quickbook file inclusion \[include\].
+* Better xml output (pretty layout). Check out the generated XML.
+* Regression testing facility: to make sure your document will always be
+ compatible (full backward compatibility) regardless of changes to
+ QuickBook.
+* Code cleanup and refactoring.
+* Allow phrase markup in the doc-info.
+* Preformatted code blocks via \`\`code\`\` (double ticks) allows code in tables
+ and lists, for example.
+* Quickbook versioning; allows full backward compatibility. You have to add
+ \[quickbook 1.3\] to the doc-info header to enable the new features. Without
+ this, QuickBook will assume that the document is a pre-1.3 document.
+* Better (intuitive) paragraph termination. Some markups may terminate a paragraph.
+ Example:``
+ [section x]
+ blah...
+ [endsect]``
+* Fully qualified section and headers. Subsection names are concatenated to the
+ ID to avoid clashing. Example: `doc_name.sect_name.sub_sect_name.sub_sub_sect_name`
+* Better &nbsp; and whitespace handling in code snippets.
+* \[xinclude\] fixes up the relative path to the target XML file when
+ input_directory is not the same as the output_directory.
+* Allow untitled tables.
+* Allow phrase markups in section titles.
+* Allow escaping back to QuickBook from code, code blocks and inline code.
+* Footnotes, with the \[footnote This is the footnote\] syntax.
+* Post-processor bug fix for escaped XML code that it does not recognize.
+* Replaceable, with the \[~replacement\] syntax.
+* Generic Headers
+* Code changes to allow full recursion (i.e. Collectors and push/pop functions)
+* Various code cleanup/maintenance
+* Templates!
+* \[conceptref\] for referencing BoostBook <concept> entities.
+* Allow escape of spaces. The escaped space is removed from the output. Syntax:
+ `\ `.
+* Nested comments are now allowed.
+* Quickbook blocks can nest inside comments.
+* __import__ facility.
+* Callouts on imported code
+* Simple markups can now span a whole block.
+* __blurbs__, __admonitions__ and table cells (see __tables__) may now
+ contain paragraphs.
+* `\n` and `[br]` are now deprecated.
+
+[endsect]
+
+[section:syntax Syntax Summary]
+
+A QuickBook document is composed of one or more blocks. An example of
+a block is the paragraph or a C++ code snippet. Some blocks have
+special mark-ups. Blocks, except code snippets which have their own
+grammar (C++ or Python), are composed of one or more phrases. A phrase
+can be a simple contiguous run of characters. Phrases can have special
+mark-ups. Marked up phrases can recursively contain other phrases, but
+cannot contain blocks. A terminal is a self contained block-level or
+phrase-level element that does not nest anything.
+
+Blocks, in general, are delimited by two end-of-lines (the block terminator).
+Phrases in each block cannot contain a block terminator. This way, syntax errors
+such as un-matched closing brackets do not go haywire and corrupt anything past
+a single block.
+
+[section Comments]
+
+Can be placed anywhere.
+
+[pre
+'''[/ comment (no output generated) ]'''
+]
+
+[/ for testing only... ]
+
+[pre
+'''[/ comments can be nested [/ some more here] ]'''
+]
+
+[/ for testing [/ only ] ]
+
+[pre
+'''[/ Quickbook blocks can nest inside comments. [*Comment this out too!] ]'''
+]
+
+[/ for testing [*only ] ]
+
+[endsect]
+
+[section:phrase Phrase Level Elements]
+
+[section Font Styles]
+
+[pre'''
+['italic], [*bold], [_underline], [^teletype], [-strikethrough]
+''']
+
+will generate:
+
+['italic], [*bold], [_underline], [^teletype], [-strikethrough]
+
+Like all non-terminal phrase level elements, this can of course be nested:
+
+[pre'''
+[*['bold-italic]]
+''']
+
+will generate:
+
+[*['bold-italic]]
+
+[endsect]
+
+[section Replaceable]
+
+When you want content that may or must be replaced by the user, use the syntax:
+
+[pre'''
+[~replacement]
+''']
+
+This will generate:
+
+[~replacement]
+
+[endsect]
+
+[section Quotations]
+
+[pre'''
+["A question that sometimes drives me hazy: am I or are the others crazy?]--Einstein
+''']
+
+will generate:
+
+["A question that sometimes drives me hazy: am I or are the others crazy?]--Einstein
+
+Note the proper left and right quote marks. Also, while you can simply use
+ordinary quote marks like "quoted", our quotation, above, will generate correct
+DocBook quotations (e.g. <quote>quoted</quote>).
+
+Like all phrase elements, quotations may be nested. Example:
+
+[pre'''
+["Here's the rule for bargains: ["Do other men, for they would do you.] That's
+the true business precept.]
+''']
+
+will generate:
+
+["Here's the rule for bargains: ["Do other men, for they would do you.]
+That's the true business precept.]
+
+[endsect]
+[section Simple formatting]
+
+Simple markup for formatting text, common in many applications, is now supported:
+
+[pre'''
+/italic/, *bold*, _underline_, =teletype=
+''']
+
+will generate:
+
+/italic/, *bold*, _underline_, =teletype=
+
+Unlike QuickBook's standard formatting scheme, the rules for simpler
+alternatives are much stricter[footnote Thanks to David Barrett, author of
+[@http://quinthar.com/qwikiwiki/index.php?page=Home Qwiki], for sharing
+these samples and teaching me these obscure formatting rules. I wasn't sure
+at all if __spirit__, being more or less a formal EBNF parser, can handle
+the context sensitivity and ambiguity.].
+
+* Simple markups cannot nest. You can combine a simple markup with a nestable markup.
+* Simple markups cannot contain any other form of quickbook markup.
+* A non-space character must follow the leading markup
+* A non-space character must precede the trailing markup
+* A space or a punctuation must follow the trailing markup
+* If the matching markup cannot be found within a block, the formatting
+ will not be applied. This is to ensure that un-matched formatting markups,
+ which can be a common mistake, does not corrupt anything past a single block.
+ We do not want the rest of the document to be rendered bold just because we
+ forgot a trailing '*'. A single block is terminated by two end of lines or
+ the close bracket: ']'.
+* A line starting with the star will be interpreted as an unordered list.
+ See __unordered_lists__.
+
+[table More Formatting Samples
+ [[Markup] [Result]]
+ [[[^'''*Bold*''']] [*Bold*]]
+ [[[^'''*Is bold*''']] [*Is bold*]]
+ [[[^'''* Not bold* *Not bold * * Not bold *''']] [* Not bold* *Not bold * * Not bold *]]
+ [[[^'''This*Isn't*Bold (no bold)''']] [This*Isn't*Bold (no bold)]]
+ [[[^'''(*Bold Inside*) (parenthesis not bold)''']] [(*Bold Inside*) (parenthesis not bold)]]
+ [[[^'''*(Bold Outside)* (parenthesis bold)''']] [*(Bold Outside)* (parenthesis bold)]]
+ [[[^'''3*4*5 = 60 (no bold)''']] [3*4*5 = 60 (no bold)]]
+ [[[^'''3 * 4 * 5 = 60 (no bold)''']] [3 * 4 * 5 = 60 (no bold)]]
+ [[[^'''3 *4* 5 = 60 (4 is bold)''']] [3 *4* 5 = 60 (4 is bold)]]
+ [[[^'''*This is bold* this is not *but this is*''']][*This is bold* this is not *but this is*]]
+ [[[^'''*This is bold*.''']] [*This is bold*.]]
+ [[[^'''*B*. (bold B)''']] [*B*. (bold B)]]
+ [[[^'''['*Bold-Italic*]''']] [['*Bold-Italic*]]]
+ [[[^'''*side-by*/-side/''']] [*side-by*/-side/]]
+]
+
+As mentioned, simple markups cannot go past a single block. The text
+from "have" to "full" in the following paragraph will be rendered as
+bold:
+
+[pre'''
+Baa baa black sheep, *have you any wool?
+Yes sir, yes sir, three bags full!*
+One for the master, one for the dame,
+And one for the little boy who lives down the lane.
+''']
+
+Baa baa black sheep, *have you any wool?
+Yes sir, yes sir, three bags full!*
+One for the master, one for the dame,
+And one for the little boy who lives down the lane.
+
+But in the following paragraph, bold is not applied:
+
+[pre'''
+Baa baa black sheep, *have you any wool?
+Yes sir, yes sir, three bags full!
+One for the master, one for the dame,
+And one for the little boy who lives down the lane.
+''']
+
+Baa baa black sheep, *have you any wool?
+Yes sir, yes sir, three bags full!
+One for the master, one for the dame,
+And one for the little boy who lives down the lane.
+
+[endsect]
+[section Inline code]
+
+Inlining code in paragraphs is quite common when writing C++ documentation. We
+provide a very simple markup for this. For example, this:
+
+[pre'''
+This text has inlined code `int main() { return 0; }` in it.
+''']
+
+will generate:
+
+This text has inlined code `int main() { return 0; }` in it. The code will be
+syntax highlighted.
+
+[note We simply enclose the code with the tick: [^'''"`"'''], not the
+single quote: `"'"`. Note too that [^'''`some code`'''] is preferred over
+[^'''[^some code]''']. ]
+
+[endsect]
+[section Code blocks]
+
+Preformatted code simply starts with a space or a tab (See __code__).
+However, such a simple syntax cannot be used as phrase elements in lists
+(See __ordered_lists__ and __unordered_lists__), tables (See __tables__),
+etc. Inline code (see above) can. The problem is, inline code does not
+allow formatting with newlines, spaces, and tabs. These are lost.
+
+We provide a phrase level markup that is a mix between the two. By using the
+double-tick, instead of the single-tick, we are telling QuickBook to use
+preformatted blocks of code. Example:
+
+[pre
+\`\`
+ #include <iostream>
+
+ int main()
+ {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+\`\`
+]
+
+will generate:
+
+``
+ #include <iostream>
+
+ int main()
+ {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+``
+
+[endsect]
+[section Source Mode]
+
+If a document contains more than one type of source code then the source
+mode may be changed dynamically as the document is processed. All QuickBook
+documents are initially in C++ mode by default, though an alternative
+initial value may be set in the __document__ section.
+
+To change the source mode, use the [^\[source-mode\]] markup, where
+=source-mode= is one of the supported modes. For example, this:
+
+[pre'''
+Python's [python] `import` is rather like C++'s [c++] `#include`. A
+C++ comment `// looks like this` whereas a Python comment [python]
+`# looks like this`.
+''']
+
+will generate:
+
+Python's [python] `import` is rather like C++'s [c++] `#include`. A
+C++ comment `// looks like this` whereas a Python comment [python]
+`#looks like this`.
+
+[table Supported Source Modes
+ [[Mode] [Source Mode Markup]]
+ [[C++] [[^\[c++\]]]]
+ [[Python] [[^\[python\]]]]
+]
+
+[note The source mode strings are lowercase.]
+
+[endsect]
+[section line-break]
+
+[pre'''
+[br]
+''']
+
+[warning `[br]` is now deprecated. __blurbs__, __admonitions__ and
+table cells (see __tables__) may now contain paragraphs.]
+
+[endsect]
+[section Anchors]
+
+[pre'''
+[#named_anchor]
+''']
+
+A named anchor is a hook that can be referenced by a link elsewhere in the
+document. You can then reference an anchor with [^'''[link named_anchor
+Some link text]''']. See __anchor_links__, __section__ and __heading__.
+
+[endsect]
+[section Links]
+
+[pre'''
+[@http://www.boost.org this is [*boost's] website....]
+''']
+
+will generate:
+
+[@http://www.boost.org this is [*boost's] website....]
+
+URL links where the link text is the link itself is common. Example:
+
+[pre'''
+see http://spirit.sourceforge.net/
+''']
+
+so, when the text is absent in a link markup, the URL is assumed. Example:
+
+[pre
+see '''[@http://spirit.sourceforge.net/]'''
+]
+
+will generate:
+
+see [@http://spirit.sourceforge.net/]
+
+[endsect]
+[section Anchor links]
+
+You can link within a document using:
+
+[pre'''
+[link section_id.normalized_header_text The link text]
+''']
+
+See sections __section__ and __heading__ for more info.
+
+[endsect]
+[section refentry links]
+
+In addition, you can link internally to an XML refentry like:
+
+[pre'''
+[link xml.refentry The link text]
+''']
+
+This gets converted into [^<link linkend="xml.refentry">The link text</link>].
+
+Like URLs, the link text is optional. If this is not present, the link text will
+automatically be the refentry. Example:
+
+[pre'''
+[link xml.refentry]
+''']
+
+This gets converted into [^<link linkend="xml.refentry">xml.refentry</link>].
+
+[endsect]
+[section:code_links Code Links]
+
+If you want to link to a function, class, member, enum, concept or header in the reference
+section, you can use:
+
+[pre'''
+[funcref fully::qualified::function_name The link text]
+[classref fully::qualified::class_name The link text]
+[memberref fully::qualified::member_name The link text]
+[enumref fully::qualified::enum_name The link text]
+[macroref MACRO_NAME The link text]
+[conceptref ConceptName The link text]
+[headerref path/to/header.hpp The link text]
+''']
+
+Again, the link text is optional. If this is not present, the link text will
+automatically be the function, class, member, enum, macro, concept or header. Example:
+
+[pre'''
+[classref boost::bar::baz]
+''']
+
+would have "boost::bar::baz" as the link text.
+
+[endsect]
+[section Escape]
+
+The escape mark-up is used when we don't want to do any processing.
+
+[pre
+\'\'\'
+escape (no processing/formatting)
+\'\'\'
+]
+
+Escaping allows us to pass XML markup to __boostbook__ or __docbook__. For example:
+
+[pre
+\'\'\'
+<emphasis role="bold">This is direct XML markup</emphasis>
+\'\'\'
+]
+
+'''
+<emphasis role="bold">This is direct XML markup</emphasis>
+'''
+
+[important Be careful when using the escape. The text must conform to
+__boostbook__/__docbook__ syntax.]
+
+[endsect]
+[section Single char escape]
+
+The backslash may be used to escape a single punctuation character. The
+punctuation immediately after the backslash is passed without any processing.
+This is useful when we need to escape QuickBook punctuations such as `[` and `]`.
+For example, how do you escape the triple quote? Simple: [^\\'\\'\\']
+
+
+`\n` has a special meaning. It is used to generate line breaks.
+
+[warning `\n` and `[br]` are now deprecated. __blurbs__, __admonitions__
+and table cells (see __tables__) may now contain paragraphs.]
+
+The escaped space: `\ ` also has a special meaning. The escaped space is removed
+from the output.
+
+[endsect]
+[section Images]
+
+[pre'''
+[$image.jpg]
+''']
+
+[endsect]
+[section Footnotes]
+
+As of version 1.3, QuickBook supports footnotes. Just put the text of the
+footnote in a `[footnote]` block, and the text will be put at the bottom
+of the current page. For example, this:
+
+[pre'''
+[footnote A sample footnote]
+''']
+
+will generate this[footnote A sample footnote].
+
+[section Macro Expansion]
+
+[pre'''
+__a_macro_identifier__
+''']
+
+See __macros__ for details.
+
+[endsect]
+
+[section Template Expansion]
+
+[pre'''
+[a_template_identifier]
+''']
+
+See __templates__ for details.
+
+[endsect]
+
+[endsect]
+[endsect]
+[section:block Block Level Elements]
+
+[section Document]
+
+Every document must begin with a Document Info section, which should look
+like this:
+
+[pre'''
+[document-type The Document Title
+ [quickbook 1.3]
+ [version 1.0]
+ [id the_document_name]
+ [dirname the_document_dir]
+ [copyright 2000 2002 2003 Joe Blow, Jane Doe]
+ [purpose The document's reason for being]
+ [category The document's category]
+ [authors [Blow, Joe], [Doe, Jane]]
+ [license The document's license]
+ [source-mode source-type]
+]
+''']
+
+Where document-type is one of:
+
+* book
+* article
+* library
+* chapter
+* part
+* appendix
+* preface
+* qandadiv
+* qandaset
+* reference
+* set
+
+quickbook 1.3 declares the version of quickbook the document is written for.
+In its absence, version 1.1 is assumed.
+
+=version=, =id=, =dirname=, =copyright=, =purpose=, =category=, =authors=,
+=license=, =last-revision= and =source-mode= are optional information.
+
+=source-type= is a lowercase string setting the initial __source_mode__. If
+the =source-mode= field is omitted, a default value of =c++= will be used.
+
+[endsect]
+[section Section]
+
+Starting a new section is accomplished with:
+
+[pre'''
+[section:id The Section Title]
+''']
+
+where /id/ is optional. id will be the filename of the generated section.
+If it is not present, "The Section Title" will be normalized and become the id.
+Valid characters are =a-Z=, =A-Z=, =0-9= and =_=. All non-valid characters are
+converted to underscore and all upper-case are converted to lower case.
+Thus: "The Section Title" will be normalized to "the_section_title".
+
+End a section with:
+
+[pre'''
+[endsect]
+''']
+
+Sections can nest, and that results in a hierarchy in the table of contents.
+
+[endsect]
+[section xinclude]
+
+You can include another XML file with:
+
+[pre'''
+[xinclude file.xml]
+''']
+
+This is useful when file.xml has been generated by Doxygen and contains your
+reference section.
+
+[endsect]
+[section Paragraphs]
+
+Paragraphs start left-flushed and are terminated by two or more newlines. No
+markup is needed for paragraphs. QuickBook automatically detects paragraphs from
+the context. Block markups \[section, endsect, h1, h2, h3, h4, h5, h6, blurb,
+(block-quote) ':', pre, def, table and include \] may also terminate a paragraph.
+
+[endsect]
+
+[section Lists]
+[section Ordered lists]
+
+[pre
+# One
+# Two
+# Three
+]
+
+will generate:
+
+# One
+# Two
+# Three
+
+[endsect]
+[section List Hierarchies]
+
+List hierarchies are supported. Example:
+
+[pre
+# One
+# Two
+# Three
+ # Three.a
+ # Three.b
+ # Three.c
+# Four
+ # Four.a
+ # Four.a.i
+ # Four.a.ii
+# Five
+]
+
+will generate:
+
+# One
+# Two
+# Three
+ # Three.a
+ # Three.b
+ # Three.c
+# Fourth
+ # Four.a
+ # Four.a.i
+ # Four.a.ii
+# Five
+
+[endsect]
+[section Long List Lines]
+
+Long lines will be wrapped appropriately. Example:
+
+[pre
+# A short item.
+# A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+# A short item.
+]
+
+# A short item.
+# A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+ A very long item. A very long item. A very long item.
+# A short item.
+
+[endsect]
+[section Unordered lists]
+
+[pre'''
+* First
+* Second
+* Third
+''']
+
+will generate:
+
+* First
+* Second
+* Third
+
+[endsect]
+[section Mixed lists]
+
+Mixed lists (ordered and unordered) are supported. Example:
+
+[pre'''
+# One
+# Two
+# Three
+ * Three.a
+ * Three.b
+ * Three.c
+# Four
+''']
+
+will generate:
+
+# One
+# Two
+# Three
+ * Three.a
+ * Three.b
+ * Three.c
+# Four
+
+And...
+
+[pre'''
+# 1
+ * 1.a
+ # 1.a.1
+ # 1.a.2
+ * 1.b
+# 2
+ * 2.a
+ * 2.b
+ # 2.b.1
+ # 2.b.2
+ * 2.b.2.a
+ * 2.b.2.b
+''']
+
+will generate:
+
+# 1
+ * 1.a
+ # 1.a.1
+ # 1.a.2
+ * 1.b
+# 2
+ * 2.a
+ * 2.b
+ # 2.b.1
+ # 2.b.2
+ * 2.b.2.a
+ * 2.b.2.b
+
+[endsect]
+[endsect]
+
+[section Code]
+
+Preformatted code starts with a space or a tab. The code will be
+syntax highlighted according to the current __source_mode__:
+
+[c++]
+
+ #include <iostream>
+
+ int main()
+ {
+ // Sample code
+ std::cout << "Hello, World\n";
+ return 0;
+ }
+
+[python]
+
+ import cgi
+
+ def cookForHtml(text):
+ '''"Cooks" the input text for HTML.'''
+
+ return cgi.escape(text)
+
+[c++]
+
+Macros that are already defined are expanded in source code. Example:
+
+[pre'''
+[def __array__ [@http://www.boost.org/doc/html/array/reference.html array]]
+[def __boost__ [@http://www.boost.org/libs/libraries.htm boost]]
+
+ using __boost__::__array__;
+''']
+
+Generates:
+
+[def __array__ [@http://www.boost.org/doc/html/array/reference.html array]]
+[def __boost__ [@http://www.boost.org/libs/libraries.htm boost]]
+
+ using __boost__::__array__;
+
+[endsect]
+[section:escape_back Escaping Back To QuickBook]
+
+Inside code, code blocks and inline code, QuickBook does not allow any
+markup to avoid conflicts with the target syntax (e.g. c++). In case you
+need to switch back to QuickBook markup inside code, you can do so using a
+language specific /escape-back/ delimiter. In C++ and Python, the delimiter
+is the double tick (back-quote): "\`\`" and "\`\`". Example:
+
+[pre'''
+void ``[@http://en.wikipedia.org/wiki/Foo#Foo.2C_Bar_and_Baz foo]``()
+{
+}
+''']
+
+Will generate:
+
+ void ``[@http://en.wikipedia.org/wiki/Foo#Foo.2C_Bar_and_Baz foo]``()
+ {
+ }
+
+When escaping from code to QuickBook, only phrase level markups are
+allowed. Block level markups like lists, tables etc. are not allowed.
+
+[endsect]
+[section Preformatted]
+
+Sometimes, you don't want some preformatted text to be parsed as C++. In such
+cases, use the [^[pre ... \]] markup block.
+
+[pre'''
+[pre
+
+ Some *preformatted* text Some *preformatted* text
+
+ Some *preformatted* text Some *preformatted* text
+
+ Some *preformatted* text Some *preformatted* text
+
+]
+''']
+
+Spaces, tabs and newlines are rendered as-is. Unlike all quickbook block level
+markup, pre (and Code) are the only ones that allow multiple newlines. The
+markup above will generate:
+
+[pre
+
+Some *preformatted* text Some *preformatted* text
+
+ Some *preformatted* text Some *preformatted* text
+
+ Some *preformatted* text Some *preformatted* text
+
+]
+
+Notice that unlike Code, phrase markup such as font style is still permitted
+inside =pre= blocks.
+
+[endsect]
+[section Blockquote]
+
+[pre
+'''[:sometext...]'''
+]
+
+[:Indents the paragraph. This applies to one paragraph only.]
+
+[endsect]
+[section Admonitions]
+
+[pre'''
+[note This is a note]
+[tip This is a tip]
+[important This is important]
+[caution This is a caution]
+[warning This is a warning]
+''']
+
+generates __docbook__ admonitions:
+
+[note This is a note]
+[tip This is a tip]
+[important This is important]
+[caution This is a caution]
+[warning This is a warning]
+
+These are the only admonitions supported by __docbook__. So,
+for example [^\[information This is some information\]] is unlikely
+to produce the desired effect.
+
+[endsect]
+[section Headings]
+
+[pre'''
+[h1 Heading 1]
+[h2 Heading 2]
+[h3 Heading 3]
+[h4 Heading 4]
+[h5 Heading 5]
+[h6 Heading 6]
+''']
+
+[h1 Heading 1]
+[h2 Heading 2]
+[h3 Heading 3]
+[h4 Heading 4]
+[h5 Heading 5]
+[h6 Heading 6]
+
+Headings 1-3 \[h1 h2 and h3\] will automatically have anchors with normalized
+names with [^name="section_id.normalized_header_text"] (i.e. valid characters are
+=a-z=, =A-Z=, =0-9= and =_=. All non-valid characters are converted to underscore
+and all upper-case are converted to lower-case. For example: Heading
+1 in section Section 2 will be normalized to [^section_2.heading_1]). You can use:
+
+[pre'''
+[link section_id.normalized_header_text The link text]
+''']
+
+to link to them. See __anchor_links__ and __section__ for more info.
+
+[endsect]
+[section Generic Heading]
+
+In cases when you don't want to care about the heading level (1 to 6), you
+can use the /Generic Heading/:
+
+[pre'''
+[heading Heading]
+''']
+
+The /Generic Heading/ assumes the level, plus one, of the innermost section
+where it is placed. For example, if it is placed in the outermost section,
+then, it assumes /h2/.
+
+Headings are often used as an alternative to sections. It is used
+particularly if you do not want to start a new section. In many cases,
+however, headings in a particular section is just flat. Example:
+
+[pre'''
+[section A]
+[h2 X]
+[h2 Y]
+[h2 Z]
+[endsect]
+''']
+
+Here we use h2 assuming that section A is the outermost level. If it is
+placed in an inner level, you'll have to use h3, h4, etc. depending on
+where the section is. In general, it is the section level plus one. It is
+rather tedious, however, to scan the section level everytime. If you
+rewrite the example above as shown below, this will be automatic:
+
+[pre'''
+[section A]
+[heading X]
+[heading Y]
+[heading Z]
+[endsect]
+''']
+
+They work well regardless where you place them. You can rearrange sections
+at will without any extra work to ensure correct heading levels. In fact,
+with /section/ and /heading/, you have all you need. /h1/../h6/ becomes
+redundant. /h1/../h6/ might be deprecated in the future.
+
+[endsect]
+[section Macros]
+
+[pre'''
+[def macro_identifier some text]
+''']
+
+When a macro is defined, the identifier replaces the text anywhere in the
+file, in paragraphs, in markups, etc. macro_identifier is a string of non-
+white space characters except '\]'. A macro may not follow an alphabetic
+character or the underscore. The replacement text can be any phrase (even
+marked up). Example:
+
+[pre'''
+[def sf_logo [$http://sourceforge.net/sflogo.php?group_id=28447&amp;type=1]]
+sf_logo
+''']
+
+Now everywhere the sf_logo is placed, the picture will be inlined.
+
+[def sf_logo [$http://sourceforge.net/sflogo.php?group_id=28447&type=1]]
+sf_logo
+
+[tip It's a good idea to use macro identifiers that are distinguishable.
+For instance, in this document, macro identifiers have two leading and
+trailing underscores (e.g. [^'''__spirit__''']). The reason is to avoid
+unwanted macro replacement.]
+
+Links (URLS) and images are good candidates for macros. *1*) They tend to
+change a lot. It is a good idea to place all links and images in one place near the top
+to make it easy to make changes. *2*) The syntax is not pretty. It's easier to read and
+write, e.g. [^'''__spirit__'''] than [^'''[@http://spirit.sourceforge.net Spirit]'''].
+
+Some more examples:
+
+[pre'''
+[def :-) [$theme/smiley.png]]
+[def __spirit__ [@http://spirit.sourceforge.net Spirit]]
+''']
+
+(See __images__ and __links__)
+
+Invoking these macros:
+
+[pre'''
+Hi __spirit__ :-)
+''']
+
+will generate this:
+
+Hi __spirit__ :-)
+
+[endsect]
+[section Predefined Macros]
+
+Quickbook has some predefined macros that you can already use.
+
+[table Predefined Macros
+ [[Macro] [Meaning] [Example]]
+ [['''__DATE__'''] [Today's date] [__DATE__]]
+ [['''__TIME__'''] [The current time] [__TIME__]]
+ [['''__FILENAME__'''] [Quickbook source filename] [__FILENAME__]]
+]
+
+[endsect]
+[section Templates]
+
+Templates provide a more versatile text substitution mechanism. Templates
+come in handy when you need to create parameterizable, multi-line,
+boilerplate text that you specify once and expand many times. Templates
+accept one or more arguments. These arguments act like place-holders for
+text replacement. Unlike simple macros, which are limited to phrase level
+markup, templates can contain block level markup (e.g. paragraphs, code
+blocks and tables).
+
+Example template:
+
+[pre'''
+[template person[name age what]
+
+Hi, my name is [name]. I am [age] years old. I am a [what].
+
+]
+''']
+
+[template person[name age what]
+
+Hi, my name is [name]. I am [age] years old. I am a [what].
+
+]
+
+[heading Template Identifier]
+
+Template identifiers can either consist of:
+
+* An initial alphabetic character or the underscore, followed by
+ zero or more alphanumeric characters or the underscore. This is
+ similar to your typical C/C++ identifier.
+* A single character punctuation (a non-alphanumeric printable character)
+
+[heading Formal Template Arguments]
+
+Template formal arguments are identifiers consisting of an initial
+alphabetic character or the underscore, followed by zero or more
+alphanumeric characters or the underscore. This is similar to your typical
+C/C++ identifier.
+
+A template formal argument temporarily hides a template of the same name at
+the point where the [link quickbook.syntax.block.templates.template_expansion
+template is expanded]. Note that the body of the [^person] template above
+refers to [^name] [^age] and [^what] as [^\[name\]] [^\[age\]] and
+[^\[what\]]. [^name] [^age] and [^what] are actually templates that exist
+in the duration of the template call.
+
+[heading Template Body]
+
+The template body can be just about any QuickBook block or phrase. There
+are actually two forms. Templates may be phrase or block level. Phrase
+templates are of the form:
+
+[pre'''
+[template sample[arg1 arg2...argN] replacement text... ]
+''']
+
+Block templates are of the form:
+
+[pre'''
+[template sample[arg1 arg2...argN]
+replacement text...
+]
+''']
+
+The basic rule is as follows: if a newline immediately follows the argument
+list, then it is a block template, otherwise, it is a phrase template.
+Phrase templates are typically expanded as part of phrases. Like macros,
+block level elements are not allowed in phrase templates.
+
+[heading Template Expansion]
+
+You expand a template this way:
+
+[pre'''
+[template_identifier arg1..arg2..arg3]
+''']
+
+At template expansion, you supply the actual arguments. The template will
+be expanded with your supplied arguments. Example:
+
+[pre'''
+[person James Bond..39..Spy]
+[person Santa Clause..87..Big Red Fatso]
+''']
+
+Which will expand to:
+
+[person James Bond..39..Spy]
+[person Santa Clause..87..Big Red Fatso]
+
+[caution A word of caution: Templates are recursive. A template can call
+another template or even itself, directly or indirectly. There are no
+control structures in QuickBook (yet) so this will always mean infinite
+recursion. QuickBook can detect this situation and report an error if
+recursion exceeds a certain limit.]
+
+Each actual argument can be a word, a text fragment or just about any [link
+quickbook.syntax.phrase QuickBook phrase]. Arguments are separated by the
+double dot [^".."] and terminated by the close parenthesis.
+
+[heading Nullary Templates]
+
+Nullary templates look and act like simple macros. Example:
+
+[pre'''
+[template alpha[]&apos;&apos;&apos;&amp;#945;&apos;&apos;&apos;]
+[template beta[]&apos;&apos;&apos;&amp;#946;&apos;&apos;&apos;]
+''']
+
+[template alpha[]'''&#945;''']
+[template beta[]'''&#946;''']
+
+Expanding:
+
+[pre'''Some squigles...[*[alpha][beta]]''']
+
+We have:
+
+Some squiggles...[*[alpha][beta]]
+
+The difference with macros are
+
+* The explicit [link quickbook.syntax.block.templates.template_expansion
+ template expansion syntax]. This is an advantage because, now, we don't
+ have to use obscure naming conventions like double underscores (e.g.
+ \_\_alpha\_\_) to avoid unwanted
+ macro replacement.
+* The template is expanded at the point where it is invoked. A macro is
+ expanded immediately at its point of declaration. This is subtle and
+ can cause a slight difference in behavior especially if you refer to
+ other macros and templates in the body.
+
+The empty brackets after the template identifier ([^alpha\[\]]) indicates no
+arguments. If the template body does not look like a template argument list, we
+can elide the empty brackets. Example:
+
+[pre'''
+[template aristotle_quote Aristotle: [*['Education is the best provision
+for the journey to old age.]]]
+''']
+
+[template aristotle_quote\ Aristotle: [*['Education is the best provision
+for the journey to old age.]]]
+
+Expanding:
+
+[pre'''
+Here's a quote from [aristotle_quote].
+''']
+
+We have:
+
+Here's a quote from [aristotle_quote].
+
+The disadvantage is that you can't avoid the space between the template
+identifier, `aristotle_quote`, and the template body "Aristotle...". This space
+will be part of the template body. If that space is unwanted, use empty
+brackets or use the space escape: "`\ `". Example:
+
+[pre'''
+[template tag\ _tag]
+''']
+
+[template tag\ _tag]
+
+Then expanding:
+
+[pre'''
+`struct` x[tag];
+''']
+
+We have:
+
+`struct` x[tag];
+
+You have a couple of ways to do it. I personally prefer the explicit empty
+brackets, though.
+
+[heading Simple Arguments]
+
+As mentioned, arguments are separated by the double dot [^".."]. If there
+are less arguments passed than expected, QuickBook attempts to break the
+last argument into two or more arguments following this logic:
+
+* Break the last argument into two, at the first space found ([^'', '\\n',
+ \\t' or '\\r']).
+* Repeat until there are enough arguments or if there are no more spaces
+ found (in which case, an error is reported).
+
+For example:
+
+[pre'''
+[template simple[a b c d] [a][b][c][d]]
+[simple w x y z]
+''']
+
+will produce:
+
+[template simple[a b c d] [a][b][c][d]]
+[simple w x y z]
+
+"w x y z" is initially treated as a single argument because we didn't
+supply any [^".."] separators. However, since [^simple] expects 4
+arguments, "w x y z" is broken down iteratively (applying the logic above)
+until we have "w", "x", "y" and "z".
+
+QuickBook only tries to get the arguments it needs. For example:
+
+[pre'''
+[simple w x y z trail]
+''']
+
+will produce:
+
+[simple w x y z trail]
+
+The arguments being: "w", "x", "y" and "z trail".
+
+It should be obvious now that for simple arguments with no spaces, we can
+get by without separating the arguments with [^".."] separators. It is
+possible to combine [^".."] separators with the argument passing
+simplification presented above. Example:
+
+[pre'''
+[simple what do you think ..m a n?]
+''']
+
+will produce:
+
+[simple what do you think ..m a n?]
+
+[heading Punctuation Templates]
+
+With templates, one of our objectives is to allow us to rewrite QuickBook
+in QuickBook (as a qbk library). For that to happen, we need to accommodate
+single character punctuation templates which are fairly common in
+QuickBook. You might have noticed that single character punctuations are
+allowed as [link quickbook.syntax.block.templates.template_identifier
+template identifiers]. Example:
+
+[pre'''
+[template ![bar] '''<hey>'''[bar]'''</hey>''']
+''']
+
+Now, expanding this:
+
+[pre'''
+[!baz]
+''']
+
+We will have:
+
+[pre
+<hey>baz</hey>
+]
+
+[endsect]
+[section Blurbs]
+
+[pre'''
+[blurb :-) [*An eye catching advertisement or note...]
+
+ __spirit__ is an object-oriented recursive-descent parser generator framework
+ implemented using template meta-programming techniques. Expression templates
+ allow us to approximate the syntax of Extended Backus-Normal Form (EBNF)
+ completely in C++.
+]
+''']
+
+will generate this:
+
+[blurb :-) [*An eye catching advertisement or note...]
+
+ __spirit__ is an object-oriented recursive-descent parser generator
+ framework implemented using template meta-programming techniques. Expression
+ templates allow us to approximate the syntax of Extended Backus-Normal Form
+ (EBNF) completely in C++.
+]
+
+[note Prefer [link quickbook.syntax.block.admonitions admonitions] wherever
+appropriate.]
+
+[endsect]
+[section Tables]
+
+[pre'''
+[table A Simple Table
+ [[Heading 1] [Heading 2] [Heading 3]]
+ [[R0-C0] [R0-C1] [R0-C2]]
+ [[R1-C0] [R1-C1] [R1-C2]]
+ [[R2-C0] [R2-C1] [R2-C2]]
+]
+''']
+
+will generate:
+
+[table A Simple Table
+ [[Heading 1] [Heading 2] [Heading 3]]
+ [[R0-C0] [R0-C1] [R0-C2]]
+ [[R2-C0] [R2-C1] [R2-C2]]
+ [[R3-C0] [R3-C1] [R3-C2]]
+]
+
+The table title is optional. The first row of the table is automatically
+treated as the table header; that is, it is wrapped in
+[^<thead>...</thead>] XML tags. Note that unlike the original QuickDoc, the
+columns are nested in [ cells... ]. The syntax is free-format and allows
+big cells to be formatted nicely. Example:
+
+[pre'''
+[table Table with fat cells
+ [[Heading 1] [Heading 2]]
+ [
+ [Row 0, Col 0: a small cell]
+ [
+ Row 0, Col 1: a big fat cell with paragraphs
+
+ Boost provides free peer-reviewed portable C++ source libraries.
+
+ We emphasize libraries that work well with the C++ Standard Library.
+ Boost libraries are intended to be widely useful, and usable across
+ a broad spectrum of applications. The Boost license encourages both
+ commercial and non-commercial use.
+ ]
+ ]
+ [
+ [Row 1, Col 0: a small cell]
+ [Row 1, Col 1: a small cell]
+ ]
+]
+''']
+
+and thus:
+
+[table Table with fat cells
+ [[Heading 1] [Heading 2]]
+ [
+ [Row 0, Col 0: a small cell]
+ [
+ Row 0, Col 1: a big fat cell with paragraphs
+
+ Boost provides free peer-reviewed portable C++ source libraries.
+
+ We emphasize libraries that work well with the C++ Standard Library.
+ Boost libraries are intended to be widely useful, and usable across
+ a broad spectrum of applications. The Boost license encourages both
+ commercial and non-commercial use.
+ ]
+ ]
+ [
+ [Row 1, Col 0: a small cell]
+ [Row 1, Col 1: a small cell]
+ ]
+]
+
+Here's how to have preformatted blocks of code in a table cell:
+
+[pre'''
+[table Table with code
+ [[Comment] [Code]]
+ [
+ [My first program]
+ ['''\`\`
+ #include <iostream>
+
+ int main()
+ {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+ \`\`''']
+ ]
+]
+''']
+
+[table Table with code
+ [[Comment] [Code]]
+ [
+ [My first program]
+ [``
+ #include <iostream>
+
+ int main()
+ {
+ std::cout << "Hello, World!" << std::endl;
+ return 0;
+ }
+ ``]
+ ]
+]
+
+[endsect]
+[section Variable Lists]
+
+[pre'''
+[variablelist A Variable List
+ [[term 1] [The definition of term 1]]
+ [[term 2] [The definition of term 2]]
+ [[term 3] [The definition of term 3]]
+]
+''']
+
+will generate:
+
+[variablelist A Variable List
+ [[term 1] [The definition of term 1]]
+ [[term 2] [The definition of term 2]]
+ [[term 3] [The definition of term 3]]
+]
+
+The rules for variable lists are the same as for tables, except that
+only 2 "columns" are allowed. The first column contains the terms, and
+the second column contains the definitions. Those familiar with HTML
+will recognize this as a "definition list".
+
+[endsect]
+[section Include]
+
+You can include one QuickBook file from another. The syntax is simply:
+
+[pre'''
+[include someother.qbk]
+''']
+
+The included file will be processed as if it had been cut and pasted
+into the current document, with the following exceptions:
+
+* The '''__FILENAME__''' predefined macro will reflect the name of the
+ file currently being processed.
+* Any macros defined in the included file are scoped to that file.
+
+The [^\[include\]] directive lets you specify a document id to use for the
+included file. When this id is not explicitly specified, the id defaults to
+the filename ("someother", in the example above). You can specify the id
+like this:
+
+[pre'''
+[include:someid someother.qbk]
+''']
+
+All auto-generated anchors will use the document id as a unique prefix. So
+for instance, if there is a top section in someother.qbk named "Intro", the
+named anchor for that section will be "someid.intro", and you can link to
+it with [^\[link someid.intro The Intro\]].
+
+[endsect]
+
+[section Import]
+
+When documenting code, you'd surely need to present code from actual source
+files. While it is possible to copy some code and paste them in your QuickBook
+file, doing so is error prone and the extracted code in the documentation tends
+to get out of sync with the actual code as the code evolves. The problem, as
+always, is that once documentation is written, the tendency is for the docs to
+languish in the archives without maintenance.
+
+QuickBook's import facility provides a nice solution.
+
+[heading Example]
+
+You can effortlessly import code snippets from source code into your QuickBook.
+The following illustrates how this is done:
+
+[pre'''
+[import ../test/stub.cpp]
+[foo]
+[bar]
+''']
+
+The first line:
+
+[pre'''
+[import ../test/stub.cpp]
+''']
+
+collects specially marked-up code snippets from [@../../test/stub.cpp stub.cpp]
+and places them in your QuickBook file as virtual templates. Each of the
+specially marked-up code snippets has a name (e.g. `foo` and `bar` in the
+example above). This shall be the template identifier for that particular code
+snippet. The second and third line above does the actual template expansion:
+
+[pre'''
+[foo]
+[bar]
+''']
+
+And the result is:
+
+[import ../test/stub.cpp]
+[foo]
+[bar]
+
+[heading Code Snippet Markup]
+
+Note how the code snippets in [@../../test/stub.cpp stub.cpp] get marked up. We
+use distinguishable comments following the form:
+
+ //[id
+ some code here
+ //]
+
+The first comment line above initiates a named code-snippet. This prefix will
+not be visible in quickbook. The entire code-snippet in between `//[id` and
+`//]` will be inserted as a template in quickbook with name ['/id/]. The comment
+`//]` ends a code-snippet This too will not be visible in quickbook.
+
+[heading Special Comments]
+
+Special comments of the form:
+
+ //` some [*quickbook] markup here
+
+and:
+
+ /*` some [*quickbook] markup here */
+
+will be parsed by QuickBook. This can contain quickbook /blocks/ (e.g. sections,
+paragraphs, tables, etc). In the first case, the initial slash-slash, tick and
+white-space shall be ignored. In the second, the initial slash-star-tick and the
+final star-slash shall be ignored.
+
+[heading Callouts]
+
+Special comments of the form:
+
+ /*< some [*quickbook] markup here >*/
+
+will be regarded as callouts. These will be collected, numbered and
+rendered as a "callout bug" (a small icon with a number). After the
+whole snippet is parsed, the callout list is generated. See
+[@http://www.docbook.org/tdg/en/html/callout.html Callouts] for details.
+Example:
+
+[foo_bar]
+
+Checkout [@../../test/stub.cpp stub.cpp] to see the actual code.
+
+[endsect]
+
+[endsect]
+[endsect]
+
+[section:install Installation and configuration]
+
+This section provides some guidelines on how to install and configure
+BoostBook and Quickbook under several operating systems.
+
+Before continuing, it is very important that you keep this in mind: if you
+try to build some documents and the process breaks due to misconfiguration,
+be absolutely sure to delete any `bin` and `bin.v2` directories generated
+by the build before trying again. Otherwise your configuration fixes will
+not take any effect.
+
+[section:windows Windows 2000, XP, 2003, Vista]
+
+[python]
+
+[:['Section contributed by Julio M. Merino Vidal]]
+
+The following instructions apply to any Windows system based on Windows
+2000, including Windows XP, Windows 2003 Server and Windows Vista. The
+paths shown below are taken from a Windows Vista machine; you will need to
+adjust them to match your system in case you are running an older version.
+
+# First of all you need to have a copy of `xsltproc` for Windows. There
+ are many ways to get this tool, but to keep things simple, use the
+ [@http://www.zlatkovic.com/pub/libxml/ binary packages] made by Igor
+ Zlatkovic. At the very least, you need to download the following
+ packages: `iconv`, `zlib`, `libxml2` and `libxslt`.
+
+# Unpack all these packages in the same directory so that you get unique
+ `bin`, `include` and `lib` directories within the hierarchy. These
+ instructions use `C:\Users\example\Documents\boost\xml` as the root for
+ all files.
+
+# From the command line, go to the `bin` directory and launch
+ `xsltproc.exe` to ensure it works. You should get usage information on
+ screen.
+
+# Download [@http://www.docbook.org/xml/4.2/docbook-xml-4.2.zip Docbook XML
+ 4.2] and unpack it in the same directory used above. That is:
+ `C:\Users\example\Documents\boost\xml\docbook-xml`.
+
+# Download the latest
+ [@http://sourceforge.net/project/showfiles.php?group_id=21935&package_id=16608
+ Docbook XSL] version and unpack it, again in the same directory
+ used before. To make things easier, rename the directory created
+ during the extraction to `docbook-xsl` (bypassing the version name):
+ `C:\Users\example\Documents\boost\xml\docbook-xsl`.
+
+# Add the following to your `user-config.jam` file, which should live in
+ your home directory (`%HOMEDRIVE%%HOMEPATH%`). You must already have it
+ somewhere or otherwise you could not be building Boost (i.e. missing
+ tools configuration).
+
+ using xsltproc
+ : "C:/Users/example/Documents/boost/xml/bin/xsltproc.exe"
+ ;
+
+ using boostbook
+ : "C:/Users/example/Documents/boost/xml/docbook-xsl"
+ : "C:/Users/example/Documents/boost/xml/docbook-xml"
+ ;
+
+The above steps are enough to get a functional BoostBook setup. Quickbook
+will be automatically built when needed. If you want to avoid these
+rebuilds:
+
+# Go to Quickbook's source directory (`BOOST_ROOT\tools\quickbook`).
+
+# Build the utility by issuing `bjam --v2`.
+
+# Copy the resulting `quickbook.exe` binary (located under the
+ `BOOST_ROOT\bin.v2` hierarchy) to a safe place. Following our previous
+ example, you can install it into:
+ `C:\Users\example\Documents\boost\xml\bin`.
+
+# Add the following to your `user-config.jam` file:
+
+ using quickbook
+ : "C:/Users/example/Documents/boost/xml/bin/quickbook.exe"
+ ;
+
+[endsect]
+
+[section:linux Debian, Ubuntu]
+
+The following instructions apply to Debian and its derivatives. They are based
+on a Ubuntu Edgy install but should work on other Debian based systems.
+
+First install the `bjam`, `xsltproc`, `docbook-xsl` and `docbook-xml` packages.
+For example, using `apt-get`:
+
+ sudo apt-get install xsltprc docbook-xsl docbook-xml
+
+If you're planning on building boost's documentation, you'll also need to
+install the `doxygen` package as well.
+
+Next, we need to configure Boost Build to compile BoostBook files. Add the
+following to your `user-config.jam` file, which should be in your home
+directory. If you don't have one, create a file containing this text. For more
+information on setting up `user-config.jam`, see the
+[@http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html Boost
+Build documentation].
+
+ using xsltproc ;
+
+ using boostbook
+ : /usr/share/xml/docbook/stylesheet/nwalsh
+ : /usr/share/xml/docbook/schema/dtd/4.2
+ ;
+
+ # Remove this line if you're not using doxygen
+ using doxygen ;
+
+The above steps are enough to get a functional BoostBook setup. Quickbook
+will be automatically built when needed. If you want to avoid these
+rebuilds:
+
+# Go to Quickbook's source directory (`BOOST_ROOT/tools/quickbook`).
+
+# Build the utility by issuing `bjam --v2`.
+
+# Copy the resulting `quickbook` binary (located under the
+ `BOOST_ROOT/bin.v2` hierarchy) to a safe place. The traditional location is
+ `/usr/local/bin`.
+
+# Add the following to your `user-config.jam` file, using the full path of the
+ quickbook executable:
+
+ using quickbook
+ : /usr/local/bin/quickbook
+ ;
+
+[endsect]
+[endsect] [/Installation and configuration]
+
+[section:editors Editor Support]
+
+Editing quickbook files is usually done with text editors both simple and
+powerful. The following sections list the settings for some editors which can
+help make editing quickbook files a bit easier.
+
+[blurb __note__ You may submit your settings, tips, and suggestions to the
+authors, or through the [@https://lists.sourceforge.net/lists/listinfo/boost-
+docs Boost Docs mailing list].]
+
+[section:scite Scintilla Text Editor]
+
+[:['Section contributed by Dean Michael Berris]]
+
+The Scintilla Text Editor (SciTE) is a free source code editor for Win32 and X.
+It uses the SCIntilla source code editing component.
+
+[blurb __tip__ SciTE can be downloaded from [@http://www.scintilla.org/SciTE.html]]
+
+You can use the following settings to highlight quickbook tags when
+editing quickbook files.
+
+[pre'''
+qbk=*.qbk
+lexer.*.qbk=props
+use.tabs.$(qbk)=0
+tab.size.$(qbk)=4
+indent.size.$(qbk)=4
+style.props.32=$(font.base)
+comment.stream.start.props=[/
+comment.stream.end.props=]
+comment.box.start.props=[/
+comment.box.middle.props=
+comment.box.end.props=]
+''']
+
+[blurb __note__ Thanks to Rene Rivera for the above SciTE settings.]
+
+[endsect] [/scite]
+[endsect] [/editors]
+
+[section:faq Frequently Asked Questions]
+
+[heading Can I use QuickBook for non-Boost documentation?]
+
+QuickBook can be used for non-Boost documentation with a little extra work.
+
+[:['Faq contributed by Michael Marcin]]
+
+When building HTML documentation with BoostBook a Boost C++ Libraries header
+is added to the files. When using QuickBook to document projects outside of
+Boost this is not desirable. This behavior can be overridden at the BoostBook
+level by specifying some XSLT options. When using Boost Build version 2 (BBv2)
+this can be achieved by adding parameters to the BoostBook target declaration.
+
+For example:
+[pre
+using quickbook ;
+
+xml my_doc : my_doc.qbk ;
+
+boostbook standalone
+ :
+ my_doc
+ :
+ <xsl:param>boost.image.src=images/my_project_logo.png
+ <xsl:param>boost.image.alt="\\"My Project\\""
+ <xsl:param>boost.image.w=100
+ <xsl:param>boost.image.h=50
+ <xsl:param>nav.layout=none
+ ;
+]
+
+[endsect] [/faq]
+
+[section:ref Quick Reference]
+
+[cpp]
+
+[template ordered_list_sample[]
+[pre'''
+# one
+# two
+# three
+''']
+]
+
+[template unordered_list_sample[]
+[pre'''
+* one
+* two
+* three
+''']
+]
+
+[template table_sample[]
+[pre'''
+[table Title
+[[a][b][c]]
+[[a][b][c]]
+]
+''']
+]
+
+[template var_list_sample[]
+[pre'''
+[variablelist Title
+[[a][b]]
+[[a][b]]
+]
+''']
+]
+
+
+[table Syntax Compendium
+ [[To do this...] [Use this...] [See this...]]
+ [[comment] [[^'''[/ some comment]''']] [__comments__]]
+ [[['italics]] [[^'''['italics] or /italics/''']] [__font_styles__ and __simple_formatting__]]
+ [[[*bold]] [[^'''[*bold] or *bold*''']] [__font_styles__ and __simple_formatting__]]
+ [[[_underline]] [[^'''[_underline] or _underline_''']] [__font_styles__ and __simple_formatting__]]
+ [[[^teletype]] [[^'''[^teletype] or =teletype=''']] [__font_styles__ and __simple_formatting__]]
+ [[[-strikethrough]] [[^'''[-strikethrough]''']] [__font_styles__ and __simple_formatting__]]
+ [[[~replaceable]] [[^'''[~replaceable]''']] [__replaceable__]]
+ [[source mode] [[^\[c++\]] or [^\[python\]]] [__source_mode__]]
+ [[inline code] [[^'''`int main();`''']] [__inline_code__]]
+ [[code block] [[^'''``int main();``''']] [__code__]]
+ [[code escape] [[^'''``from c++ to QuickBook``''']] [__escape_back__]]
+ [[line break] [[^'''[br] or \n''']] [__line_break__ *DEPRECATED*]]
+ [[anchor] [[^'''[#anchor]''']] [__anchors__]]
+ [[link] [[^'''[@http://www.boost.org Boost]''']] [__links__]]
+ [[anchor link] [[^'''[link section.anchor Link text]''']] [__anchor_links__]]
+ [[refentry link] [[^'''[link xml.refentry Link text]''']] [__refentry_links__]]
+ [[function link] [[^'''[funcref fully::qualified::function_name Link text]''']] [__code_links__]]
+ [[class link] [[^'''[classref fully::qualified::class_name Link text]''']] [__code_links__]]
+ [[member link] [[^'''[memberref fully::qualified::member_name Link text]''']] [__code_links__]]
+ [[enum link] [[^'''[enumref fully::qualified::enum_name Link text]''']] [__code_links__]]
+ [[macro link] [[^'''[macroref MACRO_NAME Link text]''']] [__code_links__]]
+ [[concept link] [[^'''[conceptref ConceptName Link text]''']] [__code_links__]]
+ [[header link] [[^'''[headerref path/to/header.hpp Link text]''']] [__code_links__]]
+ [[escape] [[^\'\'\'escaped text (no processing/formatting)\'\'\']] [__escape__]]
+ [[single char escape] [[^\\c]] [__single_char_escape__]]
+ [[images] [[^'''[$image.jpg]''']] [__images__]]
+ [[begin section] [[^'''[section The Section Title]''']] [__section__]]
+ [[end section] [[^'''[endsect]''']] [__section__]]
+ [[paragraph] [No markup. Paragraphs start left-flushed and are terminated by two or more newlines.] [__paragraphs__]]
+ [[ordered list] [[ordered_list_sample]] [__ordered_lists__]]
+ [[unordered list] [[unordered_list_sample]] [__unordered_lists__]]
+ [[code] [No markup. Preformatted code starts with a space or a tab.] [__code__]]
+ [[preformatted] [[^'''[pre preformatted]''']] [__preformatted__]]
+ [[block quote] [[^'''[:sometext...]''']] [__blockquote__]]
+ [[heading 1] [[^'''[h1 Heading 1]''']] [__heading__]]
+ [[heading 2] [[^'''[h2 Heading 2]''']] [__heading__]]
+ [[heading 3] [[^'''[h3 Heading 3]''']] [__heading__]]
+ [[heading 4] [[^'''[h4 Heading 4]''']] [__heading__]]
+ [[heading 5] [[^'''[h5 Heading 5]''']] [__heading__]]
+ [[heading 6] [[^'''[h6 Heading 6]''']] [__heading__]]
+ [[macro] [[^'''[def macro_identifier some text]''']] [__macros__]]
+ [[template] [[^'''[template[a b] [a] body [b]]''']] [__templates__]]
+ [[blurb] [[^'''[blurb advertisement or note...]''']] [__blurbs__]]
+ [[admonition] [[^'''[warning Warning text...]''']] [__admonitions__]]
+ [[table] [[table_sample]] [__tables__]]
+ [[variablelist] [[var_list_sample]] [__variable_lists__]]
+ [[include] [[^'''[include someother.qbk]''']] [__include__]]
+]
+
+[endsect]
diff --git a/tools/quickbook/test/role-1_6.gold b/tools/quickbook/test/role-1_6.gold
new file mode 100644
index 0000000000..bdb4b58ef3
--- /dev/null
+++ b/tools/quickbook/test/role-1_6.gold
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="quickbook_role_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Quickbook Role Test</title>
+ <para>
+ <phrase role="keyword">Keyword</phrase> <phrase role="keyword"></phrase> [role]
+ </para>
+</article>
diff --git a/tools/quickbook/test/role-1_6.quickbook b/tools/quickbook/test/role-1_6.quickbook
new file mode 100644
index 0000000000..0982b9cd96
--- /dev/null
+++ b/tools/quickbook/test/role-1_6.quickbook
@@ -0,0 +1,5 @@
+[article Quickbook Role Test
+[quickbook 1.6]
+]
+
+[role keyword Keyword] [role keyword] [role]
diff --git a/tools/quickbook/test/section-1_4.gold b/tools/quickbook/test/section-1_4.gold
new file mode 100644
index 0000000000..07ba43a2cd
--- /dev/null
+++ b/tools/quickbook/test/section-1_4.gold
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="section_id_1_4" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Section Id 1.4</title>
+ <section id="section_id_1_4.id_test1">
+ <title><link linkend="section_id_1_4.id_test1">Quickbook section id test</link></title>
+ </section>
+ <section id="section_id_1_4.id_test2">
+ <title><link linkend="section_id_1_4.id_test2">Quickbook section id test</link></title>
+ </section>
+ <section id="section_id_1_4.quickbook_section_no_id_test_1">
+ <title><link linkend="section_id_1_4.quickbook_section_no_id_test_1">Quickbook
+ section no id test 1</link></title>
+ </section>
+ <section id="section_id_1_4.___quickbook_section_no_id_test_2">
+ <title><link linkend="section_id_1_4.___quickbook_section_no_id_test_2">++ Quickbook
+ section no id test 2</link></title>
+ </section>
+</article>
diff --git a/tools/quickbook/test/section-1_4.quickbook b/tools/quickbook/test/section-1_4.quickbook
new file mode 100644
index 0000000000..8cf55866fe
--- /dev/null
+++ b/tools/quickbook/test/section-1_4.quickbook
@@ -0,0 +1,12 @@
+[article Section Id 1.4
+ [quickbook 1.4]
+]
+
+[section:id_test1 Quickbook section id test]
+[endsect]
+[section :id_test2 Quickbook section id test]
+[endsect]
+[section: Quickbook section no id test 1]
+[endsect]
+[section:++ Quickbook section no id test 2]
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/section-1_5-unclosed.gold b/tools/quickbook/test/section-1_5-unclosed.gold
new file mode 100644
index 0000000000..b86c556ec6
--- /dev/null
+++ b/tools/quickbook/test/section-1_5-unclosed.gold
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="unclosed_section" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Unclosed section</title>
+ <section id="unclosed_section.unclosed">
+ <title><link linkend="unclosed_section.unclosed">Unclosed Section should be closed
+ with a warning</link></title>
+ </section>
+</article>
diff --git a/tools/quickbook/test/section-1_5-unclosed.quickbook b/tools/quickbook/test/section-1_5-unclosed.quickbook
new file mode 100644
index 0000000000..49b70f4914
--- /dev/null
+++ b/tools/quickbook/test/section-1_5-unclosed.quickbook
@@ -0,0 +1,5 @@
+[article Unclosed section
+[quickbook 1.5]
+]
+
+[section:unclosed Unclosed Section should be closed with a warning] \ No newline at end of file
diff --git a/tools/quickbook/test/section-1_5.gold b/tools/quickbook/test/section-1_5.gold
new file mode 100644
index 0000000000..13ec9eba29
--- /dev/null
+++ b/tools/quickbook/test/section-1_5.gold
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="section_id_1_5" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Section Id 1.5</title>
+ <section id="section_id_1_5.id_test1">
+ <title><link linkend="section_id_1_5.id_test1">Quickbook section id test</link></title>
+ </section>
+ <section id="section_id_1_5.id_test2">
+ <title><link linkend="section_id_1_5.id_test2">Quickbook section id test</link></title>
+ </section>
+ <section id="section_id_1_5.id_test3">
+ <title><link linkend="section_id_1_5.id_test3">Quickbook section id test</link></title>
+ </section>
+ <section id="section_id_1_5.___quickbook_section_no_id_test">
+ <title><link linkend="section_id_1_5.___quickbook_section_no_id_test">++ Quickbook
+ section no id test</link></title>
+ </section>
+</article>
diff --git a/tools/quickbook/test/section-1_5.quickbook b/tools/quickbook/test/section-1_5.quickbook
new file mode 100644
index 0000000000..812c40161c
--- /dev/null
+++ b/tools/quickbook/test/section-1_5.quickbook
@@ -0,0 +1,12 @@
+[article Section Id 1.5
+ [quickbook 1.5]
+]
+
+[section:id_test1 Quickbook section id test]
+[endsect]
+[section :id_test2 Quickbook section id test]
+[endsect]
+[section: id_test3 Quickbook section id test]
+[endsect]
+[section:++ Quickbook section no id test]
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/simple_markup-1_5.gold b/tools/quickbook/test/simple_markup-1_5.gold
new file mode 100644
index 0000000000..4d044ceb4b
--- /dev/null
+++ b/tools/quickbook/test/simple_markup-1_5.gold
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="simple_markup_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Simple Markup Test</title>
+ <section id="simple_markup_test.simple_markup">
+ <title><link linkend="simple_markup_test.simple_markup">Simple Markup</link></title>
+ <para>
+ <emphasis>italic</emphasis> <emphasis role="bold">bold</emphasis> <emphasis
+ role="underline">underline</emphasis> <literal>teletype</literal>
+ </para>
+ <para>
+ //not italic// **not bold** __not underline__ ==not teletype==
+ </para>
+ <para>
+ <emphasis role="underline">odd__ edge case</emphasis>
+ </para>
+ <para>
+ not__underlined__hopefully
+ </para>
+ <para>
+ (<emphasis role="bold">bold</emphasis>) <emphasis role="underline">und/er/lined</emphasis>
+ </para>
+ <para>
+ <emphasis>all/italic</emphasis> * not bold*
+ </para>
+ <para>
+ /not italic <ulink url="http://www.boost.org/"><emphasis role="bold">bold</emphasis></ulink>
+ </para>
+ <para>
+ not_underlined_
+ </para>
+ <para>
+ _Should not underline escaped markup_. _or this escaped_ markup form.
+ </para>
+ <para>
+ <literal>Matti Meik\u00E4l\u00E4inen</literal>
+ </para>
+ <para>
+ <literal>replaced</literal>
+ </para>
+ <para>
+ <emphasis role="underline">replaced</emphasis>
+ </para>
+ <para>
+ <literal>_mac\ ro_</literal>
+ </para>
+ <para>
+ <emphasis>italic\</emphasis>
+ </para>
+ <para>
+ These shouldn't be interepted as markup: == // **
+ </para>
+ <para>
+ <literal>&lt;</literal> <literal>\&lt;</literal> <literal>\\&lt;</literal>
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/simple_markup-1_5.quickbook b/tools/quickbook/test/simple_markup-1_5.quickbook
new file mode 100644
index 0000000000..c8277fb328
--- /dev/null
+++ b/tools/quickbook/test/simple_markup-1_5.quickbook
@@ -0,0 +1,42 @@
+[article Simple Markup Test
+[quickbook 1.5]
+]
+
+[def _macro_ replaced]
+
+[section Simple Markup]
+
+/italic/ *bold* _underline_ =teletype=
+
+//not italic// **not bold** __not underline__ ==not teletype==
+
+_odd__ edge case_
+
+not__underlined__hopefully
+
+(*bold*) _und/er/lined_
+
+/all/italic/ * not bold*
+
+/not italic [@http://www.boost.org/ *bold*]
+
+not_underlined_
+
+_Should not underline '''escaped''' markup_.
+_or this '''escaped_ markup''' form.
+
+=Matti Meik\u00E4l\u00E4inen=
+
+=_macro_=
+
+__macro__
+
+=_mac\ ro_=
+
+/italic\/
+
+These shouldn't be interepted as markup: == // **
+
+=<= =\<= =\\<=
+
+[endsect]
diff --git a/tools/quickbook/test/snippets/Jamfile.v2 b/tools/quickbook/test/snippets/Jamfile.v2
new file mode 100644
index 0000000000..4dfd0d0e8f
--- /dev/null
+++ b/tools/quickbook/test/snippets/Jamfile.v2
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2011 Daniel James
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+project quickook/tests/snippets ;
+
+import quickbook-testing : quickbook-test quickbook-error-test ;
+
+test-suite quickbook.test :
+ [ quickbook-test pass_thru ]
+ [ quickbook-test unbalanced_snippet1-1_5 ]
+ [ quickbook-error-test unbalanced_snippet1-1_6-fail ]
+ [ quickbook-error-test unbalanced_snippet2-1_6-fail ]
+ ;
diff --git a/tools/quickbook/test/snippets/pass_thru.cpp b/tools/quickbook/test/snippets/pass_thru.cpp
new file mode 100644
index 0000000000..4d729d3599
--- /dev/null
+++ b/tools/quickbook/test/snippets/pass_thru.cpp
@@ -0,0 +1,31 @@
+//[foo_cpp_copyright
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+//]
+
+//[foo_cpp
+struct Foo{
+
+ Foo()//=;
+//<-
+ : x( 10 )
+ {}
+//->
+
+//<-
+ int x;
+//->
+};
+
+/*=
+int main()
+{
+ Foo x;
+}
+*/
+//]
diff --git a/tools/quickbook/test/snippets/pass_thru.gold b/tools/quickbook/test/snippets/pass_thru.gold
new file mode 100644
index 0000000000..dde5deb19c
--- /dev/null
+++ b/tools/quickbook/test/snippets/pass_thru.gold
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="pass_thru_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Pass thru test</title>
+ <para>
+<programlisting><phrase role="comment">/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/</phrase>
+</programlisting>
+ </para>
+ <para>
+<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">Foo</phrase><phrase role="special">{</phrase>
+
+ <phrase role="identifier">Foo</phrase><phrase role="special">();</phrase>
+
+<phrase role="special">};</phrase>
+
+
+<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">Foo</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ </para>
+ <para>
+<programlisting><phrase role="keyword">def</phrase> <phrase role="identifier">foo</phrase><phrase role="special">:</phrase>
+ <phrase role="keyword">print</phrase><phrase role="special">(</phrase><phrase role="string">'foo'</phrase><phrase role="special">)</phrase>
+</programlisting>
+ </para>
+</article>
diff --git a/tools/quickbook/test/snippets/pass_thru.py b/tools/quickbook/test/snippets/pass_thru.py
new file mode 100644
index 0000000000..412cee420f
--- /dev/null
+++ b/tools/quickbook/test/snippets/pass_thru.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2011 Daniel James
+#
+# Use, modification and distribution is subject to the Boost Software
+# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+#[foo_py
+def foo:
+ #=print('foo')
+ #<-
+ print('bar')
+ #->
+#] \ No newline at end of file
diff --git a/tools/quickbook/test/snippets/pass_thru.quickbook b/tools/quickbook/test/snippets/pass_thru.quickbook
new file mode 100644
index 0000000000..7e83194784
--- /dev/null
+++ b/tools/quickbook/test/snippets/pass_thru.quickbook
@@ -0,0 +1,12 @@
+[article Pass thru test
+[quickbook 1.5]
+]
+
+[import pass_thru.cpp]
+[import pass_thru.py]
+
+[foo_cpp_copyright]
+
+[foo_cpp]
+
+[foo_py] \ No newline at end of file
diff --git a/tools/quickbook/test/snippets/unbalanced_snippet1-1_5.gold b/tools/quickbook/test/snippets/unbalanced_snippet1-1_5.gold
new file mode 100644
index 0000000000..1f9115c0f5
--- /dev/null
+++ b/tools/quickbook/test/snippets/unbalanced_snippet1-1_5.gold
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="unbalanced_snippet_fail_test_1" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Unbalanced snippet fail test 1</title>
+ <para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase>
+</programlisting>
+ </para>
+</article>
diff --git a/tools/quickbook/test/snippets/unbalanced_snippet1-1_5.quickbook b/tools/quickbook/test/snippets/unbalanced_snippet1-1_5.quickbook
new file mode 100644
index 0000000000..7fdde6afdd
--- /dev/null
+++ b/tools/quickbook/test/snippets/unbalanced_snippet1-1_5.quickbook
@@ -0,0 +1,8 @@
+[article Unbalanced snippet fail test 1
+[quickbook 1.5]
+]
+
+[import unbalanced_snippet1.cpp]
+[import unbalanced_snippet2.cpp]
+
+[unclosed] \ No newline at end of file
diff --git a/tools/quickbook/test/snippets/unbalanced_snippet1-1_6-fail.quickbook b/tools/quickbook/test/snippets/unbalanced_snippet1-1_6-fail.quickbook
new file mode 100644
index 0000000000..c2fb98ec0a
--- /dev/null
+++ b/tools/quickbook/test/snippets/unbalanced_snippet1-1_6-fail.quickbook
@@ -0,0 +1,7 @@
+[article Unbalanced snippet fail test 1
+[quickbook 1.6]
+]
+
+[import unbalanced_snippet1.cpp]
+
+[unclosed] \ No newline at end of file
diff --git a/tools/quickbook/test/snippets/unbalanced_snippet1.cpp b/tools/quickbook/test/snippets/unbalanced_snippet1.cpp
new file mode 100644
index 0000000000..ec49a78878
--- /dev/null
+++ b/tools/quickbook/test/snippets/unbalanced_snippet1.cpp
@@ -0,0 +1,3 @@
+//[unclosed
+
+int main() {} \ No newline at end of file
diff --git a/tools/quickbook/test/snippets/unbalanced_snippet2-1_6-fail.quickbook b/tools/quickbook/test/snippets/unbalanced_snippet2-1_6-fail.quickbook
new file mode 100644
index 0000000000..a06a16448b
--- /dev/null
+++ b/tools/quickbook/test/snippets/unbalanced_snippet2-1_6-fail.quickbook
@@ -0,0 +1,5 @@
+[article Unbalanced snippet fail test 2
+[quickbook 1.6]
+]
+
+[import unbalanced_snippet2.cpp]
diff --git a/tools/quickbook/test/snippets/unbalanced_snippet2.cpp b/tools/quickbook/test/snippets/unbalanced_snippet2.cpp
new file mode 100644
index 0000000000..b0575171ea
--- /dev/null
+++ b/tools/quickbook/test/snippets/unbalanced_snippet2.cpp
@@ -0,0 +1 @@
+//] \ No newline at end of file
diff --git a/tools/quickbook/test/src/Jamfile.v2 b/tools/quickbook/test/src/Jamfile.v2
new file mode 100644
index 0000000000..f90ba25d71
--- /dev/null
+++ b/tools/quickbook/test/src/Jamfile.v2
@@ -0,0 +1,9 @@
+#
+# Copyright (c) 2011 Daniel James
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+exe line-compare-tool : text_diff.cpp ;
diff --git a/tools/quickbook/test/src/text_diff.cpp b/tools/quickbook/test/src/text_diff.cpp
new file mode 100644
index 0000000000..bcac672cba
--- /dev/null
+++ b/tools/quickbook/test/src/text_diff.cpp
@@ -0,0 +1,84 @@
+//
+// Copyright (c) 2005 João Abecasis
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <fstream>
+#include <iostream>
+#include <iterator>
+
+#include <boost/spirit/include/classic_scanner.hpp>
+#include <boost/spirit/include/classic_primitives.hpp>
+
+namespace spirit = boost::spirit::classic;
+
+typedef std::istream_iterator<char, char> iterator;
+typedef spirit::scanner<iterator> scanner;
+
+int main(int argc, char * argv[])
+{
+ if (argc != 3)
+ {
+ std::cerr << "ERROR: Wrong number of arguments." << std::endl;
+ std::cout << "Usage:\n\t" << argv[0] << " file1 file2" << std::endl;
+
+ return 1;
+ }
+
+ std::ifstream
+ file1(argv[1], std::ios_base::binary | std::ios_base::in),
+ file2(argv[2], std::ios_base::binary | std::ios_base::in);
+
+ if (!file1 || !file2)
+ {
+ std::cerr << "ERROR: Unable to open one or both files." << std::endl;
+ return 2;
+ }
+
+ file1.unsetf(std::ios_base::skipws);
+ file2.unsetf(std::ios_base::skipws);
+
+ iterator
+ iter_file1(file1),
+ iter_file2(file2);
+
+ scanner
+ scan1(iter_file1, iterator()),
+ scan2(iter_file2, iterator());
+
+ std::size_t line = 1, column = 1;
+
+ while (!scan1.at_end() && !scan2.at_end())
+ {
+ if (spirit::eol_p.parse(scan1))
+ {
+ if (!spirit::eol_p.parse(scan2))
+ {
+ std::cout << "Files differ at line " << line << ", column " <<
+ column << '.' << std::endl;
+ return 3;
+ }
+
+ ++line, column = 1;
+ continue;
+ }
+
+ if (*scan1 != *scan2)
+ {
+ std::cout << "Files differ at line " << line << ", column " <<
+ column << '.' << std::endl;
+ return 4;
+ }
+
+ ++scan1, ++scan2, ++column;
+ }
+
+ if (scan1.at_end() != scan2.at_end())
+ {
+ std::cout << "Files differ in length." << std::endl;
+ return 5;
+ }
+}
diff --git a/tools/quickbook/test/stub.c b/tools/quickbook/test/stub.c
new file mode 100644
index 0000000000..f7f83cfe8d
--- /dev/null
+++ b/tools/quickbook/test/stub.c
@@ -0,0 +1,32 @@
+/*=============================================================================
+ Copyright (c) 2006 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+/*`
+This should appear when =stub.c= is included.
+
+[foo_c]
+*/
+
+/*[foo_c */
+ /*`
+ This is the C [*['foo]] function.
+
+ This description can have paragraphs...
+
+ * lists
+ * etc.
+
+ And any quickbook block markup.
+ */
+char* foo()
+{
+ // return 'em, foo man!
+ return "foo";
+}
+/*]*/
diff --git a/tools/quickbook/test/stub.cpp b/tools/quickbook/test/stub.cpp
new file mode 100644
index 0000000000..358f291e3f
--- /dev/null
+++ b/tools/quickbook/test/stub.cpp
@@ -0,0 +1,84 @@
+/*=============================================================================
+ Copyright (c) 2006 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+/*` This should appear when =stub.cpp= is included. */
+
+#include <string>
+
+//[ bar
+//` This is the [*/bar/] function
+std::string bar()
+{
+ // return 'em, bar man!
+ return "bar";
+}
+/*`
+Some trailing text here
+*/
+//]
+
+//[ foo
+ /*`
+ This is the [*['foo]] function.
+
+ This description can have paragraphs...
+
+ * lists
+ * etc.
+
+ And any quickbook block markup.
+ */
+std::string foo()
+{
+ // return 'em, foo man!
+ return "foo";
+}
+//]
+
+//[ foo_bar
+std::string foo_bar() /*< The /Mythical/ FooBar.
+ See [@http://en.wikipedia.org/wiki/Foobar Foobar for details] >*/
+{
+ return "foo-bar"; /*< return 'em, foo-bar man! >*/
+}
+//]
+
+//[ class_
+class x
+{
+public:
+
+ /*<< Constructor >>*/
+ x() : n(0)
+ {
+ }
+
+ /*<< Destructor >>*/
+ ~x()
+ {
+ }
+
+ /*<< Get the `n` member variable >>*/
+ int get() const
+ {
+ return n; /*<- this will be ignored by quickbook ->*/
+ }
+
+ /*<< Set the `n` member variable >>*/
+ void set(int n_)
+ {
+ n = n_;
+ }
+//<- this will be ignored by quickbook
+private:
+
+ int n;
+//->
+};
+//]
diff --git a/tools/quickbook/test/stub.py b/tools/quickbook/test/stub.py
new file mode 100644
index 0000000000..48ba87e0c5
--- /dev/null
+++ b/tools/quickbook/test/stub.py
@@ -0,0 +1,27 @@
+# Copyright 2009 Daniel James
+#
+# Use, modification and distribution is subject to the Boost Software
+# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+#` This should appear when =stub.py= is included.
+
+#[foo_py
+"""`
+ This is the Python [*['foo]] function.
+
+ This description can have paragraphs...
+
+ * lists
+ * etc.
+
+ And any quickbook block markup.
+"""
+
+def foo():
+ # return 'em, foo man!
+ return "foo"
+
+#]
+
+print foo() \ No newline at end of file
diff --git a/tools/quickbook/test/svg-1_1.gold b/tools/quickbook/test/svg-1_1.gold
new file mode 100644
index 0000000000..a8a49b06a0
--- /dev/null
+++ b/tools/quickbook/test/svg-1_1.gold
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="svg_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>SVG test</title>
+ <para>
+ <inlinemediaobject><imageobject><imagedata contentdepth="513.25690" contentwidth="745.60706"
+ fileref="images/open_clipart_library_logo.svg" format="SVG"></imagedata></imageobject>
+ <textobject>
+ <phrase>open_clipart_library_logo</phrase>
+ </textobject>
+ </inlinemediaobject> <inlinemediaobject><imageobject><imagedata fileref="images/missing_image.svg"
+ format="SVG"></imagedata></imageobject>
+ <textobject>
+ <phrase>missing_image</phrase>
+ </textobject>
+ </inlinemediaobject>
+ </para>
+</article>
diff --git a/tools/quickbook/test/svg-1_1.quickbook b/tools/quickbook/test/svg-1_1.quickbook
new file mode 100644
index 0000000000..71b811a8c9
--- /dev/null
+++ b/tools/quickbook/test/svg-1_1.quickbook
@@ -0,0 +1,4 @@
+[article SVG test]
+
+[$images/open_clipart_library_logo.svg]
+[$images/missing_image.svg]
diff --git a/tools/quickbook/test/table-1_3.gold b/tools/quickbook/test/table-1_3.gold
new file mode 100644
index 0000000000..fcda215702
--- /dev/null
+++ b/tools/quickbook/test/table-1_3.gold
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="table_tests" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Table 1.3</title>
+ <table frame="all" id="table_tests.t0">
+ <title>Table 2</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="table_tests.t1">
+ <title>Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.t2">
+ <title>Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.t3">
+ <title>Title [/ ] containing a comment</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.t4">
+ <title>Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.t5">
+ <title>[[Title]]</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <section id="table_tests.section1">
+ <title><link linkend="table_tests.section1">Section 1</link></title>
+ <table frame="all" id="table_tests.section1.t0">
+ <title>A &amp; B</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ A
+ </para>
+ </entry>
+ <entry>
+ <para>
+ B
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ a
+ </para>
+ </entry>
+ <entry>
+ <para>
+ b
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.t1">
+ <title>Empty Table</title>
+ <tgroup cols="0">
+ <tbody>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.t2">
+ <title>Table with an empty cell</title>
+ <tgroup cols="1">
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ x
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.t3">
+ <title>Indentation</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Header 1. Paragraph 1
+ </para>
+ <para>
+ Header 1. Paragraph 2
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Header 2
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ Row 1. Cell 1.
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Row 1. Cell 2.
+ </para>
+ <para>
+ Row 1. Cell 2. Paragraph 2.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.t4">
+ <title>Nested Tables</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Header 1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Header 2
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <table frame="all" id="table_tests.section1.t5">
+ <title>Inner Table</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ 1.1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ 1.2
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ 2.1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ 2.2
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Something.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <anchor id="id1"/>
+ <table frame="all" id="table_tests.section1.t6">
+ <title>Table with anchors</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ <anchor id="id2"/>a<anchor id="id3"/>
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ b
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+</article>
diff --git a/tools/quickbook/test/table-1_3.quickbook b/tools/quickbook/test/table-1_3.quickbook
new file mode 100644
index 0000000000..1dc0489114
--- /dev/null
+++ b/tools/quickbook/test/table-1_3.quickbook
@@ -0,0 +1,113 @@
+[article Table 1.3
+ [quickbook 1.3]
+ [id table_tests]
+]
+
+[table Table 2
+ [[Heading]]
+ [[cell]]
+]
+
+[table
+ [[Heading]]
+ [[cell]]
+]
+
+[table [/ Comment?] Title
+ [[Heading]]
+ [[cell]]
+]
+
+[table [/ Multi line
+comment] Title
+ [[Heading]]
+ [[cell]]
+]
+
+[table Title [/ ] containing a comment
+ [[Heading]]
+ [[cell]]
+]
+
+[/ These two might be considered to be a bug. ]
+
+[table [/ Multi line
+comment]
+ Title
+ [[Heading]]
+ [[cell]]
+]
+
+[table [/ Multi line
+comment]
+ [[Title]]
+ [[Heading]]
+ [[cell]]
+]
+
+[section:section1 Section 1]
+
+[table A & B
+ [[A][B]]
+ [[a][b]]
+]
+
+[table Empty Table
+]
+
+[table Table with an empty cell
+[[x]]]
+
+[table Indentation
+ [
+ [
+ Header 1. Paragraph 1
+
+ Header 1. Paragraph 2
+ ]
+ [
+ Header 2
+ ]
+ ]
+ [
+ [
+ Row 1. Cell 1.
+ ]
+ [
+ Row 1. Cell 2.
+
+ Row 1. Cell 2. Paragraph 2.
+ ]
+ ]
+]
+
+[table Nested Tables
+ [
+ [
+ Header 1
+ ]
+ [
+ Header 2
+ ]
+ ]
+ [
+ [
+ [table Inner Table
+ [[1.1][1.2]]
+ [[2.1][2.2]]
+ ]
+ ]
+ ]
+ [
+ [
+ Something.
+ ]
+ ]
+]
+
+[#id1]
+[table Table with anchors
+[[[#id2]a[#id3]]][[b]]
+]
+
+[endsect]
diff --git a/tools/quickbook/test/table-1_5.gold b/tools/quickbook/test/table-1_5.gold
new file mode 100644
index 0000000000..838a400fab
--- /dev/null
+++ b/tools/quickbook/test/table-1_5.gold
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="table_tests" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Table 1.5</title>
+ <table frame="all" id="table_tests.table1">
+ <title>Table 1</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.table_2">
+ <title>Table 2</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="table_tests.table4">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="table_tests._table5_">
+ <title>-table5-</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.title">
+ <title>Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.title0">
+ <title>Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.title_______containing_a_comment">
+ <title>Title [/ ] containing a comment</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.title1">
+ <title>Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.__title__">
+ <title>[[Title]]</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <section id="table_tests.section1">
+ <title><link linkend="table_tests.section1">Section 1</link></title>
+ <table frame="all" id="table_tests.section1.table1">
+ <title>Table 1</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.a___b">
+ <title>A &amp; B</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ A
+ </para>
+ </entry>
+ <entry>
+ <para>
+ B
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ a
+ </para>
+ </entry>
+ <entry>
+ <para>
+ b
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.empty_table">
+ <title>Empty Table</title>
+ <tgroup cols="0">
+ <tbody>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.table_with_an_empty_cell">
+ <title>Table with an empty cell</title>
+ <tgroup cols="1">
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ x
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.indentation">
+ <title>Indentation</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Header 1. Paragraph 1
+ </para>
+ <para>
+ Header 1. Paragraph 2
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Header 2
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ Row 1. Cell 1.
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Row 1. Cell 2.
+ </para>
+ <para>
+ Row 1. Cell 2. Paragraph 2.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.nested_tables">
+ <title>Nested Tables</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Header 1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Header 2
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <table frame="all" id="table_tests.section1.inner_table">
+ <title>Inner Table</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ 1.1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ 1.2
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ 2.1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ 2.2
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Something.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <anchor id="id1"/>
+ <table frame="all" id="table_tests.section1.table_with_anchors">
+ <title>Table with anchors</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ <anchor id="id2"/>a<anchor id="id3"/>
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ b
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+</article>
diff --git a/tools/quickbook/test/table-1_5.quickbook b/tools/quickbook/test/table-1_5.quickbook
new file mode 100644
index 0000000000..7ab15b1aca
--- /dev/null
+++ b/tools/quickbook/test/table-1_5.quickbook
@@ -0,0 +1,133 @@
+[article Table 1.5
+ [quickbook 1.5]
+ [id table_tests]
+]
+
+[table:table1 Table 1
+ [[Heading]]
+ [[cell]]
+]
+
+[table Table 2
+ [[Heading]]
+ [[cell]]
+]
+
+[table
+ [[Heading]]
+ [[cell]]
+]
+
+[table:table4
+ [[Heading]]
+ [[cell]]
+]
+
+[table:-table5-
+ [[Heading]]
+ [[cell]]
+]
+
+[table [/ Comment?] Title
+ [[Heading]]
+ [[cell]]
+]
+
+[table [/ Multi line
+comment] Title
+ [[Heading]]
+ [[cell]]
+]
+
+[table Title [/ ] containing a comment
+ [[Heading]]
+ [[cell]]
+]
+
+[/ These two might be considered to be a bug. ]
+
+[table [/ Multi line
+comment]
+ Title
+ [[Heading]]
+ [[cell]]
+]
+
+[table [/ Multi line
+comment]
+ [[Title]]
+ [[Heading]]
+ [[cell]]
+]
+
+[section:section1 Section 1]
+
+[table:table1 Table 1
+ [[Heading]]
+ [[cell]]
+]
+
+[table A & B
+ [[A][B]]
+ [[a][b]]
+]
+
+[table Empty Table
+]
+
+[table Table with an empty cell
+[[x]]]
+
+[table Indentation
+ [
+ [
+ Header 1. Paragraph 1
+
+ Header 1. Paragraph 2
+ ]
+ [
+ Header 2
+ ]
+ ]
+ [
+ [
+ Row 1. Cell 1.
+ ]
+ [
+ Row 1. Cell 2.
+
+ Row 1. Cell 2. Paragraph 2.
+ ]
+ ]
+]
+
+[table Nested Tables
+ [
+ [
+ Header 1
+ ]
+ [
+ Header 2
+ ]
+ ]
+ [
+ [
+ [table Inner Table
+ [[1.1][1.2]]
+ [[2.1][2.2]]
+ ]
+ ]
+ ]
+ [
+ [
+ Something.
+ ]
+ ]
+]
+
+[#id1]
+[table Table with anchors
+[[[#id2]a[#id3]]][[b]]
+]
+
+[endsect]
diff --git a/tools/quickbook/test/table-1_6.gold b/tools/quickbook/test/table-1_6.gold
new file mode 100644
index 0000000000..3abe6b0d20
--- /dev/null
+++ b/tools/quickbook/test/table-1_6.gold
@@ -0,0 +1,478 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="table_tests" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Table 1.6</title>
+ <table frame="all" id="table_tests.table1">
+ <title>Table 1</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.table_2">
+ <title>Table 2</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <informaltable frame="all" id="table_tests.table4">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="table_tests.table5">
+ <title>-table5-</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.title">
+ <title>Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.title0">
+ <title>Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.title_containing_a_comment">
+ <title>Title containing a comment</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.title1">
+ <title>Title</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <informaltable frame="all">
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ Cell 1
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Cell 2
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <table frame="all" id="table_tests.title_on_multiple_lines_with_bol">
+ <title>Title on multiple lines with <emphasis role="bold">bold</emphasis> text?</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ Cell 1
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Cell 2
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <section id="table_tests.section1">
+ <title><link linkend="table_tests.section1">Section 1</link></title>
+ <table frame="all" id="table_tests.section1.table1">
+ <title>Table 1</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Heading
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ cell
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.a_b">
+ <title>A &amp; B</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ A
+ </para>
+ </entry>
+ <entry>
+ <para>
+ B
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ a
+ </para>
+ </entry>
+ <entry>
+ <para>
+ b
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.empty_table">
+ <title>Empty Table</title>
+ <tgroup cols="0">
+ <tbody>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.table_with_an_empty_cell">
+ <title>Table with an empty cell</title>
+ <tgroup cols="1">
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ x
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.indentation">
+ <title>Indentation</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Header 1. Paragraph 1
+ </para>
+ <para>
+ Header 1. Paragraph 2
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Header 2
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ Row 1. Cell 1.
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Row 1. Cell 2.
+ </para>
+ <para>
+ Row 1. Cell 2. Paragraph 2.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="all" id="table_tests.section1.nested_tables">
+ <title>Nested Tables</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ Header 1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ Header 2
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <table frame="all" id="table_tests.section1.inner_table">
+ <title>Inner Table</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ 1.1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ 1.2
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ 2.1
+ </para>
+ </entry>
+ <entry>
+ <para>
+ 2.2
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>
+ Something.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <anchor id="id1"/>
+ <table frame="all" id="table_tests.section1.table_with_anchors">
+ <title>Table with anchors</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry>
+ <para>
+ <anchor id="id2"/>a<anchor id="id3"/>
+ </para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ b
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+</article>
diff --git a/tools/quickbook/test/table-1_6.quickbook b/tools/quickbook/test/table-1_6.quickbook
new file mode 100644
index 0000000000..332e07060c
--- /dev/null
+++ b/tools/quickbook/test/table-1_6.quickbook
@@ -0,0 +1,134 @@
+[article Table 1.6
+ [quickbook 1.6]
+ [id table_tests]
+]
+
+[table:table1 Table 1 [[Heading]][[cell]]]
+
+[table Table 2
+ [[Heading]]
+ [[cell]]
+]
+
+[table
+ [[Heading]]
+ [[cell]]
+]
+
+[table:table4
+ [[Heading]]
+ [[cell]]
+]
+
+[table:-table5-
+ [[Heading]]
+ [[cell]]
+]
+
+[table [/ Comment?] Title
+ [[Heading]]
+ [[cell]]
+]
+
+[table [/ Multi line
+comment] Title
+ [[Heading]]
+ [[cell]]
+]
+
+[table Title [/ ] containing a comment
+ [[Heading]]
+ [[cell]]
+]
+
+[table [/ Multi line
+comment]
+ Title
+ [[Heading]]
+ [[cell]]
+]
+
+[table [/ Multi line
+comment]
+ [[Heading]]
+ [[Cell 1]]
+ [[Cell 2]]
+]
+
+[table Title on multiple
+ lines with *bold* text?
+ [[Heading]]
+ [[Cell 1]]
+ [[Cell 2]]
+]
+
+[section:section1 Section 1]
+
+[table:table1 Table 1
+ [[Heading]]
+ [[cell]]
+]
+
+[table A & B
+ [[A][B]]
+ [[a][b]]
+]
+
+[table Empty Table]
+
+[table Table with an empty cell
+[[x]]]
+
+[table Indentation
+ [
+ [
+ Header 1. Paragraph 1
+
+ Header 1. Paragraph 2
+ ]
+ [
+ Header 2
+ ]
+ ]
+ [
+ [
+ Row 1. Cell 1.
+ ]
+ [
+ Row 1. Cell 2.
+
+ Row 1. Cell 2. Paragraph 2.
+ ]
+ ]
+]
+
+[table Nested Tables
+ [
+ [
+ Header 1
+ ]
+ [
+ Header 2
+ ]
+ ]
+ [
+ [
+ [table Inner Table
+ [[1.1][1.2]]
+ [[2.1][2.2]]
+ ]
+ ]
+ ]
+ [
+ [
+ Something.
+ ]
+ ]
+]
+
+[#id1]
+[table Table with anchors
+[[[#id2]a[#id3]]][[b]]
+]
+
+[endsect]
diff --git a/tools/quickbook/test/template_arguments1-1_1-fail.quickbook b/tools/quickbook/test/template_arguments1-1_1-fail.quickbook
new file mode 100644
index 0000000000..d2622373d9
--- /dev/null
+++ b/tools/quickbook/test/template_arguments1-1_1-fail.quickbook
@@ -0,0 +1,10 @@
+[article Expect template to fail because there are too many arguments.
+]
+
+[template unary[x] [x]]
+
+[section Failure]
+
+[unary a..b ]
+
+[endsect]
diff --git a/tools/quickbook/test/template_arguments2-1_1-fail.quickbook b/tools/quickbook/test/template_arguments2-1_1-fail.quickbook
new file mode 100644
index 0000000000..4f8133708a
--- /dev/null
+++ b/tools/quickbook/test/template_arguments2-1_1-fail.quickbook
@@ -0,0 +1,10 @@
+[article Expect template to fail because there are not enough arguments.
+]
+
+[template ternary[x y z] [x][y][z]]
+
+[section Failure]
+
+[ternary a b ]
+
+[endsect]
diff --git a/tools/quickbook/test/template_arguments3-1_1-fail.quickbook b/tools/quickbook/test/template_arguments3-1_1-fail.quickbook
new file mode 100644
index 0000000000..1c45e09c7c
--- /dev/null
+++ b/tools/quickbook/test/template_arguments3-1_1-fail.quickbook
@@ -0,0 +1,6 @@
+[article Expect template to fail because there are not enough arguments on 1.5.
+ [quickbook 1.5]
+]
+
+[template ternary[x y z] {[x]-[y]-[z]}]
+[ternary 1..2 3 4] \ No newline at end of file
diff --git a/tools/quickbook/test/template_section-1_5.gold b/tools/quickbook/test/template_section-1_5.gold
new file mode 100644
index 0000000000..af270acb1f
--- /dev/null
+++ b/tools/quickbook/test/template_section-1_5.gold
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="section_in_a_template" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Section in a template</title>
+ <para>
+ Some text before the section.
+ </para>
+ <section id="section_in_a_template.test">
+ <title><link linkend="section_in_a_template.test">Test</link></title>
+ <para>
+ Hello.
+ </para>
+ <bridgehead renderas="sect3" id="section_in_a_template.test.h0">
+ <phrase id="section_in_a_template.test.just_to_test_id_generation"/><link linkend="section_in_a_template.test.just_to_test_id_generation">Just
+ to test id generation</link>
+ </bridgehead>
+ <para>
+ Goodbye.
+ </para>
+ </section>
+</article>
diff --git a/tools/quickbook/test/template_section-1_5.quickbook b/tools/quickbook/test/template_section-1_5.quickbook
new file mode 100644
index 0000000000..670654a23e
--- /dev/null
+++ b/tools/quickbook/test/template_section-1_5.quickbook
@@ -0,0 +1,20 @@
+[article Section in a template
+ [quickbook 1.5]
+]
+
+[template nestedsection[]
+
+Some text before the section.
+
+[section Test]
+
+Hello.
+
+[heading Just to test id generation]
+
+Goodbye.
+
+[endsect]
+]
+
+[nestedsection] \ No newline at end of file
diff --git a/tools/quickbook/test/template_section1-1_5-fail.quickbook b/tools/quickbook/test/template_section1-1_5-fail.quickbook
new file mode 100644
index 0000000000..60b34830a3
--- /dev/null
+++ b/tools/quickbook/test/template_section1-1_5-fail.quickbook
@@ -0,0 +1,9 @@
+[article Template should contain balanced sections
+ [quickbook 1.5]
+]
+
+[template begin_no_end[]
+[section Test]
+]
+
+[begin_no_end] \ No newline at end of file
diff --git a/tools/quickbook/test/template_section2-1_5-fail.quickbook b/tools/quickbook/test/template_section2-1_5-fail.quickbook
new file mode 100644
index 0000000000..5445e88e31
--- /dev/null
+++ b/tools/quickbook/test/template_section2-1_5-fail.quickbook
@@ -0,0 +1,10 @@
+[article Template should contain balanced sections
+ [quickbook 1.5]
+]
+
+[template end_before_begin[]
+[endsect]
+[section Test]
+]
+
+[end_before_begin] \ No newline at end of file
diff --git a/tools/quickbook/test/template_section3-1_5-fail.quickbook b/tools/quickbook/test/template_section3-1_5-fail.quickbook
new file mode 100644
index 0000000000..237a9f0d17
--- /dev/null
+++ b/tools/quickbook/test/template_section3-1_5-fail.quickbook
@@ -0,0 +1,9 @@
+[article Template should contain balanced sections
+ [quickbook 1.5]
+]
+
+[template end_no_begin[]
+[endsect]
+]
+
+[end_no_begin] \ No newline at end of file
diff --git a/tools/quickbook/test/templates-1_3.gold b/tools/quickbook/test/templates-1_3.gold
new file mode 100644
index 0000000000..c53fef1e62
--- /dev/null
+++ b/tools/quickbook/test/templates-1_3.gold
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="templates" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Templates</title>
+ <section id="templates.templates">
+ <title><link linkend="templates.templates">Templates</link></title>
+ <para>
+ nullary_arg
+ </para>
+ <para>
+ foo baz
+ </para>
+ <para>
+ foo baz
+ </para>
+ <para>
+ This is a complete paragraph. kalamazoo kalamazoo kalamazoo kalamazoo kalamazoo
+ kalamazoo kalamazoo kalamazoo kalamazoo.... blah blah blah......
+ </para>
+ <para>
+ <hey>baz</hey>
+ </para>
+ <para>
+ This is a complete paragraph. madagascar madagascar madagascar madagascar madagascar
+ madagascar madagascar madagascar madagascar.... blah blah blah......
+ </para>
+ <para>
+ zoom peanut zoom
+ </para>
+ <para>
+ exactly xanadu
+ </para>
+ <para>
+ wx
+ </para>
+ <para>
+ wxyz wxyz trail
+ </para>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> &quot;Hello, World&quot; <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+<phrase role="special">}</phrase>
+</programlisting>
+ <para>
+ x<superscript>2</superscript>
+ </para>
+ <para>
+ &alpha;<superscript>2</superscript>
+ </para>
+ <para>
+ x<superscript>2</superscript>
+ </para>
+ <para>
+ got a banana?
+ </para>
+ <para>
+ .0 00
+ </para>
+ <para>
+ [fool]
+ </para>
+ </section>
+ <section id="templates.empty_templates">
+ <title><link linkend="templates.empty_templates">Empty Templates</link></title>
+ </section>
+ <section id="templates.nested_templates">
+ <title><link linkend="templates.nested_templates">Nested Templates</link></title>
+ <para>
+ Pre
+ </para>
+ <para>
+ Start block template.
+ </para>
+ <para>
+ Start block template.
+ </para>
+ <para>
+ Hello!
+ </para>
+ <para>
+ End block template.
+ </para>
+ <para>
+ End block template.
+ </para>
+ <para>
+ Post
+ </para>
+ <para>
+ Pre
+ </para>
+ <para>
+ Start block template.
+ </para>
+ <para>
+ Start phrase template. Hello! End phrase template.
+ </para>
+ <para>
+ End block template.
+ </para>
+ <para>
+ Post
+ </para>
+ <para>
+ Pre
+ </para>
+ <para>
+ Start phrase template.
+ </para>
+ <para>
+ Start block template.
+ </para>
+ <para>
+ Hello!
+ </para>
+ <para>
+ End block template.
+ </para>
+ <para>
+ End phrase template.
+ </para>
+ <para>
+ Post
+ </para>
+ <para>
+ Pre Start phrase template. Start phrase template. Hello! End phrase template.
+ End phrase template. Post
+ </para>
+ </section>
+ <section id="templates.block_markup">
+ <title><link linkend="templates.block_markup">Block Markup</link></title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ a
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ b
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para/>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ <para>
+ Paragraphs 1
+ </para>
+ <para>
+ Paragraphs 2
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ a
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ b
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <para/>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase></programlisting>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <para>
+ Paragraphs 1
+ </para>
+ <para>
+ Paragraphs 2
+ </para>
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+</article>
diff --git a/tools/quickbook/test/templates-1_3.quickbook b/tools/quickbook/test/templates-1_3.quickbook
new file mode 100644
index 0000000000..457cd157d7
--- /dev/null
+++ b/tools/quickbook/test/templates-1_3.quickbook
@@ -0,0 +1,200 @@
+[article Templates
+ [quickbook 1.3]
+]
+
+[section Templates]
+
+[/-------------------------------- nullary arg ]
+
+[template foo0 nullary_arg]
+
+[foo0]
+
+[/-------------------------------- unary arg, phrase syle ]
+
+[template foo1[bar] foo [bar]]
+
+[foo1 baz]
+
+[/-------------------------------- unary arg, block syle ]
+
+[template foo2[bar]
+foo [bar]
+]
+
+[foo2 baz]
+
+[template foo3[bar]
+This is a complete paragraph. [bar] [bar] [bar] [bar] [bar]
+[bar] [bar] [bar] [bar].... blah blah blah......
+]
+
+[foo3 kalamazoo]
+
+[/-------------------------------- unary arg, using punctuation ]
+
+[template ![bar] '''<hey>'''[bar]'''</hey>''']
+
+[!baz]
+
+[/-------------------------------- recursive templates ]
+
+[template foo4[bar]
+[foo3 [bar]]
+]
+
+[foo3 madagascar]
+
+[template foo5[x] zoom [x]]
+[template foo6[x] [x] zoom]
+
+[foo6[foo5 peanut]]
+
+[template kinda_weird[x y] [x] [y]]
+
+[kinda_weird exactly..xanadu]
+
+
+[/-------------------------------- space delimitted args ]
+
+[template simple1[a b] [a][b]]
+
+[simple1 w x]
+
+[template simple2[a b c d] [a][b][c][d]]
+
+[simple2 w x y z][simple2 w x y z trail]
+
+[/-------------------------------- John's templates ]
+
+[template code[x]
+ int main()
+ {
+ std::cout << ``[x]`` << std::endl;
+ }
+]
+
+[code "Hello\, World"]
+
+[template alpha '''&alpha;''']
+[template pow[a b] [a]'''<superscript>'''[b]'''</superscript>''' ]
+[template super[text]'''<superscript>'''[text]'''</superscript>''' ]
+
+[pow x 2]
+
+[pow [alpha] 2]
+
+x[super 2]
+
+[/-------------------------------- Some more ]
+
+[template banana got a banana?]
+[template plantation[bananarama] [bananarama]]
+
+[plantation [banana]]
+
+[/-------------------------------- Not a bug (there was a syntax error here) ]
+
+[template join1[a b] [b][a]]
+[template join2[a b] [a][b]]
+[template test[x] [join1 [join2 0 [x]]...0]]
+[test 0]
+
+[/-------------------------------- Mismatched template ]
+
+[template foo 1]
+[fool]
+
+[template blah 10]
+
+[endsect]
+
+[section Empty Templates]
+
+[template empty1]
+[template empty2 ]
+[template empty3 [/comment]]
+[template empty4 [/comment]
+
+]
+[template empty5
+]
+[template empty6
+
+]
+[template empty7
+[/comment]
+]
+[template empty8
+
+[/comment]
+]
+[template empty_arg1[x]]
+[template empty_arg2[x y]]
+
+[empty1]
+[empty2]
+[empty3]
+[empty4]
+[empty5]
+[empty6]
+[empty7]
+[empty8]
+[empty_arg1 1]
+[empty_arg2 1 2]
+
+[endsect]
+
+[/----------------------------------- Nested templates ]
+
+[section Nested Templates]
+
+[template block[content]
+
+Start block template.
+
+[content]
+
+End block template.
+]
+
+[template phrase[content] Start phrase template. [content] End phrase template.]
+
+Pre [block [block Hello!]] Post
+
+Pre [block [phrase Hello!]] Post
+
+Pre [phrase [block Hello!]] Post
+
+Pre [phrase [phrase Hello!]] Post
+
+[endsect]
+
+[/----------------------------------- Block Markup ]
+
+[section Block Markup]
+
+[template list
+* a
+* b]
+
+[template horizontal
+----]
+
+[template codeblock
+ int main() {}]
+
+[template paragraphs
+Paragraphs 1
+
+Paragraphs 2
+]
+
+[list][horizontal][codeblock][paragraphs]
+
+* [list]
+* [horizontal]
+* [codeblock]
+* [paragraphs]
+
+[endsect]
diff --git a/tools/quickbook/test/templates-1_4.gold b/tools/quickbook/test/templates-1_4.gold
new file mode 100644
index 0000000000..72e33e0bfa
--- /dev/null
+++ b/tools/quickbook/test/templates-1_4.gold
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="template_1_4" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Template 1.4</title>
+ <para>
+ dynamic scoping
+ </para>
+ <para>
+ old
+ </para>
+ <para>
+ {1-2} {1-2} {1-2 3 4} {1 2-3 4} {1 2 3-4} {[1-2} {1..2-3} {1..2-3}
+ </para>
+ <para>
+ {[binary 1 2-3} 4]
+ </para>
+ <para>
+ {1-2-3} {1-2-3} {1-2-3 4} {1 2-3-4} {[1-2-3}
+ </para>
+</article>
diff --git a/tools/quickbook/test/templates-1_4.quickbook b/tools/quickbook/test/templates-1_4.quickbook
new file mode 100644
index 0000000000..fc808554e8
--- /dev/null
+++ b/tools/quickbook/test/templates-1_4.quickbook
@@ -0,0 +1,37 @@
+[article Template 1.4
+ [quickbook 1.4]
+]
+
+[/ 1.4 uses dynamic scoping ]
+
+[template x static scoping]
+[template foo1[] [x]]
+[template foo2[x] [foo1]]
+[foo2 dynamic scoping]
+
+[/ In 1.4 template arguments are scoped at the point they are used]
+
+[template y new]
+[template foo3[a y] [a]]
+[foo3 [y] old]
+
+[/ 1.4 template arguments]
+
+[template binary[x y] {[x]-[y]}]
+[binary 1..2] [/ {1-2} ]
+[binary 1 2] [/ {1-2} ]
+[binary 1..2 3 4] [/ {1-2 3 4} ]
+[binary 1 2..3 4] [/ {1 2-3 4} ]
+[binary 1 2 3..4] [/ {1 2 3-4} ]
+[binary [1..2] [/ {(1-2} but with a square bracket ]
+[binary 1.\.2..3] [/ {1..2-3} ]
+[binary 1.\.2 3] [/ {1..2-3} ]
+
+[binary [binary 1 2..3] 4] [/ {[binary 1 2-3} 4] ]
+
+[template ternary[x y z] {[x]-[y]-[z]}]
+[ternary 1..2..3] [/ {1-2-3} ]
+[ternary 1 2 3] [/ {1-2-3} ]
+[ternary 1..2 3 4] [/ {1-2-3 4} ]
+[ternary 1 2..3 4] [/ {1 2-3-4} ]
+[ternary [1..2..3] [/ {(1-2-3} (but with a square bracket) ] \ No newline at end of file
diff --git a/tools/quickbook/test/templates-1_5.gold b/tools/quickbook/test/templates-1_5.gold
new file mode 100644
index 0000000000..bb05aaca96
--- /dev/null
+++ b/tools/quickbook/test/templates-1_5.gold
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="template_1_5" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Template 1.5</title>
+ <para>
+ static scoping
+ </para>
+ <para>
+ [a]
+ </para>
+ <para>
+ new
+ </para>
+ <para>
+ foo foo
+ </para>
+ <para>
+ {1-2} {1-2} {1-2 3 4} {1 2-3 4} {1 2 3-4} {1..2-3} {1..2-3}
+ </para>
+ <para>
+ { {1 2-3}-4} { {1 2-3}-4} { {1-2 3}-4}
+ </para>
+ <para>
+ {[1-2] 3} {[1-2] 3} {[1-2}
+ </para>
+ <para>
+ {1-2-3} {1-2-3}
+ </para>
+ <para>
+ Some <emphasis role="bold">text</emphasis>
+ </para>
+ <para>
+ A &lt;emphasis&gt;paragraph&lt;/emphasis&gt;.
+ </para>
+ <para>
+ Some *text* A <emphasis>paragraph</emphasis>.
+ </para>
+ <para>
+ <index type="things"><title>Things</title></index>
+ </para>
+</article>
diff --git a/tools/quickbook/test/templates-1_5.quickbook b/tools/quickbook/test/templates-1_5.quickbook
new file mode 100644
index 0000000000..038b8b3f05
--- /dev/null
+++ b/tools/quickbook/test/templates-1_5.quickbook
@@ -0,0 +1,72 @@
+[article Template 1.5
+ [quickbook 1.5]
+]
+
+[/ 1.5 uses static scoping ]
+
+[template x static scoping]
+[template foo1[] [x]]
+[template foo2[x] [foo1]]
+[foo2 dynamic scoping]
+
+[/ This should be '[a]' because [a] isn't matched. ]
+[template test1[] [a]]
+[template test2[a] [test1]]
+[test2 1]
+
+[/ In 1.5 template arguments are scoped at the point they are defined]
+
+[template y new]
+[template foo3[a y] [a]]
+[foo3 [y] old]
+
+[/ From https://svn.boost.org/trac/boost/ticket/2034 ]
+
+[template same[x] [x]]
+[template echo[a b] [a] [b]]
+[template echo_twice[x] [echo [same [x]]..[same [x]]]]
+[echo_twice foo]
+
+[/ 1.5 template arguments]
+
+[template binary[x y] {[x]-[y]}]
+[binary 1..2] [/ {1-2} ]
+[binary 1 2] [/ {1-2} ]
+[binary 1..2 3 4] [/ {1-2 3 4} ]
+[binary 1 2..3 4] [/ {1 2-3 4} ]
+[binary 1 2 3..4] [/ {1 2 3-4} ]
+[binary 1.\.2..3] [/ {1..2-3} ]
+[binary 1.\.2 3] [/ {1..2-3} ]
+
+[binary [binary 1 2..3]..4] [/ { {1 2-3}-4} ]
+[binary [binary 1 2..3] 4] [/ { {1 2-3}-4} ]
+[binary [binary 1 2 3]..4] [/ { {1-2 3}-4} ]
+
+[binary \[1 2\] 3] [/ {[1-2] 3} ]
+[binary \[1..2\] 3] [/ {[1-2] 3} ]
+[binary \[1 2] [/ {(1-2} ]
+
+[template ternary[x y z] {[x]-[y]-[z]}]
+[ternary 1..2..3] [/ {1-2-3} ]
+[ternary 1 2 3] [/ {1-2-3} ]
+
+[/ Block vs. phrase templates ]
+
+[template phrase[] Some *text*]
+[template block[]
+
+A <emphasis>paragraph</emphasis>.
+]
+
+[phrase]
+[block]
+[`phrase]
+[`block]
+
+[/ Trailing newline shouldn't be included]
+
+[template named_index[type title]
+'''<index type="'''[type]'''"><title>'''[title]'''</title></index>'''
+]
+
+[named_index things Things] \ No newline at end of file
diff --git a/tools/quickbook/test/unicode_escape-1_5.gold b/tools/quickbook/test/unicode_escape-1_5.gold
new file mode 100644
index 0000000000..c2a8859eb6
--- /dev/null
+++ b/tools/quickbook/test/unicode_escape-1_5.gold
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="utf_8_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>UTF-8 test</title>
+ <bridgehead renderas="sect2" id="utf_8_test.h0">
+ <phrase id="utf_8_test.i__xf1_t__xeb_rn__xe2_ti__xf4_n__xe0_liz__xe6_ti__xf8_n"/><link
+ linkend="utf_8_test.i__xf1_t__xeb_rn__xe2_ti__xf4_n__xe0_liz__xe6_ti__xf8_n">I&#xF1;t&#xEB;rn&#xE2;ti&#xF4;n&#xE0;liz&#xE6;ti&#xF8;n</link>
+ </bridgehead>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ &#x391;&#x3B1; Alpha
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x392;&#x3B2; Beta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x393;&#x3B3; Gamma
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x394;&#x3B4; Delta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x395;&#x3B5; Epsilon
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x396;&#x3B6; Zeta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x397;&#x3B7; Eta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x398;&#x3B8; Theta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x399;&#x3B9; Iota
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x39A;&#x3BA; Kappa
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x39B;&#x3BB; Lambda
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x39C;&#x3BC; Mu
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x39D;&#x3BD; Nu
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x39E;&#x3BE; Xi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x39F;&#x3BF; Omicron
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x3A0;&#x3C0; Pi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x3A1;&#x3C1; Rho
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x3A3;&#x3C3;&#x3C2; Sigma
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x3A4;&#x3C4; Tau
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x3A5;&#x3C5; Upsilon
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x3A6;&#x3C6; Phi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x3A7;&#x3C7; Chi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x3A8;&#x3C8; Psi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x3A9;&#x3C9; Omega
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ In the unlikely event that you've got a Mahjong font:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ &#x1F000; East Wind
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x1F001; South Wind
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x1F002; West Wind
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &#x1F003; North Wind
+ </simpara>
+ </listitem>
+ </itemizedlist>
+</article>
diff --git a/tools/quickbook/test/unicode_escape-1_5.quickbook b/tools/quickbook/test/unicode_escape-1_5.quickbook
new file mode 100644
index 0000000000..becdef6b84
--- /dev/null
+++ b/tools/quickbook/test/unicode_escape-1_5.quickbook
@@ -0,0 +1,37 @@
+[article UTF-8 test
+ [quickbook 1.5]
+]
+
+[heading I\u00F1t\u00EBrn\u00E2ti\u00F4n\u00E0liz\u00E6ti\u00F8n]
+
+* \u0391\u03B1 Alpha
+* \u0392\u03B2 Beta
+* \u0393\u03B3 Gamma
+* \u0394\u03B4 Delta
+* \u0395\u03B5 Epsilon
+* \u0396\u03B6 Zeta
+* \u0397\u03B7 Eta
+* \u0398\u03B8 Theta
+* \u0399\u03B9 Iota
+* \u039A\u03BA Kappa
+* \u039B\u03BB Lambda
+* \u039C\u03BC Mu
+* \u039D\u03BD Nu
+* \u039E\u03BE Xi
+* \u039F\u03BF Omicron
+* \u03A0\u03C0 Pi
+* \u03A1\u03C1 Rho
+* \u03A3\u03C3\u03C2 Sigma
+* \u03A4\u03C4 Tau
+* \u03A5\u03C5 Upsilon
+* \u03A6\u03C6 Phi
+* \u03A7\u03C7 Chi
+* \u03A8\u03C8 Psi
+* \u03A9\u03C9 Omega
+
+In the unlikely event that you've got a Mahjong font:
+
+* \U0001F000 East Wind
+* \U0001F001 South Wind
+* \U0001F002 West Wind
+* \U0001F003 North Wind \ No newline at end of file
diff --git a/tools/quickbook/test/unit/Jamfile.v2 b/tools/quickbook/test/unit/Jamfile.v2
new file mode 100644
index 0000000000..ea60b90404
--- /dev/null
+++ b/tools/quickbook/test/unit/Jamfile.v2
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2011 Daniel James
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+import testing ;
+
+project quickbook-unit-tests
+ : requirements
+ <include>../../src
+ <warnings>all
+ <library>/boost//filesystem
+ ;
+
+run values_test.cpp ../../src/values.cpp ../../src/files.cpp ../../src/string_ref.cpp ;
+run post_process_test.cpp ../../src/post_process.cpp ;
+
+# Copied from spirit
+run symbols_tests.cpp ;
+run symbols_find_null.cpp ; \ No newline at end of file
diff --git a/tools/quickbook/test/unit/post_process_test.cpp b/tools/quickbook/test/unit/post_process_test.cpp
new file mode 100644
index 0000000000..737d233c25
--- /dev/null
+++ b/tools/quickbook/test/unit/post_process_test.cpp
@@ -0,0 +1,30 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "post_process.hpp"
+#include <boost/detail/lightweight_test.hpp>
+
+#define EXPECT_EXCEPTION(test, msg) \
+ try { \
+ test; \
+ BOOST_ERROR(msg); \
+ } \
+ catch(quickbook::post_process_failure&) { \
+ }
+
+int main()
+{
+ EXPECT_EXCEPTION(
+ quickbook::post_process("</thing>"),
+ "Succeeded with unbalanced tag");
+ EXPECT_EXCEPTION(
+ quickbook::post_process("<"),
+ "Succeeded with badly formed tag");
+
+ return boost::report_errors();
+}
diff --git a/tools/quickbook/test/unit/symbols_find_null.cpp b/tools/quickbook/test/unit/symbols_find_null.cpp
new file mode 100644
index 0000000000..4f3ca6cc37
--- /dev/null
+++ b/tools/quickbook/test/unit/symbols_find_null.cpp
@@ -0,0 +1,35 @@
+/*=============================================================================
+ Copyright (c) 2004 Joao Abecasis
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include <boost/spirit/include/classic_scanner.hpp>
+#include <boost/utility/addressof.hpp>
+#include "symbols.hpp"
+
+typedef char char_type;
+typedef char const * iterator;
+
+char_type data_[] = "whatever";
+
+iterator begin = data_;
+iterator end = data_
+ + sizeof(data_)/sizeof(char_type); // Yes, this is an intentional bug ;)
+
+int main()
+{
+ typedef BOOST_SPIRIT_CLASSIC_NS::scanner<> scanner;
+ typedef quickbook::tst<void *, char_type> symbols;
+
+ symbols symbols_;
+
+ symbols_.add(begin, end - 1, (void*) boost::addressof(symbols_));
+
+ // The symbol table parser should not choke on input containing the null
+ // character.
+ symbols_.find(scanner(begin, end));
+}
diff --git a/tools/quickbook/test/unit/symbols_tests.cpp b/tools/quickbook/test/unit/symbols_tests.cpp
new file mode 100644
index 0000000000..dbf3f68ac1
--- /dev/null
+++ b/tools/quickbook/test/unit/symbols_tests.cpp
@@ -0,0 +1,406 @@
+/*=============================================================================
+ Copyright (c) 1998-2003 Joel de Guzman
+ Copyright (c) 2003 Martin Wille
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <iostream>
+#include <string>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_symbols.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/swap.hpp>
+#include "symbols.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+using namespace std;
+using namespace BOOST_SPIRIT_CLASSIC_NS;
+
+///////////////////////////////////////////////////////////////////////////////
+
+template <typename IteratorT>
+bool
+equal(IteratorT p, IteratorT q)
+{
+ while (*p && *p == *q)
+ {
+ ++p;
+ ++q;
+ }
+ return *p == *q;
+}
+
+template <class SymbolsT, typename CharT>
+void
+docheck
+(
+ SymbolsT const &sym,
+ CharT const *candidate,
+ bool hit,
+ CharT const *result,
+ int length
+)
+{
+ parse_info<CharT const*> info = parse(candidate, sym);
+
+#define correctly_matched hit == info.hit
+#define correct_match_length unsigned(length) == info.length
+#define correct_tail equal(candidate + (hit?1:0)*length, result)
+
+ BOOST_TEST(correctly_matched);
+
+ if (hit)
+ {
+ BOOST_TEST(correct_match_length);
+ BOOST_TEST(correct_tail);
+ }
+ else
+ {
+ BOOST_TEST(correct_tail);
+ }
+}
+
+template <typename T>
+struct store_action
+{
+ store_action(T const &v) : value(v) {}
+ void operator()(T &v) const { v = value; }
+private:
+ T const value;
+};
+
+template <typename T>
+store_action<T>
+store(T const &v)
+{
+ return v;
+}
+
+template <typename T>
+struct check_action
+{
+ check_action(T const &v) : value(v) {}
+
+#define correct_value_stored (v==value)
+ void operator()(T const &v) const { BOOST_TEST(correct_value_stored); }
+private:
+ T const value;
+};
+
+template <typename T>
+check_action<T>
+docheck(T const &v)
+{
+ return v;
+}
+
+static void
+default_constructible()
+{ // this actually a compile time test
+ symbols<int, char, quickbook::tst<int, char> > ns1;
+ symbols<int, wchar_t, quickbook::tst<int, wchar_t> > ws1;
+ symbols<std::string, char, quickbook::tst<std::string, char> > ns2;
+ symbols<std::string, wchar_t, quickbook::tst<std::string, wchar_t> > ws2;
+
+ (void)ns1; (void)ws1; (void)ns2; (void)ws2;
+}
+
+typedef symbols<int, char, quickbook::tst<int, char> > nsymbols;
+typedef symbols<int, wchar_t, quickbook::tst<int, wchar_t> > wsymbols;
+
+static void
+narrow_match_tests()
+{
+ nsymbols sym;
+ sym = "pineapple", "orange", "banana", "applepie", "apple";
+
+ docheck(sym, "pineapple", true, "", 9);
+ docheck(sym, "orange", true, "", 6);
+ docheck(sym, "banana", true, "", 6);
+ docheck(sym, "apple", true, "", 5);
+ docheck(sym, "pizza", false, "pizza", -1);
+ docheck(sym, "steak", false, "steak", -1);
+ docheck(sym, "applepie", true, "", 8);
+ docheck(sym, "bananarama", true, "rama", 6);
+ docheck(sym, "applet", true, "t", 5);
+ docheck(sym, "applepi", true, "pi", 5);
+ docheck(sym, "appl", false, "appl", -1);
+
+ docheck(sym, "pineapplez", true, "z", 9);
+ docheck(sym, "orangez", true, "z", 6);
+ docheck(sym, "bananaz", true, "z", 6);
+ docheck(sym, "applez", true, "z", 5);
+ docheck(sym, "pizzaz", false, "pizzaz", -1);
+ docheck(sym, "steakz", false, "steakz", -1);
+ docheck(sym, "applepiez", true, "z", 8);
+ docheck(sym, "bananaramaz", true, "ramaz", 6);
+ docheck(sym, "appletz", true, "tz", 5);
+ docheck(sym, "applepix", true, "pix", 5);
+}
+
+static void
+narrow_copy_ctor_tests()
+{
+ nsymbols sym;
+ sym = "pineapple", "orange", "banana", "applepie", "apple";
+
+ nsymbols sym2(sym);
+ docheck(sym2, "pineapple", true, "", 9);
+ docheck(sym2, "pizza", false, "pizza", -1);
+ docheck(sym2, "bananarama", true, "rama", 6);
+}
+
+static void
+narrow_assigment_operator_tests()
+{
+ nsymbols sym;
+ sym = "pineapple", "orange", "banana", "applepie", "apple";
+
+ nsymbols sym2;
+ sym2 = sym;
+
+ docheck(sym2, "pineapple", true, "", 9);
+ docheck(sym2, "pizza", false, "pizza", -1);
+ docheck(sym2, "bananarama", true, "rama", 6);
+}
+
+static void
+narrow_swap_tests()
+{
+ nsymbols sym, sym2;
+ sym = "pineapple", "orange", "banana", "applepie", "apple";
+ sym2 = "potato", "cucumber", "cauliflower", "carrot";
+
+ boost::swap(sym, sym2);
+
+ docheck(sym2, "pineapple", true, "", 9);
+ docheck(sym2, "pizza", false, "pizza", -1);
+ docheck(sym2, "bananarama", true, "rama", 6);
+ docheck(sym, "potatoe", true, "e", 6);
+ docheck(sym, "cauliflour", false, "cauliflour", -1);
+}
+
+static void
+narrow_value_tests()
+{ // also tests the add member functions
+ nsymbols sym;
+
+ sym = "orange", "banana";
+ sym.add("pineapple",1234);
+ sym.add("lemon");
+
+ parse("orange", sym[store(12345)]);
+ parse("orange", sym[docheck(12345)]);
+ parse("pineapple", sym[docheck(1234)]);
+ parse("banana", sym[docheck(int())]);
+ parse("lemon", sym[docheck(int())]);
+}
+
+static void
+narrow_free_functions_tests()
+{
+ nsymbols sym;
+
+#define add_returned_non_null_value (res!=0)
+#define add_returned_null (res==0)
+#define find_returned_non_null_value (res!=0)
+#define find_returned_null (res==0)
+
+ int *res = add(sym,"pineapple");
+ BOOST_TEST(add_returned_non_null_value);
+ res = add(sym,"pineapple");
+ BOOST_TEST(add_returned_null);
+
+ res = find(sym, "pineapple");
+ BOOST_TEST(find_returned_non_null_value);
+ res = find(sym, "banana");
+ BOOST_TEST(find_returned_null);
+}
+
+static void
+wide_match_tests()
+{
+ wsymbols sym;
+ sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
+
+ docheck(sym, L"pineapple", true, L"", 9);
+ docheck(sym, L"orange", true, L"", 6);
+ docheck(sym, L"banana", true, L"", 6);
+ docheck(sym, L"apple", true, L"", 5);
+ docheck(sym, L"pizza", false, L"pizza", -1);
+ docheck(sym, L"steak", false, L"steak", -1);
+ docheck(sym, L"applepie", true, L"", 8);
+ docheck(sym, L"bananarama", true, L"rama", 6);
+ docheck(sym, L"applet", true, L"t", 5);
+ docheck(sym, L"applepi", true, L"pi", 5);
+ docheck(sym, L"appl", false, L"appl", -1);
+
+ docheck(sym, L"pineapplez", true, L"z", 9);
+ docheck(sym, L"orangez", true, L"z", 6);
+ docheck(sym, L"bananaz", true, L"z", 6);
+ docheck(sym, L"applez", true, L"z", 5);
+ docheck(sym, L"pizzaz", false, L"pizzaz", -1);
+ docheck(sym, L"steakz", false, L"steakz", -1);
+ docheck(sym, L"applepiez", true, L"z", 8);
+ docheck(sym, L"bananaramaz", true, L"ramaz", 6);
+ docheck(sym, L"appletz", true, L"tz", 5);
+ docheck(sym, L"applepix", true, L"pix", 5);
+}
+
+static void
+wide_copy_ctor_tests()
+{
+ wsymbols sym;
+ sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
+
+ wsymbols sym2(sym);
+ docheck(sym2, L"pineapple", true, L"", 9);
+ docheck(sym2, L"pizza", false, L"pizza", -1);
+ docheck(sym2, L"bananarama", true, L"rama", 6);
+}
+
+static void
+wide_assigment_operator_tests()
+{
+ wsymbols sym;
+ sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
+
+ wsymbols sym2;
+ sym2 = sym;
+
+ docheck(sym2, L"pineapple", true, L"", 9);
+ docheck(sym2, L"pizza", false, L"pizza", -1);
+ docheck(sym2, L"bananarama", true, L"rama", 6);
+}
+
+static void
+wide_swap_tests()
+{
+ wsymbols sym, sym2;
+ sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
+ sym2 = L"potato", L"cucumber", L"cauliflower", L"carrot";
+
+ boost::swap(sym, sym2);
+
+ docheck(sym2, L"pineapple", true, L"", 9);
+ docheck(sym2, L"pizza", false, L"pizza", -1);
+ docheck(sym2, L"bananarama", true, L"rama", 6);
+ docheck(sym, L"potatoe", true, L"e", 6);
+ docheck(sym, L"cauliflour", false, L"cauliflour", -1);
+}
+
+static void
+wide_value_tests()
+{ // also tests the add member functions
+ wsymbols sym;
+
+ sym = L"orange", L"banana";
+ sym.add(L"pineapple",1234);
+ sym.add(L"lemon");
+
+ parse(L"orange", sym[store(12345)]);
+ parse(L"orange", sym[docheck(12345)]);
+ parse(L"pineapple", sym[docheck(1234)]);
+ parse(L"banana", sym[docheck(int())]);
+ parse(L"lemon", sym[docheck(int())]);
+}
+
+static void
+wide_free_functions_tests()
+{
+ wsymbols sym;
+
+ int *res = add(sym,L"pineapple");
+ BOOST_TEST(add_returned_non_null_value);
+ res = add(sym,L"pineapple");
+ BOOST_TEST(add_returned_null);
+
+ res = find(sym, L"pineapple");
+ BOOST_TEST(find_returned_non_null_value);
+ res = find(sym, L"banana");
+ BOOST_TEST(find_returned_null);
+}
+
+static
+void free_add_find_functions_tests()
+{
+ nsymbols sym;
+ BOOST_TEST(*add(sym, "a", 0) == 0);
+ BOOST_TEST(*add(sym, "a2", 1) == 1);
+ BOOST_TEST(add(sym, "a2", 2) == 0);
+ BOOST_TEST(find(sym, "a2"));
+ BOOST_TEST(find(sym, "a"));
+}
+
+// The original teneray search tree implementation contained a bug when
+// inserting duplicate values. I want this implementation to be as
+// close as possible to the original (so they can be easily switched)
+// so check that the bug remains the same.
+
+struct check_parse_value
+{
+ explicit check_parse_value(int value) : value_(value){}
+
+ void operator()(int value) const { BOOST_TEST(value == value_); }
+
+ int value_;
+};
+
+// My version is different to the original, if there's an existing value
+// it replaces it with the new one.
+
+static
+void duplicate_add_tests()
+{
+ char const* foo1 = "foo";
+ char const* foo2 = foo1 + 3;
+
+ nsymbols sym;
+ sym.add(foo1, foo2, 1);
+ nsymbols sym2 = sym;
+ sym.add(foo1, foo2, 2);
+ sym2.add(foo1, foo2, 3);
+
+ BOOST_TEST(find(sym, "foo") && *find(sym, "foo") == 2);
+ BOOST_TEST(find(sym2, "foo") && *find(sym2, "foo") == 3);
+
+ parse_info<char const*> info;
+
+ info = parse("foo ", sym[check_parse_value(2)]);
+ BOOST_TEST(info.hit && info.length == 3);
+
+ info = parse("foo", sym[check_parse_value(2)]);
+ BOOST_TEST(info.hit && info.length == 3);
+
+ info = parse("foo ", sym2[check_parse_value(3)]);
+ BOOST_TEST(info.hit && info.length == 3);
+
+ info = parse("foo", sym2[check_parse_value(3)]);
+ BOOST_TEST(info.hit && info.length == 3);
+}
+
+int
+main()
+{
+ default_constructible();
+ narrow_match_tests();
+ narrow_copy_ctor_tests();
+ narrow_assigment_operator_tests();
+ narrow_swap_tests();
+ narrow_value_tests();
+ narrow_free_functions_tests();
+ wide_match_tests();
+ wide_copy_ctor_tests();
+ wide_assigment_operator_tests();
+ wide_swap_tests();
+ wide_value_tests();
+ wide_free_functions_tests();
+ free_add_find_functions_tests();
+ duplicate_add_tests();
+
+ return boost::report_errors();
+}
diff --git a/tools/quickbook/test/unit/values_test.cpp b/tools/quickbook/test/unit/values_test.cpp
new file mode 100644
index 0000000000..b6d186c555
--- /dev/null
+++ b/tools/quickbook/test/unit/values_test.cpp
@@ -0,0 +1,125 @@
+/*=============================================================================
+ Copyright (c) 2010-2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+// Some very light testing for quickbook::value and friends.
+// Just for a few issues that came up during development.
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/range/algorithm/equal.hpp>
+#include <vector>
+#include "values.hpp"
+#include "files.hpp"
+
+void empty_tests()
+{
+ quickbook::value q;
+ BOOST_TEST(q.empty());
+ BOOST_TEST(!q.is_list());
+ BOOST_TEST(!q.is_encoded());
+}
+
+void qbk_tests()
+{
+ std::string source = "Source";
+ quickbook::value q;
+ {
+ quickbook::file_ptr fake_file = new quickbook::file(
+ "(fake file)", source, 105u);
+ q = quickbook::qbk_value(
+ fake_file,
+ fake_file->source.begin(),
+ fake_file->source.end());
+ }
+ BOOST_TEST_EQ(q.get_quickbook(), source);
+}
+
+void sort_test()
+{
+ quickbook::value_builder b;
+ b.insert(quickbook::encoded_value("a", 10));
+ b.insert(quickbook::encoded_value("b", 2));
+ b.insert(quickbook::encoded_value("c", 5));
+ b.insert(quickbook::encoded_value("d", 8));
+ b.sort_list();
+
+ quickbook::value_consumer c = b.release();
+ BOOST_TEST(c.check(2)); BOOST_TEST_EQ(c.consume(2).get_encoded(), "b");
+ BOOST_TEST(c.check(5)); c.consume(5);
+ BOOST_TEST(c.check(8)); c.consume(8);
+ BOOST_TEST(c.check(10)); c.consume(10);
+ BOOST_TEST(!c.check());
+}
+
+void multiple_list_test()
+{
+ quickbook::value_builder list1;
+ quickbook::value_builder list2;
+
+ list1.insert(quickbook::encoded_value("b", 10));
+
+ {
+ quickbook::value p1 = quickbook::encoded_value("a", 5);
+ list1.insert(p1);
+ list2.insert(p1);
+ }
+
+ list2.insert(quickbook::encoded_value("c", 3));
+
+ quickbook::value_consumer l1 = list1.release();
+ quickbook::value_consumer l2 = list2.release();
+
+ BOOST_TEST(l1.check(10));
+ BOOST_TEST_EQ(l1.consume(10).get_encoded(), "b");
+ BOOST_TEST(l1.check(5));
+ BOOST_TEST_EQ(l1.consume(5).get_encoded(), "a");
+ BOOST_TEST(!l1.check());
+
+ BOOST_TEST(l2.check(5));
+ BOOST_TEST_EQ(l2.consume(5).get_encoded(), "a");
+ BOOST_TEST(l2.check(3));
+ BOOST_TEST_EQ(l2.consume(3).get_encoded(), "c");
+ BOOST_TEST(!l2.check());
+}
+
+void equality_tests()
+{
+ std::vector<quickbook::value> distinct_values;
+
+ quickbook::value_builder builder;
+ quickbook::value nil;
+
+ // 0: nil
+ distinct_values.push_back(nil);
+
+ // 1: []
+ distinct_values.push_back(builder.release());
+
+ // 2: [nil]
+ builder.insert(nil);
+ distinct_values.push_back(builder.release());
+
+ for(int i = 0; i < distinct_values.size(); ++i)
+ for(int j = 0; j < distinct_values.size(); ++j)
+ if ((i == j) != (distinct_values[i] == distinct_values[j]))
+ {
+ BOOST_ERROR("Value mismatch.");
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << "\tat " << i << ", " << j << std::endl;
+ }
+}
+
+int main()
+{
+ empty_tests();
+ qbk_tests();
+ sort_test();
+ multiple_list_test();
+ equality_tests();
+
+ return boost::report_errors();
+}
diff --git a/tools/quickbook/test/unmatched_element-1_5.gold b/tools/quickbook/test/unmatched_element-1_5.gold
new file mode 100644
index 0000000000..735503ac5f
--- /dev/null
+++ b/tools/quickbook/test/unmatched_element-1_5.gold
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="unmatched_elements" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Unmatched elements</title>
+ <para>
+ <emphasis role="bold">[non-element</emphasis>]
+ </para>
+ <para>
+ [non-element]
+ </para>
+</article>
diff --git a/tools/quickbook/test/unmatched_element-1_5.quickbook b/tools/quickbook/test/unmatched_element-1_5.quickbook
new file mode 100644
index 0000000000..84ea298d08
--- /dev/null
+++ b/tools/quickbook/test/unmatched_element-1_5.quickbook
@@ -0,0 +1,12 @@
+[article Unmatched elements
+[quickbook 1.5]
+]
+
+[template identity[x]
+
+[x]
+]
+
+[* [non-element]]
+
+[identity [non-element]] \ No newline at end of file
diff --git a/tools/quickbook/test/unmatched_element-1_6.gold b/tools/quickbook/test/unmatched_element-1_6.gold
new file mode 100644
index 0000000000..ad52f651ac
--- /dev/null
+++ b/tools/quickbook/test/unmatched_element-1_6.gold
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="unmatched_elements" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Unmatched elements</title>
+ <para>
+ <emphasis role="bold">[non-element]</emphasis>
+ </para>
+ <para>
+ [non-element]
+ </para>
+</article>
diff --git a/tools/quickbook/test/unmatched_element-1_6.quickbook b/tools/quickbook/test/unmatched_element-1_6.quickbook
new file mode 100644
index 0000000000..689e9828aa
--- /dev/null
+++ b/tools/quickbook/test/unmatched_element-1_6.quickbook
@@ -0,0 +1,12 @@
+[article Unmatched elements
+[quickbook 1.6]
+]
+
+[template identity[x]
+
+[x]
+]
+
+[* [non-element]]
+
+[identity [non-element]] \ No newline at end of file
diff --git a/tools/quickbook/test/utf16be_bom-1_5-fail.quickbook b/tools/quickbook/test/utf16be_bom-1_5-fail.quickbook
new file mode 100644
index 0000000000..be2bcbc448
--- /dev/null
+++ b/tools/quickbook/test/utf16be_bom-1_5-fail.quickbook
Binary files differ
diff --git a/tools/quickbook/test/utf16le_bom-1_5-fail.quickbook b/tools/quickbook/test/utf16le_bom-1_5-fail.quickbook
new file mode 100644
index 0000000000..d9782a4655
--- /dev/null
+++ b/tools/quickbook/test/utf16le_bom-1_5-fail.quickbook
Binary files differ
diff --git a/tools/quickbook/test/utf8-1_5.gold b/tools/quickbook/test/utf8-1_5.gold
new file mode 100644
index 0000000000..088b314b38
--- /dev/null
+++ b/tools/quickbook/test/utf8-1_5.gold
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="utf_8_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>UTF-8 test</title>
+ <bridgehead renderas="sect2" id="utf_8_test.h0">
+ <phrase id="utf_8_test.i__t__rn__ti__n__liz__ti__n"/><link linkend="utf_8_test.i__t__rn__ti__n__liz__ti__n">Iñtërnâtiônàlizætiøn</link>
+ </bridgehead>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Αα Alpha
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ββ Beta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Γγ Gamma
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Δδ Delta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Εε Epsilon
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ζζ Zeta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ηη Eta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Θθ Theta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ιι Iota
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Κκ Kappa
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Λλ Lambda
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Μμ Mu
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Îν Nu
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ξξ Xi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Οο Omicron
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ππ Pi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Î¡Ï Rho
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Σσς Sigma
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ττ Tau
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Υυ Upsilon
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Φφ Phi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Χχ Chi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ψψ Psi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ωω Omega
+ </simpara>
+ </listitem>
+ </itemizedlist>
+</article>
diff --git a/tools/quickbook/test/utf8-1_5.quickbook b/tools/quickbook/test/utf8-1_5.quickbook
new file mode 100644
index 0000000000..96f02f4f48
--- /dev/null
+++ b/tools/quickbook/test/utf8-1_5.quickbook
@@ -0,0 +1,30 @@
+[article UTF-8 test
+ [quickbook 1.5]
+]
+
+[heading Iñtërnâtiônàlizætiøn]
+
+* Αα Alpha
+* Ββ Beta
+* Γγ Gamma
+* Δδ Delta
+* Εε Epsilon
+* Ζζ Zeta
+* Ηη Eta
+* Θθ Theta
+* Ιι Iota
+* Κκ Kappa
+* Λλ Lambda
+* Μμ Mu
+* Îν Nu
+* Ξξ Xi
+* Οο Omicron
+* Ππ Pi
+* Î¡Ï Rho
+* Σσς Sigma
+* Ττ Tau
+* Υυ Upsilon
+* Φφ Phi
+* Χχ Chi
+* Ψψ Psi
+* Ωω Omega \ No newline at end of file
diff --git a/tools/quickbook/test/utf8_bom-1_5.gold b/tools/quickbook/test/utf8_bom-1_5.gold
new file mode 100644
index 0000000000..088b314b38
--- /dev/null
+++ b/tools/quickbook/test/utf8_bom-1_5.gold
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="utf_8_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>UTF-8 test</title>
+ <bridgehead renderas="sect2" id="utf_8_test.h0">
+ <phrase id="utf_8_test.i__t__rn__ti__n__liz__ti__n"/><link linkend="utf_8_test.i__t__rn__ti__n__liz__ti__n">Iñtërnâtiônàlizætiøn</link>
+ </bridgehead>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Αα Alpha
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ββ Beta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Γγ Gamma
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Δδ Delta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Εε Epsilon
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ζζ Zeta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ηη Eta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Θθ Theta
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ιι Iota
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Κκ Kappa
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Λλ Lambda
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Μμ Mu
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Îν Nu
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ξξ Xi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Οο Omicron
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ππ Pi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Î¡Ï Rho
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Σσς Sigma
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ττ Tau
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Υυ Upsilon
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Φφ Phi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Χχ Chi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ψψ Psi
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Ωω Omega
+ </simpara>
+ </listitem>
+ </itemizedlist>
+</article>
diff --git a/tools/quickbook/test/utf8_bom-1_5.quickbook b/tools/quickbook/test/utf8_bom-1_5.quickbook
new file mode 100644
index 0000000000..443f6c6c02
--- /dev/null
+++ b/tools/quickbook/test/utf8_bom-1_5.quickbook
@@ -0,0 +1,30 @@
+[article UTF-8 test
+ [quickbook 1.5]
+]
+
+[heading Iñtërnâtiônàlizætiøn]
+
+* Αα Alpha
+* Ββ Beta
+* Γγ Gamma
+* Δδ Delta
+* Εε Epsilon
+* Ζζ Zeta
+* Ηη Eta
+* Θθ Theta
+* Ιι Iota
+* Κκ Kappa
+* Λλ Lambda
+* Μμ Mu
+* Îν Nu
+* Ξξ Xi
+* Οο Omicron
+* Ππ Pi
+* Î¡Ï Rho
+* Σσς Sigma
+* Ττ Tau
+* Υυ Upsilon
+* Φφ Phi
+* Χχ Chi
+* Ψψ Psi
+* Ωω Omega \ No newline at end of file
diff --git a/tools/quickbook/test/variablelist-1_5-fail.quickbook b/tools/quickbook/test/variablelist-1_5-fail.quickbook
new file mode 100644
index 0000000000..a7e589680c
--- /dev/null
+++ b/tools/quickbook/test/variablelist-1_5-fail.quickbook
@@ -0,0 +1,5 @@
+[article Parse error [quickbook 1.4]]
+
+[variablelist Variable List
+[[1234]]
+]
diff --git a/tools/quickbook/test/variablelist-1_5.gold b/tools/quickbook/test/variablelist-1_5.gold
new file mode 100644
index 0000000000..08d66133e7
--- /dev/null
+++ b/tools/quickbook/test/variablelist-1_5.gold
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="variable_list_tests" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Variable List Tests</title>
+ <variablelist>
+ <title>Empty</title>
+ </variablelist>
+ <variablelist>
+ <title>One entry</title>
+ <varlistentry>
+ <term>a</term>
+ <listitem>
+ <para>
+ b
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <variablelist>
+ <title>One entry, multiple items</title>
+ <varlistentry>
+ <term>a</term>
+ <listitem>
+ <para>
+ b
+ </para>
+ <para>
+ c
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <variablelist>
+ <title>Several entries</title>
+ <varlistentry>
+ <term>a</term>
+ <listitem>
+ <para>
+ b
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>a</term>
+ <listitem>
+ <para>
+ b
+ </para>
+ <para>
+ c
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>a</term>
+ <listitem>
+ <para>
+ b
+ </para>
+ <para>
+ c
+ </para>
+ <para>
+ d
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>a</term>
+ <listitem>
+ <para>
+ b
+ </para>
+ <para>
+ c
+ </para>
+ <para>
+ d
+ </para>
+ <para>
+ e
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>a</term>
+ <listitem>
+ <para>
+ b
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <anchor id="id1"/>
+ <variablelist>
+ <title>Variable List with anchors</title>
+ <varlistentry>
+ <term><anchor id="id2"/>a<anchor id="id3"/></term>
+ <listitem>
+ <para>
+ <anchor id="id4"/>b<anchor id="id5"/>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+</article>
diff --git a/tools/quickbook/test/variablelist-1_5.quickbook b/tools/quickbook/test/variablelist-1_5.quickbook
new file mode 100644
index 0000000000..cb68a6df73
--- /dev/null
+++ b/tools/quickbook/test/variablelist-1_5.quickbook
@@ -0,0 +1,30 @@
+[article Variable List Tests
+[quickbook 1.5]
+]
+
+[variablelist Empty
+]
+
+[variablelist One entry
+ [[a][b]]
+]
+
+[variablelist One entry, multiple items
+ [[a][b][c]]
+]
+
+[variablelist Several entries
+ [[a][b]]
+ [[a][b][c]]
+ [[a][b][c][d]]
+ [[a][b][c][d][e]]
+ [[a][b]]
+]
+
+[#id1]
+[variablelist Variable List with anchors
+ [
+ [[#id2]a[#id3]]
+ [[#id4]b[#id5]]
+ ]
+]
diff --git a/tools/quickbook/test/version-0_1-fail.quickbook b/tools/quickbook/test/version-0_1-fail.quickbook
new file mode 100644
index 0000000000..ac3c512502
--- /dev/null
+++ b/tools/quickbook/test/version-0_1-fail.quickbook
@@ -0,0 +1,5 @@
+[article Non-existent version of quickbook
+ [quickbook 0.1]
+]
+
+This should fail... \ No newline at end of file
diff --git a/tools/quickbook/test/version-1_7-fail.quickbook b/tools/quickbook/test/version-1_7-fail.quickbook
new file mode 100644
index 0000000000..9820b7435c
--- /dev/null
+++ b/tools/quickbook/test/version-1_7-fail.quickbook
@@ -0,0 +1,5 @@
+[article Future version of quickbook
+ [quickbook 1.7]
+]
+
+This should fail... \ No newline at end of file
diff --git a/tools/quickbook/test/version-2_0-fail.quickbook b/tools/quickbook/test/version-2_0-fail.quickbook
new file mode 100644
index 0000000000..973b174f6f
--- /dev/null
+++ b/tools/quickbook/test/version-2_0-fail.quickbook
@@ -0,0 +1,5 @@
+[article Far future version of quickbook
+ [quickbook 2.0]
+]
+
+This should fail... \ No newline at end of file
diff --git a/tools/quickbook/test/versions/Jamfile.v2 b/tools/quickbook/test/versions/Jamfile.v2
new file mode 100644
index 0000000000..ccb46dc7bf
--- /dev/null
+++ b/tools/quickbook/test/versions/Jamfile.v2
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2011 Daniel James
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+project test/versions
+ : requirements
+ <toolset>msvc:<debug-symbols>off
+ ;
+
+import quickbook-testing : quickbook-test quickbook-error-test ;
+
+test-suite quickbook.test :
+ [ quickbook-test versions-1_6 ]
+ [ quickbook-test invalid_macro-1_6 ]
+ ;
diff --git a/tools/quickbook/test/versions/invalid_macro-1_6.gold b/tools/quickbook/test/versions/invalid_macro-1_6.gold
new file mode 100644
index 0000000000..cb62412473
--- /dev/null
+++ b/tools/quickbook/test/versions/invalid_macro-1_6.gold
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="invalid_macro_test" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Invalid macro test</title>
+ <para>
+ Import:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ okay
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ __invalid\macro__
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Include:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ okay
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ bad
+ </simpara>
+ </listitem>
+ </itemizedlist>
+</article>
diff --git a/tools/quickbook/test/versions/invalid_macro-1_6.quickbook b/tools/quickbook/test/versions/invalid_macro-1_6.quickbook
new file mode 100644
index 0000000000..f579f7252e
--- /dev/null
+++ b/tools/quickbook/test/versions/invalid_macro-1_6.quickbook
@@ -0,0 +1,14 @@
+[article Invalid macro test
+[quickbook 1.6]
+]
+
+Import:
+
+[import invalid_macro-inc-1_1.qbk]
+
+* __valid__
+* __invalid\macro__
+
+Include:
+
+[include invalid_macro-inc-1_1.qbk]
diff --git a/tools/quickbook/test/versions/invalid_macro-inc-1_1.qbk b/tools/quickbook/test/versions/invalid_macro-inc-1_1.qbk
new file mode 100644
index 0000000000..c44bd67417
--- /dev/null
+++ b/tools/quickbook/test/versions/invalid_macro-inc-1_1.qbk
@@ -0,0 +1,7 @@
+[quickbook 1.1]
+
+[def __valid__ okay]
+[def __invalid\macro__ bad]
+
+* __valid__
+* __invalid\macro__
diff --git a/tools/quickbook/test/versions/templates-1_1.qbk b/tools/quickbook/test/versions/templates-1_1.qbk
new file mode 100644
index 0000000000..be5365055d
--- /dev/null
+++ b/tools/quickbook/test/versions/templates-1_1.qbk
@@ -0,0 +1,15 @@
+[article 1.1 Templates
+[quickbook 1.1]
+]
+
+[template section_1_1[]
+[section In a 1.1 template]
+Some text
+[endsect]
+]
+
+[section 1.1 Document]
+[section_1_1]
+[section_1_4]
+[section_1_5]
+[endsect]
diff --git a/tools/quickbook/test/versions/templates-1_4.qbk b/tools/quickbook/test/versions/templates-1_4.qbk
new file mode 100644
index 0000000000..8b565512d4
--- /dev/null
+++ b/tools/quickbook/test/versions/templates-1_4.qbk
@@ -0,0 +1,20 @@
+[article 1.4 Templates
+[quickbook 1.4]
+]
+
+[template section_1_4[]
+[section In a 1.4 template]
+Some text
+[endsect]
+]
+
+[section 1.4 Document]
+[section_1_1]
+[section_1_4]
+[section_1_5]
+[endsect]
+
+[/ Odd test for calling 1.4 -> 1.5 -> 1.4 template]
+
+[template skip_1_5[a] [skip_1_5_2 wrong]]
+[template skip_1_5_3[] [a]]
diff --git a/tools/quickbook/test/versions/templates-1_5.qbk b/tools/quickbook/test/versions/templates-1_5.qbk
new file mode 100644
index 0000000000..9dd07f6939
--- /dev/null
+++ b/tools/quickbook/test/versions/templates-1_5.qbk
@@ -0,0 +1,19 @@
+[article 1.5 Templates
+[quickbook 1.5]
+]
+
+[template section_1_5[]
+[section In a 1.5 template]
+Some text
+[endsect]
+]
+
+[section 1.5 Document]
+[section_1_1]
+[section_1_4]
+[section_1_5]
+[endsect]
+
+[/ Odd test for calling 1.4 -> 1.5 -> 1.4 template]
+
+[template skip_1_5_2[a] [skip_1_5_3]]
diff --git a/tools/quickbook/test/versions/versions-1_6.gold b/tools/quickbook/test/versions/versions-1_6.gold
new file mode 100644
index 0000000000..7b89fdc3d2
--- /dev/null
+++ b/tools/quickbook/test/versions/versions-1_6.gold
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="mixed_version_tests" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Mixed version tests</title>
+ <para>
+ correct
+ </para>
+ <section id="mixed_version_tests.section_ids">
+ <title><link linkend="mixed_version_tests.section_ids">Section ids in templates</link></title>
+ <section id="mixed_version_tests.section_ids.in_a_1_1_template">
+ <title><link linkend="mixed_version_tests.section_ids.in_a_1_1_template">In
+ a 1.1 template</link></title>
+ <para>
+ Some text
+ </para>
+ </section>
+ <section id="mixed_version_tests.section_ids.in_a_1_4_template">
+ <title><link linkend="mixed_version_tests.section_ids.in_a_1_4_template">In
+ a 1.4 template</link></title>
+ <para>
+ Some text
+ </para>
+ </section>
+ <section id="mixed_version_tests.section_ids.in_a_1_5_template">
+ <title><link linkend="mixed_version_tests.section_ids.in_a_1_5_template">In
+ a 1.5 template</link></title>
+ <para>
+ Some text
+ </para>
+ </section>
+ </section>
+ <article id="1_1_templates" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>1.1 Templates</title>
+ <section id="1_1_templates.1_1_document">
+ <title>1.1 Document</title>
+ <section id="1_1_templates.in_a_1_1_template">
+ <title>In a 1.1 template</title>
+ <para>
+ Some text
+ </para>
+ </section>
+ <section id="1_1_templates.in_a_1_4_template">
+ <title>In a 1.4 template</title>
+ <para>
+ Some text
+ </para>
+ </section>
+ <section id="1_1_templates.in_a_1_5_template">
+ <title>In a 1.5 template</title>
+ <para>
+ Some text
+ </para>
+ </section>
+ </section>
+ </article>
+ <article id="1_4_templates" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>1.4 Templates</title>
+ <section id="1_4_templates.1_4_document">
+ <title><link linkend="1_4_templates.1_4_document">1.4 Document</link></title>
+ <section id="1_4_templates.1_4_document.in_a_1_1_template">
+ <title><link linkend="1_4_templates.1_4_document.in_a_1_1_template">In a
+ 1.1 template</link></title>
+ <para>
+ Some text
+ </para>
+ </section>
+ <section id="1_4_templates.1_4_document.in_a_1_4_template">
+ <title><link linkend="1_4_templates.1_4_document.in_a_1_4_template">In a
+ 1.4 template</link></title>
+ <para>
+ Some text
+ </para>
+ </section>
+ <section id="1_4_templates.1_4_document.in_a_1_5_template">
+ <title><link linkend="1_4_templates.1_4_document.in_a_1_5_template">In a
+ 1.5 template</link></title>
+ <para>
+ Some text
+ </para>
+ </section>
+ </section>
+ </article>
+ <article id="1_5_templates" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>1.5 Templates</title>
+ <section id="1_5_templates.1_5_document">
+ <title><link linkend="1_5_templates.1_5_document">1.5 Document</link></title>
+ <section id="1_5_templates.1_5_document.in_a_1_1_template">
+ <title><link linkend="1_5_templates.1_5_document.in_a_1_1_template">In a
+ 1.1 template</link></title>
+ <para>
+ Some text
+ </para>
+ </section>
+ <section id="1_5_templates.1_5_document.in_a_1_4_template">
+ <title><link linkend="1_5_templates.1_5_document.in_a_1_4_template">In a
+ 1.4 template</link></title>
+ <para>
+ Some text
+ </para>
+ </section>
+ <section id="1_5_templates.1_5_document.in_a_1_5_template">
+ <title><link linkend="1_5_templates.1_5_document.in_a_1_5_template">In a
+ 1.5 template</link></title>
+ <para>
+ Some text
+ </para>
+ </section>
+ </section>
+ </article>
+</article>
diff --git a/tools/quickbook/test/versions/versions-1_6.quickbook b/tools/quickbook/test/versions/versions-1_6.quickbook
new file mode 100644
index 0000000000..baac8e08d6
--- /dev/null
+++ b/tools/quickbook/test/versions/versions-1_6.quickbook
@@ -0,0 +1,26 @@
+[quickbook 1.6]
+[article Mixed version tests]
+
+[import templates-1_1.qbk]
+[import templates-1_4.qbk]
+[import templates-1_5.qbk]
+
+[/ This test calls a 1.4 template -> 1.5 template -> 1.4 template.
+ The name lookup in the 1.4 template should skip the 1.5 template
+ when doing dynamic name lookup. ]
+[skip_1_5 correct]
+
+[/ When calling templates from old versions, the ids should
+ be consistent with their context ]
+
+[section:section_ids Section ids in templates]
+[section_1_1]
+[section_1_4]
+[section_1_5]
+[endsect]
+
+[/ For comparison]
+
+[include templates-1_1.qbk]
+[include templates-1_4.qbk]
+[include templates-1_5.qbk]
diff --git a/tools/quickbook/test/xinclude/Jamfile.v2 b/tools/quickbook/test/xinclude/Jamfile.v2
new file mode 100644
index 0000000000..2974e86089
--- /dev/null
+++ b/tools/quickbook/test/xinclude/Jamfile.v2
@@ -0,0 +1,27 @@
+#
+# Copyright (c) 2005 João Abecasis
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+project test/xinclude
+ : requirements
+ <toolset>msvc:<debug-symbols>off
+ ;
+
+import quickbook-testing : quickbook-test quickbook-error-test ;
+
+path-constant xinclude_base1 : ../.. ;
+path-constant xinclude_base2 : sub ;
+
+test-suite quickbook.test :
+ [ quickbook-test xinclude-1_1 : : : <quickbook-xinclude-base>$(xinclude_base1) ]
+ [ quickbook-test xmlbase1-1_6 : : : <quickbook-xinclude-base>$(xinclude_base1) ]
+ [ quickbook-test xmlbase2-1_6 : : : <quickbook-xinclude-base>$(xinclude_base1) ]
+ [ quickbook-test xinclude-1_1-alt : xinclude-1_1.quickbook : xinclude-1_1-alt.gold : <quickbook-xinclude-base>$(xinclude_base2) ]
+ [ quickbook-test xmlbase1-1_6-alt : xmlbase1-1_6.quickbook : xmlbase1-1_6-alt.gold : <quickbook-xinclude-base>$(xinclude_base2) ]
+ [ quickbook-test xmlbase2-1_6-alt : xmlbase2-1_6.quickbook : xmlbase2-1_6-alt.gold : <quickbook-xinclude-base>$(xinclude_base2) ]
+ [ quickbook-error-test xmlbase-1_6-fail ]
+ ;
diff --git a/tools/quickbook/test/xinclude/sub/stub.xml b/tools/quickbook/test/xinclude/sub/stub.xml
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/quickbook/test/xinclude/sub/stub.xml
diff --git a/tools/quickbook/test/xinclude/xinclude-1_1-alt.gold b/tools/quickbook/test/xinclude/xinclude-1_1-alt.gold
new file mode 100644
index 0000000000..ce7018e413
--- /dev/null
+++ b/tools/quickbook/test/xinclude/xinclude-1_1-alt.gold
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include</title>
+ <xi:include href="../../stub.xml" />
+ <xi:include href="../stub.xml" />
+ <xi:include href="stub.xml" />
+</article>
diff --git a/tools/quickbook/test/xinclude/xinclude-1_1.gold b/tools/quickbook/test/xinclude/xinclude-1_1.gold
new file mode 100644
index 0000000000..ee8e86eb19
--- /dev/null
+++ b/tools/quickbook/test/xinclude/xinclude-1_1.gold
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="include" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Include</title>
+ <xi:include href="test/stub.xml" />
+ <xi:include href="test/xinclude/stub.xml" />
+ <xi:include href="test/xinclude/sub/stub.xml" />
+</article>
diff --git a/tools/quickbook/test/xinclude/xinclude-1_1.quickbook b/tools/quickbook/test/xinclude/xinclude-1_1.quickbook
new file mode 100644
index 0000000000..65ccfd70ae
--- /dev/null
+++ b/tools/quickbook/test/xinclude/xinclude-1_1.quickbook
@@ -0,0 +1,5 @@
+[article Include]
+
+[xinclude ../stub.xml]
+[xinclude stub.xml]
+[xinclude sub/stub.xml]
diff --git a/tools/quickbook/test/xinclude/xmlbase-1_6-fail.quickbook b/tools/quickbook/test/xinclude/xmlbase-1_6-fail.quickbook
new file mode 100644
index 0000000000..899b4a2b41
--- /dev/null
+++ b/tools/quickbook/test/xinclude/xmlbase-1_6-fail.quickbook
@@ -0,0 +1,4 @@
+[article Xmlbase fail
+[quickbook 1.5]
+[xmlbase non-existent]
+]
diff --git a/tools/quickbook/test/xinclude/xmlbase1-1_6-alt.gold b/tools/quickbook/test/xinclude/xmlbase1-1_6-alt.gold
new file mode 100644
index 0000000000..29aa1944d6
--- /dev/null
+++ b/tools/quickbook/test/xinclude/xmlbase1-1_6-alt.gold
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="xinclude_with_xmlbase" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xml:base=".." xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>XInclude with xmlbase</title>
+ <xi:include href="../stub.xml" />
+ <xi:include href="stub.xml" />
+ <xi:include href="sub/stub.xml" />
+</article>
diff --git a/tools/quickbook/test/xinclude/xmlbase1-1_6.gold b/tools/quickbook/test/xinclude/xmlbase1-1_6.gold
new file mode 100644
index 0000000000..baab6ce0f9
--- /dev/null
+++ b/tools/quickbook/test/xinclude/xmlbase1-1_6.gold
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="xinclude_with_xmlbase" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xml:base="test/xinclude" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>XInclude with xmlbase</title>
+ <xi:include href="../stub.xml" />
+ <xi:include href="stub.xml" />
+ <xi:include href="sub/stub.xml" />
+</article>
diff --git a/tools/quickbook/test/xinclude/xmlbase1-1_6.quickbook b/tools/quickbook/test/xinclude/xmlbase1-1_6.quickbook
new file mode 100644
index 0000000000..7851d86ed6
--- /dev/null
+++ b/tools/quickbook/test/xinclude/xmlbase1-1_6.quickbook
@@ -0,0 +1,8 @@
+[article XInclude with xmlbase
+[quickbook 1.6]
+[xmlbase .]
+]
+
+[xinclude ../stub.xml]
+[xinclude stub.xml]
+[xinclude sub/stub.xml]
diff --git a/tools/quickbook/test/xinclude/xmlbase2-1_6-alt.gold b/tools/quickbook/test/xinclude/xmlbase2-1_6-alt.gold
new file mode 100644
index 0000000000..a0168a6477
--- /dev/null
+++ b/tools/quickbook/test/xinclude/xmlbase2-1_6-alt.gold
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="xinclude_with_xmlbase" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xml:base="../../include" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>XInclude with xmlbase</title>
+ <xi:include href="../stub.xml" />
+ <xi:include href="../xinclude/stub.xml" />
+ <xi:include href="../xinclude/sub/stub.xml" />
+</article>
diff --git a/tools/quickbook/test/xinclude/xmlbase2-1_6.gold b/tools/quickbook/test/xinclude/xmlbase2-1_6.gold
new file mode 100644
index 0000000000..7e7f388857
--- /dev/null
+++ b/tools/quickbook/test/xinclude/xmlbase2-1_6.gold
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="xinclude_with_xmlbase" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xml:base="test/include" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>XInclude with xmlbase</title>
+ <xi:include href="../stub.xml" />
+ <xi:include href="../xinclude/stub.xml" />
+ <xi:include href="../xinclude/sub/stub.xml" />
+</article>
diff --git a/tools/quickbook/test/xinclude/xmlbase2-1_6.quickbook b/tools/quickbook/test/xinclude/xmlbase2-1_6.quickbook
new file mode 100644
index 0000000000..73386b1496
--- /dev/null
+++ b/tools/quickbook/test/xinclude/xmlbase2-1_6.quickbook
@@ -0,0 +1,8 @@
+[article XInclude with xmlbase
+[quickbook 1.6]
+[xmlbase ../include]
+]
+
+[xinclude ../stub.xml]
+[xinclude stub.xml]
+[xinclude sub/stub.xml]
diff --git a/tools/quickbook/test/xml_escape-1_2.gold b/tools/quickbook/test/xml_escape-1_2.gold
new file mode 100644
index 0000000000..bd28ae4394
--- /dev/null
+++ b/tools/quickbook/test/xml_escape-1_2.gold
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<library id="test_that__amp____lt__are_being_escaped_" name="Test that &amp;, &lt; are being escaped."
+dirname="test_that__amp____lt__are_being_escaped_" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <libraryinfo>
+ <legalnotice id="test_that__amp____lt__are_being_escaped_.legal">
+ <para>
+ &amp; should be &amp;amp;, &lt; should &amp;lt;
+ </para>
+ </legalnotice>
+ <librarypurpose>
+ &amp; should be &amp;amp;, &lt; should &amp;lt;
+ </librarypurpose>
+ </libraryinfo>
+ <title>Test that &amp;, &lt; are being escaped.</title>
+ <section id="test_that__amp____lt__are_being_escaped_.escapes___explicitly_written_markup">
+ <title>Escapes &amp; explicitly written markup</title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ &amp; -&gt; &amp;amp;
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &lt; -&gt; &amp;lt;
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &gt; -&gt; &amp;gt;
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &quot; -&gt; &amp;quot;
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+</library>
diff --git a/tools/quickbook/test/xml_escape-1_2.quickbook b/tools/quickbook/test/xml_escape-1_2.quickbook
new file mode 100644
index 0000000000..66a6086cc1
--- /dev/null
+++ b/tools/quickbook/test/xml_escape-1_2.quickbook
@@ -0,0 +1,14 @@
+[library Test that &amp;, &lt; are being escaped.
+ [quickbook 1.2]
+ [purpose &amp; should be &amp;amp;, &lt; should &amp;lt;]
+ [license &amp; should be &amp;amp;, &lt; should &amp;lt;]
+]
+
+[section Escapes & explicitly written markup]
+
+* & -> &amp;
+* < -> &lt;
+* > -> &gt;
+* " -> &quot;
+
+[endsect] \ No newline at end of file
diff --git a/tools/quickbook/test/xml_escape-1_5.gold b/tools/quickbook/test/xml_escape-1_5.gold
new file mode 100644
index 0000000000..f8f33edd27
--- /dev/null
+++ b/tools/quickbook/test/xml_escape-1_5.gold
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<library id="test_that__amp____lt__are_being_escaped_" name="Test that &amp;, &lt; are being escaped."
+dirname="test_that__amp____lt__are_being_escaped_" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <libraryinfo>
+ <legalnotice id="test_that__amp____lt__are_being_escaped_.legal">
+ <para>
+ &amp; should be &amp;amp;, &lt; should &amp;lt;
+ </para>
+ </legalnotice>
+ <librarypurpose>
+ &amp; should be &amp;amp;, &lt; should &amp;lt;
+ </librarypurpose>
+ </libraryinfo>
+ <title>Test that &amp;, &lt; are being escaped.</title>
+ <section id="test_that__amp____lt__are_being_escaped_.escapes___explicitly_written_markup">
+ <title><link linkend="test_that__amp____lt__are_being_escaped_.escapes___explicitly_written_markup">Escapes
+ &amp; explicitly written markup</link></title>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ &amp; -&gt; &amp;amp;
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &lt; -&gt; &amp;lt;
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &gt; -&gt; &amp;gt;
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ &quot; -&gt; &amp;quot;
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+</library>
diff --git a/tools/quickbook/test/xml_escape-1_5.quickbook b/tools/quickbook/test/xml_escape-1_5.quickbook
new file mode 100644
index 0000000000..642e1b5370
--- /dev/null
+++ b/tools/quickbook/test/xml_escape-1_5.quickbook
@@ -0,0 +1,14 @@
+[library Test that &amp;, &lt; are being escaped.
+ [quickbook 1.5]
+ [purpose & should be &amp;, < should &lt;]
+ [license & should be &amp;, < should &lt;]
+]
+
+[section Escapes & explicitly written markup]
+
+* & -> &amp;
+* < -> &lt;
+* > -> &gt;
+* " -> &quot;
+
+[endsect] \ No newline at end of file
diff --git a/tools/regression/build/Jamroot.jam b/tools/regression/build/Jamroot.jam
new file mode 100644
index 0000000000..e1abe768cd
--- /dev/null
+++ b/tools/regression/build/Jamroot.jam
@@ -0,0 +1,84 @@
+# Regression test status reporting tools build Jamfile
+
+# Copyright Rene Rivera
+
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+
+if [ glob ../../../boost-build.jam ]
+{
+ use-project /boost : ../../.. ;
+}
+else
+{
+ import modules ;
+ use-project /boost : [ MATCH --boost=(.*) : [ modules.peek : ARGV ] ] ;
+}
+
+if ! [ glob ../src/process_jam_log.cpp ]
+{
+ project boost/regression
+ :
+ source-location ..
+ ;
+}
+else
+{
+ project boost/regression
+ :
+ source-location ../src
+ ;
+}
+
+obj tiny_xml
+ :
+ detail/tiny_xml.cpp
+ :
+ <define>BOOST_ALL_NO_LIB=1
+ <define>_CRT_SECURE_NO_WARNINGS
+ <use>/boost//headers
+ :
+ release
+ ;
+explicit tiny_xml ;
+
+exe process_jam_log
+ :
+ process_jam_log.cpp
+ tiny_xml
+ /boost/filesystem//boost_filesystem/<link>static
+ :
+ <define>BOOST_ALL_NO_LIB=1
+ <define>_CRT_SECURE_NO_WARNINGS
+ <use>/boost//headers
+ :
+ release
+ ;
+#~ explicit process_jam_log ;
+
+exe compiler_status
+ :
+ compiler_status.cpp
+ tiny_xml
+ /boost/filesystem//boost_filesystem/<link>static
+ :
+ <define>BOOST_ALL_NO_LIB=1
+ <use>/boost//headers
+ :
+ release
+ ;
+explicit compiler_status ;
+
+exe library_status
+ :
+ library_status.cpp
+ tiny_xml
+ /boost/filesystem//boost_filesystem/<link>static
+ :
+ <define>BOOST_ALL_NO_LIB=1
+ <use>/boost//headers
+ :
+ release
+ ;
+explicit library_status ;
diff --git a/tools/regression/build/vcide/compiler_status.vcproj b/tools/regression/build/vcide/compiler_status.vcproj
new file mode 100644
index 0000000000..600981c9df
--- /dev/null
+++ b/tools/regression/build/vcide/compiler_status.vcproj
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="compiler_status"
+ ProjectGUID="{81F22EF9-A1B8-46CB-9C2D-56FD4327B942}"
+ Keyword="MakeFileProj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="0">
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="cd ..\..\..\..\tools\regression\build
+..\..\jam\src\bin.ntx86\bjam.exe compiler_status.exe variant=debug"
+ ReBuildCommandLine="cd ..\..\..\..\tools\regression\build
+...\..\jam\src\bin.ntx86\bjam.exe -a compiler_status.exe variant=debug"
+ CleanCommandLine="cd ..\..\..\..\tools\regression\build
+call bjam --v2 msvc-7.1 debug clean
+"
+ Output="compiler_status.exe"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="0">
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam compiler_status variant=release link=static"
+ ReBuildCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam -a compiler_status variant=release link=static"
+ CleanCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam clean"
+ Output="..\..\..\..\bin.v2\tools\regression\build\msvc-7.1\release\link-static\compiler_status.exe"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\compiler_status.cpp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tools/regression/build/vcide/library_status.vcproj b/tools/regression/build/vcide/library_status.vcproj
new file mode 100644
index 0000000000..bd069fdaf6
--- /dev/null
+++ b/tools/regression/build/vcide/library_status.vcproj
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="library_status"
+ ProjectGUID="{465BDB84-92B5-4C60-AF26-8BD1A61A089E}"
+ Keyword="MakeFileProj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="0">
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam library_status variant=debug link=static"
+ ReBuildCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam -a library_status variant=debug link=static"
+ CleanCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam clean"
+ Output="..\..\..\..\bin.v2\tools\regression\build\msvc-7.1\debug\link-static\library_status.exe"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="0">
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam library_status variant=release link=static"
+ ReBuildCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam -a library_status variant=release link=static"
+ CleanCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam clean"
+ Output="..\..\..\..\bin.v2\tools\regression\build\msvc-7.1\release\link-static\library_status.exe"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\library_status.cpp">
+ </File>
+ <File
+ RelativePath="..\..\detail\tiny_xml.cpp">
+ </File>
+ <File
+ RelativePath="..\..\detail\tiny_xml.hpp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tools/regression/build/vcide/process_jam_log.sln b/tools/regression/build/vcide/process_jam_log.sln
new file mode 100644
index 0000000000..29833cc0e1
--- /dev/null
+++ b/tools/regression/build/vcide/process_jam_log.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "process_jam_log", "process_jam_log.vcproj", "{9A751791-929F-496A-8DE7-B61020619BFA}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {9A751791-929F-496A-8DE7-B61020619BFA}.Debug.ActiveCfg = Debug|Win32
+ {9A751791-929F-496A-8DE7-B61020619BFA}.Debug.Build.0 = Debug|Win32
+ {9A751791-929F-496A-8DE7-B61020619BFA}.Release.ActiveCfg = Release|Win32
+ {9A751791-929F-496A-8DE7-B61020619BFA}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/tools/regression/build/vcide/process_jam_log.vcproj b/tools/regression/build/vcide/process_jam_log.vcproj
new file mode 100644
index 0000000000..bbc8c9d78a
--- /dev/null
+++ b/tools/regression/build/vcide/process_jam_log.vcproj
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="process_jam_log"
+ ProjectGUID="{9A751791-929F-496A-8DE7-B61020619BFA}"
+ RootNamespace="process_jam_log"
+ Keyword="MakeFileProj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="0">
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="cd ..\..\..\..\tools\regression\build
+..\..\jam\src\bin.ntx86\bjam.exe process_jam_log variant=debug
+"
+ ReBuildCommandLine="cd ..\..\..\..\tools\regression\build
+call bjam --v2 msvc-7.1 debug clean
+call bjam --v2 msvc-7.1 debug"
+ CleanCommandLine="cd ..\..\..\..\tools\regression\build
+call bjam --v2 msvc-7.1 debug clean
+"
+ Output="../../../../bin.v2/tools/regression/build/msvc-7.1/debug/link-static/process_jam_log.exe"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="0">
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam process_jam_log variant=release link=static"
+ ReBuildCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam -a process_jam_log variant=release link=static"
+ CleanCommandLine="cd ..
+..\..\jam\src\bin.ntx86\bjam clean"
+ Output="..\..\..\..\bin.v2\tools\regression\build\msvc-7.1\release\link-static\process_jam_log.exe"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+ </Filter>
+ <File
+ RelativePath=".\readme.txt">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tools/regression/build/vcide/regression.sln b/tools/regression/build/vcide/regression.sln
new file mode 100644
index 0000000000..170f08037f
--- /dev/null
+++ b/tools/regression/build/vcide/regression.sln
@@ -0,0 +1,37 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "compiler_status", "compiler_status.vcproj", "{81F22EF9-A1B8-46CB-9C2D-56FD4327B942}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "process_jam_log", "process_jam_log.vcproj", "{9A751791-929F-496A-8DE7-B61020619BFA}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "library_status", "library_status.vcproj", "{465BDB84-92B5-4C60-AF26-8BD1A61A089E}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {81F22EF9-A1B8-46CB-9C2D-56FD4327B942}.Debug.ActiveCfg = Debug|Win32
+ {81F22EF9-A1B8-46CB-9C2D-56FD4327B942}.Debug.Build.0 = Debug|Win32
+ {81F22EF9-A1B8-46CB-9C2D-56FD4327B942}.Release.ActiveCfg = Release|Win32
+ {81F22EF9-A1B8-46CB-9C2D-56FD4327B942}.Release.Build.0 = Release|Win32
+ {9A751791-929F-496A-8DE7-B61020619BFA}.Debug.ActiveCfg = Debug|Win32
+ {9A751791-929F-496A-8DE7-B61020619BFA}.Debug.Build.0 = Debug|Win32
+ {9A751791-929F-496A-8DE7-B61020619BFA}.Release.ActiveCfg = Release|Win32
+ {9A751791-929F-496A-8DE7-B61020619BFA}.Release.Build.0 = Release|Win32
+ {465BDB84-92B5-4C60-AF26-8BD1A61A089E}.Debug.ActiveCfg = Debug|Win32
+ {465BDB84-92B5-4C60-AF26-8BD1A61A089E}.Debug.Build.0 = Debug|Win32
+ {465BDB84-92B5-4C60-AF26-8BD1A61A089E}.Release.ActiveCfg = Release|Win32
+ {465BDB84-92B5-4C60-AF26-8BD1A61A089E}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/tools/regression/doc/index.html b/tools/regression/doc/index.html
new file mode 100644
index 0000000000..1ce288ab54
--- /dev/null
+++ b/tools/regression/doc/index.html
@@ -0,0 +1,57 @@
+<!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">
+<head>
+ <meta http-equiv="Content-Language" content="en-us" />
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
+ <link rel="stylesheet" type="text/css" href=
+ "../../../doc/src/boostbook.css" />
+
+ <title>Regression Test Reporting Tools</title>
+</head>
+
+<body>
+ <h1><img src="../../../boost.png" alt="boost.png (6897 bytes)" align=
+ "center" width="277" height="86" /> Regression Test Reporting Tools</h1>
+
+ <p>Boost regression testing uses <a href=
+ "../../build/index.html">Boost.Build</a> to run the actual builds and
+ tests. A separate set of tools is used to generate the actual status
+ reports.</p>
+
+ <ul>
+ <li><a href=
+ "http://beta.boost.org/development/running_regression_tests.html">Instructions</a>
+ for running the regression tests as part of the published regression
+ tests are available at the Boost web site.</li>
+
+ <li><a href="../src/process_jam_log.cpp">process_jam_log.cpp</a> -
+ Processes the bjam outputs, creating a file named test_log.xml for each
+ test encountered.</li>
+
+ <li><a href="../src/compiler_status.cpp">compiler_status.cpp</a> -
+ Generates HTML status tables from test_log.xml and other files.</li>
+
+ <li><a href="../build/Jamroot.jam">Jamroot.jam</a> - Builds process_jam_log
+ and compiler_status executables.</li>
+
+ <li><a href="library_status.html">Library Status</a> - Runs test programs
+ for one or all boost libraries on your local installation and generates
+ complete tables to show which combinations of libraries, compilers,
+ compiler settings pass and fail at your local installation.</li>
+ </ul>
+ <hr />
+
+ <p>Revised $Date: 2010-06-26 08:30:09 -0400 (Sat, 26 Jun 2010) $</p>
+
+ <p>Copyright Beman Dawes 2003.</p>
+
+ <p>Copyright Rene Rivera 2007.</p>
+
+ <p>Distributed under the Boost Software License, Version 1.0. (See
+ accompanying file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
+ copy at <a href=
+ "http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
+</body>
+</html>
diff --git a/tools/regression/doc/library_status.html b/tools/regression/doc/library_status.html
new file mode 100644
index 0000000000..e85d30405b
--- /dev/null
+++ b/tools/regression/doc/library_status.html
@@ -0,0 +1,464 @@
+<!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">
+<head>
+ <meta http-equiv="Content-Language" content="en-us" />
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
+ <link rel="stylesheet" type="text/css" href=
+ "../../../doc/src/boostbook.css" />
+
+ <title>Libary Status</title>
+ <style type="text/css">
+/*<![CDATA[*/
+ span.c3 {color: #FF0000; font-style: italic}
+ a.c2 {font-style: italic}
+ td.c1 {font-style: italic}
+ /*]]>*/
+ </style>
+</head>
+
+<body>
+ <table border="0">
+ <tr>
+ <td><img border="0" src="../../../boost.png" width="277" height="86"
+ alt="boost.png (6897 bytes)" /></td>
+
+ <td>
+ <h1>Generating Library Status Tables</h1>
+ </td>
+ </tr>
+ </table>
+
+ <h3>Purpose</h3>Any time one considers using a library as large and complex
+ as the Boost libraries, he must have a way of validating the the library
+ functions in his environment. This should be done when the library is
+ installed and anytime questions are raised regarding its applicabililty
+ and/or its usage.
+
+ <p>The procedures described here permit a user to run any combination of
+ tests on any or all libraries and generate a set of convenient tables which
+ show which libraries pass which tests under what conditions.</p>
+
+ <h3>Preliminaries</h3>Generating these tables requires a couple of utility
+ programs: <code>process_jam_log</code> and <code>library_status</code>.
+ These can be built by moving to the directory
+ <code>tools/regression/build</code> and invoking bjam. If all goes well
+ these utility programs will be found in the directory
+ <code>dist/bin</code>. From there they should be moved to a place in the
+ current path.
+
+ <h3>Running Tests for One Library</h3>
+
+ <ol>
+ <li>Start from your command line environment.</li>
+
+ <li>set the current directory to:../libs/&lt;library name&gt;/test</li>
+
+ <li>Invoke one of the following:
+
+ <ul>
+ <li><code>../../../tools/regression/src/library_test (*nix)</code>.</li>
+
+ <li><code>..\..\..\tools\regression\src\library_test
+ (windows)</code>.</li>
+ </ul>
+ </li>
+
+ <li>This will display short help message describing the how to set the
+ command line arguments for the compilers and variants you want to appear
+ in the final table.</li>
+
+ <li>Setting these arguments requires rudimentary knowledge of bjam usage.
+ Hopefully, if you've arrived at this page you've gained the required
+ knowledge during the installation and library build process.</li>
+
+ <li>Rerun the abve command with the argument set accordingly.</li>
+
+ <li>When the command terminates, there should be a file named
+ "library_status.html" in the current directory.</li>
+
+ <li>Display this file with any web browser.</li>
+ </ol>There should appear a table similar to the following for the regex
+ library.
+
+ <table border="1" cellspacing="0" cellpadding="5">
+ <tr>
+ <td rowspan="4">Test Name</td>
+
+ <td align="center" colspan="4">msvc-7.1</td>
+ </tr>
+
+ <tr>
+ <td align="center" colspan="2">debug</td>
+
+ <td align="center" colspan="2">release</td>
+ </tr>
+
+ <tr>
+ <td align="center">link-static</td>
+
+ <td align="center" rowspan="2">threading-multi</td>
+
+ <td align="center">link-static</td>
+
+ <td align="center" rowspan="2">threading-multi</td>
+ </tr>
+
+ <tr>
+ <td align="center">threading-multi</td>
+
+ <td align="center">threading-multi</td>
+ </tr>
+
+ <tr>
+ <td>bad_expression_test</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-bad_expression_test.test-msvc-7.1-debug-threading-multi">
+ Warn</a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-bad_expression_test.test-msvc-7.1-release-threading-multi">
+ Warn</a></td>
+ </tr>
+
+ <tr>
+ <td>captures</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-captures-msvc-7.1-debug-threading-multi">
+ <span class="c3">Fail</span></a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-captures-msvc-7.1-release-threading-multi">
+ <span class="c3">Fail</span></a></td>
+ </tr>
+
+ <tr>
+ <td>captures_test</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-captures_test.test-msvc-7.1-debug-threading-multi">
+ Warn</a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-captures_test.test-msvc-7.1-release-threading-multi">
+ Warn</a></td>
+ </tr>
+
+ <tr>
+ <td>concept_check</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right">Pass</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right">Pass</td>
+ </tr>
+
+ <tr>
+ <td>icu_concept_check</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right">Pass</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right">Pass</td>
+ </tr>
+
+ <tr>
+ <td>object_cache_test</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-object_cache_test.test-msvc-7.1-debug-threading-multi">
+ Warn</a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-object_cache_test.test-msvc-7.1-release-threading-multi">
+ Warn</a></td>
+ </tr>
+
+ <tr>
+ <td>posix_api_check</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-posix_api_check.test-msvc-7.1-debug-threading-multi">
+ Warn</a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-posix_api_check.test-msvc-7.1-release-threading-multi">
+ Warn</a></td>
+ </tr>
+
+ <tr>
+ <td>posix_api_check_cpp</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right">Pass</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right">Pass</td>
+ </tr>
+
+ <tr>
+ <td>recursion_test</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-recursion_test.test-msvc-7.1-debug-threading-multi">
+ Warn</a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-recursion_test.test-msvc-7.1-release-threading-multi">
+ Warn</a></td>
+ </tr>
+
+ <tr>
+ <td>regex_config_info</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-regex_config_info.test-msvc-7.1-debug-threading-multi">
+ Pass</a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-regex_config_info.test-msvc-7.1-release-threading-multi">
+ Pass</a></td>
+ </tr>
+
+ <tr>
+ <td>regex_dll_config_info</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-regex_dll_config_info.test-msvc-7.1-debug-threading-multi">
+ Pass</a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-regex_dll_config_info.test-msvc-7.1-release-threading-multi">
+ Pass</a></td>
+ </tr>
+
+ <tr>
+ <td>regex_regress</td>
+
+ <td align="right"><a href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress.test-msvc-7.1-debug-link-static-threading-multi">
+ Pass</a><sup>*</sup></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress.test-msvc-7.1-release-link-static-threading-multi">
+ Pass</a><sup>*</sup></td>
+
+ <td class="c1" align="right">Missing</td>
+ </tr>
+
+ <tr>
+ <td>regex_regress_dll</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress_dll.test-msvc-7.1-debug-threading-multi">
+ Pass</a><sup>*</sup></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-regex_regress_dll.test-msvc-7.1-release-threading-multi">
+ Pass</a><sup>*</sup></td>
+ </tr>
+
+ <tr>
+ <td>regex_regress_threaded</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right">Pass</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right">Pass</td>
+ </tr>
+
+ <tr>
+ <td>static_mutex_test</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right">Pass</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right">Pass</td>
+ </tr>
+
+ <tr>
+ <td>test_collate_info</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-test_collate_info.test-msvc-7.1-debug-threading-multi">
+ Warn</a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-test_collate_info.test-msvc-7.1-release-threading-multi">
+ Warn</a></td>
+ </tr>
+
+ <tr>
+ <td>unicode_iterator_test</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-unicode_iterator_test.test-msvc-7.1-debug-threading-multi">
+ Warn</a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-unicode_iterator_test.test-msvc-7.1-release-threading-multi">
+ Warn</a></td>
+ </tr>
+
+ <tr>
+ <td>wide_posix_api_check_c</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_c.test-msvc-7.1-debug-threading-multi">
+ Warn</a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_c.test-msvc-7.1-release-threading-multi">
+ Warn</a></td>
+ </tr>
+
+ <tr>
+ <td>wide_posix_api_check_cpp</td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_cpp.test-msvc-7.1-debug-threading-multi">
+ Warn</a></td>
+
+ <td class="c1" align="right">Missing</td>
+
+ <td align="right"><a class="c2" href=
+ "links.html#C:-Boost134-bin.v2-libs-regex-test-wide_posix_api_check_cpp.test-msvc-7.1-release-threading-multi">
+ Warn</a></td>
+ </tr>
+ </table>
+
+ <p>This table was generated by invoking the following command line:</p>
+
+ <p><code>../../../tools/regression/src/library_test --toolset=msvc-7.1
+ variant=debug,release</code></p>
+
+ <p>from within the .../libs/regex/test directory.</p>
+
+ <p>This table shows the regex test results for both debug and release
+ versions of the library. Also it displays the fact that one of the tests is
+ run specifically with the static linking/multi-threading versions of the
+ runtime libraries. The cells marked "Missing" correspond to tests that were
+ not run for some reason or another. This is usually because the
+ corresponding <code>Jamfile.v2</code> excludes this test for the given
+ combination of compiler and build attributes. In this example, all tests
+ were run with the same compiler. If additional compilers were used, they
+ would appear as more columns in the table.</p>
+
+ <p>The table above is just an illustration so the links don't actually
+ point to anything. In the table you generated, the links will display a
+ page describing any errors, warnings or other available information about
+ the tests. If the test passes, usually, there is no additional information
+ and hence no link.</p>
+
+ <p>The tables are cumulative. That is, if you run one set of tests now and
+ tests with different attributes later, the table will contain all the
+ results to date. The test results are stored in
+ <code>../bin.v2/libs/test/&lt;library%gt;/...</code>. To reinitialize the
+ test results to empty, delete the corresponding files in this
+ directory.</p>
+
+ <p>The procedure above assumes that the table are generated within the
+ directory <code>../libs/&lt;library&gt;/test</code>. This is the most
+ common case since this directory contains the <code>Jamfile.v2</code> as
+ well as the source code that is used by official boost testers. However,
+ this is just a convention. The table can be generated for other directories
+ within the libary. One possiblity would be to generate the table for all
+ the examples in <code>../libs/%lt;library%gt;/example</code>. Or one might
+ have a special directory of performance tests which take a long time to run
+ and hence are not suitable for running by official boost testers. Just
+ remember that library status table is generated in the directory from which
+ the <code>library_test</code> command is invoked.</p>
+
+ <h3>Running Tests for All Libraries</h3>For those with *nix or cygwin
+ command line shells, there is shell script that can be run from the boost
+ root directory:
+
+ <p><code>tools/regression/src/library_test_all</code></p>
+
+ <p>The command line arguments are the same as for running the test for one
+ library. This script creates all the html files in all the test directories
+ as well as an html page in the <code>status</code> directory named
+ <code>library_status_summary.html</code>. This can be used to browse
+ through all test results for all test in all libraries.</p>
+ <hr />
+
+
+ <p>Copyright 2011 Bryce Lelbach.</p>
+ <p>Copyright 2007-2011 Robert Ramey.</p>
+
+ <p>Distributed under the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or
+ http://www.boost.org/LICENSE_1_0.txt)</p>
+
+ <p>Revised $Date: 2011-10-06 11:41:40 -0400 (Thu, 06 Oct 2011) $</p>
+</body>
+</html>
diff --git a/tools/regression/index.html b/tools/regression/index.html
new file mode 100644
index 0000000000..536c846f9d
--- /dev/null
+++ b/tools/regression/index.html
@@ -0,0 +1,23 @@
+<!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">
+<head>
+ <meta http-equiv="refresh" content="0; URL=doc/index.html" />
+
+ <title></title>
+</head>
+
+<body>
+ Automatic redirection failed, please go to <a href=
+ "doc/index.html">doc/index.html</a>
+ <hr />
+
+ <p>Copyright Rene Rivera, 2007</p>
+
+ <p>Distributed under the Boost Software License, Version 1.0. (See
+ accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
+ copy at <a href=
+ "http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
+</body>
+</html>
diff --git a/tools/regression/src/boost_svn_export_archive.sh b/tools/regression/src/boost_svn_export_archive.sh
new file mode 100755
index 0000000000..e86d377ab9
--- /dev/null
+++ b/tools/regression/src/boost_svn_export_archive.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+#~ Copyright Redshift Software, Inc. 2007
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+export PATH=/bin:/usr/bin:${PATH}
+
+timestamp=`date +%F-%H-%M-%S-%Z`
+branch=$1
+revision=`svn info file:///home/subversion/boost/${branch} | grep '^Revision:' | cut --byte=11-`
+tag=boost-${1/\/*}-${timestamp}
+export_dir=boost-$$
+
+# Remove files as listed in stdin, the assumption is that processing
+# of the file is complete and can be removed.
+rm_c()
+{
+ while read f; do
+ rm -f ${f}
+ done
+}
+# Generate the export file tree, and incrementally output the files
+# created.
+svn_export()
+{
+ svn export -r ${revision} file:///home/subversion/boost/${branch} ${tag}
+ echo "Revision: ${revision}" > ${tag}/svn_info.txt
+ echo "---- ${tag}/svn_info.txt"
+}
+# Create the archive incrementally, deleting files as we are done
+# adding them to the archive.
+make_archive()
+{
+ svn_export \
+ | cut --bytes=6- \
+ | star -c -D -to-stdout -d artype=pax list=- 2>/dev/null \
+ | bzip2 -6 -c \
+ | tee $1 \
+ | tar -jtf - \
+ | rm_c
+}
+
+run()
+{
+ cd /tmp
+ rm -rf ${export_dir}
+ mkdir ${export_dir}
+ cd ${export_dir}
+ mkfifo out.tbz2
+ make_archive out.tbz2 &
+ cat out.tbz2
+ cd /tmp
+ rm -rf ${export_dir}
+}
+
+run_debug()
+{
+ rm -rf ${export_dir}
+ mkdir ${export_dir}
+ cd ${export_dir}
+ mkfifo out.tbz2
+ make_archive out.tbz2 &
+ cat out.tbz2 > ../${tag}.tar.bz2
+ cd ..
+ rm -rf ${export_dir}
+}
+
+run
+#run_debug
diff --git a/tools/regression/src/collect_and_upload_logs.py b/tools/regression/src/collect_and_upload_logs.py
new file mode 100644
index 0000000000..7f1345bd6f
--- /dev/null
+++ b/tools/regression/src/collect_and_upload_logs.py
@@ -0,0 +1,546 @@
+
+# Copyright (c) MetaCommunications, Inc. 2003-2007
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import xml.sax.saxutils
+import zipfile
+import ftplib
+import time
+import stat
+import xml.dom.minidom
+import xmlrpclib
+import httplib
+
+import os.path
+import string
+import sys
+import re
+import urlparse
+
+
+def process_xml_file( input_file, output_file ):
+ utils.log( 'Processing test log "%s"' % input_file )
+
+ f = open( input_file, 'r' )
+ xml = f.readlines()
+ f.close()
+
+ for i in range( 0, len(xml)):
+ xml[i] = string.translate( xml[i], utils.char_translation_table )
+
+ output_file.writelines( xml )
+
+
+def process_test_log_files( output_file, dir, names ):
+ for file in names:
+ if os.path.basename( file ) == 'test_log.xml':
+ process_xml_file( os.path.join( dir, file ), output_file )
+
+
+def collect_test_logs( input_dirs, test_results_writer ):
+ __log__ = 1
+ utils.log( 'Collecting test logs ...' )
+ for input_dir in input_dirs:
+ utils.log( 'Walking directory "%s" ...' % input_dir )
+ os.path.walk( input_dir, process_test_log_files, test_results_writer )
+
+dart_status_from_result = {
+ 'succeed': 'passed',
+ 'fail': 'failed',
+ 'note': 'passed',
+ '': 'notrun'
+ }
+
+dart_project = {
+ 'trunk': 'Boost_HEAD',
+ '': 'Boost_HEAD'
+ }
+
+dart_track = {
+ 'full': 'Nightly',
+ 'incremental': 'Continuous',
+ '': 'Experimental'
+ }
+
+ascii_only_table = ""
+for i in range(0,256):
+ if chr(i) == '\n' or chr(i) == '\r':
+ ascii_only_table += chr(i)
+ elif i < 32 or i >= 0x80:
+ ascii_only_table += '?'
+ else:
+ ascii_only_table += chr(i)
+
+class xmlrpcProxyTransport(xmlrpclib.Transport):
+ def __init__(self, proxy):
+ self.proxy = proxy
+ def make_connection(self, host):
+ self.realhost = host
+ return httplib.HTTP(self.proxy)
+ def send_request(self, connection, handler, request_body):
+ connection.putrequest('POST','http://%s%s' % (self.realhost,handler))
+ def send_host(self, connection, host):
+ connection.putheader('Host',self.realhost)
+
+
+def publish_test_logs(
+ input_dirs,
+ runner_id, tag, platform, comment_file, timestamp, user, source, run_type,
+ dart_server = None,
+ http_proxy = None,
+ **unused
+ ):
+ __log__ = 1
+ utils.log( 'Publishing test logs ...' )
+ dart_rpc = None
+ dart_dom = {}
+
+ def _publish_test_log_files_ ( unused, dir, names ):
+ for file in names:
+ if os.path.basename( file ) == 'test_log.xml':
+ utils.log( 'Publishing test log "%s"' % os.path.join(dir,file) )
+ if dart_server:
+ log_xml = open(os.path.join(dir,file)).read().translate(ascii_only_table)
+ #~ utils.log( '--- XML:\n%s' % log_xml)
+ #~ It seems possible to get an empty XML result file :-(
+ if log_xml == "": continue
+ log_dom = xml.dom.minidom.parseString(log_xml)
+ test = {
+ 'library': log_dom.documentElement.getAttribute('library'),
+ 'test-name': log_dom.documentElement.getAttribute('test-name'),
+ 'toolset': log_dom.documentElement.getAttribute('toolset')
+ }
+ if not test['test-name'] or test['test-name'] == '':
+ test['test-name'] = 'unknown'
+ if not test['toolset'] or test['toolset'] == '':
+ test['toolset'] = 'unknown'
+ if not dart_dom.has_key(test['toolset']):
+ dart_dom[test['toolset']] = xml.dom.minidom.parseString(
+'''<?xml version="1.0" encoding="UTF-8"?>
+<DartSubmission version="2.0" createdby="collect_and_upload_logs.py">
+ <Site>%(site)s</Site>
+ <BuildName>%(buildname)s</BuildName>
+ <Track>%(track)s</Track>
+ <DateTimeStamp>%(datetimestamp)s</DateTimeStamp>
+</DartSubmission>
+''' % {
+ 'site': runner_id,
+ 'buildname': "%s -- %s (%s)" % (platform,test['toolset'],run_type),
+ 'track': dart_track[run_type],
+ 'datetimestamp' : timestamp
+ } )
+ submission_dom = dart_dom[test['toolset']]
+ for node in log_dom.documentElement.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.firstChild:
+ log_data = xml.sax.saxutils.escape(node.firstChild.data)
+ else:
+ log_data = ''
+ test_dom = xml.dom.minidom.parseString('''<?xml version="1.0" encoding="UTF-8"?>
+<Test>
+ <Name>.Test.Boost.%(tag)s.%(library)s.%(test-name)s.%(type)s</Name>
+ <Status>%(result)s</Status>
+ <Measurement name="Toolset" type="text/string">%(toolset)s</Measurement>
+ <Measurement name="Timestamp" type="text/string">%(timestamp)s</Measurement>
+ <Measurement name="Log" type="text/text">%(log)s</Measurement>
+</Test>
+ ''' % {
+ 'tag': tag,
+ 'library': test['library'],
+ 'test-name': test['test-name'],
+ 'toolset': test['toolset'],
+ 'type': node.nodeName,
+ 'result': dart_status_from_result[node.getAttribute('result')],
+ 'timestamp': node.getAttribute('timestamp'),
+ 'log': log_data
+ })
+ submission_dom.documentElement.appendChild(
+ test_dom.documentElement.cloneNode(1) )
+
+ for input_dir in input_dirs:
+ utils.log( 'Walking directory "%s" ...' % input_dir )
+ os.path.walk( input_dir, _publish_test_log_files_, None )
+ if dart_server:
+ try:
+ rpc_transport = None
+ if http_proxy:
+ rpc_transport = xmlrpcProxyTransport(http_proxy)
+ dart_rpc = xmlrpclib.ServerProxy(
+ 'http://%s/%s/Command/' % (dart_server,dart_project[tag]),
+ rpc_transport )
+ for dom in dart_dom.values():
+ #~ utils.log('Dart XML: %s' % dom.toxml('utf-8'))
+ dart_rpc.Submit.put(xmlrpclib.Binary(dom.toxml('utf-8')))
+ except Exception, e:
+ utils.log('Dart server error: %s' % e)
+
+
+def upload_to_ftp( tag, results_file, ftp_proxy, debug_level, ftp_url ):
+
+ if not ftp_url:
+ ftp_host = 'boost.cowic.de'
+ ftp_url = ''.join(['ftp','://anonymous','@',ftp_host,'/boost/do-not-publish-this-url/results/'])
+ utils.log( 'Uploading log archive "%s" to %s/%s' % ( results_file, ftp_url, tag ) )
+
+ ftp_parts = urlparse.urlparse(ftp_url)
+ ftp_netloc = re.split('[@]',ftp_parts[1])
+ ftp_user = re.split('[:]',ftp_netloc[0])[0]
+ ftp_password = re.split('[:]',ftp_netloc[0]+':anonymous')[1]
+ ftp_site = re.split('[:]',ftp_netloc[1])[0]
+ ftp_path = ftp_parts[2]
+
+ if not ftp_proxy:
+ ftp = ftplib.FTP( ftp_site )
+ ftp.set_debuglevel( debug_level )
+ ftp.login( ftp_user, ftp_password )
+ else:
+ utils.log( ' Connecting through FTP proxy server "%s"' % ftp_proxy )
+ ftp = ftplib.FTP( ftp_proxy )
+ ftp.set_debuglevel( debug_level )
+ ftp.set_pasv (0) # turn off PASV mode
+ ftp.login( '%s@%s' % (ftp_user,ftp_site), ftp_password )
+
+ ftp.cwd( ftp_path )
+ try:
+ ftp.cwd( tag )
+ except ftplib.error_perm:
+ for dir in tag.split( '/' ):
+ ftp.mkd( dir )
+ ftp.cwd( dir )
+
+ f = open( results_file, 'rb' )
+ ftp.storbinary( 'STOR %s' % os.path.basename( results_file ), f )
+ ftp.quit()
+
+
+def copy_comments( results_xml, comment_file ):
+ results_xml.startElement( 'comment', {} )
+
+ if os.path.exists( comment_file ):
+ utils.log( 'Reading comments file "%s"...' % comment_file )
+ f = open( comment_file, 'r' )
+ try:
+ results_xml.characters( f.read() )
+ finally:
+ f.close()
+ else:
+ utils.log( 'Warning: comment file "%s" is not found.' % comment_file )
+
+ lines = ['']
+ for arg in sys.argv:
+ # Make sure that the ftp details are hidden
+ arg = re.sub( 'ftp://.*$', 'ftp://XXXXX', arg )
+
+ # Escape quotes
+ arg = re.sub( r'(\\|")', r'\\\1', arg )
+
+ # Quote arguments if needed
+ if arg.find( ' ' ) != -1:
+ arg = '"%s"' % arg
+ if len( lines[-1] ) + len( arg ) + 2 >= 80:
+ # align backslashes
+ lines[-1] += ' ' * ( 79 - len( lines[-1] ) )
+ # indent lines after the first
+ lines.append( ' ' )
+ lines[-1] += ( arg + ' ' )
+
+ results_xml.characters( '<hr>' )
+ results_xml.characters( '<dl>' )
+ results_xml.characters( '<dt>Command Line</dt>' )
+ results_xml.characters( '<dd>' )
+ results_xml.characters( '<pre>' )
+ results_xml.characters( '\\\n'.join(lines) )
+ results_xml.characters( '</pre>' )
+ results_xml.characters( '</dd>' )
+ results_xml.characters( '</dl>\n' )
+
+ results_xml.endElement( 'comment' )
+
+
+def compress_file( file_path, archive_path ):
+ utils.log( 'Compressing "%s"...' % file_path )
+
+ try:
+ z = zipfile.ZipFile( archive_path, 'w', zipfile.ZIP_DEFLATED )
+ z.write( file_path, os.path.basename( file_path ) )
+ z.close()
+ utils.log( 'Done writing "%s".'% archive_path )
+ except Exception, msg:
+ utils.log( 'Warning: Compressing falied (%s)' % msg )
+ utils.log( ' Trying to compress using a platform-specific tool...' )
+ try: import zip_cmd
+ except ImportError:
+ script_dir = os.path.dirname( os.path.abspath( sys.argv[0] ) )
+ utils.log( 'Could not find \'zip_cmd\' module in the script directory (%s).' % script_dir )
+ raise Exception( 'Compressing failed!' )
+ else:
+ if os.path.exists( archive_path ):
+ os.unlink( archive_path )
+ utils.log( 'Removing stale "%s".' % archive_path )
+
+ zip_cmd.main( file_path, archive_path )
+ utils.log( 'Done compressing "%s".' % archive_path )
+
+
+def read_timestamp( file ):
+ if not os.path.exists( file ):
+ result = time.gmtime()
+ utils.log( 'Warning: timestamp file "%s" does not exist'% file )
+ utils.log( 'Using current UTC time (%s)' % result )
+ return result
+
+ return time.gmtime( os.stat( file ).st_mtime )
+
+
+def collect_logs(
+ results_dir
+ , runner_id
+ , tag
+ , platform
+ , comment_file
+ , timestamp_file
+ , user
+ , source
+ , run_type
+ , dart_server = None
+ , http_proxy = None
+ , revision = ''
+ , **unused
+ ):
+
+ timestamp = time.strftime( '%Y-%m-%dT%H:%M:%SZ', read_timestamp( timestamp_file ) )
+
+ if dart_server:
+ publish_test_logs( [ results_dir ],
+ runner_id, tag, platform, comment_file, timestamp, user, source, run_type,
+ dart_server = dart_server,
+ http_proxy = http_proxy )
+
+ results_file = os.path.join( results_dir, '%s.xml' % runner_id )
+ results_writer = open( results_file, 'w' )
+ utils.log( 'Collecting test logs into "%s"...' % results_file )
+
+ results_xml = xml.sax.saxutils.XMLGenerator( results_writer )
+ results_xml.startDocument()
+ results_xml.startElement(
+ 'test-run'
+ , {
+ 'tag': tag
+ , 'platform': platform
+ , 'runner': runner_id
+ , 'timestamp': timestamp
+ , 'source': source
+ , 'run-type': run_type
+ , 'revision': revision
+ }
+ )
+
+ copy_comments( results_xml, comment_file )
+ collect_test_logs( [ results_dir ], results_writer )
+
+ results_xml.endElement( "test-run" )
+ results_xml.endDocument()
+ results_writer.close()
+ utils.log( 'Done writing "%s".' % results_file )
+
+ compress_file(
+ results_file
+ , os.path.join( results_dir,'%s.zip' % runner_id )
+ )
+
+
+def upload_logs(
+ results_dir
+ , runner_id
+ , tag
+ , user
+ , ftp_proxy
+ , debug_level
+ , send_bjam_log = False
+ , timestamp_file = None
+ , dart_server = None
+ , ftp_url = None
+ , **unused
+ ):
+
+ logs_archive = os.path.join( results_dir, '%s.zip' % runner_id )
+ upload_to_ftp( tag, logs_archive, ftp_proxy, debug_level, ftp_url )
+ if send_bjam_log:
+ bjam_log_path = os.path.join( results_dir, 'bjam.log' )
+ if not timestamp_file:
+ timestamp_file = bjam_log_path
+
+ timestamp = time.strftime( '%Y-%m-%d-%H-%M-%S', read_timestamp( timestamp_file ) )
+ logs_archive = os.path.join( results_dir, '%s.%s.log.zip' % ( runner_id, timestamp ) )
+ compress_file( bjam_log_path, logs_archive )
+ upload_to_ftp( '%s/logs' % tag, logs_archive, ftp_proxy, debug_level, ftp_url )
+
+
+def collect_and_upload_logs(
+ results_dir
+ , runner_id
+ , tag
+ , platform
+ , comment_file
+ , timestamp_file
+ , user
+ , source
+ , run_type
+ , revision = None
+ , ftp_proxy = None
+ , debug_level = 0
+ , send_bjam_log = False
+ , dart_server = None
+ , http_proxy = None
+ , ftp_url = None
+ , **unused
+ ):
+
+ collect_logs(
+ results_dir
+ , runner_id
+ , tag
+ , platform
+ , comment_file
+ , timestamp_file
+ , user
+ , source
+ , run_type
+ , revision = revision
+ , dart_server = dart_server
+ , http_proxy = http_proxy
+ )
+
+ upload_logs(
+ results_dir
+ , runner_id
+ , tag
+ , user
+ , ftp_proxy
+ , debug_level
+ , send_bjam_log
+ , timestamp_file
+ , dart_server = dart_server
+ , ftp_url = ftp_url
+ )
+
+
+def accept_args( args ):
+ args_spec = [
+ 'locate-root='
+ , 'runner='
+ , 'tag='
+ , 'platform='
+ , 'comment='
+ , 'timestamp='
+ , 'source='
+ , 'run-type='
+ , 'user='
+ , 'ftp-proxy='
+ , 'proxy='
+ , 'debug-level='
+ , 'send-bjam-log'
+ , 'help'
+ , 'dart-server='
+ , 'revision='
+ , 'ftp='
+ ]
+
+ options = {
+ '--tag' : 'trunk'
+ , '--platform' : sys.platform
+ , '--comment' : 'comment.html'
+ , '--timestamp' : 'timestamp'
+ , '--user' : None
+ , '--source' : 'SVN'
+ , '--run-type' : 'full'
+ , '--ftp-proxy' : None
+ , '--proxy' : None
+ , '--debug-level' : 0
+ , '--dart-server' : 'beta.boost.org:8081'
+ , '--revision' : None
+ , '--ftp' : None
+
+ }
+
+ utils.accept_args( args_spec, args, options, usage )
+
+ return {
+ 'results_dir' : options[ '--locate-root' ]
+ , 'runner_id' : options[ '--runner' ]
+ , 'tag' : options[ '--tag' ]
+ , 'platform' : options[ '--platform']
+ , 'comment_file' : options[ '--comment' ]
+ , 'timestamp_file' : options[ '--timestamp' ]
+ , 'user' : options[ '--user' ]
+ , 'source' : options[ '--source' ]
+ , 'run_type' : options[ '--run-type' ]
+ , 'ftp_proxy' : options[ '--ftp-proxy' ]
+ , 'http_proxy' : options[ '--proxy' ]
+ , 'debug_level' : int(options[ '--debug-level' ])
+ , 'send_bjam_log' : options.has_key( '--send-bjam-log' )
+ , 'dart_server' : options[ '--dart-server' ]
+ , 'revision' : options[ '--revision' ]
+ , 'ftp' : options[ '--ftp' ]
+ }
+
+
+commands = {
+ 'collect-and-upload' : collect_and_upload_logs
+ , 'collect-logs' : collect_logs
+ , 'upload-logs' : upload_logs
+ }
+
+def usage():
+ print 'Usage: %s [command] [options]' % os.path.basename( sys.argv[0] )
+ print '''
+Commands:
+\t%s
+
+Options:
+\t--locate-root directory to to scan for "test_log.xml" files
+\t--runner runner ID (e.g. "Metacomm")
+\t--timestamp path to a file which modification time will be used
+\t as a timestamp of the run ("timestamp" by default)
+\t--comment an HTML comment file to be inserted in the reports
+\t ("comment.html" by default)
+\t--tag the tag for the results ("trunk" by default)
+\t--user SourceForge user name for a shell account (optional)
+\t--source where Boost sources came from ("SVN" or "tarball";
+\t "SVN" by default)
+\t--run-type "incremental" or "full" ("full" by default)
+\t--send-bjam-log in addition to regular XML results, send in full bjam
+\t log of the regression run
+\t--proxy HTTP proxy server address and port (e.g.
+\t 'http://www.someproxy.com:3128', optional)
+\t--ftp-proxy FTP proxy server (e.g. 'ftpproxy', optional)
+\t--debug-level debugging level; controls the amount of debugging
+\t output printed; 0 by default (no debug output)
+\t--dart-server The dart server to send results to.
+\t--ftp The ftp URL to upload results to.
+''' % '\n\t'.join( commands.keys() )
+
+
+def main():
+ if len(sys.argv) > 1 and sys.argv[1] in commands:
+ command = sys.argv[1]
+ args = sys.argv[ 2: ]
+ else:
+ command = 'collect-and-upload'
+ args = sys.argv[ 1: ]
+
+ commands[ command ]( **accept_args( args ) )
+
+
+if __name__ != '__main__': import utils
+else:
+ # in absense of relative import...
+ xsl_path = os.path.abspath( os.path.dirname( sys.argv[ 0 ] ) )
+ while os.path.basename( xsl_path ) != 'xsl_reports': xsl_path = os.path.dirname( xsl_path )
+ sys.path.append( xsl_path )
+
+ import utils
+ main()
diff --git a/tools/regression/src/compiler_status.cpp b/tools/regression/src/compiler_status.cpp
new file mode 100644
index 0000000000..c4444bbcc6
--- /dev/null
+++ b/tools/regression/src/compiler_status.cpp
@@ -0,0 +1,1113 @@
+// Generate Compiler Status HTML from jam regression test output -----------//
+
+// Copyright Beman Dawes 2002.
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+// See http://www.boost.org/tools/regression/ for documentation.
+
+/*******************************************************************************
+
+ Please contact the maintainer, bdawes <at> acm <dot> org, before making
+ any non-trivial changes.
+
+ This program was designed to work unchanged on all platforms and
+ configurations. All output which is platform or configuration dependent
+ is obtained from external sources such as the .xml file from
+ process_jam_log execution, the tools/build/xxx-tools.jam files, or the
+ output of the config_info tests.
+
+ Please avoid adding platform or configuration dependencies during
+ program maintenance.
+
+*******************************************************************************/
+
+#include <boost/config/warning_disable.hpp>
+
+#include "boost/config.hpp"
+#include "boost/filesystem/operations.hpp"
+#include "boost/filesystem/convenience.hpp"
+#include "boost/filesystem/fstream.hpp"
+#include "detail/tiny_xml.hpp"
+namespace fs = boost::filesystem;
+namespace xml = boost::tiny_xml;
+
+#include <cstdlib> // for abort, exit
+#include <cctype> // for toupper
+#include <string>
+#include <vector>
+#include <set>
+#include <map>
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <stdexcept>
+#include <cassert>
+
+using std::string;
+
+const string pass_msg( "Pass" );
+const string warn_msg( "<i>Warn</i>" );
+const string fail_msg( "<font color=\"#FF0000\"><i>Fail</i></font>" );
+const string note_msg( "<sup>*</sup>" );
+const string missing_residue_msg( "<i>Missing</i>" );
+
+const std::size_t max_compile_msg_size = 10000;
+
+namespace
+{
+ fs::path boost_root; // boost-root complete path
+ fs::path locate_root; // locate-root (AKA ALL_LOCATE_TARGET) complete path
+
+ bool compile_time;
+ bool run_time;
+ bool ignore_pass;
+ bool no_warn;
+ bool no_links;
+ bool boost_build_v2 = true;
+
+ fs::path jamfile_path;
+
+ fs::directory_iterator end_itr;
+
+ // It's immportant for reliability that we find the same compilers for each
+ // test, and that they match the column header. So save the names at the
+ // time column headings are generated.
+ std::vector<string> toolsets;
+
+ fs::ifstream jamfile;
+ fs::ofstream report;
+ fs::ofstream links_file;
+ string links_name;
+
+ fs::path notes_path;
+ string notes_html;
+
+ fs::path notes_map_path;
+ typedef std::multimap< string, string > notes_map; // key is test_name-toolset,
+ // value is note bookmark
+ notes_map notes;
+
+ string specific_compiler; // if running on one toolset only
+
+ const string empty_string;
+
+ std::vector<int> error_count;
+
+ // prefix for library and test hyperlink prefix
+ string svn_root ( "http://svn.boost.org/trac/boost/browser/trunk/" );
+ string url_prefix_dir_view( svn_root );
+ string url_prefix_checkout_view( svn_root );
+ string url_suffix_text_view( "" );
+
+// get revision number (as a string) if boost_root is svn working copy -----//
+
+ string revision( const fs::path & boost_root )
+ {
+ string rev;
+ fs::path entries( boost_root / ".svn" / "entries" );
+ fs::ifstream entries_file( entries );
+ if ( entries_file )
+ {
+ std::getline( entries_file, rev );
+ std::getline( entries_file, rev );
+ std::getline( entries_file, rev );
+ std::getline( entries_file, rev ); // revision number as a string
+ }
+ return rev;
+ }
+
+
+// build notes_bookmarks from notes HTML -----------------------------------//
+
+ void build_notes_bookmarks()
+ {
+ if ( notes_map_path.empty() ) return;
+ fs::ifstream notes_map_file( notes_map_path );
+ if ( !notes_map_file )
+ {
+ std::cerr << "Could not open --notes-map input file: " << notes_map_path.string() << std::endl;
+ std::exit( 1 );
+ }
+ string line;
+ while( std::getline( notes_map_file, line ) )
+ {
+ string::size_type pos = 0;
+ if ( (pos = line.find( ',', pos )) == string::npos ) continue;
+ string key(line.substr( 0, pos ) );
+ string bookmark( line.substr( pos+1 ) );
+
+// std::cout << "inserting \"" << key << "\",\"" << bookmark << "\"\n";
+ notes.insert( notes_map::value_type( key, bookmark ) );
+ }
+ }
+
+// load_notes_html ---------------------------------------------------------//
+
+ bool load_notes_html()
+ {
+ if ( notes_path.empty() ) return false;
+ fs::ifstream notes_file( notes_path );
+ if ( !notes_file )
+ {
+ std::cerr << "Could not open --notes input file: " << notes_path.string() << std::endl;
+ std::exit( 1 );
+ }
+ string line;
+ bool in_body( false );
+ while( std::getline( notes_file, line ) )
+ {
+ if ( in_body && line.find( "</body>" ) != string::npos ) in_body = false;
+ if ( in_body ) notes_html += line;
+ else if ( line.find( "<body>" ) ) in_body = true;
+ }
+ return true;
+ }
+
+// relative path between two paths -----------------------------------------//
+
+ void relative_path( const fs::path & from, const fs::path & to,
+ fs::path & target )
+ {
+ if ( from.string().size() <= to.string().size() ) return;
+ target /= "..";
+ relative_path( from.branch_path(), to, target );
+ return;
+ }
+
+// extract object library name from target directory string ----------------//
+
+ string extract_object_library_name( const string & s )
+ {
+ string t( s );
+ string::size_type pos = t.find( "/build/" );
+ if ( pos != string::npos ) pos += 7;
+ else if ( (pos = t.find( "/test/" )) != string::npos ) pos += 6;
+ else return "";
+ return t.substr( pos, t.find( "/", pos ) - pos );
+ }
+
+// find_file ---------------------------------------------------------------//
+// given a directory to recursively search
+
+ bool find_file( const fs::path & dir_path, const string & name,
+ fs::path & path_found, const string & ignore_dir_named="" )
+ {
+ if ( !fs::exists( dir_path ) ) return false;
+ for ( fs::directory_iterator itr( dir_path ); itr != end_itr; ++itr )
+ if ( fs::is_directory( *itr )
+ && itr->path().filename() != ignore_dir_named )
+ {
+ if ( find_file( *itr, name, path_found ) ) return true;
+ }
+ else if ( itr->path().filename() == name )
+ {
+ path_found = *itr;
+ return true;
+ }
+ return false;
+ }
+
+// platform_desc -----------------------------------------------------------//
+
+ string platform_desc()
+ {
+ string result = BOOST_PLATFORM;
+ result[0] = std::toupper( result[0] );
+ return result;
+ }
+
+// version_desc ------------------------------------------------------------//
+// from locate-root/status/bin/config_info.test/xxx/.../config_info.output
+
+ string version_desc( const string & compiler_name )
+ {
+ string result;
+ fs::path dot_output_path;
+ if ( find_file( locate_root / "bin/boost/status/config_info.test"
+ / compiler_name, "config_info.output", dot_output_path )
+ || find_file( locate_root / "status/bin/config_info.test"
+ / compiler_name, "config_info.output", dot_output_path ) )
+ {
+ fs::ifstream file( dot_output_path );
+ if ( file )
+ {
+ if( std::getline( file, result ) )
+ {
+ string::size_type pos = result.find( "version " );
+ if ( pos != string::npos )
+ {
+ result.erase( 0, pos+8 );
+ }
+ else result.clear();
+ }
+ }
+ }
+ return result;
+ }
+
+// compiler_desc -----------------------------------------------------------//
+// from boost-root/tools/build/xxx-tools.jam
+
+ string compiler_desc( const string & compiler_name )
+ {
+ string result;
+ fs::path tools_path( boost_root / "tools/build/v1" / (compiler_name
+ + "-tools.jam") );
+ if ( !fs::exists( tools_path ) )
+ tools_path = boost_root / "tools/build" / (compiler_name + "-tools.jam");
+ fs::ifstream file( tools_path );
+ if ( file )
+ {
+ while( std::getline( file, result ) )
+ {
+ if ( result.substr( 0, 3 ) == "#//" )
+ {
+ result.erase( 0, 3 );
+ return result;
+ }
+ }
+ result.clear();
+ }
+ return result;
+ }
+
+// target_directory --------------------------------------------------------//
+// this amounts to a request to find a unique leaf directory
+
+ fs::path target_directory( const fs::path & root )
+ {
+ if ( !fs::exists( root ) ) return fs::path("no-such-path");
+ fs::path child;
+ for ( fs::directory_iterator itr( root ); itr != end_itr; ++itr )
+ {
+ if ( fs::is_directory( *itr ) )
+ {
+ // SunCC creates an internal subdirectory everywhere it writes
+ // object files. This confuses the target_directory() algorithm.
+ // This patch ignores the SunCC internal directory. Jens Maurer
+ if ( itr->path().filename() == "SunWS_cache" ) continue;
+ // SGI does something similar for template instantiations. Jens Maurer
+ if( itr->path().filename() == "ii_files" ) continue;
+
+ if ( child.empty() ) child = *itr;
+ else
+ {
+ std::cout << "Warning: only first of two target possibilities will be reported for: \n "
+ << root.string() << ": " << child.filename()
+ << " and " << itr->path().filename() << "\n";
+ }
+ }
+ }
+ if ( child.empty() ) return root; // this dir has no children
+ return target_directory( child );
+ }
+
+// element_content ---------------------------------------------------------//
+
+ const string & element_content(
+ const xml::element & root, const string & name )
+ {
+ static string empty_string;
+ xml::element_list::const_iterator itr;
+ for ( itr = root.elements.begin();
+ itr != root.elements.end() && (*itr)->name != name;
+ ++itr ) {}
+ return itr != root.elements.end() ? (*itr)->content : empty_string;
+ }
+
+// find_element ------------------------------------------------------------//
+
+ const xml::element empty_element;
+
+ const xml::element & find_element(
+ const xml::element & root, const string & name )
+ {
+ xml::element_list::const_iterator itr;
+ for ( itr = root.elements.begin();
+ itr != root.elements.end() && (*itr)->name != name;
+ ++itr ) {}
+ return itr != root.elements.end() ? *((*itr).get()) : empty_element;
+ }
+
+// attribute_value ----------------------------------------------------------//
+
+const string & attribute_value( const xml::element & element,
+ const string & attribute_name )
+{
+ static const string empty_string;
+ xml::attribute_list::const_iterator atr;
+ for ( atr = element.attributes.begin();
+ atr != element.attributes.end() && atr->name != attribute_name;
+ ++atr ) {}
+ return atr == element.attributes.end() ? empty_string : atr->value;
+}
+
+// find_bin_path -----------------------------------------------------------//
+
+// Takes a relative path from boost root to a Jamfile.
+// Returns the directory where the build targets from
+// that Jamfile are located. If not found, emits a warning
+// and returns empty path.
+const fs::path find_bin_path(const string& relative)
+{
+ fs::path bin_path;
+ if (boost_build_v2)
+ {
+ if ( relative == "status" )
+ bin_path = locate_root / "bin.v2" / "libs";
+ else
+ {
+ bin_path = locate_root / "bin.v2" / relative;
+ if (!fs::exists(bin_path))
+ bin_path = locate_root / "bin" / relative;
+ }
+ if (!fs::exists(bin_path))
+ {
+ std::cerr << "warning: could not find build results for '"
+ << relative << "'.\n";
+ std::cerr << "warning: tried directory "
+ << bin_path.string() << "\n";
+ bin_path = "";
+ }
+ }
+ else
+ {
+ bin_path = locate_root / "bin/boost" / relative;
+ if (!fs::exists(bin_path))
+ {
+ bin_path = locate_root / "bin" / relative / "bin";
+ if (!fs::exists(bin_path))
+ {
+ bin_path = fs::path( locate_root / relative / "bin" );
+ if (!fs::exists(bin_path))
+ {
+ bin_path = fs::path( locate_root / "bin/boost/libs" /
+ relative.substr( relative.find( '/' )+1 ) );
+ }
+ }
+ }
+ if (!fs::exists(bin_path))
+ {
+ std::cerr << "warning: could not find build results for '"
+ << relative << "'.\n";
+ bin_path = "";
+ }
+ }
+ return bin_path;
+}
+
+
+// generate_report ---------------------------------------------------------//
+
+ // return 0 if nothing generated, 1 otherwise, except 2 if compiler msgs
+ int generate_report( const xml::element & db,
+ const string & source_library_name,
+ const string & test_type,
+ const string & test_name, // possibly object library name
+ const string & toolset,
+ bool pass,
+ bool always_show_run_output = false )
+ {
+ // compile msgs sometimes modified, so make a local copy
+ string compile( ((pass && no_warn)
+ ? empty_string : element_content( db, "compile" )) );
+ const string & link( pass ? empty_string : element_content( db, "link" ) );
+ const string & run( (pass && !always_show_run_output)
+ ? empty_string : element_content( db, "run" ) );
+ string lib( (pass ? empty_string : element_content( db, "lib" )) );
+
+ string::size_type pos;
+ if ( (pos = compile.find("30 DAY EVALUATION LICENSE")) != string::npos )
+ {
+ compile.erase(pos, 25);
+ while ( compile[0] == '\n' || compile[0] == '\r' ) compile.erase(0,1);
+ }
+
+ // some compilers output the filename even if there are no errors or
+ // warnings; detect this if one line of output and it contains no space.
+ pos = compile.find( '\n', 1 );
+ if ( pos != string::npos && compile.size()-pos <= 2
+ && compile.find( ' ' ) == string::npos ) compile.clear();
+
+ if ( lib.empty()
+ && (compile.empty() || test_type == "compile_fail")
+ && link.empty() && run.empty() ) return 0;
+
+ int result = 1; // some kind of msg for sure
+
+ // limit compile message length
+ if ( compile.size() > max_compile_msg_size )
+ {
+ compile.erase( max_compile_msg_size );
+ compile += "...\n (remainder deleted because of excessive size)\n";
+ }
+
+ links_file << "<h2><a name=\""
+ << source_library_name << "-" << test_name << "-" << toolset << "\">"
+ << source_library_name << " - " << test_name << " - " << toolset << "</a></h2>\n";
+
+ if ( !compile.empty() )
+ {
+ ++result;
+ links_file << "<h3>Compiler output:</h3><pre>"
+ << compile << "</pre>\n";
+ }
+ if ( !link.empty() )
+ links_file << "<h3>Linker output:</h3><pre>" << link << "</pre>\n";
+ if ( !run.empty() )
+ links_file << "<h3>Run output:</h3><pre>" << run << "</pre>\n";
+
+ // for an object library failure, generate a reference to the object
+ // library failure message, and (once only) generate the object
+ // library failure message itself
+ static std::set< string > failed_lib_target_dirs; // only generate once
+ if ( !lib.empty() )
+ {
+ if ( lib[0] == '\n' ) lib.erase( 0, 1 );
+ string object_library_name( extract_object_library_name( lib ) );
+
+ // changing the target directory naming scheme breaks
+ // extract_object_library_name()
+ assert( !object_library_name.empty() );
+ if ( object_library_name.empty() )
+ std::cerr << "Failed to extract object library name from " << lib << "\n";
+
+ links_file << "<h3>Library build failure: </h3>\n"
+ "See <a href=\"#"
+ << source_library_name << "-"
+ << object_library_name << "-" << toolset << "\">"
+ << source_library_name << " - "
+ << object_library_name << " - " << toolset << "</a>";
+
+ if ( failed_lib_target_dirs.find( lib ) == failed_lib_target_dirs.end() )
+ {
+ failed_lib_target_dirs.insert( lib );
+ fs::path pth( locate_root / lib / "test_log.xml" );
+ fs::ifstream file( pth );
+ if ( file )
+ {
+ xml::element_ptr db = xml::parse( file, pth.string() );
+ generate_report( *db, source_library_name, test_type, object_library_name, toolset, false );
+ }
+ else
+ {
+ links_file << "<h2><a name=\""
+ << object_library_name << "-" << toolset << "\">"
+ << object_library_name << " - " << toolset << "</a></h2>\n"
+ "test_log.xml not found\n";
+ }
+ }
+ }
+ return result;
+ }
+
+ // add_notes --------------------------------------------------------------//
+
+ void add_notes( const string & key, bool fail, string & sep, string & target )
+ {
+ notes_map::const_iterator itr = notes.lower_bound( key );
+ if ( itr != notes.end() && itr->first == key )
+ {
+ for ( ; itr != notes.end() && itr->first == key; ++itr )
+ {
+ string note_desc( itr->second[0] == '-'
+ ? itr->second.substr( 1 ) : itr->second );
+ if ( fail || itr->second[0] == '-' )
+ {
+ target += sep;
+ sep = ",";
+ target += "<a href=\"";
+ target += "#";
+ target += note_desc;
+ target += "\">";
+ target += note_desc;
+ target += "</a>";
+ }
+ }
+ }
+ }
+
+ // get_notes -------------------------------------------------------------//
+
+ string get_notes( const string & toolset,
+ const string & library, const string & test, bool fail )
+ {
+ string sep;
+ string target( "<sup>" );
+ add_notes( toolset + "/" + library + "/" + test, fail, sep, target );
+ add_notes( "*/" + library + "/" + test, fail, sep, target );
+ add_notes( toolset + "/" + library + "/*", fail, sep, target );
+ add_notes( "*/" + library + "/*", fail, sep, target );
+ if ( target == "<sup>" ) target.clear();
+ else target += "</sup>";
+ return target;
+ }
+
+ // do_cell ---------------------------------------------------------------//
+
+ bool do_cell(
+ int compiler,
+ const string & lib_name,
+ const fs::path & test_dir,
+ const string & test_type,
+ const string & test_name,
+ const string & toolset,
+ string & target,
+ bool always_show_run_output )
+ // return true if any results except simple pass_msg
+ {
+ fs::path target_dir( target_directory( test_dir / toolset ) );
+ bool pass = false;
+
+ if ( !fs::exists( target_dir / "test_log.xml" ) )
+ {
+ std::cerr << "Missing test_log.xml in target:\n "
+ << target_dir.string() << "\n";
+ target += "<td>" + missing_residue_msg + "</td>";
+ return true;
+ }
+
+ int anything_generated = 0;
+ bool note = false;
+
+ fs::path pth( target_dir / "test_log.xml" );
+ fs::ifstream file( pth );
+ if ( !file )
+ {
+ std::cerr << "Can't open test_log.xml in target:\n "
+ << target_dir.string() << "\n";
+ target += "<td>" + missing_residue_msg + "</td>";
+ return false;
+ }
+
+ xml::element_ptr dbp = xml::parse( file, pth.string() );
+ const xml::element & db( *dbp );
+
+ std::string test_type_base( test_type );
+ if ( test_type_base == "run_pyd" ) test_type_base = "run";
+ else if ( test_type_base.size() > 5 )
+ {
+ const string::size_type trailer = test_type_base.size() - 5;
+ if ( test_type_base.substr( trailer ) == "_fail" )
+ {
+ test_type_base.erase( trailer );
+ }
+ }
+ const xml::element & test_type_element( find_element( db, test_type_base ) );
+
+ pass = !test_type_element.name.empty()
+ && attribute_value( test_type_element, "result" ) != "fail";
+
+ if ( !no_links )
+ {
+ note = attribute_value( test_type_element, "result" ) == "note";
+
+ // generate bookmarked report of results, and link to it
+ anything_generated
+ = generate_report( db, lib_name, test_type, test_name, toolset, pass,
+ always_show_run_output || note );
+ }
+
+ target += "<td>";
+
+ // generate the status table cell pass/warn/fail HTML
+ if ( anything_generated != 0 )
+ {
+ target += "<a href=\"";
+ target += links_name;
+ target += "#";
+ target += lib_name;
+ target += "-";
+ target += test_name;
+ target += "-";
+ target += toolset;
+ target += "\">";
+ target += pass
+ ? (anything_generated < 2 ? pass_msg : warn_msg)
+ : fail_msg;
+ target += "</a>";
+ if ( pass && note ) target += note_msg;
+ }
+ else target += pass ? pass_msg : fail_msg;
+
+ // if notes, generate the superscript HTML
+ if ( !notes.empty() )
+ target += get_notes( toolset, lib_name, test_name, !pass );
+
+ // generate compile-time if requested
+ if ( compile_time )
+ {
+ const xml::element & compile_element( find_element( db, "compile" ) );
+
+ if ( !compile_element.name.empty() )
+ {
+ string times = attribute_value( compile_element, "timings" );
+ if ( !times.empty() )
+ {
+ target += "<br>";
+ target += times.substr( 0, times.find( " " ) );
+ }
+ }
+ }
+
+ // generate run-time if requested
+ if ( run_time )
+ {
+ const xml::element & run_element( find_element( db, "run" ) );
+
+ if ( !run_element.name.empty() )
+ {
+ string times = attribute_value( run_element, "timings" );
+ if ( !times.empty() )
+ {
+ target += "<br>";
+ target += times.substr( 0, times.find( " " ) );
+ }
+ }
+ }
+
+ if ( !pass ) ++error_count[compiler];
+
+ target += "</td>";
+ return (anything_generated != 0) || !pass;
+ }
+
+// do_row ------------------------------------------------------------------//
+
+ void do_row(
+ const fs::path & test_dir, // locate_root / "status/bin/any_test.test"
+ const string & test_name, // "any_test"
+ string & target )
+ {
+ // get library name, test-type, test-program path, etc., from the .xml file
+ string lib_name;
+ string test_path( test_name ); // test_name is default if missing .test
+ string test_type( "unknown" );
+ bool always_show_run_output( false );
+ fs::path xml_file_path;
+ if ( find_file( test_dir, "test_log.xml", xml_file_path ) )
+ {
+ fs::ifstream file( xml_file_path );
+ if ( file )
+ {
+ xml::element_ptr dbp = xml::parse( file, xml_file_path.string() );
+ const xml::element & db( *dbp );
+ test_path = attribute_value( db, "test-program" );
+ lib_name = attribute_value( db, "library" );
+ test_type = attribute_value( db, "test-type" );
+ always_show_run_output
+ = attribute_value( db, "show-run-output" ) == "true";
+ }
+ }
+
+ // generate the library name, test name, and test type table data
+ string::size_type row_start_pos = target.size();
+ target += "<tr><td><a href=\"" + url_prefix_dir_view + "/libs/" + lib_name
+ + "\">" + lib_name + "</a></td>";
+ target += "<td><a href=\"" + url_prefix_checkout_view + "/" + test_path
+ + url_suffix_text_view + "\">" + test_name + "</a>";
+
+ if ( compile_time ) target += "<br> Compile time:";
+ if ( run_time ) target += "<br> Run time:";
+
+ target += "</td>";
+ target += "<td>" + test_type + "</td>";
+
+ bool no_warn_save = no_warn;
+ //if ( test_type.find( "fail" ) != string::npos ) no_warn = true;
+
+ // for each compiler, generate <td>...</td> html
+ bool anything_to_report = false;
+ int compiler = 0;
+ for ( std::vector<string>::const_iterator itr=toolsets.begin();
+ itr != toolsets.end(); ++itr, ++compiler )
+ {
+ anything_to_report |= do_cell( compiler, lib_name, test_dir, test_type, test_name, *itr, target,
+ always_show_run_output );
+ }
+
+ target += "</tr>";
+ if ( ignore_pass && !anything_to_report ) target.erase( row_start_pos );
+ no_warn = no_warn_save;
+ }
+
+// do_rows_for_sub_tree ----------------------------------------------------//
+
+ void do_rows_for_sub_tree(
+ const fs::path & bin_dir, std::vector<string> & results )
+ {
+ for ( fs::directory_iterator itr( bin_dir ); itr != end_itr; ++itr )
+ {
+ if ( fs::is_directory( *itr )
+ && itr->path().string().find( ".test" ) == (itr->path().string().size()-5) )
+ {
+ results.push_back( std::string() );
+ do_row( *itr,
+ itr->path().filename().string().substr( 0,
+ itr->path().filename().string().size()-5 ),
+ results[results.size()-1] );
+ }
+ }
+ }
+
+// find_compilers ------------------------------------------------------------//
+
+ void find_compilers(const fs::path & bin_dir)
+ {
+ fs::directory_iterator compiler_itr( bin_dir );
+ if ( specific_compiler.empty() )
+ std::clog << "Using " << bin_dir.string() << " to determine compilers\n";
+ for (; compiler_itr != end_itr; ++compiler_itr )
+ {
+ if ( fs::is_directory( *compiler_itr ) // check just to be sure
+ && compiler_itr->path().filename() != "test" ) // avoid strange directory (Jamfile bug?)
+ {
+ if ( specific_compiler.size() != 0
+ && specific_compiler != compiler_itr->path().filename() ) continue;
+ toolsets.push_back( compiler_itr->path().filename().string() );
+ string desc( compiler_desc( compiler_itr->path().filename().string() ) );
+ string vers( version_desc( compiler_itr->path().filename().string() ) );
+ report << "<td>"
+ << (desc.size() ? desc : compiler_itr->path().filename().string())
+ << (vers.size() ? (string( "<br>" ) + vers ) : string( "" ))
+ << "</td>\n";
+ error_count.push_back( 0 );
+ }
+ }
+ }
+
+// do_table_body -----------------------------------------------------------//
+
+ void do_table_body( const fs::path & bin_dir )
+ {
+ // rows are held in a vector so they can be sorted, if desired.
+ std::vector<string> results;
+
+ // do primary bin directory
+ do_rows_for_sub_tree( bin_dir, results );
+
+ // do subinclude bin directories
+ jamfile.clear();
+ jamfile.seekg(0);
+ string line;
+ bool run_tests = false;
+
+ while( std::getline( jamfile, line ) )
+ {
+ bool v2(false);
+ string::size_type sub_pos( line.find( "subinclude" ) );
+ if ( sub_pos == string::npos ) {
+ sub_pos = line.find( "build-project" );
+ v2 = true;
+ }
+ if ( sub_pos != string::npos
+ && line.find( '#' ) > sub_pos )
+ {
+ if (v2)
+ sub_pos = line.find_first_not_of( " \t./", sub_pos+13 );
+ else
+ sub_pos = line.find_first_not_of( " \t./", sub_pos+10 );
+
+ if ( sub_pos == string::npos ) continue;
+ string subinclude_bin_dir(
+ line.substr( sub_pos, line.find_first_of( " \t", sub_pos )-sub_pos ) );
+
+ fs::path bin_path = find_bin_path(subinclude_bin_dir);
+ if (!bin_path.empty())
+ do_rows_for_sub_tree( bin_path, results );
+ }
+ if ( ! run_tests )
+ {
+ string::size_type run_pos = line.find("run-tests");
+ if ( run_pos != string::npos && line.find_first_not_of(" \t") == run_pos )
+ run_tests = true;
+ }
+ else
+ {
+ if ( line.find(";") != string::npos )
+ run_tests = false;
+ else
+ {
+ string::size_type pos = line.find_first_not_of( " \t" );
+ if ( pos != string::npos && line[pos] != '#' )
+ {
+ string::size_type end_pos = line.find_first_of(" \t#", pos);
+ string::iterator end = end_pos != string::npos ? line.begin() + end_pos : line.end();
+ string run_tests_bin_dir(line.begin() + pos, end);
+ fs::path bin_path = find_bin_path("libs/" + run_tests_bin_dir);
+ if (!bin_path.empty())
+ do_rows_for_sub_tree( bin_path, results );
+ }
+ }
+ }
+ }
+
+
+ std::sort( results.begin(), results.end() );
+
+ for ( std::vector<string>::iterator v(results.begin());
+ v != results.end(); ++v )
+ { report << *v << "\n"; }
+ }
+
+// do_table ----------------------------------------------------------------//
+
+ void do_table()
+ {
+ // Find test result locations, trying:
+ // - Boost.Build V1 location with ALL_LOCATE_TARGET
+ // - Boost.Build V2 location with top-lelve "build-dir"
+ // - Boost.Build V1 location without ALL_LOCATE_TARGET
+ string relative( fs::initial_path().string() );
+
+#ifdef BOOST_WINDOWS_API
+ if (relative.size() > 1 && relative[1] == ':') relative[0] = std::tolower(relative[0]);
+#endif
+
+ if ( relative.find(boost_root.string()) != string::npos )
+ relative.erase( 0, boost_root.string().size()+1 );
+ else if ( relative.find(locate_root.string()) != string::npos )
+ relative.erase( 0, locate_root.string().size()+1 );
+ fs::path bin_path = find_bin_path(relative);
+
+ report << "<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\">\n";
+
+ // generate the column headings
+
+ report << "<tr><td>Library</td><td>Test Name</td>\n"
+ "<td><a href=\"compiler_status.html#test-type\">Test Type</a></td>\n";
+
+ if ( relative == "status" )
+ {
+ fs::recursive_directory_iterator ritr( bin_path );
+ fs::recursive_directory_iterator end_ritr;
+ while ( ritr != end_ritr
+ && ((ritr->path().string().find( ".test" ) != (ritr->path().string().size()-5))
+ || !fs::is_directory( *ritr )))
+ ++ritr; // bypass chaff
+ if ( ritr != end_ritr )
+ {
+ find_compilers( *ritr );
+ }
+ }
+ else
+ {
+ fs::directory_iterator itr( bin_path );
+ while ( itr != end_itr
+ && ((itr->path().string().find( ".test" ) != (itr->path().string().size()-5))
+ || !fs::is_directory( *itr )))
+ ++itr; // bypass chaff
+ if ( itr != end_itr )
+ {
+ find_compilers( *itr );
+ }
+ }
+
+ report << "</tr>\n";
+
+ // now the rest of the table body
+
+ do_table_body( bin_path );
+
+ // error total row
+
+ report << "<tr> <td> &nbsp;</td><td>Number of Failures</td><td> &nbsp;</td>\n";
+
+ // for each compiler, generate <td>...</td> html
+ int compiler = 0;
+ for ( std::vector<string>::const_iterator itr=toolsets.begin();
+ itr != toolsets.end(); ++itr, ++compiler )
+ {
+ report << "<td align=\"center\">" << error_count[compiler] << "</td>\n";
+ }
+
+ report << "</tr>\n</table>\n";
+ }
+
+} // unnamed namespace
+
+// main --------------------------------------------------------------------//
+
+#define BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE
+#include <boost/test/included/prg_exec_monitor.hpp>
+
+int cpp_main( int argc, char * argv[] ) // note name!
+{
+ fs::path comment_path;
+ while ( argc > 1 && *argv[1] == '-' )
+ {
+ if ( argc > 2 && std::strcmp( argv[1], "--compiler" ) == 0 )
+ { specific_compiler = argv[2]; --argc; ++argv; }
+ else if ( argc > 2 && std::strcmp( argv[1], "--locate-root" ) == 0 )
+ { locate_root = fs::path( argv[2] ); --argc; ++argv; }
+ else if ( argc > 2 && std::strcmp( argv[1], "--comment" ) == 0 )
+ { comment_path = fs::path( argv[2] ); --argc; ++argv; }
+ else if ( argc > 2 && std::strcmp( argv[1], "--notes" ) == 0 )
+ { notes_path = fs::path( argv[2] ); --argc; ++argv; }
+ else if ( argc > 2 && std::strcmp( argv[1], "--notes-map" ) == 0 )
+ { notes_map_path = fs::path( argv[2] ); --argc; ++argv; }
+ else if ( std::strcmp( argv[1], "--ignore-pass" ) == 0 ) ignore_pass = true;
+ else if ( std::strcmp( argv[1], "--no-warn" ) == 0 ) no_warn = true;
+ else if ( std::strcmp( argv[1], "--v1" ) == 0 ) boost_build_v2 = false;
+ else if ( std::strcmp( argv[1], "--v2" ) == 0 ) boost_build_v2 = true;
+ else if ( argc > 2 && std::strcmp( argv[1], "--jamfile" ) == 0)
+ { jamfile_path = fs::path( argv[2] ); --argc; ++argv; }
+ else if ( std::strcmp( argv[1], "--compile-time" ) == 0 ) compile_time = true;
+ else if ( std::strcmp( argv[1], "--run-time" ) == 0 ) run_time = true;
+ else { std::cerr << "Unknown option: " << argv[1] << "\n"; argc = 1; }
+ --argc;
+ ++argv;
+ }
+
+ if ( argc != 3 && argc != 4 )
+ {
+ std::cerr <<
+ "Usage: compiler_status [options...] boost-root status-file [links-file]\n"
+ " boost-root is the path to the boost tree root directory.\n"
+ " status-file and links-file are paths to the output files.\n"
+ "Must be run from directory containing Jamfile\n"
+ " options: --compiler name Run for named compiler only\n"
+ " --locate-root path Path to ALL_LOCATE_TARGET for bjam;\n"
+ " default boost-root.\n"
+ " --comment path Path to file containing HTML\n"
+ " to be copied into status-file.\n"
+ " --notes path Path to file containing HTML\n"
+ " to be copied into status-file.\n"
+ " --notes-map path Path to file of toolset/test,n lines, where\n"
+ " n is number of note bookmark in --notes file.\n"
+ " --jamfile path Path to Jamfile. By default \"Jamfile\".\n"
+ " --v1 Assume Boost.Build version 1.\n"
+ " --v2 Assume Boost.Build version 2. (default)\n"
+ " --ignore-pass Ignore passing tests.\n"
+ " --no-warn Do not report warnings.\n"
+ " --compile-time Show compile time.\n"
+ " --run-time Show run time.\n"
+ "Example: compiler_status --compiler gcc /boost-root cs.html cs-links.html\n"
+ "Note: Only the leaf of the links-file path and --notes file string are\n"
+ "used in status-file HTML links. Thus for browsing, status-file,\n"
+ "links-file, and --notes file must all be in the same directory.\n"
+ ;
+ return 1;
+ }
+
+ boost_root = fs::path( argv[1] );
+ if ( locate_root.empty() ) locate_root = boost_root;
+
+ if (jamfile_path.empty())
+ if (boost_build_v2)
+ jamfile_path = "Jamfile.v2";
+ else
+ jamfile_path = "Jamfile";
+ jamfile_path = fs::absolute( jamfile_path, fs::initial_path() );
+ jamfile.open( jamfile_path );
+ if ( !jamfile )
+ {
+ std::cerr << "Could not open Jamfile: " << jamfile_path.string() << std::endl;
+ return 1;
+ }
+
+ report.open( fs::path( argv[2] ) );
+ if ( !report )
+ {
+ std::cerr << "Could not open report output file: " << argv[2] << std::endl;
+ return 1;
+ }
+
+ if ( argc == 4 )
+ {
+ fs::path links_path( argv[3] );
+ links_name = links_path.filename().string();
+ links_file.open( links_path );
+ if ( !links_file )
+ {
+ std::cerr << "Could not open links output file: " << argv[3] << std::endl;
+ return 1;
+ }
+ }
+ else no_links = true;
+
+ build_notes_bookmarks();
+
+ char run_date[128];
+ std::time_t tod;
+ std::time( &tod );
+ std::strftime( run_date, sizeof(run_date),
+ "%X UTC, %A %d %B %Y", std::gmtime( &tod ) );
+
+ std::string rev = revision( boost_root );
+
+ report << "<html>\n"
+ "<head>\n"
+ "<title>Boost Test Results</title>\n"
+ "</head>\n"
+ "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
+ "<table border=\"0\">\n"
+ "<tr>\n"
+ "<td><img border=\"0\" src=\"http://www.boost.org/boost.png\" width=\"277\" "
+ "height=\"86\"></td>\n"
+ "<td>\n"
+ "<h1>Boost Test Results - " + platform_desc() + "</h1>\n"
+ "<b>Run</b> "
+ << run_date;
+ if ( !rev.empty() ) report << ", <b>Revision</b> " << rev;
+ report << "\n";
+
+
+ if ( compile_time )
+ report << "<p>Times reported are elapsed wall clock time in seconds.</p>\n";
+
+
+ if ( !comment_path.empty() )
+ {
+ fs::ifstream comment_file( comment_path );
+ if ( !comment_file )
+ {
+ std::cerr << "Could not open \"--comment\" input file: " << comment_path.string() << std::endl;
+ return 1;
+ }
+ char c;
+ while ( comment_file.get( c ) ) { report.put( c ); }
+ }
+
+ report << "</td>\n</table>\n<br>\n";
+
+ if ( !no_links )
+ {
+ links_file
+ << "<html>\n"
+ "<head>\n"
+ "<title>Boost Test Details</title>\n"
+ "</head>\n"
+ "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
+ "<table border=\"0\">\n"
+ "<tr>\n"
+ "<td><img border=\"0\" src=\"http://www.boost.org/boost.png\" width=\"277\" "
+ "height=\"86\"></td>\n"
+ "<td>\n"
+ "<h1>Boost Test Details - " + platform_desc() + "</h1>\n"
+ "<b>Run Date:</b> "
+ << run_date;
+ if ( !rev.empty() ) links_file << ", <b>Revision</b> " << rev;
+ links_file << "\n</td>\n</table>\n<br>\n";
+ }
+
+ do_table();
+
+ if ( load_notes_html() ) report << notes_html << "\n";
+
+ report << "</body>\n"
+ "</html>\n"
+ ;
+
+ if ( !no_links )
+ {
+ links_file
+ << "</body>\n"
+ "</html>\n"
+ ;
+ }
+ return 0;
+}
diff --git a/tools/regression/src/detail/tiny_xml.cpp b/tools/regression/src/detail/tiny_xml.cpp
new file mode 100644
index 0000000000..682c04ff7b
--- /dev/null
+++ b/tools/regression/src/detail/tiny_xml.cpp
@@ -0,0 +1,167 @@
+// tiny XML sub-set tools implementation -----------------------------------//
+
+// (C) Copyright Beman Dawes 2002. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "tiny_xml.hpp"
+#include <cassert>
+#include <cstring>
+
+namespace
+{
+
+ void eat_whitespace( char & c, std::istream & in )
+ {
+ while ( c == ' ' || c == '\r' || c == '\n' || c == '\t' )
+ in.get( c );
+ }
+
+ std::string get_name( char & c, std::istream & in )
+ {
+ std::string result;
+ eat_whitespace( c, in );
+ while ( std::strchr(
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.", c )
+ != 0 )
+ {
+ result += c;
+ if(!in.get( c ))
+ throw std::string("xml: unexpected eof");
+ }
+ return result;
+ }
+
+ void eat_delim( char & c, std::istream & in,
+ char delim, const std::string & msg )
+ {
+ eat_whitespace( c, in );
+ if ( c != delim )
+ throw std::string("xml syntax error, expected ") + delim
+ + " (" + msg + ")";
+ in.get( c );
+ }
+
+ std::string get_value( char & c, std::istream & in )
+ {
+ std::string result;
+ while ( c != '\"' )
+ {
+ result += c;
+ in.get( c );
+ }
+ in.get( c );
+ return result;
+ }
+
+}
+
+namespace boost
+{
+ namespace tiny_xml
+ {
+
+ // parse -----------------------------------------------------------------//
+
+ element_ptr parse( std::istream & in, const std::string & msg )
+ {
+ char c = 0; // current character
+ element_ptr e( new element );
+
+ if(!in.get( c ))
+ throw std::string("xml: unexpected eof");
+ if ( c == '<' )
+ if(!in.get( c ))
+ throw std::string("xml: unexpected eof");
+
+ e->name = get_name( c, in );
+ eat_whitespace( c, in );
+
+ // attributes
+ while ( c != '>' )
+ {
+ attribute a;
+ a.name = get_name( c, in );
+
+ eat_delim( c, in, '=', msg );
+ eat_delim( c, in, '\"', msg );
+
+ a.value = get_value( c, in );
+
+ e->attributes.push_back( a );
+ eat_whitespace( c, in );
+ }
+ if(!in.get( c )) // next after '>'
+ throw std::string("xml: unexpected eof");
+
+ eat_whitespace( c, in );
+
+ // sub-elements
+ while ( c == '<' )
+ {
+ if ( in.peek() == '/' ) break;
+ e->elements.push_back( parse( in, msg ) );
+ in.get( c ); // next after '>'
+ eat_whitespace( c, in );
+ }
+
+ // content
+ if ( c != '<' )
+ {
+ e->content += '\n';
+ while ( c != '<' )
+ {
+ e->content += c;
+ if(!in.get( c ))
+ throw std::string("xml: unexpected eof");
+ }
+ }
+
+ assert( c == '<' );
+ if(!in.get( c )) // next after '<'
+ throw std::string("xml: unexpected eof");
+
+ eat_delim( c, in, '/', msg );
+ std::string end_name( get_name( c, in ) );
+ if ( e->name != end_name )
+ throw std::string("xml syntax error: beginning name ")
+ + e->name + " did not match end name " + end_name
+ + " (" + msg + ")";
+
+ eat_delim( c, in, '>', msg );
+ return e;
+ }
+
+ // write ---------------------------------------------------------------//
+
+ void write( const element & e, std::ostream & out )
+ {
+ out << "<" << e.name;
+ if ( !e.attributes.empty() )
+ {
+ for( attribute_list::const_iterator itr = e.attributes.begin();
+ itr != e.attributes.end(); ++itr )
+ {
+ out << " " << itr->name << "=\"" << itr->value << "\"";
+ }
+ }
+ out << ">";
+ if ( !e.elements.empty() )
+ {
+ out << "\n";
+ for( element_list::const_iterator itr = e.elements.begin();
+ itr != e.elements.end(); ++itr )
+ {
+ write( **itr, out );
+ }
+ }
+ if ( !e.content.empty() )
+ {
+ out << e.content;
+ }
+ out << "</" << e.name << ">\n";
+ }
+
+ } // namespace tiny_xml
+} // namespace boost
+
diff --git a/tools/regression/src/detail/tiny_xml.hpp b/tools/regression/src/detail/tiny_xml.hpp
new file mode 100644
index 0000000000..f9d91d2652
--- /dev/null
+++ b/tools/regression/src/detail/tiny_xml.hpp
@@ -0,0 +1,70 @@
+// tiny XML sub-set tools --------------------------------------------------//
+
+// (C) Copyright Beman Dawes 2002. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Provides self-contained tools for this XML sub-set:
+//
+// element ::= { "<" name { name "=" "\"" value "\"" } ">"
+// {element} [contents] "</" name ">" }
+//
+// The point of "self-contained" is to minimize tool-chain dependencies.
+
+#ifndef BOOST_TINY_XML_H
+#define BOOST_TINY_XML_H
+
+#include "boost/smart_ptr.hpp" // for shared_ptr
+#include "boost/utility.hpp" // for noncopyable
+#include <list>
+#include <iostream>
+#include <string>
+
+namespace boost
+{
+ namespace tiny_xml
+ {
+ class element;
+ struct attribute
+ {
+ std::string name;
+ std::string value;
+
+ attribute(){}
+ attribute( const std::string & name, const std::string & value )
+ : name(name), value(value) {}
+ };
+ typedef boost::shared_ptr< element > element_ptr;
+ typedef std::list< element_ptr > element_list;
+ typedef std::list< attribute > attribute_list;
+
+ class element
+ : private boost::noncopyable // because deep copy sematics would be required
+ {
+ public:
+ std::string name;
+ attribute_list attributes;
+ element_list elements;
+ std::string content;
+
+ element() {}
+ explicit element( const std::string & name ) : name(name) {}
+ };
+
+ element_ptr parse( std::istream & in, const std::string & msg );
+ // Precondition: stream positioned at either the initial "<"
+ // or the first character after the initial "<".
+ // Postcondition: stream positioned at the first character after final
+ // ">" (or eof).
+ // Returns: an element_ptr to an element representing the parsed stream.
+ // Throws: std::string on syntax error. msg appended to what() string.
+
+ void write( const element & e, std::ostream & out );
+
+ }
+}
+
+#endif // BOOST_TINY_XML_H
+
+
+
diff --git a/tools/regression/src/detail/tiny_xml_test.cpp b/tools/regression/src/detail/tiny_xml_test.cpp
new file mode 100644
index 0000000000..b5c0542ba4
--- /dev/null
+++ b/tools/regression/src/detail/tiny_xml_test.cpp
@@ -0,0 +1,17 @@
+// tiny XML test program ---------------------------------------------------//
+
+// Copyright Beman Dawes 2002. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "tiny_xml.hpp"
+
+#include <iostream>
+
+int main()
+{
+ boost::tiny_xml::element_ptr tree( boost::tiny_xml::parse( std::cin ) );
+ boost::tiny_xml::write( *tree, std::cout );
+ return 0;
+}
+
diff --git a/tools/regression/src/detail/tiny_xml_test.txt b/tools/regression/src/detail/tiny_xml_test.txt
new file mode 100644
index 0000000000..b248cbf062
--- /dev/null
+++ b/tools/regression/src/detail/tiny_xml_test.txt
@@ -0,0 +1,17 @@
+<root>
+<frontmatter>
+// (C) Copyright Beman Dawes 2002. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+</frontmatter>
+<element-1 at-1="abcd" at-2 = "defg" >
+<element-1a>
+It's Howdy Doody time!
+</element-1a>
+<element-1b>It's not Howdy Doody time!</element-1b>
+</element-1>
+<element-2>
+It's
+Eastern Standard time!
+</element-2>
+</root>
diff --git a/tools/regression/src/library_status.cpp b/tools/regression/src/library_status.cpp
new file mode 100644
index 0000000000..d3ad418048
--- /dev/null
+++ b/tools/regression/src/library_status.cpp
@@ -0,0 +1,991 @@
+// Generate Library Status HTML from jam regression test output -----------//
+
+// Copyright Bryce Lelbach 2011
+// Copyright Beman Dawes 2002-2011.
+
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// See http://www.boost.org/tools/regression/ for documentation.
+
+//Note: This version of the original program builds a large table
+//which includes all build variations such as build/release, static/dynamic, etc.
+
+
+/*******************************************************************************
+
+This program was designed to work unchanged on all platforms and
+configurations. All output which is platform or configuration dependent
+is obtained from external sources such as the .xml file from
+process_jam_log execution, the tools/build/xxx-tools.jam files, or the
+output of the config_info tests.
+
+Please avoid adding platform or configuration dependencies during
+program maintenance.
+
+*******************************************************************************/
+
+#include "boost/filesystem/operations.hpp"
+#include "boost/filesystem/fstream.hpp"
+
+namespace fs = boost::filesystem;
+
+#include "detail/tiny_xml.hpp"
+namespace xml = boost::tiny_xml;
+
+#include "boost/iterator/transform_iterator.hpp"
+
+#include <cstdlib> // for abort, exit
+#include <string>
+#include <vector>
+#include <set>
+#include <utility> // for make_pair on STLPort
+#include <map>
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <stdexcept>
+#include <cassert>
+#include <utility>
+
+using std::string;
+
+const string pass_msg( "Pass" );
+const string warn_msg( "<i>Warn</i>" );
+const string fail_msg( "<font color=\"#FF0000\"><i>Fail</i></font>" );
+const string note_msg( "<sup>*</sup>" );
+const string missing_residue_msg( "<i>Missing</i>" );
+
+const std::size_t max_compile_msg_size = 10000;
+
+namespace
+{
+ fs::path boost_root; // boost-root complete path
+ fs::path locate_root; // locate-root (AKA ALL_LOCATE_TARGET) complete path
+ bool ignore_pass = false;
+ bool no_warn = false;
+ bool no_links = false;
+
+ fs::directory_iterator end_itr;
+
+ // transform pathname to something html can accept
+ struct char_xlate {
+ typedef char result_type;
+ result_type operator()(char c) const{
+ if(c == '/')
+ return '-';
+ return c;
+ }
+ };
+ typedef boost::transform_iterator<char_xlate, std::string::const_iterator> html_from_path;
+
+ template<class I1, class I2>
+ std::ostream & operator<<(
+ std::ostream &os,
+ std::pair<I1, I2> p
+ ){
+ while(p.first != p.second)
+ os << *p.first++;
+ return os;
+ }
+
+ struct col_node {
+ int rows, cols;
+ bool has_leaf;
+ typedef std::map<std::string, col_node> subcolumns_t;
+ subcolumns_t m_subcolumns;
+ bool operator<(const col_node &cn) const;
+ col_node() :
+ has_leaf(false)
+ {}
+ std::pair<int, int> get_spans();
+ };
+
+ std::pair<int, int> col_node::get_spans(){
+ rows = 1;
+ cols = 0;
+ if(has_leaf){
+ cols = 1;
+ }
+ if(! m_subcolumns.empty()){
+ subcolumns_t::iterator itr;
+ for(itr = m_subcolumns.begin(); itr != m_subcolumns.end(); ++itr){
+ std::pair<int, int> spans;
+ spans = itr->second.get_spans();
+ rows = (std::max)(rows, spans.first);
+ cols += spans.second;
+ }
+ ++rows;
+ }
+ return std::make_pair(rows, cols);
+ }
+
+ void build_node_tree(const fs::path & dir_root, col_node & node){
+ fs::path xml_file_path( dir_root / "test_log.xml" );
+ if (fs::exists( xml_file_path ) )
+ {
+ node.has_leaf = true;
+ }
+ fs::directory_iterator itr(dir_root);
+ while(itr != end_itr){
+ if(fs::is_directory(*itr)){
+ std::pair<col_node::subcolumns_t::iterator, bool> result
+ = node.m_subcolumns.insert(
+ std::make_pair(itr->path().native(), col_node())
+ );
+ build_node_tree(*itr, result.first->second);
+ }
+ ++itr;
+ }
+ }
+
+ fs::ofstream report;
+ fs::ofstream links_file;
+ string links_name;
+
+ fs::path notes_path;
+ string notes_html;
+
+ fs::path notes_map_path;
+ typedef std::multimap< string, string > notes_map; // key is test_name-toolset,
+ // value is note bookmark
+ notes_map notes;
+
+ string specific_compiler; // if running on one toolset only
+
+ const string empty_string;
+
+ // build notes_bookmarks from notes HTML -----------------------------------//
+
+ void build_notes_bookmarks()
+ {
+ if ( notes_map_path.empty() ) return;
+ fs::ifstream notes_map_file( notes_map_path );
+ if ( !notes_map_file )
+ {
+ std::cerr << "Could not open --notes-map input file: " << notes_map_path.string() << std::endl;
+ std::exit( 1 );
+ }
+ string line;
+ while( std::getline( notes_map_file, line ) )
+ {
+ string::size_type pos = 0;
+ if ( (pos = line.find( ',', pos )) == string::npos ) continue;
+ string key(line.substr( 0, pos ) );
+ string bookmark( line.substr( pos+1 ) );
+
+ // std::cout << "inserting \"" << key << "\",\"" << bookmark << "\"\n";
+ notes.insert( notes_map::value_type( key, bookmark ) );
+ }
+ }
+
+ // load_notes_html ---------------------------------------------------------//
+
+ bool load_notes_html()
+ {
+ if ( notes_path.empty() ) return false;
+ fs::ifstream notes_file( notes_path );
+ if ( !notes_file )
+ {
+ std::cerr << "Could not open --notes input file: " << notes_path.string() << std::endl;
+ std::exit( 1 );
+ }
+ string line;
+ bool in_body( false );
+ while( std::getline( notes_file, line ) )
+ {
+ if ( in_body && line.find( "</body>" ) != string::npos ) in_body = false;
+ if ( in_body ) notes_html += line;
+ else if ( line.find( "<body>" ) ) in_body = true;
+ }
+ return true;
+ }
+
+ // extract object library name from target directory string ----------------//
+
+ string extract_object_library_name( const string & s )
+ {
+ string t( s );
+ string::size_type pos = t.find( "/build/" );
+ if ( pos != string::npos ) pos += 7;
+ else if ( (pos = t.find( "/test/" )) != string::npos ) pos += 6;
+ else return "";
+ return t.substr( pos, t.find( "/", pos ) - pos );
+ }
+
+ // element_content ---------------------------------------------------------//
+
+ const string & element_content(
+ const xml::element & root, const string & name )
+ {
+ const static string empty_string;
+ xml::element_list::const_iterator itr;
+ for ( itr = root.elements.begin();
+ itr != root.elements.end() && (*itr)->name != name;
+ ++itr ) {}
+ return itr != root.elements.end() ? (*itr)->content : empty_string;
+ }
+
+ // find_element ------------------------------------------------------------//
+
+ const xml::element & find_element(
+ const xml::element & root, const string & name )
+ {
+ static const xml::element empty_element;
+ xml::element_list::const_iterator itr;
+ for ( itr = root.elements.begin();
+ itr != root.elements.end() && (*itr)->name != name;
+ ++itr ) {}
+ return itr != root.elements.end() ? *((*itr).get()) : empty_element;
+ }
+
+ // attribute_value ----------------------------------------------------------//
+
+ const string & attribute_value(
+ const xml::element & element,
+ const string & attribute_name
+ ){
+ xml::attribute_list::const_iterator atr;
+ for(
+ atr = element.attributes.begin();
+ atr != element.attributes.end();
+ ++atr
+ ){
+ if(atr->name == attribute_name)
+ return atr->value;
+ }
+ static const string empty_string;
+ return empty_string;
+ }
+
+ // generate_report ---------------------------------------------------------//
+
+ // return 0 if nothing generated, 1 otherwise, except 2 if compiler msgs
+ int generate_report(
+ const xml::element & db,
+ const std::string source_library_name,
+ const string & test_type,
+ const fs::path & target_dir,
+ bool pass,
+ bool always_show_run_output
+ )
+ {
+ // compile msgs sometimes modified, so make a local copy
+ string compile( ((pass && no_warn)
+ ? empty_string : element_content( db, "compile" )) );
+
+ const string & link( pass ? empty_string : element_content( db, "link" ) );
+ const string & run( (pass && !always_show_run_output)
+ ? empty_string : element_content( db, "run" ) );
+ string lib( (pass ? empty_string : element_content( db, "lib" )) );
+
+ // some compilers output the filename even if there are no errors or
+ // warnings; detect this if one line of output and it contains no space.
+ string::size_type pos = compile.find( '\n', 1 );
+ if ( pos != string::npos && compile.size()-pos <= 2
+ && compile.find( ' ' ) == string::npos ) compile.clear();
+
+ if ( lib.empty()
+ && (
+ compile.empty() || test_type == "compile_fail"
+ )
+ && link.empty()
+ && run.empty()
+ )
+ return 0;
+
+ int result = 1; // some kind of msg for sure
+
+ // limit compile message length
+ if ( compile.size() > max_compile_msg_size )
+ {
+ compile.erase( max_compile_msg_size );
+ compile += "...\n (remainder deleted because of excessive size)\n";
+ }
+
+ links_file << "<h2><a name=\"";
+ links_file << std::make_pair(
+ html_from_path(target_dir.string().begin()),
+ html_from_path(target_dir.string().end())
+ )
+ << "\">"
+ << std::make_pair(
+ html_from_path(target_dir.string().begin()),
+ html_from_path(target_dir.string().end())
+ )
+ ;
+ links_file << "</a></h2>\n";;
+
+ if ( !compile.empty() )
+ {
+ ++result;
+ links_file << "<h3>Compiler output:</h3><pre>"
+ << compile << "</pre>\n";
+ }
+ if ( !link.empty() )
+ links_file << "<h3>Linker output:</h3><pre>" << link << "</pre>\n";
+ if ( !run.empty() )
+ links_file << "<h3>Run output:</h3><pre>" << run << "</pre>\n";
+
+ // for an object library failure, generate a reference to the object
+ // library failure message, and (once only) generate the object
+ // library failure message itself
+ static std::set< string > failed_lib_target_dirs; // only generate once
+ if ( !lib.empty() )
+ {
+ if ( lib[0] == '\n' ) lib.erase( 0, 1 );
+ string object_library_name( extract_object_library_name( lib ) );
+
+ // changing the target directory naming scheme breaks
+ // extract_object_library_name()
+ assert( !object_library_name.empty() );
+ if ( object_library_name.empty() )
+ std::cerr << "Failed to extract object library name from " << lib << "\n";
+
+ links_file << "<h3>Library build failure: </h3>\n"
+ "See <a href=\"#"
+ << source_library_name << "-"
+ << object_library_name << "-"
+ << std::make_pair(
+ html_from_path(target_dir.string().begin()),
+ html_from_path(target_dir.string().end())
+ )
+ << source_library_name << " - "
+ << object_library_name << " - "
+ << std::make_pair(
+ html_from_path(target_dir.string().begin()),
+ html_from_path(target_dir.string().end())
+ )
+ << "</a>";
+ if ( failed_lib_target_dirs.find( lib ) == failed_lib_target_dirs.end() )
+ {
+ failed_lib_target_dirs.insert( lib );
+ fs::path pth( locate_root / lib / "test_log.xml" );
+ fs::ifstream file( pth );
+ if ( file )
+ {
+ xml::element_ptr db = xml::parse( file, pth.string() );
+ generate_report(
+ *db,
+ source_library_name,
+ test_type,
+ target_dir,
+ false,
+ false
+ );
+ }
+ else
+ {
+ links_file << "<h2><a name=\""
+ << object_library_name << "-"
+ << std::make_pair(
+ html_from_path(target_dir.string().begin()),
+ html_from_path(target_dir.string().end())
+ )
+ << "\">"
+ << object_library_name << " - "
+ << std::make_pair(
+ html_from_path(target_dir.string().begin()),
+ html_from_path(target_dir.string().end())
+ )
+ << "</a></h2>\n"
+ << "test_log.xml not found\n";
+ }
+ }
+ }
+ return result;
+ }
+
+ // add_notes --------------------------------------------------------------//
+
+ void add_notes( const string & key, bool fail, string & sep, string & target )
+ {
+ notes_map::const_iterator itr = notes.lower_bound( key );
+ if ( itr != notes.end() && itr->first == key )
+ {
+ for ( ; itr != notes.end() && itr->first == key; ++itr )
+ {
+ string note_desc( itr->second[0] == '-'
+ ? itr->second.substr( 1 ) : itr->second );
+ if ( fail || itr->second[0] == '-' )
+ {
+ target += sep;
+ sep = ",";
+ target += "<a href=\"";
+ target += "#";
+ target += note_desc;
+ target += "\">";
+ target += note_desc;
+ target += "</a>";
+ }
+ }
+ }
+ }
+
+ // do_cell ---------------------------------------------------------------//
+ bool do_cell(
+ const fs::path & target_dir,
+ const string & lib_name,
+ string & target,
+ bool profile
+ ){
+ // return true if any results except pass_msg
+ bool pass = false;
+
+ fs::path xml_file_path( target_dir / "test_log.xml" );
+ if ( !fs::exists( xml_file_path ) )
+ {
+ // suppress message because there are too many of them.
+ // "missing" is a legitmate result as its not a requirement
+ // that every test be run in every figuration.
+ //std::cerr << "Missing jam_log.xml in target:\n "
+ // << target_dir.string() << "\n";
+ target += "<td align=\"right\">" + missing_residue_msg + "</td>";
+ return true;
+ }
+
+ int anything_generated = 0;
+ bool note = false;
+
+ fs::ifstream file( xml_file_path );
+ if ( !file ) // could not open jam_log.xml
+ {
+ std::cerr << "Can't open jam_log.xml in target:\n "
+ << target_dir.string() << "\n";
+ target += "<td>" + missing_residue_msg + "</td>";
+ return false;
+ }
+
+ string test_type( "unknown" );
+ bool always_show_run_output( false );
+
+ xml::element_ptr dbp = xml::parse( file, xml_file_path.string() );
+ const xml::element & db( *dbp );
+ test_type = attribute_value( db, "test-type" );
+ always_show_run_output
+ = attribute_value( db, "show-run-output" ) == "true";
+
+ std::string test_type_base( test_type );
+ if ( test_type_base.size() > 5 )
+ {
+ const string::size_type trailer = test_type_base.size() - 5;
+ if ( test_type_base.substr( trailer ) == "_fail" )
+ {
+ test_type_base.erase( trailer );
+ }
+ }
+ if ( test_type_base.size() > 4 )
+ {
+ const string::size_type trailer = test_type_base.size() - 4;
+ if ( test_type_base.substr( trailer ) == "_pyd" )
+ {
+ test_type_base.erase( trailer );
+ }
+ }
+ const xml::element & test_type_element( find_element( db, test_type_base ) );
+
+ pass = !test_type_element.name.empty()
+ && attribute_value( test_type_element, "result" ) != "fail";
+
+ if (!no_links){
+ if(!test_type_element.name.empty())
+ note = attribute_value( test_type_element, "result" ) == "note";
+ anything_generated =
+ generate_report(
+ db,
+ lib_name,
+ test_type,
+ target_dir,
+ pass,
+ always_show_run_output || note
+ );
+ }
+
+ // generate the status table cell pass/warn/fail HTML
+ target += "<td align=\"right\">";
+ if ( anything_generated != 0 )
+ {
+ target += "<a href=\"";
+ target += links_name;
+ target += "#";
+ std::copy(
+ html_from_path(target_dir.string().begin()),
+ html_from_path(target_dir.string().end()),
+ std::back_inserter(target)
+ );
+ target += "\">";
+ target += pass
+ ? (anything_generated < 2 ? pass_msg : warn_msg)
+ : fail_msg;
+ target += "</a>";
+ if ( pass && note ) target += note_msg;
+ }
+ else target += pass ? pass_msg : fail_msg;
+
+ // if profiling
+ if(profile && pass){
+ // add link to profile
+ target += " <a href=\"";
+ target += (target_dir / "profile.txt").string();
+ target += "\"><i>Profile</i></a>";
+ }
+
+ // if notes, generate the superscript HTML
+// if ( !notes.empty() )
+// target += get_notes( toolset, lib_name, test_name, !pass );
+
+ target += "</td>";
+ return (anything_generated != 0) || !pass;
+ }
+
+ bool visit_node_tree(
+ const col_node & node,
+ fs::path dir_root,
+ const string & lib_name,
+ string & target,
+ bool profile
+ ){
+ bool retval = false;
+ if(node.has_leaf){
+ retval = do_cell(
+ dir_root,
+ lib_name,
+ target,
+ profile
+ );
+ }
+
+ col_node::subcolumns_t::const_iterator col_itr;
+ for(
+ col_itr = node.m_subcolumns.begin();
+ col_itr != node.m_subcolumns.end();
+ ++col_itr
+ ){
+ fs::path subdir = dir_root / col_itr->first;
+ retval |= visit_node_tree(
+ col_itr->second,
+ subdir,
+ lib_name,
+ target,
+ col_itr->first == "profile"
+ );
+ }
+ return retval;
+ }
+
+ // emit results for each test
+ void do_row(
+ col_node test_node,
+ const fs::path & test_dir,
+ const string & lib_name,
+ const string & test_name,
+ string & target
+ ){
+ string::size_type row_start_pos = target.size();
+
+ target += "<tr>";
+
+ target += "<td>";
+ //target += "<a href=\"" + url_prefix_dir_view + "/libs/" + lib_name + "\">";
+ target += test_name;
+ target += "</a>";
+ target += "</td>";
+
+// target += "<td>" + test_type + "</td>";
+
+ bool no_warn_save = no_warn;
+
+// if ( test_type.find( "fail" ) != string::npos ) no_warn = true;
+
+ // emit cells on this row
+ bool anything_to_report = visit_node_tree(
+ test_node,
+ test_dir,
+ lib_name,
+ target,
+ false
+ );
+
+ target += "</tr>";
+
+ if ( ignore_pass
+ && ! anything_to_report )
+ target.erase( row_start_pos );
+
+ no_warn = no_warn_save;
+ }
+
+ // do_table_body -----------------------------------------------------------//
+
+ void do_table_body(
+ col_node root_node,
+ const string & lib_name,
+ const fs::path & test_lib_dir
+ ){
+ // rows are held in a vector so they can be sorted, if desired.
+ std::vector<string> results;
+
+ for ( fs::directory_iterator itr( test_lib_dir ); itr != end_itr; ++itr )
+ {
+ if(! fs::is_directory(*itr))
+ continue;
+
+ string test_name = itr->path().native();
+ // if the file name contains ".test"
+ string::size_type s = test_name.find( ".test" );
+ if(string::npos != s)
+ // strip it off
+ test_name.resize(s);
+ else
+ // if it doesn't - skip this directory
+ continue;
+
+ results.push_back( std::string() );
+ do_row(
+ root_node, //*test_node_itr++,
+ *itr, // test dir
+ lib_name,
+ test_name,
+ results[results.size()-1]
+ );
+ }
+
+ std::sort( results.begin(), results.end() );
+
+ for (
+ std::vector<string>::iterator v(results.begin());
+ v != results.end();
+ ++v
+ ){
+ report << *v << "\n";
+ }
+ }
+
+ // column header-----------------------------------------------------------//
+ int header_depth(const col_node & root){
+ col_node::subcolumns_t::const_iterator itr;
+ int max_depth = 1;
+ for(itr = root.m_subcolumns.begin(); itr != root.m_subcolumns.end(); ++itr){
+ max_depth = (std::max)(max_depth, itr->second.rows);
+ }
+ return max_depth;
+ }
+
+ void header_cell(int rows, int cols, const std::string & name){
+ // add row cells
+ report << "<td align=\"center\" " ;
+ if(1 < cols)
+ report << "colspan=\"" << cols << "\" " ;
+ if(1 < rows)
+ // span rows to the end the header
+ report << "rowspan=\"" << rows << "\" " ;
+ report << ">" ;
+ report << name;
+ report << "</td>\n";
+ }
+
+ void emit_column_headers(
+ const col_node & node,
+ int display_row,
+ int current_row,
+ int row_count
+ ){
+ if(current_row < display_row){
+ if(! node.m_subcolumns.empty()){
+ col_node::subcolumns_t::const_iterator itr;
+ for(itr = node.m_subcolumns.begin(); itr != node.m_subcolumns.end(); ++itr){
+ emit_column_headers(itr->second, display_row, current_row + 1, row_count);
+ }
+ }
+ return;
+ }
+ if(node.has_leaf && ! node.m_subcolumns.empty()){
+ header_cell(row_count - current_row, 1, std::string(""));
+ }
+
+ col_node::subcolumns_t::const_iterator itr;
+ for(itr = node.m_subcolumns.begin(); itr != node.m_subcolumns.end(); ++itr){
+ if(1 == itr->second.rows)
+ header_cell(row_count - current_row, itr->second.cols, itr->first);
+ else
+ header_cell(1, itr->second.cols, itr->first);
+ }
+ }
+
+ fs::path find_lib_test_dir(fs::path const& initial_path){
+ // walk up from the path were we started until we find
+ // bin or bin.v2
+
+ fs::path::const_iterator it = initial_path.end(), end = initial_path.end();
+ fs::path test_lib_dir = initial_path;
+ for(;;){
+ if(fs::is_directory( test_lib_dir / "bin.v2")){
+ test_lib_dir /= "bin.v2";
+ break;
+ }
+ if(fs::is_directory( test_lib_dir / "bin")){
+ // v1 includes the word boost
+ test_lib_dir /= "bin";
+ test_lib_dir /= "boost";
+ break;
+ }
+ if(test_lib_dir.empty())
+ throw std::string("binary path not found");
+ if(*it != "libs")
+ --it;
+ test_lib_dir.remove_filename();
+ }
+
+ if(it == end)
+ throw std::string("must be run from within a library directory");
+
+
+ for(;it != end; ++it){
+ test_lib_dir /= *it; // append "libs"
+ }
+ return test_lib_dir;
+ }
+
+ // note : uncomment the #if/#endif and what this compile !!!
+ string find_lib_name(fs::path lib_test_dir){
+ unsigned int count;
+ fs::path::iterator e_itr = lib_test_dir.end();
+ for(count = 0;; ++count){
+ if(*--e_itr == "libs")
+ break;
+ if(lib_test_dir.empty())
+ throw std::string("must be run from within a library directory");
+ }
+ string library_name;
+ for(;;){
+ library_name.append((*++e_itr).native());
+ if(1 == --count)
+ break;
+ library_name.append("/");
+ }
+ return library_name;
+ }
+
+ fs::path find_boost_root(fs::path initial_path){
+ fs::path boost_root = initial_path;
+ for(;;){
+ if(fs::is_directory( boost_root / "boost")){
+ break;
+ }
+ if(boost_root.empty())
+ throw std::string("boost root not found");
+ boost_root.remove_filename();
+ }
+
+ return boost_root;
+ }
+
+ // do_table ----------------------------------------------------------------//
+ void do_table(fs::path const& initial_path, const string & lib_name)
+ {
+ col_node root_node;
+
+ fs::path lib_test_dir = find_lib_test_dir(initial_path);
+
+ for ( fs::directory_iterator itr(lib_test_dir); itr != end_itr; ++itr )
+ {
+ if(! fs::is_directory(*itr))
+ continue;
+ build_node_tree(*itr, root_node);
+ }
+
+ // visit directory nodes and record nodetree
+ report << "<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\">\n";
+
+ // emit
+ root_node.get_spans();
+ int row_count = header_depth(root_node);
+ report << "<tr>\n";
+ report << "<td rowspan=\"" << row_count << "\">Test Name</td>\n";
+
+ // emit column headers
+ int row_index = 0;
+ for(;;){
+ emit_column_headers(root_node, row_index, 0, row_count);
+ report << "</tr>" ;
+ if(++row_index == row_count)
+ break;
+ report << "<tr>\n";
+ }
+
+ // now the rest of the table body
+ do_table_body(root_node, lib_name, lib_test_dir);
+
+ report << "</table>\n";
+ }
+}// unnamed namespace
+
+// main --------------------------------------------------------------------//
+
+#define BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE
+#include <boost/test/included/prg_exec_monitor.hpp>
+
+int cpp_main( int argc, char * argv[] ) // note name!
+{
+ fs::path initial_path = fs::initial_path();
+
+ fs::path comment_path;
+ while ( argc > 1 && *argv[1] == '-' )
+ {
+ if ( argc > 2 && std::strcmp( argv[1], "--compiler" ) == 0 )
+ { specific_compiler = argv[2]; --argc; ++argv; }
+ else if ( argc > 2 && std::strcmp( argv[1], "--locate-root" ) == 0 )
+ { locate_root = fs::path( argv[2] ); --argc; ++argv; }
+ else if ( argc > 2 && std::strcmp( argv[1], "--boost-root" ) == 0 )
+ { boost_root = fs::path( argv[2] ); --argc; ++argv; }
+ else if ( argc > 2 && std::strcmp( argv[1], "--comment" ) == 0 )
+ { comment_path = fs::path( argv[2] ); --argc; ++argv; }
+ else if ( argc > 2 && std::strcmp( argv[1], "--notes" ) == 0 )
+ { notes_path = fs::path( argv[2] ); --argc; ++argv; }
+ else if ( argc > 2 && std::strcmp( argv[1], "--notes-map" ) == 0 )
+ { notes_map_path = fs::path( argv[2] ); --argc; ++argv; }
+ else if ( std::strcmp( argv[1], "--ignore-pass" ) == 0 ) ignore_pass = true;
+ else if ( std::strcmp( argv[1], "--no-warn" ) == 0 ) no_warn = true;
+ else if ( std::strcmp( argv[1], "--v2" ) == 0 )
+ {--argc; ++argv ;} // skip
+ else if ( argc > 2 && std::strcmp( argv[1], "--jamfile" ) == 0)
+ {--argc; ++argv;} // skip
+ else { std::cerr << "Unknown option: " << argv[1] << "\n"; argc = 1; }
+ --argc;
+ ++argv;
+ }
+
+ if ( argc != 2 && argc != 3 )
+ {
+ std::cerr <<
+ "Usage: library_status [options...] status-file [links-file]\n"
+ " boost-root is the path to the boost tree root directory.\n"
+ " status-file and links-file are paths to the output files.\n"
+ " options: --compiler name Run for named compiler only\n"
+ " --ignore-pass Do not report tests which pass all compilers\n"
+ " --no-warn Warnings not reported if test passes\n"
+ " --boost-root path default derived from current path.\n"
+ " --locate-root path Path to ALL_LOCATE_TARGET for bjam;\n"
+ " default boost-root.\n"
+ " --comment path Path to file containing HTML\n"
+ " to be copied into status-file.\n"
+ " --notes path Path to file containing HTML\n"
+ " to be copied into status-file.\n"
+ " --notes-map path Path to file of toolset/test,n lines, where\n"
+ " n is number of note bookmark in --notes file.\n"
+ "Example: compiler_status --compiler gcc /boost-root cs.html cs-links.html\n"
+ "Note: Only the leaf of the links-file path and --notes file string are\n"
+ "used in status-file HTML links. Thus for browsing, status-file,\n"
+ "links-file, and --notes file must all be in the same directory.\n"
+ ;
+ return 1;
+ }
+
+ if(boost_root.empty())
+ boost_root = find_boost_root(initial_path);
+ if ( locate_root.empty() )
+ locate_root = boost_root;
+
+ report.open( fs::path( argv[1] ) );
+ if ( !report )
+ {
+ std::cerr << "Could not open report output file: " << argv[2] << std::endl;
+ return 1;
+ }
+
+ if ( argc == 3 )
+ {
+ fs::path links_path( argv[2] );
+ links_name = links_path.native();
+ links_file.open( links_path );
+ if ( !links_file )
+ {
+ std::cerr << "Could not open links output file: " << argv[3] << std::endl;
+ return 1;
+ }
+ }
+ else no_links = true;
+
+ build_notes_bookmarks();
+
+ const string library_name = find_lib_name(initial_path);
+
+ char run_date[128];
+ std::time_t tod;
+ std::time( &tod );
+ std::strftime( run_date, sizeof(run_date),
+ "%X UTC, %A %d %B %Y", std::gmtime( &tod ) );
+
+ report
+ << "<html>\n"
+ << "<head>\n"
+ << "<title>Boost Library Status Automatic Test</title>\n"
+ << "</head>\n"
+ << "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
+ << "<table border=\"0\">\n"
+ << "<tr>\n"
+ << "<td><img border=\"0\" "
+ << "src=\""
+ << boost_root / "boost.png"
+ << "\" width=\"277\" "
+ << "height=\"86\"></td>\n"
+ << "<td>\n"
+ << "<h1>Library Status: " + library_name + "</h1>\n"
+ << "<b>Run Date:</b> "
+ << run_date
+ << "\n"
+ ;
+
+ if ( !comment_path.empty() )
+ {
+ fs::ifstream comment_file( comment_path );
+ if ( !comment_file )
+ {
+ std::cerr << "Could not open \"--comment\" input file: " << comment_path.string() << std::endl;
+ return 1;
+ }
+ char c;
+ while ( comment_file.get( c ) ) { report.put( c ); }
+ }
+
+ report << "</td>\n</table>\n<br>\n";
+
+ if ( !no_links )
+ {
+ links_file
+ << "<html>\n"
+ << "<head>\n"
+ << "<title>Boost Library Status Error Log</title>\n"
+ << "</head>\n"
+ << "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
+ << "<table border=\"0\">\n"
+ << "<tr>\n"
+ << "<td><img border=\"0\" src=\""
+ << boost_root / "boost.png"
+ << "\" width=\"277\" "
+ << "height=\"86\"></td>\n"
+ << "<td>\n"
+ << "<h1>Library Status: " + library_name + "</h1>\n"
+ << "<b>Run Date:</b> "
+ << run_date
+ << "\n</td>\n</table>\n<br>\n"
+ ;
+ }
+
+ do_table(initial_path, library_name);
+
+ if ( load_notes_html() ) report << notes_html << "\n";
+
+ report << "</body>\n"
+ "</html>\n"
+ ;
+
+ if ( !no_links )
+ {
+ links_file
+ << "</body>\n"
+ "</html>\n"
+ ;
+ }
+ return 0;
+}
diff --git a/tools/regression/src/library_test.bat b/tools/regression/src/library_test.bat
new file mode 100644
index 0000000000..0f33840c34
--- /dev/null
+++ b/tools/regression/src/library_test.bat
@@ -0,0 +1,21 @@
+@echo off
+
+rem Copyright Robert Ramey 2007
+
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+if not "%1" == "" goto bjam
+ echo Usage: %0 "<bjam arguments>"
+ echo where typical bjam arguements are:
+ echo toolset=msvc-7.1,gcc
+ echo variant=debug,release,profile
+ echo link=static,shared
+ echo threading=single,multi
+ echo -sBOOST_ARCHIVE_LIST="<archive name>"
+ goto end
+:bjam
+ bjam --dump-tests %* >bjam.log 2>&1
+ process_jam_log --v2 <bjam.log
+ library_status library_status.html links.html
+:end
diff --git a/tools/regression/src/library_test.sh b/tools/regression/src/library_test.sh
new file mode 100755
index 0000000000..0164d0d1aa
--- /dev/null
+++ b/tools/regression/src/library_test.sh
@@ -0,0 +1,19 @@
+# Copyright Robert Ramey 2007
+
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+if test $# -eq 0
+then
+ echo "Usage: $0 <bjam arguments>"
+ echo "Typical bjam arguements are:"
+ echo " toolset=msvc-7.1,gcc"
+ echo " variant=debug,release,profile"
+ echo " link=static,shared"
+ echo " threading=single,multi"
+ echo " -sBOOST_ARCHIVE_LIST=<archive name>"
+else
+ bjam --dump-tests $@ >bjam.log 2>&1
+ process_jam_log --v2 <bjam.log
+ library_status library_status.html links.html
+fi
diff --git a/tools/regression/src/library_test_all.sh b/tools/regression/src/library_test_all.sh
new file mode 100755
index 0000000000..ed5177d412
--- /dev/null
+++ b/tools/regression/src/library_test_all.sh
@@ -0,0 +1,85 @@
+if test $# -eq 0
+then
+ echo "Usage: $0 <bjam arguments>"
+ echo "Typical bjam arguments are:"
+ echo " toolset=msvc-7.1,gcc"
+ echo " variant=debug,release,profile"
+ echo " link=static,shared"
+ echo " threading=single,multi"
+ echo
+ echo "note: make sure this script is run from boost root directory !!!"
+ exit 1
+fi
+
+if ! test -e libs
+then
+ echo No libs directory found. Run from boost root directory !!!
+ exit 1
+fi
+
+#html header
+cat <<end >status/library_status_contents.html
+<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<!--
+(C) Copyright 2007 Robert Ramey - http://www.rrsd.com .
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+-->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<link rel="stylesheet" type="text/css" href="../boost.css">
+<title>Library Status Contents</title>
+<body>
+end
+
+cd >nul libs
+
+# runtests, create library pages, and body of summary page
+for lib_name in *
+do
+ if test -d $lib_name
+ then
+ cd >nul $lib_name
+
+ if test -e "test/Jamfile.v2"
+ then
+ cd >nul test
+ echo $lib_name
+ echo >>../../../status/library_status_contents.html "<a target=\"detail\" href=\"../libs/$lib_name/test/library_status.html\">$lib_name</a><br>"
+ ../../../tools/regression/src/library_test.sh $@
+ cd >nul ..
+ fi
+
+ for sublib_name in *
+ do
+ if test -d $sublib_name
+ then
+ cd >nul $sublib_name
+ if test -e "test/Jamfile.v2"
+ then
+ cd >nul test
+ echo $lib_name/$sublib_name
+ echo >>../../../../status/library_status_contents.html "<a target=\"detail\" href=\"../libs/$lib_name/$sublib_name/test/library_status.html\">$lib_name/$sublib_name</a><br>"
+ ../../../../tools/regression/src/library_test.sh $@
+ cd >nul ..
+ fi
+ cd >nul ..
+ fi
+ done
+
+ cd >nul ..
+ fi
+done
+
+
+cd >nul ..
+
+#html trailer
+cat <<end >>status/library_status_contents.html
+</body>
+</html>
+end
+
+
diff --git a/tools/regression/src/process_jam_log.cpp b/tools/regression/src/process_jam_log.cpp
new file mode 100644
index 0000000000..8f1b19b06a
--- /dev/null
+++ b/tools/regression/src/process_jam_log.cpp
@@ -0,0 +1,893 @@
+// process jam regression test output into XML -----------------------------//
+
+// Copyright Beman Dawes 2002. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/tools/regression for documentation.
+
+#define BOOST_FILESYSTEM_VERSION 3
+
+#include <boost/config/warning_disable.hpp>
+
+#include "detail/tiny_xml.hpp"
+#include "boost/filesystem/operations.hpp"
+#include "boost/filesystem/fstream.hpp"
+#include "boost/filesystem/exception.hpp"
+#include "boost/filesystem/convenience.hpp"
+
+#include <iostream>
+#include <string>
+#include <cstring>
+#include <map>
+#include <utility> // for make_pair
+#include <ctime>
+#include <cctype> // for tolower
+#include <cstdlib> // for exit
+
+using std::string;
+namespace xml = boost::tiny_xml;
+namespace fs = boost::filesystem;
+
+// options
+
+static bool echo = false;
+static bool create_dirs = false;
+static bool boost_build_v2 = true;
+
+namespace
+{
+ struct test_info
+ {
+ string file_path; // relative boost-root
+ string type;
+ bool always_show_run_output;
+ };
+ typedef std::map< string, test_info > test2info_map; // key is test-name
+ test2info_map test2info;
+
+ fs::path boost_root;
+ fs::path locate_root; // ALL_LOCATE_TARGET (or boost_root if none)
+
+ // set_boost_root --------------------------------------------------------//
+
+ void set_boost_root()
+ {
+
+ boost_root = fs::initial_path();
+
+ for(;;)
+ {
+ if ( fs::exists( boost_root / "libs" ) )
+ {
+ fs::current_path( fs::initial_path() ); // restore initial path
+ return;
+ }
+ fs::current_path( ".." );
+ if ( boost_root == fs::current_path() )
+ {
+ fs::current_path( fs::initial_path() ); // restore initial path
+ std::cout <<
+ "Abort: process_jam_log must be run from within a boost directory tree\n";
+ std::exit(1);
+ }
+ boost_root = fs::current_path();
+ }
+ }
+
+ // append_html -------------------------------------------------------------//
+
+ void append_html( const string & src, string & target )
+ {
+ // there are a few lines we want to ignore
+ if ( src.find( "th target..." ) != string::npos
+ || src.find( "cc1plus.exe: warning: changing search order for system directory" ) != string::npos
+ || src.find( "cc1plus.exe: warning: as it has already been specified as a non-system directory" ) != string::npos
+ ) return;
+
+ // on some platforms (e.g. tru64cxx) the following line is a real performance boost
+ target.reserve(src.size() * 2 + target.size());
+
+ for ( string::size_type pos = 0; pos < src.size(); ++pos )
+ {
+ if ( src[pos] == '<' ) target += "&lt;";
+ else if ( src[pos] == '>' ) target += "&gt;";
+ else if ( src[pos] == '&' ) target += "&amp;";
+ else target += src[pos];
+ }
+ }
+
+ // timestamp ---------------------------------------------------------------//
+
+ string timestamp()
+ {
+ char run_date[128];
+ std::time_t tod;
+ std::time( &tod );
+ std::strftime( run_date, sizeof(run_date),
+ "%Y-%m-%d %X UTC", std::gmtime( &tod ) );
+ return string( run_date );
+ }
+
+// convert path separators to forward slashes ------------------------------//
+
+ void convert_path_separators( string & s )
+ {
+ for ( string::iterator itr = s.begin(); itr != s.end(); ++itr )
+ if ( *itr == '\\' || *itr == '!' ) *itr = '/';
+ }
+
+// trim_left ----------------------------------------------------------------//
+
+ std::string trim_left( std::string const& s )
+ {
+ std::string::size_type const pos( s.find_first_not_of(' ') );
+ return pos != std::string::npos
+ ? s.substr( pos, s.size() - pos + 1 )
+ : ""
+ ;
+ }
+
+
+// split --------------------------------------------------------------------//
+
+ std::vector<std::string> split( std::string const& s )
+ {
+ std::string::size_type const pos( s.find_first_of(' ') );
+ std::vector<std::string> result( 1, s.substr( 0, pos ) );
+ if ( pos == std::string::npos )
+ return result;
+
+ std::vector<std::string> const rest( split( trim_left( s.substr( pos, s.size() - pos + 1 ) ) ) );
+ result.insert( result.end(), rest.begin(), rest.end() );
+ return result;
+ }
+
+
+// extract a target directory path from a jam target string ----------------//
+// s may be relative to the initial_path:
+// ..\..\..\libs\foo\build\bin\libfoo.lib\vc7\debug\runtime-link-dynamic\boo.obj
+// s may be absolute:
+// d:\myboost\libs\foo\build\bin\libfoo.lib\vc7\debug\runtime-link-dynamic\boo.obj
+// return path is always relative to the boost directory tree:
+// libs/foo/build/bin/libfs.lib/vc7/debug/runtime-link-dynamic
+
+ string target_directory( const string & s )
+ {
+ string temp( s );
+ convert_path_separators( temp );
+ temp.erase( temp.find_last_of( "/" ) ); // remove leaf
+ temp = split( trim_left( temp ) ).back();
+ if ( temp[0] == '.' ) temp.erase( 0, temp.find_first_not_of( "./" ) );
+ else temp.erase( 0, locate_root.string().size()+1 );
+ if ( echo )
+ std::cout << "\ttarget_directory( \"" << s << "\") -> \"" << temp << "\"" << std::endl;
+ return temp;
+ }
+
+ string::size_type target_name_end( const string & s )
+ {
+ string::size_type pos = s.find( ".test/" );
+ if ( pos == string::npos ) pos = s.find( ".dll/" );
+ if ( pos == string::npos ) pos = s.find( ".so/" );
+ if ( pos == string::npos ) pos = s.find( ".lib/" );
+ if ( pos == string::npos ) pos = s.find( ".pyd/" );
+ if ( pos == string::npos ) pos = s.find( ".a/" );
+ return pos;
+ }
+
+ string toolset( const string & s )
+ {
+ string::size_type pos = target_name_end( s );
+ if ( pos == string::npos ) pos = s.find( "build/" );
+ if ( pos == string::npos ) return "";
+ pos = s.find( "/", pos ) + 1;
+ return s.substr( pos, s.find( "/", pos ) - pos );
+ }
+
+ string test_name( const string & s )
+ {
+ string::size_type pos = target_name_end( s );
+ if ( pos == string::npos ) return "";
+ string::size_type pos_start = s.rfind( '/', pos ) + 1;
+ return s.substr( pos_start,
+ (s.find( ".test/" ) != string::npos
+ ? pos : s.find( "/", pos )) - pos_start );
+ }
+
+ // Take a path to a target directory of test, and
+ // returns library name corresponding to that path.
+ string test_path_to_library_name( string const& path )
+ {
+ std::string result;
+ string::size_type start_pos( path.find( "libs/" ) );
+ if ( start_pos == string::npos ) {
+ start_pos = path.find( "tools/" );
+ }
+
+ if ( start_pos != string::npos )
+ {
+ // The path format is ...libs/functional/hash/test/something.test/....
+ // So, the part between "libs" and "test/something.test" can be considered
+ // as library name. But, for some libraries tests are located too deep,
+ // say numeric/ublas/test/test1 directory, and some libraries have tests
+ // in several subdirectories (regex/example and regex/test). So, nested
+ // directory may belong to several libraries.
+
+ // To disambituate, it's possible to place a 'sublibs' file in
+ // a directory. It means that child directories are separate libraries.
+ // It's still possible to have tests in the directory that has 'sublibs'
+ // file.
+
+ std::string interesting;
+ start_pos = path.find( '/', start_pos ) + 1;
+ string::size_type end_pos( path.find( ".test/", start_pos ) );
+ end_pos = path.rfind('/', end_pos);
+ if (path.substr(end_pos - 5, 5) == "/test")
+ interesting = path.substr( start_pos, end_pos - 5 - start_pos );
+ else
+ interesting = path.substr( start_pos, end_pos - start_pos );
+
+ // Take slash separate elements until we have corresponding 'sublibs'.
+ end_pos = 0;
+ for(;;)
+ {
+ end_pos = interesting.find('/', end_pos);
+ if (end_pos == string::npos) {
+ result = interesting;
+ break;
+ }
+ result = interesting.substr(0, end_pos);
+
+ if ( fs::exists( ( boost_root / "libs" ) / result / "sublibs" ) )
+ {
+ end_pos = end_pos + 1;
+ }
+ else
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ // Tries to find target name in the string 'msg', starting from
+ // position start.
+ // If found, extract the directory name from the target name and
+ // stores it in 'dir', and return the position after the target name.
+ // Otherwise, returns string::npos.
+ string::size_type parse_skipped_msg_aux(const string& msg,
+ string::size_type start,
+ string& dir)
+ {
+ dir.clear();
+ string::size_type start_pos = msg.find( '<', start );
+ if ( start_pos == string::npos ) return string::npos;
+ ++start_pos;
+ string::size_type end_pos = msg.find( '>', start_pos );
+ dir += msg.substr( start_pos, end_pos - start_pos );
+ if ( boost_build_v2 )
+ {
+ // The first letter is a magic value indicating
+ // the type of grist.
+ convert_path_separators( dir );
+ dir.erase( 0, 1 );
+ // We need path from root, not from 'status' dir.
+ if (dir.find("../") == 0)
+ dir.erase(0,3);
+ else // dir is always relative to the boost directory tree
+ dir.erase( 0, locate_root.string().size()+1 );
+ }
+ else
+ {
+ if ( dir[0] == '@' )
+ {
+ // new style build path, rooted build tree
+ convert_path_separators( dir );
+ dir.replace( 0, 1, "bin/" );
+ }
+ else
+ {
+ // old style build path, integrated build tree
+ start_pos = dir.rfind( '!' );
+ convert_path_separators( dir );
+ string::size_type path_sep_pos = dir.find( '/', start_pos + 1 );
+ if ( path_sep_pos != string::npos )
+ dir.insert( path_sep_pos, "/bin" );
+ else
+ {
+ // see http://article.gmane.org/gmane.comp.lib.boost.devel/146688;
+ // the following code assumes that: a) 'dir' is not empty,
+ // b) 'end_pos != string::npos' and c) 'msg' always ends with '...'
+ if ( dir[dir.size() - 1] == '@' )
+ dir += "/" + msg.substr( end_pos + 1, msg.size() - end_pos - 1 - 3 );
+ }
+ }
+ }
+ return end_pos;
+ }
+
+ // the format of paths is really kinky, so convert to normal form
+ // first path is missing the leading "..\".
+ // first path is missing "\bin" after "status".
+ // second path is missing the leading "..\".
+ // second path is missing "\bin" after "build".
+ // second path uses "!" for some separators.
+ void parse_skipped_msg( const string & msg,
+ string & first_dir, string & second_dir )
+ {
+ string::size_type pos = parse_skipped_msg_aux(msg, 0, first_dir);
+ if (pos == string::npos)
+ return;
+ parse_skipped_msg_aux(msg, pos, second_dir);
+ }
+
+// test_log hides database details -----------------------------------------//
+
+ class test_log
+ : boost::noncopyable
+ {
+ const string & m_target_directory;
+ xml::element_ptr m_root;
+ public:
+ test_log( const string & target_directory,
+ const string & test_name,
+ const string & toolset,
+ bool force_new_file )
+ : m_target_directory( target_directory )
+ {
+ if ( !force_new_file )
+ {
+ fs::path pth( locate_root / target_directory / "test_log.xml" );
+ fs::ifstream file( pth );
+ if ( file ) // existing file
+ {
+ try
+ {
+ m_root = xml::parse( file, pth.string() );
+ return;
+ }
+ catch(...)
+ {
+ // unable to parse existing XML file, fall through
+ }
+ }
+ }
+
+ string library_name( test_path_to_library_name( target_directory ) );
+
+ test_info info;
+ test2info_map::iterator itr( test2info.find( library_name + "/" + test_name ) );
+ if ( itr != test2info.end() )
+ info = itr->second;
+
+ if ( !info.file_path.empty() )
+ library_name = test_path_to_library_name( info.file_path );
+
+ if ( info.type.empty() )
+ {
+ if ( target_directory.find( ".lib/" ) != string::npos
+ || target_directory.find( ".dll/" ) != string::npos
+ || target_directory.find( ".so/" ) != string::npos
+ || target_directory.find( ".dylib/" ) != string::npos
+ || target_directory.find( "/build/" ) != string::npos
+ )
+ {
+ info.type = "lib";
+ }
+ else if ( target_directory.find( ".pyd/" ) != string::npos )
+ info.type = "pyd";
+ }
+
+ m_root.reset( new xml::element( "test-log" ) );
+ m_root->attributes.push_back(
+ xml::attribute( "library", library_name ) );
+ m_root->attributes.push_back(
+ xml::attribute( "test-name", test_name ) );
+ m_root->attributes.push_back(
+ xml::attribute( "test-type", info.type ) );
+ m_root->attributes.push_back(
+ xml::attribute( "test-program", info.file_path ) );
+ m_root->attributes.push_back(
+ xml::attribute( "target-directory", target_directory ) );
+ m_root->attributes.push_back(
+ xml::attribute( "toolset", toolset ) );
+ m_root->attributes.push_back(
+ xml::attribute( "show-run-output",
+ info.always_show_run_output ? "true" : "false" ) );
+ }
+
+ ~test_log()
+ {
+ fs::path pth( locate_root / m_target_directory / "test_log.xml" );
+ if ( create_dirs && !fs::exists( pth.branch_path() ) )
+ fs::create_directories( pth.branch_path() );
+ fs::ofstream file( pth );
+ if ( !file )
+ {
+ std::cout << "*****Warning - can't open output file: "
+ << pth.string() << "\n";
+ }
+ else xml::write( *m_root, file );
+ }
+
+ const string & target_directory() const { return m_target_directory; }
+
+ void remove_action( const string & action_name )
+ // no effect if action_name not found
+ {
+ xml::element_list::iterator itr;
+ for ( itr = m_root->elements.begin();
+ itr != m_root->elements.end() && (*itr)->name != action_name;
+ ++itr ) {}
+ if ( itr != m_root->elements.end() ) m_root->elements.erase( itr );
+ }
+
+ void add_action( const string & action_name,
+ const string & result,
+ const string & timestamp,
+ const string & content )
+ {
+ remove_action( action_name );
+ xml::element_ptr action( new xml::element(action_name) );
+ m_root->elements.push_back( action );
+ action->attributes.push_back( xml::attribute( "result", result ) );
+ action->attributes.push_back( xml::attribute( "timestamp", timestamp ) );
+ action->content = content;
+ }
+ };
+
+// message_manager maps input messages into test_log actions ---------------//
+
+ class message_manager
+ : boost::noncopyable
+ {
+ string m_action_name; // !empty() implies action pending
+ // IOW, a start_message awaits stop_message
+ string m_target_directory;
+ string m_test_name;
+ string m_toolset;
+
+ bool m_note; // if true, run result set to "note"
+ // set false by start_message()
+
+ // data needed to stop further compile action after a compile failure
+ // detected in the same target directory
+ string m_previous_target_directory;
+ bool m_compile_failed;
+
+ public:
+ message_manager() : m_note(false) {}
+ ~message_manager() { /*assert( m_action_name.empty() );*/ }
+
+ bool note() const { return m_note; }
+ void note( bool value ) { m_note = value; }
+
+ void start_message( const string & action_name,
+ const string & target_directory,
+ const string & test_name,
+ const string & toolset,
+ const string & prior_content )
+ {
+ assert( !target_directory.empty() );
+
+ if ( !m_action_name.empty() ) stop_message( prior_content );
+ m_action_name = action_name;
+ m_target_directory = target_directory;
+ m_test_name = test_name;
+ m_toolset = toolset;
+ m_note = false;
+
+ if ( m_previous_target_directory != target_directory )
+ {
+ m_previous_target_directory = target_directory;
+ m_compile_failed = false;
+ }
+ }
+
+ void stop_message( const string & content )
+ {
+ if ( m_action_name.empty() ) return;
+ stop_message( m_action_name, m_target_directory,
+ "succeed", timestamp(), content );
+ }
+
+ void stop_message( const string & action_name,
+ const string & target_directory,
+ const string & result,
+ const string & timestamp,
+ const string & content )
+ // the only valid action_names are "compile", "link", "run", "lib"
+ {
+ // My understanding of the jam output is that there should never be
+ // a stop_message that was not preceeded by a matching start_message.
+ // That understanding is built into message_manager code.
+ assert( m_action_name == action_name );
+ assert( m_target_directory == target_directory );
+ assert( result == "succeed" || result == "fail" );
+
+ // if test_log.xml entry needed
+ if ( !m_compile_failed
+ || action_name != "compile"
+ || m_previous_target_directory != target_directory )
+ {
+ if ( action_name == "compile"
+ && result == "fail" ) m_compile_failed = true;
+
+ test_log tl( target_directory,
+ m_test_name, m_toolset, action_name == "compile" );
+ tl.remove_action( "lib" ); // always clear out lib residue
+
+ // dependency removal
+ if ( action_name == "lib" )
+ {
+ tl.remove_action( "compile" );
+ tl.remove_action( "link" );
+ tl.remove_action( "run" );
+ }
+ else if ( action_name == "compile" )
+ {
+ tl.remove_action( "link" );
+ tl.remove_action( "run" );
+ if ( result == "fail" ) m_compile_failed = true;
+ }
+ else if ( action_name == "link" )
+ {
+ tl.remove_action( "run" );
+ }
+
+ // dependency removal won't work right with random names, so assert
+ else { assert( action_name == "run" ); }
+
+ // add the "run" stop_message action
+ tl.add_action( action_name,
+ result == "succeed" && note() ? std::string("note") : result,
+ timestamp, content );
+ }
+
+ m_action_name = ""; // signal no pending action
+ m_previous_target_directory = target_directory;
+ }
+ };
+}
+
+
+// main --------------------------------------------------------------------//
+
+
+int main( int argc, char ** argv )
+{
+ // Turn off synchronization with corresponding C standard library files. This
+ // gives a significant speed improvement on platforms where the standard C++
+ // streams are implemented using standard C files.
+ std::ios::sync_with_stdio(false);
+
+ fs::initial_path();
+ std::istream* input = 0;
+
+ if ( argc <= 1 )
+ {
+ std::cout << "process_jam_log [--echo] [--create-directories] [--v1|--v2]\n"
+ " [--boost-root boost_root] [--locate-root locate_root]\n"
+ " [--input-file input_file]\n"
+ " [locate-root]\n"
+ "--echo - verbose diagnostic output.\n"
+ "--create-directories - if the directory for xml file doesn't exists - creates it.\n"
+ " usually used for processing logfile on different machine\n"
+ "--v2 - bjam version 2 used (default).\n"
+ "--v1 - bjam version 1 used.\n"
+ "--boost-root - the root of the boost installation being used. If not defined\n"
+ " assume to run from within it and discover it heuristically.\n"
+ "--locate-root - the same as the bjam ALL_LOCATE_TARGET\n"
+ " parameter, if any. Default is boost-root.\n"
+ "--input-file - the output of a bjam --dump-tests run. Default is std input.\n"
+ ;
+ return 1;
+ }
+
+ while ( argc > 1 )
+ {
+ if ( std::strcmp( argv[1], "--echo" ) == 0 )
+ {
+ echo = true;
+ --argc; ++argv;
+ }
+ else if ( std::strcmp( argv[1], "--create-directories" ) == 0 )
+ {
+ create_dirs = true;
+ --argc; ++argv;
+ }
+ else if ( std::strcmp( argv[1], "--v2" ) == 0 )
+ {
+ boost_build_v2 = true;
+ --argc; ++argv;
+ }
+ else if ( std::strcmp( argv[1], "--v1" ) == 0 )
+ {
+ boost_build_v2 = false;
+ --argc; ++argv;
+ }
+ else if ( std::strcmp( argv[1], "--boost-root" ) == 0 )
+ {
+ --argc; ++argv;
+ if ( argc == 1 )
+ {
+ std::cout << "Abort: option --boost-root requires a directory argument\n";
+ std::exit(1);
+ }
+ boost_root = fs::path( argv[1] );
+ if ( !boost_root.is_complete() )
+ boost_root = ( fs::initial_path() / boost_root ).normalize();
+
+ --argc; ++argv;
+ }
+ else if ( std::strcmp( argv[1], "--locate-root" ) == 0 )
+ {
+ --argc; ++argv;
+ if ( argc == 1 )
+ {
+ std::cout << "Abort: option --locate-root requires a directory argument\n";
+ std::exit(1);
+ }
+ locate_root = fs::path( argv[1] );
+ --argc; ++argv;
+ }
+ else if ( std::strcmp( argv[1], "--input-file" ) == 0 )
+ {
+ --argc; ++argv;
+ if ( argc == 1 )
+ {
+ std::cout << "Abort: option --input-file requires a filename argument\n";
+ std::exit(1);
+ }
+ input = new std::ifstream(argv[1]);
+ --argc; ++argv;
+ }
+ else if ( *argv[1] == '-' )
+ {
+ std::cout << "Abort: unknown option; invoke with no arguments to see list of valid options\n";
+ return 1;
+ }
+ else
+ {
+ locate_root = fs::path( argv[1] );
+ --argc; ++argv;
+ }
+ }
+
+ if ( boost_root.empty() )
+ {
+ set_boost_root();
+ boost_root.normalize();
+ }
+
+
+ if ( locate_root.empty() )
+ {
+ locate_root = boost_root;
+ }
+ else if ( !locate_root.is_complete() )
+ {
+ locate_root = ( fs::initial_path() / locate_root ).normalize();
+ }
+
+ if ( input == 0 )
+ {
+ input = &std::cin;
+ }
+
+ std::cout << "boost_root: " << boost_root.string() << '\n'
+ << "locate_root: " << locate_root.string() << '\n';
+
+ message_manager mgr;
+
+ string line;
+ string content;
+ bool capture_lines = false;
+
+ // This loop looks at lines for certain signatures, and accordingly:
+ // * Calls start_message() to start capturing lines. (start_message() will
+ // automatically call stop_message() if needed.)
+ // * Calls stop_message() to stop capturing lines.
+ // * Capture lines if line capture on.
+
+ static const int max_line_length = 8192;
+ int line_num = 0;
+ while ( std::getline( *input, line ) )
+ {
+ if (max_line_length < line.size()) line = line.substr(0, max_line_length);
+
+ ++line_num;
+
+ std::vector<std::string> const line_parts( split( line ) );
+ std::string const line_start( line_parts[0] != "...failed"
+ ? line_parts[0]
+ : line_parts[0] + " " + line_parts[1]
+ );
+
+ if ( echo )
+ {
+ std::cout
+ << "line " << line_num << ": " << line << "\n"
+ << "\tline_start: " << line_start << "\n";
+ }
+
+ // create map of test-name to test-info
+ if ( line_start.find( "boost-test(" ) == 0 )
+ {
+ string::size_type pos = line.find( '"' );
+ string test_name( line.substr( pos+1, line.find( '"', pos+1)-pos-1 ) );
+ test_info info;
+ info.always_show_run_output
+ = line.find( "\"always_show_run_output\"" ) != string::npos;
+ info.type = line.substr( 11, line.find( ')' )-11 );
+ for (unsigned int i = 0; i!=info.type.size(); ++i )
+ { info.type[i] = std::tolower( info.type[i] ); }
+ pos = line.find( ':' );
+ // the rest of line is missing if bjam didn't know how to make target
+ if ( pos + 1 != line.size() )
+ {
+ info.file_path = line.substr( pos+3,
+ line.find( "\"", pos+3 )-pos-3 );
+ convert_path_separators( info.file_path );
+ if ( info.file_path.find( "libs/libs/" ) == 0 ) info.file_path.erase( 0, 5 );
+ if ( test_name.find( "/" ) == string::npos )
+ test_name = "/" + test_name;
+ test2info.insert( std::make_pair( test_name, info ) );
+ // std::cout << test_name << ", " << info.type << ", " << info.file_path << "\n";
+ }
+ else
+ {
+ std::cout << "*****Warning - missing test path: " << line << "\n"
+ << " (Usually occurs when bjam doesn't know how to make a target)\n";
+ }
+ continue;
+ }
+
+ // these actions represent both the start of a new action
+ // and the end of a failed action
+ else if ( line_start.find( "C++-action" ) != string::npos
+ || line_start.find( "vc-C++" ) != string::npos
+ || line_start.find( "C-action" ) != string::npos
+ || line_start.find( "Cc-action" ) != string::npos
+ || line_start.find( "vc-Cc" ) != string::npos
+ || line_start.find( ".compile.") != string::npos
+ || line_start.find( "compile-") != string::npos
+ || line_start.find( "-compile") != string::npos
+ || line_start.find( "Link-action" ) != string::npos
+ || line_start.find( "vc-Link" ) != string::npos
+ || line_start.find( "Archive-action" ) != string::npos
+ || line_start.find( ".archive") != string::npos
+ || ( line_start.find( ".link") != string::npos &&
+ // .linkonce is present in gcc linker messages about
+ // unresolved symbols. We don't have to parse those
+ line_start.find( ".linkonce" ) == string::npos )
+ )
+ {
+ //~ if ( !test2info.size() )
+ //~ {
+ //~ std::cout << "*****Error - No \"boost-test\" lines encountered.\n"
+ //~ " (Usually occurs when bjam was envoked without the --dump-tests option\n"
+ //~ " or bjam was envoked in the wrong directory)\n";
+ //~ return 1;
+ //~ }
+
+ string action( ( line_start.find( "Link-action" ) != string::npos
+ || line_start.find( "vc-Link" ) != string::npos
+ || line_start.find( "Archive-action" ) != string::npos
+ || line_start.find( ".archive") != string::npos
+ || line_start.find( ".link") != string::npos
+ )
+ ? "link" : "compile"
+ );
+
+ if ( line_start.find( "...failed " ) != string::npos )
+ {
+ mgr.stop_message( action, target_directory( line ),
+ "fail", timestamp(), content );
+ }
+ else
+ {
+ string target_dir( target_directory( line ) );
+ mgr.start_message( action, target_dir,
+ test_name( target_dir ), toolset( target_dir ), content );
+ }
+ content = "\n";
+ capture_lines = true;
+ }
+
+ // these actions are only used to stop the previous action
+ else if ( line_start.find( "-Archive" ) != string::npos
+ || line_start.find( "MkDir" ) == 0
+ || line_start.find( "common.mkdir" ) == 0 )
+ {
+ mgr.stop_message( content );
+ content.clear();
+ capture_lines = false;
+ }
+
+ else if ( line_start.find( "execute-test" ) != string::npos
+ || line_start.find( "capture-output" ) != string::npos )
+ {
+ if ( line_start.find( "...failed " ) != string::npos )
+ {
+ mgr.stop_message( "run", target_directory( line ),
+ "fail", timestamp(), content );
+ content = "\n";
+ capture_lines = true;
+ }
+ else
+ {
+ string target_dir( target_directory( line ) );
+ mgr.start_message( "run", target_dir,
+ test_name( target_dir ), toolset( target_dir ), content );
+
+ // contents of .output file for content
+ capture_lines = false;
+ content = "\n";
+ fs::ifstream file( locate_root / target_dir
+ / (test_name(target_dir) + ".output") );
+ if ( file )
+ {
+ string ln;
+ while ( std::getline( file, ln ) )
+ {
+ if ( ln.find( "<note>" ) != string::npos ) mgr.note( true );
+ append_html( ln, content );
+ content += "\n";
+ }
+ }
+ }
+ }
+
+ // bjam indicates some prior dependency failed by a "...skipped" message
+ else if ( line_start.find( "...skipped" ) != string::npos
+ && line.find( "<directory-grist>" ) == string::npos
+ )
+ {
+ mgr.stop_message( content );
+ content.clear();
+ capture_lines = false;
+
+ if ( line.find( " for lack of " ) != string::npos )
+ {
+ capture_lines = ( line.find( ".run for lack of " ) == string::npos );
+
+ string target_dir;
+ string lib_dir;
+
+ parse_skipped_msg( line, target_dir, lib_dir );
+
+ if ( target_dir != lib_dir ) // it's a lib problem
+ {
+ mgr.start_message( "lib", target_dir,
+ test_name( target_dir ), toolset( target_dir ), content );
+ content = lib_dir;
+ mgr.stop_message( "lib", target_dir, "fail", timestamp(), content );
+ content = "\n";
+ }
+ }
+
+ }
+
+ else if ( line_start.find( "**passed**" ) != string::npos
+ || line_start.find( "failed-test-file" ) != string::npos
+ || line_start.find( "command-file-dump" ) != string::npos )
+ {
+ mgr.stop_message( content );
+ content = "\n";
+ capture_lines = true;
+ }
+
+ else if ( capture_lines ) // hang onto lines for possible later use
+ {
+ append_html( line, content );;
+ content += "\n";
+ }
+ }
+
+ mgr.stop_message( content );
+ if (input != &std::cin)
+ delete input;
+ return 0;
+}
diff --git a/tools/regression/src/process_jam_log.py b/tools/regression/src/process_jam_log.py
new file mode 100755
index 0000000000..a7722b9d7a
--- /dev/null
+++ b/tools/regression/src/process_jam_log.py
@@ -0,0 +1,468 @@
+#!/usr/bin/python
+# Copyright 2008 Rene Rivera
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+import re
+import optparse
+import time
+import xml.dom.minidom
+import xml.dom.pulldom
+from xml.sax.saxutils import unescape, escape
+import os.path
+
+#~ Process a bjam XML log into the XML log format for Boost result processing.
+class BJamLog2Results:
+
+ def __init__(self,args=None):
+ opt = optparse.OptionParser(
+ usage="%prog [options] input")
+ opt.add_option( '--output',
+ help="output file" )
+ opt.add_option( '--runner',
+ help="runner ID (e.g. 'Metacomm')" )
+ opt.add_option( '--comment',
+ help="an HTML comment file to be inserted in the reports" )
+ opt.add_option( '--tag',
+ help="the tag for the results" )
+ opt.add_option( '--incremental',
+ help="do incremental run (do not remove previous binaries)",
+ action='store_true' )
+ opt.add_option( '--platform' )
+ opt.add_option( '--source' )
+ opt.add_option( '--revision' )
+ self.output = None
+ self.runner = None
+ self.comment='comment.html'
+ self.tag='trunk'
+ self.incremental=False
+ self.platform=''
+ self.source='SVN'
+ self.revision=None
+ self.input = []
+ ( _opt_, self.input ) = opt.parse_args(args,self)
+ if self.incremental:
+ run_type = 'incremental'
+ else:
+ run_type = 'full'
+ self.results = xml.dom.minidom.parseString('''<?xml version="1.0" encoding="UTF-8"?>
+<test-run
+ source="%(source)s"
+ runner="%(runner)s"
+ timestamp=""
+ platform="%(platform)s"
+ tag="%(tag)s"
+ run-type="%(run-type)s"
+ revision="%(revision)s">
+</test-run>
+''' % {
+ 'source' : self.source,
+ 'runner' : self.runner,
+ 'platform' : self.platform,
+ 'tag' : self.tag,
+ 'run-type' : run_type,
+ 'revision' : self.revision,
+ } )
+
+ self.test = {}
+ self.target_to_test = {}
+ self.target = {}
+ self.parent = {}
+ self.log = {}
+
+ self.add_log()
+ self.gen_output()
+
+ #~ print self.test
+ #~ print self.target
+
+ def add_log(self):
+ if self.input[0]:
+ bjam_xml = self.input[0]
+ else:
+ bjam_xml = self.input[1]
+ events = xml.dom.pulldom.parse(bjam_xml)
+ context = []
+ test_run = self.results.documentElement
+ for (event,node) in events:
+ if event == xml.dom.pulldom.START_ELEMENT:
+ context.append(node)
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ x_f = self.x_name_(*context)
+ if x_f:
+ events.expandNode(node)
+ # expanding eats the end element, hence walking us out one level
+ context.pop()
+ # call the translator, and add returned items to the result
+ items = (x_f[1])(node)
+ if items:
+ for item in items:
+ if item:
+ test_run.appendChild(self.results.createTextNode("\n"))
+ test_run.appendChild(item)
+ elif event == xml.dom.pulldom.END_ELEMENT:
+ context.pop()
+ #~ Add the log items nwo that we've collected all of them.
+ items = self.log.values()
+ if items:
+ for item in items:
+ if item:
+ test_run.appendChild(self.results.createTextNode("\n"))
+ test_run.appendChild(item)
+
+ def gen_output(self):
+ if self.output:
+ out = open(self.output,'w')
+ else:
+ out = sys.stdout
+ if out:
+ self.results.writexml(out,encoding='utf-8')
+
+ def tostring(self):
+ return self.results.toxml('utf-8')
+
+ def x_name_(self, *context, **kwargs):
+ node = None
+ names = [ ]
+ for c in context:
+ if c:
+ if not isinstance(c,xml.dom.Node):
+ suffix = '_'+c.replace('-','_').replace('#','_')
+ else:
+ suffix = '_'+c.nodeName.replace('-','_').replace('#','_')
+ node = c
+ names.append('x')
+ names = map(lambda x: x+suffix,names)
+ if node:
+ for name in names:
+ if hasattr(self,name):
+ return (name,getattr(self,name))
+ return None
+
+ def x(self, *context, **kwargs):
+ node = None
+ names = [ ]
+ for c in context:
+ if c:
+ if not isinstance(c,xml.dom.Node):
+ suffix = '_'+c.replace('-','_').replace('#','_')
+ else:
+ suffix = '_'+c.nodeName.replace('-','_').replace('#','_')
+ node = c
+ names.append('x')
+ names = map(lambda x: x+suffix,names)
+ if node:
+ for name in names:
+ if hasattr(self,name):
+ return getattr(self,name)(node,**kwargs)
+ else:
+ assert False, 'Unknown node type %s'%(name)
+ return None
+
+ #~ The timestamp goes to the corresponding attribute in the result.
+ def x_build_timestamp( self, node ):
+ test_run = self.results.documentElement
+ test_run.setAttribute('timestamp',self.get_data(node).strip())
+ return None
+
+ #~ Comment file becomes a comment node.
+ def x_build_comment( self, node ):
+ comment = None
+ if self.comment:
+ comment_f = open(self.comment)
+ if comment_f:
+ comment = comment_f.read()
+ comment_f.close()
+ if not comment:
+ comment = ''
+ return [self.new_text('comment',comment)]
+
+ #~ Tests are remembered for future reference.
+ def x_build_test( self, node ):
+ test_run = self.results.documentElement
+ test_node = node
+ test_name = test_node.getAttribute('name')
+ self.test[test_name] = {
+ 'library' : '/'.join(test_name.split('/')[0:-1]),
+ 'test-name' : test_name.split('/')[-1],
+ 'test-type' : test_node.getAttribute('type').lower(),
+ 'test-program' : self.get_child_data(test_node,tag='source',strip=True),
+ 'target' : self.get_child_data(test_node,tag='target',strip=True),
+ 'info' : self.get_child_data(test_node,tag='info',strip=True)
+ }
+ #~ Add a lookup for the test given the test target.
+ self.target_to_test[self.test[test_name]['target']] = test_name
+ #~ print "--- %s\n => %s" %(self.test[test_name]['target'],test_name)
+ return None
+
+ #~ Process the target dependency DAG into an ancestry tree so we can look up
+ #~ which top-level library and test targets specific build actions correspond to.
+ def x_build_targets_target( self, node ):
+ test_run = self.results.documentElement
+ target_node = node
+ name = self.get_child_data(target_node,tag='name',strip=True)
+ path = self.get_child_data(target_node,tag='path',strip=True)
+ jam_target = self.get_child_data(target_node,tag='jam-target',strip=True)
+ #~ print "--- target :: %s" %(name)
+ #~ Map for jam targets to virtual targets.
+ self.target[jam_target] = {
+ 'name' : name,
+ 'path' : path
+ }
+ #~ Create the ancestry.
+ dep_node = self.get_child(self.get_child(target_node,tag='dependencies'),tag='dependency')
+ while dep_node:
+ child = self.get_data(dep_node,strip=True)
+ child_jam_target = '<p%s>%s' % (path,child.split('//',1)[1])
+ self.parent[child_jam_target] = jam_target
+ #~ print "--- %s\n ^ %s" %(jam_target,child_jam_target)
+ dep_node = self.get_sibling(dep_node.nextSibling,tag='dependency')
+ return None
+
+ #~ Given a build action log, process into the corresponding test log and
+ #~ specific test log sub-part.
+ def x_build_action( self, node ):
+ test_run = self.results.documentElement
+ action_node = node
+ name = self.get_child(action_node,tag='name')
+ if name:
+ name = self.get_data(name)
+ #~ Based on the action, we decide what sub-section the log
+ #~ should go into.
+ action_type = None
+ if re.match('[^%]+%[^.]+[.](compile)',name):
+ action_type = 'compile'
+ elif re.match('[^%]+%[^.]+[.](link|archive)',name):
+ action_type = 'link'
+ elif re.match('[^%]+%testing[.](capture-output)',name):
+ action_type = 'run'
+ elif re.match('[^%]+%testing[.](expect-failure|expect-success)',name):
+ action_type = 'result'
+ #~ print "+ [%s] %s %s :: %s" %(action_type,name,'','')
+ if action_type:
+ #~ Get the corresponding test.
+ (target,test) = self.get_test(action_node,type=action_type)
+ #~ Skip action that have no correspoding test as they are
+ #~ regular build actions and don't need to show up in the
+ #~ regression results.
+ if not test:
+ return None
+ #~ And the log node, which we will add the results to.
+ log = self.get_log(action_node,test)
+ #~ print "--- [%s] %s %s :: %s" %(action_type,name,target,test)
+ #~ Collect some basic info about the action.
+ result_data = "%(info)s\n\n%(command)s\n%(output)s\n" % {
+ 'command' : self.get_action_command(action_node,action_type),
+ 'output' : self.get_action_output(action_node,action_type),
+ 'info' : self.get_action_info(action_node,action_type)
+ }
+ #~ For the test result status we find the appropriate node
+ #~ based on the type of test. Then adjust the result status
+ #~ acorrdingly. This makes the result status reflect the
+ #~ expectation as the result pages post processing does not
+ #~ account for this inversion.
+ action_tag = action_type
+ if action_type == 'result':
+ if re.match(r'^compile',test['test-type']):
+ action_tag = 'compile'
+ elif re.match(r'^link',test['test-type']):
+ action_tag = 'link'
+ elif re.match(r'^run',test['test-type']):
+ action_tag = 'run'
+ #~ The result sub-part we will add this result to.
+ result_node = self.get_child(log,tag=action_tag)
+ if action_node.getAttribute('status') == '0':
+ action_result = 'succeed'
+ else:
+ action_result = 'fail'
+ if not result_node:
+ #~ If we don't have one already, create it and add the result.
+ result_node = self.new_text(action_tag,result_data,
+ result = action_result,
+ timestamp = action_node.getAttribute('start'))
+ log.appendChild(self.results.createTextNode("\n"))
+ log.appendChild(result_node)
+ else:
+ #~ For an existing result node we set the status to fail
+ #~ when any of the individual actions fail, except for result
+ #~ status.
+ if action_type != 'result':
+ result = result_node.getAttribute('result')
+ if action_node.getAttribute('status') != '0':
+ result = 'fail'
+ else:
+ result = action_result
+ result_node.setAttribute('result',result)
+ result_node.appendChild(self.results.createTextNode("\n"))
+ result_node.appendChild(self.results.createTextNode(result_data))
+ return None
+
+ #~ The command executed for the action. For run actions we omit the command
+ #~ as it's just noise.
+ def get_action_command( self, action_node, action_type ):
+ if action_type != 'run':
+ return self.get_child_data(action_node,tag='command')
+ else:
+ return ''
+
+ #~ The command output.
+ def get_action_output( self, action_node, action_type ):
+ return self.get_child_data(action_node,tag='output',default='')
+
+ #~ Some basic info about the action.
+ def get_action_info( self, action_node, action_type ):
+ info = ""
+ #~ The jam action and target.
+ info += "%s %s\n" %(self.get_child_data(action_node,tag='name'),
+ self.get_child_data(action_node,tag='path'))
+ #~ The timing of the action.
+ info += "Time: (start) %s -- (end) %s -- (user) %s -- (system) %s\n" %(
+ action_node.getAttribute('start'), action_node.getAttribute('end'),
+ action_node.getAttribute('user'), action_node.getAttribute('system'))
+ #~ And for compiles some context that may be hidden if using response files.
+ if action_type == 'compile':
+ define = self.get_child(self.get_child(action_node,tag='properties'),name='define')
+ while define:
+ info += "Define: %s\n" %(self.get_data(define,strip=True))
+ define = self.get_sibling(define.nextSibling,name='define')
+ return info
+
+ #~ Find the test corresponding to an action. For testing targets these
+ #~ are the ones pre-declared in the --dump-test option. For libraries
+ #~ we create a dummy test as needed.
+ def get_test( self, node, type = None ):
+ jam_target = self.get_child_data(node,tag='jam-target')
+ base = self.target[jam_target]['name']
+ target = jam_target
+ while target in self.parent:
+ target = self.parent[target]
+ #~ print "--- TEST: %s ==> %s" %(jam_target,target)
+ #~ main-target-type is a precise indicator of what the build target is
+ #~ proginally meant to be.
+ main_type = self.get_child_data(self.get_child(node,tag='properties'),
+ name='main-target-type',strip=True)
+ if main_type == 'LIB' and type:
+ lib = self.target[target]['name']
+ if not lib in self.test:
+ self.test[lib] = {
+ 'library' : re.search(r'libs/([^/]+)',lib).group(1),
+ 'test-name' : os.path.basename(lib),
+ 'test-type' : 'lib',
+ 'test-program' : os.path.basename(lib),
+ 'target' : lib
+ }
+ test = self.test[lib]
+ else:
+ target_name_ = self.target[target]['name']
+ if self.target_to_test.has_key(target_name_):
+ test = self.test[self.target_to_test[target_name_]]
+ else:
+ test = None
+ return (base,test)
+
+ #~ Find, or create, the test-log node to add results to.
+ def get_log( self, node, test ):
+ target_directory = os.path.dirname(self.get_child_data(
+ node,tag='path',strip=True))
+ target_directory = re.sub(r'.*[/\\]bin[.]v2[/\\]','',target_directory)
+ target_directory = re.sub(r'[\\]','/',target_directory)
+ if not target_directory in self.log:
+ if 'info' in test and test['info'] == 'always_show_run_output':
+ show_run_output = 'true'
+ else:
+ show_run_output = 'false'
+ self.log[target_directory] = self.new_node('test-log',
+ library=test['library'],
+ test_name=test['test-name'],
+ test_type=test['test-type'],
+ test_program=test['test-program'],
+ toolset=self.get_toolset(node),
+ target_directory=target_directory,
+ show_run_output=show_run_output)
+ return self.log[target_directory]
+
+ #~ The precise toolset from the build properties.
+ def get_toolset( self, node ):
+ toolset = self.get_child_data(self.get_child(node,tag='properties'),
+ name='toolset',strip=True)
+ toolset_version = self.get_child_data(self.get_child(node,tag='properties'),
+ name='toolset-%s:version'%toolset,strip=True)
+ return '%s-%s' %(toolset,toolset_version)
+
+ #~ XML utilities...
+
+ def get_sibling( self, sibling, tag = None, id = None, name = None, type = None ):
+ n = sibling
+ while n:
+ found = True
+ if type and found:
+ found = found and type == n.nodeType
+ if tag and found:
+ found = found and tag == n.nodeName
+ if (id or name) and found:
+ found = found and n.nodeType == xml.dom.Node.ELEMENT_NODE
+ if id and found:
+ if n.hasAttribute('id'):
+ found = found and n.getAttribute('id') == id
+ else:
+ found = found and n.hasAttribute('id') and n.getAttribute('id') == id
+ if name and found:
+ found = found and n.hasAttribute('name') and n.getAttribute('name') == name
+ if found:
+ return n
+ n = n.nextSibling
+ return None
+
+ def get_child( self, root, tag = None, id = None, name = None, type = None ):
+ return self.get_sibling(root.firstChild,tag=tag,id=id,name=name,type=type)
+
+ def get_data( self, node, strip = False, default = None ):
+ data = None
+ if node:
+ data_node = None
+ if not data_node:
+ data_node = self.get_child(node,tag='#text')
+ if not data_node:
+ data_node = self.get_child(node,tag='#cdata-section')
+ data = ""
+ while data_node:
+ data += data_node.data
+ data_node = data_node.nextSibling
+ if data_node:
+ if data_node.nodeName != '#text' \
+ and data_node.nodeName != '#cdata-section':
+ data_node = None
+ if not data:
+ data = default
+ else:
+ if strip:
+ data = data.strip()
+ return data
+
+ def get_child_data( self, root, tag = None, id = None, name = None, strip = False, default = None ):
+ return self.get_data(self.get_child(root,tag=tag,id=id,name=name),strip=strip,default=default)
+
+ def new_node( self, tag, *child, **kwargs ):
+ result = self.results.createElement(tag)
+ for k in kwargs.keys():
+ if kwargs[k] != '':
+ if k == 'id':
+ result.setAttribute('id',kwargs[k])
+ elif k == 'klass':
+ result.setAttribute('class',kwargs[k])
+ else:
+ result.setAttribute(k.replace('_','-'),kwargs[k])
+ for c in child:
+ if c:
+ result.appendChild(c)
+ return result
+
+ def new_text( self, tag, data, **kwargs ):
+ result = self.new_node(tag,**kwargs)
+ data = data.strip()
+ if len(data) > 0:
+ result.appendChild(self.results.createTextNode(data))
+ return result
+
+
+if __name__ == '__main__': BJamLog2Results()
diff --git a/tools/regression/src/regression-logs.pl b/tools/regression/src/regression-logs.pl
new file mode 100644
index 0000000000..97cd4e9acd
--- /dev/null
+++ b/tools/regression/src/regression-logs.pl
@@ -0,0 +1,197 @@
+#!/usr/bin/perl
+
+#~ Copyright 2003, Rene Rivera.
+#~ Use, modification and distribution are subject to the Boost Software
+#~ License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+#~ http://www.boost.org/LICENSE_1_0.txt)
+
+use FileHandle;
+use Time::Local;
+
+# Get the whle percent value
+#
+sub percent_value
+{
+ my ($count,$total) = @_;
+ my $percent = int (($count/$total)*100+0.5);
+ if ($count > 0 && $percent == 0) { $percent = 1; }
+ if ($count < $total && $percent == 100) { $percent = 99; }
+ return $percent;
+}
+
+# Generate item html for the pass column.
+#
+sub result_info_pass
+{
+ my ($color,$pass,$warn,$fail,$missing) = @_;
+ my $percent = 100-percent_value($fail+$missing,$pass+$warn+$fail+$missing);
+ return "<font color=\"$color\"><font size=\"+1\">$percent%</font><br>($warn&nbsp;warnings)</font>";
+}
+
+# Generate item html for the fail column.
+#
+sub result_info_fail
+{
+ my ($color,$pass,$warn,$fail,$missing) = @_;
+ my $percent = percent_value($fail+$missing,$pass+$warn+$fail+$missing);
+ return "<font color=\"$color\"><font size=\"+1\">$percent%</font><br>($fail)</font>";
+}
+
+# Generate an age highlighted run date string.
+# Use as: data_info(run-date-html)
+#
+sub date_info
+{
+ my %m = ('January',0,'February',1,'March',2,'April',3,'May',4,'June',5,
+ 'July',6,'August',7,'September',8,'October',9,'November',10,'December',11);
+ my @d = split(/ |:/,$_[0]);
+ my ($hour,$min,$sec,$day,$month,$year) = ($d[0],$d[1],$d[2],$d[4],$m{$d[5]},$d[6]);
+ #print "<!-- $hour.$min.$sec.$day.$month.$year -->\n";
+ my $test_t = timegm($sec,$min,$hour,$day,$month,$year);
+ my $age = time-$test_t;
+ my $age_days = $age/(60*60*24);
+ #print "<!-- $age_days days old -->\n";
+ my $age_html = "<font>";
+ if ($age_days <= 2) { }
+ elsif ($age_days <= 14) { $age_html = "<font color=\"#FF9900\">"; }
+ else { $age_html = "<font color=\"#FF0000\">"; }
+ return $age_html.$_[0]."</font>";
+}
+
+# Generate an age string based on the run date.
+# Use as: age_info(run-date-html)
+#
+sub age_info
+{
+ my %m = ('January',0,'February',1,'March',2,'April',3,'May',4,'June',5,
+ 'July',6,'August',7,'September',8,'October',9,'November',10,'December',11);
+ my @d = split(/ |:/,$_[0]);
+ my ($hour,$min,$sec,$day,$month,$year) = ($d[0],$d[1],$d[2],$d[4],$m{$d[5]},$d[6]);
+ #print "<!-- $hour.$min.$sec.$day.$month.$year -->\n";
+ my $test_t = timegm($sec,$min,$hour,$day,$month,$year);
+ my $age = time-$test_t;
+ my $age_days = $age/(60*60*24);
+ #print "<!-- $age_days days old -->\n";
+ my $age_html = "<font>";
+ if ($age_days <= 2) { }
+ elsif ($age_days <= 14) { $age_html = "<font color=\"#FF9900\">"; }
+ else { $age_html = "<font color=\"#FF0000\">"; }
+ if ($age_days <= 1) { $age_html = $age_html."today"; }
+ elsif ($age_days <= 2) { $age_html = $age_html."yesterday"; }
+ elsif ($age_days < 14) { my $days = int $age_days; $age_html = $age_html.$days." days"; }
+ elsif ($age_days < 7*8) { my $weeks = int $age_days/7; $age_html = $age_html.$weeks." weeks"; }
+ else { my $months = int $age_days/28; $age_html = $age_html.$months." months"; }
+ return $age_html."</font>";
+}
+
+#~ foreach my $k (sort keys %ENV)
+#~ {
+ #~ print "<!-- $k = $ENV{$k} -->\n";
+#~ }
+my $logdir = "$ENV{PWD}";
+#~ my $logdir = "C:\\CVSROOTs\\Boost\\boost\\status";
+opendir LOGS, "$logdir";
+my @logs = grep /.*links[^.]*\.html$/, readdir LOGS;
+closedir LOGS;
+my @bgcolor = ( "bgcolor=\"#EEEEFF\"", "" );
+my $row = 0;
+print "<table>\n";
+print "<tr>\n",
+ "<th align=\"left\" bgcolor=\"#DDDDDD\">Platform</th>\n",
+ "<th align=\"left\" bgcolor=\"#DDDDDD\">Run Date</th>\n",
+ "<th align=\"left\" bgcolor=\"#DDDDDD\">Age</th>\n",
+ "<th align=\"left\" bgcolor=\"#DDDDDD\">Compilers</th>\n",
+ "<th align=\"left\" bgcolor=\"#DDDDDD\">Pass</th>\n",
+ "<th align=\"left\" bgcolor=\"#DDDDDD\">Fail</th>\n",
+ "</tr>\n";
+foreach $l (sort { lc($a) cmp lc($b) } @logs)
+{
+ my $log = $l;
+ $log =~ s/-links//s;
+ my ($spec) = ($log =~ /cs-([^\.]+)/);
+ my $fh = new FileHandle;
+ if ($fh->open("<$logdir/$log"))
+ {
+ my $content = join('',$fh->getlines());
+ $fh->close;
+ my ($status) = ($content =~ /(<h1>Compiler(.(?!<\/td>))+.)/si);
+ my ($platform) = ($status =~ /Status: ([^<]+)/si);
+ my ($run_date) = ($status =~ /Date:<\/b> ([^<]+)/si);
+ $run_date =~ s/, /<br>/g;
+ my ($compilers) = ($content =~ /Test Type<\/a><\/t[dh]>((.(?!<\/tr>))+.)/si);
+ if ($compilers eq "") { next; }
+ $compilers =~ s/-<br>//g;
+ $compilers =~ s/<\/td>//g;
+ my @compiler = ($compilers =~ /<td>(.*)$/gim);
+ my $count = @compiler;
+ my @results = ($content =~ /(>Pass<|>Warn<|>Fail<|>Missing<)/gi);
+ my $test_count = (scalar @results)/$count;
+ my @pass = map { 0 } (1..$count);
+ my @warn = map { 0 } (1..$count);
+ my @fail = map { 0 } (1..$count);
+ my @missing = map { 0 } (1..$count);
+ my @total = map { 0 } (1..$count);
+ #~ print "<!-- ",
+ #~ "pass = ",join(',',@pass)," ",
+ #~ "warn = ",join(',',@warn)," ",
+ #~ "fail = ",join(',',@fail)," ",
+ #~ "missing = ",join(',',@missing)," ",
+ #~ "total = ",join(',',@total)," ",
+ #~ " -->\n";
+ for my $t (1..$test_count)
+ {
+ my $r0 = (($t-1)*$count);
+ my $r1 = (($t-1)*$count+$count-1);
+ my @r = @results[(($t-1)*$count)..(($t-1)*$count+$count-1)];
+ #~ print "<!-- ",
+ #~ "result = ",join(',',@r)," ",
+ #~ "range = ",$r0,"..",$r1," (",(scalar @results),")",
+ #~ " -->\n";
+ for my $c (1..$count)
+ {
+ if ($r[$c-1] =~ /Pass/i) { ++$pass[$c-1]; }
+ elsif ($r[$c-1] =~ /Warn/i) { ++$warn[$c-1]; }
+ elsif ($r[$c-1] =~ /Fail/i) { ++$fail[$c-1]; }
+ elsif ($r[$c-1] =~ /Missing/i) { ++$missing[$c-1]; }
+ ++$total[$c-1];
+ }
+ }
+ #~ print "<!-- ",
+ #~ "pass = ",join(',',@pass)," ",
+ #~ "warn = ",join(',',@warn)," ",
+ #~ "fail = ",join(',',@fail)," ",
+ #~ "missing = ",join(',',@missing)," ",
+ #~ "total = ",join(',',@total)," ",
+ #~ " -->\n";
+ for my $comp (1..(scalar @compiler))
+ {
+ my @lines = split(/<br>/,$compiler[$comp-1]);
+ if (@lines > 2) { $compiler[$comp-1] = join(' ',@lines[0..(scalar @lines)-2])."<br>".$lines[(scalar @lines)-1]; }
+ }
+ print
+ "<tr>\n",
+ "<td rowspan=\"$count\" valign=\"top\"><font size=\"+1\">$platform</font><br>(<a href=\"./$log\">$spec</a>)</td>\n",
+ "<td rowspan=\"$count\" valign=\"top\">",$run_date,"</td>\n",
+ "<td rowspan=\"$count\" valign=\"top\">",age_info($run_date),"</td>\n",
+ "<td valign=\"top\" ",$bgcolor[$row],">",$compiler[0],"</td>\n",
+ "<td valign=\"top\" ",$bgcolor[$row],">",result_info_pass("#000000",$pass[0],$warn[0],$fail[0],$missing[0]),"</td>\n",
+ "<td valign=\"top\" ",$bgcolor[$row],">",result_info_fail("#FF0000",$pass[0],$warn[0],$fail[0],$missing[0]),"</td>\n",
+ "</tr>\n";
+ $row = ($row+1)%2;
+ foreach my $c (1..($count-1))
+ {
+ print
+ "<tr>\n",
+ "<td valign=\"top\" ",$bgcolor[$row],">",$compiler[$c],"</td>\n",
+ "<td valign=\"top\" ",$bgcolor[$row],">",result_info_pass("#000000",$pass[$c],$warn[$c],$fail[$c],$missing[$c]),"</td>\n",
+ "<td valign=\"top\" ",$bgcolor[$row],">",result_info_fail("#FF0000",$pass[$c],$warn[$c],$fail[$c],$missing[$c]),"</td>\n",
+ "</tr>\n";
+ $row = ($row+1)%2;
+ }
+ print
+ "<tr>\n",
+ "<td colspan=\"7\"><hr size=\"1\" noshade></td>\n",
+ "</tr>\n";
+ }
+}
+print "</table>\n";
diff --git a/tools/regression/src/regression.py b/tools/regression/src/regression.py
new file mode 100644
index 0000000000..0976c318da
--- /dev/null
+++ b/tools/regression/src/regression.py
@@ -0,0 +1,908 @@
+#!/usr/bin/python
+
+# Copyright MetaCommunications, Inc. 2003-2007
+# Copyright Redshift Software, Inc. 2007
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import glob
+import optparse
+import os
+import os.path
+import platform
+import sys
+import time
+
+#~ Place holder for xsl_reports/util module
+utils = None
+
+repo_root = {
+ 'anon' : 'http://svn.boost.org/svn/boost/',
+ 'user' : 'https://svn.boost.org/svn/boost/'
+ }
+repo_path = {
+ 'trunk' : 'trunk',
+ 'release' : 'branches/release',
+ 'build' : 'trunk/tools/build/v2',
+ 'jam' : 'trunk/tools/build/v2/engine',
+ 'regression' : 'trunk/tools/regression',
+ 'boost-build.jam'
+ : 'trunk/boost-build.jam'
+ }
+
+class runner:
+
+ def __init__(self,root):
+ commands = map(
+ lambda m: m[8:].replace('_','-'),
+ filter(
+ lambda m: m.startswith('command_'),
+ runner.__dict__.keys())
+ )
+ commands.sort()
+ commands = "commands: %s" % ', '.join(commands)
+
+ opt = optparse.OptionParser(
+ usage="%prog [options] [commands]",
+ description=commands)
+
+ #~ Base Options:
+ opt.add_option( '--runner',
+ help="runner ID (e.g. 'Metacomm')" )
+ opt.add_option( '--comment',
+ help="an HTML comment file to be inserted in the reports" )
+ opt.add_option( '--tag',
+ help="the tag for the results" )
+ opt.add_option( '--toolsets',
+ help="comma-separated list of toolsets to test with" )
+ opt.add_option( '--libraries',
+ help="comma separated list of libraries to test")
+ opt.add_option( '--incremental',
+ help="do incremental run (do not remove previous binaries)",
+ action='store_true' )
+ opt.add_option( '--timeout',
+ help="specifies the timeout, in minutes, for a single test run/compilation",
+ type='int' )
+ opt.add_option( '--bjam-options',
+ help="options to pass to the regression test" )
+ opt.add_option( '--bjam-toolset',
+ help="bootstrap toolset for 'bjam' executable" )
+ opt.add_option( '--pjl-toolset',
+ help="bootstrap toolset for 'process_jam_log' executable" )
+ opt.add_option( '--platform' )
+
+ #~ Source Options:
+ opt.add_option( '--user',
+ help="Boost SVN user ID" )
+ opt.add_option( '--local',
+ help="the name of the boost tarball" )
+ opt.add_option( '--force-update',
+ help="do an SVN update (if applicable) instead of a clean checkout, even when performing a full run",
+ action='store_true' )
+ opt.add_option( '--have-source',
+ help="do neither a tarball download nor an SVN update; used primarily for testing script changes",
+ action='store_true' )
+
+ #~ Connection Options:
+ opt.add_option( '--ftp',
+ help="FTP URL to upload results to." )
+ opt.add_option( '--proxy',
+ help="HTTP proxy server address and port (e.g.'http://www.someproxy.com:3128')" )
+ opt.add_option( '--ftp-proxy',
+ help="FTP proxy server (e.g. 'ftpproxy')" )
+ opt.add_option( '--dart-server',
+ help="the dart server to send results to" )
+
+ #~ Debug Options:
+ opt.add_option( '--debug-level',
+ help="debugging level; controls the amount of debugging output printed",
+ type='int' )
+ opt.add_option( '--send-bjam-log',
+ help="send full bjam log of the regression run",
+ action='store_true' )
+ opt.add_option( '--mail',
+ help="email address to send run notification to" )
+ opt.add_option( '--smtp-login',
+ help="STMP server address/login information, in the following form: <user>:<password>@<host>[:<port>]" )
+ opt.add_option( '--skip-tests',
+ help="do not run bjam; used for testing script changes",
+ action='store_true' )
+
+ #~ Defaults
+ self.runner = None
+ self.comment='comment.html'
+ self.tag='trunk'
+ self.toolsets=None
+ self.libraries=None
+ self.incremental=False
+ self.timeout=5
+ self.bjam_options=''
+ self.bjam_toolset=''
+ self.pjl_toolset=''
+ self.platform=self.platform_name()
+ self.user='anonymous'
+ self.local=None
+ self.force_update=False
+ self.have_source=False
+ self.ftp=None
+ self.proxy=None
+ self.ftp_proxy=None
+ self.dart_server=None
+ self.debug_level=0
+ self.send_bjam_log=False
+ self.mail=None
+ self.smtp_login=None
+ self.skip_tests=False
+ ( _opt_, self.actions ) = opt.parse_args(None,self)
+ if not self.actions or self.actions == []:
+ self.actions = [ 'regression' ]
+
+ #~ Initialize option dependent values.
+ self.regression_root = root
+ self.boost_root = os.path.join( self.regression_root, 'boost' )
+ self.regression_results = os.path.join( self.regression_root, 'results' )
+ if self.pjl_toolset != 'python':
+ self.regression_log = os.path.join( self.regression_results, 'bjam.log' )
+ else:
+ self.regression_log = os.path.join( self.regression_results, 'bjam.xml' )
+ self.tools_bb_root = os.path.join( self.regression_root,'tools_bb' )
+ self.tools_bjam_root = os.path.join( self.regression_root,'tools_bjam' )
+ self.tools_regression_root = os.path.join( self.regression_root,'tools_regression' )
+ self.xsl_reports_dir = os.path.join( self.tools_regression_root, 'xsl_reports' )
+ self.timestamp_path = os.path.join( self.regression_root, 'timestamp' )
+ if sys.platform == 'win32':
+ self.patch_boost = 'patch_boost.bat'
+ self.bjam = { 'name' : 'bjam.exe' }
+ self.process_jam_log = { 'name' : 'process_jam_log.exe' }
+ elif sys.platform == 'cygwin':
+ self.patch_boost = 'patch_boost'
+ self.bjam = { 'name' : 'bjam.exe' }
+ self.process_jam_log = { 'name' : 'process_jam_log.exe' }
+ else:
+ self.patch_boost = 'patch_boost'
+ self.bjam = { 'name' : 'bjam' }
+ self.process_jam_log = { 'name' : 'process_jam_log' }
+ self.bjam = {
+ 'name' : self.bjam['name'],
+ 'build_cmd' : self.bjam_build_cmd,
+ 'path' : os.path.join(self.regression_root,self.bjam['name']),
+ 'source_dir' : self.tools_bjam_root,
+ 'build_dir' : self.tools_bjam_root,
+ 'build_args' : ''
+ }
+ self.process_jam_log = {
+ 'name' : self.process_jam_log['name'],
+ 'build_cmd' : self.bjam_cmd,
+ 'path' : os.path.join(self.regression_root,self.process_jam_log['name']),
+ 'source_dir' : os.path.join(self.tools_regression_root,'build'),
+ 'build_dir' : os.path.join(self.tools_regression_root,'build'),
+ 'build_args' : 'process_jam_log -d2'
+ }
+
+ if self.debug_level > 0:
+ self.log('Regression root = %s'%self.regression_root)
+ self.log('Boost root = %s'%self.boost_root)
+ self.log('Regression results = %s'%self.regression_results)
+ self.log('Regression log = %s'%self.regression_log)
+ self.log('BB root = %s'%self.tools_bb_root)
+ self.log('Bjam root = %s'%self.tools_bjam_root)
+ self.log('Tools root = %s'%self.tools_regression_root)
+ self.log('XSL reports dir = %s'%self.xsl_reports_dir)
+ self.log('Timestamp = %s'%self.timestamp_path)
+ self.log('Patch Boost script = %s'%self.patch_boost)
+
+ if self.libraries is not None:
+ self.libraries = self.libraries.split(",")
+ # Boost.Build depends on any having run
+ if "build" in self.libraries and "any" not in self.libraries:
+ self.libraries += ["any"]
+
+ self.bjam_options += ' "--limit-tests=' + \
+ "|".join(lib for lib in self.libraries if lib != "build") + '"'
+
+ self.main()
+
+ #~ The various commands that make up the testing sequence...
+
+ def command_cleanup(self,*args):
+ if not args or args == None or args == []: args = [ 'source', 'bin' ]
+
+ if 'source' in args:
+ self.log( 'Cleaning up "%s" directory ...' % self.boost_root )
+ self.rmtree( self.boost_root )
+
+ if 'bin' in args:
+ boost_bin_dir = os.path.join( self.boost_root, 'bin' )
+ self.log( 'Cleaning up "%s" directory ...' % boost_bin_dir )
+ self.rmtree( boost_bin_dir )
+
+ boost_binv2_dir = os.path.join( self.boost_root, 'bin.v2' )
+ self.log( 'Cleaning up "%s" directory ...' % boost_binv2_dir )
+ self.rmtree( boost_binv2_dir )
+
+ self.log( 'Cleaning up "%s" directory ...' % self.regression_results )
+ self.rmtree( self.regression_results )
+
+ def command_get_tools(self):
+ #~ Get Boost.Build v2...
+ self.log( 'Getting Boost.Build v2...' )
+ if self.user and self.user != '':
+ os.chdir( os.path.dirname(self.tools_bb_root) )
+ self.svn_command( 'co %s %s' % (
+ self.svn_repository_url(repo_path['build']),
+ os.path.basename(self.tools_bb_root) ) )
+ else:
+ self.retry( lambda: self.download_tarball(
+ os.path.basename(self.tools_bb_root)+".tar.bz2",
+ self.tarball_url(repo_path['build']) ) )
+ self.unpack_tarball(
+ self.tools_bb_root+".tar.bz2",
+ os.path.basename(self.tools_bb_root) )
+ #~ Get Boost.Jam...
+ self.log( 'Getting Boost.Jam...' )
+ if self.user and self.user != '':
+ os.chdir( os.path.dirname(self.tools_bjam_root) )
+ self.svn_command( 'co %s %s' % (
+ self.svn_repository_url(repo_path['jam']),
+ os.path.basename(self.tools_bjam_root) ) )
+ else:
+ self.retry( lambda: self.download_tarball(
+ os.path.basename(self.tools_bjam_root)+".tar.bz2",
+ self.tarball_url(repo_path['jam']) ) )
+ self.unpack_tarball(
+ self.tools_bjam_root+".tar.bz2",
+ os.path.basename(self.tools_bjam_root) )
+ #~ Get the regression tools and utilities...
+ self.log( 'Getting regression tools an utilities...' )
+ if self.user and self.user != '':
+ os.chdir( os.path.dirname(self.tools_regression_root) )
+ self.svn_command( 'co %s %s' % (
+ self.svn_repository_url(repo_path['regression']),
+ os.path.basename(self.tools_regression_root) ) )
+ else:
+ self.retry( lambda: self.download_tarball(
+ os.path.basename(self.tools_regression_root)+".tar.bz2",
+ self.tarball_url(repo_path['regression']) ) )
+ self.unpack_tarball(
+ self.tools_regression_root+".tar.bz2",
+ os.path.basename(self.tools_regression_root) )
+
+ #~ We get a boost-build.jam to make the tool build work even if there's
+ #~ and existing boost-build.jam above the testing root.
+ self.log( 'Getting boost-build.jam...' )
+ self.http_get(
+ self.svn_repository_url(repo_path['boost-build.jam']),
+ os.path.join( self.regression_root, 'boost-build.jam' ) )
+
+ def command_get_source(self):
+ self.refresh_timestamp()
+ self.log( 'Getting sources (%s)...' % self.timestamp() )
+
+ if self.user and self.user != '':
+ self.retry( self.svn_checkout )
+ else:
+ self.retry( self.get_tarball )
+ pass
+
+ def command_update_source(self):
+ if self.user and self.user != '' \
+ or os.path.exists( os.path.join( self.boost_root, '.svn' ) ):
+ open( self.timestamp_path, 'w' ).close()
+ self.log( 'Updating sources from SVN (%s)...' % self.timestamp() )
+ self.retry( self.svn_update )
+ else:
+ self.command_get_source( )
+ pass
+
+ def command_patch(self):
+ self.import_utils()
+ patch_boost_path = os.path.join( self.regression_root, self.patch_boost )
+ if os.path.exists( patch_boost_path ):
+ self.log( 'Found patch file "%s". Executing it.' % patch_boost_path )
+ os.chdir( self.regression_root )
+ utils.system( [ patch_boost_path ] )
+ pass
+
+ def command_setup(self):
+ self.command_patch()
+ self.build_if_needed(self.bjam,self.bjam_toolset)
+ if self.pjl_toolset != 'python':
+ self.build_if_needed(self.process_jam_log,self.pjl_toolset)
+
+ def command_test(self, *args):
+ if not args or args == None or args == []: args = [ "test", "process" ]
+ self.import_utils()
+
+ self.log( 'Making "%s" directory...' % self.regression_results )
+ utils.makedirs( self.regression_results )
+
+ results_libs = os.path.join( self.regression_results, 'libs' )
+ results_status = os.path.join( self.regression_results, 'status' )
+
+ if "clean" in args:
+ self.command_test_clean()
+
+ if "test" in args:
+ self.command_test_run()
+ self.command_test_boost_build()
+
+ if "process" in args:
+ if self.pjl_toolset != 'python':
+ self.command_test_process()
+
+ def command_test_clean(self):
+ results_libs = os.path.join( self.regression_results, 'libs' )
+ results_status = os.path.join( self.regression_results, 'status' )
+ self.rmtree( results_libs )
+ self.rmtree( results_status )
+
+ def command_test_run(self):
+ self.import_utils()
+ if self.pjl_toolset != 'python':
+ test_cmd = '%s -d2 preserve-test-targets=off --dump-tests %s "--build-dir=%s" >>"%s" 2>&1' % (
+ self.bjam_cmd( self.toolsets ),
+ self.bjam_options,
+ self.regression_results,
+ self.regression_log )
+ else:
+ test_cmd = '%s -d1 preserve-test-targets=off --dump-tests --verbose-test %s "--build-dir=%s" "--out-xml=%s"' % (
+ self.bjam_cmd( self.toolsets ),
+ self.bjam_options,
+ self.regression_results,
+ self.regression_log )
+ self.log( 'Starting tests (%s)...' % test_cmd )
+ cd = os.getcwd()
+ os.chdir( os.path.join( self.boost_root, 'status' ) )
+ utils.system( [ test_cmd ] )
+ os.chdir( cd )
+
+ def command_test_boost_build(self):
+ if self.libraries is not None and "build" not in self.libraries:
+ return
+
+ self.import_utils()
+ self.log( 'Running Boost.Build tests' )
+ # Find the true names of the toolsets used for testing
+ toolsets = os.listdir(os.path.join(self.regression_results,
+ "boost/bin.v2/libs/any/test/any_test.test"));
+ for t in toolsets:
+ d = os.path.join(self.regression_results, ("boost-build-%s" % (t)))
+ utils.makedirs (d)
+ fn = os.path.join(d, "test_log.xml")
+ cd = os.getcwd()
+ try:
+ os.chdir (os.path.join (self.boost_root, 'tools/build/v2/test'));
+ bjam_path = os.path.dirname (self.tool_path( self.bjam ))
+ self.log( "Using bjam binary in '%s'" % (bjam_path))
+ os.putenv('PATH', bjam_path + os.pathsep + os.environ['PATH'])
+ utils.system ( [ '"%s" test_all.py --default-bjam --xml %s > %s' % (sys.executable, t, fn) ] )
+ finally:
+ os.chdir( cd )
+
+ def command_test_process(self):
+ self.import_utils()
+ self.log( 'Getting test case results out of "%s"...' % self.regression_log )
+ cd = os.getcwd()
+ os.chdir( os.path.join( self.boost_root, 'status' ) )
+ utils.checked_system( [
+ '"%s" "%s" <"%s"' % (
+ self.tool_path(self.process_jam_log),
+ self.regression_results,
+ self.regression_log )
+ ] )
+ os.chdir( cd )
+
+ def command_collect_logs(self):
+ self.import_utils()
+ comment_path = os.path.join( self.regression_root, self.comment )
+ if not os.path.exists( comment_path ):
+ self.log( 'Comment file "%s" not found; creating default comment.' % comment_path )
+ f = open( comment_path, 'w' )
+ f.write( '<p>Tests are run on %s platform.</p>' % self.platform_name() )
+ f.close()
+
+ source = 'tarball'
+ revision = ''
+ svn_root_file = os.path.join( self.boost_root, '.svn' )
+ svn_info_file = os.path.join( self.boost_root, 'svn_info.txt' )
+ if os.path.exists( svn_root_file ):
+ source = 'SVN'
+ self.svn_command( 'info --xml "%s" >"%s"' % (self.boost_root,svn_info_file) )
+
+ if os.path.exists( svn_info_file ):
+ f = open( svn_info_file, 'r' )
+ svn_info = f.read()
+ f.close()
+ i = svn_info.find( 'Revision:' )
+ if i < 0: i = svn_info.find( 'revision=' ) # --xml format
+ if i >= 0:
+ i += 10
+ while svn_info[i] >= '0' and svn_info[i] <= '9':
+ revision += svn_info[i]
+ i += 1
+
+ if self.pjl_toolset != 'python':
+ from collect_and_upload_logs import collect_logs
+ if self.incremental:
+ run_type = 'incremental'
+ else:
+ run_type = 'full'
+ collect_logs(
+ self.regression_results,
+ self.runner, self.tag, self.platform, comment_path,
+ self.timestamp_path,
+ self.user,
+ source, run_type,
+ self.dart_server, self.proxy,
+ revision )
+ else:
+ from process_jam_log import BJamLog2Results
+ if self.incremental:
+ run_type = '--incremental'
+ else:
+ run_type = ''
+ BJamLog2Results([
+ '--output='+os.path.join(self.regression_results,self.runner+'.xml'),
+ '--runner='+self.runner,
+ '--comment='+comment_path,
+ '--tag='+self.tag,
+ '--platform='+self.platform,
+ '--source='+source,
+ '--revision='+revision,
+ run_type,
+ self.regression_log
+ ])
+ self.compress_file(
+ os.path.join(self.regression_results,self.runner+'.xml'),
+ os.path.join(self.regression_results,self.runner+'.zip')
+ )
+
+ def command_upload_logs(self):
+ self.import_utils()
+ from collect_and_upload_logs import upload_logs
+ if self.ftp:
+ self.retry(
+ lambda:
+ upload_logs(
+ self.regression_results,
+ self.runner, self.tag,
+ self.user,
+ self.ftp_proxy,
+ self.debug_level, self.send_bjam_log,
+ self.timestamp_path,
+ self.dart_server,
+ ftp_url = self.ftp )
+ )
+ else:
+ self.retry(
+ lambda:
+ upload_logs(
+ self.regression_results,
+ self.runner, self.tag,
+ self.user,
+ self.ftp_proxy,
+ self.debug_level, self.send_bjam_log,
+ self.timestamp_path,
+ self.dart_server )
+ )
+
+ def command_regression(self):
+ import socket
+ import string
+ try:
+ mail_subject = 'Boost regression for %s on %s' % ( self.tag,
+ string.split(socket.gethostname(), '.')[0] )
+ start_time = time.localtime()
+ if self.mail:
+ self.log( 'Sending start notification to "%s"' % self.mail )
+ self.send_mail(
+ '%s started at %s.' % ( mail_subject, format_time( start_time ) )
+ )
+
+ self.command_get_tools()
+
+ if self.local is not None:
+ self.log( 'Using local file "%s"' % self.local )
+ b = os.path.basename( self.local )
+ tag = b[ 0: b.find( '.' ) ]
+ self.log( 'Tag: "%s"' % tag )
+ self.unpack_tarball( self.local, self.boost_root )
+
+ elif self.have_source:
+ if not self.incremental: self.command_cleanup( 'bin' )
+
+ else:
+ if self.incremental or self.force_update:
+ if not self.incremental: self.command_cleanup( 'bin' )
+ else:
+ self.command_cleanup()
+ self.command_get_source()
+
+ self.command_setup()
+
+ # Not specifying --toolset in command line is not enough
+ # that would mean to use Boost.Build default ones
+ # We can skip test only we were explictly
+ # told to have no toolsets in command line "--toolset="
+ if self.toolsets != '': # --toolset=,
+ if not self.skip_tests:
+ self.command_test()
+ self.command_collect_logs()
+ self.command_upload_logs()
+
+ if self.mail:
+ self.log( 'Sending report to "%s"' % self.mail )
+ end_time = time.localtime()
+ self.send_mail(
+ '%s completed successfully at %s.' % ( mail_subject, format_time( end_time ) )
+ )
+ except:
+ if self.mail:
+ self.log( 'Sending report to "%s"' % self.mail )
+ traceback_ = '\n'.join( apply( traceback.format_exception, sys.exc_info() ) )
+ end_time = time.localtime()
+ self.send_mail(
+ '%s failed at %s.' % ( mail_subject, format_time( end_time ) ),
+ traceback_ )
+ raise
+
+ def command_show_revision(self):
+ modified = '$Date: 2011-10-06 11:41:40 -0400 (Thu, 06 Oct 2011) $'
+ revision = '$Revision: 74759 $'
+
+ import re
+ re_keyword_value = re.compile( r'^\$\w+:\s+(.*)\s+\$$' )
+ print '\n\tRevision: %s' % re_keyword_value.match( revision ).group( 1 )
+ print '\tLast modified on: %s\n' % re_keyword_value.match( modified ).group( 1 )
+
+ #~ Utilities...
+
+ def main(self):
+ for action in self.actions:
+ action_m = "command_"+action.replace('-','_')
+ if hasattr(self,action_m):
+ getattr(self,action_m)()
+
+ def platform_name(self):
+ # See http://article.gmane.org/gmane.comp.lib.boost.testing/933
+ if sys.platform == 'win32':
+ return 'Windows'
+ elif sys.platform == 'cygwin':
+ return 'Windows/Cygwin'
+ return platform.system()
+
+ def log(self,message):
+ sys.stdout.flush()
+ sys.stderr.flush()
+ sys.stderr.write( '# %s\n' % message )
+ sys.stderr.flush()
+
+ def rmtree(self,path):
+ if os.path.exists( path ):
+ import shutil
+ #~ shutil.rmtree( unicode( path ) )
+ if sys.platform == 'win32':
+ os.system( 'del /f /s /q "%s" >nul 2>&1' % path )
+ shutil.rmtree( unicode( path ) )
+ else:
+ os.system( 'rm -f -r "%s"' % path )
+
+ def refresh_timestamp( self ):
+ if os.path.exists( self.timestamp_path ):
+ os.unlink( self.timestamp_path )
+ open( self.timestamp_path, 'w' ).close()
+
+ def timestamp( self ):
+ return time.strftime(
+ '%Y-%m-%dT%H:%M:%SZ',
+ time.gmtime( os.stat( self.timestamp_path ).st_mtime ) )
+
+ def retry( self, f, max_attempts=5, sleep_secs=10 ):
+ for attempts in range( max_attempts, -1, -1 ):
+ try:
+ return f()
+ except Exception, msg:
+ self.log( '%s failed with message "%s"' % ( f.__name__, msg ) )
+ if attempts == 0:
+ self.log( 'Giving up.' )
+ raise
+
+ self.log( 'Retrying (%d more attempts).' % attempts )
+ time.sleep( sleep_secs )
+
+ def http_get( self, source_url, destination_file ):
+ import urllib
+
+ proxies = None
+ if hasattr(self,'proxy') and self.proxy is not None:
+ proxies = { 'http' : self.proxy }
+
+ src = urllib.urlopen( source_url, proxies = proxies )
+
+ f = open( destination_file, 'wb' )
+ while True:
+ data = src.read( 16*1024 )
+ if len( data ) == 0: break
+ f.write( data )
+
+ f.close()
+ src.close()
+
+ def import_utils(self):
+ global utils
+ if utils is None:
+ sys.path.append( self.xsl_reports_dir )
+ import utils as utils_module
+ utils = utils_module
+
+ def build_if_needed( self, tool, toolset ):
+ self.import_utils()
+ if os.path.exists( tool[ 'path' ] ):
+ self.log( 'Found preinstalled "%s"; will use it.' % tool[ 'path' ] )
+ return
+
+ self.log( 'Preinstalled "%s" is not found; building one...' % tool[ 'path' ] )
+
+ if toolset is None:
+ if self.toolsets is not None:
+ toolset = string.split( self.toolsets, ',' )[0]
+ else:
+ toolset = tool[ 'default_toolset' ]
+ self.log( 'Warning: No bootstrap toolset for "%s" was specified.' % tool[ 'name' ] )
+ self.log( ' Using default toolset for the platform (%s).' % toolset )
+
+ if os.path.exists( tool[ 'source_dir' ] ):
+ self.log( 'Found "%s" source directory "%s"' % ( tool[ 'name' ], tool[ 'source_dir' ] ) )
+ build_cmd = tool[ 'build_cmd' ]( toolset, tool['build_args'] )
+ self.log( 'Building "%s" (%s)...' % ( tool[ 'name'], build_cmd ) )
+ utils.system( [ 'cd "%s"' % tool[ 'source_dir' ], build_cmd ] )
+ else:
+ raise 'Could not find "%s" source directory "%s"' % ( tool[ 'name' ], tool[ 'source_dir' ] )
+
+ if not tool.has_key( 'build_path' ):
+ tool[ 'build_path' ] = self.tool_path( tool )
+
+ if not os.path.exists( tool[ 'build_path' ] ):
+ raise 'Failed to find "%s" after build.' % tool[ 'build_path' ]
+
+ self.log( '%s succesfully built in "%s" location' % ( tool[ 'name' ], tool[ 'build_path' ] ) )
+
+ def tool_path( self, name_or_spec ):
+ if isinstance( name_or_spec, basestring ):
+ return os.path.join( self.regression_root, name_or_spec )
+
+ if os.path.exists( name_or_spec[ 'path' ] ):
+ return name_or_spec[ 'path' ]
+
+ if name_or_spec.has_key( 'build_path' ):
+ return name_or_spec[ 'build_path' ]
+
+ build_dir = name_or_spec[ 'build_dir' ]
+ self.log( 'Searching for "%s" in "%s"...' % ( name_or_spec[ 'name' ], build_dir ) )
+ for root, dirs, files in os.walk( build_dir ):
+ if name_or_spec[ 'name' ] in files:
+ return os.path.join( root, name_or_spec[ 'name' ] )
+
+ raise Exception( 'Cannot find "%s" in any of the following locations:\n%s' % (
+ name_or_spec[ 'name' ]
+ , '\n'.join( [ name_or_spec[ 'path' ], build_dir ] )
+ ) )
+
+ def bjam_build_cmd( self, *rest ):
+ if sys.platform == 'win32':
+ cmd = 'build.bat %s' % self.bjam_toolset
+ else:
+ cmd = './build.sh %s' % self.bjam_toolset
+ env_setup_key = 'BJAM_ENVIRONMENT_SETUP'
+ if os.environ.has_key( env_setup_key ):
+ return '%s & %s' % ( os.environ[env_setup_key], cmd )
+ return cmd
+
+ def bjam_cmd( self, toolsets, args = '', *rest ):
+ build_path = self.regression_root
+ if build_path[-1] == '\\': build_path += '\\'
+
+ if self.timeout > 0:
+ args += ' -l%s' % (self.timeout*60)
+
+ cmd = '"%(bjam)s"' +\
+ ' "-sBOOST_BUILD_PATH=%(bbpath)s"' +\
+ ' "-sBOOST_ROOT=%(boost)s"' +\
+ ' "--boost=%(boost)s"' +\
+ ' "--boost-build=%(bb)s"' +\
+ ' "--debug-configuration"' +\
+ ' %(arg)s'
+ cmd %= {
+ 'bjam' : self.tool_path( self.bjam ),
+ 'bbpath' : os.pathsep.join([build_path,self.tools_bb_root]),
+ 'bb' : self.tools_bb_root,
+ 'boost' : self.boost_root,
+ 'arg' : args }
+
+ if toolsets:
+ import string
+ cmd += ' ' + string.join(string.split( toolsets, ',' ), ' ' )
+
+ return cmd
+
+ def send_mail( self, subject, msg = '' ):
+ import smtplib
+ if not self.smtp_login:
+ server_name = 'mail.%s' % mail.split( '@' )[-1]
+ user_name = None
+ password = None
+ else:
+ server_name = self.smtp_login.split( '@' )[-1]
+ ( user_name, password ) = string.split( self.smtp_login.split( '@' )[0], ':' )
+
+ log( ' Sending mail through "%s"...' % server_name )
+ smtp_server = smtplib.SMTP( server_name )
+ smtp_server.set_debuglevel( self.debug_level )
+ if user_name:
+ smtp_server.login( user_name, password )
+
+ smtp_server.sendmail( self.mail, [ self.mail ],
+ 'Subject: %s\nTo: %s\n\n%s' % ( subject, self.mail, msg ) )
+
+ def compress_file( self, file_path, archive_path ):
+ self.import_utils()
+ utils.log( 'Compressing "%s"...' % file_path )
+
+ try:
+ import zipfile
+ z = zipfile.ZipFile( archive_path, 'w', zipfile.ZIP_DEFLATED )
+ z.write( file_path, os.path.basename( file_path ) )
+ z.close()
+ utils.log( 'Done writing "%s".'% archive_path )
+ except Exception, msg:
+ utils.log( 'Warning: Compressing falied (%s)' % msg )
+ utils.log( ' Trying to compress using a platform-specific tool...' )
+ try:
+ import zip_cmd
+ except ImportError:
+ script_dir = os.path.dirname( os.path.abspath( sys.argv[0] ) )
+ utils.log( 'Could not find \'zip_cmd\' module in the script directory (%s).' % script_dir )
+ raise Exception( 'Compressing failed!' )
+ else:
+ if os.path.exists( archive_path ):
+ os.unlink( archive_path )
+ utils.log( 'Removing stale "%s".' % archive_path )
+
+ zip_cmd.main( file_path, archive_path )
+ utils.log( 'Done compressing "%s".' % archive_path )
+
+ #~ Dowloading source, from SVN...
+
+ def svn_checkout( self ):
+ os.chdir( self.regression_root )
+ self.svn_command( 'co %s %s' % (self.svn_repository_url(self.tag),'boost') )
+
+ def svn_update( self ):
+ os.chdir( self.boost_root )
+ self.svn_command( 'update' )
+
+ def svn_command( self, command ):
+ svn_anonymous_command_line = 'svn --non-interactive %(command)s'
+ svn_command_line = 'svn --non-interactive --username=%(user)s %(command)s'
+
+ if not hasattr(self,'user') or self.user is None or self.user == 'anonymous':
+ cmd = svn_anonymous_command_line % { 'command': command }
+ else:
+ cmd = svn_command_line % { 'user': self.user, 'command': command }
+
+ self.log( 'Executing SVN command "%s"' % cmd )
+ rc = os.system( cmd )
+ if rc != 0:
+ raise Exception( 'SVN command "%s" failed with code %d' % ( cmd, rc ) )
+
+ def svn_repository_url( self, path ):
+ if self.user != 'anonymous' and self.user != '':
+ return '%s%s' % (repo_root['user'],path)
+ else:
+ return '%s%s' % (repo_root['anon'],path)
+
+ #~ Downloading and extracting source archives, from tarballs or zipballs...
+
+ def get_tarball( self, *args ):
+ if not args or args == []:
+ args = [ 'download', 'unpack' ]
+
+ tarball_path = None
+
+ if hasattr(self,'local') and self.local is not None:
+ tarball_path = self.local
+ elif 'download' in args:
+ tarball_path = self.download_tarball(self.boost_tarball_name(),self.boost_tarball_url())
+ if not tarball_path:
+ tarball_path = os.path.join( self.regression_root, self.boost_tarball_url() )
+
+ if 'unpack' in args:
+ self.unpack_tarball( tarball_path, self.boost_root )
+ pass
+
+ def download_tarball( self, tarball_name, tarball_url ):
+ tarball_path = os.path.join( self.regression_root, tarball_name )
+
+ self.log( 'Downloading "%s" to "%s"...' % ( tarball_url, os.path.dirname( tarball_path ) ) )
+
+ if os.path.exists( tarball_path ):
+ os.unlink( tarball_path )
+ self.http_get( tarball_url, tarball_path )
+
+ return tarball_path
+
+ def tarball_url( self, path ):
+ return 'http://beta.boost.org/development/snapshot.php/%s' % path
+
+ def boost_tarball_name( self ):
+ return 'boost-%s.tar.bz2' % self.tag.split( '/' )[-1]
+
+ def boost_tarball_url( self ):
+ return self.tarball_url( self.tag )
+
+ def unpack_tarball( self, tarball_path, target_path ):
+ self.log( 'Looking for old unpacked archives...' )
+ old_boost_dirs = self.find_boost_dirs( )
+
+ for old_boost_dir in old_boost_dirs:
+ if old_boost_dir != tarball_path:
+ self.log( 'Deleting old directory %s.' % old_boost_dir )
+ self.rmtree( old_boost_dir )
+
+ self.log( 'Unpacking boost tarball ("%s")...' % tarball_path )
+
+ tarball_name = os.path.basename( tarball_path )
+ extension = tarball_name[ tarball_name.find( '.' ) : ]
+
+ if extension in ( ".tar.gz", ".tar.bz2" ):
+ import tarfile
+ import stat
+
+ mode = os.path.splitext( extension )[1][1:]
+ tar = tarfile.open( tarball_path, 'r:%s' % mode )
+ for tarinfo in tar:
+ tar.extract( tarinfo, self.regression_root )
+ if sys.platform == 'win32' and not tarinfo.isdir():
+ # workaround what appears to be a Win32-specific bug in 'tarfile'
+ # (modification times for extracted files are not set properly)
+ f = os.path.join( self.regression_root, tarinfo.name )
+ os.chmod( f, stat.S_IWRITE )
+ os.utime( f, ( tarinfo.mtime, tarinfo.mtime ) )
+ tar.close()
+ elif extension in ( ".zip" ):
+ import zipfile
+
+ z = zipfile.ZipFile( tarball_path, 'r', zipfile.ZIP_DEFLATED )
+ for f in z.infolist():
+ destination_file_path = os.path.join( self.regression_root, f.filename )
+ if destination_file_path[-1] == "/": # directory
+ if not os.path.exists( destination_file_path ):
+ os.makedirs( destination_file_path )
+ else: # file
+ result = open( destination_file_path, 'wb' )
+ result.write( z.read( f.filename ) )
+ result.close()
+ z.close()
+ else:
+ raise 'Do not know how to unpack archives with extension \"%s\"' % extension
+
+ boost_dir = self.find_boost_dirs()[0]
+ self.log( ' Unpacked into directory "%s"' % boost_dir )
+
+ if os.path.exists( target_path ):
+ self.log( 'Deleting "%s" directory...' % target_path )
+ self.rmtree( target_path )
+
+ self.log( 'Renaming "%s" into "%s"' % ( boost_dir, target_path ) )
+ os.rename( boost_dir, target_path )
+
+ def find_boost_dirs( self ):
+ return [
+ x for x in
+ glob.glob( os.path.join( self.regression_root, 'boost[-_]*' ) )
+ if os.path.isdir( x )
+ ]
+
+
diff --git a/tools/regression/src/run.py b/tools/regression/src/run.py
new file mode 100644
index 0000000000..5e8e0c7d01
--- /dev/null
+++ b/tools/regression/src/run.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+
+# Copyright Redshift Software, Inc. 2007
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import os
+import os.path
+import shutil
+import sys
+import urllib
+
+#~ Using --skip-script-download is useful to avoid repeated downloading of
+#~ the regression scripts when doing the regression commands individually.
+no_update_argument = "--skip-script-download"
+no_update = no_update_argument in sys.argv
+if no_update:
+ del sys.argv[sys.argv.index(no_update_argument)]
+
+#~ The directory this file is in.
+root = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
+print '# Running regressions in %s...' % root
+
+script_sources = [ 'collect_and_upload_logs.py', 'process_jam_log.py', 'regression.py' ]
+script_local = os.path.join(root,'tools','regression','src')
+script_remote = 'http://svn.boost.org/svn/boost/trunk/tools/regression/src'
+script_dir = os.path.join(root,'tools_regression_src')
+
+if not no_update:
+ #~ Bootstrap.
+ #~ * Clear out any old versions of the scripts
+ print '# Creating regression scripts at %s...' % script_dir
+ if os.path.exists(script_dir):
+ shutil.rmtree(script_dir)
+ os.mkdir(script_dir)
+ #~ * Get new scripts, either from local working copy, or from svn
+ if os.path.exists(script_local):
+ print '# Copying regression scripts from %s...' % script_local
+ for src in script_sources:
+ shutil.copyfile( os.path.join(script_local,src), os.path.join(script_dir,src) )
+ else:
+ print '# Dowloading regression scripts from %s...' % script_remote
+ proxy = None
+ for a in sys.argv[1:]:
+ if a.startswith('--proxy='):
+ proxy = {'http' : a.split('=')[1] }
+ print '--- %s' %(proxy['http'])
+ break
+ for src in script_sources:
+ urllib.FancyURLopener(proxy).retrieve(
+ '%s/%s' % (script_remote,src), os.path.join(script_dir,src) )
+
+#~ * Make the scripts available to Python
+sys.path.insert(0,os.path.join(root,'tools_regression_src'))
+
+#~ Launch runner.
+from regression import runner
+runner(root)
diff --git a/tools/regression/src/run_tests.sh b/tools/regression/src/run_tests.sh
new file mode 100644
index 0000000000..483cecfeae
--- /dev/null
+++ b/tools/regression/src/run_tests.sh
@@ -0,0 +1,197 @@
+#!/bin/sh
+#
+# Copyright John Maddock
+# Copyright Rene Rivera
+#
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+#
+# shell script for running the boost regression test suite and generating
+# a html table of results.
+
+# Set the following variables to configure the operation. Variables you
+# should set, i.e. usually required are listed first. Optional variables
+# have reasonable defaults for most situations.
+
+
+### THESE SHOULD BE CHANGED!
+
+#
+# "boost_root" points to the root of you boost installation:
+# This can be either a non-exitent directory or an already complete Boost
+# source tree.
+#
+boost_root="$HOME/CVSROOTs/Boost/boost_regression"
+
+#
+# Wether to fetch the most current Boost code from CVS (yes/no):
+# There are two contexts to use this script in: on an active Boost CVS
+# tree, and on a fresh Boost CVS tree. If "yes" is specified here an attempt
+# to fetch the latest CVS Boost files is made. For an active Boost CVS
+# the CVS connection information is used. If an empty tree is detected
+# the code is fetched with the anonymous read only information.
+#
+cvs_update=no
+
+#
+# "test_tools" are the Boost.Build toolsets to use for building and running the
+# regression tests. Specify a space separated list, of the Boost.Build toolsets.
+# Each will be built and tested in sequence.
+#
+test_tools=gcc
+
+#
+# "toolset" is the Boost.Build toolset to use for building the helper programs.
+# This is usually different than the toolsets one is testing. And this is
+# normally a toolset that corresponds to the compiler built into your platform.
+#
+toolset=gcc
+
+#
+# "comment_path" is the path to an html-file describing the test environment.
+# The content of this file will be embedded in the status pages being produced.
+#
+comment_path="$boost_root/../regression_comment.html"
+#
+# "test_dir" is the relative path to the directory to run the tests in,
+# defaults to "status" and runs all the tests, but could be a sub-directory
+# for example "libs/regex/test" to run the regex tests alone.
+#
+test_dir="status"
+
+
+### DEFAULTS ARE OK FOR THESE.
+
+#
+# "exe_suffix" the suffix used by exectable files:
+# In case your platform requires use of a special suffix for executables specify
+# it here, including the "." if needed. This should not be needed even in Windows
+# like platforms as they will execute without the suffix anyway.
+#
+exe_suffix=
+
+#
+# "bjam" points to your built bjam executable:
+# The location of the binary for running bjam. The default should work
+# under most circumstances.
+#
+bjam="$boost_root/tools/build/v2/engine/bin/bjam$exe_suffix"
+
+#
+# "process_jam_log", and "compiler_status" paths to built helper programs:
+# The location of the executables of the regression help programs. These
+# are built locally so the default should work in most situations.
+#
+process_jam_log="$boost_root/dist/bin/process_jam_log$exe_suffix"
+compiler_status="$boost_root/dist/bin/compiler_status$exe_suffix"
+
+#
+# "boost_build_path" can point to additional locations to find toolset files.
+#
+boost_build_path="$HOME/.boost-build"
+
+
+### NO MORE CONFIGURABLE PARTS.
+
+#
+# Some setup.
+#
+boost_dir=`basename "$boost_root"`
+if test -n "${BOOST_BUILD_PATH}" ; then
+ BOOST_BUILD_PATH="$boost_build_path:$BOOST_BUILD_PATH"
+else
+ BOOST_BUILD_PATH="$boost_build_path"
+fi
+export BOOST_BUILD_PATH
+
+#
+# STEP 0:
+#
+# Get the source code:
+#
+if test ! -d "$boost_root" ; then
+ mkdir -p "$boost_root"
+ if test $? -ne 0 ; then
+ echo "creation of $boost_root directory failed."
+ exit 256
+ fi
+fi
+if test $cvs_update = yes ; then
+ echo fetching Boost:
+ echo "/1 :pserver:anonymous@cvs.sourceforge.net:2401/cvsroot/boost A" >> "$HOME/.cvspass"
+ cat "$HOME/.cvspass" | sort | uniq > "$HOME/.cvspass"
+ cd `dirname "$boost_root"`
+ if test -f boost/CVS/Root ; then
+ cvs -z3 -d `cat "$boost_dir/CVS/Root"` co -d "$boost_dir" boost
+ else
+ cvs -z3 -d :pserver:anonymous@cvs.sourceforge.net:2401/cvsroot/boost co -d "$boost_dir" boost
+ fi
+fi
+
+#
+# STEP 1:
+# rebuild bjam if required:
+#
+echo building bjam:
+cd "$boost_root/tools/build/v2/engine" && \
+LOCATE_TARGET=bin sh ./build.sh
+if test $? != 0 ; then
+ echo "bjam build failed."
+ exit 256
+fi
+
+#
+# STEP 2:
+# rebuild the regression test helper programs if required:
+#
+echo building regression test helper programs:
+cd "$boost_root/tools/regression/build" && \
+"$bjam" $toolset release
+if test $? != 0 ; then
+ echo "helper program build failed."
+ exit 256
+fi
+
+#
+# STEP 5:
+# repeat steps 3 and 4 for each additional toolset:
+#
+for tool in $test_tools ; do
+
+#
+# STEP 3:
+# run the regression tests:
+#
+echo running the $tool regression tests:
+cd "$boost_root/$test_dir"
+"$bjam" $tool --dump-tests 2>&1 | tee regress.log
+
+#
+# STEP 4:
+# post process the results:
+#
+echo processing the regression test results for $tool:
+cat regress.log | "$process_jam_log" --v2
+if test $? != 0 ; then
+ echo "Failed regression log post processing."
+ exit 256
+fi
+
+done
+
+#
+# STEP 6:
+# create the html table:
+#
+uname=`uname`
+echo generating html tables:
+"$compiler_status" --v2 --comment "$comment_path" "$boost_root" cs-$uname.html cs-$uname-links.html
+if test $? != 0 ; then
+ echo "Failed HTML result table generation."
+ exit 256
+fi
+
+echo "done!"
+
+
+
diff --git a/tools/regression/src/smoke.py b/tools/regression/src/smoke.py
new file mode 100755
index 0000000000..1b17cfaaee
--- /dev/null
+++ b/tools/regression/src/smoke.py
@@ -0,0 +1,197 @@
+# smoke test - every so many minutes, check svn revision, and if changed:
+# update working copy, run tests, upload results
+
+# Copyright Beman Dawes 2007
+
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# ---------------------------------------------------------------------------- #
+
+import os
+import sys
+import platform
+import time
+import ftplib
+
+# invoke the system command line processor
+def cmd(command):
+ print "command:", command
+ os.system(command)
+
+# update SVN working copy
+def update_working_copy(boost_path):
+ os.chdir(boost_path)
+ cmd("svn update")
+
+# get repository url
+def repository_url(path, results_path):
+ url = ""
+ svn_info_file = results_path + "/svn_info.xml"
+ command = "svn info --xml " + path + " >" + svn_info_file
+ cmd(command)
+ f = open( svn_info_file, 'r' )
+ svn_info = f.read()
+ f.close()
+ i = svn_info.find('//svn.boost.org')
+ if i >= 0:
+ url = svn_info[i:svn_info.find("</url>")]
+ return url
+
+# get revision number of a path, which may be a filesystem path or URL
+def revision(path, results_path, test_name):
+ rev = 0
+ svn_info_file = results_path + "/" + test_name + "-svn_info.xml"
+ command = "svn info --xml " + path + " >" + svn_info_file
+ cmd(command)
+ f = open( svn_info_file, 'r' )
+ svn_info = f.read()
+ f.close()
+ i = svn_info.find( 'revision=' )
+ if i >= 0:
+ i += 10
+ while svn_info[i] >= '0' and svn_info[i] <= '9':
+ rev = rev*10 + int(svn_info[i])
+ i += 1
+ return rev
+
+# run bjam in current directory
+def bjam(boost_path, args, output_path, test_name):
+
+ # bjam seems to need BOOST_BUILD_PATH
+ #os.environ["BOOST_BUILD_PATH"]=boost_path + "/tools/build/v2"
+
+ print "Begin bjam..."
+ command = "bjam --v2 --dump-tests -l180"
+ if args != "": command += " " + args
+ command += " >" + output_path + "/" + test_name +"-bjam.log 2>&1"
+ cmd(command)
+
+# run process_jam_log in current directory
+def process_jam_log(boost_path, output_path, test_name):
+ print "Begin log processing..."
+ command = "process_jam_log " + boost_path + " <" +\
+ output_path + "/" + test_name +"-bjam.log"
+ cmd(command)
+
+# run compiler_status in current directory
+def compiler_status(boost_path, output_path, test_name):
+ print "Begin compiler status html creation... "
+ command = "compiler_status --v2 --ignore-pass --no-warn --locate-root " + boost_path + " " +\
+ boost_path + " " + output_path + "/" + test_name + "-results.html " +\
+ output_path + "/" + test_name + "-details.html "
+ cmd(command)
+
+# upload results via ftp
+def upload_to_ftp(results_path, test_name, ftp_url, user, psw, debug_level):
+
+ # to minimize the time web pages are not available, upload with temporary
+ # names and then rename to the permanent names
+
+ i = 0 # dummy variable
+ os.chdir(results_path)
+
+ tmp_results = "temp-" + test_name + "-results.html"
+ results = test_name + "-results.html"
+ tmp_details = "temp-" + test_name + "-details.html"
+ details = test_name + "-details.html"
+
+ print "Uploading results via ftp..."
+ ftp = ftplib.FTP( ftp_url, user, psw )
+ ftp.set_debuglevel( debug_level )
+
+ # ftp.cwd( site_path )
+
+ try: ftp.delete(tmp_results)
+ except: ++i
+
+ f = open( results, 'rb' )
+ ftp.storbinary( 'STOR %s' % tmp_results, f )
+ f.close()
+
+ try: ftp.delete(tmp_details)
+ except: ++i
+
+ f = open( details, 'rb' )
+ ftp.storbinary( 'STOR %s' % tmp_details, f )
+ f.close()
+
+ try: ftp.delete(results)
+ except: ++i
+
+ try: ftp.delete(details)
+ except: ++i
+
+ ftp.rename(tmp_results, results)
+ ftp.rename(tmp_details, details)
+
+ ftp.dir()
+ ftp.quit()
+
+def commit_results(results_path, test_name, rev):
+ print "Commit results..."
+ cwd = os.getcwd()
+ os.chdir(results_path)
+ command = "svn commit --non-interactive -m "+'"'+str(rev)+'" '+test_name+"-results.html"
+ cmd(command)
+ os.chdir(cwd)
+
+
+# ---------------------------------------------------------------------------- #
+
+if len(sys.argv) < 7:
+ print "Invoke with: minutes boost-path test-name results-path ftp-url user psw [bjam-args]"
+ print " boost-path must be path for a boost svn working directory."
+ print " results-path must be path for a svn working directory where an"
+ print " svn commit test-name+'-results.html' is valid."
+ print "Warning: This program hangs or crashes on network failures."
+ exit()
+
+minutes = int(sys.argv[1])
+boost_path = sys.argv[2]
+test_name = sys.argv[3]
+results_path = sys.argv[4]
+ftp_url = sys.argv[5]
+user = sys.argv[6]
+psw = sys.argv[7]
+if len(sys.argv) > 8: bjam_args = sys.argv[8]
+else: bjam_args = ""
+
+os.chdir(boost_path) # convert possible relative path
+boost_path = os.getcwd() # to absolute path
+
+print "minutes is ", minutes
+print "boost_path is ", boost_path
+print "test_name is ", test_name
+print "results_path is ", results_path
+print "ftp_url is ", ftp_url
+print "user is ", user
+print "psw is ", psw
+print 'bjam args are "' + bjam_args + '"'
+
+url = repository_url(boost_path, results_path)
+print "respository url is ", url
+
+first = 1
+while 1:
+ working_rev = revision(boost_path, results_path, test_name)
+ repos_rev = revision("http:" + url, results_path, test_name)
+ print "Working copy revision: ", working_rev, " repository revision: ", repos_rev
+ if first or working_rev != repos_rev:
+ first = 0
+ start_time = time.time()
+ print
+ print "start at", time.strftime("%H:%M:%S", time.localtime())
+ update_working_copy(boost_path)
+ os.chdir(boost_path+"/status")
+ bjam(boost_path, bjam_args, results_path, test_name)
+ process_jam_log(boost_path, results_path, test_name)
+ compiler_status(boost_path, results_path, test_name)
+ upload_to_ftp(results_path, test_name, ftp_url, user, psw, 0)
+ commit_results(results_path, test_name,revision(boost_path, results_path, test_name))
+ elapsed_time = time.time() - start_time
+ print elapsed_time/60.0, "minutes elapsed time"
+ print
+
+ print "sleep ", minutes, "minutes..."
+ time.sleep(60 * minutes)
diff --git a/tools/regression/test/Jamfile.v2 b/tools/regression/test/Jamfile.v2
new file mode 100644
index 0000000000..43c715b2e0
--- /dev/null
+++ b/tools/regression/test/Jamfile.v2
@@ -0,0 +1,27 @@
+# Copyright Misha Bergal 2006
+#
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+test-suite testlib :
+ [ compile-fail compile-fail_fail.cpp ]
+ [ compile-fail compile-fail_pass.cpp ]
+ [ compile compile_fail.cpp ]
+ [ compile compile_pass.cpp ]
+ [ compile compile_warn.cpp ]
+# The link test .cpp files were apparently never committed to the repository,
+# and were lost.
+# [ link link_fail.cpp ]
+# [ link link_pass.cpp ]
+# [ link-fail link-fail_fail.cpp ]
+# [ link-fail link-fail_pass.cpp ]
+ [ run-fail run-fail_compile-fail.cpp ]
+ [ run-fail run-fail_fail-warn.cpp ]
+ [ run-fail run-fail_fail.cpp ]
+ [ run-fail run-fail_pass.cpp ]
+ [ run run_fail.cpp ]
+ [ run run_note.cpp ]
+ [ run run_pass.cpp ]
+ [ run run_warn-note.cpp ]
+ [ run run_warn.cpp ]
+ ;
diff --git a/tools/regression/test/compile-fail_fail.cpp b/tools/regression/test/compile-fail_fail.cpp
new file mode 100644
index 0000000000..76fc53b9d7
--- /dev/null
+++ b/tools/regression/test/compile-fail_fail.cpp
@@ -0,0 +1,10 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+int main() { return 0; }
+
diff --git a/tools/regression/test/compile-fail_pass.cpp b/tools/regression/test/compile-fail_pass.cpp
new file mode 100644
index 0000000000..cacb17d133
--- /dev/null
+++ b/tools/regression/test/compile-fail_pass.cpp
@@ -0,0 +1,9 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+#error example of a compile failure
diff --git a/tools/regression/test/compile_fail.cpp b/tools/regression/test/compile_fail.cpp
new file mode 100644
index 0000000000..cacb17d133
--- /dev/null
+++ b/tools/regression/test/compile_fail.cpp
@@ -0,0 +1,9 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+#error example of a compile failure
diff --git a/tools/regression/test/compile_pass.cpp b/tools/regression/test/compile_pass.cpp
new file mode 100644
index 0000000000..384b51fa4a
--- /dev/null
+++ b/tools/regression/test/compile_pass.cpp
@@ -0,0 +1,9 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+int main() { return 0; }
diff --git a/tools/regression/test/compile_warn.cpp b/tools/regression/test/compile_warn.cpp
new file mode 100644
index 0000000000..7895a229e7
--- /dev/null
+++ b/tools/regression/test/compile_warn.cpp
@@ -0,0 +1,18 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+// provoke one or more compiler warnings
+
+int main(int argc, char * argv[] )
+{
+ short s;
+ unsigned long ul;
+ s = s & ul; // warning from many compilers
+ if ( s == ul ) {} // warning from GCC
+ return 0;
+}
diff --git a/tools/regression/test/run-fail_compile-fail.cpp b/tools/regression/test/run-fail_compile-fail.cpp
new file mode 100644
index 0000000000..cacb17d133
--- /dev/null
+++ b/tools/regression/test/run-fail_compile-fail.cpp
@@ -0,0 +1,9 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+#error example of a compile failure
diff --git a/tools/regression/test/run-fail_fail-warn.cpp b/tools/regression/test/run-fail_fail-warn.cpp
new file mode 100644
index 0000000000..577d2bb890
--- /dev/null
+++ b/tools/regression/test/run-fail_fail-warn.cpp
@@ -0,0 +1,16 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+int main()
+{
+ short s;
+ unsigned long ul;
+ s = s & ul; // warning from many compilers
+ if ( s == ul ) {} // warning from GCC
+ return 0;
+}
diff --git a/tools/regression/test/run-fail_fail.cpp b/tools/regression/test/run-fail_fail.cpp
new file mode 100644
index 0000000000..865b8eb3dd
--- /dev/null
+++ b/tools/regression/test/run-fail_fail.cpp
@@ -0,0 +1,12 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+int main()
+{
+ return 0;
+}
diff --git a/tools/regression/test/run-fail_pass.cpp b/tools/regression/test/run-fail_pass.cpp
new file mode 100644
index 0000000000..3e3ab13973
--- /dev/null
+++ b/tools/regression/test/run-fail_pass.cpp
@@ -0,0 +1,15 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+#include <iostream>
+
+int main()
+{
+ std::cout << "example of output from a run-time failure\n";
+ return 1;
+}
diff --git a/tools/regression/test/run-fail_warn.cpp b/tools/regression/test/run-fail_warn.cpp
new file mode 100644
index 0000000000..8cc21a110a
--- /dev/null
+++ b/tools/regression/test/run-fail_warn.cpp
@@ -0,0 +1,20 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+#include <iostream>
+
+int main()
+{
+ short s;
+ unsigned long ul;
+ s = s & ul; // warning from many compilers
+ if ( s == ul ) {} // warning from GCC
+
+ std::cout << "example of output from a run-time failure\n";
+ return 1;
+}
diff --git a/tools/regression/test/run_compile-fail.cpp b/tools/regression/test/run_compile-fail.cpp
new file mode 100644
index 0000000000..cacb17d133
--- /dev/null
+++ b/tools/regression/test/run_compile-fail.cpp
@@ -0,0 +1,9 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+#error example of a compile failure
diff --git a/tools/regression/test/run_fail-note.cpp b/tools/regression/test/run_fail-note.cpp
new file mode 100644
index 0000000000..b514da0938
--- /dev/null
+++ b/tools/regression/test/run_fail-note.cpp
@@ -0,0 +1,17 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+#include <iostream>
+
+int main()
+{
+ std::cout << "example of output before a <note> line\n";
+ std::cout << "<note>\n";
+ std::cout << "example of output after a <note> line\n";
+ return 1;
+}
diff --git a/tools/regression/test/run_fail-warn.cpp b/tools/regression/test/run_fail-warn.cpp
new file mode 100644
index 0000000000..8cc21a110a
--- /dev/null
+++ b/tools/regression/test/run_fail-warn.cpp
@@ -0,0 +1,20 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+#include <iostream>
+
+int main()
+{
+ short s;
+ unsigned long ul;
+ s = s & ul; // warning from many compilers
+ if ( s == ul ) {} // warning from GCC
+
+ std::cout << "example of output from a run-time failure\n";
+ return 1;
+}
diff --git a/tools/regression/test/run_fail.cpp b/tools/regression/test/run_fail.cpp
new file mode 100644
index 0000000000..d6b8ffacf9
--- /dev/null
+++ b/tools/regression/test/run_fail.cpp
@@ -0,0 +1,14 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+#include <iostream>
+
+int main()
+{
+ return 1;
+}
diff --git a/tools/regression/test/run_note.cpp b/tools/regression/test/run_note.cpp
new file mode 100644
index 0000000000..2841618522
--- /dev/null
+++ b/tools/regression/test/run_note.cpp
@@ -0,0 +1,17 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+#include <iostream>
+
+int main()
+{
+ std::cout << "example of output before a <note> line\n";
+ std::cout << "<note>\n";
+ std::cout << "example of output after a <note> line\n";
+ return 0;
+}
diff --git a/tools/regression/test/run_pass.cpp b/tools/regression/test/run_pass.cpp
new file mode 100644
index 0000000000..865b8eb3dd
--- /dev/null
+++ b/tools/regression/test/run_pass.cpp
@@ -0,0 +1,12 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+int main()
+{
+ return 0;
+}
diff --git a/tools/regression/test/run_warn-note.cpp b/tools/regression/test/run_warn-note.cpp
new file mode 100644
index 0000000000..36e1c5faf3
--- /dev/null
+++ b/tools/regression/test/run_warn-note.cpp
@@ -0,0 +1,24 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+#include <iostream>
+
+int main()
+{
+ std::cout << "example of output before a <note> line\n";
+ std::cout << "<note>\n";
+ std::cout << "example of output after a <note> line\n";
+
+ // provoke a compiler warning to make sure <note> takes priority over
+ // a warning, but neither is lost from status reporting links HTML.
+ short s;
+ unsigned long ul;
+ s = s & ul; // warning from many compilers
+ if ( s == ul ) {} // warning from GCC
+ return 0;
+}
diff --git a/tools/regression/test/run_warn.cpp b/tools/regression/test/run_warn.cpp
new file mode 100644
index 0000000000..7895a229e7
--- /dev/null
+++ b/tools/regression/test/run_warn.cpp
@@ -0,0 +1,18 @@
+// (C) Copyright Beman Dawes 2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Test naming convention: the portion of the name before the tilde ("~")
+// identifies the bjam test type. The portion after the tilde
+// identifies the correct result to be reported by compiler_status.
+
+// provoke one or more compiler warnings
+
+int main(int argc, char * argv[] )
+{
+ short s;
+ unsigned long ul;
+ s = s & ul; // warning from many compilers
+ if ( s == ul ) {} // warning from GCC
+ return 0;
+}
diff --git a/tools/regression/test/test-boost-build/ignored_rc/ignored_rc.jam b/tools/regression/test/test-boost-build/ignored_rc/ignored_rc.jam
new file mode 100644
index 0000000000..61b1459292
--- /dev/null
+++ b/tools/regression/test/test-boost-build/ignored_rc/ignored_rc.jam
@@ -0,0 +1,11 @@
+rule failure
+ {
+ }
+
+actions failure
+ {
+ dir _
+ echo a
+ }
+
+failure f ;
diff --git a/tools/regression/test/test-boost-build/ignored_rc/recognized_rc.jam b/tools/regression/test/test-boost-build/ignored_rc/recognized_rc.jam
new file mode 100644
index 0000000000..6afbc25ed4
--- /dev/null
+++ b/tools/regression/test/test-boost-build/ignored_rc/recognized_rc.jam
@@ -0,0 +1,12 @@
+rule failure
+ {
+ }
+
+actions failure
+ {
+ dir _
+ if errorlevel 1 exit %errorlevel%
+ echo a
+ }
+
+failure f ;
diff --git a/tools/regression/test/test-boost-build/missing_dependencies/Jamfile.v2 b/tools/regression/test/test-boost-build/missing_dependencies/Jamfile.v2
new file mode 100644
index 0000000000..d9e5149e8c
--- /dev/null
+++ b/tools/regression/test/test-boost-build/missing_dependencies/Jamfile.v2
@@ -0,0 +1,9 @@
+project
+ : requirements
+ <library>/boost/filesystem//boost_filesystem
+ <define>BOOST_ALL_NO_LIB
+ ;
+
+ test-suite "missing_dependencies" :
+ [ run test.cpp lib//<link>static ]
+ ;
diff --git a/tools/regression/test/test-boost-build/missing_dependencies/lib/Jamfile.v2 b/tools/regression/test/test-boost-build/missing_dependencies/lib/Jamfile.v2
new file mode 100644
index 0000000000..410e7edc9b
--- /dev/null
+++ b/tools/regression/test/test-boost-build/missing_dependencies/lib/Jamfile.v2
@@ -0,0 +1,7 @@
+SOURCES =
+ lib ;
+
+lib lib
+ :
+ $(SOURCES).cpp
+ ;
diff --git a/tools/regression/test/test-boost-build/missing_dependencies/lib/lib.cpp b/tools/regression/test/test-boost-build/missing_dependencies/lib/lib.cpp
new file mode 100644
index 0000000000..09c7cfafd0
--- /dev/null
+++ b/tools/regression/test/test-boost-build/missing_dependencies/lib/lib.cpp
@@ -0,0 +1 @@
+#error
diff --git a/tools/regression/test/test-boost-build/missing_dependencies/test.cpp b/tools/regression/test/test-boost-build/missing_dependencies/test.cpp
new file mode 100644
index 0000000000..76e8197013
--- /dev/null
+++ b/tools/regression/test/test-boost-build/missing_dependencies/test.cpp
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tools/regression/test/test-cases/Huber2629/bjam.log b/tools/regression/test/test-cases/Huber2629/bjam.log
new file mode 100644
index 0000000000..ca1fe1b9f4
--- /dev/null
+++ b/tools/regression/test/test-cases/Huber2629/bjam.log
@@ -0,0 +1,36 @@
+boost-test(RUN) "statechart/DllTestNative" : "libs/statechart/test/TuTestMain.cpp"
+boost-test(RUN) "statechart/DllTestNormal" : "libs/statechart/test/TuTestMain.cpp"
+
+compile-c-c++ ..\..\..\bin.v2\libs\statechart\test\DllTestNormal.test\msvc-7.1\debug\threading-multi\TuTestMain.obj
+TuTestMain.cpp
+c:\Users\Misha\Stuff\boost\HEAD\boost\libs\statechart\test\TuTest.hpp(36) : warning C4275: non dll-interface class 'boost::statechart::event_base' used as base for dll-interface class 'boost::statechart::detail::rtti_policy::rtti_derived_type<MostDerived,Base>'
+ with
+ [
+ MostDerived=EvX,
+ Base=boost::statechart::event_base
+ ]
+ ..\..\..\boost\statechart\event_base.hpp(49) : see declaration of 'boost::statechart::event_base'
+compile-c-c++ ..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLibTuTest.obj
+TuTest.cpp
+c:\Users\Misha\Stuff\boost\HEAD\boost\libs\statechart\test\TuTest.hpp(36) : warning C4275: non dll-interface class 'boost::statechart::event_base' used as base for dll-interface class 'boost::statechart::detail::rtti_policy::rtti_derived_type<MostDerived,Base>'
+ with
+ [
+ MostDerived=EvX,
+ Base=boost::statechart::event_base
+ ]
+ ..\..\..\boost\statechart\event_base.hpp(49) : see declaration of 'boost::statechart::event_base'
+msvc.link.dll ..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll ..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.lib
+ Creating library ..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.lib and object ..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.exp
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" >nul
+link /NOLOGO /INCREMENTAL:NO /DLL /DEBUG /subsystem:console /out:"..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll" /IMPLIB:"..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.lib" @"..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll.rsp"
+ if %errorlevel% 1 exit %errorlevel%
+ if exist "..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll.manifest" (
+ mt -nologo -manifest "..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll.manifest" "-outputresource:..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll;2"
+ )
+
+...failed msvc.link.dll ..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll ..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.lib...
+...removing ..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll
+...removing ..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.lib
+...skipped <p..\..\..\bin.v2\libs\statechart\test\DllTestNormal.test\msvc-7.1\debug\threading-multi>DllTestNormal.exe for lack of <p..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi>DllTestNormalLib-vc71-mt-gd-1_35.lib...
+...skipped <p..\..\..\bin.v2\libs\statechart\test\DllTestNormal.test\msvc-7.1\debug\threading-multi>DllTestNormal.run for lack of <p..\..\..\bin.v2\libs\statechart\test\DllTestNormal.test\msvc-7.1\debug\threading-multi>DllTestNormal.exe...
diff --git a/tools/regression/test/test-cases/Huber2629/expected/results.xml b/tools/regression/test/test-cases/Huber2629/expected/results.xml
new file mode 100644
index 0000000000..44a32b04f5
--- /dev/null
+++ b/tools/regression/test/test-cases/Huber2629/expected/results.xml
@@ -0,0 +1,27 @@
+<test-log library="statechart" test-name="DllTestNormal" test-type="run" test-program="libs/statechart/test/TuTestMain.cpp" target-directory="bin.v2/libs/statechart/test/DllTestNormal.test/msvc-7.1/debug/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<lib result="fail" timestamp="">../../bin.v2/libs/statechart/test/msvc-7.1/debug/threading-multi</lib>
+</test-log>
+
+<test-log library="statechart" test-name="" test-type="" test-program="" target-directory="bin.v2/libs/statechart/test/msvc-7.1/debug/threading-multi" toolset="" show-run-output="true">
+<compile result="succeed" timestamp="">
+TuTest.cpp
+c:\Users\Misha\Stuff\boost\HEAD\boost\libs\statechart\test\TuTest.hpp(36) : warning C4275: non dll-interface class 'boost::statechart::event_base' used as base for dll-interface class 'boost::statechart::detail::rtti_policy::rtti_derived_type&lt;MostDerived,Base&gt;'
+ with
+ [
+ MostDerived=EvX,
+ Base=boost::statechart::event_base
+ ]
+ ..\..\..\boost\statechart\event_base.hpp(49) : see declaration of 'boost::statechart::event_base'
+</compile>
+<link result="fail" timestamp="">
+ Creating library ..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.lib and object ..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.exp
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" &gt;nul
+link /NOLOGO /INCREMENTAL:NO /DLL /DEBUG /subsystem:console /out:"..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll" /IMPLIB:"..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.lib" @"..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll.rsp"
+ if %errorlevel% 1 exit %errorlevel%
+ if exist "..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll.manifest" (
+ mt -nologo -manifest "..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll.manifest" "-outputresource:..\..\..\bin.v2\libs\statechart\test\msvc-7.1\debug\threading-multi\DllTestNormalLib-vc71-mt-gd-1_35.dll;2"
+ )
+
+</link>
+</test-log>
diff --git a/tools/regression/test/test-cases/general/bjam.log b/tools/regression/test/test-cases/general/bjam.log
new file mode 100644
index 0000000000..71013f7458
--- /dev/null
+++ b/tools/regression/test/test-cases/general/bjam.log
@@ -0,0 +1,325 @@
+locate-root "..\..\..\bin.v2"
+C:\Users\Misha\Stuff\boost\HEAD\boost\tools\regression\test>C:\Users\Misha\Stuff\boost\HEAD\bin\..\boost\tools\jam\src\bin.ntx86\bjam.exe --dump-tests --v2 msvc-7.1 "-sBOOST_BUILD_PATH=C:\Users\Misha\Stuff\boost\HEAD\bin\.." "-sBOOST_ROOT="C:\Users\Misha\Stuff\boost\HEAD\bin\..\boost"
+warning: Python location is not configured
+warning: the Boost.Python library won't be built
+Building Boost.Regex with the optional Unicode/ICU support disabled.
+Please refer to the Boost.Regex documentation for more information
+(and if you don't know what ICU is then you probably don't need it).
+boost-test(RUN) "testlib/run~warn" : "tools/regression/test/run~warn.cpp"
+boost-test(RUN) "testlib/run~warn-note" : "tools/regression/test/run~warn-note.cpp"
+boost-test(RUN) "testlib/run~pass" : "tools/regression/test/run~pass.cpp"
+boost-test(RUN) "testlib/run~note" : "tools/regression/test/run~note.cpp"
+boost-test(RUN) "testlib/run~fail" : "tools/regression/test/run~fail.cpp"
+boost-test(RUN_FAIL) "testlib/run-fail~pass" : "tools/regression/test/run-fail~pass.cpp"
+boost-test(RUN_FAIL) "testlib/run-fail~fail" : "tools/regression/test/run-fail~fail.cpp"
+boost-test(RUN_FAIL) "testlib/run-fail~fail-warn" : "tools/regression/test/run-fail~fail-warn.cpp"
+boost-test(RUN_FAIL) "testlib/run-fail~compile-fail" : "tools/regression/test/run-fail~compile-fail.cpp"
+boost-test(LINK_FAIL) "testlib/link-fail~pass" : "tools/regression/test/link-fail~pass.cpp"
+boost-test(LINK_FAIL) "testlib/link-fail~fail" : "tools/regression/test/link-fail~fail.cpp"
+boost-test(LINK) "testlib/link~pass" : "tools/regression/test/link~pass.cpp"
+boost-test(LINK) "testlib/link~fail" : "tools/regression/test/link~fail.cpp"
+boost-test(COMPILE) "testlib/compile~warn" : "tools/regression/test/compile~warn.cpp"
+boost-test(COMPILE) "testlib/compile~pass" : "tools/regression/test/compile~pass.cpp"
+boost-test(COMPILE) "testlib/compile~fail" : "tools/regression/test/compile~fail.cpp"
+boost-test(COMPILE_FAIL) "testlib/compile-fail~pass" : "tools/regression/test/compile-fail~pass.cpp"
+boost-test(COMPILE_FAIL) "testlib/compile-fail~fail" : "tools/regression/test/compile-fail~fail.cpp"
+...found 210 targets...
+...updating 157 targets...
+MkDir1 ..\..\..\bin.v2\tools\regression\test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile-fail~fail.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile-fail~fail.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile-fail~fail.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile-fail~fail.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile-fail~fail.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\compile-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\compile-fail~fail.obj
+compile-fail~fail.cpp
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" >nul
+cl /Zm800 -nologo @"..\..\..\bin.v2\tools\regression\test\compile-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\compile-fail~fail.obj.rsp"
+
+...failed compile-c-c++ ..\..\..\bin.v2\tools\regression\test\compile-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\compile-fail~fail.obj...
+...removing ..\..\..\bin.v2\tools\regression\test\compile-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\compile-fail~fail.obj
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile-fail~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile-fail~pass.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile-fail~pass.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile-fail~pass.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile-fail~pass.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\compile-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\compile-fail~pass.obj
+compile-fail~pass.cpp
+compile-fail~pass.cpp(9) : fatal error C1189: #error : example of a compile failure
+(failed-as-expected) ..\..\..\bin.v2\tools\regression\test\compile-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\compile-fail~pass.obj
+**passed** ..\..\..\bin.v2\tools\regression\test\compile-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\compile-fail~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~fail.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~fail.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~fail.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~fail.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~fail.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\compile~fail.test\msvc-7.1\debug\link-static\threading-multi\compile~fail.obj
+compile~fail.cpp
+compile~fail.cpp(9) : fatal error C1189: #error : example of a compile failure
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" >nul
+cl /Zm800 -nologo @"..\..\..\bin.v2\tools\regression\test\compile~fail.test\msvc-7.1\debug\link-static\threading-multi\compile~fail.obj.rsp"
+
+...failed compile-c-c++ ..\..\..\bin.v2\tools\regression\test\compile~fail.test\msvc-7.1\debug\link-static\threading-multi\compile~fail.obj...
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~pass.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~pass.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~pass.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~pass.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\compile~pass.test\msvc-7.1\debug\link-static\threading-multi\compile~pass.obj
+compile~pass.cpp
+**passed** ..\..\..\bin.v2\tools\regression\test\compile~pass.test\msvc-7.1\debug\link-static\threading-multi\compile~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~warn.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~warn.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~warn.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~warn.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\compile~warn.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\compile~warn.test\msvc-7.1\debug\link-static\threading-multi\compile~warn.obj
+compile~warn.cpp
+compile~warn.cpp(15) : warning C4244: '=' : conversion from 'unsigned long' to 'short', possible loss of data
+c:\users\misha\stuff\boost\head\boost\tools\regression\test\compile~warn.cpp(15) : warning C4700: local variable 'ul' used without having been initialized
+**passed** ..\..\..\bin.v2\tools\regression\test\compile~warn.test\msvc-7.1\debug\link-static\threading-multi\compile~warn.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link~fail.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.obj
+link~fail.cpp
+msvc.link ..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe
+link~fail.obj : error LNK2019: unresolved external symbol "int __cdecl f(void)" (?f@@YAHXZ) referenced in function _main
+..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe : fatal error LNK1120: 1 unresolved externals
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" >nul
+link /NOLOGO /INCREMENTAL:NO /DEBUG /subsystem:console /out:"..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe" @"..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe.rsp"
+ if errorlevel 1 exit %errorlevel%
+ if exist "..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe.manifest" (
+ mt -nologo -manifest "..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe.manifest" "-outputresource:..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe;1"
+ )
+
+...failed msvc.link ..\..\..\bin.v2\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe...
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link~pass.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link~pass.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link~pass.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link~pass.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\link~pass.test\msvc-7.1\debug\link-static\threading-multi\link~pass.obj
+link~pass.cpp
+msvc.link ..\..\..\bin.v2\tools\regression\test\link~pass.test\msvc-7.1\debug\link-static\threading-multi\link~pass.exe
+**passed** ..\..\..\bin.v2\tools\regression\test\link~pass.test\msvc-7.1\debug\link-static\threading-multi\link~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link-fail~fail.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.obj
+link-fail~fail.cpp
+msvc.link ..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" >nul
+link /NOLOGO /INCREMENTAL:NO /DEBUG /subsystem:console /out:"..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe" @"..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe.rsp"
+ if errorlevel 1 exit %errorlevel%
+ if exist "..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe.manifest" (
+ mt -nologo -manifest "..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe.manifest" "-outputresource:..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe;1"
+ )
+
+...failed msvc.link ..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe...
+...removing ..\..\..\bin.v2\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link-fail~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link-fail~pass.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link-fail~pass.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link-fail~pass.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\link-fail~pass.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\link-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\link-fail~pass.obj
+link-fail~pass.cpp
+msvc.link ..\..\..\bin.v2\tools\regression\test\link-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\link-fail~pass.exe
+link-fail~pass.obj : error LNK2019: unresolved external symbol "int __cdecl f(void)" (?f@@YAHXZ) referenced in function _main
+..\..\..\bin.v2\tools\regression\test\link-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\link-fail~pass.exe : fatal error LNK1120: 1 unresolved externals
+(failed-as-expected) ..\..\..\bin.v2\tools\regression\test\link-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\link-fail~pass.exe
+**passed** ..\..\..\bin.v2\tools\regression\test\link-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\link-fail~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~compile-fail.obj
+run-fail~compile-fail.cpp
+run-fail~compile-fail.cpp(9) : fatal error C1189: #error : example of a compile failure
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" >nul
+cl /Zm800 -nologo @"..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~compile-fail.obj.rsp"
+
+...failed compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~compile-fail.obj...
+...skipped <p..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test\msvc-7.1\debug\link-static\threading-multi>run-fail~compile-fail.exe for lack of <p..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test\msvc-7.1\debug\link-static\threading-multi>run-fail~compile-fail.obj...
+...skipped <p..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test\msvc-7.1\debug\link-static\threading-multi>run-fail~compile-fail.run for lack of <p..\..\..\bin.v2\tools\regression\test\run-fail~compile-fail.test\msvc-7.1\debug\link-static\threading-multi>run-fail~compile-fail.exe...
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.obj
+run-fail~fail-warn.cpp
+run-fail~fail-warn.cpp(13) : warning C4244: '=' : conversion from 'unsigned long' to 'short', possible loss of data
+c:\users\misha\stuff\boost\head\boost\tools\regression\test\run-fail~fail-warn.cpp(13) : warning C4700: local variable 'ul' used without having been initialized
+msvc.link ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.exe
+testing.capture-output ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.run
+ 1 file(s) copied.
+
+
+ ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.exe > ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.output 2>&1
+ set status=%ERRORLEVEL%
+ echo. >> ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.output
+ echo EXIT STATUS: %status% >> ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.output
+ if %status% EQU 0 (
+ copy ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.output ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.run
+ )
+ set verbose=0
+ if %status% NEQ 0 (
+ set verbose=1
+ )
+ if %verbose% EQU 1 (
+ echo ====== BEGIN OUTPUT ======
+ type ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.output
+ echo ====== END OUTPUT ======
+ )
+ exit %status%
+
+...failed testing.capture-output ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.run...
+...removing ..\..\..\bin.v2\tools\regression\test\run-fail~fail-warn.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail-warn.run
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.obj
+run-fail~fail.cpp
+msvc.link ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.exe
+testing.capture-output ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.run
+ 1 file(s) copied.
+
+
+ ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.exe > ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.output 2>&1
+ set status=%ERRORLEVEL%
+ echo. >> ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.output
+ echo EXIT STATUS: %status% >> ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.output
+ if %status% EQU 0 (
+ copy ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.output ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.run
+ )
+ set verbose=0
+ if %status% NEQ 0 (
+ set verbose=1
+ )
+ if %verbose% EQU 1 (
+ echo ====== BEGIN OUTPUT ======
+ type ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.output
+ echo ====== END OUTPUT ======
+ )
+ exit %status%
+
+...failed testing.capture-output ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.run...
+...removing ..\..\..\bin.v2\tools\regression\test\run-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~fail.run
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~pass.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~pass.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~pass.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run-fail~pass.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\run-fail~pass.obj
+run-fail~pass.cpp
+msvc.link ..\..\..\bin.v2\tools\regression\test\run-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\run-fail~pass.exe
+testing.capture-output ..\..\..\bin.v2\tools\regression\test\run-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\run-fail~pass.run
+====== BEGIN OUTPUT ======
+example of output from a run-time failure
+
+EXIT STATUS: 1
+====== END OUTPUT ======
+
+ del /f /q "..\..\..\bin.v2\tools\regression\test\run-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\run-fail~pass.exe"
+
+...failed RmTemps ..\..\..\bin.v2\tools\regression\test\run-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\run-fail~pass.run...
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~fail.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug
+...on 100th target...
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi\run~fail.obj
+run~fail.cpp
+msvc.link ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi\run~fail.exe
+testing.capture-output ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi\run~fail.run
+====== BEGIN OUTPUT ======
+
+EXIT STATUS: 1
+====== END OUTPUT ======
+
+
+ ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi\run~fail.exe > ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi\run~fail.output 2>&1
+ set status=%ERRORLEVEL%
+ echo. >> ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi\run~fail.output
+ echo EXIT STATUS: %status% >> ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi\run~fail.output
+ if %status% EQU 0 (
+ copy ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi\run~fail.output ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi\run~fail.run
+ )
+ set verbose=0
+ if %status% NEQ 0 (
+ set verbose=1
+ )
+ if %verbose% EQU 1 (
+ echo ====== BEGIN OUTPUT ======
+ type ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi\run~fail.output
+ echo ====== END OUTPUT ======
+ )
+ exit %status%
+
+...failed testing.capture-output ..\..\..\bin.v2\tools\regression\test\run~fail.test\msvc-7.1\debug\link-static\threading-multi\run~fail.run...
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~note.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~note.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~note.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~note.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~note.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run~note.test\msvc-7.1\debug\link-static\threading-multi\run~note.obj
+run~note.cpp
+msvc.link ..\..\..\bin.v2\tools\regression\test\run~note.test\msvc-7.1\debug\link-static\threading-multi\run~note.exe
+testing.capture-output ..\..\..\bin.v2\tools\regression\test\run~note.test\msvc-7.1\debug\link-static\threading-multi\run~note.run
+ 1 file(s) copied.
+**passed** ..\..\..\bin.v2\tools\regression\test\run~note.test\msvc-7.1\debug\link-static\threading-multi\run~note.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.obj
+run~pass.cpp
+msvc.link ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.exe
+testing.capture-output ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.run
+ 1 file(s) copied.
+**passed** ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~warn-note.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~warn-note.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~warn-note.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~warn-note.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~warn-note.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run~warn-note.test\msvc-7.1\debug\link-static\threading-multi\run~warn-note.obj
+run~warn-note.cpp
+run~warn-note.cpp(21) : warning C4244: '=' : conversion from 'unsigned long' to 'short', possible loss of data
+c:\users\misha\stuff\boost\head\boost\tools\regression\test\run~warn-note.cpp(21) : warning C4700: local variable 'ul' used without having been initialized
+msvc.link ..\..\..\bin.v2\tools\regression\test\run~warn-note.test\msvc-7.1\debug\link-static\threading-multi\run~warn-note.exe
+testing.capture-output ..\..\..\bin.v2\tools\regression\test\run~warn-note.test\msvc-7.1\debug\link-static\threading-multi\run~warn-note.run
+ 1 file(s) copied.
+**passed** ..\..\..\bin.v2\tools\regression\test\run~warn-note.test\msvc-7.1\debug\link-static\threading-multi\run~warn-note.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~warn.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~warn.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~warn.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~warn.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~warn.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run~warn.test\msvc-7.1\debug\link-static\threading-multi\run~warn.obj
+run~warn.cpp
+run~warn.cpp(15) : warning C4244: '=' : conversion from 'unsigned long' to 'short', possible loss of data
+c:\users\misha\stuff\boost\head\boost\tools\regression\test\run~warn.cpp(15) : warning C4700: local variable 'ul' used without having been initialized
+msvc.link ..\..\..\bin.v2\tools\regression\test\run~warn.test\msvc-7.1\debug\link-static\threading-multi\run~warn.exe
+testing.capture-output ..\..\..\bin.v2\tools\regression\test\run~warn.test\msvc-7.1\debug\link-static\threading-multi\run~warn.run
+ 1 file(s) copied.
+**passed** ..\..\..\bin.v2\tools\regression\test\run~warn.test\msvc-7.1\debug\link-static\threading-multi\run~warn.test
+...failed updating 9 targets...
+...skipped 17 targets...
+...updated 131 targets...
diff --git a/tools/regression/test/test-cases/general/expected/results.xml b/tools/regression/test/test-cases/general/expected/results.xml
new file mode 100644
index 0000000000..13224e0113
--- /dev/null
+++ b/tools/regression/test/test-cases/general/expected/results.xml
@@ -0,0 +1,167 @@
+<test-log library="" test-name="compile-fail~fail" test-type="" test-program="" target-directory="tools/regression/test/compile-fail~fail.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="fail" timestamp="xxx">
+compile-fail~fail.cpp
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" &gt;nul
+cl /Zm800 -nologo @"C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\compile-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\compile-fail~fail.obj.rsp"
+
+</compile>
+</test-log>
+<test-log library="" test-name="compile-fail~pass" test-type="" test-program="" target-directory="tools/regression/test/compile-fail~pass.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+compile-fail~pass.cpp
+compile-fail~pass.cpp(9) : fatal error C1189: #error : example of a compile failure
+(failed-as-expected) C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\compile-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\compile-fail~pass.obj
+</compile>
+</test-log>
+<test-log library="" test-name="compile~fail" test-type="" test-program="" target-directory="tools/regression/test/compile~fail.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="fail" timestamp="xxx">
+compile~fail.cpp
+compile~fail.cpp(9) : fatal error C1189: #error : example of a compile failure
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" &gt;nul
+cl /Zm800 -nologo @"C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\compile~fail.test\msvc-7.1\debug\link-static\threading-multi\compile~fail.obj.rsp"
+
+</compile>
+</test-log>
+<test-log library="" test-name="compile~pass" test-type="" test-program="" target-directory="tools/regression/test/compile~pass.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+compile~pass.cpp
+</compile>
+</test-log>
+<test-log library="" test-name="compile~warn" test-type="" test-program="" target-directory="tools/regression/test/compile~warn.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+compile~warn.cpp
+compile~warn.cpp(15) : warning C4244: '=' : conversion from 'unsigned long' to 'short', possible loss of data
+c:\users\misha\stuff\boost\head\boost\tools\regression\test\compile~warn.cpp(15) : warning C4700: local variable 'ul' used without having been initialized
+</compile>
+</test-log>
+<test-log library="" test-name="link-fail~fail" test-type="" test-program="" target-directory="tools/regression/test/link-fail~fail.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+link-fail~fail.cpp
+</compile>
+<link result="fail" timestamp="xxx">
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" &gt;nul
+link /NOLOGO /INCREMENTAL:NO /DEBUG /subsystem:console /out:"C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe" @"C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe.rsp"
+ if errorlevel 1 exit %errorlevel%
+ if exist "C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe.manifest" (
+ mt -nologo -manifest "C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe.manifest" "-outputresource:C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link-fail~fail.test\msvc-7.1\debug\link-static\threading-multi\link-fail~fail.exe;1"
+ )
+
+</link>
+</test-log>
+<test-log library="" test-name="link-fail~pass" test-type="" test-program="" target-directory="tools/regression/test/link-fail~pass.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+link-fail~pass.cpp
+</compile>
+<link result="succeed" timestamp="xxx">
+link-fail~pass.obj : error LNK2019: unresolved external symbol "int __cdecl f(void)" (?f@@YAHXZ) referenced in function _main
+C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\link-fail~pass.exe : fatal error LNK1120: 1 unresolved externals
+(failed-as-expected) C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link-fail~pass.test\msvc-7.1\debug\link-static\threading-multi\link-fail~pass.exe
+</link>
+</test-log>
+<test-log library="" test-name="link~fail" test-type="" test-program="" target-directory="tools/regression/test/link~fail.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+link~fail.cpp
+</compile>
+<link result="fail" timestamp="xxx">
+link~fail.obj : error LNK2019: unresolved external symbol "int __cdecl f(void)" (?f@@YAHXZ) referenced in function _main
+C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe : fatal error LNK1120: 1 unresolved externals
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" &gt;nul
+link /NOLOGO /INCREMENTAL:NO /DEBUG /subsystem:console /out:"C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe" @"C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe.rsp"
+ if errorlevel 1 exit %errorlevel%
+ if exist "C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe.manifest" (
+ mt -nologo -manifest "C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe.manifest" "-outputresource:C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\link~fail.test\msvc-7.1\debug\link-static\threading-multi\link~fail.exe;1"
+ )
+
+</link>
+</test-log>
+<test-log library="" test-name="link~pass" test-type="" test-program="" target-directory="tools/regression/test/link~pass.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+link~pass.cpp
+</compile>
+<link result="succeed" timestamp="xxx">
+</link>
+</test-log>
+<test-log library="" test-name="run-fail~compile-fail" test-type="" test-program="" target-directory="tools/regression/test/run-fail~compile-fail.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="fail" timestamp="xxx">
+run-fail~compile-fail.cpp
+run-fail~compile-fail.cpp(9) : fatal error C1189: #error : example of a compile failure
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" &gt;nul
+cl /Zm800 -nologo @"C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\general\actual\tools\regression\test\run-fail~compile-fail.test\msvc-7.1\debug\link-static\threading-multi\run-fail~compile-fail.obj.rsp"
+
+</compile>
+</test-log>
+<test-log library="" test-name="run-fail~fail-warn" test-type="" test-program="" target-directory="tools/regression/test/run-fail~fail-warn.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+run-fail~fail-warn.cpp
+run-fail~fail-warn.cpp(13) : warning C4244: '=' : conversion from 'unsigned long' to 'short', possible loss of data
+c:\users\misha\stuff\boost\head\boost\tools\regression\test\run-fail~fail-warn.cpp(13) : warning C4700: local variable 'ul' used without having been initialized
+</compile>
+<link result="succeed" timestamp="xxx"></link>
+<run result="fail" timestamp="xxx">
+</run>
+</test-log>
+<test-log library="" test-name="run-fail~fail" test-type="" test-program="" target-directory="tools/regression/test/run-fail~fail.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+run-fail~fail.cpp
+</compile>
+<link result="succeed" timestamp="xxx"></link>
+<run result="fail" timestamp="xxx">
+</run>
+</test-log>
+<test-log library="" test-name="run-fail~pass" test-type="" test-program="" target-directory="tools/regression/test/run-fail~pass.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+run-fail~pass.cpp
+</compile>
+<link result="succeed" timestamp="xxx"></link>
+<run result="succeed" timestamp="xxx">
+</run>
+</test-log>
+<test-log library="" test-name="run~fail" test-type="" test-program="" target-directory="tools/regression/test/run~fail.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+run~fail.cpp
+</compile>
+<link result="succeed" timestamp="xxx"></link>
+<run result="fail" timestamp="xxx">
+</run>
+</test-log>
+<test-log library="" test-name="run~note" test-type="" test-program="" target-directory="tools/regression/test/run~note.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+run~note.cpp
+</compile>
+<link result="succeed" timestamp="xxx"></link>
+<run result="succeed" timestamp="xxx">
+</run>
+</test-log>
+<test-log library="" test-name="run~pass" test-type="" test-program="" target-directory="tools/regression/test/run~pass.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+run~pass.cpp
+</compile>
+<link result="succeed" timestamp="xxx"></link>
+<run result="succeed" timestamp="xxx">
+</run>
+</test-log>
+<test-log library="" test-name="run~warn-note" test-type="" test-program="" target-directory="tools/regression/test/run~warn-note.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+run~warn-note.cpp
+run~warn-note.cpp(21) : warning C4244: '=' : conversion from 'unsigned long' to 'short', possible loss of data
+c:\users\misha\stuff\boost\head\boost\tools\regression\test\run~warn-note.cpp(21) : warning C4700: local variable 'ul' used without having been initialized
+</compile>
+<link result="succeed" timestamp="xxx"></link>
+<run result="succeed" timestamp="xxx">
+</run>
+</test-log>
+<test-log library="" test-name="run~warn" test-type="" test-program="" target-directory="tools/regression/test/run~warn.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="succeed" timestamp="xxx">
+run~warn.cpp
+run~warn.cpp(15) : warning C4244: '=' : conversion from 'unsigned long' to 'short', possible loss of data
+c:\users\misha\stuff\boost\head\boost\tools\regression\test\run~warn.cpp(15) : warning C4700: local variable 'ul' used without having been initialized
+</compile>
+<link result="succeed" timestamp="xxx"></link>
+<run result="succeed" timestamp="xxx">
+</run>
+</test-log>
diff --git a/tools/regression/test/test-cases/incremental/bjam.log b/tools/regression/test/test-cases/incremental/bjam.log
new file mode 100644
index 0000000000..65db0844c2
--- /dev/null
+++ b/tools/regression/test/test-cases/incremental/bjam.log
@@ -0,0 +1,33 @@
+locate-root "..\..\..\bin.v2"
+C:\Users\Misha\Stuff\boost\HEAD\boost\tools\regression\test>C:\Users\Misha\Stuff\boost\HEAD\bin\..\boost\tools\jam\src\bin.ntx86\bjam.exe --dump-tests --v2 msvc-7.1 "-sBOOST_BUILD_PATH=C:\Users\Misha\Stuff\boost\HEAD\bin\.." "-sBOOST_ROOT="C:\Users\Misha\Stuff\boost\HEAD\bin\..\boost"
+
+boost-test(RUN) "testlib/run~pass" : "tools/regression/test/run~pass.cpp"
+boost-test(RUN) "testlib/run~pass" : "tools/regression/test/run~pass2s.cpp"
+
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.obj
+run~pass.cpp
+msvc.link ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.exe
+testing.capture-output ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.run
+ 1 file(s) copied.
+**passed** ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.test
+
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass2.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.obj
+run~pass2.cpp
+msvc.link ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.exe
+testing.capture-output ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.run
+ 1 file(s) copied.
+**passed** ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.test
+
+...failed updating 9 targets...
+...skipped 17 targets...
+...updated 131 targets...
diff --git a/tools/regression/test/test-cases/incremental/bjam.log.1 b/tools/regression/test/test-cases/incremental/bjam.log.1
new file mode 100644
index 0000000000..967ed9eb23
--- /dev/null
+++ b/tools/regression/test/test-cases/incremental/bjam.log.1
@@ -0,0 +1,38 @@
+locate-root "..\..\..\bin.v2"
+C:\Users\Misha\Stuff\boost\HEAD\boost\tools\regression\test>C:\Users\Misha\Stuff\boost\HEAD\bin\..\boost\tools\jam\src\bin.ntx86\bjam.exe --dump-tests --v2 msvc-7.1 "-sBOOST_BUILD_PATH=C:\Users\Misha\Stuff\boost\HEAD\bin\.." "-sBOOST_ROOT="C:\Users\Misha\Stuff\boost\HEAD\bin\..\boost"
+
+boost-test(RUN) "testlib/run~pass" : "tools/regression/test/run~pass.cpp"
+
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.obj
+run~pass.cpp
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" >nul
+cl /Zm800 -nologo @"..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.obj.rsp"
+
+...failed compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.obj...
+
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass2.test
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static
+MkDir1 ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi
+compile-c-c++ ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.obj
+run~pass2.cpp
+
+msvc.link ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.exe
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" >nul
+link /NOLOGO /INCREMENTAL:NO /DEBUG /subsystem:console /out:"..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.exe" @"..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.exe.rsp"
+ if errorlevel 1 exit %errorlevel%
+ if exist "..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.exe.manifest" (
+ mt -nologo -manifest "..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.exe.manifest" "-outputresource:..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.exe;1"
+ )
+
+...failed msvc.link ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.exe...
+...removing ..\..\..\bin.v2\tools\regression\test\run~pass2.test\msvc-7.1\debug\link-static\threading-multi\run~pass2.exe
+
+
+...failed updating 9 targets...
+...skipped 17 targets...
+...updated 131 targets...
diff --git a/tools/regression/test/test-cases/incremental/expected/results.xml b/tools/regression/test/test-cases/incremental/expected/results.xml
new file mode 100644
index 0000000000..0580bd588f
--- /dev/null
+++ b/tools/regression/test/test-cases/incremental/expected/results.xml
@@ -0,0 +1,9 @@
+<test-log library="" test-name="run~pass" test-type="" test-program="" target-directory="tools/regression/test/run~pass.test/msvc-7.1/debug/link-static/threading-multi" toolset="msvc-7.1" show-run-output="false">
+<compile result="fail" timestamp="xxx">
+run~pass.cpp
+
+ call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat" &gt;nul
+cl /Zm800 -nologo @"C:\users\Misha\Stuff\boost\boost\tools\regression\test\test-cases\incremental\actual\tools\regression\test\run~pass.test\msvc-7.1\debug\link-static\threading-multi\run~pass.obj.rsp"
+
+</compile>
+</test-log>
diff --git a/tools/regression/test/test.bat b/tools/regression/test/test.bat
new file mode 100644
index 0000000000..ce32fb727f
--- /dev/null
+++ b/tools/regression/test/test.bat
@@ -0,0 +1,15 @@
+rem Copyright Beman Dawes 2005
+
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+set TEST_LOCATE_ROOT=%TEMP%
+
+echo Begin test processing...
+bjam --dump-tests "-sALL_LOCATE_TARGET=%TEST_LOCATE_ROOT%" %* >bjam.log 2>&1
+echo Begin log processing...
+process_jam_log %TEST_LOCATE_ROOT% <bjam.log
+start bjam.log
+echo Begin compiler status processing...
+compiler_status --locate-root %TEST_LOCATE_ROOT% %BOOST_ROOT% test_status.html test_links.html
+start test_status.html
diff --git a/tools/regression/test/test.py b/tools/regression/test/test.py
new file mode 100644
index 0000000000..5a627ea2b5
--- /dev/null
+++ b/tools/regression/test/test.py
@@ -0,0 +1,181 @@
+# Copyright (c) MetaCommunications, Inc. 2003-2005
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import difflib
+import os
+import re
+import shutil
+import string
+import sys
+
+
+
+def scan_for_test_cases():
+ return [ os.path.join( "test-cases", x ) for x in os.listdir( "test-cases" ) if x != "CVS" ]
+
+def clean_dir( dir ):
+ if os.path.exists( dir ):
+ shutil.rmtree( dir )
+ os.makedirs( dir )
+
+def system( commands ):
+ if sys.platform == 'win32':
+ f = open( 'tmp.cmd', 'w' )
+ f.write( string.join( commands, '\n' ) )
+ f.close()
+ rc = os.system( 'tmp.cmd' )
+ os.unlink( 'tmp.cmd' )
+ return rc
+ else:
+ rc = os.system( '&&'.join( commands ) )
+ return rc
+
+def checked_system( commands, valid_return_codes = [ 0 ] ):
+ rc = system( commands )
+ if rc not in [ 0 ] + valid_return_codes:
+ raise Exception( 'Command sequence "%s" failed with return code %d' % ( commands, rc ) )
+ return rc
+
+def list_recursively( dir ):
+ r = []
+ for root, dirs, files in os.walk( dir, topdown=False ):
+ root = root[ len( dir ) + 1 : ]
+ r.extend( [ os.path.join( root, x ) for x in dirs ] )
+ r.extend( [ os.path.join( root, x ) for x in files ] )
+
+ return r
+
+def find_process_jam_log():
+ root = "../../../"
+
+ for root, dirs, files in os.walk( os.path.join( root, "bin.v2" ), topdown=False ):
+ if "process_jam_log.exe" in files:
+ return os.path.abspath( os.path.normpath( os.path.join( root, "process_jam_log.exe" ) ) )
+ if "process_jam_log" in files:
+ return os.path.abspath( os.path.normpath( os.path.join( root, "process_jam_log" ) ) )
+ return None
+
+def process_jam_log( executable, file, locate_root, results_dir ):
+ args = []
+ args.append( executable )
+ # args.append( '--echo' )
+ args.append( '--create-directories' )
+ args.append( '--v2' )
+ args.append( locate_root )
+ args.append( '<' )
+ args.append( file )
+
+ cmd = " ".join( args )
+ print "Running process_jam_log (%s)" % cmd
+ checked_system( [ cmd ] )
+
+
+def read_file( file_path ):
+ f = open( file_path )
+ try:
+ return f.read()
+ finally:
+ f.close()
+
+def remove_timestamps( log_lines ):
+ return [ re.sub( "timestamp=\"[^\"]+\"", "timestamp=\"\"", x ) for x in log_lines ]
+
+def determine_locate_root( bjam_log ):
+ locate_root = None
+ f = open( 'bjam.log' )
+ try:
+ locate_root_re = re.compile( r'locate-root\s+"(.*)"' )
+ for l in f.readlines():
+ m = locate_root_re.match( l )
+ if m:
+ locate_root = m.group(1)
+ break
+ finally:
+ f.close()
+ return locate_root
+
+def read_file( path ):
+ f = open( path )
+ try:
+ return f.read()
+ finally:
+ f.close()
+
+def read_file_lines( path ):
+ f = open( path )
+ try:
+ return f.readlines()
+ finally:
+ f.close()
+
+def write_file( path, content ):
+ f = open( path, 'w' )
+ try:
+ return f.write( content )
+ finally:
+ f.close()
+
+def write_file_lines( path, content ):
+ f = open( path, 'w' )
+ try:
+ return f.writelines( content )
+ finally:
+ f.close()
+
+
+def run_test_cases( test_cases ):
+ process_jam_log_executable = find_process_jam_log()
+ print 'Found process_jam_log: %s' % process_jam_log_executable
+ initial_dir = os.getcwd()
+ for test_case in test_cases:
+ os.chdir( initial_dir )
+ print 'Running test case "%s"' % test_case
+ os.chdir( test_case )
+ if os.path.exists( "expected" ):
+ locate_root = determine_locate_root( 'bjam.log' )
+ print 'locate_root: %s' % locate_root
+
+ actual_results_dir = os.path.join( test_case, "actual" )
+ clean_dir( "actual" )
+ os.chdir( "actual" )
+ root = os.getcwd()
+ i = 0
+ while 1:
+ if i == 0:
+ bjam_log_file = 'bjam.log'
+ else:
+ bjam_log_file = 'bjam.log.%0d' % i
+ i += 1
+ print 'Looking for %s' % bjam_log_file
+ if not os.path.exists( os.path.join( '..', bjam_log_file ) ):
+ print ' does not exists'
+ break
+ print ' found'
+ write_file_lines(bjam_log_file.replace( 'bjam', 'bjam_' ),
+ [ x.replace( locate_root, root ) for x in read_file_lines( os.path.join( '..', bjam_log_file ) ) ] )
+
+ process_jam_log( executable = process_jam_log_executable
+ , results_dir = "."
+ , locate_root = root
+ , file=bjam_log_file.replace( 'bjam', 'bjam_' ) )
+
+ actual_content = list_recursively( "." )
+ actual_content.sort()
+ result_xml = []
+ for test_log in [ x for x in actual_content if os.path.splitext( x )[1] == '.xml' ]:
+ print 'reading %s' % test_log
+ result = [ re.sub( r'timestamp="(.*)"', 'timestamp="xxx"', x ) for x in read_file_lines( test_log ) ]
+ result_xml.extend( result )
+
+ write_file_lines( 'results.xml', result_xml )
+ os.chdir( '..' )
+ assert read_file( 'expected/results.xml' ) == read_file( 'actual/results.xml' )
+ os.chdir( '..' )
+ else:
+ raise ' Test case "%s" doesn\'t contain the expected results directory ("expected" )' % ( test_case )
+
+run_test_cases( scan_for_test_cases() )
+# print find_process_jam_log()
diff --git a/tools/regression/xsl_reports/README.txt b/tools/regression/xsl_reports/README.txt
new file mode 100644
index 0000000000..0f9cccda4d
--- /dev/null
+++ b/tools/regression/xsl_reports/README.txt
@@ -0,0 +1,27 @@
+
+
+This folder keeps scripts the produce the Boost regression test tables.
+
+The entry point is the boost_wide_report.py script. In the simplest
+case, it should be run as:
+
+ python boost_wide_report.py
+ --locate-root=XXX
+ --results-dir=YYY
+ --tag trunk
+ --expected-results=XXX
+ --failures-markup=XXX
+
+The 'trunk' is the tag of things that are tested, and should match the
+directory name on the server keeping uploaded individual results.
+'results-dir' is a directory where individual results (zip files) will
+be downloaded, and then processed. expected-results and failures-markup
+should be paths to corresponding files in 'status' subdir of boost tree.
+locate-root should point at boost root, it's unclear if it of any use
+now.
+
+This will download and process *all* test results, but it will not
+upload them, so good for local testing. It's possible to run
+this command, interrupt it while it processes results, leave just
+a few .zip files in result dir, and then re-run with --dont-collect-logs
+option, to use downloaded zips only.
diff --git a/tools/regression/xsl_reports/boost_wide_report.py b/tools/regression/xsl_reports/boost_wide_report.py
new file mode 100644
index 0000000000..bc598685c4
--- /dev/null
+++ b/tools/regression/xsl_reports/boost_wide_report.py
@@ -0,0 +1,835 @@
+
+# Copyright (c) MetaCommunications, Inc. 2003-2007
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import shutil
+import codecs
+import xml.sax.handler
+import xml.sax.saxutils
+import glob
+import re
+import os.path
+import os
+import string
+import time
+import sys
+import ftplib
+
+import utils
+
+report_types = [ 'us', 'ds', 'ud', 'dd', 'l', 'p', 'i', 'n', 'ddr', 'dsr', 'udr', 'usr' ]
+
+if __name__ == '__main__':
+ run_dir = os.path.abspath( os.path.dirname( sys.argv[ 0 ] ) )
+else:
+ run_dir = os.path.abspath( os.path.dirname( sys.modules[ __name__ ].__file__ ) )
+
+
+def map_path( path ):
+ return os.path.join( run_dir, path )
+
+
+def xsl_path( xsl_file_name ):
+ return map_path( os.path.join( 'xsl/v2', xsl_file_name ) )
+
+class file_info:
+ def __init__( self, file_name, file_size, file_date ):
+ self.name = file_name
+ self.size = file_size
+ self.date = file_date
+
+ def __repr__( self ):
+ return "name: %s, size: %s, date %s" % ( self.name, self.size, self.date )
+
+#
+# Find the mod time from unix format directory listing line
+#
+
+def get_date( words ):
+ date = words[ 5: -1 ]
+ t = time.localtime()
+
+ month_names = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
+
+ year = time.localtime()[0] # If year is not secified is it the current year
+ month = month_names.index( date[0] ) + 1
+ day = int( date[1] )
+ hours = 0
+ minutes = 0
+
+ if date[2].find( ":" ) != -1:
+ ( hours, minutes ) = [ int(x) for x in date[2].split( ":" ) ]
+ else:
+ # there is no way to get seconds for not current year dates
+ year = int( date[2] )
+
+ return ( year, month, day, hours, minutes, 0, 0, 0, 0 )
+
+def list_ftp( f ):
+ # f is an ftp object
+ utils.log( "listing source content" )
+ lines = []
+
+ # 1. get all lines
+ f.dir( lambda x: lines.append( x ) )
+
+ # 2. split lines into words
+ word_lines = [ x.split( None, 8 ) for x in lines ]
+
+ # we don't need directories
+ result = [ file_info( l[-1], None, get_date( l ) ) for l in word_lines if l[0][0] != "d" ]
+ for f in result:
+ utils.log( " %s" % f )
+ return result
+
+def list_dir( dir ):
+ utils.log( "listing destination content %s" % dir )
+ result = []
+ for file_path in glob.glob( os.path.join( dir, "*.zip" ) ):
+ if os.path.isfile( file_path ):
+ mod_time = time.localtime( os.path.getmtime( file_path ) )
+ mod_time = ( mod_time[0], mod_time[1], mod_time[2], mod_time[3], mod_time[4], mod_time[5], 0, 0, mod_time[8] )
+ # no size (for now)
+ result.append( file_info( os.path.basename( file_path ), None, mod_time ) )
+ for fi in result:
+ utils.log( " %s" % fi )
+ return result
+
+def find_by_name( d, name ):
+ for dd in d:
+ if dd.name == name:
+ return dd
+ return None
+
+def diff( source_dir_content, destination_dir_content ):
+ utils.log( "Finding updated files" )
+ result = ( [], [] ) # ( changed_files, obsolete_files )
+ for source_file in source_dir_content:
+ found = find_by_name( destination_dir_content, source_file.name )
+ if found is None: result[0].append( source_file.name )
+ elif time.mktime( found.date ) != time.mktime( source_file.date ): result[0].append( source_file.name )
+ else:
+ pass
+ for destination_file in destination_dir_content:
+ found = find_by_name( source_dir_content, destination_file.name )
+ if found is None: result[1].append( destination_file.name )
+ utils.log( " Updated files:" )
+ for f in result[0]:
+ utils.log( " %s" % f )
+ utils.log( " Obsolete files:" )
+ for f in result[1]:
+ utils.log( " %s" % f )
+ return result
+
+def _modtime_timestamp( file ):
+ return os.stat( file ).st_mtime
+
+
+root_paths = []
+
+def shorten( file_path ):
+ root_paths.sort( lambda x, y: cmp( len(y ), len( x ) ) )
+ for root in root_paths:
+ if file_path.lower().startswith( root.lower() ):
+ return file_path[ len( root ): ].replace( "\\", "/" )
+ return file_path.replace( "\\", "/" )
+
+class action:
+ def __init__( self, file_path ):
+ self.file_path_ = file_path
+ self.relevant_paths_ = [ self.file_path_ ]
+ self.boost_paths_ = []
+ self.dependencies_ = []
+ self.other_results_ = []
+
+ def run( self ):
+ utils.log( "%s: run" % shorten( self.file_path_ ) )
+ __log__ = 2
+
+ for dependency in self.dependencies_:
+ if not os.path.exists( dependency ):
+ utils.log( "%s doesn't exists, removing target" % shorten( dependency ) )
+ self.clean()
+ return
+
+ if not os.path.exists( self.file_path_ ):
+ utils.log( "target doesn't exists, building" )
+ self.update()
+ return
+
+ dst_timestamp = _modtime_timestamp( self.file_path_ )
+ utils.log( " target: %s [%s]" % ( shorten( self.file_path_ ), dst_timestamp ) )
+ needs_updating = 0
+ utils.log( " dependencies:" )
+ for dependency in self.dependencies_:
+ dm = _modtime_timestamp( dependency )
+ update_mark = ""
+ if dm > dst_timestamp:
+ needs_updating = 1
+ utils.log( ' %s [%s] %s' % ( shorten( dependency ), dm, update_mark ) )
+
+ if needs_updating:
+ utils.log( "target needs updating, rebuilding" )
+ self.update()
+ return
+ else:
+ utils.log( "target is up-to-date" )
+
+
+ def clean( self ):
+ to_unlink = self.other_results_ + [ self.file_path_ ]
+ for result in to_unlink:
+ utils.log( ' Deleting obsolete "%s"' % shorten( result ) )
+ if os.path.exists( result ):
+ os.unlink( result )
+
+class merge_xml_action( action ):
+ def __init__( self, source, destination, expected_results_file, failures_markup_file, tag ):
+ action.__init__( self, destination )
+ self.source_ = source
+ self.destination_ = destination
+ self.tag_ = tag
+
+ self.expected_results_file_ = expected_results_file
+ self.failures_markup_file_ = failures_markup_file
+
+ self.dependencies_.extend( [
+ self.source_
+ , self.expected_results_file_
+ , self.failures_markup_file_
+ ]
+ )
+
+ self.relevant_paths_.extend( [ self.source_ ] )
+ self.boost_paths_.extend( [ self.expected_results_file_, self.failures_markup_file_ ] )
+
+
+
+ def update( self ):
+ def filter_xml( src, dest ):
+
+ class xmlgen( xml.sax.saxutils.XMLGenerator ):
+ def __init__( self, writer ):
+ xml.sax.saxutils.XMLGenerator.__init__( self, writer )
+
+ self.trimmed = 0
+ self.character_content = ""
+
+ def startElement( self, name, attrs):
+ self.flush()
+ xml.sax.saxutils.XMLGenerator.startElement( self, name, attrs )
+
+ def endElement( self, name ):
+ self.flush()
+ xml.sax.saxutils.XMLGenerator.endElement( self, name )
+
+ def flush( self ):
+ content = self.character_content
+ self.character_content = ""
+ self.trimmed = 0
+ xml.sax.saxutils.XMLGenerator.characters( self, content )
+
+ def characters( self, content ):
+ if not self.trimmed:
+ max_size = pow( 2, 16 )
+ self.character_content += content
+ if len( self.character_content ) > max_size:
+ self.character_content = self.character_content[ : max_size ] + "...\n\n[The content has been trimmed by the report system because it exceeds %d bytes]" % max_size
+ self.trimmed = 1
+
+ o = open( dest, "w" )
+ try:
+ gen = xmlgen( o )
+ xml.sax.parse( src, gen )
+ finally:
+ o.close()
+
+ return dest
+
+
+ utils.log( 'Merging "%s" with expected results...' % shorten( self.source_ ) )
+ try:
+ trimmed_source = filter_xml( self.source_, '%s-trimmed.xml' % os.path.splitext( self.source_ )[0] )
+ utils.libxslt(
+ utils.log
+ , trimmed_source
+ , xsl_path( 'add_expected_results.xsl' )
+ , self.file_path_
+ , {
+ "expected_results_file" : self.expected_results_file_
+ , "failures_markup_file": self.failures_markup_file_
+ , "source" : self.tag_
+ }
+ )
+
+ os.unlink( trimmed_source )
+
+ except Exception, msg:
+ utils.log( ' Skipping "%s" due to errors (%s)' % ( self.source_, msg ) )
+ if os.path.exists( self.file_path_ ):
+ os.unlink( self.file_path_ )
+
+
+ def _xml_timestamp( xml_path ):
+
+ class timestamp_reader( xml.sax.handler.ContentHandler ):
+ def startElement( self, name, attrs ):
+ if name == 'test-run':
+ self.timestamp = attrs.getValue( 'timestamp' )
+ raise self
+
+ try:
+ xml.sax.parse( xml_path, timestamp_reader() )
+ raise 'Cannot extract timestamp from "%s". Invalid XML file format?' % xml_path
+ except timestamp_reader, x:
+ return x.timestamp
+
+
+class make_links_action( action ):
+ def __init__( self, source, destination, output_dir, tag, run_date, comment_file, failures_markup_file ):
+ action.__init__( self, destination )
+ self.dependencies_.append( source )
+ self.source_ = source
+ self.output_dir_ = output_dir
+ self.tag_ = tag
+ self.run_date_ = run_date
+ self.comment_file_ = comment_file
+ self.failures_markup_file_ = failures_markup_file
+ self.links_file_path_ = os.path.join( output_dir, 'links.html' )
+
+ def update( self ):
+ utils.makedirs( os.path.join( os.path.dirname( self.links_file_path_ ), "output" ) )
+ utils.makedirs( os.path.join( os.path.dirname( self.links_file_path_ ), "developer", "output" ) )
+ utils.makedirs( os.path.join( os.path.dirname( self.links_file_path_ ), "user", "output" ) )
+ utils.log( ' Making test output files...' )
+ try:
+ utils.libxslt(
+ utils.log
+ , self.source_
+ , xsl_path( 'links_page.xsl' )
+ , self.links_file_path_
+ , {
+ 'source': self.tag_
+ , 'run_date': self.run_date_
+ , 'comment_file': self.comment_file_
+ , 'explicit_markup_file': self.failures_markup_file_
+ }
+ )
+ except Exception, msg:
+ utils.log( ' Skipping "%s" due to errors (%s)' % ( self.source_, msg ) )
+
+ open( self.file_path_, "w" ).close()
+
+
+class unzip_action( action ):
+ def __init__( self, source, destination, unzip_func ):
+ action.__init__( self, destination )
+ self.dependencies_.append( source )
+ self.source_ = source
+ self.unzip_func_ = unzip_func
+
+ def update( self ):
+ try:
+ utils.log( ' Unzipping "%s" ... into "%s"' % ( shorten( self.source_ ), os.path.dirname( self.file_path_ ) ) )
+ self.unzip_func_( self.source_, os.path.dirname( self.file_path_ ) )
+ except Exception, msg:
+ utils.log( ' Skipping "%s" due to errors (%s)' % ( self.source_, msg ) )
+
+
+def ftp_task( site, site_path , destination ):
+ __log__ = 1
+ utils.log( '' )
+ utils.log( 'ftp_task: "ftp://%s/%s" -> %s' % ( site, site_path, destination ) )
+
+ utils.log( ' logging on ftp site %s' % site )
+ f = ftplib.FTP( site )
+ f.login()
+ utils.log( ' cwd to "%s"' % site_path )
+ f.cwd( site_path )
+
+ source_content = list_ftp( f )
+ source_content = [ x for x in source_content if re.match( r'.+[.](?<!log[.])zip', x.name ) and x.name.lower() != 'boostbook.zip' ]
+ destination_content = list_dir( destination )
+ d = diff( source_content, destination_content )
+
+ def synchronize():
+ for source in d[0]:
+ utils.log( 'Copying "%s"' % source )
+ result = open( os.path.join( destination, source ), 'wb' )
+ f.retrbinary( 'RETR %s' % source, result.write )
+ result.close()
+ mod_date = find_by_name( source_content, source ).date
+ m = time.mktime( mod_date )
+ os.utime( os.path.join( destination, source ), ( m, m ) )
+
+ for obsolete in d[1]:
+ utils.log( 'Deleting "%s"' % obsolete )
+ os.unlink( os.path.join( destination, obsolete ) )
+
+ utils.log( " Synchronizing..." )
+ __log__ = 2
+ synchronize()
+
+ f.quit()
+
+def unzip_archives_task( source_dir, processed_dir, unzip_func ):
+ utils.log( '' )
+ utils.log( 'unzip_archives_task: unpacking updated archives in "%s" into "%s"...' % ( source_dir, processed_dir ) )
+ __log__ = 1
+
+ target_files = [ os.path.join( processed_dir, os.path.basename( x.replace( ".zip", ".xml" ) ) ) for x in glob.glob( os.path.join( source_dir, "*.zip" ) ) ] + glob.glob( os.path.join( processed_dir, "*.xml" ) )
+ actions = [ unzip_action( os.path.join( source_dir, os.path.basename( x.replace( ".xml", ".zip" ) ) ), x, unzip_func ) for x in target_files ]
+ for a in actions:
+ a.run()
+
+def merge_xmls_task( source_dir, processed_dir, merged_dir, expected_results_file, failures_markup_file, tag ):
+ utils.log( '' )
+ utils.log( 'merge_xmls_task: merging updated XMLs in "%s"...' % source_dir )
+ __log__ = 1
+
+ utils.makedirs( merged_dir )
+ target_files = [ os.path.join( merged_dir, os.path.basename( x ) ) for x in glob.glob( os.path.join( processed_dir, "*.xml" ) ) ] + glob.glob( os.path.join( merged_dir, "*.xml" ) )
+ actions = [ merge_xml_action( os.path.join( processed_dir, os.path.basename( x ) )
+ , x
+ , expected_results_file
+ , failures_markup_file
+ , tag ) for x in target_files ]
+
+ for a in actions:
+ a.run()
+
+
+def make_links_task( input_dir, output_dir, tag, run_date, comment_file, extended_test_results, failures_markup_file ):
+ utils.log( '' )
+ utils.log( 'make_links_task: make output files for test results in "%s"...' % input_dir )
+ __log__ = 1
+
+ target_files = [ x + ".links" for x in glob.glob( os.path.join( input_dir, "*.xml" ) ) ] + glob.glob( os.path.join( input_dir, "*.links" ) )
+ actions = [ make_links_action( x.replace( ".links", "" )
+ , x
+ , output_dir
+ , tag
+ , run_date
+ , comment_file
+ , failures_markup_file
+ ) for x in target_files ]
+
+ for a in actions:
+ a.run()
+
+
+class xmlgen( xml.sax.saxutils.XMLGenerator ):
+ document_started = 0
+
+ def startDocument( self ):
+ if not self.document_started:
+ xml.sax.saxutils.XMLGenerator.startDocument( self )
+ self.document_started = 1
+
+
+def merge_processed_test_runs( test_runs_dir, tag, writer ):
+ utils.log( '' )
+ utils.log( 'merge_processed_test_runs: merging processed test runs from %s into a single XML...' % test_runs_dir )
+ __log__ = 1
+
+ all_runs_xml = xmlgen( writer, encoding='utf-8' )
+ all_runs_xml.startDocument()
+ all_runs_xml.startElement( 'all-test-runs', {} )
+
+ files = glob.glob( os.path.join( test_runs_dir, '*.xml' ) )
+ for test_run in files:
+ #file_pos = writer.stream.tell()
+ file_pos = writer.tell()
+ try:
+ utils.log( ' Writing "%s" into the resulting XML...' % test_run )
+ xml.sax.parse( test_run, all_runs_xml )
+ except Exception, msg:
+ utils.log( ' Skipping "%s" due to errors (%s)' % ( test_run, msg ) )
+ #writer.stream.seek( file_pos )
+ #writer.stream.truncate()
+ writer.seek( file_pos )
+ writer.truncate()
+
+ all_runs_xml.endElement( 'all-test-runs' )
+ all_runs_xml.endDocument()
+
+
+def execute_tasks(
+ tag
+ , user
+ , run_date
+ , comment_file
+ , results_dir
+ , output_dir
+ , reports
+ , warnings
+ , extended_test_results
+ , dont_collect_logs
+ , expected_results_file
+ , failures_markup_file
+ ):
+
+ incoming_dir = os.path.join( results_dir, 'incoming', tag )
+ processed_dir = os.path.join( incoming_dir, 'processed' )
+ merged_dir = os.path.join( processed_dir, 'merged' )
+ if not os.path.exists( incoming_dir ):
+ os.makedirs( incoming_dir )
+ if not os.path.exists( processed_dir ):
+ os.makedirs( processed_dir )
+ if not os.path.exists( merged_dir ):
+ os.makedirs( merged_dir )
+
+ if not dont_collect_logs:
+ ftp_site = 'boost.cowic.de'
+ site_path = '/boost/do-not-publish-this-url/results/%s' % tag
+
+ ftp_task( ftp_site, site_path, incoming_dir )
+
+ unzip_archives_task( incoming_dir, processed_dir, utils.unzip )
+ merge_xmls_task( incoming_dir, processed_dir, merged_dir, expected_results_file, failures_markup_file, tag )
+ make_links_task( merged_dir
+ , output_dir
+ , tag
+ , run_date
+ , comment_file
+ , extended_test_results
+ , failures_markup_file )
+
+
+ results_xml_path = os.path.join( output_dir, 'extended_test_results.xml' )
+ #writer = codecs.open( results_xml_path, 'w', 'utf-8' )
+ writer = open( results_xml_path, 'w' )
+ merge_processed_test_runs( merged_dir, tag, writer )
+ writer.close()
+
+
+ make_result_pages(
+ extended_test_results
+ , expected_results_file
+ , failures_markup_file
+ , tag
+ , run_date
+ , comment_file
+ , output_dir
+ , reports
+ , warnings
+ )
+
+
+def make_result_pages(
+ extended_test_results
+ , expected_results_file
+ , failures_markup_file
+ , tag
+ , run_date
+ , comment_file
+ , output_dir
+ , reports
+ , warnings
+ ):
+
+ utils.log( 'Producing the reports...' )
+ __log__ = 1
+
+ warnings_text = '+'.join( warnings )
+
+ if comment_file != '':
+ comment_file = os.path.abspath( comment_file )
+
+ links = os.path.join( output_dir, 'links.html' )
+
+ utils.makedirs( os.path.join( output_dir, 'output' ) )
+ for mode in ( 'developer', 'user' ):
+ utils.makedirs( os.path.join( output_dir, mode , 'output' ) )
+
+ issues = os.path.join( output_dir, 'developer', 'issues.html' )
+ if 'i' in reports:
+ utils.log( ' Making issues list...' )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'issues_page.xsl' )
+ , issues
+ , {
+ 'source': tag
+ , 'run_date': run_date
+ , 'warnings': warnings_text
+ , 'comment_file': comment_file
+ , 'expected_results_file': expected_results_file
+ , 'explicit_markup_file': failures_markup_file
+ , 'release': "yes"
+ }
+ )
+
+ for mode in ( 'developer', 'user' ):
+ if mode[0] + 'd' in reports:
+ utils.log( ' Making detailed %s report...' % mode )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'result_page.xsl' )
+ , os.path.join( output_dir, mode, 'index.html' )
+ , {
+ 'links_file': 'links.html'
+ , 'mode': mode
+ , 'source': tag
+ , 'run_date': run_date
+ , 'warnings': warnings_text
+ , 'comment_file': comment_file
+ , 'expected_results_file': expected_results_file
+ , 'explicit_markup_file' : failures_markup_file
+ }
+ )
+
+ for mode in ( 'developer', 'user' ):
+ if mode[0] + 's' in reports:
+ utils.log( ' Making summary %s report...' % mode )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'summary_page.xsl' )
+ , os.path.join( output_dir, mode, 'summary.html' )
+ , {
+ 'mode' : mode
+ , 'source': tag
+ , 'run_date': run_date
+ , 'warnings': warnings_text
+ , 'comment_file': comment_file
+ , 'explicit_markup_file' : failures_markup_file
+ }
+ )
+
+ for mode in ( 'developer', 'user' ):
+ if mode[0] + 'dr' in reports:
+ utils.log( ' Making detailed %s release report...' % mode )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'result_page.xsl' )
+ , os.path.join( output_dir, mode, 'index_release.html' )
+ , {
+ 'links_file': 'links.html'
+ , 'mode': mode
+ , 'source': tag
+ , 'run_date': run_date
+ , 'warnings': warnings_text
+ , 'comment_file': comment_file
+ , 'expected_results_file': expected_results_file
+ , 'explicit_markup_file' : failures_markup_file
+ , 'release': "yes"
+ }
+ )
+
+ for mode in ( 'developer', 'user' ):
+ if mode[0] + 'sr' in reports:
+ utils.log( ' Making summary %s release report...' % mode )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'summary_page.xsl' )
+ , os.path.join( output_dir, mode, 'summary_release.html' )
+ , {
+ 'mode' : mode
+ , 'source': tag
+ , 'run_date': run_date
+ , 'warnings': warnings_text
+ , 'comment_file': comment_file
+ , 'explicit_markup_file' : failures_markup_file
+ , 'release': 'yes'
+ }
+ )
+
+ if 'e' in reports:
+ utils.log( ' Generating expected_results ...' )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'produce_expected_results.xsl' )
+ , os.path.join( output_dir, 'expected_results.xml' )
+ )
+
+ if 'n' in reports:
+ utils.log( ' Making runner comment files...' )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'runners.xsl' )
+ , os.path.join( output_dir, 'runners.html' )
+ )
+
+ shutil.copyfile(
+ xsl_path( 'html/master.css' )
+ , os.path.join( output_dir, 'master.css' )
+ )
+
+ fix_file_names( output_dir )
+
+
+def fix_file_names( dir ):
+ """
+ The current version of xslproc doesn't correctly handle
+ spaces. We have to manually go through the
+ result set and decode encoded spaces (%20).
+ """
+ utils.log( 'Fixing encoded file names...' )
+ for root, dirs, files in os.walk( dir ):
+ for file in files:
+ if file.find( "%20" ) > -1:
+ new_name = file.replace( "%20", " " )
+ utils.rename(
+ utils.log
+ , os.path.join( root, file )
+ , os.path.join( root, new_name )
+ )
+
+
+def build_xsl_reports(
+ locate_root_dir
+ , tag
+ , expected_results_file
+ , failures_markup_file
+ , comment_file
+ , results_dir
+ , result_file_prefix
+ , dont_collect_logs = 0
+ , reports = report_types
+ , warnings = []
+ , user = None
+ , upload = False
+ ):
+
+ ( run_date ) = time.strftime( '%Y-%m-%dT%H:%M:%SZ', time.gmtime() )
+
+ root_paths.append( locate_root_dir )
+ root_paths.append( results_dir )
+
+ bin_boost_dir = os.path.join( locate_root_dir, 'bin', 'boost' )
+
+ output_dir = os.path.join( results_dir, result_file_prefix )
+ utils.makedirs( output_dir )
+
+ if expected_results_file != '':
+ expected_results_file = os.path.abspath( expected_results_file )
+ else:
+ expected_results_file = os.path.abspath( map_path( 'empty_expected_results.xml' ) )
+
+
+ extended_test_results = os.path.join( output_dir, 'extended_test_results.xml' )
+
+ execute_tasks(
+ tag
+ , user
+ , run_date
+ , comment_file
+ , results_dir
+ , output_dir
+ , reports
+ , warnings
+ , extended_test_results
+ , dont_collect_logs
+ , expected_results_file
+ , failures_markup_file
+ )
+
+ if upload:
+ upload_dir = 'regression-logs/'
+ utils.log( 'Uploading results into "%s" [connecting as %s]...' % ( upload_dir, user ) )
+
+ archive_name = '%s.tar.gz' % result_file_prefix
+ utils.tar(
+ os.path.join( results_dir, result_file_prefix )
+ , archive_name
+ )
+
+ utils.sourceforge.upload( os.path.join( results_dir, archive_name ), upload_dir, user )
+ utils.sourceforge.untar( os.path.join( upload_dir, archive_name ), user, background = True )
+
+
+def accept_args( args ):
+ args_spec = [
+ 'locate-root='
+ , 'tag='
+ , 'expected-results='
+ , 'failures-markup='
+ , 'comment='
+ , 'results-dir='
+ , 'results-prefix='
+ , 'dont-collect-logs'
+ , 'reports='
+ , 'user='
+ , 'upload'
+ , 'help'
+ ]
+
+ options = {
+ '--comment': ''
+ , '--expected-results': ''
+ , '--failures-markup': ''
+ , '--reports': string.join( report_types, ',' )
+ , '--tag': None
+ , '--user': None
+ , 'upload': False
+ }
+
+ utils.accept_args( args_spec, args, options, usage )
+ if not options.has_key( '--results-dir' ):
+ options[ '--results-dir' ] = options[ '--locate-root' ]
+
+ if not options.has_key( '--results-prefix' ):
+ options[ '--results-prefix' ] = 'all'
+
+ return (
+ options[ '--locate-root' ]
+ , options[ '--tag' ]
+ , options[ '--expected-results' ]
+ , options[ '--failures-markup' ]
+ , options[ '--comment' ]
+ , options[ '--results-dir' ]
+ , options[ '--results-prefix' ]
+ , options.has_key( '--dont-collect-logs' )
+ , options[ '--reports' ].split( ',' )
+ , options[ '--user' ]
+ , options.has_key( '--upload' )
+ )
+
+
+def usage():
+ print 'Usage: %s [options]' % os.path.basename( sys.argv[0] )
+ print '''
+\t--locate-root the same as --locate-root in compiler_status
+\t--tag the tag for the results (i.e. 'trunk')
+\t--expected-results the file with the results to be compared with
+\t the current run
+\t--failures-markup the file with the failures markup
+\t--comment an html comment file (will be inserted in the reports)
+\t--results-dir the directory containing -links.html, -fail.html
+\t files produced by compiler_status (by default the
+\t same as specified in --locate-root)
+\t--results-prefix the prefix of -links.html, -fail.html
+\t files produced by compiler_status
+\t--user SourceForge user name for a shell account
+\t--upload upload reports to SourceForge
+
+The following options are useful in debugging:
+
+\t--dont-collect-logs dont collect the test logs
+\t--reports produce only the specified reports
+\t us - user summary
+\t ds - developer summary
+\t ud - user detailed
+\t dd - developer detailed
+\t l - links
+\t p - patches
+\t x - extended results file
+\t i - issues
+\t n - runner comment files
+'''
+
+def main():
+ build_xsl_reports( *accept_args( sys.argv[ 1 : ] ) )
+
+if __name__ == '__main__':
+ main()
diff --git a/tools/regression/xsl_reports/boostbook_report.py b/tools/regression/xsl_reports/boostbook_report.py
new file mode 100644
index 0000000000..6c91a939dd
--- /dev/null
+++ b/tools/regression/xsl_reports/boostbook_report.py
@@ -0,0 +1,179 @@
+import ftplib
+import optparse
+import os
+import time
+import urlparse
+import utils
+import shutil
+import sys
+import zipfile
+import xml.sax.saxutils
+
+
+import utils.libxslt
+
+def get_date( words ):
+ date = words[ 5: -1 ]
+ t = time.localtime()
+
+ month_names = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
+
+ year = time.localtime()[0] # If year is not secified is it the current year
+ month = month_names.index( date[0] ) + 1
+ day = int( date[1] )
+ hours = 0
+ minutes = 0
+
+ if date[2].find( ":" ) != -1:
+ ( hours, minutes ) = [ int(x) for x in date[2].split( ":" ) ]
+ else:
+ # there is no way to get seconds for not current year dates
+ year = int( date[2] )
+
+ return ( year, month, day, hours, minutes, 0, 0, 0, 0 )
+
+#def check_for_new_upload( target_dir, boostbook_info ):
+
+def accept_args( args ):
+ parser = optparse.OptionParser()
+ parser.add_option( '-t', '--tag', dest='tag', help="the tag for the results (i.e. 'RC_1_34_0')" )
+ parser.add_option( '-d', '--destination', dest='destination', help='destination directory' )
+
+ if len(args) == 0:
+ parser.print_help()
+ sys.exit( 1 )
+
+ (options, args) = parser.parse_args()
+ if not options.destination:
+ print '-d is required'
+ parser.print_help()
+ sys.exit( 1 )
+ return options
+
+def unzip( archive_path, result_dir ):
+ utils.log( 'Unpacking %s into %s' % ( archive_path, result_dir ) )
+ z = zipfile.ZipFile( archive_path, 'r', zipfile.ZIP_DEFLATED )
+ for f in z.infolist():
+ dir = os.path.join( result_dir, os.path.dirname( f.filename ) )
+ if not os.path.exists( dir ):
+ os.makedirs( dir )
+ result = open( os.path.join( result_dir, f.filename ), 'wb' )
+ result.write( z.read( f.filename ) )
+ result.close()
+
+ z.close()
+
+def boostbook_report( options ):
+ site = 'fx.meta-comm.com'
+ site_path = '/boost-regression/%s' % options.tag
+
+ utils.log( 'Opening %s ...' % site )
+ f = ftplib.FTP( site )
+ f.login()
+ utils.log( ' cd %s ...' % site_path )
+ f.cwd( site_path )
+
+ utils.log( ' dir' )
+ lines = []
+ f.dir( lambda x: lines.append( x ) )
+ word_lines = [ x.split( None, 8 ) for x in lines ]
+ boostbook_info = [ ( l[-1], get_date( l ) ) for l in word_lines if l[-1] == "BoostBook.zip" ]
+ if len( boostbook_info ) > 0:
+ boostbook_info = boostbook_info[0]
+ utils.log( 'BoostBook found! (%s)' % ( boostbook_info, ) )
+ local_copy = os.path.join( options.destination,'BoostBook-%s.zip' % options.tag )
+
+ if 1:
+ if os.path.exists( local_copy ):
+ utils.log( 'Local copy exists. Checking if it is older than uploaded one...' )
+ uploaded_mtime = time.mktime( boostbook_info[1] )
+ local_mtime = os.path.getmtime( local_copy )
+ utils.log( ' uploaded: %s %s, local: %s %s' %
+ ( uploaded_mtime
+ , boostbook_info[1]
+ , local_mtime
+ , time.localtime( local_mtime )) )
+ modtime = time.localtime( os.path.getmtime( local_copy ) )
+ if uploaded_mtime <= local_mtime:
+ utils.log( 'Local copy is newer: exiting' )
+ sys.exit()
+
+ if 1:
+ temp = os.path.join( options.destination,'BoostBook.zip' )
+ result = open( temp, 'wb' )
+ f.retrbinary( 'RETR %s' % boostbook_info[0], result.write )
+ result.close()
+
+ if os.path.exists( local_copy ):
+ os.unlink( local_copy )
+ os.rename( temp, local_copy )
+ m = time.mktime( boostbook_info[1] )
+ os.utime( local_copy, ( m, m ) )
+
+
+ docs_name = os.path.splitext( os.path.basename( local_copy ) )[0]
+ if 1:
+ unpacked_docs_dir = os.path.join( options.destination, docs_name )
+ utils.log( 'Dir %s ' % unpacked_docs_dir )
+ if os.path.exists( unpacked_docs_dir ):
+ utils.log( 'Cleaning up...' )
+ shutil.rmtree( unpacked_docs_dir )
+ os.makedirs( unpacked_docs_dir )
+
+ unzip( local_copy, unpacked_docs_dir )
+
+ utils.system( [ 'cd %s' % unpacked_docs_dir
+ , 'tar -c -f ../%s.tar.gz -z --exclude=tarball *' % docs_name ] )
+
+ process_boostbook_build_log( os.path.join( unpacked_docs_dir, 'boostbook.log' ), read_timestamp( unpacked_docs_dir ) )
+ utils.libxslt( log
+ , os.path.abspath( os.path.join( unpacked_docs_dir, 'boostbook.log.xml' ) )
+ , os.path.abspath( os.path.join( os.path.dirname( __file__ ), 'xsl', 'v2', 'boostbook_log.xsl' ) )
+ , os.path.abspath( os.path.join( unpacked_docs_dir, 'boostbook.log.html' ) ) )
+
+
+def log( msg ):
+ print msg
+
+def process_boostbook_build_log( path, timestamp ):
+ f = open( path + '.xml', 'w' )
+ g = xml.sax.saxutils.XMLGenerator( f )
+ lines = open( path ).read().splitlines()
+ output_lines = []
+ result = 'success'
+ for line in lines:
+ type = 'output'
+ if line.startswith( '...failed' ):
+ type = 'failure'
+ result='failure'
+
+ if line.startswith( 'runtime error:' ):
+ type = 'failure'
+
+ if line.startswith( '...skipped' ):
+ type = 'skipped'
+ output_lines.append( ( type, line ) )
+
+ g.startDocument()
+ g.startElement( 'build', { 'result': result, 'timestamp': timestamp } )
+ for line in output_lines:
+ g.startElement( 'line', { 'type': line[0]} )
+ g.characters( line[1] )
+ g.endElement( 'line' )
+ g.endElement( 'build' )
+ g.endDocument()
+
+
+def read_timestamp( docs_directory ):
+ f = open( os.path.join( docs_directory, 'timestamp' ) )
+ try:
+ return f.readline()
+ finally:
+ f.close()
+
+def main():
+ options = accept_args( sys.argv[1:])
+ boostbook_report( options )
+
+if __name__ == '__main__':
+ main() \ No newline at end of file
diff --git a/tools/regression/xsl_reports/build_results.sh b/tools/regression/xsl_reports/build_results.sh
new file mode 100755
index 0000000000..5947117fa9
--- /dev/null
+++ b/tools/regression/xsl_reports/build_results.sh
@@ -0,0 +1,146 @@
+#!/bin/sh
+
+#~ Copyright Redshift Software, Inc. 2007-2008
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+set -e
+
+build_all()
+{
+ update_tools ${1} ${2}
+ build_results ${1} ${2}
+ upload_results ${1} ${2}
+}
+
+update_tools()
+{
+ cwd=`pwd`
+ cd boost
+ svn up
+ cd "${cwd}"
+}
+
+report_info()
+{
+cat - > comment.html <<HTML
+<table style="border-spacing: 0.5em;">
+ <tr>
+ <td style="vertical-align: top;"><tt>uname</tt></td>
+ <td>
+ <pre style="border: 1px solid #666; overflow: auto;">
+`uname -a`
+ </pre>
+ </td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><tt>uptime</tt></td>
+ <td>
+ <pre style="border: 1px solid #666; overflow: auto;">
+`uptime`
+ </pre>
+ </td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><tt>vmstat</tt></td>
+ <td>
+ <pre style="border: 1px solid #666; overflow: auto;">
+`vmstat`
+ </pre>
+ </td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><tt>xsltproc</tt></td>
+ <td>
+ <pre style="border: 1px solid #666; overflow: auto;">
+`xsltproc --version`
+ </pre>
+ </td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><tt>python</tt></td>
+ <td>
+ <pre style="border: 1px solid #666; overflow: auto;">
+`python --version 2>&1`
+ </pre>
+ </td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">previous run</td>
+ <td>
+ <pre style="border: 1px solid #666; overflow: auto;">
+`cat previous.txt`
+ </pre>
+ </td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">current run</td>
+ <td>
+ <pre style="border: 1px solid #666; overflow: auto;">
+`date -u`
+ </pre>
+ </td>
+ </tr>
+</table>
+HTML
+ date -u > previous.txt
+}
+
+build_results()
+{
+ cwd=`pwd`
+ cd ${1}
+ root=`pwd`
+ boost=${cwd}/boost
+ case ${1} in
+ trunk)
+ tag=trunk
+ reports="dd,ds,i,n"
+ ;;
+
+ release)
+ tag=branches/release
+ reports="dd,ds,i,n"
+ ;;
+
+ release-1_35_0)
+ tag=tags/release/Boost_1_35_0
+ reports="dd,ud,ds,us,ddr,udr,dsr,usr,i,n,e"
+ ;;
+
+ release-1_36_0)
+ tag=tags/release/Boost_1_36_0
+ reports="dd,ud,ds,us,ddr,udr,dsr,usr,i,n,e"
+ ;;
+ esac
+ report_info
+ python "${boost}/tools/regression/xsl_reports/boost_wide_report.py" \
+ --locate-root="${root}" \
+ --tag=${tag} \
+ --expected-results="${boost}/status/expected_results.xml" \
+ --failures-markup="${boost}/status/explicit-failures-markup.xml" \
+ --comment="comment.html" \
+ --user="" \
+ --reports=${reports}
+ cd "${cwd}"
+}
+
+upload_results()
+{
+ cwd=`pwd`
+ upload_dir=/home/grafik/www.boost.org/testing
+
+ cd ${1}/all
+ rm -f ../../${1}.zip*
+ #~ zip -q -r -9 ../../${1} * -x '*.xml'
+ 7za a -tzip -mx=9 ../../${1}.zip * '-x!*.xml'
+ cd "${cwd}"
+ mv ${1}.zip ${1}.zip.uploading
+ rsync -vuz --rsh=ssh --stats \
+ ${1}.zip.uploading grafik@beta.boost.org:/${upload_dir}/incoming/
+ ssh grafik@beta.boost.org \
+ cp ${upload_dir}/incoming/${1}.zip.uploading ${upload_dir}/live/${1}.zip
+ mv ${1}.zip.uploading ${1}.zip
+}
+
+build_all ${1} ${2}
diff --git a/tools/regression/xsl_reports/email_maintainers.py b/tools/regression/xsl_reports/email_maintainers.py
new file mode 100644
index 0000000000..308ab688f5
--- /dev/null
+++ b/tools/regression/xsl_reports/email_maintainers.py
@@ -0,0 +1,840 @@
+#
+# Copyright (C) 2005, 2007 The Trustees of Indiana University
+# Author: Douglas Gregor
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+import re
+import smtplib
+import os
+import time
+import string
+import datetime
+import sys
+
+report_author = "Douglas Gregor <dgregor@osl.iu.edu>"
+boost_dev_list = "Boost Developer List <boost@lists.boost.org>"
+boost_testing_list = "Boost Testing List <boost-testing@lists.boost.org>"
+
+def sorted_keys( dict ):
+ result = dict.keys()
+ result.sort()
+ return result
+
+
+class Platform:
+ """
+ All of the failures for a particular platform.
+ """
+ def __init__(self, name):
+ self.name = name
+ self.failures = list()
+ self.maintainers = list()
+ return
+
+ def addFailure(self, failure):
+ self.failures.append(failure)
+ return
+
+ def isBroken(self):
+ return len(self.failures) > 300
+
+ def addMaintainer(self, maintainer):
+ """
+ Add a new maintainer for this platform.
+ """
+ self.maintainers.append(maintainer)
+ return
+
+class Failure:
+ """
+ A single test case failure in the report.
+ """
+ def __init__(self, test, platform):
+ self.test = test
+ self.platform = platform
+ return
+
+class Test:
+ """
+ All of the failures for a single test name within a library.
+ """
+ def __init__(self, library, name):
+ self.library = library
+ self.name = name
+ self.failures = list()
+ return
+
+ def addFailure(self, failure):
+ self.failures.append(failure)
+ return
+
+ def numFailures(self):
+ return len(self.failures)
+
+ def numReportableFailures(self):
+ """
+ Returns the number of failures that we will report to the
+ maintainers of the library. This doesn't count failures on
+ broken platforms.
+ """
+ count = 0
+ for failure in self.failures:
+ if not failure.platform.isBroken():
+ count += 1
+ pass
+ pass
+ return count
+
+class Library:
+ """
+ All of the information about the failures in a single library.
+ """
+ def __init__(self, name):
+ self.name = name
+ self.maintainers = list()
+ self.tests = list()
+ return
+
+ def addTest(self, test):
+ """
+ Add another test to the library.
+ """
+ self.tests.append(test)
+ return
+
+ def addMaintainer(self, maintainer):
+ """
+ Add a new maintainer for this library.
+ """
+ self.maintainers.append(maintainer)
+ return
+
+ def numFailures(self):
+ count = 0
+ for test in self.tests:
+ count += test.numFailures()
+ pass
+ return count
+
+ def numReportableFailures(self):
+ count = 0
+ for test in self.tests:
+ count += test.numReportableFailures()
+ pass
+ return count
+
+class Maintainer:
+ """
+ Information about the maintainer of a library
+ """
+ def __init__(self, name, email):
+ self.name = name
+ self.email = email
+ self.libraries = list()
+ return
+
+ def addLibrary(self, library):
+ self.libraries.append(library)
+ return
+
+ def composeEmail(self, report):
+ """
+ Composes an e-mail to this maintainer with information about
+ the failures in his or her libraries, omitting those that come
+ from "broken" platforms. Returns the e-mail text if a message
+ needs to be sent, or None otherwise.
+ """
+
+ # Determine if we need to send a message to this developer.
+ requires_message = False
+ for library in self.libraries:
+ if library.numReportableFailures() > 0:
+ requires_message = True
+ break
+
+ if not requires_message:
+ return None
+
+ # Build the message header
+ message = """From: Douglas Gregor <dgregor@osl.iu.edu>
+To: """
+ message += self.name + ' <' + self.email + '>'
+ message += """
+Reply-To: boost@lists.boost.org
+Subject: Failures in your Boost libraries as of """
+ message += str(datetime.date.today()) + " [" + report.branch + "]"
+ message += """
+
+You are receiving this report because one or more of the libraries you
+maintain has regression test failures that are not accounted for.
+A full version of the report is sent to the Boost developer's mailing
+list.
+
+Detailed report:
+"""
+ message += ' ' + report.url + """
+
+There are failures in these libraries you maintain:
+"""
+
+ # List the libraries this maintainer is responsible for and
+ # the number of reportable failures in that library.
+ for library in self.libraries:
+ num_failures = library.numReportableFailures()
+ if num_failures > 0:
+ message += ' ' + library.name + ' (' + str(num_failures) + ')\n'
+ pass
+ pass
+
+ # Provide the details for the failures in each library.
+ for library in self.libraries:
+ if library.numReportableFailures() > 0:
+ message += '\n|' + library.name + '|\n'
+ for test in library.tests:
+ if test.numReportableFailures() > 0:
+ message += ' ' + test.name + ':'
+ for failure in test.failures:
+ if not failure.platform.isBroken():
+ message += ' ' + failure.platform.name
+ pass
+ pass
+ message += '\n'
+ pass
+ pass
+ pass
+ pass
+
+ return message
+
+class PlatformMaintainer:
+ """
+ Information about the platform maintainer of a library
+ """
+ def __init__(self, name, email):
+ self.name = name
+ self.email = email
+ self.platforms = list()
+ return
+
+ def addPlatform(self, runner, platform):
+ self.platforms.append(platform)
+ return
+
+ def composeEmail(self, report):
+ """
+ Composes an e-mail to this platform maintainer if one or more of
+ the platforms s/he maintains has a large number of failures.
+ Returns the e-mail text if a message needs to be sent, or None
+ otherwise.
+ """
+
+ # Determine if we need to send a message to this developer.
+ requires_message = False
+ for platform in self.platforms:
+ if platform.isBroken():
+ requires_message = True
+ break
+
+ if not requires_message:
+ return None
+
+ # Build the message header
+ message = """From: Douglas Gregor <dgregor@osl.iu.edu>
+To: """
+ message += self.name + ' <' + self.email + '>'
+ message += """
+Reply-To: boost@lists.boost.org
+Subject: Large number of Boost failures on a platform you maintain as of """
+ message += str(datetime.date.today()) + " [" + report.branch + "]"
+ message += """
+
+You are receiving this report because one or more of the testing
+platforms that you maintain has a large number of Boost failures that
+are not accounted for. A full version of the report is sent to the
+Boost developer's mailing list.
+
+Detailed report:
+"""
+ message += ' ' + report.url + """
+
+The following platforms have a large number of failures:
+"""
+
+ for platform in self.platforms:
+ if platform.isBroken():
+ message += (' ' + platform.name + ' ('
+ + str(len(platform.failures)) + ' failures)\n')
+
+ return message
+
+class Report:
+ """
+ The complete report of all failing test cases.
+ """
+ def __init__(self, branch = 'trunk'):
+ self.branch = branch
+ self.date = None
+ self.url = None
+ self.libraries = dict()
+ self.platforms = dict()
+ self.maintainers = dict()
+ self.platform_maintainers = dict()
+ return
+
+ def getPlatform(self, name):
+ """
+ Retrieve the platform with the given name.
+ """
+ if self.platforms.has_key(name):
+ return self.platforms[name]
+ else:
+ self.platforms[name] = Platform(name)
+ return self.platforms[name]
+
+ def getMaintainer(self, name, email):
+ """
+ Retrieve the maintainer with the given name and e-mail address.
+ """
+ if self.maintainers.has_key(name):
+ return self.maintainers[name]
+ else:
+ self.maintainers[name] = Maintainer(name, email)
+ return self.maintainers[name]
+
+ def getPlatformMaintainer(self, name, email):
+ """
+ Retrieve the platform maintainer with the given name and
+ e-mail address.
+ """
+ if self.platform_maintainers.has_key(name):
+ return self.platform_maintainers[name]
+ else:
+ self.platform_maintainers[name] = PlatformMaintainer(name, email)
+ return self.platform_maintainers[name]
+
+ def parseIssuesEmail(self):
+ """
+ Try to parse the issues e-mail file. Returns True if everything was
+ successful, false otherwise.
+ """
+ # See if we actually got the file
+ if not os.path.isfile('issues-email.txt'):
+ return False
+
+ # Determine the set of libraries that have unresolved failures
+ date_regex = re.compile('Report time: (.*)')
+ url_regex = re.compile(' (http://.*)')
+ library_regex = re.compile('\|(.*)\|')
+ failure_regex = re.compile(' ([^:]*): (.*)')
+ current_library = None
+ for line in file('issues-email.txt', 'r'):
+ # Check for the report time line
+ m = date_regex.match(line)
+ if m:
+ self.date = m.group(1)
+ continue
+
+ # Check for the detailed report URL
+ m = url_regex.match(line)
+ if m:
+ self.url = m.group(1)
+ continue
+
+ # Check for a library header
+ m = library_regex.match(line)
+ if m:
+ current_library = Library(m.group(1))
+ self.libraries[m.group(1)] = current_library
+ continue
+
+ # Check for a library test and its failures
+ m = failure_regex.match(line)
+ if m:
+ test = Test(current_library, m.group(1))
+ for platform_name in re.split('\s*', m.group(2)):
+ if platform_name != '':
+ platform = self.getPlatform(platform_name)
+ failure = Failure(test, platform)
+ test.addFailure(failure)
+ platform.addFailure(failure)
+ pass
+ current_library.addTest(test)
+ continue
+ pass
+
+ return True
+
+ def getIssuesEmail(self):
+ """
+ Retrieve the issues email from beta.boost.org, trying a few
+ times in case something wonky is happening. If we can retrieve
+ the file, calls parseIssuesEmail and return True; otherwise,
+ return False.
+ """
+ base_url = "http://beta.boost.org/development/tests/"
+ base_url += self.branch
+ base_url += "/developer/";
+ got_issues = False
+
+ # Ping the server by looking for an HTML file
+ print "Pinging the server to initiate extraction..."
+ ping_url = base_url + "issues.html"
+ os.system('curl -O ' + ping_url)
+ os.system('rm -f issues.html')
+
+ for x in range(30):
+ # Update issues-email.txt
+ url = base_url + "issues-email.txt"
+ print 'Retrieving issues email from ' + url
+ os.system('rm -f issues-email.txt')
+ os.system('curl -O ' + url)
+
+ if self.parseIssuesEmail():
+ return True
+
+ print 'Failed to fetch issues email. '
+ time.sleep (30)
+
+ return False
+
+ # Parses the file $BOOST_ROOT/libs/maintainers.txt to create a hash
+ # mapping from the library name to the list of maintainers.
+ def parseLibraryMaintainersFile(self):
+ """
+ Parse the maintainers file in ../../../libs/maintainers.txt to
+ collect information about the maintainers of broken libraries.
+ """
+ lib_maintainer_regex = re.compile('(\S+)\s*(.*)')
+ name_email_regex = re.compile('\s*(\w*(\s*\w+)+)\s*<\s*(\S*(\s*\S+)+)\S*>')
+ at_regex = re.compile('\s*-\s*at\s*-\s*')
+ for line in file('../../../libs/maintainers.txt', 'r'):
+ if line.startswith('#'):
+ continue
+ m = lib_maintainer_regex.match (line)
+ if m:
+ libname = m.group(1)
+ if self.libraries.has_key(m.group(1)):
+ library = self.libraries[m.group(1)]
+ for person in re.split('\s*,\s*', m.group(2)):
+ nmm = name_email_regex.match(person)
+ if nmm:
+ name = nmm.group(1)
+ email = nmm.group(3)
+ email = at_regex.sub('@', email)
+ maintainer = self.getMaintainer(name, email)
+ maintainer.addLibrary(library)
+ library.addMaintainer(maintainer)
+ pass
+ pass
+ pass
+ pass
+ pass
+ pass
+
+ # Parses the file $BOOST_ROOT/libs/platform_maintainers.txt to
+ # create a hash mapping from the platform name to the list of
+ # maintainers.
+ def parsePlatformMaintainersFile(self):
+ """
+ Parse the platform maintainers file in
+ ../../../libs/platform_maintainers.txt to collect information
+ about the maintainers of the various platforms.
+ """
+ platform_maintainer_regex = re.compile('([A-Za-z0-9_.-]*|"[^"]*")\s+(\S+)\s+(.*)')
+ name_email_regex = re.compile('\s*(\w*(\s*\w+)+)\s*<\s*(\S*(\s*\S+)+)\S*>')
+ at_regex = re.compile('\s*-\s*at\s*-\s*')
+ for line in file('../../../libs/platform_maintainers.txt', 'r'):
+ if line.startswith('#'):
+ continue
+ m = platform_maintainer_regex.match (line)
+ if m:
+ platformname = m.group(2)
+ if self.platforms.has_key(platformname):
+ platform = self.platforms[platformname]
+ for person in re.split('\s*,\s*', m.group(3)):
+ nmm = name_email_regex.match(person)
+ if nmm:
+ name = nmm.group(1)
+ email = nmm.group(3)
+ email = at_regex.sub('@', email)
+ maintainer = self.getPlatformMaintainer(name, email)
+ maintainer.addPlatform(m.group(1), platform)
+ platform.addMaintainer(maintainer)
+ pass
+ pass
+ pass
+ pass
+ pass
+
+ def numFailures(self):
+ count = 0
+ for library in self.libraries:
+ count += self.libraries[library].numFailures()
+ pass
+ return count
+
+ def numReportableFailures(self):
+ count = 0
+ for library in self.libraries:
+ count += self.libraries[library].numReportableFailures()
+ pass
+ return count
+
+ def composeSummaryEmail(self):
+ """
+ Compose a message to send to the Boost developer's
+ list. Return the message and return it.
+ """
+ message = """From: Douglas Gregor <dgregor@osl.iu.edu>
+To: boost@lists.boost.org
+Reply-To: boost@lists.boost.org
+Subject: [Report] """
+ message += str(self.numFailures()) + " failures on " + branch
+ if branch != 'trunk':
+ message += ' branch'
+ message += " (" + str(datetime.date.today()) + ")"
+ message += """
+
+Boost regression test failures
+"""
+ message += "Report time: " + self.date + """
+
+This report lists all regression test failures on high-priority platforms.
+
+Detailed report:
+"""
+
+ message += ' ' + self.url + '\n\n'
+
+ if self.numFailures() == 0:
+ message += "No failures! Yay!\n"
+ return message
+
+ # List the platforms that are broken
+ any_broken_platforms = self.numReportableFailures() < self.numFailures()
+ if any_broken_platforms:
+ message += """The following platforms have a large number of failures:
+"""
+ for platform in sorted_keys( self.platforms ):
+ if self.platforms[platform].isBroken():
+ message += (' ' + platform + ' ('
+ + str(len(self.platforms[platform].failures))
+ + ' failures)\n')
+
+ message += """
+Failures on these "broken" platforms will be omitted from the results below.
+Please see the full report for information about these failures.
+
+"""
+
+ # Display the number of failures
+ message += (str(self.numReportableFailures()) + ' failures in ' +
+ str(len(self.libraries)) + ' libraries')
+ if any_broken_platforms:
+ message += (' (plus ' + str(self.numFailures() - self.numReportableFailures())
+ + ' from broken platforms)')
+
+ message += '\n'
+
+ # Display the number of failures per library
+ for k in sorted_keys( self.libraries ):
+ library = self.libraries[k]
+ num_failures = library.numFailures()
+ message += ' ' + library.name + ' ('
+
+ if library.numReportableFailures() > 0:
+ message += (str(library.numReportableFailures())
+ + " failures")
+
+ if library.numReportableFailures() < num_failures:
+ if library.numReportableFailures() > 0:
+ message += ', plus '
+
+ message += (str(num_failures-library.numReportableFailures())
+ + ' failures on broken platforms')
+ message += ')\n'
+ pass
+
+ message += '\n'
+
+ # Provide the details for the failures in each library.
+ for k in sorted_keys( self.libraries ):
+ library = self.libraries[k]
+ if library.numReportableFailures() > 0:
+ message += '\n|' + library.name + '|\n'
+ for test in library.tests:
+ if test.numReportableFailures() > 0:
+ message += ' ' + test.name + ':'
+ for failure in test.failures:
+ platform = failure.platform
+ if not platform.isBroken():
+ message += ' ' + platform.name
+ message += '\n'
+
+ return message
+
+ def composeTestingSummaryEmail(self):
+ """
+ Compose a message to send to the Boost Testing list. Returns
+ the message text if a message is needed, returns None
+ otherwise.
+ """
+ brokenPlatforms = 0
+ for platform in sorted_keys( self.platforms ):
+ if self.platforms[platform].isBroken():
+ brokenPlatforms = brokenPlatforms + 1
+
+ if brokenPlatforms == 0:
+ return None;
+
+ message = """From: Douglas Gregor <dgregor@osl.iu.edu>
+To: boost-testing@lists.boost.org
+Reply-To: boost-testing@lists.boost.org
+Subject: [Report] """
+ message += str(brokenPlatforms) + " potentially broken platforms on " + branch
+ if branch != 'trunk':
+ message += ' branch'
+ message += " (" + str(datetime.date.today()) + ")"
+ message += """
+
+Potentially broken platforms for Boost regression testing
+"""
+ message += "Report time: " + self.date + """
+
+This report lists the high-priority platforms that are exhibiting a
+large number of regression test failures, which might indicate a problem
+with the test machines or testing harness.
+
+Detailed report:
+"""
+
+ message += ' ' + self.url + '\n'
+
+ message += """
+Platforms with a large number of failures:
+"""
+ for platform in sorted_keys( self.platforms ):
+ if self.platforms[platform].isBroken():
+ message += (' ' + platform + ' ('
+ + str(len(self.platforms[platform].failures))
+ + ' failures)\n')
+
+ return message
+
+# Send a message to "person" (a maintainer of a library that is
+# failing).
+# maintainers is the result of get_library_maintainers()
+def send_individualized_message (branch, person, maintainers):
+ # There are several states we could be in:
+ # 0 Initial state. Eat everything up to the "NNN failures in MMM
+ # libraries" line
+ # 1 Suppress output within this library
+ # 2 Forward output within this library
+ state = 0
+
+ failures_in_lib_regex = re.compile('\d+ failur.*\d+ librar')
+ lib_failures_regex = re.compile(' (\S+) \((\d+)\)')
+ lib_start_regex = re.compile('\|(\S+)\|')
+ general_pass_regex = re.compile(' http://')
+ for line in file('issues-email.txt', 'r'):
+ if state == 0:
+ lfm = lib_failures_regex.match(line)
+ if lfm:
+ # Pass the line through if the current person is a
+ # maintainer of this library
+ if lfm.group(1) in maintainers and person in maintainers[lfm.group(1)]:
+ message += line
+ print line,
+
+ elif failures_in_lib_regex.match(line):
+ message += "\nThere are failures in these libraries you maintain:\n"
+ elif general_pass_regex.match(line):
+ message += line
+
+ lib_start = lib_start_regex.match(line)
+ if lib_start:
+ if state == 0:
+ message += '\n'
+
+ if lib_start.group(1) in maintainers and person in maintainers[lib_start.group(1)]:
+ message += line
+ state = 2
+ else:
+ state = 1
+ else:
+ if state == 1:
+ pass
+ elif state == 2:
+ message += line
+
+ if '--debug' in sys.argv:
+ print '-----------------Message text----------------'
+ print message
+ else:
+ print
+
+ if '--send' in sys.argv:
+ print "Sending..."
+ smtp = smtplib.SMTP('milliways.osl.iu.edu')
+ smtp.sendmail(from_addr = 'Douglas Gregor <dgregor@osl.iu.edu>',
+ to_addrs = person[1],
+ msg = message)
+ print "Done."
+
+
+# Send a message to the developer's list
+def send_boost_developers_message(branch, maintainers, failing_libraries):
+ to_line = 'boost@lists.boost.org'
+ from_line = 'Douglas Gregor <dgregor@osl.iu.edu>'
+
+ message = """From: Douglas Gregor <dgregor@osl.iu.edu>
+To: boost@lists.boost.org
+Reply-To: boost@lists.boost.org
+Subject: Boost regression testing notification ("""
+
+ message += str(datetime.date.today()) + " [" + branch + "]"
+ message += ")"
+
+ message += """
+
+"""
+
+ for line in file('issues-email.txt', 'r'):
+ # Right before the detailed report, put out a warning message if
+ # any libraries with failures to not have maintainers listed.
+ if line.startswith('Detailed report:'):
+ missing_maintainers = False
+ for lib in failing_libraries:
+ if not(lib in maintainers) or maintainers[lib] == list():
+ missing_maintainers = True
+
+ if missing_maintainers:
+ message += """WARNING: The following libraries have failing regression tests but do
+not have a maintainer on file. Once a maintainer is found, add an
+entry to libs/maintainers.txt to eliminate this message.
+"""
+
+ for lib in failing_libraries:
+ if not(lib in maintainers) or maintainers[lib] == list():
+ message += ' ' + lib + '\n'
+ message += '\n'
+
+ message += line
+
+ if '--send' in sys.argv:
+ print 'Sending notification email...'
+ smtp = smtplib.SMTP('milliways.osl.iu.edu')
+ smtp.sendmail(from_addr = from_line, to_addrs = to_line, msg = message)
+ print 'Done.'
+
+ if '--debug' in sys.argv:
+ print "----------Boost developer's message text----------"
+ print message
+
+###############################################################################
+# Main program #
+###############################################################################
+
+# Parse command-line options
+branch = "trunk"
+for arg in sys.argv:
+ if arg.startswith("--branch="):
+ branch = arg[len("--branch="):]
+
+report = Report(branch)
+
+# Try to parse the issues e-mail
+if '--no-get' in sys.argv:
+ okay = report.parseIssuesEmail()
+else:
+ okay = report.getIssuesEmail()
+
+if not okay:
+ print 'Aborting.'
+ if '--send' in sys.argv:
+ message = """From: Douglas Gregor <dgregor@osl.iu.edu>
+ To: Douglas Gregor <dgregor@osl.iu.edu>
+ Reply-To: boost@lists.boost.org
+ Subject: Regression status script failed on """
+ message += str(datetime.date.today()) + " [" + branch + "]"
+ smtp = smtplib.SMTP('milliways.osl.iu.edu')
+ smtp.sendmail(from_addr = 'Douglas Gregor <dgregor@osl.iu.edu>',
+ to_addrs = 'dgregor@osl.iu.edu',
+ msg = message)
+ sys.exit(1)
+
+# Try to parse maintainers information
+report.parseLibraryMaintainersFile()
+report.parsePlatformMaintainersFile()
+
+# Generate individualized e-mail for library maintainers
+for maintainer_name in report.maintainers:
+ maintainer = report.maintainers[maintainer_name]
+
+ email = maintainer.composeEmail(report)
+ if email:
+ if '--send' in sys.argv:
+ print ('Sending notification email to ' + maintainer.name + '...')
+ smtp = smtplib.SMTP('milliways.osl.iu.edu')
+ smtp.sendmail(from_addr = report_author,
+ to_addrs = maintainer.email,
+ msg = email)
+ print 'done.\n'
+ else:
+ print 'Would send a notification e-mail to',maintainer.name
+
+ if '--debug' in sys.argv:
+ print ('Message text for ' + maintainer.name + ':\n')
+ print email
+
+# Generate individualized e-mail for platform maintainers
+for maintainer_name in report.platform_maintainers:
+ maintainer = report.platform_maintainers[maintainer_name]
+
+ email = maintainer.composeEmail(report)
+ if email:
+ if '--send' in sys.argv:
+ print ('Sending notification email to ' + maintainer.name + '...')
+ smtp = smtplib.SMTP('milliways.osl.iu.edu')
+ smtp.sendmail(from_addr = report_author,
+ to_addrs = maintainer.email,
+ msg = email)
+ print 'done.\n'
+ else:
+ print 'Would send a notification e-mail to',maintainer.name
+
+ if '--debug' in sys.argv:
+ print ('Message text for ' + maintainer.name + ':\n')
+ print email
+
+email = report.composeSummaryEmail()
+if '--send' in sys.argv:
+ print 'Sending summary email to Boost developer list...'
+ smtp = smtplib.SMTP('milliways.osl.iu.edu')
+ smtp.sendmail(from_addr = report_author,
+ to_addrs = boost_dev_list,
+ msg = email)
+ print 'done.\n'
+if '--debug' in sys.argv:
+ print 'Message text for summary:\n'
+ print email
+
+email = report.composeTestingSummaryEmail()
+if email:
+ if '--send' in sys.argv:
+ print 'Sending summary email to Boost testing list...'
+ smtp = smtplib.SMTP('milliways.osl.iu.edu')
+ smtp.sendmail(from_addr = report_author,
+ to_addrs = boost_testing_list,
+ msg = email)
+ print 'done.\n'
+ if '--debug' in sys.argv:
+ print 'Message text for testing summary:\n'
+ print email
+
+if not ('--send' in sys.argv):
+ print 'Chickening out and not sending any e-mail.'
+ print 'Use --send to actually send e-mail, --debug to see e-mails.'
diff --git a/tools/regression/xsl_reports/empty_expected_results.xml b/tools/regression/xsl_reports/empty_expected_results.xml
new file mode 100644
index 0000000000..43e72ca406
--- /dev/null
+++ b/tools/regression/xsl_reports/empty_expected_results.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+<expected-failures>
+</expected-failures>
+</root> \ No newline at end of file
diff --git a/tools/regression/xsl_reports/make_snapshot.py b/tools/regression/xsl_reports/make_snapshot.py
new file mode 100644
index 0000000000..b060a10406
--- /dev/null
+++ b/tools/regression/xsl_reports/make_snapshot.py
@@ -0,0 +1,174 @@
+
+# Copyright (c) MetaCommunications, Inc. 2003-2007
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import tarfile
+import shutil
+import time
+import os.path
+import string
+import sys
+import traceback
+
+
+def retry( f, args, max_attempts=5, sleep_secs=10 ):
+ for attempts in range( max_attempts, -1, -1 ):
+ try:
+ return f( *args )
+ except Exception, msg:
+ utils.log( '%s failed with message "%s"' % ( f.__name__, msg ) )
+ if attempts == 0:
+ utils.log( 'Giving up.' )
+ raise
+
+ utils.log( 'Retrying (%d more attempts).' % attempts )
+ time.sleep( sleep_secs )
+
+
+def rmtree( path ):
+ if os.path.exists( path ):
+ if sys.platform == 'win32':
+ os.system( 'del /f /s /q "%s" >nul 2>&1' % path )
+ shutil.rmtree( path )
+ else:
+ os.system( 'rm -f -r "%s"' % path )
+
+
+def svn_command( command ):
+ utils.log( 'Executing SVN command "%s"' % command )
+ rc = os.system( command )
+ if rc != 0:
+ raise Exception( 'SVN command "%s" failed with code %d' % ( command, rc ) )
+
+
+def svn_export( sources_dir, user, tag ):
+ if user is None or user == 'anonymous':
+ command = 'svn export --force http://svn.boost.org/svn/boost/%s %s' % ( tag, sources_dir )
+ else:
+ command = 'svn export --force --non-interactive --username=%s https://svn.boost.org/svn/boost/%s %s' \
+ % ( user, tag, sources_dir )
+
+ os.chdir( os.path.basename( sources_dir ) )
+ retry(
+ svn_command
+ , ( command, )
+ )
+
+
+def make_tarball(
+ working_dir
+ , tag
+ , user
+ , site_dir
+ ):
+ timestamp = time.time()
+ timestamp_suffix = time.strftime( '%y-%m-%d-%H%M', time.gmtime( timestamp ) )
+
+ tag_suffix = tag.split( '/' )[-1]
+ sources_dir = os.path.join(
+ working_dir
+ , 'boost-%s-%s' % ( tag_suffix, timestamp_suffix )
+ )
+
+ if os.path.exists( sources_dir ):
+ utils.log( 'Directory "%s" already exists, cleaning it up...' % sources_dir )
+ rmtree( sources_dir )
+
+ try:
+ os.mkdir( sources_dir )
+ utils.log( 'Exporting files from SVN...' )
+ svn_export( sources_dir, user, tag )
+ except:
+ utils.log( 'Cleaning up...' )
+ rmtree( sources_dir )
+ raise
+
+
+ tarball_name = 'boost-%s.tar.bz2' % tag_suffix
+ tarball_path = os.path.join( working_dir, tarball_name )
+
+ utils.log( 'Archiving "%s" to "%s"...' % ( sources_dir, tarball_path ) )
+ tar = tarfile.open( tarball_path, 'w|bz2' )
+ tar.posix = False # see http://tinyurl.com/4ebd8
+
+ tar.add( sources_dir, os.path.basename( sources_dir ) )
+ tar.close()
+
+ tarball_timestamp_path = os.path.join( working_dir, 'boost-%s.timestamp' % tag_suffix )
+
+ utils.log( 'Writing timestamp into "%s"...' % tarball_timestamp_path )
+ timestamp_file = open( tarball_timestamp_path, 'w' )
+ timestamp_file.write( '%f' % timestamp )
+ timestamp_file.close()
+
+ md5sum_path = os.path.join( working_dir, 'boost-%s.md5' % tag_suffix )
+ utils.log( 'Writing md5 checksum into "%s"...' % md5sum_path )
+ old_dir = os.getcwd()
+ os.chdir( os.path.dirname( tarball_path ) )
+ os.system( 'md5sum -b "%s" >"%s"' % ( os.path.basename( tarball_path ), md5sum_path ) )
+ os.chdir( old_dir )
+
+ if site_dir is not None:
+ utils.log( 'Moving "%s" to the site location "%s"...' % ( tarball_name, site_dir ) )
+ temp_site_dir = os.path.join( site_dir, 'temp' )
+ if not os.path.exists( temp_site_dir ):
+ os.mkdir( temp_site_dir )
+
+ shutil.move( tarball_path, temp_site_dir )
+ shutil.move( os.path.join( temp_site_dir, tarball_name ), site_dir )
+ shutil.move( tarball_timestamp_path, site_dir )
+ shutil.move( md5sum_path, site_dir )
+ utils.log( 'Removing "%s"...' % sources_dir )
+ rmtree( sources_dir )
+
+
+def accept_args( args ):
+ args_spec = [
+ 'working-dir='
+ , 'tag='
+ , 'user='
+ , 'site-dir='
+ , 'mail='
+ , 'help'
+ ]
+
+ options = {
+ '--tag': 'trunk'
+ , '--user': None
+ , '--site-dir': None
+ }
+
+ utils.accept_args( args_spec, args, options, usage )
+
+ return (
+ options[ '--working-dir' ]
+ , options[ '--tag' ]
+ , options[ '--user' ]
+ , options[ '--site-dir' ]
+ )
+
+
+def usage():
+ print 'Usage: %s [options]' % os.path.basename( sys.argv[0] )
+ print '''
+\t--working-dir working directory
+\t--tag snapshot tag (i.e. 'trunk')
+\t--user Boost SVN user ID (optional)
+\t--site-dir site directory to copy the snapshot to (optional)
+'''
+
+def main():
+ make_tarball( *accept_args( sys.argv[ 1: ] ) )
+
+if __name__ != '__main__': import utils
+else:
+ # in absense of relative import...
+ xsl_path = os.path.abspath( os.path.dirname( sys.argv[ 0 ] ) )
+ while os.path.basename( xsl_path ) != 'xsl_reports': xsl_path = os.path.dirname( xsl_path )
+ sys.path.append( xsl_path )
+
+ import utils
+ main()
diff --git a/tools/regression/xsl_reports/report.py b/tools/regression/xsl_reports/report.py
new file mode 100644
index 0000000000..75ee1b31bc
--- /dev/null
+++ b/tools/regression/xsl_reports/report.py
@@ -0,0 +1,371 @@
+
+# Copyright (c) MetaCommunications, Inc. 2003-2004
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import shutil
+import os.path
+import os
+import string
+import time
+import sys
+
+import utils
+import runner
+
+
+report_types = [ 'us', 'ds', 'ud', 'dd', 'l', 'p', 'x', 'i', 'n', 'ddr', 'dsr' ]
+
+if __name__ == '__main__':
+ run_dir = os.path.abspath( os.path.dirname( sys.argv[ 0 ] ) )
+else:
+ run_dir = os.path.abspath( os.path.dirname( sys.modules[ __name__ ].__file__ ) )
+
+
+def map_path( path ):
+ return os.path.join( run_dir, path )
+
+
+def xsl_path( xsl_file_name, v2 = 0 ):
+ if v2:
+ return map_path( os.path.join( 'xsl/v2', xsl_file_name ) )
+ else:
+ return map_path( os.path.join( 'xsl', xsl_file_name ) )
+
+
+def make_result_pages(
+ test_results_file
+ , expected_results_file
+ , failures_markup_file
+ , tag
+ , run_date
+ , comment_file
+ , results_dir
+ , result_prefix
+ , reports
+ , v2
+ ):
+
+ utils.log( 'Producing the reports...' )
+ __log__ = 1
+
+ output_dir = os.path.join( results_dir, result_prefix )
+ utils.makedirs( output_dir )
+
+ if comment_file != '':
+ comment_file = os.path.abspath( comment_file )
+
+ if expected_results_file != '':
+ expected_results_file = os.path.abspath( expected_results_file )
+ else:
+ expected_results_file = os.path.abspath( map_path( 'empty_expected_results.xml' ) )
+
+
+ extended_test_results = os.path.join( output_dir, 'extended_test_results.xml' )
+ if 'x' in reports:
+ utils.log( ' Merging with expected results...' )
+ utils.libxslt(
+ utils.log
+ , test_results_file
+ , xsl_path( 'add_expected_results.xsl', v2 )
+ , extended_test_results
+ , { 'expected_results_file': expected_results_file
+ , 'failures_markup_file' : failures_markup_file
+ , 'source' : tag }
+ )
+
+ links = os.path.join( output_dir, 'links.html' )
+
+ utils.makedirs( os.path.join( output_dir, 'output' ) )
+ for mode in ( 'developer', 'user' ):
+ utils.makedirs( os.path.join( output_dir, mode , 'output' ) )
+
+ if 'l' in reports:
+ utils.log( ' Making test output files...' )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'links_page.xsl', v2 )
+ , links
+ , {
+ 'source': tag
+ , 'run_date': run_date
+ , 'comment_file': comment_file
+ , 'explicit_markup_file': failures_markup_file
+ }
+ )
+
+
+ issues = os.path.join( output_dir, 'developer', 'issues.html' )
+ if 'i' in reports:
+ utils.log( ' Making issues list...' )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'issues_page.xsl', v2 )
+ , issues
+ , {
+ 'source': tag
+ , 'run_date': run_date
+ , 'comment_file': comment_file
+ , 'explicit_markup_file': failures_markup_file
+ }
+ )
+
+ for mode in ( 'developer', 'user' ):
+ if mode[0] + 'd' in reports:
+ utils.log( ' Making detailed %s report...' % mode )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'result_page.xsl', v2 )
+ , os.path.join( output_dir, mode, 'index.html' )
+ , {
+ 'links_file': 'links.html'
+ , 'mode': mode
+ , 'source': tag
+ , 'run_date': run_date
+ , 'comment_file': comment_file
+ , 'expected_results_file': expected_results_file
+ , 'explicit_markup_file' : failures_markup_file
+ }
+ )
+
+ for mode in ( 'developer', 'user' ):
+ if mode[0] + 's' in reports:
+ utils.log( ' Making summary %s report...' % mode )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'summary_page.xsl', v2 )
+ , os.path.join( output_dir, mode, 'summary.html' )
+ , {
+ 'mode' : mode
+ , 'source': tag
+ , 'run_date': run_date
+ , 'comment_file': comment_file
+ , 'explicit_markup_file' : failures_markup_file
+ }
+ )
+
+ if v2 and "ddr" in reports:
+ utils.log( ' Making detailed %s release report...' % mode )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'result_page.xsl', v2 )
+ , os.path.join( output_dir, "developer", 'index_release.html' )
+ , {
+ 'links_file': 'links.html'
+ , 'mode': "developer"
+ , 'source': tag
+ , 'run_date': run_date
+ , 'comment_file': comment_file
+ , 'expected_results_file': expected_results_file
+ , 'explicit_markup_file' : failures_markup_file
+ , 'release': "yes"
+ }
+ )
+
+ if v2 and "dsr" in reports:
+ utils.log( ' Making summary %s release report...' % mode )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'summary_page.xsl', v2 )
+ , os.path.join( output_dir, "developer", 'summary_release.html' )
+ , {
+ 'mode' : "developer"
+ , 'source': tag
+ , 'run_date': run_date
+ , 'comment_file': comment_file
+ , 'explicit_markup_file' : failures_markup_file
+ , 'release': 'yes'
+ }
+ )
+
+ if 'e' in reports:
+ utils.log( ' Generating expected_results ...' )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'produce_expected_results.xsl', v2 )
+ , os.path.join( output_dir, 'expected_results.xml' )
+ )
+
+ if v2 and 'n' in reports:
+ utils.log( ' Making runner comment files...' )
+ utils.libxslt(
+ utils.log
+ , extended_test_results
+ , xsl_path( 'runners.xsl', v2 )
+ , os.path.join( output_dir, 'runners.html' )
+ )
+
+ shutil.copyfile(
+ xsl_path( 'html/master.css', v2 )
+ , os.path.join( output_dir, 'master.css' )
+ )
+
+
+def build_xsl_reports(
+ locate_root_dir
+ , tag
+ , expected_results_file
+ , failures_markup_file
+ , comment_file
+ , results_dir
+ , result_file_prefix
+ , dont_collect_logs = 0
+ , reports = report_types
+ , v2 = 0
+ , user = None
+ , upload = False
+ ):
+
+ ( run_date ) = time.strftime( '%Y-%m-%dT%H:%M:%SZ', time.gmtime() )
+
+ test_results_file = os.path.join( results_dir, 'test_results.xml' )
+ bin_boost_dir = os.path.join( locate_root_dir, 'bin', 'boost' )
+
+ if v2:
+ import merger
+ merger.merge_logs(
+ tag
+ , user
+ , results_dir
+ , test_results_file
+ , dont_collect_logs
+ )
+ else:
+ utils.log( ' dont_collect_logs: %s' % dont_collect_logs )
+ if not dont_collect_logs:
+ f = open( test_results_file, 'w+' )
+ f.write( '<tests>\n' )
+ runner.collect_test_logs( [ bin_boost_dir ], f )
+ f.write( '</tests>\n' )
+ f.close()
+
+ make_result_pages(
+ test_results_file
+ , expected_results_file
+ , failures_markup_file
+ , tag
+ , run_date
+ , comment_file
+ , results_dir
+ , result_file_prefix
+ , reports
+ , v2
+ )
+
+ if v2 and upload:
+ upload_dir = 'regression-logs/'
+ utils.log( 'Uploading v2 results into "%s" [connecting as %s]...' % ( upload_dir, user ) )
+
+ archive_name = '%s.tar.gz' % result_file_prefix
+ utils.tar(
+ os.path.join( results_dir, result_file_prefix )
+ , archive_name
+ )
+
+ utils.sourceforge.upload( os.path.join( results_dir, archive_name ), upload_dir, user )
+ utils.sourceforge.untar( os.path.join( upload_dir, archive_name ), user, background = True )
+
+
+def accept_args( args ):
+ args_spec = [
+ 'locate-root='
+ , 'tag='
+ , 'expected-results='
+ , 'failures-markup='
+ , 'comment='
+ , 'results-dir='
+ , 'results-prefix='
+ , 'dont-collect-logs'
+ , 'reports='
+ , 'v2'
+ , 'user='
+ , 'upload'
+ , 'help'
+ ]
+
+ options = {
+ '--comment': ''
+ , '--expected-results': ''
+ , '--failures-markup': ''
+ , '--reports': string.join( report_types, ',' )
+ , '--tag': None
+ , '--user': None
+ , 'upload': False
+ }
+
+ utils.accept_args( args_spec, args, options, usage )
+ if not options.has_key( '--results-dir' ):
+ options[ '--results-dir' ] = options[ '--locate-root' ]
+
+ if not options.has_key( '--results-prefix' ):
+ if options.has_key( '--v2' ):
+ options[ '--results-prefix' ] = 'all'
+ else:
+ options[ '--results-prefix' ] = ''
+
+ return (
+ options[ '--locate-root' ]
+ , options[ '--tag' ]
+ , options[ '--expected-results' ]
+ , options[ '--failures-markup' ]
+ , options[ '--comment' ]
+ , options[ '--results-dir' ]
+ , options[ '--results-prefix' ]
+ , options.has_key( '--dont-collect-logs' )
+ , options[ '--reports' ].split( ',' )
+ , options.has_key( '--v2' )
+ , options[ '--user' ]
+ , options.has_key( '--upload' )
+ )
+
+
+def usage():
+ print 'Usage: %s [options]' % os.path.basename( sys.argv[0] )
+ print '''
+\t--locate-root the same as --locate-root in compiler_status
+\t--tag the tag for the results (i.e. 'CVS-HEAD')
+\t--expected-results the file with the results to be compared with
+\t the current run
+\t--failures-markup the file with the failures markup
+\t--comment an html comment file (will be inserted in the reports)
+\t--results-dir the directory containing -links.html, -fail.html
+\t files produced by compiler_status (by default the
+\t same as specified in --locate-root)
+\t--results-prefix the prefix of -links.html, -fail.html
+\t files produced by compiler_status
+\t--v2 v2 reports (combine multiple runners results into a
+\t single set of reports)
+
+The following options are valid only for v2 reports:
+
+\t--user SourceForge user name for a shell account
+\t--upload upload v2 reports to SourceForge
+
+The following options are useful in debugging:
+
+\t--dont-collect-logs dont collect the test logs
+\t--reports produce only the specified reports
+\t us - user summary
+\t ds - developer summary
+\t ud - user detailed
+\t dd - developer detailed
+\t l - links
+\t p - patches
+\t x - extended results file
+\t i - issues
+'''
+
+def main():
+ build_xsl_reports( *accept_args( sys.argv[ 1 : ] ) )
+
+if __name__ == '__main__':
+ main()
diff --git a/tools/regression/xsl_reports/test/common.py b/tools/regression/xsl_reports/test/common.py
new file mode 100644
index 0000000000..cd9e5729a2
--- /dev/null
+++ b/tools/regression/xsl_reports/test/common.py
@@ -0,0 +1,165 @@
+import xml.sax.saxutils
+import time
+
+def make_test_name( library_idx, test_idx ):
+ return "test_%02d_%02d" % ( library_idx, test_idx )
+
+def make_library_name( library_idx ):
+ if library_idx % 4 in ( 0, 1 ):
+ return "library_%02d/%02d" % ( int( library_idx / 4 ) * 4, library_idx % 4 )
+ else:
+ return "library_%02d" % library_idx
+
+def make_toolset_name( toolset_idx ):
+ return "toolset_%02d" % toolset_idx
+
+def make_library_target_directory( library_idx, toolset_idx, variant = None ):
+ base = "lib/%s/%s" % ( make_library_name( library_idx )
+ , make_toolset_name( toolset_idx ) )
+ if variant is not None:
+ return "%s/%s" % ( base, variant )
+ else:
+ return base
+
+def make_test_target_directory( library_idx, toolset_idx, test_name, variant ):
+ base = "%s/%s/%s" % ( make_library_name( library_idx )
+ , make_toolset_name( toolset_idx )
+ , test_name )
+ if variant is not None:
+ return "%s/%s" % ( base, variant )
+ else:
+ return base
+
+def format_timestamp( timestamp ):
+ return time.strftime( "%Y-%m-%dT%H:%M:%SZ", timestamp )
+
+def make_test_log( xml_generator
+ , library_idx
+ , toolset_idx
+ , test_name
+ , test_type
+ , test_result
+ , show_run_output
+ , variant ):
+ library = make_library_name( library_idx )
+ toolset_name = make_toolset_name( toolset_idx )
+
+ target_directory = ""
+ if test_type != "lib":
+ target_directory = make_test_target_directory( library_idx, toolset_idx, test_name, variant )
+ else:
+ target_directory = make_library_target_directory( library_idx, toolset_idx, variant )
+
+ xml_generator.startElement( "test-log", { "library": library
+ , "test-name": test_name
+ , "toolset": toolset_name
+ , "test-type": test_type
+ , "test-program": "some_program"
+ , "target-directory": target_directory
+ , "show-run-output": show_run_output
+ } )
+
+ if test_type != "lib":
+
+ if test_result == "success" and ( toolset_idx + 1 ) % 4:
+ xml_generator.startElement( "compile", { "result": "success" } );
+ xml_generator.characters( "Compiling in %s" % target_directory )
+ xml_generator.endElement( "compile" )
+
+ if test_type.find( "link" ) == 0 or test_type.find( "run" ) == 0 and toolset_idx % 4:
+ xml_generator.startElement( "lib", { "result": test_result } );
+ xml_generator.characters( make_library_target_directory( library_idx, toolset_idx ) )
+ xml_generator.endElement( "lib" )
+
+ xml_generator.startElement( "link", { "result": "success" } );
+ xml_generator.characters( "Linking in %s" % target_directory )
+ xml_generator.endElement( "link" )
+
+ if test_type.find( "run" ) == 0 and ( toolset_idx + 2 ) % 4:
+ xml_generator.startElement( "run", { "result": test_result } );
+ xml_generator.characters( "Running in %s" % target_directory )
+ xml_generator.endElement( "run" )
+
+ else:
+ xml_generator.startElement( "compile", { "result": test_result } );
+ xml_generator.characters( "Compiling in %s" % make_library_target_directory( library_idx, toolset_idx ) )
+ xml_generator.endElement( "compile" )
+
+
+
+ xml_generator.endElement( "test-log" )
+
+
+def make_expicit_failure_markup( num_of_libs, num_of_toolsets, num_of_tests ):
+ g = xml.sax.saxutils.XMLGenerator( open( "explicit-failures-markup.xml", "w" ), "utf-8" )
+ g.startDocument()
+ g.startElement( "explicit-failures-markup", {} );
+
+ # required toolsets
+ for i_toolset in range( 0, num_of_toolsets ):
+ if i_toolset < 2:
+ g.startElement( "mark-toolset", { "name": "toolset_%02d" % i_toolset, "status":"required"} )
+ g.endElement( "mark-toolset" )
+
+ for i_library in range( 0, num_of_libs ):
+ g.startElement( "library", { "name": make_library_name( i_library ) } )
+ if i_library % 4 == 0:
+ g.startElement( "mark-unusable", {} )
+ for i_toolset in range( 0, num_of_toolsets ):
+ if i_toolset % 2 == 1:
+ g.startElement( "toolset", { "name": make_toolset_name( i_toolset ) } )
+ g.endElement( "toolset" )
+ g.startElement( "note", { "author": u"T. T\xe8st" } )
+ g.characters( "Test note" )
+ g.endElement( "note" )
+ g.endElement( "mark-unusable" )
+
+ for i_test in range( 0, num_of_tests ):
+
+ category = 0
+ explicitly_marked_failure = 0
+ unresearched = 0
+
+ if i_test % 2 == 0:
+ category = i_test % 3
+
+ if i_test % 3 == 0:
+ explicitly_marked_failure = 1
+ if i_test % 2 == 0:
+ unresearched = 1
+
+ if category or explicitly_marked_failure:
+ test_attrs = { "name": make_test_name( i_library, i_test ) }
+ if category:
+ test_attrs[ "category" ] = "Category %s" % category
+ g.startElement( "test", test_attrs )
+ if explicitly_marked_failure:
+ failure_attrs = {}
+ if unresearched: failure_attrs[ "reason" ] = "not-researched"
+
+ g.startElement( "mark-failure", failure_attrs )
+
+ g.startElement( "toolset", { "name": make_toolset_name( 1 ) } )
+ g.endElement( "toolset" )
+ g.startElement( "toolset", { "name": make_toolset_name( 0 ) } )
+ g.endElement( "toolset" )
+ g.startElement( "toolset", { "name": make_toolset_name( 2 ) } )
+ g.endElement( "toolset" )
+
+ g.startElement( "note", { "author": u"V. Ann\xf3tated" } )
+ g.characters( "Some thoughtful note" )
+ g.endElement( "note" )
+
+ g.endElement( "mark-failure" )
+
+ g.endElement( "test" );
+ g.endElement( "library" )
+
+
+ g.endElement( "explicit-failures-markup" )
+ g.endDocument()
+
+
+def make_expected_results( num_of_libs, num_of_toolsets, num_of_tests ):
+ pass
+
diff --git a/tools/regression/xsl_reports/test/expected_results.xml b/tools/regression/xsl_reports/test/expected_results.xml
new file mode 100644
index 0000000000..d9fdd26cc9
--- /dev/null
+++ b/tools/regression/xsl_reports/test/expected_results.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<expected-failures>
+</expected-failures>
diff --git a/tools/regression/xsl_reports/test/generate_test_results.py b/tools/regression/xsl_reports/test/generate_test_results.py
new file mode 100644
index 0000000000..ba6a7ee39f
--- /dev/null
+++ b/tools/regression/xsl_reports/test/generate_test_results.py
@@ -0,0 +1,160 @@
+#
+# Generates test test results for testing of boost_wide_report.py
+#
+import common
+import xml.sax.saxutils
+
+import os
+import time
+
+num_of_libs = 5
+num_of_runners = 5
+num_of_toolsets = 3
+num_of_tests = 10
+
+results_directory = "results/incoming/CVS-HEAD/processed"
+
+
+# Generated results follow the rules:
+#
+# * odd runners are testing on Win32, even runners are testin on Unix
+# * the third toolset has 2 variants
+#
+
+# Generated expected markup:
+#
+# * First two toolset are required
+# * Every fourth library is unusable on event toolsets
+# * Last two tests are corner-ase tests
+# * Every 4th test is explicitly marked up as expected-failure
+
+
+def library_build_failed( library_idx ):
+ return library_idx % 2
+
+def test_run_source( runner_idx ):
+ if runner_idx % 2: return "tarball"
+ else: return "cvs head"
+
+def test_run_type( runner_idx ):
+ if runner_idx % 2: return "incremental"
+ else: return "full"
+
+
+def test_type( i ):
+ types = [ "compile", "compile_fail", "link", "link_fail", "run", "run_fail", "run_pyd" ]
+ return types[ i % len( types) ]
+
+
+def make_test_results():
+ if not os.path.exists( results_directory ):
+ os.makedirs( results_directory )
+
+ for i_runner in range( 0, num_of_runners ):
+ runner_id = "runner %02d" % i_runner
+ g = xml.sax.saxutils.XMLGenerator( open( os.path.join( results_directory, runner_id + ".xml" ), "w" ), "utf-8" )
+ g.startDocument()
+ if i_runner % 2:
+ platform = "Win32"
+ else:
+ platform = "Unix"
+
+ g.startElement( "test-run", { "platform": platform
+ , "runner": runner_id
+ , "timestamp": common.format_timestamp(
+ time.gmtime( time.time() - i_runner * 24*60*60 )
+ )
+ , "revision": '%d' % ( 7000 + i_runner )
+ , "source": test_run_source( i_runner )
+ , "run-type": test_run_type( i_runner )
+ } )
+
+ g.startElement( "comment", {} )
+ g.characters( "<b>Runner</b> is who <i>running</i> does." )
+ g.endElement( "comment" )
+
+ for i_lib in range( 0, num_of_libs ):
+ for i_toolset in range( num_of_toolsets ):
+ if library_build_failed( i_lib ): test_result = "fail"
+ else: test_result = "success"
+
+ common.make_test_log( xml_generator = g
+ , library_idx = i_lib
+ , toolset_idx = i_toolset
+ , test_name = ""
+ , test_type = "lib"
+ , test_result = test_result
+ , show_run_output = "false"
+ , variant = None )
+
+
+ for i_lib in range( 0, num_of_libs ):
+ library_name = "library_%02d" % i_lib
+ if num_of_runners - 1 == i_runner and i_lib % 2:
+ continue
+
+ for i_toolset in range( num_of_toolsets ):
+ toolset_name = "toolset %02d" % ( i_toolset )
+
+ if num_of_runners - 1 == i_runner and i_toolset % 2:
+ continue
+
+ for i_test in range( num_of_tests ):
+ test_name = "test_%02d_%02d" % ( i_lib, i_test )
+ test_result = ""
+ show_run_output = "false"
+
+ if num_of_runners - 1 == i_runner and i_test % 2:
+ continue
+
+ if i_runner % 2: test_result = "success"
+ else: test_result = "fail"
+
+ if i_runner == 1 and i_toolset == 2 and i_test % 6 == 0:
+ test_result = "fail"
+
+ if test_result == "success" and ( 0 == i_test % 5 ):
+ show_run_output = "true"
+
+ if i_toolset == 2:
+ variants = [ "static-lib", "shared-lib" ]
+ else:
+ variants = [ None ]
+
+ for variant in variants:
+ common.make_test_log( xml_generator = g
+ , library_idx = i_lib
+ , toolset_idx = i_toolset
+ , test_name = test_name
+ , test_type = test_type( i_test )
+ , test_result = test_result
+ , show_run_output = show_run_output
+ , variant = variant )
+ g.endElement( "test-run" )
+ g.endDocument()
+
+
+
+## <test-log library="algorithm" test-name="container" test-type="run" test-program="libs/algorithm/string/test/container_test.cpp" target-directory="bin/boost/libs/algorithm/string/test/container.test/borland-5.6.4/debug" toolset="borland-5.6.4" show-run-output="false">
+## <compile result="fail" timestamp="2004-06-29 17:02:27 UTC">
+
+## "C:\Progra~1\Borland\CBuilder6\bin\bcc32" -j5 -g255 -q -c -P -w -Ve -Vx -a8 -b- -v -Od -vi- -tWC -tWR -tWC -WM- -DBOOST_ALL_NO_LIB=1 -w-8001 -I"C:\Users\Administrator\boost\main\results\bin\boost\libs\algorithm\string\test" -I"C:\Users\Administrator\boost\main\boost" -I"C:\Progra~1\Borland\CBuilder6\include" -o"C:\Users\Administrator\boost\main\results\bin\boost\libs\algorithm\string\test\container.test\borland-5.6.4\debug\container_test.obj" "..\libs\algorithm\string\test\container_test.cpp"
+
+## ..\libs\algorithm\string\test\container_test.cpp:
+## Warning W8091 C:\Users\Administrator\boost\main\boost\libs/test/src/unit_test_result.cpp 323: template argument _InputIter passed to 'for_each' is a output iterator: input iterator required in function unit_test_result::~unit_test_result()
+## Warning W8091 C:\Users\Administrator\boost\main\boost\libs/test/src/unit_test_suite.cpp 63: template argument _InputIter passed to 'find_if' is a output iterator: input iterator required in function test_case::Impl::check_dependencies()
+## Warning W8091 C:\Users\Administrator\boost\main\boost\libs/test/src/unit_test_suite.cpp 204: template argument _InputIter passed to 'for_each' is a output iterator: input iterator required in function test_suite::~test_suite()
+## Error E2401 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 45: Invalid template argument list
+## Error E2040 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 46: Declaration terminated incorrectly
+## Error E2090 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 277: Qualifier 'algorithm' is not a class or namespace name
+## Error E2272 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 277: Identifier expected
+## Error E2090 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 278: Qualifier 'algorithm' is not a class or namespace name
+## Error E2228 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 278: Too many error or warning messages
+## *** 6 errors in Compile ***
+## </compile>
+## </test-log>
+
+
+make_test_results()
+common.make_expicit_failure_markup( num_of_libs, num_of_toolsets, num_of_tests )
+
diff --git a/tools/regression/xsl_reports/test/generate_test_results_v1.py b/tools/regression/xsl_reports/test/generate_test_results_v1.py
new file mode 100644
index 0000000000..0f7f8f796a
--- /dev/null
+++ b/tools/regression/xsl_reports/test/generate_test_results_v1.py
@@ -0,0 +1,85 @@
+import xml.sax.saxutils
+
+import common
+
+import os
+import time
+
+num_of_libs = 2
+num_of_toolsets = 3
+num_of_tests = 10
+
+tag = "1_30_0"
+
+def library_build_failed( library_idx ):
+ return library_idx % 2
+
+def make_test_results():
+ if not os.path.exists( tag ):
+ os.makedirs( tag )
+
+ g = xml.sax.saxutils.XMLGenerator( open( os.path.join( tag, "test.xml" ), "w" ) )
+ platform = "Win32"
+ g.startElement( "test-results", {} )
+
+ for i_lib in range( 0, num_of_libs ):
+ for i_toolset in range( num_of_toolsets ):
+ if library_build_failed( i_lib ): test_result = "fail"
+ else: test_result = "success"
+
+ common.make_test_log( xml_generator = g
+ , library_idx = i_lib
+ , toolset_idx = i_toolset
+ , test_name = ""
+ , test_type = "lib"
+ , test_result = test_result
+ , show_run_output = "false" )
+
+
+ for i_lib in range( 0, num_of_libs ):
+ library_name = "library_%02d" % i_lib
+
+ for i_toolset in range( num_of_toolsets ):
+ toolset_name = "toolset_%02d" % ( i_toolset )
+
+ for i_test in range( num_of_tests ):
+ test_name = "test_%02d_%02d" % ( i_lib, i_test )
+ test_result = ""
+ test_type = "run"
+ show_run_output = "false"
+
+ if i_lib % 2: test_result = "success"
+ else: test_result = "fail"
+
+ if test_result == "success" and ( 0 == i_test % 5 ):
+ show_run_output = "true"
+
+ common.make_test_log( g, i_lib, i_toolset, test_name, test_type, test_result, show_run_output )
+
+ g.endElement( "test-results" )
+
+
+
+
+## <test-log library="algorithm" test-name="container" test-type="run" test-program="libs/algorithm/string/test/container_test.cpp" target-directory="bin/boost/libs/algorithm/string/test/container.test/borland-5.6.4/debug" toolset="borland-5.6.4" show-run-output="false">
+## <compile result="fail" timestamp="2004-06-29 17:02:27 UTC">
+
+## "C:\Progra~1\Borland\CBuilder6\bin\bcc32" -j5 -g255 -q -c -P -w -Ve -Vx -a8 -b- -v -Od -vi- -tWC -tWR -tWC -WM- -DBOOST_ALL_NO_LIB=1 -w-8001 -I"C:\Users\Administrator\boost\main\results\bin\boost\libs\algorithm\string\test" -I"C:\Users\Administrator\boost\main\boost" -I"C:\Progra~1\Borland\CBuilder6\include" -o"C:\Users\Administrator\boost\main\results\bin\boost\libs\algorithm\string\test\container.test\borland-5.6.4\debug\container_test.obj" "..\libs\algorithm\string\test\container_test.cpp"
+
+## ..\libs\algorithm\string\test\container_test.cpp:
+## Warning W8091 C:\Users\Administrator\boost\main\boost\libs/test/src/unit_test_result.cpp 323: template argument _InputIter passed to 'for_each' is a output iterator: input iterator required in function unit_test_result::~unit_test_result()
+## Warning W8091 C:\Users\Administrator\boost\main\boost\libs/test/src/unit_test_suite.cpp 63: template argument _InputIter passed to 'find_if' is a output iterator: input iterator required in function test_case::Impl::check_dependencies()
+## Warning W8091 C:\Users\Administrator\boost\main\boost\libs/test/src/unit_test_suite.cpp 204: template argument _InputIter passed to 'for_each' is a output iterator: input iterator required in function test_suite::~test_suite()
+## Error E2401 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 45: Invalid template argument list
+## Error E2040 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 46: Declaration terminated incorrectly
+## Error E2090 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 277: Qualifier 'algorithm' is not a class or namespace name
+## Error E2272 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 277: Identifier expected
+## Error E2090 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 278: Qualifier 'algorithm' is not a class or namespace name
+## Error E2228 C:\Users\Administrator\boost\main\boost\boost/algorithm/string/finder.hpp 278: Too many error or warning messages
+## *** 6 errors in Compile ***
+## </compile>
+## </test-log>
+
+
+make_test_results( )
+common.make_expicit_failure_markup( num_of_libs, num_of_toolsets, num_of_tests )
diff --git a/tools/regression/xsl_reports/test/restrict_to_library.xsl b/tools/regression/xsl_reports/test/restrict_to_library.xsl
new file mode 100644
index 0000000000..8de3354d84
--- /dev/null
+++ b/tools/regression/xsl_reports/test/restrict_to_library.xsl
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+ <xsl:output method="xml" encoding="ascii"/>
+ <xsl:param name="library"/>
+
+
+ <xsl:template match="/">
+ <xsl:message>
+ <xsl:value-of select="$library"/>
+ </xsl:message>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="*">
+ <xsl:copy>
+ <xsl:apply-templates select="@*"/>
+ <xsl:apply-templates />
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="test-log">
+ <xsl:if test="@library=$library">
+ <xsl:copy>
+ <xsl:apply-templates select="@*"/>
+ <xsl:apply-templates/>
+ </xsl:copy>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="@*">
+ <xsl:copy-of select="."/>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/test/run_notes_regression.py b/tools/regression/xsl_reports/test/run_notes_regression.py
new file mode 100644
index 0000000000..884dcfe9db
--- /dev/null
+++ b/tools/regression/xsl_reports/test/run_notes_regression.py
@@ -0,0 +1,32 @@
+import sys
+
+sys.path.append( '..' )
+
+import os
+
+import report
+import merger
+import utils
+
+
+tag = "1_32_0"
+
+# utils.makedirs( "results" )
+
+all_xml_file = "a.xml"
+
+report.make_result_pages(
+ test_results_file = os.path.abspath( all_xml_file )
+ , expected_results_file = ""
+ , failures_markup_file = os.path.abspath( "../../../../status/explicit-failures-markup.xml" )
+ , tag = tag
+ , run_date = "Today date"
+ , comment_file = os.path.abspath( "comment.html" )
+ , results_dir = "results"
+ , result_prefix = ""
+ , reports = [ "dd" ]
+ , v2 = 1
+ )
+
+
+
diff --git a/tools/regression/xsl_reports/test/run_v1.py b/tools/regression/xsl_reports/test/run_v1.py
new file mode 100644
index 0000000000..a995ed635d
--- /dev/null
+++ b/tools/regression/xsl_reports/test/run_v1.py
@@ -0,0 +1,35 @@
+import sys
+
+sys.path.append( '..' )
+
+import os
+
+import report
+import merger
+import utils
+
+
+tag = "1_30_0"
+
+utils.makedirs( "results" )
+
+all_xml_file = "results/all.xml"
+all_xml_writer = open( all_xml_file, "w" )
+merger.merge_test_runs( ".", tag, all_xml_writer )
+all_xml_writer.close()
+
+report.make_result_pages(
+ test_results_file = os.path.abspath( all_xml_file )
+ , expected_results_file = ""
+ , failures_markup_file = os.path.abspath( "explicit-failures-markup.xml" )
+ , source = tag
+ , run_date = "Today date"
+ , comment_file = os.path.abspath( "comment.html" )
+ , results_dir = os.path.abspath( "results" )
+ , result_prefix = ""
+ , reports = [ "l", "dd" ]
+ , v2 = 0
+ )
+
+
+
diff --git a/tools/regression/xsl_reports/test/test.py b/tools/regression/xsl_reports/test/test.py
new file mode 100644
index 0000000000..1378586c1d
--- /dev/null
+++ b/tools/regression/xsl_reports/test/test.py
@@ -0,0 +1,34 @@
+import sys
+
+sys.path.append( '..' )
+
+import os
+
+import boost_wide_report
+import common
+import utils
+import shutil
+import time
+
+tag = "CVS-HEAD"
+
+if os.path.exists( "results/incoming/CVS-HEAD/processed/merged" ):
+ shutil.rmtree( "results/incoming/CVS-HEAD/processed/merged" )
+
+boost_wide_report.ftp_task = lambda ftp_site, site_path, incoming_dir: 1
+boost_wide_report.unzip_archives_task = lambda incoming_dir, processed_dir, unzip: 1
+
+boost_wide_report.execute_tasks(
+ tag = tag
+ , user = None
+ , run_date = common.format_timestamp( time.gmtime() )
+ , comment_file = os.path.abspath( "comment.html" )
+ , results_dir = os.path.abspath( "results" )
+ , output_dir = os.path.abspath( "output" )
+ , reports = [ "i", "x", "ds", "dd", "dsr", "ddr", "us", "ud", "usr", "udr" ]
+ , warnings = [ 'Warning text 1', 'Warning text 2' ]
+ , extended_test_results = os.path.abspath( "output/extended_test_results.xml" )
+ , dont_collect_logs = 1
+ , expected_results_file = os.path.abspath( "expected_results.xml" )
+ , failures_markup_file = os.path.abspath( "explicit-failures-markup.xml" )
+ )
diff --git a/tools/regression/xsl_reports/test/test_boost_wide_report.py b/tools/regression/xsl_reports/test/test_boost_wide_report.py
new file mode 100644
index 0000000000..f7d52fc2ff
--- /dev/null
+++ b/tools/regression/xsl_reports/test/test_boost_wide_report.py
@@ -0,0 +1,36 @@
+import unittest
+import sys
+import time
+
+sys.path.append( ".." )
+
+import boost_wide_report
+
+class test_boost_wide_report(unittest.TestCase):
+ def test_diff( self ):
+ test_cases = [
+ ( []
+ , []
+ , ( [], [] ) )
+ , ( [ boost_wide_report.file_info( "a", 1, time.localtime( 0 ) ) ]
+ , []
+ , ( [ "a" ], [] ) )
+ , ( []
+ , [ boost_wide_report.file_info( "a", 1, time.localtime( 0 ) ) ]
+ , ( [], [ "a" ] ) )
+ , ( [ boost_wide_report.file_info( "a", 1, time.localtime( 0 ) ) ]
+ , [ boost_wide_report.file_info( "a", 1, time.localtime( 1 ) ) ]
+ , ( [ "a" ], [] ) )
+ ]
+
+ for test_case in test_cases:
+ source_dir_content = test_case[0]
+ destination_dir_content = test_case[1]
+ expected_result = test_case[2]
+ d = boost_wide_report.diff( source_dir_content, destination_dir_content )
+ self.failUnlessEqual( d, expected_result )
+
+if __name__ == '__main__':
+ unittest.main()
+
+
diff --git a/tools/regression/xsl_reports/test_results.xsd b/tools/regression/xsl_reports/test_results.xsd
new file mode 100644
index 0000000000..bd54208488
--- /dev/null
+++ b/tools/regression/xsl_reports/test_results.xsd
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+ <!--
+ The following online services can be used to validate collected test results:
+
+ - http://apps.gotdotnet.com/xmltools/xsdvalidator/
+ - http://tools.decisionsoft.com/schemaValidate.html
+ -->
+
+ <xs:simpleType name="test_result">
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="fail"/>
+ <xs:enumeration value="succeed"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="run_test_result">
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="fail"/>
+ <xs:enumeration value="succeed"/>
+ <xs:enumeration value="note"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="test_type">
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="compile"/>
+ <xs:enumeration value="compile_fail"/>
+ <xs:enumeration value="lib"/>
+ <xs:enumeration value="pyd"/>
+ <xs:enumeration value="run"/>
+ <xs:enumeration value="run_fail"/>
+ <xs:enumeration value="run_pyd"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:element name="compile">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="result" type="test_result" use="required"/>
+ <xs:attribute name="timestamp" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="link">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="result" type="test_result" use="required"/>
+ <xs:attribute name="timestamp" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="lib">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="result" type="test_result" use="required"/>
+ <xs:attribute name="timestamp" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="run">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="result" type="run_test_result" use="required"/>
+ <xs:attribute name="timestamp" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="test-log">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="compile" minOccurs="0"/>
+ <xs:element ref="link" minOccurs="0"/>
+ <xs:element ref="run" minOccurs="0"/>
+ <xs:element ref="lib" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="library" type="xs:string" use="required"/>
+ <xs:attribute name="test-name" type="xs:string" use="required"/>
+ <xs:attribute name="test-type" type="test_type" use="required"/>
+ <xs:attribute name="test-program" type="xs:string" use="required"/>
+ <xs:attribute name="target-directory" type="xs:string" use="required"/>
+ <xs:attribute name="toolset" type="xs:string" use="required"/>
+ <xs:attribute name="show-run-output" type="xs:boolean" use="required"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="tests">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="test-log" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
diff --git a/tools/regression/xsl_reports/utils/__init__.py b/tools/regression/xsl_reports/utils/__init__.py
new file mode 100644
index 0000000000..6d542083d9
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/__init__.py
@@ -0,0 +1,13 @@
+
+from accept_args import *
+from char_translation_table import *
+from check_existance import *
+from checked_system import *
+from libxslt import *
+from log import *
+from makedirs import *
+from rename import *
+from tar import *
+from zip import *
+
+import sourceforge
diff --git a/tools/regression/xsl_reports/utils/accept_args.py b/tools/regression/xsl_reports/utils/accept_args.py
new file mode 100644
index 0000000000..b08739f40b
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/accept_args.py
@@ -0,0 +1,30 @@
+
+import getopt
+import re
+import sys
+
+def accept_args( args_spec, args, options, usage ):
+
+ defaults_num = len(options)
+
+ ( option_pairs, rest_args ) = getopt.getopt( args, '', args_spec )
+ map( lambda x: options.__setitem__( x[0], x[1] ), option_pairs )
+
+ if ( options.has_key( '--help' ) or len( options.keys() ) == defaults_num ):
+ usage()
+ sys.exit( 1 )
+
+ if len( rest_args ) > 0 and rest_args[0][0] == '@':
+ f = open( rest_args[0][1:], 'r' )
+ config_lines = f.read().splitlines()
+ f.close()
+ for l in config_lines:
+ if re.search( r'^\s*#', l ): continue
+ if re.search( r'^\s*$', l ): continue
+ m = re.match( r'^(?P<name>.*?)=(?P<value>.*)', l )
+ if m:
+ options[ '--%s' % m.group( 'name' ) ] = m.group( 'value' )
+ else:
+ raise 'Invalid format of config line "%s"' % l
+
+ return rest_args
diff --git a/tools/regression/xsl_reports/utils/char_translation_table.py b/tools/regression/xsl_reports/utils/char_translation_table.py
new file mode 100644
index 0000000000..c2d8fb6c95
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/char_translation_table.py
@@ -0,0 +1,13 @@
+
+import string
+
+def chr_or_question_mark( c ):
+ if chr(c) in string.printable and c < 128 and c not in ( 0x09, 0x0b, 0x0c ):
+ return chr(c)
+ else:
+ return '?'
+
+char_translation_table = string.maketrans(
+ ''.join( map( chr, range(0, 256) ) )
+ , ''.join( map( chr_or_question_mark, range(0, 256) ) )
+ )
diff --git a/tools/regression/xsl_reports/utils/check_existance.py b/tools/regression/xsl_reports/utils/check_existance.py
new file mode 100644
index 0000000000..9e3d0e7b21
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/check_existance.py
@@ -0,0 +1,9 @@
+
+import os
+
+def check_existance( name ):
+ a = os.popen( '%s --version' % name )
+ output = a.read()
+ rc = a.close()
+ if rc is not None:
+ raise Exception( '"%s" is required' % name )
diff --git a/tools/regression/xsl_reports/utils/checked_system.py b/tools/regression/xsl_reports/utils/checked_system.py
new file mode 100644
index 0000000000..bdb8e8f8e6
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/checked_system.py
@@ -0,0 +1,22 @@
+
+import os
+import string
+import sys
+
+def system( commands ):
+ if sys.platform == 'win32':
+ f = open( 'tmp.cmd', 'w' )
+ f.write( string.join( commands, '\n' ) )
+ f.close()
+ rc = os.system( 'tmp.cmd' )
+ return rc
+ else:
+ rc = os.system( '&&'.join( commands ) )
+ return rc
+
+
+def checked_system( commands, valid_return_codes = [ 0 ] ):
+ rc = system( commands )
+ if rc not in [ 0 ] + valid_return_codes:
+ raise Exception( 'Command sequence "%s" failed with return code %d' % ( commands, rc ) )
+ return rc
diff --git a/tools/regression/xsl_reports/utils/libxslt.py b/tools/regression/xsl_reports/utils/libxslt.py
new file mode 100644
index 0000000000..d9184100e2
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/libxslt.py
@@ -0,0 +1,49 @@
+
+# Copyright (c) MetaCommunications, Inc. 2003-2007
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import utils.makedirs
+import utils.rename
+import os.path
+import os
+import sys
+
+
+def xslt_param( path, replace_spaces = 1 ):
+ path = path.replace( '\\', '/' )
+ if sys.platform == 'win32' and replace_spaces:
+ path = path.replace( ' ', '%20' )
+ return path
+
+
+def libxslt( log, xml_file, xsl_file, output_file, parameters = None ):
+
+ utils.makedirs( os.path.dirname( output_file ) )
+
+ if sys.platform == 'win32':
+ os.chdir( os.path.dirname( xsl_file ) )
+
+ transform_command = 'xsltproc'
+ transform_command = transform_command + ' -o ' + '"%s"' % xslt_param( output_file )
+
+ if parameters is not None:
+ for i in parameters:
+ if parameters[i]:
+ parameters[i] = xslt_param( parameters[i] )
+ transform_command = transform_command + ' --param %s "\'%s\'" ' % ( i, parameters[ i ] )
+
+ transform_command = transform_command + ' "%s" ' % xslt_param( xsl_file )
+ transform_command = transform_command + ' "%s" ' % xslt_param( xml_file )
+ log( transform_command )
+ rc = os.system( transform_command )
+ if rc != 0:
+ raise Exception( '"%s" failed with return code %d' % ( transform_command, rc ) )
+
+ output_file = xslt_param( output_file, 0 )
+ xlst_output_file = xslt_param( output_file )
+ if output_file != xlst_output_file and os.path.exists( xlst_output_file ):
+ utils.rename( log, xlst_output_file, output_file )
+
diff --git a/tools/regression/xsl_reports/utils/log.py b/tools/regression/xsl_reports/utils/log.py
new file mode 100644
index 0000000000..28b1366f88
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/log.py
@@ -0,0 +1,18 @@
+
+import inspect
+import sys
+
+def log_level():
+ frames = inspect.stack()
+ level = 0
+ for i in frames[ 3: ]:
+ if i[0].f_locals.has_key( '__log__' ):
+ level = level + i[0].f_locals[ '__log__' ]
+ return level
+
+
+def stdlog( message ):
+ sys.stderr.write( '# ' + ' ' * log_level() + message + '\n' )
+ sys.stderr.flush()
+
+log = stdlog
diff --git a/tools/regression/xsl_reports/utils/makedirs.py b/tools/regression/xsl_reports/utils/makedirs.py
new file mode 100644
index 0000000000..94b68d32f1
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/makedirs.py
@@ -0,0 +1,7 @@
+
+import os.path
+import os
+
+def makedirs( path ):
+ if not os.path.exists( path ):
+ os.makedirs( path )
diff --git a/tools/regression/xsl_reports/utils/rename.py b/tools/regression/xsl_reports/utils/rename.py
new file mode 100644
index 0000000000..95fb36ff48
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/rename.py
@@ -0,0 +1,17 @@
+
+# Copyright (c) MetaCommunications, Inc. 2003-2007
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import os.path
+import os
+
+
+def rename( log, src, dst ):
+ log( 'Renaming %s to %s' % ( src, dst ) )
+ if os.path.exists( dst ):
+ os.unlink( dst )
+
+ os.rename( src, dst )
diff --git a/tools/regression/xsl_reports/utils/send_mail.py b/tools/regression/xsl_reports/utils/send_mail.py
new file mode 100644
index 0000000000..d0ed98fd18
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/send_mail.py
@@ -0,0 +1,13 @@
+
+import smtplib
+
+def send_mail( mail, subject, msg = '' ):
+ smtp_server = smtplib.SMTP( 'mail.%s' % mail.split( '@' )[-1] )
+ smtp_server.sendmail(
+ mail
+ , [ mail ]
+ , 'Subject: %s\n' % subject
+ + 'To: %s\n' % mail
+ + '\n'
+ + msg
+ )
diff --git a/tools/regression/xsl_reports/utils/sourceforge.py b/tools/regression/xsl_reports/utils/sourceforge.py
new file mode 100644
index 0000000000..0c6b085286
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/sourceforge.py
@@ -0,0 +1,48 @@
+
+import utils.checked_system
+import os
+import sys
+
+site_dir = '/home/groups/b/bo/boost/htdocs/'
+
+def download( source, destination, user ):
+ if sys.platform == 'win32':
+ destination = os.popen( 'cygpath "%s"' % destination ).read().splitlines()[0]
+
+ utils.checked_system( [
+ 'rsync -v -r -z --progress %(user)s@shell.sourceforge.net:%(site_dir)s%(source)s %(dest)s'
+ % { 'user': user, 'site_dir': site_dir, 'source': source, 'dest': destination }
+ ] )
+
+
+def upload( source, destination, user ):
+ if sys.platform == 'win32':
+ source = os.popen( 'cygpath "%s"' % source ).read().splitlines()[0]
+
+ utils.checked_system( [
+ 'rsync -v -r -z --progress %(source)s %(user)s@shell.sourceforge.net:%(site_dir)s%(dest)s'
+ % { 'user': user, 'site_dir': site_dir, 'source': source, 'dest': destination }
+ ] )
+
+
+def checked_system( commands, user, background = False ):
+ if not background:
+ cmd = 'ssh -l %s shell.sourceforge.net "%s"'
+ else:
+ cmd = 'ssh -f -l %s shell.sourceforge.net "%s"'
+
+ utils.checked_system(
+ [ cmd % ( user, '&&'.join( commands ) ) ]
+ )
+
+
+def untar( archive, user, background ):
+ checked_system(
+ [
+ 'cd %s' % os.path.join( site_dir, os.path.dirname( archive ) )
+ , 'tar -x -z --overwrite --mode=+w -f %s' % os.path.basename( archive )
+ , 'rm -f %s' % archive
+ ]
+ , user = user
+ , background = background
+ )
diff --git a/tools/regression/xsl_reports/utils/tar.py b/tools/regression/xsl_reports/utils/tar.py
new file mode 100644
index 0000000000..19deb1992b
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/tar.py
@@ -0,0 +1,16 @@
+
+import utils.checked_system
+import os.path
+
+def tar( source_dir, archive_name ):
+ utils.checked_system( [
+ 'cd %s' % source_dir
+ , 'tar -c -f ../%s -z *' % archive_name
+ ] )
+
+def untar( archive_path ):
+ #utils.checked_system( [ 'tar -xjf "%s"' % archive_path ] )
+ utils.checked_system( [
+ 'cd %s' % os.path.dirname( archive_path )
+ , 'tar -xjf "%s"' % os.path.basename( archive_path )
+ ] )
diff --git a/tools/regression/xsl_reports/utils/zip.py b/tools/regression/xsl_reports/utils/zip.py
new file mode 100644
index 0000000000..7473aa0051
--- /dev/null
+++ b/tools/regression/xsl_reports/utils/zip.py
@@ -0,0 +1,12 @@
+
+import zipfile
+import os.path
+
+def unzip( archive_path, result_dir ):
+ z = zipfile.ZipFile( archive_path, 'r', zipfile.ZIP_DEFLATED )
+ for f in z.infolist():
+ result = open( os.path.join( result_dir, f.filename ), 'wb' )
+ result.write( z.read( f.filename ) )
+ result.close()
+
+ z.close()
diff --git a/tools/regression/xsl_reports/xsl/add_expected_results.xsl b/tools/regression/xsl_reports/xsl/add_expected_results.xsl
new file mode 100644
index 0000000000..6771f0034f
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/add_expected_results.xsl
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:meta="http://www.meta-comm.com"
+ exclude-result-prefixes="meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="xml" encoding="utf-8"/>
+
+ <xsl:param name="expected_results_file"/>
+ <xsl:param name="failures_markup_file"/>
+ <xsl:variable name="expected_results" select="document( $expected_results_file )" />
+ <xsl:variable name="failures_markup" select="document( $failures_markup_file )" />
+
+ <xsl:template match="/">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="test-log">
+ <xsl:variable name="library" select="@library"/>
+ <xsl:variable name="test-name" select="@test-name"/>
+ <xsl:variable name="toolset" select="@toolset"/>
+
+ <xsl:element name="{local-name()}">
+ <xsl:apply-templates select="@*"/>
+
+ <xsl:variable name="actual_result">
+ <xsl:choose>
+ <!-- Hack: needs to be researched (and removed). See M.Wille's incident. -->
+ <xsl:when test="run/@result='succeed' and lib/@result='fail'">
+ <xsl:text>success</xsl:text>
+ </xsl:when>
+ <xsl:when test="./*/@result = 'fail'" >
+ <xsl:text>fail</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>success</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="expected_results_test_case" select="$expected_results//*/test-result[ @library=$library and ( @test-name=$test-name or @test-name='*' ) and @toolset = $toolset]"/>
+ <xsl:variable name="new_failures_markup" select="$failures_markup//library[@name=$library]/mark-expected-failures[ meta:re_match( test/@name, $test-name ) and meta:re_match( toolset/@name, $toolset ) ]"/>
+ <xsl:variable name="failures_markup" select="$failures_markup//library[@name=$library]/test[ meta:re_match( @name, $test-name ) ]/mark-failure[ meta:re_match( toolset/@name, $toolset ) ]"/>
+ <xsl:variable name="is_new">
+ <xsl:choose>
+ <xsl:when test="$expected_results_test_case">
+ <xsl:text>no</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>yes</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="expected_result">
+ <xsl:choose>
+ <xsl:when test='count( $failures_markup ) &gt; 0 or count( $new_failures_markup ) &gt; 0'>
+ <xsl:text>fail</xsl:text>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$expected_results_test_case and $expected_results_test_case/@result = 'fail'">
+ <xsl:text>fail</xsl:text>
+ </xsl:when>
+
+ <xsl:otherwise>success</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="status">
+ <xsl:choose>
+ <xsl:when test="count( $failures_markup ) &gt; 0 or count( $new_failures_markup ) &gt; 0">
+ <xsl:choose>
+ <xsl:when test="$expected_result = $actual_result">expected</xsl:when>
+ <xsl:otherwise>unexpected</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$expected_result = $actual_result">expected</xsl:when>
+ <xsl:otherwise>unexpected</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="notes">
+ <xsl:choose>
+
+ <xsl:when test='count( $failures_markup ) &gt; 0'>
+ <xsl:for-each select="$failures_markup/note">
+ <xsl:copy-of select="."/>
+ </xsl:for-each>
+ </xsl:when>
+
+ <xsl:when test='count( $new_failures_markup ) &gt; 0'>
+ <xsl:for-each select="$new_failures_markup/note">
+ <xsl:copy-of select="."/>
+ </xsl:for-each>
+ </xsl:when>
+
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:attribute name="result"><xsl:value-of select="$actual_result"/></xsl:attribute>
+ <xsl:attribute name="expected-result"><xsl:value-of select="$expected_result"/></xsl:attribute>
+ <xsl:attribute name="status"><xsl:value-of select="$status"/></xsl:attribute>
+ <xsl:attribute name="is-new"><xsl:value-of select="$is_new"/></xsl:attribute>
+ <!--<a><xsl:value-of select="count( $failures_markup )"/></a>-->
+ <xsl:element name="notes"><xsl:copy-of select="$notes"/></xsl:element>
+
+
+ <xsl:apply-templates select="node()" />
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="*">
+ <xsl:element name="{local-name()}">
+ <xsl:apply-templates select="@*"/>
+ <xsl:apply-templates select="node()" />
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="@*">
+ <xsl:copy-of select="." />
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/common.xsl b/tools/regression/xsl_reports/xsl/common.xsl
new file mode 100644
index 0000000000..0029eeaebb
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/common.xsl
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func"
+ version="1.0">
+
+ <xsl:variable name="output_directory" select="'output'"/>
+
+ <xsl:template name="get_toolsets">
+ <xsl:param name="toolsets"/>
+ <xsl:param name="required-toolsets"/>
+
+ <xsl:variable name="toolset_output">
+ <xsl:for-each select="$toolsets">
+ <xsl:variable name="toolset" select="."/>
+ <xsl:element name="toolset">
+ <xsl:attribute name="toolset"><xsl:value-of select="$toolset"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$required_toolsets[ $toolset = @name ]">
+ <xsl:attribute name="required">yes</xsl:attribute>
+ <xsl:attribute name="sort">a</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="required">no</xsl:attribute>
+ <xsl:attribute name="sort">z</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:for-each select="exsl:node-set( $toolset_output )/toolset">
+ <xsl:sort select="concat( @sort, ' ', @toolset)" order="ascending"/>
+ <xsl:copy-of select="."/>
+ </xsl:for-each>
+
+ </xsl:template>
+
+ <func:function name="meta:show_output">
+ <xsl:param name="explicit_markup"/>
+ <xsl:param name="test_log"/>
+ <func:result select="$test_log/@result != 'success' and not( meta:is_unusable( $explicit_markup, $test_log/@library, $test_log/@toolset )) or $test_log/@show-run-output = 'true'"/>
+ </func:function>
+
+ <func:function name="meta:is_test_log_a_test_case">
+ <xsl:param name="test_log"/>
+ <func:result select="$test_log/@test-type='compile' or $test_log/@test-type='compile_fail' or $test_log/@test-type='run' or $test_log/@test-type='run_pyd'"/>
+ </func:function>
+
+ <func:function name="meta:is_unusable">
+ <xsl:param name="explicit_markup"/>
+ <xsl:param name="library"/>
+ <xsl:param name="toolset"/>
+
+ <func:result select="$explicit_markup//library[ @name = $library ]/mark-unusable[ toolset/@name = $toolset or toolset/@name='*' ]"/>
+ </func:function>
+
+ <func:function name="meta:re_match">
+ <xsl:param name="pattern"/>
+ <xsl:param name="text"/>
+
+ <xsl:choose>
+ <xsl:when test="not( contains( $pattern, '*' ) )">
+ <func:result select="$text = $pattern"/>
+ </xsl:when>
+ <xsl:when test="$pattern = '*'">
+ <func:result select="1 = 1"/>
+ </xsl:when>
+ <xsl:when test="substring( $pattern, 1, 1 ) = '*' and substring( $pattern, string-length($pattern), 1 ) = '*' ">
+ <func:result select="contains( $text, substring( $pattern, 2, string-length($pattern) - 2 ) ) "/>
+ </xsl:when>
+ <xsl:when test="substring( $pattern, 1, 1 ) = '*'">
+ <xsl:variable name="pattern_tail" select="substring( $pattern, 2, string-length($pattern) - 1 )"/>
+ <func:result select="substring( $text, string-length($text) - string-length($pattern_tail) + 1, string-length($pattern_tail) ) = $pattern_tail"/>
+ </xsl:when>
+ <xsl:when test="substring( $pattern, string-length($pattern), 1 ) = '*' ">
+ <xsl:variable name="pattern_head" select="substring( $pattern, 1, string-length($pattern) - 2 )"/>
+ <func:result select="substring( $text, 1, string-length($pattern_head) ) = $pattern_head "/>
+ </xsl:when>
+ </xsl:choose>
+ </func:function>
+
+ <func:function name="meta:encode_path">
+ <xsl:param name="path"/>
+ <func:result select="translate( translate( $path, '/', '-' ), './', '-' )"/>
+ </func:function>
+
+ <func:function name="meta:toolset_name">
+ <xsl:param name="name"/>
+ <func:result select="$name"/>
+ </func:function>
+
+ <func:function name="meta:output_file_path">
+ <xsl:param name="path"/>
+ <func:result select="concat( $output_directory, '/', meta:encode_path( $path ), '.html' )"/>
+ </func:function>
+
+ <xsl:template name="show_notes">
+ <xsl:param name="explicit_markup"/>
+ <xsl:param name="notes"/>
+ <div class="notes">
+ <xsl:for-each select="$notes">
+ <div>
+ <xsl:variable name="refid" select="@refid"/>
+ <xsl:call-template name="show_note">
+ <xsl:with-param name="note" select="."/>
+ <xsl:with-param name="reference" select="$explicit_markup//note[ $refid = @id ]"/>
+ </xsl:call-template>
+ </div>
+ </xsl:for-each>
+ </div>
+ </xsl:template>
+
+ <xsl:template name="show_note">
+ <xsl:param name="note"/>
+ <xsl:param name="reference"/>
+ <div class="note">
+ <xsl:variable name="author">
+ <xsl:choose>
+ <xsl:when test="$note/@author">
+ <xsl:value-of select="$note/@author"/>
+ </xsl:when>
+ <xsl:when test="$reference">
+ <xsl:value-of select="$reference/@author"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="date">
+ <xsl:choose>
+ <xsl:when test="$note/@date">
+ <xsl:value-of select="$note/@date"/>
+ </xsl:when>
+ <xsl:when test="$reference">
+ <xsl:value-of select="$reference/@date"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <span class="note-header">
+ <xsl:choose>
+ <xsl:when test="$author != '' and $date != ''">
+ [&#160;<xsl:value-of select="$author"/>&#160;<xsl:value-of select="$date"/>&#160;]
+ </xsl:when>
+ <xsl:when test="$author != ''">
+ [&#160;<xsl:value-of select="$author"/>&#160;]
+ </xsl:when>
+ <xsl:when test="$date != ''">
+ [&#160;<xsl:value-of select="$date"/>&#160;]
+ </xsl:when>
+ </xsl:choose>
+ </span>
+
+ <xsl:if test="$reference">
+ <xsl:copy-of select="$reference/node()"/>
+ </xsl:if>
+ <xsl:copy-of select="$note/node()"/>
+
+ </div>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/html/issues_legend.html b/tools/regression/xsl_reports/xsl/html/issues_legend.html
new file mode 100644
index 0000000000..6274048b55
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/html/issues_legend.html
@@ -0,0 +1,36 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<div class="legend">
+<table border="0" summary="report description">
+<tr>
+ <td>
+ <table border="0" summary="legend">
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected new fail legend">
+ <tr class="library-row-single"><td class="library-fail-unexpected-new">&lt;toolset&gt;</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">Failure on a newly added test/compiler.</td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected fail legend">
+ <tr class="library-row-single"><td class="library-fail-unexpected">&lt;toolset&gt;</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">Unexpected failure.</td>
+ </tr>
+ </table>
+ </td>
+</tr>
+</table>
+</div>
diff --git a/tools/regression/xsl_reports/xsl/html/library_developer_legend.html b/tools/regression/xsl_reports/xsl/html/library_developer_legend.html
new file mode 100644
index 0000000000..405e52ab4b
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/html/library_developer_legend.html
@@ -0,0 +1,72 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<div class="legend">
+<table border="0" summary="report description">
+<tr>
+ <td>
+ <table border="0" summary="legend">
+ <tr>
+ <td>
+ <table width="100%" summary="success legend">
+ <tr class="library-row-single"><td class="library-success-expected">pass</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">Success.</td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected pass legend">
+ <tr class="library-row-single"><td class="library-success-unexpected">pass</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">Unexpected success.</td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="expected fail legend">
+ <tr class="library-row-single"><td class="library-fail-expected">fail</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">Expected failure.</td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <table border="0" summary="legend">
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected new fail legend">
+ <tr class="library-row-single"><td class="library-fail-unexpected-new">fail</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">Failure on a newly added test/compiler.</td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected fail legend">
+ <tr class="library-row-single"><td class="library-fail-unexpected">fail</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">Unexpected failure.</td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="unusable legend">
+ <tr class="library-row-single"><td class="library-unusable">n/a</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">The library author marked it as unusable on particular platform/toolset.</td>
+ </tr>
+ </table>
+ </td>
+</tr>
+</table>
+</div>
diff --git a/tools/regression/xsl_reports/xsl/html/library_user_legend.html b/tools/regression/xsl_reports/xsl/html/library_user_legend.html
new file mode 100644
index 0000000000..5175f04271
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/html/library_user_legend.html
@@ -0,0 +1,65 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<div class="legend">
+<table border="0" summary="report description">
+<tr>
+ <td>
+ <table border="0" summary="legend">
+ <tr>
+ <td>
+ <table width="100%" summary="success legend">
+ <tr class="library-row-single"><td class="library-user-success">pass</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ The test passes.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="fail legend">
+ <tr class="library-row-single"><td class="library-user-fail-expected">fail</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ A known test failure; click on the link to see the log.
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <table border="0" summary="legend">
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected fail legend">
+ <tr class="library-row-single"><td class="library-user-fail-unexpected">unexp.</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ The test is known to pass, but is currently failing;
+ click on the link to see the log.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="unusable legend">
+ <tr class="library-row-single"><td class="library-unusable">n/a</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ The library author marked it as unusable on particular platform/toolset.
+ </td>
+ </tr>
+ </table>
+ </td>
+</tr>
+</table>
+</div>
diff --git a/tools/regression/xsl_reports/xsl/html/make_tinyurl.html b/tools/regression/xsl_reports/xsl/html/make_tinyurl.html
new file mode 100644
index 0000000000..2de8830106
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/html/make_tinyurl.html
@@ -0,0 +1,24 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<div class="tinyurl">
+
+<script type="text/javascript">
+<!--
+function make_tinyurl()
+{
+ window.open( 'http://tinyurl.com/create.php?url=' + parent.location.href );
+}
+//-->
+</script>
+
+<a href="javascript:make_tinyurl()">TinyUrl</a>
+
+</div>
diff --git a/tools/regression/xsl_reports/xsl/html/master.css b/tools/regression/xsl_reports/xsl/html/master.css
new file mode 100644
index 0000000000..8e643efebf
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/html/master.css
@@ -0,0 +1,525 @@
+/*
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+*/
+
+/* All reports */
+
+body
+{
+ background-color: white;
+}
+
+body.user-toc
+{
+ background-color: #f0f0f0;
+}
+
+body.developer-toc
+{
+ background-color: #f0f5ff;
+}
+
+span.super
+{
+ vertical-align: super;
+ font-size: 80%;
+ margin-left: 3pt;
+}
+
+h1.page-title
+{
+ text-align: left;
+ text-transform: capitalize;
+ margin-top: 10pt;
+ margin-bottom: 10pt;
+}
+
+img
+{
+ display: inline;
+}
+
+ a.hover-link:link
+,a.hover-link:visited
+,a.hover-link:active
+{
+ color: black;
+ text-decoration: none;
+}
+
+a.hover-link:hover
+{
+ color: black;
+ text-decoration: underline;
+}
+
+div.legend
+{
+ width: 80%;
+ background-color: #f5f5f5;
+ margin-top: 10pt;
+}
+
+div.comment
+{
+ width: 80%;
+ background-color: #f5f5f5;
+ padding-left: 10pt;
+ padding-right: 10pt;
+ padding-bottom: 10pt;
+}
+
+div.tinyurl
+{
+ margin-top: 10pt;
+}
+
+table.header-table
+{
+ margin-left: 10pt;
+ margin-top: 20pt;
+ margin-bottom: 10pt;
+ width: 80%;
+}
+
+td.header-item
+{
+ text-align: left;
+ vertical-align: top;
+ font-weight: bold;
+}
+
+td.header-item-content
+{
+ padding-left: 20pt;
+ padding-bottom: 10pt;
+}
+
+td.legend-item
+{
+ padding-left: 5pt;
+/* padding-top: 2pt;*/
+}
+
+div.acknowledgement
+{
+ text-align: left;
+ margin-top: 10pt;
+ margin-left: 5pt;
+ margin-bottom: 10pt;
+}
+
+div.report-info
+{
+ text-align: left;
+ margin-bottom: 10pt;
+ width: 80%;
+}
+
+div.purpose
+{
+ text-align: left;
+ margin-left: 5pt;
+ margin-top: 10pt;
+}
+
+
+div.library-name
+{
+ margin-top: 20pt;
+ margin-bottom: 10pt;
+ text-align: left;
+ font-size: 125%;
+ font-weight: bold;
+}
+
+table.summary-table
+,table.library-table
+{
+ border-collapse: collapse;
+ border: 2px solid black;
+ margin: 5px;
+}
+
+ table.summary-table td
+,table.library-table td
+{
+ text-align: center;
+ border-left: 1px solid black;
+ border-right: 1px solid black;
+}
+
+ a.log-link:link
+,a.log-link:visited
+{
+ color: black;
+/* text-decoration: none; */
+}
+
+ a.log-link:active
+,a.log-link:hover
+,a.legend-link:link
+,a.legend-link:visited
+,a.legend-link:active
+,a.legend-link:hover
+{
+ color: black;
+ text-decoration: underline;
+}
+
+ td.toolset-name
+,td.required-toolset-name
+{
+ vertical-align: middle;
+ padding-left: 3pt;
+ padding-right: 3pt;
+ word-spacing: -3pt;
+}
+
+td.required-toolset-name
+{
+ font-weight: bold;
+}
+
+td.library-corner-case-header
+{
+}
+
+tr.summary-row-first td
+, tr.library-row-first td
+{
+ border-top: 1px solid gray;
+ border-bottom: 0px;
+}
+
+tr.summary-row-last td
+, tr.library-row-last td
+{
+ border-top: 0px;
+ border-bottom: 1px solid gray;
+}
+
+tr.summary-row-single td
+, tr.library-row-single td
+{
+ border-top: 1px solid gray;
+ border-bottom: 1px solid gray;
+}
+
+tr.summary-row td
+, tr.library-row td
+{
+ border-bottom: 0px;
+ border-top: 0px;
+}
+
+ td.library-success-expected
+,td.library-fail-expected
+,td.library-user-fail-expected
+,td.library-user-success
+,td.summary-expected
+,td.summary-user-fail-expected
+,td.summary-user-success
+,td.summary-unknown-status
+{
+ width: 60pt;
+ text-align: center;
+ background-color: lightgreen;
+ border-left: 1px solid black;
+ border-right: 1px solid black;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+td.summary-unknown-status
+{
+ background-color: white;
+}
+
+ td.library-success-unexpected
+,td.summary-success-unexpected
+{
+ width: 60pt;
+ text-align: center;
+ background-color: green;
+ font-weight: bold;
+ color: white;
+ border: 0px;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+
+ tr.summary-row td.summary-fail-unexpected
+,tr.summary-row-first td.summary-fail-unexpected
+,tr.summary-row-last td.summary-fail-unexpected
+,tr.summary-row-single td.summary-fail-unexpected
+
+,tr.summary-row td.summary-user-fail-unexpected
+,tr.summary-row-first td.summary-user-fail-unexpected
+,tr.summary-row-last td.summary-user-fail-unexpected
+,tr.summary-row-single td.summary-user-fail-unexpected
+
+,tr.library-row td.library-user-fail-unexpected
+,tr.library-row-first td.library-user-fail-unexpected
+,tr.library-row-last td.library-user-fail-unexpected
+,tr.library-row-single td.library-user-fail-unexpected
+{
+ width: 60pt;
+ text-align: center;
+ background-color: red;
+ color: black;
+ border: 2px solid black;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+ tr.summary-row td.summary-missing
+, tr.summary-row-first td.summary-missing
+, tr.summary-row-last td.summary-missing
+, tr.summary-row-single td.summary-missing
+
+, tr.library-row td.library-missing
+, tr.library-row-first td.library-missing
+, tr.library-row-last td.library-missing
+, tr.library-row-single td.library-missing
+{
+ width: 60pt;
+ text-align: center;
+ background-color: white;
+ color: black;
+ border: 2px solid black;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+ tr.summary-row td.summary-unusable
+, tr.summary-row-first td.summary-unusable
+, tr.summary-row-last td.summary-unusable
+, tr.summary-row-single td.summary-unusable
+
+, tr.library-row td.library-unusable
+, tr.library-row-first td.library-unusable
+, tr.library-row-last td.library-unusable
+, tr.library-row-single td.library-unusable
+{
+ width: 60pt;
+ text-align: center;
+ background-color: silver;
+ color: black;
+ border-top: 2px solid black;
+ border-bottom: 2px solid black;
+ border-left: 2px solid black;
+ border-right: 2px solid black;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+/* Summary */
+
+table.summary-table td.library-name
+{
+ width: 100pt;
+ padding: 0pt;
+ border-top: 1px solid gray;
+ border-bottom: 1px solid gray;
+}
+
+ tr.summary-row td.summary-user-fail-unexpected
+, tr.summary-row-first td.summary-user-fail-unexpected
+, tr.summary-row-last td.summary-user-fail-unexpected
+, tr.summary-row-single td.summary-user-fail-unexpected
+{
+ width: 60pt;
+ text-align: center;
+ background-color: yellow;
+ color: black;
+ border: 2px solid black;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+ tr.summary-row td.summary-fail-unexpected-new
+, tr.summary-row-first td.summary-fail-unexpected-new
+, tr.summary-row-last td.summary-fail-unexpected-new
+, tr.summary-row-single td.summary-fail-unexpected-new
+
+, tr.library-row td.library-fail-unexpected-new
+, tr.library-row-first td.library-fail-unexpected-new
+, tr.library-row-last td.library-fail-unexpected-new
+, tr.library-row-single td.library-fail-unexpected-new
+{
+ width: 60pt;
+ text-align: center;
+ background-color: yellow;
+ color: black;
+ border: 2px solid black;
+}
+
+/* Detailed */
+
+.library-conf-problem
+{
+ font-size: 70%;
+ font-weight: normal;
+}
+
+div.library-toc
+{
+ margin: 5pt;
+}
+
+
+li.library-toc-entry
+{
+ margin-left: 5pt;
+ list-style-type: square;
+}
+
+
+div.library-footer
+{
+ margin: 5px;
+}
+
+
+table.library-table td.test-name
+{
+ width: 150pt;
+ padding-left: 6pt;
+ padding-right: 6pt;
+ border-right: 0;
+ border-top: 1px solid gray;
+ border-bottom: 1px solid gray;
+}
+
+table.library-table td.test-type
+{
+ padding-right: 5px;
+ border-left: 0;
+ border-right: 0;
+ border-top: 1px solid gray;
+ border-bottom: 1px solid gray;
+ text-align: right;
+}
+
+ tr.library-row td.library-fail-unexpected
+, tr.library-row-first td.library-fail-unexpected
+, tr.library-row-last td.library-fail-unexpected
+, tr.library-row-single td.library-fail-unexpected
+{
+ width: 60pt;
+ text-align: center;
+ background-color: red;
+ font-weight: bold;
+ color: black;
+ border: 2px solid black;
+}
+
+td.library-user-fail-expectected
+{
+ width: 60pt;
+ text-align: center;
+ background-color: yellow;
+ color: black;
+ border: 0px solid black;
+}
+
+table.library-library-notes
+{
+ background-color: LemonChiffon;
+ width: 640px;
+ margin-left: 5px;
+ margin-right: 5px;
+}
+
+tr.library-library-note
+{
+}
+
+div.note
+{
+ padding: 3pt;
+}
+
+
+span.note-header
+{
+ font-weight: bold;
+}
+
+/* Log */
+
+div.log-test-title
+{
+ font-size: 1.5em;
+ font-weight: bold;
+ border-bottom: 1px solid black;
+}
+
+div.notes-title
+{
+ font-weight: bold;
+ background-color: #ffffcc;
+}
+
+div.notes
+{
+ padding: 3pt;
+ background-color: #ffffcc;
+}
+
+div.notes-title
+{
+ font-weight: bold;
+}
+
+div.log-compiler-output-title
+{
+ font-weight: bold;
+}
+
+div.log-linker-output-title
+{
+ font-weight: bold;
+}
+
+div.log-run-output-title
+{
+ font-weight: bold;
+}
+
+
+/* Issues page */
+
+table.library-issues-table
+{
+ border-collapse: collapse;
+ border: 2px solid black;
+}
+
+table.library-issues-table td
+{
+ border: 1px solid #c0c0c0;
+ text-align: center;
+ margin-right: 5px;
+}
+
+table.library-issues-table td.failures-row
+{
+ text-align: left;
+ padding: 0px;
+}
+
+ table.issue-box tr.library-row-single td.library-fail-unexpected-new
+,table.issue-box tr.library-row-single td.library-fail-unexpected
+{
+ border: 0px;
+ font-weight: normal;
+}
diff --git a/tools/regression/xsl_reports/xsl/html/summary_developer_legend.html b/tools/regression/xsl_reports/xsl/html/summary_developer_legend.html
new file mode 100644
index 0000000000..0f82828228
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/html/summary_developer_legend.html
@@ -0,0 +1,75 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<div class="legend">
+<table border="0" summary="report description">
+<tr>
+ <td>
+ <table border="0" summary="legend">
+ <tr>
+ <td>
+ <table width="100%" summary="success legend">
+ <tr class="summary-row-single"><td class="summary-expected">OK</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ All expected tests pass.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected pass legend">
+ <tr class="summary-row-single"><td class="summary-success-unexpected">OK</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ All expected tests pass, and some other tests that were expected to fail
+ unexpectedly pass as well.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected new fail legend">
+ <tr class="summary-row-single"><td class="summary-fail-unexpected-new">fail</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ There are some failures on the newly added tests/compiler(s).
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <table border="0" summary="legend">
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected fail legend">
+ <tr class="summary-row-single"><td class="summary-fail-unexpected">broken</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ Tests that the library author expects to pass are currently failing.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="unusable legend">
+ <tr class="summary-row-single"><td class="summary-unusable">n/a</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ The library author marked it as unusable on particular platform/toolset.
+ </td>
+ </tr>
+ </table>
+ </td>
+</tr>
+</table>
+</div>
diff --git a/tools/regression/xsl_reports/xsl/html/summary_user_legend.html b/tools/regression/xsl_reports/xsl/html/summary_user_legend.html
new file mode 100644
index 0000000000..4407608120
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/html/summary_user_legend.html
@@ -0,0 +1,65 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<div class="legend">
+<table border="0" summary="report description">
+<tr>
+ <td>
+ <table border="0" summary="legend">
+ <tr>
+ <td>
+ <table width="100%" summary="success legend">
+ <tr class="summary-row-single"><td class="summary-user-success">&#160;</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ All library tests are passing.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="expected fail legend">
+ <tr class="summary-row-single"><td class="summary-user-fail-expected">details</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ There are some known failures in the tests, click on the link to see the details.
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <table border="0" summary="legend" ID="Table1">
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected fail legend">
+ <tr class="summary-row-single"><td class="summary-user-fail-unexpected">unexp.</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ Some tests that the library author expects to pass are currently failing,
+ click on the link to see the details.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="unusable legend">
+ <tr class="summary-row-single"><td class="summary-unusable">n/a</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">
+ The library author marked it as unusable on particular platform/toolset.
+ </td>
+ </tr>
+ </table>
+ </td>
+</tr>
+</table>
+</div>
diff --git a/tools/regression/xsl_reports/xsl/issues_page.xsl b/tools/regression/xsl_reports/xsl/issues_page.xsl
new file mode 100644
index 0000000000..4faa410d0d
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/issues_page.xsl
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:set="http://exslt.org/sets"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func exsl"
+ exclude-result-prefixes="set str meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="html"
+ doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
+ encoding="utf-8"
+ indent="yes"
+ />
+
+
+ <xsl:param name="links_file"/>
+ <xsl:param name="mode"/>
+ <xsl:param name="source"/>
+ <xsl:param name="run_date"/>
+ <xsl:param name="comment_file"/>
+ <xsl:param name="expected_results_file"/>
+ <xsl:param name="explicit_markup_file"/>
+
+ <!-- the author-specified expected test results -->
+ <xsl:variable name="explicit_markup" select="document( $explicit_markup_file )"/>
+ <xsl:variable name="expected_results" select="document( $expected_results_file )" />
+
+ <!-- necessary indexes -->
+ <xsl:key
+ name="test_name_key"
+ match="test-log"
+ use="concat( @library, '@', @test-name )"/>
+ <xsl:key
+ name="a"
+ match="."
+ use="concat( @library, '@', @test-name )"/>
+
+ <xsl:key
+ name="library_key"
+ match="test-log"
+ use="@library"/>
+ <xsl:key name="toolset_key" match="test-log" use="@toolset"/>
+
+ <!-- toolsets -->
+
+ <xsl:variable name="required_toolsets" select="$explicit_markup//mark-toolset[ @status='required' ]"/>
+ <xsl:variable name="required_toolset_names" select="$explicit_markup//mark-toolset[ @status='required' ]/@name"/>
+ <!-- libraries -->
+ <xsl:variable name="libraries" select="//test-log[ @library != '' and generate-id(.) = generate-id( key('library_key',@library)[1] ) ]/@library"/>
+
+ <xsl:variable name="unexpected_test_cases" select="//test-log[ @status='unexpected' and @result='fail' and @toolset = $required_toolset_names and meta:is_test_log_a_test_case(.)]"/>
+
+ <func:function name="meta:get_library_tests">
+ <xsl:param name="tests"/>
+ <xsl:param name="library"/>
+
+ <xsl:variable name="a">
+ <xsl:for-each select="$tests[ @library=$library ]">
+ <xsl:sort select="@test-name" order="ascending"/>
+ <xsl:copy-of select="."/>
+ </xsl:for-each>
+ </xsl:variable>
+ <func:result select="exsl:node-set( $a )/*"/>
+ </func:function>
+
+
+ <xsl:template match="/">
+
+ <xsl:variable name="issues_list" select="'issues_.html'"/>
+
+ <!-- Issues page -->
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <title>Boost regression unresolved issues: <xsl:value-of select="$source"/></title>
+ </head>
+ <frameset cols="190px,*" frameborder="0" framespacing="0" border="0">
+ <frame name="tocframe" src="toc.html" scrolling="auto"/>
+ <frame name="docframe" src="{$issues_list}" scrolling="auto"/>
+ </frameset>
+ </html>
+
+ <!-- Issues list -->
+ <xsl:message>Writing document <xsl:value-of select="$issues_list"/></xsl:message>
+
+ <exsl:document href="{$issues_list}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ </head>
+ <body>
+
+ <h1 class="page-title">
+ <xsl:text>Unresolved Issues: </xsl:text>
+ <a class="hover-link" href="summary.html" target="_top"><xsl:value-of select="$source"/></a>
+ </h1>
+
+ <div class="report-info">
+ <div>
+ <b>Report Time: </b> <xsl:value-of select="$run_date"/>
+ </div>
+ <div>
+ <b>Purpose: </b> Provides a list of current unresolved test failures.
+ </div>
+ </div>
+
+ <xsl:for-each select="$libraries">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="library" select="."/>
+ <xsl:variable name="library_page" select="meta:encode_path( $library )" />
+
+ <xsl:variable name="library_tests" select="meta:get_library_tests( $unexpected_test_cases, $library )"/>
+ <xsl:if test="count( $library_tests ) > 0">
+ <xsl:variable name="library_test_names" select="set:distinct( $library_tests/@test-name )"/>
+
+ <h2>
+ <a class="hover-link" href="{$library_page}.html" target="_top">
+ <xsl:value-of select="$library"/>
+ </a>
+ </h2>
+
+ <table class="library-issues-table" summary="issues">
+ <thead>
+ <tr valign="middle">
+ <td class="head">test</td>
+ <td class="head">failures</td>
+ </tr>
+ </thead>
+ <tfoot>
+ <tr valign="middle">
+ <td class="head">test</td>
+ <td class="head">failures</td>
+ </tr>
+ </tfoot>
+
+ <tbody>
+ <xsl:for-each select="$library_test_names">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="test_name" select="."/>
+
+ <xsl:variable name="unexpected_toolsets" select="$library_tests[ @test-name = $test_name and not (meta:is_unusable( $explicit_markup, $library, @toolset )) ]/@toolset"/>
+
+ <xsl:if test="count( $unexpected_toolsets ) > 0">
+ <xsl:variable name="test_program" select="$library_tests[@test-name = $test_name]/@test-program"/>
+ <tr>
+ <td class="test-name">
+ <a href="../../../{$test_program}" class="test-link">
+ <xsl:value-of select="$test_name"/>
+ </a>
+ </td>
+ <td class="failures-row">
+ <table summary="unexpected fail legend" class="issue-box">
+ <tr class="library-row-single">
+
+ <xsl:for-each select="$unexpected_toolsets">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="toolset" select="."/>
+ <xsl:variable name="test_result" select="$library_tests[@test-name = $test_name and @toolset = $toolset]"/>
+ <xsl:variable name="log_link" select="meta:output_file_path( $test_result/@target-directory )"/>
+ <xsl:variable name="class">
+ <xsl:choose>
+ <xsl:when test="$test_result/@is-new = 'yes'">
+ <xsl:text>library-fail-unexpected-new</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>library-fail-unexpected</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <td class="{$class}">
+ <span>
+ <a href="{$log_link}" class="log-link" target="_top">
+ <xsl:value-of select="."/>
+ </a>
+ </span>
+ </td>
+ </xsl:for-each>
+
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </xsl:if>
+ </xsl:for-each>
+ </tbody>
+
+ </table>
+
+
+ </xsl:if>
+ </xsl:for-each>
+
+ <xsl:copy-of select="document( 'html/issues_legend.html' )"/>
+ <xsl:copy-of select="document( 'html/make_tinyurl.html' )"/>
+
+ </body>
+ </html>
+ </exsl:document>
+
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/links_page.xsl b/tools/regression/xsl_reports/xsl/links_page.xsl
new file mode 100644
index 0000000000..ebc4488f50
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/links_page.xsl
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:set="http://exslt.org/sets"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func exsl"
+ exclude-result-prefixes="set str meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="html"
+ doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
+ encoding="utf-8"
+ indent="yes"
+ />
+
+ <xsl:param name="source"/>
+ <xsl:param name="run_date"/>
+ <xsl:param name="comment_file"/>
+ <xsl:param name="explicit_markup_file"/>
+
+ <xsl:variable name="explicit_markup" select="document( $explicit_markup_file )"/>
+
+ <xsl:template match="test-log[ meta:show_output( $explicit_markup, . ) ]">
+ <xsl:variable name="document_path" select="meta:output_file_path( @target-directory )"/>
+
+ <xsl:message>Writing log file document <xsl:value-of select="$document_path"/></xsl:message>
+
+ <exsl:document href="{$document_path}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <xsl:variable name="component">
+ <xsl:choose>
+ <xsl:when test="@test-name != ''">
+ <div class="log-test-title">
+ <xsl:value-of select="concat( @library, ' - ', @test-name, ' / ', @toolset )"/>
+ </div>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@target-dir"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <title>Boost regression - test run output: <xsl:value-of select="$component"/></title>
+ </head>
+
+ <body>
+ <div>
+ <div class="log-test-title">
+ Boost regression - test run output: <xsl:value-of select="$component"/>
+ </div>
+
+
+ <xsl:if test="notes/note">
+ <p>
+ <div class="notes-title">Notes</div>
+ <xsl:call-template name="show_notes">
+ <xsl:with-param name="notes" select="notes/note"/>
+ <xsl:with-param name="explicit_markup" select="$explicit_markup"/>
+ </xsl:call-template>
+ </p>
+ </xsl:if>
+
+ <xsl:if test="compile">
+ <p>
+ <div class="log-compiler-output-title">Compiler output:</div>
+ <pre>
+ <xsl:copy-of select="compile/node()"/>
+ </pre>
+ </p>
+ </xsl:if>
+
+ <xsl:if test="link">
+ <p>
+ <div class="log-linker-output-title">Linker output:</div>
+ <pre>
+ <xsl:copy-of select="link/node()"/>
+ </pre>
+ </p>
+ </xsl:if>
+
+ <xsl:if test="lib">
+ <p>
+ <div class="log-linker-output-title">Lib output:</div>
+ <p>
+ See <a href="{meta:encode_path( lib/node() )}.html">
+ <xsl:copy-of select="lib/node()"/>
+ </a>
+ </p>
+ </p>
+ </xsl:if>
+
+ <xsl:if test="run">
+ <p>
+ <div class="log-run-output-title">Run output:</div>
+ <pre>
+ <xsl:copy-of select="run/node()"/>
+ </pre>
+ </p>
+ </xsl:if>
+
+ </div>
+
+ <xsl:copy-of select="document( 'html/make_tinyurl.html' )"/>
+
+ </body>
+
+ </html>
+ </exsl:document>
+
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/produce_expected_results.xsl b/tools/regression/xsl_reports/xsl/produce_expected_results.xsl
new file mode 100644
index 0000000000..a47a3acfed
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/produce_expected_results.xsl
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+ <xsl:output method="xml" encoding="utf-8"/>
+
+ <xsl:template match="/">
+ <root>
+ <expected-failures>
+ <xsl:apply-templates select="*/test-log"/>
+ </expected-failures>
+ </root>
+ </xsl:template>
+
+ <xsl:template match="test-log">
+ <xsl:if test="meta:is_test_log_a_test_case(.)">
+ <test-result library="{@library}" test-name="{@test-name}" toolset="{@toolset}" result="{@result}" />
+ </xsl:if>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/result_page.xsl b/tools/regression/xsl_reports/xsl/result_page.xsl
new file mode 100644
index 0000000000..dbd0fbf919
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/result_page.xsl
@@ -0,0 +1,702 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:set="http://exslt.org/sets"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func exsl"
+ exclude-result-prefixes="set str meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="html"
+ doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
+ encoding="utf-8"
+ indent="yes"
+ />
+
+ <xsl:param name="links_file"/>
+ <xsl:param name="mode"/>
+ <xsl:param name="source"/>
+ <xsl:param name="run_date"/>
+ <xsl:param name="comment_file"/>
+ <xsl:param name="expected_results_file"/>
+ <xsl:param name="explicit_markup_file"/>
+
+ <!-- the author-specified expected test results -->
+ <xsl:variable name="explicit_markup" select="document( $explicit_markup_file )"/>
+ <xsl:variable name="expected_results" select="document( $expected_results_file )" />
+
+ <xsl:variable name="alternate_mode">
+ <xsl:choose>
+ <xsl:when test="$mode='user'">developer</xsl:when>
+ <xsl:otherwise>user</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- necessary indexes -->
+ <xsl:key
+ name="test_name_key"
+ match="test-log"
+ use="concat( @library, '&gt;@&lt;', @test-name )"/>
+ <xsl:key name="toolset_key" match="test-log" use="@toolset"/>
+
+ <!-- toolsets -->
+
+ <xsl:variable name="not_ordered_toolsets" select="//test-log[ generate-id(.) = generate-id( key('toolset_key',@toolset)[1] ) and @toolset != '' ]/@toolset"/>
+
+ <xsl:variable name="required_toolsets" select="$explicit_markup//mark-toolset[ @status='required' ]"/>
+
+ <xsl:variable name="ordered_toolsets_fragment">
+ <xsl:call-template name="get_toolsets">
+ <xsl:with-param name="toolsets" select="$not_ordered_toolsets"/>
+ <xsl:with-param name="required_toolsets" select="$required_toolsets"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="ordered_toolsets" select="exsl:node-set( $ordered_toolsets_fragment )"/>
+
+ <!-- libraries -->
+ <xsl:variable name="test_case_logs" select="//test-log[ meta:is_test_log_a_test_case(.) ]"/>
+ <xsl:variable name="libraries" select="set:distinct( $test_case_logs/@library )"/>
+
+ <xsl:template name="insert_toolsets_row">
+ <xsl:param name="library"/>
+ <xsl:param name="library_marks"/>
+ <xsl:param name="toolsets"/>
+ <tr valign="middle">
+ <td class="head" colspan="2">test / toolset</td>
+
+ <!--
+ we need to select not all library notes, but only ones
+ for toolsets present in the report
+ -->
+ <xsl:variable name="all_library_notes" select="$library_marks/note"/>
+ <xsl:message terminate="yes">
+ !!!!!!!!!!!!!!!!!!!1
+ </xsl:message>
+ <exsl:document href="debug2.xml"
+ method="xml"
+ encoding="utf-8"
+ indent="yes">
+ <debug>
+ <xsl:copy-of select="$all_library_notes"/>
+ </debug>
+ </exsl:document>
+ <xsl:for-each select="$toolsets/toolset">
+ <xsl:variable name="toolset" select="@toolset"/>
+
+ <xsl:variable name="class">
+ <xsl:choose>
+ <xsl:when test="@required='yes'">
+ <xsl:text>required-toolset-name</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>toolset-name</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="toolset_notes_fragment">
+ <xsl:for-each select="$all_library_notes">
+ <xsl:if test="../@toolset=$toolset or ( ../toolset/@name=$toolset or ../toolset/@name = '*' )">
+ <note index="{position()}"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="toolset_notes" select="exsl:node-set( $toolset_notes_fragment )/*"/>
+
+ <td class="{$class}"><xsl:value-of select="meta:toolset_name( $toolset )"/>
+ <xsl:if test="count( $toolset_notes ) > 0">
+ <span class="super">
+ <xsl:for-each select="$toolset_notes">
+ <xsl:variable name="note_index" select="@index"/>
+ <xsl:if test="generate-id( . ) != generate-id( $toolset_notes[1] )">, </xsl:if>
+ <a href="#{$library}-note-{$note_index}" title="Note {$note_index}">
+ <xsl:value-of select="$note_index"/>
+ </a>
+ </xsl:for-each>
+ </span>
+ </xsl:if>
+ </td>
+ </xsl:for-each>
+
+ <td class="head">toolset / test</td>
+ </tr>
+ </xsl:template>
+
+ <xsl:template name="test_type_col">
+ <td class="test-type">
+ <a href="../../../status/compiler_status.html#Understanding" class="legend-link">
+ <xsl:variable name="test_type" select="./@test-type"/>
+ <xsl:choose>
+ <xsl:when test="$test_type='run_pyd'"> <xsl:text>r</xsl:text> </xsl:when>
+ <xsl:when test="$test_type='run'"> <xsl:text>r</xsl:text> </xsl:when>
+ <xsl:when test="$test_type='run_fail'"> <xsl:text>rf</xsl:text> </xsl:when>
+ <xsl:when test="$test_type='compile'"> <xsl:text>c</xsl:text> </xsl:when>
+ <xsl:when test="$test_type='compile_fail'"> <xsl:text>cf</xsl:text> </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">Incorrect test type "<xsl:value-of select="$test_type"/>"</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </a>
+ </td>
+ </xsl:template>
+
+
+ <xsl:template match="/">
+
+ <xsl:variable name="index_path" select="'index_.html'"/>
+
+ <!-- Index page -->
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <title>Boost regression: <xsl:value-of select="$source"/></title>
+ </head>
+ <frameset cols="190px,*" frameborder="0" framespacing="0" border="0">
+ <frame name="tocframe" src="toc.html" scrolling="auto"/>
+ <frame name="docframe" src="{$index_path}" scrolling="auto"/>
+ </frameset>
+
+ <!-- Index content -->
+ <xsl:message>Writing document <xsl:value-of select="$index_path"/></xsl:message>
+
+ <exsl:document href="{$index_path}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ </head>
+ <body>
+
+ <img border="0" src="../../../boost.png" width="277" height="86" align="right" alt="Boost logo"></img>
+
+ <h1 class="page-title">
+ <xsl:value-of select="$mode"/>
+ <xsl:text> report: </xsl:text>
+ <a class="hover-link" href="summary.html" target="_top"><xsl:value-of select="$source"/></a>
+ </h1>
+
+ <div class="report-info">
+ <div>
+ <b>Report Time: </b> <xsl:value-of select="$run_date"/>
+ </div>
+
+ <div>
+ <b>Purpose: </b>
+ <xsl:choose>
+ <xsl:when test="$mode='user'">
+ The purpose of this report is to help a user to find out whether a particular library
+ works on the particular compiler(s). For CVS "health report", see
+ <a href="../{$alternate_mode}/index.html" target="_top">developer summary</a>.
+ </xsl:when>
+ <xsl:when test="$mode='developer'">
+ Provides Boost developers with visual indication of the CVS "health". For user-level
+ report, see <a href="../{$alternate_mode}/index.html" target="_top">user summary</a>.
+ </xsl:when>
+ </xsl:choose>
+ </div>
+ </div>
+
+ <div class="comment">
+ <xsl:if test="$comment_file != ''">
+ <xsl:copy-of select="document( $comment_file )"/>
+ </xsl:if>
+ </div>
+
+ </body>
+ </html>
+ </exsl:document>
+
+
+ <xsl:variable name="multiple.libraries" select="count( $libraries ) > 1"/>
+
+ <!-- TOC -->
+ <xsl:if test="$multiple.libraries">
+
+ <xsl:variable name="toc_path" select="'toc.html'"/>
+ <xsl:message>Writing document <xsl:value-of select="$toc_path"/></xsl:message>
+
+ <exsl:document href="{$toc_path}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ </head>
+ <body class="{$mode}-toc">
+ <div class="toc-header-entry">
+ <a href="index.html" class="toc-entry" target="_top">Report info</a>
+ </div>
+ <div class="toc-header-entry">
+ <a href="summary.html" class="toc-entry" target="_top">Summary</a>
+ </div>
+
+ <xsl:if test="$mode='developer'">
+ <div class="toc-header-entry">
+ <a href="issues.html" class="toc-entry" target="_top">Unresolved issues</a>
+ </div>
+ </xsl:if>
+ <hr/>
+
+ <xsl:for-each select="$libraries">
+ <xsl:sort select="." order="ascending" />
+ <xsl:variable name="library_page" select="meta:encode_path(.)" />
+ <div class="toc-entry">
+ <a href="{$library_page}.html" class="toc-entry" target="_top">
+ <xsl:value-of select="."/>
+ </a>
+ </div>
+ </xsl:for-each>
+ </body>
+ </html>
+
+ </exsl:document>
+ </xsl:if>
+
+ <!-- Libraries -->
+ <xsl:for-each select="$libraries">
+ <xsl:sort select="." order="ascending" />
+ <xsl:variable name="library" select="." />
+
+ <xsl:variable name="library_results" select="concat( meta:encode_path( $library ), '_.html' )"/>
+ <xsl:variable name="library_page" select="concat( meta:encode_path( $library ), '.html' )"/>
+
+ <!-- Library page -->
+ <xsl:message>Writing document <xsl:value-of select="$library_page"/></xsl:message>
+
+ <exsl:document href="{$library_page}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <title>Boost regression: <xsl:value-of select="$library"/>/<xsl:value-of select="$source"/></title>
+ </head>
+ <frameset cols="190px,*" frameborder="0" framespacing="0" border="0">
+ <frame name="tocframe" src="toc.html" scrolling="auto"/>
+ <frame name="docframe" src="{$library_results}" scrolling="auto"/>
+ </frameset>
+ </html>
+ </exsl:document>
+
+ <!-- Library results frame -->
+ <xsl:message>Writing document <xsl:value-of select="$library_results"/></xsl:message>
+
+ <exsl:document href="{$library_results}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ </head>
+
+ <body>
+
+ <h1 class="page-title">
+ <a class="hover-link" name="{$library}" href="../../../libs/{$library}">
+ <xsl:value-of select="$library" />
+ </a>
+ <xsl:text>/</xsl:text>
+ <a class="hover-link" href="summary.html" target="_top"><xsl:value-of select="$source"/></a>
+ </h1>
+
+ <div class="report-info">
+ <b>Report Time: </b> <xsl:value-of select="$run_date"/>
+ </div>
+
+ <!-- library markup = all library-unusable markup for toolsets included in the report -->
+ <xsl:variable name="library_marks" select="$explicit_markup//library[ @name = $library ]/mark-unusable[ toolset/@name = $not_ordered_toolsets ]"/>
+
+ <table border="0" cellspacing="0" cellpadding="0" class="library-table" summary="library results">
+
+ <thead>
+ <xsl:call-template name="insert_toolsets_row">
+ <xsl:with-param name="library_marks" select="$library_marks"/>
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="toolsets" select="$ordered_toolsets"/>
+ </xsl:call-template>
+ </thead>
+ <tfoot>
+ <xsl:call-template name="insert_toolsets_row">
+ <xsl:with-param name="library_marks" select="$library_marks"/>
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="toolsets" select="$ordered_toolsets"/>
+ </xsl:call-template>
+ </tfoot>
+
+ <tbody>
+ <!-- lib_tests = test_log* -->
+ <xsl:variable name="lib_tests" select="$test_case_logs[@library = $library]" />
+
+ <!-- lib_unique_test_names = test_log* -->
+ <xsl:variable name="lib_unique_test_names"
+ select="$lib_tests[ generate-id(.) = generate-id( key('test_name_key', concat( @library, '&gt;@&lt;', @test-name ) ) ) ]" />
+
+ <xsl:variable name="lib_corner_case_tests_markup" select="$explicit_markup//library[ @name = $library ]/test[ @corner-case='yes' ]"/>
+ <xsl:variable name="lib_general_tests"
+ select="meta:order_tests_by_name( $lib_unique_test_names[ not( @test-name = $lib_corner_case_tests_markup/@name ) ] )"/>
+
+
+ <xsl:variable name="lib_corner_case_tests" select="meta:order_tests_by_name( $lib_unique_test_names[ @test-name = $lib_corner_case_tests_markup/@name ] ) " />
+
+ <!-- general tests section -->
+
+ <xsl:call-template name="insert_test_section">
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="section_tests" select="$lib_general_tests"/>
+ <xsl:with-param name="lib_tests" select="$lib_tests"/>
+ <xsl:with-param name="toolsets" select="$ordered_toolsets"/>
+ </xsl:call-template>
+
+ <!-- corner-case tests section -->
+
+ <xsl:if test="count( $lib_corner_case_tests ) > 0">
+ <tr>
+ <td class="library-corner-case-header" colspan="{count($ordered_toolsets/toolset) + 3 }" align="center">Corner-case tests</td>
+ </tr>
+
+ <xsl:call-template name="insert_test_section">
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="section_tests" select="$lib_corner_case_tests"/>
+ <xsl:with-param name="lib_tests" select="$lib_tests"/>
+ <xsl:with-param name="toolsets" select="$ordered_toolsets"/>
+ </xsl:call-template>
+
+ </xsl:if>
+
+ </tbody>
+ </table>
+ <xsl:if test="count( $library_marks/note ) > 0 ">
+ <table border="0" cellpadding="0" cellspacing="0" class="library-library-notes" summary="library notes">
+ <xsl:for-each select="$library_marks/note">
+ <tr class="library-library-note">
+ <td valign="top" width="3em">
+ <a name="{$library}-note-{position()}">
+ <span class="super"><xsl:value-of select="position()"/></span>
+ </a>
+ </td>
+ <td>
+ <xsl:variable name="refid" select="@refid"/>
+ <xsl:call-template name="show_note">
+ <xsl:with-param name="note" select="." />
+ <xsl:with-param name="reference" select="$explicit_markup//note[ $refid = @id ]"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
+
+ <xsl:copy-of select="document( concat( 'html/library_', $mode, '_legend.html' ) )"/>
+ <xsl:copy-of select="document( 'html/make_tinyurl.html' )"/>
+
+ </body>
+ </html>
+
+ </exsl:document>
+
+ </xsl:for-each>
+
+ </xsl:template>
+
+
+ <!-- insert test result with log file link -->
+
+ <xsl:template name="insert_test_result">
+ <xsl:param name="result"/>
+ <xsl:param name="log_link"/>
+
+ <xsl:choose>
+ <xsl:when test="$log_link != ''">
+ <a href="{$log_link}" class="log-link" target="_top">
+ <xsl:value-of select="$result"/>
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$result"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- report developer status -->
+ <xsl:template name="insert_cell_developer">
+ <xsl:param name="test_log"/>
+ <xsl:param name="log_link"/>
+
+ <xsl:variable name="is_new">
+ <xsl:if test="$test_log/@is-new = 'yes' and $test_log/@status = 'unexpected' and $test_log/@result != 'success'">
+ <xsl:value-of select="'-new'"/>
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:variable name="class">
+ <xsl:choose>
+ <xsl:when test="not( $test_log )">
+ <xsl:text>library-missing</xsl:text>
+ </xsl:when>
+ <xsl:when test="meta:is_unusable( $explicit_markup, $test_log/@library, $test_log/@toolset )">
+ <xsl:text>library-unusable</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat( 'library-', $test_log/@result, '-', $test_log/@status, $is_new )"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <td class="{$class}">
+ <xsl:choose>
+ <xsl:when test="not( $test_log )">
+ <xsl:text>missing</xsl:text>
+ </xsl:when>
+
+ <xsl:when test="$test_log/@result != 'success' and $test_log/@status = 'expected'">
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'fail'"/>
+ <xsl:with-param name="log_link" select="$log_link"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="$test_log/@result != 'success' and $test_log/@status = 'unexpected'">
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'fail'"/>
+ <xsl:with-param name="log_link" select="$log_link"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="$test_log/@result = 'success' and $test_log/@status = 'unexpected'">
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'pass'"/>
+ <xsl:with-param name="log_link" select="$log_link"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'pass'"/>
+ <xsl:with-param name="log_link" select="$log_link"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="count( $test_log ) > 1" >
+ <div class="library-conf-problem">conf.&#160;problem</div>
+ </xsl:if>
+ </td>
+ </xsl:template>
+
+ <!-- report user status -->
+ <xsl:template name="insert_cell_user">
+ <xsl:param name="test_log"/>
+ <xsl:param name="log_link"/>
+
+ <xsl:variable name="class">
+ <xsl:choose>
+ <xsl:when test="not( $test_log )">
+ <xsl:text>library-missing</xsl:text>
+ </xsl:when>
+ <xsl:when test="meta:is_unusable( $explicit_markup, $test_log/@library, $test_log/@toolset )">
+ <xsl:text>library-unusable</xsl:text>
+ </xsl:when>
+ <xsl:when test="$test_log[@result='fail' and @status='unexpected']">
+ <xsl:text>library-user-fail-unexpected</xsl:text>
+ </xsl:when>
+ <xsl:when test="$test_log[ @result='fail' and @status='expected' ]">
+ <xsl:text>library-user-fail-expected</xsl:text>
+ </xsl:when>
+ <xsl:when test="$test_log[ @result='success']">
+ <xsl:text>library-user-success</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ Unknown status
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:variable>
+
+ <td class="{$class}">
+ <xsl:choose>
+ <xsl:when test="not( $test_log )">
+ missing
+ </xsl:when>
+ <xsl:when test="$test_log/@result != 'success' and $test_log/@status = 'expected'">
+ <a href="{$log_link}" class="log-link" target="_top">
+ fail
+ </a>
+ </xsl:when>
+ <xsl:when test="$test_log/@result != 'success'">
+ <a href="{$log_link}" class="log-link" target="_top">
+ unexp.
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>pass</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="count( $test_log ) > 1" >
+ <div class="conf-problem">conf.&#160;problem</div>
+ </xsl:if>
+ </td>
+ </xsl:template>
+
+ <xsl:template name="insert_test_line">
+ <xsl:param name="library"/>
+ <xsl:param name="test_name"/>
+ <xsl:param name="test_results"/>
+ <xsl:param name="toolsets"/>
+ <xsl:param name="line_mod"/>
+
+ <xsl:variable name="test_program">
+ <xsl:value-of select="$test_results[1]/@test-program"/>
+ </xsl:variable>
+
+ <xsl:variable name="test_header">
+ <td class="test-name">
+ <a href="../../../{$test_program}" class="test-link">
+ <xsl:value-of select="$test_name"/>
+ </a>
+ </td>
+ </xsl:variable>
+
+ <tr class="library-row{$line_mod}">
+ <xsl:copy-of select="$test_header"/>
+ <xsl:call-template name="test_type_col"/>
+
+ <xsl:for-each select="$toolsets/toolset">
+ <xsl:variable name="toolset" select="@toolset" />
+
+ <!-- Write log file -->
+ <xsl:variable name="test_result_for_toolset" select="$test_results[ @toolset = $toolset ]"/>
+
+ <xsl:variable name="log_file">
+ <xsl:choose>
+ <xsl:when test="meta:show_output( $explicit_markup, $test_result_for_toolset )">
+ <xsl:value-of select="meta:output_file_path( $test_result_for_toolset/@target-directory )"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text></xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+
+ <xsl:if test="count( $test_result_for_toolset ) > 0 and $log_file != ''">
+ <xsl:message>Writing log file document <xsl:value-of select="$log_file"/></xsl:message>
+ <exsl:document href="{$log_file}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <!--<title>Boost regression unresolved issues: <xsl:value-of select="$source"/></title>-->
+ </head>
+ <frameset cols="190px,*" frameborder="0" framespacing="0" border="0">
+ <frame name="tocframe" src="../toc.html" scrolling="auto"/>
+ <frame name="docframe" src="../../{$log_file}" scrolling="auto"/>
+ </frameset>
+ </html>
+ </exsl:document>
+ </xsl:if>
+
+ <!-- Insert cell -->
+ <xsl:choose>
+ <xsl:when test="$mode='user'">
+ <xsl:call-template name="insert_cell_user">
+ <xsl:with-param name="test_log" select="$test_result_for_toolset"/>
+ <xsl:with-param name="log_link" select="$log_file"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$mode='developer'">
+ <xsl:call-template name="insert_cell_developer">
+ <xsl:with-param name="test_log" select="$test_result_for_toolset"/>
+ <xsl:with-param name="log_link" select="$log_file"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+
+ </xsl:for-each>
+ <xsl:copy-of select="$test_header"/>
+ </tr>
+ </xsl:template>
+
+ <xsl:template name="insert_test_section">
+ <xsl:param name="library"/>
+ <xsl:param name="section_tests"/>
+ <xsl:param name="lib_tests"/>
+ <xsl:param name="toolsets"/>
+
+ <xsl:for-each select="$section_tests">
+ <xsl:variable name="test_name" select="@test-name"/>
+ <xsl:variable name="line_mod">
+ <xsl:choose>
+ <xsl:when test="1 = last()">
+ <xsl:text>-single</xsl:text>
+ </xsl:when>
+ <xsl:when test="generate-id( . ) = generate-id( $section_tests[1] )">
+ <xsl:text>-first</xsl:text>
+ </xsl:when>
+ <xsl:when test="generate-id( . ) = generate-id( $section_tests[last()] )">
+ <xsl:text>-last</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text></xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:call-template name="insert_test_line">
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="test_results" select="$lib_tests[ @test-name = $test_name ]"/>
+ <xsl:with-param name="toolsets" select="$toolsets"/>
+ <xsl:with-param name="test_name" select="$test_name"/>
+ <xsl:with-param name="line_mod" select="$line_mod"/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ </xsl:template>
+
+ <func:function name="meta:order_tests_by_name">
+ <xsl:param name="tests"/>
+
+ <xsl:variable name="a">
+ <xsl:for-each select="$tests">
+ <xsl:sort select="@test-name" order="ascending"/>
+ <xsl:copy-of select="."/>
+ </xsl:for-each>
+ </xsl:variable>
+ <func:result select="exsl:node-set( $a )/*"/>
+ </func:function>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/summary_page.xsl b/tools/regression/xsl_reports/xsl/summary_page.xsl
new file mode 100644
index 0000000000..7bf3818c29
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/summary_page.xsl
@@ -0,0 +1,361 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:set="http://exslt.org/sets"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func exsl"
+ exclude-result-prefixes="set str meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="html"
+ doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
+ encoding="utf-8"
+ indent="yes"
+ />
+
+
+ <xsl:param name="mode"/>
+ <xsl:param name="source"/>
+ <xsl:param name="run_date"/>
+ <xsl:param name="comment_file"/>
+ <xsl:param name="explicit_markup_file"/>
+
+ <xsl:variable name="explicit_markup" select="document( $explicit_markup_file )"/>
+
+ <!-- necessary indexes -->
+ <xsl:key
+ name="library_test_name_key"
+ match="test-log"
+ use="concat( @library, '&gt;@&lt;', @test-name )"/>
+ <xsl:key name="toolset_key" match="test-log" use="@toolset"/>
+ <xsl:key name="test_name_key" match="test-log" use="@test-name "/>
+
+ <!-- toolsets -->
+
+ <xsl:variable name="toolsets" select="//test-log[ generate-id(.) = generate-id( key('toolset_key',@toolset)[1] ) and @toolset != '' ]/@toolset"/>
+
+ <xsl:variable name="required_toolsets" select="$explicit_markup//mark-toolset[ @status='required' ]"/>
+
+ <xsl:variable name="sorted_toolset_fragment">
+ <xsl:call-template name="get_toolsets">
+ <xsl:with-param name="toolsets" select="$toolsets"/>
+ <xsl:with-param name="required_toolsets" select="$required_toolsets"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="sorted_toolsets" select="exsl:node-set( $sorted_toolset_fragment )"/>
+
+ <!-- libraries -->
+
+ <xsl:variable name="test_case_logs" select="//test-log[ meta:is_test_log_a_test_case(.) ]"/>
+ <xsl:variable name="libraries" select="set:distinct( $test_case_logs/@library )"/>
+
+ <xsl:variable name="sorted_libraries_output">
+ <xsl:for-each select="$libraries">
+ <xsl:sort select="." order="ascending" />
+ <library><xsl:copy-of select="."/></library>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="sorted_libraries" select="exsl:node-set( $sorted_libraries_output )/library/@library"/>
+
+
+ <xsl:template match="/">
+
+ <xsl:variable name="summary_results" select="'summary_.html'"/>
+
+ <!-- Summary page -->
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <title>Boost regression summary: <xsl:value-of select="$source"/></title>
+ </head>
+ <frameset cols="190px,*" frameborder="0" framespacing="0" border="0">
+ <frame name="tocframe" src="toc.html" scrolling="auto"/>
+ <frame name="docframe" src="{$summary_results}" scrolling="auto"/>
+ </frameset>
+ </html>
+
+ <!-- Summary results -->
+ <xsl:message>Writing document <xsl:value-of select="$summary_results"/></xsl:message>
+
+ <exsl:document href="{$summary_results}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ </head>
+ <body>
+
+ <h1 class="page-title">
+ <xsl:text>Summary: </xsl:text>
+ <a class="hover-link" href="summary.html" target="_top"><xsl:value-of select="$source"/></a>
+ </h1>
+
+ <div class="report-info">
+ <b>Report Time: </b> <xsl:value-of select="$run_date"/>
+ </div>
+
+ <!-- summary table -->
+
+ <table border="0" cellspacing="0" cellpadding="0" class="summary-table">
+
+ <thead>
+ <xsl:call-template name="insert_toolsets_row">
+ <xsl:with-param name="toolsets" select="$sorted_toolsets"/>
+ </xsl:call-template>
+ </thead>
+
+ <tfoot>
+ <xsl:call-template name="insert_toolsets_row">
+ <xsl:with-param name="toolsets" select="$sorted_toolsets"/>
+ </xsl:call-template>
+ </tfoot>
+
+ <tbody>
+ <xsl:variable name="test_logs" select="$test_case_logs"/>
+
+ <!-- for each library -->
+ <xsl:for-each select="$sorted_libraries">
+ <xsl:variable name="library" select="."/>
+ <xsl:variable name="library_page" select="meta:encode_path( $library )" />
+ <xsl:variable name="current_row" select="$test_logs[ @library=$library]"/>
+
+ <xsl:variable name="expected_test_count" select="count( $current_row[ generate-id(.) = generate-id( key('test_name_key',@test-name)[1] ) ] )"/>
+ <xsl:variable name="library_header">
+ <td class="library-name">
+ <a href="{$library_page}.html" class="library-link" target="_top">
+ <xsl:value-of select="$library"/>
+ </a>
+ </td>
+ </xsl:variable>
+
+ <xsl:variable name="line_mod">
+ <xsl:choose>
+ <xsl:when test="1 = last()">
+ <xsl:text>-single</xsl:text>
+ </xsl:when>
+ <xsl:when test="generate-id( . ) = generate-id( $sorted_libraries[1] )">
+ <xsl:text>-first</xsl:text>
+ </xsl:when>
+ <xsl:when test="generate-id( . ) = generate-id( $sorted_libraries[ last() ] )">
+ <xsl:text>-last</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text></xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+
+ <tr class="summary-row{$line_mod}">
+ <xsl:copy-of select="$library_header"/>
+
+ <xsl:for-each select="$sorted_toolsets/toolset">
+ <xsl:variable name="toolset" select="@toolset"/>
+ <xsl:variable name="current_cell" select="$current_row[ @toolset=$toolset ]"/>
+ <xsl:choose>
+ <xsl:when test="$mode='user'">
+ <xsl:call-template name="insert_cell_user">
+ <xsl:with-param name="current_cell" select="$current_cell"/>
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="toolset" select="$toolset"/>
+ <xsl:with-param name="expected_test_count" select="$expected_test_count"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$mode='developer'">
+ <xsl:call-template name="insert_cell_developer">
+ <xsl:with-param name="current_cell" select="$current_cell"/>
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="toolset" select="$toolset"/>
+ <xsl:with-param name="expected_test_count" select="$expected_test_count"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+
+ <xsl:copy-of select="$library_header"/>
+ </tr>
+ </xsl:for-each>
+ </tbody>
+ </table>
+
+ <xsl:copy-of select="document( concat( 'html/summary_', $mode, '_legend.html' ) )"/>
+ <xsl:copy-of select="document( 'html/make_tinyurl.html' )"/>
+
+ </body>
+ </html>
+ </exsl:document>
+
+ </xsl:template>
+
+ <!-- report developer status -->
+ <xsl:template name="insert_cell_developer">
+ <xsl:param name="current_cell"/>
+ <xsl:param name="library"/>
+ <xsl:param name="toolset"/>
+ <xsl:param name="expected_test_count"/>
+ <xsl:variable name="class">
+ <xsl:choose>
+ <xsl:when test="meta:is_unusable( $explicit_markup, $library, $toolset )">
+ <xsl:text>summary-unusable</xsl:text>
+ </xsl:when>
+ <xsl:when test="count( $current_cell ) &lt; $expected_test_count">
+ <xsl:text>summary-missing</xsl:text>
+ </xsl:when>
+ <xsl:when test="count( $current_cell[@result='fail' and @status='unexpected' and @is-new='no'] )">
+ <xsl:text>summary-fail-unexpected</xsl:text>
+ </xsl:when>
+ <xsl:when test="count( $current_cell[@result='fail' and @status='unexpected' and @is-new='yes'] )">
+ <xsl:text>summary-fail-unexpected-new</xsl:text>
+ </xsl:when>
+ <xsl:when test="count( $current_cell[@result='success' and @status='unexpected'] )">
+ <xsl:text>summary-success-unexpected</xsl:text>
+ </xsl:when>
+ <xsl:when test="count( $current_cell[@status='expected'] )">
+ <xsl:text>summary-expected</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>summary-unknown-status</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="library_page" select="meta:encode_path( $library )" />
+
+ <td class="{$class}">
+ <xsl:choose>
+ <xsl:when test="$class='summary-unusable'">
+ <a href="{$library_page}.html" class="log-link" target="_top">
+ <xsl:text>n/a</xsl:text>
+ </a>
+ </xsl:when>
+ <xsl:when test="$class='summary-missing'">
+ <xsl:text>missing</xsl:text>
+ </xsl:when>
+ <xsl:when test="$class='summary-fail-unexpected'">
+ <a href="{$library_page}.html" class="log-link" target="_top">
+ <xsl:text>broken</xsl:text>
+ </a>
+ </xsl:when>
+ <xsl:when test="$class='summary-fail-unexpected-new' ">
+ <a href="{$library_page}.html" class="log-link" target="_top">
+ <xsl:text>fail</xsl:text>
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>OK</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+
+ </xsl:template>
+
+
+ <!-- report user status -->
+ <xsl:template name="insert_cell_user">
+ <xsl:param name="current_cell"/>
+ <xsl:param name="library"/>
+ <xsl:param name="toolset"/>
+ <xsl:param name="expected_test_count"/>
+ <xsl:variable name="class">
+ <xsl:choose>
+ <xsl:when test="meta:is_unusable( $explicit_markup, $library, $toolset )">
+ <xsl:text>summary-unusable</xsl:text>
+ </xsl:when>
+ <xsl:when test="count( $current_cell ) &lt; $expected_test_count">
+ <xsl:text>summary-missing</xsl:text>
+ </xsl:when>
+ <xsl:when test="count( $current_cell[@result='fail' and @status='unexpected' ] )">
+ <xsl:text>summary-user-fail-unexpected</xsl:text>
+ </xsl:when>
+ <xsl:when test="count( $current_cell[ @result='fail'] )">
+ <xsl:text>summary-user-fail-expected</xsl:text>
+ </xsl:when>
+ <xsl:when test="count( $current_cell[ @result='success'] )">
+ <xsl:text>summary-user-success</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>summary-unknown-status</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="library_page" select="meta:encode_path( $library )" />
+
+ <td class="{$class}">
+ <xsl:choose>
+ <xsl:when test="$class='summary-unusable'">
+ <a href="{$library_page}.html" class="log-link" target="_top">
+ <xsl:text>unusable</xsl:text>
+ </a>
+ </xsl:when>
+
+ <xsl:when test="$class='summary-missing'">
+ <xsl:text>missing</xsl:text>
+ </xsl:when>
+
+ <xsl:when test="$class='summary-user-fail-unexpected'">
+ <a href="{$library_page}.html" class="log-link" target="_top">
+ <xsl:text>unexp.</xsl:text>
+ </a>
+ </xsl:when>
+
+ <xsl:when test="$class='summary-user-fail-expected'">
+ <a href="{$library_page}.html" class="log-link" target="_top">
+ <xsl:text>details</xsl:text>
+ </a>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:text>&#160;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+
+ </xsl:template>
+
+ <xsl:template name="insert_toolsets_row">
+ <xsl:param name="toolsets"/>
+ <tr>
+ <td class="head">library / toolset</td>
+
+ <xsl:for-each select="$toolsets/toolset">
+ <xsl:variable name="class">
+ <xsl:choose>
+ <xsl:when test="@required='yes'">
+ <xsl:text>required-toolset-name</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>toolset-name</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <td class="{$class}"><xsl:value-of select="meta:toolset_name( @toolset )"/></td>
+ </xsl:for-each>
+
+ <td class="head">toolset / library</td>
+ </tr>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/test/test_re_match.xml b/tools/regression/xsl_reports/xsl/test/test_re_match.xml
new file mode 100644
index 0000000000..3841f782d7
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/test/test_re_match.xml
@@ -0,0 +1,57 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2005.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<root>
+
+<test pattern="" text="" result="true"/>
+<test pattern="pattern" text="pattern" result="true"/>
+<test pattern="" text="pattern" result="false"/>
+<test pattern="pattern" text="" result="false"/>
+
+<test pattern="*" text="" result="true"/>
+<test pattern="*" text="pattern" result="true"/>
+
+<test pattern="*pattern*" text="" result="false"/>
+<test pattern="*pattern*" text="__pattern__" result="true"/>
+<test pattern="*pattern*" text="pattern" result="true"/>
+<test pattern="*pattern*" text="patter" result="false"/>
+<test pattern="*pattern*" text="patte__" result="false"/>
+<test pattern="*pattern*" text="attern" result="false"/>
+<test pattern="*pattern*" text="__ttern" result="false"/>
+
+<test pattern="*pattern" text="" result="false"/>
+<test pattern="*pattern" text="__pattern" result="true"/>
+<test pattern="*pattern" text="pattern" result="true"/>
+<test pattern="*pattern" text="pattern__" result="false"/>
+<test pattern="*pattern" text="patter" result="false"/>
+<test pattern="*pattern" text="patte__" result="false"/>
+<test pattern="*pattern" text="attern" result="false"/>
+<test pattern="*pattern" text="__ttern" result="false"/>
+
+<test pattern="pattern*" text="" result="false"/>
+<test pattern="pattern*" text="pattern__" result="true"/>
+<test pattern="pattern*" text="pattern" result="true"/>
+<test pattern="pattern*" text="patter" result="false"/>
+<test pattern="pattern*" text="__pattern" result="false"/>
+<test pattern="pattern*" text="attern" result="false"/>
+<test pattern="pattern*" text="patter_" result="false"/>
+<test pattern="pattern*" text="patte__" result="false"/>
+
+<test pattern="patt*ern" text="" result="false"/>
+<test pattern="patt*ern" text="patt__ern" result="true"/>
+<test pattern="patt*ern" text="pattern" result="true"/>
+<test pattern="patter*n" text="patter__n" result="true"/>
+<test pattern="p*attern" text="pttern" result="false"/>
+<test pattern="p*attern" text="pattern" result="true"/>
+<test pattern="patter*n" text="patter" result="false"/>
+<test pattern="p*attern" text="attern" result="false"/>
+<test pattern="p*attern" text="p_ttern" result="false"/>
+
+</root>
diff --git a/tools/regression/xsl_reports/xsl/test/test_re_match.xsl b/tools/regression/xsl_reports/xsl/test/test_re_match.xsl
new file mode 100644
index 0000000000..eefd313166
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/test/test_re_match.xsl
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func"
+ exclude-result-prefixes="str meta exsl"
+ version="1.0">
+
+ <func:function name="meta:re_match">
+ <xsl:param name="pattern"/>
+ <xsl:param name="text"/>
+
+ <xsl:choose>
+ <xsl:when test="not( contains( $pattern, '*' ) )">
+ <func:result select="$text = $pattern"/>
+ </xsl:when>
+ <xsl:when test="$pattern = '*'">
+ <func:result select="1 = 1"/>
+ </xsl:when>
+ <xsl:when test="substring( $pattern, 1, 1 ) = '*' and substring( $pattern, string-length($pattern), 1 ) = '*' ">
+ <func:result select="contains( $text, substring( $pattern, 2, string-length($pattern) - 2 ) ) "/>
+ </xsl:when>
+ <xsl:when test="substring( $pattern, 1, 1 ) = '*'">
+ <xsl:variable name="pattern_tail" select="substring( $pattern, 2, string-length($pattern) - 1 )"/>
+ <func:result select="substring( $text, string-length($text) - string-length($pattern_tail) + 1, string-length($pattern_tail) ) = $pattern_tail"/>
+ </xsl:when>
+ <xsl:when test="substring( $pattern, string-length($pattern), 1 ) = '*' ">
+ <xsl:variable name="pattern_head" select="substring( $pattern, 1, string-length($pattern) - 1 )"/>
+ <func:result select="starts-with( $text, $pattern_head )"/>
+ </xsl:when>
+ <xsl:when test="contains( $pattern, '*' ) ">
+ <xsl:variable name="pattern_head" select="substring-before( $pattern, '*' )"/>
+ <xsl:variable name="pattern_tail" select="substring-after( $pattern, '*' )"/>
+ <func:result select="starts-with( $text, $pattern_head ) and substring( $text, string-length($text) - string-length($pattern_tail) + 1, string-length($pattern_tail) ) = $pattern_tail"/>
+ </xsl:when>
+ </xsl:choose>
+ </func:function>
+
+ <xsl:template match='test'>
+ <xsl:variable name="result" select="meta:re_match( @pattern, @text )"/>
+ <xsl:variable name="expected-result" select="@result = 'true'"/>
+ <xsl:if test="$result != $expected-result">
+ <failed regex="{@pattern}" text="{@text}" result="{$result}" expected-result="{$expected-result}"/>
+ </xsl:if>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/v2/add_expected_results.xsl b/tools/regression/xsl_reports/xsl/v2/add_expected_results.xsl
new file mode 100644
index 0000000000..b519a7754f
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/add_expected_results.xsl
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2007.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func"
+ exclude-result-prefixes="func meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="xml" encoding="utf-8"/>
+
+ <xsl:param name="expected_results_file"/>
+ <xsl:param name="failures_markup_file"/>
+ <xsl:param name="source"/>
+ <xsl:variable name="expected_results" select="document( $expected_results_file )" />
+
+ <func:function name="meta:is_test_log_complete">
+ <xsl:param name="test_log"/>
+ <xsl:variable name="type" select="$test_log/@test-type"/>
+ <func:result>
+ <xsl:choose>
+ <xsl:when test="$type='compile' or $type='compile_fail' or $test_log/compile/@result='fail' ">
+ <xsl:value-of select="count( $test_log/compile ) = 1 and count( $test_log/link) = 0 and count( $test_log/run) = 0"/>
+ </xsl:when>
+ <xsl:when test="$type='link' or $type='link_fail' or $type='' or $type='lib' or $test_log/link/@result='fail'">
+ <xsl:value-of select="count( $test_log/compile) = 1 and count( $test_log/link) = 1 and count( $test_log/run) = 0"/></xsl:when>
+ <xsl:when test="$type='run' or $type='run_fail' or $type='run_pyd' or $type='run_mpi'">
+ <xsl:value-of select="count( $test_log/compile) = 1 and count( $test_log/link) = 1 and count($test_log/run) = 1 "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ Unknown test type "<xsl:value-of select="$type"/>"
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </func:result>
+ </func:function>
+
+
+ <xsl:key name = "trk" match = "test-result" use = "concat( ../../@name, '-', ../@name, '-', @test-name )" />
+ <xsl:key name = "tak" match = "toolset-alias" use = "@name" />
+
+ <xsl:variable name="failures_markup" select="document( $failures_markup_file )" />
+ <xsl:template match="/">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="test-log">
+ <xsl:variable name="test_log" select="."/>
+ <xsl:variable name="library" select="@library"/>
+ <xsl:variable name="test-name" select="@test-name"/>
+ <xsl:variable name="toolset" select="@toolset"/>
+
+ <xsl:variable name="is_complete" select="meta:is_test_log_complete( $test_log )"/>
+
+ <xsl:element name="{local-name()}">
+ <xsl:apply-templates select="@*"/>
+
+ <xsl:variable name="has_failures" select="./*/@result = 'fail'"/>
+ <xsl:variable name="actual_result">
+ <xsl:choose>
+ <xsl:when test="$has_failures or not( $is_complete )" >
+ <xsl:text>fail</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>success</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!--
+ Select expected_results context
+ See http://clover.slavic.pitt.edu/~repertorium/plectogram/keys/keys.html for a good explanation.
+
+ Briefly, for-each doesn't iterate through expected_results, it just selects expected result
+ as current context to make "key" function work.
+ -->
+
+ <xsl:for-each select="$expected_results">
+
+ <xsl:variable name="main_toolset" select="key( 'tak', $toolset )/../@name" />
+ <xsl:variable name="toolset_name">
+ <xsl:choose>
+ <xsl:when test="$main_toolset"><xsl:value-of select="$main_toolset"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="$toolset"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="expected_results_test_case" select="key( 'trk', concat( $toolset_name, '-', $library, '-', $test-name ) )"/>
+ <xsl:variable name="test_case_markup" select="$failures_markup//library[@name=$library]/test[ meta:re_match( @name, $test-name ) ]"/>
+ <xsl:variable name="test_failures_markup" select="$test_case_markup/mark-failure/toolset[ meta:re_match( @name, $toolset ) ]/.."/>
+ <xsl:variable name="test_failures_markup2" select="$failures_markup//library[@name=$library]/mark-expected-failures/test[ meta:re_match( @name, $test-name ) ]/../toolset[ meta:re_match( @name, $toolset ) ]/.."/>
+
+ <xsl:variable name="category">
+ <xsl:choose>
+ <xsl:when test="$test_case_markup/@category">
+ <xsl:value-of select="$test_case_markup/@category"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+
+ <xsl:variable name="is_new">
+ <xsl:choose>
+ <xsl:when test="$expected_results_test_case">
+ <xsl:text>no</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>yes</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+
+ <xsl:variable name="has_explicit_markup" select="count( $test_failures_markup ) > 0 or count( $test_failures_markup2 ) > 0"/>
+
+ <xsl:variable name="expected_result">
+ <xsl:choose>
+ <xsl:when test="$has_explicit_markup">
+ <xsl:text>fail</xsl:text>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$expected_results_test_case and $expected_results_test_case/@result = 'fail'">
+ <xsl:text>fail</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>success</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="status">
+ <xsl:choose>
+ <xsl:when test="$expected_result = $actual_result">expected</xsl:when>
+ <xsl:otherwise>unexpected</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="unexpected_success" select="$status = 'unexpected' and $actual_result = 'success'"/>
+
+ <xsl:variable name="expected_reason">
+ <xsl:choose>
+ <xsl:when test="$test_failures_markup/@reason">
+ <xsl:value-of select="$test_failures_markup/@reason"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$test_failures_markup2/@reason"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+
+ <xsl:variable name="notes">
+
+ <xsl:if test="$unexpected_success and $has_explicit_markup">
+ <note>
+ <span class="auto-note">
+ This test case was explicitly marked up in
+ <a href="http://svn.boost.org/svn/boost/{$source}/status/explicit-failures-markup.xml">
+ status/explicit-failures-markup.xml</a> file in the Boost SVN as "expected to fail",
+ but is passing. Please consult the notes/output below for more details.
+ </span>
+ </note>
+ </xsl:if>
+
+ <xsl:if test="$has_explicit_markup and count( $test_failures_markup2/note ) = 0 and count( $test_failures_markup/note ) = 0">
+ <xsl:choose>
+ <xsl:when test="$unexpected_success">
+ <note>
+ <span class="auto-note">
+ No explanation was provided for this markup. Please contact the library
+ author(s)/maintainer(s) for more details.
+ </span>
+ </note>
+ </xsl:when>
+ <xsl:otherwise>
+ <note>
+ <span class="auto-note">
+ This failure was explicitly marked as expected in
+ <a href="http://svn.boost.org/svn/boost/{$source}/status/explicit-failures-markup.xml">
+ status/explicit-failures-markup.xml</a> file in the Boost SVN.
+ Please contact the library author(s)/maintainer(s) for the explanation of this markup.
+ </span>
+ </note>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+
+ <xsl:if test="count( $test_failures_markup ) > 0">
+ <xsl:for-each select="$test_failures_markup/note">
+ <xsl:copy-of select="."/>
+ </xsl:for-each>
+ </xsl:if>
+
+ <xsl:if test="count( $test_failures_markup2 ) > 0">
+ <xsl:for-each select="$test_failures_markup2/note">
+ <xsl:copy-of select="."/>
+ </xsl:for-each>
+ </xsl:if>
+
+
+ <xsl:if test="$expected_results_test_case and $expected_results_test_case/@result = 'fail'">
+ <xsl:choose>
+ <xsl:when test="$unexpected_success">
+ <note>
+ <span class="auto-note">
+ This test case used to fail in the reference ("last-known-good") release.
+ </span>
+ </note>
+ </xsl:when>
+ <xsl:otherwise>
+ <note>
+ <span class="auto-note">
+ This failure was present in the reference ("last-known-good") release.
+ </span>
+ </note>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+
+ <xsl:if test="not( $is_complete ) and not( $has_failures )">
+ <note>
+ <span class="internal-error-note">
+ <b>[Reporting Tools Internal Error]</b> This test case's XML is missing one or more log entries
+ of the regression run's steps associated with the test case's type ("<xsl:value-of select="$test_log/@test-type"/>").
+ Please <a href="mailto:mailto:boost-testing@lists.boost.org">contact reporting tools
+ maintainers</a> about this problem.
+ </span>
+ </note>
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:attribute name="result"><xsl:value-of select="$actual_result"/></xsl:attribute>
+ <xsl:attribute name="expected-result"><xsl:value-of select="$expected_result"/></xsl:attribute>
+ <xsl:attribute name="expected-reason"><xsl:value-of select="$expected_reason"/></xsl:attribute>
+ <xsl:attribute name="status"><xsl:value-of select="$status"/></xsl:attribute>
+ <xsl:attribute name="is-new"><xsl:value-of select="$is_new"/></xsl:attribute>
+ <xsl:attribute name="category"><xsl:value-of select="$category"/></xsl:attribute>
+ <xsl:element name="notes"><xsl:copy-of select="$notes"/></xsl:element>
+
+ <xsl:apply-templates select="$test_log/node()" />
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="*">
+ <xsl:element name="{local-name()}">
+ <xsl:apply-templates select="@*"/>
+ <xsl:apply-templates select="node()" />
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="@*">
+ <xsl:copy-of select="." />
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/v2/boostbook_log.xsl b/tools/regression/xsl_reports/xsl/v2/boostbook_log.xsl
new file mode 100644
index 0000000000..009f0eb27c
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/boostbook_log.xsl
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2007.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func"
+ exclude-result-prefixes="func meta"
+ version="1.0">
+
+<xsl:output method="html" encoding="UTF-8"/>
+<xsl:template match="/">
+ <html>
+ <head>
+ <title>BoostBook build log for <xsl:value-of select="build/@timestamp"/></title>
+ <style>
+ span.failure { background-color: red; }
+ </style>
+ </head>
+ <body>
+ <xsl:apply-templates/>
+ </body>
+ </html>
+</xsl:template>
+ <xsl:template match="build">
+ <pre>
+ <xsl:apply-templates/>
+ </pre>
+ </xsl:template>
+
+ <xsl:template match="line">
+ <span class="{@type}"><xsl:value-of select="text()"/></span><br/>
+ </xsl:template>
+</xsl:stylesheet> \ No newline at end of file
diff --git a/tools/regression/xsl_reports/xsl/v2/common.xsl b/tools/regression/xsl_reports/xsl/v2/common.xsl
new file mode 100644
index 0000000000..14023f0395
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/common.xsl
@@ -0,0 +1,668 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2005.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:date="http://exslt.org/dates-and-times"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:set="http://exslt.org/sets"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func"
+ exclude-result-prefixes="exsl func date str set meta"
+ version="1.0">
+
+ <xsl:variable name="output_directory" select="'output'"/>
+
+ <!-- general -->
+
+ <func:function name="meta:iif">
+ <xsl:param name="condition"/>
+ <xsl:param name="if_true"/>
+ <xsl:param name="if_false"/>
+
+ <xsl:choose>
+ <xsl:when test="$condition">
+ <func:result select="$if_true"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <func:result select="$if_false"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </func:function>
+
+ <!-- structural -->
+
+ <func:function name="meta:test_structure">
+ <xsl:param name="document"/>
+ <xsl:param name="release"/>
+ <xsl:variable name="required_toolsets" select="$explicit_markup//mark-toolset[ @status='required' ]"/>
+
+ <xsl:variable name="runs" select="$document//test-run"/>
+ <xsl:variable name="platforms" select="set:distinct( $document//test-run/@platform )"/>
+
+
+ <xsl:variable name="run_toolsets_f">
+ <platforms>
+ <xsl:for-each select="$platforms">
+ <xsl:sort select="."/>
+ <xsl:variable name="platform" select="."/>
+ <platform name="{$platform}">
+ <runs>
+ <xsl:for-each select="$runs[ @platform = $platform ]">
+ <xsl:sort select="@platform"/>
+ <run
+ runner="{@runner}"
+ timestamp="{@timestamp}"
+ platform="{@platform}"
+ run-type="{@run-type}"
+ source="{@source}"
+ revision="{@revision}">
+
+ <comment><xsl:value-of select="comment"/></comment>
+ <xsl:variable name="not_ordered_toolsets" select="set:distinct( .//test-log[ meta:is_test_log_a_test_case(.) and meta:show_toolset( @toolset, $release ) ]/@toolset ) "/>
+
+ <xsl:variable name="not_ordered_toolsets_with_info_f">
+ <xsl:for-each select="$not_ordered_toolsets">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="toolset" select="."/>
+ <xsl:variable name="required">
+ <xsl:choose>
+ <xsl:when test="count( $required_toolsets[ @name = $toolset ] ) > 0">yes</xsl:when>
+ <xsl:otherwise>no</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="required_sort_hint">
+ <xsl:choose>
+ <xsl:when test="$required = 'yes'">sort hint A</xsl:when>
+ <xsl:otherwise>sort hint B</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <toolset name="{$toolset}" required="{$required}" required_sort_hint="{$required_sort_hint}"/>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="not_ordered_toolsets_with_info" select="exsl:node-set( $not_ordered_toolsets_with_info_f )"/>
+
+ <xsl:for-each select="$not_ordered_toolsets_with_info/toolset">
+ <xsl:sort select="concat( @required_sort_hint, '-', @name )" order="ascending"/>
+ <xsl:copy-of select="."/>
+ </xsl:for-each>
+ </run>
+ </xsl:for-each>
+ </runs>
+ </platform>
+ </xsl:for-each>
+ </platforms>
+ </xsl:variable>
+ <func:result select="exsl:node-set( $run_toolsets_f )"/>
+ </func:function>
+
+
+ <func:function name="meta:test_case_status">
+ <xsl:param name="explicit_markup"/>
+ <xsl:param name="test_log"/>
+
+ <xsl:variable name="status">
+ <xsl:choose>
+ <xsl:when test="meta:is_unusable( $explicit_markup, $test_log/@library, $test_log/@toolset )">
+ <xsl:text>unusable</xsl:text>
+ </xsl:when>
+ <xsl:when test="$test_log/@result='fail' and $test_log/@status='unexpected' and $test_log/@is-new='no'">
+ <xsl:text>fail-unexpected</xsl:text>
+ </xsl:when>
+ <xsl:when test="$test_log/@result='fail' and $test_log/@status='unexpected' and $test_log/@is-new='yes'">
+ <xsl:text>fail-unexpected-new</xsl:text>
+ </xsl:when>
+ <xsl:when test="$test_log/@result='success' and $test_log/@status='unexpected'">
+ <xsl:text>success-unexpected</xsl:text>
+ </xsl:when>
+ <xsl:when test="$test_log/@status='expected'">
+ <xsl:text>expected</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>other</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <func:result select="$status"/>
+ </func:function>
+
+ <func:function name="meta:is_toolset_required">
+ <xsl:param name="toolset"/>
+ <func:result select="count( $explicit_markup/explicit-failures-markup/mark-toolset[ @name = $toolset and @status='required' ] ) > 0"/>
+ </func:function>
+
+ <func:function name="meta:is_library_beta">
+ <xsl:param name="library"/>
+ <func:result select="count( $explicit_markup/explicit-failures-markup/library[ @name = $library and @status='beta' ] ) > 0"/>
+ </func:function>
+
+ <func:function name="meta:is_test_log_a_test_case">
+ <xsl:param name="test_log"/>
+ <xsl:variable name="type" select="$test_log/@test-type"/>
+ <func:result select="$type='compile' or $type='compile_fail' or $type='link' or $type='link_fail'
+ or $type='run' or $type='run_fail' or $type='run_pyd' or $type='run_mpi'"/>
+ </func:function>
+
+
+ <func:function name="meta:is_unusable_">
+ <xsl:param name="explicit_markup"/>
+ <xsl:param name="library"/>
+ <xsl:param name="toolset"/>
+
+ <func:result select="count( $explicit_markup//library[ @name = $library ]/mark-unusable/toolset[ meta:re_match( @name, $toolset ) ] ) > 0"/>
+ </func:function>
+
+ <func:function name="meta:is_unusable">
+ <xsl:param name="explicit_markup"/>
+ <xsl:param name="library"/>
+ <xsl:param name="toolset"/>
+
+ <func:result select="count( $explicit_markup//library[ @name = $library ]/mark-unusable/toolset[ meta:re_match( @name, $toolset ) ] ) > 0"/>
+ </func:function>
+
+ <func:function name="meta:re_match">
+ <xsl:param name="pattern"/>
+ <xsl:param name="text"/>
+
+ <xsl:choose>
+ <xsl:when test="not( contains( $pattern, '*' ) )">
+ <func:result select="$text = $pattern"/>
+ </xsl:when>
+ <xsl:when test="$pattern = '*'">
+ <func:result select="1 = 1"/>
+ </xsl:when>
+ <xsl:when test="substring( $pattern, 1, 1 ) = '*' and substring( $pattern, string-length($pattern), 1 ) = '*' ">
+ <func:result select="contains( $text, substring( $pattern, 2, string-length($pattern) - 2 ) ) "/>
+ </xsl:when>
+ <xsl:when test="substring( $pattern, 1, 1 ) = '*'">
+ <xsl:variable name="pattern_tail" select="substring( $pattern, 2, string-length($pattern) - 1 )"/>
+ <func:result select="substring( $text, string-length($text) - string-length($pattern_tail) + 1, string-length($pattern_tail) ) = $pattern_tail"/>
+ </xsl:when>
+ <xsl:when test="substring( $pattern, string-length($pattern), 1 ) = '*' ">
+ <xsl:variable name="pattern_head" select="substring( $pattern, 1, string-length($pattern) - 1 )"/>
+ <func:result select="starts-with( $text, $pattern_head )"/>
+ </xsl:when>
+ <xsl:when test="contains( $pattern, '*' ) ">
+ <xsl:variable name="pattern_head" select="substring-before( $pattern, '*' )"/>
+ <xsl:variable name="pattern_tail" select="substring-after( $pattern, '*' )"/>
+ <func:result select="starts-with( $text, $pattern_head ) and substring( $text, string-length($text) - string-length($pattern_tail) + 1, string-length($pattern_tail) ) = $pattern_tail"/>
+ </xsl:when>
+ </xsl:choose>
+ </func:function>
+
+ <!-- date-time -->
+
+ <func:function name="meta:timestamp_difference">
+ <xsl:param name="x"/>
+ <xsl:param name="y"/>
+
+ <xsl:variable name="duration" select="date:difference( $x, $y )"/>
+ <xsl:choose>
+ <xsl:when test="contains( $duration, 'D' )">
+ <xsl:variable name="days" select="substring-before( $duration, 'D' )"/>
+ <func:result select="substring-after( $days, 'P' )"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <func:result select="0"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </func:function>
+
+ <func:function name="meta:format_timestamp">
+ <xsl:param name="timestamp"/>
+ <xsl:choose>
+ <xsl:when test="date:date( $timestamp ) = ''">
+ <func:result select="$timestamp"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="time" select="substring-before( date:time( $timestamp ), 'Z' )"/>
+ <xsl:variable name="day" select="date:day-in-month( $timestamp )"/>
+ <xsl:variable name="day_abbrev" select="date:day-abbreviation( $timestamp )"/>
+ <xsl:variable name="month_abbrev" select="date:month-abbreviation( $timestamp )"/>
+ <xsl:variable name="year" select="date:year( $timestamp )"/>
+ <func:result select="concat( $day_abbrev, ', ', $day, ' ', $month_abbrev, ' ', $year, ' ', $time, ' +0000' )"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </func:function>
+
+ <!-- path -->
+
+ <func:function name="meta:encode_path">
+ <xsl:param name="path"/>
+ <func:result select="translate( translate( $path, '/', '-' ), './', '-' )"/>
+ </func:function>
+
+ <func:function name="meta:output_file_path">
+ <xsl:param name="path"/>
+ <func:result select="concat( $output_directory, '/', meta:encode_path( $path ), '.html' )"/>
+ </func:function>
+
+ <func:function name="meta:log_file_path">
+ <xsl:param name="test_log"/>
+ <xsl:param name="runner"/>
+ <xsl:param name="release_postfix" select="''"/>
+ <func:result>
+ <xsl:choose>
+ <xsl:when test="meta:show_output( $explicit_markup, $test_log )">
+ <xsl:value-of select="meta:output_file_path( concat( $runner, '-', $test_log/@target-directory, $release_postfix ) )"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text></xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </func:result>
+ </func:function>
+
+ <!-- presentation -->
+
+ <func:function name="meta:show_library">
+ <xsl:param name="library"/>
+ <xsl:param name="release" select="'no'"/>
+ <func:result select="$release != 'yes' or not( meta:is_library_beta( $library ) )"/>
+ </func:function>
+
+ <func:function name="meta:show_output">
+ <xsl:param name="explicit_markup"/>
+ <xsl:param name="test_log"/>
+ <func:result select="( $test_log/@result != 'success' or $test_log/@show-run-output = 'true' or
+ $test_log/@result = 'success' and $test_log/@status = 'unexpected' )
+ and not( meta:is_unusable( $explicit_markup, $test_log/@library, $test_log/@toolset ) )
+ "/>
+ </func:function>
+
+ <func:function name="meta:show_toolset">
+ <xsl:param name="toolset"/>
+ <xsl:param name="release" select="'no'"/>
+ <func:result select="$release != 'yes' or meta:is_toolset_required( $toolset )"/>
+ </func:function>
+
+ <func:function name="meta:result_cell_class">
+ <xsl:param name="library"/>
+ <xsl:param name="toolset"/>
+ <xsl:param name="test_logs"/>
+
+ <func:result>
+ <xsl:choose>
+ <xsl:when test="meta:is_unusable( $explicit_markup, $library, $toolset )">
+ <xsl:text>unusable</xsl:text>
+ </xsl:when>
+
+ <xsl:when test="count( $test_logs ) &lt; 1">
+ <xsl:text>missing</xsl:text>
+ </xsl:when>
+
+ <xsl:when test="count( $test_logs[@result='fail' and @status='unexpected' and @is-new='no'] )">
+ <xsl:text>fail-unexpected</xsl:text>
+ </xsl:when>
+
+ <xsl:when test="count( $test_logs[@result='fail' and @status='unexpected' and @is-new='yes'] )">
+ <xsl:text>fail-unexpected-new</xsl:text>
+ </xsl:when>
+
+
+ <xsl:when test="count( $test_logs[@result='fail' and @expected-reason != '' ] )">
+ <xsl:text>fail-expected-unresearched</xsl:text>
+ </xsl:when>
+
+ <xsl:when test="count( $test_logs[@result='fail'] )">
+ <xsl:text>fail-expected</xsl:text>
+ </xsl:when>
+
+
+ <xsl:when test="count( $test_logs[@result='success' and @status='unexpected'] )">
+ <xsl:text>success-unexpected</xsl:text>
+ </xsl:when>
+
+ <xsl:when test="count( $test_logs[@status='expected'] )">
+ <xsl:text>success-expected</xsl:text>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:text>unknown</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </func:result>
+ </func:function>
+
+ <xsl:template name="insert_report_header">
+ <xsl:param name="run_date"/>
+ <xsl:param name="warnings"/>
+ <xsl:param name="purpose"/>
+
+ <div class="report-info">
+ <div>
+ <b>Report Time: </b> <xsl:value-of select="meta:format_timestamp( $run_date )"/>
+ </div>
+
+ <xsl:if test="$purpose">
+ <div>
+ <b>Purpose: </b> <xsl:value-of select="$purpose"/>
+ </div>
+ </xsl:if>
+
+ <xsl:if test="$warnings">
+ <xsl:for-each select="str:split( $warnings, '+' )">
+ <div class="report-warning">
+ <b>Warning: </b>
+ <a href="mailto:boost-testing@lists.boost.org?subject=[Report Pages] {.} ({meta:format_timestamp( $run_date )})" class="warning-link">
+ <xsl:value-of select="."/>
+ </a>
+ </div>
+ </xsl:for-each>
+ </xsl:if>
+
+ </div>
+
+ </xsl:template>
+
+
+ <xsl:template name="insert_view_link">
+ <xsl:param name="page"/>
+ <xsl:param name="release"/>
+ <xsl:param name="class"/>
+
+ <xsl:choose>
+ <xsl:when test="$release='yes'">
+ <a href="{$page}.html" class="{$class}" target="_top">
+ <xsl:text>Full View</xsl:text>
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="{$page}_release.html" class="{$class}" target="_top">
+ <xsl:text>Release View</xsl:text>
+ </a>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:template>
+
+
+ <xsl:template name="insert_page_links">
+ <xsl:param name="page"/>
+ <xsl:param name="release"/>
+ <xsl:param name="mode"/>
+
+ <div class="links">
+ <xsl:copy-of select="document( 'html/make_tinyurl.html' )"/>
+ <xsl:text>&#160;|&#160;</xsl:text>
+ <xsl:call-template name="insert_view_link">
+ <xsl:with-param name="page" select="$page"/>
+ <xsl:with-param name="class" select="''"/>
+ <xsl:with-param name="release" select="$release"/>
+ </xsl:call-template>
+
+ <xsl:variable name="release_postfix">
+ <xsl:if test="$release='yes'">_release</xsl:if>
+ </xsl:variable>
+
+ <xsl:text>&#160;|&#160;</xsl:text>
+ <a href="../{$mode}/{$page}{$release_postfix}.html" class="view-link" target="_top">
+ <xsl:value-of select="$mode"/><xsl:text> View</xsl:text>
+ </a>
+
+ <xsl:text>&#160;|&#160;</xsl:text>
+ <a href="{$page}{$release_postfix}_.html#legend">
+ <xsl:text>Legend</xsl:text>
+ </a>
+
+ </div>
+
+ </xsl:template>
+
+
+ <xsl:template name="insert_runners_rows">
+ <xsl:param name="mode"/>
+ <xsl:param name="top_or_bottom"/>
+ <xsl:param name="run_toolsets"/>
+ <xsl:param name="run_date"/>
+
+ <xsl:variable name="colspan">
+ <xsl:choose>
+ <xsl:when test="$mode = 'summary'">1</xsl:when>
+ <xsl:when test="$mode = 'details'">2</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+
+ <xsl:if test="$top_or_bottom = 'top'">
+ <tr>
+ <td colspan="{$colspan}">&#160;</td>
+ <xsl:for-each select="$run_toolsets/platforms/platform">
+ <xsl:if test="count(./runs/run/toolset) &gt; 0">
+ <td colspan="{count(./runs/run/toolset)}" class="runner">
+ <xsl:value-of select="@name"/>
+ </td>
+ </xsl:if>
+ </xsl:for-each>
+ <td colspan="{$colspan}">&#160;</td>
+ </tr>
+ </xsl:if>
+
+ <tr>
+ <td colspan="{$colspan}">&#160;</td>
+ <xsl:for-each select="$run_toolsets//runs/run[ count(toolset) > 0 ]">
+ <td colspan="{count(toolset)}" class="runner">
+ <a href="../{@runner}.html">
+ <xsl:value-of select="@runner"/>
+ </a>
+ </td>
+ </xsl:for-each>
+ <td colspan="{$colspan}">&#160;</td>
+ </tr>
+
+ <tr>
+ <td colspan="{$colspan}">&#160;</td>
+ <xsl:for-each select="$run_toolsets//runs/run[ count(toolset) > 0 ]">
+ <td colspan="{count(toolset)}" class="revision">
+ rev <xsl:value-of select="@revision"/>
+ </td>
+ </xsl:for-each>
+ <td colspan="{$colspan}">&#160;</td>
+ </tr>
+
+ <tr>
+ <td colspan="{$colspan}">&#160;</td>
+ <xsl:for-each select="$run_toolsets//runs/run[ count(toolset) > 0 ]">
+ <xsl:variable name="timestamp_diff" select="meta:timestamp_difference( @timestamp, $run_date )"/>
+ <xsl:variable name="age" select="meta:iif( $timestamp_diff &lt; 30, $timestamp_diff, 30 )"/>
+ <td colspan="{count(toolset)}" class="timestamp">
+ <span class="timestamp-{$age}"><xsl:value-of select="meta:format_timestamp( @timestamp )"/></span>
+ <xsl:if test="@run-type != 'full'">
+ <span class="run-type-{@run-type}"><xsl:value-of select="substring( @run-type, 1, 1 )"/></span>
+ </xsl:if>
+ </td>
+ </xsl:for-each>
+ <td colspan="{$colspan}">&#160;</td>
+ </tr>
+
+ <xsl:if test="$top_or_bottom = 'bottom'">
+ <tr>
+ <td colspan="{$colspan}">&#160;</td>
+ <xsl:for-each select="$run_toolsets/platforms/platform">
+ <xsl:if test="count(./runs/run/toolset) &gt; 0">
+ <td colspan="{count(./runs/run/toolset)}" class="runner">
+ <xsl:value-of select="@name"/>
+ </td>
+ </xsl:if>
+ </xsl:for-each>
+ <td colspan="{$colspan}">&#160;</td>
+ </tr>
+ </xsl:if>
+
+ </xsl:template>
+
+ <xsl:template name="insert_toolsets_row">
+ <xsl:param name="mode"/>
+ <xsl:param name="library"/>
+ <xsl:param name="library_marks"/>
+ <xsl:param name="run_date"/>
+
+ <tr valign="middle">
+ <xsl:variable name="colspan">
+ <xsl:choose>
+ <xsl:when test="$mode = 'summary'">1</xsl:when>
+ <xsl:when test="$mode = 'details'">2</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="title">
+ <xsl:choose>
+ <xsl:when test="$mode = 'summary'">&#160;library&#160;/&#160;toolset&#160;</xsl:when>
+ <xsl:when test="$mode = 'details'">&#160;test&#160;/&#160;toolset&#160;</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <td class="head" colspan="{$colspan}" width="1%"><xsl:value-of select="$title"/></td>
+
+
+ <xsl:for-each select="$run_toolsets//runs/run/toolset">
+ <xsl:variable name="toolset" select="@name"/>
+
+ <xsl:variable name="class">
+ <xsl:choose>
+ <xsl:when test="@required='yes'">
+ <xsl:text>required-toolset-name</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>toolset-name</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <td class="{$class}">
+ <xsl:variable name="age" select="meta:timestamp_difference( ../@timestamp, $run_date )"/>
+ <span class="timestamp-{$age}">
+
+ <!-- break toolset names into words -->
+ <xsl:for-each select="str:tokenize($toolset, '-')">
+ <xsl:value-of select="." />
+ <xsl:if test="position()!=last()">
+ <xsl:text>- </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+
+ <xsl:if test="$mode = 'details'">
+ <!-- prepare toolset notes -->
+ <xsl:variable name="toolset_notes_fragment">
+ <xsl:for-each select="$library_marks/note">
+ <xsl:if test="count( ../toolset[meta:re_match( @name, $toolset )] ) > 0">
+ <note index="{position()}"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="toolset_notes" select="exsl:node-set( $toolset_notes_fragment )/*"/>
+ <xsl:if test="count( $toolset_notes ) > 0">
+ <span class="super">
+ <xsl:for-each select="$toolset_notes">
+ <xsl:variable name="note_index" select="@index"/>
+ <xsl:if test="generate-id( . ) != generate-id( $toolset_notes[1] )">, </xsl:if>
+ <a href="#{$library}-note-{$note_index}" title="Note {$note_index}">
+ <xsl:value-of select="$note_index"/>
+ </a>
+ </xsl:for-each>
+ </span>
+ </xsl:if>
+ </xsl:if>
+
+ </span>
+ </td>
+ </xsl:for-each>
+
+ <td class="head" width="1%"><xsl:value-of select="$title"/></td>
+ </tr>
+ </xsl:template>
+
+ <xsl:template name="show_notes">
+ <xsl:param name="explicit_markup"/>
+ <xsl:param name="notes"/>
+ <div class="notes">
+ <xsl:for-each select="$notes">
+ <div>
+ <xsl:variable name="ref_id" select="@refid"/>
+ <xsl:call-template name="show_note">
+ <xsl:with-param name="note" select="."/>
+ <xsl:with-param name="references" select="$ref_id"/>
+ </xsl:call-template>
+ </div>
+ </xsl:for-each>
+ </div>
+ </xsl:template>
+
+ <xsl:template name="show_note">
+ <xsl:param name="note"/>
+ <xsl:param name="references"/>
+
+ <div class="note">
+ <xsl:variable name="author">
+ <xsl:choose>
+ <xsl:when test="$note/@author">
+ <xsl:value-of select="$note/@author"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="date">
+ <xsl:choose>
+ <xsl:when test="$note/@date">
+ <xsl:value-of select="$note/@date"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <span class="note-header">
+ <xsl:choose>
+ <xsl:when test="$author != '' and $date != ''">
+ [&#160;<xsl:value-of select="$author"/>&#160;<xsl:value-of select="$date"/>&#160;]
+ </xsl:when>
+ <xsl:when test="$author != ''">
+ [&#160;<xsl:value-of select="$author"/>&#160;]
+ </xsl:when>
+ <xsl:when test="$date != ''">
+ [&#160;<xsl:value-of select="$date"/>&#160;]
+ </xsl:when>
+ </xsl:choose>
+ </span>
+
+ <xsl:if test="$references">
+ <!-- lookup references (refid="17,18") -->
+ <xsl:for-each select="str:tokenize($references, ',')">
+ <xsl:variable name="ref_id" select="."/>
+ <xsl:variable name="referenced_note" select="$explicit_markup//note[ $ref_id = @id ]"/>
+
+ <xsl:choose>
+ <xsl:when test="$referenced_note">
+ <xsl:copy-of select="$referenced_note/node()"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$ref_id"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:if>
+
+ <xsl:copy-of select="$note/node()"/>
+
+ </div>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/v2/dump_toolsets.xsl b/tools/regression/xsl_reports/xsl/v2/dump_toolsets.xsl
new file mode 100644
index 0000000000..b9058e35d0
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/dump_toolsets.xsl
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2006.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:meta="http://www.meta-comm.com"
+ exclude-result-prefixes="meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="xml" encoding="utf-8"/>
+
+ <xsl:template match="/">
+ <xsl:for-each select="expected-failures/toolset">
+ <xsl:sort select="@name"/>
+ <xsl:value-of select="@name"/>
+ <xsl:if test="count(./toolset-alias)">
+ <xsl:text> aka </xsl:text>
+ <xsl:for-each select="toolset-alias">
+ <xsl:sort select="@name"/>
+ <xsl:value-of select="@name"/>
+ <xsl:text> </xsl:text>
+ </xsl:for-each>
+ </xsl:if>
+<xsl:text>
+</xsl:text>
+ </xsl:for-each>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/v2/expected_to_1_33_format.xsl b/tools/regression/xsl_reports/xsl/v2/expected_to_1_33_format.xsl
new file mode 100644
index 0000000000..71f33d2c1c
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/expected_to_1_33_format.xsl
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:set="http://exslt.org/sets"
+ extension-element-prefixes="set"
+ version="1.0">
+
+ <xsl:output method="xml" encoding="utf-8"/>
+
+ <xsl:template match="/">
+ <expected-failures>
+ <xsl:variable name="toolsets" select="set:distinct(//test-result/@toolset)"/>
+ <xsl:for-each select="$toolsets">
+ <xsl:variable name="toolset" select="."/>
+ <toolset name="{$toolset}">
+ <xsl:variable name="toolset_test_cases" select="//test-result[@toolset = $toolset]"/>
+ <xsl:variable name="libraries" select="set:distinct($toolset_test_cases/@library)"/>
+ <xsl:for-each select="$libraries">
+ <xsl:variable name="library" select="."/>
+ <library name="{$library}">
+ <xsl:variable name="test_results" select="$toolset_test_cases[@library = $library]"/>
+ <xsl:for-each select="$test_results">
+ <xsl:variable name="test_result" select="."/>
+ <test-result test-name="{$test_result/@test-name}" result="{$test_result/@result}"/>
+ </xsl:for-each>
+ </library>
+ </xsl:for-each>
+ </toolset>
+ </xsl:for-each>
+ </expected-failures>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/v2/html/issues_legend.html b/tools/regression/xsl_reports/xsl/v2/html/issues_legend.html
new file mode 100644
index 0000000000..6274048b55
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/html/issues_legend.html
@@ -0,0 +1,36 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<div class="legend">
+<table border="0" summary="report description">
+<tr>
+ <td>
+ <table border="0" summary="legend">
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected new fail legend">
+ <tr class="library-row-single"><td class="library-fail-unexpected-new">&lt;toolset&gt;</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">Failure on a newly added test/compiler.</td>
+ </tr>
+ <tr>
+ <td>
+ <table width="100%" summary="unexpected fail legend">
+ <tr class="library-row-single"><td class="library-fail-unexpected">&lt;toolset&gt;</td></tr>
+ </table>
+ </td>
+ <td class="legend-item">Unexpected failure.</td>
+ </tr>
+ </table>
+ </td>
+</tr>
+</table>
+</div>
diff --git a/tools/regression/xsl_reports/xsl/v2/html/library_developer_legend.html b/tools/regression/xsl_reports/xsl/v2/html/library_developer_legend.html
new file mode 100644
index 0000000000..009211ac19
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/html/library_developer_legend.html
@@ -0,0 +1,82 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2005.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<div class="legend">
+<table border="0" summary="report description">
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="success legend">
+ <tr class="library-row-single"><td class="library-success-expected">pass</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">Success.</td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unexpected pass legend">
+ <tr class="library-row-single"><td class="library-success-unexpected">pass</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">Unexpected success; follow the link for more details.</td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="expected fail legend">
+ <tr class="library-row-single"><td class="library-fail-expected">fail*</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">Expected failure; follow the link for more details.</td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unusable legend">
+ <tr class="library-row-single"><td class="library-unusable">n/a</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">The library author marked it as unusable on this particular platform/toolset.</td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unresearched legend">
+ <tr class="library-row-single"><td class="library-fail-expected-unresearched">fail?</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">Unsearched failure; follow the link for more details.</td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unexpected new fail legend">
+ <tr class="library-row-single"><td class="library-fail-unexpected-new">fail</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">Failure on a newly added test/compiler.</td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unexpected fail legend">
+ <tr class="library-row-single"><td class="library-fail-unexpected">fail</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">Unexpected failure/regression.</td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ </td>
+ <td class="legend-explanation"></td>
+ </tr>
+</table>
+<hr/>
+<table border="0" summary="report description">
+ <tr>
+ <td><span class="run-type-incremental">i</span></td>
+ <td class="legend-explanation">An incremental run.</td>
+ </tr>
+</table>
+</div>
diff --git a/tools/regression/xsl_reports/xsl/v2/html/library_user_legend.html b/tools/regression/xsl_reports/xsl/v2/html/library_user_legend.html
new file mode 100644
index 0000000000..bae1742e94
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/html/library_user_legend.html
@@ -0,0 +1,89 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2005.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<div class="legend">
+<table border="0" summary="report description">
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="success legend">
+ <tr class="library-row-single"><td class="library-success-expected user-library-success-expected">pass</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">The test successfully passes.</td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="expected fail legend">
+ <tr class="library-row-single"><td class="library-fail-expected user-library-fail-expected"><u>fail*</u></td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ A <b>known failure</b> that the library maintainers are aware about. Please follow the link to
+ find out how it affects the library's functionality.
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unusable legend">
+ <tr class="library-row-single"><td class="library-unusable user-library-unusable">unusable</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ The library author marked it as <b>unusable</b> on this particular platform/toolset. Please
+ see the corresponding footnote.
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unresearched legend">
+ <tr class="library-row-single"><td class="library-fail-expected-unresearched user-library-fail-expected-unresearched"><u>fail?</u></td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ An <b>unsearched failure</b>: the library maintainers are aware of it, but need help with
+ investigating/addressing it for future releases. Please follow the link to
+ access the details and find out how it affects library functionality. </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unexpected new fail legend">
+ <tr class="library-row-single"><td class="library-fail-unexpected-new user-library-fail-unexpected-new"><u>fail</u></td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ A <b>new failure</b> on the test/compiler added in this release that hasn't been accounted for yet.
+ Please follow the link to access the details.
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unexpected fail legend">
+ <tr class="library-row-single user-library-row-single"><td class="library-fail-unexpected"><u>fail</u></td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ A <b>regression</b> comparing to the previous release. Please follow the link to
+ access the details.
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ </td>
+ <td class="legend-explanation"></td>
+ </tr>
+</table>
+<hr/>
+<table border="0" summary="report description">
+ <tr>
+ <td><span class="run-type-incremental">i</span></td>
+ <td class="legend-explanation">An incremental run.</td>
+ </tr>
+</table>
+</div>
diff --git a/tools/regression/xsl_reports/xsl/v2/html/make_tinyurl.html b/tools/regression/xsl_reports/xsl/v2/html/make_tinyurl.html
new file mode 100644
index 0000000000..e57fb06a4f
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/html/make_tinyurl.html
@@ -0,0 +1,22 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<span>
+<script type="text/javascript">
+<!--
+function make_tinyurl()
+{
+ window.open( 'http://tinyurl.com/create.php?url=' + parent.location.href );
+}
+//-->
+</script>
+
+<a href="javascript:make_tinyurl()">TinyUrl</a>
+</span>
diff --git a/tools/regression/xsl_reports/xsl/v2/html/master.css b/tools/regression/xsl_reports/xsl/v2/html/master.css
new file mode 100644
index 0000000000..a6dc486b68
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/html/master.css
@@ -0,0 +1,654 @@
+/*
+
+Copyright MetaCommunications, Inc. 2003-2005.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+*/
+
+/* All reports */
+
+body
+{
+ background-color: white;
+}
+
+body.user-toc
+{
+ background-color: #f0f0f0;
+}
+
+body.developer-toc
+{
+ background-color: #f0f5ff;
+}
+
+span.super
+{
+ vertical-align: super;
+ font-size: 80%;
+ margin-left: 3pt;
+}
+
+h1.page-title
+{
+ text-align: left;
+ text-transform: capitalize;
+ margin-top: 5pt;
+ margin-bottom: 10pt;
+}
+
+img
+{
+ display: inline;
+}
+
+ a.hover-link:link
+,a.hover-link:visited
+,a.hover-link:active
+{
+ color: black;
+ text-decoration: none;
+}
+
+a.hover-link:hover
+{
+ color: black;
+ text-decoration: underline;
+}
+
+ a.warning-link:link
+,a.warning-link:visited
+,a.warning-link:active
+{
+ color: red;
+ text-decoration: none;
+}
+
+a.warning-link:hover
+{
+ color: red;
+ text-decoration: underline;
+}
+
+a.view-link
+{
+ text-transform: capitalize;
+}
+
+div.statistics
+{
+ width: 80%;
+ padding-bottom: 5pt;
+}
+
+div.legend
+{
+ width: 80%;
+ background-color: #f5f5f5;
+ margin-top: 10pt;
+ margin-bottom: 10pt;
+}
+
+div.comment
+{
+ width: 80%;
+ background-color: #f5f5f5;
+ padding-left: 10pt;
+ padding-right: 10pt;
+ padding-bottom: 10pt;
+}
+
+div.links
+{
+ margin-top: 0pt;
+ margin-bottom: 0pt;
+}
+
+table.header-table
+{
+ margin-left: 10pt;
+ margin-top: 20pt;
+ margin-bottom: 10pt;
+ width: 80%;
+}
+
+td.header-item
+{
+ text-align: left;
+ vertical-align: top;
+ font-weight: bold;
+}
+
+td.header-item-content
+{
+ padding-left: 20pt;
+ padding-bottom: 10pt;
+}
+
+td.legend-item
+{
+ padding: 0pt;
+ width: 50pt;
+}
+
+td.legend-explanation
+{
+ padding-left: 5pt;
+}
+
+div.acknowledgement
+{
+ text-align: left;
+ margin-top: 10pt;
+ margin-left: 5pt;
+ margin-bottom: 10pt;
+}
+
+div.report-info
+{
+ text-align: left;
+ margin-bottom: 10pt;
+ width: 80%;
+}
+
+div.report-warning
+{
+ color: red;
+}
+
+div.library-name
+{
+ margin-top: 20pt;
+ margin-bottom: 10pt;
+ text-align: left;
+ font-size: 125%;
+ font-weight: bold;
+}
+
+span.run-type-incremental
+{
+ margin-left: 3pt;
+ padding-left: 1pt;
+ padding-right: 1pt;
+ background-color: yellow;
+}
+
+ span.timestamp-1
+,span.timestamp-2
+{
+ color: #555555;
+}
+
+ span.timestamp-3
+,span.timestamp-4
+,span.timestamp-5
+,span.timestamp-6
+,span.timestamp-7
+{
+ color: #999999;
+}
+
+ span.timestamp-8
+,span.timestamp-9
+,span.timestamp-10
+,span.timestamp-11
+,span.timestamp-12
+,span.timestamp-13
+,span.timestamp-14
+,span.timestamp-15
+,span.timestamp-16
+,span.timestamp-17
+,span.timestamp-18
+,span.timestamp-19
+,span.timestamp-20
+,span.timestamp-21
+,span.timestamp-22
+,span.timestamp-23
+,span.timestamp-24
+,span.timestamp-25
+,span.timestamp-26
+,span.timestamp-27
+,span.timestamp-28
+,span.timestamp-29
+,span.timestamp-30
+{
+ color: #dddddd;
+}
+
+
+table.summary-table
+,table.library-table
+{
+ border-collapse: collapse;
+ border: 2px solid black;
+ margin: 5px;
+}
+
+ table.summary-table td
+,table.library-table td
+{
+ text-align: center;
+ border-left: 1px solid black;
+ border-right: 1px solid black;
+}
+
+ a.log-link:link
+,a.log-link:visited
+{
+ color: black;
+}
+
+ a.log-link:active
+,a.log-link:hover
+,a.legend-link:link
+,a.legend-link:visited
+,a.legend-link:active
+,a.legend-link:hover
+{
+ color: black;
+ text-decoration: underline;
+}
+
+td.runner
+{
+ color: black;
+ font-weight: bold;
+ border-top: 1px solid black;
+ padding-left: 3pt;
+ padding-right: 3pt;
+
+}
+
+td.timestamp
+{
+ color: black;
+ border-bottom: 1px solid black;
+ padding-left: 3pt;
+ padding-right: 3pt;
+}
+
+ td.toolset-name
+,td.required-toolset-name
+{
+ vertical-align: middle;
+ padding-left: 3pt;
+ padding-right: 3pt;
+ word-spacing: -3pt;
+}
+
+td.required-toolset-name
+{
+ font-weight: bold;
+}
+
+td.library-test-category-header
+{
+ border-top: 1px solid gray;
+}
+
+tr.summary-row-first td
+, tr.library-row-first td
+{
+ border-top: 1px solid gray;
+ border-bottom: 0px;
+}
+
+tr.summary-row-last td
+, tr.library-row-last td
+{
+ border-top: 0px;
+ border-bottom: 1px solid gray;
+}
+
+tr.summary-row-single td
+, tr.library-row-single td
+{
+ border-top: 1px solid gray;
+ border-bottom: 1px solid gray;
+}
+
+tr.summary-row td
+, tr.library-row td
+{
+ border-bottom: 0px;
+ border-top: 0px;
+}
+
+ td.library-success-expected
+, td.summary-success-expected
+, td.summary-fail-expected
+, td.summary-unknown-status
+, td.summary-fail-expected-unresearched
+{
+ width: 60pt;
+ text-align: center;
+ background-color: lightgreen;
+ border-left: 1px solid black;
+ border-right: 1px solid black;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+ td.summary-unknown-status
+{
+ background-color: white;
+}
+
+ td.library-success-unexpected
+,td.summary-success-unexpected
+{
+ width: 60pt;
+ text-align: center;
+ background-color: green;
+ color: white;
+ border: 0px;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+ td.user-library-success-unexpected
+, td.user-summary-success-unexpected
+{
+ background-color: lightgreen;
+ color: black;
+}
+
+ td.library-success-unexpected a.log-link:link
+,td.library-success-unexpected a.log-link:visited
+,td.library-success-unexpected a.log-link:active
+,td.library-success-unexpected a.log-link:hover
+{
+ color: white;
+}
+
+ td.user-library-success-unexpected a.log-link:link
+, td.user-library-success-unexpected a.log-link:visited
+, td.user-library-success-unexpected a.log-link:active
+, td.user-library-success-unexpected a.log-link:hover
+{
+ color: black;
+}
+
+ td.summary-unusable
+, td.library-unusable
+, td.library-fail-expected
+{
+ width: 60pt;
+ text-align: center;
+ background-color: silver;
+ color: black;
+ border: 0px;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+
+ tr.summary-row td.summary-fail-unexpected
+,tr.summary-row-first td.summary-fail-unexpected
+,tr.summary-row-last td.summary-fail-unexpected
+,tr.summary-row-single td.summary-fail-unexpected
+{
+ width: 60pt;
+ text-align: center;
+ background-color: red;
+ color: black;
+ border: 2px solid black;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+ td.summary-missing
+, td.library-missing
+{
+ width: 60pt;
+ text-align: center;
+ background-color: white;
+ color: black;
+ border: 0px;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+td.library-fail-expected-unresearched
+{
+ width: 60pt;
+ text-align: center;
+ background-color: white;
+ color: black;
+ border: 1px solid black;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+
+
+ tr.summary-row-first td.summary-missing
+, tr.summary-row-single td.summary-missing
+, tr.library-row-first td.library-missing
+, tr.library-row-single td.library-missing
+{
+ border-top: 1px solid black;
+}
+
+ tr.summary-row-last td.summary-missing
+, tr.summary-row-single td.summary-missing
+, tr.library-row-last td.library-missing
+, tr.library-row-single td.library-missing
+{
+ border-bottom: 1px solid black;
+}
+
+
+/* Summary */
+
+table.summary-table td.library-name
+{
+ width: 100pt;
+ padding-left: 6pt;
+ padding-right: 6pt;
+ border-top: 1px solid gray;
+ border-bottom: 1px solid gray;
+ text-align: left;
+}
+
+ tr.summary-row td.summary-fail-unexpected-new
+, tr.summary-row-first td.summary-fail-unexpected-new
+, tr.summary-row-last td.summary-fail-unexpected-new
+, tr.summary-row-single td.summary-fail-unexpected-new
+
+, tr.library-row td.library-fail-unexpected-new
+, tr.library-row-first td.library-fail-unexpected-new
+, tr.library-row-last td.library-fail-unexpected-new
+, tr.library-row-single td.library-fail-unexpected-new
+
+, tr.summary-row td.user-summary-fail-expected-unresearched
+, tr.summary-row-first td.user-summary-fail-expected-unresearched
+, tr.summary-row-last td.user-summary-fail-expected-unresearched
+, tr.summary-row-single td.user-summary-fail-expected-unresearched
+
+, tr.library-row td.user-library-fail-expected-unresearched
+, tr.library-row-first td.user-library-fail-expected-unresearched
+, tr.library-row-last td.user-library-fail-expected-unresearched
+, tr.library-row-single td.user-library-fail-expected-unresearched
+{
+ width: 60pt;
+ text-align: center;
+ background-color: yellow;
+ color: black;
+ border: 2px solid black;
+}
+
+/* Detailed */
+
+.library-conf-problem
+{
+ font-size: 70%;
+ font-weight: normal;
+}
+
+div.library-toc
+{
+ margin: 5pt;
+}
+
+
+li.library-toc-entry
+{
+ margin-left: 5pt;
+ list-style-type: square;
+}
+
+
+div.library-footer
+{
+ margin: 5px;
+}
+
+
+table.library-table td.test-name
+{
+ width: 150pt;
+ padding-left: 6pt;
+ padding-right: 6pt;
+ border-right: 0;
+ border-top: 1px solid gray;
+ border-bottom: 1px solid gray;
+ text-align: left;
+}
+
+table.library-table td.test-type
+{
+ padding-right: 5px;
+ border-left: 0;
+ border-right: 0;
+ border-top: 1px solid gray;
+ border-bottom: 1px solid gray;
+ text-align: right;
+}
+
+ tr.library-row td.library-fail-unexpected
+, tr.library-row-first td.library-fail-unexpected
+, tr.library-row-last td.library-fail-unexpected
+, tr.library-row-single td.library-fail-unexpected
+{
+ width: 60pt;
+ text-align: center;
+ background-color: red;
+ font-weight: bold;
+ color: black;
+ border: 2px solid black;
+}
+
+table.library-library-notes
+{
+ background-color: LemonChiffon;
+ width: 80%;
+ margin-left: 5px;
+ margin-right: 5px;
+}
+
+tr.library-library-note
+{
+}
+
+div.note
+{
+ padding: 3pt;
+}
+
+span.note-header
+{
+ font-weight: bold;
+}
+
+span.auto-note
+{
+ font-style: italic;
+}
+
+span.internal-error-note
+{
+ color: red;
+}
+
+/* Log */
+
+div.log-test-title
+{
+ font-size: 1.5em;
+ font-weight: bold;
+}
+
+div.log-test-header
+{
+ border-bottom: 1px solid black;
+ margin-bottom: 5pt;
+}
+
+div.notes-title
+{
+ font-weight: bold;
+ background-color: #ffffcc;
+}
+
+div.notes
+{
+ padding: 3pt;
+ background-color: #ffffcc;
+}
+
+div.notes-title
+{
+ font-weight: bold;
+}
+
+div.log-compiler-output-title
+{
+ font-weight: bold;
+}
+
+div.log-linker-output-title
+{
+ font-weight: bold;
+}
+
+div.log-run-output-title
+{
+ font-weight: bold;
+}
+
+span.output-fail
+{
+ color: red;
+}
+
+
+/* Issues page */
+
+table.library-issues-table
+{
+ border-collapse: collapse;
+ border: 2px solid black;
+}
+
+table.library-issues-table td
+{
+ border: 1px solid #c0c0c0;
+ text-align: center;
+ margin-right: 5px;
+}
+
+table.library-issues-table td.failures-row
+{
+ text-align: left;
+ padding: 0px;
+}
+
+ table.issue-box tr.library-row-single td.library-fail-unexpected-new
+,table.issue-box tr.library-row-single td.library-fail-unexpected
+{
+ border: 0px;
+ font-weight: normal;
+}
diff --git a/tools/regression/xsl_reports/xsl/v2/html/summary_developer_legend.html b/tools/regression/xsl_reports/xsl/v2/html/summary_developer_legend.html
new file mode 100644
index 0000000000..b85a6403fa
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/html/summary_developer_legend.html
@@ -0,0 +1,72 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2005.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<div class="legend">
+<table border="0" summary="report description">
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="success legend">
+ <tr class="summary-row-single"><td class="summary-success-expected">OK</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ All expected tests pass.
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unexpected pass legend">
+ <tr class="summary-row-single"><td class="summary-success-unexpected">OK</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ All expected tests pass, and some other tests that were expected to fail
+ unexpectedly pass as well.
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unexpected new fail legend">
+ <tr class="summary-row-single"><td class="summary-fail-unexpected-new">fail</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ There are some failures on the newly added tests/compiler(s).
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unexpected fail legend">
+ <tr class="summary-row-single"><td class="summary-fail-unexpected">broken</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ Tests that the library author expects to pass are currently failing.
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unusable legend">
+ <tr class="summary-row-single"><td class="summary-unusable">n/a</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ The library author marked it as unusable on particular platform/toolset.
+ </td>
+ </tr>
+</table>
+<hr/>
+<table border="0" summary="report description" id="Table1">
+ <tr>
+ <td><span class="run-type-incremental">i</span></td>
+ <td class="legend-explanation">An incremental run.</td>
+ </tr>
+</table>
+</div>
diff --git a/tools/regression/xsl_reports/xsl/v2/html/summary_user_legend.html b/tools/regression/xsl_reports/xsl/v2/html/summary_user_legend.html
new file mode 100644
index 0000000000..1fbf68a4cd
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/html/summary_user_legend.html
@@ -0,0 +1,76 @@
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2005.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<div class="legend">
+<table border="0" summary="report description">
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="success legend">
+ <tr class="summary-row-single"><td class="summary-success-expected user-summary-success-expected">&#160;pass&#160;</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ All library's tests pass.
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="expected fail legend">
+ <tr class="summary-row-single"><td class="summary-fail-expected user-summary-fail-expected"><u>details</u></td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ Most of the library's tests pass, but there are some <b>known failures</b> which might affect the library's
+ functionality. Please follow the link to see the detailed report.
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unexpected new fail legend">
+ <tr class="summary-row-single"><td class="summary-fail-unexpected-new user-summary-fail-unexpected-new"><u>details</u></td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ Some of the <b>newly added</b> library's tests fail, or some of the library's tests fail on
+ the <b>newly added compiler</b>, or some of the tests fail due to <b>unresearched
+ reasons</b>. Please follow the link to see the detailed report.
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unexpected fail legend">
+ <tr class="summary-row-single"><td class="summary-fail-unexpected user-summary-fail-unexpected"><u>regress.</u></td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ There are some <b>regressions</b> in the library comparing to the previous release.
+ Please follow the link to see the detailed report.
+ </td>
+ </tr>
+ <tr>
+ <td class="legend-item" width="50pt">
+ <table width="100%" summary="unusable legend">
+ <tr class="summary-row-single"><td class="summary-unusable user-summary-unusable">unusable</td></tr>
+ </table>
+ </td>
+ <td class="legend-explanation">
+ The library author marked it as <b>unusable</b> on the particular platform/toolset.
+ Please follow the link to see the detailed report.
+ </td>
+ </tr>
+</table>
+<hr/>
+<table border="0" summary="report description" id="Table1">
+ <tr>
+ <td><span class="run-type-incremental">i</span></td>
+ <td class="legend-explanation">An incremental run.</td>
+ </tr>
+</table>
+</div>
diff --git a/tools/regression/xsl_reports/xsl/v2/issues_page.xsl b/tools/regression/xsl_reports/xsl/v2/issues_page.xsl
new file mode 100644
index 0000000000..64117d9007
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/issues_page.xsl
@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:meta="http://www.meta-comm.com"
+ xmlns:set="http://exslt.org/sets"
+ extension-element-prefixes="func exsl"
+ exclude-result-prefixes="exsl set meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="html"
+ doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
+ encoding="utf-8"
+ indent="yes"
+ />
+
+
+ <xsl:param name="source"/>
+ <xsl:param name="run_date"/>
+ <xsl:param name="warnings"/>
+ <xsl:param name="comment_file"/>
+ <xsl:param name="expected_results_file"/>
+ <xsl:param name="explicit_markup_file"/>
+ <xsl:param name="release"/>
+
+ <!-- the author-specified expected test results -->
+ <xsl:variable name="explicit_markup" select="document( $explicit_markup_file )"/>
+ <xsl:variable name="expected_results" select="document( $expected_results_file )" />
+
+ <xsl:variable name="release_postfix">
+ <xsl:if test="$release='yes'">
+ <xsl:text>_release</xsl:text>
+ </xsl:if>
+ </xsl:variable>
+
+ <!-- necessary indexes -->
+ <xsl:key
+ name="test_name_key"
+ match="test-log"
+ use="concat( @library, '@', @test-name )"/>
+
+ <xsl:key
+ name="library_key"
+ match="test-log"
+ use="@library"/>
+ <xsl:key name="toolset_key" match="test-log" use="@toolset"/>
+
+ <!-- toolsets -->
+
+ <xsl:variable name="required_toolsets" select="$explicit_markup//mark-toolset[ @status='required' ]"/>
+ <xsl:variable name="required_toolset_names" select="$explicit_markup//mark-toolset[ @status='required' ]/@name"/>
+
+ <!-- libraries -->
+
+ <xsl:variable
+ name="failing_tests"
+ select="//test-log[@status='unexpected' and @result='fail'
+ and @toolset = $required_toolset_names
+ and meta:is_test_log_a_test_case(.)
+ and meta:show_library( @library, $release )
+ and meta:show_toolset( @toolset, $release )
+ and not (meta:is_unusable($explicit_markup, @library,
+ @toolset )) ]"/>
+
+ <xsl:variable name="libraries" select="set:distinct( $failing_tests/@library )"/>
+
+ <xsl:template match="/">
+ <xsl:variable name="issues_list"
+ select="concat('issues', $release_postfix, '_.html')"/>
+
+ <!-- Issues page -->
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <title>Boost regression unresolved issues: <xsl:value-of select="$source"/></title>
+ </head>
+ <frameset cols="190px,*" frameborder="0" framespacing="0" border="0">
+ <frame name="tocframe" src="toc{$release_postfix}.html" scrolling="auto"/>
+ <frame name="docframe" src="{$issues_list}" scrolling="auto"/>
+ </frameset>
+ </html>
+
+ <!-- Issues list -->
+ <xsl:message>Writing document <xsl:value-of select="$issues_list"/></xsl:message>
+
+ <exsl:document href="{$issues_list}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ </head>
+ <body>
+
+ <h1 class="page-title">
+ <xsl:text>Unresolved Issues: </xsl:text>
+ <a class="hover-link" href="summary{$release_postfix}.html" target="_top"><xsl:value-of select="$source"/></a>
+ </h1>
+
+ <xsl:call-template name="insert_report_header">
+ <xsl:with-param name="run_date" select="$run_date"/>
+ <xsl:with-param name="warnings" select="$warnings"/>
+ <xsl:with-param name="purpose" select="'Provides a list of current unresolved test failures.'"/>
+ </xsl:call-template>
+
+ <!-- Emit the index -->
+ <h2>Libraries with unresolved failures</h2>
+ <div align="center">
+ <xsl:for-each select="$libraries">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="library" select="."/>
+ <a href="#{$library}">
+ <xsl:value-of select="$library"/>
+ </a>
+ <xsl:text> </xsl:text>
+ </xsl:for-each>
+ </div>
+
+ <xsl:for-each select="$libraries">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="library" select="."/>
+ <xsl:variable name="library_page" select="meta:encode_path( $library )" />
+ <xsl:variable name="library_tests" select="$failing_tests[@library = $library]"/>
+ <xsl:variable name="library_test_names" select="set:distinct( $library_tests/@test-name )"/>
+
+ <h2>
+ <a name="{$library}"/>
+ <a class="hover-link" href="{$library_page}{$release_postfix}.html" target="_top">
+ <xsl:value-of select="$library"/>
+ <xsl:text> (</xsl:text>
+ <xsl:value-of select="count($library_tests)"/>
+ <xsl:text> failure</xsl:text>
+ <xsl:if test="count($library_tests) &gt; 1">
+ <xsl:text>s</xsl:text>
+ </xsl:if>
+ <xsl:text>)</xsl:text>
+ </a>
+ </h2>
+
+ <table class="library-issues-table" summary="issues">
+ <thead>
+ <tr valign="middle">
+ <td class="head">test</td>
+ <td class="head">failures</td>
+ </tr>
+ </thead>
+ <tfoot>
+ <tr valign="middle">
+ <td class="head">test</td>
+ <td class="head">failures</td>
+ </tr>
+ </tfoot>
+
+ <tbody>
+ <xsl:for-each select="$library_test_names">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="test_name" select="."/>
+
+ <xsl:variable name="unexpected_toolsets" select="$library_tests[@test-name = $test_name]/@toolset"/>
+
+ <xsl:variable name="test_program" select="$library_tests[@test-name = $test_name]/@test-program"/>
+ <tr>
+ <td class="test-name">
+ <a href="http://svn.boost.org/svn/boost/{$source}/{$test_program}" class="test-link" target="_top">
+ <xsl:value-of select="$test_name"/>
+ </a>
+ </td>
+ <td class="failures-row">
+ <table summary="unexpected fail legend" class="issue-box">
+ <tr class="library-row-single">
+ <xsl:for-each select="$unexpected_toolsets">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="toolset" select="."/>
+ <xsl:variable name="test_logs"
+ select="$library_tests[@test-name = $test_name
+ and @toolset = $toolset]"/>
+ <xsl:for-each select="$test_logs">
+ <xsl:call-template name="print_failure_cell">
+ <xsl:with-param name="test_log" select="."/>
+ <xsl:with-param name="toolset" select="$toolset"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:for-each>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </tbody>
+
+ </table>
+ </xsl:for-each>
+ <xsl:copy-of select="document( 'html/issues_legend.html' )"/>
+ <xsl:copy-of select="document( 'html/make_tinyurl.html' )"/>
+ </body>
+ </html>
+ </exsl:document>
+
+ <xsl:message>Writing document issues-email.txt</xsl:message>
+ <exsl:document href="issues-email.txt" method="text" encoding="utf-8">
+ <xsl:text>Boost regression test failures
+------------------------------
+Report time: </xsl:text>
+
+ <xsl:value-of select="$run_date"/>
+
+ <xsl:text>
+
+This report lists all regression test failures on release platforms.
+
+Detailed report:
+ http://beta.boost.org/development/tests/</xsl:text>
+ <xsl:value-of select="$source"/>
+ <xsl:text>/developer/issues.html
+
+</xsl:text>
+ <xsl:value-of select="count($failing_tests)"/>
+ <xsl:text> failure</xsl:text>
+ <xsl:if test="count($failing_tests) &gt; 1">
+ <xsl:text>s</xsl:text>
+ </xsl:if>
+ <xsl:text> in </xsl:text>
+ <xsl:value-of select="count($libraries)"/>
+ <xsl:text> librar</xsl:text>
+ <xsl:choose>
+ <xsl:when test="count($libraries) &gt; 1">
+ <xsl:text>ies</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>y</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>:
+</xsl:text>
+ <xsl:for-each select="$libraries">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="library" select="."/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$library"/>
+ <xsl:text> (</xsl:text>
+ <xsl:value-of select="count($failing_tests[@library = $library])"/>
+ <xsl:text>)
+</xsl:text>
+ </xsl:for-each>
+
+ <xsl:for-each select="$libraries">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="library" select="."/>
+ <xsl:variable name="library_page" select="meta:encode_path( $library )" />
+ <xsl:variable name="library_tests" select="$failing_tests[@library = $library]"/>
+ <xsl:variable name="library_test_names" select="set:distinct( $library_tests/@test-name )"/>
+
+ <xsl:text>
+|</xsl:text>
+ <xsl:value-of select="$library"/>
+ <xsl:text>|
+</xsl:text>
+
+ <xsl:for-each select="$library_test_names">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="test_name" select="."/>
+
+ <xsl:variable name="unexpected_toolsets" select="$library_tests[@test-name = $test_name]/@toolset"/>
+
+ <xsl:variable name="test_program" select="$library_tests[@test-name = $test_name]/@test-program"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$test_name"/>
+ <xsl:text>:</xsl:text>
+ <xsl:for-each select="$unexpected_toolsets">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="."/>
+ </xsl:for-each>
+ <xsl:text>
+</xsl:text>
+ </xsl:for-each>
+ </xsl:for-each>
+ </exsl:document>
+ </xsl:template>
+
+ <xsl:template name="print_failure_cell">
+ <xsl:param name="test_log" select="."/>
+ <xsl:param name="toolset"/>
+
+ <xsl:variable name="test_run" select="$test_log/.."/>
+
+ <xsl:variable name="log_link">
+ <xsl:value-of select="meta:log_file_path($test_log, $test_run/@runner,
+ $release_postfix )"/>
+ </xsl:variable>
+ <xsl:variable name="class">
+ <xsl:choose>
+ <xsl:when test="$test_log/@is-new = 'yes'">
+ <xsl:text>library-fail-unexpected-new</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>library-fail-unexpected</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <td class="{$class}">
+ <span>
+ <a href="{$log_link}" class="log-link" target="_top">
+ <xsl:value-of select="$toolset"/>
+ </a>
+ </span>
+ </td>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/v2/links_page.xsl b/tools/regression/xsl_reports/xsl/v2/links_page.xsl
new file mode 100644
index 0000000000..1aacd6c7c8
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/links_page.xsl
@@ -0,0 +1,399 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2006.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:set="http://exslt.org/sets"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func exsl str set"
+ exclude-result-prefixes="meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="html"
+ doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
+ encoding="utf-8"
+ indent="yes"
+ />
+
+ <xsl:param name="source"/>
+ <xsl:param name="run_date"/>
+ <xsl:param name="comment_file"/>
+ <xsl:param name="explicit_markup_file"/>
+
+ <xsl:variable name="explicit_markup" select="document( $explicit_markup_file )"/>
+ <xsl:variable name="runner_id" select="test-run/@runner"/>
+ <xsl:variable name="revision" select="test-run/@revision"/>
+ <xsl:variable name="timestamp" select="test-run/@timestamp"/>
+
+ <!-- runs / toolsets -->
+ <xsl:variable name="run_toolsets" select="meta:test_structure( /, 'no' )"/>
+
+ <!-- libraries -->
+ <xsl:variable name="test_case_logs" select="//test-log[ meta:is_test_log_a_test_case(.) ]"/>
+ <xsl:variable name="libraries" select="set:distinct( $test_case_logs/@library )"/>
+
+ <xsl:variable name="unusables_f">
+ <xsl:for-each select="set:distinct( $run_toolsets//toolset/@name )">
+ <xsl:variable name="toolset" select="."/>
+ <xsl:for-each select="$libraries">
+ <xsl:variable name="library" select="."/>
+ <xsl:if test="meta:is_unusable_( $explicit_markup, $library, $toolset )">
+ <unusable library-name="{$library}" toolset-name="{$toolset}"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="unusables" select="exsl:node-set( $unusables_f )"/>
+
+
+ <xsl:key
+ name="library-name_toolset-name_key"
+ match="unusable"
+ use="concat( @library-name, '&gt;@&lt;', @toolset-name )"/>
+
+
+ <!--
+ Build a tree with the following structure:
+
+ lib -> test -> toolsets -> test-log
+ -->
+
+ <xsl:template match="/">
+ <xsl:variable name="test_logs_to_show" select="//test-log"/>
+ <xsl:variable name="libs_test_test_log_tree" select="meta:restructure_logs( $test_logs_to_show )"/>
+
+ <exsl:document href="debug.xml"
+ method="xml"
+ encoding="utf-8"
+ indent="yes">
+ <debug>
+ <xsl:copy-of select="$libs_test_test_log_tree"/>
+ </debug>
+ </exsl:document>
+
+ <xsl:for-each select="$libs_test_test_log_tree//toolset">
+ <xsl:variable name="toolset" select="."/>
+ <xsl:variable name="library_name" select="$toolset/../../@name"/>
+ <xsl:variable name="test_name" select="$toolset/../@name"/>
+ <xsl:variable name="toolset_name" select="$toolset/@name"/>
+ <xsl:message>Processing test "<xsl:value-of select="$runner_id"/>/<xsl:value-of select="$library_name"/>/<xsl:value-of select="$test_name"/>/<xsl:value-of select="$toolset_name"/>"</xsl:message>
+
+ <xsl:if test="count( $toolset/* ) &gt; 1">
+ <xsl:message> Processing variants</xsl:message>
+
+ <xsl:variable name="variants_file_path" select="meta:output_file_path( concat( $runner_id, '-', $library_name, '-', $toolset_name, '-', $test_name, '-variants' ) )"/>
+
+ <xsl:call-template name="write_variants_file">
+ <xsl:with-param name="path" select="$variants_file_path"/>
+ <xsl:with-param name="test_logs" select="$toolset/*"/>
+ <xsl:with-param name="runner_id" select="$runner_id"/>
+ <xsl:with-param name="revision" select="$revision"/>
+ <xsl:with-param name="timestamp" select="$timestamp"/>
+ </xsl:call-template>
+
+ <xsl:for-each select="str:tokenize( string( ' |_release' ), '|')">
+ <xsl:variable name="release_postfix" select="translate(.,' ','')"/>
+ <xsl:for-each select="str:tokenize( string( 'developer|user' ), '|')">
+ <xsl:variable name="directory" select="."/>
+ <xsl:variable name="variants__file_path" select="concat( $directory, '/', meta:encode_path( concat( $runner_id, '-', $library_name, '-', $toolset_name, '-', $test_name, '-variants_', $release_postfix ) ), '.html' )"/>
+
+ <xsl:call-template name="write_variants_reference_file">
+ <xsl:with-param name="path" select="$variants__file_path"/>
+ <xsl:with-param name="variants_file_path" select="concat( '../', $variants_file_path )"/>
+ <xsl:with-param name="release_postfix" select="$release_postfix"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:if>
+
+ <xsl:for-each select="./test-log">
+ <xsl:message> Processing test-log</xsl:message>
+ <xsl:variable name="test_log" select="."/>
+
+ <xsl:if test="meta:show_output( $explicit_markup, $test_log )">
+ <xsl:variable name="log_file_path" select="meta:log_file_path( ., $runner_id )"/>
+
+ <xsl:call-template name="write_test_result_file">
+ <xsl:with-param name="path" select="$log_file_path"/>
+ <xsl:with-param name="test_log" select="$test_log"/>
+ <xsl:with-param name="runner_id" select="$runner_id"/>
+ <xsl:with-param name="revision" select="$revision"/>
+ <xsl:with-param name="timestamp" select="$timestamp"/>
+ </xsl:call-template>
+
+ <xsl:for-each select="str:tokenize( string( ' |_release' ), '|')">
+ <xsl:variable name="release_postfix" select="translate(.,' ','')"/>
+ <xsl:for-each select="str:tokenize( string( 'developer|user' ), '|')">
+ <xsl:variable name="directory" select="."/>
+
+ <xsl:variable name="reference_file_path" select="concat( $directory, '/', meta:log_file_path( $test_log, $runner_id, $release_postfix ) )"/>
+ <xsl:call-template name="write_test_results_reference_file">
+ <xsl:with-param name="path" select="$reference_file_path"/>
+ <xsl:with-param name="log_file_path" select="$log_file_path"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:if>
+
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:template>
+
+ <func:function name="meta:restructure_logs">
+ <xsl:param name="test_logs"/>
+ <xsl:variable name="libs" select="set:distinct( $test_logs/@library )"/>
+ <xsl:variable name="fragment">
+ <runner runner_id="{$test_logs[1]/../@runner}" revision="{$test_logs[1]/../@revision}" timestamp="{$test_logs[1]/../@timestamp}">
+ <xsl:for-each select="$libs">
+ <xsl:variable name="library_name" select="."/>
+ <xsl:variable name="library_test_logs" select="$test_logs[@library=$library_name]"/>
+ <library name="{$library_name}">
+ <xsl:variable name="tests" select="set:distinct( $library_test_logs/@test-name )"/>
+ <xsl:for-each select="$tests">
+ <xsl:variable name="test_name" select="."/>
+ <xsl:variable name="test_test_logs" select="$library_test_logs[@test-name=$test_name]"/>
+ <test name="{$test_name}" >
+ <xsl:variable name="toolsets" select="set:distinct( $test_test_logs/@toolset )"/>
+ <xsl:for-each select="$toolsets">
+ <xsl:variable name="toolset" select="."/>
+ <xsl:variable name="toolset_test_logs" select="$test_test_logs[@toolset=$toolset]"/>
+ <toolset name="{$toolset}">
+ <xsl:copy-of select="$toolset_test_logs"/>
+ </toolset>
+ </xsl:for-each>
+ </test>
+ </xsl:for-each>
+ </library>
+ </xsl:for-each>
+ </runner>
+ </xsl:variable>
+ <func:result select="exsl:node-set( $fragment )"/>
+ </func:function>
+
+ <xsl:template name="write_variants_reference_file">
+ <xsl:param name="path"/>
+ <xsl:param name="variants_file_path"/>
+ <xsl:param name="release_postfix"/>
+
+ <xsl:message> Writing variants reference file <xsl:value-of select="$path"/></xsl:message>
+ <exsl:document href="{$path}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <!-- <title>Boost regression: <xsl:value-of select="$library_name"/>/<xsl:value-of select="$source"/></title>-->
+ </head>
+ <frameset cols="190px,*" frameborder="0" framespacing="0" border="0">
+ <frame name="tocframe" src="toc{$release_postfix}.html" scrolling="auto"/>
+ <frame name="docframe" src="{$variants_file_path}" scrolling="auto"/>
+ </frameset>
+ </html>
+ </exsl:document>
+
+ </xsl:template>
+
+ <func:function name="meta:output_page_header">
+ <xsl:param name="test_log"/>
+ <xsl:param name="runner_id"/>
+ <xsl:choose>
+ <xsl:when test="$test_log/@test-name != ''">
+ <func:result select="concat( $runner_id, ' - ', $test_log/@library, ' - ', $test_log/@test-name, ' / ', $test_log/@toolset )"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <func:result select="$test_log/@target-dir"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </func:function>
+
+
+ <xsl:template name="write_variants_file">
+ <xsl:param name="path"/>
+ <xsl:param name="test_logs"/>
+ <xsl:param name="runner_id"/>
+ <xsl:param name="revision"/>
+ <xsl:param name="timestamp"/>
+ <xsl:message> Writing variants file <xsl:value-of select="$path"/></xsl:message>
+ <exsl:document href="{$path}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <xsl:variable name="component" select="meta:output_page_header( $test_logs[1], $runner_id )"/>
+ <xsl:variable name="age" select="meta:timestamp_difference( $timestamp, $run_date )"/>
+
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <title>Test output: <xsl:value-of select="$component"/></title>
+ </head>
+
+ <body>
+ <div class="log-test-header">
+ <div class="log-test-title">
+ Test output: <xsl:value-of select="$component"/>
+ </div>
+ <div><span class="timestamp-{$age}">
+ Rev <xsl:value-of select="$revision"/> /
+ <xsl:value-of select="meta:format_timestamp( $timestamp )"/>
+ </span></div>
+ </div>
+
+ <div>
+ <b>Report Time: </b> <xsl:value-of select="meta:format_timestamp( $run_date )"/>
+ </div>
+
+ <p>Output by test variants:</p>
+ <table>
+ <xsl:for-each select="$test_logs">
+ <tr>
+ <td>
+ <xsl:choose>
+ <xsl:when test="meta:log_file_path(.,$runner_id) != ''">
+ <a href="../{meta:log_file_path(.,$runner_id)}">
+ <xsl:value-of select="@target-directory"/>
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@target-directory"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </body>
+ </html>
+ </exsl:document>
+ </xsl:template>
+
+ <xsl:template name="write_test_result_file">
+ <xsl:param name="path"/>
+ <xsl:param name="test_log"/>
+ <xsl:param name="runner_id"/>
+ <xsl:param name="revision"/>
+ <xsl:param name="timestamp"/>
+ <xsl:message> Writing log file document <xsl:value-of select="$path"/></xsl:message>
+
+ <exsl:document href="{$path}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <xsl:variable name="component" select="meta:output_page_header( $test_log, $runner_id )"/>
+ <xsl:variable name="age" select="meta:timestamp_difference( $timestamp, $run_date )"/>
+
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <title>Test output: <xsl:value-of select="$component"/></title>
+ </head>
+
+ <body>
+ <div class="log-test-header">
+ <div class="log-test-title">
+ Test output: <xsl:value-of select="$component"/>
+ </div>
+ <div><span class="timestamp-{$age}">
+ Rev <xsl:value-of select="$revision"/> /
+ <xsl:value-of select="meta:format_timestamp( $timestamp )"/>
+ </span></div>
+ </div>
+
+ <div>
+ <b>Report Time: </b> <xsl:value-of select="meta:format_timestamp( $run_date )"/>
+ </div>
+
+ <xsl:if test="notes/note">
+ <p>
+ <div class="notes-title">Notes</div>
+ <xsl:call-template name="show_notes">
+ <xsl:with-param name="notes" select="notes/note"/>
+ <xsl:with-param name="explicit_markup" select="$explicit_markup"/>
+ </xsl:call-template>
+ </p>
+ </xsl:if>
+
+ <xsl:if test="compile">
+ <p>
+ <div class="log-compiler-output-title">Compile [<xsl:value-of select="compile/@timestamp"/>]: <span class="output-{compile/@result}"><xsl:value-of select="compile/@result"/></span></div>
+ <pre><xsl:copy-of select="compile/node()"/></pre>
+ </p>
+ </xsl:if>
+
+ <xsl:if test="link">
+ <p>
+ <div class="log-linker-output-title">Link [<xsl:value-of select="link/@timestamp"/>]: <span class="output-{link/@result}"><xsl:value-of select="link/@result"/></span></div>
+ <pre><xsl:copy-of select="link/node()"/></pre>
+ </p>
+ </xsl:if>
+
+ <xsl:if test="lib">
+ <p>
+ <div class="log-linker-output-title">Lib [<xsl:value-of select="lib/@timestamp"/>]: <span class="output-{lib/@result}"><xsl:value-of select="lib/@result"/></span></div>
+ <p>
+ See <a href="{meta:encode_path( concat( $runner_id, '-', lib/node() ) ) }.html">
+ <xsl:copy-of select="lib/node()"/>
+ </a>
+ </p>
+ </p>
+ </xsl:if>
+
+ <xsl:if test="run">
+ <p>
+ <div class="log-run-output-title">Run [<xsl:value-of select="run/@timestamp"/>]: <span class="output-{run/@result}"><xsl:value-of select="run/@result"/></span></div>
+ <pre>
+ <xsl:copy-of select="run/node()"/>
+ </pre>
+ </p>
+ </xsl:if>
+
+ <xsl:copy-of select="document( 'html/make_tinyurl.html' )"/>
+ </body>
+
+ </html>
+ </exsl:document>
+ </xsl:template>
+
+
+ <xsl:template name="write_test_results_reference_file">
+ <xsl:param name="path"/>
+ <xsl:param name="log_file_path"/>
+ <xsl:message> Writing log frame document <xsl:value-of select="$path"/></xsl:message>
+ <exsl:document href="{$path}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ </head>
+ <frameset cols="190px,*" frameborder="0" framespacing="0" border="0">
+ <frame name="tocframe" src="../toc.html" scrolling="auto"/>
+ <frame name="docframe" src="../../{$log_file_path}" scrolling="auto"/>
+ </frameset>
+ </html>
+ </exsl:document>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/v2/produce_expected_results.xsl b/tools/regression/xsl_reports/xsl/v2/produce_expected_results.xsl
new file mode 100644
index 0000000000..8574c59361
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/produce_expected_results.xsl
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2005.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:meta="http://www.meta-comm.com"
+ exclude-result-prefixes="meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="xml" encoding="utf-8"/>
+
+ <xsl:template match="/">
+ <root>
+ <expected-failures>
+ <xsl:apply-templates select="*//test-log"/>
+ </expected-failures>
+ </root>
+ </xsl:template>
+
+ <xsl:template match="test-log">
+ <xsl:if test="meta:is_test_log_a_test_case(.)">
+ <test-result library="{@library}" test-name="{@test-name}" toolset="{@toolset}" result="{@result}" />
+ </xsl:if>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/v2/result_page.xsl b/tools/regression/xsl_reports/xsl/v2/result_page.xsl
new file mode 100644
index 0000000000..7528430f97
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/result_page.xsl
@@ -0,0 +1,691 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2007.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:set="http://exslt.org/sets"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func exsl"
+ exclude-result-prefixes="exsl set meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="html"
+ doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
+ encoding="utf-8"
+ indent="yes"
+ />
+
+ <xsl:param name="links_file"/>
+ <xsl:param name="mode"/>
+ <xsl:param name="source"/>
+ <xsl:param name="run_date"/>
+ <xsl:param name="warnings"/>
+ <xsl:param name="comment_file"/>
+ <xsl:param name="expected_results_file"/>
+ <xsl:param name="explicit_markup_file"/>
+ <xsl:param name="release"/>
+
+ <!-- the author-specified expected test results -->
+ <xsl:variable name="explicit_markup" select="document( $explicit_markup_file )"/>
+ <xsl:variable name="expected_results" select="document( $expected_results_file )" />
+
+ <!-- necessary indexes -->
+ <xsl:key
+ name="test_name_key"
+ match="test-log"
+ use="concat( @library, '&gt;@&lt;', @test-name )"/>
+ <xsl:key name="toolset_key" match="test-log" use="@toolset"/>
+
+ <!-- runs / toolsets -->
+ <xsl:variable name="run_toolsets" select="meta:test_structure( /, $release )"/>
+
+ <!-- libraries -->
+
+ <xsl:variable name="test_case_logs" select="//test-log[ meta:is_test_log_a_test_case(.) ]"/>
+ <xsl:variable name="libraries" select="set:distinct( $test_case_logs/@library )"/>
+ <xsl:variable name="unusables_f">
+ <unusables>
+ <xsl:for-each select="set:distinct( $run_toolsets//toolset/@name )">
+ <xsl:variable name="toolset" select="."/>
+ <xsl:for-each select="$libraries">
+ <xsl:variable name="library" select="."/>
+ <xsl:if test="meta:is_unusable_( $explicit_markup, $library, $toolset )">
+ <unusable library-name="{$library}" toolset-name="{$toolset}"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ </unusables>
+ </xsl:variable>
+
+ <xsl:variable name="unusables" select="exsl:node-set( $unusables_f )"/>
+
+
+ <xsl:key
+ name="library-name_toolset-name_key"
+ match="unusables/unusable"
+ use="concat( @library-name, '&gt;@&lt;', @toolset-name )"/>
+
+ <!-- modes -->
+
+ <xsl:variable name="alternate_mode">
+ <xsl:choose>
+ <xsl:when test="$mode='user'">developer</xsl:when>
+ <xsl:otherwise>user</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="release_postfix">
+ <xsl:if test="$release='yes'">_release</xsl:if>
+ </xsl:variable>
+
+
+
+ <xsl:template name="test_type_col">
+ <td class="test-type">
+ <a href="http://www.boost.org/status/compiler_status.html#Understanding" class="legend-link" target="_top">
+ <xsl:variable name="test_type" select="./@test-type"/>
+ <xsl:choose>
+ <xsl:when test="$test_type='run_pyd'"> <xsl:text>r</xsl:text> </xsl:when>
+ <xsl:when test="$test_type='run_mpi'"> <xsl:text>r</xsl:text> </xsl:when>
+ <xsl:when test="$test_type='run'"> <xsl:text>r</xsl:text> </xsl:when>
+ <xsl:when test="$test_type='run_fail'"> <xsl:text>rf</xsl:text> </xsl:when>
+ <xsl:when test="$test_type='compile'"> <xsl:text>c</xsl:text> </xsl:when>
+ <xsl:when test="$test_type='compile_fail'"> <xsl:text>cf</xsl:text> </xsl:when>
+ <xsl:when test="$test_type='link'"> <xsl:text>l</xsl:text> </xsl:when>
+ <xsl:when test="$test_type='link_fail'"> <xsl:text>lf</xsl:text> </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">Incorrect test type "<xsl:value-of select="$test_type"/>"</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </a>
+ </td>
+ </xsl:template>
+
+
+ <xsl:template match="/">
+
+ <xsl:message><xsl:value-of select="count($unusables)"/><xsl:copy-of select="$unusables"/></xsl:message>
+
+ <exsl:document href="debug.xml"
+ method="xml"
+ encoding="utf-8"
+ indent="yes">
+
+ <debug>
+ <runs>
+ <xsl:for-each select="$run_toolsets">
+ <xsl:copy-of select="."/>
+ </xsl:for-each>
+ </runs>
+ <xsl:copy-of select="$unusables_f"/>
+ <xsl:copy-of select="$unusables"/>
+ </debug>
+
+ </exsl:document>
+ <xsl:message>Wrote debug</xsl:message>
+ <xsl:variable name="index_path" select="concat( 'index', $release_postfix, '_.html' )"/>
+
+ <!-- Index page -->
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <title>Boost regression: <xsl:value-of select="$source"/></title>
+ </head>
+ <frameset cols="190px,*" frameborder="0" framespacing="0" border="0">
+ <frame name="tocframe" src="toc{$release_postfix}.html" scrolling="auto"/>
+ <frame name="docframe" src="{$index_path}" scrolling="auto"/>
+ </frameset>
+
+ <!-- Index content -->
+ <xsl:message>Writing document <xsl:value-of select="$index_path"/></xsl:message>
+
+ <exsl:document href="{$index_path}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ </head>
+ <body>
+
+ <img border="0" src="http://www.boost.org/boost.png" width="277" height="86" align="right" alt="Boost logo"></img>
+
+ <h1 class="page-title">
+ <xsl:value-of select="$mode"/>
+ <xsl:text> report: </xsl:text>
+ <a class="hover-link" href="summary.html" target="_top"><xsl:value-of select="$source"/></a>
+ </h1>
+
+ <xsl:variable name="purpose">
+ <xsl:choose>
+ <xsl:when test="$mode='user'">
+ The purpose of this report is to help a user to find out whether a particular library
+ works on the particular compiler(s). For SVN "health report", see
+ <a href="../{$alternate_mode}/index.html" target="_top">developer summary</a>.
+ </xsl:when>
+ <xsl:when test="$mode='developer'">
+ Provides Boost developers with visual indication of the SVN "health". For user-level
+ report, see <a href="../{$alternate_mode}/index.html" target="_top">user summary</a>.
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:call-template name="insert_report_header">
+ <xsl:with-param name="run_date" select="$run_date"/>
+ <xsl:with-param name="warnings" select="$warnings"/>
+ <xsl:with-param name="purpose" select="$purpose"/>
+ </xsl:call-template>
+
+ <div class="comment">
+ <xsl:if test="$comment_file != ''">
+ <xsl:copy-of select="document( $comment_file )"/>
+ </xsl:if>
+ </div>
+
+ </body>
+ </html>
+ </exsl:document>
+
+
+ <xsl:variable name="multiple.libraries" select="count( $libraries ) > 1"/>
+
+ <!-- TOC -->
+ <xsl:if test="$multiple.libraries">
+
+ <xsl:variable name="toc_path" select="concat( 'toc', $release_postfix, '.html' )"/>
+ <xsl:message>Writing document <xsl:value-of select="$toc_path"/></xsl:message>
+
+ <exsl:document href="{$toc_path}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ </head>
+ <body class="{$mode}-toc">
+ <div class="toc-header-entry">
+ <a href="index{$release_postfix}.html" class="toc-entry" target="_top">Report info</a>
+ </div>
+ <div class="toc-header-entry">
+ <a href="summary{$release_postfix}.html" class="toc-entry" target="_top">Summary</a>
+ </div>
+
+ <xsl:if test="$mode='developer'">
+ <div class="toc-header-entry">
+ <a href="issues.html" class="toc-entry" target="_top">Unresolved issues</a>
+ </div>
+ </xsl:if>
+
+ <div class="toc-header-entry">
+ <xsl:call-template name="insert_view_link">
+ <xsl:with-param name="page" select="'index'"/>
+ <xsl:with-param name="class" select="'toc-entry'"/>
+ <xsl:with-param name="release" select="$release"/>
+ </xsl:call-template>
+ </div>
+
+ <hr/>
+
+ <xsl:for-each select="$libraries">
+ <xsl:sort select="." order="ascending" />
+ <xsl:variable name="library_page" select="meta:encode_path(.)" />
+ <div class="toc-entry">
+ <a href="{$library_page}{$release_postfix}.html" class="toc-entry" target="_top">
+ <xsl:value-of select="."/>
+ </a>
+ </div>
+ </xsl:for-each>
+ </body>
+ </html>
+
+ </exsl:document>
+ </xsl:if>
+
+ <!-- Libraries -->
+ <xsl:for-each select="$libraries[ meta:show_library( ., $release )]">
+ <xsl:sort select="." order="ascending" />
+ <xsl:variable name="library" select="." />
+
+ <xsl:variable name="library_results" select="concat( meta:encode_path( $library ), $release_postfix, '_.html' )"/>
+ <xsl:variable name="library_page" select="concat( meta:encode_path( $library ), $release_postfix, '.html' )"/>
+
+ <!-- Library page -->
+ <xsl:message>Writing document <xsl:value-of select="$library_page"/></xsl:message>
+
+ <exsl:document href="{$library_page}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <title>Boost regression: <xsl:value-of select="$library"/>/<xsl:value-of select="$source"/></title>
+ </head>
+ <frameset cols="190px,*" frameborder="0" framespacing="0" border="0">
+ <frame name="tocframe" src="toc{$release_postfix}.html" scrolling="auto"/>
+ <frame name="docframe" src="{$library_results}" scrolling="auto"/>
+ </frameset>
+ </html>
+ </exsl:document>
+
+ <!-- Library results frame -->
+ <xsl:message>Writing document <xsl:value-of select="$library_results"/></xsl:message>
+
+ <exsl:document href="{$library_results}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ </head>
+
+ <body>
+
+ <xsl:call-template name="insert_page_links">
+ <xsl:with-param name="page" select="meta:encode_path( $library )"/>
+ <xsl:with-param name="release" select="$release"/>
+ <xsl:with-param name="mode" select="$alternate_mode"/>
+ </xsl:call-template>
+
+ <h1 class="page-title">
+ <a class="hover-link" name="{$library}" href="http://www.boost.org/libs/{$library}" target="_top">
+ <xsl:value-of select="$library" />
+ </a>
+ <xsl:text>/</xsl:text>
+ <a class="hover-link" href="summary.html" target="_top"><xsl:value-of select="$source"/></a>
+ </h1>
+
+ <xsl:call-template name="insert_report_header">
+ <xsl:with-param name="run_date" select="$run_date"/>
+ <xsl:with-param name="warnings" select="$warnings"/>
+ </xsl:call-template>
+
+ <!-- library marks = library-unusable markup for toolsets in the report -->
+ <xsl:variable name="library_marks" select="$explicit_markup//library[ @name = $library ]/mark-unusable/toolset[ meta:re_match( @name, $run_toolsets//toolset/@name ) ]/.."/>
+
+ <table border="0" cellspacing="0" cellpadding="0" class="library-table" width="1%" summary="Library results">
+
+ <thead>
+ <xsl:call-template name="insert_runners_rows">
+ <xsl:with-param name="mode" select="'details'"/>
+ <xsl:with-param name="top_or_bottom" select="'top'"/>
+ <xsl:with-param name="run_toolsets" select="$run_toolsets"/>
+ <xsl:with-param name="run_date" select="$run_date"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="insert_toolsets_row">
+ <xsl:with-param name="mode" select="'details'"/>
+ <xsl:with-param name="library_marks" select="$library_marks"/>
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="run_date" select="$run_date"/>
+ </xsl:call-template>
+ </thead>
+ <tfoot>
+ <xsl:call-template name="insert_toolsets_row">
+ <xsl:with-param name="mode" select="'details'"/>
+ <xsl:with-param name="library_marks" select="$library_marks"/>
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="run_date" select="$run_date"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="insert_runners_rows">
+ <xsl:with-param name="mode" select="'details'"/>
+ <xsl:with-param name="top_or_bottom" select="'bottom'"/>
+ <xsl:with-param name="run_toolsets" select="$run_toolsets"/>
+ <xsl:with-param name="run_date" select="$run_date"/>
+ </xsl:call-template>
+ </tfoot>
+
+ <tbody>
+ <xsl:variable name="lib_tests" select="$test_case_logs[@library = $library]" />
+ <xsl:variable name="lib_unique_tests_list"
+ select="$lib_tests[ generate-id(.) = generate-id( key('test_name_key', concat( @library, '&gt;@&lt;', @test-name ) ) ) ]" />
+
+ <xsl:variable name="lib_tests_by_category"
+ select="meta:order_tests_by_category( $lib_unique_tests_list )"/>
+
+ <xsl:call-template name="insert_test_section">
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="section_test_names" select="$lib_tests_by_category"/>
+ <xsl:with-param name="lib_tests" select="$lib_tests"/>
+ <xsl:with-param name="toolsets" select="$run_toolsets"/>
+ </xsl:call-template>
+
+ </tbody>
+ </table>
+ <xsl:if test="count( $library_marks/note ) > 0 ">
+ <table border="0" cellpadding="0" cellspacing="0" class="library-library-notes" summary="library notes">
+ <xsl:for-each select="$library_marks/note">
+ <tr class="library-library-note">
+ <td valign="top" width="3em">
+ <a name="{$library}-note-{position()}">
+ <span class="super"><xsl:value-of select="position()"/></span>
+ </a>
+ </td>
+ <td>
+ <xsl:variable name="refid" select="@refid"/>
+ <xsl:call-template name="show_note">
+ <xsl:with-param name="note" select="." />
+ <xsl:with-param name="references" select="$refid"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
+
+ <div id="legend">
+ <xsl:copy-of select="document( concat( 'html/library_', $mode, '_legend.html' ) )"/>
+ </div>
+
+ <xsl:call-template name="insert_page_links">
+ <xsl:with-param name="page" select="meta:encode_path( $library )"/>
+ <xsl:with-param name="release" select="$release"/>
+ <xsl:with-param name="mode" select="$alternate_mode"/>
+ </xsl:call-template>
+
+ </body>
+ </html>
+
+ </exsl:document>
+
+ </xsl:for-each>
+
+ </xsl:template>
+
+
+ <!-- insert test result with log file link -->
+
+ <xsl:template name="insert_test_result">
+ <xsl:param name="result"/>
+ <xsl:param name="log_link"/>
+
+ <xsl:choose>
+ <xsl:when test="$log_link != ''">
+ <xsl:text>&#160;&#160;</xsl:text>
+ <a href="{$log_link}" class="log-link" target="_top">
+ <xsl:copy-of select="$result"/>
+ </a>
+ <xsl:text>&#160;&#160;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&#160;&#160;</xsl:text>
+ <xsl:copy-of select="$result"/>
+ <xsl:text>&#160;&#160;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- report developer status -->
+ <xsl:template name="insert_cell_developer">
+ <xsl:param name="library"/>
+ <xsl:param name="toolset"/>
+ <xsl:param name="test_log"/>
+
+ <xsl:variable name="class" select="concat( 'library-', meta:result_cell_class( $library, $toolset, $test_log ) )"/>
+
+ <xsl:variable name="cell_link">
+ <xsl:choose>
+ <xsl:when test="count( $test_log ) &gt; 1">
+ <xsl:variable name="variants__file_path" select="concat( meta:encode_path( concat( $test_log/../@runner, '-', $test_log/@library, '-', $test_log/@toolset, '-', $test_log/@test-name, '-variants_', $release_postfix ) ), '.html' )"/>
+ <xsl:value-of select="$variants__file_path"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="meta:log_file_path( $test_log, $test_log/../@runner, $release_postfix )"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <td class="{$class}" title="{$test_log/@test-name}/{$toolset}">
+ <xsl:choose>
+ <xsl:when test="meta:is_unusable( $explicit_markup, $library, $toolset )">
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'n/a'"/>
+ <xsl:with-param name="log_link" select="$cell_link"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="count( $test_log ) &lt; 1">
+ <xsl:text>&#160;&#160;&#160;&#160;</xsl:text>
+ </xsl:when>
+
+ <xsl:when test="count( $test_log[ @result != 'success' and @status = 'expected' ] ) &gt; 0">
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result">
+ <xsl:choose>
+ <xsl:when test="$test_log/@expected-reason != ''">
+ <xsl:text>fail?</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>fail*</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="log_link" select="$cell_link"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="$test_log/@result != 'success' and $test_log/@status = 'unexpected'">
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'fail'"/>
+ <xsl:with-param name="log_link" select="$cell_link"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="$test_log/@result = 'success' and $test_log/@status = 'unexpected'">
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'pass'"/>
+ <xsl:with-param name="log_link" select="$cell_link"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'pass'"/>
+ <xsl:with-param name="log_link" select="$cell_link"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ </xsl:template>
+
+ <!-- report user status -->
+ <xsl:template name="insert_cell_user">
+ <xsl:param name="library"/>
+ <xsl:param name="toolset"/>
+ <xsl:param name="test_log"/>
+
+ <xsl:variable name="class" select="concat( 'library-', meta:result_cell_class( $library, $toolset, $test_log ) )"/>
+
+ <xsl:variable name="cell_link">
+ <xsl:choose>
+ <xsl:when test="count( $test_log ) &gt; 1">
+ <xsl:variable name="variants__file_path" select="concat( meta:encode_path( concat( $test_log/../@runner, '-', $test_log/@library, '-', $test_log/@toolset, '-', $test_log/@test-name, '-variants_', $release_postfix ) ), '.html' )"/>
+ <xsl:value-of select="$variants__file_path"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="meta:log_file_path( $test_log, $test_log/../@runner, $release_postfix )"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <td class="{$class} user-{$class}" title="{$test_log/@test-name}/{$toolset}">
+ <xsl:choose>
+ <xsl:when test="meta:is_unusable( $explicit_markup, $library, $toolset )">
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'unusable'"/>
+ <xsl:with-param name="log_link" select="$cell_link"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="count( $test_log ) &lt; 1">
+ <xsl:text>&#160;&#160;&#160;&#160;</xsl:text>
+ </xsl:when>
+
+ <xsl:when test="$test_log/@result != 'success' and $test_log/@status = 'expected'">
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result">
+ <xsl:choose>
+ <xsl:when test="$test_log/@expected-reason != ''">
+ <xsl:text>fail?</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>fail*</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="log_link" select="$cell_link"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="$test_log/@result != 'success' and $test_log/@status = 'unexpected'">
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'fail'"/>
+ <xsl:with-param name="log_link" select="$cell_link"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:when test="$test_log/@result = 'success' and $test_log/@status = 'unexpected'">
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'pass'"/>
+ <xsl:with-param name="log_link" select="$cell_link"/>
+ </xsl:call-template>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:call-template name="insert_test_result">
+ <xsl:with-param name="result" select="'pass'"/>
+ <xsl:with-param name="log_link" select="$cell_link"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ </xsl:template>
+
+ <xsl:template name="insert_test_line">
+ <xsl:param name="library"/>
+ <xsl:param name="test_name"/>
+ <xsl:param name="test_results"/>
+ <xsl:param name="line_mod"/>
+
+ <xsl:variable name="test_program">
+ <xsl:value-of select="$test_results[1]/@test-program"/>
+ </xsl:variable>
+
+ <xsl:variable name="test_header">
+ <td class="test-name">
+ <a href="http://svn.boost.org/svn/boost/{$source}/{$test_program}" class="test-link" target="_top">
+ <xsl:value-of select="$test_name"/>
+ </a>
+ </td>
+ </xsl:variable>
+
+ <tr class="library-row{$line_mod}">
+ <xsl:copy-of select="$test_header"/>
+ <xsl:call-template name="test_type_col"/>
+
+ <xsl:for-each select="$run_toolsets/platforms/platform/runs/run/toolset">
+ <xsl:variable name="toolset" select="@name" />
+ <xsl:variable name="runner" select="../@runner" />
+
+ <xsl:variable name="test_result_for_toolset" select="$test_results[ @toolset = $toolset and ../@runner=$runner ]"/>
+
+ <!-- Insert cell -->
+ <xsl:choose>
+ <xsl:when test="$mode='user'">
+ <xsl:call-template name="insert_cell_user">
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="toolset" select="$toolset"/>
+ <xsl:with-param name="test_log" select="$test_result_for_toolset"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$mode='developer'">
+ <xsl:call-template name="insert_cell_developer">
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="toolset" select="$toolset"/>
+ <xsl:with-param name="test_log" select="$test_result_for_toolset"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+
+ </xsl:for-each>
+ <xsl:copy-of select="$test_header"/>
+ </tr>
+ </xsl:template>
+
+ <xsl:template name="insert_test_section">
+ <xsl:param name="library"/>
+ <xsl:param name="section_test_names"/>
+ <xsl:param name="lib_tests"/>
+ <xsl:param name="toolsets"/>
+
+ <xsl:variable name="category_span" select="count($toolsets/platforms/platform/runs/run/toolset) + 3"/>
+
+ <xsl:for-each select="$section_test_names">
+
+ <xsl:variable name="test_name" select="@test-name"/>
+ <xsl:variable name="category_start" select="position() = 1 or @category != preceding-sibling::*[1]/@category"/>
+ <xsl:variable name="category_end" select="position() = last() or @category != following-sibling::*[1]/@category"/>
+
+ <xsl:variable name="line_mod">
+ <xsl:choose>
+ <xsl:when test="$category_start and $category_end"><xsl:text>-single</xsl:text></xsl:when>
+ <xsl:when test="$category_start"><xsl:text>-first</xsl:text></xsl:when>
+ <xsl:when test="$category_end"><xsl:text>-last</xsl:text></xsl:when>
+ <xsl:otherwise><xsl:text></xsl:text></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:if test="$category_start and @category != '0'">
+ <tr>
+ <td class="library-test-category-header" colspan="{$category_span}" align="center">
+ <xsl:value-of select="@category"/>
+ </td>
+ </tr>
+ </xsl:if>
+
+ <xsl:call-template name="insert_test_line">
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="test_results" select="$lib_tests[ @test-name = $test_name ]"/>
+ <xsl:with-param name="test_name" select="$test_name"/>
+ <xsl:with-param name="line_mod" select="$line_mod"/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ </xsl:template>
+
+ <func:function name="meta:order_tests_by_category">
+ <xsl:param name="tests"/>
+
+ <xsl:variable name="a">
+ <xsl:for-each select="$tests">
+ <xsl:sort select="concat( @category, '|', @test-name )" order="ascending"/>
+ <xsl:copy-of select="."/>
+ </xsl:for-each>
+ </xsl:variable>
+ <func:result select="exsl:node-set( $a )/*"/>
+ </func:function>
+
+</xsl:stylesheet>
diff --git a/tools/regression/xsl_reports/xsl/v2/runners.xsl b/tools/regression/xsl_reports/xsl/v2/runners.xsl
new file mode 100644
index 0000000000..9bda7db8d3
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/runners.xsl
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl"
+ version="1.0">
+
+ <xsl:output method="html"/>
+
+ <xsl:template match="/">
+ <html>
+ <body bgcolor="#FFFFFF">
+ <xsl:apply-templates/>
+ </body>
+ </html>
+ </xsl:template>
+
+ <xsl:template match="test-run">
+ <table>
+ <tr>
+ <td>
+ <xsl:message>Writing runner document <xsl:value-of select="@runner"/></xsl:message>
+ <a href="{@runner}.html"><xsl:value-of select="@runner"/></a>
+ <exsl:document href="{@runner}.html"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+ <html>
+ <head>
+ <title><xsl:value-of select="@runner"/></title>
+ </head>
+ <body>
+ <h1><xsl:value-of select="@runner"/></h1>
+ <hr></hr>
+ <xsl:value-of select="comment/text()" disable-output-escaping="yes"/>
+ </body>
+ </html>
+ </exsl:document>
+ </td>
+ </tr>
+ </table>
+ </xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/tools/regression/xsl_reports/xsl/v2/summary_page.xsl b/tools/regression/xsl_reports/xsl/v2/summary_page.xsl
new file mode 100644
index 0000000000..b0e1deb477
--- /dev/null
+++ b/tools/regression/xsl_reports/xsl/v2/summary_page.xsl
@@ -0,0 +1,367 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright MetaCommunications, Inc. 2003-2004.
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:set="http://exslt.org/sets"
+ xmlns:meta="http://www.meta-comm.com"
+ extension-element-prefixes="func exsl"
+ exclude-result-prefixes="exsl func set meta"
+ version="1.0">
+
+ <xsl:import href="common.xsl"/>
+
+ <xsl:output method="html"
+ doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
+ encoding="utf-8"
+ indent="yes"
+ />
+
+ <xsl:param name="mode"/>
+ <xsl:param name="source"/>
+ <xsl:param name="run_date"/>
+ <xsl:param name="warnings"/>
+ <xsl:param name="comment_file"/>
+ <xsl:param name="explicit_markup_file"/>
+ <xsl:param name="release"/>
+
+ <xsl:variable name="explicit_markup" select="document( $explicit_markup_file )"/>
+
+ <!-- necessary indexes -->
+ <xsl:key
+ name="library_test_name_key"
+ match="test-log"
+ use="concat( @library, '&gt;@&lt;', @test-name )"/>
+ <xsl:key name="toolset_key" match="test-log" use="@toolset"/>
+ <xsl:key name="test_name_key" match="test-log" use="@test-name "/>
+
+ <xsl:variable name="unusables_f">
+ <xsl:for-each select="set:distinct( $run_toolsets//toolset/@name )">
+ <xsl:variable name="toolset" select="."/>
+ <xsl:for-each select="$libraries">
+ <xsl:variable name="library" select="."/>
+ <xsl:if test="meta:is_unusable_( $explicit_markup, $library, $toolset )">
+ <unusable library-name="{$library}" toolset-name="{$toolset}"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="unusables" select="exsl:node-set( $unusables_f )"/>
+
+
+ <xsl:key
+ name="library-name_toolset-name_key"
+ match="unusable"
+ use="concat( @library-name, '&gt;@&lt;', @toolset-name )"/>
+
+ <!--<xsl:variable name="expected_results" select="document( $expected_results_file )" />-->
+
+ <!-- runs / toolsets -->
+ <xsl:variable name="run_toolsets" select="meta:test_structure( /, $release )"/>
+
+ <!-- libraries -->
+
+ <xsl:variable name="test_case_logs" select="//test-log[ meta:is_test_log_a_test_case(.) and meta:show_library( @library, $release ) and meta:show_toolset( @toolset, $release )]"/>
+ <xsl:variable name="libraries" select="set:distinct( $test_case_logs/@library )"/>
+
+ <xsl:variable name="sorted_libraries_output">
+ <xsl:for-each select="$libraries[ meta:show_library( ., $release )]">
+ <xsl:sort select="." order="ascending" />
+ <library><xsl:copy-of select="."/></library>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="sorted_libraries" select="exsl:node-set( $sorted_libraries_output )/library/@library"/>
+
+ <!-- modes -->
+
+ <xsl:variable name="alternate_mode">
+ <xsl:choose>
+ <xsl:when test="$mode='user'">developer</xsl:when>
+ <xsl:otherwise>user</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="release_postfix">
+ <xsl:if test="$release='yes'">
+ <xsl:text>_release</xsl:text>
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:template match="/">
+
+ <xsl:variable name="summary_results" select="concat( 'summary', $release_postfix, '_.html' )"/>
+
+ <!-- Summary page -->
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ <title>Boost regression summary: <xsl:value-of select="$source"/></title>
+ </head>
+ <frameset cols="190px,*" frameborder="0" framespacing="0" border="0">
+ <frame name="tocframe" src="toc{$release_postfix}.html" scrolling="auto"/>
+ <frame name="docframe" src="{$summary_results}" scrolling="auto"/>
+ </frameset>
+ </html>
+
+ <!-- Summary results -->
+ <xsl:message>Writing document <xsl:value-of select="$summary_results"/></xsl:message>
+
+ <exsl:document href="{$summary_results}"
+ method="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ encoding="utf-8"
+ indent="yes">
+
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../master.css" title="master" />
+ </head>
+ <body>
+
+ <xsl:call-template name="insert_page_links">
+ <xsl:with-param name="page" select="'summary'"/>
+ <xsl:with-param name="release" select="$release"/>
+ <xsl:with-param name="mode" select="$alternate_mode"/>
+ </xsl:call-template>
+
+ <h1 class="page-title">
+ <xsl:text>Summary: </xsl:text>
+ <a class="hover-link" href="summary{$release_postfix}.html" target="_top"><xsl:value-of select="$source"/></a>
+ </h1>
+
+ <xsl:call-template name="insert_report_header">
+ <xsl:with-param name="run_date" select="$run_date"/>
+ <xsl:with-param name="warnings" select="$warnings"/>
+ </xsl:call-template>
+
+ <div class="statistics">
+ Unusable: <xsl:value-of select="count( $test_case_logs[ meta:test_case_status( $explicit_markup, . ) = 'unusable' ] )"/>
+ &#160;|&#160;
+ Regressions: <xsl:value-of select="count( $test_case_logs[ meta:test_case_status( $explicit_markup, . ) = 'fail-unexpected' ] )"/>
+ &#160;|&#160;
+ New failures: <xsl:value-of select="count( $test_case_logs[ meta:test_case_status( $explicit_markup, . ) = 'fail-unexpected-new' ] )"/>
+ </div>
+
+ <!-- summary table -->
+
+ <table border="0" cellspacing="0" cellpadding="0" width="1%" class="summary-table" summary="Overall summary">
+
+ <thead>
+ <xsl:call-template name="insert_runners_rows">
+ <xsl:with-param name="mode" select="'summary'"/>
+ <xsl:with-param name="top_or_bottom" select="'top'"/>
+ <xsl:with-param name="run_toolsets" select="$run_toolsets"/>
+ <xsl:with-param name="run_date" select="$run_date"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="insert_toolsets_row">
+ <xsl:with-param name="mode" select="'summary'"/>
+ <xsl:with-param name="run_date" select="$run_date"/>
+ </xsl:call-template>
+ </thead>
+
+ <tfoot>
+ <xsl:call-template name="insert_toolsets_row">
+ <xsl:with-param name="mode" select="'summary'"/>
+ <xsl:with-param name="run_date" select="$run_date"/>
+ </xsl:call-template>
+ <xsl:call-template name="insert_runners_rows">
+ <xsl:with-param name="mode" select="'summary'"/>
+ <xsl:with-param name="top_or_bottom" select="'bottom'"/>
+ <xsl:with-param name="run_toolsets" select="$run_toolsets"/>
+ <xsl:with-param name="run_date" select="$run_date"/>
+ </xsl:call-template>
+ </tfoot>
+
+ <tbody>
+ <xsl:variable name="test_logs" select="$test_case_logs"/>
+
+ <!-- for each library -->
+ <xsl:for-each select="$sorted_libraries">
+ <xsl:variable name="library" select="."/>
+ <xsl:variable name="library_page" select="meta:encode_path( $library )" />
+ <xsl:variable name="current_row" select="$test_logs[ @library=$library ]"/>
+
+ <xsl:variable name="expected_test_count" select="count( $current_row[ generate-id(.) = generate-id( key('test_name_key',@test-name)[1] ) ] )"/>
+ <xsl:variable name="library_header">
+ <td class="library-name">
+ <a href="{$library_page}{$release_postfix}.html" class="library-link" target="_top">
+ <xsl:value-of select="$library"/>
+ </a>
+ </td>
+ </xsl:variable>
+
+ <xsl:variable name="line_mod">
+ <xsl:choose>
+ <xsl:when test="1 = last()">
+ <xsl:text>-single</xsl:text>
+ </xsl:when>
+ <xsl:when test="generate-id( . ) = generate-id( $sorted_libraries[1] )">
+ <xsl:text>-first</xsl:text>
+ </xsl:when>
+ <xsl:when test="generate-id( . ) = generate-id( $sorted_libraries[ last() ] )">
+ <xsl:text>-last</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text></xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+
+ <tr class="summary-row{$line_mod}">
+ <xsl:copy-of select="$library_header"/>
+
+ <xsl:for-each select="$run_toolsets/platforms/platform/runs/run/toolset">
+ <xsl:variable name="toolset" select="@name" />
+ <xsl:variable name="runner" select="../@runner" />
+
+ <xsl:variable name="current_cell" select="$current_row[ @toolset=$toolset and ../@runner = $runner ]"/>
+
+ <xsl:choose>
+ <xsl:when test="$mode='user'">
+ <xsl:call-template name="insert_cell_user">
+ <xsl:with-param name="current_cell" select="$current_cell"/>
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="toolset" select="$toolset"/>
+ <xsl:with-param name="expected_test_count" select="$expected_test_count"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$mode='developer'">
+ <xsl:call-template name="insert_cell_developer">
+ <xsl:with-param name="current_cell" select="$current_cell"/>
+ <xsl:with-param name="library" select="$library"/>
+ <xsl:with-param name="toolset" select="$toolset"/>
+ <xsl:with-param name="expected_test_count" select="$expected_test_count"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+
+ <xsl:copy-of select="$library_header"/>
+ </tr>
+ </xsl:for-each>
+ </tbody>
+ </table>
+
+ <div id="legend">
+ <xsl:copy-of select="document( concat( 'html/summary_', $mode, '_legend.html' ) )"/>
+ </div>
+
+ <xsl:call-template name="insert_page_links">
+ <xsl:with-param name="page" select="'summary'"/>
+ <xsl:with-param name="release" select="$release"/>
+ <xsl:with-param name="mode" select="$alternate_mode"/>
+ </xsl:call-template>
+
+ </body>
+ </html>
+ </exsl:document>
+
+ </xsl:template>
+
+ <!-- report developer status -->
+ <xsl:template name="insert_cell_developer">
+ <xsl:param name="current_cell"/>
+ <xsl:param name="library"/>
+ <xsl:param name="toolset"/>
+ <xsl:param name="expected_test_count"/>
+
+ <xsl:variable name="class" select="concat( 'summary-', meta:result_cell_class( $library, $toolset, $current_cell ) )"/>
+
+ <xsl:variable name="library_page" select="meta:encode_path( $library )" />
+
+ <td class="{$class}" title="{$library}/{$toolset}">
+ <xsl:choose>
+ <xsl:when test="$class='summary-unusable'">
+ <xsl:text>&#160;&#160;</xsl:text>
+ <a href="{$library_page}{$release_postfix}.html" class="log-link" target="_top">
+ <xsl:text>n/a</xsl:text>
+ </a>
+ <xsl:text>&#160;&#160;</xsl:text>
+ </xsl:when>
+ <xsl:when test="$class='summary-missing'">
+ <xsl:text>&#160;&#160;&#160;&#160;</xsl:text>
+ </xsl:when>
+ <xsl:when test="$class='summary-fail-unexpected'">
+ <a href="{$library_page}{$release_postfix}.html" class="log-link" target="_top">
+ <xsl:text>broken</xsl:text>
+ </a>
+ </xsl:when>
+ <xsl:when test="$class='summary-fail-unexpected-new' ">
+ <xsl:text>&#160;&#160;</xsl:text>
+ <a href="{$library_page}{$release_postfix}.html" class="log-link" target="_top">
+ <xsl:text>fail</xsl:text>
+ </a>
+ <xsl:text>&#160;&#160;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&#160;&#160;OK&#160;&#160;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+
+ </xsl:template>
+
+
+ <!-- report user status -->
+ <xsl:template name="insert_cell_user">
+ <xsl:param name="current_cell"/>
+ <xsl:param name="library"/>
+ <xsl:param name="toolset"/>
+ <xsl:param name="expected_test_count"/>
+
+ <xsl:variable name="class" select="concat( 'summary-', meta:result_cell_class( $library, $toolset, $current_cell ) )"/>
+
+ <xsl:variable name="library_page" select="meta:encode_path( $library )" />
+
+ <td class="{$class} user-{$class}" title="{$library}/{$toolset}">
+ <xsl:choose>
+ <xsl:when test="$class='summary-unusable'">
+ <xsl:text>&#160;</xsl:text>
+ <a href="{$library_page}{$release_postfix}.html" class="log-link" target="_top">
+ <xsl:text>unusable</xsl:text>
+ </a>
+ <xsl:text>&#160;</xsl:text>
+ </xsl:when>
+ <xsl:when test="$class='summary-missing'">
+ <xsl:text>&#160;no&#160;results&#160;</xsl:text>
+ </xsl:when>
+ <xsl:when test="$class='summary-fail-unexpected'">
+ <xsl:text>&#160;</xsl:text>
+ <a href="{$library_page}{$release_postfix}.html" class="log-link" target="_top">
+ <xsl:text>regress.</xsl:text>
+ </a>
+ <xsl:text>&#160;</xsl:text>
+ </xsl:when>
+ <xsl:when test="$class='summary-fail-unexpected-new'
+ or $class='summary-fail-expected'
+ or $class='summary-unknown-status'
+ or $class='summary-fail-expected-unresearched'">
+ <xsl:text>&#160;</xsl:text>
+ <a href="{$library_page}{$release_postfix}.html" class="log-link" target="_top">
+ <xsl:text>details</xsl:text>
+ </a>
+ <xsl:text>&#160;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&#160;pass&#160;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/release/2release.bat b/tools/release/2release.bat
new file mode 100644
index 0000000000..391ac2ea11
--- /dev/null
+++ b/tools/release/2release.bat
@@ -0,0 +1,16 @@
+@echo off
+rem Copyright Beman Dawes 2011
+rem Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt
+if not %1$==$ goto usage_ok
+echo Usage: 2release path-relative-to-boost-root [svn-options]
+echo Path may be to file or directory
+echo Options include --dry-run
+echo WARNING: The current directory must be the directory in %BOOST_RELEASE%
+echo specified by the path-relative argument
+goto done
+
+:usage_ok
+svn merge %2 %3 %4 %5 %6 https://svn.boost.org/svn/boost/branches/release/%1 ^
+ https://svn.boost.org/svn/boost/trunk/%1
+
+:done
diff --git a/tools/release/README b/tools/release/README
new file mode 100644
index 0000000000..bb8eaeca59
--- /dev/null
+++ b/tools/release/README
@@ -0,0 +1,11 @@
+Boost SourceForge release folder README
+---------------------------------------
+
+The only differences between the distribution files are the line endings
+and archive format. The .bz2 and .7z formats are preferred as more compact.
+
+Distribution files with extensions .gz and .bz2 use Unix line endings.
+
+Distribution files with extensions .zip and .7z use Windows line endings.
+
+See http://www.boost.org/users/history for information about each Boost release.
diff --git a/tools/release/bjam_warnings.bat b/tools/release/bjam_warnings.bat
new file mode 100644
index 0000000000..b45f4b785b
--- /dev/null
+++ b/tools/release/bjam_warnings.bat
@@ -0,0 +1,17 @@
+@echo off
+rem Scan bjam/b2 log file for compile warnings
+
+rem Copyright 2011 Beman Dawes
+
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+if not %1$==$ goto usage_ok
+echo Usage: bjam_warnings log-path
+goto done
+
+:usage_ok
+
+grep -i "warning" %1 | grep -E "boost|libs" | sort | uniq
+
+:done
diff --git a/tools/release/build_docs.sh b/tools/release/build_docs.sh
new file mode 100755
index 0000000000..6e00fb31a0
--- /dev/null
+++ b/tools/release/build_docs.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+# Build docs
+
+# Copyright 2008 Beman Dawes
+# Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt
+
+if [ $# -lt 1 ]
+then
+ echo "invoke:" $0 "directory-name"
+ echo "example:" $0 "posix"
+ exit 1
+fi
+
+echo building $1 docs...
+pushd $1/doc
+bjam --v2 >../../$1-bjam.log
+ls html
+popd
+
diff --git a/tools/release/build_release.sh b/tools/release/build_release.sh
new file mode 100755
index 0000000000..39a10df4db
--- /dev/null
+++ b/tools/release/build_release.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+# Build release packages
+
+# Copyright 2008 Beman Dawes
+# Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt
+
+if [ $# -lt 1 ]
+then
+ echo "invoke:" $0 "release-name"
+ echo "example:" $0 "boost_1_35_0_RC3"
+ exit 1
+fi
+
+./load_posix.sh
+./load_windows.sh
+./build_docs.sh posix
+./build_docs.sh windows
+./build_release_packages.sh $1
+
diff --git a/tools/release/build_release_packages.bat b/tools/release/build_release_packages.bat
new file mode 100644
index 0000000000..5f72e5157c
--- /dev/null
+++ b/tools/release/build_release_packages.bat
@@ -0,0 +1,47 @@
+@echo off
+rem Build release packages
+
+rem Copyright Beman Dawes 2009
+
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+echo Build release packages...
+
+if not %1$==$ goto ok
+echo Usage: build_release_packages release-name
+echo Example: build_release_packages boost_1_38_0_Beta1
+goto done
+
+:ok
+
+echo Preping posix...
+rmdir /s /q posix\bin.v2 2>nul
+rmdir /s /q posix\dist 2>nul
+ren posix %1
+del %1.tar.gz 2>nul
+del %1.tar.bz2 2>nul
+echo Creating gz...
+tar cfz %1.tar.gz %1
+echo Creating bz2...
+gzip -d -c %1.tar.gz | bzip2 >%1.tar.bz2
+echo Cleaning up posix...
+ren %1 posix
+
+echo Preping windows...
+rmdir /s /q windows\bin.v2 2>nul
+rmdir /s /q windows\dist 2>nul
+ren windows %1
+del %1.zip 2>nul
+del %1.7z 2>nul
+echo Creating zip...
+zip -r -q %1.zip %1
+echo Creating 7z...
+7z a -r -bd %1.7z %1
+echo Cleaning up windows...
+ren %1 windows
+
+grep "Revision:" snapshot.log
+echo Build release packages complete
+
+:done
diff --git a/tools/release/build_release_packages.sh b/tools/release/build_release_packages.sh
new file mode 100755
index 0000000000..2a126c01c0
--- /dev/null
+++ b/tools/release/build_release_packages.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+
+# Build release packages
+
+# Copyright 2008 Beman Dawes
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+if [ $# -lt 1 ]
+then
+ echo "invoke:" $0 "release-name"
+ echo "example:" $0 "boost_1_35_0_RC3"
+ exit 1
+fi
+
+echo "preping posix..."
+rm -r posix/bin.v2 2>/dev/null
+rm -r posix/dist 2>/dev/null
+mv posix $1
+rm -f $1.tar.gz 2>/dev/null
+rm -f $1.tar.bz2 2>/dev/null
+echo "creating gz..."
+tar cfz $1.tar.gz $1
+echo "creating bz2..."
+gzip -c $1.tar.gz | bzip2 >$1.tar.bz2
+echo "cleaning up..."
+mv $1 posix
+
+echo "preping windows..."
+rm -r windows/bin.v2 2>/dev/null
+rm -r windows/dist 2>/dev/null
+mv windows $1
+rm -f $1.zip 2>/dev/null
+rm -f $1.7z 2>/dev/null
+echo "creating zip..."
+zip -r $1.zip $1
+echo "creating 7z..."
+7z a -r $1.7z $1
+echo "cleaning up..."
+mv $1 windows
+
+exit 0
+
diff --git a/tools/release/index.html b/tools/release/index.html
new file mode 100644
index 0000000000..8e850eab4f
--- /dev/null
+++ b/tools/release/index.html
@@ -0,0 +1,64 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<title>Release Scripts</title>
+<link rel="stylesheet" type="text/css" href="../../doc/src/minimal.css">
+</head>
+
+<body>
+<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="637">
+ <tr>
+ <td width="277">
+<a href="../../index.htm">
+<img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86" border="0"></a></td>
+ <td width="337" align="middle">
+ <font size="7">Release Scripts</font>
+ </td>
+ </tr>
+</table>
+
+<h2>Introduction</h2>
+<p>The release scripts are used by the release management team to build the
+release distribution files, and perform related release management functions.</p>
+<p>The files being built include:</p>
+<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
+ <tr>
+ <td width="100%" colspan="2">
+ <p align="center"><b><i>Files</i></b></td>
+ </tr>
+ <tr>
+ <td width="50%">boost_x_xx_x.7z</td>
+ <td width="50%">&nbsp;</td>
+ </tr>
+ <tr>
+ <td width="50%">boost_x_xx_x.tar.bz2</td>
+ <td width="50%">Unix-style line endings</td>
+ </tr>
+ <tr>
+ <td width="50%">boost_x_xx_x.tar.gz</td>
+ <td width="50%">Unix-style line endings</td>
+ </tr>
+ <tr>
+ <td width="50%">boost_x_xx_x.zip</td>
+ <td width="50%">Windows-style line endings</td>
+ </tr>
+</table>
+<p>The content of all files is identical except for the line endings.</p>
+
+<hr>
+
+<p>© Copyright Beman Dawes, 2008<br>
+Distributed under the Boost Software License, Version 1.0. See
+<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
+
+<p>Revised
+<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%B %d, %Y" startspan -->January 18, 2008<!--webbot bot="Timestamp" endspan i-checksum="31853" --> </font>
+</p>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/tools/release/inspect.sh b/tools/release/inspect.sh
new file mode 100755
index 0000000000..7c04fb58c2
--- /dev/null
+++ b/tools/release/inspect.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+
+# Inspect snapshot
+
+# © Copyright 2008 Beman Dawes
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+# This script uses ftp, and thus assumes ~/.netrc contains a machine ... entry
+
+pushd posix/tools/inspect/build
+bjam
+popd
+echo inspect...
+pushd posix
+dist/bin/inspect >../inspect.html
+popd
+
+# create the ftp script
+echo create ftp script...
+echo "dir" >inspect.ftp
+echo "binary" >>inspect.ftp
+echo "put inspect.html" >>inspect.ftp
+echo "delete inspect-snapshot.html" >>inspect.ftp
+echo "rename inspect.html inspect-snapshot.html" >>inspect.ftp
+echo "dir" >>inspect.ftp
+echo "bye" >>inspect.ftp
+# use cygwin ftp rather than Windows ftp
+echo ftp...
+/usr/bin/ftp -v -i boost.cowic.de <inspect.ftp
+echo inspect.sh complete
diff --git a/tools/release/inspect_trunk.bat b/tools/release/inspect_trunk.bat
new file mode 100644
index 0000000000..4a306a9302
--- /dev/null
+++ b/tools/release/inspect_trunk.bat
@@ -0,0 +1,42 @@
+rem Inspect Trunk
+rem Copyright Beman Dawes 2008, 2009
+
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+echo Must be run in directory containing svn checkout of trunk
+
+echo Clean trunk working copy ...
+rem cleanup clears locks or other residual problems (we learned this the hard way!)
+svn cleanup
+echo Update trunk working copy...
+svn up --non-interactive --trust-server-cert
+pushd tools\inspect\build
+echo Build inspect program...
+bjam
+popd
+echo Copy inspect.exe to %UTIL% directory...
+copy /y dist\bin\inspect.exe %UTIL%
+echo Inspect...
+inspect >%TEMP%\trunk_inspect.html
+
+echo Create ftp script...
+pushd %TEMP%
+copy %BOOST_TRUNK%\..\user.txt inspect.ftp
+echo dir >>inspect.ftp
+echo binary >>inspect.ftp
+echo put trunk_inspect.html >>inspect.ftp
+echo dir >>inspect.ftp
+echo mdelete inspect-trunk.html >>inspect.ftp
+echo rename trunk_inspect.html inspect-trunk.html >>inspect.ftp
+echo dir >>inspect.ftp
+echo bye >>inspect.ftp
+
+echo Run ftp script...
+ftp -n -i -s:inspect.ftp boost.cowic.de
+popd
+
+echo Update script for next run
+copy /y tools\release\inspect_trunk.bat
+
+echo Inspect script complete
diff --git a/tools/release/linux_user-config.jam b/tools/release/linux_user-config.jam
new file mode 100644
index 0000000000..6b62071b02
--- /dev/null
+++ b/tools/release/linux_user-config.jam
@@ -0,0 +1,21 @@
+# Linux user-config.jam
+
+import toolset : using ;
+
+using gcc ;
+
+using python ; # requires pythonN.NN-dev be installed
+
+# Boost iostreams requires no user-config.jam entries,
+# but does require zliblg-dev, libbz2-dev, be installed
+
+using xsltproc ;
+
+using boostbook
+ : /usr/share/xml/docbook/stylesheet/nwalsh
+ : /usr/share/xml/docbook/schema/dtd/4.2
+ ;
+
+# Remove this line if you're not using doxygen
+using doxygen ;
+using quickbook ;
diff --git a/tools/release/load_posix.sh b/tools/release/load_posix.sh
new file mode 100755
index 0000000000..eecdbed240
--- /dev/null
+++ b/tools/release/load_posix.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+# Load posix directory from branches/release snapshot, using LF line termination
+
+# Copyright 2008 Beman Dawes
+# Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt
+
+rm -r -f posix 2>/dev/null
+svn export --non-interactive --native-eol LF http://svn.boost.org/svn/boost/branches/release posix
+
diff --git a/tools/release/load_windows.sh b/tools/release/load_windows.sh
new file mode 100755
index 0000000000..08967ddf9e
--- /dev/null
+++ b/tools/release/load_windows.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+# Load windows directory from branches/release snapshot, using CR/LF line termination
+
+# Copyright 2008 Beman Dawes
+# Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt
+
+rm -r -f windows 2>/dev/null
+svn export --non-interactive --native-eol CRLF http://svn.boost.org/svn/boost/branches/release windows
+
diff --git a/tools/release/make_packages.sh b/tools/release/make_packages.sh
new file mode 100755
index 0000000000..3aeb17f8f5
--- /dev/null
+++ b/tools/release/make_packages.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+# Build branches/release packages
+
+# © Copyright 2008 Beman Dawes
+# Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt
+
+if [ $# -lt 1 ]
+then
+ echo "invoke:" $0 "package-name"
+ echo "example:" $0 "boost_1_35_0_RC3"
+ exit 1
+fi
+
+echo "preping posix..."
+rm -r posix/bin.v2 2>/dev/null
+rm -r posix/dist 2>/dev/null
+mv posix $1
+rm -f $1.tar.gz 2>/dev/null
+rm -f $1.tar.bz2 2>/dev/null
+echo "creating gz..."
+tar cfz $1.tar.gz $1
+echo "creating bz2..."
+gunzip -c $1.tar.gz | bzip2 >$1.tar.bz2
+echo "cleaning up..."
+mv $1 posix
+
+echo "preping windows..."
+rm -r windows/bin.v2 2>/dev/null
+rm -r windows/dist 2>/dev/null
+mv windows $1
+rm -f $1.zip 2>/dev/null
+rm -f $1.7z 2>/dev/null
+echo "creating zip..."
+zip -r $1.zip $1
+echo "creating 7z..."
+7z a -r $1.7z $1
+echo "cleaning up..."
+mv $1 windows
+
+echo "done automatic processing; you must now upload packages manually"
+exit 0
+
+
+
diff --git a/tools/release/merge2release.bat b/tools/release/merge2release.bat
new file mode 100644
index 0000000000..39bb01f216
--- /dev/null
+++ b/tools/release/merge2release.bat
@@ -0,0 +1,22 @@
+rem @echo off
+rem Copyright Beman Dawes 2010
+rem Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt
+if not %1$==$ goto usage_ok
+echo Usage: merge2release library-name [svn-options]
+echo Options include --dry-run
+goto done
+
+:usage_ok
+pushd %BOOST_RELEASE%
+pushd boost
+call 2release boost/%1.hpp %2 %3 %4 %5 %6
+pushd %1
+call 2release boost/%1 %2 %3 %4 %5 %6
+popd
+popd
+pushd libs\%1
+call 2release libs/%1 %2 %3 %4 %5 %6
+popd
+popd
+
+:done
diff --git a/tools/release/merge_release_cycle_init.bat b/tools/release/merge_release_cycle_init.bat
new file mode 100644
index 0000000000..3eb3bbe707
--- /dev/null
+++ b/tools/release/merge_release_cycle_init.bat
@@ -0,0 +1,16 @@
+rem @echo off
+rem Copyright Beman Dawes 2011
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+pushd %BOOST_RELEASE%
+svn up
+call 2release Jamroot
+call 2release index.html
+pushd boost
+call 2release boost/version.hpp
+popd
+pushd more
+call 2release more
+popd
+popd
diff --git a/tools/release/release-mgt-msvc/compare_trees/compare_trees.vcproj b/tools/release/release-mgt-msvc/compare_trees/compare_trees.vcproj
new file mode 100644
index 0000000000..f52093006f
--- /dev/null
+++ b/tools/release/release-mgt-msvc/compare_trees/compare_trees.vcproj
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="compare_trees"
+ ProjectGUID="{7E6AD5ED-4168-4613-A342-0217AA82DEC1}"
+ RootNamespace="compare_trees"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="..\..\..\..\stage\lib"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\..\.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="..\..\..\..\stage\lib"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\compare_trees.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tools/release/release-mgt-msvc/msvc.sln b/tools/release/release-mgt-msvc/msvc.sln
new file mode 100644
index 0000000000..ca70e06f63
--- /dev/null
+++ b/tools/release/release-mgt-msvc/msvc.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "compare_trees", "compare_trees\compare_trees.vcproj", "{7E6AD5ED-4168-4613-A342-0217AA82DEC1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "strftime", "strftime\strftime.vcproj", "{4A82F955-7630-4B79-9C50-E45F27E28BA8}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7E6AD5ED-4168-4613-A342-0217AA82DEC1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7E6AD5ED-4168-4613-A342-0217AA82DEC1}.Debug|Win32.Build.0 = Debug|Win32
+ {7E6AD5ED-4168-4613-A342-0217AA82DEC1}.Release|Win32.ActiveCfg = Release|Win32
+ {7E6AD5ED-4168-4613-A342-0217AA82DEC1}.Release|Win32.Build.0 = Release|Win32
+ {4A82F955-7630-4B79-9C50-E45F27E28BA8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4A82F955-7630-4B79-9C50-E45F27E28BA8}.Debug|Win32.Build.0 = Debug|Win32
+ {4A82F955-7630-4B79-9C50-E45F27E28BA8}.Release|Win32.ActiveCfg = Release|Win32
+ {4A82F955-7630-4B79-9C50-E45F27E28BA8}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/tools/release/release-mgt-msvc/strftime/strftime.vcproj b/tools/release/release-mgt-msvc/strftime/strftime.vcproj
new file mode 100644
index 0000000000..4b8e9ab866
--- /dev/null
+++ b/tools/release/release-mgt-msvc/strftime/strftime.vcproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="strftime"
+ ProjectGUID="{4A82F955-7630-4B79-9C50-E45F27E28BA8}"
+ RootNamespace="strftime"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\strftime.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tools/release/release_reports.sh b/tools/release/release_reports.sh
new file mode 100755
index 0000000000..73d8ead91d
--- /dev/null
+++ b/tools/release/release_reports.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+
+# Run the release branch regression reporting system
+
+# Copyright 2008 Beman Dawes
+
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+# Requirements:
+#
+# * ~/boost/trunk is an svn working copy of the trunk
+# * ~/boost/release-reports is a directory devoted to release regression reporting
+# * ~/boost/release-reports/boost is an svn working of branches/release
+# * ~/boost/release-reports/release/ exists
+
+echo Updating ~/boost/trunk/tools/regression ...
+svn up ~/boost/trunk/tools/regression
+
+echo Updating ~/boost/trunk/tools/release ...
+svn up ~/boost/trunk/tools/release
+
+pushd ~/boost/release-reports
+
+echo Running build_results.sh ...
+date >report.log
+~/boost/trunk/tools/regression/xsl_reports/build_results.sh release 1>>report.log 2>>report.log
+date >>report.log
+
+popd
+echo Release regression reporting complete - see ~/boost/release-reports/report.log
diff --git a/tools/release/revision_number.bat b/tools/release/revision_number.bat
new file mode 100644
index 0000000000..8f03bd0f16
--- /dev/null
+++ b/tools/release/revision_number.bat
@@ -0,0 +1,13 @@
+rem Create revision information, to be used by other script
+
+rem Copyright 2011 Beman Dawes
+
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+echo Getting current subversion revision number...
+svn co --non-interactive --depth=files http://svn.boost.org/svn/boost/branches/release svn_info
+svn info svn_info
+
+svn info svn_info | grep Revision | sed "s/Revision: /set BOOST_REVISION_NUMBER=/" >generated_set_release.bat
+call generated_set_release.bat
diff --git a/tools/release/snapshot.bat b/tools/release/snapshot.bat
new file mode 100644
index 0000000000..5029e3d73b
--- /dev/null
+++ b/tools/release/snapshot.bat
@@ -0,0 +1,39 @@
+@echo off
+rem Run POSIX and Windows snapshots and inspection
+
+rem Copyright 2008 Beman Dawes
+
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+rem Must be run in a directory devoted to boost release snapshots
+
+echo Remove residue from prior runs...
+rem rmdir commands seem to finish before the deletes are necessarily complete.
+rem This can occasionally cause subsequent commands to fail because they expect
+rem the directory to be gone or empty. snapshot_posix and snapshot_windows
+rem are affected. Fix is to run rmdir here so that deletes are complete
+rem by the time snapshots are run.
+rmdir /s /q posix >nul
+rmdir /s /q windows >nul
+time /t
+
+echo Using %BOOST_TRUNK% as boost trunk
+time /t
+pushd %BOOST_TRUNK%
+echo Running svn cleanup on %BOOST_TRUNK%
+svn --non-interactive --trust-server-cert cleanup
+echo Running svn update on %BOOST_TRUNK%
+svn --non-interactive --trust-server-cert up
+popd
+call %BOOST_TRUNK%\tools\release\revision_number.bat
+time /t
+call %BOOST_TRUNK%\tools\release\snapshot_download_docs.bat
+time /t
+call %BOOST_TRUNK%\tools\release\snapshot_posix.bat
+time /t
+call %BOOST_TRUNK%\tools\release\snapshot_windows.bat
+time /t
+call %BOOST_TRUNK%\tools\release\snapshot_inspection.bat
+time /t
+echo Revision %BOOST_REVISION_NUMBER% snapshot complete
diff --git a/tools/release/snapshot.sh b/tools/release/snapshot.sh
new file mode 100755
index 0000000000..8e45abbccc
--- /dev/null
+++ b/tools/release/snapshot.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+# © Copyright 2008 Beman Dawes
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+sleep 5s
+echo Using $BOOST_TRUNK as boost trunk
+date
+$BOOST_TRUNK/tools/release/snapshot_posix.sh
+date
+$BOOST_TRUNK/tools/release/snapshot_windows.sh
+date
+$BOOST_TRUNK/tools/release/snapshot_inspect.sh
+date
+sleep 5s
diff --git a/tools/release/snapshot_download_docs.bat b/tools/release/snapshot_download_docs.bat
new file mode 100644
index 0000000000..5bdae2b5a8
--- /dev/null
+++ b/tools/release/snapshot_download_docs.bat
@@ -0,0 +1,31 @@
+@echo off
+rem Download and unpack boost-release-docs.7z
+
+rem Copyright 2008 Beman Dawes
+
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+echo Downloading docs subdirectory...
+
+echo Deleting old files and directories ...
+del boost-docs.7z 2>nul
+del boost-release-docs.7z 2>nul
+rmdir /s /q docs_temp 2>nul
+mkdir docs_temp
+
+echo Creating ftp script ...
+rem user.txt must be a single line: user userid password
+rem where "userid" and "password" are replace with the appropriate values
+copy user.txt download_docs.ftp
+echo binary >>download_docs.ftp
+echo get boost-release-docs.7z >>download_docs.ftp
+echo bye >>download_docs.ftp
+
+echo Running ftp script ...
+ftp -d -n -i -s:download_docs.ftp boost.cowic.de
+
+echo Unpacking 7z file ...
+7z x -y -odocs_temp boost-release-docs.7z
+
+echo Download and unpack boost-release-docs.7z complete! \ No newline at end of file
diff --git a/tools/release/snapshot_inspect.sh b/tools/release/snapshot_inspect.sh
new file mode 100755
index 0000000000..7c04fb58c2
--- /dev/null
+++ b/tools/release/snapshot_inspect.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+
+# Inspect snapshot
+
+# © Copyright 2008 Beman Dawes
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+# This script uses ftp, and thus assumes ~/.netrc contains a machine ... entry
+
+pushd posix/tools/inspect/build
+bjam
+popd
+echo inspect...
+pushd posix
+dist/bin/inspect >../inspect.html
+popd
+
+# create the ftp script
+echo create ftp script...
+echo "dir" >inspect.ftp
+echo "binary" >>inspect.ftp
+echo "put inspect.html" >>inspect.ftp
+echo "delete inspect-snapshot.html" >>inspect.ftp
+echo "rename inspect.html inspect-snapshot.html" >>inspect.ftp
+echo "dir" >>inspect.ftp
+echo "bye" >>inspect.ftp
+# use cygwin ftp rather than Windows ftp
+echo ftp...
+/usr/bin/ftp -v -i boost.cowic.de <inspect.ftp
+echo inspect.sh complete
diff --git a/tools/release/snapshot_inspection.bat b/tools/release/snapshot_inspection.bat
new file mode 100644
index 0000000000..1a86aa4b8e
--- /dev/null
+++ b/tools/release/snapshot_inspection.bat
@@ -0,0 +1,28 @@
+rem Inspect snapshot
+
+rem Copyright Beman Dawes 2008, 2011
+
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+echo inspect...
+pushd windows
+rem inspect_trunk.bat builds inspect program every day and copies it to %UTIL%
+%UTIL%%\inspect >..\inspect.html
+popd
+
+echo Create ftp script...
+copy user.txt inspect.ftp
+echo dir >>inspect.ftp
+echo binary >>inspect.ftp
+echo put inspect.html >>inspect.ftp
+echo dir >>inspect.ftp
+echo mdelete inspect-snapshot.html >>inspect.ftp
+echo rename inspect.html inspect-snapshot.html >>inspect.ftp
+echo dir >>inspect.ftp
+echo bye >>inspect.ftp
+
+echo Run ftp script...
+ftp -n -i -s:inspect.ftp boost.cowic.de
+
+echo Inspect script complete
diff --git a/tools/release/snapshot_posix.bat b/tools/release/snapshot_posix.bat
new file mode 100644
index 0000000000..1a061dccba
--- /dev/null
+++ b/tools/release/snapshot_posix.bat
@@ -0,0 +1,69 @@
+rem Build a branches/release snapshot for POSIX, using LF line termination
+
+rem Copyright 2008 Beman Dawes
+
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+echo Build a branches/release snapshot for POSIX, using LF line termination...
+echo Revision %BOOST_REVISION_NUMBER%
+echo Removing old files...
+rmdir /s /q posix >nul
+rmdir /s /q svn_info >nul
+del posix.tar.gz >nul
+del posix.tar.bz2 >nul
+
+echo Exporting files from subversion...
+svn export --non-interactive --native-eol LF -r %BOOST_REVISION_NUMBER% http://svn.boost.org/svn/boost/branches/release posix
+
+echo Copying docs into posix...
+pushd posix
+xcopy /s /y ..\docs_temp
+popd
+
+echo Setting SNAPSHOT_DATE
+strftime "%%Y-%%m-%%d" >date.txt
+set /p SNAPSHOT_DATE= <date.txt
+echo SNAPSHOT_DATE is %SNAPSHOT_DATE%
+
+echo Renaming root directory...
+ren posix boost-posix-%SNAPSHOT_DATE%
+
+echo Building .gz file...
+tar cfz posix.tar.gz --numeric-owner --group=0 --owner=0 boost-posix-%SNAPSHOT_DATE%
+echo Building .bz2 file...
+gzip -d -c posix.tar.gz | bzip2 >posix.tar.bz2
+
+ren boost-posix-%SNAPSHOT_DATE% posix
+
+echo The ftp transfer will be done in two steps because that has proved more
+echo reliable on Beman's Windows XP 64-bit system.
+
+echo Creating ftp script 1 ...
+copy user.txt posix.ftp
+echo dir >>posix.ftp
+echo binary >>posix.ftp
+
+rem echo put posix.tar.gz >>posix.ftp
+rem echo mdelete boost-posix*.gz >>posix.ftp
+rem echo rename posix.tar.gz boost-posix-%SNAPSHOT_DATE%.tar.gz >>posix.ftp
+
+echo put posix.tar.bz2 >>posix.ftp
+echo bye >>posix.ftp
+
+echo Running ftp script 1 ...
+ftp -n -i -s:posix.ftp boost.cowic.de
+
+echo Creating ftp script 2 ...
+copy user.txt posix.ftp
+echo dir >>posix.ftp
+echo mdelete boost-posix*.bz2 >>posix.ftp
+echo rename posix.tar.bz2 boost-posix-%SNAPSHOT_DATE%.tar.bz2 >>posix.ftp
+
+echo dir >>posix.ftp
+echo bye >>posix.ftp
+
+echo Running ftp script 2 ...
+ftp -n -i -s:posix.ftp boost.cowic.de
+
+echo POSIX snapshot complete!
diff --git a/tools/release/snapshot_posix.sh b/tools/release/snapshot_posix.sh
new file mode 100755
index 0000000000..ccc625a999
--- /dev/null
+++ b/tools/release/snapshot_posix.sh
@@ -0,0 +1,65 @@
+#!/usr/bin/env bash
+
+# Build a branches/release snapshot for Posix, using LF line termination
+
+# © Copyright 2008 Beman Dawes
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+echo "Build a branches/release snapshot for POSIX, using LF line termination..."
+
+echo "Removing old files..."
+rm -r -f posix
+rm -r -f svn_info
+
+echo "Exporting files from subversion..."
+# leave an audit trail, which is used by inspect to determine revision number
+# use --non-recursive rather than --depth=files until the linux distros catch up
+svn co --non-recursive http://svn.boost.org/svn/boost/branches/release svn_info
+svn export --non-interactive --native-eol LF http://svn.boost.org/svn/boost/branches/release posix
+
+#echo "Building bjam..."
+# failure to use an up-to-date copy of bjam has caused much wasted effort.
+#pushd posix/tools/build/v2/engine
+#./build.sh gcc
+#popd
+#
+#echo "Building docs..."
+#pushd posix/doc
+#../tools/build/v2/engine/bin.cygwinx86/bjam --toolset=gcc &>../../posix-bjam.log
+#popd
+
+echo "Cleaning up and renaming..."
+#rm -r posix/bin.v2
+SNAPSHOT_DATE=`eval date +%Y-%m-%d`
+echo SNAPSHOT_DATE is $SNAPSHOT_DATE
+mv posix boost-posix-$SNAPSHOT_DATE
+rm -f posix.tar.gz
+rm -f posix.tar.bz2
+
+echo "Building .gz file..."
+tar cfz posix.tar.gz boost-posix-$SNAPSHOT_DATE
+echo "Building .bz2 file..."
+gunzip -c posix.tar.gz | bzip2 >posix.tar.bz2
+mv boost-posix-$SNAPSHOT_DATE posix
+
+echo "Creating ftp script..."
+echo "dir" >posix.ftp
+echo "binary" >>posix.ftp
+
+#echo "put posix.tar.gz" >>posix.ftp
+#echo "mdelete boost-posix*.gz" >>posix.ftp
+#echo "rename posix.tar.gz boost-posix-$SNAPSHOT_DATE.tar.gz" >>posix.ftp
+
+echo "put posix.tar.bz2" >>posix.ftp
+echo "mdelete boost-posix*.bz2" >>posix.ftp
+echo "rename posix.tar.bz2 boost-posix-$SNAPSHOT_DATE.tar.bz2" >>posix.ftp
+
+echo "dir" >>posix.ftp
+echo "bye" >>posix.ftp
+
+echo "Running ftp script..."
+# use cygwin ftp rather than Windows ftp
+/usr/bin/ftp -v -i boost.cowic.de <posix.ftp
+
+echo POSIX snapshot complete!
diff --git a/tools/release/snapshot_windows.bat b/tools/release/snapshot_windows.bat
new file mode 100644
index 0000000000..af31d62610
--- /dev/null
+++ b/tools/release/snapshot_windows.bat
@@ -0,0 +1,75 @@
+rem Build a branches/release snapshot for Windows, using CRLF line termination
+
+rem Copyright 2008 Beman Dawes
+
+rem Distributed under the Boost Software License, Version 1.0.
+rem See http://www.boost.org/LICENSE_1_0.txt
+
+echo Build a branches/release snapshot for Windows, using CRLF line termination...
+echo Revision %BOOST_REVISION_NUMBER%
+
+echo Removing old files...
+rmdir /s /q windows >nul
+rmdir /s /q svn_info >nul
+del windows.7z >nul
+del windows.zip >nul
+
+echo Exporting files from subversion...
+svn export --non-interactive --native-eol CRLF -r %BOOST_REVISION_NUMBER% http://svn.boost.org/svn/boost/branches/release windows
+
+echo Copying docs into windows...
+pushd windows
+xcopy /s /y ..\docs_temp
+popd
+
+echo Setting SNAPSHOT_DATE
+strftime "%%Y-%%m-%%d" >date.txt
+set /p SNAPSHOT_DATE= <date.txt
+echo SNAPSHOT_DATE is %SNAPSHOT_DATE%
+
+echo Renaming root directory...
+ren windows boost-windows-%SNAPSHOT_DATE%
+
+echo Building .7z file...
+rem On Windows, 7z comes from the 7-Zip package, not Cygwin,
+rem so path must include C:\Program Files\7-Zip
+7z a -r windows.7z boost-windows-%SNAPSHOT_DATE%
+
+rem Building .zip file...
+rem zip -r windows.zip boost-windows-%SNAPSHOT_DATE%
+
+ren boost-windows-%SNAPSHOT_DATE% windows
+
+echo The ftp transfer will be done in two steps because that has proved more
+echo reliable on Beman's Windows XP 64-bit system.
+
+echo Creating ftp script 1 ...
+rem user.txt must be a single line: user userid password
+rem where "userid" and "password" are replace with the appropriate values
+copy user.txt windows.ftp
+echo dir >>windows.ftp
+echo binary >>windows.ftp
+
+rem echo put windows.zip >>windows.ftp
+rem echo mdelete boost-windows*.zip >>windows.ftp
+rem echo rename windows.zip boost-windows-%SNAPSHOT_DATE%.zip >>windows.ftp
+
+echo put windows.7z >>windows.ftp
+echo bye >>windows.ftp
+
+echo Running ftp script 1 ...
+ftp -n -i -s:windows.ftp boost.cowic.de
+
+echo Creating ftp script 2 ...
+copy user.txt windows.ftp
+echo dir >>windows.ftp
+echo mdelete boost-windows*.7z >>windows.ftp
+echo rename windows.7z boost-windows-%SNAPSHOT_DATE%.7z >>windows.ftp
+
+echo dir >>windows.ftp
+echo bye >>windows.ftp
+
+echo Running ftp script 2 ...
+ftp -n -i -s:windows.ftp boost.cowic.de
+
+echo Windows snapshot complete!
diff --git a/tools/release/snapshot_windows.sh b/tools/release/snapshot_windows.sh
new file mode 100755
index 0000000000..14de67f147
--- /dev/null
+++ b/tools/release/snapshot_windows.sh
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+
+# Build a branches/release snapshot for Windows, using CRLF line termination
+
+# © Copyright 2008 Beman Dawes
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+# This script uses ftp, and thus assumes ~/.netrc contains a machine ... entry
+
+echo "Build a branches/release snapshot for Windows, using CRLF line termination..."
+
+echo "Removing old files..."
+rm -r -f windows
+
+echo "Exporting files from subversion..."
+svn export --non-interactive --native-eol CRLF http://svn.boost.org/svn/boost/branches/release windows
+
+#echo "Copying docs from posix tree..."
+#cp --recursive posix/doc/html windows/doc
+
+echo "Renaming..."
+SNAPSHOT_DATE=`eval date +%Y-%m-%d`
+echo SNAPSHOT_DATE is $SNAPSHOT_DATE
+mv windows boost-windows-$SNAPSHOT_DATE
+
+#rm -f windows.zip
+#zip -r windows.zip boost-windows-$SNAPSHOT_DATE
+
+echo "Building .7z..."
+rm -f windows.7z
+# On Windows, 7z comes from the 7-Zip package, not Cygwin,
+# so path must include C:\Program Files\7-Zip.
+7z a -r windows.7z boost-windows-$SNAPSHOT_DATE
+
+echo "Reverting name..."
+mv boost-windows-$SNAPSHOT_DATE windows
+
+echo "Creating ftp script..."
+cat <user.txt >>windows.ftp
+echo "dir" >>windows.ftp
+echo "binary" >>windows.ftp
+
+#echo "put windows.zip" >>windows.ftp
+#echo "mdelete boost-windows*.zip" >>windows.ftp
+#echo "rename windows.zip boost-windows-$SNAPSHOT_DATE.zip" >>windows.ftp
+
+echo "put windows.7z" >>windows.ftp
+echo "mdelete boost-windows*.7z" >>windows.ftp
+echo "rename windows.7z boost-windows-$SNAPSHOT_DATE.7z" >>windows.ftp
+echo "dir" >>windows.ftp
+echo "bye" >>windows.ftp
+
+echo "Running ftp script..."
+# This is the Windows ftp client
+ftp -n -i -d -s:windows.ftp boost.cowic.de
+
+echo "Windows snapshot complete!"
diff --git a/tools/release/strftime.cpp b/tools/release/strftime.cpp
new file mode 100644
index 0000000000..57d66099ae
--- /dev/null
+++ b/tools/release/strftime.cpp
@@ -0,0 +1,68 @@
+// Command line utility to output the date under control of a format string
+
+// Copyright 2008 Beman Dawes
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <ctime>
+#include <string>
+#include <iostream>
+#include <cstdlib>
+
+using namespace std;
+
+int main(int argc, char * argv[])
+{
+ if (argc != 2 )
+ {
+ cerr <<
+ "Invoke: strftime format\n"
+ "Example: strftime \"The date is %Y-%m-%d in ISO format\""
+ "The format codes are:\n"
+ " %a Abbreviated weekday name\n"
+ " %A Full weekday name\n"
+ " %b Abbreviated month name\n"
+ " %B Full month name\n"
+ " %c Date and time representation appropriate for locale\n"
+ " %d Day of month as decimal number (01 - 31)\n"
+ " %H Hour in 24-hour format (00 - 23)\n"
+ " %I Hour in 12-hour format (01 - 12)\n"
+ " %j Day of year as decimal number (001 - 366)\n"
+ " %m Month as decimal number (01 - 12)\n"
+ " %M Minute as decimal number (00 - 59)\n"
+ " %p Current locale's A.M./P.M. indicator for 12-hour clock\n"
+ " %S Second as decimal number (00 - 59)\n"
+ " %U Week of year as decimal number, with Sunday as first day of week (00 - 53)\n"
+ " %w Weekday as decimal number (0 - 6; Sunday is 0)\n"
+ " %W Week of year as decimal number, with Monday as first day of week (00 - 53)\n"
+ " %x Date representation for current locale\n"
+ " %X Time representation for current locale\n"
+ " %y Year without century, as decimal number (00 - 99)\n"
+ " %Y Year with century, as decimal number\n"
+ " %z, %Z Either the time-zone name or time zone abbreviation, depending on registry settings; no characters if time zone is unknown\n"
+ " %% Percent sign\n"
+ ;
+ return 1;
+ }
+
+ string format = argv[1];
+ time_t t = time(0);
+ tm * tod = localtime(&t);
+ if (!tod)
+ {
+ cerr << "error: localtime function failed\n";
+ return 1;
+ }
+ char* s = new char [format.size() + 256];
+ if (strftime( s, format.size() + 256, format.c_str(), tod ) == 0 )
+ {
+ cerr << "error: buffer overflow\n";
+ return 1;
+ }
+
+ cout << s;
+ return 0;
+}
diff --git a/tools/release/unmerged.bat b/tools/release/unmerged.bat
new file mode 100644
index 0000000000..9a3581b8ab
--- /dev/null
+++ b/tools/release/unmerged.bat
@@ -0,0 +1,17 @@
+@echo off
+rem Copyright Beman Dawes 2009
+rem Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt
+if not %1$==$ goto usage_ok
+echo Usage: unmerged library-name [svn-options]
+echo Options include --summarize to show paths only. i.e. suppresses line-by-line diffs
+goto done
+
+:usage_ok
+svn diff %2 %3 %4 %5 %6 http://svn.boost.org/svn/boost/branches/release/boost/%1.hpp ^
+ http://svn.boost.org/svn/boost/trunk/boost/%1.hpp
+svn diff %2 %3 %4 %5 %6 http://svn.boost.org/svn/boost/branches/release/boost/%1 ^
+ http://svn.boost.org/svn/boost/trunk/boost/%1
+svn diff %2 %3 %4 %5 %6 http://svn.boost.org/svn/boost/branches/release/libs/%1 ^
+ http://svn.boost.org/svn/boost/trunk/libs/%1
+
+:done
diff --git a/tools/release/unmerged_all.bat b/tools/release/unmerged_all.bat
new file mode 100644
index 0000000000..6bb19dd9f1
--- /dev/null
+++ b/tools/release/unmerged_all.bat
@@ -0,0 +1,86 @@
+rem Copyright Beman Dawes 2009
+rem Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt
+call unmerged accumulators --summarize
+call unmerged algorithm --summarize
+call unmerged any --summarize
+call unmerged array --summarize
+call unmerged asio --summarize
+call unmerged assign --summarize
+call unmerged bimap --summarize
+call unmerged bind --summarize
+call unmerged circular_buffer --summarize
+call unmerged compatibility --summarize
+call unmerged compose --summarize
+call unmerged concept --summarize
+call unmerged concept_check --summarize
+call unmerged config --summarize
+call unmerged conversion --summarize
+call unmerged crc --summarize
+call unmerged date_time --summarize
+call unmerged detail --summarize
+call unmerged disjoint_sets --summarize
+call unmerged dynamic_bitset --summarize
+call unmerged exception --summarize
+call unmerged filesystem --summarize
+call unmerged flyweight --summarize
+call unmerged foreach --summarize
+call unmerged format --summarize
+call unmerged function --summarize
+call unmerged functional --summarize
+call unmerged function_types --summarize
+call unmerged fusion --summarize
+call unmerged gil --summarize
+call unmerged graph --summarize
+call unmerged graph_parallel --summarize
+call unmerged integer --summarize
+call unmerged interprocess --summarize
+call unmerged intrusive --summarize
+call unmerged io --summarize
+call unmerged iostreams --summarize
+call unmerged iterator --summarize
+call unmerged lambda --summarize
+call unmerged logic --summarize
+call unmerged math --summarize
+call unmerged mem_fn --summarize
+call unmerged mpi --summarize
+call unmerged mpl --summarize
+call unmerged multi_array --summarize
+call unmerged multi_index --summarize
+call unmerged numeric --summarize
+call unmerged optional --summarize
+call unmerged parameter --summarize
+call unmerged pool --summarize
+call unmerged preprocessor --summarize
+call unmerged program_options --summarize
+call unmerged property_map --summarize
+call unmerged property_tree --summarize
+call unmerged proto --summarize
+call unmerged ptr_container --summarize
+call unmerged python --summarize
+call unmerged random --summarize
+call unmerged range --summarize
+call unmerged rational --summarize
+call unmerged regex --summarize
+call unmerged scope_exit --summarize
+call unmerged serialization --summarize
+call unmerged signals --summarize
+call unmerged signals2 --summarize
+call unmerged smart_ptr --summarize
+call unmerged spirit --summarize
+call unmerged statechart --summarize
+call unmerged static_assert --summarize
+call unmerged system --summarize
+call unmerged test --summarize
+call unmerged thread --summarize
+call unmerged timer --summarize
+call unmerged tokenizer --summarize
+call unmerged tr1 --summarize
+call unmerged tuple --summarize
+call unmerged typeof --summarize
+call unmerged type_traits --summarize
+call unmerged units --summarize
+call unmerged unordered --summarize
+call unmerged utility --summarize
+call unmerged variant --summarize
+call unmerged wave --summarize
+call unmerged xpressive --summarize
diff --git a/tools/release/unmerged_whatever.bat b/tools/release/unmerged_whatever.bat
new file mode 100644
index 0000000000..d49e468b2e
--- /dev/null
+++ b/tools/release/unmerged_whatever.bat
@@ -0,0 +1,13 @@
+@echo off
+rem Copyright Beman Dawes 2011
+rem Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt
+if not %1$==$ goto usage_ok
+echo Usage: unmerged_whatever path-from-root [svn-options]
+echo Options include --summarize to show paths only. i.e. suppresses line-by-line diffs
+goto done
+
+:usage_ok
+svn diff %2 %3 %4 %5 %6 http://svn.boost.org/svn/boost/branches/release/%1 ^
+ http://svn.boost.org/svn/boost/trunk/%1
+
+:done
diff --git a/tools/release/upload2sourceforge.bat b/tools/release/upload2sourceforge.bat
new file mode 100644
index 0000000000..f16a2e809b
--- /dev/null
+++ b/tools/release/upload2sourceforge.bat
@@ -0,0 +1,13 @@
+rem Copyright Beman Dawes 2009
+rem Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt
+if not %1$==$ goto usage_ok
+echo Usage: upload2sourceforge release-folder
+echo Example: upload2sourceforge 1.40.0
+goto done
+
+:usage_ok
+dir boost_*
+pause Are these the correct files to upload? [Ctrl-C to interrupt]
+rsync -avP -e ssh boost_* beman_dawes,boost@frs.sourceforge.net:/home/frs/project/b/bo/boost/boost/%1/
+
+:done
diff --git a/tools/wave/build/Jamfile.v2 b/tools/wave/build/Jamfile.v2
new file mode 100644
index 0000000000..3e839eeaed
--- /dev/null
+++ b/tools/wave/build/Jamfile.v2
@@ -0,0 +1,69 @@
+# Wave: A Standard compliant C++ preprocessor
+#
+# Boost Wave Library Build Jamfile
+#
+# http://www.boost.org/
+#
+# Copyright (c) 2001-2010 Hartmut Kaiser. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying file
+# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# Make sure all of Wave is compiled with threading disabled. We still need
+# to link with Boost.Thread, but no multi-threaded features are being used
+# in the Wave tool anyway.
+
+import feature ;
+
+feature.feature wavetool
+ : on
+ : optional composite propagated
+ ;
+
+feature.compose <wavetool>on
+ : <define>BOOST_WAVE_SUPPORT_THREADING=0
+ ;
+
+###############################################################################
+project
+ : requirements
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ ;
+
+exe wave
+ :
+ ../cpp.cpp
+ /boost//wave
+ /boost//program_options
+ /boost//filesystem
+ /boost//serialization
+ /boost//system
+ /boost//thread
+ /boost//date_time
+ :
+ <threading>multi
+# <debug-symbols>on
+ <wavetool>on
+ :
+ release
+ ;
+
+install dist-bin
+ :
+ wave
+ :
+ <install-type>EXE
+ <location>../../../dist/bin
+ :
+ release
+ ;
+
+install dist-lib
+ :
+ wave
+ :
+ <install-type>LIB
+ <location>../../../dist/lib
+ :
+ release
+ ;
diff --git a/tools/wave/cpp.cpp b/tools/wave/cpp.cpp
new file mode 100644
index 0000000000..91270dcf49
--- /dev/null
+++ b/tools/wave/cpp.cpp
@@ -0,0 +1,1436 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+
+ http://www.boost.org/
+
+ Copyright (c) 2001-2011 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#define BOOST_WAVE_SERIALIZATION 0 // enable serialization
+#define BOOST_WAVE_BINARY_SERIALIZATION 0 // use binary archives
+#define BOOST_WAVE_XML_SERIALIZATION 1 // use XML archives
+
+#include "cpp.hpp" // global configuration
+
+///////////////////////////////////////////////////////////////////////////////
+// Include additional Boost libraries
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/convenience.hpp>
+#include <boost/timer.hpp>
+#include <boost/any.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// Include Wave itself
+#include <boost/wave.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// Include the lexer related stuff
+#include <boost/wave/cpplexer/cpp_lex_token.hpp> // token type
+#include <boost/wave/cpplexer/cpp_lex_iterator.hpp> // lexer type
+
+///////////////////////////////////////////////////////////////////////////////
+// Include serialization support, if requested
+#if BOOST_WAVE_SERIALIZATION != 0
+#include <boost/serialization/serialization.hpp>
+#if BOOST_WAVE_BINARY_SERIALIZATION != 0
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/archive/binary_oarchive.hpp>
+typedef boost::archive::binary_iarchive iarchive;
+typedef boost::archive::binary_oarchive oarchive;
+#elif BOOST_WAVE_XML_SERIALIZATION != 0
+#include <boost/archive/xml_iarchive.hpp>
+#include <boost/archive/xml_oarchive.hpp>
+typedef boost::archive::xml_iarchive iarchive;
+typedef boost::archive::xml_oarchive oarchive;
+#else
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/archive/text_oarchive.hpp>
+typedef boost::archive::text_iarchive iarchive;
+typedef boost::archive::text_oarchive oarchive;
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Include the context policies to use
+#include "trace_macro_expansion.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Include lexer specifics, import lexer names
+#if BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION == 0
+#include <boost/wave/cpplexer/re2clex/cpp_re2c_lexer.hpp>
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Include the grammar definitions, if these shouldn't be compiled separately
+// (ATTENTION: _very_ large compilation times!)
+#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION == 0
+#include <boost/wave/grammars/cpp_intlit_grammar.hpp>
+#include <boost/wave/grammars/cpp_chlit_grammar.hpp>
+#include <boost/wave/grammars/cpp_grammar.hpp>
+#include <boost/wave/grammars/cpp_expression_grammar.hpp>
+#include <boost/wave/grammars/cpp_predef_macros_grammar.hpp>
+#include <boost/wave/grammars/cpp_defined_grammar.hpp>
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Import required names
+using namespace boost::spirit::classic;
+
+using std::pair;
+using std::vector;
+using std::getline;
+using std::ifstream;
+using std::ofstream;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::ostream;
+using std::istreambuf_iterator;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// This application uses the lex_iterator and lex_token types predefined
+// with the Wave library, but it is possible to use your own types.
+//
+// You may want to have a look at the other samples to see how this is
+// possible to achieve.
+ typedef boost::wave::cpplexer::lex_token<> token_type;
+ typedef boost::wave::cpplexer::lex_iterator<token_type>
+ lex_iterator_type;
+
+// The C++ preprocessor iterators shouldn't be constructed directly. They
+// are to be generated through a boost::wave::context<> object. This
+// boost::wave::context object is additionally to be used to initialize and
+// define different parameters of the actual preprocessing.
+ typedef boost::wave::context<
+ std::string::iterator, lex_iterator_type,
+ boost::wave::iteration_context_policies::load_file_to_string,
+ trace_macro_expansion<token_type> >
+ context_type;
+
+///////////////////////////////////////////////////////////////////////////////
+// print the current version
+std::string get_version()
+{
+ std::string version (context_type::get_version_string());
+ version = version.substr(1, version.size()-2); // strip quotes
+ version += std::string(" (" CPP_VERSION_DATE_STR ")"); // add date
+ return version;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// print the current version for interactive sessions
+int print_interactive_version()
+{
+ cout << "Wave: A Standard conformant C++ preprocessor based on the Boost.Wave library" << endl;
+ cout << "Version: " << get_version() << endl;
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// print the copyright statement
+int print_copyright()
+{
+ char const *copyright[] = {
+ "",
+ "Wave: A Standard conformant C++ preprocessor based on the Boost.Wave library",
+ "http://www.boost.org/",
+ "",
+ "Copyright (c) 2001-2011 Hartmut Kaiser, Distributed under the Boost",
+ "Software License, Version 1.0. (See accompanying file",
+ "LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)",
+ 0
+ };
+
+ for (int i = 0; 0 != copyright[i]; ++i)
+ cout << copyright[i] << endl;
+
+ return 0; // exit app
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// forward declarations only
+namespace cmd_line_utils
+{
+ class include_paths;
+}
+
+namespace boost { namespace program_options {
+
+ void validate(boost::any &v, std::vector<std::string> const &s,
+ cmd_line_utils::include_paths *, long);
+
+}} // boost::program_options
+
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/program_options.hpp>
+
+namespace po = boost::program_options;
+namespace fs = boost::filesystem;
+
+///////////////////////////////////////////////////////////////////////////////
+namespace cmd_line_utils {
+
+ // Additional command line parser which interprets '@something' as an
+ // option "config-file" with the value "something".
+ inline pair<std::string, std::string>
+ at_option_parser(std::string const&s)
+ {
+ if ('@' == s[0])
+ return std::make_pair(std::string("config-file"), s.substr(1));
+ else
+ return pair<std::string, std::string>();
+ }
+
+ // class, which keeps include file information read from the command line
+ class include_paths {
+ public:
+ include_paths() : seen_separator(false) {}
+
+ vector<std::string> paths; // stores user paths
+ vector<std::string> syspaths; // stores system paths
+ bool seen_separator; // command line contains a '-I-' option
+
+ // Function which validates additional tokens from command line.
+ static void
+ validate(boost::any &v, vector<std::string> const &tokens)
+ {
+ if (v.empty())
+ v = boost::any(include_paths());
+
+ include_paths *p = boost::any_cast<include_paths>(&v);
+
+ BOOST_ASSERT(p);
+ // Assume only one path per '-I' occurrence.
+ std::string const& t = po::validators::get_single_string(tokens);
+ if (t == "-") {
+ // found -I- option, so switch behaviour
+ p->seen_separator = true;
+ }
+ else if (p->seen_separator) {
+ // store this path as a system path
+ p->syspaths.push_back(t);
+ }
+ else {
+ // store this path as an user path
+ p->paths.push_back(t);
+ }
+ }
+ };
+
+ // Read all options from a given config file, parse and add them to the
+ // given variables_map
+ bool read_config_file_options(std::string const &filename,
+ po::options_description const &desc, po::variables_map &vm,
+ bool may_fail = false)
+ {
+ ifstream ifs(filename.c_str());
+
+ if (!ifs.is_open()) {
+ if (!may_fail) {
+ cerr << filename
+ << ": command line warning: config file not found"
+ << endl;
+ }
+ return false;
+ }
+
+ vector<std::string> options;
+ std::string line;
+
+ while (std::getline(ifs, line)) {
+ // skip empty lines
+ std::string::size_type pos = line.find_first_not_of(" \t");
+ if (pos == std::string::npos)
+ continue;
+
+ // skip comment lines
+ if ('#' != line[pos]) {
+ // strip leading and trailing whitespace
+ std::string::size_type endpos = line.find_last_not_of(" \t");
+ BOOST_ASSERT(endpos != std::string::npos);
+ options.push_back(line.substr(pos, endpos-pos+1));
+ }
+ }
+
+ if (options.size() > 0) {
+ using namespace boost::program_options::command_line_style;
+ po::store(po::command_line_parser(options)
+ .options(desc).style(unix_style).run(), vm);
+ po::notify(vm);
+ }
+ return true;
+ }
+
+ // predicate to extract all positional arguments from the command line
+ struct is_argument {
+ bool operator()(po::option const &opt)
+ {
+ return (opt.position_key == -1) ? true : false;
+ }
+ };
+
+ // trim quotes from path names, if any
+ std::string trim_quotes(std::string const& file)
+ {
+ if (('"' == file[0] || '\'' == file[0]) && file[0] == file[file.size()-1])
+ {
+ return file.substr(1, file.size()-2);
+ }
+ return file;
+ }
+
+///////////////////////////////////////////////////////////////////////////////
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Special validator overload, which allows to handle the -I- syntax for
+// switching the semantics of an -I option.
+//
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace program_options {
+
+ void validate(boost::any &v, std::vector<std::string> const &s,
+ cmd_line_utils::include_paths *, long)
+ {
+ cmd_line_utils::include_paths::validate(v, s);
+ }
+
+}} // namespace boost::program_options
+
+///////////////////////////////////////////////////////////////////////////////
+namespace {
+
+ class auto_stop_watch : public stop_watch
+ {
+ public:
+ auto_stop_watch(std::ostream &outstrm_)
+ : print_time(false), outstrm(outstrm_)
+ {
+ }
+
+ ~auto_stop_watch()
+ {
+ if (print_time) {
+ outstrm << "Elapsed time: "
+ << this->format_elapsed_time()
+ << std::endl;
+ }
+ }
+
+ void set_print_time(bool print_time_)
+ {
+ print_time = print_time_;
+ }
+
+ private:
+ bool print_time;
+ std::ostream &outstrm;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ inline std::string
+ report_iostate_error(std::ios::iostate state)
+ {
+ BOOST_ASSERT(state & (std::ios::badbit | std::ios::failbit | std::ios::eofbit));
+ std::string result;
+ if (state & std::ios::badbit) {
+ result += " the reported problem was: "
+ "loss of integrity of the stream buffer\n";
+ }
+ if (state & std::ios::failbit) {
+ result += " the reported problem was: "
+ "an operation was not processed correctly\n";
+ }
+ if (state & std::ios::eofbit) {
+ result += " the reported problem was: "
+ "end-of-file while writing to the stream\n";
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Retrieve the position of a macro definition
+ template <typename Context>
+ inline bool
+ get_macro_position(Context &ctx,
+ typename Context::token_type::string_type const& name,
+ typename Context::position_type &pos)
+ {
+ bool has_parameters = false;
+ bool is_predefined = false;
+ std::vector<typename Context::token_type> parameters;
+ typename Context::token_sequence_type definition;
+
+ return ctx.get_macro_definition(name, has_parameters, is_predefined,
+ pos, parameters, definition);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Generate some meaningful error messages
+ template <typename Exception>
+ inline int
+ report_error_message(Exception const &e)
+ {
+ // default error reporting
+ cerr
+ << e.file_name() << ":" << e.line_no() << ":" << e.column_no()
+ << ": " << e.description() << endl;
+
+ // errors count as one
+ return (e.get_severity() == boost::wave::util::severity_error ||
+ e.get_severity() == boost::wave::util::severity_fatal) ? 1 : 0;
+ }
+
+ template <typename Context>
+ inline int
+ report_error_message(Context &ctx, boost::wave::cpp_exception const &e)
+ {
+ // default error reporting
+ int result = report_error_message(e);
+
+ using boost::wave::preprocess_exception;
+ switch(e.get_errorcode()) {
+ case preprocess_exception::macro_redefinition:
+ {
+ // report the point of the initial macro definition
+ typename Context::position_type pos;
+ if (get_macro_position(ctx, e.get_related_name(), pos)) {
+ cerr
+ << pos << ": "
+ << preprocess_exception::severity_text(e.get_severity())
+ << ": this is the location of the previous definition."
+ << endl;
+ }
+ else {
+ cerr
+ << e.file_name() << ":" << e.line_no() << ":"
+ << e.column_no() << ": "
+ << preprocess_exception::severity_text(e.get_severity())
+ << ": not able to retrieve the location of the previous "
+ << "definition." << endl;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Read one logical line of text
+ inline bool
+ read_a_line (std::istream &instream, std::string &instring)
+ {
+ bool eol = true;
+ do {
+ std::string line;
+ std::getline(instream, line);
+ if (instream.rdstate() & std::ios::failbit)
+ return false; // nothing to do
+
+ eol = true;
+ if (line.find_last_of('\\') == line.size()-1)
+ eol = false;
+
+ instring += line + '\n';
+ } while (!eol);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Load and save the internal tables of the wave::context object
+ template <typename Context>
+ inline void
+ load_state(po::variables_map const &vm, Context &ctx)
+ {
+#if BOOST_WAVE_SERIALIZATION != 0
+ try {
+ if (vm.count("state") > 0) {
+ fs::path state_file (
+ boost::wave::util::create_path(vm["state"].as<std::string>()));
+ if (state_file == "-")
+ state_file = boost::wave::util::create_path("wave.state");
+
+ std::ios::openmode mode = std::ios::in;
+
+#if BOOST_WAVE_BINARY_SERIALIZATION != 0
+ mode = (std::ios::openmode)(mode | std::ios::binary);
+#endif
+ ifstream ifs (state_file.string().c_str(), mode);
+ if (ifs.is_open()) {
+ using namespace boost::serialization;
+ iarchive ia(ifs);
+ std::string version;
+
+ ia >> make_nvp("version", version); // load version
+ if (version == CPP_VERSION_FULL_STR)
+ ia >> make_nvp("state", ctx); // load the internal tables from disc
+ else {
+ cerr << "wave: detected version mismatch while loading state, state was not loaded." << endl;
+ cerr << " loaded version: " << version << endl;
+ cerr << " expected version: " << CPP_VERSION_FULL_STR << endl;
+ }
+ }
+ }
+ }
+ catch (boost::archive::archive_exception const& e) {
+ cerr << "wave: error while loading state: "
+ << e.what() << endl;
+ }
+ catch (boost::wave::preprocess_exception const& e) {
+ cerr << "wave: error while loading state: "
+ << e.description() << endl;
+ }
+#endif
+ }
+
+ template <typename Context>
+ inline void
+ save_state(po::variables_map const &vm, Context const &ctx)
+ {
+#if BOOST_WAVE_SERIALIZATION != 0
+ try {
+ if (vm.count("state") > 0) {
+ fs::path state_file (boost::wave::util::create_path(
+ vm["state"].as<std::string>()));
+ if (state_file == "-")
+ state_file = boost::wave::util::create_path("wave.state");
+
+ std::ios::openmode mode = std::ios::out;
+
+#if BOOST_WAVE_BINARY_SERIALIZATION != 0
+ mode = (std::ios::openmode)(mode | std::ios::binary);
+#endif
+ ofstream ofs(state_file.string().c_str(), mode);
+ if (!ofs.is_open()) {
+ cerr << "wave: could not open state file for writing: "
+ << state_file.string() << endl;
+ // this is non-fatal
+ }
+ else {
+ using namespace boost::serialization;
+ oarchive oa(ofs);
+ std::string version(CPP_VERSION_FULL_STR);
+ oa << make_nvp("version", version); // write version
+ oa << make_nvp("state", ctx); // write the internal tables to disc
+ }
+ }
+ }
+ catch (boost::archive::archive_exception const& e) {
+ cerr << "wave: error while writing state: "
+ << e.what() << endl;
+ }
+#endif
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // list all defined macros
+ bool list_macro_names(context_type const& ctx, std::string filename)
+ {
+ // open file for macro names listing
+ std::ofstream macronames_out;
+ fs::path macronames_file (boost::wave::util::create_path(filename));
+
+ if (macronames_file != "-") {
+ macronames_file = boost::wave::util::complete_path(macronames_file);
+ fs::create_directories(boost::wave::util::branch_path(macronames_file));
+ macronames_out.open(macronames_file.string().c_str());
+ if (!macronames_out.is_open()) {
+ cerr << "wave: could not open file for macro name listing: "
+ << macronames_file.string() << endl;
+ return false;
+ }
+ }
+ else {
+ macronames_out.copyfmt(cout);
+ macronames_out.clear(cout.rdstate());
+ static_cast<std::basic_ios<char> &>(macronames_out).rdbuf(cout.rdbuf());
+ }
+
+ // simply list all defined macros and its definitions
+ typedef context_type::const_name_iterator name_iterator;
+ name_iterator end = ctx.macro_names_end();
+ for (name_iterator it = ctx.macro_names_begin(); it != end; ++it)
+ {
+ typedef std::vector<context_type::token_type> parameters_type;
+
+ bool has_pars = false;
+ bool predef = false;
+ context_type::position_type pos;
+ parameters_type pars;
+ context_type::token_sequence_type def;
+
+ if (ctx.get_macro_definition(*it, has_pars, predef, pos, pars, def))
+ {
+ macronames_out << (predef ? "-P" : "-D") << *it;
+ if (has_pars) {
+ // list the parameter names for function style macros
+ macronames_out << "(";
+ parameters_type::const_iterator pend = pars.end();
+ for (parameters_type::const_iterator pit = pars.begin();
+ pit != pend; /**/)
+ {
+ macronames_out << (*pit).get_value();
+ if (++pit != pend)
+ macronames_out << ", ";
+ }
+ macronames_out << ")";
+ }
+ macronames_out << "=";
+
+ // print the macro definition
+ context_type::token_sequence_type::const_iterator dend = def.end();
+ for (context_type::token_sequence_type::const_iterator dit = def.begin();
+ dit != dend; ++dit)
+ {
+ macronames_out << (*dit).get_value();
+ }
+
+ macronames_out << std::endl;
+ }
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // list macro invocation counts
+ bool list_macro_counts(context_type const& ctx, std::string filename)
+ {
+ // open file for macro invocation count listing
+ std::ofstream macrocounts_out;
+ fs::path macrocounts_file (boost::wave::util::create_path(filename));
+
+ if (macrocounts_file != "-") {
+ macrocounts_file = boost::wave::util::complete_path(macrocounts_file);
+ fs::create_directories(boost::wave::util::branch_path(macrocounts_file));
+ macrocounts_out.open(macrocounts_file.string().c_str());
+ if (!macrocounts_out.is_open()) {
+ cerr << "wave: could not open file for macro invocation count listing: "
+ << macrocounts_file.string() << endl;
+ return false;
+ }
+ }
+ else {
+ macrocounts_out.copyfmt(cout);
+ macrocounts_out.clear(cout.rdstate());
+ static_cast<std::basic_ios<char> &>(macrocounts_out).rdbuf(cout.rdbuf());
+ }
+
+ // list all expanded macro names and their counts in alphabetical order
+ std::map<std::string, std::size_t> const& counts =
+ ctx.get_hooks().get_macro_counts();
+
+ typedef std::map<std::string, std::size_t>::const_iterator iterator;
+ iterator end = counts.end();
+ for (iterator it = counts.begin(); it != end; ++it)
+ macrocounts_out << (*it).first << "," << (*it).second << std::endl;
+
+ return true;
+ }
+
+///////////////////////////////////////////////////////////////////////////////
+} // anonymous namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// do the actual preprocessing
+int
+do_actual_work (std::string file_name, std::istream &instream,
+ po::variables_map const &vm, bool input_is_stdin)
+{
+// current file position is saved for exception handling
+boost::wave::util::file_position_type current_position;
+auto_stop_watch elapsed_time(cerr);
+int error_count = 0;
+
+ try {
+ // process the given file
+ std::string instring;
+
+ instream.unsetf(std::ios::skipws);
+
+ if (!input_is_stdin) {
+#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
+ // this is known to be very slow for large files on some systems
+ copy (std::istream_iterator<char>(instream),
+ std::istream_iterator<char>(),
+ std::inserter(instring, instring.end()));
+#else
+ instring = std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
+ std::istreambuf_iterator<char>());
+#endif
+ }
+
+ // The preprocessing of the input stream is done on the fly behind the
+ // scenes during iteration over the context_type::iterator_type stream.
+ std::ofstream output;
+ std::ofstream traceout;
+ std::ofstream includelistout;
+ std::ofstream listguardsout;
+
+ trace_flags enable_trace = trace_nothing;
+
+ if (vm.count("traceto")) {
+ // try to open the file, where to put the trace output
+ fs::path trace_file (boost::wave::util::create_path(
+ vm["traceto"].as<std::string>()));
+
+ if (trace_file != "-") {
+ fs::create_directories(boost::wave::util::branch_path(trace_file));
+ traceout.open(trace_file.string().c_str());
+ if (!traceout.is_open()) {
+ cerr << "wave: could not open trace file: " << trace_file
+ << endl;
+ return -1;
+ }
+ }
+ enable_trace = trace_macros;
+ }
+ if ((enable_trace & trace_macros) && !traceout.is_open()) {
+ // by default trace to std::cerr
+ traceout.copyfmt(cerr);
+ traceout.clear(cerr.rdstate());
+ static_cast<std::basic_ios<char> &>(traceout).rdbuf(cerr.rdbuf());
+ }
+
+ // Open the stream where to output the list of included file names
+ if (vm.count("listincludes")) {
+ // try to open the file, where to put the include list
+ fs::path includes_file(boost::wave::util::create_path(
+ vm["listincludes"].as<std::string>()));
+
+ if (includes_file != "-") {
+ fs::create_directories(boost::wave::util::branch_path(includes_file));
+ includelistout.open(includes_file.string().c_str());
+ if (!includelistout.is_open()) {
+ cerr << "wave: could not open include list file: "
+ << includes_file.string() << endl;
+ return -1;
+ }
+ }
+ enable_trace = trace_flags(enable_trace | trace_includes);
+ }
+ if ((enable_trace & trace_includes) && !includelistout.is_open()) {
+ // by default list included names to std::cout
+ includelistout.copyfmt(cout);
+ includelistout.clear(cout.rdstate());
+ static_cast<std::basic_ios<char> &>(includelistout).
+ rdbuf(cout.rdbuf());
+ }
+
+ // Open the stream where to output the list of included file names
+ if (vm.count("listguards")) {
+ // try to open the file, where to put the include list
+ fs::path listguards_file(boost::wave::util::create_path(
+ vm["listguards"].as<std::string>()));
+
+ if (listguards_file != "-") {
+ fs::create_directories(boost::wave::util::branch_path(listguards_file));
+ listguardsout.open(listguards_file.string().c_str());
+ if (!listguardsout.is_open()) {
+ cerr << "wave: could not open include guard list file: "
+ << listguards_file.string() << endl;
+ return -1;
+ }
+ }
+ enable_trace = trace_flags(enable_trace | trace_guards);
+ }
+ if ((enable_trace & trace_guards) && !listguardsout.is_open()) {
+ // by default list included names to std::cout
+ listguardsout.copyfmt(cout);
+ listguardsout.clear(cout.rdstate());
+ static_cast<std::basic_ios<char> &>(listguardsout).
+ rdbuf(cout.rdbuf());
+ }
+
+ // enable preserving comments mode
+ bool preserve_comments = false;
+ bool preserve_whitespace = false;
+ bool preserve_bol_whitespace = false;
+
+ if (vm.count("preserve")) {
+ int preserve = vm["preserve"].as<int>();
+
+ switch(preserve) {
+ case 0: break; // preserve no whitespace
+ case 3: // preserve all whitespace
+ preserve_whitespace = true;
+ preserve_comments = true;
+ preserve_bol_whitespace = true;
+ break;
+
+ case 2: // preserve comments and BOL whitespace only
+ preserve_comments = true;
+ preserve_bol_whitespace = true;
+ break;
+
+ case 1: // preserve BOL whitespace only
+ preserve_bol_whitespace = true;
+ break;
+
+ default:
+ cerr << "wave: bogus preserve whitespace option value: "
+ << preserve << ", should be 0, 1, 2, or 3" << endl;
+ return -1;
+ }
+ }
+
+ // Since the #pragma wave system() directive may cause a potential security
+ // threat, it has to be enabled explicitly by --extended or -x
+ bool enable_system_command = false;
+
+ if (vm.count("extended"))
+ enable_system_command = true;
+
+ // This this the central piece of the Wave library, it provides you with
+ // the iterators to get the preprocessed tokens and allows to configure
+ // the preprocessing stage in advance.
+ bool allow_output = true; // will be manipulated from inside the hooks object
+ std::string default_outfile; // will be used from inside the hooks object
+ trace_macro_expansion<token_type> hooks(preserve_whitespace,
+ preserve_bol_whitespace, output, traceout, includelistout,
+ listguardsout, enable_trace, enable_system_command, allow_output,
+ default_outfile);
+
+ // enable macro invocation count, if appropriate
+ if (vm.count("macrocounts"))
+ hooks.enable_macro_counting();
+
+ context_type ctx (instring.begin(), instring.end(), file_name.c_str(), hooks);
+
+#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
+ // enable C99 mode, if appropriate (implies variadics)
+ if (vm.count("c99")) {
+#if BOOST_WAVE_SUPPORT_CPP0X != 0
+ if (vm.count("c++0x")) {
+ cerr << "wave: multiple language options specified: --c99 "
+ "and --c++0x" << endl;
+ return -1;
+ }
+#endif
+ ctx.set_language(
+ boost::wave::language_support(
+ boost::wave::support_c99
+ | boost::wave::support_option_convert_trigraphs
+ | boost::wave::support_option_emit_line_directives
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+ | boost::wave::support_option_include_guard_detection
+#endif
+#if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
+ | boost::wave::support_option_emit_pragma_directives
+#endif
+ | boost::wave::support_option_insert_whitespace
+ ));
+ }
+ else if (vm.count("variadics")) {
+ // enable variadics and placemarkers, if appropriate
+ ctx.set_language(boost::wave::enable_variadics(ctx.get_language()));
+ }
+#endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
+#if BOOST_WAVE_SUPPORT_CPP0X != 0
+ if (vm.count("c++0x")) {
+ if (vm.count("c99")) {
+ cerr << "wave: multiple language options specified: --c99 "
+ "and --c++0x" << endl;
+ return -1;
+ }
+ ctx.set_language(
+ boost::wave::language_support(
+ boost::wave::support_cpp0x
+ | boost::wave::support_option_convert_trigraphs
+ | boost::wave::support_option_long_long
+ | boost::wave::support_option_emit_line_directives
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+ | boost::wave::support_option_include_guard_detection
+#endif
+#if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
+ | boost::wave::support_option_emit_pragma_directives
+#endif
+ | boost::wave::support_option_insert_whitespace
+ ));
+ }
+#endif // BOOST_WAVE_SUPPORT_CPP0X != 0
+
+ // enable long long support, if appropriate
+ if (vm.count("long_long")) {
+ ctx.set_language(
+ boost::wave::enable_long_long(ctx.get_language()));
+ }
+
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+// disable include guard detection
+ if (vm.count("noguard")) {
+ ctx.set_language(
+ boost::wave::enable_include_guard_detection(
+ ctx.get_language(), false));
+ }
+#endif
+
+ // enable preserving comments mode
+ if (preserve_comments) {
+ ctx.set_language(
+ boost::wave::enable_preserve_comments(ctx.get_language()));
+ }
+
+ // control the generation of #line directives
+ if (vm.count("line")) {
+ int lineopt = vm["line"].as<int>();
+ if (0 != lineopt && 1 != lineopt && 2 != lineopt) {
+ cerr << "wave: bogus value for --line command line option: "
+ << lineopt << endl;
+ return -1;
+ }
+ ctx.set_language(
+ boost::wave::enable_emit_line_directives(ctx.get_language(),
+ lineopt != 0));
+
+ if (2 == lineopt)
+ ctx.get_hooks().enable_relative_names_in_line_directives(true);
+ }
+
+ // control whether whitespace should be inserted to disambiguate output
+ if (vm.count("disambiguate")) {
+ int disambiguateopt = vm["disambiguate"].as<int>();
+ if (0 != disambiguateopt && 1 != disambiguateopt) {
+ cerr << "wave: bogus value for --disambiguate command line option: "
+ << disambiguateopt << endl;
+ return -1;
+ }
+ ctx.set_language(
+ boost::wave::enable_insert_whitespace(ctx.get_language(),
+ disambiguateopt != 0));
+ }
+
+ // add include directories to the system include search paths
+ if (vm.count("sysinclude")) {
+ vector<std::string> syspaths = vm["sysinclude"].as<vector<std::string> >();
+
+ vector<std::string>::const_iterator end = syspaths.end();
+ for (vector<std::string>::const_iterator cit = syspaths.begin();
+ cit != end; ++cit)
+ {
+ ctx.add_sysinclude_path(cmd_line_utils::trim_quotes(*cit).c_str());
+ }
+ }
+
+ // add include directories to the include search paths
+ if (vm.count("include")) {
+ cmd_line_utils::include_paths const &ip =
+ vm["include"].as<cmd_line_utils::include_paths>();
+ vector<std::string>::const_iterator end = ip.paths.end();
+
+ for (vector<std::string>::const_iterator cit = ip.paths.begin();
+ cit != end; ++cit)
+ {
+ ctx.add_include_path(cmd_line_utils::trim_quotes(*cit).c_str());
+ }
+
+ // if -I- was given on the command line, this has to be propagated
+ if (ip.seen_separator)
+ ctx.set_sysinclude_delimiter();
+
+ // add system include directories to the include path
+ vector<std::string>::const_iterator sysend = ip.syspaths.end();
+ for (vector<std::string>::const_iterator syscit = ip.syspaths.begin();
+ syscit != sysend; ++syscit)
+ {
+ ctx.add_sysinclude_path(cmd_line_utils::trim_quotes(*syscit).c_str());
+ }
+ }
+
+ // add additional defined macros
+ if (vm.count("define")) {
+ vector<std::string> const &macros = vm["define"].as<vector<std::string> >();
+ vector<std::string>::const_iterator end = macros.end();
+ for (vector<std::string>::const_iterator cit = macros.begin();
+ cit != end; ++cit)
+ {
+ ctx.add_macro_definition(*cit);
+ }
+ }
+
+ // add additional predefined macros
+ if (vm.count("predefine")) {
+ vector<std::string> const &predefmacros =
+ vm["predefine"].as<vector<std::string> >();
+ vector<std::string>::const_iterator end = predefmacros.end();
+ for (vector<std::string>::const_iterator cit = predefmacros.begin();
+ cit != end; ++cit)
+ {
+ ctx.add_macro_definition(*cit, true);
+ }
+ }
+
+ // undefine specified macros
+ if (vm.count("undefine")) {
+ vector<std::string> const &undefmacros =
+ vm["undefine"].as<vector<std::string> >();
+ vector<std::string>::const_iterator end = undefmacros.end();
+ for (vector<std::string>::const_iterator cit = undefmacros.begin();
+ cit != end; ++cit)
+ {
+ ctx.remove_macro_definition(*cit, true);
+ }
+ }
+
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS == 0
+ // suppress expansion of specified macros
+ if (vm.count("noexpand")) {
+ vector<std::string> const &noexpandmacros =
+ vm["noexpand"].as<vector<std::string> >();
+ vector<std::string>::const_iterator end = noexpandmacros.end();
+ for (vector<std::string>::const_iterator cit = noexpandmacros.begin();
+ cit != end; ++cit)
+ {
+ ctx.get_hooks().add_noexpandmacro(*cit);
+ }
+ }
+#endif
+
+ // maximal include nesting depth
+ if (vm.count("nesting")) {
+ int max_depth = vm["nesting"].as<int>();
+ if (max_depth < 1 || max_depth > 100000) {
+ cerr << "wave: bogus maximal include nesting depth: "
+ << max_depth << endl;
+ return -1;
+ }
+ ctx.set_max_include_nesting_depth(max_depth);
+ }
+
+ // open the output file
+ if (vm.count("output")) {
+ // try to open the file, where to put the preprocessed output
+ fs::path out_file (boost::wave::util::create_path(
+ vm["output"].as<std::string>()));
+
+ if (out_file == "-") {
+ allow_output = false; // inhibit output initially
+ default_outfile = "-";
+ }
+ else {
+ out_file = boost::wave::util::complete_path(out_file);
+ fs::create_directories(boost::wave::util::branch_path(out_file));
+ output.open(out_file.string().c_str());
+ if (!output.is_open()) {
+ cerr << "wave: could not open output file: "
+ << out_file.string() << endl;
+ return -1;
+ }
+ default_outfile = out_file.string();
+ }
+ }
+ else if (!input_is_stdin && vm.count("autooutput")) {
+ // generate output in the file <input_base_name>.i
+ fs::path out_file (boost::wave::util::create_path(file_name));
+ std::string basename (boost::wave::util::leaf(out_file));
+ std::string::size_type pos = basename.find_last_of(".");
+
+ if (std::string::npos != pos)
+ basename = basename.substr(0, pos);
+ out_file = boost::wave::util::branch_path(out_file) / (basename + ".i");
+
+ fs::create_directories(boost::wave::util::branch_path(out_file));
+ output.open(out_file.string().c_str());
+ if (!output.is_open()) {
+ cerr << "wave: could not open output file: "
+ << out_file.string() << endl;
+ return -1;
+ }
+ default_outfile = out_file.string();
+ }
+
+ // we assume the session to be interactive if input is stdin and output is
+ // stdout and the output is not inhibited
+ bool is_interactive = input_is_stdin && !output.is_open() && allow_output;
+
+ if (is_interactive) {
+ // if interactive we don't warn for missing endif's etc.
+ ctx.set_language(
+ boost::wave::enable_single_line(ctx.get_language()), false);
+ }
+
+ // analyze the input file
+ context_type::iterator_type first = ctx.begin();
+ context_type::iterator_type last = ctx.end();
+
+ // preprocess the required include files
+ if (vm.count("forceinclude")) {
+ // add the filenames to force as include files in _reverse_ order
+ // the second parameter 'is_last' of the force_include function should
+ // be set to true for the last (first given) file.
+ vector<std::string> const &force =
+ vm["forceinclude"].as<vector<std::string> >();
+ vector<std::string>::const_reverse_iterator rend = force.rend();
+ for (vector<std::string>::const_reverse_iterator cit = force.rbegin();
+ cit != rend; /**/)
+ {
+ std::string filename(*cit);
+ first.force_include(filename.c_str(), ++cit == rend);
+ }
+ }
+
+ elapsed_time.set_print_time(!input_is_stdin && vm.count("timer") > 0);
+ if (is_interactive) {
+ print_interactive_version(); // print welcome message
+ load_state(vm, ctx); // load the internal tables from disc
+ }
+ else if (vm.count("state")) {
+ // the option "state" is usable in interactive mode only
+ cerr << "wave: ignoring the command line option 'state', "
+ << "use it in interactive mode only." << endl;
+ }
+
+ // >>>>>>>>>>>>> The actual preprocessing happens here. <<<<<<<<<<<<<<<<<<<
+ // loop over the input lines if reading from stdin, otherwise this loop
+ // will be executed once
+ do {
+ // loop over all generated tokens outputting the generated text
+ bool finished = false;
+
+ if (input_is_stdin) {
+ if (is_interactive)
+ cout << ">>> "; // prompt if is interactive
+
+ // read next line and continue
+ instring.clear();
+ if (!read_a_line(instream, instring))
+ break; // end of input reached
+ first = ctx.begin(instring.begin(), instring.end());
+ }
+
+ bool need_to_advanve = false;
+
+ do {
+ try {
+ if (need_to_advanve) {
+ ++first;
+ need_to_advanve = false;
+ }
+
+ while (first != last) {
+ // store the last known good token position
+ current_position = (*first).get_position();
+
+ // print out the current token value
+ if (allow_output) {
+ if (!output.good()) {
+ cerr << "wave: problem writing to the current "
+ << "output file" << endl;
+ cerr << report_iostate_error(output.rdstate());
+ break;
+ }
+ if (output.is_open())
+ output << (*first).get_value();
+ else
+ cout << (*first).get_value();
+ }
+
+ // advance to the next token
+ ++first;
+ }
+ finished = true;
+ }
+ catch (boost::wave::cpp_exception const &e) {
+ // some preprocessing error
+ if (is_interactive || boost::wave::is_recoverable(e)) {
+ error_count += report_error_message(ctx, e);
+ need_to_advanve = true; // advance to the next token
+ }
+ else {
+ throw; // re-throw for non-recoverable errors
+ }
+ }
+ catch (boost::wave::cpplexer::lexing_exception const &e) {
+ // some preprocessing error
+ if (is_interactive ||
+ boost::wave::cpplexer::is_recoverable(e))
+ {
+ error_count += report_error_message(e);
+ need_to_advanve = true; // advance to the next token
+ }
+ else {
+ throw; // re-throw for non-recoverable errors
+ }
+ }
+ } while (!finished);
+ } while (input_is_stdin);
+
+ if (is_interactive)
+ save_state(vm, ctx); // write the internal tables to disc
+
+ // list all defined macros at the end of the preprocessing
+ if (vm.count("macronames")) {
+ if (!list_macro_names(ctx, vm["macronames"].as<std::string>()))
+ return -1;
+ }
+ if (vm.count("macrocounts")) {
+ if (!list_macro_counts(ctx, vm["macrocounts"].as<std::string>()))
+ return -1;
+ }
+ }
+ catch (boost::wave::cpp_exception const &e) {
+ // some preprocessing error
+ report_error_message(e);
+ return 1;
+ }
+ catch (boost::wave::cpplexer::lexing_exception const &e) {
+ // some lexing error
+ report_error_message(e);
+ return 2;
+ }
+ catch (std::exception const &e) {
+ // use last recognized token to retrieve the error position
+ cerr
+ << current_position << ": "
+ << "exception caught: " << e.what()
+ << endl;
+ return 3;
+ }
+ catch (...) {
+ // use last recognized token to retrieve the error position
+ cerr
+ << current_position << ": "
+ << "unexpected exception caught." << endl;
+ return 4;
+ }
+ return -error_count; // returns the number of errors as a negative integer
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// main entry point
+int
+main (int argc, char *argv[])
+{
+ // test Wave compilation configuration
+ if (!BOOST_WAVE_TEST_CONFIGURATION()) {
+ cout << "wave: warning: the library this application was linked against was compiled "
+ << endl
+ << " using a different configuration (see wave_config.hpp)."
+ << endl;
+ }
+
+ // analyze the command line options and arguments
+ try {
+ // declare the options allowed on the command line only
+ po::options_description desc_cmdline ("Options allowed on the command line only");
+
+ desc_cmdline.add_options()
+ ("help,h", "print out program usage (this message)")
+ ("version,v", "print the version number")
+ ("copyright", "print out the copyright statement")
+ ("config-file", po::value<vector<std::string> >()->composing(),
+ "specify a config file (alternatively: @filepath)")
+ ;
+
+ // declare the options allowed on command line and in config files
+ po::options_description desc_generic ("Options allowed additionally in a config file");
+
+ desc_generic.add_options()
+ ("output,o", po::value<std::string>(),
+ "specify a file [arg] to use for output instead of stdout or "
+ "disable output [-]")
+ ("autooutput,E",
+ "output goes into a file named <input_basename>.i")
+ ("include,I", po::value<cmd_line_utils::include_paths>()->composing(),
+ "specify an additional include directory")
+ ("sysinclude,S", po::value<vector<std::string> >()->composing(),
+ "specify an additional system include directory")
+ ("forceinclude,F", po::value<vector<std::string> >()->composing(),
+ "force inclusion of the given file")
+ ("define,D", po::value<vector<std::string> >()->composing(),
+ "specify a macro to define (as macro[=[value]])")
+ ("predefine,P", po::value<vector<std::string> >()->composing(),
+ "specify a macro to predefine (as macro[=[value]])")
+ ("undefine,U", po::value<vector<std::string> >()->composing(),
+ "specify a macro to undefine")
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS == 0
+ ("noexpand,N", po::value<vector<std::string> >()->composing(),
+ "specify a macro name, which should not be expanded")
+#endif
+ ("nesting,n", po::value<int>(),
+ "specify a new maximal include nesting depth")
+ ;
+
+ po::options_description desc_ext ("Extended options (allowed everywhere)");
+
+ desc_ext.add_options()
+ ("traceto,t", po::value<std::string>(),
+ "output macro expansion tracing information to a file [arg] "
+ "or to stderr [-]")
+ ("timer", "output overall elapsed computing time to stderr")
+ ("long_long", "enable long long support in C++ mode")
+#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
+ ("variadics", "enable certain C99 extensions in C++ mode")
+ ("c99", "enable C99 mode (implies --variadics)")
+#endif
+#if BOOST_WAVE_SUPPORT_CPP0X != 0
+ ("c++0x", "enable C++0x mode (implies --variadics and --long_long)")
+#endif
+ ("listincludes,l", po::value<std::string>(),
+ "list names of included files to a file [arg] or to stdout [-]")
+ ("macronames,m", po::value<std::string>(),
+ "list all defined macros to a file [arg] or to stdout [-]")
+ ("macrocounts,c", po::value<std::string>(),
+ "list macro invocation counts to a file [arg] or to stdout [-]")
+ ("preserve,p", po::value<int>()->default_value(0),
+ "preserve whitespace\n"
+ "0: no whitespace is preserved (default),\n"
+ "1: begin of line whitespace is preserved,\n"
+ "2: comments and begin of line whitespace is preserved,\n"
+ "3: all whitespace is preserved")
+ ("line,L", po::value<int>()->default_value(1),
+ "control the generation of #line directives\n"
+ "0: no #line directives are generated,\n"
+ "1: #line directives will be emitted (default),\n"
+ "2: #line directives will be emitted using relative\n"
+ " filenames")
+ ("disambiguate", po::value<int>()->default_value(1),
+ "control whitespace insertion to disambiguate\n"
+ "consecutive tokens\n"
+ "0: no additional whitespace is generated,\n"
+ "1: whitespace is used to disambiguate output (default)")
+ ("extended,x", "enable the #pragma wave system() directive")
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+ ("noguard,G", "disable include guard detection")
+ ("listguards,g", po::value<std::string>(),
+ "list names of files flagged as 'include once' to a file [arg] "
+ "or to stdout [-]")
+#endif
+#if BOOST_WAVE_SERIALIZATION != 0
+ ("state,s", po::value<std::string>(),
+ "load and save state information from/to the given file [arg] "
+ "or 'wave.state' [-] (interactive mode only)")
+#endif
+ ;
+
+ // combine the options for the different usage schemes
+ po::options_description desc_overall_cmdline;
+ po::options_description desc_overall_cfgfile;
+
+ desc_overall_cmdline.add(desc_cmdline).add(desc_generic).add(desc_ext);
+ desc_overall_cfgfile.add(desc_generic).add(desc_ext);
+
+ // parse command line and store results
+ using namespace boost::program_options::command_line_style;
+
+ po::parsed_options opts(po::parse_command_line(argc, argv,
+ desc_overall_cmdline, unix_style, cmd_line_utils::at_option_parser));
+ po::variables_map vm;
+
+ po::store(opts, vm);
+ po::notify(vm);
+
+// // Try to find a wave.cfg in the same directory as the executable was
+// // started from. If this exists, treat it as a wave config file
+// fs::path filename(argv[0]);
+//
+// filename = filename.branch_path() / "wave.cfg";
+// cmd_line_utils::read_config_file_options(filename.string(),
+// desc_overall_cfgfile, vm, true);
+
+ // extract the arguments from the parsed command line
+ vector<po::option> arguments;
+
+ std::remove_copy_if(opts.options.begin(), opts.options.end(),
+ back_inserter(arguments), cmd_line_utils::is_argument());
+
+ // try to find a config file somewhere up the filesystem hierarchy
+ // starting with the input file path. This allows to use a general wave.cfg
+ // file for all files in a certain project.
+ if (arguments.size() > 0 && arguments[0].value[0] != "-") {
+ // construct full path of input file
+ fs::path input_dir (boost::wave::util::complete_path(
+ boost::wave::util::create_path(arguments[0].value[0])));
+
+ // chop of file name
+ input_dir = boost::wave::util::branch_path(
+ boost::wave::util::normalize(input_dir));
+
+ // walk up the hierarchy, trying to find a file wave.cfg
+ while (!input_dir.empty()) {
+ fs::path filename = input_dir / "wave.cfg";
+ if (cmd_line_utils::read_config_file_options(filename.string(),
+ desc_overall_cfgfile, vm, true))
+ {
+ break; // break on the first cfg file found
+ }
+ input_dir = boost::wave::util::branch_path(input_dir);
+ }
+ }
+
+ // if there is specified at least one config file, parse it and add the
+ // options to the main variables_map
+ if (vm.count("config-file")) {
+ vector<std::string> const &cfg_files =
+ vm["config-file"].as<vector<std::string> >();
+ vector<std::string>::const_iterator end = cfg_files.end();
+ for (vector<std::string>::const_iterator cit = cfg_files.begin();
+ cit != end; ++cit)
+ {
+ // parse a single config file and store the results
+ cmd_line_utils::read_config_file_options(*cit,
+ desc_overall_cfgfile, vm);
+ }
+ }
+
+ // ... act as required
+ if (vm.count("help")) {
+ po::options_description desc_help (
+ "Usage: wave [options] [@config-file(s)] [file]");
+
+ desc_help.add(desc_cmdline).add(desc_generic).add(desc_ext);
+ cout << desc_help << endl;
+ return 1;
+ }
+
+ if (vm.count("version")) {
+ cout << get_version() << endl;
+ return 0;
+ }
+
+ if (vm.count("copyright")) {
+ return print_copyright();
+ }
+
+ // if there is no input file given, then take input from stdin
+ if (0 == arguments.size() || 0 == arguments[0].value.size() ||
+ arguments[0].value[0] == "-")
+ {
+ // preprocess the given input from stdin
+ return do_actual_work("<stdin>", std::cin, vm, true);
+ }
+ else {
+ if (arguments.size() > 1) {
+ // this driver understands to parse one input file only
+ cerr << "wave: more than one input file specified, "
+ << "ignoring all but the first!" << endl;
+ }
+
+ std::string file_name(arguments[0].value[0]);
+ ifstream instream(file_name.c_str());
+
+ // preprocess the given input file
+ if (!instream.is_open()) {
+ cerr << "wave: could not open input file: " << file_name << endl;
+ return -1;
+ }
+ return do_actual_work(file_name, instream, vm, false);
+ }
+ }
+ catch (std::exception const &e) {
+ cout << "wave: exception caught: " << e.what() << endl;
+ return 6;
+ }
+ catch (...) {
+ cerr << "wave: unexpected exception caught." << endl;
+ return 7;
+ }
+}
+
diff --git a/tools/wave/cpp.hpp b/tools/wave/cpp.hpp
new file mode 100644
index 0000000000..d92dcc8ded
--- /dev/null
+++ b/tools/wave/cpp.hpp
@@ -0,0 +1,43 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+
+ http://www.boost.org/
+
+ Copyright (c) 2001-2011 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(CPP_HPP_920D0370_741F_44AF_BF86_F6104BDACF75_INCLUDED)
+#define CPP_HPP_920D0370_741F_44AF_BF86_F6104BDACF75_INCLUDED
+
+///////////////////////////////////////////////////////////////////////////////
+// This file may be used as a precompiled header (if applicable)
+
+///////////////////////////////////////////////////////////////////////////////
+// include often used files from the stdlib
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <iterator>
+
+///////////////////////////////////////////////////////////////////////////////
+// include boost config
+#include <boost/config.hpp> // global configuration information
+
+///////////////////////////////////////////////////////////////////////////////
+// build version
+#include "cpp_version.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// configure this app here (global configuration constants)
+#include "cpp_config.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// include required boost libraries
+#include <boost/assert.hpp>
+#include <boost/pool/pool_alloc.hpp>
+
+#endif // !defined(CPP_HPP_920D0370_741F_44AF_BF86_F6104BDACF75_INCLUDED)
diff --git a/tools/wave/cpp_config.hpp b/tools/wave/cpp_config.hpp
new file mode 100644
index 0000000000..aed8630855
--- /dev/null
+++ b/tools/wave/cpp_config.hpp
@@ -0,0 +1,63 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+ Global application configuration of the Wave driver command
+
+ http://www.boost.org/
+
+ Copyright (c) 2001-2011 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(CPP_CONFIG_HPP_F143F90A_A63F_4B27_AC41_9CA4F14F538D_INCLUDED)
+#define CPP_CONFIG_HPP_F143F90A_A63F_4B27_AC41_9CA4F14F538D_INCLUDED
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment the following, if you need debug output, the
+// BOOST_SPIRIT_DEBUG_FLAGS constants below helps to fine control the amount of
+// the generated debug output
+//#define BOOST_SPIRIT_DEBUG
+
+///////////////////////////////////////////////////////////////////////////////
+// debug rules, subrules and grammars only, for possible flags see
+// spirit/include/classic_debug.hpp
+#if defined(BOOST_SPIRIT_DEBUG)
+
+#define BOOST_SPIRIT_DEBUG_FLAGS ( \
+ BOOST_SPIRIT_DEBUG_FLAGS_NODES | \
+ BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES \
+ ) \
+ /**/
+
+///////////////////////////////////////////////////////////////////////////////
+// Debug flags for the Wave library, possible flags (defined in
+// wave_config.hpp):
+//
+// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR 0x0001
+// #define BOOST_SPIRIT_DEBUG_FLAGS_TIME_CONVERSION 0x0002
+// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_EXPR_GRAMMAR 0x0004
+// #define BOOST_SPIRIT_DEBUG_FLAGS_INTLIT_GRAMMAR 0x0008
+// #define BOOST_SPIRIT_DEBUG_FLAGS_CHLIT_GRAMMAR 0x0010
+// #define BOOST_SPIRIT_DEBUG_FLAGS_DEFINED_GRAMMAR 0x0020
+// #define BOOST_SPIRIT_DEBUG_FLAGS_PREDEF_MACROS_GRAMMAR 0x0040
+
+#define BOOST_SPIRIT_DEBUG_FLAGS_CPP ( 0 \
+ /* insert the required flags from above */ \
+ ) \
+ /**/
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Include the configuration stuff for the Wave library itself
+#include <boost/wave/wave_config.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// MSVC specific #pragma's
+#if defined(BOOST_MSVC)
+#pragma warning (disable: 4355) // 'this' used in base member initializer list
+#pragma warning (disable: 4800) // forcing value to bool 'true' or 'false'
+#pragma inline_depth(255)
+#pragma inline_recursion(on)
+#endif // defined(BOOST_MSVC)
+
+#endif // !defined(CPP_CONFIG_HPP_F143F90A_A63F_4B27_AC41_9CA4F14F538D_INCLUDED)
diff --git a/tools/wave/cpp_version.hpp b/tools/wave/cpp_version.hpp
new file mode 100644
index 0000000000..5ce2ac1f1e
--- /dev/null
+++ b/tools/wave/cpp_version.hpp
@@ -0,0 +1,25 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+ http://www.boost.org/
+
+ Copyright (c) 2001-2011 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(CPP_VERSION_HPP_CE4FE67F_63F9_468D_8364_C855F89D3C5D_INCLUDED)
+#define CPP_VERSION_HPP_CE4FE67F_63F9_468D_8364_C855F89D3C5D_INCLUDED
+
+#include <boost/wave/wave_version.hpp>
+
+#define CPP_VERSION_MAJOR BOOST_WAVE_VERSION_MAJOR
+#define CPP_VERSION_MINOR BOOST_WAVE_VERSION_MINOR
+#define CPP_VERSION_SUBMINOR BOOST_WAVE_VERSION_SUBMINOR
+#define CPP_VERSION_FULL BOOST_WAVE_VERSION
+
+#define CPP_VERSION_FULL_STR BOOST_PP_STRINGIZE(CPP_VERSION_FULL)
+
+#define CPP_VERSION_DATE 20110507L
+#define CPP_VERSION_DATE_STR "20110507"
+
+#endif // !defined(CPP_VERSION_HPP_CE4FE67F_63F9_468D_8364_C855F89D3C5D_INCLUDED)
diff --git a/tools/wave/stop_watch.hpp b/tools/wave/stop_watch.hpp
new file mode 100644
index 0000000000..2342ccc903
--- /dev/null
+++ b/tools/wave/stop_watch.hpp
@@ -0,0 +1,84 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+ http://www.boost.org/
+
+ Copyright (c) 2001-2011 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(STOP_WATCH_HPP_HK040911_INCLUDED)
+#define STOP_WATCH_HPP_HK040911_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/timer.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class stop_watch : public boost::timer {
+
+ typedef boost::timer base_t;
+
+public:
+ stop_watch() : is_suspended_since(0), suspended_overall(0) {}
+
+ void suspend()
+ {
+ if (0 == is_suspended_since) {
+ // if not already suspended
+ is_suspended_since = this->base_t::elapsed();
+ }
+ }
+ void resume()
+ {
+ if (0 != is_suspended_since) {
+ // if really suspended
+ suspended_overall += this->base_t::elapsed() - is_suspended_since;
+ is_suspended_since = 0;
+ }
+ }
+ double elapsed() const
+ {
+ if (0 == is_suspended_since) {
+ // currently running
+ return this->base_t::elapsed() - suspended_overall;
+ }
+
+ // currently suspended
+ BOOST_ASSERT(is_suspended_since >= suspended_overall);
+ return is_suspended_since - suspended_overall;
+ }
+
+ std::string format_elapsed_time() const
+ {
+ double current = elapsed();
+ char time_buffer[sizeof("1234:56:78.90 abcd.")+1];
+
+ using namespace std;
+ if (current >= 3600) {
+ // show hours
+ sprintf (time_buffer, "%d:%02d:%02d.%03d hrs.",
+ (int)(current) / 3600, ((int)(current) % 3600) / 60,
+ ((int)(current) % 3600) % 60,
+ (int)(current * 1000) % 1000);
+ }
+ else if (current >= 60) {
+ // show minutes
+ sprintf (time_buffer, "%d:%02d.%03d min.",
+ (int)(current) / 60, (int)(current) % 60,
+ (int)(current * 1000) % 1000);
+ }
+ else {
+ // show seconds
+ sprintf(time_buffer, "%d.%03d sec.", (int)current,
+ (int)(current * 1000) % 1000);
+ }
+ return time_buffer;
+ }
+
+private:
+ double is_suspended_since;
+ double suspended_overall;
+};
+
+#endif // !defined(STOP_WATCH_HPP_HK040911_INCLUDED)
diff --git a/tools/wave/trace_macro_expansion.hpp b/tools/wave/trace_macro_expansion.hpp
new file mode 100644
index 0000000000..7679a2edb6
--- /dev/null
+++ b/tools/wave/trace_macro_expansion.hpp
@@ -0,0 +1,1481 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+ http://www.boost.org/
+
+ Copyright (c) 2001-2011 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(TRACE_MACRO_EXPANSION_HPP_D8469318_8407_4B9D_A19F_13CA60C1661F_INCLUDED)
+#define TRACE_MACRO_EXPANSION_HPP_D8469318_8407_4B9D_A19F_13CA60C1661F_INCLUDED
+
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+
+#include <ostream>
+#include <string>
+#include <stack>
+#include <set>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/convenience.hpp>
+
+#include <boost/wave/token_ids.hpp>
+#include <boost/wave/util/macro_helpers.hpp>
+#include <boost/wave/util/filesystem_compatibility.hpp>
+#include <boost/wave/preprocessing_hooks.hpp>
+#include <boost/wave/whitespace_handling.hpp>
+#include <boost/wave/language_support.hpp>
+#include <boost/wave/cpp_exceptions.hpp>
+
+#include "stop_watch.hpp"
+
+#ifdef BOOST_NO_STRINGSTREAM
+#include <strstream>
+#define BOOST_WAVE_OSSTREAM std::ostrstream
+std::string BOOST_WAVE_GETSTRING(std::ostrstream& ss)
+{
+ ss << std::ends;
+ std::string rval = ss.str();
+ ss.freeze(false);
+ return rval;
+}
+#else
+#include <sstream>
+#define BOOST_WAVE_GETSTRING(ss) ss.str()
+#define BOOST_WAVE_OSSTREAM std::ostringstream
+#endif
+
+// trace_flags: enable single tracing functionality
+enum trace_flags {
+ trace_nothing = 0, // disable tracing
+ trace_macros = 1, // enable macro tracing
+ trace_macro_counts = 2, // enable invocation counting
+ trace_includes = 4, // enable include file tracing
+ trace_guards = 8 // enable include guard tracing
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Special error thrown whenever the #pragma wave system() directive is
+// disabled
+//
+///////////////////////////////////////////////////////////////////////////////
+class bad_pragma_exception :
+ public boost::wave::preprocess_exception
+{
+public:
+ enum error_code {
+ pragma_system_not_enabled =
+ boost::wave::preprocess_exception::last_error_number + 1,
+ pragma_mismatched_push_pop,
+ };
+
+ bad_pragma_exception(char const *what_, error_code code, int line_,
+ int column_, char const *filename_) throw()
+ : boost::wave::preprocess_exception(what_,
+ (boost::wave::preprocess_exception::error_code)code, line_,
+ column_, filename_)
+ {
+ }
+ ~bad_pragma_exception() throw() {}
+
+ virtual char const *what() const throw()
+ {
+ return "boost::wave::bad_pragma_exception";
+ }
+ virtual bool is_recoverable() const throw()
+ {
+ return true;
+ }
+ virtual int get_severity() const throw()
+ {
+ return boost::wave::util::severity_remark;
+ }
+
+ static char const *error_text(int code)
+ {
+ switch(code) {
+ case pragma_system_not_enabled:
+ return "the directive '#pragma wave system()' was not enabled, use the "
+ "-x command line argument to enable the execution of";
+
+ case pragma_mismatched_push_pop:
+ return "unbalanced #pragma push/pop in input file(s) for option";
+ }
+ return "Unknown exception";
+ }
+ static boost::wave::util::severity severity_level(int code)
+ {
+ switch(code) {
+ case pragma_system_not_enabled:
+ return boost::wave::util::severity_remark;
+
+ case pragma_mismatched_push_pop:
+ return boost::wave::util::severity_error;
+ }
+ return boost::wave::util::severity_fatal;
+ }
+ static char const *severity_text(int code)
+ {
+ return boost::wave::util::get_severity(boost::wave::util::severity_remark);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// The trace_macro_expansion policy is used to trace the macro expansion of
+// macros whenever it is requested from inside the input stream to preprocess
+// through the '#pragma wave_option(trace: enable)' directive. The macro
+// tracing is disabled with the help of a '#pragma wave_option(trace: disable)'
+// directive.
+//
+// This policy type is used as a template parameter to the boost::wave::context<>
+// object.
+//
+///////////////////////////////////////////////////////////////////////////////
+template <typename TokenT>
+class trace_macro_expansion
+: public boost::wave::context_policies::eat_whitespace<TokenT>
+{
+ typedef boost::wave::context_policies::eat_whitespace<TokenT> base_type;
+
+public:
+ trace_macro_expansion(
+ bool preserve_whitespace_, bool preserve_bol_whitespace_,
+ std::ofstream &output_, std::ostream &tracestrm_,
+ std::ostream &includestrm_, std::ostream &guardstrm_,
+ trace_flags flags_, bool enable_system_command_,
+ bool& generate_output_, std::string const& default_outfile_)
+ : outputstrm(output_), tracestrm(tracestrm_),
+ includestrm(includestrm_), guardstrm(guardstrm_),
+ level(0), flags(flags_), logging_flags(trace_nothing),
+ enable_system_command(enable_system_command_),
+ preserve_whitespace(preserve_whitespace_),
+ preserve_bol_whitespace(preserve_bol_whitespace_),
+ generate_output(generate_output_),
+ default_outfile(default_outfile_),
+ emit_relative_filenames(false)
+ {
+ }
+ ~trace_macro_expansion()
+ {
+ }
+
+ void enable_macro_counting()
+ {
+ logging_flags = trace_flags(logging_flags | trace_macro_counts);
+ }
+ std::map<std::string, std::size_t> const& get_macro_counts() const
+ {
+ return counts;
+ }
+
+ void enable_relative_names_in_line_directives(bool flag)
+ {
+ emit_relative_filenames = flag;
+ }
+ bool enable_relative_names_in_line_directives() const
+ {
+ return emit_relative_filenames;
+ }
+
+ // add a macro name, which should not be expanded at all (left untouched)
+ void add_noexpandmacro(std::string const& name)
+ {
+ noexpandmacros.insert(name);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'expanding_function_like_macro' is called whenever a
+ // function-like macro is to be expanded.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'macrodef' marks the position, where the macro to expand
+ // is defined.
+ //
+ // The parameter 'formal_args' holds the formal arguments used during the
+ // definition of the macro.
+ //
+ // The parameter 'definition' holds the macro definition for the macro to
+ // trace.
+ //
+ // The parameter 'macro_call' marks the position, where this macro invoked.
+ //
+ // The parameter 'arguments' holds the macro arguments used during the
+ // invocation of the macro
+ //
+ // The parameters 'seqstart' and 'seqend' point into the input token
+ // stream allowing to access the whole token sequence comprising the macro
+ // invocation (starting with the opening parenthesis and ending after the
+ // closing one).
+ //
+ // The return value defines whether the corresponding macro will be
+ // expanded (return false) or will be copied to the output (return true).
+ // Note: the whole argument list is copied unchanged to the output as well
+ // without any further processing.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
+ // old signature
+ template <typename ContainerT>
+ void expanding_function_like_macro(
+ TokenT const &macrodef, std::vector<TokenT> const &formal_args,
+ ContainerT const &definition,
+ TokenT const &macrocall, std::vector<ContainerT> const &arguments)
+ {
+ if (enabled_macro_counting())
+ count_invocation(macrodef.get_value().c_str());
+
+ if (!enabled_macro_tracing())
+ return;
+#else
+ // new signature
+ template <typename ContextT, typename ContainerT, typename IteratorT>
+ bool
+ expanding_function_like_macro(ContextT const& ctx,
+ TokenT const &macrodef, std::vector<TokenT> const &formal_args,
+ ContainerT const &definition,
+ TokenT const &macrocall, std::vector<ContainerT> const &arguments,
+ IteratorT const& seqstart, IteratorT const& seqend)
+ {
+ if (enabled_macro_counting() || !noexpandmacros.empty()) {
+ std::string name (macrodef.get_value().c_str());
+
+ if (noexpandmacros.find(name.c_str()) != noexpandmacros.end())
+ return true; // do not expand this macro
+
+ if (enabled_macro_counting())
+ count_invocation(name.c_str());
+ }
+
+ if (!enabled_macro_tracing())
+ return false;
+#endif
+ if (0 == get_level()) {
+ // output header line
+ BOOST_WAVE_OSSTREAM stream;
+
+ stream
+ << macrocall.get_position() << ": "
+ << macrocall.get_value() << "(";
+
+ // argument list
+ for (typename ContainerT::size_type i = 0; i < arguments.size(); ++i) {
+ stream << boost::wave::util::impl::as_string(arguments[i]);
+ if (i < arguments.size()-1)
+ stream << ", ";
+ }
+ stream << ")" << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ increment_level();
+ }
+
+ // output definition reference
+ {
+ BOOST_WAVE_OSSTREAM stream;
+
+ stream
+ << macrodef.get_position() << ": see macro definition: "
+ << macrodef.get_value() << "(";
+
+ // formal argument list
+ for (typename std::vector<TokenT>::size_type i = 0;
+ i < formal_args.size(); ++i)
+ {
+ stream << formal_args[i].get_value();
+ if (i < formal_args.size()-1)
+ stream << ", ";
+ }
+ stream << ")" << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ }
+
+ if (formal_args.size() > 0) {
+ // map formal and real arguments
+ open_trace_body("invoked with\n");
+ for (typename std::vector<TokenT>::size_type j = 0;
+ j < formal_args.size(); ++j)
+ {
+ using namespace boost::wave;
+
+ BOOST_WAVE_OSSTREAM stream;
+ stream << formal_args[j].get_value() << " = ";
+#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
+ if (T_ELLIPSIS == token_id(formal_args[j])) {
+ // ellipsis
+ for (typename ContainerT::size_type k = j;
+ k < arguments.size(); ++k)
+ {
+ stream << boost::wave::util::impl::as_string(arguments[k]);
+ if (k < arguments.size()-1)
+ stream << ", ";
+ }
+ }
+ else
+#endif
+ {
+ stream << boost::wave::util::impl::as_string(arguments[j]);
+ }
+ stream << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ }
+ close_trace_body();
+ }
+ open_trace_body();
+
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS == 0
+ return false;
+#endif
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'expanding_object_like_macro' is called whenever a
+ // object-like macro is to be expanded .
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'macrodef' marks the position, where the macro to expand
+ // is defined.
+ //
+ // The definition 'definition' holds the macro definition for the macro to
+ // trace.
+ //
+ // The parameter 'macrocall' marks the position, where this macro invoked.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
+ // old signature
+ template <typename ContainerT>
+ void expanding_object_like_macro(TokenT const &macrodef,
+ ContainerT const &definition, TokenT const &macrocall)
+ {
+ if (enabled_macro_counting())
+ count_invocation(macrodef.get_value().c_str());
+
+ if (!enabled_macro_tracing())
+ return;
+#else
+ // new signature
+ template <typename ContextT, typename ContainerT>
+ bool
+ expanding_object_like_macro(ContextT const& ctx,
+ TokenT const &macrodef, ContainerT const &definition,
+ TokenT const &macrocall)
+ {
+ if (enabled_macro_counting() || !noexpandmacros.empty()) {
+ std::string name (macrodef.get_value().c_str());
+
+ if (noexpandmacros.find(name.c_str()) != noexpandmacros.end())
+ return true; // do not expand this macro
+
+ if (enabled_macro_counting())
+ count_invocation(name.c_str());
+ }
+
+ if (!enabled_macro_tracing())
+ return false;
+#endif
+ if (0 == get_level()) {
+ // output header line
+ BOOST_WAVE_OSSTREAM stream;
+
+ stream
+ << macrocall.get_position() << ": "
+ << macrocall.get_value() << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ increment_level();
+ }
+
+ // output definition reference
+ {
+ BOOST_WAVE_OSSTREAM stream;
+
+ stream
+ << macrodef.get_position() << ": see macro definition: "
+ << macrodef.get_value() << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ }
+ open_trace_body();
+
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS == 0
+ return false;
+#endif
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'expanded_macro' is called whenever the expansion of a
+ // macro is finished but before the rescanning process starts.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'result' contains the token sequence generated as the
+ // result of the macro expansion.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
+ // old signature
+ template <typename ContainerT>
+ void expanded_macro(ContainerT const &result)
+#else
+ // new signature
+ template <typename ContextT, typename ContainerT>
+ void expanded_macro(ContextT const& ctx,ContainerT const &result)
+#endif
+ {
+ if (!enabled_macro_tracing()) return;
+
+ BOOST_WAVE_OSSTREAM stream;
+ stream << boost::wave::util::impl::as_string(result) << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+
+ open_trace_body("rescanning\n");
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'rescanned_macro' is called whenever the rescanning of a
+ // macro is finished.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'result' contains the token sequence generated as the
+ // result of the rescanning.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
+ // old signature
+ template <typename ContainerT>
+ void rescanned_macro(ContainerT const &result)
+#else
+ // new signature
+ template <typename ContextT, typename ContainerT>
+ void rescanned_macro(ContextT const& ctx,ContainerT const &result)
+#endif
+ {
+ if (!enabled_macro_tracing() || get_level() == 0)
+ return;
+
+ BOOST_WAVE_OSSTREAM stream;
+ stream << boost::wave::util::impl::as_string(result) << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ close_trace_body();
+ close_trace_body();
+
+ if (1 == get_level())
+ decrement_level();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'interpret_pragma' is called whenever a #pragma command
+ // directive is found which isn't known to the core Wave library, where
+ // command is the value defined as the BOOST_WAVE_PRAGMA_KEYWORD constant
+ // which defaults to "wave".
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'pending' may be used to push tokens back into the input
+ // stream, which are to be used as the replacement text for the whole
+ // #pragma directive.
+ //
+ // The parameter 'option' contains the name of the interpreted pragma.
+ //
+ // The parameter 'values' holds the values of the parameter provided to
+ // the pragma operator.
+ //
+ // The parameter 'act_token' contains the actual #pragma token, which may
+ // be used for error output.
+ //
+ // If the return value is 'false', the whole #pragma directive is
+ // interpreted as unknown and a corresponding error message is issued. A
+ // return value of 'true' signs a successful interpretation of the given
+ // #pragma.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT, typename ContainerT>
+ bool
+ interpret_pragma(ContextT &ctx, ContainerT &pending,
+ typename ContextT::token_type const &option, ContainerT const &valuetokens,
+ typename ContextT::token_type const &act_token)
+ {
+ typedef typename ContextT::token_type token_type;
+
+ ContainerT values(valuetokens);
+ boost::wave::util::impl::trim_sequence(values); // trim whitespace
+
+ if (option.get_value() == "timer") {
+ // #pragma wave timer(value)
+ if (0 == values.size()) {
+ // no value means '1'
+ using namespace boost::wave;
+ timer(token_type(T_INTLIT, "1", act_token.get_position()));
+ }
+ else {
+ timer(values.front());
+ }
+ return true;
+ }
+ if (option.get_value() == "trace") {
+ // enable/disable tracing option
+ return interpret_pragma_trace(ctx, values, act_token);
+ }
+ if (option.get_value() == "system") {
+ if (!enable_system_command) {
+ // if the #pragma wave system() directive is not enabled, throw
+ // a corresponding error (actually its a remark),
+ typename ContextT::string_type msg(
+ boost::wave::util::impl::as_string(values));
+ BOOST_WAVE_THROW_CTX(ctx, bad_pragma_exception,
+ pragma_system_not_enabled,
+ msg.c_str(), act_token.get_position());
+ return false;
+ }
+
+ // try to spawn the given argument as a system command and return the
+ // std::cout of this process as the replacement of this _Pragma
+ return interpret_pragma_system(ctx, pending, values, act_token);
+ }
+ if (option.get_value() == "stop") {
+ // stop the execution and output the argument
+ typename ContextT::string_type msg(
+ boost::wave::util::impl::as_string(values));
+ BOOST_WAVE_THROW_CTX(ctx, boost::wave::preprocess_exception,
+ error_directive, msg.c_str(), act_token.get_position());
+ return false;
+ }
+ if (option.get_value() == "option") {
+ // handle different options
+ return interpret_pragma_option(ctx, values, act_token);
+ }
+ return false;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'emit_line_directive' is called whenever a #line directive
+ // has to be emitted into the generated output.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'pending' may be used to push tokens back into the input
+ // stream, which are to be used instead of the default output generated
+ // for the #line directive.
+ //
+ // The parameter 'act_token' contains the actual #pragma token, which may
+ // be used for error output. The line number stored in this token can be
+ // used as the line number emitted as part of the #line directive.
+ //
+ // If the return value is 'false', a default #line directive is emitted
+ // by the library. A return value of 'true' will inhibit any further
+ // actions, the tokens contained in 'pending' will be copied verbatim
+ // to the output.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT, typename ContainerT>
+ bool
+ emit_line_directive(ContextT const& ctx, ContainerT &pending,
+ typename ContextT::token_type const& act_token)
+ {
+ if (!need_emit_line_directives(ctx.get_language()) ||
+ !enable_relative_names_in_line_directives())
+ {
+ return false;
+ }
+
+ // emit a #line directive showing the relative filename instead
+ typename ContextT::position_type pos = act_token.get_position();
+ unsigned int column = 6;
+
+ typedef typename ContextT::token_type result_type;
+ using namespace boost::wave;
+
+ pos.set_column(1);
+ pending.push_back(result_type(T_PP_LINE, "#line", pos));
+
+ pos.set_column(column); // account for '#line'
+ pending.push_back(result_type(T_SPACE, " ", pos));
+
+ // 21 is the max required size for a 64 bit integer represented as a
+ // string
+ char buffer[22];
+
+ using namespace std; // for some systems sprintf is in namespace std
+ sprintf (buffer, "%d", pos.get_line());
+
+ pos.set_column(++column); // account for ' '
+ pending.push_back(result_type(T_INTLIT, buffer, pos));
+ pos.set_column(column += (unsigned int)strlen(buffer)); // account for <number>
+ pending.push_back(result_type(T_SPACE, " ", pos));
+ pos.set_column(++column); // account for ' '
+
+ std::string file("\"");
+ boost::filesystem::path filename(
+ boost::wave::util::create_path(ctx.get_current_relative_filename().c_str()));
+
+ using boost::wave::util::impl::escape_lit;
+ file += escape_lit(boost::wave::util::native_file_string(filename)) + "\"";
+
+ pending.push_back(result_type(T_STRINGLIT, file.c_str(), pos));
+ pos.set_column(column += (unsigned int)file.size()); // account for filename
+ pending.push_back(result_type(T_GENERATEDNEWLINE, "\n", pos));
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'opened_include_file' is called whenever a file referred
+ // by an #include directive was successfully located and opened.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'filename' contains the file system path of the
+ // opened file (this is relative to the directory of the currently
+ // processed file or a absolute path depending on the paths given as the
+ // include search paths).
+ //
+ // The include_depth parameter contains the current include file depth.
+ //
+ // The is_system_include parameter denotes, whether the given file was
+ // found as a result of a #include <...> directive.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
+ // old signature
+ void
+ opened_include_file(std::string const &relname, std::string const &absname,
+ std::size_t include_depth, bool is_system_include)
+ {
+#else
+ // new signature
+ template <typename ContextT>
+ void
+ opened_include_file(ContextT const& ctx, std::string const &relname,
+ std::string const &absname, bool is_system_include)
+ {
+ std::size_t include_depth = ctx.get_iteration_depth();
+#endif
+ if (enabled_include_tracing()) {
+ // print indented filename
+ for (std::size_t i = 0; i < include_depth; ++i)
+ includestrm << " ";
+
+ if (is_system_include)
+ includestrm << "<" << relname << "> (" << absname << ")";
+ else
+ includestrm << "\"" << relname << "\" (" << absname << ")";
+
+ includestrm << std::endl;
+ }
+ }
+
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'detected_include_guard' is called whenever either a
+ // include file is about to be added to the list of #pragma once headers.
+ // That means this header file will not be opened and parsed again even
+ // if it is specified in a later #include directive.
+ // This function is called as the result of a detected include guard
+ // scheme.
+ //
+ // The implemented heuristics for include guards detects two forms of
+ // include guards:
+ //
+ // #ifndef INCLUDE_GUARD_MACRO
+ // #define INCLUDE_GUARD_MACRO
+ // ...
+ // #endif
+ //
+ // or
+ //
+ // if !defined(INCLUDE_GUARD_MACRO)
+ // #define INCLUDE_GUARD_MACRO
+ // ...
+ // #endif
+ //
+ // note, that the parenthesis are optional (i.e. !defined INCLUDE_GUARD_MACRO
+ // will work as well). The code allows for any whitespace, newline and single
+ // '#' tokens before the #if/#ifndef and after the final #endif.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'filename' contains the file system path of the
+ // opened file (this is relative to the directory of the currently
+ // processed file or a absolute path depending on the paths given as the
+ // include search paths).
+ //
+ // The parameter contains the name of the detected include guard.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT>
+ void
+ detected_include_guard(ContextT const& ctx, std::string const& filename,
+ std::string const& include_guard)
+ {
+ if (enabled_guard_tracing()) {
+ guardstrm << include_guard << ":" << std::endl
+ << " " << filename << std::endl;
+ }
+ }
+#endif
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'may_skip_whitespace' will be called by the
+ // library whenever a token is about to be returned to the calling
+ // application.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The 'token' parameter holds a reference to the current token. The policy
+ // is free to change this token if needed.
+ //
+ // The 'skipped_newline' parameter holds a reference to a boolean value
+ // which should be set to true by the policy function whenever a newline
+ // is going to be skipped.
+ //
+ // If the return value is true, the given token is skipped and the
+ // preprocessing continues to the next token. If the return value is
+ // false, the given token is returned to the calling application.
+ //
+ // ATTENTION!
+ // Caution has to be used, because by returning true the policy function
+ // is able to force skipping even significant tokens, not only whitespace.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT>
+ bool may_skip_whitespace(ContextT const &ctx, TokenT &token,
+ bool &skipped_newline)
+ {
+ return this->base_type::may_skip_whitespace(
+ ctx, token, need_preserve_comments(ctx.get_language()),
+ preserve_bol_whitespace, skipped_newline) ?
+ !preserve_whitespace : false;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'throw_exception' will be called by the library whenever a
+ // preprocessing exception occurs.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'e' is the exception object containing detailed error
+ // information.
+ //
+ // The default behavior is to call the function boost::throw_exception.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT>
+ void
+ throw_exception(ContextT const& ctx, boost::wave::preprocess_exception const& e)
+ {
+#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
+ if (!is_import_directive_error(e))
+ boost::throw_exception(e);
+#else
+ boost::throw_exception(e);
+#endif
+ }
+ using base_type::throw_exception;
+
+protected:
+#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
+ ///////////////////////////////////////////////////////////////////////////
+ // Avoid throwing an error from a #import directive
+ bool is_import_directive_error(boost::wave::preprocess_exception const& e)
+ {
+ using namespace boost::wave;
+ if (e.get_errorcode() != preprocess_exception::ill_formed_directive)
+ return false;
+
+ // the error string is formatted as 'severity: error: directive'
+ std::string error(e.description());
+ std::string::size_type p = error.find_last_of(":");
+ return p != std::string::npos && error.substr(p+2) == "import";
+ }
+#endif
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Interpret the different Wave specific pragma directives/operators
+ template <typename ContextT, typename ContainerT>
+ bool
+ interpret_pragma_trace(ContextT& ctx, ContainerT const &values,
+ typename ContextT::token_type const &act_token)
+ {
+ typedef typename ContextT::token_type token_type;
+ typedef typename token_type::string_type string_type;
+
+ bool valid_option = false;
+
+ if (1 == values.size()) {
+ token_type const &value = values.front();
+
+ if (value.get_value() == "enable" ||
+ value.get_value() == "on" ||
+ value.get_value() == "1")
+ {
+ // #pragma wave trace(enable)
+ enable_tracing(static_cast<trace_flags>(
+ tracing_enabled() | trace_macros));
+ valid_option = true;
+ }
+ else if (value.get_value() == "disable" ||
+ value.get_value() == "off" ||
+ value.get_value() == "0")
+ {
+ // #pragma wave trace(disable)
+ enable_tracing(static_cast<trace_flags>(
+ tracing_enabled() & ~trace_macros));
+ valid_option = true;
+ }
+ }
+ if (!valid_option) {
+ // unknown option value
+ string_type option_str ("trace");
+
+ if (values.size() > 0) {
+ option_str += "(";
+ option_str += boost::wave::util::impl::as_string(values);
+ option_str += ")";
+ }
+ BOOST_WAVE_THROW_CTX(ctx, boost::wave::preprocess_exception,
+ ill_formed_pragma_option, option_str.c_str(),
+ act_token.get_position());
+ return false;
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // interpret the pragma wave option(preserve: [0|1|2|3|push|pop]) directive
+ template <typename ContextT>
+ static bool
+ interpret_pragma_option_preserve_set(int mode, bool &preserve_whitespace,
+ bool& preserve_bol_whitespace, ContextT &ctx)
+ {
+ switch(mode) {
+ // preserve no whitespace
+ case 0:
+ preserve_whitespace = false;
+ preserve_bol_whitespace = false;
+ ctx.set_language(
+ enable_preserve_comments(ctx.get_language(), false),
+ false);
+ break;
+
+ // preserve BOL whitespace only
+ case 1:
+ preserve_whitespace = false;
+ preserve_bol_whitespace = true;
+ ctx.set_language(
+ enable_preserve_comments(ctx.get_language(), false),
+ false);
+ break;
+
+ // preserve comments and BOL whitespace only
+ case 2:
+ preserve_whitespace = false;
+ preserve_bol_whitespace = true;
+ ctx.set_language(
+ enable_preserve_comments(ctx.get_language()),
+ false);
+ break;
+
+ // preserve all whitespace
+ case 3:
+ preserve_whitespace = true;
+ preserve_bol_whitespace = true;
+ ctx.set_language(
+ enable_preserve_comments(ctx.get_language()),
+ false);
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ template <typename ContextT, typename IteratorT>
+ bool
+ interpret_pragma_option_preserve(ContextT &ctx, IteratorT &it,
+ IteratorT end, typename ContextT::token_type const &act_token)
+ {
+ using namespace boost::wave;
+
+ token_id id = util::impl::skip_whitespace(it, end);
+ if (T_COLON == id)
+ id = util::impl::skip_whitespace(it, end);
+
+ // implement push/pop
+ if (T_IDENTIFIER == id) {
+ if ((*it).get_value() == "push") {
+ // push current preserve option onto the internal option stack
+ if (need_preserve_comments(ctx.get_language())) {
+ if (preserve_whitespace)
+ preserve_options.push(3);
+ else
+ preserve_options.push(2);
+ }
+ else if (preserve_bol_whitespace) {
+ preserve_options.push(1);
+ }
+ else {
+ preserve_options.push(0);
+ }
+ return true;
+ }
+ else if ((*it).get_value() == "pop") {
+ // test for mismatched push/pop #pragmas
+ if (preserve_options.empty()) {
+ BOOST_WAVE_THROW_CTX(ctx, bad_pragma_exception,
+ pragma_mismatched_push_pop, "preserve",
+ act_token.get_position());
+ }
+
+ // pop output preserve from the internal option stack
+ bool result = interpret_pragma_option_preserve_set(
+ preserve_options.top(), preserve_whitespace,
+ preserve_bol_whitespace, ctx);
+ preserve_options.pop();
+ return result;
+ }
+ return false;
+ }
+
+ if (T_PP_NUMBER != id)
+ return false;
+
+ using namespace std; // some platforms have atoi in namespace std
+ return interpret_pragma_option_preserve_set(
+ atoi((*it).get_value().c_str()), preserve_whitespace,
+ preserve_bol_whitespace, ctx);
+ }
+
+ // interpret the pragma wave option(line: [0|1|2|push|pop]) directive
+ template <typename ContextT, typename IteratorT>
+ bool
+ interpret_pragma_option_line(ContextT &ctx, IteratorT &it,
+ IteratorT end, typename ContextT::token_type const &act_token)
+ {
+ using namespace boost::wave;
+
+ token_id id = util::impl::skip_whitespace(it, end);
+ if (T_COLON == id)
+ id = util::impl::skip_whitespace(it, end);
+
+ // implement push/pop
+ if (T_IDENTIFIER == id) {
+ if ((*it).get_value() == "push") {
+ // push current line option onto the internal option stack
+ int mode = 0;
+ if (need_emit_line_directives(ctx.get_language())) {
+ mode = 1;
+ if (enable_relative_names_in_line_directives())
+ mode = 2;
+ }
+ line_options.push(mode);
+ return true;
+ }
+ else if ((*it).get_value() == "pop") {
+ // test for mismatched push/pop #pragmas
+ if (line_options.empty()) {
+ BOOST_WAVE_THROW_CTX(ctx, bad_pragma_exception,
+ pragma_mismatched_push_pop, "line",
+ act_token.get_position());
+ }
+
+ // pop output line from the internal option stack
+ ctx.set_language(
+ enable_emit_line_directives(ctx.get_language(), 0 != line_options.top()),
+ false);
+ enable_relative_names_in_line_directives(2 == line_options.top());
+ line_options.pop();
+ return true;
+ }
+ return false;
+ }
+
+ if (T_PP_NUMBER != id)
+ return false;
+
+ using namespace std; // some platforms have atoi in namespace std
+ int emit_lines = atoi((*it).get_value().c_str());
+ if (0 == emit_lines || 1 == emit_lines || 2 == emit_lines) {
+ // set the new emit #line directive mode
+ ctx.set_language(
+ enable_emit_line_directives(ctx.get_language(), emit_lines),
+ false);
+ return true;
+ }
+ return false;
+ }
+
+ // interpret the pragma wave option(output: ["filename"|null|default|push|pop])
+ // directive
+ template <typename ContextT>
+ bool
+ interpret_pragma_option_output_open(boost::filesystem::path &fpath,
+ ContextT& ctx, typename ContextT::token_type const &act_token)
+ {
+ namespace fs = boost::filesystem;
+
+ // ensure all directories for this file do exist
+ fs::create_directories(boost::wave::util::branch_path(fpath));
+
+ // figure out, whether the file has been written to by us, if yes, we
+ // append any output to this file, otherwise we overwrite it
+ std::ios::openmode mode = std::ios::out;
+ if (fs::exists(fpath) && written_by_us.find(fpath) != written_by_us.end())
+ mode = (std::ios::openmode)(std::ios::out | std::ios::app);
+
+ written_by_us.insert(fpath);
+
+ // close the current file
+ if (outputstrm.is_open())
+ outputstrm.close();
+
+ // open the new file
+ outputstrm.open(fpath.string().c_str(), mode);
+ if (!outputstrm.is_open()) {
+ BOOST_WAVE_THROW_CTX(ctx, boost::wave::preprocess_exception,
+ could_not_open_output_file,
+ fpath.string().c_str(), act_token.get_position());
+ return false;
+ }
+ generate_output = true;
+ current_outfile = fpath;
+ return true;
+ }
+
+ bool interpret_pragma_option_output_close(bool generate)
+ {
+ if (outputstrm.is_open())
+ outputstrm.close();
+ current_outfile = boost::filesystem::path();
+ generate_output = generate;
+ return true;
+ }
+
+ template <typename ContextT, typename IteratorT>
+ bool
+ interpret_pragma_option_output(ContextT &ctx, IteratorT &it,
+ IteratorT end, typename ContextT::token_type const &act_token)
+ {
+ using namespace boost::wave;
+ namespace fs = boost::filesystem;
+
+ typedef typename ContextT::token_type token_type;
+ typedef typename token_type::string_type string_type;
+
+ token_id id = util::impl::skip_whitespace(it, end);
+ if (T_COLON == id)
+ id = util::impl::skip_whitespace(it, end);
+
+ bool result = false;
+ if (T_STRINGLIT == id) {
+ namespace fs = boost::filesystem;
+
+ string_type fname ((*it).get_value());
+ fs::path fpath (boost::wave::util::create_path(
+ util::impl::unescape_lit(fname.substr(1, fname.size()-2)).c_str()));
+ fpath = boost::wave::util::complete_path(fpath, ctx.get_current_directory());
+ result = interpret_pragma_option_output_open(fpath, ctx, act_token);
+ }
+ else if (T_IDENTIFIER == id) {
+ if ((*it).get_value() == "null") {
+ // suppress all output from this point on
+ result = interpret_pragma_option_output_close(false);
+ }
+ else if ((*it).get_value() == "push") {
+ // initialize the current_outfile, if appropriate
+ if (output_options.empty() && current_outfile.empty() &&
+ !default_outfile.empty() && default_outfile != "-")
+ {
+ current_outfile = boost::wave::util::complete_path(
+ default_outfile, ctx.get_current_directory());
+ }
+
+ // push current output option onto the internal option stack
+ output_options.push(
+ output_option_type(generate_output, current_outfile));
+ result = true;
+ }
+ else if ((*it).get_value() == "pop") {
+ // test for mismatched push/pop #pragmas
+ if (output_options.empty()) {
+ BOOST_WAVE_THROW_CTX(ctx, bad_pragma_exception,
+ pragma_mismatched_push_pop, "output",
+ act_token.get_position());
+ return false;
+ }
+
+ // pop output option from the internal option stack
+ output_option_type const& opts = output_options.top();
+ generate_output = opts.first;
+ current_outfile = opts.second;
+ if (!current_outfile.empty()) {
+ // re-open the last file
+ result = interpret_pragma_option_output_open(current_outfile,
+ ctx, act_token);
+ }
+ else {
+ // either no output or generate to std::cout
+ result = interpret_pragma_option_output_close(generate_output);
+ }
+ output_options.pop();
+ }
+ }
+ else if (T_DEFAULT == id) {
+ // re-open the default output given on command line
+ if (!default_outfile.empty()) {
+ if (default_outfile == "-") {
+ // the output was suppressed on the command line
+ result = interpret_pragma_option_output_close(false);
+ }
+ else {
+ // there was a file name on the command line
+ fs::path fpath(boost::wave::util::create_path(default_outfile));
+ result = interpret_pragma_option_output_open(fpath, ctx,
+ act_token);
+ }
+ }
+ else {
+ // generate the output to std::cout
+ result = interpret_pragma_option_output_close(true);
+ }
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // join all adjacent string tokens into the first one
+ template <typename StringT>
+ StringT unlit(StringT const& str)
+ {
+ return str.substr(1, str.size()-2);
+ }
+
+ template <typename StringT>
+ StringT merge_string_lits(StringT const& lhs, StringT const& rhs)
+ {
+ StringT result ("\"");
+
+ result += unlit(lhs);
+ result += unlit(rhs);
+ result += "\"";
+ return result;
+ }
+
+ template <typename ContextT, typename ContainerT>
+ void join_adjacent_string_tokens(ContextT &ctx, ContainerT const& values,
+ ContainerT& joined_values)
+ {
+ using namespace boost::wave;
+
+ typedef typename ContextT::token_type token_type;
+ typedef typename token_type::string_type string_type;
+ typedef typename ContainerT::const_iterator const_iterator;
+ typedef typename ContainerT::iterator iterator;
+
+ token_type* current = 0;
+
+ const_iterator end = values.end();
+ for (const_iterator it = values.begin(); it != end; ++it) {
+ token_id id(*it);
+
+ if (id == T_STRINGLIT) {
+ if (!current) {
+ joined_values.push_back(*it);
+ current = &joined_values.back();
+ }
+ else {
+ current->set_value(merge_string_lits(
+ current->get_value(), (*it).get_value()));
+ }
+ }
+ else if (current) {
+ typedef util::impl::next_token<const_iterator> next_token_type;
+ token_id next_id (next_token_type::peek(it, end, true));
+
+ if (next_id != T_STRINGLIT) {
+ current = 0;
+ joined_values.push_back(*it);
+ }
+ }
+ else {
+ joined_values.push_back(*it);
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // interpret the pragma wave option() directives
+ template <typename ContextT, typename ContainerT>
+ bool
+ interpret_pragma_option(ContextT &ctx, ContainerT const &cvalues,
+ typename ContextT::token_type const &act_token)
+ {
+ using namespace boost::wave;
+
+ typedef typename ContextT::token_type token_type;
+ typedef typename token_type::string_type string_type;
+ typedef typename ContainerT::const_iterator const_iterator;
+
+ ContainerT values;
+ join_adjacent_string_tokens(ctx, cvalues, values);
+
+ const_iterator end = values.end();
+ for (const_iterator it = values.begin(); it != end; /**/) {
+ bool valid_option = false;
+
+ token_type const &value = *it;
+ if (value.get_value() == "preserve") {
+ // #pragma wave option(preserve: [0|1|2|3|push|pop])
+ valid_option = interpret_pragma_option_preserve(ctx, it, end,
+ act_token);
+ }
+ else if (value.get_value() == "line") {
+ // #pragma wave option(line: [0|1|2|push|pop])
+ valid_option = interpret_pragma_option_line(ctx, it, end,
+ act_token);
+ }
+ else if (value.get_value() == "output") {
+ // #pragma wave option(output: ["filename"|null|default|push|pop])
+ valid_option = interpret_pragma_option_output(ctx, it, end,
+ act_token);
+ }
+
+ if (!valid_option) {
+ // unknown option value
+ string_type option_str ("option");
+
+ if (values.size() > 0) {
+ option_str += "(";
+ option_str += util::impl::as_string(values);
+ option_str += ")";
+ }
+ BOOST_WAVE_THROW_CTX(ctx, boost::wave::preprocess_exception,
+ ill_formed_pragma_option,
+ option_str.c_str(), act_token.get_position());
+ return false;
+ }
+
+ token_id id = util::impl::skip_whitespace(it, end);
+ if (id == T_COMMA)
+ util::impl::skip_whitespace(it, end);
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // interpret the #pragma wave system() directive
+ template <typename ContextT, typename ContainerT>
+ bool
+ interpret_pragma_system(ContextT& ctx, ContainerT &pending,
+ ContainerT const &values,
+ typename ContextT::token_type const &act_token)
+ {
+ typedef typename ContextT::token_type token_type;
+ typedef typename token_type::string_type string_type;
+
+ if (0 == values.size()) return false; // ill_formed_pragma_option
+
+ string_type stdout_file(std::tmpnam(0));
+ string_type stderr_file(std::tmpnam(0));
+ string_type system_str(boost::wave::util::impl::as_string(values));
+ string_type native_cmd(system_str);
+
+ system_str += " >" + stdout_file + " 2>" + stderr_file;
+ if (0 != std::system(system_str.c_str())) {
+ // unable to spawn the command
+ string_type error_str("unable to spawn command: ");
+
+ error_str += native_cmd;
+ BOOST_WAVE_THROW_CTX(ctx, boost::wave::preprocess_exception,
+ ill_formed_pragma_option,
+ error_str.c_str(), act_token.get_position());
+ return false;
+ }
+
+ // rescan the content of the stdout_file and insert it as the
+ // _Pragma replacement
+ typedef typename ContextT::lexer_type lexer_type;
+ typedef typename ContextT::input_policy_type input_policy_type;
+ typedef boost::wave::iteration_context<
+ ContextT, lexer_type, input_policy_type>
+ iteration_context_type;
+
+ iteration_context_type iter_ctx(ctx, stdout_file.c_str(),
+ act_token.get_position(), ctx.get_language());
+ ContainerT pragma;
+
+ for (/**/; iter_ctx.first != iter_ctx.last; ++iter_ctx.first)
+ pragma.push_back(*iter_ctx.first);
+
+ // prepend the newly generated token sequence to the 'pending' container
+ pending.splice(pending.begin(), pragma);
+
+ // erase the created tempfiles
+ std::remove(stdout_file.c_str());
+ std::remove(stderr_file.c_str());
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The function enable_tracing is called, whenever the status of the
+ // tracing was changed.
+ // The parameter 'enable' is to be used as the new tracing status.
+ void enable_tracing(trace_flags flags)
+ { logging_flags = flags; }
+
+ // The function tracing_enabled should return the current tracing status.
+ trace_flags tracing_enabled()
+ { return logging_flags; }
+
+ // Helper functions for generating the trace output
+ void open_trace_body(char const *label = 0)
+ {
+ if (label)
+ output(label);
+ output("[\n");
+ increment_level();
+ }
+ void close_trace_body()
+ {
+ if (get_level() > 0) {
+ decrement_level();
+ output("]\n");
+ tracestrm << std::flush; // flush the stream buffer
+ }
+ }
+
+ template <typename StringT>
+ void output(StringT const &outstr) const
+ {
+ indent(get_level());
+ tracestrm << outstr; // output the given string
+ }
+
+ void indent(int level) const
+ {
+ for (int i = 0; i < level; ++i)
+ tracestrm << " "; // indent
+ }
+
+ int increment_level() { return ++level; }
+ int decrement_level() { BOOST_ASSERT(level > 0); return --level; }
+ int get_level() const { return level; }
+
+ bool enabled_macro_tracing() const
+ {
+ return (flags & trace_macros) && (logging_flags & trace_macros);
+ }
+ bool enabled_include_tracing() const
+ {
+ return (flags & trace_includes);
+ }
+ bool enabled_guard_tracing() const
+ {
+ return (flags & trace_guards);
+ }
+ bool enabled_macro_counting() const
+ {
+ return logging_flags & trace_macro_counts;
+ }
+
+ void count_invocation(std::string const& name)
+ {
+ typedef std::map<std::string, std::size_t>::iterator iterator;
+ typedef std::map<std::string, std::size_t>::value_type value_type;
+
+ iterator it = counts.find(name);
+ if (it == counts.end())
+ {
+ std::pair<iterator, bool> p = counts.insert(value_type(name, 0));
+ if (p.second)
+ it = p.first;
+ }
+
+ if (it != counts.end())
+ ++(*it).second;
+ }
+
+ void timer(TokenT const &value)
+ {
+ if (value.get_value() == "0" || value.get_value() == "restart") {
+ // restart the timer
+ elapsed_time.restart();
+ }
+ else if (value.get_value() == "1") {
+ // print out the current elapsed time
+ std::cerr
+ << value.get_position() << ": "
+ << elapsed_time.format_elapsed_time()
+ << std::endl;
+ }
+ else if (value.get_value() == "suspend") {
+ // suspend the timer
+ elapsed_time.suspend();
+ }
+ else if (value.get_value() == "resume") {
+ // resume the timer
+ elapsed_time.resume();
+ }
+ }
+
+private:
+ std::ofstream &outputstrm; // main output stream
+ std::ostream &tracestrm; // trace output stream
+ std::ostream &includestrm; // included list output stream
+ std::ostream &guardstrm; // include guard output stream
+ int level; // indentation level
+ trace_flags flags; // enabled globally
+ trace_flags logging_flags; // enabled by a #pragma
+ bool enable_system_command; // enable #pragma wave system() command
+ bool preserve_whitespace; // enable whitespace preservation
+ bool preserve_bol_whitespace; // enable begin of line whitespace preservation
+ bool& generate_output; // allow generated tokens to be streamed to output
+ std::string const& default_outfile; // name of the output file given on command line
+ boost::filesystem::path current_outfile; // name of the current output file
+
+ stop_watch elapsed_time; // trace timings
+ std::set<boost::filesystem::path> written_by_us; // all files we have written to
+
+ typedef std::pair<bool, boost::filesystem::path> output_option_type;
+ std::stack<output_option_type> output_options; // output option stack
+ std::stack<int> line_options; // line option stack
+ std::stack<int> preserve_options; // preserve option stack
+
+ std::map<std::string, std::size_t> counts; // macro invocation counts
+ bool emit_relative_filenames; // emit relative names in #line directives
+
+ std::set<std::string> noexpandmacros; // list of macros not to expand
+};
+
+#undef BOOST_WAVE_GETSTRING
+#undef BOOST_WAVE_OSSTREAM
+
+#endif // !defined(TRACE_MACRO_EXPANSION_HPP_D8469318_8407_4B9D_A19F_13CA60C1661F_INCLUDED)